9511 printf family isn't aware of multibyte decimal point characters (fix regression)
[unleashed.git] / usr / src / lib / libc / port / print / doprnt.c
blobe8cfaad6debfc5394f88bc02d46c460e154a3d5c
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1988 AT&T */
28 /* All Rights Reserved */
31 * _doprnt: common code for printf, fprintf, sprintf
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"
55 static const char nullstr[] = "(null)";
56 static const wchar_t widenullstr[] = L"(null)";
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) */
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 */
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 } \
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); \
107 #define FPCONV(func, val, prec, decpt, sign, cvtbuf) \
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++; \
118 *wp = L'\0'; \
121 #else /* _WIDE */
122 #define PUT(p, n) \
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. \
132 if (snflag || bufptr > bufferend ||\
133 (unsigned long)(bufferend - bufptr) < (n)) {\
134 if (!_dowrite(p, n, iop, &bufptr)) {\
135 return (EOF);\
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);\
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); \
175 #define FPCONV(func, val, prec, decpt, sign, cvtbuf) \
176 (void) func(val, prec, decpt, sign, cvtbuf);
178 #endif /* _WIDE */
180 /* bit positions for flags used in doprnt */
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 */
197 #ifdef _WIDE
198 static wchar_t *insert_decimal_point(wchar_t *ep);
199 static wchar_t *insert_thousands_sep(wchar_t *bp, wchar_t *ep);
200 #else /* _WIDE */
201 static char *insert_decimal_point(char *ep);
202 static char *insert_thousands_sep(char *bp, char *ep);
203 #endif /* _WIDE */
205 static int _rec_scrswidth(wchar_t *, ssize_t);
208 * Positional Parameter information
210 #define MAXARGS 30 /* max. number of args for fast positional paramters */
212 static ssize_t
213 _dowrite(const char *p, ssize_t n, FILE *iop, unsigned char **ptrptr);
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..
221 typedef struct stva_list {
222 va_list ap;
223 } stva_list;
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 */
236 static int
237 _lowdigit(ssize_t *valptr)
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. */
244 ssize_t lowbit = *valptr & 1;
245 long value = (*valptr >> 1) & ~HIBITL;
247 *valptr = value / 5;
248 value = value % 5 * 2 + lowbit + '0';
249 return ((int)value);
252 static int
253 _lowlldigit(long long *valptr)
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);
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. */
266 static ssize_t
267 _dowrite(const char *p, ssize_t n, FILE *iop, unsigned char **ptrptr)
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);
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;
284 return (1);
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 */
298 #ifdef _WIDE
299 static int
300 put_wide(FILE *iop, unsigned char **bufptr,
301 unsigned char *bufferend, wchar_t *p, size_t n,
302 int sflag)
304 unsigned char *newbufptr;
305 wchar_t *q;
306 int r;
307 size_t len, i;
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);
320 } else {
321 char *tmpp, *tmpq;
322 size_t tsize;
324 tsize = (n + 1) * MB_LEN_MAX;
325 tmpp = lmalloc(tsize);
326 if (tmpp == NULL) {
327 errno = ENOMEM;
328 return (EOF);
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);
339 len += r;
340 tmpq += r;
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);
349 } else {
350 (void) memcpy(*bufptr, tmpp, len);
351 *bufptr = newbufptr;
353 lfree(tmpp, tsize);
354 return (0);
358 static int
359 pad_wide(FILE *iop, unsigned char **bufptr,
360 unsigned char *bufferend, const char *s, size_t n,
361 int sflag)
363 unsigned char *newbufptr;
364 ssize_t nn;
365 size_t len;
366 wchar_t ps;
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);
381 } else {
382 for (nn = n; nn > PAD_LEN; nn -= PAD_LEN) {
383 if (!_dowrite(s, PAD_LEN, iop, bufptr))
384 return (EOF);
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;
394 return (0);
397 #endif /* _WIDE */
399 #ifdef _WIDE
400 ssize_t
401 _wdoprnt(const wchar_t *format, va_list in_args, FILE *iop)
403 return (_wndoprnt(format, in_args, iop, 0));
405 #else /* _WIDE */
406 ssize_t
407 _doprnt(const char *format, va_list in_args, FILE *iop)
409 return (_ndoprnt(format, in_args, iop, 0));
411 #endif /* _WIDE */
414 #ifdef _WIDE
415 ssize_t
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 */
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. */
436 unsigned char *bufptr;
437 unsigned char *bufferend;
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 */
447 #ifdef _WIDE
448 wchar_t *bp;
449 size_t bpsize;
450 wchar_t *p;
451 char *cbp;
453 #else /* _WIDE */
454 /* Starting and ending points for value to be printed */
455 char *bp;
456 char *p;
457 #endif /* _WIDE */
458 /* Field width and precision */
459 int prec = 0;
460 ssize_t width;
461 ssize_t num;
462 wchar_t *wp;
463 ssize_t preco;
464 ssize_t wcount = 0;
465 char tmpbuf[10];
466 char wflag;
467 char lflag;
468 int quote; /* ' */
469 int retcode;
471 #ifdef _WIDE
472 /* Format code */
473 wchar_t fcode;
474 #else /* _WIDE */
475 /* Format code */
476 char fcode;
477 ssize_t sec_display;
478 #endif /* _WIDE */
480 /* Number of padding zeroes required on the left and right */
481 ssize_t lzero, rzero, rz, leadzeroes;
484 /* Flags - bit positions defined by LENGTH, FPLUS, FMINUS, FBLANK, */
485 /* and FSHARP are set if corresponding character is in format */
486 /* Bit position defined by PADZERO means extra space in the field */
487 /* should be padded with leading zeroes rather than with blanks */
489 ssize_t flagword;
491 #ifdef _WIDE
492 /* Values are developed in this buffer */
493 wchar_t buf[max(MAXLLDIGS, 1034)];
494 wchar_t cvtbuf[512 + DECIMAL_STRING_LENGTH];
496 /* Pointer to sign, "0x", "0X", or empty */
497 wchar_t *prefix;
498 wchar_t prefixbuf[4];
500 /* Exponent or empty */
501 wchar_t *suffix;
503 /* Buffer to create exponent */
504 wchar_t expbuf[MAXESIZ + 1];
505 #else /* _WIDE */
506 /* Values are developed in this buffer */
507 char buf[max(MAXLLDIGS, 1034)];
508 char cvtbuf[512 + DECIMAL_STRING_LENGTH];
510 /* Pointer to sign, "0x", "0X", or empty */
511 char *prefix;
512 char prefixbuf[4];
514 /* Exponent or empty */
515 char *suffix;
517 /* Buffer to create exponent */
518 char expbuf[MAXESIZ + 1];
519 #endif /* _WIDE */
521 /* Length of prefix and of suffix */
522 ssize_t prefixlength, suffixlength;
524 /* Combined length of leading zeroes, trailing zeroes, and suffix */
525 ssize_t otherlength;
527 /* The value being converted, if integer */
528 ssize_t val;
530 /* The value being converted, if long long */
531 long long ll = 0LL;
533 /* Output value from aconvert */
534 int exp;
536 /* Output values from fcvt and ecvt */
537 int decpt, sign;
539 #ifdef _WIDE
540 /* Pointer to a translate table for digits of whatever radix */
541 const wchar_t *tab;
542 #else /* _WIDE */
543 /* Pointer to a translate table for digits of whatever radix */
544 const char *tab;
545 #endif /* _WIDE */
547 /* Work variables */
548 ssize_t k, lradix, mradix;
550 int inf_nan = 0;
551 int inf_nan_mixed_case = 0;
553 #ifdef _WIDE
554 /* variables for positional parameters */
555 /* save the beginning of the format */
556 wchar_t *sformat = (wchar_t *)format;
557 #else /* _WIDE */
558 /* variables for positional parameters */
559 char *sformat = (char *)format; /* save the beginning of the format */
560 #endif
562 int fpos = 1; /* 1 if first positional parameter */
563 stva_list args, /* used to step through the argument list */
564 sargs; /* used to save the start of the arg list */
565 stva_list bargs; /* used to restore args if positional width */
566 /* or precision */
567 stva_list arglst[MAXARGS]; /* array giving appropriate values */
568 /* for va_arg() to retrieve the */
569 /* corresponding argument: */
570 /* arglst[0] is the first arg */
571 /* arglst[1] is the second arg, etc */
573 int starflg = 0; /* set to 1 if * format specifier seen */
576 * Initialize args and sargs to the start of the argument list.
577 * We don't know any portable way to copy an arbitrary C object
578 * so we use a system-specific routine (probably a macro) from
579 * stdarg.h. (Remember that if va_list is an array, in_args will
580 * be a pointer and &in_args won't be what we would want for
581 * memcpy.)
583 va_copy(args.ap, in_args);
584 sargs = args;
586 #ifdef _WIDE
587 if (iop->_flag == _IOREAD)
588 sflag = 1;
590 if (!sflag) {
591 #endif /* _WIDE */
592 /* if first I/O to the stream get a buffer */
593 /* Note that iop->_base should not equal 0 for sprintf and vsprintf */
594 if (iop->_base == 0) {
595 if (_findbuf(iop) == 0)
596 return (EOF);
597 /* _findbuf leaves _cnt set to 0 which is the wrong thing to do */
598 /* for fully buffered files */
599 if (!(iop->_flag & (_IOLBF|_IONBF)))
600 iop->_cnt = _bufend(iop) - iop->_base;
602 #ifdef _WIDE
604 #endif /* _WIDE */
606 #ifdef _WIDE
607 bufptr = iop->_ptr;
608 if (sflag) {
609 maxcount = (size_t)iop->_cnt;
610 bufferend = (unsigned char *)(((wchar_t *)iop->_ptr) +
611 maxcount);
612 } else {
613 bufferend = _bufend(iop);
615 #else /* _WIDE */
616 /* initialize buffer pointer and buffer end pointer */
617 bufptr = iop->_ptr;
618 if (iop->_flag & _IOREAD) {
620 * [v]sprintf or [v]snprintf
622 if (iop->_cnt == MAXINT) {
624 * [v]sprintf (no boundschecking)
626 bufferend =
627 (unsigned char *)((long)bufptr | (-1L & ~HIBITL));
628 } else {
630 * [v]snprintf (with boundschecking) or
631 * iop with _IORW has been read.
633 bufferend = _bufend(iop);
634 if (bufferend == NULL) {
636 * [v]snprintf
638 * [v]snprint() needs to be always handled by
639 * _dowrite().
641 snflag = 1;
644 } else {
646 * [v]printf or [v]fprintf
648 bufferend = _bufend(iop);
650 #endif /* _WIDE */
653 * The main loop -- this loop goes through one iteration
654 * for each string of ordinary characters or format specification.
656 for (; ; ) {
657 ssize_t n;
659 if ((fcode = *format) != '\0' && fcode != '%') {
660 #ifdef _WIDE
661 bp = (wchar_t *)format;
662 #else /* _WIDE */
663 bp = (char *)format;
664 #endif /* _WIDE */
665 do {
666 format++;
667 } while ((fcode = *format) != '\0' && fcode != '%');
669 count += (n = format - bp); /* n = no. of non-% chars */
670 PUT(bp, n);
672 if (fcode == '\0') { /* end of format; return */
673 ssize_t nn = bufptr - iop->_ptr;
675 #ifdef _WIDE
676 if (sflag) {
677 iop->_ptr = bufptr;
678 return ((ssize_t)count);
680 #endif /* _WIDE */
682 iop->_cnt -= nn;
683 iop->_ptr = bufptr;
684 /* in case of interrupt during last several lines */
685 if ((bufptr + iop->_cnt) > bufferend && !(iop->_flag \
686 & _IOREAD))
687 _bufsync(iop, bufferend);
688 if (iop->_flag & (_IONBF | _IOLBF) && \
689 (iop->_flag & _IONBF || \
690 memchr((char *)(bufptr+iop->_cnt), \
691 '\n', -iop->_cnt) != NULL))
692 (void) _xflsbuf(iop);
693 #ifdef _WIDE
694 return (FERROR(iop) ? EOF : (ssize_t)count);
695 #else /* _WIDE */
696 return (FERROR(iop) ? EOF : (int)count);
697 #endif /* _WIDE */
701 * % has been found.
702 * The following switch is used to parse the format
703 * specification and to perform the operation specified
704 * by the format letter. The program repeatedly goes
705 * back to this switch until the format letter is
706 * encountered.
708 width = prefixlength = otherlength = 0;
709 flagword = suffixlength = 0;
710 format++;
711 wflag = 0;
712 lflag = 0;
713 quote = 0;
714 #ifndef _WIDE
715 sec_display = 0;
716 #endif
718 charswitch:
720 switch (fcode = *format++) {
722 case '+':
723 flagword |= FPLUS;
724 goto charswitch;
725 case '-':
726 flagword |= FMINUS;
727 flagword &= ~PADZERO; /* ignore 0 flag */
728 goto charswitch;
729 case ' ':
730 flagword |= FBLANK;
731 goto charswitch;
732 case '\'': /* XSH4 */
733 quote++;
734 goto charswitch;
735 case '#':
736 flagword |= FSHARP;
737 goto charswitch;
739 /* Scan the field width and precision */
740 case '.':
741 flagword |= DOTSEEN;
742 prec = 0;
743 goto charswitch;
745 case '*':
746 if (_M_ISDIGIT(*format)) {
747 starflg = 1;
748 bargs = args;
749 goto charswitch;
751 if (!(flagword & DOTSEEN)) {
752 width = va_arg(args.ap, int);
753 if (width < 0) {
754 width = -width;
755 flagword |= FMINUS;
757 } else {
758 prec = va_arg(args.ap, int);
759 if (prec < 0) {
760 prec = 0;
761 flagword ^= DOTSEEN; /* ANSI sez so */
764 goto charswitch;
766 case '$':
768 ssize_t position;
769 stva_list targs;
770 if (fpos) {
771 #ifdef _WIDE
772 _wmkarglst(sformat, sargs, arglst, prflag);
773 #else /* _WIDE */
774 _mkarglst(sformat, sargs, arglst, prflag);
775 #endif /* _WIDE */
776 fpos = 0;
778 if (flagword & DOTSEEN) {
779 position = prec;
780 prec = 0;
781 } else {
782 position = width;
783 width = 0;
785 if (position <= 0) {
786 /* illegal position */
787 format--;
788 continue;
790 if (position <= MAXARGS) {
791 targs = arglst[position - 1];
792 } else {
793 targs = arglst[MAXARGS - 1];
794 #ifdef _WIDE
795 _wgetarg(sformat, &targs, position, prflag);
796 #else /* _WIDE */
797 _getarg(sformat, &targs, position, prflag);
798 #endif /* _WIDE */
800 if (!starflg)
801 args = targs;
802 else {
803 starflg = 0;
804 args = bargs;
805 if (flagword & DOTSEEN) {
806 prec = va_arg(targs.ap, int);
807 if (prec < 0) {
808 prec = 0;
809 flagword ^= DOTSEEN; /* XSH */
811 } else {
812 width = va_arg(targs.ap, int);
813 if (width < 0) {
814 width = -width;
815 flagword |= FMINUS;
819 goto charswitch;
822 case '0': /* obsolescent spec: leading zero in width */
823 /* means pad with leading zeros */
824 if (!(flagword & (DOTSEEN | FMINUS)))
825 flagword |= PADZERO;
826 /* FALLTHROUGH */
827 case '1':
828 case '2':
829 case '3':
830 case '4':
831 case '5':
832 case '6':
833 case '7':
834 case '8':
835 case '9':
836 { num = fcode - '0';
837 while (_M_ISDIGIT(fcode = *format)) {
838 num = num * 10 + fcode - '0';
839 format++;
841 if (flagword & DOTSEEN)
842 prec = num;
843 else
844 width = num;
845 goto charswitch;
848 /* Scan the length modifier */
849 case 'l':
850 if (!(flagword & XLONG)) {
851 if (lflag) {
852 /* long long */
853 flagword &= ~LENGTH;
854 flagword |= XLONG;
855 } else {
856 /* long */
857 flagword |= LENGTH;
860 lflag++;
861 goto charswitch;
863 case 'L': /* long double */
864 flagword |= QUAD;
865 goto charswitch;
867 case 'h':
868 if (!(flagword & CHAR)) {
869 if (flagword & SHORT) {
870 /* char - hh */
871 flagword &= ~SHORT;
872 flagword |= CHAR;
873 } else {
874 /* short */
875 flagword |= SHORT;
878 goto charswitch;
879 case 'j':
880 #ifndef _LP64
882 * *printf_c89() in 32-bit libc uses
883 * 32-bit intmax_t; otherwise intmax_t
884 * is 64-bits.
886 if (!(prflag & _F_INTMAX32)) {
887 #endif
888 flagword |= XLONG; /* [u]intmax_t (64) */
889 #ifndef _LP64
891 #endif
892 goto charswitch;
894 case 't':
896 * LENGTH is shared by l, t, z specifiers; protect
897 * against (destructive) undefined behavior (eg:
898 * avoid %llt setting XLONG and LENGTH) with invalid
899 * combinations of specifiers
901 if (!(flagword & XLONG)) {
902 flagword |= LENGTH; /* ptrdiff_t */
904 goto charswitch;
906 case 'z':
907 if (!(flagword & XLONG)) {
908 flagword |= LENGTH; /* [s]size_t */
910 goto charswitch;
913 * The character addressed by format must be
914 * the format letter -- there is nothing
915 * left for it to be.
917 * The status of the +, -, #, and blank
918 * flags are reflected in the variable
919 * "flagword". "width" and "prec" contain
920 * numbers corresponding to the digit
921 * strings before and after the decimal
922 * point, respectively. If there was no
923 * decimal point, then flagword & DOTSEEN
924 * is false and the value of prec is meaningless.
926 * The following switch cases set things up
927 * for printing. What ultimately gets
928 * printed will be padding blanks, a
929 * prefix, left padding zeroes, a value,
930 * right padding zeroes, a suffix, and
931 * more padding blanks. Padding blanks
932 * will not appear simultaneously on both
933 * the left and the right. Each case in
934 * this switch will compute the value, and
935 * leave in several variables the informa-
936 * tion necessary to construct what is to
937 * be printed.
939 * The prefix is a sign, a blank, "0x",
940 * "0X", a sign or a blank followed by "0x"
941 * or "0X", or nothing, and is addressed by
942 * "prefix".
944 * The suffix is either null or an
945 * exponent, and is addressed by "suffix".
946 * If there is a suffix, the flagword bit
947 * SUFFIX will be set.
949 * The value to be printed starts at "bp"
950 * and continues up to and not including
951 * "p".
953 * "lzero" and "rzero" will contain the
954 * number of padding zeroes required on
955 * the left and right, respectively.
956 * The flagword bits LZERO and RZERO tell
957 * whether padding zeros are required.
959 * The number of padding blanks, and
960 * whether they go on the left or the
961 * right, will be computed on exit from
962 * the switch.
968 * decimal fixed point representations
970 * HIBITL is 100...000
971 * binary, and is equal to the maximum
972 * negative number.
973 * We assume a 2's complement machine
975 case 'i':
976 case 'd':
977 if ((flagword & PADZERO) && (flagword & DOTSEEN))
978 flagword &= ~PADZERO; /* ignore 0 flag */
979 /* Set buffer pointer to last digit */
980 p = bp = buf + MAXLLDIGS;
982 /* Fetch the argument to be printed */
983 if (flagword & XLONG) { /* long long */
984 ll = va_arg(args.ap, long long);
986 /* If signed conversion, make sign */
987 if (ll < 0) {
988 prefix = _P_HYPHEN;
989 prefixlength = 1;
991 * Negate, checking in advance for
992 * possible overflow.
994 if (ll != HIBITLL)
995 ll = -ll;
996 else
997 /* number is -HIBITLL; convert last */
998 /* digit now and get positive number */
999 *--bp = _lowlldigit(&ll);
1000 } else if (flagword & FPLUS) {
1001 prefix = _P_PLUS;
1002 prefixlength = 1;
1003 } else if (flagword & FBLANK) {
1004 prefix = _P_BLANK;
1005 prefixlength = 1;
1007 } else { /* not long long */
1008 if (flagword & LENGTH)
1009 val = va_arg(args.ap, long);
1010 else
1011 val = va_arg(args.ap, int);
1013 if (flagword & SHORT)
1014 val = (short)val;
1015 else if (flagword & CHAR)
1016 val = (char)val;
1018 /* If signed conversion, make sign */
1019 if (val < 0) {
1020 prefix = _P_HYPHEN;
1021 prefixlength = 1;
1023 * Negate, checking in advance
1024 * for possible overflow.
1026 if (val != HIBITL)
1027 val = -val;
1029 * number is -HIBITL; convert
1030 * last digit now and get
1031 * positive number
1033 else
1034 *--bp = _lowdigit(&val);
1035 } else if (flagword & FPLUS) {
1036 prefix = _P_PLUS;
1037 prefixlength = 1;
1038 } else if (flagword & FBLANK) {
1039 prefix = _P_BLANK;
1040 prefixlength = 1;
1044 decimal:
1046 long qval = val;
1047 long long lll = ll;
1048 long long tll;
1049 if (flagword & XLONG) {
1050 if (lll < 10LL) {
1051 #ifdef _WIDE
1052 if (lll != 0LL || !(flagword & DOTSEEN))
1053 *--bp = (wchar_t)lll + L'0';
1054 #else /* _WIDE */
1055 if (lll != 0LL || !(flagword & DOTSEEN))
1056 *--bp = (char)lll + '0';
1057 #endif /* _WIDE */
1058 } else {
1059 do {
1060 tll = lll;
1061 lll /= 10;
1062 #ifdef _WIDE
1063 *--bp = (wchar_t)
1064 (tll - lll * 10 + '0');
1065 #else /* _WIDE */
1066 *--bp = (char) \
1067 (tll - lll * 10 + '0');
1068 #endif /* _WIDE */
1069 } while (lll >= 10);
1070 #ifdef _WIDE
1071 *--bp = (wchar_t)lll + '0';
1072 #else /* _WIDE */
1073 *--bp = (char)lll + '0';
1074 #endif /* _WIDE */
1076 } else {
1077 if (qval <= 9) {
1078 #ifdef _WIDE
1079 if (qval != 0 || !(flagword & DOTSEEN))
1080 *--bp = (wchar_t)qval + '0';
1081 #else /* _WIDE */
1082 if (qval != 0 || !(flagword & DOTSEEN))
1083 *--bp = (char)qval + '0';
1084 #endif /* _WIDE */
1085 } else {
1086 do {
1087 n = qval;
1088 qval /= 10;
1089 #ifdef _WIDE
1090 *--bp = (wchar_t) \
1091 (n - qval * 10 + '0');
1092 #else /* _WIDE */
1093 *--bp = (char) \
1094 (n - qval * 10 + '0');
1095 #endif /* _WIDE */
1096 } while (qval > 9);
1097 #ifdef _WIDE
1098 *--bp = (wchar_t)qval + '0';
1099 #else /* _WIDE */
1100 *--bp = (char)qval + '0';
1101 #endif /* _WIDE */
1105 /* Handle the ' flag */
1106 if (quote) {
1107 p = insert_thousands_sep(bp, p);
1110 /* Calculate minimum padding zero requirement */
1111 if (flagword & DOTSEEN) {
1112 leadzeroes = prec - (p - bp);
1113 if (leadzeroes > 0) {
1114 otherlength = lzero = leadzeroes;
1115 flagword |= LZERO;
1118 break;
1120 case 'u':
1121 if ((flagword & PADZERO) && (flagword & DOTSEEN))
1122 flagword &= ~PADZERO; /* ignore 0 flag */
1123 p = bp = buf + MAXLLDIGS;
1125 /* Fetch the argument to be printed */
1126 if (flagword & XLONG) {
1127 ll = va_arg(args.ap, long long);
1129 if (ll & HIBITLL)
1130 *--bp = _lowlldigit(&ll);
1131 } else {
1132 if (flagword & LENGTH)
1133 val = va_arg(args.ap, long);
1134 else
1135 val = va_arg(args.ap, unsigned);
1137 if (flagword & SHORT)
1138 val = (unsigned short)val;
1139 else if (flagword & CHAR)
1140 val = (unsigned char)val;
1142 if (val & HIBITL)
1143 *--bp = _lowdigit(&val);
1146 goto decimal;
1149 * non-decimal fixed point representations
1150 * for radix equal to a power of two
1152 * "mradix" is one less than the radix for the conversion.
1153 * "lradix" is one less than the base 2 log
1154 * of the radix for the conversion. Conversion is unsigned.
1155 * HIBITL is 100...000
1156 * binary, and is equal to the maximum
1157 * negative number.
1158 * We assume a 2's complement machine
1161 case 'o':
1162 mradix = 7;
1163 lradix = 2;
1165 * DR151 and clarification in C90
1166 * presence of '#' increases precision to first
1167 * digit of the result to be zero
1169 if ((flagword & DOTSEEN) && (flagword & FSHARP) &&
1170 prec == 0)
1171 prec = 1;
1173 goto fixed;
1175 case 'p':
1176 flagword &= ~(XLONG | SHORT);
1177 flagword |= LENGTH;
1179 /* FALLTHRU */
1180 case 'X':
1181 case 'x':
1182 mradix = 15;
1183 lradix = 3;
1185 fixed:
1186 if ((flagword & PADZERO) && (flagword & DOTSEEN))
1187 flagword &= ~PADZERO; /* ignore 0 flag */
1189 #ifdef _WIDE
1190 /* Set translate table for digits */
1191 tab = (wchar_t *)((fcode == 'X') ? uc_digs : lc_digs);
1192 #else /* _WIDE */
1193 /* Set translate table for digits */
1194 tab = (fcode == 'X') ? uc_digs : lc_digs;
1195 #endif /* _WIDE */
1197 /* Fetch the argument to be printed */
1198 if (flagword & XLONG) {
1199 ll = va_arg(args.ap, long long);
1200 } else {
1201 if (flagword & LENGTH)
1202 val = va_arg(args.ap, long);
1203 else
1204 val = va_arg(args.ap, unsigned);
1206 if (flagword & SHORT)
1207 val = (unsigned short) val;
1208 else if (flagword & CHAR)
1209 val = (unsigned char) val;
1211 p = bp = buf + MAXLLDIGS;
1213 /* Develop the digits of the value */
1214 if (flagword & XLONG) {
1215 long long lll = ll;
1217 if (lll == 0LL) {
1218 if (!(flagword & DOTSEEN)) {
1219 otherlength = lzero = 1;
1220 flagword |= LZERO;
1222 } else do {
1223 *--bp = tab[(ssize_t)(lll & mradix)];
1224 lll = ((lll >> 1) & ~HIBITLL) \
1225 >> lradix;
1226 } while (lll != 0LL);
1227 } else {
1228 long qval = val;
1230 if (qval == 0) {
1231 if (!(flagword & DOTSEEN)) {
1232 otherlength = lzero = 1;
1233 flagword |= LZERO;
1235 } else do {
1236 *--bp = tab[qval & mradix];
1237 qval = ((qval >> 1) & ~HIBITL) \
1238 >> lradix;
1239 } while (qval != 0);
1242 /* Calculate minimum padding zero requirement */
1243 if (flagword & DOTSEEN) {
1244 leadzeroes = prec - (p - bp);
1245 if (leadzeroes > 0) {
1246 otherlength = lzero = leadzeroes;
1247 flagword |= LZERO;
1251 /* Handle the # flag, (val != 0) for int and long */
1252 /* (ll!= 0) handles long long case */
1253 if ((flagword & FSHARP) &&
1254 (((flagword & XLONG) == 0 && val != 0) ||
1255 ((flagword & XLONG) == XLONG && ll != 0)))
1256 switch (fcode) {
1257 case 'o':
1258 if (!(flagword & LZERO)) {
1259 otherlength = lzero = 1;
1260 flagword |= LZERO;
1262 break;
1263 case 'x':
1264 prefix = _P_ZEROx;
1265 prefixlength = 2;
1266 break;
1267 case 'X':
1268 prefix = _P_ZEROX;
1269 prefixlength = 2;
1270 break;
1273 break;
1275 case 'A':
1276 case 'a':
1277 /* A format */
1278 if (flagword & QUAD) {
1279 long double qval = GETQVAL(args.ap);
1281 /* establish default precision */
1282 if (!(flagword & DOTSEEN))
1283 #if defined(__sparc)
1284 prec = HEXFP_QUAD_DIG - 1;
1285 #elif defined(__i386) || defined(__amd64)
1286 prec = HEXFP_EXTENDED_DIG - 1;
1287 #else
1288 #error Unknown architecture
1289 #endif
1291 FPCONV(__qaconvert, &qval,
1292 min(prec + 1, MAXECVT), &exp, &sign,
1293 cvtbuf);
1294 } else {
1295 double dval = va_arg(args.ap, double);
1297 /* establish default precision */
1298 if (!(flagword & DOTSEEN))
1299 prec = HEXFP_DOUBLE_DIG - 1;
1301 FPCONV(__aconvert, dval,
1302 min(prec + 1, MAXECVT), &exp, &sign,
1303 cvtbuf);
1305 bp = cvtbuf;
1308 * The following is wide-character safe because
1309 * __aconvert and __qaconvert only produce ASCII
1310 * characters.
1312 if (!isxdigit((unsigned char)*bp)) {
1313 inf_nan = 1;
1314 break;
1318 * Create the prefix. We ought to use the strings
1319 * defined above (_P_HYPHEN, etc.), but that would
1320 * be awkward: we'd either have to define six more
1321 * of them or we'd have to use strcpy/strcat to
1322 * assemble the ones already defined. So instead,
1323 * we just build the prefix character by character.
1325 p = prefix = prefixbuf;
1326 if (sign) {
1327 *p++ = '-';
1328 prefixlength = 1;
1329 } else if (flagword & FPLUS) {
1330 *p++ = '+';
1331 prefixlength = 1;
1332 } else if (flagword & FBLANK) {
1333 *p++ = ' ';
1334 prefixlength = 1;
1336 *p++ = '0';
1337 *p++ = (fcode == 'A') ? 'X' : 'x';
1338 *p = '\0';
1339 prefixlength += 2;
1341 /* put the first digit in the buffer */
1342 p = &buf[0];
1343 *p++ = (*bp != '\0') ? *bp++ : '0';
1345 /* Put in a decimal point if needed */
1346 if (prec != 0 || (flagword & FSHARP))
1347 p = insert_decimal_point(p);
1349 /* Create the rest of the mantissa */
1350 rz = prec;
1351 if (fcode == 'A') {
1352 for (; rz > 0 && *bp != '\0'; --rz) {
1353 *p++ = ('a' <= *bp && *bp <= 'f')?
1354 *bp - 32 : *bp;
1355 bp++;
1357 } else {
1358 for (; rz > 0 && *bp != '\0'; --rz)
1359 *p++ = *bp++;
1361 if (rz > 0) {
1362 otherlength = rzero = rz;
1363 flagword |= RZERO;
1366 bp = &buf[0];
1369 * Create the exponent in right-to-left order.
1370 * buf[0] == '0' if and only if the value being
1371 * converted is exactly zero, in which case the
1372 * exponent should be +0 regardless of exp.
1374 suffix = &expbuf[MAXESIZ];
1375 *suffix = '\0';
1376 if (buf[0] != '0') {
1377 int nn;
1379 nn = exp;
1380 if (nn < 0)
1381 nn = -nn;
1382 for (; nn > 9; nn /= 10)
1383 *--suffix = todigit(nn % 10);
1384 *--suffix = todigit(nn);
1385 *--suffix = (exp >= 0) ? '+' : '-';
1386 } else {
1387 *--suffix = '0';
1388 *--suffix = '+';
1391 /* put in the p */
1392 *--suffix = (fcode == 'A') ? 'P' : 'p';
1394 /* compute size of suffix */
1395 suffixlength = &expbuf[MAXESIZ] - suffix;
1396 otherlength += suffixlength;
1397 flagword |= SUFFIX;
1398 break;
1400 case 'E':
1401 case 'e':
1403 * E-format. The general strategy
1404 * here is fairly easy: we take what
1405 * econvert gives us and re-format it.
1406 * (qeconvert for long double)
1409 /* Establish default precision */
1410 if (!(flagword & DOTSEEN))
1411 prec = 6;
1413 if (flagword & QUAD) { /* long double */
1414 long double qval = GETQVAL(args.ap);
1416 FPCONV(qeconvert, &qval,
1417 min(prec + 1, MAXECVT), &decpt, &sign,
1418 cvtbuf);
1419 } else { /* double */
1420 double dval = va_arg(args.ap, double);
1422 FPCONV(econvert, dval,
1423 min(prec + 1, MAXECVT), &decpt, &sign,
1424 cvtbuf);
1426 bp = cvtbuf;
1427 if (*bp > '9') {
1428 inf_nan = 1;
1429 inf_nan_mixed_case = (__xpg6 &
1430 _C99SUSv3_mixed_case_Inf_and_NaN);
1431 break;
1434 /* Determine the prefix */
1435 e_merge:
1436 if (sign) {
1437 prefix = _P_HYPHEN;
1438 prefixlength = 1;
1439 } else if (flagword & FPLUS) {
1440 prefix = _P_PLUS;
1441 prefixlength = 1;
1442 } else if (flagword & FBLANK) {
1443 prefix = _P_BLANK;
1444 prefixlength = 1;
1447 /* Place the first digit in the buffer */
1448 p = &buf[0];
1449 *p++ = (*bp != '\0') ? *bp++ : '0';
1451 /* Put in a decimal point if needed */
1452 if (prec != 0 || (flagword & FSHARP))
1453 p = insert_decimal_point(p);
1455 /* Create the rest of the mantissa */
1456 rz = prec;
1457 for (; rz > 0 && *bp != '\0'; --rz)
1458 *p++ = *bp++;
1459 if (rz > 0) {
1460 otherlength = rzero = rz;
1461 flagword |= RZERO;
1464 bp = &buf[0];
1467 * Create the exponent. buf[0] == '0' if and
1468 * only if the value being converted is exactly
1469 * zero, in which case the exponent should be
1470 * +0 regardless of decpt.
1472 *(suffix = &expbuf[MAXESIZ]) = '\0';
1473 if (buf[0] != '0') {
1474 int nn = decpt - 1;
1475 if (nn < 0)
1476 nn = -nn;
1477 for (; nn > 9; nn /= 10)
1478 *--suffix = todigit(nn % 10);
1479 *--suffix = todigit(nn);
1482 /* Prepend leading zeroes to the exponent */
1483 while (suffix > &expbuf[MAXESIZ - 2])
1484 *--suffix = '0';
1486 /* Put in the exponent sign */
1487 *--suffix = (decpt > 0 || buf[0] == '0') ? '+' : '-';
1489 /* Put in the e */
1490 *--suffix = _M_ISUPPER(fcode) ? 'E' : 'e';
1492 /* compute size of suffix */
1493 otherlength += (suffixlength = &expbuf[MAXESIZ] \
1494 - suffix);
1495 flagword |= SUFFIX;
1496 break;
1498 case 'F':
1499 case 'f':
1501 * F-format floating point. This is a
1502 * good deal less simple than E-format.
1503 * The overall strategy will be to call
1504 * fconvert, reformat its result into buf,
1505 * and calculate how many trailing
1506 * zeroes will be required. There will
1507 * never be any leading zeroes needed.
1508 * (qfconvert for long double)
1511 /* Establish default precision */
1512 if (!(flagword & DOTSEEN))
1513 prec = 6;
1515 if (flagword & QUAD) { /* long double */
1516 long double qval = GETQVAL(args.ap);
1518 FPCONV(qfconvert, &qval, min(prec, MAXFCVT),
1519 &decpt, &sign, cvtbuf);
1520 bp = cvtbuf;
1521 if (*bp == 0) {
1523 * qfconvert would have required
1524 * too many characters; use qeconvert
1525 * instead
1527 FPCONV(qeconvert, &qval,
1528 min(prec + 1, MAXECVT), &decpt,
1529 &sign, cvtbuf);
1530 goto e_merge;
1532 } else { /* double */
1533 double dval = va_arg(args.ap, double);
1535 FPCONV(fconvert, dval, min(prec, MAXFCVT),
1536 &decpt, &sign, cvtbuf);
1538 bp = cvtbuf;
1539 if (*bp > '9') {
1540 inf_nan = 1;
1541 if (fcode == 'f')
1542 inf_nan_mixed_case = (__xpg6 &
1543 _C99SUSv3_mixed_case_Inf_and_NaN);
1544 break;
1547 /* Determine the prefix */
1548 f_merge:
1549 if (sign) {
1550 prefix = _P_HYPHEN;
1551 prefixlength = 1;
1552 } else if (flagword & FPLUS) {
1553 prefix = _P_PLUS;
1554 prefixlength = 1;
1555 } else if (flagword & FBLANK) {
1556 prefix = _P_BLANK;
1557 prefixlength = 1;
1560 /* Initialize buffer pointer */
1561 p = &buf[0];
1564 ssize_t nn = decpt;
1566 /* Emit the digits before the decimal point */
1567 k = 0;
1568 do {
1569 *p++ = (nn <= 0 || *bp == '\0' || \
1570 k >= MAXFSIG) ? '0' : (k++, *bp++);
1571 } while (--nn > 0);
1573 if (quote)
1574 p = insert_thousands_sep(buf, p);
1576 /* Put in a decimal point if needed */
1577 if (prec > 0 || (flagword & FSHARP))
1578 p = insert_decimal_point(p);
1580 /* Digits (if any) after the decimal point */
1581 nn = min(prec, MAXFCVT);
1582 if (prec > nn) {
1583 flagword |= RZERO;
1584 otherlength = rzero = prec - nn;
1586 while (--nn >= 0)
1587 *p++ = (++decpt <= 0 || *bp == '\0' || \
1588 k >= MAXFSIG) ? '0' : (k++, *bp++);
1591 bp = &buf[0];
1593 break;
1595 case 'G':
1596 case 'g':
1598 * g-format. We play around a bit
1599 * and then jump into e or f, as needed.
1602 /* Establish default precision */
1603 if (!(flagword & DOTSEEN))
1604 prec = 6;
1605 else if (prec == 0)
1606 prec = 1;
1608 if (flagword & QUAD) { /* long double */
1609 long double qval = GETQVAL(args.ap);
1611 FPCONV(qeconvert, &qval, min(prec, MAXECVT),
1612 &decpt, &sign, cvtbuf);
1613 } else { /* double */
1614 double dval = va_arg(args.ap, double);
1616 FPCONV(econvert, dval, min(prec, MAXECVT),
1617 &decpt, &sign, cvtbuf);
1619 bp = cvtbuf;
1620 if (*bp > '9') {
1621 inf_nan = 1;
1622 inf_nan_mixed_case = (__xpg6 &
1623 _C99SUSv3_mixed_case_Inf_and_NaN);
1624 break;
1626 if (*bp == '0') /* the value converted is zero */
1627 decpt = 1;
1630 int kk = prec;
1631 if (!(flagword & FSHARP)) {
1632 #ifdef _WIDE
1633 n = wcslen(bp);
1634 #else /* _WIDE */
1635 n = strlen(bp);
1636 #endif /* _WIDE */
1637 if (n < kk)
1638 kk = (int)n;
1639 while (kk >= 1 && bp[kk-1] == '0')
1640 --kk;
1642 if (decpt < -3 || decpt > prec) {
1643 prec = kk - 1;
1644 goto e_merge;
1646 prec = kk - decpt;
1647 goto f_merge;
1650 case '%':
1651 buf[0] = fcode;
1652 goto c_merge;
1654 #ifndef _WIDE
1655 case 'w':
1656 wflag = 1;
1657 goto charswitch;
1658 #endif /* _WIDE */
1661 case 'C': /* XPG XSH4 extention */
1662 wide_C:
1664 wchar_t temp;
1666 temp = va_arg(args.ap, wchar_t);
1667 #ifdef _WIDE
1668 if (temp) {
1669 buf[0] = temp;
1670 p = (bp = buf) + 1;
1671 } else {
1672 buf[0] = 0;
1673 p = (bp = buf) + 1;
1675 wcount = 1;
1676 wflag = 1;
1677 #else /* _WIDE */
1678 if (temp) {
1679 if ((retcode = wctomb(buf, temp))
1680 == -1) {
1681 errno = EILSEQ;
1682 return (EOF);
1683 } else {
1684 p = (bp = buf) + retcode;
1686 } else { /* NULL character */
1687 buf[0] = 0;
1688 p = (bp = buf) + 1;
1690 wcount = p - bp;
1691 #endif /* _WIDE */
1693 break;
1694 case 'c':
1695 if (lflag) {
1696 goto wide_C;
1698 #ifndef _WIDE
1699 if (wflag) {
1700 wchar_t temp;
1702 temp = va_arg(args.ap, wchar_t);
1703 if (temp) {
1704 if ((retcode = wctomb(buf, temp))
1705 == -1) {
1706 p = (bp = buf) + 1;
1707 } else {
1708 p = (bp = buf) + retcode;
1710 } else { /* NULL character */
1711 buf[0] = 0;
1712 p = (bp = buf) + 1;
1714 wcount = p - bp;
1715 } else {
1716 #endif /* _WIDE */
1717 if (flagword & XLONG) {
1718 long long temp;
1719 temp = va_arg(args.ap, long long);
1720 #ifdef _WIDE
1721 buf[0] = (wchar_t)temp;
1722 #else /* _WIDE */
1723 buf[0] = (char)temp;
1724 #endif /* _WIDE */
1725 } else
1726 buf[0] = va_arg(args.ap, int);
1727 c_merge:
1728 p = (bp = &buf[0]) + 1;
1729 #ifdef _WIDE
1730 wcount = 1;
1731 wflag = 1;
1732 #endif /* _WIDE */
1733 #ifndef _WIDE
1735 #endif /* _WIDE */
1736 break;
1738 case 'S': /* XPG XSH4 extention */
1739 wide_S:
1740 #ifdef _WIDE
1741 if (!lflag) {
1742 lflag++;
1744 bp = va_arg(args.ap, wchar_t *);
1745 if (bp == NULL)
1746 bp = (wchar_t *)widenullstr;
1747 if (!(flagword & DOTSEEN)) {
1748 /* wide character handling */
1749 prec = MAXINT;
1752 wp = bp;
1753 wcount = 0;
1754 while (*wp) {
1755 if ((prec - wcount - 1) >= 0) {
1756 wcount++;
1757 wp++;
1758 } else {
1759 break;
1762 p = wp;
1763 wflag = 1;
1764 break;
1765 #else /* _WIDE */
1766 if (!wflag)
1767 wflag++;
1768 bp = va_arg(args.ap, char *);
1769 if (bp == NULL)
1770 bp = (char *)widenullstr;
1771 if (!(flagword & DOTSEEN)) {
1772 /* wide character handling */
1773 prec = MAXINT;
1776 wp = (wchar_t *)(uintptr_t)bp;
1777 wcount = 0;
1778 while (*wp) {
1779 int nbytes;
1781 nbytes = wctomb(tmpbuf, *wp);
1782 if (nbytes < 0) {
1783 errno = EILSEQ;
1784 return (EOF);
1786 if ((prec - (wcount + nbytes)) >= 0) {
1787 wcount += nbytes;
1788 wp++;
1789 } else {
1790 break;
1793 sec_display = wcount;
1794 p = (char *)wp;
1795 break;
1796 #endif /* _WIDE */
1797 case 's':
1798 if (lflag) {
1799 goto wide_S;
1801 #ifdef _WIDE
1802 cbp = va_arg(args.ap, char *);
1803 if (cbp == NULL)
1804 cbp = (char *)nullstr;
1805 if (!(flagword & DOTSEEN)) {
1806 size_t nwc;
1807 wchar_t *wstr;
1809 nwc = mbstowcs(NULL, cbp, 0);
1810 if (nwc == (size_t)-1) {
1811 errno = EILSEQ;
1812 return (EOF);
1814 bpsize = sizeof (wchar_t) * (nwc + 1);
1815 wstr = (wchar_t *)lmalloc(bpsize);
1816 if (wstr == NULL) {
1817 errno = EILSEQ;
1818 return (EOF);
1820 nwc = mbstowcs(wstr, cbp, MAXINT);
1821 wcount = nwc;
1822 bp = wstr;
1823 p = wstr + nwc;
1824 } else {
1825 size_t nwc;
1826 wchar_t *wstr;
1828 nwc = mbstowcs(NULL, cbp, 0);
1829 if (nwc == (size_t)-1) {
1830 errno = EILSEQ;
1831 return (EOF);
1833 if (prec > nwc) {
1834 bpsize = sizeof (wchar_t) * nwc;
1835 wstr = (wchar_t *)lmalloc(bpsize);
1836 if (wstr == NULL) {
1837 errno = ENOMEM;
1838 return (EOF);
1840 nwc = mbstowcs(wstr, cbp, nwc);
1841 wcount = nwc;
1842 bp = wstr;
1843 p = wstr + nwc;
1844 } else {
1845 size_t nnwc;
1846 int len;
1847 char *s;
1848 wchar_t *wstr;
1850 bpsize = sizeof (wchar_t) * prec;
1851 wstr = (wchar_t *)lmalloc(bpsize);
1852 if (wstr == NULL) {
1853 errno = ENOMEM;
1854 return (EOF);
1856 nwc = mbstowcs(wstr, cbp, prec);
1857 wcount = prec;
1858 bp = wstr;
1859 p = wstr + nwc;
1862 wflag = 1;
1863 #else /* _WIDE */
1864 bp = va_arg(args.ap, char *);
1865 if (bp == NULL)
1866 bp = (char *)nullstr;
1867 if (!(flagword & DOTSEEN)) {
1868 if (wflag) {
1869 /* wide character handling */
1870 prec = MAXINT;
1871 goto wide_hand;
1875 p = bp + strlen(bp);
1878 * sec_display only needed if width
1879 * is specified (ie, "%<width>s")
1880 * Solaris behavior counts <width> in
1881 * screen column width. (If XPG4 behavior,
1882 * <width> is counted in bytes.)
1884 if (width > 0 && __xpg4 == 0 &&
1885 MB_CUR_MAX > 1) {
1886 #define NW 256
1887 wchar_t wbuff[NW];
1888 wchar_t *wp, *wptr;
1889 size_t wpsize;
1890 size_t nwc;
1892 wp = NULL;
1893 if ((nwc = mbstowcs(wbuff, bp,
1894 NW)) == (size_t)-1) {
1895 /* Estimate width */
1896 sec_display = strlen(bp);
1897 goto mbs_err;
1899 if (nwc < NW) {
1900 wptr = wbuff;
1901 } else {
1903 * If widechar does not fit into
1904 * wbuff, allocate larger buffer
1906 if ((nwc =
1907 mbstowcs(NULL, bp, NULL)) ==
1908 (size_t)-1) {
1909 sec_display =
1910 strlen(bp);
1911 goto mbs_err;
1913 wpsize = (nwc + 1) *
1914 sizeof (wchar_t);
1915 if ((wp = lmalloc(wpsize))
1916 == NULL) {
1917 errno = ENOMEM;
1918 return (EOF);
1920 if ((nwc = mbstowcs(wp,
1921 bp, nwc)) == (size_t)-1) {
1922 sec_display = \
1923 strlen(bp);
1924 goto mbs_err;
1926 wptr = wp;
1928 if ((sec_display = wcswidth(wptr, nwc))
1929 == -1) {
1930 sec_display =
1931 _rec_scrswidth
1932 (wptr, nwc);
1934 mbs_err:
1935 if (wp)
1936 lfree(wp, wpsize);
1938 } else { /* a strnlen function would be useful here! */
1940 * If we've seen a dot, and count has been set
1941 * to 0, then we don't output in any cases
1942 * below. prec should be always >= 0. So we only
1943 * check to see if it's zero.
1945 if (prec == 0) {
1946 p = bp;
1947 break;
1950 if (wflag) {
1951 /* wide character handling */
1953 wide_hand:
1954 wp = (wchar_t *)(uintptr_t)bp;
1955 preco = prec;
1956 wcount = 0;
1957 while (*wp &&
1958 (prec -= _scrwidth(*wp)) >= 0) {
1959 if ((retcode =
1960 wctomb(tmpbuf, *wp)) < 0)
1961 wcount++;
1962 else
1963 wcount += retcode;
1964 wp++;
1966 if (*wp)
1967 prec += _scrwidth(*wp);
1968 p = (char *)wp;
1969 sec_display = preco - prec;
1970 } else if (__xpg4 == 0 && MB_CUR_MAX > 1) {
1972 * Solaris behavior - count
1973 * precision as screen column width
1975 char *qp = bp;
1976 int ncol, nbytes;
1977 wchar_t wc;
1979 ncol = 0;
1980 preco = prec;
1981 while (*qp) {
1982 if (isascii(*qp)) {
1983 qp++;
1984 if (--prec == 0)
1985 break;
1986 continue;
1988 if ((nbytes = mbtowc(&wc, qp,
1989 MB_LEN_MAX)) == -1) {
1990 /* print illegal char */
1991 nbytes = 1;
1992 ncol = 1;
1993 } else {
1994 if ((ncol =
1995 _scrwidth(wc))
1996 == 0) {
1997 ncol = 1;
2001 if ((prec -= ncol) >= 0) {
2002 qp += nbytes;
2003 if (prec == 0)
2004 break;
2005 } else {
2006 break;
2009 if (prec < 0)
2010 prec += ncol;
2011 p = qp;
2012 sec_display = preco - prec;
2013 } else {
2015 * XPG4 behavior - count
2016 * precision as bytes.
2017 * We don't use strlen() because
2018 * the given char string may not
2019 * be null-terminated.
2021 char *qp;
2023 qp = memchr(bp, '\0', prec);
2024 if (qp == NULL) {
2025 p = bp + prec;
2026 } else {
2027 p = qp;
2031 #endif /* _WIDE */
2032 break;
2034 case 'n':
2036 if (flagword & XLONG) {
2037 long long *svcount;
2038 svcount = va_arg(args.ap, long long *);
2039 *svcount = (long long)count;
2040 } else if (flagword & LENGTH) {
2041 long *svcount;
2042 svcount = va_arg(args.ap, long *);
2043 *svcount = (long)count;
2044 } else if (flagword & SHORT) {
2045 short *svcount;
2046 svcount = va_arg(args.ap, short *);
2047 *svcount = (short)count;
2048 } else if (flagword & CHAR) {
2049 char *svcount;
2050 svcount = va_arg(args.ap, char *);
2051 *svcount = (char)count;
2052 } else {
2053 int *svcount;
2054 svcount = va_arg(args.ap, int *);
2055 *svcount = count;
2057 continue;
2059 default: /* this is technically an error; what we do is to */
2060 /* back up the format pointer to the offending char */
2061 /* and continue with the format scan */
2062 format--;
2063 continue;
2066 if (inf_nan) {
2067 if (inf_nan_mixed_case) {
2068 /* advance p */
2069 for (p = bp + 1; *p != '\0'; p++)
2071 } else {
2072 int upper;
2074 /* advance p and make output all one case */
2075 upper = _M_ISUPPER(fcode);
2076 for (p = bp; *p != '\0'; p++)
2077 *p = upper? toupper(*p) : tolower(*p);
2079 if (sign) {
2080 prefix = _P_HYPHEN;
2081 prefixlength = 1;
2082 } else if (flagword & FPLUS) {
2083 prefix = _P_PLUS;
2084 prefixlength = 1;
2085 } else if (flagword & FBLANK) {
2086 prefix = _P_BLANK;
2087 prefixlength = 1;
2089 inf_nan = 0;
2090 inf_nan_mixed_case = 0;
2091 flagword &= ~PADZERO; /* ignore 0 flag */
2094 /* Calculate number of padding blanks */
2095 n = p - bp; /* n == size of the converted value (in bytes) */
2097 #ifdef _WIDE
2098 k = n;
2099 #else /* _WIDE */
2100 if (sec_display) /* when format is %s or %ws or %S */
2101 k = sec_display;
2102 else
2103 k = n;
2104 #endif /* _WIDE */
2106 * k is the (screen) width or # of bytes of the converted value
2108 k += prefixlength + otherlength;
2110 #ifdef _WIDE
2111 if (wflag) {
2112 count += wcount;
2113 } else {
2114 count += n;
2116 #else /* _WIDE */
2118 * update count which is the overall size of the output data
2119 * and passed to memchr()
2121 if (wflag)
2123 * when wflag != 0 (i.e. %ws or %wc), the size of the
2124 * converted value is wcount bytes
2126 count += wcount;
2127 else
2129 * when wflag == 0, the size of the converted
2130 * value is n (= p-bp) bytes
2132 count += n;
2133 #endif /* _WIDE */
2134 count += prefixlength + otherlength;
2136 if (width > k) {
2137 count += (width - k);
2139 * Set up for padding zeroes if requested
2140 * Otherwise emit padding blanks unless output is
2141 * to be left-justified.
2144 if (flagword & PADZERO) {
2145 if (!(flagword & LZERO)) {
2146 flagword |= LZERO;
2147 lzero = width - k;
2148 } else
2149 lzero += width - k;
2150 k = width; /* cancel padding blanks */
2151 } else
2152 /* Blanks on left if required */
2153 if (!(flagword & FMINUS))
2154 PAD(_blanks, width - k);
2157 /* Prefix, if any */
2158 if (prefixlength != 0)
2159 PUT(prefix, prefixlength);
2161 /* Zeroes on the left */
2162 if ((flagword & LZERO)) /* && */
2163 /* (!(flagword & SHORT) || !(flagword & FMINUS)) */
2164 PAD(_zeroes, lzero);
2166 #ifdef _WIDE
2167 if (n > 0)
2168 PUT(bp, n);
2169 if ((fcode == 's') && !lflag) {
2170 if (bp)
2171 lfree(bp, bpsize);
2173 #else /* _WIDE */
2174 /* The value itself */
2175 if ((fcode == 's' || fcode == 'S') && wflag) {
2176 /* wide character handling */
2177 wchar_t *wp = (wchar_t *)(uintptr_t)bp;
2178 int cnt;
2179 char *bufp;
2180 long printn;
2181 printn = (wchar_t *)(uintptr_t)p -
2182 (wchar_t *)(uintptr_t)bp;
2183 bufp = buf;
2184 while (printn > 0) {
2185 if ((cnt = wctomb(buf, *wp)) < 0)
2186 cnt = 1;
2187 PUT(bufp, cnt);
2188 wp++;
2189 printn--;
2191 } else { /* non wide character value */
2192 if (n > 0)
2193 PUT(bp, n);
2195 #endif /* _WIDE */
2197 if (flagword & (RZERO | SUFFIX | FMINUS)) {
2198 /* Zeroes on the right */
2199 if (flagword & RZERO)
2200 PAD(_zeroes, rzero);
2202 /* The suffix */
2203 if (flagword & SUFFIX)
2204 PUT(suffix, suffixlength);
2206 /* Blanks on the right if required */
2207 if (flagword & FMINUS && width > k)
2208 PAD(_blanks, width - k);
2213 #ifdef _WIDE
2214 static int
2215 _watoi(wchar_t *fmt)
2217 int n = 0;
2218 wchar_t ch;
2220 ch = *fmt;
2221 if (_M_ISDIGIT(ch)) {
2222 n = ch - '0';
2223 ch = *++fmt;
2224 while (_M_ISDIGIT(ch)) {
2225 n *= 10;
2226 n += ch - '0';
2227 ch = *++fmt;
2230 return (n);
2232 #endif /* _WIDE */
2235 * This function initializes arglst, to contain the appropriate va_list values
2236 * for the first MAXARGS arguments.
2240 * Type modifier flags:
2241 * 0x01 for long
2242 * 0x02 for int
2243 * 0x04 for long long
2244 * 0x08 for long double
2247 #define FLAG_LONG 0x01
2248 #define FLAG_INT 0x02
2249 #define FLAG_LONG_LONG 0x04
2250 #define FLAG_LONG_DBL 0x08
2252 /* ARGSUSED3 */
2253 #ifdef _WIDE
2254 static void
2255 _wmkarglst(wchar_t *fmt, stva_list args, stva_list arglst[], int prflag)
2256 #else /* _WIDE */
2257 static void
2258 _mkarglst(char *fmt, stva_list args, stva_list arglst[], int prflag)
2259 #endif /* _WIDE */
2261 #ifdef _WIDE
2262 static const wchar_t digits[] = L"01234567890";
2263 static const wchar_t skips[] = L"# +-.'0123456789h$";
2264 #else /* _WIDE */
2265 static const char digits[] = "01234567890";
2266 static const char skips[] = "# +-.'0123456789h$";
2267 #endif /* _WIDE */
2268 enum types {INT = 1, LONG, CHAR_PTR, DOUBLE, LONG_DOUBLE, VOID_PTR,
2269 LONG_PTR, INT_PTR, LONG_LONG, LONG_LONG_PTR};
2270 enum types typelst[MAXARGS], curtype;
2271 ssize_t n;
2272 int maxnum, curargno, flags;
2275 * Algorithm 1. set all argument types to zero.
2276 * 2. walk through fmt putting arg types in typelst[].
2277 * 3. walk through args using va_arg(args.ap, typelst[n])
2278 * and set arglst[] to the appropriate values.
2279 * Assumptions: Cannot use %*$... to specify variable position.
2282 (void) memset((void *) typelst, 0, sizeof (typelst));
2283 maxnum = -1;
2284 curargno = 0;
2285 while ((fmt = STRCHR(fmt, '%')) != 0) {
2286 fmt++; /* skip % */
2287 if (fmt[n = STRSPN(fmt, digits)] == '$') {
2288 /* convert to zero base */
2289 curargno = ATOI(fmt) - 1;
2290 if (curargno < 0)
2291 continue;
2292 fmt += n + 1;
2294 flags = 0;
2295 again:;
2296 fmt += STRSPN(fmt, skips);
2297 switch (*fmt++) {
2298 case '%': /* there is no argument! */
2299 continue;
2300 case 'l':
2301 if (flags & (FLAG_LONG | FLAG_LONG_LONG)) {
2302 flags |= FLAG_LONG_LONG;
2303 flags &= ~FLAG_LONG;
2304 } else {
2305 flags |= FLAG_LONG;
2307 goto again;
2308 case 'j':
2309 #ifndef _LP64
2311 * *printf_c89() in 32-bit libc uses
2312 * 32-bit intmax_t; otherwise intmax_t
2313 * is 64-bits.
2315 if (!(prflag & _F_INTMAX32)) {
2316 #endif
2317 flags |= FLAG_LONG_LONG; /* 64-bit */
2318 #ifndef _LP64
2320 #endif
2321 goto again;
2322 case 't':
2323 flags |= FLAG_LONG;
2324 goto again;
2325 case 'z':
2326 flags |= FLAG_LONG;
2327 goto again;
2328 case 'L':
2329 flags |= FLAG_LONG_DBL;
2330 goto again;
2331 case '*': /* int argument used for value */
2332 /* check if there is a positional parameter */
2333 #ifdef _WIDE
2334 if ((*fmt >= 0) && (*fmt < 256) &&
2335 isdigit(*fmt))
2336 #else /* _WIDE */
2337 if (isdigit(*fmt))
2338 #endif /* _WIDE */
2340 int targno;
2341 targno = ATOI(fmt) - 1;
2342 fmt += STRSPN(fmt, digits);
2343 if (*fmt == '$')
2344 fmt++; /* skip '$' */
2345 if (targno >= 0 && targno < MAXARGS) {
2346 typelst[targno] = INT;
2347 if (maxnum < targno)
2348 maxnum = targno;
2350 goto again;
2352 flags |= FLAG_INT;
2353 curtype = INT;
2354 break;
2355 case 'a':
2356 case 'A':
2357 case 'e':
2358 case 'E':
2359 case 'f':
2360 case 'F':
2361 case 'g':
2362 case 'G':
2363 if (flags & FLAG_LONG_DBL)
2364 curtype = LONG_DOUBLE;
2365 else
2366 curtype = DOUBLE;
2367 break;
2368 case 's':
2369 curtype = CHAR_PTR;
2370 break;
2371 case 'p':
2372 curtype = VOID_PTR;
2373 break;
2374 case 'n':
2375 if (flags & FLAG_LONG_LONG)
2376 curtype = LONG_LONG_PTR;
2377 else if (flags & FLAG_LONG)
2378 curtype = LONG_PTR;
2379 else
2380 curtype = INT_PTR;
2381 break;
2382 default:
2383 if (flags & FLAG_LONG_LONG)
2384 curtype = LONG_LONG;
2385 else if (flags & FLAG_LONG)
2386 curtype = LONG;
2387 else
2388 curtype = INT;
2389 break;
2391 if (curargno >= 0 && curargno < MAXARGS) {
2392 typelst[curargno] = curtype;
2393 if (maxnum < curargno)
2394 maxnum = curargno;
2396 curargno++; /* default to next in list */
2397 if (flags & FLAG_INT) /* took care of *, keep going */
2399 flags ^= FLAG_INT;
2400 goto again;
2403 for (n = 0; n <= maxnum; n++) {
2404 arglst[n] = args;
2405 if (typelst[n] == 0)
2406 typelst[n] = INT;
2408 switch (typelst[n]) {
2409 case INT:
2410 (void) va_arg(args.ap, int);
2411 break;
2412 case LONG:
2413 (void) va_arg(args.ap, long);
2414 break;
2415 case CHAR_PTR:
2416 (void) va_arg(args.ap, char *);
2417 break;
2418 case DOUBLE:
2419 (void) va_arg(args.ap, double);
2420 break;
2421 case LONG_DOUBLE:
2422 (void) GETQVAL(args.ap);
2423 break;
2424 case VOID_PTR:
2425 (void) va_arg(args.ap, void *);
2426 break;
2427 case LONG_PTR:
2428 (void) va_arg(args.ap, long *);
2429 break;
2430 case INT_PTR:
2431 (void) va_arg(args.ap, int *);
2432 break;
2433 case LONG_LONG:
2434 (void) va_arg(args.ap, long long);
2435 break;
2436 case LONG_LONG_PTR:
2437 (void) va_arg(args.ap, long long *);
2438 break;
2444 * This function is used to find the va_list value for arguments whose
2445 * position is greater than MAXARGS. This function is slow, so hopefully
2446 * MAXARGS will be big enough so that this function need only be called in
2447 * unusual circumstances.
2448 * pargs is assumed to contain the value of arglst[MAXARGS - 1].
2450 /* ARGSUSED3 */
2451 #ifdef _WIDE
2452 static void
2453 _wgetarg(wchar_t *fmt, stva_list *pargs, long argno, int prflag)
2454 #else /* _WIDE */
2455 void
2456 _getarg(char *fmt, stva_list *pargs, long argno, int prflag)
2457 #endif /* _WIDE */
2460 #ifdef _WIDE
2461 static const wchar_t digits[] = L"01234567890";
2462 static const wchar_t skips[] = L"# +-.'0123456789h$";
2463 wchar_t *sfmt = fmt;
2464 #else /* _WIDE */
2465 static const char digits[] = "01234567890";
2466 static const char skips[] = "# +-.'0123456789h$";
2467 char *sfmt = fmt;
2468 #endif /* _WIDE */
2469 ssize_t n;
2470 int i, curargno, flags;
2471 int found = 1;
2473 i = MAXARGS;
2474 curargno = 1;
2475 while (found) {
2476 fmt = sfmt;
2477 found = 0;
2478 while ((i != argno) && (fmt = STRCHR(fmt, '%')) != 0) {
2479 fmt++; /* skip % */
2480 if (fmt[n = STRSPN(fmt, digits)] == '$') {
2481 curargno = ATOI(fmt);
2482 if (curargno <= 0)
2483 continue;
2484 fmt += n + 1;
2487 /* find conversion specifier for next argument */
2488 if (i != curargno) {
2489 curargno++;
2490 continue;
2491 } else
2492 found = 1;
2493 flags = 0;
2494 again:;
2495 fmt += STRSPN(fmt, skips);
2496 switch (*fmt++) {
2497 case '%': /* there is no argument! */
2498 continue;
2499 case 'l':
2500 if (flags & (FLAG_LONG | FLAG_LONG_LONG)) {
2501 flags |= FLAG_LONG_LONG;
2502 flags &= ~FLAG_LONG;
2503 } else {
2504 flags |= FLAG_LONG;
2506 goto again;
2507 case 'j':
2508 #ifndef _LP64
2510 * *printf_c89() in 32-bit libc uses
2511 * 32-bit intmax_t; otherwise intmax_t
2512 * is 64-bits.
2514 if (!(prflag & _F_INTMAX32)) {
2515 #endif
2516 flags |= FLAG_LONG_LONG; /* 64-bit */
2517 #ifndef _LP64
2519 #endif
2520 goto again;
2521 case 't':
2522 flags |= FLAG_LONG;
2523 goto again;
2524 case 'z':
2525 flags |= FLAG_LONG;
2526 goto again;
2527 case 'L':
2528 flags |= FLAG_LONG_DBL;
2529 goto again;
2530 case '*': /* int argument used for value */
2532 * check if there is a positional parameter;
2533 * if so, just skip it; its size will be
2534 * correctly determined by default
2536 if (_M_ISDIGIT(*fmt)) {
2537 fmt += STRSPN(fmt, digits);
2538 if (*fmt == '$')
2539 fmt++; /* skip '$' */
2540 goto again;
2542 flags |= FLAG_INT;
2543 (void) va_arg((*pargs).ap, int);
2544 break;
2545 case 'a':
2546 case 'A':
2547 case 'e':
2548 case 'E':
2549 case 'f':
2550 case 'F':
2551 case 'g':
2552 case 'G':
2553 if (flags & FLAG_LONG_DBL)
2554 (void) GETQVAL((*pargs).ap);
2555 else
2556 (void) va_arg((*pargs).ap, double);
2557 break;
2558 case 's':
2559 (void) va_arg((*pargs).ap, char *);
2560 break;
2561 case 'p':
2562 (void) va_arg((*pargs).ap, void *);
2563 break;
2564 case 'n':
2565 if (flags & FLAG_LONG_LONG)
2566 (void) va_arg((*pargs).ap, long long *);
2567 else if (flags & FLAG_LONG)
2568 (void) va_arg((*pargs).ap, long *);
2569 else
2570 (void) va_arg((*pargs).ap, int *);
2571 break;
2572 default:
2573 if (flags & FLAG_LONG_LONG)
2574 (void) va_arg((*pargs).ap, long long);
2575 else if (flags & FLAG_LONG)
2576 (void) va_arg((*pargs).ap, long int);
2577 else
2578 (void) va_arg((*pargs).ap, int);
2579 break;
2581 i++;
2582 curargno++; /* default to next in list */
2583 if (flags & FLAG_INT) /* took care of *, keep going */
2585 flags ^= FLAG_INT;
2586 goto again;
2590 /* missing specifier for parameter, assume param is an int */
2591 if (!found && i != argno) {
2592 (void) va_arg((*pargs).ap, int);
2593 i++;
2594 curargno = i;
2595 found = 1;
2600 #ifdef _WIDE
2601 static wchar_t *
2602 insert_thousands_sep(wchar_t *bp, wchar_t *ep)
2603 #else /* _WIDE */
2604 static char *
2605 insert_thousands_sep(char *bp, char *ep)
2606 #endif /* _WIDE */
2608 char thousep;
2609 struct lconv *locptr;
2610 ssize_t buf_index;
2611 int i;
2612 #ifdef _WIDE
2613 wchar_t *obp = bp;
2614 wchar_t buf[371];
2615 wchar_t *bufptr = buf;
2616 #else /* _WIDE */
2617 char *obp = bp;
2618 char buf[371];
2619 char *bufptr = buf;
2620 #endif /* _WIDE */
2621 char *grp_ptr;
2623 /* get the thousands sep. from the current locale */
2624 locptr = localeconv();
2625 thousep = *locptr->thousands_sep;
2626 grp_ptr = locptr->grouping;
2628 /* thousands sep. not use in this locale or no grouping required */
2629 if (!thousep || (*grp_ptr == '\0'))
2630 return (ep);
2632 buf_index = ep - bp;
2633 for (;;) {
2634 if (*grp_ptr == CHAR_MAX) {
2635 for (i = 0; i < buf_index--; i++)
2636 *bufptr++ = *(bp + buf_index);
2637 break;
2639 for (i = 0; i < *grp_ptr && buf_index-- > 0; i++)
2640 *bufptr++ = *(bp + buf_index);
2642 if (buf_index > 0) {
2643 #ifdef _WIDE
2644 *bufptr++ = (wchar_t)thousep;
2645 #else /* _WIDE */
2646 *bufptr++ = thousep;
2647 #endif /* _WIDE */
2648 ep++;
2650 else
2651 break;
2652 if (*(grp_ptr + 1) != '\0')
2653 ++grp_ptr;
2656 /* put the string in the caller's buffer in reverse order */
2657 --bufptr;
2658 while (buf <= bufptr)
2659 *obp++ = *bufptr--;
2660 return (ep);
2663 #ifdef _WIDE
2664 static wchar_t *
2665 insert_decimal_point(wchar_t *ep)
2666 #else
2667 static char *
2668 insert_decimal_point(char *ep)
2669 #endif
2671 struct lconv *locptr = localeconv();
2672 char *dp = locptr->decimal_point;
2673 #ifdef _WIDE
2674 wchar_t wdp;
2676 (void) mbtowc(&wdp, dp, MB_CUR_MAX);
2677 *ep = wdp;
2678 return (ep + 1);
2679 #else
2680 (void) memcpy(ep, dp, strlen(dp));
2681 return (ep + strlen(dp));
2682 #endif
2687 * Recovery scrswidth function -
2688 * this variant of wcswidth() accepts non-printable or illegal
2689 * widechar characters.
2691 static int
2692 _rec_scrswidth(wchar_t *wp, ssize_t n)
2694 int col;
2695 int i;
2697 col = 0;
2698 while (*wp && (n-- > 0)) {
2699 if ((i = _scrwidth(*wp++)) == 0)
2700 i = 1;
2701 col += i;
2703 return (col);