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