]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/gdtoa/printf.c0
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / gdtoa / printf.c0
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 #ifdef KR_headers
32 #include "varargs.h"
33 #else
34 #include "stddef.h"
35 #include "stdarg.h"
36 #include "stdlib.h"
37 #endif
38
39 #ifdef Use_GDTOA_for_i386_long_double /*{{*/
40 #include "gdtoa.h"
41 #else /*}{*/
42 #ifndef NO_PRINTF_A_FMT /*{*/
43 #include "gdtoa.h"
44 #endif /*}*/
45 #endif /*}}*/
46
47 #ifdef __i386
48 #define NO_GDTOA_i386_Quad
49 #endif
50
51 #ifdef Use_GDTOA_for_i386_long_double /*{*/
52 #ifndef NO_GDTOA_i386_Quad /*{*/
53 #define GDTOA_both
54 #define Use_GDTOA_Qtype
55 #ifdef __ICC__ /* or __INTEL_COMPILER__ or __INTEL_COMPILER ?? */
56 #define GDTOA_Qtype _Quad
57 #else
58 #define GDTOA_Qtype __float128
59 #endif
60 #endif /*} NO_GDTOA_i386_Quad */
61 #endif /*} Use_GDTOA_for_i386_long_double */
62
63 #ifdef Use_GDTOA_Qtype /*{*/
64 #ifndef GDTOA_H_INCLUDED
65 #include "gdtoa.h"
66 #endif
67 #ifndef GDTOA_Qtype
68 #define GDTOA_Qtype long double
69 #endif
70 #endif /*}*/
71
72 #ifndef GDTOA_H_INCLUDED /*{*/
73
74  enum { /* return values from strtodg */
75         STRTOG_Zero     = 0,
76         STRTOG_Normal   = 1,
77         STRTOG_Denormal = 2,
78         STRTOG_Infinite = 3,
79         STRTOG_NaN      = 4,
80         STRTOG_NaNbits  = 5,
81         STRTOG_NoNumber = 6,
82         STRTOG_Retmask  = 7};
83
84  typedef struct
85 FPI {
86         int nbits;
87         int emin;
88         int emax;
89         int rounding;
90         int sudden_underflow;
91         } FPI;
92
93 enum {  /* FPI.rounding values: same as FLT_ROUNDS */
94         FPI_Round_zero = 0,
95         FPI_Round_near = 1,
96         FPI_Round_up = 2,
97         FPI_Round_down = 3
98         };
99 #endif /*}*/
100
101 #ifdef NO_PRINTF_A_FMT /*{{*/
102 #define WANT_A_FMT(x) /*nothing*/
103 #else /*}{*/
104 #define WANT_A_FMT(x) x
105 #endif /*}}*/
106
107 #include "stdio1.h"
108 #include "string.h"
109 #include "errno.h"
110
111  typedef struct
112 Finfo {
113         union { FILE *cf; char *sf; } u;
114         char *ob0, *obe1;
115         size_t lastlen;
116         } Finfo;
117
118  typedef char *(*pgdtoa) ANSI((FPI*, int be, ULong *bits, int *kind, int mode, int ndigits, int *decpt, char **rve));
119
120  typedef struct
121 FPBits {
122         ULong bits[4];  /* sufficient for quad; modify if considering wider types */
123         FPI *fpi;
124         pgdtoa gdtoa;
125         int sign;
126         int ex; /* exponent */
127         int kind;
128         } FPBits;
129
130  typedef union U
131 {
132         double d;
133         long double ld;
134 #ifdef GDTOA_Qtype
135         GDTOA_Qtype Qd;
136 #endif
137         unsigned int ui[4];
138         unsigned short us[5];
139         } U;
140
141  typedef char *(*Putfunc) ANSI((Finfo*, int*));
142  typedef void (*Fpbits) ANSI((U*, FPBits*));
143
144 /* Would have preferred typedef void (*Fpbits)(va_list*, FPBits*)
145  * but gcc is buggy in this regard.
146  */
147
148 #ifdef Use_GDTOA_for_i386_long_double /*{*/
149
150 #ifdef IEEE_MC68k
151 #define _0 0
152 #define _1 1
153 #define _2 2
154 #define _3 3
155 #define _4 4
156 #endif
157 #ifdef IEEE_8087
158 #define _0 4
159 #define _1 3
160 #define _2 2
161 #define _3 1
162 #define _4 0
163 #endif
164
165  static void
166 xfpbits(U *u, FPBits *b)
167 {
168         ULong *bits;
169         int ex, i;
170         static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0 };
171
172         b->fpi = &fpi0;
173         b->gdtoa = gdtoa;
174         b->sign = u->us[_0] & 0x8000;
175         bits = b->bits;
176         bits[1] = (u->us[_1] << 16) | u->us[_2];
177         bits[0] = (u->us[_3] << 16) | u->us[_4];
178         if ( (ex = u->us[_0] & 0x7fff) !=0) {
179                 i = STRTOG_Normal;
180                 if (ex == 0x7fff)
181                         /* Infinity or NaN */
182                         i = bits[0] | bits[1] ? STRTOG_NaN : STRTOG_Infinite;
183                 }
184         else if (bits[0] | bits[1]) {
185                 i = STRTOG_Denormal;
186                 ex = 1;
187                 }
188         else
189                 i = STRTOG_Zero;
190         b->kind = i;
191         b->ex = ex - (0x3fff + 63);
192         }
193
194 #undef _0
195 #undef _1
196 #undef _2
197 #undef _3
198 #undef _4
199 #define GDTOA_LD_fpbits xfpbits
200 #endif /*} Use_GDTOA_for_i386_long_double */
201
202 #ifdef Use_GDTOA_Qtype /*{*/
203 #include "gdtoa.h"
204 #ifndef GDTOA_Qtype
205 #define GDTOA_Qtype long double
206 #endif
207 #ifdef GDTOA_LD_fpbits
208 #define GDTOA_Q_fpbits Qfpbits
209 #else
210 #define GDTOA_LD_fpbits Qfpbits
211 #endif
212
213 #ifdef IEEE_MC68k
214 #define _0 0
215 #define _1 1
216 #define _2 2
217 #define _3 3
218 #endif
219 #ifdef IEEE_8087
220 #define _0 3
221 #define _1 2
222 #define _2 1
223 #define _3 0
224 #endif
225
226  static void
227 Qfpbits(U *u, FPBits *b)
228 {
229         ULong *bits;
230         int ex, i;
231         static FPI fpi0 = { 113, 1-16383-113+1, 32766 - 16383 - 113 + 1, 1, 0 };
232
233         b->fpi = &fpi0;
234         b->gdtoa = gdtoa;
235         b->sign = u->ui[_0] & 0x80000000L;
236         bits = b->bits;
237         bits[3] = u->ui[_0] & 0xffff;
238         bits[2] = u->ui[_1];
239         bits[1] = u->ui[_2];
240         bits[0] = u->ui[_3];
241         if ( (ex = (u->ui[_0] & 0x7fff0000L) >> 16) !=0) {
242                 if (ex == 0x7fff) {
243                         /* Infinity or NaN */
244                         i = bits[0] | bits[1] | bits[2] | bits[3]
245                                 ? STRTOG_NaN : STRTOG_Infinite;
246                         }
247                 else {
248                         i = STRTOG_Normal;
249                         bits[3] |= 0x10000;
250                         }
251                 }
252         else if (bits[0] | bits[1] | bits[2] | bits[3]) {
253                 i = STRTOG_Denormal;
254                 ex = 1;
255                 }
256         else
257                 i = STRTOG_Zero;
258         b->kind = i;
259         b->ex = ex - (0x3fff + 112);
260         }
261
262 #undef _0
263 #undef _1
264 #undef _2
265 #undef _3
266 #endif /*} GDTOA_Qtype */
267
268 #ifdef KR_headers
269 #define Const /* const */
270 #define Voidptr char*
271 #ifndef size_t__
272 #define size_t int
273 #define size_t__
274 #endif
275
276 #else
277
278 #define Const const
279 #define Voidptr void*
280
281 #endif
282
283 #undef MESS
284 #ifndef Stderr
285 #define Stderr stderr
286 #endif
287
288 #ifdef _windows_
289 #undef PF_BUF
290 #define MESS
291 #include "mux0.h"
292 #define stdout_or_err(f) (f == stdout)
293 #else
294 #define stdout_or_err(f) (f == Stderr || f == stdout)
295 #endif
296
297 #ifdef __cplusplus
298 extern "C" {
299 #endif
300
301  extern char *dtoa ANSI((double, int, int, int*, int*, char **));
302  extern void freedtoa ANSI((char*));
303
304
305
306 #ifdef USE_ULDIV
307 /* This is for avoiding 64-bit divisions on the DEC Alpha, since */
308 /* they are not portable among variants of OSF1 (DEC's Unix). */
309
310 #define ULDIV(a,b) uldiv_ASL(a,(unsigned long)(b))
311
312 #ifndef LLBITS
313 #define LLBITS 6
314 #endif
315 #ifndef ULONG
316 #define ULONG unsigned long
317 #endif
318
319  static int
320 klog(ULONG x)
321 {
322         int k, rv = 0;
323
324         if (x > 1L)
325             for(k = 1 << LLBITS-1;;) {
326                 if (x >= (1L << k)) {
327                         rv |= k;
328                         x >>= k;
329                         }
330                 if (!(k >>= 1))
331                         break;
332                 }
333         return rv;
334         }
335
336  ULONG
337 uldiv_ASL(ULONG a, ULONG b)
338 {
339         int ka;
340         ULONG c, k;
341         static ULONG b0;
342         static int kb;
343
344         if (a < b)
345                 return 0;
346         if (b != b0) {
347                 b0 = b;
348                 kb = klog(b);
349                 }
350         k = 1;
351         if ((ka = klog(a) - kb) > 0) {
352                 k <<= ka;
353                 b <<= ka;
354                 }
355         c = 0;
356         for(;;) {
357                 if (a >= b) {
358                         a -= b;
359                         c |= k;
360                         }
361                 if (!(k >>= 1))
362                         break;
363                 a <<= 1;
364                 }
365         return c;
366         }
367
368 #else
369 #define ULDIV(a,b) a / b
370 #endif /* USE_ULDIV */
371
372 #ifdef PF_BUF
373 FILE *stderr_ASL = (FILE*)&stderr_ASL;
374 void (*pfbuf_print_ASL) ANSI((char*));
375 char *pfbuf_ASL;
376 static char *pfbuf_next;
377 static size_t pfbuf_len;
378 extern Char *mymalloc_ASL ANSI((size_t));
379 extern Char *myralloc_ASL ANSI((void *, size_t));
380
381 #undef fflush
382 #ifdef old_fflush_ASL
383 #define fflush old_fflush_ASL
384 #endif
385
386  void
387 fflush_ASL(FILE *f)
388 {
389         if (f == stderr_ASL) {
390                 if (pfbuf_ASL && pfbuf_print_ASL) {
391                         (*pfbuf_print_ASL)(pfbuf_ASL);
392                         free(pfbuf_ASL);
393                         pfbuf_ASL = 0;
394                         }
395                 }
396         else
397                 fflush(f);
398         }
399
400  static void
401 pf_put(char *buf, int len)
402 {
403         size_t x, y;
404         if (!pfbuf_ASL) {
405                 x = len + 256;
406                 if (x < 512)
407                         x = 512;
408                 pfbuf_ASL = pfbuf_next = (char*)mymalloc_ASL(pfbuf_len = x);
409                 }
410         else if ((y = (pfbuf_next - pfbuf_ASL) + len) >= pfbuf_len) {
411                 x = pfbuf_len;
412                 while((x <<= 1) <= y);
413                 y = pfbuf_next - pfbuf_ASL;
414                 pfbuf_ASL = (char*)myralloc_ASL(pfbuf_ASL, x);
415                 pfbuf_next = pfbuf_ASL + y;
416                 pfbuf_len = x;
417                 }
418         memcpy(pfbuf_next, buf, len);
419         pfbuf_next += len;
420         *pfbuf_next = 0;
421         }
422
423  static char *
424 pfput(Finfo *f, int *rvp)
425 {
426         int n;
427         char *ob0 = f->ob0;
428         *rvp += n = (int)(f->obe1 - ob0);
429         pf_put(ob0, n);
430         return ob0;
431         }
432 #endif /* PF_BUF */
433
434  static char *
435 Fput
436 #ifdef KR_headers
437         (f, rvp) Finfo *f; int *rvp;
438 #else
439         (Finfo *f, int *rvp)
440 #endif
441 {
442         char *ob0 = f->ob0;
443
444         *rvp += f->obe1 - ob0;
445         *f->obe1 = 0;
446         fputs(ob0, f->u.cf);
447         return ob0;
448         }
449
450
451 #ifdef _windows_
452 int stdout_fileno_ASL = 1;
453
454  static char *
455 Wput
456 #ifdef KR_headers
457         (f, rvp) Finfo *f; int *rvp;
458 #else
459         (Finfo *f, int *rvp)
460 #endif
461 {
462         char *ob0 = f->ob0;
463
464         *rvp += f->obe1 - ob0;
465         *f->obe1 = 0;
466         mwrite(ob0, f->obe1 - ob0);
467         return ob0;
468         }
469 #endif /*_windows_*/
470
471
472 #ifdef IEEE_MC68k
473 #define _0 0
474 #define _1 1
475 #endif
476 #ifdef IEEE_8087
477 #define _0 1
478 #define _1 0
479 #endif
480
481  static void
482 dfpbits(U *u, FPBits *b)
483 {
484         ULong *bits;
485         int ex, i;
486         static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, 0 };
487
488         b->fpi = &fpi0;
489         b->gdtoa = gdtoa;
490         b->sign = u->ui[_0] & 0x80000000L;
491         bits = b->bits;
492         bits[1] = u->ui[_0] & 0xfffff;
493         bits[0] = u->ui[_1];
494         if ( (ex = (u->ui[_0] & 0x7ff00000L) >> 20) !=0) {
495                 if (ex == 0x7ff) {
496                         /* Infinity or NaN */
497                         i = bits[0] | bits[1] ? STRTOG_NaN : STRTOG_Infinite;
498                         }
499                 else {
500                         i = STRTOG_Normal;
501                         bits[1] |= 0x100000;
502                         }
503                 }
504         else if (bits[0] | bits[1]) {
505                 i = STRTOG_Denormal;
506                 ex = 1;
507                 }
508         else
509                 i = STRTOG_Zero;
510         b->kind = i;
511         b->ex = ex - (0x3ff + 52);
512         }
513
514 #undef _0
515 #undef _1
516
517 #ifdef Honor_FLT_ROUNDS /*{{*/
518 #ifdef Trust_FLT_ROUNDS /*{{*/
519 #define RoundCheck if (Rounding == -1) Rounding = Flt_Rounds; if (Rounding != 1){\
520         fpi1 = *fpb.fpi; fpi1.rounding = Rounding; fpb.fpi = &fpi1;}
521 #else /*}{*/
522 #define RoundCheck if (Rounding == -1) { Rounding = 1; switch((fegetround()) {\
523           case FE_TOWARDZERO:   Rounding = 0; break;\
524           case FE_UPWARD:       Rounding = 2; break;\
525           case FE_DOWNWARD:     Rounding = 3; }}\
526         if (Rounding != 1){\
527         fpi1 = *fpb.fpi; fpi1.rounding = Rounding; fpb.fpi = &fpi1;}
528 #endif /*}}*/
529 #else /*}{*/
530 #define RoundCheck /*nothing*/
531 #endif /*}}*/
532
533 #ifndef NO_PRINTF_A_FMT /*{*/
534  static int
535 fpiprec(FPBits *b)      /* return number of hex digits minus 1, or 0 for zero */
536 {
537         FPI *fpi;
538         ULong *bits;
539         int i, j, k, m;
540
541         if (b->kind == STRTOG_Zero)
542                 return b->ex = 0;
543         fpi = b->fpi;
544         bits = b->bits;
545         for(k = (fpi->nbits - 1) >> 2; k > 0; --k)
546                 if ((bits[k >> 3] >> 4*(k & 7)) & 0xf) {
547                         m = k >> 3;
548                         for(i = 0; i <= m; ++i)
549                                 if (bits[i]) {
550                                         if (i > 0) {
551                                                 k -= 8*i;
552                                                 b->ex += 32*i;
553                                                 for(j = i; j <= m; ++j)
554                                                         bits[j-i] = bits[j];
555                                                 }
556                                         break;
557                                         }
558                         for(i = 0; i < 28 && !((bits[0] >> i) & 0xf); i += 4);
559                         if (i) {
560                                 b->ex += i;
561                                 m = k >> 3;
562                                 k -= (i >> 2);
563                                 for(j = 0;;++j) {
564                                         bits[j] >>= i;
565                                         if (j == m)
566                                                 break;
567                                         bits[j] |= bits[j+1] << (32 - i);
568                                         }
569                                 }
570                         break;
571                         }
572         return k;
573         }
574
575  static int
576 bround(FPBits *b, int prec, int prec1)  /* round to prec hex digits after the "." */
577 {                                       /* prec1 = incoming precision (after ".") */
578         FPI *fpi = b->fpi;
579         ULong *bits, t;
580         int i, inc, j, k, m, n;
581 #ifdef Honor_FLT_ROUNDS
582         int rounding = fpi->rounding;
583
584         if (rounding > FPI_Round_near && b->sign)
585                 rounding = FPI_Round_up + FPI_Round_down - rounding;
586         if (rounding == FPI_Round_down)
587                 rounding = FPI_Round_zero;
588 #endif
589         m = prec1 - prec;
590         bits = b->bits;
591         inc = 0;
592 #ifdef Honor_FLT_ROUNDS
593         switch(rounding) {
594                 case FPI_Round_up:
595                         for(i = 0; i < m; i += 8)
596                                 if (bits[i>>3])
597                                         goto inc1;
598                         if ((j = i - m) > 0 && bits[(i-8)>>3] << j*4)
599                                 goto inc1;
600                         break;
601                 case FPI_Round_near:
602 #endif
603                         k = m - 1;
604                         if ((t = bits[k >> 3] >> (j = (k&7)*4)) & 8) {
605                                 if (t & 7)
606                                         goto inc1;
607                                 if (j && bits[k >> 3] << (32 - j))
608                                         goto inc1;
609                                 while(k >= 8) {
610                                         k -= 8;
611                                         if (bits[k>>3]) {
612  inc1:
613                                                 inc = 1;
614                                                 goto haveinc;
615                                                 }
616                                         }
617                                 }
618 #ifdef Honor_FLT_ROUNDS
619                 }
620 #endif
621  haveinc:
622         b->ex += m*4;
623         i = m >> 3;
624         k = prec1 >> 3;
625         j = i;
626         if ((n = 4*(m & 7)))
627                 for(;; ++j) {
628                         bits[j-i] = bits[j] >> n;
629                         if (j == k)
630                                 break;
631                         bits[j-i] |= bits[j+1] << (32-n);
632                         }
633         else
634                 for(;; ++j) {
635                         bits[j-i] = bits[j];
636                         if (j == k)
637                                 break;
638                         }
639         k = prec >> 3;
640         if (inc) {
641                 for(j = 0; !(++bits[j] & 0xffffffff); ++j);
642                 if (j > k) {
643  onebit:
644                         bits[0] = 1;
645                         b->ex += 4*prec;
646                         return 1;
647                         }
648                 if ((j = prec & 7) < 7 && bits[k] >> (j+1)*4)
649                         goto onebit;
650                 }
651         for(i = 0; !(bits[i >> 3] & (0xf << 4*(i&7))); ++i);
652         if (i) {
653                 b->ex += 4*i;
654                 prec -= i;
655                 j = i >> 3;
656                 i &= 7;
657                 i *= 4;
658                 for(m = j; ; ++m) {
659                         bits[m-j] = bits[m] >> i;
660                         if (m == k)
661                                 break;
662                         bits[m-j] |= bits[m+1] << (32 - i);
663                         }
664                 }
665         return prec;
666         }
667 #endif /*}NO_PRINTF_A_FMT*/
668
669 #define put(x) { *outbuf++ = x; if (outbuf == obe) outbuf = (*fput)(f,&rv); }
670
671  static int
672 x_sprintf
673 #ifdef KR_headers
674         (obe, fput, f, fmt, ap)
675         char *obe, *fmt; Finfo *f; Putfunc fput; va_list ap;
676 #else
677         (char *obe, Putfunc fput, Finfo *f, const char *fmt, va_list ap)
678 #endif
679 {
680         FPBits fpb;
681         Fpbits fpbits;
682         U u;
683         char *digits, *ob0, *outbuf, *s, *s0, *se;
684         Const char *fmt0;
685         char buf[32];
686         long i;
687         unsigned long j, ul;
688         double x;
689         int alt, base, c, decpt, dot, conv, i1, k, lead0, left,
690                 len, prec, prec1, psign, rv, sign, width;
691         long Ltmp, *ip;
692         short sh;
693         unsigned short us;
694         unsigned int ui;
695 #ifdef Honor_FLT_ROUNDS
696         FPI fpi1;
697         int Rounding = -1;
698 #endif
699 #ifndef NO_PRINTF_A_FMT /*{*/
700         int bex, bw;
701 #endif /*} NO_PRINTF_A_FMT */
702         static char hex[] = "0123456789abcdefpx";
703         static char Hex[] = "0123456789ABCDEFPX";
704
705         ob0 = outbuf = f->ob0;
706         rv = 0;
707         for(;;) {
708                 for(;;) {
709                         switch(c = *fmt++) {
710                                 case 0:
711                                         goto done;
712                                 case '%':
713                                         break;
714                                 default:
715                                         put(c)
716                                         continue;
717                                 }
718                         break;
719                         }
720                 alt=dot=lead0=left=len=prec=psign=sign=width=0;
721                 fpbits = dfpbits;
722                 fmt0 = fmt;
723  fmtloop:
724                 switch(conv = *fmt++) {
725                         case ' ':
726                         case '+':
727                                 sign = conv;
728                                 goto fmtloop;
729                         case '-':
730                                 if (dot)
731                                         psign = 1;
732                                 else
733                                         left = 1;
734                                 goto fmtloop;
735                         case '#':
736                                 alt = 1;
737                                 goto fmtloop;
738                         case '0':
739                                 if (!lead0 && !dot) {
740                                         lead0 = 1;
741                                         goto fmtloop;
742                                         }
743                         case '1':
744                         case '2':
745                         case '3':
746                         case '4':
747                         case '5':
748                         case '6':
749                         case '7':
750                         case '8':
751                         case '9':
752                                 k = conv - '0';
753                                 while((c = *fmt) >= '0' && c <= '9') {
754                                         k = 10*k + c - '0';
755                                         fmt++;
756                                         }
757                                 if (dot)
758                                         prec = psign ? -k : k;
759                                 else
760                                         width = k;
761                                 goto fmtloop;
762                         case 'h':
763                                 len = 2;
764                                 goto fmtloop;
765                         case 'L':
766 #ifdef GDTOA_LD_fpbits /*{*/
767                                 fpbits = GDTOA_LD_fpbits;
768 #ifdef GDTOA_Q_fpbits
769                                 if (*fmt == 'q') {
770                                         ++fmt;
771                                         fpbits = Qfpbits;
772                                         }
773 #endif
774 #endif /*}*/
775                                 goto fmtloop;
776                         case 'l':
777                                 len = 1;
778                                 goto fmtloop;
779                         case '.':
780                                 dot = 1;
781                                 goto fmtloop;
782                         case '*':
783                                 k = va_arg(ap, int);
784                                 if (dot)
785                                         prec = k;
786                                 else {
787                                         if (k < 0) {
788                                                 sign = '-';
789                                                 k = -k;
790                                                 }
791                                         width = k;
792                                         }
793                                 goto fmtloop;
794                         case 'c':
795                                 c = va_arg(ap, int);
796                                 put(c)
797                                 continue;
798                         case '%':
799                                 put(conv)
800                                 continue;
801                         case 'u':
802                                 switch(len) {
803                                   case 0:
804                                         ui = va_arg(ap, int);
805                                         i = ui;
806                                         break;
807                                   case 1:
808                                         i = va_arg(ap, long);
809                                         break;
810                                   case 2:
811                                         us = va_arg(ap, int);
812                                         i = us;
813                                   }
814                                 sign = 0;
815                                 goto have_i;
816                         case 'i':
817                         case 'd':
818                                 switch(len) {
819                                   case 0:
820                                         k = va_arg(ap, int);
821                                         i = k;
822                                         break;
823                                   case 1:
824                                         i = va_arg(ap, long);
825                                         break;
826                                   case 2:
827                                         sh = va_arg(ap, int);
828                                         i = sh;
829                                   }
830                                 if (i < 0) {
831                                         sign = '-';
832                                         i = -i;
833                                         }
834  have_i:
835                                 base = 10;
836                                 ul = i;
837                                 digits = hex;
838  baseloop:
839                                 if (dot)
840                                         lead0 = 0;
841                                 s = buf;
842                                 if (!ul)
843                                         alt = 0;
844                                 do {
845                                         j = ULDIV(ul, base);
846                                         *s++ = digits[ul - base*j];
847                                         }
848                                         while((ul = j));
849                                 prec -= c = s - buf;
850                                 if (alt && conv == 'o' && prec <= 0)
851                                         prec = 1;
852                                 if ((width -= c) > 0) {
853                                         if (prec > 0)
854                                                 width -= prec;
855                                         if (sign)
856                                                 width--;
857                                         if (alt == 2)
858                                                 width--;
859                                         }
860                                 if (left) {
861                                         if (alt == 2)
862                                                 put('0') /* for 0x */
863                                         if (sign)
864                                                 put(sign)
865                                         while(--prec >= 0)
866                                                 put('0')
867                                         do put(*--s)
868                                                 while(s > buf);
869                                         while(--width >= 0)
870                                                 put(' ')
871                                         continue;
872                                         }
873                                 if (width > 0) {
874                                         if (lead0) {
875                                                 if (alt == 2)
876                                                         put('0')
877                                                 if (sign)
878                                                         put(sign)
879                                                 while(--width >= 0)
880                                                         put('0')
881                                                 goto s_loop;
882                                                 }
883                                         else
884                                                 while(--width >= 0)
885                                                         put(' ')
886                                         }
887                                 if (alt == 2)
888                                         put('0')
889                                 if (sign)
890                                         put(sign)
891  s_loop:
892                                 while(--prec >= 0)
893                                         put('0')
894                                 do put(*--s)
895                                         while(s > buf);
896                                 continue;
897                         case 'n':
898                                 ip = va_arg(ap, long*);
899                                 if (!ip)
900                                         ip = &Ltmp;
901                                 c = outbuf - ob0 + rv;
902                                 switch(len) {
903                                   case 0:
904                                         *(int*)ip = c;
905                                         break;
906                                   case 1:
907                                         *ip = c;
908                                         break;
909                                   case 2:
910                                         *(short*)ip = c;
911                                   }
912                                 break;
913                         case 'p':
914                                 len = alt = 1;
915                                 /* no break */
916                         case 'x':
917                                 digits = hex;
918                                 goto more_x;
919                         case 'X':
920                                 digits = Hex;
921  more_x:
922                                 if (alt) {
923                                         alt = 2;
924                                         sign = conv;
925                                         }
926                                 else
927                                         sign = 0;
928                                 base = 16;
929  get_u:
930                                 switch(len) {
931                                   case 0:
932                                         ui = va_arg(ap, int);
933                                         ul = ui;
934                                         break;
935                                   case 1:
936                                         ul = va_arg(ap, long);
937                                         break;
938                                   case 2:
939                                         us = va_arg(ap, int);
940                                         ul = us;
941                                   }
942                                 if (!ul)
943                                         sign = alt = 0;
944                                 goto baseloop;
945                         case 'o':
946                                 base = 8;
947                                 digits = hex;
948                                 goto get_u;
949                         case 's':
950                                 s0 = 0;
951                                 s = va_arg(ap, char*);
952                                 if (!s)
953                                         s = "<NULL>";
954                                 if (prec < 0)
955                                         prec = 0;
956  have_s:
957                                 if (dot) {
958                                         for(c = 0; c < prec; c++)
959                                                 if (!s[c])
960                                                         break;
961                                         prec = c;
962                                         }
963                                 else
964                                         prec = strlen(s);
965                                 width -= prec;
966                                 if (!left)
967                                         while(--width >= 0)
968                                                 put(' ')
969                                 while(--prec >= 0)
970                                         put(*s++)
971                                 while(--width >= 0)
972                                         put(' ')
973                                 if (s0)
974                                         freedtoa(s0);
975                                 continue;
976                         case 'f':
977                                 if (!dot)
978                                         prec = 6;
979 #ifdef GDTOA_H_INCLUDED
980                                 if (fpbits == dfpbits) {
981 #endif
982                                 x = va_arg(ap, double);
983                                 s = s0 = dtoa(x, 3, prec, &decpt, &fpb.sign, &se);
984 #ifdef GDTOA_H_INCLUDED
985                                         }
986                                 else {
987 #ifdef GDTOA_both
988                                         if (fpbits == GDTOA_LD_fpbits)
989                                                 u.ld = va_arg(ap, long double);
990                                         else
991                                                 u.Qd = va_arg(ap, GDTOA_Qtype);
992 #else
993                                         u.ld = va_arg(ap, long double);
994 #endif
995                                         fpbits(&u, &fpb);
996                                         RoundCheck
997                                         s = s0 = fpb.gdtoa(fpb.fpi, fpb.ex, fpb.bits,
998                                                 &fpb.kind, 3, prec, &decpt, &se);
999                                         }
1000 #endif
1001                                 if (decpt == 9999) {
1002  fmt9999:
1003                                         dot = prec = alt = 0;
1004                                         if (*s == 'N')
1005                                                 goto have_s;
1006                                         decpt = strlen(s);
1007                                         }
1008  f_fmt:
1009                                 if (fpb.sign && (x||sign))
1010                                         sign = '-';
1011                                 if (prec > 0)
1012                                         width -= prec;
1013                                 if (width > 0) {
1014                                         if (sign)
1015                                                 --width;
1016                                         if (decpt <= 0) {
1017                                                 --width;
1018                                                 if (prec > 0)
1019                                                         --width;
1020                                                 }
1021                                         else {
1022                                                 if (s == se)
1023                                                         decpt = 1;
1024                                                 width -= decpt;
1025                                                 if (prec > 0 || alt)
1026                                                         --width;
1027                                                 }
1028                                         }
1029                                 if (width > 0 && !left) {
1030                                         if (lead0) {
1031                                                 if (sign)
1032                                                         put(sign)
1033                                                 sign = 0;
1034                                                 do put('0')
1035                                                         while(--width > 0);
1036                                                 }
1037                                         else do put(' ')
1038                                                 while(--width > 0);
1039                                         }
1040                                 if (sign)
1041                                         put(sign)
1042                                 if (decpt <= 0) {
1043                                         put('0')
1044                                         if (prec > 0 || alt)
1045                                                 put('.')
1046                                         while(decpt < 0) {
1047                                                 put('0')
1048                                                 prec--;
1049                                                 decpt++;
1050                                                 }
1051                                         }
1052                                 else {
1053                                         do {
1054                                                 if ((c = *s))
1055                                                         s++;
1056                                                 else
1057                                                         c = '0';
1058                                                 put(c)
1059                                                 }
1060                                                 while(--decpt > 0);
1061                                         if (prec > 0 || alt)
1062                                                 put('.')
1063                                         }
1064                                 while(--prec >= 0) {
1065                                         if ((c = *s))
1066                                                 s++;
1067                                         else
1068                                                 c = '0';
1069                                         put(c)
1070                                         }
1071                                 while(--width >= 0)
1072                                         put(' ')
1073                                 if (s0)
1074                                         freedtoa(s0);
1075                                 continue;
1076                         case 'G':
1077                         case 'g':
1078                                 if (!dot)
1079                                         prec = 6;
1080                                 if (prec < 0)
1081                                         prec = 0;
1082 #ifdef GDTOA_H_INCLUDED
1083                                 if (fpbits == dfpbits) {
1084 #endif
1085                                         x = va_arg(ap, double);
1086                                         s = s0 = dtoa(x, prec ? 2 : 0, prec, &decpt,
1087                                                 &fpb.sign, &se);
1088 #ifdef GDTOA_H_INCLUDED
1089                                         }
1090                                 else {
1091 #ifdef GDTOA_both
1092                                         if (fpbits == GDTOA_LD_fpbits)
1093                                                 u.ld = va_arg(ap, long double);
1094                                         else
1095                                                 u.Qd = va_arg(ap, GDTOA_Qtype);
1096 #else
1097                                         u.ld = va_arg(ap, long double);
1098 #endif
1099                                         fpbits(&u, &fpb);
1100                                         RoundCheck
1101                                         s = s0 = fpb.gdtoa(fpb.fpi, fpb.ex, fpb.bits,
1102                                                 &fpb.kind, prec ? 2 : 0, prec, &decpt, &se);
1103                                         }
1104 #endif
1105                                 if (decpt == 9999)
1106                                         goto fmt9999;
1107                                 c = se - s;
1108                                 prec1 = prec;
1109                                 if (!prec) {
1110                                         prec = c;
1111                                         prec1 = c + (s[1] || alt ? 5 : 4);
1112                                         /* %.0g gives 10 rather than 1e1 */
1113                                         }
1114                                 if (decpt > -4 && decpt <= prec1) {
1115                                         if (alt)
1116                                                 prec -= decpt;
1117                                         else
1118                                                 prec = c - decpt;
1119                                         if (prec < 0)
1120                                                 prec = 0;
1121                                         goto f_fmt;
1122                                         }
1123                                 conv -= 2;
1124                                 if (!alt && prec > c)
1125                                         prec = c;
1126                                 --prec;
1127                                 goto e_fmt;
1128                         case 'e':
1129                         case 'E':
1130                                 if (!dot)
1131                                         prec = 6;
1132                                 if (prec < 0)
1133                                         prec = 0;
1134 #ifdef GDTOA_H_INCLUDED
1135                                 if (fpbits == dfpbits) {
1136 #endif
1137                                         x = va_arg(ap, double);
1138                                         s = s0 = dtoa(x, prec ? 2 : 0, prec+1, &decpt,
1139                                                 &fpb.sign, &se);
1140 #ifdef GDTOA_H_INCLUDED
1141                                         }
1142                                 else {
1143 #ifdef GDTOA_both
1144                                         if (fpbits == GDTOA_LD_fpbits)
1145                                                 u.ld = va_arg(ap, long double);
1146                                         else
1147                                                 u.Qd = va_arg(ap, GDTOA_Qtype);
1148 #else
1149                                         u.ld = va_arg(ap, long double);
1150 #endif
1151                                         fpbits(&u, &fpb);
1152                                         RoundCheck
1153                                         s = s0 = fpb.gdtoa(fpb.fpi, fpb.ex, fpb.bits,
1154                                                 &fpb.kind, prec ? 2 : 0, prec, &decpt, &se);
1155                                         }
1156 #endif
1157                                 if (decpt == 9999)
1158                                         goto fmt9999;
1159  e_fmt:
1160                                 if (fpb.sign && (x||sign))
1161                                         sign = '-';
1162                                 if ((width -= prec + 5) > 0) {
1163                                         if (sign)
1164                                                 --width;
1165                                         if (prec || alt)
1166                                                 --width;
1167                                         }
1168                                 if ((c = --decpt) < 0)
1169                                         c = -c;
1170                                 while(c >= 100) {
1171                                         --width;
1172                                         c /= 10;
1173                                         }
1174                                 if (width > 0 && !left) {
1175                                         if (lead0) {
1176                                                 if (sign)
1177                                                         put(sign)
1178                                                 sign = 0;
1179                                                 do put('0')
1180                                                         while(--width > 0);
1181                                                 }
1182                                         else do put(' ')
1183                                                 while(--width > 0);
1184                                         }
1185                                 if (sign)
1186                                         put(sign)
1187                                 put(*s++)
1188                                 if (prec || alt)
1189                                         put('.')
1190                                 while(--prec >= 0) {
1191                                         if ((c = *s))
1192                                                 s++;
1193                                         else
1194                                                 c = '0';
1195                                         put(c)
1196                                         }
1197                                 put(conv)
1198                                 if (decpt < 0) {
1199                                         put('-')
1200                                         decpt = -decpt;
1201                                         }
1202                                 else
1203                                         put('+')
1204                                 for(c = 2, k = 10; 10*k <= decpt; c++, k *= 10);
1205                                 for(;;) {
1206                                         i1 = decpt / k;
1207                                         put(i1 + '0')
1208                                         if (--c <= 0)
1209                                                 break;
1210                                         decpt -= i1*k;
1211                                         decpt *= 10;
1212                                         }
1213                                 while(--width >= 0)
1214                                         put(' ')
1215                                 freedtoa(s0);
1216                                 continue;
1217 #ifndef NO_PRINTF_A_FMT
1218                         case 'a':
1219                                 digits = hex;
1220                                 goto more_a;
1221                         case 'A':
1222                                 digits = Hex;
1223  more_a:
1224 #ifdef GDTOA_H_INCLUDED /*{{*/
1225                                 if (fpbits == dfpbits)
1226                                         u.d = va_arg(ap, double);
1227 #ifdef GDTOA_both /*{*/
1228                                 else if (fpbits == GDTOA_LD_fpbits)
1229                                         u.ld = va_arg(ap, long double);
1230                                 else
1231                                         u.Qd = va_arg(ap, GDTOA_Qtype);
1232 #else
1233                                 else
1234                                         u.ld = va_arg(ap, long double);
1235 #endif /*}*/
1236 #else /*}{*/
1237                                 u.d = va_arg(ap, double);
1238 #endif /*}}*/
1239                                 fpbits(&u, &fpb);
1240                                 if (fpb.kind == STRTOG_Infinite) {
1241                                         s = "Infinity";
1242                                         s0 = 0;
1243                                         goto fmt9999;
1244                                         }
1245                                 if (fpb.kind == STRTOG_NaN) {
1246                                         s = "NaN";
1247                                         s0 = 0;
1248                                         goto fmt9999;
1249                                         }
1250                                 prec1 = fpiprec(&fpb);
1251                                 if (dot && prec < prec1)
1252                                         prec1 = bround(&fpb, prec, prec1);
1253                                 bw = 1;
1254                                 bex = fpb.ex + 4*prec1;
1255                                 if (bex) {
1256                                         if ((i1 = bex) < 0)
1257                                                 i1 = -i1;
1258                                         while(i1 >= 10) {
1259                                                 ++bw;
1260                                                 i1 /= 10;
1261                                                 }
1262                                         }
1263                                 if (fpb.sign && (sign || fpb.kind != STRTOG_Zero))
1264                                         sign = '-';
1265                                 if ((width -= bw + 5) > 0) {
1266                                         if (sign)
1267                                                 --width;
1268                                         if (prec1 || alt)
1269                                                 --width;
1270                                         }
1271                                 if ((width -= prec1) > 0 && !left && !lead0) {
1272                                         do put(' ')
1273                                                 while(--width > 0);
1274                                         }
1275                                 if (sign)
1276                                         put(sign)
1277                                 put('0')
1278                                 put(digits[17])
1279                                 if (lead0 && width > 0 && !left) {
1280                                         do put('0')
1281                                                 while(--width > 0);
1282                                         }
1283                                 i1 = prec1 & 7;
1284                                 k = prec1 >> 3;
1285                                 put(digits[(fpb.bits[k] >> 4*i1) & 0xf])
1286                                 if (prec1 > 0 || alt)
1287                                         put('.')
1288                                 if (prec1 > 0) {
1289                                         prec -= prec1;
1290                                         while(prec1 > 0) {
1291                                                 if (--i1 < 0) {
1292                                                         if (--k < 0)
1293                                                                 break;
1294                                                         i1 = 7;
1295                                                         }
1296                                                 put(digits[(fpb.bits[k] >> 4*i1) & 0xf])
1297                                                 --prec1;
1298                                                 }
1299                                         if (alt && prec > 0)
1300                                                 do put(0)
1301                                                         while(--prec > 0);
1302                                         }
1303                                 put(digits[16])
1304                                 if (bex < 0) {
1305                                         put('-')
1306                                         bex = -bex;
1307                                         }
1308                                 else
1309                                         put('+')
1310                                 for(c = 1; 10*c <= bex; c *= 10);
1311                                 for(;;) {
1312                                         i1 = bex / c;
1313                                         put('0' + i1)
1314                                         if (!--bw)
1315                                                 break;
1316                                         bex -= i1 * c;
1317                                         bex *= 10;
1318                                         }
1319                                 while(--width >= 0)
1320                                         put(' ')
1321                                 continue;
1322 #endif /* NO_PRINTF_A_FMT */
1323                         default:
1324                                 put('%')
1325                                 while(fmt0 < fmt)
1326                                         put(*fmt0++)
1327                                 continue;
1328                         }
1329                 }
1330  done:
1331         *outbuf = 0;
1332         return (f->lastlen = outbuf - ob0) + rv;
1333         }
1334
1335 #define Bsize 256
1336
1337  int
1338 Printf
1339 #ifdef KR_headers
1340         (va_alist)
1341  va_dcl
1342 {
1343         char *fmt;
1344
1345         va_list ap;
1346         int rv;
1347         Finfo f;
1348         char buf[Bsize];
1349
1350         va_start(ap);
1351         fmt = va_arg(ap, char*);
1352         /*}*/
1353 #else
1354         (const char *fmt, ...)
1355 {
1356         va_list ap;
1357         int rv;
1358         Finfo f;
1359         char buf[Bsize];
1360
1361         va_start(ap, fmt);
1362 #endif
1363         f.u.cf = stdout;
1364         f.ob0 = buf;
1365         f.obe1 = buf + Bsize - 1;
1366 #ifdef _windows_
1367         if (fileno(stdout) == stdout_fileno_ASL) {
1368                 rv = x_sprintf(f.obe1, Wput, &f, fmt, ap);
1369                 mwrite(buf, f.lastlen);
1370                 }
1371         else
1372 #endif
1373 #ifdef PF_BUF
1374         if (stdout == stderr_ASL) {
1375                 rv = x_sprintf(f.obe1, pfput, &f, fmt, ap);
1376                 pf_put(buf, f.lastlen);
1377                 }
1378         else
1379 #endif
1380                 {
1381                 rv = x_sprintf(f.obe1, Fput, &f, fmt, ap);
1382                 fputs(buf, stdout);
1383                 }
1384         va_end(ap);
1385         return rv;
1386         }
1387
1388  static char *
1389 Sput
1390 #ifdef KR_headers
1391         (f, rvp) Finfo *f; int *rvp;
1392 #else
1393         (Finfo *f, int *rvp)
1394 #endif
1395 {
1396         if (Printf("\nBUG! Sput called!\n", f, rvp))
1397                 /* pass vp, rvp and return 0 to shut diagnostics off */
1398                 exit(250);
1399         return 0;
1400         }
1401
1402  int
1403 Sprintf
1404 #ifdef KR_headers
1405         (va_alist)
1406  va_dcl
1407 {
1408         char *s, *fmt;
1409         va_list ap;
1410         int rv;
1411         Finfo f;
1412
1413         va_start(ap);
1414         s = va_arg(ap, char*);
1415         fmt = va_arg(ap, char*);
1416         /*}*/
1417 #else
1418         (char *s, const char *fmt, ...)
1419 {
1420         va_list ap;
1421         int rv;
1422         Finfo f;
1423
1424         va_start(ap, fmt);
1425 #endif
1426         f.ob0 = s;
1427         rv = x_sprintf(s, Sput, &f, fmt, ap);
1428         va_end(ap);
1429         return rv;
1430         }
1431
1432  int
1433 Fprintf
1434 #ifdef KR_headers
1435         (va_alist)
1436  va_dcl
1437 {
1438         FILE *F;
1439         char *s, *fmt;
1440         va_list ap;
1441         int rv;
1442         Finfo f;
1443         char buf[Bsize];
1444
1445         va_start(ap);
1446         F = va_arg(ap, FILE*);
1447         fmt = va_arg(ap, char*);
1448         /*}*/
1449 #else
1450         (FILE *F, const char *fmt, ...)
1451 {
1452         va_list ap;
1453         int rv;
1454         Finfo f;
1455         char buf[Bsize];
1456
1457         va_start(ap, fmt);
1458 #endif
1459         f.u.cf = F;
1460         f.ob0 = buf;
1461         f.obe1 = buf + Bsize - 1;
1462 #ifdef MESS
1463         if (stdout_or_err(F)) {
1464 #ifdef _windows_
1465                 if (fileno(stdout) == stdout_fileno_ASL) {
1466                         rv = x_sprintf(f.obe1, Wput, &f, fmt, ap);
1467                         mwrite(buf, f.lastlen);
1468                         }
1469                 else
1470 #endif
1471 #ifdef PF_BUF
1472                 if (F == stderr_ASL) {
1473                         rv = x_sprintf(f.obe1, pfput, &f, fmt, ap);
1474                         pf_put(buf, f.lastlen);
1475                         }
1476                 else
1477 #endif
1478                         {
1479                         rv = x_sprintf(f.obe1, Fput, &f, fmt, ap);
1480                         fputs(buf, F);
1481                         }
1482                 }
1483         else
1484 #endif /*MESS*/
1485                 {
1486 #ifdef PF_BUF
1487                 if (F == stderr_ASL) {
1488                         rv = x_sprintf(f.obe1, pfput, &f, fmt, ap);
1489                         pf_put(buf, f.lastlen);
1490                         }
1491         else
1492 #endif
1493                         {
1494                         rv = x_sprintf(f.obe1, Fput, &f, fmt, ap);
1495                         fputs(buf, F);
1496                         }
1497                 }
1498         va_end(ap);
1499         return rv;
1500         }
1501
1502  int
1503 Vsprintf
1504 #ifdef KR_headers
1505         (s, fmt, ap) char *s, *fmt; va_list ap;
1506 #else
1507         (char *s, const char *fmt, va_list ap)
1508 #endif
1509 {
1510         Finfo f;
1511         return x_sprintf(f.ob0 = s, Sput, &f, fmt, ap);
1512         }
1513
1514  int
1515 Vfprintf
1516 #ifdef KR_headers
1517         (F, fmt, ap) FILE *F; char *fmt; va_list ap;
1518 #else
1519         (FILE *F, const char *fmt, va_list ap)
1520 #endif
1521 {
1522         char buf[Bsize];
1523         int rv;
1524         Finfo f;
1525
1526         f.u.cf = F;
1527         f.ob0 = buf;
1528         f.obe1 = buf + Bsize - 1;
1529 #ifdef MESS
1530         if (stdout_or_err(F)) {
1531 #ifdef _windows_
1532                 if (fileno(stdout) == stdout_fileno_ASL) {
1533                         rv = x_sprintf(f.obe1, Wput, &f, fmt, ap);
1534                         mwrite(buf, f.lastlen);
1535                         }
1536                 else
1537 #endif
1538 #ifdef PF_BUF
1539                 if (F == stderr_ASL) {
1540                         rv = x_sprintf(f.obe1, pfput, &f, fmt, ap);
1541                         pf_put(buf, f.lastlen);
1542                         }
1543                 else
1544 #endif
1545                         {
1546                         rv = x_sprintf(f.obe1, Fput, &f, fmt, ap);
1547                         fputs(buf, F);
1548                         }
1549                 }
1550         else
1551 #endif /*MESS*/
1552                 {
1553 #ifdef PF_BUF
1554                 if (F == stderr_ASL) {
1555                         rv = x_sprintf(f.obe1, pfput, &f, fmt, ap);
1556                         pf_put(buf, f.lastlen);
1557                         }
1558                 else
1559 #endif
1560                         {
1561                         rv = x_sprintf(f.obe1, Fput, &f, fmt, ap);
1562                         fputs(buf, F);
1563                         }
1564                 }
1565         va_end(ap);
1566         return rv;
1567         }
1568
1569  void
1570 Perror
1571 #ifdef KR_headers
1572         (s) char *s;
1573 #else
1574         (const char *s)
1575 #endif
1576 {
1577         if (s && *s)
1578                 Fprintf(Stderr, "%s: ", s);
1579         Fprintf(Stderr, "%s\n", strerror(errno));
1580         }
1581
1582  static char *
1583 Snput
1584 #ifdef KR_headers
1585         (f, rvp) Finfo *f; int *rvp;
1586 #else
1587         (Finfo *f, int *rvp)
1588 #endif
1589 {
1590         char *s, *s0;
1591         size_t L;
1592
1593         *rvp += Bsize;
1594         s0 = f->ob0;
1595         s = f->u.sf;
1596         if ((L = f->obe1 - s) > Bsize) {
1597                 L = Bsize;
1598                 goto copy;
1599                 }
1600         if (L > 0) {
1601  copy:
1602                 memcpy(s, s0, L);
1603                 f->u.sf = s + L;
1604                 }
1605         return s0;
1606         }
1607
1608  int
1609 Vsnprintf
1610 #ifdef KR_headers
1611         (s, n, fmt, ap) char *s; size_t n; char *fmt; va_list ap;
1612 #else
1613         (char *s, size_t n, const char *fmt, va_list ap)
1614 #endif
1615 {
1616         Finfo f;
1617         char buf[Bsize];
1618         int L, rv;
1619
1620         if (n <= 0 || !s) {
1621                 n = 1;
1622                 s = buf;
1623                 }
1624         f.u.sf = s;
1625         f.ob0 = buf;
1626         f.obe1 = s + n - 1;
1627         rv = x_sprintf(buf + Bsize, Snput, &f, fmt, ap);
1628         if (f.lastlen > (L = f.obe1 - f.u.sf))
1629                 f.lastlen = L;
1630         if (f.lastlen > 0) {
1631                 memcpy(f.u.sf, buf, f.lastlen);
1632                 f.u.sf += f.lastlen;
1633                 }
1634         *f.u.sf = 0;
1635         return rv;
1636         }
1637  int
1638 Snprintf
1639 #ifdef KR_headers
1640         (va_alist)
1641  va_dcl
1642 {
1643         char *s, *fmt;
1644         int rv;
1645         size_t n;
1646         va_list ap;
1647
1648         va_start(ap);
1649         s = va_arg(ap, char*);
1650         n = va_arg(ap, size_t);
1651         fmt = va_arg(ap, char*);
1652         /*}*/
1653 #else
1654         (char *s, size_t n, const char *fmt, ...)
1655 {
1656         int rv;
1657         va_list ap;
1658
1659         va_start(ap, fmt);
1660 #endif
1661         rv = Vsnprintf(s, n, fmt, ap);
1662         va_end(ap);
1663         return rv;
1664         }
1665
1666
1667 #ifdef __cplusplus
1668 }
1669 #endif