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