xref: /onnv-gate/usr/src/lib/libc/port/print/doprnt.c (revision 9959:acbef346fd18)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
56812Sraf  * Common Development and Distribution License (the "License").
66812Sraf  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
216812Sraf 
220Sstevel@tonic-gate /*
23*9959SDarren.Moffat@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate /*	Copyright (c) 1988 AT&T	*/
280Sstevel@tonic-gate /*	  All Rights Reserved  	*/
290Sstevel@tonic-gate 
300Sstevel@tonic-gate /*
310Sstevel@tonic-gate  *	_doprnt: common code for printf, fprintf, sprintf
320Sstevel@tonic-gate  */
330Sstevel@tonic-gate 
346812Sraf #include "lint.h"
350Sstevel@tonic-gate #include "mtlib.h"
360Sstevel@tonic-gate #include "print.h"	/* parameters & macros for doprnt */
370Sstevel@tonic-gate #include <wchar.h>
380Sstevel@tonic-gate #include "libc.h"
390Sstevel@tonic-gate #include <stdlib.h>
400Sstevel@tonic-gate #include <limits.h>
410Sstevel@tonic-gate #include <ctype.h>
420Sstevel@tonic-gate #include <stdarg.h>
430Sstevel@tonic-gate #include <values.h>
440Sstevel@tonic-gate #include <memory.h>
450Sstevel@tonic-gate #include <string.h>
460Sstevel@tonic-gate #include <locale.h>
470Sstevel@tonic-gate #include <widec.h>
480Sstevel@tonic-gate #include "../i18n/_locale.h"
490Sstevel@tonic-gate #include <errno.h>
500Sstevel@tonic-gate #include <sys/types.h>
510Sstevel@tonic-gate #include <libw.h>
520Sstevel@tonic-gate #include "mse.h"
530Sstevel@tonic-gate #include "xpg6.h"
540Sstevel@tonic-gate 
55*9959SDarren.Moffat@Sun.COM static const char nullstr[] = "(null)";
56*9959SDarren.Moffat@Sun.COM static const wchar_t widenullstr[] = L"(null)";
57*9959SDarren.Moffat@Sun.COM 
580Sstevel@tonic-gate #if defined(__i386) || defined(__amd64) || defined(__sparcv9)
590Sstevel@tonic-gate #define	GETQVAL(arg)	(va_arg(arg, long double))
600Sstevel@tonic-gate #else /* !defined(__i386) && !defined(__sparcv9) */
610Sstevel@tonic-gate #define	GETQVAL(arg)	*(va_arg(arg, long double *))
620Sstevel@tonic-gate #endif /* !defined(__i386) && !defined(__sparcv9) */
630Sstevel@tonic-gate 
640Sstevel@tonic-gate #ifdef	_WIDE
650Sstevel@tonic-gate #define	STRCHR	wcschr
660Sstevel@tonic-gate #define	STRSPN	wcsspn
670Sstevel@tonic-gate #define	ATOI(x)	_watoi((wchar_t *)x)
680Sstevel@tonic-gate #define	_P_HYPHEN	L"-"
690Sstevel@tonic-gate #define	_P_PLUS		L"+"
700Sstevel@tonic-gate #define	_P_BLANK	L" "
710Sstevel@tonic-gate #define	_P_ZEROx	L"0x"
720Sstevel@tonic-gate #define	_P_ZEROX	L"0X"
730Sstevel@tonic-gate #define	_M_ISDIGIT(c)	(((c) >= 0) && ((c) < 256) && isdigit((c)))
740Sstevel@tonic-gate #define	_M_ISUPPER(c)	(((c) >= 0) && ((c) < 256) && isupper((c)))
750Sstevel@tonic-gate #else  /* _WIDE */
760Sstevel@tonic-gate #define	STRCHR	strchr
770Sstevel@tonic-gate #define	STRSPN	strspn
780Sstevel@tonic-gate #define	ATOI(x)	atoi(x)
790Sstevel@tonic-gate #define	_P_HYPHEN	"-"
800Sstevel@tonic-gate #define	_P_PLUS		"+"
810Sstevel@tonic-gate #define	_P_BLANK	" "
820Sstevel@tonic-gate #define	_P_ZEROx	"0x"
830Sstevel@tonic-gate #define	_P_ZEROX	"0X"
840Sstevel@tonic-gate #define	_M_ISDIGIT(c)	isdigit((c))
850Sstevel@tonic-gate #define	_M_ISUPPER(c)	isupper((c))
860Sstevel@tonic-gate #endif /* _WIDE */
870Sstevel@tonic-gate 
880Sstevel@tonic-gate #ifdef	_WIDE
890Sstevel@tonic-gate #define	PUT(p, n) \
900Sstevel@tonic-gate 	{ \
910Sstevel@tonic-gate 		int	retp; \
920Sstevel@tonic-gate 		retp = put_wide(iop, &bufptr, bufferend, p, n, sflag, lc, fp); \
930Sstevel@tonic-gate 		if (retp == EOF) { \
940Sstevel@tonic-gate 			return ((ssize_t)EOF); \
950Sstevel@tonic-gate 		} \
960Sstevel@tonic-gate 	}
970Sstevel@tonic-gate 
980Sstevel@tonic-gate #define	PAD(s, n) \
990Sstevel@tonic-gate 	{ \
1000Sstevel@tonic-gate 		int	retp; \
1010Sstevel@tonic-gate 		retp = pad_wide(iop, &bufptr, bufferend, s, n, sflag); \
1020Sstevel@tonic-gate 		if (retp == EOF) { \
1030Sstevel@tonic-gate 			return ((ssize_t)EOF); \
1040Sstevel@tonic-gate 		} \
1050Sstevel@tonic-gate 	}
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate #define	FPCONV(func, val, prec, decpt, sign, cvtbuf) \
1080Sstevel@tonic-gate 	{ \
1090Sstevel@tonic-gate 		char	cb[DECIMAL_STRING_LENGTH]; \
1100Sstevel@tonic-gate 		wchar_t	*wp; \
1110Sstevel@tonic-gate 		char	*cp; \
1120Sstevel@tonic-gate 		(void) func(val, prec, decpt, sign, cb); \
1130Sstevel@tonic-gate 		wp = cvtbuf; \
1140Sstevel@tonic-gate 		cp = cb; \
1150Sstevel@tonic-gate 		while (*cp) { \
1160Sstevel@tonic-gate 			*wp++ = (wchar_t)*cp++; \
1170Sstevel@tonic-gate 		} \
1180Sstevel@tonic-gate 		*wp = L'\0'; \
1190Sstevel@tonic-gate 	}
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate #else  /* _WIDE */
1220Sstevel@tonic-gate #define	PUT(p, n)	\
1230Sstevel@tonic-gate 	{\
1240Sstevel@tonic-gate 		/*\
1250Sstevel@tonic-gate 		 * When _doprnt() is called by [v]snprintf, we need to \
1260Sstevel@tonic-gate 		 * always call _dowrite().  We also need to call _dowrite() \
1270Sstevel@tonic-gate 		 * if the bufptr lies beyond the end of the buffer.  This \
1280Sstevel@tonic-gate 		 * is possible due to known off-by-one errors in __flsbuf() \
1290Sstevel@tonic-gate 		 * and _fwrite_unlocked().  See 1235867 and 1231720 for the \
1300Sstevel@tonic-gate 		 * sordid details. \
1310Sstevel@tonic-gate 		 */\
1320Sstevel@tonic-gate 		if (snflag || bufptr > bufferend ||\
1330Sstevel@tonic-gate 		    (unsigned long)(bufferend - bufptr) < (n)) {\
1340Sstevel@tonic-gate 			if (!_dowrite(p, n, iop, &bufptr)) {\
1350Sstevel@tonic-gate 				return (EOF);\
1360Sstevel@tonic-gate 			}\
1370Sstevel@tonic-gate 		} else {\
1380Sstevel@tonic-gate 			unsigned char	*fbp = bufptr;\
1390Sstevel@tonic-gate 			switch (n) {\
1400Sstevel@tonic-gate 			case 4:\
1410Sstevel@tonic-gate 				*fbp = *p;\
1420Sstevel@tonic-gate 				*(fbp + 1) = *(p + 1);\
1430Sstevel@tonic-gate 				*(fbp + 2) = *(p + 2);\
1440Sstevel@tonic-gate 				*(fbp + 3) = *(p + 3);\
1450Sstevel@tonic-gate 				bufptr += 4;\
1460Sstevel@tonic-gate 				break;\
1470Sstevel@tonic-gate 			case 3:\
1480Sstevel@tonic-gate 				*fbp = *p;\
1490Sstevel@tonic-gate 				*(fbp + 1) = *(p + 1);\
1500Sstevel@tonic-gate 				*(fbp + 2) = *(p + 2);\
1510Sstevel@tonic-gate 				bufptr += 3;\
1520Sstevel@tonic-gate 				break;\
1530Sstevel@tonic-gate 			case 2:\
1540Sstevel@tonic-gate 				*fbp = *p;\
1550Sstevel@tonic-gate 				*(fbp + 1) = *(p + 1);\
1560Sstevel@tonic-gate 				bufptr += 2;\
1570Sstevel@tonic-gate 				break;\
1580Sstevel@tonic-gate 			case 1:\
1590Sstevel@tonic-gate 				*bufptr++ = *p;\
1600Sstevel@tonic-gate 				break;\
1610Sstevel@tonic-gate 			default:\
1620Sstevel@tonic-gate 				bufptr = (unsigned char *)memcpy(fbp, p, n)\
1630Sstevel@tonic-gate 					+ (n);\
1640Sstevel@tonic-gate 			}\
1650Sstevel@tonic-gate 		}\
1660Sstevel@tonic-gate 	}
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate #define	PAD(s, n)    { ssize_t nn; \
1690Sstevel@tonic-gate 		    for (nn = n; nn > PAD_LEN; nn -= PAD_LEN) \
1700Sstevel@tonic-gate 			if (!_dowrite(s, PAD_LEN, iop, &bufptr)) \
1710Sstevel@tonic-gate 				return (EOF); \
1720Sstevel@tonic-gate 			PUT(s, nn); \
1730Sstevel@tonic-gate 		}
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate #define	FPCONV(func, val, prec, decpt, sign, cvtbuf) \
1760Sstevel@tonic-gate 		(void) func(val, prec, decpt, sign, cvtbuf);
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate #endif /* _WIDE */
1790Sstevel@tonic-gate 
1800Sstevel@tonic-gate /* bit positions for flags used in doprnt */
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate #define	LENGTH	0x1	/* l */
1830Sstevel@tonic-gate #define	FPLUS	0x2	/* + */
1840Sstevel@tonic-gate #define	FMINUS	0x4	/* - */
1850Sstevel@tonic-gate #define	FBLANK	0x8	/* blank */
1860Sstevel@tonic-gate #define	FSHARP	0x10	/* # */
1870Sstevel@tonic-gate #define	PADZERO 0x20	/* padding zeroes requested via '0' */
1880Sstevel@tonic-gate #define	DOTSEEN 0x40	/* dot appeared in format specification */
1890Sstevel@tonic-gate #define	SUFFIX	0x80	/* a suffix is to appear in the output */
1900Sstevel@tonic-gate #define	RZERO	0x100	/* there will be trailing zeros in output */
1910Sstevel@tonic-gate #define	LZERO	0x200	/* there will be leading zeroes in output */
1920Sstevel@tonic-gate #define	SHORT   0x400	/* h */
1930Sstevel@tonic-gate #define	QUAD    0x800	/* Q for long double */
1940Sstevel@tonic-gate #define	XLONG   0x1000	/* ll for long long */
1950Sstevel@tonic-gate #define	CHAR    0x2000	/* hh for char */
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate #ifdef	_WIDE
1980Sstevel@tonic-gate static wchar_t *
1990Sstevel@tonic-gate insert_thousands_sep(wchar_t *bp, wchar_t *ep);
2000Sstevel@tonic-gate #else  /* _WIDE */
2010Sstevel@tonic-gate static char *
2020Sstevel@tonic-gate insert_thousands_sep(char *bp, char *ep);
2030Sstevel@tonic-gate #endif /* _WIDE */
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate static int	_rec_scrswidth(wchar_t *, ssize_t);
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate /*
2080Sstevel@tonic-gate  *	Positional Parameter information
2090Sstevel@tonic-gate  */
2100Sstevel@tonic-gate #define	MAXARGS	30	/* max. number of args for fast positional paramters */
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate static ssize_t
2130Sstevel@tonic-gate _dowrite(const char *p, ssize_t n, FILE *iop, unsigned char **ptrptr);
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate /*
2160Sstevel@tonic-gate  * stva_list is used to subvert C's restriction that a variable with an
2170Sstevel@tonic-gate  * array type can not appear on the left hand side of an assignment operator.
2180Sstevel@tonic-gate  * By putting the array inside a structure, the functionality of assigning to
2190Sstevel@tonic-gate  * the whole array through a simple assignment is achieved..
2200Sstevel@tonic-gate  */
2210Sstevel@tonic-gate typedef struct stva_list {
2220Sstevel@tonic-gate 	va_list	ap;
2230Sstevel@tonic-gate } stva_list;
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate #ifdef	_WIDE
2260Sstevel@tonic-gate static void _wmkarglst(wchar_t *, stva_list, stva_list [], int);
2270Sstevel@tonic-gate static void _wgetarg(wchar_t *, stva_list *, long, int);
2280Sstevel@tonic-gate #else  /* _WIDE */
2297632SNick.Todd@Sun.COM static void _mkarglst(char *, stva_list, stva_list [], int);
2300Sstevel@tonic-gate void _getarg(char *, stva_list *, long, int);
2310Sstevel@tonic-gate #endif /* _WIDE */
2320Sstevel@tonic-gate 
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate static int
_lowdigit(ssize_t * valptr)2370Sstevel@tonic-gate _lowdigit(ssize_t *valptr)
2380Sstevel@tonic-gate {
2390Sstevel@tonic-gate 	/* This function computes the decimal low-order digit of the number */
2400Sstevel@tonic-gate 	/* pointed to by valptr, and returns this digit after dividing   */
2410Sstevel@tonic-gate 	/* *valptr by ten.  This function is called ONLY to compute the */
2420Sstevel@tonic-gate 	/* low-order digit of a long whose high-order bit is set. */
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate 	ssize_t lowbit = *valptr & 1;
2450Sstevel@tonic-gate 	long value = (*valptr >> 1) & ~HIBITL;
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate 	*valptr = value / 5;
2480Sstevel@tonic-gate 	value = value % 5 * 2 + lowbit + '0';
2490Sstevel@tonic-gate 	return ((int)value);
2500Sstevel@tonic-gate }
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate static int
_lowlldigit(long long * valptr)2530Sstevel@tonic-gate _lowlldigit(long long *valptr)
2540Sstevel@tonic-gate {
2550Sstevel@tonic-gate 	ssize_t lowbit = *valptr & 1;
2560Sstevel@tonic-gate 	long long value = (*valptr >> 1) & ~HIBITLL;
2570Sstevel@tonic-gate 		*valptr = value / 5;
2580Sstevel@tonic-gate 		value = value % 5 * 2 + lowbit + '0';
2590Sstevel@tonic-gate 		return ((int)value);
2600Sstevel@tonic-gate }
2610Sstevel@tonic-gate 
2620Sstevel@tonic-gate /* The function _dowrite carries out buffer pointer bookkeeping surrounding */
2630Sstevel@tonic-gate /* a call to fwrite.  It is called only when the end of the file output */
2640Sstevel@tonic-gate /* buffer is approached or in other unusual situations. */
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate static ssize_t
_dowrite(const char * p,ssize_t n,FILE * iop,unsigned char ** ptrptr)2670Sstevel@tonic-gate _dowrite(const char *p, ssize_t n, FILE *iop, unsigned char **ptrptr)
2680Sstevel@tonic-gate {
2690Sstevel@tonic-gate 	if (!(iop->_flag & _IOREAD)) {
2700Sstevel@tonic-gate 		iop->_cnt -= (*ptrptr - iop->_ptr);
2710Sstevel@tonic-gate 		iop->_ptr = *ptrptr;
2720Sstevel@tonic-gate 		_bufsync(iop, _bufend(iop));
2730Sstevel@tonic-gate 		if (_FWRITE(p, 1, n, iop) != n) {
2740Sstevel@tonic-gate 			return (0);
2750Sstevel@tonic-gate 		}
2760Sstevel@tonic-gate 		*ptrptr = iop->_ptr;
2770Sstevel@tonic-gate 	} else {
2780Sstevel@tonic-gate 		if (n > iop->_cnt)
2790Sstevel@tonic-gate 			n = iop->_cnt;
2800Sstevel@tonic-gate 		iop->_cnt -= n;
2810Sstevel@tonic-gate 		*ptrptr = (unsigned char *)memcpy((char *)*ptrptr, p, n) + n;
2820Sstevel@tonic-gate 		iop->_ptr = *ptrptr;
2830Sstevel@tonic-gate 	}
2840Sstevel@tonic-gate 	return (1);
2850Sstevel@tonic-gate }
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate #define	PAD_LEN	20
2880Sstevel@tonic-gate 	static const char _blanks[] = "                    ";
2890Sstevel@tonic-gate 	static const char _zeroes[] = "00000000000000000000";
2900Sstevel@tonic-gate #ifdef	_WIDE
2910Sstevel@tonic-gate 	static const wchar_t uc_digs[] = L"0123456789ABCDEF";
2920Sstevel@tonic-gate 	static const wchar_t lc_digs[] = L"0123456789abcdef";
2930Sstevel@tonic-gate #else /* _WIDE */
2940Sstevel@tonic-gate 	static const char uc_digs[] = "0123456789ABCDEF";
2950Sstevel@tonic-gate 	static const char lc_digs[] = "0123456789abcdef";
2960Sstevel@tonic-gate #endif /* _WIDE */
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate #ifdef	_WIDE
2990Sstevel@tonic-gate static int
put_wide(FILE * iop,unsigned char ** bufptr,unsigned char * bufferend,wchar_t * p,size_t n,int sflag,void * lc,int (* fp_wctomb)(void *,char *,wchar_t))3000Sstevel@tonic-gate put_wide(FILE *iop, unsigned char **bufptr,
3010Sstevel@tonic-gate 	unsigned char *bufferend, wchar_t *p, size_t n,
3020Sstevel@tonic-gate 	int sflag, void *lc, int (*fp_wctomb)(void *, char *, wchar_t))
3030Sstevel@tonic-gate {
3040Sstevel@tonic-gate 	unsigned char	*newbufptr;
3050Sstevel@tonic-gate 	wchar_t	*q;
3060Sstevel@tonic-gate 	int	r;
3070Sstevel@tonic-gate 	size_t	len, i;
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate 	if (sflag) {
3100Sstevel@tonic-gate 		len = (wchar_t *)bufferend - (wchar_t *)*bufptr;
3110Sstevel@tonic-gate 		if (n > len) {
3120Sstevel@tonic-gate 			(void) wmemcpy((wchar_t *)*bufptr, p, len);
3130Sstevel@tonic-gate 			iop->_ptr = bufferend;
3140Sstevel@tonic-gate 			return (EOF);
3150Sstevel@tonic-gate 		} else {
3160Sstevel@tonic-gate 			(void) wmemcpy((wchar_t *)*bufptr, p, n);
3176812Sraf 			*bufptr = (unsigned char *)((wchar_t *)*bufptr + n);
3180Sstevel@tonic-gate 			return (0);
3190Sstevel@tonic-gate 		}
3200Sstevel@tonic-gate 	} else {
3210Sstevel@tonic-gate 		char *tmpp, *tmpq;
3220Sstevel@tonic-gate 		size_t tsize;
3230Sstevel@tonic-gate 
3240Sstevel@tonic-gate 		tsize = (n + 1) * MB_LEN_MAX;
3250Sstevel@tonic-gate 		tmpp = lmalloc(tsize);
3260Sstevel@tonic-gate 		if (tmpp == NULL) {
3270Sstevel@tonic-gate 			errno = ENOMEM;
3280Sstevel@tonic-gate 			return (EOF);
3290Sstevel@tonic-gate 		}
3300Sstevel@tonic-gate 		q = p;
3310Sstevel@tonic-gate 		tmpq = tmpp;
3320Sstevel@tonic-gate 		for (len = 0, i = 0; i < n; i++) {
3330Sstevel@tonic-gate 			r = fp_wctomb(lc, tmpq, *q++);
3340Sstevel@tonic-gate 			if (r == -1) {
3350Sstevel@tonic-gate 				lfree(tmpp, tsize);
3360Sstevel@tonic-gate 				errno = EILSEQ;
3370Sstevel@tonic-gate 				return (EOF);
3380Sstevel@tonic-gate 			}
3390Sstevel@tonic-gate 			len += r;
3400Sstevel@tonic-gate 			tmpq += r;
3410Sstevel@tonic-gate 		}
3420Sstevel@tonic-gate 		tmpq = tmpp;
3430Sstevel@tonic-gate 		newbufptr = *bufptr + len;
3440Sstevel@tonic-gate 		if (newbufptr > bufferend) {
3450Sstevel@tonic-gate 			if (!_dowrite(tmpp, len, iop, bufptr)) {
3460Sstevel@tonic-gate 				lfree(tmpp, tsize);
3470Sstevel@tonic-gate 				return (EOF);
3480Sstevel@tonic-gate 			}
3490Sstevel@tonic-gate 		} else {
3500Sstevel@tonic-gate 			(void) memcpy(*bufptr, tmpp, len);
3510Sstevel@tonic-gate 			*bufptr = newbufptr;
3520Sstevel@tonic-gate 		}
3530Sstevel@tonic-gate 		lfree(tmpp, tsize);
3540Sstevel@tonic-gate 		return (0);
3550Sstevel@tonic-gate 	}
3560Sstevel@tonic-gate }
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate static int
pad_wide(FILE * iop,unsigned char ** bufptr,unsigned char * bufferend,const char * s,size_t n,int sflag)3590Sstevel@tonic-gate pad_wide(FILE *iop, unsigned char **bufptr,
3600Sstevel@tonic-gate 	unsigned char *bufferend, const char *s, size_t n,
3610Sstevel@tonic-gate 	int sflag)
3620Sstevel@tonic-gate {
3630Sstevel@tonic-gate 	unsigned char	*newbufptr;
3640Sstevel@tonic-gate 	ssize_t	nn;
3650Sstevel@tonic-gate 	size_t	len;
3660Sstevel@tonic-gate 	wchar_t	ps;
3670Sstevel@tonic-gate 
3680Sstevel@tonic-gate 	if (sflag) {
3690Sstevel@tonic-gate 		/* for swprintf */
3700Sstevel@tonic-gate 		ps = (wchar_t)s[0];
3710Sstevel@tonic-gate 		len = (wchar_t *)bufferend - (wchar_t *)*bufptr;
3720Sstevel@tonic-gate 		if (n > len) {
3730Sstevel@tonic-gate 			(void) wmemset((wchar_t *)*bufptr, ps, len);
3740Sstevel@tonic-gate 			iop->_ptr = bufferend;
3750Sstevel@tonic-gate 			return (EOF);
3760Sstevel@tonic-gate 		} else {
3770Sstevel@tonic-gate 			(void) wmemset((wchar_t *)*bufptr, ps, n);
3786812Sraf 			*bufptr = (unsigned char *)((wchar_t *)*bufptr + n);
3790Sstevel@tonic-gate 			return (0);
3800Sstevel@tonic-gate 		}
3810Sstevel@tonic-gate 	} else {
3820Sstevel@tonic-gate 		for (nn = n; nn > PAD_LEN; nn -= PAD_LEN) {
3830Sstevel@tonic-gate 			if (!_dowrite(s, PAD_LEN, iop, bufptr))
3840Sstevel@tonic-gate 				return (EOF);
3850Sstevel@tonic-gate 		}
3860Sstevel@tonic-gate 		newbufptr = *bufptr + nn;
3870Sstevel@tonic-gate 		if (newbufptr > bufferend) {
3880Sstevel@tonic-gate 			if (!_dowrite(s, nn, iop, bufptr))
3890Sstevel@tonic-gate 				return (EOF);
3900Sstevel@tonic-gate 		} else {
3910Sstevel@tonic-gate 			(void) memcpy(*bufptr, s, nn);
3920Sstevel@tonic-gate 			*bufptr = newbufptr;
3930Sstevel@tonic-gate 		}
3940Sstevel@tonic-gate 		return (0);
3950Sstevel@tonic-gate 	}
3960Sstevel@tonic-gate }
3970Sstevel@tonic-gate #endif /* _WIDE */
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate #ifdef	_WIDE
4000Sstevel@tonic-gate ssize_t
_wdoprnt(const wchar_t * format,va_list in_args,FILE * iop)4010Sstevel@tonic-gate _wdoprnt(const wchar_t *format, va_list in_args, FILE *iop)
4020Sstevel@tonic-gate {
4030Sstevel@tonic-gate 	return (_wndoprnt(format, in_args, iop, 0));
4040Sstevel@tonic-gate }
4050Sstevel@tonic-gate #else	/* _WIDE */
4060Sstevel@tonic-gate ssize_t
_doprnt(const char * format,va_list in_args,FILE * iop)4070Sstevel@tonic-gate _doprnt(const char *format, va_list in_args, FILE *iop)
4080Sstevel@tonic-gate {
4090Sstevel@tonic-gate 	return (_ndoprnt(format, in_args, iop, 0));
4100Sstevel@tonic-gate }
4110Sstevel@tonic-gate #endif	/* _WIDE */
4120Sstevel@tonic-gate 
4130Sstevel@tonic-gate 
4140Sstevel@tonic-gate #ifdef	_WIDE
4150Sstevel@tonic-gate ssize_t
_wndoprnt(const wchar_t * format,va_list in_args,FILE * iop,int prflag)4160Sstevel@tonic-gate _wndoprnt(const wchar_t *format, va_list in_args, FILE *iop, int prflag)
4170Sstevel@tonic-gate #else  /* _WIDE */
4180Sstevel@tonic-gate ssize_t
4190Sstevel@tonic-gate _ndoprnt(const char *format, va_list in_args, FILE *iop, int prflag)
4200Sstevel@tonic-gate #endif /* _WIDE */
4210Sstevel@tonic-gate {
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate #ifdef	_WIDE
4240Sstevel@tonic-gate 	int	sflag = 0;
4250Sstevel@tonic-gate 	size_t	maxcount;
4260Sstevel@tonic-gate 	mbstate_t	*mbst;
4270Sstevel@tonic-gate 	void	*lc;
4280Sstevel@tonic-gate 	int	(*fp)(void *, char *, wchar_t);
4290Sstevel@tonic-gate #else
4300Sstevel@tonic-gate 	int	snflag = 0;
4310Sstevel@tonic-gate #endif /* _WIDE */
4320Sstevel@tonic-gate 	/* bufptr is used inside of doprnt instead of iop->_ptr; */
4330Sstevel@tonic-gate 	/* bufferend is a copy of _bufend(iop), if it exists.  For */
4340Sstevel@tonic-gate 	/* dummy file descriptors (iop->_flag & _IOREAD), bufferend */
4350Sstevel@tonic-gate 	/* may be meaningless. Dummy file descriptors are used so that */
4360Sstevel@tonic-gate 	/* sprintf and vsprintf may share the _doprnt routine with the */
4370Sstevel@tonic-gate 	/* rest of the printf family. */
4380Sstevel@tonic-gate 
4390Sstevel@tonic-gate 	unsigned char *bufptr;
4400Sstevel@tonic-gate 	unsigned char *bufferend;
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate #ifdef	_WIDE
4430Sstevel@tonic-gate 	/* This variable counts output characters. */
4440Sstevel@tonic-gate 	size_t	count = 0;
4450Sstevel@tonic-gate #else  /* _WIDE */
4460Sstevel@tonic-gate 	/* This variable counts output characters. */
4470Sstevel@tonic-gate 	int	count = 0;
4480Sstevel@tonic-gate #endif /* _WIDE */
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate #ifdef	_WIDE
4510Sstevel@tonic-gate 	wchar_t	*bp;
4520Sstevel@tonic-gate 	size_t bpsize;
4530Sstevel@tonic-gate 	wchar_t	*p;
4540Sstevel@tonic-gate 	char	*cbp;
4550Sstevel@tonic-gate 	char	*cp;
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate #else  /* _WIDE */
4580Sstevel@tonic-gate 	/* Starting and ending points for value to be printed */
4590Sstevel@tonic-gate 	char	*bp;
4600Sstevel@tonic-gate 	char *p;
4610Sstevel@tonic-gate #endif /* _WIDE */
4620Sstevel@tonic-gate 	/* Field width and precision */
4630Sstevel@tonic-gate 	int	prec = 0;
4640Sstevel@tonic-gate 	ssize_t width;
4650Sstevel@tonic-gate 	ssize_t num;
4660Sstevel@tonic-gate 	ssize_t sec_display;
4670Sstevel@tonic-gate 	wchar_t *wp;
4680Sstevel@tonic-gate 	ssize_t preco;
4690Sstevel@tonic-gate 	ssize_t wcount = 0;
4700Sstevel@tonic-gate 	char tmpbuf[10];
4710Sstevel@tonic-gate 	char wflag;
4720Sstevel@tonic-gate 	char lflag;
4730Sstevel@tonic-gate 	int quote;		/* ' */
4740Sstevel@tonic-gate 	int	retcode;
4750Sstevel@tonic-gate 
4760Sstevel@tonic-gate 
4770Sstevel@tonic-gate #ifdef	_WIDE
4780Sstevel@tonic-gate 	/* Format code */
4790Sstevel@tonic-gate 	wchar_t	fcode;
4800Sstevel@tonic-gate #else  /* _WIDE */
4810Sstevel@tonic-gate 	/* Format code */
4820Sstevel@tonic-gate 	char	fcode;
4830Sstevel@tonic-gate #endif /* _WIDE */
4840Sstevel@tonic-gate 
4850Sstevel@tonic-gate 	/* Number of padding zeroes required on the left and right */
4860Sstevel@tonic-gate 	ssize_t	lzero, rzero, rz, leadzeroes;
4870Sstevel@tonic-gate 
4880Sstevel@tonic-gate 
4890Sstevel@tonic-gate 	/* Flags - bit positions defined by LENGTH, FPLUS, FMINUS, FBLANK, */
4900Sstevel@tonic-gate 	/* and FSHARP are set if corresponding character is in format */
4910Sstevel@tonic-gate 	/* Bit position defined by PADZERO means extra space in the field */
4920Sstevel@tonic-gate 	/* should be padded with leading zeroes rather than with blanks */
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate 	ssize_t	flagword;
4950Sstevel@tonic-gate 
4960Sstevel@tonic-gate #ifdef	_WIDE
4970Sstevel@tonic-gate 	/* Values are developed in this buffer */
4980Sstevel@tonic-gate 	wchar_t	buf[max(MAXLLDIGS, 1034)];
4990Sstevel@tonic-gate 	wchar_t	cvtbuf[512 + DECIMAL_STRING_LENGTH];
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate 	/* Pointer to sign, "0x", "0X", or empty */
5020Sstevel@tonic-gate 	wchar_t	*prefix;
5030Sstevel@tonic-gate 	wchar_t	prefixbuf[4];
5040Sstevel@tonic-gate 
5050Sstevel@tonic-gate 	/* Exponent or empty */
5060Sstevel@tonic-gate 	wchar_t	*suffix;
5070Sstevel@tonic-gate 
5080Sstevel@tonic-gate 	/* Buffer to create exponent */
5090Sstevel@tonic-gate 	wchar_t	expbuf[MAXESIZ + 1];
5100Sstevel@tonic-gate #else  /* _WIDE */
5110Sstevel@tonic-gate 	/* Values are developed in this buffer */
5120Sstevel@tonic-gate 	char	buf[max(MAXLLDIGS, 1034)];
5130Sstevel@tonic-gate 	char	cvtbuf[512 + DECIMAL_STRING_LENGTH];
5140Sstevel@tonic-gate 
5150Sstevel@tonic-gate 	/* Pointer to sign, "0x", "0X", or empty */
5160Sstevel@tonic-gate 	char	*prefix;
5170Sstevel@tonic-gate 	char	prefixbuf[4];
5180Sstevel@tonic-gate 
5190Sstevel@tonic-gate 	/* Exponent or empty */
5200Sstevel@tonic-gate 	char	*suffix;
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate 	/* Buffer to create exponent */
5230Sstevel@tonic-gate 	char	expbuf[MAXESIZ + 1];
5240Sstevel@tonic-gate #endif /* _WIDE */
5250Sstevel@tonic-gate 
5260Sstevel@tonic-gate 	/* Length of prefix and of suffix */
5270Sstevel@tonic-gate 	ssize_t	prefixlength, suffixlength;
5280Sstevel@tonic-gate 
5290Sstevel@tonic-gate 	/* Combined length of leading zeroes, trailing zeroes, and suffix */
5300Sstevel@tonic-gate 	ssize_t 	otherlength;
5310Sstevel@tonic-gate 
5320Sstevel@tonic-gate 	/* The value being converted, if integer */
5330Sstevel@tonic-gate 	ssize_t	val;
5340Sstevel@tonic-gate 
5350Sstevel@tonic-gate 	/* The value being converted, if long long */
5360Sstevel@tonic-gate 	long long ll = 0LL;
5370Sstevel@tonic-gate 
5380Sstevel@tonic-gate 	/* Output value from aconvert */
5390Sstevel@tonic-gate 	int	exp;
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 	/* Output values from fcvt and ecvt */
5420Sstevel@tonic-gate 	int	decpt, sign;
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate #ifdef	_WIDE
5450Sstevel@tonic-gate 	/* Pointer to a translate table for digits of whatever radix */
5460Sstevel@tonic-gate 	const wchar_t *tab;
5470Sstevel@tonic-gate #else  /* _WIDE */
5480Sstevel@tonic-gate 	/* Pointer to a translate table for digits of whatever radix */
5490Sstevel@tonic-gate 	const char *tab;
5500Sstevel@tonic-gate #endif /* _WIDE */
5510Sstevel@tonic-gate 
5520Sstevel@tonic-gate 	/* Work variables */
5530Sstevel@tonic-gate 	ssize_t	k, lradix, mradix;
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate 	int	inf_nan = 0;
5560Sstevel@tonic-gate 	int	inf_nan_mixed_case = 0;
5570Sstevel@tonic-gate 
5580Sstevel@tonic-gate #ifdef	_WIDE
5590Sstevel@tonic-gate 	/* variables for positional parameters */
5600Sstevel@tonic-gate 	/* save the beginning of the format */
5610Sstevel@tonic-gate 	wchar_t *sformat = (wchar_t *)format;
5620Sstevel@tonic-gate #else  /* _WIDE */
5630Sstevel@tonic-gate 	/* variables for positional parameters */
5640Sstevel@tonic-gate 	char *sformat = (char *)format; /* save the beginning of the format */
5650Sstevel@tonic-gate #endif
5660Sstevel@tonic-gate 
5670Sstevel@tonic-gate 	int	fpos = 1;		/* 1 if first positional parameter */
5680Sstevel@tonic-gate 	stva_list	args,	/* used to step through the argument list */
5690Sstevel@tonic-gate 			sargs;	/* used to save the start of the arg list */
5700Sstevel@tonic-gate 	stva_list	bargs;	/* used to restore args if positional width */
5710Sstevel@tonic-gate 				/* or precision */
5720Sstevel@tonic-gate 	stva_list	arglst[MAXARGS]; /* array giving appropriate values */
5730Sstevel@tonic-gate 					/* for va_arg() to retrieve the */
5740Sstevel@tonic-gate 					/* corresponding argument: */
5750Sstevel@tonic-gate 					/* arglst[0] is the first arg */
5760Sstevel@tonic-gate 					/* arglst[1] is the second arg, etc */
5770Sstevel@tonic-gate 
5780Sstevel@tonic-gate 	int	starflg = 0;	/* set to 1 if * format specifier seen */
5790Sstevel@tonic-gate 	/*
5800Sstevel@tonic-gate 	 * Initialize args and sargs to the start of the argument list.
5810Sstevel@tonic-gate 	 * We don't know any portable way to copy an arbitrary C object
5820Sstevel@tonic-gate 	 * so we use a system-specific routine (probably a macro) from
5830Sstevel@tonic-gate 	 * stdarg.h.  (Remember that if va_list is an array, in_args will
5840Sstevel@tonic-gate 	 * be a pointer and &in_args won't be what we would want for
5850Sstevel@tonic-gate 	 * memcpy.)
5860Sstevel@tonic-gate 	 */
5870Sstevel@tonic-gate 	va_copy(args.ap, in_args);
5880Sstevel@tonic-gate 	sargs = args;
5890Sstevel@tonic-gate 
5900Sstevel@tonic-gate #ifdef	_WIDE
5910Sstevel@tonic-gate 	if (iop->_flag == _IOREAD)
5920Sstevel@tonic-gate 		sflag = 1;
5930Sstevel@tonic-gate 
5940Sstevel@tonic-gate 	if (!sflag) {
5950Sstevel@tonic-gate 		mbst = _getmbstate(iop);
5960Sstevel@tonic-gate 		if (mbst == NULL) {
5970Sstevel@tonic-gate 			errno = EBADF;
5980Sstevel@tonic-gate 			return (EOF);
5990Sstevel@tonic-gate 		}
6000Sstevel@tonic-gate 		lc = __mbst_get_lc_and_fp((const mbstate_t *)mbst,
6010Sstevel@tonic-gate 		    (void (*(*))(void))&fp, FP_WCTOMB);
6020Sstevel@tonic-gate #endif /* _WIDE */
6030Sstevel@tonic-gate 	/* if first I/O to the stream get a buffer */
6040Sstevel@tonic-gate 	/* Note that iop->_base should not equal 0 for sprintf and vsprintf */
6050Sstevel@tonic-gate 	if (iop->_base == 0)  {
6060Sstevel@tonic-gate 	    if (_findbuf(iop) == 0)
6070Sstevel@tonic-gate 		return (EOF);
6080Sstevel@tonic-gate 	    /* _findbuf leaves _cnt set to 0 which is the wrong thing to do */
6090Sstevel@tonic-gate 	    /* for fully buffered files */
6100Sstevel@tonic-gate 	    if (!(iop->_flag & (_IOLBF|_IONBF)))
6110Sstevel@tonic-gate 		iop->_cnt = _bufend(iop) - iop->_base;
6120Sstevel@tonic-gate 	}
6130Sstevel@tonic-gate #ifdef	_WIDE
6140Sstevel@tonic-gate 	}
6150Sstevel@tonic-gate #endif /* _WIDE */
6160Sstevel@tonic-gate 
6170Sstevel@tonic-gate #ifdef	_WIDE
6180Sstevel@tonic-gate 	bufptr = iop->_ptr;
6190Sstevel@tonic-gate 	if (sflag) {
6200Sstevel@tonic-gate 		maxcount = (size_t)iop->_cnt;
6210Sstevel@tonic-gate 		bufferend = (unsigned char *)(((wchar_t *)iop->_ptr) +
6220Sstevel@tonic-gate 			maxcount);
6230Sstevel@tonic-gate 	} else {
6240Sstevel@tonic-gate 		bufferend = _bufend(iop);
6250Sstevel@tonic-gate 	}
6260Sstevel@tonic-gate #else  /* _WIDE */
6270Sstevel@tonic-gate 	/* initialize buffer pointer and buffer end pointer */
6280Sstevel@tonic-gate 	bufptr = iop->_ptr;
6290Sstevel@tonic-gate 	if (iop->_flag & _IOREAD) {
6300Sstevel@tonic-gate 		/*
6310Sstevel@tonic-gate 		 * [v]sprintf or [v]snprintf
6320Sstevel@tonic-gate 		 */
6330Sstevel@tonic-gate 		if (iop->_cnt == MAXINT) {
6340Sstevel@tonic-gate 			/*
6350Sstevel@tonic-gate 			 * [v]sprintf (no boundschecking)
6360Sstevel@tonic-gate 			 */
6370Sstevel@tonic-gate 			bufferend =
6380Sstevel@tonic-gate 			    (unsigned char *)((long)bufptr | (-1L & ~HIBITL));
6390Sstevel@tonic-gate 		} else {
6400Sstevel@tonic-gate 			/*
6410Sstevel@tonic-gate 			 * [v]snprintf (with boundschecking) or
6420Sstevel@tonic-gate 			 * iop with _IORW has been read.
6430Sstevel@tonic-gate 			 */
6440Sstevel@tonic-gate 			bufferend = _bufend(iop);
6450Sstevel@tonic-gate 			if (bufferend == NULL) {
6460Sstevel@tonic-gate 				/*
6470Sstevel@tonic-gate 				 * [v]snprintf
6480Sstevel@tonic-gate 				 *
6490Sstevel@tonic-gate 				 * [v]snprint() needs to be always handled by
6500Sstevel@tonic-gate 				 * _dowrite().
6510Sstevel@tonic-gate 				 */
6520Sstevel@tonic-gate 				snflag = 1;
6530Sstevel@tonic-gate 			}
6540Sstevel@tonic-gate 		}
6550Sstevel@tonic-gate 	} else {
6560Sstevel@tonic-gate 		/*
6570Sstevel@tonic-gate 		 * [v]printf or [v]fprintf
6580Sstevel@tonic-gate 		 */
6590Sstevel@tonic-gate 		bufferend = _bufend(iop);
6600Sstevel@tonic-gate 	}
6610Sstevel@tonic-gate #endif /* _WIDE */
6620Sstevel@tonic-gate 
6630Sstevel@tonic-gate 	/*
6640Sstevel@tonic-gate 	 *	The main loop -- this loop goes through one iteration
6650Sstevel@tonic-gate 	 *	for each string of ordinary characters or format specification.
6660Sstevel@tonic-gate 	 */
6670Sstevel@tonic-gate 	for (; ; ) {
6680Sstevel@tonic-gate 		ssize_t n;
6690Sstevel@tonic-gate 
6700Sstevel@tonic-gate 		if ((fcode = *format) != '\0' && fcode != '%') {
6710Sstevel@tonic-gate #ifdef	_WIDE
6720Sstevel@tonic-gate 			bp = (wchar_t *)format;
6730Sstevel@tonic-gate #else  /* _WIDE */
6740Sstevel@tonic-gate 			bp = (char *)format;
6750Sstevel@tonic-gate #endif /* _WIDE */
6760Sstevel@tonic-gate 			do {
6770Sstevel@tonic-gate 				format++;
6780Sstevel@tonic-gate 			} while ((fcode = *format) != '\0' && fcode != '%');
6790Sstevel@tonic-gate 
6800Sstevel@tonic-gate 			count += (n = format - bp); /* n = no. of non-% chars */
6810Sstevel@tonic-gate 			PUT(bp, n);
6820Sstevel@tonic-gate 		}
6830Sstevel@tonic-gate 		if (fcode == '\0') {  /* end of format; return */
6840Sstevel@tonic-gate 			ssize_t nn = bufptr - iop->_ptr;
6850Sstevel@tonic-gate 
6860Sstevel@tonic-gate #ifdef	_WIDE
6870Sstevel@tonic-gate 			if (sflag) {
6880Sstevel@tonic-gate 				iop->_ptr = bufptr;
6890Sstevel@tonic-gate 				return ((ssize_t)count);
6900Sstevel@tonic-gate 			}
6910Sstevel@tonic-gate #endif /* _WIDE */
6920Sstevel@tonic-gate 
6930Sstevel@tonic-gate 			iop->_cnt -= nn;
6940Sstevel@tonic-gate 			iop->_ptr = bufptr;
6950Sstevel@tonic-gate 			/* in case of interrupt during last several lines */
6960Sstevel@tonic-gate 			if ((bufptr + iop->_cnt) > bufferend && !(iop->_flag \
6970Sstevel@tonic-gate 			    & _IOREAD))
6980Sstevel@tonic-gate 				_bufsync(iop, bufferend);
6990Sstevel@tonic-gate 			if (iop->_flag & (_IONBF | _IOLBF) && \
7000Sstevel@tonic-gate 			    (iop->_flag & _IONBF || \
7010Sstevel@tonic-gate 			    memchr((char *)(bufptr+iop->_cnt), \
7020Sstevel@tonic-gate 			    '\n', -iop->_cnt) != NULL))
7030Sstevel@tonic-gate 				(void) _xflsbuf(iop);
7040Sstevel@tonic-gate #ifdef	_WIDE
7050Sstevel@tonic-gate 			return (FERROR(iop) ? EOF : (ssize_t)count);
7060Sstevel@tonic-gate #else  /* _WIDE */
7070Sstevel@tonic-gate 			return (FERROR(iop) ? EOF : (int)count);
7080Sstevel@tonic-gate #endif /* _WIDE */
7090Sstevel@tonic-gate 		}
7100Sstevel@tonic-gate 
7110Sstevel@tonic-gate 		/*
7120Sstevel@tonic-gate 		 *	% has been found.
7130Sstevel@tonic-gate 		 *	The following switch is used to parse the format
7140Sstevel@tonic-gate 		 *	specification and to perform the operation specified
7150Sstevel@tonic-gate 		 *	by the format letter.  The program repeatedly goes
7160Sstevel@tonic-gate 		 *	back to this switch until the format letter is
7170Sstevel@tonic-gate 		 *	encountered.
7180Sstevel@tonic-gate 		 */
7190Sstevel@tonic-gate 		width = prefixlength = otherlength = 0;
7200Sstevel@tonic-gate 		flagword = suffixlength = 0;
7210Sstevel@tonic-gate 		format++;
7220Sstevel@tonic-gate 		wflag = 0;
7230Sstevel@tonic-gate 		lflag = 0;
7240Sstevel@tonic-gate 		sec_display = 0;
7250Sstevel@tonic-gate 		quote = 0;
7260Sstevel@tonic-gate 
7270Sstevel@tonic-gate 	charswitch:
7280Sstevel@tonic-gate 
7290Sstevel@tonic-gate 		switch (fcode = *format++) {
7300Sstevel@tonic-gate 
7310Sstevel@tonic-gate 		case '+':
7320Sstevel@tonic-gate 			flagword |= FPLUS;
7330Sstevel@tonic-gate 			goto charswitch;
7340Sstevel@tonic-gate 		case '-':
7350Sstevel@tonic-gate 			flagword |= FMINUS;
7360Sstevel@tonic-gate 			flagword &= ~PADZERO; /* ignore 0 flag */
7370Sstevel@tonic-gate 			goto charswitch;
7380Sstevel@tonic-gate 		case ' ':
7390Sstevel@tonic-gate 			flagword |= FBLANK;
7400Sstevel@tonic-gate 			goto charswitch;
7410Sstevel@tonic-gate 		case '\'':	/* XSH4 */
7420Sstevel@tonic-gate 			quote++;
7430Sstevel@tonic-gate 			goto charswitch;
7440Sstevel@tonic-gate 		case '#':
7450Sstevel@tonic-gate 			flagword |= FSHARP;
7460Sstevel@tonic-gate 			goto charswitch;
7470Sstevel@tonic-gate 
7480Sstevel@tonic-gate 		/* Scan the field width and precision */
7490Sstevel@tonic-gate 		case '.':
7500Sstevel@tonic-gate 			flagword |= DOTSEEN;
7510Sstevel@tonic-gate 			prec = 0;
7520Sstevel@tonic-gate 			goto charswitch;
7530Sstevel@tonic-gate 
7540Sstevel@tonic-gate 		case '*':
7550Sstevel@tonic-gate 			if (_M_ISDIGIT(*format)) {
7560Sstevel@tonic-gate 				starflg = 1;
7570Sstevel@tonic-gate 				bargs = args;
7580Sstevel@tonic-gate 				goto charswitch;
7590Sstevel@tonic-gate 			}
7600Sstevel@tonic-gate 			if (!(flagword & DOTSEEN)) {
7610Sstevel@tonic-gate 				width = va_arg(args.ap, int);
7620Sstevel@tonic-gate 				if (width < 0) {
7630Sstevel@tonic-gate 					width = -width;
7640Sstevel@tonic-gate 					flagword |= FMINUS;
7650Sstevel@tonic-gate 				}
7660Sstevel@tonic-gate 			} else {
7670Sstevel@tonic-gate 				prec = va_arg(args.ap, int);
7680Sstevel@tonic-gate 				if (prec < 0) {
7690Sstevel@tonic-gate 					prec = 0;
7700Sstevel@tonic-gate 					flagword ^= DOTSEEN; /* ANSI sez so */
7710Sstevel@tonic-gate 				}
7720Sstevel@tonic-gate 			}
7730Sstevel@tonic-gate 			goto charswitch;
7740Sstevel@tonic-gate 
7750Sstevel@tonic-gate 		case '$':
7760Sstevel@tonic-gate 			{
7770Sstevel@tonic-gate 			ssize_t		position;
7780Sstevel@tonic-gate 			stva_list	targs;
7790Sstevel@tonic-gate 			if (fpos) {
7800Sstevel@tonic-gate #ifdef	_WIDE
7810Sstevel@tonic-gate 				_wmkarglst(sformat, sargs, arglst, prflag);
7820Sstevel@tonic-gate #else  /* _WIDE */
7830Sstevel@tonic-gate 				_mkarglst(sformat, sargs, arglst, prflag);
7840Sstevel@tonic-gate #endif /* _WIDE */
7850Sstevel@tonic-gate 				fpos = 0;
7860Sstevel@tonic-gate 			}
7870Sstevel@tonic-gate 			if (flagword & DOTSEEN) {
7880Sstevel@tonic-gate 				position = prec;
7890Sstevel@tonic-gate 				prec = 0;
7900Sstevel@tonic-gate 			} else {
7910Sstevel@tonic-gate 				position = width;
7920Sstevel@tonic-gate 				width = 0;
7930Sstevel@tonic-gate 			}
7940Sstevel@tonic-gate 			if (position <= 0) {
7950Sstevel@tonic-gate 				/* illegal position */
7960Sstevel@tonic-gate 				format--;
7970Sstevel@tonic-gate 				continue;
7980Sstevel@tonic-gate 			}
7990Sstevel@tonic-gate 			if (position <= MAXARGS) {
8000Sstevel@tonic-gate 				targs = arglst[position - 1];
8010Sstevel@tonic-gate 			} else {
8020Sstevel@tonic-gate 				targs = arglst[MAXARGS - 1];
8030Sstevel@tonic-gate #ifdef	_WIDE
8040Sstevel@tonic-gate 				_wgetarg(sformat, &targs, position, prflag);
8050Sstevel@tonic-gate #else  /* _WIDE */
8060Sstevel@tonic-gate 				_getarg(sformat, &targs, position, prflag);
8070Sstevel@tonic-gate #endif /* _WIDE */
8080Sstevel@tonic-gate 			}
8090Sstevel@tonic-gate 			if (!starflg)
8100Sstevel@tonic-gate 				args = targs;
8110Sstevel@tonic-gate 			else {
8120Sstevel@tonic-gate 				starflg = 0;
8130Sstevel@tonic-gate 				args = bargs;
8140Sstevel@tonic-gate 				if (flagword & DOTSEEN) {
8150Sstevel@tonic-gate 					prec = va_arg(targs.ap, int);
8160Sstevel@tonic-gate 					if (prec < 0) {
8170Sstevel@tonic-gate 						prec = 0;
8180Sstevel@tonic-gate 						flagword ^= DOTSEEN; /* XSH */
8190Sstevel@tonic-gate 					}
8200Sstevel@tonic-gate 				} else {
8210Sstevel@tonic-gate 					width = va_arg(targs.ap, int);
8220Sstevel@tonic-gate 					if (width < 0) {
8230Sstevel@tonic-gate 						width = -width;
8240Sstevel@tonic-gate 						flagword |= FMINUS;
8250Sstevel@tonic-gate 					}
8260Sstevel@tonic-gate 				}
8270Sstevel@tonic-gate 			}
8280Sstevel@tonic-gate 			goto charswitch;
8290Sstevel@tonic-gate 			}
8300Sstevel@tonic-gate 
8310Sstevel@tonic-gate 		case '0':	/* obsolescent spec:  leading zero in width */
8320Sstevel@tonic-gate 				/* means pad with leading zeros */
8330Sstevel@tonic-gate 			if (!(flagword & (DOTSEEN | FMINUS)))
8340Sstevel@tonic-gate 				flagword |= PADZERO;
8350Sstevel@tonic-gate 			/* FALLTHROUGH */
8360Sstevel@tonic-gate 		case '1':
8370Sstevel@tonic-gate 		case '2':
8380Sstevel@tonic-gate 		case '3':
8390Sstevel@tonic-gate 		case '4':
8400Sstevel@tonic-gate 		case '5':
8410Sstevel@tonic-gate 		case '6':
8420Sstevel@tonic-gate 		case '7':
8430Sstevel@tonic-gate 		case '8':
8440Sstevel@tonic-gate 		case '9':
8450Sstevel@tonic-gate 			{ num = fcode - '0';
8460Sstevel@tonic-gate 			while (_M_ISDIGIT(fcode = *format)) {
8470Sstevel@tonic-gate 				num = num * 10 + fcode - '0';
8480Sstevel@tonic-gate 				format++;
8490Sstevel@tonic-gate 			}
8500Sstevel@tonic-gate 			if (flagword & DOTSEEN)
8510Sstevel@tonic-gate 				prec = num;
8520Sstevel@tonic-gate 			else
8530Sstevel@tonic-gate 				width = num;
8540Sstevel@tonic-gate 			goto charswitch;
8550Sstevel@tonic-gate 			}
8560Sstevel@tonic-gate 
8570Sstevel@tonic-gate 		/* Scan the length modifier */
8580Sstevel@tonic-gate 		case 'l':
8590Sstevel@tonic-gate 			if (!(flagword & XLONG)) {
8600Sstevel@tonic-gate 				if (lflag) {
8610Sstevel@tonic-gate 					/* long long */
8620Sstevel@tonic-gate 					flagword &= ~LENGTH;
8630Sstevel@tonic-gate 					flagword |= XLONG;
8640Sstevel@tonic-gate 				} else	{
8650Sstevel@tonic-gate 					/* long */
8660Sstevel@tonic-gate 					flagword |= LENGTH;
8670Sstevel@tonic-gate 				}
8680Sstevel@tonic-gate 			}
8690Sstevel@tonic-gate 			lflag++;
8700Sstevel@tonic-gate 			goto charswitch;
8710Sstevel@tonic-gate 
8720Sstevel@tonic-gate 		case 'L':			/* long double */
8730Sstevel@tonic-gate 			flagword |= QUAD;
8740Sstevel@tonic-gate 			goto charswitch;
8750Sstevel@tonic-gate 
8760Sstevel@tonic-gate 		case 'h':
8770Sstevel@tonic-gate 			if (!(flagword & CHAR)) {
8780Sstevel@tonic-gate 				if (flagword & SHORT) {
8790Sstevel@tonic-gate 					/* char - hh */
8800Sstevel@tonic-gate 					flagword &= ~SHORT;
8810Sstevel@tonic-gate 					flagword |= CHAR;
8820Sstevel@tonic-gate 				} else {
8830Sstevel@tonic-gate 					/* short */
8840Sstevel@tonic-gate 					flagword |= SHORT;
8850Sstevel@tonic-gate 				}
8860Sstevel@tonic-gate 			}
8870Sstevel@tonic-gate 			goto charswitch;
8880Sstevel@tonic-gate 		case 'j':
8890Sstevel@tonic-gate #ifndef _LP64
8900Sstevel@tonic-gate 			/*
8910Sstevel@tonic-gate 			 * *printf_c89() in 32-bit libc uses
8920Sstevel@tonic-gate 			 * 32-bit intmax_t; otherwise intmax_t
8930Sstevel@tonic-gate 			 * is 64-bits.
8940Sstevel@tonic-gate 			 */
8950Sstevel@tonic-gate 			if (!(prflag & _F_INTMAX32)) {
8960Sstevel@tonic-gate #endif
8970Sstevel@tonic-gate 				flagword |= XLONG;	/* [u]intmax_t (64) */
8980Sstevel@tonic-gate #ifndef _LP64
8990Sstevel@tonic-gate 			}
9000Sstevel@tonic-gate #endif
9010Sstevel@tonic-gate 			goto charswitch;
9020Sstevel@tonic-gate 
9030Sstevel@tonic-gate 		case 't':
9040Sstevel@tonic-gate 			/*
9050Sstevel@tonic-gate 			 * LENGTH is shared by l, t, z specifiers; protect
9060Sstevel@tonic-gate 			 * against (destructive) undefined behavior (eg:
9070Sstevel@tonic-gate 			 * avoid %llt setting XLONG and LENGTH) with invalid
9080Sstevel@tonic-gate 			 * combinations of specifiers
9090Sstevel@tonic-gate 			 */
9100Sstevel@tonic-gate 			if (!(flagword & XLONG)) {
9110Sstevel@tonic-gate 				flagword |= LENGTH;	/* ptrdiff_t */
9120Sstevel@tonic-gate 			}
9130Sstevel@tonic-gate 			goto charswitch;
9140Sstevel@tonic-gate 
9150Sstevel@tonic-gate 		case 'z':
9160Sstevel@tonic-gate 			if (!(flagword & XLONG)) {
9170Sstevel@tonic-gate 				flagword |= LENGTH;	/* [s]size_t */
9180Sstevel@tonic-gate 			}
9190Sstevel@tonic-gate 			goto charswitch;
9200Sstevel@tonic-gate 
9210Sstevel@tonic-gate 		/*
9220Sstevel@tonic-gate 		 *	The character addressed by format must be
9230Sstevel@tonic-gate 		 *	the format letter -- there is nothing
9240Sstevel@tonic-gate 		 *	left for it to be.
9250Sstevel@tonic-gate 		 *
9260Sstevel@tonic-gate 		 *	The status of the +, -, #, and blank
9270Sstevel@tonic-gate 		 *	flags are reflected in the variable
9280Sstevel@tonic-gate 		 *	"flagword".  "width" and "prec" contain
9290Sstevel@tonic-gate 		 *	numbers corresponding to the digit
9300Sstevel@tonic-gate 		 *	strings before and after the decimal
9310Sstevel@tonic-gate 		 *	point, respectively. If there was no
9320Sstevel@tonic-gate 		 *	decimal point, then flagword & DOTSEEN
9330Sstevel@tonic-gate 		 *	is false and the value of prec is meaningless.
9340Sstevel@tonic-gate 		 *
9350Sstevel@tonic-gate 		 *	The following switch cases set things up
9360Sstevel@tonic-gate 		 *	for printing.  What ultimately gets
9370Sstevel@tonic-gate 		 *	printed will be padding blanks, a
9380Sstevel@tonic-gate 		 *	prefix, left padding zeroes, a value,
9390Sstevel@tonic-gate 		 *	right padding zeroes, a suffix, and
9400Sstevel@tonic-gate 		 *	more padding blanks.  Padding blanks
9410Sstevel@tonic-gate 		 *	will not appear simultaneously on both
9420Sstevel@tonic-gate 		 *	the left and the right.  Each case in
9430Sstevel@tonic-gate 		 *	this switch will compute the value, and
9440Sstevel@tonic-gate 		 *	leave in several variables the informa-
9450Sstevel@tonic-gate 		 *	tion necessary to construct what is to
9460Sstevel@tonic-gate 		 *	be printed.
9470Sstevel@tonic-gate 		 *
9480Sstevel@tonic-gate 		 *	The prefix is a sign, a blank, "0x",
9490Sstevel@tonic-gate 		 *	"0X", a sign or a blank followed by "0x"
9500Sstevel@tonic-gate 		 *	or "0X", or nothing, and is addressed by
9510Sstevel@tonic-gate 		 *	"prefix".
9520Sstevel@tonic-gate 		 *
9530Sstevel@tonic-gate 		 *	The suffix is either null or an
9540Sstevel@tonic-gate 		 *	exponent, and is addressed by "suffix".
9550Sstevel@tonic-gate 		 *	If there is a suffix, the flagword bit
9560Sstevel@tonic-gate 		 *	SUFFIX will be set.
9570Sstevel@tonic-gate 		 *
9580Sstevel@tonic-gate 		 *	The value to be printed starts at "bp"
9590Sstevel@tonic-gate 		 *	and continues up to and not including
9600Sstevel@tonic-gate 		 *	"p".
9610Sstevel@tonic-gate 		 *
9620Sstevel@tonic-gate 		 *	"lzero" and "rzero" will contain the
9630Sstevel@tonic-gate 		 *	number of padding zeroes required on
9640Sstevel@tonic-gate 		 *	the left and right, respectively.
9650Sstevel@tonic-gate 		 *	The flagword bits LZERO and RZERO tell
9660Sstevel@tonic-gate 		 *	whether padding zeros are required.
9670Sstevel@tonic-gate 		 *
9680Sstevel@tonic-gate 		 *	The number of padding blanks, and
9690Sstevel@tonic-gate 		 *	whether they go on the left or the
9700Sstevel@tonic-gate 		 *	right, will be computed on exit from
9710Sstevel@tonic-gate 		 *	the switch.
9720Sstevel@tonic-gate 		 */
9730Sstevel@tonic-gate 
9740Sstevel@tonic-gate 
9750Sstevel@tonic-gate 
9760Sstevel@tonic-gate 		/*
9770Sstevel@tonic-gate 		 *	decimal fixed point representations
9780Sstevel@tonic-gate 		 *
9790Sstevel@tonic-gate 		 *	HIBITL is 100...000
9800Sstevel@tonic-gate 		 *	binary, and is equal to	the maximum
9810Sstevel@tonic-gate 		 *	negative number.
9820Sstevel@tonic-gate 		 *	We assume a 2's complement machine
9830Sstevel@tonic-gate 		 */
9840Sstevel@tonic-gate 		case 'i':
9850Sstevel@tonic-gate 		case 'd':
9860Sstevel@tonic-gate 			if ((flagword & PADZERO) && (flagword & DOTSEEN))
9870Sstevel@tonic-gate 				flagword &= ~PADZERO; /* ignore 0 flag */
9880Sstevel@tonic-gate 			/* Set buffer pointer to last digit */
9890Sstevel@tonic-gate 			p = bp = buf + MAXLLDIGS;
9900Sstevel@tonic-gate 
9910Sstevel@tonic-gate 			/* Fetch the argument to be printed */
9920Sstevel@tonic-gate 			if (flagword & XLONG) {		/* long long */
9930Sstevel@tonic-gate 				ll = va_arg(args.ap, long long);
9940Sstevel@tonic-gate 
9950Sstevel@tonic-gate 				/* If signed conversion, make sign */
9960Sstevel@tonic-gate 				if (ll < 0) {
9970Sstevel@tonic-gate 					prefix = _P_HYPHEN;
9980Sstevel@tonic-gate 					prefixlength = 1;
9990Sstevel@tonic-gate 					/*
10000Sstevel@tonic-gate 					 * Negate, checking in advance for
10010Sstevel@tonic-gate 					 * possible overflow.
10020Sstevel@tonic-gate 					 */
10030Sstevel@tonic-gate 					if (ll != HIBITLL)
10040Sstevel@tonic-gate 						ll = -ll;
10050Sstevel@tonic-gate 					else
10060Sstevel@tonic-gate 					/* number is -HIBITLL; convert last */
10070Sstevel@tonic-gate 					/* digit now and get positive number */
10080Sstevel@tonic-gate 						*--bp = _lowlldigit(&ll);
10090Sstevel@tonic-gate 				} else if (flagword & FPLUS) {
10100Sstevel@tonic-gate 					prefix = _P_PLUS;
10110Sstevel@tonic-gate 					prefixlength = 1;
10120Sstevel@tonic-gate 				} else if (flagword & FBLANK) {
10130Sstevel@tonic-gate 					prefix = _P_BLANK;
10140Sstevel@tonic-gate 					prefixlength = 1;
10150Sstevel@tonic-gate 				}
10160Sstevel@tonic-gate 			} else {		/* not long long */
10170Sstevel@tonic-gate 				if (flagword & LENGTH)
10180Sstevel@tonic-gate 					val = va_arg(args.ap, long);
10190Sstevel@tonic-gate 				else
10200Sstevel@tonic-gate 					val = va_arg(args.ap, int);
10210Sstevel@tonic-gate 
10220Sstevel@tonic-gate 				if (flagword & SHORT)
10230Sstevel@tonic-gate 					val = (short)val;
10240Sstevel@tonic-gate 				else if (flagword & CHAR)
10250Sstevel@tonic-gate 					val = (char)val;
10260Sstevel@tonic-gate 
10270Sstevel@tonic-gate 				/* If signed conversion, make sign */
10280Sstevel@tonic-gate 				if (val < 0) {
10290Sstevel@tonic-gate 					prefix = _P_HYPHEN;
10300Sstevel@tonic-gate 					prefixlength = 1;
10310Sstevel@tonic-gate 					/*
10320Sstevel@tonic-gate 					 * Negate, checking in advance
10330Sstevel@tonic-gate 					 * for possible overflow.
10340Sstevel@tonic-gate 					 */
10350Sstevel@tonic-gate 					if (val != HIBITL)
10360Sstevel@tonic-gate 						val = -val;
10370Sstevel@tonic-gate 					/*
10380Sstevel@tonic-gate 					 * number is -HIBITL; convert
10390Sstevel@tonic-gate 					 * last digit now and get
10400Sstevel@tonic-gate 					 * positive number
10410Sstevel@tonic-gate 					 */
10420Sstevel@tonic-gate 					else
10430Sstevel@tonic-gate 						*--bp = _lowdigit(&val);
10440Sstevel@tonic-gate 				} else if (flagword & FPLUS) {
10450Sstevel@tonic-gate 					prefix = _P_PLUS;
10460Sstevel@tonic-gate 					prefixlength = 1;
10470Sstevel@tonic-gate 				} else if (flagword & FBLANK) {
10480Sstevel@tonic-gate 					prefix = _P_BLANK;
10490Sstevel@tonic-gate 					prefixlength = 1;
10500Sstevel@tonic-gate 				}
10510Sstevel@tonic-gate 			}
10520Sstevel@tonic-gate 
10530Sstevel@tonic-gate 		decimal:
10540Sstevel@tonic-gate 			{
10550Sstevel@tonic-gate 			long qval = val;
10560Sstevel@tonic-gate 			long long lll = ll;
10570Sstevel@tonic-gate 			long long tll;
10580Sstevel@tonic-gate 			if (flagword & XLONG) {
10590Sstevel@tonic-gate 				if (lll < 10LL) {
10600Sstevel@tonic-gate #ifdef	_WIDE
10610Sstevel@tonic-gate 					if (lll != 0LL || !(flagword & DOTSEEN))
10620Sstevel@tonic-gate 						*--bp = (wchar_t)lll + L'0';
10630Sstevel@tonic-gate #else  /* _WIDE */
10640Sstevel@tonic-gate 					if (lll != 0LL || !(flagword & DOTSEEN))
10650Sstevel@tonic-gate 						*--bp = (char)lll + '0';
10660Sstevel@tonic-gate #endif /* _WIDE */
10670Sstevel@tonic-gate 				} else {
10680Sstevel@tonic-gate 					do {
10690Sstevel@tonic-gate 						tll = lll;
10700Sstevel@tonic-gate 						lll /= 10;
10710Sstevel@tonic-gate #ifdef	_WIDE
10720Sstevel@tonic-gate 						*--bp = (wchar_t)
10730Sstevel@tonic-gate 							(tll - lll * 10 + '0');
10740Sstevel@tonic-gate #else  /* _WIDE */
10750Sstevel@tonic-gate 						*--bp = (char) \
10760Sstevel@tonic-gate 						    (tll - lll * 10 + '0');
10770Sstevel@tonic-gate #endif /* _WIDE */
10780Sstevel@tonic-gate 					} while (lll >= 10);
10790Sstevel@tonic-gate #ifdef	_WIDE
10800Sstevel@tonic-gate 					*--bp = (wchar_t)lll + '0';
10810Sstevel@tonic-gate #else  /* _WIDE */
10820Sstevel@tonic-gate 					*--bp = (char)lll + '0';
10830Sstevel@tonic-gate #endif /* _WIDE */
10840Sstevel@tonic-gate 				}
10850Sstevel@tonic-gate 			} else {
10860Sstevel@tonic-gate 				if (qval <= 9) {
10870Sstevel@tonic-gate #ifdef	_WIDE
10880Sstevel@tonic-gate 					if (qval != 0 || !(flagword & DOTSEEN))
10890Sstevel@tonic-gate 						*--bp = (wchar_t)qval + '0';
10900Sstevel@tonic-gate #else  /* _WIDE */
10910Sstevel@tonic-gate 					if (qval != 0 || !(flagword & DOTSEEN))
10920Sstevel@tonic-gate 						*--bp = (char)qval + '0';
10930Sstevel@tonic-gate #endif /* _WIDE */
10940Sstevel@tonic-gate 				} else {
10950Sstevel@tonic-gate 					do {
10960Sstevel@tonic-gate 						n = qval;
10970Sstevel@tonic-gate 						qval /= 10;
10980Sstevel@tonic-gate #ifdef	_WIDE
10990Sstevel@tonic-gate 						*--bp = (wchar_t) \
11000Sstevel@tonic-gate 						    (n - qval * 10 + '0');
11010Sstevel@tonic-gate #else  /* _WIDE */
11020Sstevel@tonic-gate 						*--bp = (char) \
11030Sstevel@tonic-gate 						    (n - qval * 10 + '0');
11040Sstevel@tonic-gate #endif /* _WIDE */
11050Sstevel@tonic-gate 					} while (qval > 9);
11060Sstevel@tonic-gate #ifdef	_WIDE
11070Sstevel@tonic-gate 					*--bp = (wchar_t)qval + '0';
11080Sstevel@tonic-gate #else  /* _WIDE */
11090Sstevel@tonic-gate 					*--bp = (char)qval + '0';
11100Sstevel@tonic-gate #endif /* _WIDE */
11110Sstevel@tonic-gate 				}
11120Sstevel@tonic-gate 			}
11130Sstevel@tonic-gate 			}
11140Sstevel@tonic-gate 			/* Handle the ' flag */
11150Sstevel@tonic-gate 			if (quote) {
11160Sstevel@tonic-gate 				p = insert_thousands_sep(bp, p);
11170Sstevel@tonic-gate 			}
11180Sstevel@tonic-gate 
11190Sstevel@tonic-gate 			/* Calculate minimum padding zero requirement */
11200Sstevel@tonic-gate 			if (flagword & DOTSEEN) {
11210Sstevel@tonic-gate 				leadzeroes = prec - (p - bp);
11220Sstevel@tonic-gate 				if (leadzeroes > 0) {
11230Sstevel@tonic-gate 					otherlength = lzero = leadzeroes;
11240Sstevel@tonic-gate 					flagword |= LZERO;
11250Sstevel@tonic-gate 				}
11260Sstevel@tonic-gate 			}
11270Sstevel@tonic-gate 			break;
11280Sstevel@tonic-gate 
11290Sstevel@tonic-gate 		case 'u':
11300Sstevel@tonic-gate 			if ((flagword & PADZERO) && (flagword & DOTSEEN))
11310Sstevel@tonic-gate 				flagword &= ~PADZERO; /* ignore 0 flag */
11320Sstevel@tonic-gate 			p = bp = buf + MAXLLDIGS;
11330Sstevel@tonic-gate 
11340Sstevel@tonic-gate 			/* Fetch the argument to be printed */
11350Sstevel@tonic-gate 			if (flagword & XLONG) {
11360Sstevel@tonic-gate 				ll = va_arg(args.ap, long long);
11370Sstevel@tonic-gate 
11380Sstevel@tonic-gate 				if (ll & HIBITLL)
11390Sstevel@tonic-gate 					*--bp = _lowlldigit(&ll);
11400Sstevel@tonic-gate 			} else {
11410Sstevel@tonic-gate 				if (flagword & LENGTH)
11420Sstevel@tonic-gate 					val = va_arg(args.ap, long);
11430Sstevel@tonic-gate 				else
11440Sstevel@tonic-gate 					val = va_arg(args.ap, unsigned);
11450Sstevel@tonic-gate 
11460Sstevel@tonic-gate 				if (flagword & SHORT)
11470Sstevel@tonic-gate 					val = (unsigned short)val;
11480Sstevel@tonic-gate 				else if (flagword & CHAR)
11490Sstevel@tonic-gate 					val = (unsigned char)val;
11500Sstevel@tonic-gate 
11510Sstevel@tonic-gate 				if (val & HIBITL)
11520Sstevel@tonic-gate 					*--bp = _lowdigit(&val);
11530Sstevel@tonic-gate 			}
11540Sstevel@tonic-gate 
11550Sstevel@tonic-gate 			goto decimal;
11560Sstevel@tonic-gate 
11570Sstevel@tonic-gate 		/*
11580Sstevel@tonic-gate 		 *	non-decimal fixed point representations
11590Sstevel@tonic-gate 		 *	for radix equal to a power of two
11600Sstevel@tonic-gate 		 *
11610Sstevel@tonic-gate 		 *	"mradix" is one less than the radix for the conversion.
11620Sstevel@tonic-gate 		 *	"lradix" is one less than the base 2 log
11630Sstevel@tonic-gate 		 *	of the radix for the conversion. Conversion is unsigned.
11640Sstevel@tonic-gate 		 *	HIBITL is 100...000
11650Sstevel@tonic-gate 		 *	binary, and is equal to	the maximum
11660Sstevel@tonic-gate 		 *	negative number.
11670Sstevel@tonic-gate 		 *	We assume a 2's complement machine
11680Sstevel@tonic-gate 		 */
11690Sstevel@tonic-gate 
11700Sstevel@tonic-gate 		case 'o':
11710Sstevel@tonic-gate 			mradix = 7;
11720Sstevel@tonic-gate 			lradix = 2;
11730Sstevel@tonic-gate 			/*
11740Sstevel@tonic-gate 			 * DR151 and clarification in C90
11750Sstevel@tonic-gate 			 * presence of '#' increases precision to first
11760Sstevel@tonic-gate 			 * digit of the result to be zero
11770Sstevel@tonic-gate 			 */
11780Sstevel@tonic-gate 			if ((flagword & DOTSEEN) && (flagword & FSHARP) &&
11790Sstevel@tonic-gate 			    prec == 0)
11800Sstevel@tonic-gate 				prec = 1;
11810Sstevel@tonic-gate 
11820Sstevel@tonic-gate 			goto fixed;
11830Sstevel@tonic-gate 
11840Sstevel@tonic-gate 		case 'p':
11850Sstevel@tonic-gate 			flagword &= ~(XLONG | SHORT);
11860Sstevel@tonic-gate 			flagword |= LENGTH;
11870Sstevel@tonic-gate 
11880Sstevel@tonic-gate 			/* FALLTHRU */
11890Sstevel@tonic-gate 		case 'X':
11900Sstevel@tonic-gate 		case 'x':
11910Sstevel@tonic-gate 			mradix = 15;
11920Sstevel@tonic-gate 			lradix = 3;
11930Sstevel@tonic-gate 
11940Sstevel@tonic-gate 		fixed:
11950Sstevel@tonic-gate 			if ((flagword & PADZERO) && (flagword & DOTSEEN))
11960Sstevel@tonic-gate 				flagword &= ~PADZERO; /* ignore 0 flag */
11970Sstevel@tonic-gate 
11980Sstevel@tonic-gate #ifdef	_WIDE
11990Sstevel@tonic-gate 			/* Set translate table for digits */
12000Sstevel@tonic-gate 			tab = (wchar_t *)((fcode == 'X') ? uc_digs : lc_digs);
12010Sstevel@tonic-gate #else  /* _WIDE */
12020Sstevel@tonic-gate 			/* Set translate table for digits */
12030Sstevel@tonic-gate 			tab = (fcode == 'X') ? uc_digs : lc_digs;
12040Sstevel@tonic-gate #endif /* _WIDE */
12050Sstevel@tonic-gate 
12060Sstevel@tonic-gate 			/* Fetch the argument to be printed */
12070Sstevel@tonic-gate 			if (flagword & XLONG) {
12080Sstevel@tonic-gate 				ll = va_arg(args.ap, long long);
12090Sstevel@tonic-gate 			} else {
12100Sstevel@tonic-gate 				if (flagword & LENGTH)
12110Sstevel@tonic-gate 					val = va_arg(args.ap, long);
12120Sstevel@tonic-gate 				else
12130Sstevel@tonic-gate 					val = va_arg(args.ap, unsigned);
12140Sstevel@tonic-gate 
12150Sstevel@tonic-gate 				if (flagword & SHORT)
12160Sstevel@tonic-gate 					val = (unsigned short) val;
12170Sstevel@tonic-gate 				else if (flagword & CHAR)
12180Sstevel@tonic-gate 					val = (unsigned char) val;
12190Sstevel@tonic-gate 			}
12200Sstevel@tonic-gate 			p = bp = buf + MAXLLDIGS;
12210Sstevel@tonic-gate 
12220Sstevel@tonic-gate 			/* Develop the digits of the value */
12230Sstevel@tonic-gate 			if (flagword & XLONG) {
12240Sstevel@tonic-gate 				long long lll = ll;
12250Sstevel@tonic-gate 
12260Sstevel@tonic-gate 				if (lll == 0LL) {
12270Sstevel@tonic-gate 					if (!(flagword & DOTSEEN)) {
12280Sstevel@tonic-gate 						otherlength = lzero = 1;
12290Sstevel@tonic-gate 						flagword |= LZERO;
12300Sstevel@tonic-gate 					}
12310Sstevel@tonic-gate 				} else do {
12320Sstevel@tonic-gate 					*--bp = tab[(ssize_t)(lll & mradix)];
12330Sstevel@tonic-gate 					lll = ((lll >> 1) & ~HIBITLL) \
12340Sstevel@tonic-gate 					    >> lradix;
12350Sstevel@tonic-gate 				} while (lll != 0LL);
12360Sstevel@tonic-gate 			} else {
12370Sstevel@tonic-gate 				long qval = val;
12380Sstevel@tonic-gate 
12390Sstevel@tonic-gate 				if (qval == 0) {
12400Sstevel@tonic-gate 					if (!(flagword & DOTSEEN)) {
12410Sstevel@tonic-gate 						otherlength = lzero = 1;
12420Sstevel@tonic-gate 						flagword |= LZERO;
12430Sstevel@tonic-gate 					}
12440Sstevel@tonic-gate 				} else do {
12450Sstevel@tonic-gate 					*--bp = tab[qval & mradix];
12460Sstevel@tonic-gate 					qval = ((qval >> 1) & ~HIBITL) \
12470Sstevel@tonic-gate 					    >> lradix;
12480Sstevel@tonic-gate 				} while (qval != 0);
12490Sstevel@tonic-gate 			}
12500Sstevel@tonic-gate 
12510Sstevel@tonic-gate 			/* Calculate minimum padding zero requirement */
12520Sstevel@tonic-gate 			if (flagword & DOTSEEN) {
12530Sstevel@tonic-gate 				leadzeroes = prec - (p - bp);
12540Sstevel@tonic-gate 				if (leadzeroes > 0) {
12550Sstevel@tonic-gate 					otherlength = lzero = leadzeroes;
12560Sstevel@tonic-gate 					flagword |= LZERO;
12570Sstevel@tonic-gate 				}
12580Sstevel@tonic-gate 			}
12590Sstevel@tonic-gate 
12600Sstevel@tonic-gate 			/* Handle the # flag, (val != 0) for int and long */
12610Sstevel@tonic-gate 			/* (ll!= 0) handles long long case */
12620Sstevel@tonic-gate 			if ((flagword & FSHARP) &&
12630Sstevel@tonic-gate 			    (((flagword & XLONG) == 0 && val != 0) ||
12640Sstevel@tonic-gate 			    ((flagword & XLONG) == XLONG && ll != 0)))
12650Sstevel@tonic-gate 				switch (fcode) {
12660Sstevel@tonic-gate 				case 'o':
12670Sstevel@tonic-gate 					if (!(flagword & LZERO)) {
12680Sstevel@tonic-gate 						otherlength = lzero = 1;
12690Sstevel@tonic-gate 						flagword |= LZERO;
12700Sstevel@tonic-gate 					}
12710Sstevel@tonic-gate 					break;
12720Sstevel@tonic-gate 				case 'x':
12730Sstevel@tonic-gate 					prefix = _P_ZEROx;
12740Sstevel@tonic-gate 					prefixlength = 2;
12750Sstevel@tonic-gate 					break;
12760Sstevel@tonic-gate 				case 'X':
12770Sstevel@tonic-gate 					prefix = _P_ZEROX;
12780Sstevel@tonic-gate 					prefixlength = 2;
12790Sstevel@tonic-gate 					break;
12800Sstevel@tonic-gate 				}
12810Sstevel@tonic-gate 
12820Sstevel@tonic-gate 			break;
12830Sstevel@tonic-gate 
12840Sstevel@tonic-gate 		case 'A':
12850Sstevel@tonic-gate 		case 'a':
12860Sstevel@tonic-gate 			/* A format */
12870Sstevel@tonic-gate 			if (flagword & QUAD) {
12880Sstevel@tonic-gate 				long double	qval = GETQVAL(args.ap);
12890Sstevel@tonic-gate 
12900Sstevel@tonic-gate 				/* establish default precision */
12910Sstevel@tonic-gate 				if (!(flagword & DOTSEEN))
12920Sstevel@tonic-gate #if defined(__sparc)
12930Sstevel@tonic-gate 					prec = HEXFP_QUAD_DIG - 1;
12940Sstevel@tonic-gate #elif defined(__i386) || defined(__amd64)
12950Sstevel@tonic-gate 					prec = HEXFP_EXTENDED_DIG - 1;
12960Sstevel@tonic-gate #else
12970Sstevel@tonic-gate #error Unknown architecture
12980Sstevel@tonic-gate #endif
12990Sstevel@tonic-gate 
13000Sstevel@tonic-gate 				FPCONV(__qaconvert, &qval,
13010Sstevel@tonic-gate 				    min(prec + 1, MAXECVT), &exp, &sign,
13020Sstevel@tonic-gate 				    cvtbuf);
13030Sstevel@tonic-gate 			} else {
13040Sstevel@tonic-gate 				double	dval = va_arg(args.ap, double);
13050Sstevel@tonic-gate 
13060Sstevel@tonic-gate 				/* establish default precision */
13070Sstevel@tonic-gate 				if (!(flagword & DOTSEEN))
13080Sstevel@tonic-gate 					prec = HEXFP_DOUBLE_DIG - 1;
13090Sstevel@tonic-gate 
13100Sstevel@tonic-gate 				FPCONV(__aconvert, dval,
13110Sstevel@tonic-gate 				    min(prec + 1, MAXECVT), &exp, &sign,
13120Sstevel@tonic-gate 				    cvtbuf);
13130Sstevel@tonic-gate 			}
13140Sstevel@tonic-gate 			bp = cvtbuf;
13150Sstevel@tonic-gate 
13160Sstevel@tonic-gate 			/*
13170Sstevel@tonic-gate 			 * The following is wide-character safe because
13180Sstevel@tonic-gate 			 * __aconvert and __qaconvert only produce ASCII
13190Sstevel@tonic-gate 			 * characters.
13200Sstevel@tonic-gate 			 */
13210Sstevel@tonic-gate 			if (!isxdigit((unsigned char)*bp)) {
13220Sstevel@tonic-gate 				inf_nan = 1;
13230Sstevel@tonic-gate 				break;
13240Sstevel@tonic-gate 			}
13250Sstevel@tonic-gate 
13260Sstevel@tonic-gate 			/*
13270Sstevel@tonic-gate 			 * Create the prefix.  We ought to use the strings
13280Sstevel@tonic-gate 			 * defined above (_P_HYPHEN, etc.), but that would
13290Sstevel@tonic-gate 			 * be awkward: we'd either have to define six more
13300Sstevel@tonic-gate 			 * of them or we'd have to use strcpy/strcat to
13310Sstevel@tonic-gate 			 * assemble the ones already defined.  So instead,
13320Sstevel@tonic-gate 			 * we just build the prefix character by character.
13330Sstevel@tonic-gate 			 */
13340Sstevel@tonic-gate 			p = prefix = prefixbuf;
13350Sstevel@tonic-gate 			if (sign) {
13360Sstevel@tonic-gate 				*p++ = '-';
13370Sstevel@tonic-gate 				prefixlength = 1;
13380Sstevel@tonic-gate 			} else if (flagword & FPLUS) {
13390Sstevel@tonic-gate 				*p++ = '+';
13400Sstevel@tonic-gate 				prefixlength = 1;
13410Sstevel@tonic-gate 			} else if (flagword & FBLANK) {
13420Sstevel@tonic-gate 				*p++ = ' ';
13430Sstevel@tonic-gate 				prefixlength = 1;
13440Sstevel@tonic-gate 			}
13450Sstevel@tonic-gate 			*p++ = '0';
13460Sstevel@tonic-gate 			*p++ = (fcode == 'A') ? 'X' : 'x';
13470Sstevel@tonic-gate 			*p = '\0';
13480Sstevel@tonic-gate 			prefixlength += 2;
13490Sstevel@tonic-gate 
13500Sstevel@tonic-gate 			/* put the first digit in the buffer */
13510Sstevel@tonic-gate 			p = &buf[0];
13520Sstevel@tonic-gate 			*p++ = (*bp != '\0') ? *bp++ : '0';
13530Sstevel@tonic-gate 
13540Sstevel@tonic-gate 			/* put in a decimal point if needed */
13550Sstevel@tonic-gate 			if (prec != 0 || (flagword & FSHARP))
13560Sstevel@tonic-gate 				*p++ = _numeric[0];
13570Sstevel@tonic-gate 
13580Sstevel@tonic-gate 			/* create the rest of the mantissa */
13590Sstevel@tonic-gate 			rz = prec;
13600Sstevel@tonic-gate 			if (fcode == 'A') {
13610Sstevel@tonic-gate 				for (; rz > 0 && *bp != '\0'; --rz) {
13620Sstevel@tonic-gate 					*p++ = ('a' <= *bp && *bp <= 'f')?
13630Sstevel@tonic-gate 					    *bp - 32 : *bp;
13640Sstevel@tonic-gate 					bp++;
13650Sstevel@tonic-gate 				}
13660Sstevel@tonic-gate 			} else {
13670Sstevel@tonic-gate 				for (; rz > 0 && *bp != '\0'; --rz)
13680Sstevel@tonic-gate 					*p++ = *bp++;
13690Sstevel@tonic-gate 			}
13700Sstevel@tonic-gate 			if (rz > 0) {
13710Sstevel@tonic-gate 				otherlength = rzero = rz;
13720Sstevel@tonic-gate 				flagword |= RZERO;
13730Sstevel@tonic-gate 			}
13740Sstevel@tonic-gate 
13750Sstevel@tonic-gate 			bp = &buf[0];
13760Sstevel@tonic-gate 
13770Sstevel@tonic-gate 			/*
13780Sstevel@tonic-gate 			 * Create the exponent in right-to-left order.
13790Sstevel@tonic-gate 			 * buf[0] == '0' if and only if the value being
13800Sstevel@tonic-gate 			 * converted is exactly zero, in which case the
13810Sstevel@tonic-gate 			 * exponent should be +0 regardless of exp.
13820Sstevel@tonic-gate 			 */
13830Sstevel@tonic-gate 			suffix = &expbuf[MAXESIZ];
13840Sstevel@tonic-gate 			*suffix = '\0';
13850Sstevel@tonic-gate 			if (buf[0] != '0') {
13860Sstevel@tonic-gate 				int	nn;
13870Sstevel@tonic-gate 
13880Sstevel@tonic-gate 				nn = exp;
13890Sstevel@tonic-gate 				if (nn < 0)
13900Sstevel@tonic-gate 				    nn = -nn;
13910Sstevel@tonic-gate 				for (; nn > 9; nn /= 10)
13920Sstevel@tonic-gate 					*--suffix = todigit(nn % 10);
13930Sstevel@tonic-gate 				*--suffix = todigit(nn);
13940Sstevel@tonic-gate 				*--suffix = (exp >= 0) ? '+' : '-';
13950Sstevel@tonic-gate 			} else {
13960Sstevel@tonic-gate 				*--suffix = '0';
13970Sstevel@tonic-gate 				*--suffix = '+';
13980Sstevel@tonic-gate 			}
13990Sstevel@tonic-gate 
14000Sstevel@tonic-gate 			/* put in the p */
14010Sstevel@tonic-gate 			*--suffix = (fcode == 'A') ? 'P' : 'p';
14020Sstevel@tonic-gate 
14030Sstevel@tonic-gate 			/* compute size of suffix */
14040Sstevel@tonic-gate 			suffixlength = &expbuf[MAXESIZ] - suffix;
14050Sstevel@tonic-gate 			otherlength += suffixlength;
14060Sstevel@tonic-gate 			flagword |= SUFFIX;
14070Sstevel@tonic-gate 			break;
14080Sstevel@tonic-gate 
14090Sstevel@tonic-gate 		case 'E':
14100Sstevel@tonic-gate 		case 'e':
14110Sstevel@tonic-gate 			/*
14120Sstevel@tonic-gate 			 * E-format.  The general strategy
14130Sstevel@tonic-gate 			 * here is fairly easy: we take what
14140Sstevel@tonic-gate 			 * econvert gives us and re-format it.
14150Sstevel@tonic-gate 			 * (qeconvert for long double)
14160Sstevel@tonic-gate 			 */
14170Sstevel@tonic-gate 
14180Sstevel@tonic-gate 			/* Establish default precision */
14190Sstevel@tonic-gate 			if (!(flagword & DOTSEEN))
14200Sstevel@tonic-gate 				prec = 6;
14210Sstevel@tonic-gate 
14220Sstevel@tonic-gate 			if (flagword & QUAD) {	/* long double */
14230Sstevel@tonic-gate 				long double	qval = GETQVAL(args.ap);
14240Sstevel@tonic-gate 
14250Sstevel@tonic-gate 				FPCONV(qeconvert, &qval,
14260Sstevel@tonic-gate 				    min(prec + 1, MAXECVT), &decpt, &sign,
14270Sstevel@tonic-gate 				    cvtbuf);
14280Sstevel@tonic-gate 			} else {	/* double */
14290Sstevel@tonic-gate 				double	dval = va_arg(args.ap, double);
14300Sstevel@tonic-gate 
14310Sstevel@tonic-gate 				FPCONV(econvert, dval,
14320Sstevel@tonic-gate 				    min(prec + 1, MAXECVT), &decpt, &sign,
14330Sstevel@tonic-gate 				    cvtbuf);
14340Sstevel@tonic-gate 			}
14350Sstevel@tonic-gate 			bp = cvtbuf;
14360Sstevel@tonic-gate 			if (*bp > '9') {
14370Sstevel@tonic-gate 				inf_nan = 1;
14380Sstevel@tonic-gate 				inf_nan_mixed_case = (__xpg6 &
14390Sstevel@tonic-gate 				    _C99SUSv3_mixed_case_Inf_and_NaN);
14400Sstevel@tonic-gate 				break;
14410Sstevel@tonic-gate 			}
14420Sstevel@tonic-gate 
14430Sstevel@tonic-gate 			/* Determine the prefix */
14440Sstevel@tonic-gate 		e_merge:
14450Sstevel@tonic-gate 			if (sign) {
14460Sstevel@tonic-gate 				prefix = _P_HYPHEN;
14470Sstevel@tonic-gate 				prefixlength = 1;
14480Sstevel@tonic-gate 			} else if (flagword & FPLUS) {
14490Sstevel@tonic-gate 				prefix = _P_PLUS;
14500Sstevel@tonic-gate 				prefixlength = 1;
14510Sstevel@tonic-gate 			} else if (flagword & FBLANK) {
14520Sstevel@tonic-gate 				prefix = _P_BLANK;
14530Sstevel@tonic-gate 				prefixlength = 1;
14540Sstevel@tonic-gate 			}
14550Sstevel@tonic-gate 
14560Sstevel@tonic-gate 			/* Place the first digit in the buffer */
14570Sstevel@tonic-gate 			p = &buf[0];
14580Sstevel@tonic-gate 			*p++ = (*bp != '\0') ? *bp++ : '0';
14590Sstevel@tonic-gate 
14600Sstevel@tonic-gate 			/* Put in a decimal point if needed */
14610Sstevel@tonic-gate 			if (prec != 0 || (flagword & FSHARP))
14620Sstevel@tonic-gate 				*p++ = _numeric[0];
14630Sstevel@tonic-gate 
14640Sstevel@tonic-gate 			/* Create the rest of the mantissa */
14650Sstevel@tonic-gate 			rz = prec;
14660Sstevel@tonic-gate 			for (; rz > 0 && *bp != '\0'; --rz)
14670Sstevel@tonic-gate 				*p++ = *bp++;
14680Sstevel@tonic-gate 			if (rz > 0) {
14690Sstevel@tonic-gate 				otherlength = rzero = rz;
14700Sstevel@tonic-gate 				flagword |= RZERO;
14710Sstevel@tonic-gate 			}
14720Sstevel@tonic-gate 
14730Sstevel@tonic-gate 			bp = &buf[0];
14740Sstevel@tonic-gate 
14750Sstevel@tonic-gate 			/*
14760Sstevel@tonic-gate 			 * Create the exponent.  buf[0] == '0' if and
14770Sstevel@tonic-gate 			 * only if the value being converted is exactly
14780Sstevel@tonic-gate 			 * zero, in which case the exponent should be
14790Sstevel@tonic-gate 			 * +0 regardless of decpt.
14800Sstevel@tonic-gate 			 */
14810Sstevel@tonic-gate 			*(suffix = &expbuf[MAXESIZ]) = '\0';
14820Sstevel@tonic-gate 			if (buf[0] != '0') {
14830Sstevel@tonic-gate 				int nn = decpt - 1;
14840Sstevel@tonic-gate 				if (nn < 0)
14850Sstevel@tonic-gate 				    nn = -nn;
14860Sstevel@tonic-gate 				for (; nn > 9; nn /= 10)
14870Sstevel@tonic-gate 					*--suffix = todigit(nn % 10);
14880Sstevel@tonic-gate 				*--suffix = todigit(nn);
14890Sstevel@tonic-gate 			}
14900Sstevel@tonic-gate 
14910Sstevel@tonic-gate 			/* Prepend leading zeroes to the exponent */
14920Sstevel@tonic-gate 			while (suffix > &expbuf[MAXESIZ - 2])
14930Sstevel@tonic-gate 				*--suffix = '0';
14940Sstevel@tonic-gate 
14950Sstevel@tonic-gate 			/* Put in the exponent sign */
14960Sstevel@tonic-gate 			*--suffix = (decpt > 0 || buf[0] == '0') ? '+' : '-';
14970Sstevel@tonic-gate 
14980Sstevel@tonic-gate 			/* Put in the e */
14990Sstevel@tonic-gate 			*--suffix = _M_ISUPPER(fcode) ? 'E'  : 'e';
15000Sstevel@tonic-gate 
15010Sstevel@tonic-gate 			/* compute size of suffix */
15020Sstevel@tonic-gate 			otherlength += (suffixlength = &expbuf[MAXESIZ] \
15030Sstevel@tonic-gate 			    - suffix);
15040Sstevel@tonic-gate 			flagword |= SUFFIX;
15050Sstevel@tonic-gate 			break;
15060Sstevel@tonic-gate 
15070Sstevel@tonic-gate 		case 'F':
15080Sstevel@tonic-gate 		case 'f':
15090Sstevel@tonic-gate 			/*
15100Sstevel@tonic-gate 			 * F-format floating point.  This is a
15110Sstevel@tonic-gate 			 * good deal less simple than E-format.
15120Sstevel@tonic-gate 			 * The overall strategy will be to call
15130Sstevel@tonic-gate 			 * fconvert, reformat its result into buf,
15140Sstevel@tonic-gate 			 * and calculate how many trailing
15150Sstevel@tonic-gate 			 * zeroes will be required.  There will
15160Sstevel@tonic-gate 			 * never be any leading zeroes needed.
15170Sstevel@tonic-gate 			 * (qfconvert for long double)
15180Sstevel@tonic-gate 			 */
15190Sstevel@tonic-gate 
15200Sstevel@tonic-gate 			/* Establish default precision */
15210Sstevel@tonic-gate 			if (!(flagword & DOTSEEN))
15220Sstevel@tonic-gate 				prec = 6;
15230Sstevel@tonic-gate 
15240Sstevel@tonic-gate 			if (flagword & QUAD) {	/* long double */
15250Sstevel@tonic-gate 				long double	qval = GETQVAL(args.ap);
15260Sstevel@tonic-gate 
15270Sstevel@tonic-gate 				FPCONV(qfconvert, &qval, min(prec, MAXFCVT),
15280Sstevel@tonic-gate 				    &decpt, &sign, cvtbuf);
15290Sstevel@tonic-gate 				bp = cvtbuf;
15300Sstevel@tonic-gate 				if (*bp == 0) {
15310Sstevel@tonic-gate 					/*
15320Sstevel@tonic-gate 					 * qfconvert would have required
15330Sstevel@tonic-gate 					 * too many characters; use qeconvert
15340Sstevel@tonic-gate 					 * instead
15350Sstevel@tonic-gate 					 */
15360Sstevel@tonic-gate 					FPCONV(qeconvert, &qval,
15370Sstevel@tonic-gate 					    min(prec + 1, MAXECVT), &decpt,
15380Sstevel@tonic-gate 					    &sign, cvtbuf);
15390Sstevel@tonic-gate 					goto e_merge;
15400Sstevel@tonic-gate 				}
15410Sstevel@tonic-gate 			} else {	/* double */
15420Sstevel@tonic-gate 				double	dval = va_arg(args.ap, double);
15430Sstevel@tonic-gate 
15440Sstevel@tonic-gate 				FPCONV(fconvert, dval, min(prec, MAXFCVT),
15450Sstevel@tonic-gate 				    &decpt, &sign, cvtbuf);
15460Sstevel@tonic-gate 			}
15470Sstevel@tonic-gate 			bp = cvtbuf;
15480Sstevel@tonic-gate 			if (*bp > '9') {
15490Sstevel@tonic-gate 				inf_nan = 1;
15500Sstevel@tonic-gate 				if (fcode == 'f')
15510Sstevel@tonic-gate 					inf_nan_mixed_case = (__xpg6 &
15520Sstevel@tonic-gate 					    _C99SUSv3_mixed_case_Inf_and_NaN);
15530Sstevel@tonic-gate 				break;
15540Sstevel@tonic-gate 			}
15550Sstevel@tonic-gate 
15560Sstevel@tonic-gate 			/* Determine the prefix */
15570Sstevel@tonic-gate 		f_merge:
15580Sstevel@tonic-gate 			if (sign) {
15590Sstevel@tonic-gate 				prefix = _P_HYPHEN;
15600Sstevel@tonic-gate 				prefixlength = 1;
15610Sstevel@tonic-gate 			} else if (flagword & FPLUS) {
15620Sstevel@tonic-gate 				prefix = _P_PLUS;
15630Sstevel@tonic-gate 				prefixlength = 1;
15640Sstevel@tonic-gate 			} else if (flagword & FBLANK) {
15650Sstevel@tonic-gate 				prefix = _P_BLANK;
15660Sstevel@tonic-gate 				prefixlength = 1;
15670Sstevel@tonic-gate 			}
15680Sstevel@tonic-gate 
15690Sstevel@tonic-gate 			/* Initialize buffer pointer */
15700Sstevel@tonic-gate 			p = &buf[0];
15710Sstevel@tonic-gate 
15720Sstevel@tonic-gate 			{
15730Sstevel@tonic-gate 				ssize_t nn = decpt;
15740Sstevel@tonic-gate 
15750Sstevel@tonic-gate 				/* Emit the digits before the decimal point */
15760Sstevel@tonic-gate 				k = 0;
15770Sstevel@tonic-gate 				do {
15780Sstevel@tonic-gate 					*p++ = (nn <= 0 || *bp == '\0' || \
15790Sstevel@tonic-gate 					    k >= MAXFSIG) ? '0' : (k++, *bp++);
15800Sstevel@tonic-gate 				} while (--nn > 0);
15810Sstevel@tonic-gate 
15820Sstevel@tonic-gate 				if (quote)
15830Sstevel@tonic-gate 					p = insert_thousands_sep(buf, p);
15840Sstevel@tonic-gate 
15850Sstevel@tonic-gate 				/* Decide whether we need a decimal point */
15860Sstevel@tonic-gate 				if ((flagword & FSHARP) || prec > 0)
15870Sstevel@tonic-gate 					*p++ = _numeric[0];
15880Sstevel@tonic-gate 
15890Sstevel@tonic-gate 				/* Digits (if any) after the decimal point */
15900Sstevel@tonic-gate 				nn = min(prec, MAXFCVT);
15910Sstevel@tonic-gate 				if (prec > nn) {
15920Sstevel@tonic-gate 					flagword |= RZERO;
15930Sstevel@tonic-gate 					otherlength = rzero = prec - nn;
15940Sstevel@tonic-gate 				}
15950Sstevel@tonic-gate 				while (--nn >= 0)
15960Sstevel@tonic-gate 					*p++ = (++decpt <= 0 || *bp == '\0' || \
15970Sstevel@tonic-gate 					    k >= MAXFSIG) ? '0' : (k++, *bp++);
15980Sstevel@tonic-gate 			}
15990Sstevel@tonic-gate 
16000Sstevel@tonic-gate 			bp = &buf[0];
16010Sstevel@tonic-gate 
16020Sstevel@tonic-gate 			break;
16030Sstevel@tonic-gate 
16040Sstevel@tonic-gate 		case 'G':
16050Sstevel@tonic-gate 		case 'g':
16060Sstevel@tonic-gate 			/*
16070Sstevel@tonic-gate 			 * g-format.  We play around a bit
16080Sstevel@tonic-gate 			 * and then jump into e or f, as needed.
16090Sstevel@tonic-gate 			 */
16100Sstevel@tonic-gate 
16110Sstevel@tonic-gate 			/* Establish default precision */
16120Sstevel@tonic-gate 			if (!(flagword & DOTSEEN))
16130Sstevel@tonic-gate 				prec = 6;
16140Sstevel@tonic-gate 			else if (prec == 0)
16150Sstevel@tonic-gate 				prec = 1;
16160Sstevel@tonic-gate 
16170Sstevel@tonic-gate 			if (flagword & QUAD) {	/* long double */
16180Sstevel@tonic-gate 				long double	qval = GETQVAL(args.ap);
16190Sstevel@tonic-gate 
16200Sstevel@tonic-gate 				FPCONV(qeconvert, &qval, min(prec, MAXECVT),
16210Sstevel@tonic-gate 				    &decpt, &sign, cvtbuf);
16220Sstevel@tonic-gate 			} else {	/* double */
16230Sstevel@tonic-gate 				double	dval = va_arg(args.ap, double);
16240Sstevel@tonic-gate 
16250Sstevel@tonic-gate 				FPCONV(econvert, dval, min(prec, MAXECVT),
16260Sstevel@tonic-gate 				    &decpt, &sign, cvtbuf);
16270Sstevel@tonic-gate 			}
16280Sstevel@tonic-gate 			bp = cvtbuf;
16290Sstevel@tonic-gate 			if (*bp > '9') {
16300Sstevel@tonic-gate 				inf_nan = 1;
16310Sstevel@tonic-gate 				inf_nan_mixed_case = (__xpg6 &
16320Sstevel@tonic-gate 				    _C99SUSv3_mixed_case_Inf_and_NaN);
16330Sstevel@tonic-gate 				break;
16340Sstevel@tonic-gate 			}
16350Sstevel@tonic-gate 			if (*bp == '0')	/* the value converted is zero */
16360Sstevel@tonic-gate 				decpt = 1;
16370Sstevel@tonic-gate 
16380Sstevel@tonic-gate 			{
16390Sstevel@tonic-gate 				int kk = prec;
16400Sstevel@tonic-gate 				if (!(flagword & FSHARP)) {
16410Sstevel@tonic-gate #ifdef	_WIDE
16420Sstevel@tonic-gate 					n = wcslen(bp);
16430Sstevel@tonic-gate #else  /* _WIDE */
16440Sstevel@tonic-gate 					n = strlen(bp);
16450Sstevel@tonic-gate #endif /* _WIDE */
16460Sstevel@tonic-gate 					if (n < kk)
16470Sstevel@tonic-gate 						kk = (int)n;
16480Sstevel@tonic-gate 					while (kk >= 1 && bp[kk-1] == '0')
16490Sstevel@tonic-gate 						--kk;
16500Sstevel@tonic-gate 				}
16510Sstevel@tonic-gate 				if (decpt < -3 || decpt > prec) {
16520Sstevel@tonic-gate 					prec = kk - 1;
16530Sstevel@tonic-gate 					goto e_merge;
16540Sstevel@tonic-gate 				}
16550Sstevel@tonic-gate 				prec = kk - decpt;
16560Sstevel@tonic-gate 				goto f_merge;
16570Sstevel@tonic-gate 			}
16580Sstevel@tonic-gate 
16590Sstevel@tonic-gate 		case '%':
16600Sstevel@tonic-gate 			buf[0] = fcode;
16610Sstevel@tonic-gate 			goto c_merge;
16620Sstevel@tonic-gate 
16630Sstevel@tonic-gate #ifndef	_WIDE
16640Sstevel@tonic-gate 		case 'w':
16650Sstevel@tonic-gate 			wflag = 1;
16660Sstevel@tonic-gate 			goto charswitch;
16670Sstevel@tonic-gate #endif /* _WIDE */
16680Sstevel@tonic-gate 
16690Sstevel@tonic-gate 
16700Sstevel@tonic-gate 		case 'C': /* XPG XSH4 extention */
16710Sstevel@tonic-gate wide_C:
16720Sstevel@tonic-gate 			{
16730Sstevel@tonic-gate 				wchar_t	temp;
16740Sstevel@tonic-gate 
16750Sstevel@tonic-gate 				temp = va_arg(args.ap, wchar_t);
16760Sstevel@tonic-gate #ifdef	_WIDE
16770Sstevel@tonic-gate 				if (temp) {
16780Sstevel@tonic-gate 					buf[0] = temp;
16790Sstevel@tonic-gate 					p = (bp = buf) + 1;
16800Sstevel@tonic-gate 				} else {
16810Sstevel@tonic-gate 					buf[0] = 0;
16820Sstevel@tonic-gate 					p = (bp = buf) + 1;
16830Sstevel@tonic-gate 				}
16840Sstevel@tonic-gate 				wcount = 1;
16850Sstevel@tonic-gate 				wflag = 1;
16860Sstevel@tonic-gate #else  /* _WIDE */
16870Sstevel@tonic-gate 				if (temp) {
16880Sstevel@tonic-gate 					if ((retcode = wctomb(buf, temp))
16890Sstevel@tonic-gate 						== -1) {
16900Sstevel@tonic-gate 						errno = EILSEQ;
16910Sstevel@tonic-gate 						return (EOF);
16920Sstevel@tonic-gate 					} else {
16930Sstevel@tonic-gate 						p = (bp = buf) + retcode;
16940Sstevel@tonic-gate 					}
16950Sstevel@tonic-gate 				} else { /* NULL character */
16960Sstevel@tonic-gate 					buf[0] = 0;
16970Sstevel@tonic-gate 					p = (bp = buf) + 1;
16980Sstevel@tonic-gate 				}
16990Sstevel@tonic-gate 				wcount = p - bp;
17000Sstevel@tonic-gate #endif /* _WIDE */
17010Sstevel@tonic-gate 			}
17020Sstevel@tonic-gate 			break;
17030Sstevel@tonic-gate 		case 'c':
17040Sstevel@tonic-gate 			if (lflag) {
17050Sstevel@tonic-gate 				goto wide_C;
17060Sstevel@tonic-gate 			}
17070Sstevel@tonic-gate #ifndef	_WIDE
17080Sstevel@tonic-gate 			if (wflag) {
17090Sstevel@tonic-gate 				wchar_t	temp;
17100Sstevel@tonic-gate 
17110Sstevel@tonic-gate 				temp = va_arg(args.ap, wchar_t);
17120Sstevel@tonic-gate 				if (temp) {
17130Sstevel@tonic-gate 					if ((retcode = wctomb(buf, temp))
17140Sstevel@tonic-gate 						== -1) {
17150Sstevel@tonic-gate 						p = (bp = buf) + 1;
17160Sstevel@tonic-gate 					} else {
17170Sstevel@tonic-gate 						p = (bp = buf) + retcode;
17180Sstevel@tonic-gate 					}
17190Sstevel@tonic-gate 				} else { /* NULL character */
17200Sstevel@tonic-gate 					buf[0] = 0;
17210Sstevel@tonic-gate 					p = (bp = buf) + 1;
17220Sstevel@tonic-gate 				}
17230Sstevel@tonic-gate 				wcount = p - bp;
17240Sstevel@tonic-gate 			} else {
17250Sstevel@tonic-gate #endif /* _WIDE */
17260Sstevel@tonic-gate 				if (flagword & XLONG) {
17270Sstevel@tonic-gate 					long long temp;
17280Sstevel@tonic-gate 					temp = va_arg(args.ap, long long);
17290Sstevel@tonic-gate #ifdef	_WIDE
17300Sstevel@tonic-gate 					buf[0] = (wchar_t)temp;
17310Sstevel@tonic-gate #else  /* _WIDE */
17320Sstevel@tonic-gate 					buf[0] = (char)temp;
17330Sstevel@tonic-gate #endif /* _WIDE */
17340Sstevel@tonic-gate 				} else
17350Sstevel@tonic-gate 					buf[0] = va_arg(args.ap, int);
17360Sstevel@tonic-gate 			c_merge:
17370Sstevel@tonic-gate 				p = (bp = &buf[0]) + 1;
17380Sstevel@tonic-gate #ifdef	_WIDE
17390Sstevel@tonic-gate 				wcount = 1;
17400Sstevel@tonic-gate 				wflag = 1;
17410Sstevel@tonic-gate #endif /* _WIDE */
17420Sstevel@tonic-gate #ifndef	_WIDE
17430Sstevel@tonic-gate 			}
17440Sstevel@tonic-gate #endif /* _WIDE */
17450Sstevel@tonic-gate 			break;
17460Sstevel@tonic-gate 
17470Sstevel@tonic-gate 		case 'S': /* XPG XSH4 extention */
17480Sstevel@tonic-gate wide_S:
17490Sstevel@tonic-gate #ifdef	_WIDE
17500Sstevel@tonic-gate 			if (!lflag) {
17510Sstevel@tonic-gate 				lflag++;
17520Sstevel@tonic-gate 			}
17530Sstevel@tonic-gate 			bp = va_arg(args.ap, wchar_t *);
1754*9959SDarren.Moffat@Sun.COM 			if (bp == NULL)
1755*9959SDarren.Moffat@Sun.COM 				bp = (wchar_t *)widenullstr;
17560Sstevel@tonic-gate 			if (!(flagword & DOTSEEN)) {
17570Sstevel@tonic-gate 				/* wide character handling */
17580Sstevel@tonic-gate 				prec = MAXINT;
17590Sstevel@tonic-gate 			}
17600Sstevel@tonic-gate 
17610Sstevel@tonic-gate 			wp = bp;
17620Sstevel@tonic-gate 			wcount = 0;
17630Sstevel@tonic-gate 			while (*wp) {
17640Sstevel@tonic-gate 				if ((prec - wcount - 1) >= 0) {
17650Sstevel@tonic-gate 					wcount++;
17660Sstevel@tonic-gate 					wp++;
17670Sstevel@tonic-gate 				} else {
17680Sstevel@tonic-gate 					break;
17690Sstevel@tonic-gate 				}
17700Sstevel@tonic-gate 			}
17710Sstevel@tonic-gate 			p = wp;
17720Sstevel@tonic-gate 			wflag = 1;
17730Sstevel@tonic-gate 			break;
17740Sstevel@tonic-gate #else  /* _WIDE */
17750Sstevel@tonic-gate 			if (!wflag)
17760Sstevel@tonic-gate 				wflag++;
17770Sstevel@tonic-gate 			bp = va_arg(args.ap, char *);
1778*9959SDarren.Moffat@Sun.COM 			if (bp == NULL)
1779*9959SDarren.Moffat@Sun.COM 				bp = (char *)widenullstr;
17800Sstevel@tonic-gate 			if (!(flagword & DOTSEEN)) {
17810Sstevel@tonic-gate 				/* wide character handling */
17820Sstevel@tonic-gate 				prec = MAXINT;
17830Sstevel@tonic-gate 			}
17840Sstevel@tonic-gate 
17850Sstevel@tonic-gate 			wp = (wchar_t *)(uintptr_t)bp;
17860Sstevel@tonic-gate 			wcount = 0;
17870Sstevel@tonic-gate 			while (*wp) {
17880Sstevel@tonic-gate 				int nbytes;
17890Sstevel@tonic-gate 
17900Sstevel@tonic-gate 				nbytes = wctomb(tmpbuf, *wp);
17910Sstevel@tonic-gate 				if (nbytes < 0) {
17920Sstevel@tonic-gate 					errno = EILSEQ;
17930Sstevel@tonic-gate 					return (EOF);
17940Sstevel@tonic-gate 				}
17950Sstevel@tonic-gate 				if ((prec - (wcount + nbytes)) >= 0) {
17960Sstevel@tonic-gate 					wcount += nbytes;
17970Sstevel@tonic-gate 					wp++;
17980Sstevel@tonic-gate 				} else {
17990Sstevel@tonic-gate 					break;
18000Sstevel@tonic-gate 				}
18010Sstevel@tonic-gate 			}
18020Sstevel@tonic-gate 			sec_display = wcount;
18030Sstevel@tonic-gate 			p = (char *)wp;
18040Sstevel@tonic-gate 			break;
18050Sstevel@tonic-gate #endif /* _WIDE */
18060Sstevel@tonic-gate 		case 's':
18070Sstevel@tonic-gate 			if (lflag) {
18080Sstevel@tonic-gate 				goto wide_S;
18090Sstevel@tonic-gate 			}
18100Sstevel@tonic-gate #ifdef	_WIDE
18110Sstevel@tonic-gate 			cbp = va_arg(args.ap, char *);
1812*9959SDarren.Moffat@Sun.COM 			if (cbp == NULL)
1813*9959SDarren.Moffat@Sun.COM 				cbp = (char *)nullstr;
18140Sstevel@tonic-gate 			if (!(flagword & DOTSEEN)) {
18150Sstevel@tonic-gate 				size_t	nwc;
18160Sstevel@tonic-gate 				wchar_t	*wstr;
18170Sstevel@tonic-gate 
18180Sstevel@tonic-gate 				nwc = mbstowcs(NULL, cbp, 0);
18190Sstevel@tonic-gate 				if (nwc == (size_t)-1) {
18200Sstevel@tonic-gate 					errno = EILSEQ;
18210Sstevel@tonic-gate 					return (EOF);
18220Sstevel@tonic-gate 				}
18230Sstevel@tonic-gate 				bpsize = sizeof (wchar_t) * (nwc + 1);
18240Sstevel@tonic-gate 				wstr = (wchar_t *)lmalloc(bpsize);
18250Sstevel@tonic-gate 				if (wstr == NULL) {
18260Sstevel@tonic-gate 					errno = EILSEQ;
18270Sstevel@tonic-gate 					return (EOF);
18280Sstevel@tonic-gate 				}
18290Sstevel@tonic-gate 				nwc = mbstowcs(wstr, cbp, MAXINT);
18300Sstevel@tonic-gate 				wcount = nwc;
18310Sstevel@tonic-gate 				bp = wstr;
18320Sstevel@tonic-gate 				p = wstr + nwc;
18330Sstevel@tonic-gate 			} else {
18340Sstevel@tonic-gate 				size_t	nwc;
18350Sstevel@tonic-gate 				wchar_t	*wstr;
18360Sstevel@tonic-gate 
18370Sstevel@tonic-gate 				nwc = mbstowcs(NULL, cbp, 0);
18380Sstevel@tonic-gate 				if (nwc == (size_t)-1) {
18390Sstevel@tonic-gate 					errno = EILSEQ;
18400Sstevel@tonic-gate 					return (EOF);
18410Sstevel@tonic-gate 				}
18420Sstevel@tonic-gate 				if (prec > nwc) {
18430Sstevel@tonic-gate 					bpsize = sizeof (wchar_t) * nwc;
18440Sstevel@tonic-gate 					wstr = (wchar_t *)lmalloc(bpsize);
18450Sstevel@tonic-gate 					if (wstr == NULL) {
18460Sstevel@tonic-gate 						errno = ENOMEM;
18470Sstevel@tonic-gate 						return (EOF);
18480Sstevel@tonic-gate 					}
18490Sstevel@tonic-gate 					nwc = mbstowcs(wstr, cbp, nwc);
18500Sstevel@tonic-gate 					cp = cbp + strlen(cbp);
18510Sstevel@tonic-gate 					wcount = nwc;
18520Sstevel@tonic-gate 					bp = wstr;
18530Sstevel@tonic-gate 					p = wstr + nwc;
18540Sstevel@tonic-gate 				} else {
18550Sstevel@tonic-gate 					size_t	nnwc;
18560Sstevel@tonic-gate 					int	len;
18570Sstevel@tonic-gate 					char	*s;
18580Sstevel@tonic-gate 					wchar_t	*wstr;
18590Sstevel@tonic-gate 
18600Sstevel@tonic-gate 					bpsize = sizeof (wchar_t) * prec;
18610Sstevel@tonic-gate 					wstr = (wchar_t *)lmalloc(bpsize);
18620Sstevel@tonic-gate 					if (wstr == NULL) {
18630Sstevel@tonic-gate 						errno = ENOMEM;
18640Sstevel@tonic-gate 						return (EOF);
18650Sstevel@tonic-gate 					}
18660Sstevel@tonic-gate 					nwc = mbstowcs(wstr, cbp, prec);
18670Sstevel@tonic-gate 					wcount = prec;
18680Sstevel@tonic-gate 					bp = wstr;
18690Sstevel@tonic-gate 					p = wstr + nwc;
18700Sstevel@tonic-gate 				}
18710Sstevel@tonic-gate 			}
18720Sstevel@tonic-gate 			wflag = 1;
18730Sstevel@tonic-gate #else  /* _WIDE */
18740Sstevel@tonic-gate 			bp = va_arg(args.ap, char *);
1875*9959SDarren.Moffat@Sun.COM 			if (bp == NULL)
1876*9959SDarren.Moffat@Sun.COM 				bp = (char *)nullstr;
18770Sstevel@tonic-gate 			if (!(flagword & DOTSEEN)) {
18780Sstevel@tonic-gate 				if (wflag) {
18790Sstevel@tonic-gate 					/* wide character handling */
18800Sstevel@tonic-gate 					prec = MAXINT;
18810Sstevel@tonic-gate 					goto wide_hand;
18820Sstevel@tonic-gate 				}
18830Sstevel@tonic-gate 
18840Sstevel@tonic-gate 
18850Sstevel@tonic-gate 				p = bp + strlen(bp);
18860Sstevel@tonic-gate 
18870Sstevel@tonic-gate 				/*
18880Sstevel@tonic-gate 				 * sec_display only needed if width
18890Sstevel@tonic-gate 				 * is specified (ie, "%<width>s")
18900Sstevel@tonic-gate 				 * Solaris behavior counts <width> in
18910Sstevel@tonic-gate 				 * screen column width.  (If XPG4 behavior,
18920Sstevel@tonic-gate 				 * <width> is counted in bytes.)
18930Sstevel@tonic-gate 				 */
18940Sstevel@tonic-gate 				if (width > 0 && __xpg4 == 0 &&
18950Sstevel@tonic-gate 				    MB_CUR_MAX > 1) {
18960Sstevel@tonic-gate #define	NW	256
18970Sstevel@tonic-gate 					wchar_t wbuff[NW];
18980Sstevel@tonic-gate 					wchar_t *wp, *wptr;
18990Sstevel@tonic-gate 					size_t wpsize;
19000Sstevel@tonic-gate 					size_t nwc;
19010Sstevel@tonic-gate 
19020Sstevel@tonic-gate 					wp = NULL;
19030Sstevel@tonic-gate 					if ((nwc = mbstowcs(wbuff, bp,
19040Sstevel@tonic-gate 					    NW)) == (size_t)-1) {
19050Sstevel@tonic-gate 						/* Estimate width */
19060Sstevel@tonic-gate 						sec_display = strlen(bp);
19070Sstevel@tonic-gate 						goto mbs_err;
19080Sstevel@tonic-gate 					}
19090Sstevel@tonic-gate 					if (nwc < NW) {
19100Sstevel@tonic-gate 						wptr = wbuff;
19110Sstevel@tonic-gate 					} else {
19120Sstevel@tonic-gate 						/*
19130Sstevel@tonic-gate 						 * If widechar does not fit into
19140Sstevel@tonic-gate 						 * wbuff, allocate larger buffer
19150Sstevel@tonic-gate 						 */
19160Sstevel@tonic-gate 						if ((nwc =
19170Sstevel@tonic-gate 						    mbstowcs(NULL, bp, NULL)) ==
19180Sstevel@tonic-gate 						    (size_t)-1) {
19190Sstevel@tonic-gate 							sec_display =
19200Sstevel@tonic-gate 							    strlen(bp);
19210Sstevel@tonic-gate 							goto mbs_err;
19220Sstevel@tonic-gate 						}
19230Sstevel@tonic-gate 						wpsize = (nwc + 1) *
19240Sstevel@tonic-gate 						    sizeof (wchar_t);
19250Sstevel@tonic-gate 						if ((wp = lmalloc(wpsize))
19260Sstevel@tonic-gate 						    == NULL) {
19270Sstevel@tonic-gate 							errno = ENOMEM;
19280Sstevel@tonic-gate 							return (EOF);
19290Sstevel@tonic-gate 						}
19300Sstevel@tonic-gate 						if ((nwc = mbstowcs(wp,
19310Sstevel@tonic-gate 						    bp, nwc)) == (size_t)-1) {
19320Sstevel@tonic-gate 							sec_display = \
19330Sstevel@tonic-gate 							    strlen(bp);
19340Sstevel@tonic-gate 							goto mbs_err;
19350Sstevel@tonic-gate 						}
19360Sstevel@tonic-gate 						wptr = wp;
19370Sstevel@tonic-gate 					}
19380Sstevel@tonic-gate 					if ((sec_display = wcswidth(wptr, nwc))
19390Sstevel@tonic-gate 					    == -1) {
19400Sstevel@tonic-gate 						sec_display =
19410Sstevel@tonic-gate 							_rec_scrswidth
19420Sstevel@tonic-gate 								(wptr, nwc);
19430Sstevel@tonic-gate 					}
19440Sstevel@tonic-gate 				mbs_err:
19450Sstevel@tonic-gate 					if (wp)
19460Sstevel@tonic-gate 						lfree(wp, wpsize);
19470Sstevel@tonic-gate 				}
19480Sstevel@tonic-gate 			} else { /* a strnlen function would be useful here! */
19490Sstevel@tonic-gate 				/*
19500Sstevel@tonic-gate 				 * If we've seen a dot, and count has been set
19510Sstevel@tonic-gate 				 * to 0, then we don't output in any cases
19520Sstevel@tonic-gate 				 * below. prec should be always >= 0. So we only
19530Sstevel@tonic-gate 				 * check to see if it's zero.
19540Sstevel@tonic-gate 				 */
19550Sstevel@tonic-gate 				if (prec == 0) {
19560Sstevel@tonic-gate 					p = bp;
19570Sstevel@tonic-gate 					break;
19580Sstevel@tonic-gate 				}
19590Sstevel@tonic-gate 
19600Sstevel@tonic-gate 				if (wflag) {
19610Sstevel@tonic-gate 					/* wide character handling */
19620Sstevel@tonic-gate 
19630Sstevel@tonic-gate 				wide_hand:
19640Sstevel@tonic-gate 					wp = (wchar_t *)(uintptr_t)bp;
19650Sstevel@tonic-gate 					preco = prec;
19660Sstevel@tonic-gate 					wcount = 0;
19670Sstevel@tonic-gate 					while (*wp &&
19680Sstevel@tonic-gate 					    (prec -= _scrwidth(*wp)) >= 0) {
19690Sstevel@tonic-gate 						if ((retcode =
19700Sstevel@tonic-gate 						    wctomb(tmpbuf, *wp)) < 0)
19710Sstevel@tonic-gate 							wcount++;
19720Sstevel@tonic-gate 						else
19730Sstevel@tonic-gate 							wcount += retcode;
19740Sstevel@tonic-gate 						wp++;
19750Sstevel@tonic-gate 					}
19760Sstevel@tonic-gate 					if (*wp)
19770Sstevel@tonic-gate 						prec += _scrwidth(*wp);
19780Sstevel@tonic-gate 					p = (char *)wp;
19790Sstevel@tonic-gate 					sec_display = preco - prec;
19800Sstevel@tonic-gate 				} else if (__xpg4 == 0 && MB_CUR_MAX > 1) {
19810Sstevel@tonic-gate 					/*
19820Sstevel@tonic-gate 					 * Solaris behavior - count
19830Sstevel@tonic-gate 					 * precision as screen column width
19840Sstevel@tonic-gate 					 */
19850Sstevel@tonic-gate 					char *qp = bp;
19860Sstevel@tonic-gate 					int ncol, nbytes;
19870Sstevel@tonic-gate 					wchar_t wc;
19880Sstevel@tonic-gate 
19890Sstevel@tonic-gate 					ncol = 0;
19900Sstevel@tonic-gate 					preco = prec;
19910Sstevel@tonic-gate 					while (*qp) {
19920Sstevel@tonic-gate 						if (isascii(*qp)) {
19930Sstevel@tonic-gate 							qp++;
19940Sstevel@tonic-gate 							if (--prec == 0)
19950Sstevel@tonic-gate 								break;
19960Sstevel@tonic-gate 							continue;
19970Sstevel@tonic-gate 						}
19980Sstevel@tonic-gate 						if ((nbytes = mbtowc(&wc, qp,
19990Sstevel@tonic-gate 							MB_LEN_MAX)) == -1) {
20000Sstevel@tonic-gate 							/* print illegal char */
20010Sstevel@tonic-gate 							nbytes = 1;
20020Sstevel@tonic-gate 							ncol = 1;
20030Sstevel@tonic-gate 						} else {
20040Sstevel@tonic-gate 							if ((ncol =
20050Sstevel@tonic-gate 							_scrwidth(wc))
20060Sstevel@tonic-gate 								== 0) {
20070Sstevel@tonic-gate 								ncol = 1;
20080Sstevel@tonic-gate 							}
20090Sstevel@tonic-gate 						}
20100Sstevel@tonic-gate 
20110Sstevel@tonic-gate 						if ((prec -= ncol) >= 0) {
20120Sstevel@tonic-gate 							qp += nbytes;
20130Sstevel@tonic-gate 							if (prec == 0)
20140Sstevel@tonic-gate 								break;
20150Sstevel@tonic-gate 						} else {
20160Sstevel@tonic-gate 							break;
20170Sstevel@tonic-gate 						}
20180Sstevel@tonic-gate 					}
20190Sstevel@tonic-gate 					if (prec < 0)
20200Sstevel@tonic-gate 						prec += ncol;
20210Sstevel@tonic-gate 					p = qp;
20220Sstevel@tonic-gate 					sec_display = preco - prec;
20230Sstevel@tonic-gate 				} else {
20240Sstevel@tonic-gate 					/*
20250Sstevel@tonic-gate 					 * XPG4 behavior - count
20260Sstevel@tonic-gate 					 * precision as bytes.
20270Sstevel@tonic-gate 					 * We don't use strlen() because
20280Sstevel@tonic-gate 					 * the given char string may not
20290Sstevel@tonic-gate 					 * be null-terminated.
20300Sstevel@tonic-gate 					 */
20310Sstevel@tonic-gate 					char *qp;
20320Sstevel@tonic-gate 
20330Sstevel@tonic-gate 					qp = memchr(bp, '\0', prec);
20340Sstevel@tonic-gate 					if (qp == NULL) {
20350Sstevel@tonic-gate 						p = bp + prec;
20360Sstevel@tonic-gate 					} else {
20370Sstevel@tonic-gate 						p = qp;
20380Sstevel@tonic-gate 					}
20390Sstevel@tonic-gate 				}
20400Sstevel@tonic-gate 			}
20410Sstevel@tonic-gate #endif /* _WIDE */
20420Sstevel@tonic-gate 			break;
20430Sstevel@tonic-gate 
20440Sstevel@tonic-gate 		case 'n':
20450Sstevel@tonic-gate 			{
20460Sstevel@tonic-gate 			if (flagword & XLONG) {
20470Sstevel@tonic-gate 				long long *svcount;
20480Sstevel@tonic-gate 				svcount = va_arg(args.ap, long long *);
20490Sstevel@tonic-gate 				*svcount = (long long)count;
20500Sstevel@tonic-gate 			} else if (flagword & LENGTH) {
20510Sstevel@tonic-gate 				long *svcount;
20520Sstevel@tonic-gate 				svcount = va_arg(args.ap, long *);
20530Sstevel@tonic-gate 				*svcount = (long)count;
20540Sstevel@tonic-gate 			} else if (flagword & SHORT) {
20550Sstevel@tonic-gate 				short *svcount;
20560Sstevel@tonic-gate 				svcount = va_arg(args.ap, short *);
20570Sstevel@tonic-gate 				*svcount = (short)count;
20580Sstevel@tonic-gate 			} else if (flagword & CHAR) {
20590Sstevel@tonic-gate 				char *svcount;
20600Sstevel@tonic-gate 				svcount = va_arg(args.ap, char *);
20610Sstevel@tonic-gate 				*svcount = (char)count;
20620Sstevel@tonic-gate 			} else {
20630Sstevel@tonic-gate 				int *svcount;
20640Sstevel@tonic-gate 				svcount = va_arg(args.ap, int *);
20650Sstevel@tonic-gate 				*svcount = count;
20660Sstevel@tonic-gate 			}
20670Sstevel@tonic-gate 			continue;
20680Sstevel@tonic-gate 		}
20690Sstevel@tonic-gate 		default: /* this is technically an error; what we do is to */
20700Sstevel@tonic-gate 			/* back up the format pointer to the offending char */
20710Sstevel@tonic-gate 			/* and continue with the format scan */
20720Sstevel@tonic-gate 			format--;
20730Sstevel@tonic-gate 			continue;
20740Sstevel@tonic-gate 		}
20750Sstevel@tonic-gate 
20760Sstevel@tonic-gate 		if (inf_nan) {
20770Sstevel@tonic-gate 			if (inf_nan_mixed_case) {
20780Sstevel@tonic-gate 				/* advance p */
20790Sstevel@tonic-gate 				for (p = bp + 1; *p != '\0'; p++)
20800Sstevel@tonic-gate 					;
20810Sstevel@tonic-gate 			} else {
20820Sstevel@tonic-gate 				int upper;
20830Sstevel@tonic-gate 
20840Sstevel@tonic-gate 				/* advance p and make output all one case */
20850Sstevel@tonic-gate 				upper = _M_ISUPPER(fcode);
20860Sstevel@tonic-gate 				for (p = bp; *p != '\0'; p++)
20870Sstevel@tonic-gate 					*p = upper? toupper(*p) : tolower(*p);
20880Sstevel@tonic-gate 			}
20890Sstevel@tonic-gate 			if (sign) {
20900Sstevel@tonic-gate 				prefix = _P_HYPHEN;
20910Sstevel@tonic-gate 				prefixlength = 1;
20920Sstevel@tonic-gate 			} else if (flagword & FPLUS) {
20930Sstevel@tonic-gate 				prefix = _P_PLUS;
20940Sstevel@tonic-gate 				prefixlength = 1;
20950Sstevel@tonic-gate 			} else if (flagword & FBLANK) {
20960Sstevel@tonic-gate 				prefix = _P_BLANK;
20970Sstevel@tonic-gate 				prefixlength = 1;
20980Sstevel@tonic-gate 			}
20990Sstevel@tonic-gate 			inf_nan = 0;
21000Sstevel@tonic-gate 			inf_nan_mixed_case = 0;
21018378SDouglas.Priest@Sun.COM 			flagword &= ~PADZERO; /* ignore 0 flag */
21020Sstevel@tonic-gate 		}
21030Sstevel@tonic-gate 
21040Sstevel@tonic-gate 		/* Calculate number of padding blanks */
21050Sstevel@tonic-gate 		n = p - bp; /* n == size of the converted value (in bytes) */
21060Sstevel@tonic-gate 
21070Sstevel@tonic-gate #ifdef	_WIDE
21080Sstevel@tonic-gate 		k = n;
21090Sstevel@tonic-gate #else  /* _WIDE */
21100Sstevel@tonic-gate 		if (sec_display) /* when format is %s or %ws or %S */
21110Sstevel@tonic-gate 			k = sec_display;
21120Sstevel@tonic-gate 		else
21130Sstevel@tonic-gate 			k = n;
21140Sstevel@tonic-gate #endif /* _WIDE */
21150Sstevel@tonic-gate 		/*
21160Sstevel@tonic-gate 		 * k is the (screen) width or # of bytes of the converted value
21170Sstevel@tonic-gate 		 */
21180Sstevel@tonic-gate 		k += prefixlength + otherlength;
21190Sstevel@tonic-gate 
21200Sstevel@tonic-gate #ifdef	_WIDE
21210Sstevel@tonic-gate 		if (wflag) {
21220Sstevel@tonic-gate 			count += wcount;
21230Sstevel@tonic-gate 		} else {
21240Sstevel@tonic-gate 			count += n;
21250Sstevel@tonic-gate 		}
21260Sstevel@tonic-gate #else  /* _WIDE */
21270Sstevel@tonic-gate 		/*
21280Sstevel@tonic-gate 		 * update count which is the overall size of the output data
21290Sstevel@tonic-gate 		 * and passed to memchr()
21300Sstevel@tonic-gate 		 */
21310Sstevel@tonic-gate 		if (wflag)
21320Sstevel@tonic-gate 			/*
21330Sstevel@tonic-gate 			 * when wflag != 0 (i.e. %ws or %wc), the size of the
21340Sstevel@tonic-gate 			 * converted value is wcount bytes
21350Sstevel@tonic-gate 			 */
21360Sstevel@tonic-gate 			count += wcount;
21370Sstevel@tonic-gate 		else
21380Sstevel@tonic-gate 			/*
21390Sstevel@tonic-gate 			 * when wflag == 0, the size of the converted
21400Sstevel@tonic-gate 			 * value is n (= p-bp) bytes
21410Sstevel@tonic-gate 			 */
21420Sstevel@tonic-gate 			count += n;
21430Sstevel@tonic-gate #endif /* _WIDE */
21440Sstevel@tonic-gate 		count += prefixlength + otherlength;
21450Sstevel@tonic-gate 
21460Sstevel@tonic-gate 		if (width > k) {
21470Sstevel@tonic-gate 			count += (width - k);
21480Sstevel@tonic-gate 			/*
21490Sstevel@tonic-gate 			 * Set up for padding zeroes if requested
21500Sstevel@tonic-gate 			 * Otherwise emit padding blanks unless output is
21510Sstevel@tonic-gate 			 * to be left-justified.
21520Sstevel@tonic-gate 			 */
21530Sstevel@tonic-gate 
21540Sstevel@tonic-gate 			if (flagword & PADZERO) {
21550Sstevel@tonic-gate 				if (!(flagword & LZERO)) {
21560Sstevel@tonic-gate 					flagword |= LZERO;
21570Sstevel@tonic-gate 					lzero = width - k;
21580Sstevel@tonic-gate 				} else
21590Sstevel@tonic-gate 					lzero += width - k;
21600Sstevel@tonic-gate 				k = width; /* cancel padding blanks */
21610Sstevel@tonic-gate 			} else
21620Sstevel@tonic-gate 				/* Blanks on left if required */
21630Sstevel@tonic-gate 				if (!(flagword & FMINUS))
21640Sstevel@tonic-gate 					PAD(_blanks, width - k);
21650Sstevel@tonic-gate 		}
21660Sstevel@tonic-gate 
21670Sstevel@tonic-gate 		/* Prefix, if any */
21680Sstevel@tonic-gate 		if (prefixlength != 0)
21690Sstevel@tonic-gate 			PUT(prefix, prefixlength);
21700Sstevel@tonic-gate 
21710Sstevel@tonic-gate 		/* Zeroes on the left */
21720Sstevel@tonic-gate 		if ((flagword & LZERO)) /* && */
21730Sstevel@tonic-gate 			/* (!(flagword & SHORT) || !(flagword & FMINUS)) */
21740Sstevel@tonic-gate 			PAD(_zeroes, lzero);
21750Sstevel@tonic-gate 
21760Sstevel@tonic-gate #ifdef	_WIDE
21770Sstevel@tonic-gate 		if (n > 0)
21780Sstevel@tonic-gate 			PUT(bp, n);
21790Sstevel@tonic-gate 		if ((fcode == 's') && !lflag) {
21800Sstevel@tonic-gate 			if (bp)
21810Sstevel@tonic-gate 				lfree(bp, bpsize);
21820Sstevel@tonic-gate 		}
21830Sstevel@tonic-gate #else  /* _WIDE */
21840Sstevel@tonic-gate 		/* The value itself */
21850Sstevel@tonic-gate 		if ((fcode == 's' || fcode == 'S') && wflag) {
21860Sstevel@tonic-gate 			/* wide character handling */
21870Sstevel@tonic-gate 			wchar_t *wp = (wchar_t *)(uintptr_t)bp;
21880Sstevel@tonic-gate 			int cnt;
21890Sstevel@tonic-gate 			char *bufp;
21900Sstevel@tonic-gate 			long printn;
21910Sstevel@tonic-gate 			printn = (wchar_t *)(uintptr_t)p -
21920Sstevel@tonic-gate 				(wchar_t *)(uintptr_t)bp;
21930Sstevel@tonic-gate 			bufp = buf;
21940Sstevel@tonic-gate 			while (printn > 0) {
21950Sstevel@tonic-gate 				if ((cnt = wctomb(buf, *wp)) < 0)
21960Sstevel@tonic-gate 					cnt = 1;
21970Sstevel@tonic-gate 			PUT(bufp, cnt);
21980Sstevel@tonic-gate 				wp++;
21990Sstevel@tonic-gate 				printn--;
22000Sstevel@tonic-gate 			}
22010Sstevel@tonic-gate 		} else {	/* non wide character value */
22020Sstevel@tonic-gate 			if (n > 0)
22030Sstevel@tonic-gate 				PUT(bp, n);
22040Sstevel@tonic-gate 		}
22050Sstevel@tonic-gate #endif /* _WIDE */
22060Sstevel@tonic-gate 
22070Sstevel@tonic-gate 		if (flagword & (RZERO | SUFFIX | FMINUS)) {
22080Sstevel@tonic-gate 			/* Zeroes on the right */
22090Sstevel@tonic-gate 			if (flagword & RZERO)
22100Sstevel@tonic-gate 				PAD(_zeroes, rzero);
22110Sstevel@tonic-gate 
22120Sstevel@tonic-gate 			/* The suffix */
22130Sstevel@tonic-gate 			if (flagword & SUFFIX)
22140Sstevel@tonic-gate 				PUT(suffix, suffixlength);
22150Sstevel@tonic-gate 
22160Sstevel@tonic-gate 			/* Blanks on the right if required */
22170Sstevel@tonic-gate 			if (flagword & FMINUS && width > k)
22180Sstevel@tonic-gate 				PAD(_blanks, width - k);
22190Sstevel@tonic-gate 		}
22200Sstevel@tonic-gate 	}
22210Sstevel@tonic-gate }
22220Sstevel@tonic-gate 
22230Sstevel@tonic-gate #ifdef	_WIDE
22240Sstevel@tonic-gate static int
_watoi(wchar_t * fmt)22250Sstevel@tonic-gate _watoi(wchar_t *fmt)
22260Sstevel@tonic-gate {
22270Sstevel@tonic-gate 	int	n = 0;
22280Sstevel@tonic-gate 	wchar_t	ch;
22290Sstevel@tonic-gate 
22300Sstevel@tonic-gate 	ch = *fmt;
22310Sstevel@tonic-gate 	if (_M_ISDIGIT(ch)) {
22320Sstevel@tonic-gate 		n = ch - '0';
22330Sstevel@tonic-gate 		ch = *++fmt;
22340Sstevel@tonic-gate 		while (_M_ISDIGIT(ch)) {
22350Sstevel@tonic-gate 			n *= 10;
22360Sstevel@tonic-gate 			n += ch - '0';
22370Sstevel@tonic-gate 			ch = *++fmt;
22380Sstevel@tonic-gate 		}
22390Sstevel@tonic-gate 	}
22400Sstevel@tonic-gate 	return (n);
22410Sstevel@tonic-gate }
22420Sstevel@tonic-gate #endif /* _WIDE */
22430Sstevel@tonic-gate 
22440Sstevel@tonic-gate /*
22450Sstevel@tonic-gate  * This function initializes arglst, to contain the appropriate va_list values
22460Sstevel@tonic-gate  * for the first MAXARGS arguments.
22470Sstevel@tonic-gate  */
22480Sstevel@tonic-gate 
22490Sstevel@tonic-gate /*
22500Sstevel@tonic-gate  * Type modifier flags:
22510Sstevel@tonic-gate  *  0x01	for long
22520Sstevel@tonic-gate  *  0x02	for int
22530Sstevel@tonic-gate  *  0x04	for long long
22540Sstevel@tonic-gate  *  0x08	for long double
22550Sstevel@tonic-gate  */
22560Sstevel@tonic-gate 
22570Sstevel@tonic-gate #define	FLAG_LONG	0x01
22580Sstevel@tonic-gate #define	FLAG_INT	0x02
22590Sstevel@tonic-gate #define	FLAG_LONG_LONG	0x04
22600Sstevel@tonic-gate #define	FLAG_LONG_DBL	0x08
22610Sstevel@tonic-gate 
22620Sstevel@tonic-gate /* ARGSUSED3 */
22630Sstevel@tonic-gate #ifdef	_WIDE
22640Sstevel@tonic-gate static void
_wmkarglst(wchar_t * fmt,stva_list args,stva_list arglst[],int prflag)22650Sstevel@tonic-gate _wmkarglst(wchar_t *fmt, stva_list args, stva_list arglst[], int prflag)
22660Sstevel@tonic-gate #else  /* _WIDE */
22677632SNick.Todd@Sun.COM static void
22680Sstevel@tonic-gate _mkarglst(char *fmt, stva_list args, stva_list arglst[], int prflag)
22690Sstevel@tonic-gate #endif /* _WIDE */
22700Sstevel@tonic-gate {
22710Sstevel@tonic-gate #ifdef	_WIDE
22720Sstevel@tonic-gate 	static const wchar_t	digits[] = L"01234567890";
22730Sstevel@tonic-gate 	static const wchar_t	skips[] = L"# +-.'0123456789h$";
22740Sstevel@tonic-gate #else  /* _WIDE */
22750Sstevel@tonic-gate 	static const char digits[] = "01234567890";
22760Sstevel@tonic-gate 	static const char skips[] = "# +-.'0123456789h$";
22770Sstevel@tonic-gate #endif /* _WIDE */
22780Sstevel@tonic-gate 	enum types {INT = 1, LONG, CHAR_PTR, DOUBLE, LONG_DOUBLE, VOID_PTR,
22790Sstevel@tonic-gate 		LONG_PTR, INT_PTR, LONG_LONG, LONG_LONG_PTR};
22800Sstevel@tonic-gate 	enum types typelst[MAXARGS], curtype;
22810Sstevel@tonic-gate 	ssize_t n;
22820Sstevel@tonic-gate 	int  maxnum, curargno, flags;
22830Sstevel@tonic-gate 
22840Sstevel@tonic-gate 	/*
22850Sstevel@tonic-gate 	 * Algorithm	1. set all argument types to zero.
22860Sstevel@tonic-gate 	 *		2. walk through fmt putting arg types in typelst[].
22870Sstevel@tonic-gate 	 *		3. walk through args using va_arg(args.ap, typelst[n])
22880Sstevel@tonic-gate 	 *		   and set arglst[] to the appropriate values.
22890Sstevel@tonic-gate 	 * Assumptions:	Cannot use %*$... to specify variable position.
22900Sstevel@tonic-gate 	 */
22910Sstevel@tonic-gate 
22920Sstevel@tonic-gate 	(void) memset((void *) typelst, 0, sizeof (typelst));
22930Sstevel@tonic-gate 	maxnum = -1;
22940Sstevel@tonic-gate 	curargno = 0;
22950Sstevel@tonic-gate 	while ((fmt = STRCHR(fmt, '%')) != 0) {
22960Sstevel@tonic-gate 		fmt++;	/* skip % */
22970Sstevel@tonic-gate 		if (fmt[n = STRSPN(fmt, digits)] == '$') {
22980Sstevel@tonic-gate 			/* convert to zero base */
22990Sstevel@tonic-gate 			curargno = ATOI(fmt) - 1;
23000Sstevel@tonic-gate 			if (curargno < 0)
23010Sstevel@tonic-gate 				continue;
23020Sstevel@tonic-gate 			fmt += n + 1;
23030Sstevel@tonic-gate 		}
23040Sstevel@tonic-gate 		flags = 0;
23050Sstevel@tonic-gate 	again:;
23060Sstevel@tonic-gate 		fmt += STRSPN(fmt, skips);
23070Sstevel@tonic-gate 		switch (*fmt++) {
23080Sstevel@tonic-gate 		case '%':	/* there is no argument! */
23090Sstevel@tonic-gate 			continue;
23100Sstevel@tonic-gate 		case 'l':
23110Sstevel@tonic-gate 			if (flags & (FLAG_LONG | FLAG_LONG_LONG)) {
23120Sstevel@tonic-gate 				flags |= FLAG_LONG_LONG;
23130Sstevel@tonic-gate 				flags &= ~FLAG_LONG;
23140Sstevel@tonic-gate 			} else {
23150Sstevel@tonic-gate 				flags |= FLAG_LONG;
23160Sstevel@tonic-gate 			}
23170Sstevel@tonic-gate 			goto again;
23180Sstevel@tonic-gate 		case 'j':
23190Sstevel@tonic-gate #ifndef _LP64
23200Sstevel@tonic-gate 			/*
23210Sstevel@tonic-gate 			 * *printf_c89() in 32-bit libc uses
23220Sstevel@tonic-gate 			 * 32-bit intmax_t; otherwise intmax_t
23230Sstevel@tonic-gate 			 * is 64-bits.
23240Sstevel@tonic-gate 			 */
23250Sstevel@tonic-gate 			if (!(prflag & _F_INTMAX32)) {
23260Sstevel@tonic-gate #endif
23270Sstevel@tonic-gate 				flags |= FLAG_LONG_LONG;	/* 64-bit */
23280Sstevel@tonic-gate #ifndef _LP64
23290Sstevel@tonic-gate 			}
23300Sstevel@tonic-gate #endif
23310Sstevel@tonic-gate 			goto again;
23320Sstevel@tonic-gate 		case 't':
23330Sstevel@tonic-gate 			flags |= FLAG_LONG;
23340Sstevel@tonic-gate 			goto again;
23350Sstevel@tonic-gate 		case 'z':
23360Sstevel@tonic-gate 			flags |= FLAG_LONG;
23370Sstevel@tonic-gate 			goto again;
23380Sstevel@tonic-gate 		case 'L':
23390Sstevel@tonic-gate 			flags |= FLAG_LONG_DBL;
23400Sstevel@tonic-gate 			goto again;
23410Sstevel@tonic-gate 		case '*':	/* int argument used for value */
23420Sstevel@tonic-gate 			/* check if there is a positional parameter */
23430Sstevel@tonic-gate #ifdef	_WIDE
23440Sstevel@tonic-gate 			if ((*fmt >= 0) && (*fmt < 256) &&
23450Sstevel@tonic-gate 				isdigit(*fmt))
23460Sstevel@tonic-gate #else  /* _WIDE */
23470Sstevel@tonic-gate 			if (isdigit(*fmt))
23480Sstevel@tonic-gate #endif /* _WIDE */
23490Sstevel@tonic-gate 			{
23500Sstevel@tonic-gate 				int	targno;
23510Sstevel@tonic-gate 				targno = ATOI(fmt) - 1;
23520Sstevel@tonic-gate 				fmt += STRSPN(fmt, digits);
23530Sstevel@tonic-gate 				if (*fmt == '$')
23540Sstevel@tonic-gate 					fmt++; /* skip '$' */
23550Sstevel@tonic-gate 				if (targno >= 0 && targno < MAXARGS) {
23560Sstevel@tonic-gate 					typelst[targno] = INT;
23570Sstevel@tonic-gate 					if (maxnum < targno)
23580Sstevel@tonic-gate 						maxnum = targno;
23590Sstevel@tonic-gate 				}
23600Sstevel@tonic-gate 				goto again;
23610Sstevel@tonic-gate 			}
23620Sstevel@tonic-gate 			flags |= FLAG_INT;
23630Sstevel@tonic-gate 			curtype = INT;
23640Sstevel@tonic-gate 			break;
23650Sstevel@tonic-gate 		case 'a':
23660Sstevel@tonic-gate 		case 'A':
23670Sstevel@tonic-gate 		case 'e':
23680Sstevel@tonic-gate 		case 'E':
23690Sstevel@tonic-gate 		case 'f':
23700Sstevel@tonic-gate 		case 'F':
23710Sstevel@tonic-gate 		case 'g':
23720Sstevel@tonic-gate 		case 'G':
23730Sstevel@tonic-gate 			if (flags & FLAG_LONG_DBL)
23740Sstevel@tonic-gate 				curtype = LONG_DOUBLE;
23750Sstevel@tonic-gate 			else
23760Sstevel@tonic-gate 				curtype = DOUBLE;
23770Sstevel@tonic-gate 			break;
23780Sstevel@tonic-gate 		case 's':
23790Sstevel@tonic-gate 			curtype = CHAR_PTR;
23800Sstevel@tonic-gate 			break;
23810Sstevel@tonic-gate 		case 'p':
23820Sstevel@tonic-gate 			curtype = VOID_PTR;
23830Sstevel@tonic-gate 			break;
23840Sstevel@tonic-gate 		case 'n':
23850Sstevel@tonic-gate 			if (flags & FLAG_LONG_LONG)
23860Sstevel@tonic-gate 				curtype = LONG_LONG_PTR;
23870Sstevel@tonic-gate 			else if (flags & FLAG_LONG)
23880Sstevel@tonic-gate 				curtype = LONG_PTR;
23890Sstevel@tonic-gate 			else
23900Sstevel@tonic-gate 				curtype = INT_PTR;
23910Sstevel@tonic-gate 			break;
23920Sstevel@tonic-gate 		default:
23930Sstevel@tonic-gate 			if (flags & FLAG_LONG_LONG)
23940Sstevel@tonic-gate 				curtype = LONG_LONG;
23950Sstevel@tonic-gate 			else if (flags & FLAG_LONG)
23960Sstevel@tonic-gate 				curtype = LONG;
23970Sstevel@tonic-gate 			else
23980Sstevel@tonic-gate 				curtype = INT;
23990Sstevel@tonic-gate 			break;
24000Sstevel@tonic-gate 		}
24010Sstevel@tonic-gate 		if (curargno >= 0 && curargno < MAXARGS) {
24020Sstevel@tonic-gate 			typelst[curargno] = curtype;
24030Sstevel@tonic-gate 			if (maxnum < curargno)
24040Sstevel@tonic-gate 				maxnum = curargno;
24050Sstevel@tonic-gate 		}
24060Sstevel@tonic-gate 		curargno++;	/* default to next in list */
24070Sstevel@tonic-gate 		if (flags & FLAG_INT)	/* took care of *, keep going */
24080Sstevel@tonic-gate 		{
24090Sstevel@tonic-gate 			flags ^= FLAG_INT;
24100Sstevel@tonic-gate 			goto again;
24110Sstevel@tonic-gate 		}
24120Sstevel@tonic-gate 	}
24130Sstevel@tonic-gate 	for (n = 0; n <= maxnum; n++) {
24140Sstevel@tonic-gate 		arglst[n] = args;
24150Sstevel@tonic-gate 		if (typelst[n] == 0)
24160Sstevel@tonic-gate 			typelst[n] = INT;
24170Sstevel@tonic-gate 
24180Sstevel@tonic-gate 		switch (typelst[n]) {
24190Sstevel@tonic-gate 		case INT:
24200Sstevel@tonic-gate 			(void) va_arg(args.ap, int);
24210Sstevel@tonic-gate 			break;
24220Sstevel@tonic-gate 		case LONG:
24230Sstevel@tonic-gate 			(void) va_arg(args.ap, long);
24240Sstevel@tonic-gate 			break;
24250Sstevel@tonic-gate 		case CHAR_PTR:
24260Sstevel@tonic-gate 			(void) va_arg(args.ap, char *);
24270Sstevel@tonic-gate 			break;
24280Sstevel@tonic-gate 		case DOUBLE:
24290Sstevel@tonic-gate 			(void) va_arg(args.ap, double);
24300Sstevel@tonic-gate 			break;
24310Sstevel@tonic-gate 		case LONG_DOUBLE:
24320Sstevel@tonic-gate 			(void) GETQVAL(args.ap);
24330Sstevel@tonic-gate 			break;
24340Sstevel@tonic-gate 		case VOID_PTR:
24350Sstevel@tonic-gate 			(void) va_arg(args.ap, void *);
24360Sstevel@tonic-gate 			break;
24370Sstevel@tonic-gate 		case LONG_PTR:
24380Sstevel@tonic-gate 			(void) va_arg(args.ap, long *);
24390Sstevel@tonic-gate 			break;
24400Sstevel@tonic-gate 		case INT_PTR:
24410Sstevel@tonic-gate 			(void) va_arg(args.ap, int *);
24420Sstevel@tonic-gate 			break;
24430Sstevel@tonic-gate 		case LONG_LONG:
24440Sstevel@tonic-gate 			(void) va_arg(args.ap, long long);
24450Sstevel@tonic-gate 			break;
24460Sstevel@tonic-gate 		case LONG_LONG_PTR:
24470Sstevel@tonic-gate 			(void) va_arg(args.ap, long long *);
24480Sstevel@tonic-gate 			break;
24490Sstevel@tonic-gate 		}
24500Sstevel@tonic-gate 	}
24510Sstevel@tonic-gate }
24520Sstevel@tonic-gate 
24530Sstevel@tonic-gate /*
24540Sstevel@tonic-gate  * This function is used to find the va_list value for arguments whose
24550Sstevel@tonic-gate  * position is greater than MAXARGS.  This function is slow, so hopefully
24560Sstevel@tonic-gate  * MAXARGS will be big enough so that this function need only be called in
24570Sstevel@tonic-gate  * unusual circumstances.
24580Sstevel@tonic-gate  * pargs is assumed to contain the value of arglst[MAXARGS - 1].
24590Sstevel@tonic-gate  */
24600Sstevel@tonic-gate /* ARGSUSED3 */
24610Sstevel@tonic-gate #ifdef	_WIDE
24620Sstevel@tonic-gate static void
_wgetarg(wchar_t * fmt,stva_list * pargs,long argno,int prflag)24630Sstevel@tonic-gate _wgetarg(wchar_t *fmt, stva_list *pargs, long argno, int prflag)
24640Sstevel@tonic-gate #else  /* _WIDE */
24650Sstevel@tonic-gate void
24660Sstevel@tonic-gate _getarg(char *fmt, stva_list *pargs, long argno, int prflag)
24670Sstevel@tonic-gate #endif /* _WIDE */
24680Sstevel@tonic-gate {
24690Sstevel@tonic-gate 
24700Sstevel@tonic-gate #ifdef	_WIDE
24710Sstevel@tonic-gate 	static const wchar_t	digits[] = L"01234567890";
24720Sstevel@tonic-gate 	static const wchar_t	skips[] = L"# +-.'0123456789h$";
24730Sstevel@tonic-gate 	wchar_t	*sfmt = fmt;
24740Sstevel@tonic-gate #else  /* _WIDE */
24750Sstevel@tonic-gate 	static const char digits[] = "01234567890";
24760Sstevel@tonic-gate 	static const char skips[] = "# +-.'0123456789h$";
24770Sstevel@tonic-gate 	char	*sfmt = fmt;
24780Sstevel@tonic-gate #endif /* _WIDE */
24790Sstevel@tonic-gate 	ssize_t n;
24800Sstevel@tonic-gate 	int i, curargno, flags;
24810Sstevel@tonic-gate 	int	found = 1;
24820Sstevel@tonic-gate 
24830Sstevel@tonic-gate 	i = MAXARGS;
24840Sstevel@tonic-gate 	curargno = 1;
24850Sstevel@tonic-gate 	while (found) {
24860Sstevel@tonic-gate 		fmt = sfmt;
24870Sstevel@tonic-gate 		found = 0;
24880Sstevel@tonic-gate 		while ((i != argno) && (fmt = STRCHR(fmt, '%')) != 0) {
24890Sstevel@tonic-gate 			fmt++;	/* skip % */
24900Sstevel@tonic-gate 			if (fmt[n = STRSPN(fmt, digits)] == '$') {
24910Sstevel@tonic-gate 				curargno = ATOI(fmt);
24920Sstevel@tonic-gate 				if (curargno <= 0)
24930Sstevel@tonic-gate 					continue;
24940Sstevel@tonic-gate 				fmt += n + 1;
24950Sstevel@tonic-gate 			}
24960Sstevel@tonic-gate 
24970Sstevel@tonic-gate 			/* find conversion specifier for next argument */
24980Sstevel@tonic-gate 			if (i != curargno) {
24990Sstevel@tonic-gate 				curargno++;
25000Sstevel@tonic-gate 				continue;
25010Sstevel@tonic-gate 			} else
25020Sstevel@tonic-gate 				found = 1;
25030Sstevel@tonic-gate 			flags = 0;
25040Sstevel@tonic-gate 		again:;
25050Sstevel@tonic-gate 			fmt += STRSPN(fmt, skips);
25060Sstevel@tonic-gate 			switch (*fmt++) {
25070Sstevel@tonic-gate 			case '%':	/* there is no argument! */
25080Sstevel@tonic-gate 				continue;
25090Sstevel@tonic-gate 			case 'l':
25100Sstevel@tonic-gate 				if (flags & (FLAG_LONG | FLAG_LONG_LONG)) {
25110Sstevel@tonic-gate 					flags |= FLAG_LONG_LONG;
25120Sstevel@tonic-gate 					flags &= ~FLAG_LONG;
25130Sstevel@tonic-gate 				} else {
25140Sstevel@tonic-gate 					flags |= FLAG_LONG;
25150Sstevel@tonic-gate 				}
25160Sstevel@tonic-gate 				goto again;
25170Sstevel@tonic-gate 			case 'j':
25180Sstevel@tonic-gate #ifndef _LP64
25190Sstevel@tonic-gate 				/*
25200Sstevel@tonic-gate 				 * *printf_c89() in 32-bit libc uses
25210Sstevel@tonic-gate 				 * 32-bit intmax_t; otherwise intmax_t
25220Sstevel@tonic-gate 				 * is 64-bits.
25230Sstevel@tonic-gate 				 */
25240Sstevel@tonic-gate 				if (!(prflag & _F_INTMAX32)) {
25250Sstevel@tonic-gate #endif
25260Sstevel@tonic-gate 					flags |= FLAG_LONG_LONG;  /* 64-bit */
25270Sstevel@tonic-gate #ifndef _LP64
25280Sstevel@tonic-gate 				}
25290Sstevel@tonic-gate #endif
25300Sstevel@tonic-gate 				goto again;
25310Sstevel@tonic-gate 			case 't':
25320Sstevel@tonic-gate 				flags |= FLAG_LONG;
25330Sstevel@tonic-gate 				goto again;
25340Sstevel@tonic-gate 			case 'z':
25350Sstevel@tonic-gate 				flags |= FLAG_LONG;
25360Sstevel@tonic-gate 				goto again;
25370Sstevel@tonic-gate 			case 'L':
25380Sstevel@tonic-gate 				flags |= FLAG_LONG_DBL;
25390Sstevel@tonic-gate 				goto again;
25400Sstevel@tonic-gate 			case '*':	/* int argument used for value */
25410Sstevel@tonic-gate 				/*
25420Sstevel@tonic-gate 				 * check if there is a positional parameter;
25430Sstevel@tonic-gate 				 * if so, just skip it; its size will be
25440Sstevel@tonic-gate 				 * correctly determined by default
25450Sstevel@tonic-gate 				 */
25460Sstevel@tonic-gate 				if (_M_ISDIGIT(*fmt)) {
25470Sstevel@tonic-gate 					fmt += STRSPN(fmt, digits);
25480Sstevel@tonic-gate 					if (*fmt == '$')
25490Sstevel@tonic-gate 						fmt++; /* skip '$' */
25500Sstevel@tonic-gate 					goto again;
25510Sstevel@tonic-gate 				}
25520Sstevel@tonic-gate 				flags |= FLAG_INT;
25530Sstevel@tonic-gate 				(void) va_arg((*pargs).ap, int);
25540Sstevel@tonic-gate 				break;
25550Sstevel@tonic-gate 			case 'a':
25560Sstevel@tonic-gate 			case 'A':
25570Sstevel@tonic-gate 			case 'e':
25580Sstevel@tonic-gate 			case 'E':
25590Sstevel@tonic-gate 			case 'f':
25600Sstevel@tonic-gate 			case 'F':
25610Sstevel@tonic-gate 			case 'g':
25620Sstevel@tonic-gate 			case 'G':
25630Sstevel@tonic-gate 				if (flags & FLAG_LONG_DBL)
25640Sstevel@tonic-gate 					(void) GETQVAL((*pargs).ap);
25650Sstevel@tonic-gate 				else
25660Sstevel@tonic-gate 					(void) va_arg((*pargs).ap, double);
25670Sstevel@tonic-gate 				break;
25680Sstevel@tonic-gate 			case 's':
25690Sstevel@tonic-gate 				(void) va_arg((*pargs).ap, char *);
25700Sstevel@tonic-gate 				break;
25710Sstevel@tonic-gate 			case 'p':
25720Sstevel@tonic-gate 				(void) va_arg((*pargs).ap, void *);
25730Sstevel@tonic-gate 				break;
25740Sstevel@tonic-gate 			case 'n':
25750Sstevel@tonic-gate 				if (flags & FLAG_LONG_LONG)
25760Sstevel@tonic-gate 					(void) va_arg((*pargs).ap, long long *);
25770Sstevel@tonic-gate 				else if (flags & FLAG_LONG)
25780Sstevel@tonic-gate 					(void) va_arg((*pargs).ap, long *);
25790Sstevel@tonic-gate 				else
25800Sstevel@tonic-gate 					(void) va_arg((*pargs).ap, int *);
25810Sstevel@tonic-gate 				break;
25820Sstevel@tonic-gate 			default:
25830Sstevel@tonic-gate 				if (flags & FLAG_LONG_LONG)
25840Sstevel@tonic-gate 					(void) va_arg((*pargs).ap, long long);
25850Sstevel@tonic-gate 				else if (flags & FLAG_LONG)
25860Sstevel@tonic-gate 					(void) va_arg((*pargs).ap, long int);
25870Sstevel@tonic-gate 				else
25880Sstevel@tonic-gate 					(void) va_arg((*pargs).ap, int);
25890Sstevel@tonic-gate 				break;
25900Sstevel@tonic-gate 			}
25910Sstevel@tonic-gate 			i++;
25920Sstevel@tonic-gate 			curargno++;	/* default to next in list */
25930Sstevel@tonic-gate 			if (flags & FLAG_INT)	/* took care of *, keep going */
25940Sstevel@tonic-gate 			{
25950Sstevel@tonic-gate 				flags ^= FLAG_INT;
25960Sstevel@tonic-gate 				goto again;
25970Sstevel@tonic-gate 			}
25980Sstevel@tonic-gate 		}
25990Sstevel@tonic-gate 
26000Sstevel@tonic-gate 		/* missing specifier for parameter, assume param is an int */
26010Sstevel@tonic-gate 		if (!found && i != argno) {
26020Sstevel@tonic-gate 			(void) va_arg((*pargs).ap, int);
26030Sstevel@tonic-gate 			i++;
26040Sstevel@tonic-gate 			curargno = i;
26050Sstevel@tonic-gate 			found = 1;
26060Sstevel@tonic-gate 		}
26070Sstevel@tonic-gate 	}
26080Sstevel@tonic-gate }
26090Sstevel@tonic-gate 
26100Sstevel@tonic-gate #ifdef	_WIDE
26110Sstevel@tonic-gate static wchar_t *
insert_thousands_sep(wchar_t * bp,wchar_t * ep)26120Sstevel@tonic-gate insert_thousands_sep(wchar_t *bp, wchar_t *ep)
26130Sstevel@tonic-gate #else  /* _WIDE */
26140Sstevel@tonic-gate static char *
26150Sstevel@tonic-gate insert_thousands_sep(char *bp, char *ep)
26160Sstevel@tonic-gate #endif /* _WIDE */
26170Sstevel@tonic-gate {
26180Sstevel@tonic-gate 	char thousep;
26190Sstevel@tonic-gate 	struct lconv *locptr;
26200Sstevel@tonic-gate 	ssize_t buf_index;
26210Sstevel@tonic-gate 	int i;
26220Sstevel@tonic-gate #ifdef	_WIDE
26230Sstevel@tonic-gate 	wchar_t *obp = bp;
26240Sstevel@tonic-gate 	wchar_t buf[371];
26250Sstevel@tonic-gate 	wchar_t *bufptr = buf;
26260Sstevel@tonic-gate #else  /* _WIDE */
26270Sstevel@tonic-gate 	char *obp = bp;
26280Sstevel@tonic-gate 	char buf[371];
26290Sstevel@tonic-gate 	char *bufptr = buf;
26300Sstevel@tonic-gate #endif /* _WIDE */
26310Sstevel@tonic-gate 	char *grp_ptr;
26320Sstevel@tonic-gate 
26330Sstevel@tonic-gate 	/* get the thousands sep. from the current locale */
26340Sstevel@tonic-gate 	locptr = localeconv();
26350Sstevel@tonic-gate 	thousep	= *locptr->thousands_sep;
26360Sstevel@tonic-gate 	grp_ptr = locptr->grouping;
26370Sstevel@tonic-gate 
26380Sstevel@tonic-gate 	/* thousands sep. not use in this locale or no grouping required */
26390Sstevel@tonic-gate 	if (!thousep || (*grp_ptr == '\0'))
26400Sstevel@tonic-gate 		return (ep);
26410Sstevel@tonic-gate 
26420Sstevel@tonic-gate 	buf_index = ep - bp;
26430Sstevel@tonic-gate 	for (;;) {
26440Sstevel@tonic-gate 		if (*grp_ptr == CHAR_MAX) {
26450Sstevel@tonic-gate 			for (i = 0; i < buf_index--; i++)
26460Sstevel@tonic-gate 				*bufptr++ = *(bp + buf_index);
26470Sstevel@tonic-gate 			break;
26480Sstevel@tonic-gate 		}
26490Sstevel@tonic-gate 		for (i = 0; i < *grp_ptr && buf_index-- > 0; i++)
26500Sstevel@tonic-gate 			*bufptr++ = *(bp + buf_index);
26510Sstevel@tonic-gate 
26520Sstevel@tonic-gate 		if (buf_index > 0) {
26530Sstevel@tonic-gate #ifdef	_WIDE
26540Sstevel@tonic-gate 			*bufptr++ = (wchar_t)thousep;
26550Sstevel@tonic-gate #else  /* _WIDE */
26560Sstevel@tonic-gate 			*bufptr++ = thousep;
26570Sstevel@tonic-gate #endif /* _WIDE */
26580Sstevel@tonic-gate 			ep++;
26590Sstevel@tonic-gate 		}
26600Sstevel@tonic-gate 		else
26610Sstevel@tonic-gate 			break;
26620Sstevel@tonic-gate 		if (*(grp_ptr + 1) != '\0')
26630Sstevel@tonic-gate 			++grp_ptr;
26640Sstevel@tonic-gate 	}
26650Sstevel@tonic-gate 
26660Sstevel@tonic-gate 	/* put the string in the caller's buffer in reverse order */
26670Sstevel@tonic-gate 	--bufptr;
26680Sstevel@tonic-gate 	while (buf <= bufptr)
26690Sstevel@tonic-gate 		*obp++ = *bufptr--;
26700Sstevel@tonic-gate 	return (ep);
26710Sstevel@tonic-gate }
26720Sstevel@tonic-gate 
26730Sstevel@tonic-gate 
26740Sstevel@tonic-gate /*
26750Sstevel@tonic-gate  *  Recovery scrswidth function -
26760Sstevel@tonic-gate  *  this variant of wcswidth() accepts non-printable or illegal
26770Sstevel@tonic-gate  *  widechar characters.
26780Sstevel@tonic-gate  */
26790Sstevel@tonic-gate static int
_rec_scrswidth(wchar_t * wp,ssize_t n)26800Sstevel@tonic-gate _rec_scrswidth(wchar_t *wp, ssize_t n)
26810Sstevel@tonic-gate {
26820Sstevel@tonic-gate 	int col;
26830Sstevel@tonic-gate 	int i;
26840Sstevel@tonic-gate 
26850Sstevel@tonic-gate 	col = 0;
26860Sstevel@tonic-gate 	while (*wp && (n-- > 0)) {
26870Sstevel@tonic-gate 		if ((i = _scrwidth(*wp++)) == 0)
26880Sstevel@tonic-gate 			i = 1;
26890Sstevel@tonic-gate 		col += i;
26900Sstevel@tonic-gate 	}
26910Sstevel@tonic-gate 	return (col);
26920Sstevel@tonic-gate }
2693