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