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]
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
36 #include "print.h" /* parameters & macros for doprnt */
48 #include "../i18n/_locale.h"
50 #include <sys/types.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) */
67 #define ATOI(x) _watoi((wchar_t *)x)
68 #define _P_HYPHEN 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)))
78 #define ATOI(x) atoi(x)
84 #define _M_ISDIGIT(c) isdigit((c))
85 #define _M_ISUPPER(c) isupper((c))
92 retp = put_wide(iop, &bufptr, bufferend, p, n, sflag); \
94 return ((ssize_t)EOF); \
101 retp = pad_wide(iop, &bufptr, bufferend, s, n, sflag); \
103 return ((ssize_t)EOF); \
107 #define FPCONV(func, val, prec, decpt, sign, cvtbuf) \
109 char cb[DECIMAL_STRING_LENGTH]; \
112 (void) func(val, prec, decpt, sign, cb); \
116 *wp++ = (wchar_t)*cp++; \
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 \
132 if (snflag || bufptr > bufferend ||\
133 (unsigned long)(bufferend - bufptr) < (n)) {\
134 if (!_dowrite(p, n, iop, &bufptr)) {\
138 unsigned char *fbp = bufptr;\
142 *(fbp + 1) = *(p + 1);\
143 *(fbp + 2) = *(p + 2);\
144 *(fbp + 3) = *(p + 3);\
149 *(fbp + 1) = *(p + 1);\
150 *(fbp + 2) = *(p + 2);\
155 *(fbp + 1) = *(p + 1);\
162 bufptr = (unsigned char *)memcpy(fbp, p, 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)) \
175 #define FPCONV(func, val, prec, decpt, sign, cvtbuf) \
176 (void) func(val, prec, decpt, sign, cvtbuf);
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 */
198 static wchar_t *insert_decimal_point(wchar_t *ep
);
199 static wchar_t *insert_thousands_sep(wchar_t *bp
, wchar_t *ep
);
201 static char *insert_decimal_point(char *ep
);
202 static char *insert_thousands_sep(char *bp
, char *ep
);
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 */
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
{
226 static void _wmkarglst(wchar_t *, stva_list
, stva_list
[], int);
227 static void _wgetarg(wchar_t *, stva_list
*, long, int);
229 static void _mkarglst(char *, stva_list
, stva_list
[], int);
230 void _getarg(char *, stva_list
*, long, 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
;
248 value
= value
% 5 * 2 + lowbit
+ '0';
253 _lowlldigit(long long *valptr
)
255 ssize_t lowbit
= *valptr
& 1;
256 long long value
= (*valptr
>> 1) & ~HIBITLL
;
258 value
= value
% 5 * 2 + lowbit
+ '0';
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. */
267 _dowrite(const char *p
, ssize_t n
, FILE *iop
, unsigned char **ptrptr
)
269 if (!(iop
->_flag
& _IOREAD
)) {
270 iop
->_cnt
-= (*ptrptr
- iop
->_ptr
);
272 _bufsync(iop
, _bufend(iop
));
273 if (_FWRITE(p
, 1, n
, iop
) != n
) {
281 *ptrptr
= (unsigned char *)memcpy((char *)*ptrptr
, p
, n
) + n
;
288 static const char _blanks
[] = " ";
289 static const char _zeroes
[] = "00000000000000000000";
291 static const wchar_t uc_digs
[] = L
"0123456789ABCDEF";
292 static const wchar_t lc_digs
[] = L
"0123456789abcdef";
294 static const char uc_digs
[] = "0123456789ABCDEF";
295 static const char lc_digs
[] = "0123456789abcdef";
300 put_wide(FILE *iop
, unsigned char **bufptr
,
301 unsigned char *bufferend
, wchar_t *p
, size_t n
,
304 unsigned char *newbufptr
;
310 len
= (wchar_t *)bufferend
- (wchar_t *)*bufptr
;
312 (void) wmemcpy((wchar_t *)*bufptr
, p
, len
);
313 iop
->_ptr
= bufferend
;
316 (void) wmemcpy((wchar_t *)*bufptr
, p
, n
);
317 *bufptr
= (unsigned char *)((wchar_t *)*bufptr
+ n
);
324 tsize
= (n
+ 1) * MB_LEN_MAX
;
325 tmpp
= lmalloc(tsize
);
332 for (len
= 0, i
= 0; i
< n
; i
++) {
333 r
= wctomb(tmpq
, *q
++);
343 newbufptr
= *bufptr
+ len
;
344 if (newbufptr
> bufferend
) {
345 if (!_dowrite(tmpp
, len
, iop
, bufptr
)) {
350 (void) memcpy(*bufptr
, tmpp
, len
);
359 pad_wide(FILE *iop
, unsigned char **bufptr
,
360 unsigned char *bufferend
, const char *s
, size_t n
,
363 unsigned char *newbufptr
;
371 len
= (wchar_t *)bufferend
- (wchar_t *)*bufptr
;
373 (void) wmemset((wchar_t *)*bufptr
, ps
, len
);
374 iop
->_ptr
= bufferend
;
377 (void) wmemset((wchar_t *)*bufptr
, ps
, n
);
378 *bufptr
= (unsigned char *)((wchar_t *)*bufptr
+ n
);
382 for (nn
= n
; nn
> PAD_LEN
; nn
-= PAD_LEN
) {
383 if (!_dowrite(s
, PAD_LEN
, iop
, bufptr
))
386 newbufptr
= *bufptr
+ nn
;
387 if (newbufptr
> bufferend
) {
388 if (!_dowrite(s
, nn
, iop
, bufptr
))
391 (void) memcpy(*bufptr
, s
, nn
);
401 _wdoprnt(const wchar_t *format
, va_list in_args
, FILE *iop
)
403 return (_wndoprnt(format
, in_args
, iop
, 0));
407 _doprnt(const char *format
, va_list in_args
, FILE *iop
)
409 return (_ndoprnt(format
, in_args
, iop
, 0));
416 _wndoprnt(const wchar_t *format
, va_list in_args
, FILE *iop
, int prflag
)
419 _ndoprnt(const char *format
, va_list in_args
, FILE *iop
, int prflag
)
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
;
440 /* This variable counts output characters. */
443 /* This variable counts output characters. */
454 /* Starting and ending points for value to be printed */
458 /* Field width and precision */
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 */
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 */
498 wchar_t prefixbuf
[4];
500 /* Exponent or empty */
503 /* Buffer to create exponent */
504 wchar_t expbuf
[MAXESIZ
+ 1];
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 */
514 /* Exponent or empty */
517 /* Buffer to create exponent */
518 char expbuf
[MAXESIZ
+ 1];
521 /* Length of prefix and of suffix */
522 ssize_t prefixlength
, suffixlength
;
524 /* Combined length of leading zeroes, trailing zeroes, and suffix */
527 /* The value being converted, if integer */
530 /* The value being converted, if long long */
533 /* Output value from aconvert */
536 /* Output values from fcvt and ecvt */
540 /* Pointer to a translate table for digits of whatever radix */
543 /* Pointer to a translate table for digits of whatever radix */
548 ssize_t k
, lradix
, mradix
;
551 int inf_nan_mixed_case
= 0;
554 /* variables for positional parameters */
555 /* save the beginning of the format */
556 wchar_t *sformat
= (wchar_t *)format
;
558 /* variables for positional parameters */
559 char *sformat
= (char *)format
; /* save the beginning of the format */
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 */
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
583 va_copy(args
.ap
, in_args
);
587 if (iop
->_flag
== _IOREAD
)
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)
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
;
609 maxcount
= (size_t)iop
->_cnt
;
610 bufferend
= (unsigned char *)(((wchar_t *)iop
->_ptr
) +
613 bufferend
= _bufend(iop
);
616 /* initialize buffer pointer and buffer end pointer */
618 if (iop
->_flag
& _IOREAD
) {
620 * [v]sprintf or [v]snprintf
622 if (iop
->_cnt
== MAXINT
) {
624 * [v]sprintf (no boundschecking)
627 (unsigned char *)((long)bufptr
| (-1L & ~HIBITL
));
630 * [v]snprintf (with boundschecking) or
631 * iop with _IORW has been read.
633 bufferend
= _bufend(iop
);
634 if (bufferend
== NULL
) {
638 * [v]snprint() needs to be always handled by
646 * [v]printf or [v]fprintf
648 bufferend
= _bufend(iop
);
653 * The main loop -- this loop goes through one iteration
654 * for each string of ordinary characters or format specification.
659 if ((fcode
= *format
) != '\0' && fcode
!= '%') {
661 bp
= (wchar_t *)format
;
667 } while ((fcode
= *format
) != '\0' && fcode
!= '%');
669 count
+= (n
= format
- bp
); /* n = no. of non-% chars */
672 if (fcode
== '\0') { /* end of format; return */
673 ssize_t nn
= bufptr
- iop
->_ptr
;
678 return ((ssize_t
)count
);
684 /* in case of interrupt during last several lines */
685 if ((bufptr
+ iop
->_cnt
) > bufferend
&& !(iop
->_flag \
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
);
694 return (FERROR(iop
) ? EOF
: (ssize_t
)count
);
696 return (FERROR(iop
) ? EOF
: (int)count
);
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
708 width
= prefixlength
= otherlength
= 0;
709 flagword
= suffixlength
= 0;
720 switch (fcode
= *format
++) {
727 flagword
&= ~PADZERO
; /* ignore 0 flag */
732 case '\'': /* XSH4 */
739 /* Scan the field width and precision */
746 if (_M_ISDIGIT(*format
)) {
751 if (!(flagword
& DOTSEEN
)) {
752 width
= va_arg(args
.ap
, int);
758 prec
= va_arg(args
.ap
, int);
761 flagword
^= DOTSEEN
; /* ANSI sez so */
772 _wmkarglst(sformat
, sargs
, arglst
, prflag
);
774 _mkarglst(sformat
, sargs
, arglst
, prflag
);
778 if (flagword
& DOTSEEN
) {
786 /* illegal position */
790 if (position
<= MAXARGS
) {
791 targs
= arglst
[position
- 1];
793 targs
= arglst
[MAXARGS
- 1];
795 _wgetarg(sformat
, &targs
, position
, prflag
);
797 _getarg(sformat
, &targs
, position
, prflag
);
805 if (flagword
& DOTSEEN
) {
806 prec
= va_arg(targs
.ap
, int);
809 flagword
^= DOTSEEN
; /* XSH */
812 width
= va_arg(targs
.ap
, int);
822 case '0': /* obsolescent spec: leading zero in width */
823 /* means pad with leading zeros */
824 if (!(flagword
& (DOTSEEN
| FMINUS
)))
837 while (_M_ISDIGIT(fcode
= *format
)) {
838 num
= num
* 10 + fcode
- '0';
841 if (flagword
& DOTSEEN
)
848 /* Scan the length modifier */
850 if (!(flagword
& XLONG
)) {
863 case 'L': /* long double */
868 if (!(flagword
& CHAR
)) {
869 if (flagword
& SHORT
) {
882 * *printf_c89() in 32-bit libc uses
883 * 32-bit intmax_t; otherwise intmax_t
886 if (!(prflag
& _F_INTMAX32
)) {
888 flagword
|= XLONG
; /* [u]intmax_t (64) */
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 */
907 if (!(flagword
& XLONG
)) {
908 flagword
|= LENGTH
; /* [s]size_t */
913 * The character addressed by format must be
914 * the format letter -- there is nothing
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
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
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
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
968 * decimal fixed point representations
970 * HIBITL is 100...000
971 * binary, and is equal to the maximum
973 * We assume a 2's complement machine
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 */
991 * Negate, checking in advance for
997 /* number is -HIBITLL; convert last */
998 /* digit now and get positive number */
999 *--bp
= _lowlldigit(&ll
);
1000 } else if (flagword
& FPLUS
) {
1003 } else if (flagword
& FBLANK
) {
1007 } else { /* not long long */
1008 if (flagword
& LENGTH
)
1009 val
= va_arg(args
.ap
, long);
1011 val
= va_arg(args
.ap
, int);
1013 if (flagword
& SHORT
)
1015 else if (flagword
& CHAR
)
1018 /* If signed conversion, make sign */
1023 * Negate, checking in advance
1024 * for possible overflow.
1029 * number is -HIBITL; convert
1030 * last digit now and get
1034 *--bp
= _lowdigit(&val
);
1035 } else if (flagword
& FPLUS
) {
1038 } else if (flagword
& FBLANK
) {
1049 if (flagword
& XLONG
) {
1052 if (lll
!= 0LL || !(flagword
& DOTSEEN
))
1053 *--bp
= (wchar_t)lll
+ L
'0';
1055 if (lll
!= 0LL || !(flagword
& DOTSEEN
))
1056 *--bp
= (char)lll
+ '0';
1064 (tll
- lll
* 10 + '0');
1067 (tll
- lll
* 10 + '0');
1069 } while (lll
>= 10);
1071 *--bp
= (wchar_t)lll
+ '0';
1073 *--bp
= (char)lll
+ '0';
1079 if (qval
!= 0 || !(flagword
& DOTSEEN
))
1080 *--bp
= (wchar_t)qval
+ '0';
1082 if (qval
!= 0 || !(flagword
& DOTSEEN
))
1083 *--bp
= (char)qval
+ '0';
1091 (n
- qval
* 10 + '0');
1094 (n
- qval
* 10 + '0');
1098 *--bp
= (wchar_t)qval
+ '0';
1100 *--bp
= (char)qval
+ '0';
1105 /* Handle the ' flag */
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
;
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);
1130 *--bp
= _lowlldigit(&ll
);
1132 if (flagword
& LENGTH
)
1133 val
= va_arg(args
.ap
, long);
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
;
1143 *--bp
= _lowdigit(&val
);
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
1158 * We assume a 2's complement machine
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
) &&
1176 flagword
&= ~(XLONG
| SHORT
);
1186 if ((flagword
& PADZERO
) && (flagword
& DOTSEEN
))
1187 flagword
&= ~PADZERO
; /* ignore 0 flag */
1190 /* Set translate table for digits */
1191 tab
= (wchar_t *)((fcode
== 'X') ? uc_digs
: lc_digs
);
1193 /* Set translate table for digits */
1194 tab
= (fcode
== 'X') ? uc_digs
: lc_digs
;
1197 /* Fetch the argument to be printed */
1198 if (flagword
& XLONG
) {
1199 ll
= va_arg(args
.ap
, long long);
1201 if (flagword
& LENGTH
)
1202 val
= va_arg(args
.ap
, long);
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
) {
1218 if (!(flagword
& DOTSEEN
)) {
1219 otherlength
= lzero
= 1;
1223 *--bp
= tab
[(ssize_t
)(lll
& mradix
)];
1224 lll
= ((lll
>> 1) & ~HIBITLL
) \
1226 } while (lll
!= 0LL);
1231 if (!(flagword
& DOTSEEN
)) {
1232 otherlength
= lzero
= 1;
1236 *--bp
= tab
[qval
& mradix
];
1237 qval
= ((qval
>> 1) & ~HIBITL
) \
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
;
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)))
1258 if (!(flagword
& LZERO
)) {
1259 otherlength
= lzero
= 1;
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;
1288 #error Unknown architecture
1291 FPCONV(__qaconvert
, &qval
,
1292 min(prec
+ 1, MAXECVT
), &exp
, &sign
,
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
,
1308 * The following is wide-character safe because
1309 * __aconvert and __qaconvert only produce ASCII
1312 if (!isxdigit((unsigned char)*bp
)) {
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
;
1329 } else if (flagword
& FPLUS
) {
1332 } else if (flagword
& FBLANK
) {
1337 *p
++ = (fcode
== 'A') ? 'X' : 'x';
1341 /* put the first digit in the buffer */
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 */
1352 for (; rz
> 0 && *bp
!= '\0'; --rz
) {
1353 *p
++ = ('a' <= *bp
&& *bp
<= 'f')?
1358 for (; rz
> 0 && *bp
!= '\0'; --rz
)
1362 otherlength
= rzero
= rz
;
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
];
1376 if (buf
[0] != '0') {
1382 for (; nn
> 9; nn
/= 10)
1383 *--suffix
= todigit(nn
% 10);
1384 *--suffix
= todigit(nn
);
1385 *--suffix
= (exp
>= 0) ? '+' : '-';
1392 *--suffix
= (fcode
== 'A') ? 'P' : 'p';
1394 /* compute size of suffix */
1395 suffixlength
= &expbuf
[MAXESIZ
] - suffix
;
1396 otherlength
+= suffixlength
;
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
))
1413 if (flagword
& QUAD
) { /* long double */
1414 long double qval
= GETQVAL(args
.ap
);
1416 FPCONV(qeconvert
, &qval
,
1417 min(prec
+ 1, MAXECVT
), &decpt
, &sign
,
1419 } else { /* double */
1420 double dval
= va_arg(args
.ap
, double);
1422 FPCONV(econvert
, dval
,
1423 min(prec
+ 1, MAXECVT
), &decpt
, &sign
,
1429 inf_nan_mixed_case
= (__xpg6
&
1430 _C99SUSv3_mixed_case_Inf_and_NaN
);
1434 /* Determine the prefix */
1439 } else if (flagword
& FPLUS
) {
1442 } else if (flagword
& FBLANK
) {
1447 /* Place the first digit in the buffer */
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 */
1457 for (; rz
> 0 && *bp
!= '\0'; --rz
)
1460 otherlength
= rzero
= rz
;
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') {
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])
1486 /* Put in the exponent sign */
1487 *--suffix
= (decpt
> 0 || buf
[0] == '0') ? '+' : '-';
1490 *--suffix
= _M_ISUPPER(fcode
) ? 'E' : 'e';
1492 /* compute size of suffix */
1493 otherlength
+= (suffixlength
= &expbuf
[MAXESIZ
] \
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
))
1515 if (flagword
& QUAD
) { /* long double */
1516 long double qval
= GETQVAL(args
.ap
);
1518 FPCONV(qfconvert
, &qval
, min(prec
, MAXFCVT
),
1519 &decpt
, &sign
, cvtbuf
);
1523 * qfconvert would have required
1524 * too many characters; use qeconvert
1527 FPCONV(qeconvert
, &qval
,
1528 min(prec
+ 1, MAXECVT
), &decpt
,
1532 } else { /* double */
1533 double dval
= va_arg(args
.ap
, double);
1535 FPCONV(fconvert
, dval
, min(prec
, MAXFCVT
),
1536 &decpt
, &sign
, cvtbuf
);
1542 inf_nan_mixed_case
= (__xpg6
&
1543 _C99SUSv3_mixed_case_Inf_and_NaN
);
1547 /* Determine the prefix */
1552 } else if (flagword
& FPLUS
) {
1555 } else if (flagword
& FBLANK
) {
1560 /* Initialize buffer pointer */
1566 /* Emit the digits before the decimal point */
1569 *p
++ = (nn
<= 0 || *bp
== '\0' || \
1570 k
>= MAXFSIG
) ? '0' : (k
++, *bp
++);
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
);
1584 otherlength
= rzero
= prec
- nn
;
1587 *p
++ = (++decpt
<= 0 || *bp
== '\0' || \
1588 k
>= MAXFSIG
) ? '0' : (k
++, *bp
++);
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
))
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
);
1622 inf_nan_mixed_case
= (__xpg6
&
1623 _C99SUSv3_mixed_case_Inf_and_NaN
);
1626 if (*bp
== '0') /* the value converted is zero */
1631 if (!(flagword
& FSHARP
)) {
1639 while (kk
>= 1 && bp
[kk
-1] == '0')
1642 if (decpt
< -3 || decpt
> prec
) {
1661 case 'C': /* XPG XSH4 extention */
1666 temp
= va_arg(args
.ap
, wchar_t);
1679 if ((retcode
= wctomb(buf
, temp
))
1684 p
= (bp
= buf
) + retcode
;
1686 } else { /* NULL character */
1702 temp
= va_arg(args
.ap
, wchar_t);
1704 if ((retcode
= wctomb(buf
, temp
))
1708 p
= (bp
= buf
) + retcode
;
1710 } else { /* NULL character */
1717 if (flagword
& XLONG
) {
1719 temp
= va_arg(args
.ap
, long long);
1721 buf
[0] = (wchar_t)temp
;
1723 buf
[0] = (char)temp
;
1726 buf
[0] = va_arg(args
.ap
, int);
1728 p
= (bp
= &buf
[0]) + 1;
1738 case 'S': /* XPG XSH4 extention */
1744 bp
= va_arg(args
.ap
, wchar_t *);
1746 bp
= (wchar_t *)widenullstr
;
1747 if (!(flagword
& DOTSEEN
)) {
1748 /* wide character handling */
1755 if ((prec
- wcount
- 1) >= 0) {
1768 bp
= va_arg(args
.ap
, char *);
1770 bp
= (char *)widenullstr
;
1771 if (!(flagword
& DOTSEEN
)) {
1772 /* wide character handling */
1776 wp
= (wchar_t *)(uintptr_t)bp
;
1781 nbytes
= wctomb(tmpbuf
, *wp
);
1786 if ((prec
- (wcount
+ nbytes
)) >= 0) {
1793 sec_display
= wcount
;
1802 cbp
= va_arg(args
.ap
, char *);
1804 cbp
= (char *)nullstr
;
1805 if (!(flagword
& DOTSEEN
)) {
1809 nwc
= mbstowcs(NULL
, cbp
, 0);
1810 if (nwc
== (size_t)-1) {
1814 bpsize
= sizeof (wchar_t) * (nwc
+ 1);
1815 wstr
= (wchar_t *)lmalloc(bpsize
);
1820 nwc
= mbstowcs(wstr
, cbp
, MAXINT
);
1828 nwc
= mbstowcs(NULL
, cbp
, 0);
1829 if (nwc
== (size_t)-1) {
1834 bpsize
= sizeof (wchar_t) * nwc
;
1835 wstr
= (wchar_t *)lmalloc(bpsize
);
1840 nwc
= mbstowcs(wstr
, cbp
, nwc
);
1850 bpsize
= sizeof (wchar_t) * prec
;
1851 wstr
= (wchar_t *)lmalloc(bpsize
);
1856 nwc
= mbstowcs(wstr
, cbp
, prec
);
1864 bp
= va_arg(args
.ap
, char *);
1866 bp
= (char *)nullstr
;
1867 if (!(flagword
& DOTSEEN
)) {
1869 /* wide character handling */
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 &&
1893 if ((nwc
= mbstowcs(wbuff
, bp
,
1894 NW
)) == (size_t)-1) {
1895 /* Estimate width */
1896 sec_display
= strlen(bp
);
1903 * If widechar does not fit into
1904 * wbuff, allocate larger buffer
1907 mbstowcs(NULL
, bp
, NULL
)) ==
1913 wpsize
= (nwc
+ 1) *
1915 if ((wp
= lmalloc(wpsize
))
1920 if ((nwc
= mbstowcs(wp
,
1921 bp
, nwc
)) == (size_t)-1) {
1928 if ((sec_display
= wcswidth(wptr
, nwc
))
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.
1951 /* wide character handling */
1954 wp
= (wchar_t *)(uintptr_t)bp
;
1958 (prec
-= _scrwidth(*wp
)) >= 0) {
1960 wctomb(tmpbuf
, *wp
)) < 0)
1967 prec
+= _scrwidth(*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
1988 if ((nbytes
= mbtowc(&wc
, qp
,
1989 MB_LEN_MAX
)) == -1) {
1990 /* print illegal char */
2001 if ((prec
-= ncol
) >= 0) {
2012 sec_display
= preco
- prec
;
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.
2023 qp
= memchr(bp
, '\0', prec
);
2036 if (flagword
& XLONG
) {
2038 svcount
= va_arg(args
.ap
, long long *);
2039 *svcount
= (long long)count
;
2040 } else if (flagword
& LENGTH
) {
2042 svcount
= va_arg(args
.ap
, long *);
2043 *svcount
= (long)count
;
2044 } else if (flagword
& SHORT
) {
2046 svcount
= va_arg(args
.ap
, short *);
2047 *svcount
= (short)count
;
2048 } else if (flagword
& CHAR
) {
2050 svcount
= va_arg(args
.ap
, char *);
2051 *svcount
= (char)count
;
2054 svcount
= va_arg(args
.ap
, int *);
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 */
2067 if (inf_nan_mixed_case
) {
2069 for (p
= bp
+ 1; *p
!= '\0'; p
++)
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
);
2082 } else if (flagword
& FPLUS
) {
2085 } else if (flagword
& FBLANK
) {
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) */
2100 if (sec_display
) /* when format is %s or %ws or %S */
2106 * k is the (screen) width or # of bytes of the converted value
2108 k
+= prefixlength
+ otherlength
;
2118 * update count which is the overall size of the output data
2119 * and passed to memchr()
2123 * when wflag != 0 (i.e. %ws or %wc), the size of the
2124 * converted value is wcount bytes
2129 * when wflag == 0, the size of the converted
2130 * value is n (= p-bp) bytes
2134 count
+= prefixlength
+ otherlength
;
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
)) {
2150 k
= width
; /* cancel padding blanks */
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
);
2169 if ((fcode
== 's') && !lflag
) {
2174 /* The value itself */
2175 if ((fcode
== 's' || fcode
== 'S') && wflag
) {
2176 /* wide character handling */
2177 wchar_t *wp
= (wchar_t *)(uintptr_t)bp
;
2181 printn
= (wchar_t *)(uintptr_t)p
-
2182 (wchar_t *)(uintptr_t)bp
;
2184 while (printn
> 0) {
2185 if ((cnt
= wctomb(buf
, *wp
)) < 0)
2191 } else { /* non wide character value */
2197 if (flagword
& (RZERO
| SUFFIX
| FMINUS
)) {
2198 /* Zeroes on the right */
2199 if (flagword
& RZERO
)
2200 PAD(_zeroes
, rzero
);
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
);
2215 _watoi(wchar_t *fmt
)
2221 if (_M_ISDIGIT(ch
)) {
2224 while (_M_ISDIGIT(ch
)) {
2235 * This function initializes arglst, to contain the appropriate va_list values
2236 * for the first MAXARGS arguments.
2240 * Type modifier flags:
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
2255 _wmkarglst(wchar_t *fmt
, stva_list args
, stva_list arglst
[], int prflag
)
2258 _mkarglst(char *fmt
, stva_list args
, stva_list arglst
[], int prflag
)
2262 static const wchar_t digits
[] = L
"01234567890";
2263 static const wchar_t skips
[] = L
"# +-.'0123456789h$";
2265 static const char digits
[] = "01234567890";
2266 static const char skips
[] = "# +-.'0123456789h$";
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
;
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
));
2285 while ((fmt
= STRCHR(fmt
, '%')) != 0) {
2287 if (fmt
[n
= STRSPN(fmt
, digits
)] == '$') {
2288 /* convert to zero base */
2289 curargno
= ATOI(fmt
) - 1;
2296 fmt
+= STRSPN(fmt
, skips
);
2298 case '%': /* there is no argument! */
2301 if (flags
& (FLAG_LONG
| FLAG_LONG_LONG
)) {
2302 flags
|= FLAG_LONG_LONG
;
2303 flags
&= ~FLAG_LONG
;
2311 * *printf_c89() in 32-bit libc uses
2312 * 32-bit intmax_t; otherwise intmax_t
2315 if (!(prflag
& _F_INTMAX32
)) {
2317 flags
|= FLAG_LONG_LONG
; /* 64-bit */
2329 flags
|= FLAG_LONG_DBL
;
2331 case '*': /* int argument used for value */
2332 /* check if there is a positional parameter */
2334 if ((*fmt
>= 0) && (*fmt
< 256) &&
2341 targno
= ATOI(fmt
) - 1;
2342 fmt
+= STRSPN(fmt
, digits
);
2344 fmt
++; /* skip '$' */
2345 if (targno
>= 0 && targno
< MAXARGS
) {
2346 typelst
[targno
] = INT
;
2347 if (maxnum
< targno
)
2363 if (flags
& FLAG_LONG_DBL
)
2364 curtype
= LONG_DOUBLE
;
2375 if (flags
& FLAG_LONG_LONG
)
2376 curtype
= LONG_LONG_PTR
;
2377 else if (flags
& FLAG_LONG
)
2383 if (flags
& FLAG_LONG_LONG
)
2384 curtype
= LONG_LONG
;
2385 else if (flags
& FLAG_LONG
)
2391 if (curargno
>= 0 && curargno
< MAXARGS
) {
2392 typelst
[curargno
] = curtype
;
2393 if (maxnum
< curargno
)
2396 curargno
++; /* default to next in list */
2397 if (flags
& FLAG_INT
) /* took care of *, keep going */
2403 for (n
= 0; n
<= maxnum
; n
++) {
2405 if (typelst
[n
] == 0)
2408 switch (typelst
[n
]) {
2410 (void) va_arg(args
.ap
, int);
2413 (void) va_arg(args
.ap
, long);
2416 (void) va_arg(args
.ap
, char *);
2419 (void) va_arg(args
.ap
, double);
2422 (void) GETQVAL(args
.ap
);
2425 (void) va_arg(args
.ap
, void *);
2428 (void) va_arg(args
.ap
, long *);
2431 (void) va_arg(args
.ap
, int *);
2434 (void) va_arg(args
.ap
, long long);
2437 (void) va_arg(args
.ap
, long long *);
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].
2453 _wgetarg(wchar_t *fmt
, stva_list
*pargs
, long argno
, int prflag
)
2456 _getarg(char *fmt
, stva_list
*pargs
, long argno
, int prflag
)
2461 static const wchar_t digits
[] = L
"01234567890";
2462 static const wchar_t skips
[] = L
"# +-.'0123456789h$";
2463 wchar_t *sfmt
= fmt
;
2465 static const char digits
[] = "01234567890";
2466 static const char skips
[] = "# +-.'0123456789h$";
2470 int i
, curargno
, flags
;
2478 while ((i
!= argno
) && (fmt
= STRCHR(fmt
, '%')) != 0) {
2480 if (fmt
[n
= STRSPN(fmt
, digits
)] == '$') {
2481 curargno
= ATOI(fmt
);
2487 /* find conversion specifier for next argument */
2488 if (i
!= curargno
) {
2495 fmt
+= STRSPN(fmt
, skips
);
2497 case '%': /* there is no argument! */
2500 if (flags
& (FLAG_LONG
| FLAG_LONG_LONG
)) {
2501 flags
|= FLAG_LONG_LONG
;
2502 flags
&= ~FLAG_LONG
;
2510 * *printf_c89() in 32-bit libc uses
2511 * 32-bit intmax_t; otherwise intmax_t
2514 if (!(prflag
& _F_INTMAX32
)) {
2516 flags
|= FLAG_LONG_LONG
; /* 64-bit */
2528 flags
|= FLAG_LONG_DBL
;
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
);
2539 fmt
++; /* skip '$' */
2543 (void) va_arg((*pargs
).ap
, int);
2553 if (flags
& FLAG_LONG_DBL
)
2554 (void) GETQVAL((*pargs
).ap
);
2556 (void) va_arg((*pargs
).ap
, double);
2559 (void) va_arg((*pargs
).ap
, char *);
2562 (void) va_arg((*pargs
).ap
, void *);
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 *);
2570 (void) va_arg((*pargs
).ap
, int *);
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);
2578 (void) va_arg((*pargs
).ap
, int);
2582 curargno
++; /* default to next in list */
2583 if (flags
& FLAG_INT
) /* took care of *, keep going */
2590 /* missing specifier for parameter, assume param is an int */
2591 if (!found
&& i
!= argno
) {
2592 (void) va_arg((*pargs
).ap
, int);
2602 insert_thousands_sep(wchar_t *bp
, wchar_t *ep
)
2605 insert_thousands_sep(char *bp
, char *ep
)
2609 struct lconv
*locptr
;
2615 wchar_t *bufptr
= buf
;
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'))
2632 buf_index
= ep
- bp
;
2634 if (*grp_ptr
== CHAR_MAX
) {
2635 for (i
= 0; i
< buf_index
--; i
++)
2636 *bufptr
++ = *(bp
+ buf_index
);
2639 for (i
= 0; i
< *grp_ptr
&& buf_index
-- > 0; i
++)
2640 *bufptr
++ = *(bp
+ buf_index
);
2642 if (buf_index
> 0) {
2644 *bufptr
++ = (wchar_t)thousep
;
2646 *bufptr
++ = thousep
;
2652 if (*(grp_ptr
+ 1) != '\0')
2656 /* put the string in the caller's buffer in reverse order */
2658 while (buf
<= bufptr
)
2665 insert_decimal_point(wchar_t *ep
)
2668 insert_decimal_point(char *ep
)
2671 struct lconv
*locptr
= localeconv();
2672 char *dp
= locptr
->decimal_point
;
2676 (void) mbtowc(&wdp
, dp
, MB_CUR_MAX
);
2680 (void) memcpy(ep
, dp
, strlen(dp
));
2681 return (ep
+ strlen(dp
));
2687 * Recovery scrswidth function -
2688 * this variant of wcswidth() accepts non-printable or illegal
2689 * widechar characters.
2692 _rec_scrswidth(wchar_t *wp
, ssize_t n
)
2698 while (*wp
&& (n
-- > 0)) {
2699 if ((i
= _scrwidth(*wp
++)) == 0)