xref: /illumos-gate/usr/src/lib/libc/port/print/doprnt.c (revision 4a38094c)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57257d1b4Sraf  * Common Development and Distribution License (the "License").
67257d1b4Sraf  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217257d1b4Sraf 
227c478bd9Sstevel@tonic-gate /*
239f773e28SDarren Moffat  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*	Copyright (c) 1988 AT&T	*/
282829495dSToomas Soome /*	  All Rights Reserved	*/
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate  *	_doprnt: common code for printf, fprintf, sprintf
327c478bd9Sstevel@tonic-gate  */
337c478bd9Sstevel@tonic-gate 
347257d1b4Sraf #include "lint.h"
357c478bd9Sstevel@tonic-gate #include "mtlib.h"
367c478bd9Sstevel@tonic-gate #include "print.h"	/* parameters & macros for doprnt */
377c478bd9Sstevel@tonic-gate #include <wchar.h>
387c478bd9Sstevel@tonic-gate #include "libc.h"
397c478bd9Sstevel@tonic-gate #include <stdlib.h>
407c478bd9Sstevel@tonic-gate #include <limits.h>
417c478bd9Sstevel@tonic-gate #include <ctype.h>
427c478bd9Sstevel@tonic-gate #include <stdarg.h>
437c478bd9Sstevel@tonic-gate #include <values.h>
447c478bd9Sstevel@tonic-gate #include <memory.h>
457c478bd9Sstevel@tonic-gate #include <string.h>
467c478bd9Sstevel@tonic-gate #include <locale.h>
477c478bd9Sstevel@tonic-gate #include <widec.h>
487c478bd9Sstevel@tonic-gate #include "../i18n/_locale.h"
497c478bd9Sstevel@tonic-gate #include <errno.h>
507c478bd9Sstevel@tonic-gate #include <sys/types.h>
517c478bd9Sstevel@tonic-gate #include <libw.h>
527c478bd9Sstevel@tonic-gate #include "mse.h"
537c478bd9Sstevel@tonic-gate #include "xpg6.h"
547c478bd9Sstevel@tonic-gate 
559f773e28SDarren Moffat static const char nullstr[] = "(null)";
569f773e28SDarren Moffat static const wchar_t widenullstr[] = L"(null)";
579f773e28SDarren Moffat 
587c478bd9Sstevel@tonic-gate #if defined(__i386) || defined(__amd64) || defined(__sparcv9)
597c478bd9Sstevel@tonic-gate #define	GETQVAL(arg)	(va_arg(arg, long double))
607c478bd9Sstevel@tonic-gate #else /* !defined(__i386) && !defined(__sparcv9) */
617c478bd9Sstevel@tonic-gate #define	GETQVAL(arg)	*(va_arg(arg, long double *))
627c478bd9Sstevel@tonic-gate #endif /* !defined(__i386) && !defined(__sparcv9) */
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate #ifdef	_WIDE
657c478bd9Sstevel@tonic-gate #define	STRCHR	wcschr
667c478bd9Sstevel@tonic-gate #define	STRSPN	wcsspn
677c478bd9Sstevel@tonic-gate #define	ATOI(x)	_watoi((wchar_t *)x)
687c478bd9Sstevel@tonic-gate #define	_P_HYPHEN	L"-"
697c478bd9Sstevel@tonic-gate #define	_P_PLUS		L"+"
707c478bd9Sstevel@tonic-gate #define	_P_BLANK	L" "
717c478bd9Sstevel@tonic-gate #define	_P_ZEROx	L"0x"
727c478bd9Sstevel@tonic-gate #define	_P_ZEROX	L"0X"
737c478bd9Sstevel@tonic-gate #define	_M_ISDIGIT(c)	(((c) >= 0) && ((c) < 256) && isdigit((c)))
747c478bd9Sstevel@tonic-gate #define	_M_ISUPPER(c)	(((c) >= 0) && ((c) < 256) && isupper((c)))
757c478bd9Sstevel@tonic-gate #else  /* _WIDE */
767c478bd9Sstevel@tonic-gate #define	STRCHR	strchr
777c478bd9Sstevel@tonic-gate #define	STRSPN	strspn
787c478bd9Sstevel@tonic-gate #define	ATOI(x)	atoi(x)
797c478bd9Sstevel@tonic-gate #define	_P_HYPHEN	"-"
807c478bd9Sstevel@tonic-gate #define	_P_PLUS		"+"
817c478bd9Sstevel@tonic-gate #define	_P_BLANK	" "
827c478bd9Sstevel@tonic-gate #define	_P_ZEROx	"0x"
837c478bd9Sstevel@tonic-gate #define	_P_ZEROX	"0X"
847c478bd9Sstevel@tonic-gate #define	_M_ISDIGIT(c)	isdigit((c))
857c478bd9Sstevel@tonic-gate #define	_M_ISUPPER(c)	isupper((c))
867c478bd9Sstevel@tonic-gate #endif /* _WIDE */
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate #ifdef	_WIDE
897c478bd9Sstevel@tonic-gate #define	PUT(p, n) \
907c478bd9Sstevel@tonic-gate 	{ \
917c478bd9Sstevel@tonic-gate 		int	retp; \
924297a3b0SGarrett D'Amore 		retp = put_wide(iop, &bufptr, bufferend, p, n, sflag); \
937c478bd9Sstevel@tonic-gate 		if (retp == EOF) { \
947c478bd9Sstevel@tonic-gate 			return ((ssize_t)EOF); \
957c478bd9Sstevel@tonic-gate 		} \
967c478bd9Sstevel@tonic-gate 	}
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate #define	PAD(s, n) \
997c478bd9Sstevel@tonic-gate 	{ \
1007c478bd9Sstevel@tonic-gate 		int	retp; \
1017c478bd9Sstevel@tonic-gate 		retp = pad_wide(iop, &bufptr, bufferend, s, n, sflag); \
1027c478bd9Sstevel@tonic-gate 		if (retp == EOF) { \
1037c478bd9Sstevel@tonic-gate 			return ((ssize_t)EOF); \
1047c478bd9Sstevel@tonic-gate 		} \
1057c478bd9Sstevel@tonic-gate 	}
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate #define	FPCONV(func, val, prec, decpt, sign, cvtbuf) \
1087c478bd9Sstevel@tonic-gate 	{ \
1097c478bd9Sstevel@tonic-gate 		char	cb[DECIMAL_STRING_LENGTH]; \
1107c478bd9Sstevel@tonic-gate 		wchar_t	*wp; \
1117c478bd9Sstevel@tonic-gate 		char	*cp; \
1127c478bd9Sstevel@tonic-gate 		(void) func(val, prec, decpt, sign, cb); \
1137c478bd9Sstevel@tonic-gate 		wp = cvtbuf; \
1147c478bd9Sstevel@tonic-gate 		cp = cb; \
1157c478bd9Sstevel@tonic-gate 		while (*cp) { \
1167c478bd9Sstevel@tonic-gate 			*wp++ = (wchar_t)*cp++; \
1177c478bd9Sstevel@tonic-gate 		} \
1187c478bd9Sstevel@tonic-gate 		*wp = L'\0'; \
1197c478bd9Sstevel@tonic-gate 	}
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate #else  /* _WIDE */
1227c478bd9Sstevel@tonic-gate #define	PUT(p, n)	\
1237c478bd9Sstevel@tonic-gate 	{\
1247c478bd9Sstevel@tonic-gate 		/*\
1257c478bd9Sstevel@tonic-gate 		 * When _doprnt() is called by [v]snprintf, we need to \
1267c478bd9Sstevel@tonic-gate 		 * always call _dowrite().  We also need to call _dowrite() \
1277c478bd9Sstevel@tonic-gate 		 * if the bufptr lies beyond the end of the buffer.  This \
1287c478bd9Sstevel@tonic-gate 		 * is possible due to known off-by-one errors in __flsbuf() \
1297c478bd9Sstevel@tonic-gate 		 * and _fwrite_unlocked().  See 1235867 and 1231720 for the \
1307c478bd9Sstevel@tonic-gate 		 * sordid details. \
1317c478bd9Sstevel@tonic-gate 		 */\
1327c478bd9Sstevel@tonic-gate 		if (snflag || bufptr > bufferend ||\
1337c478bd9Sstevel@tonic-gate 		    (unsigned long)(bufferend - bufptr) < (n)) {\
1347c478bd9Sstevel@tonic-gate 			if (!_dowrite(p, n, iop, &bufptr)) {\
1357c478bd9Sstevel@tonic-gate 				return (EOF);\
1367c478bd9Sstevel@tonic-gate 			}\
1377c478bd9Sstevel@tonic-gate 		} else {\
1387c478bd9Sstevel@tonic-gate 			unsigned char	*fbp = bufptr;\
1397c478bd9Sstevel@tonic-gate 			switch (n) {\
1407c478bd9Sstevel@tonic-gate 			case 4:\
1417c478bd9Sstevel@tonic-gate 				*fbp = *p;\
1427c478bd9Sstevel@tonic-gate 				*(fbp + 1) = *(p + 1);\
1437c478bd9Sstevel@tonic-gate 				*(fbp + 2) = *(p + 2);\
1447c478bd9Sstevel@tonic-gate 				*(fbp + 3) = *(p + 3);\
1457c478bd9Sstevel@tonic-gate 				bufptr += 4;\
1467c478bd9Sstevel@tonic-gate 				break;\
1477c478bd9Sstevel@tonic-gate 			case 3:\
1487c478bd9Sstevel@tonic-gate 				*fbp = *p;\
1497c478bd9Sstevel@tonic-gate 				*(fbp + 1) = *(p + 1);\
1507c478bd9Sstevel@tonic-gate 				*(fbp + 2) = *(p + 2);\
1517c478bd9Sstevel@tonic-gate 				bufptr += 3;\
1527c478bd9Sstevel@tonic-gate 				break;\
1537c478bd9Sstevel@tonic-gate 			case 2:\
1547c478bd9Sstevel@tonic-gate 				*fbp = *p;\
1557c478bd9Sstevel@tonic-gate 				*(fbp + 1) = *(p + 1);\
1567c478bd9Sstevel@tonic-gate 				bufptr += 2;\
1577c478bd9Sstevel@tonic-gate 				break;\
1587c478bd9Sstevel@tonic-gate 			case 1:\
1597c478bd9Sstevel@tonic-gate 				*bufptr++ = *p;\
1607c478bd9Sstevel@tonic-gate 				break;\
1617c478bd9Sstevel@tonic-gate 			default:\
1627c478bd9Sstevel@tonic-gate 				bufptr = (unsigned char *)memcpy(fbp, p, n)\
1637c478bd9Sstevel@tonic-gate 					+ (n);\
1647c478bd9Sstevel@tonic-gate 			}\
1657c478bd9Sstevel@tonic-gate 		}\
1667c478bd9Sstevel@tonic-gate 	}
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate #define	PAD(s, n)    { ssize_t nn; \
1692829495dSToomas Soome 			for (nn = n; nn > PAD_LEN; nn -= PAD_LEN) \
1708a67df42SToomas Soome 				if (!_dowrite(s, PAD_LEN, iop, &bufptr)) \
1718a67df42SToomas Soome 					return (EOF); \
1727c478bd9Sstevel@tonic-gate 			PUT(s, nn); \
1737c478bd9Sstevel@tonic-gate 		}
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate #define	FPCONV(func, val, prec, decpt, sign, cvtbuf) \
1767c478bd9Sstevel@tonic-gate 		(void) func(val, prec, decpt, sign, cvtbuf);
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate #endif /* _WIDE */
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate /* bit positions for flags used in doprnt */
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate #define	LENGTH	0x1	/* l */
1837c478bd9Sstevel@tonic-gate #define	FPLUS	0x2	/* + */
1847c478bd9Sstevel@tonic-gate #define	FMINUS	0x4	/* - */
1857c478bd9Sstevel@tonic-gate #define	FBLANK	0x8	/* blank */
1867c478bd9Sstevel@tonic-gate #define	FSHARP	0x10	/* # */
1877c478bd9Sstevel@tonic-gate #define	PADZERO 0x20	/* padding zeroes requested via '0' */
1887c478bd9Sstevel@tonic-gate #define	DOTSEEN 0x40	/* dot appeared in format specification */
1897c478bd9Sstevel@tonic-gate #define	SUFFIX	0x80	/* a suffix is to appear in the output */
1907c478bd9Sstevel@tonic-gate #define	RZERO	0x100	/* there will be trailing zeros in output */
1917c478bd9Sstevel@tonic-gate #define	LZERO	0x200	/* there will be leading zeroes in output */
1927c478bd9Sstevel@tonic-gate #define	SHORT   0x400	/* h */
1937c478bd9Sstevel@tonic-gate #define	QUAD    0x800	/* Q for long double */
1947c478bd9Sstevel@tonic-gate #define	XLONG   0x1000	/* ll for long long */
1957c478bd9Sstevel@tonic-gate #define	CHAR    0x2000	/* hh for char */
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate #ifdef	_WIDE
198804635d7SYuri Pankov static wchar_t *insert_decimal_point(wchar_t *ep);
199804635d7SYuri Pankov static wchar_t *insert_thousands_sep(wchar_t *bp, wchar_t *ep);
2007c478bd9Sstevel@tonic-gate #else  /* _WIDE */
201804635d7SYuri Pankov static char *insert_decimal_point(char *ep);
202804635d7SYuri Pankov static char *insert_thousands_sep(char *bp, char *ep);
2037c478bd9Sstevel@tonic-gate #endif /* _WIDE */
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate static int	_rec_scrswidth(wchar_t *, ssize_t);
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate /*
2087c478bd9Sstevel@tonic-gate  *	Positional Parameter information
2097c478bd9Sstevel@tonic-gate  */
2107c478bd9Sstevel@tonic-gate #define	MAXARGS	30	/* max. number of args for fast positional paramters */
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate static ssize_t
2137c478bd9Sstevel@tonic-gate _dowrite(const char *p, ssize_t n, FILE *iop, unsigned char **ptrptr);
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate /*
2167c478bd9Sstevel@tonic-gate  * stva_list is used to subvert C's restriction that a variable with an
2177c478bd9Sstevel@tonic-gate  * array type can not appear on the left hand side of an assignment operator.
2187c478bd9Sstevel@tonic-gate  * By putting the array inside a structure, the functionality of assigning to
2197c478bd9Sstevel@tonic-gate  * the whole array through a simple assignment is achieved..
2207c478bd9Sstevel@tonic-gate  */
2217c478bd9Sstevel@tonic-gate typedef struct stva_list {
2227c478bd9Sstevel@tonic-gate 	va_list	ap;
2237c478bd9Sstevel@tonic-gate } stva_list;
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate #ifdef	_WIDE
2267c478bd9Sstevel@tonic-gate static void _wmkarglst(wchar_t *, stva_list, stva_list [], int);
2277c478bd9Sstevel@tonic-gate static void _wgetarg(wchar_t *, stva_list *, long, int);
2287c478bd9Sstevel@tonic-gate #else  /* _WIDE */
2298793b36bSNick Todd static void _mkarglst(char *, stva_list, stva_list [], int);
2307c478bd9Sstevel@tonic-gate void _getarg(char *, stva_list *, long, int);
2317c478bd9Sstevel@tonic-gate #endif /* _WIDE */
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate static int
_lowdigit(ssize_t * valptr)2377c478bd9Sstevel@tonic-gate _lowdigit(ssize_t *valptr)
2387c478bd9Sstevel@tonic-gate {
2397c478bd9Sstevel@tonic-gate 	/* This function computes the decimal low-order digit of the number */
2407c478bd9Sstevel@tonic-gate 	/* pointed to by valptr, and returns this digit after dividing   */
2417c478bd9Sstevel@tonic-gate 	/* *valptr by ten.  This function is called ONLY to compute the */
2427c478bd9Sstevel@tonic-gate 	/* low-order digit of a long whose high-order bit is set. */
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	ssize_t lowbit = *valptr & 1;
2457c478bd9Sstevel@tonic-gate 	long value = (*valptr >> 1) & ~HIBITL;
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate 	*valptr = value / 5;
2487c478bd9Sstevel@tonic-gate 	value = value % 5 * 2 + lowbit + '0';
2497c478bd9Sstevel@tonic-gate 	return ((int)value);
2507c478bd9Sstevel@tonic-gate }
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate static int
_lowlldigit(long long * valptr)2537c478bd9Sstevel@tonic-gate _lowlldigit(long long *valptr)
2547c478bd9Sstevel@tonic-gate {
2557c478bd9Sstevel@tonic-gate 	ssize_t lowbit = *valptr & 1;
2567c478bd9Sstevel@tonic-gate 	long long value = (*valptr >> 1) & ~HIBITLL;
2577c478bd9Sstevel@tonic-gate 		*valptr = value / 5;
2587c478bd9Sstevel@tonic-gate 		value = value % 5 * 2 + lowbit + '0';
2597c478bd9Sstevel@tonic-gate 		return ((int)value);
2607c478bd9Sstevel@tonic-gate }
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate /* The function _dowrite carries out buffer pointer bookkeeping surrounding */
2637c478bd9Sstevel@tonic-gate /* a call to fwrite.  It is called only when the end of the file output */
2647c478bd9Sstevel@tonic-gate /* buffer is approached or in other unusual situations. */
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate static ssize_t
_dowrite(const char * p,ssize_t n,FILE * iop,unsigned char ** ptrptr)2677c478bd9Sstevel@tonic-gate _dowrite(const char *p, ssize_t n, FILE *iop, unsigned char **ptrptr)
2687c478bd9Sstevel@tonic-gate {
2697c478bd9Sstevel@tonic-gate 	if (!(iop->_flag & _IOREAD)) {
2707c478bd9Sstevel@tonic-gate 		iop->_cnt -= (*ptrptr - iop->_ptr);
2717c478bd9Sstevel@tonic-gate 		iop->_ptr = *ptrptr;
2727c478bd9Sstevel@tonic-gate 		_bufsync(iop, _bufend(iop));
2737c478bd9Sstevel@tonic-gate 		if (_FWRITE(p, 1, n, iop) != n) {
2747c478bd9Sstevel@tonic-gate 			return (0);
2757c478bd9Sstevel@tonic-gate 		}
2767c478bd9Sstevel@tonic-gate 		*ptrptr = iop->_ptr;
2777c478bd9Sstevel@tonic-gate 	} else {
2787c478bd9Sstevel@tonic-gate 		if (n > iop->_cnt)
2797c478bd9Sstevel@tonic-gate 			n = iop->_cnt;
2807c478bd9Sstevel@tonic-gate 		iop->_cnt -= n;
2817c478bd9Sstevel@tonic-gate 		*ptrptr = (unsigned char *)memcpy((char *)*ptrptr, p, n) + n;
2827c478bd9Sstevel@tonic-gate 		iop->_ptr = *ptrptr;
2837c478bd9Sstevel@tonic-gate 	}
2847c478bd9Sstevel@tonic-gate 	return (1);
2857c478bd9Sstevel@tonic-gate }
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate #define	PAD_LEN	20
2887c478bd9Sstevel@tonic-gate 	static const char _blanks[] = "                    ";
2897c478bd9Sstevel@tonic-gate 	static const char _zeroes[] = "00000000000000000000";
2907c478bd9Sstevel@tonic-gate #ifdef	_WIDE
2917c478bd9Sstevel@tonic-gate 	static const wchar_t uc_digs[] = L"0123456789ABCDEF";
2927c478bd9Sstevel@tonic-gate 	static const wchar_t lc_digs[] = L"0123456789abcdef";
2937c478bd9Sstevel@tonic-gate #else /* _WIDE */
2947c478bd9Sstevel@tonic-gate 	static const char uc_digs[] = "0123456789ABCDEF";
2957c478bd9Sstevel@tonic-gate 	static const char lc_digs[] = "0123456789abcdef";
2967c478bd9Sstevel@tonic-gate #endif /* _WIDE */
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate #ifdef	_WIDE
2997c478bd9Sstevel@tonic-gate static int
put_wide(FILE * iop,unsigned char ** bufptr,unsigned char * bufferend,wchar_t * p,size_t n,int sflag)3007c478bd9Sstevel@tonic-gate put_wide(FILE *iop, unsigned char **bufptr,
3018a67df42SToomas Soome     unsigned char *bufferend, wchar_t *p, size_t n,
3028a67df42SToomas Soome     int sflag)
3037c478bd9Sstevel@tonic-gate {
3047c478bd9Sstevel@tonic-gate 	unsigned char	*newbufptr;
3057c478bd9Sstevel@tonic-gate 	wchar_t	*q;
3067c478bd9Sstevel@tonic-gate 	int	r;
3077c478bd9Sstevel@tonic-gate 	size_t	len, i;
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 	if (sflag) {
3107c478bd9Sstevel@tonic-gate 		len = (wchar_t *)bufferend - (wchar_t *)*bufptr;
3117c478bd9Sstevel@tonic-gate 		if (n > len) {
3127c478bd9Sstevel@tonic-gate 			(void) wmemcpy((wchar_t *)*bufptr, p, len);
3137c478bd9Sstevel@tonic-gate 			iop->_ptr = bufferend;
3147c478bd9Sstevel@tonic-gate 			return (EOF);
3157c478bd9Sstevel@tonic-gate 		} else {
3167c478bd9Sstevel@tonic-gate 			(void) wmemcpy((wchar_t *)*bufptr, p, n);
3177257d1b4Sraf 			*bufptr = (unsigned char *)((wchar_t *)*bufptr + n);
3187c478bd9Sstevel@tonic-gate 			return (0);
3197c478bd9Sstevel@tonic-gate 		}
3207c478bd9Sstevel@tonic-gate 	} else {
3217c478bd9Sstevel@tonic-gate 		char *tmpp, *tmpq;
3227c478bd9Sstevel@tonic-gate 		size_t tsize;
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 		tsize = (n + 1) * MB_LEN_MAX;
3257c478bd9Sstevel@tonic-gate 		tmpp = lmalloc(tsize);
3267c478bd9Sstevel@tonic-gate 		if (tmpp == NULL) {
3277c478bd9Sstevel@tonic-gate 			errno = ENOMEM;
3287c478bd9Sstevel@tonic-gate 			return (EOF);
3297c478bd9Sstevel@tonic-gate 		}
3307c478bd9Sstevel@tonic-gate 		q = p;
3317c478bd9Sstevel@tonic-gate 		tmpq = tmpp;
3327c478bd9Sstevel@tonic-gate 		for (len = 0, i = 0; i < n; i++) {
3334297a3b0SGarrett D'Amore 			r = wctomb(tmpq, *q++);
3347c478bd9Sstevel@tonic-gate 			if (r == -1) {
3357c478bd9Sstevel@tonic-gate 				lfree(tmpp, tsize);
3367c478bd9Sstevel@tonic-gate 				errno = EILSEQ;
3377c478bd9Sstevel@tonic-gate 				return (EOF);
3387c478bd9Sstevel@tonic-gate 			}
3397c478bd9Sstevel@tonic-gate 			len += r;
3407c478bd9Sstevel@tonic-gate 			tmpq += r;
3417c478bd9Sstevel@tonic-gate 		}
3427c478bd9Sstevel@tonic-gate 		tmpq = tmpp;
3437c478bd9Sstevel@tonic-gate 		newbufptr = *bufptr + len;
3447c478bd9Sstevel@tonic-gate 		if (newbufptr > bufferend) {
3457c478bd9Sstevel@tonic-gate 			if (!_dowrite(tmpp, len, iop, bufptr)) {
3467c478bd9Sstevel@tonic-gate 				lfree(tmpp, tsize);
3477c478bd9Sstevel@tonic-gate 				return (EOF);
3487c478bd9Sstevel@tonic-gate 			}
3497c478bd9Sstevel@tonic-gate 		} else {
3507c478bd9Sstevel@tonic-gate 			(void) memcpy(*bufptr, tmpp, len);
3517c478bd9Sstevel@tonic-gate 			*bufptr = newbufptr;
3527c478bd9Sstevel@tonic-gate 		}
3537c478bd9Sstevel@tonic-gate 		lfree(tmpp, tsize);
3547c478bd9Sstevel@tonic-gate 		return (0);
3557c478bd9Sstevel@tonic-gate 	}
3567c478bd9Sstevel@tonic-gate }
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate static int
pad_wide(FILE * iop,unsigned char ** bufptr,unsigned char * bufferend,const char * s,size_t n,int sflag)3597c478bd9Sstevel@tonic-gate pad_wide(FILE *iop, unsigned char **bufptr,
3608a67df42SToomas Soome     unsigned char *bufferend, const char *s, size_t n,
3618a67df42SToomas Soome     int sflag)
3627c478bd9Sstevel@tonic-gate {
3637c478bd9Sstevel@tonic-gate 	unsigned char	*newbufptr;
3647c478bd9Sstevel@tonic-gate 	ssize_t	nn;
3657c478bd9Sstevel@tonic-gate 	size_t	len;
3667c478bd9Sstevel@tonic-gate 	wchar_t	ps;
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 	if (sflag) {
3697c478bd9Sstevel@tonic-gate 		/* for swprintf */
3707c478bd9Sstevel@tonic-gate 		ps = (wchar_t)s[0];
3717c478bd9Sstevel@tonic-gate 		len = (wchar_t *)bufferend - (wchar_t *)*bufptr;
3727c478bd9Sstevel@tonic-gate 		if (n > len) {
3737c478bd9Sstevel@tonic-gate 			(void) wmemset((wchar_t *)*bufptr, ps, len);
3747c478bd9Sstevel@tonic-gate 			iop->_ptr = bufferend;
3757c478bd9Sstevel@tonic-gate 			return (EOF);
3767c478bd9Sstevel@tonic-gate 		} else {
3777c478bd9Sstevel@tonic-gate 			(void) wmemset((wchar_t *)*bufptr, ps, n);
3787257d1b4Sraf 			*bufptr = (unsigned char *)((wchar_t *)*bufptr + n);
3797c478bd9Sstevel@tonic-gate 			return (0);
3807c478bd9Sstevel@tonic-gate 		}
3817c478bd9Sstevel@tonic-gate 	} else {
3827c478bd9Sstevel@tonic-gate 		for (nn = n; nn > PAD_LEN; nn -= PAD_LEN) {
3837c478bd9Sstevel@tonic-gate 			if (!_dowrite(s, PAD_LEN, iop, bufptr))
3847c478bd9Sstevel@tonic-gate 				return (EOF);
3857c478bd9Sstevel@tonic-gate 		}
3867c478bd9Sstevel@tonic-gate 		newbufptr = *bufptr + nn;
3877c478bd9Sstevel@tonic-gate 		if (newbufptr > bufferend) {
3887c478bd9Sstevel@tonic-gate 			if (!_dowrite(s, nn, iop, bufptr))
3897c478bd9Sstevel@tonic-gate 				return (EOF);
3907c478bd9Sstevel@tonic-gate 		} else {
3917c478bd9Sstevel@tonic-gate 			(void) memcpy(*bufptr, s, nn);
3927c478bd9Sstevel@tonic-gate 			*bufptr = newbufptr;
3937c478bd9Sstevel@tonic-gate 		}
3947c478bd9Sstevel@tonic-gate 		return (0);
3957c478bd9Sstevel@tonic-gate 	}
3967c478bd9Sstevel@tonic-gate }
3977c478bd9Sstevel@tonic-gate #endif /* _WIDE */
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate #ifdef	_WIDE
4007c478bd9Sstevel@tonic-gate ssize_t
_wdoprnt(const wchar_t * format,va_list in_args,FILE * iop)4017c478bd9Sstevel@tonic-gate _wdoprnt(const wchar_t *format, va_list in_args, FILE *iop)
4027c478bd9Sstevel@tonic-gate {
4037c478bd9Sstevel@tonic-gate 	return (_wndoprnt(format, in_args, iop, 0));
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate #else	/* _WIDE */
4067c478bd9Sstevel@tonic-gate ssize_t
_doprnt(const char * format,va_list in_args,FILE * iop)4077c478bd9Sstevel@tonic-gate _doprnt(const char *format, va_list in_args, FILE *iop)
4087c478bd9Sstevel@tonic-gate {
4097c478bd9Sstevel@tonic-gate 	return (_ndoprnt(format, in_args, iop, 0));
4107c478bd9Sstevel@tonic-gate }
4117c478bd9Sstevel@tonic-gate #endif	/* _WIDE */
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate #ifdef	_WIDE
4157c478bd9Sstevel@tonic-gate ssize_t
_wndoprnt(const wchar_t * format,va_list in_args,FILE * iop,int prflag)4167c478bd9Sstevel@tonic-gate _wndoprnt(const wchar_t *format, va_list in_args, FILE *iop, int prflag)
4177c478bd9Sstevel@tonic-gate #else  /* _WIDE */
4187c478bd9Sstevel@tonic-gate ssize_t
4197c478bd9Sstevel@tonic-gate _ndoprnt(const char *format, va_list in_args, FILE *iop, int prflag)
4207c478bd9Sstevel@tonic-gate #endif /* _WIDE */
4217c478bd9Sstevel@tonic-gate {
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate #ifdef	_WIDE
4247c478bd9Sstevel@tonic-gate 	int	sflag = 0;
4257c478bd9Sstevel@tonic-gate 	size_t	maxcount;
4267c478bd9Sstevel@tonic-gate #else
4277c478bd9Sstevel@tonic-gate 	int	snflag = 0;
4287c478bd9Sstevel@tonic-gate #endif /* _WIDE */
4297c478bd9Sstevel@tonic-gate 	/* bufptr is used inside of doprnt instead of iop->_ptr; */
4307c478bd9Sstevel@tonic-gate 	/* bufferend is a copy of _bufend(iop), if it exists.  For */
4317c478bd9Sstevel@tonic-gate 	/* dummy file descriptors (iop->_flag & _IOREAD), bufferend */
4327c478bd9Sstevel@tonic-gate 	/* may be meaningless. Dummy file descriptors are used so that */
4337c478bd9Sstevel@tonic-gate 	/* sprintf and vsprintf may share the _doprnt routine with the */
4347c478bd9Sstevel@tonic-gate 	/* rest of the printf family. */
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 	unsigned char *bufptr;
4377c478bd9Sstevel@tonic-gate 	unsigned char *bufferend;
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate #ifdef	_WIDE
4407c478bd9Sstevel@tonic-gate 	/* This variable counts output characters. */
4417c478bd9Sstevel@tonic-gate 	size_t	count = 0;
4427c478bd9Sstevel@tonic-gate #else  /* _WIDE */
4437c478bd9Sstevel@tonic-gate 	/* This variable counts output characters. */
4447c478bd9Sstevel@tonic-gate 	int	count = 0;
4457c478bd9Sstevel@tonic-gate #endif /* _WIDE */
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate #ifdef	_WIDE
4487c478bd9Sstevel@tonic-gate 	wchar_t	*bp;
4497c478bd9Sstevel@tonic-gate 	size_t bpsize;
4507c478bd9Sstevel@tonic-gate 	wchar_t	*p;
4517c478bd9Sstevel@tonic-gate 	char	*cbp;
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate #else  /* _WIDE */
4547c478bd9Sstevel@tonic-gate 	/* Starting and ending points for value to be printed */
4557c478bd9Sstevel@tonic-gate 	char	*bp;
4567c478bd9Sstevel@tonic-gate 	char *p;
4578a67df42SToomas Soome 
4588a67df42SToomas Soome 	/* Field width and precision */
4598a67df42SToomas Soome 	ssize_t preco;
4608a67df42SToomas Soome 	char tmpbuf[10];
4618a67df42SToomas Soome 	int	retcode;
4627c478bd9Sstevel@tonic-gate #endif /* _WIDE */
4637c478bd9Sstevel@tonic-gate 	/* Field width and precision */
4647c478bd9Sstevel@tonic-gate 	int	prec = 0;
4657c478bd9Sstevel@tonic-gate 	ssize_t width;
4667c478bd9Sstevel@tonic-gate 	ssize_t num;
4677c478bd9Sstevel@tonic-gate 	wchar_t *wp;
4687c478bd9Sstevel@tonic-gate 	ssize_t wcount = 0;
4697c478bd9Sstevel@tonic-gate 	char wflag;
4707c478bd9Sstevel@tonic-gate 	char lflag;
4717c478bd9Sstevel@tonic-gate 	int quote;		/* ' */
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate #ifdef	_WIDE
4747c478bd9Sstevel@tonic-gate 	/* Format code */
4757c478bd9Sstevel@tonic-gate 	wchar_t	fcode;
4767c478bd9Sstevel@tonic-gate #else  /* _WIDE */
4777c478bd9Sstevel@tonic-gate 	/* Format code */
4787c478bd9Sstevel@tonic-gate 	char	fcode;
4799c3b8506SToomas Soome 	ssize_t sec_display;
4807c478bd9Sstevel@tonic-gate #endif /* _WIDE */
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate 	/* Number of padding zeroes required on the left and right */
4837c478bd9Sstevel@tonic-gate 	ssize_t	lzero, rzero, rz, leadzeroes;
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 	/* Flags - bit positions defined by LENGTH, FPLUS, FMINUS, FBLANK, */
4877c478bd9Sstevel@tonic-gate 	/* and FSHARP are set if corresponding character is in format */
4887c478bd9Sstevel@tonic-gate 	/* Bit position defined by PADZERO means extra space in the field */
4897c478bd9Sstevel@tonic-gate 	/* should be padded with leading zeroes rather than with blanks */
4907c478bd9Sstevel@tonic-gate 
4917c478bd9Sstevel@tonic-gate 	ssize_t	flagword;
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate #ifdef	_WIDE
4947c478bd9Sstevel@tonic-gate 	/* Values are developed in this buffer */
4957c478bd9Sstevel@tonic-gate 	wchar_t	buf[max(MAXLLDIGS, 1034)];
4967c478bd9Sstevel@tonic-gate 	wchar_t	cvtbuf[512 + DECIMAL_STRING_LENGTH];
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 	/* Pointer to sign, "0x", "0X", or empty */
4997c478bd9Sstevel@tonic-gate 	wchar_t	*prefix;
5007c478bd9Sstevel@tonic-gate 	wchar_t	prefixbuf[4];
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 	/* Exponent or empty */
5037c478bd9Sstevel@tonic-gate 	wchar_t	*suffix;
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate 	/* Buffer to create exponent */
5067c478bd9Sstevel@tonic-gate 	wchar_t	expbuf[MAXESIZ + 1];
5077c478bd9Sstevel@tonic-gate #else  /* _WIDE */
5087c478bd9Sstevel@tonic-gate 	/* Values are developed in this buffer */
5097c478bd9Sstevel@tonic-gate 	char	buf[max(MAXLLDIGS, 1034)];
5107c478bd9Sstevel@tonic-gate 	char	cvtbuf[512 + DECIMAL_STRING_LENGTH];
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 	/* Pointer to sign, "0x", "0X", or empty */
5137c478bd9Sstevel@tonic-gate 	char	*prefix;
5147c478bd9Sstevel@tonic-gate 	char	prefixbuf[4];
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate 	/* Exponent or empty */
5177c478bd9Sstevel@tonic-gate 	char	*suffix;
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 	/* Buffer to create exponent */
5207c478bd9Sstevel@tonic-gate 	char	expbuf[MAXESIZ + 1];
5217c478bd9Sstevel@tonic-gate #endif /* _WIDE */
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate 	/* Length of prefix and of suffix */
5247c478bd9Sstevel@tonic-gate 	ssize_t	prefixlength, suffixlength;
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 	/* Combined length of leading zeroes, trailing zeroes, and suffix */
5272829495dSToomas Soome 	ssize_t	otherlength;
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate 	/* The value being converted, if integer */
5307c478bd9Sstevel@tonic-gate 	ssize_t	val;
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate 	/* The value being converted, if long long */
5337c478bd9Sstevel@tonic-gate 	long long ll = 0LL;
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate 	/* Output value from aconvert */
5367c478bd9Sstevel@tonic-gate 	int	exp;
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate 	/* Output values from fcvt and ecvt */
5397c478bd9Sstevel@tonic-gate 	int	decpt, sign;
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate #ifdef	_WIDE
5427c478bd9Sstevel@tonic-gate 	/* Pointer to a translate table for digits of whatever radix */
5437c478bd9Sstevel@tonic-gate 	const wchar_t *tab;
5447c478bd9Sstevel@tonic-gate #else  /* _WIDE */
5457c478bd9Sstevel@tonic-gate 	/* Pointer to a translate table for digits of whatever radix */
5467c478bd9Sstevel@tonic-gate 	const char *tab;
5477c478bd9Sstevel@tonic-gate #endif /* _WIDE */
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate 	/* Work variables */
5507c478bd9Sstevel@tonic-gate 	ssize_t	k, lradix, mradix;
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate 	int	inf_nan = 0;
5537c478bd9Sstevel@tonic-gate 	int	inf_nan_mixed_case = 0;
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate #ifdef	_WIDE
5567c478bd9Sstevel@tonic-gate 	/* variables for positional parameters */
5577c478bd9Sstevel@tonic-gate 	/* save the beginning of the format */
5587c478bd9Sstevel@tonic-gate 	wchar_t *sformat = (wchar_t *)format;
5597c478bd9Sstevel@tonic-gate #else  /* _WIDE */
5607c478bd9Sstevel@tonic-gate 	/* variables for positional parameters */
5617c478bd9Sstevel@tonic-gate 	char *sformat = (char *)format; /* save the beginning of the format */
5627c478bd9Sstevel@tonic-gate #endif
5637c478bd9Sstevel@tonic-gate 
5647c478bd9Sstevel@tonic-gate 	int	fpos = 1;		/* 1 if first positional parameter */
5657c478bd9Sstevel@tonic-gate 	stva_list	args,	/* used to step through the argument list */
5668a67df42SToomas Soome 	    sargs;		/* used to save the start of the arg list */
5677c478bd9Sstevel@tonic-gate 	stva_list	bargs;	/* used to restore args if positional width */
5687c478bd9Sstevel@tonic-gate 				/* or precision */
5697c478bd9Sstevel@tonic-gate 	stva_list	arglst[MAXARGS]; /* array giving appropriate values */
5707c478bd9Sstevel@tonic-gate 					/* for va_arg() to retrieve the */
5717c478bd9Sstevel@tonic-gate 					/* corresponding argument: */
5727c478bd9Sstevel@tonic-gate 					/* arglst[0] is the first arg */
5737c478bd9Sstevel@tonic-gate 					/* arglst[1] is the second arg, etc */
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 	int	starflg = 0;	/* set to 1 if * format specifier seen */
576762f6727SJason King 
5777c478bd9Sstevel@tonic-gate 	/*
5787c478bd9Sstevel@tonic-gate 	 * Initialize args and sargs to the start of the argument list.
5797c478bd9Sstevel@tonic-gate 	 * We don't know any portable way to copy an arbitrary C object
5807c478bd9Sstevel@tonic-gate 	 * so we use a system-specific routine (probably a macro) from
5817c478bd9Sstevel@tonic-gate 	 * stdarg.h.  (Remember that if va_list is an array, in_args will
5827c478bd9Sstevel@tonic-gate 	 * be a pointer and &in_args won't be what we would want for
5837c478bd9Sstevel@tonic-gate 	 * memcpy.)
5847c478bd9Sstevel@tonic-gate 	 */
5857c478bd9Sstevel@tonic-gate 	va_copy(args.ap, in_args);
5867c478bd9Sstevel@tonic-gate 	sargs = args;
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate #ifdef	_WIDE
5897c478bd9Sstevel@tonic-gate 	if (iop->_flag == _IOREAD)
5907c478bd9Sstevel@tonic-gate 		sflag = 1;
5917c478bd9Sstevel@tonic-gate 
5927c478bd9Sstevel@tonic-gate 	if (!sflag) {
5937c478bd9Sstevel@tonic-gate #endif /* _WIDE */
5947c478bd9Sstevel@tonic-gate 	/* if first I/O to the stream get a buffer */
5957c478bd9Sstevel@tonic-gate 	/* Note that iop->_base should not equal 0 for sprintf and vsprintf */
5967c478bd9Sstevel@tonic-gate 	if (iop->_base == 0)  {
5978a67df42SToomas Soome 		if (_findbuf(iop) == 0)
5988a67df42SToomas Soome 			return (EOF);
5998a67df42SToomas Soome 		/*
6008a67df42SToomas Soome 		 * _findbuf leaves _cnt set to 0 which is the wrong thing
6018a67df42SToomas Soome 		 * to do for fully buffered files
6028a67df42SToomas Soome 		 */
6038a67df42SToomas Soome 		if (!(iop->_flag & (_IOLBF|_IONBF)))
6048a67df42SToomas Soome 			iop->_cnt = _bufend(iop) - iop->_base;
6057c478bd9Sstevel@tonic-gate 	}
6067c478bd9Sstevel@tonic-gate #ifdef	_WIDE
6077c478bd9Sstevel@tonic-gate 	}
6087c478bd9Sstevel@tonic-gate #endif /* _WIDE */
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate #ifdef	_WIDE
6117c478bd9Sstevel@tonic-gate 	bufptr = iop->_ptr;
6127c478bd9Sstevel@tonic-gate 	if (sflag) {
6137c478bd9Sstevel@tonic-gate 		maxcount = (size_t)iop->_cnt;
6147c478bd9Sstevel@tonic-gate 		bufferend = (unsigned char *)(((wchar_t *)iop->_ptr) +
6158a67df42SToomas Soome 		    maxcount);
6167c478bd9Sstevel@tonic-gate 	} else {
6177c478bd9Sstevel@tonic-gate 		bufferend = _bufend(iop);
6187c478bd9Sstevel@tonic-gate 	}
6197c478bd9Sstevel@tonic-gate #else  /* _WIDE */
6207c478bd9Sstevel@tonic-gate 	/* initialize buffer pointer and buffer end pointer */
6217c478bd9Sstevel@tonic-gate 	bufptr = iop->_ptr;
6227c478bd9Sstevel@tonic-gate 	if (iop->_flag & _IOREAD) {
6237c478bd9Sstevel@tonic-gate 		/*
6247c478bd9Sstevel@tonic-gate 		 * [v]sprintf or [v]snprintf
6257c478bd9Sstevel@tonic-gate 		 */
6267c478bd9Sstevel@tonic-gate 		if (iop->_cnt == MAXINT) {
6277c478bd9Sstevel@tonic-gate 			/*
6287c478bd9Sstevel@tonic-gate 			 * [v]sprintf (no boundschecking)
6297c478bd9Sstevel@tonic-gate 			 */
6307c478bd9Sstevel@tonic-gate 			bufferend =
6317c478bd9Sstevel@tonic-gate 			    (unsigned char *)((long)bufptr | (-1L & ~HIBITL));
6327c478bd9Sstevel@tonic-gate 		} else {
6337c478bd9Sstevel@tonic-gate 			/*
6347c478bd9Sstevel@tonic-gate 			 * [v]snprintf (with boundschecking) or
6357c478bd9Sstevel@tonic-gate 			 * iop with _IORW has been read.
6367c478bd9Sstevel@tonic-gate 			 */
6377c478bd9Sstevel@tonic-gate 			bufferend = _bufend(iop);
6387c478bd9Sstevel@tonic-gate 			if (bufferend == NULL) {
6397c478bd9Sstevel@tonic-gate 				/*
6407c478bd9Sstevel@tonic-gate 				 * [v]snprintf
6417c478bd9Sstevel@tonic-gate 				 *
6427c478bd9Sstevel@tonic-gate 				 * [v]snprint() needs to be always handled by
6437c478bd9Sstevel@tonic-gate 				 * _dowrite().
6447c478bd9Sstevel@tonic-gate 				 */
6457c478bd9Sstevel@tonic-gate 				snflag = 1;
6467c478bd9Sstevel@tonic-gate 			}
6477c478bd9Sstevel@tonic-gate 		}
6487c478bd9Sstevel@tonic-gate 	} else {
6497c478bd9Sstevel@tonic-gate 		/*
6507c478bd9Sstevel@tonic-gate 		 * [v]printf or [v]fprintf
6517c478bd9Sstevel@tonic-gate 		 */
6527c478bd9Sstevel@tonic-gate 		bufferend = _bufend(iop);
6537c478bd9Sstevel@tonic-gate 	}
6547c478bd9Sstevel@tonic-gate #endif /* _WIDE */
6557c478bd9Sstevel@tonic-gate 
6567c478bd9Sstevel@tonic-gate 	/*
6577c478bd9Sstevel@tonic-gate 	 *	The main loop -- this loop goes through one iteration
6587c478bd9Sstevel@tonic-gate 	 *	for each string of ordinary characters or format specification.
6597c478bd9Sstevel@tonic-gate 	 */
6607c478bd9Sstevel@tonic-gate 	for (; ; ) {
6617c478bd9Sstevel@tonic-gate 		ssize_t n;
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 		if ((fcode = *format) != '\0' && fcode != '%') {
6647c478bd9Sstevel@tonic-gate #ifdef	_WIDE
6657c478bd9Sstevel@tonic-gate 			bp = (wchar_t *)format;
6667c478bd9Sstevel@tonic-gate #else  /* _WIDE */
6677c478bd9Sstevel@tonic-gate 			bp = (char *)format;
6687c478bd9Sstevel@tonic-gate #endif /* _WIDE */
6697c478bd9Sstevel@tonic-gate 			do {
6707c478bd9Sstevel@tonic-gate 				format++;
6717c478bd9Sstevel@tonic-gate 			} while ((fcode = *format) != '\0' && fcode != '%');
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate 			count += (n = format - bp); /* n = no. of non-% chars */
6747c478bd9Sstevel@tonic-gate 			PUT(bp, n);
6757c478bd9Sstevel@tonic-gate 		}
6767c478bd9Sstevel@tonic-gate 		if (fcode == '\0') {  /* end of format; return */
6777c478bd9Sstevel@tonic-gate 			ssize_t nn = bufptr - iop->_ptr;
6787c478bd9Sstevel@tonic-gate 
6797c478bd9Sstevel@tonic-gate #ifdef	_WIDE
6807c478bd9Sstevel@tonic-gate 			if (sflag) {
6817c478bd9Sstevel@tonic-gate 				iop->_ptr = bufptr;
6827c478bd9Sstevel@tonic-gate 				return ((ssize_t)count);
6837c478bd9Sstevel@tonic-gate 			}
6847c478bd9Sstevel@tonic-gate #endif /* _WIDE */
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate 			iop->_cnt -= nn;
6877c478bd9Sstevel@tonic-gate 			iop->_ptr = bufptr;
6887c478bd9Sstevel@tonic-gate 			/* in case of interrupt during last several lines */
6897c478bd9Sstevel@tonic-gate 			if ((bufptr + iop->_cnt) > bufferend && !(iop->_flag \
6907c478bd9Sstevel@tonic-gate 			    & _IOREAD))
6917c478bd9Sstevel@tonic-gate 				_bufsync(iop, bufferend);
6927c478bd9Sstevel@tonic-gate 			if (iop->_flag & (_IONBF | _IOLBF) && \
6937c478bd9Sstevel@tonic-gate 			    (iop->_flag & _IONBF || \
6947c478bd9Sstevel@tonic-gate 			    memchr((char *)(bufptr+iop->_cnt), \
6957c478bd9Sstevel@tonic-gate 			    '\n', -iop->_cnt) != NULL))
6967c478bd9Sstevel@tonic-gate 				(void) _xflsbuf(iop);
6977c478bd9Sstevel@tonic-gate #ifdef	_WIDE
6987c478bd9Sstevel@tonic-gate 			return (FERROR(iop) ? EOF : (ssize_t)count);
6997c478bd9Sstevel@tonic-gate #else  /* _WIDE */
7007c478bd9Sstevel@tonic-gate 			return (FERROR(iop) ? EOF : (int)count);
7017c478bd9Sstevel@tonic-gate #endif /* _WIDE */
7027c478bd9Sstevel@tonic-gate 		}
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 		/*
7057c478bd9Sstevel@tonic-gate 		 *	% has been found.
7067c478bd9Sstevel@tonic-gate 		 *	The following switch is used to parse the format
7077c478bd9Sstevel@tonic-gate 		 *	specification and to perform the operation specified
7087c478bd9Sstevel@tonic-gate 		 *	by the format letter.  The program repeatedly goes
7097c478bd9Sstevel@tonic-gate 		 *	back to this switch until the format letter is
7107c478bd9Sstevel@tonic-gate 		 *	encountered.
7117c478bd9Sstevel@tonic-gate 		 */
7127c478bd9Sstevel@tonic-gate 		width = prefixlength = otherlength = 0;
7137c478bd9Sstevel@tonic-gate 		flagword = suffixlength = 0;
7147c478bd9Sstevel@tonic-gate 		format++;
7157c478bd9Sstevel@tonic-gate 		wflag = 0;
7167c478bd9Sstevel@tonic-gate 		lflag = 0;
7177c478bd9Sstevel@tonic-gate 		quote = 0;
7189c3b8506SToomas Soome #ifndef	_WIDE
7199c3b8506SToomas Soome 		sec_display = 0;
7209c3b8506SToomas Soome #endif
7217c478bd9Sstevel@tonic-gate 
7227c478bd9Sstevel@tonic-gate 	charswitch:
7237c478bd9Sstevel@tonic-gate 
7247c478bd9Sstevel@tonic-gate 		switch (fcode = *format++) {
7257c478bd9Sstevel@tonic-gate 
7267c478bd9Sstevel@tonic-gate 		case '+':
7277c478bd9Sstevel@tonic-gate 			flagword |= FPLUS;
7287c478bd9Sstevel@tonic-gate 			goto charswitch;
7297c478bd9Sstevel@tonic-gate 		case '-':
7307c478bd9Sstevel@tonic-gate 			flagword |= FMINUS;
7317c478bd9Sstevel@tonic-gate 			flagword &= ~PADZERO; /* ignore 0 flag */
7327c478bd9Sstevel@tonic-gate 			goto charswitch;
7337c478bd9Sstevel@tonic-gate 		case ' ':
7347c478bd9Sstevel@tonic-gate 			flagword |= FBLANK;
7357c478bd9Sstevel@tonic-gate 			goto charswitch;
7367c478bd9Sstevel@tonic-gate 		case '\'':	/* XSH4 */
7377c478bd9Sstevel@tonic-gate 			quote++;
7387c478bd9Sstevel@tonic-gate 			goto charswitch;
7397c478bd9Sstevel@tonic-gate 		case '#':
7407c478bd9Sstevel@tonic-gate 			flagword |= FSHARP;
7417c478bd9Sstevel@tonic-gate 			goto charswitch;
7427c478bd9Sstevel@tonic-gate 
7437c478bd9Sstevel@tonic-gate 		/* Scan the field width and precision */
7447c478bd9Sstevel@tonic-gate 		case '.':
7457c478bd9Sstevel@tonic-gate 			flagword |= DOTSEEN;
7467c478bd9Sstevel@tonic-gate 			prec = 0;
7477c478bd9Sstevel@tonic-gate 			goto charswitch;
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate 		case '*':
7507c478bd9Sstevel@tonic-gate 			if (_M_ISDIGIT(*format)) {
7517c478bd9Sstevel@tonic-gate 				starflg = 1;
7527c478bd9Sstevel@tonic-gate 				bargs = args;
7537c478bd9Sstevel@tonic-gate 				goto charswitch;
7547c478bd9Sstevel@tonic-gate 			}
7557c478bd9Sstevel@tonic-gate 			if (!(flagword & DOTSEEN)) {
7567c478bd9Sstevel@tonic-gate 				width = va_arg(args.ap, int);
7577c478bd9Sstevel@tonic-gate 				if (width < 0) {
7587c478bd9Sstevel@tonic-gate 					width = -width;
7597c478bd9Sstevel@tonic-gate 					flagword |= FMINUS;
7607c478bd9Sstevel@tonic-gate 				}
7617c478bd9Sstevel@tonic-gate 			} else {
7627c478bd9Sstevel@tonic-gate 				prec = va_arg(args.ap, int);
7637c478bd9Sstevel@tonic-gate 				if (prec < 0) {
7647c478bd9Sstevel@tonic-gate 					prec = 0;
7657c478bd9Sstevel@tonic-gate 					flagword ^= DOTSEEN; /* ANSI sez so */
7667c478bd9Sstevel@tonic-gate 				}
7677c478bd9Sstevel@tonic-gate 			}
7687c478bd9Sstevel@tonic-gate 			goto charswitch;
7697c478bd9Sstevel@tonic-gate 
7707c478bd9Sstevel@tonic-gate 		case '$':
7717c478bd9Sstevel@tonic-gate 			{
7727c478bd9Sstevel@tonic-gate 			ssize_t		position;
7737c478bd9Sstevel@tonic-gate 			stva_list	targs;
7747c478bd9Sstevel@tonic-gate 			if (fpos) {
7757c478bd9Sstevel@tonic-gate #ifdef	_WIDE
7767c478bd9Sstevel@tonic-gate 				_wmkarglst(sformat, sargs, arglst, prflag);
7777c478bd9Sstevel@tonic-gate #else  /* _WIDE */
7787c478bd9Sstevel@tonic-gate 				_mkarglst(sformat, sargs, arglst, prflag);
7797c478bd9Sstevel@tonic-gate #endif /* _WIDE */
7807c478bd9Sstevel@tonic-gate 				fpos = 0;
7817c478bd9Sstevel@tonic-gate 			}
7827c478bd9Sstevel@tonic-gate 			if (flagword & DOTSEEN) {
7837c478bd9Sstevel@tonic-gate 				position = prec;
7847c478bd9Sstevel@tonic-gate 				prec = 0;
7857c478bd9Sstevel@tonic-gate 			} else {
7867c478bd9Sstevel@tonic-gate 				position = width;
7877c478bd9Sstevel@tonic-gate 				width = 0;
7887c478bd9Sstevel@tonic-gate 			}
7897c478bd9Sstevel@tonic-gate 			if (position <= 0) {
7907c478bd9Sstevel@tonic-gate 				/* illegal position */
7917c478bd9Sstevel@tonic-gate 				format--;
7927c478bd9Sstevel@tonic-gate 				continue;
7937c478bd9Sstevel@tonic-gate 			}
7947c478bd9Sstevel@tonic-gate 			if (position <= MAXARGS) {
7957c478bd9Sstevel@tonic-gate 				targs = arglst[position - 1];
7967c478bd9Sstevel@tonic-gate 			} else {
7977c478bd9Sstevel@tonic-gate 				targs = arglst[MAXARGS - 1];
7987c478bd9Sstevel@tonic-gate #ifdef	_WIDE
7997c478bd9Sstevel@tonic-gate 				_wgetarg(sformat, &targs, position, prflag);
8007c478bd9Sstevel@tonic-gate #else  /* _WIDE */
8017c478bd9Sstevel@tonic-gate 				_getarg(sformat, &targs, position, prflag);
8027c478bd9Sstevel@tonic-gate #endif /* _WIDE */
8037c478bd9Sstevel@tonic-gate 			}
8047c478bd9Sstevel@tonic-gate 			if (!starflg)
8057c478bd9Sstevel@tonic-gate 				args = targs;
8067c478bd9Sstevel@tonic-gate 			else {
8077c478bd9Sstevel@tonic-gate 				starflg = 0;
8087c478bd9Sstevel@tonic-gate 				args = bargs;
8097c478bd9Sstevel@tonic-gate 				if (flagword & DOTSEEN) {
8107c478bd9Sstevel@tonic-gate 					prec = va_arg(targs.ap, int);
8117c478bd9Sstevel@tonic-gate 					if (prec < 0) {
8127c478bd9Sstevel@tonic-gate 						prec = 0;
8137c478bd9Sstevel@tonic-gate 						flagword ^= DOTSEEN; /* XSH */
8147c478bd9Sstevel@tonic-gate 					}
8157c478bd9Sstevel@tonic-gate 				} else {
8167c478bd9Sstevel@tonic-gate 					width = va_arg(targs.ap, int);
8177c478bd9Sstevel@tonic-gate 					if (width < 0) {
8187c478bd9Sstevel@tonic-gate 						width = -width;
8197c478bd9Sstevel@tonic-gate 						flagword |= FMINUS;
8207c478bd9Sstevel@tonic-gate 					}
8217c478bd9Sstevel@tonic-gate 				}
8227c478bd9Sstevel@tonic-gate 			}
8237c478bd9Sstevel@tonic-gate 			goto charswitch;
8247c478bd9Sstevel@tonic-gate 			}
8257c478bd9Sstevel@tonic-gate 
8267c478bd9Sstevel@tonic-gate 		case '0':	/* obsolescent spec:  leading zero in width */
8277c478bd9Sstevel@tonic-gate 				/* means pad with leading zeros */
8287c478bd9Sstevel@tonic-gate 			if (!(flagword & (DOTSEEN | FMINUS)))
8297c478bd9Sstevel@tonic-gate 				flagword |= PADZERO;
8307c478bd9Sstevel@tonic-gate 			/* FALLTHROUGH */
8317c478bd9Sstevel@tonic-gate 		case '1':
8327c478bd9Sstevel@tonic-gate 		case '2':
8337c478bd9Sstevel@tonic-gate 		case '3':
8347c478bd9Sstevel@tonic-gate 		case '4':
8357c478bd9Sstevel@tonic-gate 		case '5':
8367c478bd9Sstevel@tonic-gate 		case '6':
8377c478bd9Sstevel@tonic-gate 		case '7':
8387c478bd9Sstevel@tonic-gate 		case '8':
8397c478bd9Sstevel@tonic-gate 		case '9':
8408a67df42SToomas Soome 			num = fcode - '0';
8417c478bd9Sstevel@tonic-gate 			while (_M_ISDIGIT(fcode = *format)) {
8427c478bd9Sstevel@tonic-gate 				num = num * 10 + fcode - '0';
8437c478bd9Sstevel@tonic-gate 				format++;
8447c478bd9Sstevel@tonic-gate 			}
8457c478bd9Sstevel@tonic-gate 			if (flagword & DOTSEEN)
8467c478bd9Sstevel@tonic-gate 				prec = num;
8477c478bd9Sstevel@tonic-gate 			else
8487c478bd9Sstevel@tonic-gate 				width = num;
8497c478bd9Sstevel@tonic-gate 			goto charswitch;
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate 		/* Scan the length modifier */
8527c478bd9Sstevel@tonic-gate 		case 'l':
8537c478bd9Sstevel@tonic-gate 			if (!(flagword & XLONG)) {
8547c478bd9Sstevel@tonic-gate 				if (lflag) {
8557c478bd9Sstevel@tonic-gate 					/* long long */
8567c478bd9Sstevel@tonic-gate 					flagword &= ~LENGTH;
8577c478bd9Sstevel@tonic-gate 					flagword |= XLONG;
8587c478bd9Sstevel@tonic-gate 				} else	{
8597c478bd9Sstevel@tonic-gate 					/* long */
8607c478bd9Sstevel@tonic-gate 					flagword |= LENGTH;
8617c478bd9Sstevel@tonic-gate 				}
8627c478bd9Sstevel@tonic-gate 			}
8637c478bd9Sstevel@tonic-gate 			lflag++;
8647c478bd9Sstevel@tonic-gate 			goto charswitch;
8657c478bd9Sstevel@tonic-gate 
8667c478bd9Sstevel@tonic-gate 		case 'L':			/* long double */
8677c478bd9Sstevel@tonic-gate 			flagword |= QUAD;
8687c478bd9Sstevel@tonic-gate 			goto charswitch;
8697c478bd9Sstevel@tonic-gate 
8707c478bd9Sstevel@tonic-gate 		case 'h':
8717c478bd9Sstevel@tonic-gate 			if (!(flagword & CHAR)) {
8727c478bd9Sstevel@tonic-gate 				if (flagword & SHORT) {
8737c478bd9Sstevel@tonic-gate 					/* char - hh */
8747c478bd9Sstevel@tonic-gate 					flagword &= ~SHORT;
8757c478bd9Sstevel@tonic-gate 					flagword |= CHAR;
8767c478bd9Sstevel@tonic-gate 				} else {
8777c478bd9Sstevel@tonic-gate 					/* short */
8787c478bd9Sstevel@tonic-gate 					flagword |= SHORT;
8797c478bd9Sstevel@tonic-gate 				}
8807c478bd9Sstevel@tonic-gate 			}
8817c478bd9Sstevel@tonic-gate 			goto charswitch;
8827c478bd9Sstevel@tonic-gate 		case 'j':
8837c478bd9Sstevel@tonic-gate #ifndef _LP64
8847c478bd9Sstevel@tonic-gate 			/*
8857c478bd9Sstevel@tonic-gate 			 * *printf_c89() in 32-bit libc uses
8867c478bd9Sstevel@tonic-gate 			 * 32-bit intmax_t; otherwise intmax_t
8877c478bd9Sstevel@tonic-gate 			 * is 64-bits.
8887c478bd9Sstevel@tonic-gate 			 */
8897c478bd9Sstevel@tonic-gate 			if (!(prflag & _F_INTMAX32)) {
8907c478bd9Sstevel@tonic-gate #endif
8917c478bd9Sstevel@tonic-gate 				flagword |= XLONG;	/* [u]intmax_t (64) */
8927c478bd9Sstevel@tonic-gate #ifndef _LP64
8937c478bd9Sstevel@tonic-gate 			}
8947c478bd9Sstevel@tonic-gate #endif
8957c478bd9Sstevel@tonic-gate 			goto charswitch;
8967c478bd9Sstevel@tonic-gate 
8977c478bd9Sstevel@tonic-gate 		case 't':
8987c478bd9Sstevel@tonic-gate 			/*
8997c478bd9Sstevel@tonic-gate 			 * LENGTH is shared by l, t, z specifiers; protect
9007c478bd9Sstevel@tonic-gate 			 * against (destructive) undefined behavior (eg:
9017c478bd9Sstevel@tonic-gate 			 * avoid %llt setting XLONG and LENGTH) with invalid
9027c478bd9Sstevel@tonic-gate 			 * combinations of specifiers
9037c478bd9Sstevel@tonic-gate 			 */
9047c478bd9Sstevel@tonic-gate 			if (!(flagword & XLONG)) {
9057c478bd9Sstevel@tonic-gate 				flagword |= LENGTH;	/* ptrdiff_t */
9067c478bd9Sstevel@tonic-gate 			}
9077c478bd9Sstevel@tonic-gate 			goto charswitch;
9087c478bd9Sstevel@tonic-gate 
9097c478bd9Sstevel@tonic-gate 		case 'z':
9107c478bd9Sstevel@tonic-gate 			if (!(flagword & XLONG)) {
9117c478bd9Sstevel@tonic-gate 				flagword |= LENGTH;	/* [s]size_t */
9127c478bd9Sstevel@tonic-gate 			}
9137c478bd9Sstevel@tonic-gate 			goto charswitch;
9147c478bd9Sstevel@tonic-gate 
9157c478bd9Sstevel@tonic-gate 		/*
9167c478bd9Sstevel@tonic-gate 		 *	The character addressed by format must be
9177c478bd9Sstevel@tonic-gate 		 *	the format letter -- there is nothing
9187c478bd9Sstevel@tonic-gate 		 *	left for it to be.
9197c478bd9Sstevel@tonic-gate 		 *
9207c478bd9Sstevel@tonic-gate 		 *	The status of the +, -, #, and blank
9217c478bd9Sstevel@tonic-gate 		 *	flags are reflected in the variable
9227c478bd9Sstevel@tonic-gate 		 *	"flagword".  "width" and "prec" contain
9237c478bd9Sstevel@tonic-gate 		 *	numbers corresponding to the digit
9247c478bd9Sstevel@tonic-gate 		 *	strings before and after the decimal
9257c478bd9Sstevel@tonic-gate 		 *	point, respectively. If there was no
9267c478bd9Sstevel@tonic-gate 		 *	decimal point, then flagword & DOTSEEN
9277c478bd9Sstevel@tonic-gate 		 *	is false and the value of prec is meaningless.
9287c478bd9Sstevel@tonic-gate 		 *
9297c478bd9Sstevel@tonic-gate 		 *	The following switch cases set things up
9307c478bd9Sstevel@tonic-gate 		 *	for printing.  What ultimately gets
9317c478bd9Sstevel@tonic-gate 		 *	printed will be padding blanks, a
9327c478bd9Sstevel@tonic-gate 		 *	prefix, left padding zeroes, a value,
9337c478bd9Sstevel@tonic-gate 		 *	right padding zeroes, a suffix, and
9347c478bd9Sstevel@tonic-gate 		 *	more padding blanks.  Padding blanks
9357c478bd9Sstevel@tonic-gate 		 *	will not appear simultaneously on both
9367c478bd9Sstevel@tonic-gate 		 *	the left and the right.  Each case in
9377c478bd9Sstevel@tonic-gate 		 *	this switch will compute the value, and
9387c478bd9Sstevel@tonic-gate 		 *	leave in several variables the informa-
9397c478bd9Sstevel@tonic-gate 		 *	tion necessary to construct what is to
9407c478bd9Sstevel@tonic-gate 		 *	be printed.
9417c478bd9Sstevel@tonic-gate 		 *
9427c478bd9Sstevel@tonic-gate 		 *	The prefix is a sign, a blank, "0x",
9437c478bd9Sstevel@tonic-gate 		 *	"0X", a sign or a blank followed by "0x"
9447c478bd9Sstevel@tonic-gate 		 *	or "0X", or nothing, and is addressed by
9457c478bd9Sstevel@tonic-gate 		 *	"prefix".
9467c478bd9Sstevel@tonic-gate 		 *
9477c478bd9Sstevel@tonic-gate 		 *	The suffix is either null or an
9487c478bd9Sstevel@tonic-gate 		 *	exponent, and is addressed by "suffix".
9497c478bd9Sstevel@tonic-gate 		 *	If there is a suffix, the flagword bit
9507c478bd9Sstevel@tonic-gate 		 *	SUFFIX will be set.
9517c478bd9Sstevel@tonic-gate 		 *
9527c478bd9Sstevel@tonic-gate 		 *	The value to be printed starts at "bp"
9537c478bd9Sstevel@tonic-gate 		 *	and continues up to and not including
9547c478bd9Sstevel@tonic-gate 		 *	"p".
9557c478bd9Sstevel@tonic-gate 		 *
9567c478bd9Sstevel@tonic-gate 		 *	"lzero" and "rzero" will contain the
9577c478bd9Sstevel@tonic-gate 		 *	number of padding zeroes required on
9587c478bd9Sstevel@tonic-gate 		 *	the left and right, respectively.
9597c478bd9Sstevel@tonic-gate 		 *	The flagword bits LZERO and RZERO tell
9607c478bd9Sstevel@tonic-gate 		 *	whether padding zeros are required.
9617c478bd9Sstevel@tonic-gate 		 *
9627c478bd9Sstevel@tonic-gate 		 *	The number of padding blanks, and
9637c478bd9Sstevel@tonic-gate 		 *	whether they go on the left or the
9647c478bd9Sstevel@tonic-gate 		 *	right, will be computed on exit from
9657c478bd9Sstevel@tonic-gate 		 *	the switch.
9667c478bd9Sstevel@tonic-gate 		 */
9677c478bd9Sstevel@tonic-gate 
9687c478bd9Sstevel@tonic-gate 
9697c478bd9Sstevel@tonic-gate 
9707c478bd9Sstevel@tonic-gate 		/*
9717c478bd9Sstevel@tonic-gate 		 *	decimal fixed point representations
9727c478bd9Sstevel@tonic-gate 		 *
9737c478bd9Sstevel@tonic-gate 		 *	HIBITL is 100...000
9747c478bd9Sstevel@tonic-gate 		 *	binary, and is equal to	the maximum
9757c478bd9Sstevel@tonic-gate 		 *	negative number.
9767c478bd9Sstevel@tonic-gate 		 *	We assume a 2's complement machine
9777c478bd9Sstevel@tonic-gate 		 */
9787c478bd9Sstevel@tonic-gate 		case 'i':
9797c478bd9Sstevel@tonic-gate 		case 'd':
9807c478bd9Sstevel@tonic-gate 			if ((flagword & PADZERO) && (flagword & DOTSEEN))
9817c478bd9Sstevel@tonic-gate 				flagword &= ~PADZERO; /* ignore 0 flag */
9827c478bd9Sstevel@tonic-gate 			/* Set buffer pointer to last digit */
9837c478bd9Sstevel@tonic-gate 			p = bp = buf + MAXLLDIGS;
9847c478bd9Sstevel@tonic-gate 
9857c478bd9Sstevel@tonic-gate 			/* Fetch the argument to be printed */
9867c478bd9Sstevel@tonic-gate 			if (flagword & XLONG) {		/* long long */
9877c478bd9Sstevel@tonic-gate 				ll = va_arg(args.ap, long long);
9887c478bd9Sstevel@tonic-gate 
9897c478bd9Sstevel@tonic-gate 				/* If signed conversion, make sign */
9907c478bd9Sstevel@tonic-gate 				if (ll < 0) {
9917c478bd9Sstevel@tonic-gate 					prefix = _P_HYPHEN;
9927c478bd9Sstevel@tonic-gate 					prefixlength = 1;
9937c478bd9Sstevel@tonic-gate 					/*
9947c478bd9Sstevel@tonic-gate 					 * Negate, checking in advance for
9957c478bd9Sstevel@tonic-gate 					 * possible overflow.
9967c478bd9Sstevel@tonic-gate 					 */
9977c478bd9Sstevel@tonic-gate 					if (ll != HIBITLL)
9987c478bd9Sstevel@tonic-gate 						ll = -ll;
9997c478bd9Sstevel@tonic-gate 					else
10007c478bd9Sstevel@tonic-gate 					/* number is -HIBITLL; convert last */
10017c478bd9Sstevel@tonic-gate 					/* digit now and get positive number */
10027c478bd9Sstevel@tonic-gate 						*--bp = _lowlldigit(&ll);
10037c478bd9Sstevel@tonic-gate 				} else if (flagword & FPLUS) {
10047c478bd9Sstevel@tonic-gate 					prefix = _P_PLUS;
10057c478bd9Sstevel@tonic-gate 					prefixlength = 1;
10067c478bd9Sstevel@tonic-gate 				} else if (flagword & FBLANK) {
10077c478bd9Sstevel@tonic-gate 					prefix = _P_BLANK;
10087c478bd9Sstevel@tonic-gate 					prefixlength = 1;
10097c478bd9Sstevel@tonic-gate 				}
10107c478bd9Sstevel@tonic-gate 			} else {		/* not long long */
10117c478bd9Sstevel@tonic-gate 				if (flagword & LENGTH)
10127c478bd9Sstevel@tonic-gate 					val = va_arg(args.ap, long);
10137c478bd9Sstevel@tonic-gate 				else
10147c478bd9Sstevel@tonic-gate 					val = va_arg(args.ap, int);
10157c478bd9Sstevel@tonic-gate 
10167c478bd9Sstevel@tonic-gate 				if (flagword & SHORT)
10177c478bd9Sstevel@tonic-gate 					val = (short)val;
10187c478bd9Sstevel@tonic-gate 				else if (flagword & CHAR)
10197c478bd9Sstevel@tonic-gate 					val = (char)val;
10207c478bd9Sstevel@tonic-gate 
10217c478bd9Sstevel@tonic-gate 				/* If signed conversion, make sign */
10227c478bd9Sstevel@tonic-gate 				if (val < 0) {
10237c478bd9Sstevel@tonic-gate 					prefix = _P_HYPHEN;
10247c478bd9Sstevel@tonic-gate 					prefixlength = 1;
10257c478bd9Sstevel@tonic-gate 					/*
10267c478bd9Sstevel@tonic-gate 					 * Negate, checking in advance
10277c478bd9Sstevel@tonic-gate 					 * for possible overflow.
10287c478bd9Sstevel@tonic-gate 					 */
10297c478bd9Sstevel@tonic-gate 					if (val != HIBITL)
10307c478bd9Sstevel@tonic-gate 						val = -val;
10317c478bd9Sstevel@tonic-gate 					/*
10327c478bd9Sstevel@tonic-gate 					 * number is -HIBITL; convert
10337c478bd9Sstevel@tonic-gate 					 * last digit now and get
10347c478bd9Sstevel@tonic-gate 					 * positive number
10357c478bd9Sstevel@tonic-gate 					 */
10367c478bd9Sstevel@tonic-gate 					else
10377c478bd9Sstevel@tonic-gate 						*--bp = _lowdigit(&val);
10387c478bd9Sstevel@tonic-gate 				} else if (flagword & FPLUS) {
10397c478bd9Sstevel@tonic-gate 					prefix = _P_PLUS;
10407c478bd9Sstevel@tonic-gate 					prefixlength = 1;
10417c478bd9Sstevel@tonic-gate 				} else if (flagword & FBLANK) {
10427c478bd9Sstevel@tonic-gate 					prefix = _P_BLANK;
10437c478bd9Sstevel@tonic-gate 					prefixlength = 1;
10447c478bd9Sstevel@tonic-gate 				}
10457c478bd9Sstevel@tonic-gate 			}
10467c478bd9Sstevel@tonic-gate 
10477c478bd9Sstevel@tonic-gate 		decimal:
10487c478bd9Sstevel@tonic-gate 			{
10497c478bd9Sstevel@tonic-gate 			long qval = val;
10507c478bd9Sstevel@tonic-gate 			long long lll = ll;
10517c478bd9Sstevel@tonic-gate 			long long tll;
10527c478bd9Sstevel@tonic-gate 			if (flagword & XLONG) {
10537c478bd9Sstevel@tonic-gate 				if (lll < 10LL) {
10547c478bd9Sstevel@tonic-gate #ifdef	_WIDE
10557c478bd9Sstevel@tonic-gate 					if (lll != 0LL || !(flagword & DOTSEEN))
10567c478bd9Sstevel@tonic-gate 						*--bp = (wchar_t)lll + L'0';
10577c478bd9Sstevel@tonic-gate #else  /* _WIDE */
10587c478bd9Sstevel@tonic-gate 					if (lll != 0LL || !(flagword & DOTSEEN))
10597c478bd9Sstevel@tonic-gate 						*--bp = (char)lll + '0';
10607c478bd9Sstevel@tonic-gate #endif /* _WIDE */
10617c478bd9Sstevel@tonic-gate 				} else {
10627c478bd9Sstevel@tonic-gate 					do {
10637c478bd9Sstevel@tonic-gate 						tll = lll;
10647c478bd9Sstevel@tonic-gate 						lll /= 10;
10657c478bd9Sstevel@tonic-gate #ifdef	_WIDE
10667c478bd9Sstevel@tonic-gate 						*--bp = (wchar_t)
10678a67df42SToomas Soome 						    (tll - lll * 10 + '0');
10687c478bd9Sstevel@tonic-gate #else  /* _WIDE */
10697c478bd9Sstevel@tonic-gate 						*--bp = (char) \
10707c478bd9Sstevel@tonic-gate 						    (tll - lll * 10 + '0');
10717c478bd9Sstevel@tonic-gate #endif /* _WIDE */
10727c478bd9Sstevel@tonic-gate 					} while (lll >= 10);
10737c478bd9Sstevel@tonic-gate #ifdef	_WIDE
10747c478bd9Sstevel@tonic-gate 					*--bp = (wchar_t)lll + '0';
10757c478bd9Sstevel@tonic-gate #else  /* _WIDE */
10767c478bd9Sstevel@tonic-gate 					*--bp = (char)lll + '0';
10777c478bd9Sstevel@tonic-gate #endif /* _WIDE */
10787c478bd9Sstevel@tonic-gate 				}
10797c478bd9Sstevel@tonic-gate 			} else {
10807c478bd9Sstevel@tonic-gate 				if (qval <= 9) {
10817c478bd9Sstevel@tonic-gate #ifdef	_WIDE
10827c478bd9Sstevel@tonic-gate 					if (qval != 0 || !(flagword & DOTSEEN))
10837c478bd9Sstevel@tonic-gate 						*--bp = (wchar_t)qval + '0';
10847c478bd9Sstevel@tonic-gate #else  /* _WIDE */
10857c478bd9Sstevel@tonic-gate 					if (qval != 0 || !(flagword & DOTSEEN))
10867c478bd9Sstevel@tonic-gate 						*--bp = (char)qval + '0';
10877c478bd9Sstevel@tonic-gate #endif /* _WIDE */
10887c478bd9Sstevel@tonic-gate 				} else {
10897c478bd9Sstevel@tonic-gate 					do {
10907c478bd9Sstevel@tonic-gate 						n = qval;
10917c478bd9Sstevel@tonic-gate 						qval /= 10;
10927c478bd9Sstevel@tonic-gate #ifdef	_WIDE
10937c478bd9Sstevel@tonic-gate 						*--bp = (wchar_t) \
10947c478bd9Sstevel@tonic-gate 						    (n - qval * 10 + '0');
10957c478bd9Sstevel@tonic-gate #else  /* _WIDE */
10967c478bd9Sstevel@tonic-gate 						*--bp = (char) \
10977c478bd9Sstevel@tonic-gate 						    (n - qval * 10 + '0');
10987c478bd9Sstevel@tonic-gate #endif /* _WIDE */
10997c478bd9Sstevel@tonic-gate 					} while (qval > 9);
11007c478bd9Sstevel@tonic-gate #ifdef	_WIDE
11017c478bd9Sstevel@tonic-gate 					*--bp = (wchar_t)qval + '0';
11027c478bd9Sstevel@tonic-gate #else  /* _WIDE */
11037c478bd9Sstevel@tonic-gate 					*--bp = (char)qval + '0';
11047c478bd9Sstevel@tonic-gate #endif /* _WIDE */
11057c478bd9Sstevel@tonic-gate 				}
11067c478bd9Sstevel@tonic-gate 			}
11077c478bd9Sstevel@tonic-gate 			}
11087c478bd9Sstevel@tonic-gate 			/* Handle the ' flag */
11097c478bd9Sstevel@tonic-gate 			if (quote) {
11107c478bd9Sstevel@tonic-gate 				p = insert_thousands_sep(bp, p);
11117c478bd9Sstevel@tonic-gate 			}
11127c478bd9Sstevel@tonic-gate 
11137c478bd9Sstevel@tonic-gate 			/* Calculate minimum padding zero requirement */
11147c478bd9Sstevel@tonic-gate 			if (flagword & DOTSEEN) {
11157c478bd9Sstevel@tonic-gate 				leadzeroes = prec - (p - bp);
11167c478bd9Sstevel@tonic-gate 				if (leadzeroes > 0) {
11177c478bd9Sstevel@tonic-gate 					otherlength = lzero = leadzeroes;
11187c478bd9Sstevel@tonic-gate 					flagword |= LZERO;
11197c478bd9Sstevel@tonic-gate 				}
11207c478bd9Sstevel@tonic-gate 			}
11217c478bd9Sstevel@tonic-gate 			break;
11227c478bd9Sstevel@tonic-gate 
11237c478bd9Sstevel@tonic-gate 		case 'u':
11247c478bd9Sstevel@tonic-gate 			if ((flagword & PADZERO) && (flagword & DOTSEEN))
11257c478bd9Sstevel@tonic-gate 				flagword &= ~PADZERO; /* ignore 0 flag */
11267c478bd9Sstevel@tonic-gate 			p = bp = buf + MAXLLDIGS;
11277c478bd9Sstevel@tonic-gate 
11287c478bd9Sstevel@tonic-gate 			/* Fetch the argument to be printed */
11297c478bd9Sstevel@tonic-gate 			if (flagword & XLONG) {
11307c478bd9Sstevel@tonic-gate 				ll = va_arg(args.ap, long long);
11317c478bd9Sstevel@tonic-gate 
11327c478bd9Sstevel@tonic-gate 				if (ll & HIBITLL)
11337c478bd9Sstevel@tonic-gate 					*--bp = _lowlldigit(&ll);
11347c478bd9Sstevel@tonic-gate 			} else {
11357c478bd9Sstevel@tonic-gate 				if (flagword & LENGTH)
11367c478bd9Sstevel@tonic-gate 					val = va_arg(args.ap, long);
11377c478bd9Sstevel@tonic-gate 				else
11387c478bd9Sstevel@tonic-gate 					val = va_arg(args.ap, unsigned);
11397c478bd9Sstevel@tonic-gate 
11407c478bd9Sstevel@tonic-gate 				if (flagword & SHORT)
11417c478bd9Sstevel@tonic-gate 					val = (unsigned short)val;
11427c478bd9Sstevel@tonic-gate 				else if (flagword & CHAR)
11437c478bd9Sstevel@tonic-gate 					val = (unsigned char)val;
11447c478bd9Sstevel@tonic-gate 
11457c478bd9Sstevel@tonic-gate 				if (val & HIBITL)
11467c478bd9Sstevel@tonic-gate 					*--bp = _lowdigit(&val);
11477c478bd9Sstevel@tonic-gate 			}
11487c478bd9Sstevel@tonic-gate 
11497c478bd9Sstevel@tonic-gate 			goto decimal;
11507c478bd9Sstevel@tonic-gate 
11517c478bd9Sstevel@tonic-gate 		/*
11527c478bd9Sstevel@tonic-gate 		 *	non-decimal fixed point representations
11537c478bd9Sstevel@tonic-gate 		 *	for radix equal to a power of two
11547c478bd9Sstevel@tonic-gate 		 *
11557c478bd9Sstevel@tonic-gate 		 *	"mradix" is one less than the radix for the conversion.
11567c478bd9Sstevel@tonic-gate 		 *	"lradix" is one less than the base 2 log
11577c478bd9Sstevel@tonic-gate 		 *	of the radix for the conversion. Conversion is unsigned.
11587c478bd9Sstevel@tonic-gate 		 *	HIBITL is 100...000
11597c478bd9Sstevel@tonic-gate 		 *	binary, and is equal to	the maximum
11607c478bd9Sstevel@tonic-gate 		 *	negative number.
11617c478bd9Sstevel@tonic-gate 		 *	We assume a 2's complement machine
11627c478bd9Sstevel@tonic-gate 		 */
11637c478bd9Sstevel@tonic-gate 
11647c478bd9Sstevel@tonic-gate 		case 'o':
11657c478bd9Sstevel@tonic-gate 			mradix = 7;
11667c478bd9Sstevel@tonic-gate 			lradix = 2;
11677c478bd9Sstevel@tonic-gate 			/*
11687c478bd9Sstevel@tonic-gate 			 * DR151 and clarification in C90
11697c478bd9Sstevel@tonic-gate 			 * presence of '#' increases precision to first
11707c478bd9Sstevel@tonic-gate 			 * digit of the result to be zero
11717c478bd9Sstevel@tonic-gate 			 */
11727c478bd9Sstevel@tonic-gate 			if ((flagword & DOTSEEN) && (flagword & FSHARP) &&
11737c478bd9Sstevel@tonic-gate 			    prec == 0)
11747c478bd9Sstevel@tonic-gate 				prec = 1;
11757c478bd9Sstevel@tonic-gate 
11767c478bd9Sstevel@tonic-gate 			goto fixed;
11777c478bd9Sstevel@tonic-gate 
11787c478bd9Sstevel@tonic-gate 		case 'p':
11797c478bd9Sstevel@tonic-gate 			flagword &= ~(XLONG | SHORT);
11807c478bd9Sstevel@tonic-gate 			flagword |= LENGTH;
11817c478bd9Sstevel@tonic-gate 
11827c478bd9Sstevel@tonic-gate 			/* FALLTHRU */
11837c478bd9Sstevel@tonic-gate 		case 'X':
11847c478bd9Sstevel@tonic-gate 		case 'x':
11857c478bd9Sstevel@tonic-gate 			mradix = 15;
11867c478bd9Sstevel@tonic-gate 			lradix = 3;
11877c478bd9Sstevel@tonic-gate 
11887c478bd9Sstevel@tonic-gate 		fixed:
11897c478bd9Sstevel@tonic-gate 			if ((flagword & PADZERO) && (flagword & DOTSEEN))
11907c478bd9Sstevel@tonic-gate 				flagword &= ~PADZERO; /* ignore 0 flag */
11917c478bd9Sstevel@tonic-gate 
11927c478bd9Sstevel@tonic-gate #ifdef	_WIDE
11937c478bd9Sstevel@tonic-gate 			/* Set translate table for digits */
11947c478bd9Sstevel@tonic-gate 			tab = (wchar_t *)((fcode == 'X') ? uc_digs : lc_digs);
11957c478bd9Sstevel@tonic-gate #else  /* _WIDE */
11967c478bd9Sstevel@tonic-gate 			/* Set translate table for digits */
11977c478bd9Sstevel@tonic-gate 			tab = (fcode == 'X') ? uc_digs : lc_digs;
11987c478bd9Sstevel@tonic-gate #endif /* _WIDE */
11997c478bd9Sstevel@tonic-gate 
12007c478bd9Sstevel@tonic-gate 			/* Fetch the argument to be printed */
12017c478bd9Sstevel@tonic-gate 			if (flagword & XLONG) {
12027c478bd9Sstevel@tonic-gate 				ll = va_arg(args.ap, long long);
12037c478bd9Sstevel@tonic-gate 			} else {
12047c478bd9Sstevel@tonic-gate 				if (flagword & LENGTH)
12057c478bd9Sstevel@tonic-gate 					val = va_arg(args.ap, long);
12067c478bd9Sstevel@tonic-gate 				else
12077c478bd9Sstevel@tonic-gate 					val = va_arg(args.ap, unsigned);
12087c478bd9Sstevel@tonic-gate 
12097c478bd9Sstevel@tonic-gate 				if (flagword & SHORT)
12107c478bd9Sstevel@tonic-gate 					val = (unsigned short) val;
12117c478bd9Sstevel@tonic-gate 				else if (flagword & CHAR)
12127c478bd9Sstevel@tonic-gate 					val = (unsigned char) val;
12137c478bd9Sstevel@tonic-gate 			}
12147c478bd9Sstevel@tonic-gate 			p = bp = buf + MAXLLDIGS;
12157c478bd9Sstevel@tonic-gate 
12167c478bd9Sstevel@tonic-gate 			/* Develop the digits of the value */
12177c478bd9Sstevel@tonic-gate 			if (flagword & XLONG) {
12187c478bd9Sstevel@tonic-gate 				long long lll = ll;
12197c478bd9Sstevel@tonic-gate 
12207c478bd9Sstevel@tonic-gate 				if (lll == 0LL) {
12217c478bd9Sstevel@tonic-gate 					if (!(flagword & DOTSEEN)) {
12227c478bd9Sstevel@tonic-gate 						otherlength = lzero = 1;
12237c478bd9Sstevel@tonic-gate 						flagword |= LZERO;
12247c478bd9Sstevel@tonic-gate 					}
12257c478bd9Sstevel@tonic-gate 				} else do {
12267c478bd9Sstevel@tonic-gate 					*--bp = tab[(ssize_t)(lll & mradix)];
12277c478bd9Sstevel@tonic-gate 					lll = ((lll >> 1) & ~HIBITLL) \
12287c478bd9Sstevel@tonic-gate 					    >> lradix;
12297c478bd9Sstevel@tonic-gate 				} while (lll != 0LL);
12307c478bd9Sstevel@tonic-gate 			} else {
12317c478bd9Sstevel@tonic-gate 				long qval = val;
12327c478bd9Sstevel@tonic-gate 
12337c478bd9Sstevel@tonic-gate 				if (qval == 0) {
12347c478bd9Sstevel@tonic-gate 					if (!(flagword & DOTSEEN)) {
12357c478bd9Sstevel@tonic-gate 						otherlength = lzero = 1;
12367c478bd9Sstevel@tonic-gate 						flagword |= LZERO;
12377c478bd9Sstevel@tonic-gate 					}
12387c478bd9Sstevel@tonic-gate 				} else do {
12397c478bd9Sstevel@tonic-gate 					*--bp = tab[qval & mradix];
12407c478bd9Sstevel@tonic-gate 					qval = ((qval >> 1) & ~HIBITL) \
12417c478bd9Sstevel@tonic-gate 					    >> lradix;
12427c478bd9Sstevel@tonic-gate 				} while (qval != 0);
12437c478bd9Sstevel@tonic-gate 			}
12447c478bd9Sstevel@tonic-gate 
12457c478bd9Sstevel@tonic-gate 			/* Calculate minimum padding zero requirement */
12467c478bd9Sstevel@tonic-gate 			if (flagword & DOTSEEN) {
12477c478bd9Sstevel@tonic-gate 				leadzeroes = prec - (p - bp);
12487c478bd9Sstevel@tonic-gate 				if (leadzeroes > 0) {
12497c478bd9Sstevel@tonic-gate 					otherlength = lzero = leadzeroes;
12507c478bd9Sstevel@tonic-gate 					flagword |= LZERO;
12517c478bd9Sstevel@tonic-gate 				}
12527c478bd9Sstevel@tonic-gate 			}
12537c478bd9Sstevel@tonic-gate 
12547c478bd9Sstevel@tonic-gate 			/* Handle the # flag, (val != 0) for int and long */
12557c478bd9Sstevel@tonic-gate 			/* (ll!= 0) handles long long case */
12567c478bd9Sstevel@tonic-gate 			if ((flagword & FSHARP) &&
12577c478bd9Sstevel@tonic-gate 			    (((flagword & XLONG) == 0 && val != 0) ||
12587c478bd9Sstevel@tonic-gate 			    ((flagword & XLONG) == XLONG && ll != 0)))
12597c478bd9Sstevel@tonic-gate 				switch (fcode) {
12607c478bd9Sstevel@tonic-gate 				case 'o':
12617c478bd9Sstevel@tonic-gate 					if (!(flagword & LZERO)) {
12627c478bd9Sstevel@tonic-gate 						otherlength = lzero = 1;
12637c478bd9Sstevel@tonic-gate 						flagword |= LZERO;
12647c478bd9Sstevel@tonic-gate 					}
12657c478bd9Sstevel@tonic-gate 					break;
12667c478bd9Sstevel@tonic-gate 				case 'x':
12677c478bd9Sstevel@tonic-gate 					prefix = _P_ZEROx;
12687c478bd9Sstevel@tonic-gate 					prefixlength = 2;
12697c478bd9Sstevel@tonic-gate 					break;
12707c478bd9Sstevel@tonic-gate 				case 'X':
12717c478bd9Sstevel@tonic-gate 					prefix = _P_ZEROX;
12727c478bd9Sstevel@tonic-gate 					prefixlength = 2;
12737c478bd9Sstevel@tonic-gate 					break;
12747c478bd9Sstevel@tonic-gate 				}
12757c478bd9Sstevel@tonic-gate 
12767c478bd9Sstevel@tonic-gate 			break;
12777c478bd9Sstevel@tonic-gate 
12787c478bd9Sstevel@tonic-gate 		case 'A':
12797c478bd9Sstevel@tonic-gate 		case 'a':
12807c478bd9Sstevel@tonic-gate 			/* A format */
12817c478bd9Sstevel@tonic-gate 			if (flagword & QUAD) {
12827c478bd9Sstevel@tonic-gate 				long double	qval = GETQVAL(args.ap);
12837c478bd9Sstevel@tonic-gate 
12847c478bd9Sstevel@tonic-gate 				/* establish default precision */
12857c478bd9Sstevel@tonic-gate 				if (!(flagword & DOTSEEN))
12867c478bd9Sstevel@tonic-gate #if defined(__sparc)
12877c478bd9Sstevel@tonic-gate 					prec = HEXFP_QUAD_DIG - 1;
12887c478bd9Sstevel@tonic-gate #elif defined(__i386) || defined(__amd64)
12897c478bd9Sstevel@tonic-gate 					prec = HEXFP_EXTENDED_DIG - 1;
12907c478bd9Sstevel@tonic-gate #else
12917c478bd9Sstevel@tonic-gate #error Unknown architecture
12927c478bd9Sstevel@tonic-gate #endif
12937c478bd9Sstevel@tonic-gate 
12947c478bd9Sstevel@tonic-gate 				FPCONV(__qaconvert, &qval,
12957c478bd9Sstevel@tonic-gate 				    min(prec + 1, MAXECVT), &exp, &sign,
12967c478bd9Sstevel@tonic-gate 				    cvtbuf);
12977c478bd9Sstevel@tonic-gate 			} else {
12987c478bd9Sstevel@tonic-gate 				double	dval = va_arg(args.ap, double);
12997c478bd9Sstevel@tonic-gate 
13007c478bd9Sstevel@tonic-gate 				/* establish default precision */
13017c478bd9Sstevel@tonic-gate 				if (!(flagword & DOTSEEN))
13027c478bd9Sstevel@tonic-gate 					prec = HEXFP_DOUBLE_DIG - 1;
13037c478bd9Sstevel@tonic-gate 
13047c478bd9Sstevel@tonic-gate 				FPCONV(__aconvert, dval,
13057c478bd9Sstevel@tonic-gate 				    min(prec + 1, MAXECVT), &exp, &sign,
13067c478bd9Sstevel@tonic-gate 				    cvtbuf);
13077c478bd9Sstevel@tonic-gate 			}
13087c478bd9Sstevel@tonic-gate 			bp = cvtbuf;
13097c478bd9Sstevel@tonic-gate 
13107c478bd9Sstevel@tonic-gate 			/*
13117c478bd9Sstevel@tonic-gate 			 * The following is wide-character safe because
13127c478bd9Sstevel@tonic-gate 			 * __aconvert and __qaconvert only produce ASCII
13137c478bd9Sstevel@tonic-gate 			 * characters.
13147c478bd9Sstevel@tonic-gate 			 */
13157c478bd9Sstevel@tonic-gate 			if (!isxdigit((unsigned char)*bp)) {
13167c478bd9Sstevel@tonic-gate 				inf_nan = 1;
13177c478bd9Sstevel@tonic-gate 				break;
13187c478bd9Sstevel@tonic-gate 			}
13197c478bd9Sstevel@tonic-gate 
13207c478bd9Sstevel@tonic-gate 			/*
13217c478bd9Sstevel@tonic-gate 			 * Create the prefix.  We ought to use the strings
13227c478bd9Sstevel@tonic-gate 			 * defined above (_P_HYPHEN, etc.), but that would
13237c478bd9Sstevel@tonic-gate 			 * be awkward: we'd either have to define six more
13247c478bd9Sstevel@tonic-gate 			 * of them or we'd have to use strcpy/strcat to
13257c478bd9Sstevel@tonic-gate 			 * assemble the ones already defined.  So instead,
13267c478bd9Sstevel@tonic-gate 			 * we just build the prefix character by character.
13277c478bd9Sstevel@tonic-gate 			 */
13287c478bd9Sstevel@tonic-gate 			p = prefix = prefixbuf;
13297c478bd9Sstevel@tonic-gate 			if (sign) {
13307c478bd9Sstevel@tonic-gate 				*p++ = '-';
13317c478bd9Sstevel@tonic-gate 				prefixlength = 1;
13327c478bd9Sstevel@tonic-gate 			} else if (flagword & FPLUS) {
13337c478bd9Sstevel@tonic-gate 				*p++ = '+';
13347c478bd9Sstevel@tonic-gate 				prefixlength = 1;
13357c478bd9Sstevel@tonic-gate 			} else if (flagword & FBLANK) {
13367c478bd9Sstevel@tonic-gate 				*p++ = ' ';
13377c478bd9Sstevel@tonic-gate 				prefixlength = 1;
13387c478bd9Sstevel@tonic-gate 			}
13397c478bd9Sstevel@tonic-gate 			*p++ = '0';
13407c478bd9Sstevel@tonic-gate 			*p++ = (fcode == 'A') ? 'X' : 'x';
13417c478bd9Sstevel@tonic-gate 			*p = '\0';
13427c478bd9Sstevel@tonic-gate 			prefixlength += 2;
13437c478bd9Sstevel@tonic-gate 
13447c478bd9Sstevel@tonic-gate 			/* put the first digit in the buffer */
13457c478bd9Sstevel@tonic-gate 			p = &buf[0];
13467c478bd9Sstevel@tonic-gate 			*p++ = (*bp != '\0') ? *bp++ : '0';
13477c478bd9Sstevel@tonic-gate 
1348804635d7SYuri Pankov 			/* Put in a decimal point if needed */
13497c478bd9Sstevel@tonic-gate 			if (prec != 0 || (flagword & FSHARP))
1350804635d7SYuri Pankov 				p = insert_decimal_point(p);
13517c478bd9Sstevel@tonic-gate 
1352804635d7SYuri Pankov 			/* Create the rest of the mantissa */
13537c478bd9Sstevel@tonic-gate 			rz = prec;
13547c478bd9Sstevel@tonic-gate 			if (fcode == 'A') {
13557c478bd9Sstevel@tonic-gate 				for (; rz > 0 && *bp != '\0'; --rz) {
13567c478bd9Sstevel@tonic-gate 					*p++ = ('a' <= *bp && *bp <= 'f')?
13577c478bd9Sstevel@tonic-gate 					    *bp - 32 : *bp;
13587c478bd9Sstevel@tonic-gate 					bp++;
13597c478bd9Sstevel@tonic-gate 				}
13607c478bd9Sstevel@tonic-gate 			} else {
13617c478bd9Sstevel@tonic-gate 				for (; rz > 0 && *bp != '\0'; --rz)
13627c478bd9Sstevel@tonic-gate 					*p++ = *bp++;
13637c478bd9Sstevel@tonic-gate 			}
13647c478bd9Sstevel@tonic-gate 			if (rz > 0) {
13657c478bd9Sstevel@tonic-gate 				otherlength = rzero = rz;
13667c478bd9Sstevel@tonic-gate 				flagword |= RZERO;
13677c478bd9Sstevel@tonic-gate 			}
13687c478bd9Sstevel@tonic-gate 
13697c478bd9Sstevel@tonic-gate 			bp = &buf[0];
13707c478bd9Sstevel@tonic-gate 
13717c478bd9Sstevel@tonic-gate 			/*
13727c478bd9Sstevel@tonic-gate 			 * Create the exponent in right-to-left order.
13737c478bd9Sstevel@tonic-gate 			 * buf[0] == '0' if and only if the value being
13747c478bd9Sstevel@tonic-gate 			 * converted is exactly zero, in which case the
13757c478bd9Sstevel@tonic-gate 			 * exponent should be +0 regardless of exp.
13767c478bd9Sstevel@tonic-gate 			 */
13777c478bd9Sstevel@tonic-gate 			suffix = &expbuf[MAXESIZ];
13787c478bd9Sstevel@tonic-gate 			*suffix = '\0';
13797c478bd9Sstevel@tonic-gate 			if (buf[0] != '0') {
13807c478bd9Sstevel@tonic-gate 				int	nn;
13817c478bd9Sstevel@tonic-gate 
13827c478bd9Sstevel@tonic-gate 				nn = exp;
13837c478bd9Sstevel@tonic-gate 				if (nn < 0)
13848a67df42SToomas Soome 					nn = -nn;
13857c478bd9Sstevel@tonic-gate 				for (; nn > 9; nn /= 10)
13867c478bd9Sstevel@tonic-gate 					*--suffix = todigit(nn % 10);
13877c478bd9Sstevel@tonic-gate 				*--suffix = todigit(nn);
13887c478bd9Sstevel@tonic-gate 				*--suffix = (exp >= 0) ? '+' : '-';
13897c478bd9Sstevel@tonic-gate 			} else {
13907c478bd9Sstevel@tonic-gate 				*--suffix = '0';
13917c478bd9Sstevel@tonic-gate 				*--suffix = '+';
13927c478bd9Sstevel@tonic-gate 			}
13937c478bd9Sstevel@tonic-gate 
13947c478bd9Sstevel@tonic-gate 			/* put in the p */
13957c478bd9Sstevel@tonic-gate 			*--suffix = (fcode == 'A') ? 'P' : 'p';
13967c478bd9Sstevel@tonic-gate 
13977c478bd9Sstevel@tonic-gate 			/* compute size of suffix */
13987c478bd9Sstevel@tonic-gate 			suffixlength = &expbuf[MAXESIZ] - suffix;
13997c478bd9Sstevel@tonic-gate 			otherlength += suffixlength;
14007c478bd9Sstevel@tonic-gate 			flagword |= SUFFIX;
14017c478bd9Sstevel@tonic-gate 			break;
14027c478bd9Sstevel@tonic-gate 
14037c478bd9Sstevel@tonic-gate 		case 'E':
14047c478bd9Sstevel@tonic-gate 		case 'e':
14057c478bd9Sstevel@tonic-gate 			/*
14067c478bd9Sstevel@tonic-gate 			 * E-format.  The general strategy
14077c478bd9Sstevel@tonic-gate 			 * here is fairly easy: we take what
14087c478bd9Sstevel@tonic-gate 			 * econvert gives us and re-format it.
14097c478bd9Sstevel@tonic-gate 			 * (qeconvert for long double)
14107c478bd9Sstevel@tonic-gate 			 */
14117c478bd9Sstevel@tonic-gate 
14127c478bd9Sstevel@tonic-gate 			/* Establish default precision */
14137c478bd9Sstevel@tonic-gate 			if (!(flagword & DOTSEEN))
14147c478bd9Sstevel@tonic-gate 				prec = 6;
14157c478bd9Sstevel@tonic-gate 
14167c478bd9Sstevel@tonic-gate 			if (flagword & QUAD) {	/* long double */
14177c478bd9Sstevel@tonic-gate 				long double	qval = GETQVAL(args.ap);
14187c478bd9Sstevel@tonic-gate 
14197c478bd9Sstevel@tonic-gate 				FPCONV(qeconvert, &qval,
14207c478bd9Sstevel@tonic-gate 				    min(prec + 1, MAXECVT), &decpt, &sign,
14217c478bd9Sstevel@tonic-gate 				    cvtbuf);
14227c478bd9Sstevel@tonic-gate 			} else {	/* double */
14237c478bd9Sstevel@tonic-gate 				double	dval = va_arg(args.ap, double);
14247c478bd9Sstevel@tonic-gate 
14257c478bd9Sstevel@tonic-gate 				FPCONV(econvert, dval,
14267c478bd9Sstevel@tonic-gate 				    min(prec + 1, MAXECVT), &decpt, &sign,
14277c478bd9Sstevel@tonic-gate 				    cvtbuf);
14287c478bd9Sstevel@tonic-gate 			}
14297c478bd9Sstevel@tonic-gate 			bp = cvtbuf;
14307c478bd9Sstevel@tonic-gate 			if (*bp > '9') {
14317c478bd9Sstevel@tonic-gate 				inf_nan = 1;
14327c478bd9Sstevel@tonic-gate 				inf_nan_mixed_case = (__xpg6 &
14337c478bd9Sstevel@tonic-gate 				    _C99SUSv3_mixed_case_Inf_and_NaN);
14347c478bd9Sstevel@tonic-gate 				break;
14357c478bd9Sstevel@tonic-gate 			}
14367c478bd9Sstevel@tonic-gate 
14377c478bd9Sstevel@tonic-gate 			/* Determine the prefix */
14387c478bd9Sstevel@tonic-gate 		e_merge:
14397c478bd9Sstevel@tonic-gate 			if (sign) {
14407c478bd9Sstevel@tonic-gate 				prefix = _P_HYPHEN;
14417c478bd9Sstevel@tonic-gate 				prefixlength = 1;
14427c478bd9Sstevel@tonic-gate 			} else if (flagword & FPLUS) {
14437c478bd9Sstevel@tonic-gate 				prefix = _P_PLUS;
14447c478bd9Sstevel@tonic-gate 				prefixlength = 1;
14457c478bd9Sstevel@tonic-gate 			} else if (flagword & FBLANK) {
14467c478bd9Sstevel@tonic-gate 				prefix = _P_BLANK;
14477c478bd9Sstevel@tonic-gate 				prefixlength = 1;
14487c478bd9Sstevel@tonic-gate 			}
14497c478bd9Sstevel@tonic-gate 
14507c478bd9Sstevel@tonic-gate 			/* Place the first digit in the buffer */
14517c478bd9Sstevel@tonic-gate 			p = &buf[0];
14527c478bd9Sstevel@tonic-gate 			*p++ = (*bp != '\0') ? *bp++ : '0';
14537c478bd9Sstevel@tonic-gate 
14547c478bd9Sstevel@tonic-gate 			/* Put in a decimal point if needed */
14557c478bd9Sstevel@tonic-gate 			if (prec != 0 || (flagword & FSHARP))
1456804635d7SYuri Pankov 				p = insert_decimal_point(p);
14577c478bd9Sstevel@tonic-gate 
14587c478bd9Sstevel@tonic-gate 			/* Create the rest of the mantissa */
14597c478bd9Sstevel@tonic-gate 			rz = prec;
14607c478bd9Sstevel@tonic-gate 			for (; rz > 0 && *bp != '\0'; --rz)
14617c478bd9Sstevel@tonic-gate 				*p++ = *bp++;
14627c478bd9Sstevel@tonic-gate 			if (rz > 0) {
14637c478bd9Sstevel@tonic-gate 				otherlength = rzero = rz;
14647c478bd9Sstevel@tonic-gate 				flagword |= RZERO;
14657c478bd9Sstevel@tonic-gate 			}
14667c478bd9Sstevel@tonic-gate 
14677c478bd9Sstevel@tonic-gate 			bp = &buf[0];
14687c478bd9Sstevel@tonic-gate 
14697c478bd9Sstevel@tonic-gate 			/*
14707c478bd9Sstevel@tonic-gate 			 * Create the exponent.  buf[0] == '0' if and
14717c478bd9Sstevel@tonic-gate 			 * only if the value being converted is exactly
14727c478bd9Sstevel@tonic-gate 			 * zero, in which case the exponent should be
14737c478bd9Sstevel@tonic-gate 			 * +0 regardless of decpt.
14747c478bd9Sstevel@tonic-gate 			 */
14757c478bd9Sstevel@tonic-gate 			*(suffix = &expbuf[MAXESIZ]) = '\0';
14767c478bd9Sstevel@tonic-gate 			if (buf[0] != '0') {
14777c478bd9Sstevel@tonic-gate 				int nn = decpt - 1;
14787c478bd9Sstevel@tonic-gate 				if (nn < 0)
14798a67df42SToomas Soome 					nn = -nn;
14807c478bd9Sstevel@tonic-gate 				for (; nn > 9; nn /= 10)
14817c478bd9Sstevel@tonic-gate 					*--suffix = todigit(nn % 10);
14827c478bd9Sstevel@tonic-gate 				*--suffix = todigit(nn);
14837c478bd9Sstevel@tonic-gate 			}
14847c478bd9Sstevel@tonic-gate 
14857c478bd9Sstevel@tonic-gate 			/* Prepend leading zeroes to the exponent */
14867c478bd9Sstevel@tonic-gate 			while (suffix > &expbuf[MAXESIZ - 2])
14877c478bd9Sstevel@tonic-gate 				*--suffix = '0';
14887c478bd9Sstevel@tonic-gate 
14897c478bd9Sstevel@tonic-gate 			/* Put in the exponent sign */
14907c478bd9Sstevel@tonic-gate 			*--suffix = (decpt > 0 || buf[0] == '0') ? '+' : '-';
14917c478bd9Sstevel@tonic-gate 
14927c478bd9Sstevel@tonic-gate 			/* Put in the e */
14937c478bd9Sstevel@tonic-gate 			*--suffix = _M_ISUPPER(fcode) ? 'E'  : 'e';
14947c478bd9Sstevel@tonic-gate 
14957c478bd9Sstevel@tonic-gate 			/* compute size of suffix */
14967c478bd9Sstevel@tonic-gate 			otherlength += (suffixlength = &expbuf[MAXESIZ] \
14977c478bd9Sstevel@tonic-gate 			    - suffix);
14987c478bd9Sstevel@tonic-gate 			flagword |= SUFFIX;
14997c478bd9Sstevel@tonic-gate 			break;
15007c478bd9Sstevel@tonic-gate 
15017c478bd9Sstevel@tonic-gate 		case 'F':
15027c478bd9Sstevel@tonic-gate 		case 'f':
15037c478bd9Sstevel@tonic-gate 			/*
15047c478bd9Sstevel@tonic-gate 			 * F-format floating point.  This is a
15057c478bd9Sstevel@tonic-gate 			 * good deal less simple than E-format.
15067c478bd9Sstevel@tonic-gate 			 * The overall strategy will be to call
15077c478bd9Sstevel@tonic-gate 			 * fconvert, reformat its result into buf,
15087c478bd9Sstevel@tonic-gate 			 * and calculate how many trailing
15097c478bd9Sstevel@tonic-gate 			 * zeroes will be required.  There will
15107c478bd9Sstevel@tonic-gate 			 * never be any leading zeroes needed.
15117c478bd9Sstevel@tonic-gate 			 * (qfconvert for long double)
15127c478bd9Sstevel@tonic-gate 			 */
15137c478bd9Sstevel@tonic-gate 
15147c478bd9Sstevel@tonic-gate 			/* Establish default precision */
15157c478bd9Sstevel@tonic-gate 			if (!(flagword & DOTSEEN))
15167c478bd9Sstevel@tonic-gate 				prec = 6;
15177c478bd9Sstevel@tonic-gate 
15187c478bd9Sstevel@tonic-gate 			if (flagword & QUAD) {	/* long double */
15197c478bd9Sstevel@tonic-gate 				long double	qval = GETQVAL(args.ap);
15207c478bd9Sstevel@tonic-gate 
15217c478bd9Sstevel@tonic-gate 				FPCONV(qfconvert, &qval, min(prec, MAXFCVT),
15227c478bd9Sstevel@tonic-gate 				    &decpt, &sign, cvtbuf);
15237c478bd9Sstevel@tonic-gate 				bp = cvtbuf;
15247c478bd9Sstevel@tonic-gate 				if (*bp == 0) {
15257c478bd9Sstevel@tonic-gate 					/*
15267c478bd9Sstevel@tonic-gate 					 * qfconvert would have required
15277c478bd9Sstevel@tonic-gate 					 * too many characters; use qeconvert
15287c478bd9Sstevel@tonic-gate 					 * instead
15297c478bd9Sstevel@tonic-gate 					 */
15307c478bd9Sstevel@tonic-gate 					FPCONV(qeconvert, &qval,
15317c478bd9Sstevel@tonic-gate 					    min(prec + 1, MAXECVT), &decpt,
15327c478bd9Sstevel@tonic-gate 					    &sign, cvtbuf);
15337c478bd9Sstevel@tonic-gate 					goto e_merge;
15347c478bd9Sstevel@tonic-gate 				}
15357c478bd9Sstevel@tonic-gate 			} else {	/* double */
15367c478bd9Sstevel@tonic-gate 				double	dval = va_arg(args.ap, double);
15377c478bd9Sstevel@tonic-gate 
15387c478bd9Sstevel@tonic-gate 				FPCONV(fconvert, dval, min(prec, MAXFCVT),
15397c478bd9Sstevel@tonic-gate 				    &decpt, &sign, cvtbuf);
15407c478bd9Sstevel@tonic-gate 			}
15417c478bd9Sstevel@tonic-gate 			bp = cvtbuf;
15427c478bd9Sstevel@tonic-gate 			if (*bp > '9') {
15437c478bd9Sstevel@tonic-gate 				inf_nan = 1;
15447c478bd9Sstevel@tonic-gate 				if (fcode == 'f')
15457c478bd9Sstevel@tonic-gate 					inf_nan_mixed_case = (__xpg6 &
15467c478bd9Sstevel@tonic-gate 					    _C99SUSv3_mixed_case_Inf_and_NaN);
15477c478bd9Sstevel@tonic-gate 				break;
15487c478bd9Sstevel@tonic-gate 			}
15497c478bd9Sstevel@tonic-gate 
15507c478bd9Sstevel@tonic-gate 			/* Determine the prefix */
15517c478bd9Sstevel@tonic-gate 		f_merge:
15527c478bd9Sstevel@tonic-gate 			if (sign) {
15537c478bd9Sstevel@tonic-gate 				prefix = _P_HYPHEN;
15547c478bd9Sstevel@tonic-gate 				prefixlength = 1;
15557c478bd9Sstevel@tonic-gate 			} else if (flagword & FPLUS) {
15567c478bd9Sstevel@tonic-gate 				prefix = _P_PLUS;
15577c478bd9Sstevel@tonic-gate 				prefixlength = 1;
15587c478bd9Sstevel@tonic-gate 			} else if (flagword & FBLANK) {
15597c478bd9Sstevel@tonic-gate 				prefix = _P_BLANK;
15607c478bd9Sstevel@tonic-gate 				prefixlength = 1;
15617c478bd9Sstevel@tonic-gate 			}
15627c478bd9Sstevel@tonic-gate 
15637c478bd9Sstevel@tonic-gate 			/* Initialize buffer pointer */
15647c478bd9Sstevel@tonic-gate 			p = &buf[0];
15657c478bd9Sstevel@tonic-gate 
15667c478bd9Sstevel@tonic-gate 			{
15677c478bd9Sstevel@tonic-gate 				ssize_t nn = decpt;
15687c478bd9Sstevel@tonic-gate 
15697c478bd9Sstevel@tonic-gate 				/* Emit the digits before the decimal point */
15707c478bd9Sstevel@tonic-gate 				k = 0;
15717c478bd9Sstevel@tonic-gate 				do {
15727c478bd9Sstevel@tonic-gate 					*p++ = (nn <= 0 || *bp == '\0' || \
15737c478bd9Sstevel@tonic-gate 					    k >= MAXFSIG) ? '0' : (k++, *bp++);
15747c478bd9Sstevel@tonic-gate 				} while (--nn > 0);
15757c478bd9Sstevel@tonic-gate 
15767c478bd9Sstevel@tonic-gate 				if (quote)
15777c478bd9Sstevel@tonic-gate 					p = insert_thousands_sep(buf, p);
15787c478bd9Sstevel@tonic-gate 
1579804635d7SYuri Pankov 				/* Put in a decimal point if needed */
1580f3992799SYuri Pankov 				if (prec > 0 || (flagword & FSHARP))
1581804635d7SYuri Pankov 					p = insert_decimal_point(p);
15827c478bd9Sstevel@tonic-gate 
15837c478bd9Sstevel@tonic-gate 				/* Digits (if any) after the decimal point */
15847c478bd9Sstevel@tonic-gate 				nn = min(prec, MAXFCVT);
15857c478bd9Sstevel@tonic-gate 				if (prec > nn) {
15867c478bd9Sstevel@tonic-gate 					flagword |= RZERO;
15877c478bd9Sstevel@tonic-gate 					otherlength = rzero = prec - nn;
15887c478bd9Sstevel@tonic-gate 				}
15897c478bd9Sstevel@tonic-gate 				while (--nn >= 0)
15907c478bd9Sstevel@tonic-gate 					*p++ = (++decpt <= 0 || *bp == '\0' || \
15917c478bd9Sstevel@tonic-gate 					    k >= MAXFSIG) ? '0' : (k++, *bp++);
15927c478bd9Sstevel@tonic-gate 			}
15937c478bd9Sstevel@tonic-gate 
15947c478bd9Sstevel@tonic-gate 			bp = &buf[0];
15957c478bd9Sstevel@tonic-gate 
15967c478bd9Sstevel@tonic-gate 			break;
15977c478bd9Sstevel@tonic-gate 
15987c478bd9Sstevel@tonic-gate 		case 'G':
15997c478bd9Sstevel@tonic-gate 		case 'g':
16007c478bd9Sstevel@tonic-gate 			/*
16017c478bd9Sstevel@tonic-gate 			 * g-format.  We play around a bit
16027c478bd9Sstevel@tonic-gate 			 * and then jump into e or f, as needed.
16037c478bd9Sstevel@tonic-gate 			 */
16047c478bd9Sstevel@tonic-gate 
16057c478bd9Sstevel@tonic-gate 			/* Establish default precision */
16067c478bd9Sstevel@tonic-gate 			if (!(flagword & DOTSEEN))
16077c478bd9Sstevel@tonic-gate 				prec = 6;
16087c478bd9Sstevel@tonic-gate 			else if (prec == 0)
16097c478bd9Sstevel@tonic-gate 				prec = 1;
16107c478bd9Sstevel@tonic-gate 
16117c478bd9Sstevel@tonic-gate 			if (flagword & QUAD) {	/* long double */
16127c478bd9Sstevel@tonic-gate 				long double	qval = GETQVAL(args.ap);
16137c478bd9Sstevel@tonic-gate 
16147c478bd9Sstevel@tonic-gate 				FPCONV(qeconvert, &qval, min(prec, MAXECVT),
16157c478bd9Sstevel@tonic-gate 				    &decpt, &sign, cvtbuf);
16167c478bd9Sstevel@tonic-gate 			} else {	/* double */
16177c478bd9Sstevel@tonic-gate 				double	dval = va_arg(args.ap, double);
16187c478bd9Sstevel@tonic-gate 
16197c478bd9Sstevel@tonic-gate 				FPCONV(econvert, dval, min(prec, MAXECVT),
16207c478bd9Sstevel@tonic-gate 				    &decpt, &sign, cvtbuf);
16217c478bd9Sstevel@tonic-gate 			}
16227c478bd9Sstevel@tonic-gate 			bp = cvtbuf;
16237c478bd9Sstevel@tonic-gate 			if (*bp > '9') {
16247c478bd9Sstevel@tonic-gate 				inf_nan = 1;
16257c478bd9Sstevel@tonic-gate 				inf_nan_mixed_case = (__xpg6 &
16267c478bd9Sstevel@tonic-gate 				    _C99SUSv3_mixed_case_Inf_and_NaN);
16277c478bd9Sstevel@tonic-gate 				break;
16287c478bd9Sstevel@tonic-gate 			}
16297c478bd9Sstevel@tonic-gate 			if (*bp == '0')	/* the value converted is zero */
16307c478bd9Sstevel@tonic-gate 				decpt = 1;
16317c478bd9Sstevel@tonic-gate 
16327c478bd9Sstevel@tonic-gate 			{
16337c478bd9Sstevel@tonic-gate 				int kk = prec;
16347c478bd9Sstevel@tonic-gate 				if (!(flagword & FSHARP)) {
16357c478bd9Sstevel@tonic-gate #ifdef	_WIDE
16367c478bd9Sstevel@tonic-gate 					n = wcslen(bp);
16377c478bd9Sstevel@tonic-gate #else  /* _WIDE */
16387c478bd9Sstevel@tonic-gate 					n = strlen(bp);
16397c478bd9Sstevel@tonic-gate #endif /* _WIDE */
16407c478bd9Sstevel@tonic-gate 					if (n < kk)
16417c478bd9Sstevel@tonic-gate 						kk = (int)n;
16427c478bd9Sstevel@tonic-gate 					while (kk >= 1 && bp[kk-1] == '0')
16437c478bd9Sstevel@tonic-gate 						--kk;
16447c478bd9Sstevel@tonic-gate 				}
16457c478bd9Sstevel@tonic-gate 				if (decpt < -3 || decpt > prec) {
16467c478bd9Sstevel@tonic-gate 					prec = kk - 1;
16477c478bd9Sstevel@tonic-gate 					goto e_merge;
16487c478bd9Sstevel@tonic-gate 				}
16497c478bd9Sstevel@tonic-gate 				prec = kk - decpt;
16507c478bd9Sstevel@tonic-gate 				goto f_merge;
16517c478bd9Sstevel@tonic-gate 			}
16527c478bd9Sstevel@tonic-gate 
16537c478bd9Sstevel@tonic-gate 		case '%':
16547c478bd9Sstevel@tonic-gate 			buf[0] = fcode;
16557c478bd9Sstevel@tonic-gate 			goto c_merge;
16567c478bd9Sstevel@tonic-gate 
16577c478bd9Sstevel@tonic-gate #ifndef	_WIDE
16587c478bd9Sstevel@tonic-gate 		case 'w':
16597c478bd9Sstevel@tonic-gate 			wflag = 1;
16607c478bd9Sstevel@tonic-gate 			goto charswitch;
16617c478bd9Sstevel@tonic-gate #endif /* _WIDE */
16627c478bd9Sstevel@tonic-gate 
16637c478bd9Sstevel@tonic-gate 
16647c478bd9Sstevel@tonic-gate 		case 'C': /* XPG XSH4 extention */
16657c478bd9Sstevel@tonic-gate wide_C:
16667c478bd9Sstevel@tonic-gate 			{
16677c478bd9Sstevel@tonic-gate 				wchar_t	temp;
16687c478bd9Sstevel@tonic-gate 
16697c478bd9Sstevel@tonic-gate 				temp = va_arg(args.ap, wchar_t);
16707c478bd9Sstevel@tonic-gate #ifdef	_WIDE
16717c478bd9Sstevel@tonic-gate 				if (temp) {
16727c478bd9Sstevel@tonic-gate 					buf[0] = temp;
16737c478bd9Sstevel@tonic-gate 					p = (bp = buf) + 1;
16747c478bd9Sstevel@tonic-gate 				} else {
16757c478bd9Sstevel@tonic-gate 					buf[0] = 0;
16767c478bd9Sstevel@tonic-gate 					p = (bp = buf) + 1;
16777c478bd9Sstevel@tonic-gate 				}
16787c478bd9Sstevel@tonic-gate 				wcount = 1;
16797c478bd9Sstevel@tonic-gate 				wflag = 1;
16807c478bd9Sstevel@tonic-gate #else  /* _WIDE */
16817c478bd9Sstevel@tonic-gate 				if (temp) {
16828a67df42SToomas Soome 					retcode = wctomb(buf, temp);
16838a67df42SToomas Soome 					if (retcode == -1) {
16847c478bd9Sstevel@tonic-gate 						errno = EILSEQ;
16857c478bd9Sstevel@tonic-gate 						return (EOF);
16867c478bd9Sstevel@tonic-gate 					} else {
16877c478bd9Sstevel@tonic-gate 						p = (bp = buf) + retcode;
16887c478bd9Sstevel@tonic-gate 					}
16897c478bd9Sstevel@tonic-gate 				} else { /* NULL character */
16907c478bd9Sstevel@tonic-gate 					buf[0] = 0;
16917c478bd9Sstevel@tonic-gate 					p = (bp = buf) + 1;
16927c478bd9Sstevel@tonic-gate 				}
16937c478bd9Sstevel@tonic-gate 				wcount = p - bp;
16947c478bd9Sstevel@tonic-gate #endif /* _WIDE */
16957c478bd9Sstevel@tonic-gate 			}
16967c478bd9Sstevel@tonic-gate 			break;
16977c478bd9Sstevel@tonic-gate 		case 'c':
16987c478bd9Sstevel@tonic-gate 			if (lflag) {
16997c478bd9Sstevel@tonic-gate 				goto wide_C;
17007c478bd9Sstevel@tonic-gate 			}
17017c478bd9Sstevel@tonic-gate #ifndef	_WIDE
17027c478bd9Sstevel@tonic-gate 			if (wflag) {
17037c478bd9Sstevel@tonic-gate 				wchar_t	temp;
17047c478bd9Sstevel@tonic-gate 
17057c478bd9Sstevel@tonic-gate 				temp = va_arg(args.ap, wchar_t);
17067c478bd9Sstevel@tonic-gate 				if (temp) {
17078a67df42SToomas Soome 					retcode = wctomb(buf, temp);
17088a67df42SToomas Soome 					if (retcode == -1) {
17097c478bd9Sstevel@tonic-gate 						p = (bp = buf) + 1;
17107c478bd9Sstevel@tonic-gate 					} else {
17117c478bd9Sstevel@tonic-gate 						p = (bp = buf) + retcode;
17127c478bd9Sstevel@tonic-gate 					}
17137c478bd9Sstevel@tonic-gate 				} else { /* NULL character */
17147c478bd9Sstevel@tonic-gate 					buf[0] = 0;
17157c478bd9Sstevel@tonic-gate 					p = (bp = buf) + 1;
17167c478bd9Sstevel@tonic-gate 				}
17177c478bd9Sstevel@tonic-gate 				wcount = p - bp;
17187c478bd9Sstevel@tonic-gate 			} else {
17197c478bd9Sstevel@tonic-gate #endif /* _WIDE */
17207c478bd9Sstevel@tonic-gate 				if (flagword & XLONG) {
17217c478bd9Sstevel@tonic-gate 					long long temp;
17227c478bd9Sstevel@tonic-gate 					temp = va_arg(args.ap, long long);
17237c478bd9Sstevel@tonic-gate #ifdef	_WIDE
17247c478bd9Sstevel@tonic-gate 					buf[0] = (wchar_t)temp;
17257c478bd9Sstevel@tonic-gate #else  /* _WIDE */
17267c478bd9Sstevel@tonic-gate 					buf[0] = (char)temp;
17277c478bd9Sstevel@tonic-gate #endif /* _WIDE */
17287c478bd9Sstevel@tonic-gate 				} else
17297c478bd9Sstevel@tonic-gate 					buf[0] = va_arg(args.ap, int);
17307c478bd9Sstevel@tonic-gate 			c_merge:
17317c478bd9Sstevel@tonic-gate 				p = (bp = &buf[0]) + 1;
17327c478bd9Sstevel@tonic-gate #ifdef	_WIDE
17337c478bd9Sstevel@tonic-gate 				wcount = 1;
17347c478bd9Sstevel@tonic-gate 				wflag = 1;
17357c478bd9Sstevel@tonic-gate #endif /* _WIDE */
17367c478bd9Sstevel@tonic-gate #ifndef	_WIDE
17377c478bd9Sstevel@tonic-gate 			}
17387c478bd9Sstevel@tonic-gate #endif /* _WIDE */
17397c478bd9Sstevel@tonic-gate 			break;
17407c478bd9Sstevel@tonic-gate 
17417c478bd9Sstevel@tonic-gate 		case 'S': /* XPG XSH4 extention */
17427c478bd9Sstevel@tonic-gate wide_S:
17437c478bd9Sstevel@tonic-gate #ifdef	_WIDE
17447c478bd9Sstevel@tonic-gate 			if (!lflag) {
17457c478bd9Sstevel@tonic-gate 				lflag++;
17467c478bd9Sstevel@tonic-gate 			}
17477c478bd9Sstevel@tonic-gate 			bp = va_arg(args.ap, wchar_t *);
17489f773e28SDarren Moffat 			if (bp == NULL)
17499f773e28SDarren Moffat 				bp = (wchar_t *)widenullstr;
17507c478bd9Sstevel@tonic-gate 			if (!(flagword & DOTSEEN)) {
17517c478bd9Sstevel@tonic-gate 				/* wide character handling */
17527c478bd9Sstevel@tonic-gate 				prec = MAXINT;
17537c478bd9Sstevel@tonic-gate 			}
17547c478bd9Sstevel@tonic-gate 
17557c478bd9Sstevel@tonic-gate 			wp = bp;
17567c478bd9Sstevel@tonic-gate 			wcount = 0;
17577c478bd9Sstevel@tonic-gate 			while (*wp) {
17587c478bd9Sstevel@tonic-gate 				if ((prec - wcount - 1) >= 0) {
17597c478bd9Sstevel@tonic-gate 					wcount++;
17607c478bd9Sstevel@tonic-gate 					wp++;
17617c478bd9Sstevel@tonic-gate 				} else {
17627c478bd9Sstevel@tonic-gate 					break;
17637c478bd9Sstevel@tonic-gate 				}
17647c478bd9Sstevel@tonic-gate 			}
17657c478bd9Sstevel@tonic-gate 			p = wp;
17667c478bd9Sstevel@tonic-gate 			wflag = 1;
17677c478bd9Sstevel@tonic-gate 			break;
17687c478bd9Sstevel@tonic-gate #else  /* _WIDE */
17697c478bd9Sstevel@tonic-gate 			if (!wflag)
17707c478bd9Sstevel@tonic-gate 				wflag++;
17717c478bd9Sstevel@tonic-gate 			bp = va_arg(args.ap, char *);
17729f773e28SDarren Moffat 			if (bp == NULL)
17739f773e28SDarren Moffat 				bp = (char *)widenullstr;
17747c478bd9Sstevel@tonic-gate 			if (!(flagword & DOTSEEN)) {
17757c478bd9Sstevel@tonic-gate 				/* wide character handling */
17767c478bd9Sstevel@tonic-gate 				prec = MAXINT;
17777c478bd9Sstevel@tonic-gate 			}
17787c478bd9Sstevel@tonic-gate 
17797c478bd9Sstevel@tonic-gate 			wp = (wchar_t *)(uintptr_t)bp;
17807c478bd9Sstevel@tonic-gate 			wcount = 0;
17817c478bd9Sstevel@tonic-gate 			while (*wp) {
17827c478bd9Sstevel@tonic-gate 				int nbytes;
17837c478bd9Sstevel@tonic-gate 
17847c478bd9Sstevel@tonic-gate 				nbytes = wctomb(tmpbuf, *wp);
17857c478bd9Sstevel@tonic-gate 				if (nbytes < 0) {
17867c478bd9Sstevel@tonic-gate 					errno = EILSEQ;
17877c478bd9Sstevel@tonic-gate 					return (EOF);
17887c478bd9Sstevel@tonic-gate 				}
17897c478bd9Sstevel@tonic-gate 				if ((prec - (wcount + nbytes)) >= 0) {
17907c478bd9Sstevel@tonic-gate 					wcount += nbytes;
17917c478bd9Sstevel@tonic-gate 					wp++;
17927c478bd9Sstevel@tonic-gate 				} else {
17937c478bd9Sstevel@tonic-gate 					break;
17947c478bd9Sstevel@tonic-gate 				}
17957c478bd9Sstevel@tonic-gate 			}
17967c478bd9Sstevel@tonic-gate 			sec_display = wcount;
17977c478bd9Sstevel@tonic-gate 			p = (char *)wp;
17987c478bd9Sstevel@tonic-gate 			break;
17997c478bd9Sstevel@tonic-gate #endif /* _WIDE */
18007c478bd9Sstevel@tonic-gate 		case 's':
18017c478bd9Sstevel@tonic-gate 			if (lflag) {
18027c478bd9Sstevel@tonic-gate 				goto wide_S;
18037c478bd9Sstevel@tonic-gate 			}
18047c478bd9Sstevel@tonic-gate #ifdef	_WIDE
18057c478bd9Sstevel@tonic-gate 			cbp = va_arg(args.ap, char *);
18069f773e28SDarren Moffat 			if (cbp == NULL)
18079f773e28SDarren Moffat 				cbp = (char *)nullstr;
18087c478bd9Sstevel@tonic-gate 			if (!(flagword & DOTSEEN)) {
18097c478bd9Sstevel@tonic-gate 				size_t	nwc;
18107c478bd9Sstevel@tonic-gate 				wchar_t	*wstr;
18117c478bd9Sstevel@tonic-gate 
18127c478bd9Sstevel@tonic-gate 				nwc = mbstowcs(NULL, cbp, 0);
18137c478bd9Sstevel@tonic-gate 				if (nwc == (size_t)-1) {
18147c478bd9Sstevel@tonic-gate 					errno = EILSEQ;
18157c478bd9Sstevel@tonic-gate 					return (EOF);
18167c478bd9Sstevel@tonic-gate 				}
18177c478bd9Sstevel@tonic-gate 				bpsize = sizeof (wchar_t) * (nwc + 1);
18187c478bd9Sstevel@tonic-gate 				wstr = (wchar_t *)lmalloc(bpsize);
18197c478bd9Sstevel@tonic-gate 				if (wstr == NULL) {
18207c478bd9Sstevel@tonic-gate 					errno = EILSEQ;
18217c478bd9Sstevel@tonic-gate 					return (EOF);
18227c478bd9Sstevel@tonic-gate 				}
18237c478bd9Sstevel@tonic-gate 				nwc = mbstowcs(wstr, cbp, MAXINT);
18247c478bd9Sstevel@tonic-gate 				wcount = nwc;
18257c478bd9Sstevel@tonic-gate 				bp = wstr;
18267c478bd9Sstevel@tonic-gate 				p = wstr + nwc;
18277c478bd9Sstevel@tonic-gate 			} else {
18287c478bd9Sstevel@tonic-gate 				size_t	nwc;
18297c478bd9Sstevel@tonic-gate 				wchar_t	*wstr;
18307c478bd9Sstevel@tonic-gate 
18317c478bd9Sstevel@tonic-gate 				nwc = mbstowcs(NULL, cbp, 0);
18327c478bd9Sstevel@tonic-gate 				if (nwc == (size_t)-1) {
18337c478bd9Sstevel@tonic-gate 					errno = EILSEQ;
18347c478bd9Sstevel@tonic-gate 					return (EOF);
18357c478bd9Sstevel@tonic-gate 				}
18367c478bd9Sstevel@tonic-gate 				if (prec > nwc) {
18377c478bd9Sstevel@tonic-gate 					bpsize = sizeof (wchar_t) * nwc;
18387c478bd9Sstevel@tonic-gate 					wstr = (wchar_t *)lmalloc(bpsize);
18397c478bd9Sstevel@tonic-gate 					if (wstr == NULL) {
18407c478bd9Sstevel@tonic-gate 						errno = ENOMEM;
18417c478bd9Sstevel@tonic-gate 						return (EOF);
18427c478bd9Sstevel@tonic-gate 					}
18437c478bd9Sstevel@tonic-gate 					nwc = mbstowcs(wstr, cbp, nwc);
18447c478bd9Sstevel@tonic-gate 					wcount = nwc;
18457c478bd9Sstevel@tonic-gate 					bp = wstr;
18467c478bd9Sstevel@tonic-gate 					p = wstr + nwc;
18477c478bd9Sstevel@tonic-gate 				} else {
18487c478bd9Sstevel@tonic-gate 					wchar_t	*wstr;
18497c478bd9Sstevel@tonic-gate 
18507c478bd9Sstevel@tonic-gate 					bpsize = sizeof (wchar_t) * prec;
18517c478bd9Sstevel@tonic-gate 					wstr = (wchar_t *)lmalloc(bpsize);
18527c478bd9Sstevel@tonic-gate 					if (wstr == NULL) {
18537c478bd9Sstevel@tonic-gate 						errno = ENOMEM;
18547c478bd9Sstevel@tonic-gate 						return (EOF);
18557c478bd9Sstevel@tonic-gate 					}
18567c478bd9Sstevel@tonic-gate 					nwc = mbstowcs(wstr, cbp, prec);
18577c478bd9Sstevel@tonic-gate 					wcount = prec;
18587c478bd9Sstevel@tonic-gate 					bp = wstr;
18597c478bd9Sstevel@tonic-gate 					p = wstr + nwc;
18607c478bd9Sstevel@tonic-gate 				}
18617c478bd9Sstevel@tonic-gate 			}
18627c478bd9Sstevel@tonic-gate 			wflag = 1;
18637c478bd9Sstevel@tonic-gate #else  /* _WIDE */
18647c478bd9Sstevel@tonic-gate 			bp = va_arg(args.ap, char *);
18659f773e28SDarren Moffat 			if (bp == NULL)
18669f773e28SDarren Moffat 				bp = (char *)nullstr;
18677c478bd9Sstevel@tonic-gate 			if (!(flagword & DOTSEEN)) {
18687c478bd9Sstevel@tonic-gate 				if (wflag) {
18697c478bd9Sstevel@tonic-gate 					/* wide character handling */
18707c478bd9Sstevel@tonic-gate 					prec = MAXINT;
18717c478bd9Sstevel@tonic-gate 					goto wide_hand;
18727c478bd9Sstevel@tonic-gate 				}
18737c478bd9Sstevel@tonic-gate 
18747c478bd9Sstevel@tonic-gate 
18757c478bd9Sstevel@tonic-gate 				p = bp + strlen(bp);
18767c478bd9Sstevel@tonic-gate 
18777c478bd9Sstevel@tonic-gate 				/*
18787c478bd9Sstevel@tonic-gate 				 * sec_display only needed if width
18797c478bd9Sstevel@tonic-gate 				 * is specified (ie, "%<width>s")
18807c478bd9Sstevel@tonic-gate 				 * Solaris behavior counts <width> in
18817c478bd9Sstevel@tonic-gate 				 * screen column width.  (If XPG4 behavior,
18827c478bd9Sstevel@tonic-gate 				 * <width> is counted in bytes.)
18837c478bd9Sstevel@tonic-gate 				 */
18847c478bd9Sstevel@tonic-gate 				if (width > 0 && __xpg4 == 0 &&
18857c478bd9Sstevel@tonic-gate 				    MB_CUR_MAX > 1) {
18867c478bd9Sstevel@tonic-gate #define	NW	256
18877c478bd9Sstevel@tonic-gate 					wchar_t wbuff[NW];
18887c478bd9Sstevel@tonic-gate 					wchar_t *wp, *wptr;
18897c478bd9Sstevel@tonic-gate 					size_t wpsize;
18907c478bd9Sstevel@tonic-gate 					size_t nwc;
18917c478bd9Sstevel@tonic-gate 
18927c478bd9Sstevel@tonic-gate 					wp = NULL;
18937c478bd9Sstevel@tonic-gate 					if ((nwc = mbstowcs(wbuff, bp,
18947c478bd9Sstevel@tonic-gate 					    NW)) == (size_t)-1) {
18957c478bd9Sstevel@tonic-gate 						/* Estimate width */
18967c478bd9Sstevel@tonic-gate 						sec_display = strlen(bp);
18977c478bd9Sstevel@tonic-gate 						goto mbs_err;
18987c478bd9Sstevel@tonic-gate 					}
18997c478bd9Sstevel@tonic-gate 					if (nwc < NW) {
19007c478bd9Sstevel@tonic-gate 						wptr = wbuff;
19017c478bd9Sstevel@tonic-gate 					} else {
19027c478bd9Sstevel@tonic-gate 						/*
19037c478bd9Sstevel@tonic-gate 						 * If widechar does not fit into
19047c478bd9Sstevel@tonic-gate 						 * wbuff, allocate larger buffer
19057c478bd9Sstevel@tonic-gate 						 */
19067c478bd9Sstevel@tonic-gate 						if ((nwc =
1907e86c3f00SToomas Soome 						    mbstowcs(NULL, bp, 0)) ==
19087c478bd9Sstevel@tonic-gate 						    (size_t)-1) {
19097c478bd9Sstevel@tonic-gate 							sec_display =
19107c478bd9Sstevel@tonic-gate 							    strlen(bp);
19117c478bd9Sstevel@tonic-gate 							goto mbs_err;
19127c478bd9Sstevel@tonic-gate 						}
19137c478bd9Sstevel@tonic-gate 						wpsize = (nwc + 1) *
19147c478bd9Sstevel@tonic-gate 						    sizeof (wchar_t);
19157c478bd9Sstevel@tonic-gate 						if ((wp = lmalloc(wpsize))
19167c478bd9Sstevel@tonic-gate 						    == NULL) {
19177c478bd9Sstevel@tonic-gate 							errno = ENOMEM;
19187c478bd9Sstevel@tonic-gate 							return (EOF);
19197c478bd9Sstevel@tonic-gate 						}
19207c478bd9Sstevel@tonic-gate 						if ((nwc = mbstowcs(wp,
19217c478bd9Sstevel@tonic-gate 						    bp, nwc)) == (size_t)-1) {
19227c478bd9Sstevel@tonic-gate 							sec_display = \
19237c478bd9Sstevel@tonic-gate 							    strlen(bp);
19247c478bd9Sstevel@tonic-gate 							goto mbs_err;
19257c478bd9Sstevel@tonic-gate 						}
19267c478bd9Sstevel@tonic-gate 						wptr = wp;
19277c478bd9Sstevel@tonic-gate 					}
19288a67df42SToomas Soome 					sec_display = wcswidth(wptr, nwc);
19298a67df42SToomas Soome 					if (sec_display == -1) {
19307c478bd9Sstevel@tonic-gate 						sec_display =
19318a67df42SToomas Soome 						    _rec_scrswidth(wptr, nwc);
19327c478bd9Sstevel@tonic-gate 					}
19337c478bd9Sstevel@tonic-gate 				mbs_err:
19347c478bd9Sstevel@tonic-gate 					if (wp)
19357c478bd9Sstevel@tonic-gate 						lfree(wp, wpsize);
19367c478bd9Sstevel@tonic-gate 				}
19377c478bd9Sstevel@tonic-gate 			} else { /* a strnlen function would be useful here! */
19387c478bd9Sstevel@tonic-gate 				/*
19397c478bd9Sstevel@tonic-gate 				 * If we've seen a dot, and count has been set
19407c478bd9Sstevel@tonic-gate 				 * to 0, then we don't output in any cases
19417c478bd9Sstevel@tonic-gate 				 * below. prec should be always >= 0. So we only
19427c478bd9Sstevel@tonic-gate 				 * check to see if it's zero.
19437c478bd9Sstevel@tonic-gate 				 */
19447c478bd9Sstevel@tonic-gate 				if (prec == 0) {
19457c478bd9Sstevel@tonic-gate 					p = bp;
19467c478bd9Sstevel@tonic-gate 					break;
19477c478bd9Sstevel@tonic-gate 				}
19487c478bd9Sstevel@tonic-gate 
19497c478bd9Sstevel@tonic-gate 				if (wflag) {
19507c478bd9Sstevel@tonic-gate 					/* wide character handling */
19517c478bd9Sstevel@tonic-gate 
19527c478bd9Sstevel@tonic-gate 				wide_hand:
19537c478bd9Sstevel@tonic-gate 					wp = (wchar_t *)(uintptr_t)bp;
19547c478bd9Sstevel@tonic-gate 					preco = prec;
19557c478bd9Sstevel@tonic-gate 					wcount = 0;
19567c478bd9Sstevel@tonic-gate 					while (*wp &&
19577c478bd9Sstevel@tonic-gate 					    (prec -= _scrwidth(*wp)) >= 0) {
19587c478bd9Sstevel@tonic-gate 						if ((retcode =
19597c478bd9Sstevel@tonic-gate 						    wctomb(tmpbuf, *wp)) < 0)
19607c478bd9Sstevel@tonic-gate 							wcount++;
19617c478bd9Sstevel@tonic-gate 						else
19627c478bd9Sstevel@tonic-gate 							wcount += retcode;
19637c478bd9Sstevel@tonic-gate 						wp++;
19647c478bd9Sstevel@tonic-gate 					}
19657c478bd9Sstevel@tonic-gate 					if (*wp)
19667c478bd9Sstevel@tonic-gate 						prec += _scrwidth(*wp);
19677c478bd9Sstevel@tonic-gate 					p = (char *)wp;
19687c478bd9Sstevel@tonic-gate 					sec_display = preco - prec;
19697c478bd9Sstevel@tonic-gate 				} else if (__xpg4 == 0 && MB_CUR_MAX > 1) {
19707c478bd9Sstevel@tonic-gate 					/*
19717c478bd9Sstevel@tonic-gate 					 * Solaris behavior - count
19727c478bd9Sstevel@tonic-gate 					 * precision as screen column width
19737c478bd9Sstevel@tonic-gate 					 */
19747c478bd9Sstevel@tonic-gate 					char *qp = bp;
19757c478bd9Sstevel@tonic-gate 					int ncol, nbytes;
19767c478bd9Sstevel@tonic-gate 					wchar_t wc;
19777c478bd9Sstevel@tonic-gate 
19787c478bd9Sstevel@tonic-gate 					ncol = 0;
19797c478bd9Sstevel@tonic-gate 					preco = prec;
19807c478bd9Sstevel@tonic-gate 					while (*qp) {
19817c478bd9Sstevel@tonic-gate 						if (isascii(*qp)) {
19827c478bd9Sstevel@tonic-gate 							qp++;
19837c478bd9Sstevel@tonic-gate 							if (--prec == 0)
19847c478bd9Sstevel@tonic-gate 								break;
19857c478bd9Sstevel@tonic-gate 							continue;
19867c478bd9Sstevel@tonic-gate 						}
19877c478bd9Sstevel@tonic-gate 						if ((nbytes = mbtowc(&wc, qp,
19888a67df42SToomas Soome 						    MB_LEN_MAX)) == -1) {
19897c478bd9Sstevel@tonic-gate 							/* print illegal char */
19907c478bd9Sstevel@tonic-gate 							nbytes = 1;
19917c478bd9Sstevel@tonic-gate 							ncol = 1;
19927c478bd9Sstevel@tonic-gate 						} else {
19938a67df42SToomas Soome 							ncol = _scrwidth(wc);
19948a67df42SToomas Soome 							if (ncol == 0) {
19957c478bd9Sstevel@tonic-gate 								ncol = 1;
19967c478bd9Sstevel@tonic-gate 							}
19977c478bd9Sstevel@tonic-gate 						}
19987c478bd9Sstevel@tonic-gate 
19997c478bd9Sstevel@tonic-gate 						if ((prec -= ncol) >= 0) {
20007c478bd9Sstevel@tonic-gate 							qp += nbytes;
20017c478bd9Sstevel@tonic-gate 							if (prec == 0)
20027c478bd9Sstevel@tonic-gate 								break;
20037c478bd9Sstevel@tonic-gate 						} else {
20047c478bd9Sstevel@tonic-gate 							break;
20057c478bd9Sstevel@tonic-gate 						}
20067c478bd9Sstevel@tonic-gate 					}
20077c478bd9Sstevel@tonic-gate 					if (prec < 0)
20087c478bd9Sstevel@tonic-gate 						prec += ncol;
20097c478bd9Sstevel@tonic-gate 					p = qp;
20107c478bd9Sstevel@tonic-gate 					sec_display = preco - prec;
20117c478bd9Sstevel@tonic-gate 				} else {
20127c478bd9Sstevel@tonic-gate 					/*
20137c478bd9Sstevel@tonic-gate 					 * XPG4 behavior - count
20147c478bd9Sstevel@tonic-gate 					 * precision as bytes.
20157c478bd9Sstevel@tonic-gate 					 * We don't use strlen() because
20167c478bd9Sstevel@tonic-gate 					 * the given char string may not
20177c478bd9Sstevel@tonic-gate 					 * be null-terminated.
20187c478bd9Sstevel@tonic-gate 					 */
20197c478bd9Sstevel@tonic-gate 					char *qp;
20207c478bd9Sstevel@tonic-gate 
20217c478bd9Sstevel@tonic-gate 					qp = memchr(bp, '\0', prec);
20227c478bd9Sstevel@tonic-gate 					if (qp == NULL) {
20237c478bd9Sstevel@tonic-gate 						p = bp + prec;
20247c478bd9Sstevel@tonic-gate 					} else {
20257c478bd9Sstevel@tonic-gate 						p = qp;
20267c478bd9Sstevel@tonic-gate 					}
20277c478bd9Sstevel@tonic-gate 				}
20287c478bd9Sstevel@tonic-gate 			}
20297c478bd9Sstevel@tonic-gate #endif /* _WIDE */
20307c478bd9Sstevel@tonic-gate 			break;
20317c478bd9Sstevel@tonic-gate 
20327c478bd9Sstevel@tonic-gate 		case 'n':
20337c478bd9Sstevel@tonic-gate 			{
20347c478bd9Sstevel@tonic-gate 			if (flagword & XLONG) {
20357c478bd9Sstevel@tonic-gate 				long long *svcount;
20367c478bd9Sstevel@tonic-gate 				svcount = va_arg(args.ap, long long *);
20377c478bd9Sstevel@tonic-gate 				*svcount = (long long)count;
20387c478bd9Sstevel@tonic-gate 			} else if (flagword & LENGTH) {
20397c478bd9Sstevel@tonic-gate 				long *svcount;
20407c478bd9Sstevel@tonic-gate 				svcount = va_arg(args.ap, long *);
20417c478bd9Sstevel@tonic-gate 				*svcount = (long)count;
20427c478bd9Sstevel@tonic-gate 			} else if (flagword & SHORT) {
20437c478bd9Sstevel@tonic-gate 				short *svcount;
20447c478bd9Sstevel@tonic-gate 				svcount = va_arg(args.ap, short *);
20457c478bd9Sstevel@tonic-gate 				*svcount = (short)count;
20467c478bd9Sstevel@tonic-gate 			} else if (flagword & CHAR) {
20477c478bd9Sstevel@tonic-gate 				char *svcount;
20487c478bd9Sstevel@tonic-gate 				svcount = va_arg(args.ap, char *);
20497c478bd9Sstevel@tonic-gate 				*svcount = (char)count;
20507c478bd9Sstevel@tonic-gate 			} else {
20517c478bd9Sstevel@tonic-gate 				int *svcount;
20527c478bd9Sstevel@tonic-gate 				svcount = va_arg(args.ap, int *);
20537c478bd9Sstevel@tonic-gate 				*svcount = count;
20547c478bd9Sstevel@tonic-gate 			}
20557c478bd9Sstevel@tonic-gate 			continue;
20567c478bd9Sstevel@tonic-gate 		}
20577c478bd9Sstevel@tonic-gate 		default: /* this is technically an error; what we do is to */
20587c478bd9Sstevel@tonic-gate 			/* back up the format pointer to the offending char */
20597c478bd9Sstevel@tonic-gate 			/* and continue with the format scan */
20607c478bd9Sstevel@tonic-gate 			format--;
20617c478bd9Sstevel@tonic-gate 			continue;
20627c478bd9Sstevel@tonic-gate 		}
20637c478bd9Sstevel@tonic-gate 
20647c478bd9Sstevel@tonic-gate 		if (inf_nan) {
20657c478bd9Sstevel@tonic-gate 			if (inf_nan_mixed_case) {
20667c478bd9Sstevel@tonic-gate 				/* advance p */
20677c478bd9Sstevel@tonic-gate 				for (p = bp + 1; *p != '\0'; p++)
20687c478bd9Sstevel@tonic-gate 					;
20697c478bd9Sstevel@tonic-gate 			} else {
20707c478bd9Sstevel@tonic-gate 				int upper;
20717c478bd9Sstevel@tonic-gate 
20727c478bd9Sstevel@tonic-gate 				/* advance p and make output all one case */
20737c478bd9Sstevel@tonic-gate 				upper = _M_ISUPPER(fcode);
20747c478bd9Sstevel@tonic-gate 				for (p = bp; *p != '\0'; p++)
20757c478bd9Sstevel@tonic-gate 					*p = upper? toupper(*p) : tolower(*p);
20767c478bd9Sstevel@tonic-gate 			}
20777c478bd9Sstevel@tonic-gate 			if (sign) {
20787c478bd9Sstevel@tonic-gate 				prefix = _P_HYPHEN;
20797c478bd9Sstevel@tonic-gate 				prefixlength = 1;
20807c478bd9Sstevel@tonic-gate 			} else if (flagword & FPLUS) {
20817c478bd9Sstevel@tonic-gate 				prefix = _P_PLUS;
20827c478bd9Sstevel@tonic-gate 				prefixlength = 1;
20837c478bd9Sstevel@tonic-gate 			} else if (flagword & FBLANK) {
20847c478bd9Sstevel@tonic-gate 				prefix = _P_BLANK;
20857c478bd9Sstevel@tonic-gate 				prefixlength = 1;
20867c478bd9Sstevel@tonic-gate 			}
20877c478bd9Sstevel@tonic-gate 			inf_nan = 0;
20887c478bd9Sstevel@tonic-gate 			inf_nan_mixed_case = 0;
2089146fa2c5SDouglas Priest 			flagword &= ~PADZERO; /* ignore 0 flag */
20907c478bd9Sstevel@tonic-gate 		}
20917c478bd9Sstevel@tonic-gate 
20927c478bd9Sstevel@tonic-gate 		/* Calculate number of padding blanks */
20937c478bd9Sstevel@tonic-gate 		n = p - bp; /* n == size of the converted value (in bytes) */
20947c478bd9Sstevel@tonic-gate 
20957c478bd9Sstevel@tonic-gate #ifdef	_WIDE
20967c478bd9Sstevel@tonic-gate 		k = n;
20977c478bd9Sstevel@tonic-gate #else  /* _WIDE */
20987c478bd9Sstevel@tonic-gate 		if (sec_display) /* when format is %s or %ws or %S */
20997c478bd9Sstevel@tonic-gate 			k = sec_display;
21007c478bd9Sstevel@tonic-gate 		else
21017c478bd9Sstevel@tonic-gate 			k = n;
21027c478bd9Sstevel@tonic-gate #endif /* _WIDE */
21037c478bd9Sstevel@tonic-gate 		/*
21047c478bd9Sstevel@tonic-gate 		 * k is the (screen) width or # of bytes of the converted value
21057c478bd9Sstevel@tonic-gate 		 */
21067c478bd9Sstevel@tonic-gate 		k += prefixlength + otherlength;
21077c478bd9Sstevel@tonic-gate 
21087c478bd9Sstevel@tonic-gate #ifdef	_WIDE
21097c478bd9Sstevel@tonic-gate 		if (wflag) {
21107c478bd9Sstevel@tonic-gate 			count += wcount;
21117c478bd9Sstevel@tonic-gate 		} else {
21127c478bd9Sstevel@tonic-gate 			count += n;
21137c478bd9Sstevel@tonic-gate 		}
21147c478bd9Sstevel@tonic-gate #else  /* _WIDE */
21157c478bd9Sstevel@tonic-gate 		/*
21167c478bd9Sstevel@tonic-gate 		 * update count which is the overall size of the output data
21177c478bd9Sstevel@tonic-gate 		 * and passed to memchr()
21187c478bd9Sstevel@tonic-gate 		 */
21197c478bd9Sstevel@tonic-gate 		if (wflag)
21207c478bd9Sstevel@tonic-gate 			/*
21217c478bd9Sstevel@tonic-gate 			 * when wflag != 0 (i.e. %ws or %wc), the size of the
21227c478bd9Sstevel@tonic-gate 			 * converted value is wcount bytes
21237c478bd9Sstevel@tonic-gate 			 */
21247c478bd9Sstevel@tonic-gate 			count += wcount;
21257c478bd9Sstevel@tonic-gate 		else
21267c478bd9Sstevel@tonic-gate 			/*
21277c478bd9Sstevel@tonic-gate 			 * when wflag == 0, the size of the converted
21287c478bd9Sstevel@tonic-gate 			 * value is n (= p-bp) bytes
21297c478bd9Sstevel@tonic-gate 			 */
21307c478bd9Sstevel@tonic-gate 			count += n;
21317c478bd9Sstevel@tonic-gate #endif /* _WIDE */
21327c478bd9Sstevel@tonic-gate 		count += prefixlength + otherlength;
21337c478bd9Sstevel@tonic-gate 
21347c478bd9Sstevel@tonic-gate 		if (width > k) {
21357c478bd9Sstevel@tonic-gate 			count += (width - k);
21367c478bd9Sstevel@tonic-gate 			/*
21377c478bd9Sstevel@tonic-gate 			 * Set up for padding zeroes if requested
21387c478bd9Sstevel@tonic-gate 			 * Otherwise emit padding blanks unless output is
21397c478bd9Sstevel@tonic-gate 			 * to be left-justified.
21407c478bd9Sstevel@tonic-gate 			 */
21417c478bd9Sstevel@tonic-gate 
21427c478bd9Sstevel@tonic-gate 			if (flagword & PADZERO) {
21437c478bd9Sstevel@tonic-gate 				if (!(flagword & LZERO)) {
21447c478bd9Sstevel@tonic-gate 					flagword |= LZERO;
21457c478bd9Sstevel@tonic-gate 					lzero = width - k;
21467c478bd9Sstevel@tonic-gate 				} else
21477c478bd9Sstevel@tonic-gate 					lzero += width - k;
21487c478bd9Sstevel@tonic-gate 				k = width; /* cancel padding blanks */
21497c478bd9Sstevel@tonic-gate 			} else
21507c478bd9Sstevel@tonic-gate 				/* Blanks on left if required */
21517c478bd9Sstevel@tonic-gate 				if (!(flagword & FMINUS))
21527c478bd9Sstevel@tonic-gate 					PAD(_blanks, width - k);
21537c478bd9Sstevel@tonic-gate 		}
21547c478bd9Sstevel@tonic-gate 
21557c478bd9Sstevel@tonic-gate 		/* Prefix, if any */
21567c478bd9Sstevel@tonic-gate 		if (prefixlength != 0)
21577c478bd9Sstevel@tonic-gate 			PUT(prefix, prefixlength);
21587c478bd9Sstevel@tonic-gate 
21597c478bd9Sstevel@tonic-gate 		/* Zeroes on the left */
21607c478bd9Sstevel@tonic-gate 		if ((flagword & LZERO)) /* && */
21617c478bd9Sstevel@tonic-gate 			/* (!(flagword & SHORT) || !(flagword & FMINUS)) */
21627c478bd9Sstevel@tonic-gate 			PAD(_zeroes, lzero);
21637c478bd9Sstevel@tonic-gate 
21647c478bd9Sstevel@tonic-gate #ifdef	_WIDE
21657c478bd9Sstevel@tonic-gate 		if (n > 0)
21667c478bd9Sstevel@tonic-gate 			PUT(bp, n);
21677c478bd9Sstevel@tonic-gate 		if ((fcode == 's') && !lflag) {
21687c478bd9Sstevel@tonic-gate 			if (bp)
21697c478bd9Sstevel@tonic-gate 				lfree(bp, bpsize);
21707c478bd9Sstevel@tonic-gate 		}
21717c478bd9Sstevel@tonic-gate #else  /* _WIDE */
21727c478bd9Sstevel@tonic-gate 		/* The value itself */
21737c478bd9Sstevel@tonic-gate 		if ((fcode == 's' || fcode == 'S') && wflag) {
21747c478bd9Sstevel@tonic-gate 			/* wide character handling */
21757c478bd9Sstevel@tonic-gate 			wchar_t *wp = (wchar_t *)(uintptr_t)bp;
21767c478bd9Sstevel@tonic-gate 			int cnt;
21777c478bd9Sstevel@tonic-gate 			char *bufp;
21787c478bd9Sstevel@tonic-gate 			long printn;
21797c478bd9Sstevel@tonic-gate 			printn = (wchar_t *)(uintptr_t)p -
21808a67df42SToomas Soome 			    (wchar_t *)(uintptr_t)bp;
21817c478bd9Sstevel@tonic-gate 			bufp = buf;
21827c478bd9Sstevel@tonic-gate 			while (printn > 0) {
21837c478bd9Sstevel@tonic-gate 				if ((cnt = wctomb(buf, *wp)) < 0)
21847c478bd9Sstevel@tonic-gate 					cnt = 1;
2185*4a38094cSToomas Soome 				PUT(bufp, cnt);
21867c478bd9Sstevel@tonic-gate 				wp++;
21877c478bd9Sstevel@tonic-gate 				printn--;
21887c478bd9Sstevel@tonic-gate 			}
21897c478bd9Sstevel@tonic-gate 		} else {	/* non wide character value */
21907c478bd9Sstevel@tonic-gate 			if (n > 0)
21917c478bd9Sstevel@tonic-gate 				PUT(bp, n);
21927c478bd9Sstevel@tonic-gate 		}
21937c478bd9Sstevel@tonic-gate #endif /* _WIDE */
21947c478bd9Sstevel@tonic-gate 
21957c478bd9Sstevel@tonic-gate 		if (flagword & (RZERO | SUFFIX | FMINUS)) {
21967c478bd9Sstevel@tonic-gate 			/* Zeroes on the right */
21977c478bd9Sstevel@tonic-gate 			if (flagword & RZERO)
21987c478bd9Sstevel@tonic-gate 				PAD(_zeroes, rzero);
21997c478bd9Sstevel@tonic-gate 
22007c478bd9Sstevel@tonic-gate 			/* The suffix */
22017c478bd9Sstevel@tonic-gate 			if (flagword & SUFFIX)
22027c478bd9Sstevel@tonic-gate 				PUT(suffix, suffixlength);
22037c478bd9Sstevel@tonic-gate 
22047c478bd9Sstevel@tonic-gate 			/* Blanks on the right if required */
22057c478bd9Sstevel@tonic-gate 			if (flagword & FMINUS && width > k)
22067c478bd9Sstevel@tonic-gate 				PAD(_blanks, width - k);
22077c478bd9Sstevel@tonic-gate 		}
22087c478bd9Sstevel@tonic-gate 	}
22097c478bd9Sstevel@tonic-gate }
22107c478bd9Sstevel@tonic-gate 
22117c478bd9Sstevel@tonic-gate #ifdef	_WIDE
22127c478bd9Sstevel@tonic-gate static int
_watoi(wchar_t * fmt)22137c478bd9Sstevel@tonic-gate _watoi(wchar_t *fmt)
22147c478bd9Sstevel@tonic-gate {
22157c478bd9Sstevel@tonic-gate 	int	n = 0;
22167c478bd9Sstevel@tonic-gate 	wchar_t	ch;
22177c478bd9Sstevel@tonic-gate 
22187c478bd9Sstevel@tonic-gate 	ch = *fmt;
22197c478bd9Sstevel@tonic-gate 	if (_M_ISDIGIT(ch)) {
22207c478bd9Sstevel@tonic-gate 		n = ch - '0';
22217c478bd9Sstevel@tonic-gate 		ch = *++fmt;
22227c478bd9Sstevel@tonic-gate 		while (_M_ISDIGIT(ch)) {
22237c478bd9Sstevel@tonic-gate 			n *= 10;
22247c478bd9Sstevel@tonic-gate 			n += ch - '0';
22257c478bd9Sstevel@tonic-gate 			ch = *++fmt;
22267c478bd9Sstevel@tonic-gate 		}
22277c478bd9Sstevel@tonic-gate 	}
22287c478bd9Sstevel@tonic-gate 	return (n);
22297c478bd9Sstevel@tonic-gate }
22307c478bd9Sstevel@tonic-gate #endif /* _WIDE */
22317c478bd9Sstevel@tonic-gate 
22327c478bd9Sstevel@tonic-gate /*
22337c478bd9Sstevel@tonic-gate  * This function initializes arglst, to contain the appropriate va_list values
22347c478bd9Sstevel@tonic-gate  * for the first MAXARGS arguments.
22357c478bd9Sstevel@tonic-gate  */
22367c478bd9Sstevel@tonic-gate 
22377c478bd9Sstevel@tonic-gate /*
22387c478bd9Sstevel@tonic-gate  * Type modifier flags:
22397c478bd9Sstevel@tonic-gate  *  0x01	for long
22407c478bd9Sstevel@tonic-gate  *  0x02	for int
22417c478bd9Sstevel@tonic-gate  *  0x04	for long long
22427c478bd9Sstevel@tonic-gate  *  0x08	for long double
22437c478bd9Sstevel@tonic-gate  */
22447c478bd9Sstevel@tonic-gate 
22457c478bd9Sstevel@tonic-gate #define	FLAG_LONG	0x01
22467c478bd9Sstevel@tonic-gate #define	FLAG_INT	0x02
22477c478bd9Sstevel@tonic-gate #define	FLAG_LONG_LONG	0x04
22487c478bd9Sstevel@tonic-gate #define	FLAG_LONG_DBL	0x08
22497c478bd9Sstevel@tonic-gate 
22507c478bd9Sstevel@tonic-gate #ifdef	_WIDE
22517c478bd9Sstevel@tonic-gate static void
_wmkarglst(wchar_t * fmt,stva_list args,stva_list arglst[],int prflag __unused)2252*4a38094cSToomas Soome _wmkarglst(wchar_t *fmt, stva_list args, stva_list arglst[],
2253*4a38094cSToomas Soome     int prflag __unused)
22547c478bd9Sstevel@tonic-gate #else  /* _WIDE */
22558793b36bSNick Todd static void
2256*4a38094cSToomas Soome _mkarglst(char *fmt, stva_list args, stva_list arglst[], int prflag __unused)
22577c478bd9Sstevel@tonic-gate #endif /* _WIDE */
22587c478bd9Sstevel@tonic-gate {
22597c478bd9Sstevel@tonic-gate #ifdef	_WIDE
22607c478bd9Sstevel@tonic-gate 	static const wchar_t	digits[] = L"01234567890";
22617c478bd9Sstevel@tonic-gate 	static const wchar_t	skips[] = L"# +-.'0123456789h$";
22627c478bd9Sstevel@tonic-gate #else  /* _WIDE */
22637c478bd9Sstevel@tonic-gate 	static const char digits[] = "01234567890";
22647c478bd9Sstevel@tonic-gate 	static const char skips[] = "# +-.'0123456789h$";
22657c478bd9Sstevel@tonic-gate #endif /* _WIDE */
22667c478bd9Sstevel@tonic-gate 	enum types {INT = 1, LONG, CHAR_PTR, DOUBLE, LONG_DOUBLE, VOID_PTR,
2267*4a38094cSToomas Soome 	    LONG_PTR, INT_PTR, LONG_LONG, LONG_LONG_PTR};
22687c478bd9Sstevel@tonic-gate 	enum types typelst[MAXARGS], curtype;
22697c478bd9Sstevel@tonic-gate 	ssize_t n;
22707c478bd9Sstevel@tonic-gate 	int  maxnum, curargno, flags;
22717c478bd9Sstevel@tonic-gate 
22727c478bd9Sstevel@tonic-gate 	/*
22737c478bd9Sstevel@tonic-gate 	 * Algorithm	1. set all argument types to zero.
22747c478bd9Sstevel@tonic-gate 	 *		2. walk through fmt putting arg types in typelst[].
22757c478bd9Sstevel@tonic-gate 	 *		3. walk through args using va_arg(args.ap, typelst[n])
22767c478bd9Sstevel@tonic-gate 	 *		   and set arglst[] to the appropriate values.
22777c478bd9Sstevel@tonic-gate 	 * Assumptions:	Cannot use %*$... to specify variable position.
22787c478bd9Sstevel@tonic-gate 	 */
22797c478bd9Sstevel@tonic-gate 
22807c478bd9Sstevel@tonic-gate 	(void) memset((void *) typelst, 0, sizeof (typelst));
22817c478bd9Sstevel@tonic-gate 	maxnum = -1;
22827c478bd9Sstevel@tonic-gate 	curargno = 0;
22837c478bd9Sstevel@tonic-gate 	while ((fmt = STRCHR(fmt, '%')) != 0) {
22847c478bd9Sstevel@tonic-gate 		fmt++;	/* skip % */
22857c478bd9Sstevel@tonic-gate 		if (fmt[n = STRSPN(fmt, digits)] == '$') {
22867c478bd9Sstevel@tonic-gate 			/* convert to zero base */
22877c478bd9Sstevel@tonic-gate 			curargno = ATOI(fmt) - 1;
22887c478bd9Sstevel@tonic-gate 			if (curargno < 0)
22897c478bd9Sstevel@tonic-gate 				continue;
22907c478bd9Sstevel@tonic-gate 			fmt += n + 1;
22917c478bd9Sstevel@tonic-gate 		}
22927c478bd9Sstevel@tonic-gate 		flags = 0;
22937c478bd9Sstevel@tonic-gate 	again:;
22947c478bd9Sstevel@tonic-gate 		fmt += STRSPN(fmt, skips);
22957c478bd9Sstevel@tonic-gate 		switch (*fmt++) {
22967c478bd9Sstevel@tonic-gate 		case '%':	/* there is no argument! */
22977c478bd9Sstevel@tonic-gate 			continue;
22987c478bd9Sstevel@tonic-gate 		case 'l':
22997c478bd9Sstevel@tonic-gate 			if (flags & (FLAG_LONG | FLAG_LONG_LONG)) {
23007c478bd9Sstevel@tonic-gate 				flags |= FLAG_LONG_LONG;
23017c478bd9Sstevel@tonic-gate 				flags &= ~FLAG_LONG;
23027c478bd9Sstevel@tonic-gate 			} else {
23037c478bd9Sstevel@tonic-gate 				flags |= FLAG_LONG;
23047c478bd9Sstevel@tonic-gate 			}
23057c478bd9Sstevel@tonic-gate 			goto again;
23067c478bd9Sstevel@tonic-gate 		case 'j':
23077c478bd9Sstevel@tonic-gate #ifndef _LP64
23087c478bd9Sstevel@tonic-gate 			/*
23097c478bd9Sstevel@tonic-gate 			 * *printf_c89() in 32-bit libc uses
23107c478bd9Sstevel@tonic-gate 			 * 32-bit intmax_t; otherwise intmax_t
23117c478bd9Sstevel@tonic-gate 			 * is 64-bits.
23127c478bd9Sstevel@tonic-gate 			 */
23137c478bd9Sstevel@tonic-gate 			if (!(prflag & _F_INTMAX32)) {
23147c478bd9Sstevel@tonic-gate #endif
23157c478bd9Sstevel@tonic-gate 				flags |= FLAG_LONG_LONG;	/* 64-bit */
23167c478bd9Sstevel@tonic-gate #ifndef _LP64
23177c478bd9Sstevel@tonic-gate 			}
23187c478bd9Sstevel@tonic-gate #endif
23197c478bd9Sstevel@tonic-gate 			goto again;
23207c478bd9Sstevel@tonic-gate 		case 't':
23217c478bd9Sstevel@tonic-gate 			flags |= FLAG_LONG;
23227c478bd9Sstevel@tonic-gate 			goto again;
23237c478bd9Sstevel@tonic-gate 		case 'z':
23247c478bd9Sstevel@tonic-gate 			flags |= FLAG_LONG;
23257c478bd9Sstevel@tonic-gate 			goto again;
23267c478bd9Sstevel@tonic-gate 		case 'L':
23277c478bd9Sstevel@tonic-gate 			flags |= FLAG_LONG_DBL;
23287c478bd9Sstevel@tonic-gate 			goto again;
23297c478bd9Sstevel@tonic-gate 		case '*':	/* int argument used for value */
23307c478bd9Sstevel@tonic-gate 			/* check if there is a positional parameter */
23317c478bd9Sstevel@tonic-gate #ifdef	_WIDE
23328a67df42SToomas Soome 			if ((*fmt >= 0) && (*fmt < 256) && isdigit(*fmt))
23337c478bd9Sstevel@tonic-gate #else  /* _WIDE */
23347c478bd9Sstevel@tonic-gate 			if (isdigit(*fmt))
23357c478bd9Sstevel@tonic-gate #endif /* _WIDE */
23367c478bd9Sstevel@tonic-gate 			{
23377c478bd9Sstevel@tonic-gate 				int	targno;
23387c478bd9Sstevel@tonic-gate 				targno = ATOI(fmt) - 1;
23397c478bd9Sstevel@tonic-gate 				fmt += STRSPN(fmt, digits);
23407c478bd9Sstevel@tonic-gate 				if (*fmt == '$')
23417c478bd9Sstevel@tonic-gate 					fmt++; /* skip '$' */
23427c478bd9Sstevel@tonic-gate 				if (targno >= 0 && targno < MAXARGS) {
23437c478bd9Sstevel@tonic-gate 					typelst[targno] = INT;
23447c478bd9Sstevel@tonic-gate 					if (maxnum < targno)
23457c478bd9Sstevel@tonic-gate 						maxnum = targno;
23467c478bd9Sstevel@tonic-gate 				}
23477c478bd9Sstevel@tonic-gate 				goto again;
23487c478bd9Sstevel@tonic-gate 			}
23497c478bd9Sstevel@tonic-gate 			flags |= FLAG_INT;
23507c478bd9Sstevel@tonic-gate 			curtype = INT;
23517c478bd9Sstevel@tonic-gate 			break;
23527c478bd9Sstevel@tonic-gate 		case 'a':
23537c478bd9Sstevel@tonic-gate 		case 'A':
23547c478bd9Sstevel@tonic-gate 		case 'e':
23557c478bd9Sstevel@tonic-gate 		case 'E':
23567c478bd9Sstevel@tonic-gate 		case 'f':
23577c478bd9Sstevel@tonic-gate 		case 'F':
23587c478bd9Sstevel@tonic-gate 		case 'g':
23597c478bd9Sstevel@tonic-gate 		case 'G':
23607c478bd9Sstevel@tonic-gate 			if (flags & FLAG_LONG_DBL)
23617c478bd9Sstevel@tonic-gate 				curtype = LONG_DOUBLE;
23627c478bd9Sstevel@tonic-gate 			else
23637c478bd9Sstevel@tonic-gate 				curtype = DOUBLE;
23647c478bd9Sstevel@tonic-gate 			break;
23657c478bd9Sstevel@tonic-gate 		case 's':
23667c478bd9Sstevel@tonic-gate 			curtype = CHAR_PTR;
23677c478bd9Sstevel@tonic-gate 			break;
23687c478bd9Sstevel@tonic-gate 		case 'p':
23697c478bd9Sstevel@tonic-gate 			curtype = VOID_PTR;
23707c478bd9Sstevel@tonic-gate 			break;
23717c478bd9Sstevel@tonic-gate 		case 'n':
23727c478bd9Sstevel@tonic-gate 			if (flags & FLAG_LONG_LONG)
23737c478bd9Sstevel@tonic-gate 				curtype = LONG_LONG_PTR;
23747c478bd9Sstevel@tonic-gate 			else if (flags & FLAG_LONG)
23757c478bd9Sstevel@tonic-gate 				curtype = LONG_PTR;
23767c478bd9Sstevel@tonic-gate 			else
23777c478bd9Sstevel@tonic-gate 				curtype = INT_PTR;
23787c478bd9Sstevel@tonic-gate 			break;
23797c478bd9Sstevel@tonic-gate 		default:
23807c478bd9Sstevel@tonic-gate 			if (flags & FLAG_LONG_LONG)
23817c478bd9Sstevel@tonic-gate 				curtype = LONG_LONG;
23827c478bd9Sstevel@tonic-gate 			else if (flags & FLAG_LONG)
23837c478bd9Sstevel@tonic-gate 				curtype = LONG;
23847c478bd9Sstevel@tonic-gate 			else
23857c478bd9Sstevel@tonic-gate 				curtype = INT;
23867c478bd9Sstevel@tonic-gate 			break;
23877c478bd9Sstevel@tonic-gate 		}
23887c478bd9Sstevel@tonic-gate 		if (curargno >= 0 && curargno < MAXARGS) {
23897c478bd9Sstevel@tonic-gate 			typelst[curargno] = curtype;
23907c478bd9Sstevel@tonic-gate 			if (maxnum < curargno)
23917c478bd9Sstevel@tonic-gate 				maxnum = curargno;
23927c478bd9Sstevel@tonic-gate 		}
23937c478bd9Sstevel@tonic-gate 		curargno++;	/* default to next in list */
23947c478bd9Sstevel@tonic-gate 		if (flags & FLAG_INT)	/* took care of *, keep going */
23957c478bd9Sstevel@tonic-gate 		{
23967c478bd9Sstevel@tonic-gate 			flags ^= FLAG_INT;
23977c478bd9Sstevel@tonic-gate 			goto again;
23987c478bd9Sstevel@tonic-gate 		}
23997c478bd9Sstevel@tonic-gate 	}
24007c478bd9Sstevel@tonic-gate 	for (n = 0; n <= maxnum; n++) {
24017c478bd9Sstevel@tonic-gate 		arglst[n] = args;
24027c478bd9Sstevel@tonic-gate 		if (typelst[n] == 0)
24037c478bd9Sstevel@tonic-gate 			typelst[n] = INT;
24047c478bd9Sstevel@tonic-gate 
24057c478bd9Sstevel@tonic-gate 		switch (typelst[n]) {
24067c478bd9Sstevel@tonic-gate 		case INT:
24077c478bd9Sstevel@tonic-gate 			(void) va_arg(args.ap, int);
24087c478bd9Sstevel@tonic-gate 			break;
24097c478bd9Sstevel@tonic-gate 		case LONG:
24107c478bd9Sstevel@tonic-gate 			(void) va_arg(args.ap, long);
24117c478bd9Sstevel@tonic-gate 			break;
24127c478bd9Sstevel@tonic-gate 		case CHAR_PTR:
24137c478bd9Sstevel@tonic-gate 			(void) va_arg(args.ap, char *);
24147c478bd9Sstevel@tonic-gate 			break;
24157c478bd9Sstevel@tonic-gate 		case DOUBLE:
24167c478bd9Sstevel@tonic-gate 			(void) va_arg(args.ap, double);
24177c478bd9Sstevel@tonic-gate 			break;
24187c478bd9Sstevel@tonic-gate 		case LONG_DOUBLE:
24197c478bd9Sstevel@tonic-gate 			(void) GETQVAL(args.ap);
24207c478bd9Sstevel@tonic-gate 			break;
24217c478bd9Sstevel@tonic-gate 		case VOID_PTR:
24227c478bd9Sstevel@tonic-gate 			(void) va_arg(args.ap, void *);
24237c478bd9Sstevel@tonic-gate 			break;
24247c478bd9Sstevel@tonic-gate 		case LONG_PTR:
24257c478bd9Sstevel@tonic-gate 			(void) va_arg(args.ap, long *);
24267c478bd9Sstevel@tonic-gate 			break;
24277c478bd9Sstevel@tonic-gate 		case INT_PTR:
24287c478bd9Sstevel@tonic-gate 			(void) va_arg(args.ap, int *);
24297c478bd9Sstevel@tonic-gate 			break;
24307c478bd9Sstevel@tonic-gate 		case LONG_LONG:
24317c478bd9Sstevel@tonic-gate 			(void) va_arg(args.ap, long long);
24327c478bd9Sstevel@tonic-gate 			break;
24337c478bd9Sstevel@tonic-gate 		case LONG_LONG_PTR:
24347c478bd9Sstevel@tonic-gate 			(void) va_arg(args.ap, long long *);
24357c478bd9Sstevel@tonic-gate 			break;
24367c478bd9Sstevel@tonic-gate 		}
24377c478bd9Sstevel@tonic-gate 	}
24387c478bd9Sstevel@tonic-gate }
24397c478bd9Sstevel@tonic-gate 
24407c478bd9Sstevel@tonic-gate /*
24417c478bd9Sstevel@tonic-gate  * This function is used to find the va_list value for arguments whose
24427c478bd9Sstevel@tonic-gate  * position is greater than MAXARGS.  This function is slow, so hopefully
24437c478bd9Sstevel@tonic-gate  * MAXARGS will be big enough so that this function need only be called in
24447c478bd9Sstevel@tonic-gate  * unusual circumstances.
24457c478bd9Sstevel@tonic-gate  * pargs is assumed to contain the value of arglst[MAXARGS - 1].
24467c478bd9Sstevel@tonic-gate  */
24477c478bd9Sstevel@tonic-gate #ifdef	_WIDE
24487c478bd9Sstevel@tonic-gate static void
_wgetarg(wchar_t * fmt,stva_list * pargs,long argno,int prflag __unused)2449*4a38094cSToomas Soome _wgetarg(wchar_t *fmt, stva_list *pargs, long argno, int prflag __unused)
24507c478bd9Sstevel@tonic-gate #else  /* _WIDE */
24517c478bd9Sstevel@tonic-gate void
2452*4a38094cSToomas Soome _getarg(char *fmt, stva_list *pargs, long argno, int prflag __unused)
24537c478bd9Sstevel@tonic-gate #endif /* _WIDE */
24547c478bd9Sstevel@tonic-gate {
24557c478bd9Sstevel@tonic-gate 
24567c478bd9Sstevel@tonic-gate #ifdef	_WIDE
24577c478bd9Sstevel@tonic-gate 	static const wchar_t	digits[] = L"01234567890";
24587c478bd9Sstevel@tonic-gate 	static const wchar_t	skips[] = L"# +-.'0123456789h$";
24597c478bd9Sstevel@tonic-gate 	wchar_t	*sfmt = fmt;
24607c478bd9Sstevel@tonic-gate #else  /* _WIDE */
24617c478bd9Sstevel@tonic-gate 	static const char digits[] = "01234567890";
24627c478bd9Sstevel@tonic-gate 	static const char skips[] = "# +-.'0123456789h$";
24637c478bd9Sstevel@tonic-gate 	char	*sfmt = fmt;
24647c478bd9Sstevel@tonic-gate #endif /* _WIDE */
24657c478bd9Sstevel@tonic-gate 	ssize_t n;
24667c478bd9Sstevel@tonic-gate 	int i, curargno, flags;
24677c478bd9Sstevel@tonic-gate 	int	found = 1;
24687c478bd9Sstevel@tonic-gate 
24697c478bd9Sstevel@tonic-gate 	i = MAXARGS;
24707c478bd9Sstevel@tonic-gate 	curargno = 1;
24717c478bd9Sstevel@tonic-gate 	while (found) {
24727c478bd9Sstevel@tonic-gate 		fmt = sfmt;
24737c478bd9Sstevel@tonic-gate 		found = 0;
24747c478bd9Sstevel@tonic-gate 		while ((i != argno) && (fmt = STRCHR(fmt, '%')) != 0) {
24757c478bd9Sstevel@tonic-gate 			fmt++;	/* skip % */
24767c478bd9Sstevel@tonic-gate 			if (fmt[n = STRSPN(fmt, digits)] == '$') {
24777c478bd9Sstevel@tonic-gate 				curargno = ATOI(fmt);
24787c478bd9Sstevel@tonic-gate 				if (curargno <= 0)
24797c478bd9Sstevel@tonic-gate 					continue;
24807c478bd9Sstevel@tonic-gate 				fmt += n + 1;
24817c478bd9Sstevel@tonic-gate 			}
24827c478bd9Sstevel@tonic-gate 
24837c478bd9Sstevel@tonic-gate 			/* find conversion specifier for next argument */
24847c478bd9Sstevel@tonic-gate 			if (i != curargno) {
24857c478bd9Sstevel@tonic-gate 				curargno++;
24867c478bd9Sstevel@tonic-gate 				continue;
24877c478bd9Sstevel@tonic-gate 			} else
24887c478bd9Sstevel@tonic-gate 				found = 1;
24897c478bd9Sstevel@tonic-gate 			flags = 0;
24907c478bd9Sstevel@tonic-gate 		again:;
24917c478bd9Sstevel@tonic-gate 			fmt += STRSPN(fmt, skips);
24927c478bd9Sstevel@tonic-gate 			switch (*fmt++) {
24937c478bd9Sstevel@tonic-gate 			case '%':	/* there is no argument! */
24947c478bd9Sstevel@tonic-gate 				continue;
24957c478bd9Sstevel@tonic-gate 			case 'l':
24967c478bd9Sstevel@tonic-gate 				if (flags & (FLAG_LONG | FLAG_LONG_LONG)) {
24977c478bd9Sstevel@tonic-gate 					flags |= FLAG_LONG_LONG;
24987c478bd9Sstevel@tonic-gate 					flags &= ~FLAG_LONG;
24997c478bd9Sstevel@tonic-gate 				} else {
25007c478bd9Sstevel@tonic-gate 					flags |= FLAG_LONG;
25017c478bd9Sstevel@tonic-gate 				}
25027c478bd9Sstevel@tonic-gate 				goto again;
25037c478bd9Sstevel@tonic-gate 			case 'j':
25047c478bd9Sstevel@tonic-gate #ifndef _LP64
25057c478bd9Sstevel@tonic-gate 				/*
25067c478bd9Sstevel@tonic-gate 				 * *printf_c89() in 32-bit libc uses
25077c478bd9Sstevel@tonic-gate 				 * 32-bit intmax_t; otherwise intmax_t
25087c478bd9Sstevel@tonic-gate 				 * is 64-bits.
25097c478bd9Sstevel@tonic-gate 				 */
25107c478bd9Sstevel@tonic-gate 				if (!(prflag & _F_INTMAX32)) {
25117c478bd9Sstevel@tonic-gate #endif
25127c478bd9Sstevel@tonic-gate 					flags |= FLAG_LONG_LONG;  /* 64-bit */
25137c478bd9Sstevel@tonic-gate #ifndef _LP64
25147c478bd9Sstevel@tonic-gate 				}
25157c478bd9Sstevel@tonic-gate #endif
25167c478bd9Sstevel@tonic-gate 				goto again;
25177c478bd9Sstevel@tonic-gate 			case 't':
25187c478bd9Sstevel@tonic-gate 				flags |= FLAG_LONG;
25197c478bd9Sstevel@tonic-gate 				goto again;
25207c478bd9Sstevel@tonic-gate 			case 'z':
25217c478bd9Sstevel@tonic-gate 				flags |= FLAG_LONG;
25227c478bd9Sstevel@tonic-gate 				goto again;
25237c478bd9Sstevel@tonic-gate 			case 'L':
25247c478bd9Sstevel@tonic-gate 				flags |= FLAG_LONG_DBL;
25257c478bd9Sstevel@tonic-gate 				goto again;
25267c478bd9Sstevel@tonic-gate 			case '*':	/* int argument used for value */
25277c478bd9Sstevel@tonic-gate 				/*
25287c478bd9Sstevel@tonic-gate 				 * check if there is a positional parameter;
25297c478bd9Sstevel@tonic-gate 				 * if so, just skip it; its size will be
25307c478bd9Sstevel@tonic-gate 				 * correctly determined by default
25317c478bd9Sstevel@tonic-gate 				 */
25327c478bd9Sstevel@tonic-gate 				if (_M_ISDIGIT(*fmt)) {
25337c478bd9Sstevel@tonic-gate 					fmt += STRSPN(fmt, digits);
25347c478bd9Sstevel@tonic-gate 					if (*fmt == '$')
25357c478bd9Sstevel@tonic-gate 						fmt++; /* skip '$' */
25367c478bd9Sstevel@tonic-gate 					goto again;
25377c478bd9Sstevel@tonic-gate 				}
25387c478bd9Sstevel@tonic-gate 				flags |= FLAG_INT;
25397c478bd9Sstevel@tonic-gate 				(void) va_arg((*pargs).ap, int);
25407c478bd9Sstevel@tonic-gate 				break;
25417c478bd9Sstevel@tonic-gate 			case 'a':
25427c478bd9Sstevel@tonic-gate 			case 'A':
25437c478bd9Sstevel@tonic-gate 			case 'e':
25447c478bd9Sstevel@tonic-gate 			case 'E':
25457c478bd9Sstevel@tonic-gate 			case 'f':
25467c478bd9Sstevel@tonic-gate 			case 'F':
25477c478bd9Sstevel@tonic-gate 			case 'g':
25487c478bd9Sstevel@tonic-gate 			case 'G':
25497c478bd9Sstevel@tonic-gate 				if (flags & FLAG_LONG_DBL)
25507c478bd9Sstevel@tonic-gate 					(void) GETQVAL((*pargs).ap);
25517c478bd9Sstevel@tonic-gate 				else
25527c478bd9Sstevel@tonic-gate 					(void) va_arg((*pargs).ap, double);
25537c478bd9Sstevel@tonic-gate 				break;
25547c478bd9Sstevel@tonic-gate 			case 's':
25557c478bd9Sstevel@tonic-gate 				(void) va_arg((*pargs).ap, char *);
25567c478bd9Sstevel@tonic-gate 				break;
25577c478bd9Sstevel@tonic-gate 			case 'p':
25587c478bd9Sstevel@tonic-gate 				(void) va_arg((*pargs).ap, void *);
25597c478bd9Sstevel@tonic-gate 				break;
25607c478bd9Sstevel@tonic-gate 			case 'n':
25617c478bd9Sstevel@tonic-gate 				if (flags & FLAG_LONG_LONG)
25627c478bd9Sstevel@tonic-gate 					(void) va_arg((*pargs).ap, long long *);
25637c478bd9Sstevel@tonic-gate 				else if (flags & FLAG_LONG)
25647c478bd9Sstevel@tonic-gate 					(void) va_arg((*pargs).ap, long *);
25657c478bd9Sstevel@tonic-gate 				else
25667c478bd9Sstevel@tonic-gate 					(void) va_arg((*pargs).ap, int *);
25677c478bd9Sstevel@tonic-gate 				break;
25687c478bd9Sstevel@tonic-gate 			default:
25697c478bd9Sstevel@tonic-gate 				if (flags & FLAG_LONG_LONG)
25707c478bd9Sstevel@tonic-gate 					(void) va_arg((*pargs).ap, long long);
25717c478bd9Sstevel@tonic-gate 				else if (flags & FLAG_LONG)
25727c478bd9Sstevel@tonic-gate 					(void) va_arg((*pargs).ap, long int);
25737c478bd9Sstevel@tonic-gate 				else
25747c478bd9Sstevel@tonic-gate 					(void) va_arg((*pargs).ap, int);
25757c478bd9Sstevel@tonic-gate 				break;
25767c478bd9Sstevel@tonic-gate 			}
25777c478bd9Sstevel@tonic-gate 			i++;
25787c478bd9Sstevel@tonic-gate 			curargno++;	/* default to next in list */
25797c478bd9Sstevel@tonic-gate 			if (flags & FLAG_INT)	/* took care of *, keep going */
25807c478bd9Sstevel@tonic-gate 			{
25817c478bd9Sstevel@tonic-gate 				flags ^= FLAG_INT;
25827c478bd9Sstevel@tonic-gate 				goto again;
25837c478bd9Sstevel@tonic-gate 			}
25847c478bd9Sstevel@tonic-gate 		}
25857c478bd9Sstevel@tonic-gate 
25867c478bd9Sstevel@tonic-gate 		/* missing specifier for parameter, assume param is an int */
25877c478bd9Sstevel@tonic-gate 		if (!found && i != argno) {
25887c478bd9Sstevel@tonic-gate 			(void) va_arg((*pargs).ap, int);
25897c478bd9Sstevel@tonic-gate 			i++;
25907c478bd9Sstevel@tonic-gate 			curargno = i;
25917c478bd9Sstevel@tonic-gate 			found = 1;
25927c478bd9Sstevel@tonic-gate 		}
25937c478bd9Sstevel@tonic-gate 	}
25947c478bd9Sstevel@tonic-gate }
25957c478bd9Sstevel@tonic-gate 
25967c478bd9Sstevel@tonic-gate #ifdef	_WIDE
25977c478bd9Sstevel@tonic-gate static wchar_t *
insert_thousands_sep(wchar_t * bp,wchar_t * ep)25987c478bd9Sstevel@tonic-gate insert_thousands_sep(wchar_t *bp, wchar_t *ep)
25997c478bd9Sstevel@tonic-gate #else  /* _WIDE */
26007c478bd9Sstevel@tonic-gate static char *
26017c478bd9Sstevel@tonic-gate insert_thousands_sep(char *bp, char *ep)
26027c478bd9Sstevel@tonic-gate #endif /* _WIDE */
26037c478bd9Sstevel@tonic-gate {
26047c478bd9Sstevel@tonic-gate 	char thousep;
26057c478bd9Sstevel@tonic-gate 	struct lconv *locptr;
26067c478bd9Sstevel@tonic-gate 	ssize_t buf_index;
26077c478bd9Sstevel@tonic-gate 	int i;
26087c478bd9Sstevel@tonic-gate #ifdef	_WIDE
26097c478bd9Sstevel@tonic-gate 	wchar_t *obp = bp;
26107c478bd9Sstevel@tonic-gate 	wchar_t buf[371];
26117c478bd9Sstevel@tonic-gate 	wchar_t *bufptr = buf;
26127c478bd9Sstevel@tonic-gate #else  /* _WIDE */
26137c478bd9Sstevel@tonic-gate 	char *obp = bp;
26147c478bd9Sstevel@tonic-gate 	char buf[371];
26157c478bd9Sstevel@tonic-gate 	char *bufptr = buf;
26167c478bd9Sstevel@tonic-gate #endif /* _WIDE */
26177c478bd9Sstevel@tonic-gate 	char *grp_ptr;
26187c478bd9Sstevel@tonic-gate 
26197c478bd9Sstevel@tonic-gate 	/* get the thousands sep. from the current locale */
26207c478bd9Sstevel@tonic-gate 	locptr = localeconv();
26217c478bd9Sstevel@tonic-gate 	thousep	= *locptr->thousands_sep;
26227c478bd9Sstevel@tonic-gate 	grp_ptr = locptr->grouping;
26237c478bd9Sstevel@tonic-gate 
26247c478bd9Sstevel@tonic-gate 	/* thousands sep. not use in this locale or no grouping required */
26257c478bd9Sstevel@tonic-gate 	if (!thousep || (*grp_ptr == '\0'))
26267c478bd9Sstevel@tonic-gate 		return (ep);
26277c478bd9Sstevel@tonic-gate 
26287c478bd9Sstevel@tonic-gate 	buf_index = ep - bp;
26297c478bd9Sstevel@tonic-gate 	for (;;) {
26307c478bd9Sstevel@tonic-gate 		if (*grp_ptr == CHAR_MAX) {
26317c478bd9Sstevel@tonic-gate 			for (i = 0; i < buf_index--; i++)
26327c478bd9Sstevel@tonic-gate 				*bufptr++ = *(bp + buf_index);
26337c478bd9Sstevel@tonic-gate 			break;
26347c478bd9Sstevel@tonic-gate 		}
26357c478bd9Sstevel@tonic-gate 		for (i = 0; i < *grp_ptr && buf_index-- > 0; i++)
26367c478bd9Sstevel@tonic-gate 			*bufptr++ = *(bp + buf_index);
26377c478bd9Sstevel@tonic-gate 
26387c478bd9Sstevel@tonic-gate 		if (buf_index > 0) {
26397c478bd9Sstevel@tonic-gate #ifdef	_WIDE
26407c478bd9Sstevel@tonic-gate 			*bufptr++ = (wchar_t)thousep;
26417c478bd9Sstevel@tonic-gate #else  /* _WIDE */
26427c478bd9Sstevel@tonic-gate 			*bufptr++ = thousep;
26437c478bd9Sstevel@tonic-gate #endif /* _WIDE */
26447c478bd9Sstevel@tonic-gate 			ep++;
26457c478bd9Sstevel@tonic-gate 		}
26467c478bd9Sstevel@tonic-gate 		else
26477c478bd9Sstevel@tonic-gate 			break;
26487c478bd9Sstevel@tonic-gate 		if (*(grp_ptr + 1) != '\0')
26497c478bd9Sstevel@tonic-gate 			++grp_ptr;
26507c478bd9Sstevel@tonic-gate 	}
26517c478bd9Sstevel@tonic-gate 
26527c478bd9Sstevel@tonic-gate 	/* put the string in the caller's buffer in reverse order */
26537c478bd9Sstevel@tonic-gate 	--bufptr;
26547c478bd9Sstevel@tonic-gate 	while (buf <= bufptr)
26557c478bd9Sstevel@tonic-gate 		*obp++ = *bufptr--;
26567c478bd9Sstevel@tonic-gate 	return (ep);
26577c478bd9Sstevel@tonic-gate }
26587c478bd9Sstevel@tonic-gate 
2659804635d7SYuri Pankov #ifdef _WIDE
2660804635d7SYuri Pankov static wchar_t *
insert_decimal_point(wchar_t * ep)2661804635d7SYuri Pankov insert_decimal_point(wchar_t *ep)
2662804635d7SYuri Pankov #else
2663804635d7SYuri Pankov static char *
2664804635d7SYuri Pankov insert_decimal_point(char *ep)
2665804635d7SYuri Pankov #endif
2666804635d7SYuri Pankov {
2667804635d7SYuri Pankov 	struct lconv *locptr = localeconv();
2668804635d7SYuri Pankov 	char	*dp = locptr->decimal_point;
2669804635d7SYuri Pankov #ifdef _WIDE
2670804635d7SYuri Pankov 	wchar_t wdp;
2671804635d7SYuri Pankov 
2672804635d7SYuri Pankov 	(void) mbtowc(&wdp, dp, MB_CUR_MAX);
2673804635d7SYuri Pankov 	*ep = wdp;
2674804635d7SYuri Pankov 	return (ep + 1);
2675804635d7SYuri Pankov #else
2676804635d7SYuri Pankov 	(void) memcpy(ep, dp, strlen(dp));
2677804635d7SYuri Pankov 	return (ep + strlen(dp));
2678804635d7SYuri Pankov #endif
2679804635d7SYuri Pankov }
2680804635d7SYuri Pankov 
26817c478bd9Sstevel@tonic-gate 
26827c478bd9Sstevel@tonic-gate /*
26837c478bd9Sstevel@tonic-gate  *  Recovery scrswidth function -
26847c478bd9Sstevel@tonic-gate  *  this variant of wcswidth() accepts non-printable or illegal
26857c478bd9Sstevel@tonic-gate  *  widechar characters.
26867c478bd9Sstevel@tonic-gate  */
26877c478bd9Sstevel@tonic-gate static int
_rec_scrswidth(wchar_t * wp,ssize_t n)26887c478bd9Sstevel@tonic-gate _rec_scrswidth(wchar_t *wp, ssize_t n)
26897c478bd9Sstevel@tonic-gate {
26907c478bd9Sstevel@tonic-gate 	int col;
26917c478bd9Sstevel@tonic-gate 	int i;
26927c478bd9Sstevel@tonic-gate 
26937c478bd9Sstevel@tonic-gate 	col = 0;
26947c478bd9Sstevel@tonic-gate 	while (*wp && (n-- > 0)) {
26957c478bd9Sstevel@tonic-gate 		if ((i = _scrwidth(*wp++)) == 0)
26967c478bd9Sstevel@tonic-gate 			i = 1;
26977c478bd9Sstevel@tonic-gate 		col += i;
26987c478bd9Sstevel@tonic-gate 	}
26997c478bd9Sstevel@tonic-gate 	return (col);
27007c478bd9Sstevel@tonic-gate }
2701