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