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