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