1 --- vfprintf.c.orig Thu Jul 24 12:42:14 2003
2 +++ vfprintf.c Tue Apr 6 17:44:49 2004
10 #include "un-namespace.h"
16 +#include <machine/cpu_capabilities.h>
18 +#define VECTORTYPE vector unsigned char
21 /* Define FLOATING_POINT to get floating point. */
22 #define FLOATING_POINT
24 +/* if no floating point, turn off HEXFLOAT as well */
25 +#if defined(HEXFLOAT) && !defined(FLOATING_POINT)
27 +#endif /* defined(HEXFLOAT) && !defined(FLOATING_POINT) */
34 long long *plonglongarg;
35 ptrdiff_t *pptrdiffarg;
46 + VECTORTYPE vectorarg;
47 + unsigned char vuchararg[16];
48 + signed char vchararg[16];
49 + unsigned short vushortarg[8];
50 + signed short vshortarg[8];
51 + unsigned int vuintarg[4];
52 + signed int vintarg[4];
59 T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG,
60 T_PTRDIFFT, TP_PTRDIFFT, T_SIZET, TP_SIZET,
61 T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR,
63 + T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR, T_VECTOR
64 +#else /* ! ALTIVEC */
65 T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR
69 static int __sprint(FILE *, struct __suio *);
71 static void __find_arguments(const char *, va_list, union arg **);
72 static void __grow_type_table(int, enum typeid **, int *);
75 + * Get the argument indexed by nextarg. If the argument table is
76 + * built, use it to get the argument. If its not, get the next
77 + * argument (and arguments must be gotten sequentially).
79 +#define GETARG(type) \
80 + ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
81 + (nextarg++, va_arg(ap, type)))
84 +#define hasAltivec (_cpu_capabilities & kHasAltivec)
85 +/*-----------------------------------------------------------------------
86 + * getvec() must be a real subroutine. If it is a #define, then __vfprintf()
87 + * would have its calling sequence changed by Altivec so that a non-Altivec
88 + * processor would crash on illegal instruction. By isolating the calling
89 + * sequence in getvec(), __vprintf() is callable by a non-Altivec processor.
90 + *-----------------------------------------------------------------------*/
92 +getvec(union arg *dst, const union arg *argtable, int nextarg, va_list ap)
94 + dst->vectorarg = GETARG(VECTORTYPE);
98 +#define SETVEC(dst) \
100 + ap = getvec(&dst, argtable, nextarg, ap); \
103 +#endif /* ALTIVEC */
106 * Flush out all the vectors defined by the given uio,
107 * then reset it so that it can be reused.
110 #endif /* FLOATING_POINT */
113 +extern int __hdtoa(double d, const char *xdigs, int prec, char *cp,
114 + int *expt, int *signflag, char **dtoaend);
115 +#if !__TYPE_LONGDOUBLE_IS_DOUBLE
116 +extern int __hldtoa(long double d, const char *xdigs, int prec, char *cp,
117 + int *expt, int *signflag, char **dtoaend);
118 +#endif /* !__TYPE_LONGDOUBLE_IS_DOUBLE */
119 +#endif /* HEXFLOAT */
122 * The size of the buffer we use as scratch space for integer
123 * conversions, among other things. Technically, we would need the
125 #define PTRDIFFT 0x800 /* ptrdiff_t */
126 #define INTMAXT 0x1000 /* intmax_t */
127 #define CHARINT 0x2000 /* print char using int format */
129 +#define VECTOR 0x4000 /* Altivec vector */
130 +#endif /* ALTIVEC */
133 * Non-MT-safe version
135 int nseps; /* number of group separators with ' */
136 int nrepeats; /* number of repeats of the last group */
139 + union arg vval; /* Vector argument. */
140 + char *pct; /* Pointer to '%' at beginning of specifier. */
141 + char vsep; /* Vector separator character. */
143 u_long ulval; /* integer arguments %[diouxX] */
144 uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
145 int base; /* base for [diouxX] conversion */
148 static const char xdigs_lower[16] = "0123456789abcdef";
149 static const char xdigs_upper[16] = "0123456789ABCDEF";
151 +#define HEXFLOATDELTA 32
152 +#define HEXFLOATSTART 32
153 + static char *hexfloat = NULL;
154 + static int hexfloatlen = 0;
155 +#endif /* HEXFLOAT */
158 * BEWARE, these `goto error' on error, and PAD uses `n'.
163 - * Get the argument indexed by nextarg. If the argument table is
164 - * built, use it to get the argument. If its not, get the next
165 - * argument (and arguments must be gotten sequentially).
167 -#define GETARG(type) \
168 - ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
169 - (nextarg++, va_arg(ap, type)))
172 * To extend shorts properly, we need both signed and unsigned
173 * argument extraction methods.
176 val = GETARG (int); \
180 thousands_sep = '\0';
184 decimal_point = localeconv()->decimal_point;
186 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
188 + if (cantwrite(fp)) {
193 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
194 if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
201 +#endif /* ALTIVEC */
202 fmt++; /* skip over '%' */
210 + vsep = 'X'; /* Illegal value, changed to defaults later. */
211 +#endif /* ALTIVEC */
214 reswitch: switch (ch) {
220 + case ',': case ';': case ':': case '_':
223 +#endif /* ALTIVEC */
226 * ``A negative field width argument is taken as a
229 size = (int)mbseqlen;
232 + if (flags & VECTOR) {
236 +#endif /* ALTIVEC */
237 *(cp = buf) = GETARG(int);
245 + if (flags & VECTOR) {
249 +#endif /* ALTIVEC */
250 if (flags & INTMAX_SIZE) {
252 if ((intmax_t)ujval < 0) {
258 + if (flags & VECTOR) {
263 +#endif /* ALTIVEC */
267 @@ -845,25 +947,51 @@
272 - * XXX We don't actually have a conversion
273 - * XXX routine for this yet.
276 + hexfloat = malloc(hexfloatlen = HEXFLOATSTART);
280 + if (prec > hexfloatlen - 1) {
281 + int hlen = prec + HEXFLOATDELTA;
282 + char *hf = realloc(hexfloat, hlen);
286 + hexfloatlen = hlen;
289 if (flags & LONGDBL) {
290 - fparg.ldbl = (double)GETARG(long double);
292 - __hldtoa(fparg.ldbl, xdigs, prec,
293 +#if __TYPE_LONGDOUBLE_IS_DOUBLE
294 + fparg.dbl = (double)GETARG(long double);
295 + prec = __hdtoa(fparg.dbl, xdigs, prec, cp,
296 &expt, &signflag, &dtoaend);
297 +#else /* ! __TYPE_LONGDOUBLE_IS_DOUBLE */
298 + fparg.ldbl = GETARG(long double);
299 + prec = __hldtoa(fparg.ldbl, xdigs, prec, cp,
300 + &expt, &signflag, &dtoaend);
301 +#endif /* __TYPE_LONGDOUBLE_IS_DOUBLE */
303 fparg.dbl = GETARG(double);
305 - __hdtoa(fparg.dbl, xdigs, prec,
306 + prec = __hdtoa(fparg.dbl, xdigs, prec, cp,
307 &expt, &signflag, &dtoaend);
311 + if (expt == INT_MAX)
320 + if (flags & VECTOR) {
325 +#endif /* ALTIVEC */
327 if (prec < 0) /* account for digit before decpt */
329 @@ -872,10 +1000,24 @@
334 + if (flags & VECTOR) {
339 +#endif /* ALTIVEC */
345 + if (flags & VECTOR) {
350 +#endif /* ALTIVEC */
351 expchar = ch - ('g' - 'e');
354 @@ -884,6 +1026,17 @@
356 if (dtoaresult != NULL)
357 freedtoa(dtoaresult);
358 +#if __TYPE_LONGDOUBLE_IS_DOUBLE
359 + if (flags & LONGDBL)
360 + fparg.dbl = (double)GETARG(long double);
362 + fparg.dbl = GETARG(double);
364 + dtoa(fparg.dbl, expchar ? 2 : 3, prec,
365 + &expt, &signflag, &dtoaend);
368 +#else /* ! __TYPE_LONGDOUBLE_IS_DOUBLE */
369 if (flags & LONGDBL) {
370 fparg.ldbl = GETARG(long double);
372 @@ -897,6 +1050,10 @@
376 +#endif /* __TYPE_LONGDOUBLE_IS_DOUBLE */
379 +#endif /* HEXFLOAT */
382 if (expt == INT_MAX) { /* inf or nan */
383 @@ -990,6 +1147,12 @@
388 + if (flags & VECTOR) {
392 +#endif /* ALTIVEC */
393 if (flags & INTMAX_SIZE)
396 @@ -1004,6 +1167,12 @@
401 + if (flags & VECTOR) {
405 +#endif /* ALTIVEC */
406 ujval = (uintmax_t)(uintptr_t)GETARG(void *);
409 @@ -1053,6 +1222,12 @@
414 + if (flags & VECTOR) {
418 +#endif /* ALTIVEC */
419 if (flags & INTMAX_SIZE)
422 @@ -1065,6 +1240,12 @@
427 + if (flags & VECTOR) {
431 +#endif /* ALTIVEC */
432 if (flags & INTMAX_SIZE)
435 @@ -1109,6 +1290,14 @@
436 if (size > BUF) /* should never happen */
446 +#endif /* ALTIVEC */
447 default: /* "%?" prints ?, unless ? is NUL */
450 @@ -1120,6 +1309,186 @@
455 + if (flags & VECTOR) {
457 + * Do the minimum amount of work necessary to construct
458 + * a format specifier that can be used to recursively
459 + * call vfprintf() for each element in the vector.
461 + int i, j; /* Counter. */
462 + int vcnt; /* Number of elements in vector. */
463 + char *vfmt; /* Pointer to format specifier. */
464 + char vfmt_buf[32]; /* Static buffer for format spec. */
465 + int vwidth = 0; /* Width specified via '*'. */
466 + int vprec = 0; /* Precision specified via '*'. */
467 + union { /* Element. */
471 + char *vstr; /* Used for asprintf(). */
472 + int vlen; /* Length returned by asprintf(). */
475 + * Set vfmt. If vfmt_buf may not be big enough,
476 + * malloc() space, taking care to free it later.
478 + if (&fmt[-1] - pct < sizeof(vfmt_buf))
481 + vfmt = (char *)malloc(&fmt[-1] - pct + 1);
483 + /* Set the separator character, if not specified. */
491 + /* Create the format specifier. */
492 + for (i = j = 0; i < &fmt[-1] - pct; i++) {
494 + case ',': case ';': case ':': case '_':
495 + case 'v': case 'h': case 'l':
499 + if (pct[i - 1] != '.')
505 + vfmt[j++] = pct[i];
510 + * Determine the number of elements in the vector and
511 + * finish up the format specifier.
513 + if (flags & SHORTINT) {
516 + } else if (flags & LONGINT) {
532 + * The default case should never
549 +/* Get a vector element. */
550 +#define VPRINT(cnt, ind, args...) do { \
551 + if (flags & FPT) { \
552 + velm.f = vval.vfloatarg[ind]; \
553 + vlen = asprintf(&vstr, vfmt , ## args, velm.f); \
557 + /* The default case should never happen. */ \
559 + velm.i = (unsigned)vval.vintarg[ind]; \
562 + velm.i = (unsigned short)vval.vshortarg[ind]; \
565 + velm.i = (unsigned char)vval.vchararg[ind]; \
568 + vlen = asprintf(&vstr, vfmt , ## args, velm.i); \
571 + PRINT(vstr, vlen); \
576 + /* Actually print. */
579 + /* First element. */
581 + for (i = 1; i < vcnt; i++) {
590 + /* First element. */
591 + VPRINT(vcnt, 0, prec);
592 + for (i = 1; i < vcnt; i++) {
598 + VPRINT(vcnt, i, prec);
603 + /* First element. */
604 + VPRINT(vcnt, 0, width);
605 + for (i = 1; i < vcnt; i++) {
611 + VPRINT(vcnt, i, width);
614 + /* First element. */
615 + VPRINT(vcnt, 0, width, prec);
616 + for (i = 1; i < vcnt; i++) {
622 + VPRINT(vcnt, i, width, prec);
628 + if (vfmt != vfmt_buf)
633 +#endif /* ALTIVEC */
635 * All reasonable formats wind up here. At this point, `cp'
636 * points to a string which (if not flags&LADJUST) should be
637 @@ -1137,7 +1506,7 @@
638 realsz = dprec > size ? dprec : size;
645 prsize = width > realsz ? width : realsz;
646 @@ -1151,9 +1520,9 @@
647 PAD(width - realsz, blanks);
653 - } else if (ox[1]) { /* ox[1] is either x, X, or \0 */
654 + if (ox[1]) { /* ox[1] is either x, X, or \0 */
658 @@ -1400,6 +1769,11 @@
663 + if (flags & VECTOR)
666 +#endif /* ALTIVEC */
670 @@ -1407,6 +1781,11 @@
675 + if (flags & VECTOR)
681 #ifdef FLOATING_POINT
682 @@ -1419,6 +1798,11 @@
687 + if (flags & VECTOR)
690 +#endif /* ALTIVEC */
692 ADDTYPE(T_LONG_DOUBLE);
694 @@ -1447,9 +1831,19 @@
699 + if (flags & VECTOR)
702 +#endif /* ALTIVEC */
707 + if (flags & VECTOR)
710 +#endif /* ALTIVEC */
714 @@ -1467,6 +1861,11 @@
719 + if (flags & VECTOR)
722 +#endif /* ALTIVEC */
725 default: /* "%?" prints ?, unless ? is NUL */
726 @@ -1552,6 +1951,12 @@
727 (*argtable) [n].longdoublearg = va_arg (ap, long double);
733 + ap = getvec( &((*argtable) [n]), NULL, 0, ap );
735 +#endif /* ALTIVEC */
737 (*argtable) [n].pchararg = va_arg (ap, char *);