1 /****************************************************************
2 Copyright (C) 1997, 1999, 2001 Lucent Technologies
3 All Rights Reserved
4 
5 Permission to use, copy, modify, and distribute this software and
6 its documentation for any purpose and without fee is hereby
7 granted, provided that the above copyright notice appear in all
8 copies and that both that the copyright notice and this
9 permission notice and warranty disclaimer appear in supporting
10 documentation, and that the name of Lucent or any of its entities
11 not be used in advertising or publicity pertaining to
12 distribution of the software without specific, written prior
13 permission.
14 
15 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
17 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
18 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
20 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
22 THIS SOFTWARE.
23 ****************************************************************/
24 
25 /* This implements most of ANSI C's printf, fprintf, and sprintf,
26  * omitting L, with %.0g and %.0G giving the shortest decimal string
27  * that rounds to the number being converted, and with negative
28  * precisions allowed for %f.
29  */
30 
31 #include "stddef.h"
32 #include "stdarg.h"
33 #include "stdlib.h"
34 
35 #ifndef NO_PRINTF_A_FMT
36 #include "arith.h"
37 #endif
38 
39 #include "stdio1.h"
40 #include "string.h"
41 #include "errno.h"
42 
43 #ifdef KR_headers
44 #define Const /* const */
45 #define Voidptr char*
46 #ifndef size_t__
47 #define size_t int
48 #define size_t__
49 #endif
50 
51 #else
52 
53 #define Const const
54 #define Voidptr void*
55 
56 #endif
57 
58 #undef MESS
59 #ifndef Stderr
60 #define Stderr stderr
61 #endif
62 
63 #ifdef _windows_
64 #undef PF_BUF
65 #define MESS
66 #include "mux0.h"
67 #define stdout_or_err(f) (f == stdout)
68 #else
69 #define stdout_or_err(f) (f == Stderr || f == stdout)
70 #endif
71 
72 #ifdef __cplusplus
73 extern "C" {
74 #endif
75 
76  extern char *dtoa_r ANSI((double, int, int, int*, int*, char **, char*, size_t));
77 
78 
79 
80 #ifdef USE_ULDIV
81 /* This is for avoiding 64-bit divisions on the DEC Alpha, since */
82 /* they are not portable among variants of OSF1 (DEC's Unix). */
83 
84 #define ULDIV(a,b) uldiv_ASL(a,(unsigned long)(b))
85 
86 #ifndef LLBITS
87 #define LLBITS 6
88 #endif
89 #ifndef ULONG
90 #define ULONG unsigned long
91 #endif
92 
93  static int
klog(ULONG x)94 klog(ULONG x)
95 {
96 	int k, rv = 0;
97 
98 	if (x > 1L)
99 	    for(k = 1 << LLBITS-1;;) {
100 		if (x >= (1L << k)) {
101 			rv |= k;
102 			x >>= k;
103 			}
104 		if (!(k >>= 1))
105 			break;
106 		}
107 	return rv;
108 	}
109 
110  ULONG
uldiv_ASL(ULONG a,ULONG b)111 uldiv_ASL(ULONG a, ULONG b)
112 {
113 	int ka;
114 	ULONG c, k;
115 	static ULONG b0;
116 	static int kb;
117 
118 	if (a < b)
119 		return 0;
120 	if (b != b0) {
121 		b0 = b;
122 		kb = klog(b);
123 		}
124 	k = 1;
125 	if ((ka = klog(a) - kb) > 0) {
126 		k <<= ka;
127 		b <<= ka;
128 		}
129 	c = 0;
130 	for(;;) {
131 		if (a >= b) {
132 			a -= b;
133 			c |= k;
134 			}
135 		if (!(k >>= 1))
136 			break;
137 		a <<= 1;
138 		}
139 	return c;
140 	}
141 
142 #else
143 #define ULDIV(a,b) a / b
144 #endif /* USE_ULDIV */
145 
146  typedef struct
147 Finfo {
148 	union { FILE *cf; char *sf; } u;
149 	char *ob0, *obe1;
150 	size_t lastlen;
151 	} Finfo;
152 
153  typedef char *(*Putfunc) ANSI((Finfo*, int*));
154 
155 #ifdef PF_BUF
156 FILE *stderr_ASL = (FILE*)&stderr_ASL;
157 void (*pfbuf_print_ASL) ANSI((char*));
158 char *pfbuf_ASL;
159 static char *pfbuf_next;
160 static size_t pfbuf_len;
161 extern Char *mymalloc_ASL ANSI((size_t));
162 extern Char *myralloc_ASL ANSI((void *, size_t));
163 
164 #undef fflush
165 #ifdef old_fflush_ASL
166 #define fflush old_fflush_ASL
167 #endif
168 
169  void
fflush_ASL(FILE * f)170 fflush_ASL(FILE *f)
171 {
172 	if (f == stderr_ASL) {
173 		if (pfbuf_ASL && pfbuf_print_ASL) {
174 			(*pfbuf_print_ASL)(pfbuf_ASL);
175 			free(pfbuf_ASL);
176 			pfbuf_ASL = 0;
177 			}
178 		}
179 	else
180 		fflush(f);
181 	}
182 
183  static void
pf_put(char * buf,int len)184 pf_put(char *buf, int len)
185 {
186 	size_t x, y;
187 	if (!pfbuf_ASL) {
188 		x = len + 256;
189 		if (x < 512)
190 			x = 512;
191 		pfbuf_ASL = pfbuf_next = (char*)mymalloc_ASL(pfbuf_len = x);
192 		}
193 	else if ((y = (pfbuf_next - pfbuf_ASL) + len) >= pfbuf_len) {
194 		x = pfbuf_len;
195 		while((x <<= 1) <= y);
196 		y = pfbuf_next - pfbuf_ASL;
197 		pfbuf_ASL = (char*)myralloc_ASL(pfbuf_ASL, x);
198 		pfbuf_next = pfbuf_ASL + y;
199 		pfbuf_len = x;
200 		}
201 	memcpy(pfbuf_next, buf, len);
202 	pfbuf_next += len;
203 	*pfbuf_next = 0;
204 	}
205 
206  static char *
pfput(Finfo * f,int * rvp)207 pfput(Finfo *f, int *rvp)
208 {
209 	int n;
210 	char *ob0 = f->ob0;
211 	*rvp += n = (int)(f->obe1 - ob0);
212 	pf_put(ob0, n);
213 	return ob0;
214 	}
215 #endif /* PF_BUF */
216 
217  static char *
Fput(Finfo * f,int * rvp)218 Fput ( Finfo *f, int *rvp)
219 {
220 	char *ob0 = f->ob0;
221 
222 	*rvp += f->obe1 - ob0;
223 	*f->obe1 = 0;
224 	fputs(ob0, f->u.cf);
225 	return ob0;
226 	}
227 
228 
229 #ifdef _windows_
230 int stdout_fileno_ASL = 1;
231 
232  static char *
Wput(Finfo * f,int * rvp)233 Wput(Finfo *f, int *rvp)
234 {
235 	char *ob0 = f->ob0;
236 
237 	*rvp += f->obe1 - ob0;
238 	*f->obe1 = 0;
239 	mwrite(ob0, f->obe1 - ob0);
240 	return ob0;
241 	}
242 #endif /*_windows_*/
243 
244 #ifdef QUOTIFY /*{*/
245  static char qtype[256];
246  static char dig[256] = {
247 	13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
248 	13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
249 	13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 10, 13, 10, 13, 13,
250 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 13, 13, 13, 13, 13, 13,
251 	13, 13, 13, 13, 11, 11, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
252 	13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
253 	13, 13, 13, 13, 11, 11, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
254 	13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
255 	13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
256 	13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
257 	13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
258 	13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
259 	13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
260 	13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
261 	13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
262 	13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13
263 	};
264 
265  static int
lcstrcmp(const char * a,const char * b)266 lcstrcmp(const char *a, const char *b)
267 {
268 	int c, d;
269 
270 	for(;;) {
271 		if ((c = *a++) >= 'A' && c <= 'Z')
272 			c += 'a' - 'A';
273 		if (d = c - *b++)
274 			return d;
275 		if (!c)
276 			break;
277 		}
278 	return 0;
279 	}
280 
281  static int
valid_param(char * t,int ekeep)282 valid_param(char *t, int ekeep)
283 	/* return 0 unless valid decimal fp number */
284 	/* also adjust Fortran exponent notations to C style */
285 {
286 	char *Dig = dig, *e = 0, *se;
287 	int dc = 0;
288 	/* digit types: 0 <= d <= 9 ==> d, +- = 10, e,E,d,D = 11 */
289 
290 #define D(n) Dig[*(unsigned char *)n]
291 
292 	if (D(t) == 10)
293 		t++;
294 	switch(*t) {
295 	 case '0':
296 		if ((t[1] == 'x' || t[1] == 'X')) {
297 			strtod(t,&se);
298 			return *se == 0;
299 			}
300 		break;
301 	 case 'I':
302 	 case 'i':
303 		if (!lcstrcmp(t,"infinity"))
304 			return 1;
305 		break;
306 	 case 'N':
307 	 case 'n':
308 		if (Arith_Kind_ASL < 3 && !lcstrcmp(t,"nan"))
309 			return 1;
310 	 }
311 	while(D(t) < 10)
312 		{ t++; dc++; }
313 	if (*t == '.')
314 		while(D(++t) < 10)
315 			dc++;
316 	if (D(t) == 11) {
317 		e = t;
318 		if (D(++t) == 10)
319 			t++;
320 		if (D(t) >= 10)
321 			return 0;
322 		while(D(t) < 10)
323 			t++;
324 		}
325 	if (dc && !*t) {
326 		if (e && !ekeep)
327 			*e = 'e';
328 		return 1;
329 		}
330 	return 0;
331 	}
332 #undef D
333 
334 
335  void
qt_init(void)336 qt_init(void)
337 {
338 	int n1;
339 	const char *t;
340 	for(t = "\"'\n.+-_"; *t; ++t)
341 		qtype[(int)*t] = *t;
342 	for(n1 = 'A'; n1 <= 'Z'; ++n1)
343 		qtype[n1] = qtype[n1+'a'-'A'] = 1;
344 	for(n1 = '0'; n1 <= '9'; ++n1)
345 		qtype[n1] = 2;
346 	}
347 
348  static void
qkind(char * s,int prec,int * quote,int * widthp)349 qkind(char *s, int prec, int *quote, int *widthp)
350 {
351 	int n0, n1, n2, ne;
352 	char *s0, *se;
353 
354 	if (!*s)
355 		goto quote_it;
356 	if (!qtype['"'])
357 		qt_init();
358 	n0 = n1 = n2 = ne = 0;
359 	s0 = s;
360 	se = s + prec;
361 	while(s < se) {
362 		switch(qtype[*(unsigned char *)s]) {
363 			case '\'': n1++; break;
364 			case '"':  n2++; break;
365 			case '\n': ne++; break;
366 			case 0:	   n0++;
367 			}
368 		++s;
369 		}
370 	if ((ne + n1 + n2) || n0) {
371 		if (n1 > n2) {
372 			ne += n2;
373 			*quote = '"';
374 			}
375 		else {
376 			ne += n1;
377 			*quote = '\'';
378 			}
379 		*widthp -= ne + 2;
380 		}
381 	else if ((*s0 == '.' && s - s0 == 1) || valid_param(s0,1)) {
382  quote_it:
383 		*widthp -= 2;
384 		*quote = '\'';
385 		}
386 	}
387 #endif /*QUOTIFY*/ /*}*/
388 
389 #define put(x) { *outbuf++ = x; if (outbuf == obe) outbuf = (*fput)(f,&rv); }
390 
391  static int
x_sprintf(char * obe,Putfunc fput,Finfo * f,const char * fmt,va_list ap)392 x_sprintf(char *obe, Putfunc fput, Finfo *f, const char *fmt, va_list ap)
393 {
394 	char *digits, *ob0, *outbuf, *s, *se;
395 	Const char *fmt0;
396 	char buf[32], sbuf[400];
397 	double x;
398 	int alt, base, c, decpt, dot, conv, i1, k, lead0, left,
399 		len, prec, prec1, psign, rv, sgn, sign, width;
400 #ifdef QUOTIFY
401 	int quote;
402 #endif /*QUOTIFY*/
403 	long sl;
404 	short sh;
405 	size_t Ltmp, *ip, j, u;
406 	ssize_t i;
407 	unsigned int ui;
408 	unsigned long ul;
409 	unsigned short us;
410 #ifndef NO_PRINTF_A_FMT /*{*/
411 #ifdef IEEE_8087 /*{{*/
412 #define I0 1
413 #define I1 0
414 #else /*}{*/
415 #ifdef IEEE_MC68k /*{{*/
416 #define I0 0
417 #define I1 1
418 #else /*}{*/
419 #define NO_PRINTF_A_FMT
420 #endif /*}} IEEE_MC68k */
421 #endif /*}} IEEE_8087  */
422 #ifndef NO_PRINTF_A_FMT
423 	typedef union U { double d; unsigned int u[2]; } U;
424 	U uu;
425 	int bex, bw;
426 #endif
427 #endif /*} NO_PRINTF_A_FMT */
428 	static char hex[] = "0123456789abcdefpx";
429 	static char Hex[] = "0123456789ABCDEFPX";
430 	static char NullStr[] = "<NULL>";
431 
432 	ob0 = outbuf = f->ob0;
433 	i = rv = 0;
434 	for(;;) {
435 		for(;;) {
436 			switch(c = *fmt++) {
437 				case 0:
438 					goto done;
439 				case '%':
440 					break;
441 				default:
442 					put(c)
443 					continue;
444 				}
445 			break;
446 			}
447 #ifdef QUOTIFY
448 		quote =
449 #endif /*QUOTIFY*/
450 		alt=dot=lead0=left=len=prec=psign=sign=width=0;
451 		fmt0 = fmt;
452  fmtloop:
453 		switch(conv = *fmt++) {
454 			case ' ':
455 			case '+':
456 				sign = conv;
457 				goto fmtloop;
458 			case '-':
459 				if (dot)
460 					psign = 1;
461 				else
462 					left = 1;
463 				goto fmtloop;
464 			case '#':
465 				alt = 1;
466 				goto fmtloop;
467 			case '0':
468 				if (!lead0 && !dot) {
469 					lead0 = 1;
470 					goto fmtloop;
471 					}
472 			case '1':
473 			case '2':
474 			case '3':
475 			case '4':
476 			case '5':
477 			case '6':
478 			case '7':
479 			case '8':
480 			case '9':
481 				k = conv - '0';
482 				while((c = *fmt) >= '0' && c <= '9') {
483 					k = 10*k + c - '0';
484 					fmt++;
485 					}
486 				if (dot)
487 					prec = psign ? -k : k;
488 				else
489 					width = k;
490 				goto fmtloop;
491 			case 'h':
492 				len = 2;
493 				goto fmtloop;
494 			case 'l':
495 				len = 1;
496 				goto fmtloop;
497 			case 'z':
498 				len = 3;
499 				goto fmtloop;
500 			case '.':
501 				dot = 1;
502 				goto fmtloop;
503 			case '*':
504 				k = va_arg(ap, int);
505 				if (dot)
506 					prec = k;
507 				else {
508 					if (k < 0) {
509 						sign = '-';
510 						k = -k;
511 						}
512 					width = k;
513 					}
514 				goto fmtloop;
515 			case 'c':
516 				c = va_arg(ap, int);
517 				if (width > 1 && !left) {
518 					while(--width >= 1)
519 						put(' ');
520 					}
521 				put(c)
522 				if (width > 1) {
523 					while(--width >= 1)
524 						put(' ');
525 					}
526 				continue;
527 			case '%':
528 				put(conv)
529 				continue;
530 			case 'u':
531 				switch(len) {
532 				  case 0:
533 					ui = va_arg(ap, int);
534 					i = ui;
535 					break;
536 				  case 1:
537 					sl = va_arg(ap, long);
538 					i = sl;
539 					break;
540 				  case 2:
541 					us = va_arg(ap, int);
542 					i = us;
543 					break;
544 				  case 3:
545 					i = va_arg(ap, size_t);
546 				  }
547 				sign = 0;
548 				goto have_i;
549 			case 'i':
550 			case 'd':
551 				switch(len) {
552 				  case 0:
553 					k = va_arg(ap, int);
554 					i = k;
555 					break;
556 				  case 1:
557 					sl = va_arg(ap, long);
558 					i = sl;
559 					break;
560 				  case 2:
561 					sh = va_arg(ap, int);
562 					i = sh;
563 					break;
564 				  case 3:
565 					i = va_arg(ap, ssize_t);
566 				  }
567 				if (i < 0) {
568 					sign = '-';
569 					i = -i;
570 					}
571  have_i:
572 				base = 10;
573 				u = i;
574 				digits = hex;
575  baseloop:
576 				if (dot)
577 					lead0 = 0;
578 				s = buf;
579 				if (!u)
580 					alt = 0;
581 				do {
582 					j = ULDIV(u, base);
583 					*s++ = digits[u - base*j];
584 					}
585 					while((u = j));
586 				prec -= c = s - buf;
587 				if (alt && conv == 'o' && prec <= 0)
588 					prec = 1;
589 				if ((width -= c) > 0) {
590 					if (prec > 0)
591 						width -= prec;
592 					if (sign)
593 						width--;
594 					if (alt == 2)
595 						width--;
596 					}
597 				if (left) {
598 					if (alt == 2)
599 						put('0') /* for 0x */
600 					if (sign)
601 						put(sign)
602 					while(--prec >= 0)
603 						put('0')
604 					do put(*--s)
605 						while(s > buf);
606 					while(--width >= 0)
607 						put(' ')
608 					continue;
609 					}
610 				if (width > 0) {
611 					if (lead0) {
612 						if (alt == 2)
613 							put('0')
614 						if (sign)
615 							put(sign)
616 						while(--width >= 0)
617 							put('0')
618 						goto s_loop;
619 						}
620 					else
621 						while(--width >= 0)
622 							put(' ')
623 					}
624 				if (alt == 2)
625 					put('0')
626 				if (sign)
627 					put(sign)
628  s_loop:
629 				while(--prec >= 0)
630 					put('0')
631 				do put(*--s)
632 					while(s > buf);
633 				continue;
634 			case 'n':
635 				ip = va_arg(ap, size_t*);
636 				if (!ip)
637 					ip = &Ltmp;
638 				c = outbuf - ob0 + rv;
639 				switch(len) {
640 				  case 0:
641 					*(int*)ip = c;
642 					break;
643 				  case 1:
644 					*(long*)ip = c;
645 					break;
646 				  case 2:
647 					*(short*)ip = c;
648 					break;
649 				  case 3:
650 					*ip = c;
651 				  }
652 				break;
653 			case 'p':
654 				len = alt = 1;
655 				/* no break */
656 			case 'x':
657 				digits = hex;
658 				goto more_x;
659 			case 'X':
660 				digits = Hex;
661  more_x:
662 				if (alt) {
663 					alt = 2;
664 					sign = conv;
665 					}
666 				else
667 					sign = 0;
668 				base = 16;
669  get_u:
670 				switch(len) {
671 				  case 0:
672 					ui = va_arg(ap, int);
673 					u = ui;
674 					break;
675 				  case 1:
676 					ul = va_arg(ap, long);
677 					u = ul;
678 					break;
679 				  case 2:
680 					us = va_arg(ap, int);
681 					u = us;
682 					break;
683 				  case 3:
684 					u = va_arg(ap, size_t);
685 				  }
686 				if (!u)
687 					sign = alt = 0;
688 				goto baseloop;
689 			case 'o':
690 				base = 8;
691 				digits = hex;
692 				goto get_u;
693 #ifdef QUOTIFY
694 			case 'Q':
695 				conv = 'q';
696 				quote = '\'';
697 			case 'q':
698 #endif /*QUOTIFY*/
699 			case 's':
700 				s = va_arg(ap, char*);
701 				if (!s)
702 					s = NullStr;
703 				if (prec < 0)
704 					prec = 0;
705  have_s:
706 				if (dot) {
707 					for(c = 0; c < prec; c++)
708 						if (!s[c])
709 							break;
710 					prec = c;
711 					}
712 				else
713 					prec = strlen(s);
714 				width -= prec;
715 #ifdef QUOTIFY
716 				if (conv == 'q')
717 					qkind(s,prec,&quote,&width);
718 #endif /*QUOTIFY*/
719 				if (!left)
720 					while(--width >= 0)
721 						put(' ')
722 #ifdef QUOTIFY
723 				if (quote) {
724 					put(quote)
725 					while(--prec >= 0) {
726 						if ((c = *s++) == quote)
727 							put(quote)
728 						else if (c == '\n')
729 							put('\\')
730 						put(c)
731 						}
732 					put(quote)
733 					}
734 				else
735 #endif /*QUOTIFY*/
736 				while(--prec >= 0)
737 					put(*s++)
738 				while(--width >= 0)
739 					put(' ')
740 				continue;
741 			case 'f':
742 				if (!dot)
743 					prec = 6;
744 				x = va_arg(ap, double);
745  infnan:
746 				s = dtoa_r(x, 3, prec, &decpt, &sgn, &se, sbuf, sizeof(sbuf));
747 				if (decpt == 9999) {
748  fmt9999:
749 					dot = prec = alt = 0;
750 					if (*s == 'N')
751 						goto have_s;
752 					decpt = strlen(s);
753 					}
754  f_fmt:
755 				if (sgn && (x||sign))
756 					sign = '-';
757 				if (prec > 0)
758 					width -= prec;
759 				if (width > 0) {
760 					if (sign)
761 						--width;
762 					if (decpt <= 0) {
763 						--width;
764 						if (prec > 0)
765 							--width;
766 						}
767 					else {
768 						if (s == se)
769 							decpt = 1;
770 						width -= decpt;
771 						if (prec > 0 || alt)
772 							--width;
773 						}
774 					}
775 				if (width > 0 && !left) {
776 					if (lead0) {
777 						if (sign)
778 							put(sign)
779 						sign = 0;
780 						do put('0')
781 							while(--width > 0);
782 						}
783 					else do put(' ')
784 						while(--width > 0);
785 					}
786 				if (sign)
787 					put(sign)
788 				if (decpt <= 0) {
789 					put('0')
790 					if (prec > 0 || alt)
791 						put('.')
792 					while(decpt < 0) {
793 						put('0')
794 						prec--;
795 						decpt++;
796 						}
797 					}
798 				else {
799 					do {
800 						if ((c = *s))
801 							s++;
802 						else
803 							c = '0';
804 						put(c)
805 						}
806 						while(--decpt > 0);
807 					if (prec > 0 || alt)
808 						put('.')
809 					}
810 				while(--prec >= 0) {
811 					if ((c = *s))
812 						s++;
813 					else
814 						c = '0';
815 					put(c)
816 					}
817 				while(--width >= 0)
818 					put(' ')
819 				continue;
820 			case 'G':
821 			case 'g':
822 				if (!dot)
823 					prec = 6;
824 				x = va_arg(ap, double);
825 				if (prec < 0)
826 					prec = 0;
827 				s = dtoa_r(x, prec ? 2 : 0, prec, &decpt,
828 					   &sgn, &se, sbuf, sizeof(sbuf));
829 				if (decpt == 9999)
830 					goto fmt9999;
831 				c = se - s;
832 				prec1 = prec;
833 				if (!prec) {
834 					prec = c;
835 					prec1 = c + (s[1] || alt ? 5 : 4);
836 					/* %.0g gives 10 rather than 1e1 */
837 					}
838 				if (decpt > -4 && decpt <= prec1) {
839 					if (alt)
840 						prec -= decpt;
841 					else
842 						prec = c - decpt;
843 					if (prec < 0)
844 						prec = 0;
845 					goto f_fmt;
846 					}
847 				conv -= 2;
848 				if (!alt && prec > c)
849 					prec = c;
850 				--prec;
851 				goto e_fmt;
852 			case 'e':
853 			case 'E':
854 				if (!dot)
855 					prec = 6;
856 				x = va_arg(ap, double);
857 				if (prec < 0)
858 					prec = 0;
859 				s = dtoa_r(x, 2, prec+1, &decpt,
860 					   &sgn, &se, sbuf, sizeof(sbuf));
861 				if (decpt == 9999)
862 					goto fmt9999;
863  e_fmt:
864 				if (sgn && (x||sign))
865 					sign = '-';
866 				if ((width -= prec + 5) > 0) {
867 					if (sign)
868 						--width;
869 					if (prec || alt)
870 						--width;
871 					}
872 				if ((c = --decpt) < 0)
873 					c = -c;
874 				while(c >= 100) {
875 					--width;
876 					c /= 10;
877 					}
878 				if (width > 0 && !left) {
879 					if (lead0) {
880 						if (sign)
881 							put(sign)
882 						sign = 0;
883 						do put('0')
884 							while(--width > 0);
885 						}
886 					else do put(' ')
887 						while(--width > 0);
888 					}
889 				if (sign)
890 					put(sign)
891 				put(*s++)
892 				if (prec || alt)
893 					put('.')
894 				while(--prec >= 0) {
895 					if ((c = *s))
896 						s++;
897 					else
898 						c = '0';
899 					put(c)
900 					}
901 				put(conv)
902 				if (decpt < 0) {
903 					put('-')
904 					decpt = -decpt;
905 					}
906 				else
907 					put('+')
908 				for(c = 2, k = 10; 10*k <= decpt; c++, k *= 10);
909 				for(;;) {
910 					i1 = decpt / k;
911 					put(i1 + '0')
912 					if (--c <= 0)
913 						break;
914 					decpt -= i1*k;
915 					decpt *= 10;
916 					}
917 				while(--width >= 0)
918 					put(' ')
919 				continue;
920 #ifndef NO_PRINTF_A_FMT
921 			case 'a':
922 				digits = hex;
923 				goto more_a;
924 			case 'A':
925 				digits = Hex;
926  more_a:
927 				uu.d = va_arg(ap, double);
928 				if ((uu.u[I0] & 0x7ff00000) == 0x7ff00000) {
929 					x = uu.d;
930 					goto infnan;
931 					}
932 				if (uu.d) {
933 					c = '1';
934 					if (uu.u[I0] & 0x80000000) {
935 						sign = '-';
936 						uu.u[I0] &= 0x7fffffff;
937 						}
938 					bex = (uu.u[I0] >> 20) - 1023;
939 					uu.u[I0] &= 0xfffff;
940 					if (bex == -1023) {
941 						++bex;
942 						if (uu.u[I0])
943 							do {
944 								--bex;
945 								uu.u[I0] <<= 1;
946 								if (uu.u[I1] & 0x80000000)
947 									uu.u[I0] |= 1;
948 								uu.u[I1] <<= 1;
949 								} while (uu.u[I0] < 0x100000);
950 						else {
951 							while(!(uu.u[I1] & 0x80000000)) {
952 								--bex;
953 								uu.u[I1] <<= 1;
954 								}
955 							bex -= 21;
956 							uu.u[I0] = uu.u[I1] >> 11;
957 							uu.u[I1] <<= 21;
958 							}
959 						}
960 					}
961 				else {
962 					c = '0';
963 					bex = 0;
964 					}
965 				if (dot) {
966 					if (prec > 13)
967 						prec = 13;
968 					if (uu.d && prec < 13) {
969 						uu.u[I0] |= 0x100000;
970 						if (prec < 5) {
971 						    ui = 1 << ((5-prec)*4 - 1);
972 						    if (uu.u[I0] & ui) {
973 							if (uu.u[I0] & ((ui-1) | (ui << 1))
974 							 || uu.u[I1]) {
975 							    uu.u[I0] += ui;
976  bex_check:
977 							    if (uu.u[I0] & 0x200000) {
978 								++bex;
979 								uu.u[I0] >>= 1;
980 								}
981 							    }
982 							}
983 						    }
984 						else if (prec == 5) {
985 						    if (uu.u[I1] & 0x80000000) {
986  u0_bump:
987 							++uu.u[I0];
988 							goto bex_check;
989 							}
990 						    }
991 						else {
992 						    i1 = (13 - prec) * 4;
993 						    ui = 1 << (i1 - 1);
994 						    if (uu.u[I1] & ui
995 						     && uu.u[I1] & ((ui-1) | (ui << 1))) {
996 							uu.u[I1] += ui;
997 							if (!(uu.u[I1] >> i1))
998 								goto u0_bump;
999 							}
1000 						    }
1001 						}
1002 					}
1003 				else {
1004 					if ((ui = uu.u[I1]))
1005 						for(prec = 6;
1006 							(ui = (ui << 4) & 0xffffffff);
1007 							++prec);
1008 					else
1009 						for(prec = 0, ui = uu.u[I0] & 0xfffff;
1010 							ui;
1011 							++prec, ui = (ui << 4) & 0xfffff);
1012 					}
1013 				bw = 1;
1014 				if (bex) {
1015 					if ((i1 = bex) < 0)
1016 						i1 = -i1;
1017 					while(i1 >= 10) {
1018 						++bw;
1019 						i1 /= 10;
1020 						}
1021 					}
1022 				if ((sgn = uu.u[I0] & 0x80000000)) {
1023 					uu.u[I0] &= 0x7fffffff;
1024 					if (uu.d||sign)
1025 						sign = '-';
1026 					}
1027 				if ((width -= bw + 5) > 0) {
1028 					if (sign)
1029 						--width;
1030 					if (prec || alt)
1031 						--width;
1032 					}
1033 				if (width > 0 && !left) {
1034 					if (lead0) {
1035 						if (sign) {
1036 							put(sign)
1037 							sign = 0;
1038 							}
1039 						do put('0')
1040 							while(--width > 0);
1041 						}
1042 					else do put(' ')
1043 						while(--width > 0);
1044 					}
1045 				if (sign)
1046 					put(sign)
1047 				put('0')
1048 				put(digits[17])
1049 				put(c)
1050 				if (prec > 0 || alt)
1051 					put('.')
1052 				if (prec > 0) {
1053 					if ((i1 = prec) > 5)
1054 						i1 = 5;
1055 					prec -= i1;
1056 					do {
1057 						put(digits[(uu.u[I0] >> 16) & 0xf])
1058 						uu.u[I0] <<= 4;
1059 						}
1060 						while(--i1 > 0);
1061 					while(prec > 0) {
1062 						--prec;
1063 						put(digits[(uu.u[I1] >> 28) & 0xf])
1064 						uu.u[I1] <<= 4;
1065 						}
1066 					}
1067 				put(digits[16])
1068 				if (bex < 0) {
1069 					put('-')
1070 					bex = -bex;
1071 					}
1072 				else
1073 					put('+')
1074 				for(c = 1; 10*c <= bex; c *= 10);
1075 				for(;;) {
1076 					i1 = bex / c;
1077 					put('0' + i1)
1078 					if (!--bw)
1079 						break;
1080 					bex -= i1 * c;
1081 					bex *= 10;
1082 					}
1083 				continue;
1084 #endif /* NO_PRINTF_A_FMT */
1085 			default:
1086 				put('%')
1087 				while(fmt0 < fmt)
1088 					put(*fmt0++)
1089 				continue;
1090 			}
1091 		}
1092  done:
1093 	*outbuf = 0;
1094 	return (f->lastlen = outbuf - ob0) + rv;
1095 	}
1096 
1097 #define Bsize 4096
1098 
1099  int
Printf(const char * fmt,...)1100 Printf(const char *fmt, ...)
1101 {
1102 	va_list ap;
1103 	int rv;
1104 	Finfo f;
1105 	char buf[Bsize];
1106 
1107 	va_start(ap, fmt);
1108 	f.u.cf = stdout;
1109 	f.ob0 = buf;
1110 	f.obe1 = buf + Bsize - 1;
1111 #ifdef _windows_
1112 	if (fileno(stdout) == stdout_fileno_ASL) {
1113 		rv = x_sprintf(f.obe1, Wput, &f, fmt, ap);
1114 		mwrite(buf, f.lastlen);
1115 		}
1116 	else
1117 #endif
1118 #ifdef PF_BUF
1119 	if (stdout == stderr_ASL) {
1120 		rv = x_sprintf(f.obe1, pfput, &f, fmt, ap);
1121 		pf_put(buf, f.lastlen);
1122 		}
1123 	else
1124 #endif
1125 		{
1126 		rv = x_sprintf(f.obe1, Fput, &f, fmt, ap);
1127 		fputs(buf, stdout);
1128 		}
1129 	va_end(ap);
1130 	return rv;
1131 	}
1132 
1133  static char *
Sput(Finfo * f,int * rvp)1134 Sput(Finfo *f, int *rvp)
1135 {
1136 	if (Printf("\nBUG! Sput called!\n", f, rvp))
1137 		/* pass vp, rvp and return 0 to shut diagnostics off */
1138 		exit(250);
1139 	return 0;
1140 	}
1141 
1142  int
Sprintf(char * s,const char * fmt,...)1143 Sprintf(char *s, const char *fmt, ...)
1144 {
1145 	va_list ap;
1146 	int rv;
1147 	Finfo f;
1148 
1149 	va_start(ap, fmt);
1150 	f.ob0 = s;
1151 	rv = x_sprintf(s, Sput, &f, fmt, ap);
1152 	va_end(ap);
1153 	return rv;
1154 	}
1155 
1156  int
Fprintf(FILE * F,const char * fmt,...)1157 Fprintf(FILE *F, const char *fmt, ...)
1158 {
1159 	va_list ap;
1160 	int rv;
1161 	Finfo f;
1162 	char buf[Bsize];
1163 
1164 	va_start(ap, fmt);
1165 	f.u.cf = F;
1166 	f.ob0 = buf;
1167 	f.obe1 = buf + Bsize - 1;
1168 #ifdef MESS
1169 	if (stdout_or_err(F)) {
1170 #ifdef _windows_
1171 		if (fileno(stdout) == stdout_fileno_ASL) {
1172 			rv = x_sprintf(f.obe1, Wput, &f, fmt, ap);
1173 			mwrite(buf, f.lastlen);
1174 			}
1175 		else
1176 #endif
1177 #ifdef PF_BUF
1178 		if (F == stderr_ASL) {
1179 			rv = x_sprintf(f.obe1, pfput, &f, fmt, ap);
1180 			pf_put(buf, f.lastlen);
1181 			}
1182 		else
1183 #endif
1184 			{
1185 			rv = x_sprintf(f.obe1, Fput, &f, fmt, ap);
1186 			fputs(buf, F);
1187 			}
1188 		}
1189 	else
1190 #endif /*MESS*/
1191 		{
1192 #ifdef PF_BUF
1193 		if (F == stderr_ASL) {
1194 			rv = x_sprintf(f.obe1, pfput, &f, fmt, ap);
1195 			pf_put(buf, f.lastlen);
1196 			}
1197 	else
1198 #endif
1199 			{
1200 			rv = x_sprintf(f.obe1, Fput, &f, fmt, ap);
1201 			fputs(buf, F);
1202 			}
1203 		}
1204 	va_end(ap);
1205 	return rv;
1206 	}
1207 
1208  int
Vsprintf(char * s,const char * fmt,va_list ap)1209 Vsprintf(char *s, const char *fmt, va_list ap)
1210 {
1211 	Finfo f;
1212 	return x_sprintf(f.ob0 = s, Sput, &f, fmt, ap);
1213 	}
1214 
1215  int
Vfprintf(FILE * F,const char * fmt,va_list ap)1216 Vfprintf(FILE *F, const char *fmt, va_list ap)
1217 {
1218 	char buf[Bsize];
1219 	int rv;
1220 	Finfo f;
1221 
1222 	f.u.cf = F;
1223 	f.ob0 = buf;
1224 	f.obe1 = buf + Bsize - 1;
1225 #ifdef MESS
1226 	if (stdout_or_err(F)) {
1227 #ifdef _windows_
1228 		if (fileno(stdout) == stdout_fileno_ASL) {
1229 			rv = x_sprintf(f.obe1, Wput, &f, fmt, ap);
1230 			mwrite(buf, f.lastlen);
1231 			}
1232 		else
1233 #endif
1234 #ifdef PF_BUF
1235 		if (F == stderr_ASL) {
1236 			rv = x_sprintf(f.obe1, pfput, &f, fmt, ap);
1237 			pf_put(buf, f.lastlen);
1238 			}
1239 		else
1240 #endif
1241 			{
1242 			rv = x_sprintf(f.obe1, Fput, &f, fmt, ap);
1243 			fputs(buf, F);
1244 			}
1245 		}
1246 	else
1247 #endif /*MESS*/
1248 		{
1249 #ifdef PF_BUF
1250 		if (F == stderr_ASL) {
1251 			rv = x_sprintf(f.obe1, pfput, &f, fmt, ap);
1252 			pf_put(buf, f.lastlen);
1253 			}
1254 		else
1255 #endif
1256 			{
1257 			rv = x_sprintf(f.obe1, Fput, &f, fmt, ap);
1258 			fputs(buf, F);
1259 			}
1260 		}
1261 	va_end(ap);
1262 	return rv;
1263 	}
1264 
1265  void
Perror(const char * s)1266 Perror(const char *s)
1267 {
1268 	if (s && *s)
1269 		Fprintf(Stderr, "%s: ", s);
1270 	Fprintf(Stderr, "%s\n", strerror(errno));
1271 	}
1272 
1273  static char *
Snput(Finfo * f,int * rvp)1274 Snput(Finfo *f, int *rvp)
1275 {
1276 	char *s, *s0;
1277 	size_t L;
1278 
1279 	*rvp += Bsize;
1280 	s0 = f->ob0;
1281 	s = f->u.sf;
1282 	if ((L = f->obe1 - s) > Bsize) {
1283 		L = Bsize;
1284 		goto copy;
1285 		}
1286 	if (L > 0) {
1287  copy:
1288 		memcpy(s, s0, L);
1289 		f->u.sf = s + L;
1290 		}
1291 	return s0;
1292 	}
1293 
1294  int
Vsnprintf(char * s,size_t n,const char * fmt,va_list ap)1295 Vsnprintf(char *s, size_t n, const char *fmt, va_list ap)
1296 {
1297 	Finfo f;
1298 	char buf[Bsize];
1299 	int L, rv;
1300 
1301 	if (n <= 0 || !s) {
1302 		n = 1;
1303 		s = buf;
1304 		}
1305 	f.u.sf = s;
1306 	f.ob0 = buf;
1307 	f.obe1 = s + n - 1;
1308 	rv = x_sprintf(buf + Bsize, Snput, &f, fmt, ap);
1309 	if (f.lastlen > (L = f.obe1 - f.u.sf))
1310 		f.lastlen = L;
1311 	if (f.lastlen > 0) {
1312 		memcpy(f.u.sf, buf, f.lastlen);
1313 		f.u.sf += f.lastlen;
1314 		}
1315 	*f.u.sf = 0;
1316 	return rv;
1317 	}
1318  int
Snprintf(char * s,size_t n,const char * fmt,...)1319 Snprintf(char *s, size_t n, const char *fmt, ...)
1320 {
1321 	int rv;
1322 	va_list ap;
1323 
1324 	va_start(ap, fmt);
1325 	rv = Vsnprintf(s, n, fmt, ap);
1326 	va_end(ap);
1327 	return rv;
1328 	}
1329 
1330 
1331 #ifdef __cplusplus
1332 }
1333 #endif
1334