xref: /titanic_44/usr/src/lib/libbc/libc/stdio/common/doprnt.c (revision 5d54f3d8999eac1762fe0a8c7177d20f1f201fae)
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
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
23*5d54f3d8Smuffin  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*5d54f3d8Smuffin  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /* Copyright (c) 1988 AT&T */
287c478bd9Sstevel@tonic-gate /* All Rights Reserved */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate /*
337c478bd9Sstevel@tonic-gate  *	_doprnt: common code for printf, fprintf, sprintf
347c478bd9Sstevel@tonic-gate  *	Floating-point code is included or not, depending
357c478bd9Sstevel@tonic-gate  *	on whether the preprocessor variable FLOAT is 1 or 0.
367c478bd9Sstevel@tonic-gate  */
377c478bd9Sstevel@tonic-gate #define MAXARGS 50
387c478bd9Sstevel@tonic-gate #ifndef FLOAT
397c478bd9Sstevel@tonic-gate #define	FLOAT	1	/* YES! we want floating */
407c478bd9Sstevel@tonic-gate #endif
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate #include <stdio.h>
437c478bd9Sstevel@tonic-gate #include <ctype.h>
44*5d54f3d8Smuffin #include <stdarg.h>
457c478bd9Sstevel@tonic-gate #include <values.h>
467c478bd9Sstevel@tonic-gate #include <locale.h>
477c478bd9Sstevel@tonic-gate #include "doprnt.h"
487c478bd9Sstevel@tonic-gate #include "stdiom.h"
497c478bd9Sstevel@tonic-gate #include <string.h>	/* strchr, strlen, strspn */
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate #define max(a,b)	((a) > (b) ? (a) : (b))
527c478bd9Sstevel@tonic-gate #define min(a,b)	((a) < (b) ? (a) : (b))
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate /* If this symbol is nonzero, allow '0' as a flag */
557c478bd9Sstevel@tonic-gate /* If this symbol is nonzero, allow '0' as a flag */
567c478bd9Sstevel@tonic-gate #define FZERO 1
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate #if FLOAT
597c478bd9Sstevel@tonic-gate /*
607c478bd9Sstevel@tonic-gate  *	libc/gen/common functions for floating-point conversion
617c478bd9Sstevel@tonic-gate  */
627c478bd9Sstevel@tonic-gate #include <floatingpoint.h>
637c478bd9Sstevel@tonic-gate extern void _fourdigitsquick();
647c478bd9Sstevel@tonic-gate #endif
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate #define emitchar(c)   { if (--filecnt < 0) { \
67*5d54f3d8Smuffin 				FILE *iop = file; \
687c478bd9Sstevel@tonic-gate 				if (((iop->_flag & (_IOLBF|_IONBF)) == 0 \
697c478bd9Sstevel@tonic-gate 				    || -filecnt >= iop->_bufsiz)) { \
707c478bd9Sstevel@tonic-gate 					iop->_ptr = fileptr; \
717c478bd9Sstevel@tonic-gate 					if (iop->_flag & _IOSTRG) \
727c478bd9Sstevel@tonic-gate 						return iop->_ptr - iop->_base; \
737c478bd9Sstevel@tonic-gate 					else \
747c478bd9Sstevel@tonic-gate 						(void) _xflsbuf(iop); \
757c478bd9Sstevel@tonic-gate 					fileptr = iop->_ptr; \
767c478bd9Sstevel@tonic-gate 					filecnt = iop->_cnt; \
777c478bd9Sstevel@tonic-gate 					filecnt--; \
787c478bd9Sstevel@tonic-gate 				    } \
797c478bd9Sstevel@tonic-gate 			} \
807c478bd9Sstevel@tonic-gate 			*fileptr++ = (unsigned)(c); \
817c478bd9Sstevel@tonic-gate 			count++; \
827c478bd9Sstevel@tonic-gate                       }
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate static char *nullstr = "(null)";
857c478bd9Sstevel@tonic-gate static char *lowerhex = "0123456789abcdef";
867c478bd9Sstevel@tonic-gate static char *upperhex = "0123456789ABCDEF";
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate /* stva_list is used to subvert C's restriction that a variable with an
897c478bd9Sstevel@tonic-gate  * array type can not appear on the left hand side of an assignment operator.
907c478bd9Sstevel@tonic-gate  * By putting the array inside a structure, the functionality of assigning to
917c478bd9Sstevel@tonic-gate  * the whole array through a simple assignment is achieved..
927c478bd9Sstevel@tonic-gate */
937c478bd9Sstevel@tonic-gate typedef struct stva_list {
947c478bd9Sstevel@tonic-gate 	va_list ap;
957c478bd9Sstevel@tonic-gate } stva_list;
967c478bd9Sstevel@tonic-gate 
97*5d54f3d8Smuffin void	_mkarglst(char *, stva_list, stva_list []);
98*5d54f3d8Smuffin void	_getarg(char *, stva_list *, int);
99*5d54f3d8Smuffin static char	*_check_dol(char *, int *);
100*5d54f3d8Smuffin 
101*5d54f3d8Smuffin int
_doprnt(char * format,va_list in_args,FILE * file)102*5d54f3d8Smuffin _doprnt(char *format, va_list in_args, FILE *file)
1037c478bd9Sstevel@tonic-gate {
1047c478bd9Sstevel@tonic-gate 	char convertbuffer[1024] ;
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	/* Current position in format */
107*5d54f3d8Smuffin 	char *cp;
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate 	/* Starting and ending points for value to be printed */
110*5d54f3d8Smuffin 	char *bp;
1117c478bd9Sstevel@tonic-gate 	char *p;
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 	/* Pointer and count for I/O buffer */
114*5d54f3d8Smuffin 	unsigned char *fileptr;
115*5d54f3d8Smuffin 	int filecnt;
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 	/* Field width and precision */
1187c478bd9Sstevel@tonic-gate 	int width;
119*5d54f3d8Smuffin 	int prec;
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate 	/* Format code */
1227c478bd9Sstevel@tonic-gate 	char fcode;
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	/* Number of padding zeroes required on the left */
1257c478bd9Sstevel@tonic-gate 	int lzero;
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	/* Flags - nonzero if corresponding character appears in format */
1287c478bd9Sstevel@tonic-gate 	bool fplus;		/* + */
1297c478bd9Sstevel@tonic-gate 	bool fminus;		/* - */
1307c478bd9Sstevel@tonic-gate 	bool fblank;		/* blank */
1317c478bd9Sstevel@tonic-gate 	bool fsharp;		/* # */
1327c478bd9Sstevel@tonic-gate #if FZERO
1337c478bd9Sstevel@tonic-gate 	bool ansi_fzero;	/* 0 for ansi-dictated formats */
1347c478bd9Sstevel@tonic-gate 	bool compat_fzero;	/* 0 for backward compatibility */
1357c478bd9Sstevel@tonic-gate #endif
1367c478bd9Sstevel@tonic-gate 	bool Lsize;             /* Capital L for size = long double = quadruple */
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	/* Pointer to sign, "0x", "0X", or empty */
1397c478bd9Sstevel@tonic-gate 	char *prefix;
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	/* Scratch */
1427c478bd9Sstevel@tonic-gate 	int nblank;
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate #if FLOAT
1457c478bd9Sstevel@tonic-gate 	/* Exponent or empty */
1467c478bd9Sstevel@tonic-gate 	char *suffix;
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	/* Buffer to create exponent */
1497c478bd9Sstevel@tonic-gate 	char expbuf[7];  /* "e+xxxx\0" */
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	/* Number of padding zeroes required on the right */
1527c478bd9Sstevel@tonic-gate 	int rzero;
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	/* Length of exponent suffix. */
1557c478bd9Sstevel@tonic-gate 	int suffixlength;
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate 	/* The value being converted, if real or quadruple */
1587c478bd9Sstevel@tonic-gate 	double dval;
1597c478bd9Sstevel@tonic-gate 	quadruple qval;
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	/* Output values from fconvert and econvert */
1627c478bd9Sstevel@tonic-gate 	int decpt, sign;
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	/* Values are developed in this buffer */
1657c478bd9Sstevel@tonic-gate 	char buf[1034];		/* Size of convertbuffer, plus some for exponent and sign. */
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 	/* Current locale's decimal point */
1687c478bd9Sstevel@tonic-gate 	char decpt_char = *(localeconv()->decimal_point);
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate #else
1717c478bd9Sstevel@tonic-gate 	/* Values are developed in this buffer */
1727c478bd9Sstevel@tonic-gate 	char buf[MAXDIGS];
1737c478bd9Sstevel@tonic-gate #endif
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	/* The value being converted, if integer */
177*5d54f3d8Smuffin 	unsigned long val;
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 	/* Work variables */
180*5d54f3d8Smuffin 	int n;
181*5d54f3d8Smuffin 	char c;
1827c478bd9Sstevel@tonic-gate 	char radix;
1837c478bd9Sstevel@tonic-gate 	int svswitch = 0;
1847c478bd9Sstevel@tonic-gate 	/* count of output characters */
185*5d54f3d8Smuffin 	int count;
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate 	/* variables for positional parameters */
1887c478bd9Sstevel@tonic-gate 	char    *sformat = format;      /* save the beginning of the format */
1897c478bd9Sstevel@tonic-gate 	int     fpos = 1;               /* 1 if first positional parameter */
1907c478bd9Sstevel@tonic-gate 	stva_list       args,   /* used to step through the argument list */
1917c478bd9Sstevel@tonic-gate 			args_width, 	/* for width */
1927c478bd9Sstevel@tonic-gate 			args_prec, 	/* for prec */
1937c478bd9Sstevel@tonic-gate 			sargs;  /* used to save the start of the argument list */
1947c478bd9Sstevel@tonic-gate 	stva_list       arglst[MAXARGS];/* array giving the approriate values
1957c478bd9Sstevel@tonic-gate 					 * for va_arg() to retrieve the
1967c478bd9Sstevel@tonic-gate 				  	 * corresponding argument:
1977c478bd9Sstevel@tonic-gate 					 * arglst[0] is the first argument
1987c478bd9Sstevel@tonic-gate 				         * arglst[1] is the second argument, etc.
1997c478bd9Sstevel@tonic-gate 				         */
2007c478bd9Sstevel@tonic-gate 											      int index = 0;			/* argument placeolder */
2017c478bd9Sstevel@tonic-gate 											     /* Initialize args and sargs to the start of the argument list.
2027c478bd9Sstevel@tonic-gate         * Note that ANSI guarantees that the address of the first member of
2037c478bd9Sstevel@tonic-gate         * a structure will be the same as the address of the structure. */
2047c478bd9Sstevel@tonic-gate 											       args_width = args_prec = args = sargs = *(struct stva_list *)&in_args;
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate /*  initialize p an bp (starting and ending points)  bugid 1141781 */
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 	p = bp = NULL;
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	cp = format;
2127c478bd9Sstevel@tonic-gate 	if ((c = *cp++) != '\0') {
2137c478bd9Sstevel@tonic-gate 		/*
2147c478bd9Sstevel@tonic-gate 		 * We know we're going to write something; make sure
2157c478bd9Sstevel@tonic-gate 		 * we can write and set up buffers, etc..
2167c478bd9Sstevel@tonic-gate 		 */
2177c478bd9Sstevel@tonic-gate 		if (_WRTCHK(file))
2187c478bd9Sstevel@tonic-gate 			return(EOF);
2197c478bd9Sstevel@tonic-gate 	} else
2207c478bd9Sstevel@tonic-gate 		return(0);	/* no fault, no error */
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 	count = 0;
2237c478bd9Sstevel@tonic-gate 	fileptr = file->_ptr;
2247c478bd9Sstevel@tonic-gate 	filecnt = file->_cnt;
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 	/*
2277c478bd9Sstevel@tonic-gate 	 *	The main loop -- this loop goes through one iteration
2287c478bd9Sstevel@tonic-gate 	 *	for each ordinary character or format specification.
2297c478bd9Sstevel@tonic-gate 	 */
2307c478bd9Sstevel@tonic-gate 	do {
2317c478bd9Sstevel@tonic-gate 		if (c != '%') {
2327c478bd9Sstevel@tonic-gate 			/* Ordinary (non-%) character */
2337c478bd9Sstevel@tonic-gate 			emitchar(c);
2347c478bd9Sstevel@tonic-gate 		} else {
2357c478bd9Sstevel@tonic-gate 			/*
2367c478bd9Sstevel@tonic-gate 			 *	% has been spotted!
2377c478bd9Sstevel@tonic-gate 			 *
2387c478bd9Sstevel@tonic-gate 			 *	First, try the 99% cases.
2397c478bd9Sstevel@tonic-gate 			 *	then parse the format specification.
2407c478bd9Sstevel@tonic-gate 			 *
2417c478bd9Sstevel@tonic-gate 			 *	Note that this code assumes the Sun
2427c478bd9Sstevel@tonic-gate 			 *	Workstation environment (all params
2437c478bd9Sstevel@tonic-gate 			 *	passed as int == long, no interrupts
2447c478bd9Sstevel@tonic-gate 			 *	for fixed point overflow from negating
2457c478bd9Sstevel@tonic-gate 			 *	the most negative number).
2467c478bd9Sstevel@tonic-gate 			 */
2477c478bd9Sstevel@tonic-gate 		skipit:
2487c478bd9Sstevel@tonic-gate 			switch(c = *cp++) {
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 			case 'l':
2517c478bd9Sstevel@tonic-gate 			case 'h':
2527c478bd9Sstevel@tonic-gate 				/* Quickly ignore long & short specifiers */
2537c478bd9Sstevel@tonic-gate 				goto skipit;
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 			case 's':
2567c478bd9Sstevel@tonic-gate 				bp = va_arg(args.ap, char *);
2577c478bd9Sstevel@tonic-gate 				if (bp == NULL)
2587c478bd9Sstevel@tonic-gate 					bp = nullstr;
2597c478bd9Sstevel@tonic-gate 				while (c = *bp++)
2607c478bd9Sstevel@tonic-gate 					emitchar(c);
2617c478bd9Sstevel@tonic-gate 				p = bp;
2627c478bd9Sstevel@tonic-gate 				continue;
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate 			case 'c':
2657c478bd9Sstevel@tonic-gate 				c = va_arg(args.ap, int);
2667c478bd9Sstevel@tonic-gate 			emitc:
2677c478bd9Sstevel@tonic-gate 				emitchar(c);
2687c478bd9Sstevel@tonic-gate 				continue;
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 			case 'i':
2717c478bd9Sstevel@tonic-gate 			case 'd':
2727c478bd9Sstevel@tonic-gate 			case 'D':
2737c478bd9Sstevel@tonic-gate 				val = va_arg(args.ap, int);
2747c478bd9Sstevel@tonic-gate 				if ((long) val < 0) {
2757c478bd9Sstevel@tonic-gate 					emitchar('-');
2767c478bd9Sstevel@tonic-gate 					val = -val;
2777c478bd9Sstevel@tonic-gate 				}
2787c478bd9Sstevel@tonic-gate 				goto udcommon;
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 			case 'U':
2817c478bd9Sstevel@tonic-gate 			case 'u':
2827c478bd9Sstevel@tonic-gate 				val = va_arg(args.ap, unsigned);
2837c478bd9Sstevel@tonic-gate 			udcommon:
2847c478bd9Sstevel@tonic-gate                                 {
285*5d54f3d8Smuffin                                 char *stringp = lowerhex;
2867c478bd9Sstevel@tonic-gate                                 bp = buf+MAXDIGS;
2877c478bd9Sstevel@tonic-gate                                 stringp = lowerhex;
2887c478bd9Sstevel@tonic-gate                                 do {
2897c478bd9Sstevel@tonic-gate                                         *--bp = stringp[val%10];
2907c478bd9Sstevel@tonic-gate                                         val /= 10;
2917c478bd9Sstevel@tonic-gate                                 } while (val);
2927c478bd9Sstevel@tonic-gate 				}
2937c478bd9Sstevel@tonic-gate                                 goto intout;
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 			case 'X':
2967c478bd9Sstevel@tonic-gate 				{
297*5d54f3d8Smuffin 				char *stringp = upperhex;
2987c478bd9Sstevel@tonic-gate 				val = va_arg(args.ap, unsigned);
2997c478bd9Sstevel@tonic-gate 				bp = buf + MAXDIGS;
3007c478bd9Sstevel@tonic-gate 				if (val == 0)
3017c478bd9Sstevel@tonic-gate 					goto zero;
3027c478bd9Sstevel@tonic-gate 				while (val) {
3037c478bd9Sstevel@tonic-gate 					*--bp = stringp[val%16];
3047c478bd9Sstevel@tonic-gate 					val /= 16;
3057c478bd9Sstevel@tonic-gate 				}
3067c478bd9Sstevel@tonic-gate 				}
3077c478bd9Sstevel@tonic-gate 				goto intout;
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 			case 'x':
3107c478bd9Sstevel@tonic-gate 			case 'p':
3117c478bd9Sstevel@tonic-gate 				{
312*5d54f3d8Smuffin 				char *stringp = lowerhex;
3137c478bd9Sstevel@tonic-gate 				val = va_arg(args.ap, unsigned);
3147c478bd9Sstevel@tonic-gate 				bp = buf + MAXDIGS;
3157c478bd9Sstevel@tonic-gate 				if (val == 0)
3167c478bd9Sstevel@tonic-gate 					goto zero;
3177c478bd9Sstevel@tonic-gate 				while (val) {
3187c478bd9Sstevel@tonic-gate 					*--bp = stringp[val%16];
3197c478bd9Sstevel@tonic-gate 					val /= 16;
3207c478bd9Sstevel@tonic-gate 				}
3217c478bd9Sstevel@tonic-gate 				}
3227c478bd9Sstevel@tonic-gate 				goto intout;
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 			case 'O':
3257c478bd9Sstevel@tonic-gate 			case 'o':
3267c478bd9Sstevel@tonic-gate 				{
327*5d54f3d8Smuffin 				char *stringp = lowerhex;
3287c478bd9Sstevel@tonic-gate 				val = va_arg(args.ap, unsigned);
3297c478bd9Sstevel@tonic-gate 				bp = buf + MAXDIGS;
3307c478bd9Sstevel@tonic-gate 				if (val == 0)
3317c478bd9Sstevel@tonic-gate 					goto zero;
3327c478bd9Sstevel@tonic-gate 				while (val) {
3337c478bd9Sstevel@tonic-gate 					*--bp = stringp[val%8];
3347c478bd9Sstevel@tonic-gate 					val /= 8;
3357c478bd9Sstevel@tonic-gate 				}
3367c478bd9Sstevel@tonic-gate 				}
3377c478bd9Sstevel@tonic-gate 				/* Common code to output integers */
3387c478bd9Sstevel@tonic-gate 			intout:
3397c478bd9Sstevel@tonic-gate 				p = buf + MAXDIGS;
3407c478bd9Sstevel@tonic-gate 				while (bp < p) {
3417c478bd9Sstevel@tonic-gate 					c = *bp++;
3427c478bd9Sstevel@tonic-gate 					emitchar(c);
3437c478bd9Sstevel@tonic-gate 				}
3447c478bd9Sstevel@tonic-gate 				continue;
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 			zero:
3477c478bd9Sstevel@tonic-gate 				c = '0';
3487c478bd9Sstevel@tonic-gate 				goto emitc;
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 			default:
3517c478bd9Sstevel@tonic-gate 				/*
3527c478bd9Sstevel@tonic-gate 				 * let AT&T deal with it
3537c478bd9Sstevel@tonic-gate 				 */
3547c478bd9Sstevel@tonic-gate 				cp-= 2;
3557c478bd9Sstevel@tonic-gate 			}
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate 			Lsize = 0;      /* Not long double unless we say so. */
3587c478bd9Sstevel@tonic-gate                         /* Scan the <flags> */
3597c478bd9Sstevel@tonic-gate 			fplus = 0;
3607c478bd9Sstevel@tonic-gate 			fminus = 0;
3617c478bd9Sstevel@tonic-gate 			fblank = 0;
3627c478bd9Sstevel@tonic-gate 			fsharp = 0;
3637c478bd9Sstevel@tonic-gate #if FZERO
3647c478bd9Sstevel@tonic-gate 			ansi_fzero = 0;
3657c478bd9Sstevel@tonic-gate 			compat_fzero = 0;
3667c478bd9Sstevel@tonic-gate #endif
3677c478bd9Sstevel@tonic-gate 		scan:	switch (*++cp) {
3687c478bd9Sstevel@tonic-gate 			case '+':
3697c478bd9Sstevel@tonic-gate 				fplus = 1;
3707c478bd9Sstevel@tonic-gate 				goto scan;
3717c478bd9Sstevel@tonic-gate 			case '-':
3727c478bd9Sstevel@tonic-gate 				fminus = 1;
3737c478bd9Sstevel@tonic-gate 				goto scan;
3747c478bd9Sstevel@tonic-gate 			case ' ':
3757c478bd9Sstevel@tonic-gate 				fblank = 1;
3767c478bd9Sstevel@tonic-gate 				goto scan;
3777c478bd9Sstevel@tonic-gate 			case '#':
3787c478bd9Sstevel@tonic-gate 				fsharp = 1;
3797c478bd9Sstevel@tonic-gate 				goto scan;
3807c478bd9Sstevel@tonic-gate #if FZERO
3817c478bd9Sstevel@tonic-gate 			case '0':
3827c478bd9Sstevel@tonic-gate 				ansi_fzero = 1;
3837c478bd9Sstevel@tonic-gate 				compat_fzero = 1;
3847c478bd9Sstevel@tonic-gate 				goto scan;
3857c478bd9Sstevel@tonic-gate #endif
3867c478bd9Sstevel@tonic-gate 			}
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 			/* Scan the field width */
3897c478bd9Sstevel@tonic-gate 			if (*cp == '*') {
3907c478bd9Sstevel@tonic-gate 				char *p;
3917c478bd9Sstevel@tonic-gate 				int val;
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 				p = _check_dol(cp+1, &val);
3947c478bd9Sstevel@tonic-gate 				if (p != (char *)NULL) {
3957c478bd9Sstevel@tonic-gate 					/*
3967c478bd9Sstevel@tonic-gate 					 * argument re-order
3977c478bd9Sstevel@tonic-gate 					 */
3987c478bd9Sstevel@tonic-gate 					if (fpos) {
3997c478bd9Sstevel@tonic-gate 						_mkarglst(sformat, sargs, arglst);
4007c478bd9Sstevel@tonic-gate 						fpos = 0;
4017c478bd9Sstevel@tonic-gate 					}
4027c478bd9Sstevel@tonic-gate 					if (val <= MAXARGS) {
4037c478bd9Sstevel@tonic-gate 						args_width = arglst[val - 1];
4047c478bd9Sstevel@tonic-gate 					} else {
4057c478bd9Sstevel@tonic-gate 						args_width = arglst[MAXARGS - 1];
4067c478bd9Sstevel@tonic-gate 						_getarg(sformat, &args_width, val);
4077c478bd9Sstevel@tonic-gate 					}
4087c478bd9Sstevel@tonic-gate 					width = va_arg(args_width.ap, int);
4097c478bd9Sstevel@tonic-gate 					if (width < 0) {
4107c478bd9Sstevel@tonic-gate 						width = -width;
4117c478bd9Sstevel@tonic-gate 						fminus = 1;
4127c478bd9Sstevel@tonic-gate 					}
4137c478bd9Sstevel@tonic-gate 					cp = p;
4147c478bd9Sstevel@tonic-gate 				}
4157c478bd9Sstevel@tonic-gate 				else {
4167c478bd9Sstevel@tonic-gate 					width = va_arg(args.ap, int);
4177c478bd9Sstevel@tonic-gate 					if (width < 0) {
4187c478bd9Sstevel@tonic-gate 						width = -width;
4197c478bd9Sstevel@tonic-gate 						fminus = 1;
4207c478bd9Sstevel@tonic-gate 					}
4217c478bd9Sstevel@tonic-gate 					cp++;
4227c478bd9Sstevel@tonic-gate 				}
4237c478bd9Sstevel@tonic-gate 			} else {
4247c478bd9Sstevel@tonic-gate 				index = width = 0;
4257c478bd9Sstevel@tonic-gate 				while (isdigit(*cp)) {
4267c478bd9Sstevel@tonic-gate 					n = tonumber(*cp++);
4277c478bd9Sstevel@tonic-gate 					index = width = width * 10 + n;
4287c478bd9Sstevel@tonic-gate 				}
4297c478bd9Sstevel@tonic-gate 			}
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 			/* Scan the precision */
4327c478bd9Sstevel@tonic-gate 			if (*cp == '.') {
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 				/* '*' instead of digits? */
4357c478bd9Sstevel@tonic-gate 				if (*++cp == '*') {
4367c478bd9Sstevel@tonic-gate 					char *p;
4377c478bd9Sstevel@tonic-gate 					int val;
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 					p = _check_dol(cp+1, &val);
4407c478bd9Sstevel@tonic-gate 					if (p != (char *)NULL) {
4417c478bd9Sstevel@tonic-gate 						/*
4427c478bd9Sstevel@tonic-gate 						 * argument re-order
4437c478bd9Sstevel@tonic-gate 						 */
4447c478bd9Sstevel@tonic-gate 						if (fpos) {
4457c478bd9Sstevel@tonic-gate 							_mkarglst(sformat, sargs, arglst);
4467c478bd9Sstevel@tonic-gate 							fpos = 0;
4477c478bd9Sstevel@tonic-gate 						}
4487c478bd9Sstevel@tonic-gate 						if (val <= MAXARGS) {
4497c478bd9Sstevel@tonic-gate 							args_prec = arglst[val - 1];
4507c478bd9Sstevel@tonic-gate 						} else {
4517c478bd9Sstevel@tonic-gate 							args_prec = arglst[MAXARGS - 1];
4527c478bd9Sstevel@tonic-gate 							_getarg(sformat, &args_prec, val);
4537c478bd9Sstevel@tonic-gate 						}
4547c478bd9Sstevel@tonic-gate 						prec = va_arg(args_prec.ap, int);
4557c478bd9Sstevel@tonic-gate 						cp = p;
4567c478bd9Sstevel@tonic-gate 					}
4577c478bd9Sstevel@tonic-gate 					else {
4587c478bd9Sstevel@tonic-gate 						prec = va_arg(args.ap, int);
4597c478bd9Sstevel@tonic-gate 						cp++;
4607c478bd9Sstevel@tonic-gate 					}
4617c478bd9Sstevel@tonic-gate 				} else {
4627c478bd9Sstevel@tonic-gate 					prec = 0;
4637c478bd9Sstevel@tonic-gate 					while (isdigit(*cp)) {
4647c478bd9Sstevel@tonic-gate 						n = tonumber(*cp++);
4657c478bd9Sstevel@tonic-gate 						prec = prec * 10 + n;
4667c478bd9Sstevel@tonic-gate 					}
4677c478bd9Sstevel@tonic-gate 				}
4687c478bd9Sstevel@tonic-gate 			} else
4697c478bd9Sstevel@tonic-gate 				prec = -1;
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 			if (*cp == '$') {
4727c478bd9Sstevel@tonic-gate 				if (fpos) {
4737c478bd9Sstevel@tonic-gate 					_mkarglst(sformat, sargs, arglst);
4747c478bd9Sstevel@tonic-gate 					fpos = 0;
4757c478bd9Sstevel@tonic-gate 				}
4767c478bd9Sstevel@tonic-gate 				if (index <= MAXARGS) {
4777c478bd9Sstevel@tonic-gate 					args = arglst[index - 1];
4787c478bd9Sstevel@tonic-gate 				} else {
4797c478bd9Sstevel@tonic-gate 					args = arglst[MAXARGS - 1];
4807c478bd9Sstevel@tonic-gate 					_getarg(sformat, &args, index);
4817c478bd9Sstevel@tonic-gate 				}
4827c478bd9Sstevel@tonic-gate 				goto scan;
4837c478bd9Sstevel@tonic-gate 			}
4847c478bd9Sstevel@tonic-gate 			/*
4857c478bd9Sstevel@tonic-gate 			 *	The character addressed by cp must be the
4867c478bd9Sstevel@tonic-gate 			 *	format letter -- there is nothing left for
4877c478bd9Sstevel@tonic-gate 			 *	it to be.
4887c478bd9Sstevel@tonic-gate 			 *
4897c478bd9Sstevel@tonic-gate 			 *	The status of the +, -, #, blank, and 0
4907c478bd9Sstevel@tonic-gate 			 *	flags are reflected in the variables
4917c478bd9Sstevel@tonic-gate 			 *	"fplus", "fminus", "fsharp", "fblank",
4927c478bd9Sstevel@tonic-gate 			 *	and "ansi_fzero"/"compat_fzero", respectively.
4937c478bd9Sstevel@tonic-gate 			 *	"width" and "prec" contain numbers
4947c478bd9Sstevel@tonic-gate 			 *	corresponding to the digit strings
4957c478bd9Sstevel@tonic-gate 			 *	before and after the decimal point,
4967c478bd9Sstevel@tonic-gate 			 *	respectively. If there was no decimal
4977c478bd9Sstevel@tonic-gate 			 *	point, "prec" is -1.
4987c478bd9Sstevel@tonic-gate 			 *
4997c478bd9Sstevel@tonic-gate 			 *	The following switch sets things up
5007c478bd9Sstevel@tonic-gate 			 *	for printing.  What ultimately gets
5017c478bd9Sstevel@tonic-gate 			 *	printed will be padding blanks, a prefix,
5027c478bd9Sstevel@tonic-gate 			 *	left padding zeroes, a value, right padding
5037c478bd9Sstevel@tonic-gate 			 *	zeroes, a suffix, and more padding
5047c478bd9Sstevel@tonic-gate 			 *	blanks.  Padding blanks will not appear
5057c478bd9Sstevel@tonic-gate 			 *	simultaneously on both the left and the
5067c478bd9Sstevel@tonic-gate 			 *	right.  Each case in this switch will
5077c478bd9Sstevel@tonic-gate 			 *	compute the value, and leave in several
5087c478bd9Sstevel@tonic-gate 			 *	variables the information necessary to
5097c478bd9Sstevel@tonic-gate 			 *	construct what is to be printed.
5107c478bd9Sstevel@tonic-gate 			 *
5117c478bd9Sstevel@tonic-gate 			 *	The prefix is a sign, a blank, "0x", "0X",
5127c478bd9Sstevel@tonic-gate 			 *	or null, and is addressed by "prefix".
5137c478bd9Sstevel@tonic-gate 			 *
5147c478bd9Sstevel@tonic-gate 			 *	The suffix is either null or an exponent,
5157c478bd9Sstevel@tonic-gate 			 *	and is addressed by "suffix".
5167c478bd9Sstevel@tonic-gate 			 *
5177c478bd9Sstevel@tonic-gate 			 *	The value to be printed starts at "bp"
5187c478bd9Sstevel@tonic-gate 			 *	and continues up to and not including "p".
5197c478bd9Sstevel@tonic-gate 			 *
5207c478bd9Sstevel@tonic-gate 			 *	"lzero" and "rzero" will contain the number
5217c478bd9Sstevel@tonic-gate 			 *	of padding zeroes required on the left
5227c478bd9Sstevel@tonic-gate 			 *	and right, respectively.  If either of
5237c478bd9Sstevel@tonic-gate 			 *	these variables is negative, it will be
5247c478bd9Sstevel@tonic-gate 			 *	treated as if it were zero.
5257c478bd9Sstevel@tonic-gate 			 *
5267c478bd9Sstevel@tonic-gate 			 *	The number of padding blanks, and whether
5277c478bd9Sstevel@tonic-gate 			 *	they go on the left or the right, will be
5287c478bd9Sstevel@tonic-gate 			 *	computed on exit from the switch.
5297c478bd9Sstevel@tonic-gate 			 */
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 			lzero = 0;
5327c478bd9Sstevel@tonic-gate 			prefix = "";
5337c478bd9Sstevel@tonic-gate #if FLOAT
5347c478bd9Sstevel@tonic-gate 			rzero = 0;
5357c478bd9Sstevel@tonic-gate 			suffix = prefix;
5367c478bd9Sstevel@tonic-gate #endif
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate #if FZERO
5397c478bd9Sstevel@tonic-gate 		  	/* if both zero-padding and left-justify flags
5407c478bd9Sstevel@tonic-gate 			 * are used, ignore zero-padding, per ansi c
5417c478bd9Sstevel@tonic-gate 			 */
5427c478bd9Sstevel@tonic-gate 		  	if (ansi_fzero & fminus) {
5437c478bd9Sstevel@tonic-gate 				ansi_fzero = 0;
5447c478bd9Sstevel@tonic-gate 				compat_fzero = 0;
5457c478bd9Sstevel@tonic-gate 			}
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 		  	/* if zero-padding and precision are specified,
5487c478bd9Sstevel@tonic-gate 			 * ignore zero-padding for ansi-dictated formats,
5497c478bd9Sstevel@tonic-gate 			 * per ansi c
5507c478bd9Sstevel@tonic-gate 			 */
5517c478bd9Sstevel@tonic-gate 		  	if (ansi_fzero & (prec != -1)) ansi_fzero = 0;
5527c478bd9Sstevel@tonic-gate #endif
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 		next:
5557c478bd9Sstevel@tonic-gate 			switch (fcode = *cp++) {
5567c478bd9Sstevel@tonic-gate 
5577c478bd9Sstevel@tonic-gate 			/* toss the length modifier, if any */
5587c478bd9Sstevel@tonic-gate 			case 'l':
5597c478bd9Sstevel@tonic-gate 			case 'h':
5607c478bd9Sstevel@tonic-gate 				goto next;
5617c478bd9Sstevel@tonic-gate 
5627c478bd9Sstevel@tonic-gate                        	case 'L':
5637c478bd9Sstevel@tonic-gate                       		Lsize = 1;      /* Remember long double size. */
5647c478bd9Sstevel@tonic-gate                          	goto next;
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate 			/*
5677c478bd9Sstevel@tonic-gate 			 *	fixed point representations
5687c478bd9Sstevel@tonic-gate 			 *
5697c478bd9Sstevel@tonic-gate 			 *	"radix" is the radix for the conversion.
5707c478bd9Sstevel@tonic-gate 			 *	Conversion is unsigned unless fcode is 'd'.
5717c478bd9Sstevel@tonic-gate 			 *	We assume a 2's complement machine and
5727c478bd9Sstevel@tonic-gate 			 *	that fixed point overflow (from negating
5737c478bd9Sstevel@tonic-gate 			 *	the largest negative int) is ignored.
5747c478bd9Sstevel@tonic-gate 			 */
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate 			case 'i':
5777c478bd9Sstevel@tonic-gate 			case 'D':
5787c478bd9Sstevel@tonic-gate 			case 'U':
5797c478bd9Sstevel@tonic-gate 			case 'd':
5807c478bd9Sstevel@tonic-gate 			case 'u':
5817c478bd9Sstevel@tonic-gate 				radix = 10;
5827c478bd9Sstevel@tonic-gate 				goto fixed;
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 			case 'O':
5857c478bd9Sstevel@tonic-gate 			case 'o':
5867c478bd9Sstevel@tonic-gate 				radix = 8;
5877c478bd9Sstevel@tonic-gate 				goto fixed;
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate 			case 'X':
5907c478bd9Sstevel@tonic-gate 			case 'x':
5917c478bd9Sstevel@tonic-gate 				radix = 16;
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 			fixed:
5947c478bd9Sstevel@tonic-gate 				/* Establish default precision */
5957c478bd9Sstevel@tonic-gate 				if (prec < 0)
5967c478bd9Sstevel@tonic-gate 					prec = 1;
5977c478bd9Sstevel@tonic-gate 
5987c478bd9Sstevel@tonic-gate 				/* Fetch the argument to be printed */
5997c478bd9Sstevel@tonic-gate 				val = va_arg(args.ap, unsigned);
6007c478bd9Sstevel@tonic-gate 
6017c478bd9Sstevel@tonic-gate 				/* If signed conversion, establish sign */
6027c478bd9Sstevel@tonic-gate 				if (fcode == 'd' || fcode == 'D' || fcode == 'i') {
6037c478bd9Sstevel@tonic-gate 					if ((long) val < 0) {
6047c478bd9Sstevel@tonic-gate 						prefix = "-";
6057c478bd9Sstevel@tonic-gate 						val = -val;
6067c478bd9Sstevel@tonic-gate 					} else if (fplus)
6077c478bd9Sstevel@tonic-gate 						prefix = "+";
6087c478bd9Sstevel@tonic-gate 					else if (fblank)
6097c478bd9Sstevel@tonic-gate 						prefix = " ";
6107c478bd9Sstevel@tonic-gate 				}
6117c478bd9Sstevel@tonic-gate 				/* Set translate table for digits */
6127c478bd9Sstevel@tonic-gate 				{
613*5d54f3d8Smuffin 				char *stringp;
6147c478bd9Sstevel@tonic-gate 				if (fcode == 'X')
6157c478bd9Sstevel@tonic-gate 					stringp = upperhex;
6167c478bd9Sstevel@tonic-gate 				else
6177c478bd9Sstevel@tonic-gate 					stringp = lowerhex;
6187c478bd9Sstevel@tonic-gate 
6197c478bd9Sstevel@tonic-gate 				/* Develop the digits of the value */
6207c478bd9Sstevel@tonic-gate 				bp = buf + MAXDIGS;
6217c478bd9Sstevel@tonic-gate 				switch(radix) {
6227c478bd9Sstevel@tonic-gate 				case 8:	/*octal*/
6237c478bd9Sstevel@tonic-gate 					while (val) {
6247c478bd9Sstevel@tonic-gate 						*--bp = stringp[val%8];
6257c478bd9Sstevel@tonic-gate 						val /= 8;
6267c478bd9Sstevel@tonic-gate 					}
6277c478bd9Sstevel@tonic-gate 					break;
6287c478bd9Sstevel@tonic-gate 				case 16:/*hex*/
6297c478bd9Sstevel@tonic-gate 					while (val) {
6307c478bd9Sstevel@tonic-gate 						*--bp = stringp[val%16];
6317c478bd9Sstevel@tonic-gate 						val /= 16;
6327c478bd9Sstevel@tonic-gate 					}
6337c478bd9Sstevel@tonic-gate 					break;
6347c478bd9Sstevel@tonic-gate 				default:
6357c478bd9Sstevel@tonic-gate 					while (val) {
6367c478bd9Sstevel@tonic-gate 						*--bp = stringp[val%10];
6377c478bd9Sstevel@tonic-gate 						val /= 10;
6387c478bd9Sstevel@tonic-gate 					}
6397c478bd9Sstevel@tonic-gate 					break;
6407c478bd9Sstevel@tonic-gate 				} /* switch */
6417c478bd9Sstevel@tonic-gate 				}
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate 				/* Calculate padding zero requirement */
6447c478bd9Sstevel@tonic-gate 				p = buf + MAXDIGS;
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate 				/* Handle the # flag */
6477c478bd9Sstevel@tonic-gate 				if (fsharp && bp != p) {
6487c478bd9Sstevel@tonic-gate 					switch (fcode) {
6497c478bd9Sstevel@tonic-gate 					case 'x':
6507c478bd9Sstevel@tonic-gate 						prefix = "0x";
6517c478bd9Sstevel@tonic-gate 						break;
6527c478bd9Sstevel@tonic-gate 					case 'X':
6537c478bd9Sstevel@tonic-gate 						prefix = "0X";
6547c478bd9Sstevel@tonic-gate 						break;
6557c478bd9Sstevel@tonic-gate 					}
6567c478bd9Sstevel@tonic-gate 				}
6577c478bd9Sstevel@tonic-gate #if FZERO
6587c478bd9Sstevel@tonic-gate 				if (ansi_fzero) {
6597c478bd9Sstevel@tonic-gate 					n = width - strlen(prefix);
6607c478bd9Sstevel@tonic-gate 					if (n > prec)
6617c478bd9Sstevel@tonic-gate 						prec = n;
6627c478bd9Sstevel@tonic-gate 				}
6637c478bd9Sstevel@tonic-gate #endif
6647c478bd9Sstevel@tonic-gate 				lzero = bp - p + prec;
6657c478bd9Sstevel@tonic-gate 
6667c478bd9Sstevel@tonic-gate 				/* Handle the # flag for 'o' */
6677c478bd9Sstevel@tonic-gate 				if (fsharp && bp != p && fcode == 'o' &&
6687c478bd9Sstevel@tonic-gate 				    lzero < 1) {
6697c478bd9Sstevel@tonic-gate 					lzero = 1;
6707c478bd9Sstevel@tonic-gate 				}
6717c478bd9Sstevel@tonic-gate 				break;
6727c478bd9Sstevel@tonic-gate #if FLOAT
6737c478bd9Sstevel@tonic-gate 
674*5d54f3d8Smuffin #if	defined(__sparc)
6757c478bd9Sstevel@tonic-gate #define GETQVAL /* Sun-4 macro to get a quad q from the argument list, passed as a pointer. */ \
6767c478bd9Sstevel@tonic-gate       { qval = *(va_arg(args.ap, quadruple*)) ; }
6777c478bd9Sstevel@tonic-gate #else
6787c478bd9Sstevel@tonic-gate #define GETQVAL /* Sun-3 macro to get a quad q from the argument list, passed as a value. */ \
6797c478bd9Sstevel@tonic-gate       { int iq ; unsigned long * pl = (unsigned long *) (&qval) ; for(iq=0;iq<4;iq++) pl[iq] = (unsigned long) va_arg(args.ap, unsigned long) ; }
6807c478bd9Sstevel@tonic-gate #endif
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate 			case 'E':
6837c478bd9Sstevel@tonic-gate 			case 'e':
6847c478bd9Sstevel@tonic-gate 				/*
6857c478bd9Sstevel@tonic-gate 				 *	E-format.  The general strategy
6867c478bd9Sstevel@tonic-gate 				 *	here is fairly easy: we take
6877c478bd9Sstevel@tonic-gate 				 *	what econvert gives us and re-format it.
6887c478bd9Sstevel@tonic-gate 				 */
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate 				/* Establish default precision */
6917c478bd9Sstevel@tonic-gate 				if (prec < 0)
6927c478bd9Sstevel@tonic-gate 					prec = 6;
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate 				/* Fetch the value */
6957c478bd9Sstevel@tonic-gate                                if (Lsize == 0) { /* Double */
6967c478bd9Sstevel@tonic-gate                                 dval = va_arg(args.ap, double);
6977c478bd9Sstevel@tonic-gate                                 bp = econvert(dval, prec + 1, &decpt, &sign, convertbuffer);
6987c478bd9Sstevel@tonic-gate                                } else { /* Long Double = quadruple */
6997c478bd9Sstevel@tonic-gate                                GETQVAL;
7007c478bd9Sstevel@tonic-gate                                bp = qeconvert(&qval, prec + 1, &decpt, &sign, convertbuffer);
7017c478bd9Sstevel@tonic-gate                                }
7027c478bd9Sstevel@tonic-gate 
7037c478bd9Sstevel@tonic-gate 				/* Determine the prefix */
7047c478bd9Sstevel@tonic-gate 				if (sign)
7057c478bd9Sstevel@tonic-gate 					prefix = "-";
7067c478bd9Sstevel@tonic-gate 				else if (fplus)
7077c478bd9Sstevel@tonic-gate 					prefix = "+";
7087c478bd9Sstevel@tonic-gate 				else if (fblank)
7097c478bd9Sstevel@tonic-gate 					prefix = " ";
7107c478bd9Sstevel@tonic-gate 				if (convertbuffer[0] > '9')
7117c478bd9Sstevel@tonic-gate 					{ /* handle infinity, nan */
7127c478bd9Sstevel@tonic-gate 					bp = &convertbuffer[0];
7137c478bd9Sstevel@tonic-gate 					for (p = bp+1 ; *p != 0 ; p++) ;
7147c478bd9Sstevel@tonic-gate 					goto ebreak ;
7157c478bd9Sstevel@tonic-gate 					}
7167c478bd9Sstevel@tonic-gate 				{
717*5d54f3d8Smuffin 				char *stringp;
7187c478bd9Sstevel@tonic-gate 				/* Place the first digit in the buffer */
7197c478bd9Sstevel@tonic-gate 				stringp = &buf[0];
7207c478bd9Sstevel@tonic-gate 				*stringp++ = *bp != '\0'? *bp++: '0';
7217c478bd9Sstevel@tonic-gate 
7227c478bd9Sstevel@tonic-gate 				/* Put in a decimal point if needed */
7237c478bd9Sstevel@tonic-gate 				if (prec != 0 || fsharp)
7247c478bd9Sstevel@tonic-gate 					*stringp++ = decpt_char;
7257c478bd9Sstevel@tonic-gate 
7267c478bd9Sstevel@tonic-gate 				/* Create the rest of the mantissa */
7277c478bd9Sstevel@tonic-gate 				rzero = prec;
7287c478bd9Sstevel@tonic-gate 				while (rzero > 0 && *bp!= '\0') {
7297c478bd9Sstevel@tonic-gate 					--rzero;
7307c478bd9Sstevel@tonic-gate 					*stringp++ = *bp++;
7317c478bd9Sstevel@tonic-gate 				}
7327c478bd9Sstevel@tonic-gate 				p = stringp;
7337c478bd9Sstevel@tonic-gate 				}
7347c478bd9Sstevel@tonic-gate 
7357c478bd9Sstevel@tonic-gate 				bp = &buf[0];
7367c478bd9Sstevel@tonic-gate 
7377c478bd9Sstevel@tonic-gate 				/* Create the exponent */
7387c478bd9Sstevel@tonic-gate 				if (convertbuffer[0] != '0')
7397c478bd9Sstevel@tonic-gate 					n = decpt - 1;
7407c478bd9Sstevel@tonic-gate 				else
7417c478bd9Sstevel@tonic-gate 					n = 0 ;
7427c478bd9Sstevel@tonic-gate 				if (n < 0)
7437c478bd9Sstevel@tonic-gate 					n = -n;
7447c478bd9Sstevel@tonic-gate 				_fourdigitsquick( (short unsigned) n, &(expbuf[2]) ) ;
7457c478bd9Sstevel@tonic-gate 				expbuf[6] = 0 ;
7467c478bd9Sstevel@tonic-gate 				if (n < 100)
7477c478bd9Sstevel@tonic-gate 					/*
7487c478bd9Sstevel@tonic-gate                                          * Normally two digit exponent field,
7497c478bd9Sstevel@tonic-gate                                          * three or four if required.
7507c478bd9Sstevel@tonic-gate 					 */
7517c478bd9Sstevel@tonic-gate 					{ suffix = &(expbuf[4]) ; suffixlength = 4 ; }
7527c478bd9Sstevel@tonic-gate                                 else if (n < 1000)
7537c478bd9Sstevel@tonic-gate                                         { suffix = &(expbuf[3]) ; suffixlength = 5 ; }
7547c478bd9Sstevel@tonic-gate                                 else
7557c478bd9Sstevel@tonic-gate                                         { suffix = &(expbuf[2]) ; suffixlength = 6 ; }
7567c478bd9Sstevel@tonic-gate 				/* Put in the exponent sign */
7577c478bd9Sstevel@tonic-gate 				*--suffix = (decpt > 0 || convertbuffer[0] == '0' )? '+': '-';
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate 				/* Put in the e; note kludge in 'g' format */
7607c478bd9Sstevel@tonic-gate 				*--suffix = fcode;
7617c478bd9Sstevel@tonic-gate ebreak:
7627c478bd9Sstevel@tonic-gate #if FZERO
7637c478bd9Sstevel@tonic-gate 				if (compat_fzero &! fminus)
7647c478bd9Sstevel@tonic-gate 					/* Calculate padding zero requirement */
7657c478bd9Sstevel@tonic-gate 					lzero = width - (strlen(prefix)
7667c478bd9Sstevel@tonic-gate 					    + (p - buf) + rzero + suffixlength);
7677c478bd9Sstevel@tonic-gate #endif
7687c478bd9Sstevel@tonic-gate 				break;
7697c478bd9Sstevel@tonic-gate 
7707c478bd9Sstevel@tonic-gate 			case 'f':
7717c478bd9Sstevel@tonic-gate 				/*
7727c478bd9Sstevel@tonic-gate 				 *	F-format floating point.  This is
7737c478bd9Sstevel@tonic-gate 				 *	a good deal less simple than E-format.
7747c478bd9Sstevel@tonic-gate 				 *	The overall strategy will be to call
7757c478bd9Sstevel@tonic-gate 				 *	fconvert, reformat its result into buf,
7767c478bd9Sstevel@tonic-gate 				 *	and calculate how many trailing
7777c478bd9Sstevel@tonic-gate 				 *	zeroes will be required.  There will
7787c478bd9Sstevel@tonic-gate 				 *	never be any leading zeroes needed.
7797c478bd9Sstevel@tonic-gate 				 */
7807c478bd9Sstevel@tonic-gate 
7817c478bd9Sstevel@tonic-gate 				/* Establish default precision */
7827c478bd9Sstevel@tonic-gate 				if (prec < 0)
7837c478bd9Sstevel@tonic-gate 					prec = 6;
7847c478bd9Sstevel@tonic-gate 
7857c478bd9Sstevel@tonic-gate                                 if (Lsize == 0) {
7867c478bd9Sstevel@tonic-gate                                 dval = va_arg(args.ap, double);
7877c478bd9Sstevel@tonic-gate                                 bp = fconvert(dval, prec, &decpt, &sign, convertbuffer);
7887c478bd9Sstevel@tonic-gate                                 } else {
7897c478bd9Sstevel@tonic-gate                                 GETQVAL ;
7907c478bd9Sstevel@tonic-gate                                 bp = qfconvert(&qval, prec, &decpt, &sign, convertbuffer);
7917c478bd9Sstevel@tonic-gate                                 }
7927c478bd9Sstevel@tonic-gate 
7937c478bd9Sstevel@tonic-gate 				/* Determine the prefix */
7947c478bd9Sstevel@tonic-gate 				if (sign)
7957c478bd9Sstevel@tonic-gate 					prefix = "-";
7967c478bd9Sstevel@tonic-gate 				else if (fplus)
7977c478bd9Sstevel@tonic-gate 					prefix = "+";
7987c478bd9Sstevel@tonic-gate 				else if (fblank)
7997c478bd9Sstevel@tonic-gate 					prefix = " ";
8007c478bd9Sstevel@tonic-gate 				if (convertbuffer[0] > '9')
8017c478bd9Sstevel@tonic-gate 					{ /* handle infinity, nan */
8027c478bd9Sstevel@tonic-gate 					bp = &convertbuffer[0];
8037c478bd9Sstevel@tonic-gate 					for (p = bp+1 ; *p != 0 ; p++) ;
8047c478bd9Sstevel@tonic-gate 					goto fbreak ;
8057c478bd9Sstevel@tonic-gate 					}
8067c478bd9Sstevel@tonic-gate 				{
807*5d54f3d8Smuffin 				char *stringp;
8087c478bd9Sstevel@tonic-gate 				/* Initialize buffer pointer */
8097c478bd9Sstevel@tonic-gate 				stringp = &buf[0];
8107c478bd9Sstevel@tonic-gate 
8117c478bd9Sstevel@tonic-gate 				/* Emit the digits before the decimal point */
8127c478bd9Sstevel@tonic-gate 				n = decpt;
8137c478bd9Sstevel@tonic-gate 				if (n <= 0)
8147c478bd9Sstevel@tonic-gate 					*stringp++ = '0';
8157c478bd9Sstevel@tonic-gate 				else
8167c478bd9Sstevel@tonic-gate 					do
8177c478bd9Sstevel@tonic-gate 						if (*bp == '\0' )
8187c478bd9Sstevel@tonic-gate 							*stringp++ = '0';
8197c478bd9Sstevel@tonic-gate 						else {
8207c478bd9Sstevel@tonic-gate 							*stringp++ = *bp++;
8217c478bd9Sstevel@tonic-gate 						}
8227c478bd9Sstevel@tonic-gate 					while (--n != 0);
8237c478bd9Sstevel@tonic-gate 
8247c478bd9Sstevel@tonic-gate 				/* Decide whether we need a decimal point */
8257c478bd9Sstevel@tonic-gate 				if (fsharp || prec > 0)
8267c478bd9Sstevel@tonic-gate 					*stringp++ = decpt_char;
8277c478bd9Sstevel@tonic-gate 
8287c478bd9Sstevel@tonic-gate 				/* Digits(if any) after the decimal point */
8297c478bd9Sstevel@tonic-gate 				n = prec;
8307c478bd9Sstevel@tonic-gate 				rzero = prec - n;
8317c478bd9Sstevel@tonic-gate 				while (--n >= 0) {
8327c478bd9Sstevel@tonic-gate 					if (++decpt <= 0 || *bp == '\0')
8337c478bd9Sstevel@tonic-gate 						*stringp++ = '0';
8347c478bd9Sstevel@tonic-gate 					else {
8357c478bd9Sstevel@tonic-gate 						*stringp++ = *bp++;
8367c478bd9Sstevel@tonic-gate 					}
8377c478bd9Sstevel@tonic-gate 				}
8387c478bd9Sstevel@tonic-gate #if FZERO
8397c478bd9Sstevel@tonic-gate 				if (compat_fzero &! fminus)
8407c478bd9Sstevel@tonic-gate 					/* Calculate padding zero requirement */
8417c478bd9Sstevel@tonic-gate 					lzero = width - (strlen(prefix)
8427c478bd9Sstevel@tonic-gate 					    + (stringp - buf) + rzero);
8437c478bd9Sstevel@tonic-gate #endif
8447c478bd9Sstevel@tonic-gate 				p = stringp;
8457c478bd9Sstevel@tonic-gate 				}
8467c478bd9Sstevel@tonic-gate 
8477c478bd9Sstevel@tonic-gate 				bp = &buf[0];
8487c478bd9Sstevel@tonic-gate fbreak:
8497c478bd9Sstevel@tonic-gate 				break;
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate 			case 'G':
8527c478bd9Sstevel@tonic-gate 			case 'g':
8537c478bd9Sstevel@tonic-gate 				/*
8547c478bd9Sstevel@tonic-gate 				 *	g-format.  We play around a bit
8557c478bd9Sstevel@tonic-gate 				 *	and then jump into e or f, as needed.
8567c478bd9Sstevel@tonic-gate 				 */
8577c478bd9Sstevel@tonic-gate 
8587c478bd9Sstevel@tonic-gate 				/* Establish default precision */
8597c478bd9Sstevel@tonic-gate 				if (prec < 0)
8607c478bd9Sstevel@tonic-gate 					prec = 6;
8617c478bd9Sstevel@tonic-gate 				else if (prec == 0)
8627c478bd9Sstevel@tonic-gate 					prec = 1;
8637c478bd9Sstevel@tonic-gate 
8647c478bd9Sstevel@tonic-gate                                 if (Lsize == 0) {
8657c478bd9Sstevel@tonic-gate                                 dval = va_arg(args.ap, double);
8667c478bd9Sstevel@tonic-gate                                 bp = gconvert(dval, prec, fsharp, convertbuffer);
8677c478bd9Sstevel@tonic-gate                                 } else {
8687c478bd9Sstevel@tonic-gate                                 GETQVAL;
8697c478bd9Sstevel@tonic-gate                                 bp = qgconvert(&qval, prec, fsharp, convertbuffer);
8707c478bd9Sstevel@tonic-gate                                 }
8717c478bd9Sstevel@tonic-gate 				bp = convertbuffer ;
8727c478bd9Sstevel@tonic-gate 				if (convertbuffer[0] == '-') {
8737c478bd9Sstevel@tonic-gate 					prefix = "-" ;
8747c478bd9Sstevel@tonic-gate 					bp++;
8757c478bd9Sstevel@tonic-gate 					}
8767c478bd9Sstevel@tonic-gate 				else if (fplus)
8777c478bd9Sstevel@tonic-gate 					prefix = "+";
8787c478bd9Sstevel@tonic-gate 				else if (fblank)
8797c478bd9Sstevel@tonic-gate 					prefix = " ";
8807c478bd9Sstevel@tonic-gate 				if (isupper(fcode))
8817c478bd9Sstevel@tonic-gate 				        { /* Put in a big E for small minds. */
8827c478bd9Sstevel@tonic-gate 				        for (p = bp ; (*p != NULL) && (*p != 'e') ; p++) ;
8837c478bd9Sstevel@tonic-gate 				        if (*p == 'e') *p = 'E' ;
8847c478bd9Sstevel@tonic-gate 				        for (; (*p != NULL) ; p++) ;
8857c478bd9Sstevel@tonic-gate 				                                /* Find end of string. */
8867c478bd9Sstevel@tonic-gate 			                }
8877c478bd9Sstevel@tonic-gate 				else
8887c478bd9Sstevel@tonic-gate 				        for (p = bp ; *p != NULL ; p++) ;
8897c478bd9Sstevel@tonic-gate 				                                /* Find end of string. */
8907c478bd9Sstevel@tonic-gate 				rzero = 0;
8917c478bd9Sstevel@tonic-gate #if FZERO
8927c478bd9Sstevel@tonic-gate 				if (compat_fzero & !fminus)
8937c478bd9Sstevel@tonic-gate 					/* Calculate padding zero requirement */
8947c478bd9Sstevel@tonic-gate 					lzero = width - (strlen(prefix)
8957c478bd9Sstevel@tonic-gate 					    + (p - bp) + rzero);
8967c478bd9Sstevel@tonic-gate #endif
8977c478bd9Sstevel@tonic-gate 				break ;
8987c478bd9Sstevel@tonic-gate 
8997c478bd9Sstevel@tonic-gate #endif
9007c478bd9Sstevel@tonic-gate 			case 'c':
9017c478bd9Sstevel@tonic-gate 				buf[0] = va_arg(args.ap, int);
9027c478bd9Sstevel@tonic-gate 				bp = &buf[0];
9037c478bd9Sstevel@tonic-gate 				p = bp + 1;
9047c478bd9Sstevel@tonic-gate 				break;
9057c478bd9Sstevel@tonic-gate 
9067c478bd9Sstevel@tonic-gate                         case 's':
9077c478bd9Sstevel@tonic-gate 				bp = va_arg(args.ap, char *);
9087c478bd9Sstevel@tonic-gate 				if (prec < 0)
9097c478bd9Sstevel@tonic-gate 					prec = MAXINT;
9107c478bd9Sstevel@tonic-gate 				/* avoid *(0) */
9117c478bd9Sstevel@tonic-gate 				if (bp == NULL)
9127c478bd9Sstevel@tonic-gate 					bp = nullstr;
9137c478bd9Sstevel@tonic-gate 				for (n=0; *bp++ != '\0' && n < prec; n++)
9147c478bd9Sstevel@tonic-gate 					;
9157c478bd9Sstevel@tonic-gate #if FZERO
9167c478bd9Sstevel@tonic-gate 				if (compat_fzero &! fminus)
9177c478bd9Sstevel@tonic-gate 				        lzero = width - n;
9187c478bd9Sstevel@tonic-gate #endif
9197c478bd9Sstevel@tonic-gate 				p = --bp;
9207c478bd9Sstevel@tonic-gate 				bp -= n;
9217c478bd9Sstevel@tonic-gate 				break;
9227c478bd9Sstevel@tonic-gate 
9237c478bd9Sstevel@tonic-gate 			case '\0':
9247c478bd9Sstevel@tonic-gate 				/* well, what's the punch line? */
9257c478bd9Sstevel@tonic-gate 				goto out;
9267c478bd9Sstevel@tonic-gate 
9277c478bd9Sstevel@tonic-gate 			case 'n':
9287c478bd9Sstevel@tonic-gate 				svswitch = 1;
9297c478bd9Sstevel@tonic-gate 				break;
9307c478bd9Sstevel@tonic-gate 			default:
9317c478bd9Sstevel@tonic-gate 				p = bp = &fcode;
9327c478bd9Sstevel@tonic-gate 				p++;
9337c478bd9Sstevel@tonic-gate 				break;
9347c478bd9Sstevel@tonic-gate 
9357c478bd9Sstevel@tonic-gate 			}
9367c478bd9Sstevel@tonic-gate 			/* Calculate number of padding blanks */
9377c478bd9Sstevel@tonic-gate 			nblank = width
9387c478bd9Sstevel@tonic-gate #if FLOAT
9397c478bd9Sstevel@tonic-gate 				- (rzero < 0? 0: rzero)
9407c478bd9Sstevel@tonic-gate 				- strlen(suffix)
9417c478bd9Sstevel@tonic-gate #endif
9427c478bd9Sstevel@tonic-gate 				- (p - bp)
9437c478bd9Sstevel@tonic-gate 				- (lzero < 0? 0: lzero)
9447c478bd9Sstevel@tonic-gate 				- strlen(prefix);
9457c478bd9Sstevel@tonic-gate 
9467c478bd9Sstevel@tonic-gate 			/* Blanks on left if required */
9477c478bd9Sstevel@tonic-gate 			if (!fminus)
9487c478bd9Sstevel@tonic-gate 				while (--nblank >= 0)
9497c478bd9Sstevel@tonic-gate 					emitchar(' ');
9507c478bd9Sstevel@tonic-gate 
9517c478bd9Sstevel@tonic-gate 			/* Prefix, if any */
9527c478bd9Sstevel@tonic-gate 			while (*prefix != '\0') {
9537c478bd9Sstevel@tonic-gate 				emitchar(*prefix);
9547c478bd9Sstevel@tonic-gate 				prefix++;
9557c478bd9Sstevel@tonic-gate 			}
9567c478bd9Sstevel@tonic-gate 
9577c478bd9Sstevel@tonic-gate 			/* Zeroes on the left */
9587c478bd9Sstevel@tonic-gate 			while (--lzero >= 0)
9597c478bd9Sstevel@tonic-gate 				emitchar('0');
9607c478bd9Sstevel@tonic-gate 
9617c478bd9Sstevel@tonic-gate 			/* The value itself */
9627c478bd9Sstevel@tonic-gate 			while (bp < p) {
9637c478bd9Sstevel@tonic-gate 				emitchar(*bp);
9647c478bd9Sstevel@tonic-gate 				bp++;
9657c478bd9Sstevel@tonic-gate 			}
9667c478bd9Sstevel@tonic-gate #if FLOAT
9677c478bd9Sstevel@tonic-gate 			/* Zeroes on the right */
9687c478bd9Sstevel@tonic-gate 			while (--rzero >= 0)
9697c478bd9Sstevel@tonic-gate 				emitchar('0');
9707c478bd9Sstevel@tonic-gate 
9717c478bd9Sstevel@tonic-gate 			/* The suffix */
9727c478bd9Sstevel@tonic-gate 			while (*suffix != '\0') {
9737c478bd9Sstevel@tonic-gate 				emitchar(*suffix);
9747c478bd9Sstevel@tonic-gate 				suffix++;
9757c478bd9Sstevel@tonic-gate 			}
9767c478bd9Sstevel@tonic-gate #endif
9777c478bd9Sstevel@tonic-gate 			/* Blanks on the right if required */
9787c478bd9Sstevel@tonic-gate 			if (fminus)
9797c478bd9Sstevel@tonic-gate 				while (--nblank >= 0)
9807c478bd9Sstevel@tonic-gate 					emitchar(' ');
9817c478bd9Sstevel@tonic-gate 			/* If %n is seen, save count in argument */
9827c478bd9Sstevel@tonic-gate 			if (svswitch == 1) {
9837c478bd9Sstevel@tonic-gate 				long *svcount;
9847c478bd9Sstevel@tonic-gate 				svcount = va_arg (args.ap, long *);
9857c478bd9Sstevel@tonic-gate 				*svcount = count;
9867c478bd9Sstevel@tonic-gate 				svswitch = 0;
9877c478bd9Sstevel@tonic-gate 			}
9887c478bd9Sstevel@tonic-gate 		} /* else */
9897c478bd9Sstevel@tonic-gate 	} while ((c = *cp++) != '\0');	/* do */
9907c478bd9Sstevel@tonic-gate out:
9917c478bd9Sstevel@tonic-gate 	file->_ptr = fileptr;
9927c478bd9Sstevel@tonic-gate 	file->_cnt = filecnt;
9937c478bd9Sstevel@tonic-gate 	if (file->_flag & (_IONBF | _IOLBF) &&
9947c478bd9Sstevel@tonic-gate 	    (file->_flag & _IONBF ||
9957c478bd9Sstevel@tonic-gate 	     memchr((char *)file->_base, '\n', fileptr - file->_base) != NULL))
9967c478bd9Sstevel@tonic-gate 		(void) _xflsbuf(file);
9977c478bd9Sstevel@tonic-gate 	return (ferror(file)? EOF: count);
9987c478bd9Sstevel@tonic-gate }
9997c478bd9Sstevel@tonic-gate 
1000*5d54f3d8Smuffin #if	defined(__sparc)
10017c478bd9Sstevel@tonic-gate /*
10027c478bd9Sstevel@tonic-gate  * We use "double *" instead of "quadruple *" to skip over the pointer to
10037c478bd9Sstevel@tonic-gate  * long double on the argument list since a pointer is a pointer after all.
10047c478bd9Sstevel@tonic-gate  */
10057c478bd9Sstevel@tonic-gate #define SKIPQVAL { \
10067c478bd9Sstevel@tonic-gate 	(void) va_arg(args.ap, double *); \
10077c478bd9Sstevel@tonic-gate }
10087c478bd9Sstevel@tonic-gate #else	/* Sun-3 */
10097c478bd9Sstevel@tonic-gate #define SKIPQVAL { \
10107c478bd9Sstevel@tonic-gate 	int iq; \
10117c478bd9Sstevel@tonic-gate 	for (iq = 0; iq < 4; iq++) \
10127c478bd9Sstevel@tonic-gate 		(void) va_arg(args.ap, unsigned long); \
10137c478bd9Sstevel@tonic-gate }
10147c478bd9Sstevel@tonic-gate #endif
1015*5d54f3d8Smuffin /*
1016*5d54f3d8Smuffin  * This function initializes arglst, to contain the appropriate va_list values
1017*5d54f3d8Smuffin  * for the first MAXARGS arguments.
1018*5d54f3d8Smuffin  */
10197c478bd9Sstevel@tonic-gate void
_mkarglst(char * fmt,stva_list args,stva_list arglst[])1020*5d54f3d8Smuffin _mkarglst(char *fmt, stva_list args, stva_list arglst[])
10217c478bd9Sstevel@tonic-gate {
10227c478bd9Sstevel@tonic-gate 	static char *digits = "01234567890", *skips = "# +-.0123456789h$";
10237c478bd9Sstevel@tonic-gate 
10247c478bd9Sstevel@tonic-gate 	enum types {INT = 1, LONG, CHAR_PTR, DOUBLE, LONG_DOUBLE, VOID_PTR,
10257c478bd9Sstevel@tonic-gate 		LONG_PTR, INT_PTR};
10267c478bd9Sstevel@tonic-gate 	enum types typelst[MAXARGS], curtype;
10277c478bd9Sstevel@tonic-gate 	int maxnum, n, curargno, flags;
10287c478bd9Sstevel@tonic-gate 
10297c478bd9Sstevel@tonic-gate 	/*
10307c478bd9Sstevel@tonic-gate 	* Algorithm	1. set all argument types to zero.
10317c478bd9Sstevel@tonic-gate 	*		2. walk through fmt putting arg types in typelst[].
10327c478bd9Sstevel@tonic-gate 	*		3. walk through args using va_arg(args.ap, typelst[n])
10337c478bd9Sstevel@tonic-gate 	*		   and set arglst[] to the appropriate values.
10347c478bd9Sstevel@tonic-gate 	* Assumptions:	Cannot use %*$... to specify variable position.
10357c478bd9Sstevel@tonic-gate 	*/
10367c478bd9Sstevel@tonic-gate 
10377c478bd9Sstevel@tonic-gate 	(void)memset((void *)typelst, 0, sizeof(typelst));
10387c478bd9Sstevel@tonic-gate 	maxnum = -1;
10397c478bd9Sstevel@tonic-gate 	curargno = 0;
10407c478bd9Sstevel@tonic-gate 	while ((fmt = strchr(fmt, '%')) != 0)
10417c478bd9Sstevel@tonic-gate 	{
10427c478bd9Sstevel@tonic-gate 		fmt++;	/* skip % */
10437c478bd9Sstevel@tonic-gate 		if (fmt[n = strspn(fmt, digits)] == '$')
10447c478bd9Sstevel@tonic-gate 		{
10457c478bd9Sstevel@tonic-gate 			curargno = atoi(fmt) - 1;	/* convert to zero base */
10467c478bd9Sstevel@tonic-gate 			fmt += n + 1;
10477c478bd9Sstevel@tonic-gate 		}
10487c478bd9Sstevel@tonic-gate 		flags = 0;
10497c478bd9Sstevel@tonic-gate 	again:;
10507c478bd9Sstevel@tonic-gate 		fmt += strspn(fmt, skips);
10517c478bd9Sstevel@tonic-gate 		switch (*fmt++)
10527c478bd9Sstevel@tonic-gate 		{
10537c478bd9Sstevel@tonic-gate 		case '%':	/*there is no argument! */
10547c478bd9Sstevel@tonic-gate 			continue;
10557c478bd9Sstevel@tonic-gate 		case 'l':
10567c478bd9Sstevel@tonic-gate 			flags |= 0x1;
10577c478bd9Sstevel@tonic-gate 			goto again;
10587c478bd9Sstevel@tonic-gate 		case 'L':
10597c478bd9Sstevel@tonic-gate 			flags |= 0x8;
10607c478bd9Sstevel@tonic-gate 			goto again;
10617c478bd9Sstevel@tonic-gate 		case '*':	/* int argument used for value */
10627c478bd9Sstevel@tonic-gate 			flags |= 0x2;
10637c478bd9Sstevel@tonic-gate 			curtype = INT;
10647c478bd9Sstevel@tonic-gate 			break;
10657c478bd9Sstevel@tonic-gate 		case 'e':
10667c478bd9Sstevel@tonic-gate 		case 'E':
10677c478bd9Sstevel@tonic-gate 		case 'f':
10687c478bd9Sstevel@tonic-gate 		case 'g':
10697c478bd9Sstevel@tonic-gate 		case 'G':
10707c478bd9Sstevel@tonic-gate 			if (flags & 0x8)
10717c478bd9Sstevel@tonic-gate 				curtype = LONG_DOUBLE;
10727c478bd9Sstevel@tonic-gate 			else
10737c478bd9Sstevel@tonic-gate 				curtype = DOUBLE;
10747c478bd9Sstevel@tonic-gate 			break;
10757c478bd9Sstevel@tonic-gate 		case 's':
10767c478bd9Sstevel@tonic-gate 			curtype = CHAR_PTR;
10777c478bd9Sstevel@tonic-gate 			break;
10787c478bd9Sstevel@tonic-gate 		case 'p':
10797c478bd9Sstevel@tonic-gate 			curtype = VOID_PTR;
10807c478bd9Sstevel@tonic-gate 			break;
10817c478bd9Sstevel@tonic-gate 		case 'n':
10827c478bd9Sstevel@tonic-gate 			if (flags & 0x1)
10837c478bd9Sstevel@tonic-gate 				curtype = LONG_PTR;
10847c478bd9Sstevel@tonic-gate 			else
10857c478bd9Sstevel@tonic-gate 				curtype = INT_PTR;
10867c478bd9Sstevel@tonic-gate 			break;
10877c478bd9Sstevel@tonic-gate 		default:
10887c478bd9Sstevel@tonic-gate 			if (flags & 0x1)
10897c478bd9Sstevel@tonic-gate 				curtype = LONG;
10907c478bd9Sstevel@tonic-gate 			else
10917c478bd9Sstevel@tonic-gate 				curtype = INT;
10927c478bd9Sstevel@tonic-gate 			break;
10937c478bd9Sstevel@tonic-gate 		}
10947c478bd9Sstevel@tonic-gate 		if (curargno >= 0 && curargno < MAXARGS)
10957c478bd9Sstevel@tonic-gate 		{
10967c478bd9Sstevel@tonic-gate 			typelst[curargno] = curtype;
10977c478bd9Sstevel@tonic-gate 			if (maxnum < curargno)
10987c478bd9Sstevel@tonic-gate 				maxnum = curargno;
10997c478bd9Sstevel@tonic-gate 		}
11007c478bd9Sstevel@tonic-gate 		curargno++;	/* default to next in list */
11017c478bd9Sstevel@tonic-gate 		if (flags & 0x2)	/* took care of *, keep going */
11027c478bd9Sstevel@tonic-gate 		{
11037c478bd9Sstevel@tonic-gate 			flags ^= 0x2;
11047c478bd9Sstevel@tonic-gate 			goto again;
11057c478bd9Sstevel@tonic-gate 		}
11067c478bd9Sstevel@tonic-gate 	}
11077c478bd9Sstevel@tonic-gate 	for (n = 0 ; n <= maxnum; n++)
11087c478bd9Sstevel@tonic-gate 	{
11097c478bd9Sstevel@tonic-gate 		arglst[n] = args;
11107c478bd9Sstevel@tonic-gate 		if (typelst[n] == 0)
11117c478bd9Sstevel@tonic-gate 			typelst[n] = INT;
11127c478bd9Sstevel@tonic-gate 
11137c478bd9Sstevel@tonic-gate 		switch (typelst[n])
11147c478bd9Sstevel@tonic-gate 		{
11157c478bd9Sstevel@tonic-gate 		case INT:
11167c478bd9Sstevel@tonic-gate 			va_arg(args.ap, int);
11177c478bd9Sstevel@tonic-gate 			break;
11187c478bd9Sstevel@tonic-gate 		case LONG:
11197c478bd9Sstevel@tonic-gate 			va_arg(args.ap, long);
11207c478bd9Sstevel@tonic-gate 			break;
11217c478bd9Sstevel@tonic-gate 		case CHAR_PTR:
11227c478bd9Sstevel@tonic-gate 			va_arg(args.ap, char *);
11237c478bd9Sstevel@tonic-gate 			break;
11247c478bd9Sstevel@tonic-gate 		case DOUBLE:
11257c478bd9Sstevel@tonic-gate 			va_arg(args.ap, double);
11267c478bd9Sstevel@tonic-gate 			break;
11277c478bd9Sstevel@tonic-gate 		case LONG_DOUBLE:
11287c478bd9Sstevel@tonic-gate 			SKIPQVAL
11297c478bd9Sstevel@tonic-gate 			break;
11307c478bd9Sstevel@tonic-gate 		case VOID_PTR:
11317c478bd9Sstevel@tonic-gate 			va_arg(args.ap, void *);
11327c478bd9Sstevel@tonic-gate 			break;
11337c478bd9Sstevel@tonic-gate 		case LONG_PTR:
11347c478bd9Sstevel@tonic-gate 			va_arg(args.ap, long *);
11357c478bd9Sstevel@tonic-gate 			break;
11367c478bd9Sstevel@tonic-gate 		case INT_PTR:
11377c478bd9Sstevel@tonic-gate 			va_arg(args.ap, int *);
11387c478bd9Sstevel@tonic-gate 			break;
11397c478bd9Sstevel@tonic-gate 		}
11407c478bd9Sstevel@tonic-gate 	}
11417c478bd9Sstevel@tonic-gate }
11427c478bd9Sstevel@tonic-gate 
11437c478bd9Sstevel@tonic-gate /*
11447c478bd9Sstevel@tonic-gate  * This function is used to find the va_list value for arguments whose
11457c478bd9Sstevel@tonic-gate  * position is greater than MAXARGS.  This function is slow, so hopefully
11467c478bd9Sstevel@tonic-gate  * MAXARGS will be big enough so that this function need only be called in
11477c478bd9Sstevel@tonic-gate  * unusual circumstances.
11487c478bd9Sstevel@tonic-gate  * pargs is assumed to contain the value of arglst[MAXARGS - 1].
11497c478bd9Sstevel@tonic-gate  */
11507c478bd9Sstevel@tonic-gate void
_getarg(char * fmt,stva_list * pargs,int argno)1151*5d54f3d8Smuffin _getarg(char *fmt, stva_list *pargs, int argno)
11527c478bd9Sstevel@tonic-gate {
11537c478bd9Sstevel@tonic-gate 	static char *digits = "01234567890", *skips = "# +-.0123456789h$";
11547c478bd9Sstevel@tonic-gate 	int i, n, curargno, flags;
11557c478bd9Sstevel@tonic-gate 	char	*sfmt = fmt;
11567c478bd9Sstevel@tonic-gate 	int	found = 1;
11577c478bd9Sstevel@tonic-gate 
11587c478bd9Sstevel@tonic-gate 	curargno = i = MAXARGS;
11597c478bd9Sstevel@tonic-gate 	while (found)
11607c478bd9Sstevel@tonic-gate 	{
11617c478bd9Sstevel@tonic-gate 		fmt = sfmt;
11627c478bd9Sstevel@tonic-gate 		found = 0;
11637c478bd9Sstevel@tonic-gate 		while ((i != argno) && (fmt = strchr(fmt, '%')) != 0)
11647c478bd9Sstevel@tonic-gate 		{
11657c478bd9Sstevel@tonic-gate 			fmt++;	/* skip % */
11667c478bd9Sstevel@tonic-gate 			if (fmt[n = strspn(fmt, digits)] == '$')
11677c478bd9Sstevel@tonic-gate 			{
11687c478bd9Sstevel@tonic-gate 				curargno = atoi(fmt);
11697c478bd9Sstevel@tonic-gate 				fmt += n + 1;
11707c478bd9Sstevel@tonic-gate 			}
11717c478bd9Sstevel@tonic-gate 
11727c478bd9Sstevel@tonic-gate 			/* find conversion specifier for next argument */
11737c478bd9Sstevel@tonic-gate 			if (i != curargno)
11747c478bd9Sstevel@tonic-gate 			{
11757c478bd9Sstevel@tonic-gate 				curargno++;
11767c478bd9Sstevel@tonic-gate 				continue;
11777c478bd9Sstevel@tonic-gate 			} else
11787c478bd9Sstevel@tonic-gate 				found = 1;
11797c478bd9Sstevel@tonic-gate 			flags = 0;
11807c478bd9Sstevel@tonic-gate 		again:;
11817c478bd9Sstevel@tonic-gate 			fmt += strspn(fmt, skips);
11827c478bd9Sstevel@tonic-gate 			switch (*fmt++)
11837c478bd9Sstevel@tonic-gate 			{
11847c478bd9Sstevel@tonic-gate 			case '%':	/*there is no argument! */
11857c478bd9Sstevel@tonic-gate 				continue;
11867c478bd9Sstevel@tonic-gate 			case 'l':
11877c478bd9Sstevel@tonic-gate 				flags |= 0x1;
11887c478bd9Sstevel@tonic-gate 				goto again;
11897c478bd9Sstevel@tonic-gate 			case 'L':
11907c478bd9Sstevel@tonic-gate 				flags |= 0x8;
11917c478bd9Sstevel@tonic-gate 				goto again;
11927c478bd9Sstevel@tonic-gate 			case '*':	/* int argument used for value */
11937c478bd9Sstevel@tonic-gate 				flags |= 0x2;
11947c478bd9Sstevel@tonic-gate 				(void)va_arg((*pargs).ap, int);
11957c478bd9Sstevel@tonic-gate 				break;
11967c478bd9Sstevel@tonic-gate 			case 'e':
11977c478bd9Sstevel@tonic-gate 			case 'E':
11987c478bd9Sstevel@tonic-gate 			case 'f':
11997c478bd9Sstevel@tonic-gate 			case 'g':
12007c478bd9Sstevel@tonic-gate 			case 'G':
12017c478bd9Sstevel@tonic-gate 				if (flags & 0x8) {
12027c478bd9Sstevel@tonic-gate #define	args	(*pargs)
12037c478bd9Sstevel@tonic-gate 					SKIPQVAL
12047c478bd9Sstevel@tonic-gate #undef	args
12057c478bd9Sstevel@tonic-gate 				}
12067c478bd9Sstevel@tonic-gate 				else
12077c478bd9Sstevel@tonic-gate 					(void)va_arg((*pargs).ap, double);
12087c478bd9Sstevel@tonic-gate 				break;
12097c478bd9Sstevel@tonic-gate 			case 's':
12107c478bd9Sstevel@tonic-gate 				(void)va_arg((*pargs).ap, char *);
12117c478bd9Sstevel@tonic-gate 				break;
12127c478bd9Sstevel@tonic-gate 			case 'p':
12137c478bd9Sstevel@tonic-gate 				(void)va_arg((*pargs).ap, void *);
12147c478bd9Sstevel@tonic-gate 				break;
12157c478bd9Sstevel@tonic-gate 			case 'n':
12167c478bd9Sstevel@tonic-gate 				if (flags & 0x1)
12177c478bd9Sstevel@tonic-gate 					(void)va_arg((*pargs).ap, long *);
12187c478bd9Sstevel@tonic-gate 				else
12197c478bd9Sstevel@tonic-gate 					(void)va_arg((*pargs).ap, int *);
12207c478bd9Sstevel@tonic-gate 				break;
12217c478bd9Sstevel@tonic-gate 			default:
12227c478bd9Sstevel@tonic-gate 				if (flags & 0x1)
12237c478bd9Sstevel@tonic-gate 					(void)va_arg((*pargs).ap, long int);
12247c478bd9Sstevel@tonic-gate 				else
12257c478bd9Sstevel@tonic-gate 					(void)va_arg((*pargs).ap, int);
12267c478bd9Sstevel@tonic-gate 				break;
12277c478bd9Sstevel@tonic-gate 			}
12287c478bd9Sstevel@tonic-gate 			i++;
12297c478bd9Sstevel@tonic-gate 			curargno++;	/* default to next in list */
12307c478bd9Sstevel@tonic-gate 			if (flags & 0x2)	/* took care of *, keep going */
12317c478bd9Sstevel@tonic-gate 			{
12327c478bd9Sstevel@tonic-gate 				flags ^= 0x2;
12337c478bd9Sstevel@tonic-gate 				goto again;
12347c478bd9Sstevel@tonic-gate 			}
12357c478bd9Sstevel@tonic-gate 		}
12367c478bd9Sstevel@tonic-gate 
12377c478bd9Sstevel@tonic-gate 		/* missing specifier for parameter, assume parameter is an int */
12387c478bd9Sstevel@tonic-gate 		if (!found && i != argno) {
12397c478bd9Sstevel@tonic-gate 			(void)va_arg((*pargs).ap, int);
12407c478bd9Sstevel@tonic-gate 			i++;
12417c478bd9Sstevel@tonic-gate 			curargno++;
12427c478bd9Sstevel@tonic-gate 			found = 1;
12437c478bd9Sstevel@tonic-gate 		}
12447c478bd9Sstevel@tonic-gate 	}
12457c478bd9Sstevel@tonic-gate }
12467c478bd9Sstevel@tonic-gate 
12477c478bd9Sstevel@tonic-gate 
12487c478bd9Sstevel@tonic-gate /*
12497c478bd9Sstevel@tonic-gate  * parse a string, mini parse
12507c478bd9Sstevel@tonic-gate  */
12517c478bd9Sstevel@tonic-gate static char *
_check_dol(char * s,int * val)1252*5d54f3d8Smuffin _check_dol(char *s, int *val)
12537c478bd9Sstevel@tonic-gate {
12547c478bd9Sstevel@tonic-gate 	char *os;	/* save old string */
12557c478bd9Sstevel@tonic-gate 	int tmp_val = 0;
12567c478bd9Sstevel@tonic-gate 	int flag = 0;
12577c478bd9Sstevel@tonic-gate 
12587c478bd9Sstevel@tonic-gate 	while (isdigit (*s)) {
12597c478bd9Sstevel@tonic-gate 		++flag;
12607c478bd9Sstevel@tonic-gate 		tmp_val = tmp_val*10 + *s - '0';
12617c478bd9Sstevel@tonic-gate 		s++;
12627c478bd9Sstevel@tonic-gate 	}
12637c478bd9Sstevel@tonic-gate 	if (flag == 0)
12647c478bd9Sstevel@tonic-gate 		return ((char *)NULL);
12657c478bd9Sstevel@tonic-gate 	if (*s == '$') {
12667c478bd9Sstevel@tonic-gate 		*val = tmp_val;
12677c478bd9Sstevel@tonic-gate 		return(++s);
12687c478bd9Sstevel@tonic-gate 	}
12697c478bd9Sstevel@tonic-gate 	return ((char *)NULL);
12707c478bd9Sstevel@tonic-gate }
1271