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