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