1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1988 AT&T */
28 /* All Rights Reserved */
29
30 /*
31 * _doprnt: common code for printf, fprintf, sprintf
32 */
33
34 #include "lint.h"
35 #include "mtlib.h"
36 #include "print.h" /* parameters & macros for doprnt */
37 #include <wchar.h>
38 #include "libc.h"
39 #include <stdlib.h>
40 #include <limits.h>
41 #include <ctype.h>
42 #include <stdarg.h>
43 #include <values.h>
44 #include <memory.h>
45 #include <string.h>
46 #include <locale.h>
47 #include <widec.h>
48 #include "../i18n/_locale.h"
49 #include <errno.h>
50 #include <sys/types.h>
51 #include <libw.h>
52 #include "mse.h"
53 #include "xpg6.h"
54
55 static const char nullstr[] = "(null)";
56 static const wchar_t widenullstr[] = L"(null)";
57
58 #if defined(__i386) || defined(__amd64) || defined(__sparcv9)
59 #define GETQVAL(arg) (va_arg(arg, long double))
60 #else /* !defined(__i386) && !defined(__sparcv9) */
61 #define GETQVAL(arg) *(va_arg(arg, long double *))
62 #endif /* !defined(__i386) && !defined(__sparcv9) */
63
64 #ifdef _WIDE
65 #define STRCHR wcschr
66 #define STRSPN wcsspn
67 #define ATOI(x) _watoi((wchar_t *)x)
68 #define _P_HYPHEN L"-"
69 #define _P_PLUS L"+"
70 #define _P_BLANK L" "
71 #define _P_ZEROx L"0x"
72 #define _P_ZEROX L"0X"
73 #define _M_ISDIGIT(c) (((c) >= 0) && ((c) < 256) && isdigit((c)))
74 #define _M_ISUPPER(c) (((c) >= 0) && ((c) < 256) && isupper((c)))
75 #else /* _WIDE */
76 #define STRCHR strchr
77 #define STRSPN strspn
78 #define ATOI(x) atoi(x)
79 #define _P_HYPHEN "-"
80 #define _P_PLUS "+"
81 #define _P_BLANK " "
82 #define _P_ZEROx "0x"
83 #define _P_ZEROX "0X"
84 #define _M_ISDIGIT(c) isdigit((c))
85 #define _M_ISUPPER(c) isupper((c))
86 #endif /* _WIDE */
87
88 #ifdef _WIDE
89 #define PUT(p, n) \
90 { \
91 int retp; \
92 retp = put_wide(iop, &bufptr, bufferend, p, n, sflag); \
93 if (retp == EOF) { \
94 return ((ssize_t)EOF); \
95 } \
96 }
97
98 #define PAD(s, n) \
99 { \
100 int retp; \
101 retp = pad_wide(iop, &bufptr, bufferend, s, n, sflag); \
102 if (retp == EOF) { \
103 return ((ssize_t)EOF); \
104 } \
105 }
106
107 #define FPCONV(func, val, prec, decpt, sign, cvtbuf) \
108 { \
109 char cb[DECIMAL_STRING_LENGTH]; \
110 wchar_t *wp; \
111 char *cp; \
112 (void) func(val, prec, decpt, sign, cb); \
113 wp = cvtbuf; \
114 cp = cb; \
115 while (*cp) { \
116 *wp++ = (wchar_t)*cp++; \
117 } \
118 *wp = L'\0'; \
119 }
120
121 #else /* _WIDE */
122 #define PUT(p, n) \
123 {\
124 /*\
125 * When _doprnt() is called by [v]snprintf, we need to \
126 * always call _dowrite(). We also need to call _dowrite() \
127 * if the bufptr lies beyond the end of the buffer. This \
128 * is possible due to known off-by-one errors in __flsbuf() \
129 * and _fwrite_unlocked(). See 1235867 and 1231720 for the \
130 * sordid details. \
131 */\
132 if (snflag || bufptr > bufferend ||\
133 (unsigned long)(bufferend - bufptr) < (n)) {\
134 if (!_dowrite(p, n, iop, &bufptr)) {\
135 return (EOF);\
136 }\
137 } else {\
138 unsigned char *fbp = bufptr;\
139 switch (n) {\
140 case 4:\
141 *fbp = *p;\
142 *(fbp + 1) = *(p + 1);\
143 *(fbp + 2) = *(p + 2);\
144 *(fbp + 3) = *(p + 3);\
145 bufptr += 4;\
146 break;\
147 case 3:\
148 *fbp = *p;\
149 *(fbp + 1) = *(p + 1);\
150 *(fbp + 2) = *(p + 2);\
151 bufptr += 3;\
152 break;\
153 case 2:\
154 *fbp = *p;\
155 *(fbp + 1) = *(p + 1);\
156 bufptr += 2;\
157 break;\
158 case 1:\
159 *bufptr++ = *p;\
160 break;\
161 default:\
162 bufptr = (unsigned char *)memcpy(fbp, p, n)\
163 + (n);\
164 }\
165 }\
166 }
167
168 #define PAD(s, n) { ssize_t nn; \
169 for (nn = n; nn > PAD_LEN; nn -= PAD_LEN) \
170 if (!_dowrite(s, PAD_LEN, iop, &bufptr)) \
171 return (EOF); \
172 PUT(s, nn); \
173 }
174
175 #define FPCONV(func, val, prec, decpt, sign, cvtbuf) \
176 (void) func(val, prec, decpt, sign, cvtbuf);
177
178 #endif /* _WIDE */
179
180 /* bit positions for flags used in doprnt */
181
182 #define LENGTH 0x1 /* l */
183 #define FPLUS 0x2 /* + */
184 #define FMINUS 0x4 /* - */
185 #define FBLANK 0x8 /* blank */
186 #define FSHARP 0x10 /* # */
187 #define PADZERO 0x20 /* padding zeroes requested via '0' */
188 #define DOTSEEN 0x40 /* dot appeared in format specification */
189 #define SUFFIX 0x80 /* a suffix is to appear in the output */
190 #define RZERO 0x100 /* there will be trailing zeros in output */
191 #define LZERO 0x200 /* there will be leading zeroes in output */
192 #define SHORT 0x400 /* h */
193 #define QUAD 0x800 /* Q for long double */
194 #define XLONG 0x1000 /* ll for long long */
195 #define CHAR 0x2000 /* hh for char */
196
197 #ifdef _WIDE
198 static wchar_t *
199 insert_thousands_sep(wchar_t *bp, wchar_t *ep);
200 #else /* _WIDE */
201 static char *
202 insert_thousands_sep(char *bp, char *ep);
203 #endif /* _WIDE */
204
205 static int _rec_scrswidth(wchar_t *, ssize_t);
206
207 /*
208 * Positional Parameter information
209 */
210 #define MAXARGS 30 /* max. number of args for fast positional paramters */
211
212 static ssize_t
213 _dowrite(const char *p, ssize_t n, FILE *iop, unsigned char **ptrptr);
214
215 /*
216 * stva_list is used to subvert C's restriction that a variable with an
217 * array type can not appear on the left hand side of an assignment operator.
218 * By putting the array inside a structure, the functionality of assigning to
219 * the whole array through a simple assignment is achieved..
220 */
221 typedef struct stva_list {
222 va_list ap;
223 } stva_list;
224
225 #ifdef _WIDE
226 static void _wmkarglst(wchar_t *, stva_list, stva_list [], int);
227 static void _wgetarg(wchar_t *, stva_list *, long, int);
228 #else /* _WIDE */
229 static void _mkarglst(char *, stva_list, stva_list [], int);
230 void _getarg(char *, stva_list *, long, int);
231 #endif /* _WIDE */
232
233
234
235
236 static int
_lowdigit(ssize_t * valptr)237 _lowdigit(ssize_t *valptr)
238 {
239 /* This function computes the decimal low-order digit of the number */
240 /* pointed to by valptr, and returns this digit after dividing */
241 /* *valptr by ten. This function is called ONLY to compute the */
242 /* low-order digit of a long whose high-order bit is set. */
243
244 ssize_t lowbit = *valptr & 1;
245 long value = (*valptr >> 1) & ~HIBITL;
246
247 *valptr = value / 5;
248 value = value % 5 * 2 + lowbit + '0';
249 return ((int)value);
250 }
251
252 static int
_lowlldigit(long long * valptr)253 _lowlldigit(long long *valptr)
254 {
255 ssize_t lowbit = *valptr & 1;
256 long long value = (*valptr >> 1) & ~HIBITLL;
257 *valptr = value / 5;
258 value = value % 5 * 2 + lowbit + '0';
259 return ((int)value);
260 }
261
262 /* The function _dowrite carries out buffer pointer bookkeeping surrounding */
263 /* a call to fwrite. It is called only when the end of the file output */
264 /* buffer is approached or in other unusual situations. */
265
266 static ssize_t
_dowrite(const char * p,ssize_t n,FILE * iop,unsigned char ** ptrptr)267 _dowrite(const char *p, ssize_t n, FILE *iop, unsigned char **ptrptr)
268 {
269 if (!(iop->_flag & _IOREAD)) {
270 iop->_cnt -= (*ptrptr - iop->_ptr);
271 iop->_ptr = *ptrptr;
272 _bufsync(iop, _bufend(iop));
273 if (_FWRITE(p, 1, n, iop) != n) {
274 return (0);
275 }
276 *ptrptr = iop->_ptr;
277 } else {
278 if (n > iop->_cnt)
279 n = iop->_cnt;
280 iop->_cnt -= n;
281 *ptrptr = (unsigned char *)memcpy((char *)*ptrptr, p, n) + n;
282 iop->_ptr = *ptrptr;
283 }
284 return (1);
285 }
286
287 #define PAD_LEN 20
288 static const char _blanks[] = " ";
289 static const char _zeroes[] = "00000000000000000000";
290 #ifdef _WIDE
291 static const wchar_t uc_digs[] = L"0123456789ABCDEF";
292 static const wchar_t lc_digs[] = L"0123456789abcdef";
293 #else /* _WIDE */
294 static const char uc_digs[] = "0123456789ABCDEF";
295 static const char lc_digs[] = "0123456789abcdef";
296 #endif /* _WIDE */
297
298 #ifdef _WIDE
299 static int
put_wide(FILE * iop,unsigned char ** bufptr,unsigned char * bufferend,wchar_t * p,size_t n,int sflag)300 put_wide(FILE *iop, unsigned char **bufptr,
301 unsigned char *bufferend, wchar_t *p, size_t n,
302 int sflag)
303 {
304 unsigned char *newbufptr;
305 wchar_t *q;
306 int r;
307 size_t len, i;
308
309 if (sflag) {
310 len = (wchar_t *)bufferend - (wchar_t *)*bufptr;
311 if (n > len) {
312 (void) wmemcpy((wchar_t *)*bufptr, p, len);
313 iop->_ptr = bufferend;
314 return (EOF);
315 } else {
316 (void) wmemcpy((wchar_t *)*bufptr, p, n);
317 *bufptr = (unsigned char *)((wchar_t *)*bufptr + n);
318 return (0);
319 }
320 } else {
321 char *tmpp, *tmpq;
322 size_t tsize;
323
324 tsize = (n + 1) * MB_LEN_MAX;
325 tmpp = lmalloc(tsize);
326 if (tmpp == NULL) {
327 errno = ENOMEM;
328 return (EOF);
329 }
330 q = p;
331 tmpq = tmpp;
332 for (len = 0, i = 0; i < n; i++) {
333 r = wctomb(tmpq, *q++);
334 if (r == -1) {
335 lfree(tmpp, tsize);
336 errno = EILSEQ;
337 return (EOF);
338 }
339 len += r;
340 tmpq += r;
341 }
342 tmpq = tmpp;
343 newbufptr = *bufptr + len;
344 if (newbufptr > bufferend) {
345 if (!_dowrite(tmpp, len, iop, bufptr)) {
346 lfree(tmpp, tsize);
347 return (EOF);
348 }
349 } else {
350 (void) memcpy(*bufptr, tmpp, len);
351 *bufptr = newbufptr;
352 }
353 lfree(tmpp, tsize);
354 return (0);
355 }
356 }
357
358 static int
pad_wide(FILE * iop,unsigned char ** bufptr,unsigned char * bufferend,const char * s,size_t n,int sflag)359 pad_wide(FILE *iop, unsigned char **bufptr,
360 unsigned char *bufferend, const char *s, size_t n,
361 int sflag)
362 {
363 unsigned char *newbufptr;
364 ssize_t nn;
365 size_t len;
366 wchar_t ps;
367
368 if (sflag) {
369 /* for swprintf */
370 ps = (wchar_t)s[0];
371 len = (wchar_t *)bufferend - (wchar_t *)*bufptr;
372 if (n > len) {
373 (void) wmemset((wchar_t *)*bufptr, ps, len);
374 iop->_ptr = bufferend;
375 return (EOF);
376 } else {
377 (void) wmemset((wchar_t *)*bufptr, ps, n);
378 *bufptr = (unsigned char *)((wchar_t *)*bufptr + n);
379 return (0);
380 }
381 } else {
382 for (nn = n; nn > PAD_LEN; nn -= PAD_LEN) {
383 if (!_dowrite(s, PAD_LEN, iop, bufptr))
384 return (EOF);
385 }
386 newbufptr = *bufptr + nn;
387 if (newbufptr > bufferend) {
388 if (!_dowrite(s, nn, iop, bufptr))
389 return (EOF);
390 } else {
391 (void) memcpy(*bufptr, s, nn);
392 *bufptr = newbufptr;
393 }
394 return (0);
395 }
396 }
397 #endif /* _WIDE */
398
399 #ifdef _WIDE
400 ssize_t
_wdoprnt(const wchar_t * format,va_list in_args,FILE * iop)401 _wdoprnt(const wchar_t *format, va_list in_args, FILE *iop)
402 {
403 return (_wndoprnt(format, in_args, iop, 0));
404 }
405 #else /* _WIDE */
406 ssize_t
_doprnt(const char * format,va_list in_args,FILE * iop)407 _doprnt(const char *format, va_list in_args, FILE *iop)
408 {
409 return (_ndoprnt(format, in_args, iop, 0));
410 }
411 #endif /* _WIDE */
412
413
414 #ifdef _WIDE
415 ssize_t
_wndoprnt(const wchar_t * format,va_list in_args,FILE * iop,int prflag)416 _wndoprnt(const wchar_t *format, va_list in_args, FILE *iop, int prflag)
417 #else /* _WIDE */
418 ssize_t
419 _ndoprnt(const char *format, va_list in_args, FILE *iop, int prflag)
420 #endif /* _WIDE */
421 {
422
423 #ifdef _WIDE
424 int sflag = 0;
425 size_t maxcount;
426 #else
427 int snflag = 0;
428 #endif /* _WIDE */
429 /* bufptr is used inside of doprnt instead of iop->_ptr; */
430 /* bufferend is a copy of _bufend(iop), if it exists. For */
431 /* dummy file descriptors (iop->_flag & _IOREAD), bufferend */
432 /* may be meaningless. Dummy file descriptors are used so that */
433 /* sprintf and vsprintf may share the _doprnt routine with the */
434 /* rest of the printf family. */
435
436 unsigned char *bufptr;
437 unsigned char *bufferend;
438
439 #ifdef _WIDE
440 /* This variable counts output characters. */
441 size_t count = 0;
442 #else /* _WIDE */
443 /* This variable counts output characters. */
444 int count = 0;
445 #endif /* _WIDE */
446
447 #ifdef _WIDE
448 wchar_t *bp;
449 size_t bpsize;
450 wchar_t *p;
451 char *cbp;
452 char *cp;
453
454 #else /* _WIDE */
455 /* Starting and ending points for value to be printed */
456 char *bp;
457 char *p;
458 #endif /* _WIDE */
459 /* Field width and precision */
460 int prec = 0;
461 ssize_t width;
462 ssize_t num;
463 ssize_t sec_display;
464 wchar_t *wp;
465 ssize_t preco;
466 ssize_t wcount = 0;
467 char tmpbuf[10];
468 char wflag;
469 char lflag;
470 int quote; /* ' */
471 int retcode;
472
473
474 #ifdef _WIDE
475 /* Format code */
476 wchar_t fcode;
477 #else /* _WIDE */
478 /* Format code */
479 char fcode;
480 #endif /* _WIDE */
481
482 /* Number of padding zeroes required on the left and right */
483 ssize_t lzero, rzero, rz, leadzeroes;
484
485
486 /* Flags - bit positions defined by LENGTH, FPLUS, FMINUS, FBLANK, */
487 /* and FSHARP are set if corresponding character is in format */
488 /* Bit position defined by PADZERO means extra space in the field */
489 /* should be padded with leading zeroes rather than with blanks */
490
491 ssize_t flagword;
492
493 #ifdef _WIDE
494 /* Values are developed in this buffer */
495 wchar_t buf[max(MAXLLDIGS, 1034)];
496 wchar_t cvtbuf[512 + DECIMAL_STRING_LENGTH];
497
498 /* Pointer to sign, "0x", "0X", or empty */
499 wchar_t *prefix;
500 wchar_t prefixbuf[4];
501
502 /* Exponent or empty */
503 wchar_t *suffix;
504
505 /* Buffer to create exponent */
506 wchar_t expbuf[MAXESIZ + 1];
507 #else /* _WIDE */
508 /* Values are developed in this buffer */
509 char buf[max(MAXLLDIGS, 1034)];
510 char cvtbuf[512 + DECIMAL_STRING_LENGTH];
511
512 /* Pointer to sign, "0x", "0X", or empty */
513 char *prefix;
514 char prefixbuf[4];
515
516 /* Exponent or empty */
517 char *suffix;
518
519 /* Buffer to create exponent */
520 char expbuf[MAXESIZ + 1];
521 #endif /* _WIDE */
522
523 /* Length of prefix and of suffix */
524 ssize_t prefixlength, suffixlength;
525
526 /* Combined length of leading zeroes, trailing zeroes, and suffix */
527 ssize_t otherlength;
528
529 /* The value being converted, if integer */
530 ssize_t val;
531
532 /* The value being converted, if long long */
533 long long ll = 0LL;
534
535 /* Output value from aconvert */
536 int exp;
537
538 /* Output values from fcvt and ecvt */
539 int decpt, sign;
540
541 #ifdef _WIDE
542 /* Pointer to a translate table for digits of whatever radix */
543 const wchar_t *tab;
544 #else /* _WIDE */
545 /* Pointer to a translate table for digits of whatever radix */
546 const char *tab;
547 #endif /* _WIDE */
548
549 /* Work variables */
550 ssize_t k, lradix, mradix;
551
552 int inf_nan = 0;
553 int inf_nan_mixed_case = 0;
554
555 #ifdef _WIDE
556 /* variables for positional parameters */
557 /* save the beginning of the format */
558 wchar_t *sformat = (wchar_t *)format;
559 #else /* _WIDE */
560 /* variables for positional parameters */
561 char *sformat = (char *)format; /* save the beginning of the format */
562 #endif
563
564 int fpos = 1; /* 1 if first positional parameter */
565 stva_list args, /* used to step through the argument list */
566 sargs; /* used to save the start of the arg list */
567 stva_list bargs; /* used to restore args if positional width */
568 /* or precision */
569 stva_list arglst[MAXARGS]; /* array giving appropriate values */
570 /* for va_arg() to retrieve the */
571 /* corresponding argument: */
572 /* arglst[0] is the first arg */
573 /* arglst[1] is the second arg, etc */
574
575 int starflg = 0; /* set to 1 if * format specifier seen */
576 struct lconv *locptr = localeconv();
577 char decimal_point = *locptr->decimal_point;
578
579 /*
580 * Initialize args and sargs to the start of the argument list.
581 * We don't know any portable way to copy an arbitrary C object
582 * so we use a system-specific routine (probably a macro) from
583 * stdarg.h. (Remember that if va_list is an array, in_args will
584 * be a pointer and &in_args won't be what we would want for
585 * memcpy.)
586 */
587 va_copy(args.ap, in_args);
588 sargs = args;
589
590 #ifdef _WIDE
591 if (iop->_flag == _IOREAD)
592 sflag = 1;
593
594 if (!sflag) {
595 #endif /* _WIDE */
596 /* if first I/O to the stream get a buffer */
597 /* Note that iop->_base should not equal 0 for sprintf and vsprintf */
598 if (iop->_base == 0) {
599 if (_findbuf(iop) == 0)
600 return (EOF);
601 /* _findbuf leaves _cnt set to 0 which is the wrong thing to do */
602 /* for fully buffered files */
603 if (!(iop->_flag & (_IOLBF|_IONBF)))
604 iop->_cnt = _bufend(iop) - iop->_base;
605 }
606 #ifdef _WIDE
607 }
608 #endif /* _WIDE */
609
610 #ifdef _WIDE
611 bufptr = iop->_ptr;
612 if (sflag) {
613 maxcount = (size_t)iop->_cnt;
614 bufferend = (unsigned char *)(((wchar_t *)iop->_ptr) +
615 maxcount);
616 } else {
617 bufferend = _bufend(iop);
618 }
619 #else /* _WIDE */
620 /* initialize buffer pointer and buffer end pointer */
621 bufptr = iop->_ptr;
622 if (iop->_flag & _IOREAD) {
623 /*
624 * [v]sprintf or [v]snprintf
625 */
626 if (iop->_cnt == MAXINT) {
627 /*
628 * [v]sprintf (no boundschecking)
629 */
630 bufferend =
631 (unsigned char *)((long)bufptr | (-1L & ~HIBITL));
632 } else {
633 /*
634 * [v]snprintf (with boundschecking) or
635 * iop with _IORW has been read.
636 */
637 bufferend = _bufend(iop);
638 if (bufferend == NULL) {
639 /*
640 * [v]snprintf
641 *
642 * [v]snprint() needs to be always handled by
643 * _dowrite().
644 */
645 snflag = 1;
646 }
647 }
648 } else {
649 /*
650 * [v]printf or [v]fprintf
651 */
652 bufferend = _bufend(iop);
653 }
654 #endif /* _WIDE */
655
656 /*
657 * The main loop -- this loop goes through one iteration
658 * for each string of ordinary characters or format specification.
659 */
660 for (; ; ) {
661 ssize_t n;
662
663 if ((fcode = *format) != '\0' && fcode != '%') {
664 #ifdef _WIDE
665 bp = (wchar_t *)format;
666 #else /* _WIDE */
667 bp = (char *)format;
668 #endif /* _WIDE */
669 do {
670 format++;
671 } while ((fcode = *format) != '\0' && fcode != '%');
672
673 count += (n = format - bp); /* n = no. of non-% chars */
674 PUT(bp, n);
675 }
676 if (fcode == '\0') { /* end of format; return */
677 ssize_t nn = bufptr - iop->_ptr;
678
679 #ifdef _WIDE
680 if (sflag) {
681 iop->_ptr = bufptr;
682 return ((ssize_t)count);
683 }
684 #endif /* _WIDE */
685
686 iop->_cnt -= nn;
687 iop->_ptr = bufptr;
688 /* in case of interrupt during last several lines */
689 if ((bufptr + iop->_cnt) > bufferend && !(iop->_flag \
690 & _IOREAD))
691 _bufsync(iop, bufferend);
692 if (iop->_flag & (_IONBF | _IOLBF) && \
693 (iop->_flag & _IONBF || \
694 memchr((char *)(bufptr+iop->_cnt), \
695 '\n', -iop->_cnt) != NULL))
696 (void) _xflsbuf(iop);
697 #ifdef _WIDE
698 return (FERROR(iop) ? EOF : (ssize_t)count);
699 #else /* _WIDE */
700 return (FERROR(iop) ? EOF : (int)count);
701 #endif /* _WIDE */
702 }
703
704 /*
705 * % has been found.
706 * The following switch is used to parse the format
707 * specification and to perform the operation specified
708 * by the format letter. The program repeatedly goes
709 * back to this switch until the format letter is
710 * encountered.
711 */
712 width = prefixlength = otherlength = 0;
713 flagword = suffixlength = 0;
714 format++;
715 wflag = 0;
716 lflag = 0;
717 sec_display = 0;
718 quote = 0;
719
720 charswitch:
721
722 switch (fcode = *format++) {
723
724 case '+':
725 flagword |= FPLUS;
726 goto charswitch;
727 case '-':
728 flagword |= FMINUS;
729 flagword &= ~PADZERO; /* ignore 0 flag */
730 goto charswitch;
731 case ' ':
732 flagword |= FBLANK;
733 goto charswitch;
734 case '\'': /* XSH4 */
735 quote++;
736 goto charswitch;
737 case '#':
738 flagword |= FSHARP;
739 goto charswitch;
740
741 /* Scan the field width and precision */
742 case '.':
743 flagword |= DOTSEEN;
744 prec = 0;
745 goto charswitch;
746
747 case '*':
748 if (_M_ISDIGIT(*format)) {
749 starflg = 1;
750 bargs = args;
751 goto charswitch;
752 }
753 if (!(flagword & DOTSEEN)) {
754 width = va_arg(args.ap, int);
755 if (width < 0) {
756 width = -width;
757 flagword |= FMINUS;
758 }
759 } else {
760 prec = va_arg(args.ap, int);
761 if (prec < 0) {
762 prec = 0;
763 flagword ^= DOTSEEN; /* ANSI sez so */
764 }
765 }
766 goto charswitch;
767
768 case '$':
769 {
770 ssize_t position;
771 stva_list targs;
772 if (fpos) {
773 #ifdef _WIDE
774 _wmkarglst(sformat, sargs, arglst, prflag);
775 #else /* _WIDE */
776 _mkarglst(sformat, sargs, arglst, prflag);
777 #endif /* _WIDE */
778 fpos = 0;
779 }
780 if (flagword & DOTSEEN) {
781 position = prec;
782 prec = 0;
783 } else {
784 position = width;
785 width = 0;
786 }
787 if (position <= 0) {
788 /* illegal position */
789 format--;
790 continue;
791 }
792 if (position <= MAXARGS) {
793 targs = arglst[position - 1];
794 } else {
795 targs = arglst[MAXARGS - 1];
796 #ifdef _WIDE
797 _wgetarg(sformat, &targs, position, prflag);
798 #else /* _WIDE */
799 _getarg(sformat, &targs, position, prflag);
800 #endif /* _WIDE */
801 }
802 if (!starflg)
803 args = targs;
804 else {
805 starflg = 0;
806 args = bargs;
807 if (flagword & DOTSEEN) {
808 prec = va_arg(targs.ap, int);
809 if (prec < 0) {
810 prec = 0;
811 flagword ^= DOTSEEN; /* XSH */
812 }
813 } else {
814 width = va_arg(targs.ap, int);
815 if (width < 0) {
816 width = -width;
817 flagword |= FMINUS;
818 }
819 }
820 }
821 goto charswitch;
822 }
823
824 case '0': /* obsolescent spec: leading zero in width */
825 /* means pad with leading zeros */
826 if (!(flagword & (DOTSEEN | FMINUS)))
827 flagword |= PADZERO;
828 /* FALLTHROUGH */
829 case '1':
830 case '2':
831 case '3':
832 case '4':
833 case '5':
834 case '6':
835 case '7':
836 case '8':
837 case '9':
838 { num = fcode - '0';
839 while (_M_ISDIGIT(fcode = *format)) {
840 num = num * 10 + fcode - '0';
841 format++;
842 }
843 if (flagword & DOTSEEN)
844 prec = num;
845 else
846 width = num;
847 goto charswitch;
848 }
849
850 /* Scan the length modifier */
851 case 'l':
852 if (!(flagword & XLONG)) {
853 if (lflag) {
854 /* long long */
855 flagword &= ~LENGTH;
856 flagword |= XLONG;
857 } else {
858 /* long */
859 flagword |= LENGTH;
860 }
861 }
862 lflag++;
863 goto charswitch;
864
865 case 'L': /* long double */
866 flagword |= QUAD;
867 goto charswitch;
868
869 case 'h':
870 if (!(flagword & CHAR)) {
871 if (flagword & SHORT) {
872 /* char - hh */
873 flagword &= ~SHORT;
874 flagword |= CHAR;
875 } else {
876 /* short */
877 flagword |= SHORT;
878 }
879 }
880 goto charswitch;
881 case 'j':
882 #ifndef _LP64
883 /*
884 * *printf_c89() in 32-bit libc uses
885 * 32-bit intmax_t; otherwise intmax_t
886 * is 64-bits.
887 */
888 if (!(prflag & _F_INTMAX32)) {
889 #endif
890 flagword |= XLONG; /* [u]intmax_t (64) */
891 #ifndef _LP64
892 }
893 #endif
894 goto charswitch;
895
896 case 't':
897 /*
898 * LENGTH is shared by l, t, z specifiers; protect
899 * against (destructive) undefined behavior (eg:
900 * avoid %llt setting XLONG and LENGTH) with invalid
901 * combinations of specifiers
902 */
903 if (!(flagword & XLONG)) {
904 flagword |= LENGTH; /* ptrdiff_t */
905 }
906 goto charswitch;
907
908 case 'z':
909 if (!(flagword & XLONG)) {
910 flagword |= LENGTH; /* [s]size_t */
911 }
912 goto charswitch;
913
914 /*
915 * The character addressed by format must be
916 * the format letter -- there is nothing
917 * left for it to be.
918 *
919 * The status of the +, -, #, and blank
920 * flags are reflected in the variable
921 * "flagword". "width" and "prec" contain
922 * numbers corresponding to the digit
923 * strings before and after the decimal
924 * point, respectively. If there was no
925 * decimal point, then flagword & DOTSEEN
926 * is false and the value of prec is meaningless.
927 *
928 * The following switch cases set things up
929 * for printing. What ultimately gets
930 * printed will be padding blanks, a
931 * prefix, left padding zeroes, a value,
932 * right padding zeroes, a suffix, and
933 * more padding blanks. Padding blanks
934 * will not appear simultaneously on both
935 * the left and the right. Each case in
936 * this switch will compute the value, and
937 * leave in several variables the informa-
938 * tion necessary to construct what is to
939 * be printed.
940 *
941 * The prefix is a sign, a blank, "0x",
942 * "0X", a sign or a blank followed by "0x"
943 * or "0X", or nothing, and is addressed by
944 * "prefix".
945 *
946 * The suffix is either null or an
947 * exponent, and is addressed by "suffix".
948 * If there is a suffix, the flagword bit
949 * SUFFIX will be set.
950 *
951 * The value to be printed starts at "bp"
952 * and continues up to and not including
953 * "p".
954 *
955 * "lzero" and "rzero" will contain the
956 * number of padding zeroes required on
957 * the left and right, respectively.
958 * The flagword bits LZERO and RZERO tell
959 * whether padding zeros are required.
960 *
961 * The number of padding blanks, and
962 * whether they go on the left or the
963 * right, will be computed on exit from
964 * the switch.
965 */
966
967
968
969 /*
970 * decimal fixed point representations
971 *
972 * HIBITL is 100...000
973 * binary, and is equal to the maximum
974 * negative number.
975 * We assume a 2's complement machine
976 */
977 case 'i':
978 case 'd':
979 if ((flagword & PADZERO) && (flagword & DOTSEEN))
980 flagword &= ~PADZERO; /* ignore 0 flag */
981 /* Set buffer pointer to last digit */
982 p = bp = buf + MAXLLDIGS;
983
984 /* Fetch the argument to be printed */
985 if (flagword & XLONG) { /* long long */
986 ll = va_arg(args.ap, long long);
987
988 /* If signed conversion, make sign */
989 if (ll < 0) {
990 prefix = _P_HYPHEN;
991 prefixlength = 1;
992 /*
993 * Negate, checking in advance for
994 * possible overflow.
995 */
996 if (ll != HIBITLL)
997 ll = -ll;
998 else
999 /* number is -HIBITLL; convert last */
1000 /* digit now and get positive number */
1001 *--bp = _lowlldigit(&ll);
1002 } else if (flagword & FPLUS) {
1003 prefix = _P_PLUS;
1004 prefixlength = 1;
1005 } else if (flagword & FBLANK) {
1006 prefix = _P_BLANK;
1007 prefixlength = 1;
1008 }
1009 } else { /* not long long */
1010 if (flagword & LENGTH)
1011 val = va_arg(args.ap, long);
1012 else
1013 val = va_arg(args.ap, int);
1014
1015 if (flagword & SHORT)
1016 val = (short)val;
1017 else if (flagword & CHAR)
1018 val = (char)val;
1019
1020 /* If signed conversion, make sign */
1021 if (val < 0) {
1022 prefix = _P_HYPHEN;
1023 prefixlength = 1;
1024 /*
1025 * Negate, checking in advance
1026 * for possible overflow.
1027 */
1028 if (val != HIBITL)
1029 val = -val;
1030 /*
1031 * number is -HIBITL; convert
1032 * last digit now and get
1033 * positive number
1034 */
1035 else
1036 *--bp = _lowdigit(&val);
1037 } else if (flagword & FPLUS) {
1038 prefix = _P_PLUS;
1039 prefixlength = 1;
1040 } else if (flagword & FBLANK) {
1041 prefix = _P_BLANK;
1042 prefixlength = 1;
1043 }
1044 }
1045
1046 decimal:
1047 {
1048 long qval = val;
1049 long long lll = ll;
1050 long long tll;
1051 if (flagword & XLONG) {
1052 if (lll < 10LL) {
1053 #ifdef _WIDE
1054 if (lll != 0LL || !(flagword & DOTSEEN))
1055 *--bp = (wchar_t)lll + L'0';
1056 #else /* _WIDE */
1057 if (lll != 0LL || !(flagword & DOTSEEN))
1058 *--bp = (char)lll + '0';
1059 #endif /* _WIDE */
1060 } else {
1061 do {
1062 tll = lll;
1063 lll /= 10;
1064 #ifdef _WIDE
1065 *--bp = (wchar_t)
1066 (tll - lll * 10 + '0');
1067 #else /* _WIDE */
1068 *--bp = (char) \
1069 (tll - lll * 10 + '0');
1070 #endif /* _WIDE */
1071 } while (lll >= 10);
1072 #ifdef _WIDE
1073 *--bp = (wchar_t)lll + '0';
1074 #else /* _WIDE */
1075 *--bp = (char)lll + '0';
1076 #endif /* _WIDE */
1077 }
1078 } else {
1079 if (qval <= 9) {
1080 #ifdef _WIDE
1081 if (qval != 0 || !(flagword & DOTSEEN))
1082 *--bp = (wchar_t)qval + '0';
1083 #else /* _WIDE */
1084 if (qval != 0 || !(flagword & DOTSEEN))
1085 *--bp = (char)qval + '0';
1086 #endif /* _WIDE */
1087 } else {
1088 do {
1089 n = qval;
1090 qval /= 10;
1091 #ifdef _WIDE
1092 *--bp = (wchar_t) \
1093 (n - qval * 10 + '0');
1094 #else /* _WIDE */
1095 *--bp = (char) \
1096 (n - qval * 10 + '0');
1097 #endif /* _WIDE */
1098 } while (qval > 9);
1099 #ifdef _WIDE
1100 *--bp = (wchar_t)qval + '0';
1101 #else /* _WIDE */
1102 *--bp = (char)qval + '0';
1103 #endif /* _WIDE */
1104 }
1105 }
1106 }
1107 /* Handle the ' flag */
1108 if (quote) {
1109 p = insert_thousands_sep(bp, p);
1110 }
1111
1112 /* Calculate minimum padding zero requirement */
1113 if (flagword & DOTSEEN) {
1114 leadzeroes = prec - (p - bp);
1115 if (leadzeroes > 0) {
1116 otherlength = lzero = leadzeroes;
1117 flagword |= LZERO;
1118 }
1119 }
1120 break;
1121
1122 case 'u':
1123 if ((flagword & PADZERO) && (flagword & DOTSEEN))
1124 flagword &= ~PADZERO; /* ignore 0 flag */
1125 p = bp = buf + MAXLLDIGS;
1126
1127 /* Fetch the argument to be printed */
1128 if (flagword & XLONG) {
1129 ll = va_arg(args.ap, long long);
1130
1131 if (ll & HIBITLL)
1132 *--bp = _lowlldigit(&ll);
1133 } else {
1134 if (flagword & LENGTH)
1135 val = va_arg(args.ap, long);
1136 else
1137 val = va_arg(args.ap, unsigned);
1138
1139 if (flagword & SHORT)
1140 val = (unsigned short)val;
1141 else if (flagword & CHAR)
1142 val = (unsigned char)val;
1143
1144 if (val & HIBITL)
1145 *--bp = _lowdigit(&val);
1146 }
1147
1148 goto decimal;
1149
1150 /*
1151 * non-decimal fixed point representations
1152 * for radix equal to a power of two
1153 *
1154 * "mradix" is one less than the radix for the conversion.
1155 * "lradix" is one less than the base 2 log
1156 * of the radix for the conversion. Conversion is unsigned.
1157 * HIBITL is 100...000
1158 * binary, and is equal to the maximum
1159 * negative number.
1160 * We assume a 2's complement machine
1161 */
1162
1163 case 'o':
1164 mradix = 7;
1165 lradix = 2;
1166 /*
1167 * DR151 and clarification in C90
1168 * presence of '#' increases precision to first
1169 * digit of the result to be zero
1170 */
1171 if ((flagword & DOTSEEN) && (flagword & FSHARP) &&
1172 prec == 0)
1173 prec = 1;
1174
1175 goto fixed;
1176
1177 case 'p':
1178 flagword &= ~(XLONG | SHORT);
1179 flagword |= LENGTH;
1180
1181 /* FALLTHRU */
1182 case 'X':
1183 case 'x':
1184 mradix = 15;
1185 lradix = 3;
1186
1187 fixed:
1188 if ((flagword & PADZERO) && (flagword & DOTSEEN))
1189 flagword &= ~PADZERO; /* ignore 0 flag */
1190
1191 #ifdef _WIDE
1192 /* Set translate table for digits */
1193 tab = (wchar_t *)((fcode == 'X') ? uc_digs : lc_digs);
1194 #else /* _WIDE */
1195 /* Set translate table for digits */
1196 tab = (fcode == 'X') ? uc_digs : lc_digs;
1197 #endif /* _WIDE */
1198
1199 /* Fetch the argument to be printed */
1200 if (flagword & XLONG) {
1201 ll = va_arg(args.ap, long long);
1202 } else {
1203 if (flagword & LENGTH)
1204 val = va_arg(args.ap, long);
1205 else
1206 val = va_arg(args.ap, unsigned);
1207
1208 if (flagword & SHORT)
1209 val = (unsigned short) val;
1210 else if (flagword & CHAR)
1211 val = (unsigned char) val;
1212 }
1213 p = bp = buf + MAXLLDIGS;
1214
1215 /* Develop the digits of the value */
1216 if (flagword & XLONG) {
1217 long long lll = ll;
1218
1219 if (lll == 0LL) {
1220 if (!(flagword & DOTSEEN)) {
1221 otherlength = lzero = 1;
1222 flagword |= LZERO;
1223 }
1224 } else do {
1225 *--bp = tab[(ssize_t)(lll & mradix)];
1226 lll = ((lll >> 1) & ~HIBITLL) \
1227 >> lradix;
1228 } while (lll != 0LL);
1229 } else {
1230 long qval = val;
1231
1232 if (qval == 0) {
1233 if (!(flagword & DOTSEEN)) {
1234 otherlength = lzero = 1;
1235 flagword |= LZERO;
1236 }
1237 } else do {
1238 *--bp = tab[qval & mradix];
1239 qval = ((qval >> 1) & ~HIBITL) \
1240 >> lradix;
1241 } while (qval != 0);
1242 }
1243
1244 /* Calculate minimum padding zero requirement */
1245 if (flagword & DOTSEEN) {
1246 leadzeroes = prec - (p - bp);
1247 if (leadzeroes > 0) {
1248 otherlength = lzero = leadzeroes;
1249 flagword |= LZERO;
1250 }
1251 }
1252
1253 /* Handle the # flag, (val != 0) for int and long */
1254 /* (ll!= 0) handles long long case */
1255 if ((flagword & FSHARP) &&
1256 (((flagword & XLONG) == 0 && val != 0) ||
1257 ((flagword & XLONG) == XLONG && ll != 0)))
1258 switch (fcode) {
1259 case 'o':
1260 if (!(flagword & LZERO)) {
1261 otherlength = lzero = 1;
1262 flagword |= LZERO;
1263 }
1264 break;
1265 case 'x':
1266 prefix = _P_ZEROx;
1267 prefixlength = 2;
1268 break;
1269 case 'X':
1270 prefix = _P_ZEROX;
1271 prefixlength = 2;
1272 break;
1273 }
1274
1275 break;
1276
1277 case 'A':
1278 case 'a':
1279 /* A format */
1280 if (flagword & QUAD) {
1281 long double qval = GETQVAL(args.ap);
1282
1283 /* establish default precision */
1284 if (!(flagword & DOTSEEN))
1285 #if defined(__sparc)
1286 prec = HEXFP_QUAD_DIG - 1;
1287 #elif defined(__i386) || defined(__amd64)
1288 prec = HEXFP_EXTENDED_DIG - 1;
1289 #else
1290 #error Unknown architecture
1291 #endif
1292
1293 FPCONV(__qaconvert, &qval,
1294 min(prec + 1, MAXECVT), &exp, &sign,
1295 cvtbuf);
1296 } else {
1297 double dval = va_arg(args.ap, double);
1298
1299 /* establish default precision */
1300 if (!(flagword & DOTSEEN))
1301 prec = HEXFP_DOUBLE_DIG - 1;
1302
1303 FPCONV(__aconvert, dval,
1304 min(prec + 1, MAXECVT), &exp, &sign,
1305 cvtbuf);
1306 }
1307 bp = cvtbuf;
1308
1309 /*
1310 * The following is wide-character safe because
1311 * __aconvert and __qaconvert only produce ASCII
1312 * characters.
1313 */
1314 if (!isxdigit((unsigned char)*bp)) {
1315 inf_nan = 1;
1316 break;
1317 }
1318
1319 /*
1320 * Create the prefix. We ought to use the strings
1321 * defined above (_P_HYPHEN, etc.), but that would
1322 * be awkward: we'd either have to define six more
1323 * of them or we'd have to use strcpy/strcat to
1324 * assemble the ones already defined. So instead,
1325 * we just build the prefix character by character.
1326 */
1327 p = prefix = prefixbuf;
1328 if (sign) {
1329 *p++ = '-';
1330 prefixlength = 1;
1331 } else if (flagword & FPLUS) {
1332 *p++ = '+';
1333 prefixlength = 1;
1334 } else if (flagword & FBLANK) {
1335 *p++ = ' ';
1336 prefixlength = 1;
1337 }
1338 *p++ = '0';
1339 *p++ = (fcode == 'A') ? 'X' : 'x';
1340 *p = '\0';
1341 prefixlength += 2;
1342
1343 /* put the first digit in the buffer */
1344 p = &buf[0];
1345 *p++ = (*bp != '\0') ? *bp++ : '0';
1346
1347 /* put in a decimal point if needed */
1348 if (prec != 0 || (flagword & FSHARP))
1349 *p++ = decimal_point;
1350
1351 /* create the rest of the mantissa */
1352 rz = prec;
1353 if (fcode == 'A') {
1354 for (; rz > 0 && *bp != '\0'; --rz) {
1355 *p++ = ('a' <= *bp && *bp <= 'f')?
1356 *bp - 32 : *bp;
1357 bp++;
1358 }
1359 } else {
1360 for (; rz > 0 && *bp != '\0'; --rz)
1361 *p++ = *bp++;
1362 }
1363 if (rz > 0) {
1364 otherlength = rzero = rz;
1365 flagword |= RZERO;
1366 }
1367
1368 bp = &buf[0];
1369
1370 /*
1371 * Create the exponent in right-to-left order.
1372 * buf[0] == '0' if and only if the value being
1373 * converted is exactly zero, in which case the
1374 * exponent should be +0 regardless of exp.
1375 */
1376 suffix = &expbuf[MAXESIZ];
1377 *suffix = '\0';
1378 if (buf[0] != '0') {
1379 int nn;
1380
1381 nn = exp;
1382 if (nn < 0)
1383 nn = -nn;
1384 for (; nn > 9; nn /= 10)
1385 *--suffix = todigit(nn % 10);
1386 *--suffix = todigit(nn);
1387 *--suffix = (exp >= 0) ? '+' : '-';
1388 } else {
1389 *--suffix = '0';
1390 *--suffix = '+';
1391 }
1392
1393 /* put in the p */
1394 *--suffix = (fcode == 'A') ? 'P' : 'p';
1395
1396 /* compute size of suffix */
1397 suffixlength = &expbuf[MAXESIZ] - suffix;
1398 otherlength += suffixlength;
1399 flagword |= SUFFIX;
1400 break;
1401
1402 case 'E':
1403 case 'e':
1404 /*
1405 * E-format. The general strategy
1406 * here is fairly easy: we take what
1407 * econvert gives us and re-format it.
1408 * (qeconvert for long double)
1409 */
1410
1411 /* Establish default precision */
1412 if (!(flagword & DOTSEEN))
1413 prec = 6;
1414
1415 if (flagword & QUAD) { /* long double */
1416 long double qval = GETQVAL(args.ap);
1417
1418 FPCONV(qeconvert, &qval,
1419 min(prec + 1, MAXECVT), &decpt, &sign,
1420 cvtbuf);
1421 } else { /* double */
1422 double dval = va_arg(args.ap, double);
1423
1424 FPCONV(econvert, dval,
1425 min(prec + 1, MAXECVT), &decpt, &sign,
1426 cvtbuf);
1427 }
1428 bp = cvtbuf;
1429 if (*bp > '9') {
1430 inf_nan = 1;
1431 inf_nan_mixed_case = (__xpg6 &
1432 _C99SUSv3_mixed_case_Inf_and_NaN);
1433 break;
1434 }
1435
1436 /* Determine the prefix */
1437 e_merge:
1438 if (sign) {
1439 prefix = _P_HYPHEN;
1440 prefixlength = 1;
1441 } else if (flagword & FPLUS) {
1442 prefix = _P_PLUS;
1443 prefixlength = 1;
1444 } else if (flagword & FBLANK) {
1445 prefix = _P_BLANK;
1446 prefixlength = 1;
1447 }
1448
1449 /* Place the first digit in the buffer */
1450 p = &buf[0];
1451 *p++ = (*bp != '\0') ? *bp++ : '0';
1452
1453 /* Put in a decimal point if needed */
1454 if (prec != 0 || (flagword & FSHARP))
1455 *p++ = decimal_point;
1456
1457 /* Create the rest of the mantissa */
1458 rz = prec;
1459 for (; rz > 0 && *bp != '\0'; --rz)
1460 *p++ = *bp++;
1461 if (rz > 0) {
1462 otherlength = rzero = rz;
1463 flagword |= RZERO;
1464 }
1465
1466 bp = &buf[0];
1467
1468 /*
1469 * Create the exponent. buf[0] == '0' if and
1470 * only if the value being converted is exactly
1471 * zero, in which case the exponent should be
1472 * +0 regardless of decpt.
1473 */
1474 *(suffix = &expbuf[MAXESIZ]) = '\0';
1475 if (buf[0] != '0') {
1476 int nn = decpt - 1;
1477 if (nn < 0)
1478 nn = -nn;
1479 for (; nn > 9; nn /= 10)
1480 *--suffix = todigit(nn % 10);
1481 *--suffix = todigit(nn);
1482 }
1483
1484 /* Prepend leading zeroes to the exponent */
1485 while (suffix > &expbuf[MAXESIZ - 2])
1486 *--suffix = '0';
1487
1488 /* Put in the exponent sign */
1489 *--suffix = (decpt > 0 || buf[0] == '0') ? '+' : '-';
1490
1491 /* Put in the e */
1492 *--suffix = _M_ISUPPER(fcode) ? 'E' : 'e';
1493
1494 /* compute size of suffix */
1495 otherlength += (suffixlength = &expbuf[MAXESIZ] \
1496 - suffix);
1497 flagword |= SUFFIX;
1498 break;
1499
1500 case 'F':
1501 case 'f':
1502 /*
1503 * F-format floating point. This is a
1504 * good deal less simple than E-format.
1505 * The overall strategy will be to call
1506 * fconvert, reformat its result into buf,
1507 * and calculate how many trailing
1508 * zeroes will be required. There will
1509 * never be any leading zeroes needed.
1510 * (qfconvert for long double)
1511 */
1512
1513 /* Establish default precision */
1514 if (!(flagword & DOTSEEN))
1515 prec = 6;
1516
1517 if (flagword & QUAD) { /* long double */
1518 long double qval = GETQVAL(args.ap);
1519
1520 FPCONV(qfconvert, &qval, min(prec, MAXFCVT),
1521 &decpt, &sign, cvtbuf);
1522 bp = cvtbuf;
1523 if (*bp == 0) {
1524 /*
1525 * qfconvert would have required
1526 * too many characters; use qeconvert
1527 * instead
1528 */
1529 FPCONV(qeconvert, &qval,
1530 min(prec + 1, MAXECVT), &decpt,
1531 &sign, cvtbuf);
1532 goto e_merge;
1533 }
1534 } else { /* double */
1535 double dval = va_arg(args.ap, double);
1536
1537 FPCONV(fconvert, dval, min(prec, MAXFCVT),
1538 &decpt, &sign, cvtbuf);
1539 }
1540 bp = cvtbuf;
1541 if (*bp > '9') {
1542 inf_nan = 1;
1543 if (fcode == 'f')
1544 inf_nan_mixed_case = (__xpg6 &
1545 _C99SUSv3_mixed_case_Inf_and_NaN);
1546 break;
1547 }
1548
1549 /* Determine the prefix */
1550 f_merge:
1551 if (sign) {
1552 prefix = _P_HYPHEN;
1553 prefixlength = 1;
1554 } else if (flagword & FPLUS) {
1555 prefix = _P_PLUS;
1556 prefixlength = 1;
1557 } else if (flagword & FBLANK) {
1558 prefix = _P_BLANK;
1559 prefixlength = 1;
1560 }
1561
1562 /* Initialize buffer pointer */
1563 p = &buf[0];
1564
1565 {
1566 ssize_t nn = decpt;
1567
1568 /* Emit the digits before the decimal point */
1569 k = 0;
1570 do {
1571 *p++ = (nn <= 0 || *bp == '\0' || \
1572 k >= MAXFSIG) ? '0' : (k++, *bp++);
1573 } while (--nn > 0);
1574
1575 if (quote)
1576 p = insert_thousands_sep(buf, p);
1577
1578 /* Decide whether we need a decimal point */
1579 if ((flagword & FSHARP) || prec > 0)
1580 *p++ = decimal_point;
1581
1582 /* Digits (if any) after the decimal point */
1583 nn = min(prec, MAXFCVT);
1584 if (prec > nn) {
1585 flagword |= RZERO;
1586 otherlength = rzero = prec - nn;
1587 }
1588 while (--nn >= 0)
1589 *p++ = (++decpt <= 0 || *bp == '\0' || \
1590 k >= MAXFSIG) ? '0' : (k++, *bp++);
1591 }
1592
1593 bp = &buf[0];
1594
1595 break;
1596
1597 case 'G':
1598 case 'g':
1599 /*
1600 * g-format. We play around a bit
1601 * and then jump into e or f, as needed.
1602 */
1603
1604 /* Establish default precision */
1605 if (!(flagword & DOTSEEN))
1606 prec = 6;
1607 else if (prec == 0)
1608 prec = 1;
1609
1610 if (flagword & QUAD) { /* long double */
1611 long double qval = GETQVAL(args.ap);
1612
1613 FPCONV(qeconvert, &qval, min(prec, MAXECVT),
1614 &decpt, &sign, cvtbuf);
1615 } else { /* double */
1616 double dval = va_arg(args.ap, double);
1617
1618 FPCONV(econvert, dval, min(prec, MAXECVT),
1619 &decpt, &sign, cvtbuf);
1620 }
1621 bp = cvtbuf;
1622 if (*bp > '9') {
1623 inf_nan = 1;
1624 inf_nan_mixed_case = (__xpg6 &
1625 _C99SUSv3_mixed_case_Inf_and_NaN);
1626 break;
1627 }
1628 if (*bp == '0') /* the value converted is zero */
1629 decpt = 1;
1630
1631 {
1632 int kk = prec;
1633 if (!(flagword & FSHARP)) {
1634 #ifdef _WIDE
1635 n = wcslen(bp);
1636 #else /* _WIDE */
1637 n = strlen(bp);
1638 #endif /* _WIDE */
1639 if (n < kk)
1640 kk = (int)n;
1641 while (kk >= 1 && bp[kk-1] == '0')
1642 --kk;
1643 }
1644 if (decpt < -3 || decpt > prec) {
1645 prec = kk - 1;
1646 goto e_merge;
1647 }
1648 prec = kk - decpt;
1649 goto f_merge;
1650 }
1651
1652 case '%':
1653 buf[0] = fcode;
1654 goto c_merge;
1655
1656 #ifndef _WIDE
1657 case 'w':
1658 wflag = 1;
1659 goto charswitch;
1660 #endif /* _WIDE */
1661
1662
1663 case 'C': /* XPG XSH4 extention */
1664 wide_C:
1665 {
1666 wchar_t temp;
1667
1668 temp = va_arg(args.ap, wchar_t);
1669 #ifdef _WIDE
1670 if (temp) {
1671 buf[0] = temp;
1672 p = (bp = buf) + 1;
1673 } else {
1674 buf[0] = 0;
1675 p = (bp = buf) + 1;
1676 }
1677 wcount = 1;
1678 wflag = 1;
1679 #else /* _WIDE */
1680 if (temp) {
1681 if ((retcode = wctomb(buf, temp))
1682 == -1) {
1683 errno = EILSEQ;
1684 return (EOF);
1685 } else {
1686 p = (bp = buf) + retcode;
1687 }
1688 } else { /* NULL character */
1689 buf[0] = 0;
1690 p = (bp = buf) + 1;
1691 }
1692 wcount = p - bp;
1693 #endif /* _WIDE */
1694 }
1695 break;
1696 case 'c':
1697 if (lflag) {
1698 goto wide_C;
1699 }
1700 #ifndef _WIDE
1701 if (wflag) {
1702 wchar_t temp;
1703
1704 temp = va_arg(args.ap, wchar_t);
1705 if (temp) {
1706 if ((retcode = wctomb(buf, temp))
1707 == -1) {
1708 p = (bp = buf) + 1;
1709 } else {
1710 p = (bp = buf) + retcode;
1711 }
1712 } else { /* NULL character */
1713 buf[0] = 0;
1714 p = (bp = buf) + 1;
1715 }
1716 wcount = p - bp;
1717 } else {
1718 #endif /* _WIDE */
1719 if (flagword & XLONG) {
1720 long long temp;
1721 temp = va_arg(args.ap, long long);
1722 #ifdef _WIDE
1723 buf[0] = (wchar_t)temp;
1724 #else /* _WIDE */
1725 buf[0] = (char)temp;
1726 #endif /* _WIDE */
1727 } else
1728 buf[0] = va_arg(args.ap, int);
1729 c_merge:
1730 p = (bp = &buf[0]) + 1;
1731 #ifdef _WIDE
1732 wcount = 1;
1733 wflag = 1;
1734 #endif /* _WIDE */
1735 #ifndef _WIDE
1736 }
1737 #endif /* _WIDE */
1738 break;
1739
1740 case 'S': /* XPG XSH4 extention */
1741 wide_S:
1742 #ifdef _WIDE
1743 if (!lflag) {
1744 lflag++;
1745 }
1746 bp = va_arg(args.ap, wchar_t *);
1747 if (bp == NULL)
1748 bp = (wchar_t *)widenullstr;
1749 if (!(flagword & DOTSEEN)) {
1750 /* wide character handling */
1751 prec = MAXINT;
1752 }
1753
1754 wp = bp;
1755 wcount = 0;
1756 while (*wp) {
1757 if ((prec - wcount - 1) >= 0) {
1758 wcount++;
1759 wp++;
1760 } else {
1761 break;
1762 }
1763 }
1764 p = wp;
1765 wflag = 1;
1766 break;
1767 #else /* _WIDE */
1768 if (!wflag)
1769 wflag++;
1770 bp = va_arg(args.ap, char *);
1771 if (bp == NULL)
1772 bp = (char *)widenullstr;
1773 if (!(flagword & DOTSEEN)) {
1774 /* wide character handling */
1775 prec = MAXINT;
1776 }
1777
1778 wp = (wchar_t *)(uintptr_t)bp;
1779 wcount = 0;
1780 while (*wp) {
1781 int nbytes;
1782
1783 nbytes = wctomb(tmpbuf, *wp);
1784 if (nbytes < 0) {
1785 errno = EILSEQ;
1786 return (EOF);
1787 }
1788 if ((prec - (wcount + nbytes)) >= 0) {
1789 wcount += nbytes;
1790 wp++;
1791 } else {
1792 break;
1793 }
1794 }
1795 sec_display = wcount;
1796 p = (char *)wp;
1797 break;
1798 #endif /* _WIDE */
1799 case 's':
1800 if (lflag) {
1801 goto wide_S;
1802 }
1803 #ifdef _WIDE
1804 cbp = va_arg(args.ap, char *);
1805 if (cbp == NULL)
1806 cbp = (char *)nullstr;
1807 if (!(flagword & DOTSEEN)) {
1808 size_t nwc;
1809 wchar_t *wstr;
1810
1811 nwc = mbstowcs(NULL, cbp, 0);
1812 if (nwc == (size_t)-1) {
1813 errno = EILSEQ;
1814 return (EOF);
1815 }
1816 bpsize = sizeof (wchar_t) * (nwc + 1);
1817 wstr = (wchar_t *)lmalloc(bpsize);
1818 if (wstr == NULL) {
1819 errno = EILSEQ;
1820 return (EOF);
1821 }
1822 nwc = mbstowcs(wstr, cbp, MAXINT);
1823 wcount = nwc;
1824 bp = wstr;
1825 p = wstr + nwc;
1826 } else {
1827 size_t nwc;
1828 wchar_t *wstr;
1829
1830 nwc = mbstowcs(NULL, cbp, 0);
1831 if (nwc == (size_t)-1) {
1832 errno = EILSEQ;
1833 return (EOF);
1834 }
1835 if (prec > nwc) {
1836 bpsize = sizeof (wchar_t) * nwc;
1837 wstr = (wchar_t *)lmalloc(bpsize);
1838 if (wstr == NULL) {
1839 errno = ENOMEM;
1840 return (EOF);
1841 }
1842 nwc = mbstowcs(wstr, cbp, nwc);
1843 cp = cbp + strlen(cbp);
1844 wcount = nwc;
1845 bp = wstr;
1846 p = wstr + nwc;
1847 } else {
1848 size_t nnwc;
1849 int len;
1850 char *s;
1851 wchar_t *wstr;
1852
1853 bpsize = sizeof (wchar_t) * prec;
1854 wstr = (wchar_t *)lmalloc(bpsize);
1855 if (wstr == NULL) {
1856 errno = ENOMEM;
1857 return (EOF);
1858 }
1859 nwc = mbstowcs(wstr, cbp, prec);
1860 wcount = prec;
1861 bp = wstr;
1862 p = wstr + nwc;
1863 }
1864 }
1865 wflag = 1;
1866 #else /* _WIDE */
1867 bp = va_arg(args.ap, char *);
1868 if (bp == NULL)
1869 bp = (char *)nullstr;
1870 if (!(flagword & DOTSEEN)) {
1871 if (wflag) {
1872 /* wide character handling */
1873 prec = MAXINT;
1874 goto wide_hand;
1875 }
1876
1877
1878 p = bp + strlen(bp);
1879
1880 /*
1881 * sec_display only needed if width
1882 * is specified (ie, "%<width>s")
1883 * Solaris behavior counts <width> in
1884 * screen column width. (If XPG4 behavior,
1885 * <width> is counted in bytes.)
1886 */
1887 if (width > 0 && __xpg4 == 0 &&
1888 MB_CUR_MAX > 1) {
1889 #define NW 256
1890 wchar_t wbuff[NW];
1891 wchar_t *wp, *wptr;
1892 size_t wpsize;
1893 size_t nwc;
1894
1895 wp = NULL;
1896 if ((nwc = mbstowcs(wbuff, bp,
1897 NW)) == (size_t)-1) {
1898 /* Estimate width */
1899 sec_display = strlen(bp);
1900 goto mbs_err;
1901 }
1902 if (nwc < NW) {
1903 wptr = wbuff;
1904 } else {
1905 /*
1906 * If widechar does not fit into
1907 * wbuff, allocate larger buffer
1908 */
1909 if ((nwc =
1910 mbstowcs(NULL, bp, NULL)) ==
1911 (size_t)-1) {
1912 sec_display =
1913 strlen(bp);
1914 goto mbs_err;
1915 }
1916 wpsize = (nwc + 1) *
1917 sizeof (wchar_t);
1918 if ((wp = lmalloc(wpsize))
1919 == NULL) {
1920 errno = ENOMEM;
1921 return (EOF);
1922 }
1923 if ((nwc = mbstowcs(wp,
1924 bp, nwc)) == (size_t)-1) {
1925 sec_display = \
1926 strlen(bp);
1927 goto mbs_err;
1928 }
1929 wptr = wp;
1930 }
1931 if ((sec_display = wcswidth(wptr, nwc))
1932 == -1) {
1933 sec_display =
1934 _rec_scrswidth
1935 (wptr, nwc);
1936 }
1937 mbs_err:
1938 if (wp)
1939 lfree(wp, wpsize);
1940 }
1941 } else { /* a strnlen function would be useful here! */
1942 /*
1943 * If we've seen a dot, and count has been set
1944 * to 0, then we don't output in any cases
1945 * below. prec should be always >= 0. So we only
1946 * check to see if it's zero.
1947 */
1948 if (prec == 0) {
1949 p = bp;
1950 break;
1951 }
1952
1953 if (wflag) {
1954 /* wide character handling */
1955
1956 wide_hand:
1957 wp = (wchar_t *)(uintptr_t)bp;
1958 preco = prec;
1959 wcount = 0;
1960 while (*wp &&
1961 (prec -= _scrwidth(*wp)) >= 0) {
1962 if ((retcode =
1963 wctomb(tmpbuf, *wp)) < 0)
1964 wcount++;
1965 else
1966 wcount += retcode;
1967 wp++;
1968 }
1969 if (*wp)
1970 prec += _scrwidth(*wp);
1971 p = (char *)wp;
1972 sec_display = preco - prec;
1973 } else if (__xpg4 == 0 && MB_CUR_MAX > 1) {
1974 /*
1975 * Solaris behavior - count
1976 * precision as screen column width
1977 */
1978 char *qp = bp;
1979 int ncol, nbytes;
1980 wchar_t wc;
1981
1982 ncol = 0;
1983 preco = prec;
1984 while (*qp) {
1985 if (isascii(*qp)) {
1986 qp++;
1987 if (--prec == 0)
1988 break;
1989 continue;
1990 }
1991 if ((nbytes = mbtowc(&wc, qp,
1992 MB_LEN_MAX)) == -1) {
1993 /* print illegal char */
1994 nbytes = 1;
1995 ncol = 1;
1996 } else {
1997 if ((ncol =
1998 _scrwidth(wc))
1999 == 0) {
2000 ncol = 1;
2001 }
2002 }
2003
2004 if ((prec -= ncol) >= 0) {
2005 qp += nbytes;
2006 if (prec == 0)
2007 break;
2008 } else {
2009 break;
2010 }
2011 }
2012 if (prec < 0)
2013 prec += ncol;
2014 p = qp;
2015 sec_display = preco - prec;
2016 } else {
2017 /*
2018 * XPG4 behavior - count
2019 * precision as bytes.
2020 * We don't use strlen() because
2021 * the given char string may not
2022 * be null-terminated.
2023 */
2024 char *qp;
2025
2026 qp = memchr(bp, '\0', prec);
2027 if (qp == NULL) {
2028 p = bp + prec;
2029 } else {
2030 p = qp;
2031 }
2032 }
2033 }
2034 #endif /* _WIDE */
2035 break;
2036
2037 case 'n':
2038 {
2039 if (flagword & XLONG) {
2040 long long *svcount;
2041 svcount = va_arg(args.ap, long long *);
2042 *svcount = (long long)count;
2043 } else if (flagword & LENGTH) {
2044 long *svcount;
2045 svcount = va_arg(args.ap, long *);
2046 *svcount = (long)count;
2047 } else if (flagword & SHORT) {
2048 short *svcount;
2049 svcount = va_arg(args.ap, short *);
2050 *svcount = (short)count;
2051 } else if (flagword & CHAR) {
2052 char *svcount;
2053 svcount = va_arg(args.ap, char *);
2054 *svcount = (char)count;
2055 } else {
2056 int *svcount;
2057 svcount = va_arg(args.ap, int *);
2058 *svcount = count;
2059 }
2060 continue;
2061 }
2062 default: /* this is technically an error; what we do is to */
2063 /* back up the format pointer to the offending char */
2064 /* and continue with the format scan */
2065 format--;
2066 continue;
2067 }
2068
2069 if (inf_nan) {
2070 if (inf_nan_mixed_case) {
2071 /* advance p */
2072 for (p = bp + 1; *p != '\0'; p++)
2073 ;
2074 } else {
2075 int upper;
2076
2077 /* advance p and make output all one case */
2078 upper = _M_ISUPPER(fcode);
2079 for (p = bp; *p != '\0'; p++)
2080 *p = upper? toupper(*p) : tolower(*p);
2081 }
2082 if (sign) {
2083 prefix = _P_HYPHEN;
2084 prefixlength = 1;
2085 } else if (flagword & FPLUS) {
2086 prefix = _P_PLUS;
2087 prefixlength = 1;
2088 } else if (flagword & FBLANK) {
2089 prefix = _P_BLANK;
2090 prefixlength = 1;
2091 }
2092 inf_nan = 0;
2093 inf_nan_mixed_case = 0;
2094 flagword &= ~PADZERO; /* ignore 0 flag */
2095 }
2096
2097 /* Calculate number of padding blanks */
2098 n = p - bp; /* n == size of the converted value (in bytes) */
2099
2100 #ifdef _WIDE
2101 k = n;
2102 #else /* _WIDE */
2103 if (sec_display) /* when format is %s or %ws or %S */
2104 k = sec_display;
2105 else
2106 k = n;
2107 #endif /* _WIDE */
2108 /*
2109 * k is the (screen) width or # of bytes of the converted value
2110 */
2111 k += prefixlength + otherlength;
2112
2113 #ifdef _WIDE
2114 if (wflag) {
2115 count += wcount;
2116 } else {
2117 count += n;
2118 }
2119 #else /* _WIDE */
2120 /*
2121 * update count which is the overall size of the output data
2122 * and passed to memchr()
2123 */
2124 if (wflag)
2125 /*
2126 * when wflag != 0 (i.e. %ws or %wc), the size of the
2127 * converted value is wcount bytes
2128 */
2129 count += wcount;
2130 else
2131 /*
2132 * when wflag == 0, the size of the converted
2133 * value is n (= p-bp) bytes
2134 */
2135 count += n;
2136 #endif /* _WIDE */
2137 count += prefixlength + otherlength;
2138
2139 if (width > k) {
2140 count += (width - k);
2141 /*
2142 * Set up for padding zeroes if requested
2143 * Otherwise emit padding blanks unless output is
2144 * to be left-justified.
2145 */
2146
2147 if (flagword & PADZERO) {
2148 if (!(flagword & LZERO)) {
2149 flagword |= LZERO;
2150 lzero = width - k;
2151 } else
2152 lzero += width - k;
2153 k = width; /* cancel padding blanks */
2154 } else
2155 /* Blanks on left if required */
2156 if (!(flagword & FMINUS))
2157 PAD(_blanks, width - k);
2158 }
2159
2160 /* Prefix, if any */
2161 if (prefixlength != 0)
2162 PUT(prefix, prefixlength);
2163
2164 /* Zeroes on the left */
2165 if ((flagword & LZERO)) /* && */
2166 /* (!(flagword & SHORT) || !(flagword & FMINUS)) */
2167 PAD(_zeroes, lzero);
2168
2169 #ifdef _WIDE
2170 if (n > 0)
2171 PUT(bp, n);
2172 if ((fcode == 's') && !lflag) {
2173 if (bp)
2174 lfree(bp, bpsize);
2175 }
2176 #else /* _WIDE */
2177 /* The value itself */
2178 if ((fcode == 's' || fcode == 'S') && wflag) {
2179 /* wide character handling */
2180 wchar_t *wp = (wchar_t *)(uintptr_t)bp;
2181 int cnt;
2182 char *bufp;
2183 long printn;
2184 printn = (wchar_t *)(uintptr_t)p -
2185 (wchar_t *)(uintptr_t)bp;
2186 bufp = buf;
2187 while (printn > 0) {
2188 if ((cnt = wctomb(buf, *wp)) < 0)
2189 cnt = 1;
2190 PUT(bufp, cnt);
2191 wp++;
2192 printn--;
2193 }
2194 } else { /* non wide character value */
2195 if (n > 0)
2196 PUT(bp, n);
2197 }
2198 #endif /* _WIDE */
2199
2200 if (flagword & (RZERO | SUFFIX | FMINUS)) {
2201 /* Zeroes on the right */
2202 if (flagword & RZERO)
2203 PAD(_zeroes, rzero);
2204
2205 /* The suffix */
2206 if (flagword & SUFFIX)
2207 PUT(suffix, suffixlength);
2208
2209 /* Blanks on the right if required */
2210 if (flagword & FMINUS && width > k)
2211 PAD(_blanks, width - k);
2212 }
2213 }
2214 }
2215
2216 #ifdef _WIDE
2217 static int
_watoi(wchar_t * fmt)2218 _watoi(wchar_t *fmt)
2219 {
2220 int n = 0;
2221 wchar_t ch;
2222
2223 ch = *fmt;
2224 if (_M_ISDIGIT(ch)) {
2225 n = ch - '0';
2226 ch = *++fmt;
2227 while (_M_ISDIGIT(ch)) {
2228 n *= 10;
2229 n += ch - '0';
2230 ch = *++fmt;
2231 }
2232 }
2233 return (n);
2234 }
2235 #endif /* _WIDE */
2236
2237 /*
2238 * This function initializes arglst, to contain the appropriate va_list values
2239 * for the first MAXARGS arguments.
2240 */
2241
2242 /*
2243 * Type modifier flags:
2244 * 0x01 for long
2245 * 0x02 for int
2246 * 0x04 for long long
2247 * 0x08 for long double
2248 */
2249
2250 #define FLAG_LONG 0x01
2251 #define FLAG_INT 0x02
2252 #define FLAG_LONG_LONG 0x04
2253 #define FLAG_LONG_DBL 0x08
2254
2255 /* ARGSUSED3 */
2256 #ifdef _WIDE
2257 static void
_wmkarglst(wchar_t * fmt,stva_list args,stva_list arglst[],int prflag)2258 _wmkarglst(wchar_t *fmt, stva_list args, stva_list arglst[], int prflag)
2259 #else /* _WIDE */
2260 static void
2261 _mkarglst(char *fmt, stva_list args, stva_list arglst[], int prflag)
2262 #endif /* _WIDE */
2263 {
2264 #ifdef _WIDE
2265 static const wchar_t digits[] = L"01234567890";
2266 static const wchar_t skips[] = L"# +-.'0123456789h$";
2267 #else /* _WIDE */
2268 static const char digits[] = "01234567890";
2269 static const char skips[] = "# +-.'0123456789h$";
2270 #endif /* _WIDE */
2271 enum types {INT = 1, LONG, CHAR_PTR, DOUBLE, LONG_DOUBLE, VOID_PTR,
2272 LONG_PTR, INT_PTR, LONG_LONG, LONG_LONG_PTR};
2273 enum types typelst[MAXARGS], curtype;
2274 ssize_t n;
2275 int maxnum, curargno, flags;
2276
2277 /*
2278 * Algorithm 1. set all argument types to zero.
2279 * 2. walk through fmt putting arg types in typelst[].
2280 * 3. walk through args using va_arg(args.ap, typelst[n])
2281 * and set arglst[] to the appropriate values.
2282 * Assumptions: Cannot use %*$... to specify variable position.
2283 */
2284
2285 (void) memset((void *) typelst, 0, sizeof (typelst));
2286 maxnum = -1;
2287 curargno = 0;
2288 while ((fmt = STRCHR(fmt, '%')) != 0) {
2289 fmt++; /* skip % */
2290 if (fmt[n = STRSPN(fmt, digits)] == '$') {
2291 /* convert to zero base */
2292 curargno = ATOI(fmt) - 1;
2293 if (curargno < 0)
2294 continue;
2295 fmt += n + 1;
2296 }
2297 flags = 0;
2298 again:;
2299 fmt += STRSPN(fmt, skips);
2300 switch (*fmt++) {
2301 case '%': /* there is no argument! */
2302 continue;
2303 case 'l':
2304 if (flags & (FLAG_LONG | FLAG_LONG_LONG)) {
2305 flags |= FLAG_LONG_LONG;
2306 flags &= ~FLAG_LONG;
2307 } else {
2308 flags |= FLAG_LONG;
2309 }
2310 goto again;
2311 case 'j':
2312 #ifndef _LP64
2313 /*
2314 * *printf_c89() in 32-bit libc uses
2315 * 32-bit intmax_t; otherwise intmax_t
2316 * is 64-bits.
2317 */
2318 if (!(prflag & _F_INTMAX32)) {
2319 #endif
2320 flags |= FLAG_LONG_LONG; /* 64-bit */
2321 #ifndef _LP64
2322 }
2323 #endif
2324 goto again;
2325 case 't':
2326 flags |= FLAG_LONG;
2327 goto again;
2328 case 'z':
2329 flags |= FLAG_LONG;
2330 goto again;
2331 case 'L':
2332 flags |= FLAG_LONG_DBL;
2333 goto again;
2334 case '*': /* int argument used for value */
2335 /* check if there is a positional parameter */
2336 #ifdef _WIDE
2337 if ((*fmt >= 0) && (*fmt < 256) &&
2338 isdigit(*fmt))
2339 #else /* _WIDE */
2340 if (isdigit(*fmt))
2341 #endif /* _WIDE */
2342 {
2343 int targno;
2344 targno = ATOI(fmt) - 1;
2345 fmt += STRSPN(fmt, digits);
2346 if (*fmt == '$')
2347 fmt++; /* skip '$' */
2348 if (targno >= 0 && targno < MAXARGS) {
2349 typelst[targno] = INT;
2350 if (maxnum < targno)
2351 maxnum = targno;
2352 }
2353 goto again;
2354 }
2355 flags |= FLAG_INT;
2356 curtype = INT;
2357 break;
2358 case 'a':
2359 case 'A':
2360 case 'e':
2361 case 'E':
2362 case 'f':
2363 case 'F':
2364 case 'g':
2365 case 'G':
2366 if (flags & FLAG_LONG_DBL)
2367 curtype = LONG_DOUBLE;
2368 else
2369 curtype = DOUBLE;
2370 break;
2371 case 's':
2372 curtype = CHAR_PTR;
2373 break;
2374 case 'p':
2375 curtype = VOID_PTR;
2376 break;
2377 case 'n':
2378 if (flags & FLAG_LONG_LONG)
2379 curtype = LONG_LONG_PTR;
2380 else if (flags & FLAG_LONG)
2381 curtype = LONG_PTR;
2382 else
2383 curtype = INT_PTR;
2384 break;
2385 default:
2386 if (flags & FLAG_LONG_LONG)
2387 curtype = LONG_LONG;
2388 else if (flags & FLAG_LONG)
2389 curtype = LONG;
2390 else
2391 curtype = INT;
2392 break;
2393 }
2394 if (curargno >= 0 && curargno < MAXARGS) {
2395 typelst[curargno] = curtype;
2396 if (maxnum < curargno)
2397 maxnum = curargno;
2398 }
2399 curargno++; /* default to next in list */
2400 if (flags & FLAG_INT) /* took care of *, keep going */
2401 {
2402 flags ^= FLAG_INT;
2403 goto again;
2404 }
2405 }
2406 for (n = 0; n <= maxnum; n++) {
2407 arglst[n] = args;
2408 if (typelst[n] == 0)
2409 typelst[n] = INT;
2410
2411 switch (typelst[n]) {
2412 case INT:
2413 (void) va_arg(args.ap, int);
2414 break;
2415 case LONG:
2416 (void) va_arg(args.ap, long);
2417 break;
2418 case CHAR_PTR:
2419 (void) va_arg(args.ap, char *);
2420 break;
2421 case DOUBLE:
2422 (void) va_arg(args.ap, double);
2423 break;
2424 case LONG_DOUBLE:
2425 (void) GETQVAL(args.ap);
2426 break;
2427 case VOID_PTR:
2428 (void) va_arg(args.ap, void *);
2429 break;
2430 case LONG_PTR:
2431 (void) va_arg(args.ap, long *);
2432 break;
2433 case INT_PTR:
2434 (void) va_arg(args.ap, int *);
2435 break;
2436 case LONG_LONG:
2437 (void) va_arg(args.ap, long long);
2438 break;
2439 case LONG_LONG_PTR:
2440 (void) va_arg(args.ap, long long *);
2441 break;
2442 }
2443 }
2444 }
2445
2446 /*
2447 * This function is used to find the va_list value for arguments whose
2448 * position is greater than MAXARGS. This function is slow, so hopefully
2449 * MAXARGS will be big enough so that this function need only be called in
2450 * unusual circumstances.
2451 * pargs is assumed to contain the value of arglst[MAXARGS - 1].
2452 */
2453 /* ARGSUSED3 */
2454 #ifdef _WIDE
2455 static void
_wgetarg(wchar_t * fmt,stva_list * pargs,long argno,int prflag)2456 _wgetarg(wchar_t *fmt, stva_list *pargs, long argno, int prflag)
2457 #else /* _WIDE */
2458 void
2459 _getarg(char *fmt, stva_list *pargs, long argno, int prflag)
2460 #endif /* _WIDE */
2461 {
2462
2463 #ifdef _WIDE
2464 static const wchar_t digits[] = L"01234567890";
2465 static const wchar_t skips[] = L"# +-.'0123456789h$";
2466 wchar_t *sfmt = fmt;
2467 #else /* _WIDE */
2468 static const char digits[] = "01234567890";
2469 static const char skips[] = "# +-.'0123456789h$";
2470 char *sfmt = fmt;
2471 #endif /* _WIDE */
2472 ssize_t n;
2473 int i, curargno, flags;
2474 int found = 1;
2475
2476 i = MAXARGS;
2477 curargno = 1;
2478 while (found) {
2479 fmt = sfmt;
2480 found = 0;
2481 while ((i != argno) && (fmt = STRCHR(fmt, '%')) != 0) {
2482 fmt++; /* skip % */
2483 if (fmt[n = STRSPN(fmt, digits)] == '$') {
2484 curargno = ATOI(fmt);
2485 if (curargno <= 0)
2486 continue;
2487 fmt += n + 1;
2488 }
2489
2490 /* find conversion specifier for next argument */
2491 if (i != curargno) {
2492 curargno++;
2493 continue;
2494 } else
2495 found = 1;
2496 flags = 0;
2497 again:;
2498 fmt += STRSPN(fmt, skips);
2499 switch (*fmt++) {
2500 case '%': /* there is no argument! */
2501 continue;
2502 case 'l':
2503 if (flags & (FLAG_LONG | FLAG_LONG_LONG)) {
2504 flags |= FLAG_LONG_LONG;
2505 flags &= ~FLAG_LONG;
2506 } else {
2507 flags |= FLAG_LONG;
2508 }
2509 goto again;
2510 case 'j':
2511 #ifndef _LP64
2512 /*
2513 * *printf_c89() in 32-bit libc uses
2514 * 32-bit intmax_t; otherwise intmax_t
2515 * is 64-bits.
2516 */
2517 if (!(prflag & _F_INTMAX32)) {
2518 #endif
2519 flags |= FLAG_LONG_LONG; /* 64-bit */
2520 #ifndef _LP64
2521 }
2522 #endif
2523 goto again;
2524 case 't':
2525 flags |= FLAG_LONG;
2526 goto again;
2527 case 'z':
2528 flags |= FLAG_LONG;
2529 goto again;
2530 case 'L':
2531 flags |= FLAG_LONG_DBL;
2532 goto again;
2533 case '*': /* int argument used for value */
2534 /*
2535 * check if there is a positional parameter;
2536 * if so, just skip it; its size will be
2537 * correctly determined by default
2538 */
2539 if (_M_ISDIGIT(*fmt)) {
2540 fmt += STRSPN(fmt, digits);
2541 if (*fmt == '$')
2542 fmt++; /* skip '$' */
2543 goto again;
2544 }
2545 flags |= FLAG_INT;
2546 (void) va_arg((*pargs).ap, int);
2547 break;
2548 case 'a':
2549 case 'A':
2550 case 'e':
2551 case 'E':
2552 case 'f':
2553 case 'F':
2554 case 'g':
2555 case 'G':
2556 if (flags & FLAG_LONG_DBL)
2557 (void) GETQVAL((*pargs).ap);
2558 else
2559 (void) va_arg((*pargs).ap, double);
2560 break;
2561 case 's':
2562 (void) va_arg((*pargs).ap, char *);
2563 break;
2564 case 'p':
2565 (void) va_arg((*pargs).ap, void *);
2566 break;
2567 case 'n':
2568 if (flags & FLAG_LONG_LONG)
2569 (void) va_arg((*pargs).ap, long long *);
2570 else if (flags & FLAG_LONG)
2571 (void) va_arg((*pargs).ap, long *);
2572 else
2573 (void) va_arg((*pargs).ap, int *);
2574 break;
2575 default:
2576 if (flags & FLAG_LONG_LONG)
2577 (void) va_arg((*pargs).ap, long long);
2578 else if (flags & FLAG_LONG)
2579 (void) va_arg((*pargs).ap, long int);
2580 else
2581 (void) va_arg((*pargs).ap, int);
2582 break;
2583 }
2584 i++;
2585 curargno++; /* default to next in list */
2586 if (flags & FLAG_INT) /* took care of *, keep going */
2587 {
2588 flags ^= FLAG_INT;
2589 goto again;
2590 }
2591 }
2592
2593 /* missing specifier for parameter, assume param is an int */
2594 if (!found && i != argno) {
2595 (void) va_arg((*pargs).ap, int);
2596 i++;
2597 curargno = i;
2598 found = 1;
2599 }
2600 }
2601 }
2602
2603 #ifdef _WIDE
2604 static wchar_t *
insert_thousands_sep(wchar_t * bp,wchar_t * ep)2605 insert_thousands_sep(wchar_t *bp, wchar_t *ep)
2606 #else /* _WIDE */
2607 static char *
2608 insert_thousands_sep(char *bp, char *ep)
2609 #endif /* _WIDE */
2610 {
2611 char thousep;
2612 struct lconv *locptr;
2613 ssize_t buf_index;
2614 int i;
2615 #ifdef _WIDE
2616 wchar_t *obp = bp;
2617 wchar_t buf[371];
2618 wchar_t *bufptr = buf;
2619 #else /* _WIDE */
2620 char *obp = bp;
2621 char buf[371];
2622 char *bufptr = buf;
2623 #endif /* _WIDE */
2624 char *grp_ptr;
2625
2626 /* get the thousands sep. from the current locale */
2627 locptr = localeconv();
2628 thousep = *locptr->thousands_sep;
2629 grp_ptr = locptr->grouping;
2630
2631 /* thousands sep. not use in this locale or no grouping required */
2632 if (!thousep || (*grp_ptr == '\0'))
2633 return (ep);
2634
2635 buf_index = ep - bp;
2636 for (;;) {
2637 if (*grp_ptr == CHAR_MAX) {
2638 for (i = 0; i < buf_index--; i++)
2639 *bufptr++ = *(bp + buf_index);
2640 break;
2641 }
2642 for (i = 0; i < *grp_ptr && buf_index-- > 0; i++)
2643 *bufptr++ = *(bp + buf_index);
2644
2645 if (buf_index > 0) {
2646 #ifdef _WIDE
2647 *bufptr++ = (wchar_t)thousep;
2648 #else /* _WIDE */
2649 *bufptr++ = thousep;
2650 #endif /* _WIDE */
2651 ep++;
2652 }
2653 else
2654 break;
2655 if (*(grp_ptr + 1) != '\0')
2656 ++grp_ptr;
2657 }
2658
2659 /* put the string in the caller's buffer in reverse order */
2660 --bufptr;
2661 while (buf <= bufptr)
2662 *obp++ = *bufptr--;
2663 return (ep);
2664 }
2665
2666
2667 /*
2668 * Recovery scrswidth function -
2669 * this variant of wcswidth() accepts non-printable or illegal
2670 * widechar characters.
2671 */
2672 static int
_rec_scrswidth(wchar_t * wp,ssize_t n)2673 _rec_scrswidth(wchar_t *wp, ssize_t n)
2674 {
2675 int col;
2676 int i;
2677
2678 col = 0;
2679 while (*wp && (n-- > 0)) {
2680 if ((i = _scrwidth(*wp++)) == 0)
2681 i = 1;
2682 col += i;
2683 }
2684 return (col);
2685 }
2686