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