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,"e,&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