1 --- vfprintf.c.orig Thu Jul 24 12:42:14 2003
2 +++ vfprintf.c Sun Aug 24 16:21:44 2003
8 +#include <machine/cpu_capabilities.h>
10 +#define VECTORTYPE vector unsigned char
13 /* Define FLOATING_POINT to get floating point. */
14 #define FLOATING_POINT
16 +/* if no floating point, turn off HEXFLOAT as well */
17 +#if defined(HEXFLOAT) && !defined(FLOATING_POINT)
19 +#endif /* defined(HEXFLOAT) && !defined(FLOATING_POINT) */
26 long long *plonglongarg;
27 ptrdiff_t *pptrdiffarg;
38 + VECTORTYPE vectorarg;
39 + unsigned char vuchararg[16];
40 + signed char vchararg[16];
41 + unsigned short vushortarg[8];
42 + signed short vshortarg[8];
43 + unsigned int vuintarg[4];
44 + signed int vintarg[4];
51 T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG,
52 T_PTRDIFFT, TP_PTRDIFFT, T_SIZET, TP_SIZET,
53 T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR,
55 + T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR, T_VECTOR
56 +#else /* ! ALTIVEC */
57 T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR
61 static int __sprint(FILE *, struct __suio *);
63 static void __find_arguments(const char *, va_list, union arg **);
64 static void __grow_type_table(int, enum typeid **, int *);
67 + * Get the argument indexed by nextarg. If the argument table is
68 + * built, use it to get the argument. If its not, get the next
69 + * argument (and arguments must be gotten sequentially).
71 +#define GETARG(type) \
72 + ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
73 + (nextarg++, va_arg(ap, type)))
76 +#define hasAltivec (_cpu_capabilities & kHasAltivec)
77 +/*-----------------------------------------------------------------------
78 + * getvec() must be a real subroutine. If it is a #define, then __vfprintf()
79 + * would have its calling sequence changed by Altivec so that a non-Altivec
80 + * processor would crash on illegal instruction. By isolating the calling
81 + * sequence in getvec(), __vprintf() is callable by a non-Altivec processor.
82 + *-----------------------------------------------------------------------*/
84 +getvec(union arg *dst, const union arg *argtable, int nextarg, va_list ap)
86 + dst->vectorarg = GETARG(VECTORTYPE);
90 +#define SETVEC(dst) \
92 + ap = getvec(&dst, argtable, nextarg, ap); \
98 * Flush out all the vectors defined by the given uio,
99 * then reset it so that it can be reused.
102 #endif /* FLOATING_POINT */
105 +extern int __hdtoa(double d, const char *xdigs, int prec, char *cp,
106 + int *expt, int *signflag, char **dtoaend);
107 +#if !__TYPE_LONGDOUBLE_IS_DOUBLE
108 +extern int __hldtoa(long double d, const char *xdigs, int prec, char *cp,
109 + int *expt, int *signflag, char **dtoaend);
110 +#endif /* !__TYPE_LONGDOUBLE_IS_DOUBLE */
111 +#endif /* HEXFLOAT */
114 * The size of the buffer we use as scratch space for integer
115 * conversions, among other things. Technically, we would need the
117 #define PTRDIFFT 0x800 /* ptrdiff_t */
118 #define INTMAXT 0x1000 /* intmax_t */
119 #define CHARINT 0x2000 /* print char using int format */
121 +#define VECTOR 0x4000 /* Altivec vector */
122 +#endif /* ALTIVEC */
125 * Non-MT-safe version
127 int nseps; /* number of group separators with ' */
128 int nrepeats; /* number of repeats of the last group */
131 + union arg vval; /* Vector argument. */
132 + char *pct; /* Pointer to '%' at beginning of specifier. */
133 + char vsep; /* Vector separator character. */
135 u_long ulval; /* integer arguments %[diouxX] */
136 uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
137 int base; /* base for [diouxX] conversion */
140 static const char xdigs_lower[16] = "0123456789abcdef";
141 static const char xdigs_upper[16] = "0123456789ABCDEF";
143 +#define HEXFLOATDELTA 32
144 +#define HEXFLOATSTART 32
145 + static char *hexfloat = NULL;
146 + static int hexfloatlen = 0;
147 +#endif /* HEXFLOAT */
150 * BEWARE, these `goto error' on error, and PAD uses `n'.
155 - * Get the argument indexed by nextarg. If the argument table is
156 - * built, use it to get the argument. If its not, get the next
157 - * argument (and arguments must be gotten sequentially).
159 -#define GETARG(type) \
160 - ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
161 - (nextarg++, va_arg(ap, type)))
164 * To extend shorts properly, we need both signed and unsigned
165 * argument extraction methods.
168 val = GETARG (int); \
172 thousands_sep = '\0';
181 +#endif /* ALTIVEC */
182 fmt++; /* skip over '%' */
190 + vsep = 'X'; /* Illegal value, changed to defaults later. */
191 +#endif /* ALTIVEC */
194 reswitch: switch (ch) {
200 + case ',': case ';': case ':': case '_':
203 +#endif /* ALTIVEC */
206 * ``A negative field width argument is taken as a
209 size = (int)mbseqlen;
212 + if (flags & VECTOR) {
216 +#endif /* ALTIVEC */
217 *(cp = buf) = GETARG(int);
225 + if (flags & VECTOR) {
229 +#endif /* ALTIVEC */
230 if (flags & INTMAX_SIZE) {
232 if ((intmax_t)ujval < 0) {
238 + if (flags & VECTOR) {
243 +#endif /* ALTIVEC */
247 @@ -845,25 +944,51 @@
252 - * XXX We don't actually have a conversion
253 - * XXX routine for this yet.
256 + hexfloat = malloc(hexfloatlen = HEXFLOATSTART);
260 + if (prec > hexfloatlen - 1) {
261 + int hlen = prec + HEXFLOATDELTA;
262 + char *hf = realloc(hexfloat, hlen);
266 + hexfloatlen = hlen;
269 if (flags & LONGDBL) {
270 - fparg.ldbl = (double)GETARG(long double);
272 - __hldtoa(fparg.ldbl, xdigs, prec,
273 +#if __TYPE_LONGDOUBLE_IS_DOUBLE
274 + fparg.dbl = (double)GETARG(long double);
275 + prec = __hdtoa(fparg.dbl, xdigs, prec, cp,
276 &expt, &signflag, &dtoaend);
277 +#else /* ! __TYPE_LONGDOUBLE_IS_DOUBLE */
278 + fparg.ldbl = GETARG(long double);
279 + prec = __hldtoa(fparg.ldbl, xdigs, prec, cp,
280 + &expt, &signflag, &dtoaend);
281 +#endif /* __TYPE_LONGDOUBLE_IS_DOUBLE */
283 fparg.dbl = GETARG(double);
285 - __hdtoa(fparg.dbl, xdigs, prec,
286 + prec = __hdtoa(fparg.dbl, xdigs, prec, cp,
287 &expt, &signflag, &dtoaend);
291 + if (expt == INT_MAX)
300 + if (flags & VECTOR) {
305 +#endif /* ALTIVEC */
307 if (prec < 0) /* account for digit before decpt */
309 @@ -872,10 +997,24 @@
314 + if (flags & VECTOR) {
319 +#endif /* ALTIVEC */
325 + if (flags & VECTOR) {
330 +#endif /* ALTIVEC */
331 expchar = ch - ('g' - 'e');
334 @@ -884,6 +1023,17 @@
336 if (dtoaresult != NULL)
337 freedtoa(dtoaresult);
338 +#if __TYPE_LONGDOUBLE_IS_DOUBLE
339 + if (flags & LONGDBL)
340 + fparg.dbl = (double)GETARG(long double);
342 + fparg.dbl = GETARG(double);
344 + dtoa(fparg.dbl, expchar ? 2 : 3, prec,
345 + &expt, &signflag, &dtoaend);
348 +#else /* ! __TYPE_LONGDOUBLE_IS_DOUBLE */
349 if (flags & LONGDBL) {
350 fparg.ldbl = GETARG(long double);
352 @@ -897,6 +1047,10 @@
356 +#endif /* __TYPE_LONGDOUBLE_IS_DOUBLE */
359 +#endif /* HEXFLOAT */
362 if (expt == INT_MAX) { /* inf or nan */
363 @@ -990,6 +1144,12 @@
368 + if (flags & VECTOR) {
372 +#endif /* ALTIVEC */
373 if (flags & INTMAX_SIZE)
376 @@ -1004,6 +1164,12 @@
381 + if (flags & VECTOR) {
385 +#endif /* ALTIVEC */
386 ujval = (uintmax_t)(uintptr_t)GETARG(void *);
389 @@ -1053,6 +1219,12 @@
394 + if (flags & VECTOR) {
398 +#endif /* ALTIVEC */
399 if (flags & INTMAX_SIZE)
402 @@ -1065,6 +1237,12 @@
407 + if (flags & VECTOR) {
411 +#endif /* ALTIVEC */
412 if (flags & INTMAX_SIZE)
415 @@ -1109,6 +1287,14 @@
416 if (size > BUF) /* should never happen */
426 +#endif /* ALTIVEC */
427 default: /* "%?" prints ?, unless ? is NUL */
430 @@ -1120,6 +1306,186 @@
435 + if (flags & VECTOR) {
437 + * Do the minimum amount of work necessary to construct
438 + * a format specifier that can be used to recursively
439 + * call vfprintf() for each element in the vector.
441 + int i, j; /* Counter. */
442 + int vcnt; /* Number of elements in vector. */
443 + char *vfmt; /* Pointer to format specifier. */
444 + char vfmt_buf[32]; /* Static buffer for format spec. */
445 + int vwidth = 0; /* Width specified via '*'. */
446 + int vprec = 0; /* Precision specified via '*'. */
447 + union { /* Element. */
451 + char *vstr; /* Used for asprintf(). */
452 + int vlen; /* Length returned by asprintf(). */
455 + * Set vfmt. If vfmt_buf may not be big enough,
456 + * malloc() space, taking care to free it later.
458 + if (&fmt[-1] - pct < sizeof(vfmt_buf))
461 + vfmt = (char *)malloc(&fmt[-1] - pct + 1);
463 + /* Set the separator character, if not specified. */
471 + /* Create the format specifier. */
472 + for (i = j = 0; i < &fmt[-1] - pct; i++) {
474 + case ',': case ';': case ':': case '_':
475 + case 'v': case 'h': case 'l':
479 + if (pct[i - 1] != '.')
485 + vfmt[j++] = pct[i];
490 + * Determine the number of elements in the vector and
491 + * finish up the format specifier.
493 + if (flags & SHORTINT) {
496 + } else if (flags & LONGINT) {
512 + * The default case should never
529 +/* Get a vector element. */
530 +#define VPRINT(cnt, ind, args...) do { \
531 + if (flags & FPT) { \
532 + velm.f = vval.vfloatarg[ind]; \
533 + vlen = asprintf(&vstr, vfmt , ## args, velm.f); \
537 + /* The default case should never happen. */ \
539 + velm.i = (unsigned)vval.vintarg[ind]; \
542 + velm.i = (unsigned short)vval.vshortarg[ind]; \
545 + velm.i = (unsigned char)vval.vchararg[ind]; \
548 + vlen = asprintf(&vstr, vfmt , ## args, velm.i); \
551 + PRINT(vstr, vlen); \
556 + /* Actually print. */
559 + /* First element. */
561 + for (i = 1; i < vcnt; i++) {
570 + /* First element. */
571 + VPRINT(vcnt, 0, prec);
572 + for (i = 1; i < vcnt; i++) {
578 + VPRINT(vcnt, i, prec);
583 + /* First element. */
584 + VPRINT(vcnt, 0, width);
585 + for (i = 1; i < vcnt; i++) {
591 + VPRINT(vcnt, i, width);
594 + /* First element. */
595 + VPRINT(vcnt, 0, width, prec);
596 + for (i = 1; i < vcnt; i++) {
602 + VPRINT(vcnt, i, width, prec);
608 + if (vfmt != vfmt_buf)
613 +#endif /* ALTIVEC */
615 * All reasonable formats wind up here. At this point, `cp'
616 * points to a string which (if not flags&LADJUST) should be
617 @@ -1137,7 +1503,7 @@
618 realsz = dprec > size ? dprec : size;
625 prsize = width > realsz ? width : realsz;
626 @@ -1151,9 +1517,9 @@
627 PAD(width - realsz, blanks);
633 - } else if (ox[1]) { /* ox[1] is either x, X, or \0 */
634 + if (ox[1]) { /* ox[1] is either x, X, or \0 */
638 @@ -1400,6 +1766,11 @@
643 + if (flags & VECTOR)
646 +#endif /* ALTIVEC */
650 @@ -1407,6 +1778,11 @@
655 + if (flags & VECTOR)
661 #ifdef FLOATING_POINT
662 @@ -1419,6 +1795,11 @@
667 + if (flags & VECTOR)
670 +#endif /* ALTIVEC */
672 ADDTYPE(T_LONG_DOUBLE);
674 @@ -1447,9 +1828,19 @@
679 + if (flags & VECTOR)
682 +#endif /* ALTIVEC */
687 + if (flags & VECTOR)
690 +#endif /* ALTIVEC */
694 @@ -1467,6 +1858,11 @@
699 + if (flags & VECTOR)
702 +#endif /* ALTIVEC */
705 default: /* "%?" prints ?, unless ? is NUL */
706 @@ -1552,6 +1948,12 @@
707 (*argtable) [n].longdoublearg = va_arg (ap, long double);
713 + ap = getvec( &((*argtable) [n]), NULL, 0, ap );
715 +#endif /* ALTIVEC */
717 (*argtable) [n].pchararg = va_arg (ap, char *);