xref: /illumos-gate/usr/src/cmd/csh/printf.c (revision 2a8bcb4e)
17c478bd9Sstevel@tonic-gate /*
2*6c02b4a4Smuffin  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
77c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
87c478bd9Sstevel@tonic-gate 
97c478bd9Sstevel@tonic-gate /*
107c478bd9Sstevel@tonic-gate  * Copyright (c) 1980 Regents of the University of California.
117c478bd9Sstevel@tonic-gate  * All rights reserved. The Berkeley Software License Agreement
127c478bd9Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
137c478bd9Sstevel@tonic-gate  */
147c478bd9Sstevel@tonic-gate 
157c478bd9Sstevel@tonic-gate /*
167c478bd9Sstevel@tonic-gate  * Hacked "printf" which prints through putbyte and Putchar.
177c478bd9Sstevel@tonic-gate  * putbyte() is used to send a pure byte, which might be a part
187c478bd9Sstevel@tonic-gate  * of a mutlibyte character, mainly for %s.  A control character
197c478bd9Sstevel@tonic-gate  * for putbyte() may be QUOTE'd meaning not to convert it to ^x
207c478bd9Sstevel@tonic-gate  * sequence.  In all other cases Putchar() is used to send a character
217c478bd9Sstevel@tonic-gate  * in tchar (== wchar_t + * optional QUOE.)
227c478bd9Sstevel@tonic-gate  * DONT USE WITH STDIO!
237c478bd9Sstevel@tonic-gate  * This printf has been hacked again so that it understands tchar string
247c478bd9Sstevel@tonic-gate  * when the format specifier %t is used.  Also %c has been expanded
257c478bd9Sstevel@tonic-gate  * to take a tchar character as well as normal int.
267c478bd9Sstevel@tonic-gate  * %t is supported in its simplest form; no width or precision will
277c478bd9Sstevel@tonic-gate  * be understood.
287c478bd9Sstevel@tonic-gate  * Assumption here is that sizeof(tchar)<=sizeof(int) so that tchar is
297c478bd9Sstevel@tonic-gate  * passed as int.  Otherwise, %T must be specified instead of %c to
307c478bd9Sstevel@tonic-gate  * print a character in tchar.
317c478bd9Sstevel@tonic-gate  */
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #include <stdarg.h>
347c478bd9Sstevel@tonic-gate #include <values.h>
357c478bd9Sstevel@tonic-gate #include "sh.h" /* For tchar. */
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #define	HIBITLL		(1ULL << 63)
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate void _print(char *format, va_list *args);
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate static char *p;
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate int
printf(const char * format,...)447c478bd9Sstevel@tonic-gate printf(const char *format, ...)
457c478bd9Sstevel@tonic-gate {
467c478bd9Sstevel@tonic-gate 	va_list stupid;
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate 	p = (char *)gettext(format);
497c478bd9Sstevel@tonic-gate 	va_start(stupid, format);
507c478bd9Sstevel@tonic-gate 	_print(p, &stupid);
517c478bd9Sstevel@tonic-gate 	va_end(stupid);
52*6c02b4a4Smuffin 
53*6c02b4a4Smuffin 	return (0);
547c478bd9Sstevel@tonic-gate }
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate /*
577c478bd9Sstevel@tonic-gate  *	Floating-point code is included or not, depending
587c478bd9Sstevel@tonic-gate  *	on whether the preprocessor variable FLOAT is 1 or 0.
597c478bd9Sstevel@tonic-gate  */
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate /* Maximum number of digits in any integer (long) representation */
627c478bd9Sstevel@tonic-gate #define	MAXDIGS	20
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate /* Convert a digit character to the corresponding number */
657c478bd9Sstevel@tonic-gate #define	tonumber(x)	((x) - '0')
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate /* Convert a number between 0 and 9 to the corresponding digit */
687c478bd9Sstevel@tonic-gate #define	todigit(x)	((x) + '0')
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate /* Maximum total number of digits in E format */
717c478bd9Sstevel@tonic-gate #define	MAXECVT	17
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate /* Maximum number of digits after decimal point in F format */
747c478bd9Sstevel@tonic-gate #define	MAXFCVT	60
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate /* Maximum significant figures in a floating-point number */
777c478bd9Sstevel@tonic-gate #define	MAXFSIG	17
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate /* Maximum number of characters in an exponent */
807c478bd9Sstevel@tonic-gate #define	MAXESIZ	4
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate /* Maximum (positive) exponent or greater */
837c478bd9Sstevel@tonic-gate #define	MAXEXP	40
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate #define	max(a, b) ((a) > (b) ? (a) : (b))
887c478bd9Sstevel@tonic-gate #define	min(a, b) ((a) < (b) ? (a) : (b))
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate /* If this symbol is nonzero, allow '0' as a flag */
917c478bd9Sstevel@tonic-gate #define	FZERO 1
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate #if FLOAT
947c478bd9Sstevel@tonic-gate /*
957c478bd9Sstevel@tonic-gate  *	System-supplied routines for floating conversion
967c478bd9Sstevel@tonic-gate  */
977c478bd9Sstevel@tonic-gate char *fcvt();
987c478bd9Sstevel@tonic-gate char *ecvt();
997c478bd9Sstevel@tonic-gate #endif
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate void
_print(char * format,va_list * args)1027c478bd9Sstevel@tonic-gate _print(char *format, va_list *args)
1037c478bd9Sstevel@tonic-gate {
1047c478bd9Sstevel@tonic-gate 	/* Current position in format */
1057c478bd9Sstevel@tonic-gate 	char *cp;
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate 	/* Starting and ending points for value to be printed */
1087c478bd9Sstevel@tonic-gate 	char *bp, *p;
1097c478bd9Sstevel@tonic-gate 	tchar *tbp, *tep;	/* For "%t". */
1107c478bd9Sstevel@tonic-gate 	tchar tcbuf[2];		/* For "%c" or "%T". */
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 	/* Field width and precision */
1137c478bd9Sstevel@tonic-gate 	int width, prec;
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	/* Format code */
1167c478bd9Sstevel@tonic-gate 	char fcode;
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 	/* Number of padding zeroes required on the left */
1197c478bd9Sstevel@tonic-gate 	int lzero;
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate 	/* Flags - nonzero if corresponding character appears in format */
1227c478bd9Sstevel@tonic-gate 	bool length;		/* l */
1237c478bd9Sstevel@tonic-gate 	bool double_length;	/* ll */
1247c478bd9Sstevel@tonic-gate 	bool fplus;		/* + */
1257c478bd9Sstevel@tonic-gate 	bool fminus;		/* - */
1267c478bd9Sstevel@tonic-gate 	bool fblank;		/* blank */
1277c478bd9Sstevel@tonic-gate 	bool fsharp;		/* # */
1287c478bd9Sstevel@tonic-gate #if FZERO
1297c478bd9Sstevel@tonic-gate 	bool fzero;		/* 0 */
1307c478bd9Sstevel@tonic-gate #endif
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 	/* Pointer to sign, "0x", "0X", or empty */
1337c478bd9Sstevel@tonic-gate 	char *prefix;
1347c478bd9Sstevel@tonic-gate #if FLOAT
1357c478bd9Sstevel@tonic-gate 	/* Exponent or empty */
1367c478bd9Sstevel@tonic-gate 	char *suffix;
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	/* Buffer to create exponent */
1397c478bd9Sstevel@tonic-gate 	char expbuf[MAXESIZ + 1];
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	/* Number of padding zeroes required on the right */
1427c478bd9Sstevel@tonic-gate 	int rzero;
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	/* The value being converted, if real */
1457c478bd9Sstevel@tonic-gate 	double dval;
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 	/* Output values from fcvt and ecvt */
1487c478bd9Sstevel@tonic-gate 	int decpt, sign;
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 	/* Scratch */
1517c478bd9Sstevel@tonic-gate 	int k;
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 	/* Values are developed in this buffer */
1547c478bd9Sstevel@tonic-gate 	char buf[max(MAXDIGS, max(MAXFCVT + DMAXEXP, MAXECVT) + 1)];
1557c478bd9Sstevel@tonic-gate #else
1567c478bd9Sstevel@tonic-gate 	char buf[MAXDIGS];
1577c478bd9Sstevel@tonic-gate #endif
1587c478bd9Sstevel@tonic-gate 	/* The value being converted, if integer */
1597c478bd9Sstevel@tonic-gate 	long long val;
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	/* Set to point to a translate table for digits of whatever radix */
1627c478bd9Sstevel@tonic-gate 	char *tab;
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	/* Work variables */
1657c478bd9Sstevel@tonic-gate 	int n, hradix, lowbit;
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 	cp = format;
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 	/*
1707c478bd9Sstevel@tonic-gate 	 *	The main loop -- this loop goes through one iteration
1717c478bd9Sstevel@tonic-gate 	 *	for each ordinary character or format specification.
1727c478bd9Sstevel@tonic-gate 	 */
1737c478bd9Sstevel@tonic-gate 	while (*cp)
1747c478bd9Sstevel@tonic-gate 		if (*cp != '%') {
1757c478bd9Sstevel@tonic-gate 			/* Ordinary (non-%) character */
1767c478bd9Sstevel@tonic-gate 			putbyte (*cp++);
1777c478bd9Sstevel@tonic-gate 		} else {
1787c478bd9Sstevel@tonic-gate 			/*
1797c478bd9Sstevel@tonic-gate 			 *	% has been found.
1807c478bd9Sstevel@tonic-gate 			 *	First, parse the format specification.
1817c478bd9Sstevel@tonic-gate 			 */
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate 			/* Scan the <flags> */
1847c478bd9Sstevel@tonic-gate 			fplus = fminus = fblank = fsharp = 0;
1857c478bd9Sstevel@tonic-gate #if FZERO
1867c478bd9Sstevel@tonic-gate 			fzero = 0;
1877c478bd9Sstevel@tonic-gate #endif
1887c478bd9Sstevel@tonic-gate scan:
1897c478bd9Sstevel@tonic-gate 			switch (*++cp) {
1907c478bd9Sstevel@tonic-gate 			case '+':
1917c478bd9Sstevel@tonic-gate 				fplus = 1;
1927c478bd9Sstevel@tonic-gate 				goto scan;
1937c478bd9Sstevel@tonic-gate 			case '-':
1947c478bd9Sstevel@tonic-gate 				fminus = 1;
1957c478bd9Sstevel@tonic-gate 				goto scan;
1967c478bd9Sstevel@tonic-gate 			case ' ':
1977c478bd9Sstevel@tonic-gate 				fblank = 1;
1987c478bd9Sstevel@tonic-gate 				goto scan;
1997c478bd9Sstevel@tonic-gate 			case '#':
2007c478bd9Sstevel@tonic-gate 				fsharp = 1;
2017c478bd9Sstevel@tonic-gate 				goto scan;
2027c478bd9Sstevel@tonic-gate #if FZERO
2037c478bd9Sstevel@tonic-gate 			case '0':
2047c478bd9Sstevel@tonic-gate 				fzero = 1;
2057c478bd9Sstevel@tonic-gate 				goto scan;
2067c478bd9Sstevel@tonic-gate #endif
2077c478bd9Sstevel@tonic-gate 			}
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 			/* Scan the field width */
2107c478bd9Sstevel@tonic-gate 			if (*cp == '*') {
2117c478bd9Sstevel@tonic-gate 				width = va_arg (*args, int);
2127c478bd9Sstevel@tonic-gate 				if (width < 0) {
2137c478bd9Sstevel@tonic-gate 					width = -width;
2147c478bd9Sstevel@tonic-gate 					fminus = 1;
2157c478bd9Sstevel@tonic-gate 				}
2167c478bd9Sstevel@tonic-gate 				cp++;
2177c478bd9Sstevel@tonic-gate 			} else {
2187c478bd9Sstevel@tonic-gate 				width = 0;
2197c478bd9Sstevel@tonic-gate 				while (isdigit(*cp)) {
2207c478bd9Sstevel@tonic-gate 					n = tonumber(*cp++);
2217c478bd9Sstevel@tonic-gate 					width = width * 10 + n;
2227c478bd9Sstevel@tonic-gate 				}
2237c478bd9Sstevel@tonic-gate 			}
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate 			/* Scan the precision */
2267c478bd9Sstevel@tonic-gate 			if (*cp == '.') {
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 				/* '*' instead of digits? */
2297c478bd9Sstevel@tonic-gate 				if (*++cp == '*') {
2307c478bd9Sstevel@tonic-gate 					prec = va_arg(*args, int);
2317c478bd9Sstevel@tonic-gate 					cp++;
2327c478bd9Sstevel@tonic-gate 				} else {
2337c478bd9Sstevel@tonic-gate 					prec = 0;
2347c478bd9Sstevel@tonic-gate 					while (isdigit(*cp)) {
2357c478bd9Sstevel@tonic-gate 						n = tonumber(*cp++);
2367c478bd9Sstevel@tonic-gate 						prec = prec * 10 + n;
2377c478bd9Sstevel@tonic-gate 					}
2387c478bd9Sstevel@tonic-gate 				}
2397c478bd9Sstevel@tonic-gate 			} else {
2407c478bd9Sstevel@tonic-gate 				prec = -1;
2417c478bd9Sstevel@tonic-gate 			}
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 			/* Scan the length modifier */
2447c478bd9Sstevel@tonic-gate 			double_length = length = 0;
2457c478bd9Sstevel@tonic-gate 			switch (*cp) {
2467c478bd9Sstevel@tonic-gate 			case 'l':
2477c478bd9Sstevel@tonic-gate 				if (*(cp + 1) == 'l') {
2487c478bd9Sstevel@tonic-gate 					cp++;
2497c478bd9Sstevel@tonic-gate 					double_length = 1;
2507c478bd9Sstevel@tonic-gate 				} else {
2517c478bd9Sstevel@tonic-gate 					length = 1;
2527c478bd9Sstevel@tonic-gate 				}
2537c478bd9Sstevel@tonic-gate 				/* No break */
2547c478bd9Sstevel@tonic-gate 			case 'h':
2557c478bd9Sstevel@tonic-gate 				cp++;
2567c478bd9Sstevel@tonic-gate 			}
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 			/*
2597c478bd9Sstevel@tonic-gate 			 *	The character addressed by cp must be the
2607c478bd9Sstevel@tonic-gate 			 *	format letter -- there is nothing left for
2617c478bd9Sstevel@tonic-gate 			 *	it to be.
2627c478bd9Sstevel@tonic-gate 			 *
2637c478bd9Sstevel@tonic-gate 			 *	The status of the +, -, #, blank, and 0
2647c478bd9Sstevel@tonic-gate 			 *	flags are reflected in the variables
2657c478bd9Sstevel@tonic-gate 			 *	"fplus", "fminus", "fsharp", "fblank",
2667c478bd9Sstevel@tonic-gate 			 *	and "fzero", respectively.
2677c478bd9Sstevel@tonic-gate 			 *	"width" and "prec" contain numbers
2687c478bd9Sstevel@tonic-gate 			 *	corresponding to the digit strings
2697c478bd9Sstevel@tonic-gate 			 *	before and after the decimal point,
2707c478bd9Sstevel@tonic-gate 			 *	respectively. If there was no decimal
2717c478bd9Sstevel@tonic-gate 			 *	point, "prec" is -1.
2727c478bd9Sstevel@tonic-gate 			 *
2737c478bd9Sstevel@tonic-gate 			 *	The following switch sets things up
2747c478bd9Sstevel@tonic-gate 			 *	for printing.  What ultimately gets
2757c478bd9Sstevel@tonic-gate 			 *	printed will be padding blanks, a prefix,
2767c478bd9Sstevel@tonic-gate 			 *	left padding zeroes, a value, right padding
2777c478bd9Sstevel@tonic-gate 			 *	zeroes, a suffix, and more padding
2787c478bd9Sstevel@tonic-gate 			 *	blanks.  Padding blanks will not appear
2797c478bd9Sstevel@tonic-gate 			 *	simultaneously on both the left and the
2807c478bd9Sstevel@tonic-gate 			 *	right.  Each case in this switch will
2817c478bd9Sstevel@tonic-gate 			 *	compute the value, and leave in several
2827c478bd9Sstevel@tonic-gate 			 *	variables the information necessary to
2837c478bd9Sstevel@tonic-gate 			 *	construct what is to be printed.
2847c478bd9Sstevel@tonic-gate 			 *
2857c478bd9Sstevel@tonic-gate 			 *	The prefix is a sign, a blank, "0x", "0X",
2867c478bd9Sstevel@tonic-gate 			 *	or null, and is addressed by "prefix".
2877c478bd9Sstevel@tonic-gate 			 *
2887c478bd9Sstevel@tonic-gate 			 *	The suffix is either null or an exponent,
2897c478bd9Sstevel@tonic-gate 			 *	and is addressed by "suffix".
2907c478bd9Sstevel@tonic-gate 			 *
2917c478bd9Sstevel@tonic-gate 			 *	The value to be printed starts at "bp"
2927c478bd9Sstevel@tonic-gate 			 *	and continues up to and not including "p".
2937c478bd9Sstevel@tonic-gate 			 *
2947c478bd9Sstevel@tonic-gate 			 *	"lzero" and "rzero" will contain the number
2957c478bd9Sstevel@tonic-gate 			 *	of padding zeroes required on the left
2967c478bd9Sstevel@tonic-gate 			 *	and right, respectively.  If either of
2977c478bd9Sstevel@tonic-gate 			 *	these variables is negative, it will be
2987c478bd9Sstevel@tonic-gate 			 *	treated as if it were zero.
2997c478bd9Sstevel@tonic-gate 			 *
3007c478bd9Sstevel@tonic-gate 			 *	The number of padding blanks, and whether
3017c478bd9Sstevel@tonic-gate 			 *	they go on the left or the right, will be
3027c478bd9Sstevel@tonic-gate 			 *	computed on exit from the switch.
3037c478bd9Sstevel@tonic-gate 			 */
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 			lzero = 0;
3067c478bd9Sstevel@tonic-gate 			prefix = "";
3077c478bd9Sstevel@tonic-gate #if FLOAT
3087c478bd9Sstevel@tonic-gate 			rzero = lzero;
3097c478bd9Sstevel@tonic-gate 			suffix = prefix;
3107c478bd9Sstevel@tonic-gate #endif
3117c478bd9Sstevel@tonic-gate 			switch (fcode = *cp++) {
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate 			/*
3147c478bd9Sstevel@tonic-gate 			 *	fixed point representations
3157c478bd9Sstevel@tonic-gate 			 *
3167c478bd9Sstevel@tonic-gate 			 *	"hradix" is half the radix for the conversion.
3177c478bd9Sstevel@tonic-gate 			 *	Conversion is unsigned unless fcode is 'd'.
3187c478bd9Sstevel@tonic-gate 			 *	HIBITLL is 1000...000 binary, and is equal to
3197c478bd9Sstevel@tonic-gate 			 *		the maximum negative number.
3207c478bd9Sstevel@tonic-gate 			 *	We assume a 2's complement machine
3217c478bd9Sstevel@tonic-gate 			 */
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 			case 'D':
3247c478bd9Sstevel@tonic-gate 			case 'U':
3257c478bd9Sstevel@tonic-gate 				length = 1;
3267c478bd9Sstevel@tonic-gate 			case 'd':
3277c478bd9Sstevel@tonic-gate 			case 'u':
3287c478bd9Sstevel@tonic-gate 				hradix = 5;
3297c478bd9Sstevel@tonic-gate 				goto fixed;
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 			case 'O':
3327c478bd9Sstevel@tonic-gate 				length = 1;
3337c478bd9Sstevel@tonic-gate 			case 'o':
3347c478bd9Sstevel@tonic-gate 				hradix = 4;
3357c478bd9Sstevel@tonic-gate 				goto fixed;
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 			case 'X':
3387c478bd9Sstevel@tonic-gate 			case 'x':
3397c478bd9Sstevel@tonic-gate 				hradix = 8;
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate fixed:
3427c478bd9Sstevel@tonic-gate 				/* Establish default precision */
3437c478bd9Sstevel@tonic-gate 				if (prec < 0) {
3447c478bd9Sstevel@tonic-gate 					prec = 1;
3457c478bd9Sstevel@tonic-gate 				}
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 				/* Fetch the argument to be printed */
3487c478bd9Sstevel@tonic-gate 				if (double_length) {
3497c478bd9Sstevel@tonic-gate 					val = va_arg(*args, long long);
3507c478bd9Sstevel@tonic-gate 				} else if (length) {
3517c478bd9Sstevel@tonic-gate 					val = va_arg(*args, long);
3527c478bd9Sstevel@tonic-gate 				} else if (fcode == 'd') {
3537c478bd9Sstevel@tonic-gate 					val = va_arg(*args, int);
3547c478bd9Sstevel@tonic-gate 				} else {
3557c478bd9Sstevel@tonic-gate 					val = va_arg(*args, unsigned);
3567c478bd9Sstevel@tonic-gate 				}
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 				/* If signed conversion, establish sign */
3597c478bd9Sstevel@tonic-gate 				if (fcode == 'd' || fcode == 'D') {
3607c478bd9Sstevel@tonic-gate 					if (val < 0) {
3617c478bd9Sstevel@tonic-gate 						prefix = "-";
3627c478bd9Sstevel@tonic-gate 						/*
3637c478bd9Sstevel@tonic-gate 						 *	Negate, checking in
3647c478bd9Sstevel@tonic-gate 						 *	advance for possible
3657c478bd9Sstevel@tonic-gate 						 *	overflow.
3667c478bd9Sstevel@tonic-gate 						 */
3677c478bd9Sstevel@tonic-gate 						if (val != HIBITLL) {
3687c478bd9Sstevel@tonic-gate 							val = -val;
3697c478bd9Sstevel@tonic-gate 						}
3707c478bd9Sstevel@tonic-gate 					} else if (fplus) {
3717c478bd9Sstevel@tonic-gate 						prefix = "+";
3727c478bd9Sstevel@tonic-gate 					} else if (fblank) {
3737c478bd9Sstevel@tonic-gate 						prefix = " ";
3747c478bd9Sstevel@tonic-gate 					}
3757c478bd9Sstevel@tonic-gate 				}
3767c478bd9Sstevel@tonic-gate #if FZERO
3777c478bd9Sstevel@tonic-gate 				if (fzero) {
3787c478bd9Sstevel@tonic-gate 					int n = width - strlen(prefix);
3797c478bd9Sstevel@tonic-gate 					if (n > prec) {
3807c478bd9Sstevel@tonic-gate 						prec = n;
3817c478bd9Sstevel@tonic-gate 					}
3827c478bd9Sstevel@tonic-gate 				}
3837c478bd9Sstevel@tonic-gate #endif
3847c478bd9Sstevel@tonic-gate 				/* Set translate table for digits */
3857c478bd9Sstevel@tonic-gate 				if (fcode == 'X') {
3867c478bd9Sstevel@tonic-gate 					tab = "0123456789ABCDEF";
3877c478bd9Sstevel@tonic-gate 				} else {
3887c478bd9Sstevel@tonic-gate 					tab = "0123456789abcdef";
3897c478bd9Sstevel@tonic-gate 				}
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 				/* Develop the digits of the value */
3927c478bd9Sstevel@tonic-gate 				p = bp = buf + MAXDIGS;
3937c478bd9Sstevel@tonic-gate 				while (val) {
3947c478bd9Sstevel@tonic-gate 					lowbit = val & 1;
3957c478bd9Sstevel@tonic-gate 					val = (val >> 1) & ~HIBITLL;
3967c478bd9Sstevel@tonic-gate 					*--bp = tab[val % hradix * 2 + lowbit];
3977c478bd9Sstevel@tonic-gate 					val /= hradix;
3987c478bd9Sstevel@tonic-gate 				}
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 				/* Calculate padding zero requirement */
4017c478bd9Sstevel@tonic-gate 				lzero = bp - p + prec;
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 				/* Handle the # flag */
4047c478bd9Sstevel@tonic-gate 				if (fsharp && bp != p) {
4057c478bd9Sstevel@tonic-gate 					switch (fcode) {
4067c478bd9Sstevel@tonic-gate 					case 'o':
4077c478bd9Sstevel@tonic-gate 						if (lzero < 1)
4087c478bd9Sstevel@tonic-gate 							lzero = 1;
4097c478bd9Sstevel@tonic-gate 						break;
4107c478bd9Sstevel@tonic-gate 					case 'x':
4117c478bd9Sstevel@tonic-gate 						prefix = "0x";
4127c478bd9Sstevel@tonic-gate 						break;
4137c478bd9Sstevel@tonic-gate 					case 'X':
4147c478bd9Sstevel@tonic-gate 						prefix = "0X";
4157c478bd9Sstevel@tonic-gate 						break;
4167c478bd9Sstevel@tonic-gate 					}
4177c478bd9Sstevel@tonic-gate 				}
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 				break;
4207c478bd9Sstevel@tonic-gate #if FLOAT
4217c478bd9Sstevel@tonic-gate 			case 'E':
4227c478bd9Sstevel@tonic-gate 			case 'e':
4237c478bd9Sstevel@tonic-gate 				/*
4247c478bd9Sstevel@tonic-gate 				 *	E-format.  The general strategy
4257c478bd9Sstevel@tonic-gate 				 *	here is fairly easy: we take
4267c478bd9Sstevel@tonic-gate 				 *	what ecvt gives us and re-format it.
4277c478bd9Sstevel@tonic-gate 				 */
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate 				/* Establish default precision */
4307c478bd9Sstevel@tonic-gate 				if (prec < 0) {
4317c478bd9Sstevel@tonic-gate 					prec = 6;
4327c478bd9Sstevel@tonic-gate 				}
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate 				/* Fetch the value */
4357c478bd9Sstevel@tonic-gate 				dval = va_arg(*args, double);
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate 				/* Develop the mantissa */
4387c478bd9Sstevel@tonic-gate 				bp = ecvt(dval,
4397c478bd9Sstevel@tonic-gate 				    min(prec + 1, MAXECVT),
4407c478bd9Sstevel@tonic-gate 				    &decpt,
4417c478bd9Sstevel@tonic-gate 				    &sign);
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 				/* Determine the prefix */
4447c478bd9Sstevel@tonic-gate e_merge:
4457c478bd9Sstevel@tonic-gate 				if (sign) {
4467c478bd9Sstevel@tonic-gate 					prefix = "-";
4477c478bd9Sstevel@tonic-gate 				} else if (fplus) {
4487c478bd9Sstevel@tonic-gate 					prefix = "+";
4497c478bd9Sstevel@tonic-gate 				} else if (fblank) {
4507c478bd9Sstevel@tonic-gate 					prefix = " ";
4517c478bd9Sstevel@tonic-gate 				}
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate 				/* Place the first digit in the buffer */
4547c478bd9Sstevel@tonic-gate 				p = &buf[0];
4557c478bd9Sstevel@tonic-gate 				*p++ = *bp != '\0' ? *bp++ : '0';
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 				/* Put in a decimal point if needed */
4587c478bd9Sstevel@tonic-gate 				if (prec != 0 || fsharp) {
4597c478bd9Sstevel@tonic-gate 					*p++ = '.';
4607c478bd9Sstevel@tonic-gate 				}
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 				/* Create the rest of the mantissa */
4637c478bd9Sstevel@tonic-gate 				rzero = prec;
4647c478bd9Sstevel@tonic-gate 				while (rzero > 0 && *bp != '\0') {
4657c478bd9Sstevel@tonic-gate 					--rzero;
4667c478bd9Sstevel@tonic-gate 					*p++ = *bp++;
4677c478bd9Sstevel@tonic-gate 				}
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 				bp = &buf[0];
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 				/* Create the exponent */
4727c478bd9Sstevel@tonic-gate 				suffix = &expbuf[MAXESIZ];
4737c478bd9Sstevel@tonic-gate 				*suffix = '\0';
4747c478bd9Sstevel@tonic-gate 				if (dval != 0) {
4757c478bd9Sstevel@tonic-gate 					n = decpt - 1;
4767c478bd9Sstevel@tonic-gate 					if (n < 0) {
4777c478bd9Sstevel@tonic-gate 						n = -n;
4787c478bd9Sstevel@tonic-gate 					}
4797c478bd9Sstevel@tonic-gate 					while (n != 0) {
4807c478bd9Sstevel@tonic-gate 						*--suffix = todigit(n % 10);
4817c478bd9Sstevel@tonic-gate 						n /= 10;
4827c478bd9Sstevel@tonic-gate 					}
4837c478bd9Sstevel@tonic-gate 				}
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 				/* Prepend leading zeroes to the exponent */
4867c478bd9Sstevel@tonic-gate 				while (suffix > &expbuf[MAXESIZ - 2]) {
4877c478bd9Sstevel@tonic-gate 					*--suffix = '0';
4887c478bd9Sstevel@tonic-gate 				}
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate 				/* Put in the exponent sign */
4917c478bd9Sstevel@tonic-gate 				*--suffix = (decpt > 0 || dval == 0) ?
4927c478bd9Sstevel@tonic-gate 				    '+' : '-';
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate 				/* Put in the e */
4957c478bd9Sstevel@tonic-gate 				*--suffix = isupper(fcode) ? 'E' : 'e';
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 				break;
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate 			case 'f':
5007c478bd9Sstevel@tonic-gate 				/*
5017c478bd9Sstevel@tonic-gate 				 *	F-format floating point.  This is
5027c478bd9Sstevel@tonic-gate 				 *	a good deal less simple than E-format.
5037c478bd9Sstevel@tonic-gate 				 *	The overall strategy will be to call
5047c478bd9Sstevel@tonic-gate 				 *	fcvt, reformat its result into buf,
5057c478bd9Sstevel@tonic-gate 				 *	and calculate how many trailing
5067c478bd9Sstevel@tonic-gate 				 *	zeroes will be required.  There will
5077c478bd9Sstevel@tonic-gate 				 *	never be any leading zeroes needed.
5087c478bd9Sstevel@tonic-gate 				 */
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate 				/* Establish default precision */
5117c478bd9Sstevel@tonic-gate 				if (prec < 0) {
5127c478bd9Sstevel@tonic-gate 					prec = 6;
5137c478bd9Sstevel@tonic-gate 				}
5147c478bd9Sstevel@tonic-gate 
5157c478bd9Sstevel@tonic-gate 				/* Fetch the value */
5167c478bd9Sstevel@tonic-gate 				dval = va_arg(*args, double);
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 				/* Do the conversion */
5197c478bd9Sstevel@tonic-gate 				bp = fcvt(dval,
5207c478bd9Sstevel@tonic-gate 				    min(prec, MAXFCVT),
5217c478bd9Sstevel@tonic-gate 				    &decpt,
5227c478bd9Sstevel@tonic-gate 				    &sign);
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate 				/* Determine the prefix */
5257c478bd9Sstevel@tonic-gate f_merge:
5267c478bd9Sstevel@tonic-gate 				if (sign && decpt > -prec &&
5277c478bd9Sstevel@tonic-gate 				    *bp != '\0' && *bp != '0') {
5287c478bd9Sstevel@tonic-gate 					prefix = "-";
5297c478bd9Sstevel@tonic-gate 				} else if (fplus) {
5307c478bd9Sstevel@tonic-gate 					prefix = "+";
5317c478bd9Sstevel@tonic-gate 				} else if (fblank) {
5327c478bd9Sstevel@tonic-gate 					prefix = " ";
5337c478bd9Sstevel@tonic-gate 				}
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate 				/* Initialize buffer pointer */
5367c478bd9Sstevel@tonic-gate 				p = &buf[0];
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate 				/* Emit the digits before the decimal point */
5397c478bd9Sstevel@tonic-gate 				n = decpt;
5407c478bd9Sstevel@tonic-gate 				k = 0;
5417c478bd9Sstevel@tonic-gate 				if (n <= 0) {
5427c478bd9Sstevel@tonic-gate 					*p++ = '0';
5437c478bd9Sstevel@tonic-gate 				} else {
5447c478bd9Sstevel@tonic-gate 					do {
5457c478bd9Sstevel@tonic-gate 						if (*bp == '\0' ||
5467c478bd9Sstevel@tonic-gate 						    k >= MAXFSIG) {
5477c478bd9Sstevel@tonic-gate 							*p++ = '0';
5487c478bd9Sstevel@tonic-gate 						} else {
5497c478bd9Sstevel@tonic-gate 							*p++ = *bp++;
5507c478bd9Sstevel@tonic-gate 							++k;
5517c478bd9Sstevel@tonic-gate 						}
5527c478bd9Sstevel@tonic-gate 					} while (--n != 0);
5537c478bd9Sstevel@tonic-gate 				}
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate 				/* Decide whether we need a decimal point */
5567c478bd9Sstevel@tonic-gate 				if (fsharp || prec > 0) {
5577c478bd9Sstevel@tonic-gate 					*p++ = '.';
5587c478bd9Sstevel@tonic-gate 				}
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 				/* Digits (if any) after the decimal point */
5617c478bd9Sstevel@tonic-gate 				n = min(prec, MAXFCVT);
5627c478bd9Sstevel@tonic-gate 				rzero = prec - n;
5637c478bd9Sstevel@tonic-gate 				while (--n >= 0) {
5647c478bd9Sstevel@tonic-gate 					if (++decpt <= 0 || *bp == '\0' ||
5657c478bd9Sstevel@tonic-gate 					    k >= MAXFSIG) {
5667c478bd9Sstevel@tonic-gate 						*p++ = '0';
5677c478bd9Sstevel@tonic-gate 					} else {
5687c478bd9Sstevel@tonic-gate 						*p++ = *bp++;
5697c478bd9Sstevel@tonic-gate 						++k;
5707c478bd9Sstevel@tonic-gate 					}
5717c478bd9Sstevel@tonic-gate 				}
5727c478bd9Sstevel@tonic-gate 
5737c478bd9Sstevel@tonic-gate 				bp = &buf[0];
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 				break;
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate 			case 'G':
5787c478bd9Sstevel@tonic-gate 			case 'g':
5797c478bd9Sstevel@tonic-gate 				/*
5807c478bd9Sstevel@tonic-gate 				 *	g-format.  We play around a bit
5817c478bd9Sstevel@tonic-gate 				 *	and then jump into e or f, as needed.
5827c478bd9Sstevel@tonic-gate 				 */
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 				/* Establish default precision */
5857c478bd9Sstevel@tonic-gate 				if (prec < 0) {
5867c478bd9Sstevel@tonic-gate 					prec = 6;
5877c478bd9Sstevel@tonic-gate 				}
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate 				/* Fetch the value */
5907c478bd9Sstevel@tonic-gate 				dval = va_arg(*args, double);
5917c478bd9Sstevel@tonic-gate 
5927c478bd9Sstevel@tonic-gate 				/* Do the conversion */
5937c478bd9Sstevel@tonic-gate 				bp = ecvt(dval,
5947c478bd9Sstevel@tonic-gate 				    min(prec, MAXECVT),
5957c478bd9Sstevel@tonic-gate 				    &decpt,
5967c478bd9Sstevel@tonic-gate 				    &sign);
5977c478bd9Sstevel@tonic-gate 				if (dval == 0) {
5987c478bd9Sstevel@tonic-gate 					decpt = 1;
5997c478bd9Sstevel@tonic-gate 				}
6007c478bd9Sstevel@tonic-gate 
6017c478bd9Sstevel@tonic-gate 				k = prec;
6027c478bd9Sstevel@tonic-gate 				if (!fsharp) {
6037c478bd9Sstevel@tonic-gate 					n = strlen(bp);
6047c478bd9Sstevel@tonic-gate 					if (n < k) {
6057c478bd9Sstevel@tonic-gate 						k = n;
6067c478bd9Sstevel@tonic-gate 					}
6077c478bd9Sstevel@tonic-gate 					while (k >= 1 && bp[k-1] == '0') {
6087c478bd9Sstevel@tonic-gate 						--k;
6097c478bd9Sstevel@tonic-gate 					}
6107c478bd9Sstevel@tonic-gate 				}
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 				if (decpt < -3 || decpt > prec) {
6137c478bd9Sstevel@tonic-gate 					prec = k - 1;
6147c478bd9Sstevel@tonic-gate 					goto e_merge;
6157c478bd9Sstevel@tonic-gate 				} else {
6167c478bd9Sstevel@tonic-gate 					prec = k - decpt;
6177c478bd9Sstevel@tonic-gate 					goto f_merge;
6187c478bd9Sstevel@tonic-gate 				}
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate #endif
6217c478bd9Sstevel@tonic-gate 			case 'c':
6227c478bd9Sstevel@tonic-gate #ifdef MBCHAR_1 /* sizeof(int)>=sizeof(tchar) */
6237c478bd9Sstevel@tonic-gate /*
6247c478bd9Sstevel@tonic-gate  * A tchar arg is passed as int so we used the normal %c to specify
6257c478bd9Sstevel@tonic-gate  * such an arugument.
6267c478bd9Sstevel@tonic-gate  */
6277c478bd9Sstevel@tonic-gate 				tcbuf[0] = va_arg(*args, int);
6287c478bd9Sstevel@tonic-gate 				tbp = &tcbuf[0];
6297c478bd9Sstevel@tonic-gate 				tep = tbp + 1;
6307c478bd9Sstevel@tonic-gate 				fcode = 't'; /* Fake the rest of code. */
6317c478bd9Sstevel@tonic-gate 				break;
6327c478bd9Sstevel@tonic-gate #else
6337c478bd9Sstevel@tonic-gate /*
6347c478bd9Sstevel@tonic-gate  * We would have to invent another new format speficier such as "%T" to
6357c478bd9Sstevel@tonic-gate  * take a tchar arg.  Let's worry about when that time comes.
6367c478bd9Sstevel@tonic-gate  */
6377c478bd9Sstevel@tonic-gate 				/*
6387c478bd9Sstevel@tonic-gate 				 * Following code take care of a char arg
6397c478bd9Sstevel@tonic-gate 				 * only.
6407c478bd9Sstevel@tonic-gate 				 */
6417c478bd9Sstevel@tonic-gate 				buf[0] = va_arg(*args, int);
6427c478bd9Sstevel@tonic-gate 				bp = &buf[0];
6437c478bd9Sstevel@tonic-gate 				p = bp + 1;
6447c478bd9Sstevel@tonic-gate 				break;
6457c478bd9Sstevel@tonic-gate 			case 'T': /* Corresponding arg is tchar. */
6467c478bd9Sstevel@tonic-gate 				tcbuf[0] = va_arg(*args, tchar);
6477c478bd9Sstevel@tonic-gate 				tbp = &tcbuf[0];
6487c478bd9Sstevel@tonic-gate 				tep = tbp + 1;
6497c478bd9Sstevel@tonic-gate 				fcode = 't'; /* Fake the rest of code. */
6507c478bd9Sstevel@tonic-gate 				break;
6517c478bd9Sstevel@tonic-gate #endif
6527c478bd9Sstevel@tonic-gate 			case 's':
6537c478bd9Sstevel@tonic-gate 				bp = va_arg(*args, char *);
6547c478bd9Sstevel@tonic-gate 				if (bp == 0) {
6557c478bd9Sstevel@tonic-gate nullstr:				bp = "(null)";
6567c478bd9Sstevel@tonic-gate 					p = bp + strlen("(null)");
6577c478bd9Sstevel@tonic-gate 					break;
6587c478bd9Sstevel@tonic-gate 				}
6597c478bd9Sstevel@tonic-gate 				if (prec < 0) {
6607c478bd9Sstevel@tonic-gate 					prec = MAXINT;
6617c478bd9Sstevel@tonic-gate 				}
6627c478bd9Sstevel@tonic-gate 				for (n = 0; *bp++ != '\0' && n < prec; n++)
6637c478bd9Sstevel@tonic-gate 					;
6647c478bd9Sstevel@tonic-gate 				p = --bp;
6657c478bd9Sstevel@tonic-gate 				bp -= n;
6667c478bd9Sstevel@tonic-gate 				break;
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate 			case 't':
6697c478bd9Sstevel@tonic-gate 				/*
6707c478bd9Sstevel@tonic-gate 				 * Special format specifier "%t" tells
6717c478bd9Sstevel@tonic-gate 				 * printf() to print char strings written
6727c478bd9Sstevel@tonic-gate 				 * as tchar string.
6737c478bd9Sstevel@tonic-gate 				 */
6747c478bd9Sstevel@tonic-gate 				tbp = va_arg(*args, tchar *);
6757c478bd9Sstevel@tonic-gate 				if (tbp == 0) {
6767c478bd9Sstevel@tonic-gate 					fcode = 's'; /* Act as if it were %s. */
6777c478bd9Sstevel@tonic-gate 					goto nullstr;
6787c478bd9Sstevel@tonic-gate 				}
6797c478bd9Sstevel@tonic-gate 				if (prec < 0) {
6807c478bd9Sstevel@tonic-gate 					prec = MAXINT;
6817c478bd9Sstevel@tonic-gate 				}
6827c478bd9Sstevel@tonic-gate 				for (n = 0; *tbp++ != 0 && n < prec; n++)
6837c478bd9Sstevel@tonic-gate 					;
6847c478bd9Sstevel@tonic-gate 				tep = --tbp;
6857c478bd9Sstevel@tonic-gate 				tbp -= n;
6867c478bd9Sstevel@tonic-gate 
6877c478bd9Sstevel@tonic-gate 				/*
6887c478bd9Sstevel@tonic-gate 				 * Just to make the following padding
6897c478bd9Sstevel@tonic-gate 				 * calculation not to go very crazy...
6907c478bd9Sstevel@tonic-gate 				 */
6917c478bd9Sstevel@tonic-gate 				bp = NULL;
6927c478bd9Sstevel@tonic-gate 				p = bp + n;
6937c478bd9Sstevel@tonic-gate 				break;
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 			case '\0':
6967c478bd9Sstevel@tonic-gate 				cp--;
6977c478bd9Sstevel@tonic-gate 				break;
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate 			default:
7007c478bd9Sstevel@tonic-gate 				p = bp = &fcode;
7017c478bd9Sstevel@tonic-gate 				p++;
7027c478bd9Sstevel@tonic-gate 				break;
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 			}
7057c478bd9Sstevel@tonic-gate 			if (fcode != '\0') {
7067c478bd9Sstevel@tonic-gate 				/* Calculate number of padding blanks */
7077c478bd9Sstevel@tonic-gate 				int nblank;
7087c478bd9Sstevel@tonic-gate 				nblank = width
7097c478bd9Sstevel@tonic-gate #if FLOAT
7107c478bd9Sstevel@tonic-gate 					- (rzero < 0 ? 0:  rzero)
7117c478bd9Sstevel@tonic-gate 					- strlen(suffix)
7127c478bd9Sstevel@tonic-gate #endif
7137c478bd9Sstevel@tonic-gate 					- (p - bp)
7147c478bd9Sstevel@tonic-gate 					- (lzero < 0 ? 0 : lzero)
7157c478bd9Sstevel@tonic-gate 					- strlen(prefix);
7167c478bd9Sstevel@tonic-gate 
7177c478bd9Sstevel@tonic-gate 				/* Blanks on left if required */
7187c478bd9Sstevel@tonic-gate 				if (!fminus) {
7197c478bd9Sstevel@tonic-gate 					while (--nblank >= 0) {
7207c478bd9Sstevel@tonic-gate 						Putchar(' ');
7217c478bd9Sstevel@tonic-gate 					}
7227c478bd9Sstevel@tonic-gate 				}
7237c478bd9Sstevel@tonic-gate 
7247c478bd9Sstevel@tonic-gate 				/* Prefix, if any */
7257c478bd9Sstevel@tonic-gate 				while (*prefix != '\0') {
7267c478bd9Sstevel@tonic-gate 					Putchar(*prefix++);
7277c478bd9Sstevel@tonic-gate 				}
7287c478bd9Sstevel@tonic-gate 
7297c478bd9Sstevel@tonic-gate 				/* Zeroes on the left */
7307c478bd9Sstevel@tonic-gate 				while (--lzero >= 0) {
7317c478bd9Sstevel@tonic-gate 					Putchar('0');
7327c478bd9Sstevel@tonic-gate 				}
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate 				/* The value itself */
7357c478bd9Sstevel@tonic-gate 				if (fcode == 't') {	/* %t is special. */
7367c478bd9Sstevel@tonic-gate 					while (tbp < tep) {
7377c478bd9Sstevel@tonic-gate 					    Putchar(*tbp++);
7387c478bd9Sstevel@tonic-gate 					}
7397c478bd9Sstevel@tonic-gate 				} else {	/* For rest of the cases. */
7407c478bd9Sstevel@tonic-gate 					while (bp < p) {
7417c478bd9Sstevel@tonic-gate 					    putbyte(*bp++);
7427c478bd9Sstevel@tonic-gate 					}
7437c478bd9Sstevel@tonic-gate 				}
7447c478bd9Sstevel@tonic-gate #if FLOAT
7457c478bd9Sstevel@tonic-gate 				/* Zeroes on the right */
7467c478bd9Sstevel@tonic-gate 				while (--rzero >= 0)
7477c478bd9Sstevel@tonic-gate 					Putchar('0');
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate 				/* The suffix */
7507c478bd9Sstevel@tonic-gate 				while (*suffix != '\0') {
7517c478bd9Sstevel@tonic-gate 					Putchar(*suffix++);
7527c478bd9Sstevel@tonic-gate 				}
7537c478bd9Sstevel@tonic-gate #endif
7547c478bd9Sstevel@tonic-gate 				/* Blanks on the right if required */
7557c478bd9Sstevel@tonic-gate 				if (fminus) {
7567c478bd9Sstevel@tonic-gate 					while (--nblank >= 0) {
7577c478bd9Sstevel@tonic-gate 						Putchar(' ');
7587c478bd9Sstevel@tonic-gate 					}
7597c478bd9Sstevel@tonic-gate 				}
7607c478bd9Sstevel@tonic-gate 			}
7617c478bd9Sstevel@tonic-gate 		}
7627c478bd9Sstevel@tonic-gate }
763