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