]> git.saurik.com Git - apple/libc.git/blame - stdio/FreeBSD/vfprintf.c.patch
Libc-320.tar.gz
[apple/libc.git] / stdio / FreeBSD / vfprintf.c.patch
CommitLineData
9385eb3d
A
1--- vfprintf.c.orig Thu Jul 24 12:42:14 2003
2+++ vfprintf.c Sun Aug 24 16:21:44 2003
3@@ -66,9 +66,20 @@
4 #include "local.h"
5 #include "fvwrite.h"
6
7+#ifdef ALTIVEC
8+#include <machine/cpu_capabilities.h>
9+
10+#define VECTORTYPE vector unsigned char
11+#endif /* ALTIVEC */
12+
13 /* Define FLOATING_POINT to get floating point. */
14 #define FLOATING_POINT
15
16+/* if no floating point, turn off HEXFLOAT as well */
17+#if defined(HEXFLOAT) && !defined(FLOATING_POINT)
18+#undef HEXFLOAT
19+#endif /* defined(HEXFLOAT) && !defined(FLOATING_POINT) */
20+
21 union arg {
22 int intarg;
23 u_int uintarg;
24@@ -88,7 +99,7 @@
25 long *plongarg;
26 long long *plonglongarg;
27 ptrdiff_t *pptrdiffarg;
28- size_t *psizearg;
29+ ssize_t *psizearg;
30 intmax_t *pintmaxarg;
31 #ifdef FLOATING_POINT
32 double doublearg;
33@@ -96,6 +107,16 @@
34 #endif
35 wint_t wintarg;
36 wchar_t *pwchararg;
37+#ifdef ALTIVEC
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];
45+ float vfloatarg[4];
46+#endif /* ALTIVEC */
47 };
48
49 /*
50@@ -106,7 +127,11 @@
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,
54+#ifdef ALTIVEC
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
58+#endif /* ALTIVEC */
59 };
60
61 static int __sprint(FILE *, struct __suio *);
62@@ -119,6 +144,37 @@
63 static void __find_arguments(const char *, va_list, union arg **);
64 static void __grow_type_table(int, enum typeid **, int *);
65
66+ /*
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).
70+ */
71+#define GETARG(type) \
72+ ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
73+ (nextarg++, va_arg(ap, type)))
74+
75+#ifdef ALTIVEC
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+ *-----------------------------------------------------------------------*/
83+static va_list
84+getvec(union arg *dst, const union arg *argtable, int nextarg, va_list ap)
85+{
86+ dst->vectorarg = GETARG(VECTORTYPE);
87+ return ap;
88+}
89+
90+#define SETVEC(dst) \
91+{ \
92+ ap = getvec(&dst, argtable, nextarg, ap); \
93+ nextarg++; \
94+}
95+#endif /* ALTIVEC */
96+
97 /*
98 * Flush out all the vectors defined by the given uio,
99 * then reset it so that it can be reused.
100@@ -424,6 +480,15 @@
101
102 #endif /* FLOATING_POINT */
103
104+#ifdef HEXFLOAT
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 */
112+
113 /*
114 * The size of the buffer we use as scratch space for integer
115 * conversions, among other things. Technically, we would need the
116@@ -452,6 +517,9 @@
117 #define PTRDIFFT 0x800 /* ptrdiff_t */
118 #define INTMAXT 0x1000 /* intmax_t */
119 #define CHARINT 0x2000 /* print char using int format */
120+#ifdef ALTIVEC
121+#define VECTOR 0x4000 /* Altivec vector */
122+#endif /* ALTIVEC */
123
124 /*
125 * Non-MT-safe version
126@@ -503,6 +571,11 @@
127 int nseps; /* number of group separators with ' */
128 int nrepeats; /* number of repeats of the last group */
129 #endif
130+#ifdef ALTIVEC
131+ union arg vval; /* Vector argument. */
132+ char *pct; /* Pointer to '%' at beginning of specifier. */
133+ char vsep; /* Vector separator character. */
134+#endif
135 u_long ulval; /* integer arguments %[diouxX] */
136 uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
137 int base; /* base for [diouxX] conversion */
138@@ -535,6 +608,12 @@
139
140 static const char xdigs_lower[16] = "0123456789abcdef";
141 static const char xdigs_upper[16] = "0123456789ABCDEF";
142+#ifdef HEXFLOAT
143+#define HEXFLOATDELTA 32
144+#define HEXFLOATSTART 32
145+ static char *hexfloat = NULL;
146+ static int hexfloatlen = 0;
147+#endif /* HEXFLOAT */
148
149 /*
150 * BEWARE, these `goto error' on error, and PAD uses `n'.
151@@ -575,15 +654,6 @@
152 }
153
154 /*
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).
158- */
159-#define GETARG(type) \
160- ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
161- (nextarg++, va_arg(ap, type)))
162-
163- /*
164 * To extend shorts properly, we need both signed and unsigned
165 * argument extraction methods.
166 */
167@@ -634,7 +704,6 @@
168 val = GETARG (int); \
169 }
170
171-
172 thousands_sep = '\0';
173 grouping = NULL;
174 convbuf = NULL;
175@@ -676,6 +745,9 @@
176 }
177 if (ch == '\0')
178 goto done;
179+#ifdef ALTIVEC
180+ pct = fmt;
181+#endif /* ALTIVEC */
182 fmt++; /* skip over '%' */
183
184 flags = 0;
185@@ -684,6 +756,9 @@
186 prec = -1;
187 sign = '\0';
188 ox[1] = '\0';
189+#ifdef ALTIVEC
190+ vsep = 'X'; /* Illegal value, changed to defaults later. */
191+#endif /* ALTIVEC */
192
193 rflag: ch = *fmt++;
194 reswitch: switch (ch) {
195@@ -699,6 +774,11 @@
196 case '#':
197 flags |= ALT;
198 goto rflag;
199+#ifdef ALTIVEC
200+ case ',': case ';': case ':': case '_':
201+ vsep = ch;
202+ goto rflag;
203+#endif /* ALTIVEC */
204 case '*':
205 /*-
206 * ``A negative field width argument is taken as a
207@@ -807,6 +887,12 @@
208 }
209 size = (int)mbseqlen;
210 } else {
211+#ifdef ALTIVEC
212+ if (flags & VECTOR) {
213+ SETVEC(vval);
214+ break;
215+ }
216+#endif /* ALTIVEC */
217 *(cp = buf) = GETARG(int);
218 size = 1;
219 }
220@@ -817,6 +903,12 @@
221 /*FALLTHROUGH*/
222 case 'd':
223 case 'i':
224+#ifdef ALTIVEC
225+ if (flags & VECTOR) {
226+ SETVEC(vval);
227+ break;
228+ } else
229+#endif /* ALTIVEC */
230 if (flags & INTMAX_SIZE) {
231 ujval = SJARG();
232 if ((intmax_t)ujval < 0) {
233@@ -836,6 +928,13 @@
234 #ifdef HEXFLOAT
235 case 'a':
236 case 'A':
237+#ifdef ALTIVEC
238+ if (flags & VECTOR) {
239+ flags |= FPT;
240+ SETVEC(vval);
241+ break;
242+ }
243+#endif /* ALTIVEC */
244 if (ch == 'a') {
245 ox[1] = 'x';
246 xdigs = xdigs_lower;
247@@ -845,25 +944,51 @@
248 xdigs = xdigs_upper;
249 expchar = 'P';
250 }
251- /*
252- * XXX We don't actually have a conversion
253- * XXX routine for this yet.
254- */
255+ if (!hexfloat) {
256+ hexfloat = malloc(hexfloatlen = HEXFLOATSTART);
257+ if (!hexfloat)
258+ goto error;
259+ }
260+ if (prec > hexfloatlen - 1) {
261+ int hlen = prec + HEXFLOATDELTA;
262+ char *hf = realloc(hexfloat, hlen);
263+ if (hf == NULL)
264+ goto error;
265+ hexfloat = hf;
266+ hexfloatlen = hlen;
267+ }
268+ cp = hexfloat;
269 if (flags & LONGDBL) {
270- fparg.ldbl = (double)GETARG(long double);
271- dtoaresult = cp =
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 */
282 } else {
283 fparg.dbl = GETARG(double);
284- dtoaresult = cp =
285- __hdtoa(fparg.dbl, xdigs, prec,
286+ prec = __hdtoa(fparg.dbl, xdigs, prec, cp,
287 &expt, &signflag, &dtoaend);
288 }
289- goto fp_begin;
290+ prec++;
291+ if (expt == INT_MAX)
292+ ox[1] = 0;
293+ else
294+ expt++;
295+ goto hex_begin;
296 #endif
297 case 'e':
298 case 'E':
299+#ifdef ALTIVEC
300+ if (flags & VECTOR) {
301+ flags |= FPT;
302+ SETVEC(vval);
303+ break;
304+ }
305+#endif /* ALTIVEC */
306 expchar = ch;
307 if (prec < 0) /* account for digit before decpt */
308 prec = DEFPREC + 1;
309@@ -872,10 +997,24 @@
310 goto fp_begin;
311 case 'f':
312 case 'F':
313+#ifdef ALTIVEC
314+ if (flags & VECTOR) {
315+ flags |= FPT;
316+ SETVEC(vval);
317+ break;
318+ }
319+#endif /* ALTIVEC */
320 expchar = '\0';
321 goto fp_begin;
322 case 'g':
323 case 'G':
324+#ifdef ALTIVEC
325+ if (flags & VECTOR) {
326+ flags |= FPT;
327+ SETVEC(vval);
328+ break;
329+ }
330+#endif /* ALTIVEC */
331 expchar = ch - ('g' - 'e');
332 if (prec == 0)
333 prec = 1;
334@@ -884,6 +1023,17 @@
335 prec = DEFPREC;
336 if (dtoaresult != NULL)
337 freedtoa(dtoaresult);
338+#if __TYPE_LONGDOUBLE_IS_DOUBLE
339+ if (flags & LONGDBL)
340+ fparg.dbl = (double)GETARG(long double);
341+ else
342+ fparg.dbl = GETARG(double);
343+ dtoaresult = cp =
344+ dtoa(fparg.dbl, expchar ? 2 : 3, prec,
345+ &expt, &signflag, &dtoaend);
346+ if (expt == 9999)
347+ expt = INT_MAX;
348+#else /* ! __TYPE_LONGDOUBLE_IS_DOUBLE */
349 if (flags & LONGDBL) {
350 fparg.ldbl = GETARG(long double);
351 dtoaresult = cp =
352@@ -897,6 +1047,10 @@
353 if (expt == 9999)
354 expt = INT_MAX;
355 }
356+#endif /* __TYPE_LONGDOUBLE_IS_DOUBLE */
357+#ifdef HEXFLOAT
358+hex_begin:
359+#endif /* HEXFLOAT */
360 if (signflag)
361 sign = '-';
362 if (expt == INT_MAX) { /* inf or nan */
363@@ -990,6 +1144,12 @@
364 flags |= LONGINT;
365 /*FALLTHROUGH*/
366 case 'o':
367+#ifdef ALTIVEC
368+ if (flags & VECTOR) {
369+ SETVEC(vval);
370+ break;
371+ } else
372+#endif /* ALTIVEC */
373 if (flags & INTMAX_SIZE)
374 ujval = UJARG();
375 else
376@@ -1004,6 +1164,12 @@
377 * defined manner.''
378 * -- ANSI X3J11
379 */
380+#ifdef ALTIVEC
381+ if (flags & VECTOR) {
382+ SETVEC(vval);
383+ break;
384+ }
385+#endif /* ALTIVEC */
386 ujval = (uintmax_t)(uintptr_t)GETARG(void *);
387 base = 16;
388 xdigs = xdigs_lower;
389@@ -1053,6 +1219,12 @@
390 flags |= LONGINT;
391 /*FALLTHROUGH*/
392 case 'u':
393+#ifdef ALTIVEC
394+ if (flags & VECTOR) {
395+ SETVEC(vval);
396+ break;
397+ } else
398+#endif /* ALTIVEC */
399 if (flags & INTMAX_SIZE)
400 ujval = UJARG();
401 else
402@@ -1065,6 +1237,12 @@
403 case 'x':
404 xdigs = xdigs_lower;
405 hex:
406+#ifdef ALTIVEC
407+ if (flags & VECTOR) {
408+ SETVEC(vval);
409+ break;
410+ } else
411+#endif /* ALTIVEC */
412 if (flags & INTMAX_SIZE)
413 ujval = UJARG();
414 else
415@@ -1109,6 +1287,14 @@
416 if (size > BUF) /* should never happen */
417 abort();
418 break;
419+#ifdef ALTIVEC
420+ case 'v':
421+ if (hasAltivec) {
422+ flags |= VECTOR;
423+ goto rflag;
424+ }
425+ /* drap through */
426+#endif /* ALTIVEC */
427 default: /* "%?" prints ?, unless ? is NUL */
428 if (ch == '\0')
429 goto done;
430@@ -1120,6 +1306,186 @@
431 break;
432 }
433
434+#ifdef ALTIVEC
435+ if (flags & VECTOR) {
436+ /*
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.
440+ */
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. */
448+ int i;
449+ float f;
450+ } velm;
451+ char *vstr; /* Used for asprintf(). */
452+ int vlen; /* Length returned by asprintf(). */
453+
454+ /*
455+ * Set vfmt. If vfmt_buf may not be big enough,
456+ * malloc() space, taking care to free it later.
457+ */
458+ if (&fmt[-1] - pct < sizeof(vfmt_buf))
459+ vfmt = vfmt_buf;
460+ else
461+ vfmt = (char *)malloc(&fmt[-1] - pct + 1);
462+
463+ /* Set the separator character, if not specified. */
464+ if (vsep == 'X') {
465+ if (ch == 'c')
466+ vsep = '\0';
467+ else
468+ vsep = ' ';
469+ }
470+
471+ /* Create the format specifier. */
472+ for (i = j = 0; i < &fmt[-1] - pct; i++) {
473+ switch (pct[i]) {
474+ case ',': case ';': case ':': case '_':
475+ case 'v': case 'h': case 'l':
476+ /* Ignore. */
477+ break;
478+ case '*':
479+ if (pct[i - 1] != '.')
480+ vwidth = 1;
481+ else
482+ vprec = 1;
483+ /* FALLTHROUGH */
484+ default:
485+ vfmt[j++] = pct[i];
486+ }
487+ }
488+
489+ /*
490+ * Determine the number of elements in the vector and
491+ * finish up the format specifier.
492+ */
493+ if (flags & SHORTINT) {
494+ vfmt[j++] = 'h';
495+ vcnt = 8;
496+ } else if (flags & LONGINT) {
497+ vfmt[j++] = 'l';
498+ vcnt = 4;
499+ } else {
500+ switch (ch) {
501+ case 'a':
502+ case 'A':
503+ case 'e':
504+ case 'E':
505+ case 'f':
506+ case 'g':
507+ case 'G':
508+ vcnt = 4;
509+ break;
510+ default:
511+ /*
512+ * The default case should never
513+ * happen.
514+ */
515+ case 'c':
516+ case 'd':
517+ case 'i':
518+ case 'u':
519+ case 'o':
520+ case 'p':
521+ case 'x':
522+ case 'X':
523+ vcnt = 16;
524+ }
525+ }
526+ vfmt[j++] = ch;
527+ vfmt[j++] = '\0';
528+
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); \
534+ } else { \
535+ switch (cnt) { \
536+ default: \
537+ /* The default case should never happen. */ \
538+ case 4: \
539+ velm.i = (unsigned)vval.vintarg[ind]; \
540+ break; \
541+ case 8: \
542+ velm.i = (unsigned short)vval.vshortarg[ind]; \
543+ break; \
544+ case 16: \
545+ velm.i = (unsigned char)vval.vchararg[ind]; \
546+ break; \
547+ } \
548+ vlen = asprintf(&vstr, vfmt , ## args, velm.i); \
549+ } \
550+ ret += vlen; \
551+ PRINT(vstr, vlen); \
552+ FLUSH(); \
553+ free(vstr); \
554+} while (0)
555+
556+ /* Actually print. */
557+ if (vwidth == 0) {
558+ if (vprec == 0) {
559+ /* First element. */
560+ VPRINT(vcnt, 0);
561+ for (i = 1; i < vcnt; i++) {
562+ /* Separator. */
563+ if (vsep)
564+ PRINT(&vsep, 1);
565+
566+ /* Element. */
567+ VPRINT(vcnt, i);
568+ }
569+ } else {
570+ /* First element. */
571+ VPRINT(vcnt, 0, prec);
572+ for (i = 1; i < vcnt; i++) {
573+ /* Separator. */
574+ if (vsep)
575+ PRINT(&vsep, 1);
576+
577+ /* Element. */
578+ VPRINT(vcnt, i, prec);
579+ }
580+ }
581+ } else {
582+ if (vprec == 0) {
583+ /* First element. */
584+ VPRINT(vcnt, 0, width);
585+ for (i = 1; i < vcnt; i++) {
586+ /* Separator. */
587+ if (vsep)
588+ PRINT(&vsep, 1);
589+
590+ /* Element. */
591+ VPRINT(vcnt, i, width);
592+ }
593+ } else {
594+ /* First element. */
595+ VPRINT(vcnt, 0, width, prec);
596+ for (i = 1; i < vcnt; i++) {
597+ /* Separator. */
598+ if (vsep)
599+ PRINT(&vsep, 1);
600+
601+ /* Element. */
602+ VPRINT(vcnt, i, width, prec);
603+ }
604+ }
605+ }
606+#undef VPRINT
607+
608+ if (vfmt != vfmt_buf)
609+ free(vfmt);
610+
611+ continue;
612+ }
613+#endif /* ALTIVEC */
614 /*
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;
619 if (sign)
620 realsz++;
621- else if (ox[1])
622+ if (ox[1])
623 realsz += 2;
624
625 prsize = width > realsz ? width : realsz;
626@@ -1151,9 +1517,9 @@
627 PAD(width - realsz, blanks);
628
629 /* prefix */
630- if (sign) {
631+ if (sign)
632 PRINT(&sign, 1);
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 */
635 ox[0] = '0';
636 PRINT(ox, 2);
637 }
638@@ -1400,6 +1766,11 @@
639 if (flags & LONGINT)
640 ADDTYPE(T_WINT);
641 else
642+#ifdef ALTIVEC
643+ if (flags & VECTOR)
644+ ADDTYPE(T_VECTOR);
645+ else
646+#endif /* ALTIVEC */
647 ADDTYPE(T_INT);
648 break;
649 case 'D':
650@@ -1407,6 +1778,11 @@
651 /*FALLTHROUGH*/
652 case 'd':
653 case 'i':
654+#ifdef ALTIVEC
655+ if (flags & VECTOR)
656+ ADDTYPE(T_VECTOR);
657+ else
658+#endif
659 ADDSARG();
660 break;
661 #ifdef FLOATING_POINT
662@@ -1419,6 +1795,11 @@
663 case 'f':
664 case 'g':
665 case 'G':
666+#ifdef ALTIVEC
667+ if (flags & VECTOR)
668+ ADDTYPE(T_VECTOR);
669+ else
670+#endif /* ALTIVEC */
671 if (flags & LONGDBL)
672 ADDTYPE(T_LONG_DOUBLE);
673 else
674@@ -1447,9 +1828,19 @@
675 flags |= LONGINT;
676 /*FALLTHROUGH*/
677 case 'o':
678+#ifdef ALTIVEC
679+ if (flags & VECTOR)
680+ ADDTYPE(T_VECTOR);
681+ else
682+#endif /* ALTIVEC */
683 ADDUARG();
684 break;
685 case 'p':
686+#ifdef ALTIVEC
687+ if (flags & VECTOR)
688+ ADDTYPE(T_VECTOR);
689+ else
690+#endif /* ALTIVEC */
691 ADDTYPE(TP_VOID);
692 break;
693 case 'S':
694@@ -1467,6 +1858,11 @@
695 case 'u':
696 case 'X':
697 case 'x':
698+#ifdef ALTIVEC
699+ if (flags & VECTOR)
700+ ADDTYPE(T_VECTOR);
701+ else
702+#endif /* ALTIVEC */
703 ADDUARG();
704 break;
705 default: /* "%?" prints ?, unless ? is NUL */
706@@ -1552,6 +1948,12 @@
707 (*argtable) [n].longdoublearg = va_arg (ap, long double);
708 break;
709 #endif
710+#ifdef ALTIVEC
711+ case T_VECTOR:
712+ if (hasAltivec)
713+ ap = getvec( &((*argtable) [n]), NULL, 0, ap );
714+ break;
715+#endif /* ALTIVEC */
716 case TP_CHAR:
717 (*argtable) [n].pchararg = va_arg (ap, char *);
718 break;