1 --- vfwprintf.c.orig Thu Jul 24 12:42:14 2003
2 +++ vfwprintf.c Sun Aug 24 16:22:23 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 __sbprintf(FILE *, const wchar_t *, va_list);
63 static void __find_arguments(const wchar_t *, 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 * Helper function for `fprintf to unbuffered unix file': creates a
99 * temporary buffer. We only work on write-only files; this avoids
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 + wchar_t *pct; /* Pointer to '%' at beginning of specifier. */
133 + wchar_t 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 wchar_t xdigs_lower[16] = L"0123456789abcdef";
141 static const wchar_t xdigs_upper[16] = L"0123456789ABCDEF";
143 +#define HEXFLOATDELTA 32
144 +#define HEXFLOATSTART 32
145 + static char *hexfloat = NULL;
146 + static int hexfloatlen = 0;
147 + const char *xdigs0; /* digits for [aA] conversion */
148 + static const char xdigs_lower0[16] = "0123456789abcdef";
149 + static const char xdigs_upper0[16] = "0123456789ABCDEF";
150 +#endif /* HEXFLOAT */
153 * BEWARE, these `goto error' on error, PRINT uses `n2' and
158 - * Get the argument indexed by nextarg. If the argument table is
159 - * built, use it to get the argument. If its not, get the next
160 - * argument (and arguments must be gotten sequentially).
162 -#define GETARG(type) \
163 - ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
164 - (nextarg++, va_arg(ap, type)))
167 * To extend shorts properly, we need both signed and unsigned
168 * argument extraction methods.
171 val = GETARG (int); \
175 thousands_sep = '\0';
177 #ifdef FLOATING_POINT
184 +#endif /* ALTIVEC */
185 fmt++; /* skip over '%' */
193 + vsep = 'X'; /* Illegal value, changed to defaults later. */
194 +#endif /* ALTIVEC */
197 reswitch: switch (ch) {
203 + case ',': case ';': case ':': case '_':
206 +#endif /* ALTIVEC */
209 * ``A negative field width argument is taken as a
213 *(cp = buf) = (wchar_t)GETARG(wint_t);
216 + if (flags & VECTOR) {
220 + *(cp = buf) = (wchar_t)btowc(GETARG(int));
224 *(cp = buf) = (wchar_t)btowc(GETARG(int));
225 +#endif /* ALTIVEC */
234 + if (flags & VECTOR) {
238 +#endif /* ALTIVEC */
239 if (flags & INTMAX_SIZE) {
241 if ((intmax_t)ujval < 0) {
242 @@ -799,38 +898,74 @@
247 + if (flags & VECTOR) {
252 +#endif /* ALTIVEC */
255 - xdigs = xdigs_lower;
256 + xdigs0 = xdigs_lower0;
260 - xdigs = xdigs_upper;
261 + xdigs0 = xdigs_upper0;
265 - * XXX We don't actually have a conversion
266 - * XXX routine for this yet.
269 + hexfloat = malloc(hexfloatlen = HEXFLOATSTART);
273 + /* one extra for integer part and another for null */
274 + if (prec > hexfloatlen - 2) {
275 + int hlen = prec + HEXFLOATDELTA;
276 + char *hf = realloc(hexfloat, hlen);
280 + hexfloatlen = hlen;
282 if (flags & LONGDBL) {
283 - fparg.ldbl = (double)GETARG(long double);
285 - __hldtoa(fparg.ldbl, xdigs, prec,
286 - &expt, &signflag, &dtoaend);
287 +#if __TYPE_LONGDOUBLE_IS_DOUBLE
288 + fparg.dbl = (double)GETARG(long double);
289 + prec = __hdtoa(fparg.dbl, xdigs0, prec,
290 + hexfloat, &expt, &signflag, &dtoaend);
291 +#else /* ! __TYPE_LONGDOUBLE_IS_DOUBLE */
292 + fparg.ldbl = GETARG(long double);
293 + prec = __hldtoa(fparg.ldbl, xdigs0, prec,
294 + hexfloat, &expt, &signflag, &dtoaend);
295 +#endif /* __TYPE_LONGDOUBLE_IS_DOUBLE */
297 fparg.dbl = GETARG(double);
299 - __hdtoa(fparg.dbl, xdigs, prec,
300 - &expt, &signflag, &dtoaend);
301 + prec = __hdtoa(fparg.dbl, xdigs0, prec,
302 + hexfloat, &expt, &signflag, &dtoaend);
305 + if (expt == INT_MAX) {
311 + ndig = dtoaend - hexfloat;
315 - cp = convbuf = __mbsconv(dtoaresult, -1);
316 - freedtoa(dtoaresult);
318 + cp = convbuf = __mbsconv(hexfloat, -1);
324 + if (flags & VECTOR) {
329 +#endif /* ALTIVEC */
331 if (prec < 0) /* account for digit before decpt */
333 @@ -839,10 +974,24 @@
338 + if (flags & VECTOR) {
343 +#endif /* ALTIVEC */
349 + if (flags & VECTOR) {
354 +#endif /* ALTIVEC */
355 expchar = ch - ('g' - 'e');
358 @@ -851,6 +1000,17 @@
362 +#if __TYPE_LONGDOUBLE_IS_DOUBLE
363 + if (flags & LONGDBL)
364 + fparg.ldbl = GETARG(long double);
366 + fparg.dbl = GETARG(double);
368 + dtoa(fparg.dbl, expchar ? 2 : 3, prec,
369 + &expt, &signflag, &dtoaend);
372 +#else /* ! __TYPE_LONGDOUBLE_IS_DOUBLE */
373 if (flags & LONGDBL) {
374 fparg.ldbl = GETARG(long double);
376 @@ -864,9 +1024,13 @@
380 +#endif /* __TYPE_LONGDOUBLE_IS_DOUBLE */
381 ndig = dtoaend - dtoaresult;
382 cp = convbuf = __mbsconv(dtoaresult, -1);
383 freedtoa(dtoaresult);
386 +#endif /* HEXFLOAT */
389 if (expt == INT_MAX) { /* inf or nan */
390 @@ -959,6 +1123,12 @@
395 + if (flags & VECTOR) {
399 +#endif /* ALTIVEC */
400 if (flags & INTMAX_SIZE)
403 @@ -973,6 +1143,12 @@
408 + if (flags & VECTOR) {
412 +#endif /* ALTIVEC */
413 ujval = (uintmax_t)(uintptr_t)GETARG(void *);
416 @@ -1025,6 +1201,12 @@
421 + if (flags & VECTOR) {
425 +#endif /* ALTIVEC */
426 if (flags & INTMAX_SIZE)
429 @@ -1037,6 +1219,12 @@
434 + if (flags & VECTOR) {
438 +#endif /* ALTIVEC */
439 if (flags & INTMAX_SIZE)
442 @@ -1081,6 +1269,14 @@
443 if (size > BUF) /* should never happen */
453 +#endif /* ALTIVEC */
454 default: /* "%?" prints ?, unless ? is NUL */
457 @@ -1092,6 +1288,185 @@
462 + if (flags & VECTOR) {
464 + * Do the minimum amount of work necessary to construct
465 + * a format specifier that can be used to recursively
466 + * call vfprintf() for each element in the vector.
468 + int i, j; /* Counter. */
469 + int vcnt; /* Number of elements in vector. */
470 + char *vfmt; /* Pointer to format specifier. */
471 + char vfmt_buf[32]; /* Static buffer for format spec. */
472 + int vwidth = 0; /* Width specified via '*'. */
473 + int vprec = 0; /* Precision specified via '*'. */
474 + union { /* Element. */
478 + char *vstr; /* Used for asprintf(). */
479 + int vlen; /* Length returned by asprintf(). */
482 + * Set vfmt. If vfmt_buf may not be big enough,
483 + * malloc() space, taking care to free it later.
485 + if (&fmt[-1] - pct < sizeof(vfmt_buf))
488 + vfmt = (char *)malloc(&fmt[-1] - pct + 1);
490 + /* Set the separator character, if not specified. */
498 + /* Create the format specifier. */
499 + for (i = j = 0; i < &fmt[-1] - pct; i++) {
501 + case ',': case ';': case ':': case '_':
502 + case 'v': case 'h': case 'l':
506 + if (pct[i - 1] != '.')
512 + vfmt[j++] = pct[i];
517 + * Determine the number of elements in the vector and
518 + * finish up the format specifier.
520 + if (flags & SHORTINT) {
523 + } else if (flags & LONGINT) {
539 + * The default case should never
556 +/* Get a vector element. */
557 +#define VPRINT(cnt, ind, args...) do { \
558 + if (flags & FPT) { \
559 + velm.f = vval.vfloatarg[ind]; \
560 + vlen = asprintf(&vstr, vfmt , ## args, velm.f); \
564 + /* The default case should never happen. */ \
566 + velm.i = (unsigned)vval.vintarg[ind]; \
569 + velm.i = (unsigned short)vval.vshortarg[ind]; \
572 + velm.i = (unsigned char)vval.vchararg[ind]; \
575 + vlen = asprintf(&vstr, vfmt , ## args, velm.i); \
578 + PRINT(vstr, vlen); \
582 + /* Actually print. */
585 + /* First element. */
587 + for (i = 1; i < vcnt; i++) {
596 + /* First element. */
597 + VPRINT(vcnt, 0, prec);
598 + for (i = 1; i < vcnt; i++) {
604 + VPRINT(vcnt, i, prec);
609 + /* First element. */
610 + VPRINT(vcnt, 0, width);
611 + for (i = 1; i < vcnt; i++) {
617 + VPRINT(vcnt, i, width);
620 + /* First element. */
621 + VPRINT(vcnt, 0, width, prec);
622 + for (i = 1; i < vcnt; i++) {
628 + VPRINT(vcnt, i, width, prec);
634 + if (vfmt != vfmt_buf)
639 +#endif /* ALTIVEC */
641 * All reasonable formats wind up here. At this point, `cp'
642 * points to a string which (if not flags&LADJUST) should be
643 @@ -1109,7 +1484,7 @@
644 realsz = dprec > size ? dprec : size;
651 prsize = width > realsz ? width : realsz;
652 @@ -1123,9 +1498,9 @@
653 PAD(width - realsz, blanks);
659 - } else if (ox[1]) { /* ox[1] is either x, X, or \0 */
660 + if (ox[1]) { /* ox[1] is either x, X, or \0 */
664 @@ -1368,6 +1743,11 @@
669 + if (flags & VECTOR)
672 +#endif /* ALTIVEC */
676 @@ -1387,6 +1767,11 @@
681 + if (flags & VECTOR)
684 +#endif /* ALTIVEC */
686 ADDTYPE(T_LONG_DOUBLE);
688 @@ -1415,9 +1800,19 @@
693 + if (flags & VECTOR)
696 +#endif /* ALTIVEC */
701 + if (flags & VECTOR)
704 +#endif /* ALTIVEC */
708 @@ -1435,6 +1830,11 @@
713 + if (flags & VECTOR)
716 +#endif /* ALTIVEC */
719 default: /* "%?" prints ?, unless ? is NUL */
720 @@ -1520,6 +1920,12 @@
721 (*argtable) [n].longdoublearg = va_arg (ap, long double);
727 + ap = getvec( &((*argtable) [n]), NULL, 0, ap );
729 +#endif /* ALTIVEC */
731 (*argtable) [n].pchararg = va_arg (ap, char *);