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