xref: /titanic_53/usr/src/cmd/csh/printf.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
3*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
4*7c478bd9Sstevel@tonic-gate  */
5*7c478bd9Sstevel@tonic-gate 
6*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
7*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
8*7c478bd9Sstevel@tonic-gate 
9*7c478bd9Sstevel@tonic-gate /*
10*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1980 Regents of the University of California.
11*7c478bd9Sstevel@tonic-gate  * All rights reserved. The Berkeley Software License Agreement
12*7c478bd9Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
13*7c478bd9Sstevel@tonic-gate  */
14*7c478bd9Sstevel@tonic-gate 
15*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
16*7c478bd9Sstevel@tonic-gate 
17*7c478bd9Sstevel@tonic-gate /*
18*7c478bd9Sstevel@tonic-gate  * Hacked "printf" which prints through putbyte and Putchar.
19*7c478bd9Sstevel@tonic-gate  * putbyte() is used to send a pure byte, which might be a part
20*7c478bd9Sstevel@tonic-gate  * of a mutlibyte character, mainly for %s.  A control character
21*7c478bd9Sstevel@tonic-gate  * for putbyte() may be QUOTE'd meaning not to convert it to ^x
22*7c478bd9Sstevel@tonic-gate  * sequence.  In all other cases Putchar() is used to send a character
23*7c478bd9Sstevel@tonic-gate  * in tchar (== wchar_t + * optional QUOE.)
24*7c478bd9Sstevel@tonic-gate  * DONT USE WITH STDIO!
25*7c478bd9Sstevel@tonic-gate  * This printf has been hacked again so that it understands tchar string
26*7c478bd9Sstevel@tonic-gate  * when the format specifier %t is used.  Also %c has been expanded
27*7c478bd9Sstevel@tonic-gate  * to take a tchar character as well as normal int.
28*7c478bd9Sstevel@tonic-gate  * %t is supported in its simplest form; no width or precision will
29*7c478bd9Sstevel@tonic-gate  * be understood.
30*7c478bd9Sstevel@tonic-gate  * Assumption here is that sizeof(tchar)<=sizeof(int) so that tchar is
31*7c478bd9Sstevel@tonic-gate  * passed as int.  Otherwise, %T must be specified instead of %c to
32*7c478bd9Sstevel@tonic-gate  * print a character in tchar.
33*7c478bd9Sstevel@tonic-gate  */
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate #include <stdarg.h>
36*7c478bd9Sstevel@tonic-gate #include <values.h>
37*7c478bd9Sstevel@tonic-gate #include "sh.h" /* For tchar. */
38*7c478bd9Sstevel@tonic-gate 
39*7c478bd9Sstevel@tonic-gate #define	HIBITLL		(1ULL << 63)
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate void _print(char *format, va_list *args);
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate static char *p;
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate int
46*7c478bd9Sstevel@tonic-gate printf(const char *format, ...)
47*7c478bd9Sstevel@tonic-gate {
48*7c478bd9Sstevel@tonic-gate 	va_list stupid;
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate 	p = (char *)gettext(format);
51*7c478bd9Sstevel@tonic-gate 	va_start(stupid, format);
52*7c478bd9Sstevel@tonic-gate 	_print(p, &stupid);
53*7c478bd9Sstevel@tonic-gate 	va_end(stupid);
54*7c478bd9Sstevel@tonic-gate }
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate /*
57*7c478bd9Sstevel@tonic-gate  *	Floating-point code is included or not, depending
58*7c478bd9Sstevel@tonic-gate  *	on whether the preprocessor variable FLOAT is 1 or 0.
59*7c478bd9Sstevel@tonic-gate  */
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate /* Maximum number of digits in any integer (long) representation */
62*7c478bd9Sstevel@tonic-gate #define	MAXDIGS	20
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate /* Convert a digit character to the corresponding number */
65*7c478bd9Sstevel@tonic-gate #define	tonumber(x)	((x) - '0')
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate /* Convert a number between 0 and 9 to the corresponding digit */
68*7c478bd9Sstevel@tonic-gate #define	todigit(x)	((x) + '0')
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate /* Maximum total number of digits in E format */
71*7c478bd9Sstevel@tonic-gate #define	MAXECVT	17
72*7c478bd9Sstevel@tonic-gate 
73*7c478bd9Sstevel@tonic-gate /* Maximum number of digits after decimal point in F format */
74*7c478bd9Sstevel@tonic-gate #define	MAXFCVT	60
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate /* Maximum significant figures in a floating-point number */
77*7c478bd9Sstevel@tonic-gate #define	MAXFSIG	17
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate /* Maximum number of characters in an exponent */
80*7c478bd9Sstevel@tonic-gate #define	MAXESIZ	4
81*7c478bd9Sstevel@tonic-gate 
82*7c478bd9Sstevel@tonic-gate /* Maximum (positive) exponent or greater */
83*7c478bd9Sstevel@tonic-gate #define	MAXEXP	40
84*7c478bd9Sstevel@tonic-gate 
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate #define	max(a, b) ((a) > (b) ? (a) : (b))
88*7c478bd9Sstevel@tonic-gate #define	min(a, b) ((a) < (b) ? (a) : (b))
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate /* If this symbol is nonzero, allow '0' as a flag */
91*7c478bd9Sstevel@tonic-gate #define	FZERO 1
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate #if FLOAT
94*7c478bd9Sstevel@tonic-gate /*
95*7c478bd9Sstevel@tonic-gate  *	System-supplied routines for floating conversion
96*7c478bd9Sstevel@tonic-gate  */
97*7c478bd9Sstevel@tonic-gate char *fcvt();
98*7c478bd9Sstevel@tonic-gate char *ecvt();
99*7c478bd9Sstevel@tonic-gate #endif
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate void
102*7c478bd9Sstevel@tonic-gate _print(char *format, va_list *args)
103*7c478bd9Sstevel@tonic-gate {
104*7c478bd9Sstevel@tonic-gate 	/* Current position in format */
105*7c478bd9Sstevel@tonic-gate 	char *cp;
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate 	/* Starting and ending points for value to be printed */
108*7c478bd9Sstevel@tonic-gate 	char *bp, *p;
109*7c478bd9Sstevel@tonic-gate 	tchar *tbp, *tep;	/* For "%t". */
110*7c478bd9Sstevel@tonic-gate 	tchar tcbuf[2];		/* For "%c" or "%T". */
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate 	/* Field width and precision */
113*7c478bd9Sstevel@tonic-gate 	int width, prec;
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate 	/* Format code */
116*7c478bd9Sstevel@tonic-gate 	char fcode;
117*7c478bd9Sstevel@tonic-gate 
118*7c478bd9Sstevel@tonic-gate 	/* Number of padding zeroes required on the left */
119*7c478bd9Sstevel@tonic-gate 	int lzero;
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate 	/* Flags - nonzero if corresponding character appears in format */
122*7c478bd9Sstevel@tonic-gate 	bool length;		/* l */
123*7c478bd9Sstevel@tonic-gate 	bool double_length;	/* ll */
124*7c478bd9Sstevel@tonic-gate 	bool fplus;		/* + */
125*7c478bd9Sstevel@tonic-gate 	bool fminus;		/* - */
126*7c478bd9Sstevel@tonic-gate 	bool fblank;		/* blank */
127*7c478bd9Sstevel@tonic-gate 	bool fsharp;		/* # */
128*7c478bd9Sstevel@tonic-gate #if FZERO
129*7c478bd9Sstevel@tonic-gate 	bool fzero;		/* 0 */
130*7c478bd9Sstevel@tonic-gate #endif
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate 	/* Pointer to sign, "0x", "0X", or empty */
133*7c478bd9Sstevel@tonic-gate 	char *prefix;
134*7c478bd9Sstevel@tonic-gate #if FLOAT
135*7c478bd9Sstevel@tonic-gate 	/* Exponent or empty */
136*7c478bd9Sstevel@tonic-gate 	char *suffix;
137*7c478bd9Sstevel@tonic-gate 
138*7c478bd9Sstevel@tonic-gate 	/* Buffer to create exponent */
139*7c478bd9Sstevel@tonic-gate 	char expbuf[MAXESIZ + 1];
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate 	/* Number of padding zeroes required on the right */
142*7c478bd9Sstevel@tonic-gate 	int rzero;
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate 	/* The value being converted, if real */
145*7c478bd9Sstevel@tonic-gate 	double dval;
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate 	/* Output values from fcvt and ecvt */
148*7c478bd9Sstevel@tonic-gate 	int decpt, sign;
149*7c478bd9Sstevel@tonic-gate 
150*7c478bd9Sstevel@tonic-gate 	/* Scratch */
151*7c478bd9Sstevel@tonic-gate 	int k;
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 	/* Values are developed in this buffer */
154*7c478bd9Sstevel@tonic-gate 	char buf[max(MAXDIGS, max(MAXFCVT + DMAXEXP, MAXECVT) + 1)];
155*7c478bd9Sstevel@tonic-gate #else
156*7c478bd9Sstevel@tonic-gate 	char buf[MAXDIGS];
157*7c478bd9Sstevel@tonic-gate #endif
158*7c478bd9Sstevel@tonic-gate 	/* The value being converted, if integer */
159*7c478bd9Sstevel@tonic-gate 	long long val;
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate 	/* Set to point to a translate table for digits of whatever radix */
162*7c478bd9Sstevel@tonic-gate 	char *tab;
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate 	/* Work variables */
165*7c478bd9Sstevel@tonic-gate 	int n, hradix, lowbit;
166*7c478bd9Sstevel@tonic-gate 
167*7c478bd9Sstevel@tonic-gate 	cp = format;
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate 	/*
170*7c478bd9Sstevel@tonic-gate 	 *	The main loop -- this loop goes through one iteration
171*7c478bd9Sstevel@tonic-gate 	 *	for each ordinary character or format specification.
172*7c478bd9Sstevel@tonic-gate 	 */
173*7c478bd9Sstevel@tonic-gate 	while (*cp)
174*7c478bd9Sstevel@tonic-gate 		if (*cp != '%') {
175*7c478bd9Sstevel@tonic-gate 			/* Ordinary (non-%) character */
176*7c478bd9Sstevel@tonic-gate 			putbyte (*cp++);
177*7c478bd9Sstevel@tonic-gate 		} else {
178*7c478bd9Sstevel@tonic-gate 			/*
179*7c478bd9Sstevel@tonic-gate 			 *	% has been found.
180*7c478bd9Sstevel@tonic-gate 			 *	First, parse the format specification.
181*7c478bd9Sstevel@tonic-gate 			 */
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate 			/* Scan the <flags> */
184*7c478bd9Sstevel@tonic-gate 			fplus = fminus = fblank = fsharp = 0;
185*7c478bd9Sstevel@tonic-gate #if FZERO
186*7c478bd9Sstevel@tonic-gate 			fzero = 0;
187*7c478bd9Sstevel@tonic-gate #endif
188*7c478bd9Sstevel@tonic-gate scan:
189*7c478bd9Sstevel@tonic-gate 			switch (*++cp) {
190*7c478bd9Sstevel@tonic-gate 			case '+':
191*7c478bd9Sstevel@tonic-gate 				fplus = 1;
192*7c478bd9Sstevel@tonic-gate 				goto scan;
193*7c478bd9Sstevel@tonic-gate 			case '-':
194*7c478bd9Sstevel@tonic-gate 				fminus = 1;
195*7c478bd9Sstevel@tonic-gate 				goto scan;
196*7c478bd9Sstevel@tonic-gate 			case ' ':
197*7c478bd9Sstevel@tonic-gate 				fblank = 1;
198*7c478bd9Sstevel@tonic-gate 				goto scan;
199*7c478bd9Sstevel@tonic-gate 			case '#':
200*7c478bd9Sstevel@tonic-gate 				fsharp = 1;
201*7c478bd9Sstevel@tonic-gate 				goto scan;
202*7c478bd9Sstevel@tonic-gate #if FZERO
203*7c478bd9Sstevel@tonic-gate 			case '0':
204*7c478bd9Sstevel@tonic-gate 				fzero = 1;
205*7c478bd9Sstevel@tonic-gate 				goto scan;
206*7c478bd9Sstevel@tonic-gate #endif
207*7c478bd9Sstevel@tonic-gate 			}
208*7c478bd9Sstevel@tonic-gate 
209*7c478bd9Sstevel@tonic-gate 			/* Scan the field width */
210*7c478bd9Sstevel@tonic-gate 			if (*cp == '*') {
211*7c478bd9Sstevel@tonic-gate 				width = va_arg (*args, int);
212*7c478bd9Sstevel@tonic-gate 				if (width < 0) {
213*7c478bd9Sstevel@tonic-gate 					width = -width;
214*7c478bd9Sstevel@tonic-gate 					fminus = 1;
215*7c478bd9Sstevel@tonic-gate 				}
216*7c478bd9Sstevel@tonic-gate 				cp++;
217*7c478bd9Sstevel@tonic-gate 			} else {
218*7c478bd9Sstevel@tonic-gate 				width = 0;
219*7c478bd9Sstevel@tonic-gate 				while (isdigit(*cp)) {
220*7c478bd9Sstevel@tonic-gate 					n = tonumber(*cp++);
221*7c478bd9Sstevel@tonic-gate 					width = width * 10 + n;
222*7c478bd9Sstevel@tonic-gate 				}
223*7c478bd9Sstevel@tonic-gate 			}
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate 			/* Scan the precision */
226*7c478bd9Sstevel@tonic-gate 			if (*cp == '.') {
227*7c478bd9Sstevel@tonic-gate 
228*7c478bd9Sstevel@tonic-gate 				/* '*' instead of digits? */
229*7c478bd9Sstevel@tonic-gate 				if (*++cp == '*') {
230*7c478bd9Sstevel@tonic-gate 					prec = va_arg(*args, int);
231*7c478bd9Sstevel@tonic-gate 					cp++;
232*7c478bd9Sstevel@tonic-gate 				} else {
233*7c478bd9Sstevel@tonic-gate 					prec = 0;
234*7c478bd9Sstevel@tonic-gate 					while (isdigit(*cp)) {
235*7c478bd9Sstevel@tonic-gate 						n = tonumber(*cp++);
236*7c478bd9Sstevel@tonic-gate 						prec = prec * 10 + n;
237*7c478bd9Sstevel@tonic-gate 					}
238*7c478bd9Sstevel@tonic-gate 				}
239*7c478bd9Sstevel@tonic-gate 			} else {
240*7c478bd9Sstevel@tonic-gate 				prec = -1;
241*7c478bd9Sstevel@tonic-gate 			}
242*7c478bd9Sstevel@tonic-gate 
243*7c478bd9Sstevel@tonic-gate 			/* Scan the length modifier */
244*7c478bd9Sstevel@tonic-gate 			double_length = length = 0;
245*7c478bd9Sstevel@tonic-gate 			switch (*cp) {
246*7c478bd9Sstevel@tonic-gate 			case 'l':
247*7c478bd9Sstevel@tonic-gate 				if (*(cp + 1) == 'l') {
248*7c478bd9Sstevel@tonic-gate 					cp++;
249*7c478bd9Sstevel@tonic-gate 					double_length = 1;
250*7c478bd9Sstevel@tonic-gate 				} else {
251*7c478bd9Sstevel@tonic-gate 					length = 1;
252*7c478bd9Sstevel@tonic-gate 				}
253*7c478bd9Sstevel@tonic-gate 				/* No break */
254*7c478bd9Sstevel@tonic-gate 			case 'h':
255*7c478bd9Sstevel@tonic-gate 				cp++;
256*7c478bd9Sstevel@tonic-gate 			}
257*7c478bd9Sstevel@tonic-gate 
258*7c478bd9Sstevel@tonic-gate 			/*
259*7c478bd9Sstevel@tonic-gate 			 *	The character addressed by cp must be the
260*7c478bd9Sstevel@tonic-gate 			 *	format letter -- there is nothing left for
261*7c478bd9Sstevel@tonic-gate 			 *	it to be.
262*7c478bd9Sstevel@tonic-gate 			 *
263*7c478bd9Sstevel@tonic-gate 			 *	The status of the +, -, #, blank, and 0
264*7c478bd9Sstevel@tonic-gate 			 *	flags are reflected in the variables
265*7c478bd9Sstevel@tonic-gate 			 *	"fplus", "fminus", "fsharp", "fblank",
266*7c478bd9Sstevel@tonic-gate 			 *	and "fzero", respectively.
267*7c478bd9Sstevel@tonic-gate 			 *	"width" and "prec" contain numbers
268*7c478bd9Sstevel@tonic-gate 			 *	corresponding to the digit strings
269*7c478bd9Sstevel@tonic-gate 			 *	before and after the decimal point,
270*7c478bd9Sstevel@tonic-gate 			 *	respectively. If there was no decimal
271*7c478bd9Sstevel@tonic-gate 			 *	point, "prec" is -1.
272*7c478bd9Sstevel@tonic-gate 			 *
273*7c478bd9Sstevel@tonic-gate 			 *	The following switch sets things up
274*7c478bd9Sstevel@tonic-gate 			 *	for printing.  What ultimately gets
275*7c478bd9Sstevel@tonic-gate 			 *	printed will be padding blanks, a prefix,
276*7c478bd9Sstevel@tonic-gate 			 *	left padding zeroes, a value, right padding
277*7c478bd9Sstevel@tonic-gate 			 *	zeroes, a suffix, and more padding
278*7c478bd9Sstevel@tonic-gate 			 *	blanks.  Padding blanks will not appear
279*7c478bd9Sstevel@tonic-gate 			 *	simultaneously on both the left and the
280*7c478bd9Sstevel@tonic-gate 			 *	right.  Each case in this switch will
281*7c478bd9Sstevel@tonic-gate 			 *	compute the value, and leave in several
282*7c478bd9Sstevel@tonic-gate 			 *	variables the information necessary to
283*7c478bd9Sstevel@tonic-gate 			 *	construct what is to be printed.
284*7c478bd9Sstevel@tonic-gate 			 *
285*7c478bd9Sstevel@tonic-gate 			 *	The prefix is a sign, a blank, "0x", "0X",
286*7c478bd9Sstevel@tonic-gate 			 *	or null, and is addressed by "prefix".
287*7c478bd9Sstevel@tonic-gate 			 *
288*7c478bd9Sstevel@tonic-gate 			 *	The suffix is either null or an exponent,
289*7c478bd9Sstevel@tonic-gate 			 *	and is addressed by "suffix".
290*7c478bd9Sstevel@tonic-gate 			 *
291*7c478bd9Sstevel@tonic-gate 			 *	The value to be printed starts at "bp"
292*7c478bd9Sstevel@tonic-gate 			 *	and continues up to and not including "p".
293*7c478bd9Sstevel@tonic-gate 			 *
294*7c478bd9Sstevel@tonic-gate 			 *	"lzero" and "rzero" will contain the number
295*7c478bd9Sstevel@tonic-gate 			 *	of padding zeroes required on the left
296*7c478bd9Sstevel@tonic-gate 			 *	and right, respectively.  If either of
297*7c478bd9Sstevel@tonic-gate 			 *	these variables is negative, it will be
298*7c478bd9Sstevel@tonic-gate 			 *	treated as if it were zero.
299*7c478bd9Sstevel@tonic-gate 			 *
300*7c478bd9Sstevel@tonic-gate 			 *	The number of padding blanks, and whether
301*7c478bd9Sstevel@tonic-gate 			 *	they go on the left or the right, will be
302*7c478bd9Sstevel@tonic-gate 			 *	computed on exit from the switch.
303*7c478bd9Sstevel@tonic-gate 			 */
304*7c478bd9Sstevel@tonic-gate 
305*7c478bd9Sstevel@tonic-gate 			lzero = 0;
306*7c478bd9Sstevel@tonic-gate 			prefix = "";
307*7c478bd9Sstevel@tonic-gate #if FLOAT
308*7c478bd9Sstevel@tonic-gate 			rzero = lzero;
309*7c478bd9Sstevel@tonic-gate 			suffix = prefix;
310*7c478bd9Sstevel@tonic-gate #endif
311*7c478bd9Sstevel@tonic-gate 			switch (fcode = *cp++) {
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate 			/*
314*7c478bd9Sstevel@tonic-gate 			 *	fixed point representations
315*7c478bd9Sstevel@tonic-gate 			 *
316*7c478bd9Sstevel@tonic-gate 			 *	"hradix" is half the radix for the conversion.
317*7c478bd9Sstevel@tonic-gate 			 *	Conversion is unsigned unless fcode is 'd'.
318*7c478bd9Sstevel@tonic-gate 			 *	HIBITLL is 1000...000 binary, and is equal to
319*7c478bd9Sstevel@tonic-gate 			 *		the maximum negative number.
320*7c478bd9Sstevel@tonic-gate 			 *	We assume a 2's complement machine
321*7c478bd9Sstevel@tonic-gate 			 */
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate 			case 'D':
324*7c478bd9Sstevel@tonic-gate 			case 'U':
325*7c478bd9Sstevel@tonic-gate 				length = 1;
326*7c478bd9Sstevel@tonic-gate 			case 'd':
327*7c478bd9Sstevel@tonic-gate 			case 'u':
328*7c478bd9Sstevel@tonic-gate 				hradix = 5;
329*7c478bd9Sstevel@tonic-gate 				goto fixed;
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate 			case 'O':
332*7c478bd9Sstevel@tonic-gate 				length = 1;
333*7c478bd9Sstevel@tonic-gate 			case 'o':
334*7c478bd9Sstevel@tonic-gate 				hradix = 4;
335*7c478bd9Sstevel@tonic-gate 				goto fixed;
336*7c478bd9Sstevel@tonic-gate 
337*7c478bd9Sstevel@tonic-gate 			case 'X':
338*7c478bd9Sstevel@tonic-gate 			case 'x':
339*7c478bd9Sstevel@tonic-gate 				hradix = 8;
340*7c478bd9Sstevel@tonic-gate 
341*7c478bd9Sstevel@tonic-gate fixed:
342*7c478bd9Sstevel@tonic-gate 				/* Establish default precision */
343*7c478bd9Sstevel@tonic-gate 				if (prec < 0) {
344*7c478bd9Sstevel@tonic-gate 					prec = 1;
345*7c478bd9Sstevel@tonic-gate 				}
346*7c478bd9Sstevel@tonic-gate 
347*7c478bd9Sstevel@tonic-gate 				/* Fetch the argument to be printed */
348*7c478bd9Sstevel@tonic-gate 				if (double_length) {
349*7c478bd9Sstevel@tonic-gate 					val = va_arg(*args, long long);
350*7c478bd9Sstevel@tonic-gate 				} else if (length) {
351*7c478bd9Sstevel@tonic-gate 					val = va_arg(*args, long);
352*7c478bd9Sstevel@tonic-gate 				} else if (fcode == 'd') {
353*7c478bd9Sstevel@tonic-gate 					val = va_arg(*args, int);
354*7c478bd9Sstevel@tonic-gate 				} else {
355*7c478bd9Sstevel@tonic-gate 					val = va_arg(*args, unsigned);
356*7c478bd9Sstevel@tonic-gate 				}
357*7c478bd9Sstevel@tonic-gate 
358*7c478bd9Sstevel@tonic-gate 				/* If signed conversion, establish sign */
359*7c478bd9Sstevel@tonic-gate 				if (fcode == 'd' || fcode == 'D') {
360*7c478bd9Sstevel@tonic-gate 					if (val < 0) {
361*7c478bd9Sstevel@tonic-gate 						prefix = "-";
362*7c478bd9Sstevel@tonic-gate 						/*
363*7c478bd9Sstevel@tonic-gate 						 *	Negate, checking in
364*7c478bd9Sstevel@tonic-gate 						 *	advance for possible
365*7c478bd9Sstevel@tonic-gate 						 *	overflow.
366*7c478bd9Sstevel@tonic-gate 						 */
367*7c478bd9Sstevel@tonic-gate 						if (val != HIBITLL) {
368*7c478bd9Sstevel@tonic-gate 							val = -val;
369*7c478bd9Sstevel@tonic-gate 						}
370*7c478bd9Sstevel@tonic-gate 					} else if (fplus) {
371*7c478bd9Sstevel@tonic-gate 						prefix = "+";
372*7c478bd9Sstevel@tonic-gate 					} else if (fblank) {
373*7c478bd9Sstevel@tonic-gate 						prefix = " ";
374*7c478bd9Sstevel@tonic-gate 					}
375*7c478bd9Sstevel@tonic-gate 				}
376*7c478bd9Sstevel@tonic-gate #if FZERO
377*7c478bd9Sstevel@tonic-gate 				if (fzero) {
378*7c478bd9Sstevel@tonic-gate 					int n = width - strlen(prefix);
379*7c478bd9Sstevel@tonic-gate 					if (n > prec) {
380*7c478bd9Sstevel@tonic-gate 						prec = n;
381*7c478bd9Sstevel@tonic-gate 					}
382*7c478bd9Sstevel@tonic-gate 				}
383*7c478bd9Sstevel@tonic-gate #endif
384*7c478bd9Sstevel@tonic-gate 				/* Set translate table for digits */
385*7c478bd9Sstevel@tonic-gate 				if (fcode == 'X') {
386*7c478bd9Sstevel@tonic-gate 					tab = "0123456789ABCDEF";
387*7c478bd9Sstevel@tonic-gate 				} else {
388*7c478bd9Sstevel@tonic-gate 					tab = "0123456789abcdef";
389*7c478bd9Sstevel@tonic-gate 				}
390*7c478bd9Sstevel@tonic-gate 
391*7c478bd9Sstevel@tonic-gate 				/* Develop the digits of the value */
392*7c478bd9Sstevel@tonic-gate 				p = bp = buf + MAXDIGS;
393*7c478bd9Sstevel@tonic-gate 				while (val) {
394*7c478bd9Sstevel@tonic-gate 					lowbit = val & 1;
395*7c478bd9Sstevel@tonic-gate 					val = (val >> 1) & ~HIBITLL;
396*7c478bd9Sstevel@tonic-gate 					*--bp = tab[val % hradix * 2 + lowbit];
397*7c478bd9Sstevel@tonic-gate 					val /= hradix;
398*7c478bd9Sstevel@tonic-gate 				}
399*7c478bd9Sstevel@tonic-gate 
400*7c478bd9Sstevel@tonic-gate 				/* Calculate padding zero requirement */
401*7c478bd9Sstevel@tonic-gate 				lzero = bp - p + prec;
402*7c478bd9Sstevel@tonic-gate 
403*7c478bd9Sstevel@tonic-gate 				/* Handle the # flag */
404*7c478bd9Sstevel@tonic-gate 				if (fsharp && bp != p) {
405*7c478bd9Sstevel@tonic-gate 					switch (fcode) {
406*7c478bd9Sstevel@tonic-gate 					case 'o':
407*7c478bd9Sstevel@tonic-gate 						if (lzero < 1)
408*7c478bd9Sstevel@tonic-gate 							lzero = 1;
409*7c478bd9Sstevel@tonic-gate 						break;
410*7c478bd9Sstevel@tonic-gate 					case 'x':
411*7c478bd9Sstevel@tonic-gate 						prefix = "0x";
412*7c478bd9Sstevel@tonic-gate 						break;
413*7c478bd9Sstevel@tonic-gate 					case 'X':
414*7c478bd9Sstevel@tonic-gate 						prefix = "0X";
415*7c478bd9Sstevel@tonic-gate 						break;
416*7c478bd9Sstevel@tonic-gate 					}
417*7c478bd9Sstevel@tonic-gate 				}
418*7c478bd9Sstevel@tonic-gate 
419*7c478bd9Sstevel@tonic-gate 				break;
420*7c478bd9Sstevel@tonic-gate #if FLOAT
421*7c478bd9Sstevel@tonic-gate 			case 'E':
422*7c478bd9Sstevel@tonic-gate 			case 'e':
423*7c478bd9Sstevel@tonic-gate 				/*
424*7c478bd9Sstevel@tonic-gate 				 *	E-format.  The general strategy
425*7c478bd9Sstevel@tonic-gate 				 *	here is fairly easy: we take
426*7c478bd9Sstevel@tonic-gate 				 *	what ecvt gives us and re-format it.
427*7c478bd9Sstevel@tonic-gate 				 */
428*7c478bd9Sstevel@tonic-gate 
429*7c478bd9Sstevel@tonic-gate 				/* Establish default precision */
430*7c478bd9Sstevel@tonic-gate 				if (prec < 0) {
431*7c478bd9Sstevel@tonic-gate 					prec = 6;
432*7c478bd9Sstevel@tonic-gate 				}
433*7c478bd9Sstevel@tonic-gate 
434*7c478bd9Sstevel@tonic-gate 				/* Fetch the value */
435*7c478bd9Sstevel@tonic-gate 				dval = va_arg(*args, double);
436*7c478bd9Sstevel@tonic-gate 
437*7c478bd9Sstevel@tonic-gate 				/* Develop the mantissa */
438*7c478bd9Sstevel@tonic-gate 				bp = ecvt(dval,
439*7c478bd9Sstevel@tonic-gate 				    min(prec + 1, MAXECVT),
440*7c478bd9Sstevel@tonic-gate 				    &decpt,
441*7c478bd9Sstevel@tonic-gate 				    &sign);
442*7c478bd9Sstevel@tonic-gate 
443*7c478bd9Sstevel@tonic-gate 				/* Determine the prefix */
444*7c478bd9Sstevel@tonic-gate e_merge:
445*7c478bd9Sstevel@tonic-gate 				if (sign) {
446*7c478bd9Sstevel@tonic-gate 					prefix = "-";
447*7c478bd9Sstevel@tonic-gate 				} else if (fplus) {
448*7c478bd9Sstevel@tonic-gate 					prefix = "+";
449*7c478bd9Sstevel@tonic-gate 				} else if (fblank) {
450*7c478bd9Sstevel@tonic-gate 					prefix = " ";
451*7c478bd9Sstevel@tonic-gate 				}
452*7c478bd9Sstevel@tonic-gate 
453*7c478bd9Sstevel@tonic-gate 				/* Place the first digit in the buffer */
454*7c478bd9Sstevel@tonic-gate 				p = &buf[0];
455*7c478bd9Sstevel@tonic-gate 				*p++ = *bp != '\0' ? *bp++ : '0';
456*7c478bd9Sstevel@tonic-gate 
457*7c478bd9Sstevel@tonic-gate 				/* Put in a decimal point if needed */
458*7c478bd9Sstevel@tonic-gate 				if (prec != 0 || fsharp) {
459*7c478bd9Sstevel@tonic-gate 					*p++ = '.';
460*7c478bd9Sstevel@tonic-gate 				}
461*7c478bd9Sstevel@tonic-gate 
462*7c478bd9Sstevel@tonic-gate 				/* Create the rest of the mantissa */
463*7c478bd9Sstevel@tonic-gate 				rzero = prec;
464*7c478bd9Sstevel@tonic-gate 				while (rzero > 0 && *bp != '\0') {
465*7c478bd9Sstevel@tonic-gate 					--rzero;
466*7c478bd9Sstevel@tonic-gate 					*p++ = *bp++;
467*7c478bd9Sstevel@tonic-gate 				}
468*7c478bd9Sstevel@tonic-gate 
469*7c478bd9Sstevel@tonic-gate 				bp = &buf[0];
470*7c478bd9Sstevel@tonic-gate 
471*7c478bd9Sstevel@tonic-gate 				/* Create the exponent */
472*7c478bd9Sstevel@tonic-gate 				suffix = &expbuf[MAXESIZ];
473*7c478bd9Sstevel@tonic-gate 				*suffix = '\0';
474*7c478bd9Sstevel@tonic-gate 				if (dval != 0) {
475*7c478bd9Sstevel@tonic-gate 					n = decpt - 1;
476*7c478bd9Sstevel@tonic-gate 					if (n < 0) {
477*7c478bd9Sstevel@tonic-gate 						n = -n;
478*7c478bd9Sstevel@tonic-gate 					}
479*7c478bd9Sstevel@tonic-gate 					while (n != 0) {
480*7c478bd9Sstevel@tonic-gate 						*--suffix = todigit(n % 10);
481*7c478bd9Sstevel@tonic-gate 						n /= 10;
482*7c478bd9Sstevel@tonic-gate 					}
483*7c478bd9Sstevel@tonic-gate 				}
484*7c478bd9Sstevel@tonic-gate 
485*7c478bd9Sstevel@tonic-gate 				/* Prepend leading zeroes to the exponent */
486*7c478bd9Sstevel@tonic-gate 				while (suffix > &expbuf[MAXESIZ - 2]) {
487*7c478bd9Sstevel@tonic-gate 					*--suffix = '0';
488*7c478bd9Sstevel@tonic-gate 				}
489*7c478bd9Sstevel@tonic-gate 
490*7c478bd9Sstevel@tonic-gate 				/* Put in the exponent sign */
491*7c478bd9Sstevel@tonic-gate 				*--suffix = (decpt > 0 || dval == 0) ?
492*7c478bd9Sstevel@tonic-gate 				    '+' : '-';
493*7c478bd9Sstevel@tonic-gate 
494*7c478bd9Sstevel@tonic-gate 				/* Put in the e */
495*7c478bd9Sstevel@tonic-gate 				*--suffix = isupper(fcode) ? 'E' : 'e';
496*7c478bd9Sstevel@tonic-gate 
497*7c478bd9Sstevel@tonic-gate 				break;
498*7c478bd9Sstevel@tonic-gate 
499*7c478bd9Sstevel@tonic-gate 			case 'f':
500*7c478bd9Sstevel@tonic-gate 				/*
501*7c478bd9Sstevel@tonic-gate 				 *	F-format floating point.  This is
502*7c478bd9Sstevel@tonic-gate 				 *	a good deal less simple than E-format.
503*7c478bd9Sstevel@tonic-gate 				 *	The overall strategy will be to call
504*7c478bd9Sstevel@tonic-gate 				 *	fcvt, reformat its result into buf,
505*7c478bd9Sstevel@tonic-gate 				 *	and calculate how many trailing
506*7c478bd9Sstevel@tonic-gate 				 *	zeroes will be required.  There will
507*7c478bd9Sstevel@tonic-gate 				 *	never be any leading zeroes needed.
508*7c478bd9Sstevel@tonic-gate 				 */
509*7c478bd9Sstevel@tonic-gate 
510*7c478bd9Sstevel@tonic-gate 				/* Establish default precision */
511*7c478bd9Sstevel@tonic-gate 				if (prec < 0) {
512*7c478bd9Sstevel@tonic-gate 					prec = 6;
513*7c478bd9Sstevel@tonic-gate 				}
514*7c478bd9Sstevel@tonic-gate 
515*7c478bd9Sstevel@tonic-gate 				/* Fetch the value */
516*7c478bd9Sstevel@tonic-gate 				dval = va_arg(*args, double);
517*7c478bd9Sstevel@tonic-gate 
518*7c478bd9Sstevel@tonic-gate 				/* Do the conversion */
519*7c478bd9Sstevel@tonic-gate 				bp = fcvt(dval,
520*7c478bd9Sstevel@tonic-gate 				    min(prec, MAXFCVT),
521*7c478bd9Sstevel@tonic-gate 				    &decpt,
522*7c478bd9Sstevel@tonic-gate 				    &sign);
523*7c478bd9Sstevel@tonic-gate 
524*7c478bd9Sstevel@tonic-gate 				/* Determine the prefix */
525*7c478bd9Sstevel@tonic-gate f_merge:
526*7c478bd9Sstevel@tonic-gate 				if (sign && decpt > -prec &&
527*7c478bd9Sstevel@tonic-gate 				    *bp != '\0' && *bp != '0') {
528*7c478bd9Sstevel@tonic-gate 					prefix = "-";
529*7c478bd9Sstevel@tonic-gate 				} else if (fplus) {
530*7c478bd9Sstevel@tonic-gate 					prefix = "+";
531*7c478bd9Sstevel@tonic-gate 				} else if (fblank) {
532*7c478bd9Sstevel@tonic-gate 					prefix = " ";
533*7c478bd9Sstevel@tonic-gate 				}
534*7c478bd9Sstevel@tonic-gate 
535*7c478bd9Sstevel@tonic-gate 				/* Initialize buffer pointer */
536*7c478bd9Sstevel@tonic-gate 				p = &buf[0];
537*7c478bd9Sstevel@tonic-gate 
538*7c478bd9Sstevel@tonic-gate 				/* Emit the digits before the decimal point */
539*7c478bd9Sstevel@tonic-gate 				n = decpt;
540*7c478bd9Sstevel@tonic-gate 				k = 0;
541*7c478bd9Sstevel@tonic-gate 				if (n <= 0) {
542*7c478bd9Sstevel@tonic-gate 					*p++ = '0';
543*7c478bd9Sstevel@tonic-gate 				} else {
544*7c478bd9Sstevel@tonic-gate 					do {
545*7c478bd9Sstevel@tonic-gate 						if (*bp == '\0' ||
546*7c478bd9Sstevel@tonic-gate 						    k >= MAXFSIG) {
547*7c478bd9Sstevel@tonic-gate 							*p++ = '0';
548*7c478bd9Sstevel@tonic-gate 						} else {
549*7c478bd9Sstevel@tonic-gate 							*p++ = *bp++;
550*7c478bd9Sstevel@tonic-gate 							++k;
551*7c478bd9Sstevel@tonic-gate 						}
552*7c478bd9Sstevel@tonic-gate 					} while (--n != 0);
553*7c478bd9Sstevel@tonic-gate 				}
554*7c478bd9Sstevel@tonic-gate 
555*7c478bd9Sstevel@tonic-gate 				/* Decide whether we need a decimal point */
556*7c478bd9Sstevel@tonic-gate 				if (fsharp || prec > 0) {
557*7c478bd9Sstevel@tonic-gate 					*p++ = '.';
558*7c478bd9Sstevel@tonic-gate 				}
559*7c478bd9Sstevel@tonic-gate 
560*7c478bd9Sstevel@tonic-gate 				/* Digits (if any) after the decimal point */
561*7c478bd9Sstevel@tonic-gate 				n = min(prec, MAXFCVT);
562*7c478bd9Sstevel@tonic-gate 				rzero = prec - n;
563*7c478bd9Sstevel@tonic-gate 				while (--n >= 0) {
564*7c478bd9Sstevel@tonic-gate 					if (++decpt <= 0 || *bp == '\0' ||
565*7c478bd9Sstevel@tonic-gate 					    k >= MAXFSIG) {
566*7c478bd9Sstevel@tonic-gate 						*p++ = '0';
567*7c478bd9Sstevel@tonic-gate 					} else {
568*7c478bd9Sstevel@tonic-gate 						*p++ = *bp++;
569*7c478bd9Sstevel@tonic-gate 						++k;
570*7c478bd9Sstevel@tonic-gate 					}
571*7c478bd9Sstevel@tonic-gate 				}
572*7c478bd9Sstevel@tonic-gate 
573*7c478bd9Sstevel@tonic-gate 				bp = &buf[0];
574*7c478bd9Sstevel@tonic-gate 
575*7c478bd9Sstevel@tonic-gate 				break;
576*7c478bd9Sstevel@tonic-gate 
577*7c478bd9Sstevel@tonic-gate 			case 'G':
578*7c478bd9Sstevel@tonic-gate 			case 'g':
579*7c478bd9Sstevel@tonic-gate 				/*
580*7c478bd9Sstevel@tonic-gate 				 *	g-format.  We play around a bit
581*7c478bd9Sstevel@tonic-gate 				 *	and then jump into e or f, as needed.
582*7c478bd9Sstevel@tonic-gate 				 */
583*7c478bd9Sstevel@tonic-gate 
584*7c478bd9Sstevel@tonic-gate 				/* Establish default precision */
585*7c478bd9Sstevel@tonic-gate 				if (prec < 0) {
586*7c478bd9Sstevel@tonic-gate 					prec = 6;
587*7c478bd9Sstevel@tonic-gate 				}
588*7c478bd9Sstevel@tonic-gate 
589*7c478bd9Sstevel@tonic-gate 				/* Fetch the value */
590*7c478bd9Sstevel@tonic-gate 				dval = va_arg(*args, double);
591*7c478bd9Sstevel@tonic-gate 
592*7c478bd9Sstevel@tonic-gate 				/* Do the conversion */
593*7c478bd9Sstevel@tonic-gate 				bp = ecvt(dval,
594*7c478bd9Sstevel@tonic-gate 				    min(prec, MAXECVT),
595*7c478bd9Sstevel@tonic-gate 				    &decpt,
596*7c478bd9Sstevel@tonic-gate 				    &sign);
597*7c478bd9Sstevel@tonic-gate 				if (dval == 0) {
598*7c478bd9Sstevel@tonic-gate 					decpt = 1;
599*7c478bd9Sstevel@tonic-gate 				}
600*7c478bd9Sstevel@tonic-gate 
601*7c478bd9Sstevel@tonic-gate 				k = prec;
602*7c478bd9Sstevel@tonic-gate 				if (!fsharp) {
603*7c478bd9Sstevel@tonic-gate 					n = strlen(bp);
604*7c478bd9Sstevel@tonic-gate 					if (n < k) {
605*7c478bd9Sstevel@tonic-gate 						k = n;
606*7c478bd9Sstevel@tonic-gate 					}
607*7c478bd9Sstevel@tonic-gate 					while (k >= 1 && bp[k-1] == '0') {
608*7c478bd9Sstevel@tonic-gate 						--k;
609*7c478bd9Sstevel@tonic-gate 					}
610*7c478bd9Sstevel@tonic-gate 				}
611*7c478bd9Sstevel@tonic-gate 
612*7c478bd9Sstevel@tonic-gate 				if (decpt < -3 || decpt > prec) {
613*7c478bd9Sstevel@tonic-gate 					prec = k - 1;
614*7c478bd9Sstevel@tonic-gate 					goto e_merge;
615*7c478bd9Sstevel@tonic-gate 				} else {
616*7c478bd9Sstevel@tonic-gate 					prec = k - decpt;
617*7c478bd9Sstevel@tonic-gate 					goto f_merge;
618*7c478bd9Sstevel@tonic-gate 				}
619*7c478bd9Sstevel@tonic-gate 
620*7c478bd9Sstevel@tonic-gate #endif
621*7c478bd9Sstevel@tonic-gate 			case 'c':
622*7c478bd9Sstevel@tonic-gate #ifdef MBCHAR_1 /* sizeof(int)>=sizeof(tchar) */
623*7c478bd9Sstevel@tonic-gate /*
624*7c478bd9Sstevel@tonic-gate  * A tchar arg is passed as int so we used the normal %c to specify
625*7c478bd9Sstevel@tonic-gate  * such an arugument.
626*7c478bd9Sstevel@tonic-gate  */
627*7c478bd9Sstevel@tonic-gate 				tcbuf[0] = va_arg(*args, int);
628*7c478bd9Sstevel@tonic-gate 				tbp = &tcbuf[0];
629*7c478bd9Sstevel@tonic-gate 				tep = tbp + 1;
630*7c478bd9Sstevel@tonic-gate 				fcode = 't'; /* Fake the rest of code. */
631*7c478bd9Sstevel@tonic-gate 				break;
632*7c478bd9Sstevel@tonic-gate #else
633*7c478bd9Sstevel@tonic-gate /*
634*7c478bd9Sstevel@tonic-gate  * We would have to invent another new format speficier such as "%T" to
635*7c478bd9Sstevel@tonic-gate  * take a tchar arg.  Let's worry about when that time comes.
636*7c478bd9Sstevel@tonic-gate  */
637*7c478bd9Sstevel@tonic-gate 				/*
638*7c478bd9Sstevel@tonic-gate 				 * Following code take care of a char arg
639*7c478bd9Sstevel@tonic-gate 				 * only.
640*7c478bd9Sstevel@tonic-gate 				 */
641*7c478bd9Sstevel@tonic-gate 				buf[0] = va_arg(*args, int);
642*7c478bd9Sstevel@tonic-gate 				bp = &buf[0];
643*7c478bd9Sstevel@tonic-gate 				p = bp + 1;
644*7c478bd9Sstevel@tonic-gate 				break;
645*7c478bd9Sstevel@tonic-gate 			case 'T': /* Corresponding arg is tchar. */
646*7c478bd9Sstevel@tonic-gate 				tcbuf[0] = va_arg(*args, tchar);
647*7c478bd9Sstevel@tonic-gate 				tbp = &tcbuf[0];
648*7c478bd9Sstevel@tonic-gate 				tep = tbp + 1;
649*7c478bd9Sstevel@tonic-gate 				fcode = 't'; /* Fake the rest of code. */
650*7c478bd9Sstevel@tonic-gate 				break;
651*7c478bd9Sstevel@tonic-gate #endif
652*7c478bd9Sstevel@tonic-gate 			case 's':
653*7c478bd9Sstevel@tonic-gate 				bp = va_arg(*args, char *);
654*7c478bd9Sstevel@tonic-gate 				if (bp == 0) {
655*7c478bd9Sstevel@tonic-gate nullstr:				bp = "(null)";
656*7c478bd9Sstevel@tonic-gate 					p = bp + strlen("(null)");
657*7c478bd9Sstevel@tonic-gate 					break;
658*7c478bd9Sstevel@tonic-gate 				}
659*7c478bd9Sstevel@tonic-gate 				if (prec < 0) {
660*7c478bd9Sstevel@tonic-gate 					prec = MAXINT;
661*7c478bd9Sstevel@tonic-gate 				}
662*7c478bd9Sstevel@tonic-gate 				for (n = 0; *bp++ != '\0' && n < prec; n++)
663*7c478bd9Sstevel@tonic-gate 					;
664*7c478bd9Sstevel@tonic-gate 				p = --bp;
665*7c478bd9Sstevel@tonic-gate 				bp -= n;
666*7c478bd9Sstevel@tonic-gate 				break;
667*7c478bd9Sstevel@tonic-gate 
668*7c478bd9Sstevel@tonic-gate 			case 't':
669*7c478bd9Sstevel@tonic-gate 				/*
670*7c478bd9Sstevel@tonic-gate 				 * Special format specifier "%t" tells
671*7c478bd9Sstevel@tonic-gate 				 * printf() to print char strings written
672*7c478bd9Sstevel@tonic-gate 				 * as tchar string.
673*7c478bd9Sstevel@tonic-gate 				 */
674*7c478bd9Sstevel@tonic-gate 				tbp = va_arg(*args, tchar *);
675*7c478bd9Sstevel@tonic-gate 				if (tbp == 0) {
676*7c478bd9Sstevel@tonic-gate 					fcode = 's'; /* Act as if it were %s. */
677*7c478bd9Sstevel@tonic-gate 					goto nullstr;
678*7c478bd9Sstevel@tonic-gate 				}
679*7c478bd9Sstevel@tonic-gate 				if (prec < 0) {
680*7c478bd9Sstevel@tonic-gate 					prec = MAXINT;
681*7c478bd9Sstevel@tonic-gate 				}
682*7c478bd9Sstevel@tonic-gate 				for (n = 0; *tbp++ != 0 && n < prec; n++)
683*7c478bd9Sstevel@tonic-gate 					;
684*7c478bd9Sstevel@tonic-gate 				tep = --tbp;
685*7c478bd9Sstevel@tonic-gate 				tbp -= n;
686*7c478bd9Sstevel@tonic-gate 
687*7c478bd9Sstevel@tonic-gate 				/*
688*7c478bd9Sstevel@tonic-gate 				 * Just to make the following padding
689*7c478bd9Sstevel@tonic-gate 				 * calculation not to go very crazy...
690*7c478bd9Sstevel@tonic-gate 				 */
691*7c478bd9Sstevel@tonic-gate 				bp = NULL;
692*7c478bd9Sstevel@tonic-gate 				p = bp + n;
693*7c478bd9Sstevel@tonic-gate 				break;
694*7c478bd9Sstevel@tonic-gate 
695*7c478bd9Sstevel@tonic-gate 			case '\0':
696*7c478bd9Sstevel@tonic-gate 				cp--;
697*7c478bd9Sstevel@tonic-gate 				break;
698*7c478bd9Sstevel@tonic-gate 
699*7c478bd9Sstevel@tonic-gate 			default:
700*7c478bd9Sstevel@tonic-gate 				p = bp = &fcode;
701*7c478bd9Sstevel@tonic-gate 				p++;
702*7c478bd9Sstevel@tonic-gate 				break;
703*7c478bd9Sstevel@tonic-gate 
704*7c478bd9Sstevel@tonic-gate 			}
705*7c478bd9Sstevel@tonic-gate 			if (fcode != '\0') {
706*7c478bd9Sstevel@tonic-gate 				/* Calculate number of padding blanks */
707*7c478bd9Sstevel@tonic-gate 				int nblank;
708*7c478bd9Sstevel@tonic-gate 				nblank = width
709*7c478bd9Sstevel@tonic-gate #if FLOAT
710*7c478bd9Sstevel@tonic-gate 					- (rzero < 0 ? 0:  rzero)
711*7c478bd9Sstevel@tonic-gate 					- strlen(suffix)
712*7c478bd9Sstevel@tonic-gate #endif
713*7c478bd9Sstevel@tonic-gate 					- (p - bp)
714*7c478bd9Sstevel@tonic-gate 					- (lzero < 0 ? 0 : lzero)
715*7c478bd9Sstevel@tonic-gate 					- strlen(prefix);
716*7c478bd9Sstevel@tonic-gate 
717*7c478bd9Sstevel@tonic-gate 				/* Blanks on left if required */
718*7c478bd9Sstevel@tonic-gate 				if (!fminus) {
719*7c478bd9Sstevel@tonic-gate 					while (--nblank >= 0) {
720*7c478bd9Sstevel@tonic-gate 						Putchar(' ');
721*7c478bd9Sstevel@tonic-gate 					}
722*7c478bd9Sstevel@tonic-gate 				}
723*7c478bd9Sstevel@tonic-gate 
724*7c478bd9Sstevel@tonic-gate 				/* Prefix, if any */
725*7c478bd9Sstevel@tonic-gate 				while (*prefix != '\0') {
726*7c478bd9Sstevel@tonic-gate 					Putchar(*prefix++);
727*7c478bd9Sstevel@tonic-gate 				}
728*7c478bd9Sstevel@tonic-gate 
729*7c478bd9Sstevel@tonic-gate 				/* Zeroes on the left */
730*7c478bd9Sstevel@tonic-gate 				while (--lzero >= 0) {
731*7c478bd9Sstevel@tonic-gate 					Putchar('0');
732*7c478bd9Sstevel@tonic-gate 				}
733*7c478bd9Sstevel@tonic-gate 
734*7c478bd9Sstevel@tonic-gate 				/* The value itself */
735*7c478bd9Sstevel@tonic-gate 				if (fcode == 't') {	/* %t is special. */
736*7c478bd9Sstevel@tonic-gate 					while (tbp < tep) {
737*7c478bd9Sstevel@tonic-gate 					    Putchar(*tbp++);
738*7c478bd9Sstevel@tonic-gate 					}
739*7c478bd9Sstevel@tonic-gate 				} else {	/* For rest of the cases. */
740*7c478bd9Sstevel@tonic-gate 					while (bp < p) {
741*7c478bd9Sstevel@tonic-gate 					    putbyte(*bp++);
742*7c478bd9Sstevel@tonic-gate 					}
743*7c478bd9Sstevel@tonic-gate 				}
744*7c478bd9Sstevel@tonic-gate #if FLOAT
745*7c478bd9Sstevel@tonic-gate 				/* Zeroes on the right */
746*7c478bd9Sstevel@tonic-gate 				while (--rzero >= 0)
747*7c478bd9Sstevel@tonic-gate 					Putchar('0');
748*7c478bd9Sstevel@tonic-gate 
749*7c478bd9Sstevel@tonic-gate 				/* The suffix */
750*7c478bd9Sstevel@tonic-gate 				while (*suffix != '\0') {
751*7c478bd9Sstevel@tonic-gate 					Putchar(*suffix++);
752*7c478bd9Sstevel@tonic-gate 				}
753*7c478bd9Sstevel@tonic-gate #endif
754*7c478bd9Sstevel@tonic-gate 				/* Blanks on the right if required */
755*7c478bd9Sstevel@tonic-gate 				if (fminus) {
756*7c478bd9Sstevel@tonic-gate 					while (--nblank >= 0) {
757*7c478bd9Sstevel@tonic-gate 						Putchar(' ');
758*7c478bd9Sstevel@tonic-gate 					}
759*7c478bd9Sstevel@tonic-gate 				}
760*7c478bd9Sstevel@tonic-gate 			}
761*7c478bd9Sstevel@tonic-gate 		}
762*7c478bd9Sstevel@tonic-gate }
763