xref: /freebsd/contrib/gdtoa/printf.c0 (revision 62cfcf62f627e5093fb37026a6d8c98e4d2ef04c)
1/****************************************************************
2Copyright (C) 1997, 1999, 2001 Lucent Technologies
3All Rights Reserved
4
5Permission to use, copy, modify, and distribute this software and
6its documentation for any purpose and without fee is hereby
7granted, provided that the above copyright notice appear in all
8copies and that both that the copyright notice and this
9permission notice and warranty disclaimer appear in supporting
10documentation, and that the name of Lucent or any of its entities
11not be used in advertising or publicity pertaining to
12distribution of the software without specific, written prior
13permission.
14
15LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
17IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
18SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
20IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
22THIS 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
85FPI {
86	int nbits;
87	int emin;
88	int emax;
89	int rounding;
90	int sudden_underflow;
91	} FPI;
92
93enum {	/* 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
112Finfo {
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
121FPBits {
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
166xfpbits(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
227Qfpbits(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
298extern "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
320klog(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
337uldiv_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
373FILE *stderr_ASL = (FILE*)&stderr_ASL;
374void (*pfbuf_print_ASL) ANSI((char*));
375char *pfbuf_ASL;
376static char *pfbuf_next;
377static size_t pfbuf_len;
378extern Char *mymalloc_ASL ANSI((size_t));
379extern 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
387fflush_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
401pf_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 *
424pfput(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 *
435Fput
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_
452int stdout_fileno_ASL = 1;
453
454 static char *
455Wput
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
482dfpbits(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
535fpiprec(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
576bround(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
672x_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
1338Printf
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 *
1389Sput
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
1403Sprintf
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
1433Fprintf
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
1503Vsprintf
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
1515Vfprintf
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
1570Perror
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 *
1583Snput
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
1609Vsnprintf
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
1638Snprintf
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
1670