]> git.saurik.com Git - apple/libc.git/blob - stdio/FreeBSD/vfprintf.c.patch
c84878a4ed36064e028410a2f26d0273f81c843d
[apple/libc.git] / stdio / FreeBSD / vfprintf.c.patch
1 --- vfprintf.c.orig Sun May 30 01:12:48 2004
2 +++ vfprintf.c Sun May 30 01:18:16 2004
3 @@ -58,6 +58,7 @@
4 #include <stdlib.h>
5 #include <string.h>
6 #include <wchar.h>
7 +#include <errno.h>
8
9 #include <stdarg.h>
10 #include "un-namespace.h"
11 @@ -66,6 +67,12 @@
12 #include "local.h"
13 #include "fvwrite.h"
14
15 +#ifdef ALTIVEC
16 +#include <machine/cpu_capabilities.h>
17 +
18 +#define VECTORTYPE vector unsigned char
19 +#endif /* ALTIVEC */
20 +
21 union arg {
22 int intarg;
23 u_int uintarg;
24 @@ -93,6 +100,16 @@
25 #endif
26 wint_t wintarg;
27 wchar_t *pwchararg;
28 +#ifdef ALTIVEC
29 + VECTORTYPE vectorarg;
30 + unsigned char vuchararg[16];
31 + signed char vchararg[16];
32 + unsigned short vushortarg[8];
33 + signed short vshortarg[8];
34 + unsigned int vuintarg[4];
35 + signed int vintarg[4];
36 + float vfloatarg[4];
37 +#endif /* ALTIVEC */
38 };
39
40 /*
41 @@ -103,7 +120,11 @@
42 T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG,
43 T_PTRDIFFT, TP_PTRDIFFT, T_SIZET, TP_SIZET,
44 T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR,
45 +#ifdef ALTIVEC
46 + T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR, T_VECTOR
47 +#else /* ! ALTIVEC */
48 T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR
49 +#endif /* ALTIVEC */
50 };
51
52 static int __sprint(FILE *, struct __suio *);
53 @@ -116,6 +137,37 @@
54 static void __find_arguments(const char *, va_list, union arg **);
55 static void __grow_type_table(int, enum typeid **, int *);
56
57 + /*
58 + * Get the argument indexed by nextarg. If the argument table is
59 + * built, use it to get the argument. If its not, get the next
60 + * argument (and arguments must be gotten sequentially).
61 + */
62 +#define GETARG(type) \
63 + ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
64 + (nextarg++, va_arg(ap, type)))
65 +
66 +#ifdef ALTIVEC
67 +#define hasAltivec (_cpu_capabilities & kHasAltivec)
68 +/*-----------------------------------------------------------------------
69 + * getvec() must be a real subroutine. If it is a #define, then __vfprintf()
70 + * would have its calling sequence changed by Altivec so that a non-Altivec
71 + * processor would crash on illegal instruction. By isolating the calling
72 + * sequence in getvec(), __vprintf() is callable by a non-Altivec processor.
73 + *-----------------------------------------------------------------------*/
74 +static va_list
75 +getvec(union arg *dst, const union arg *argtable, int nextarg, va_list ap)
76 +{
77 + dst->vectorarg = GETARG(VECTORTYPE);
78 + return ap;
79 +}
80 +
81 +#define SETVEC(dst) \
82 +{ \
83 + ap = getvec(&dst, argtable, nextarg, ap); \
84 + nextarg++; \
85 +}
86 +#endif /* ALTIVEC */
87 +
88 /*
89 * Flush out all the vectors defined by the given uio,
90 * then reset it so that it can be reused.
91 @@ -451,6 +503,9 @@
92 #define PTRDIFFT 0x800 /* ptrdiff_t */
93 #define INTMAXT 0x1000 /* intmax_t */
94 #define CHARINT 0x2000 /* print char using int format */
95 +#ifdef ALTIVEC
96 +#define VECTOR 0x4000 /* Altivec vector */
97 +#endif /* ALTIVEC */
98
99 /*
100 * Non-MT-safe version
101 @@ -502,6 +557,11 @@
102 int nseps; /* number of group separators with ' */
103 int nrepeats; /* number of repeats of the last group */
104 #endif
105 +#ifdef ALTIVEC
106 + union arg vval; /* Vector argument. */
107 + char *pct; /* Pointer to '%' at beginning of specifier. */
108 + char vsep; /* Vector separator character. */
109 +#endif
110 u_long ulval; /* integer arguments %[diouxX] */
111 uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
112 int base; /* base for [diouxX] conversion */
113 @@ -574,15 +634,6 @@
114 }
115
116 /*
117 - * Get the argument indexed by nextarg. If the argument table is
118 - * built, use it to get the argument. If its not, get the next
119 - * argument (and arguments must be gotten sequentially).
120 - */
121 -#define GETARG(type) \
122 - ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
123 - (nextarg++, va_arg(ap, type)))
124 -
125 - /*
126 * To extend shorts properly, we need both signed and unsigned
127 * argument extraction methods.
128 */
129 @@ -633,7 +684,6 @@
130 val = GETARG (int); \
131 }
132
133 -
134 thousands_sep = '\0';
135 grouping = NULL;
136 convbuf = NULL;
137 @@ -642,8 +692,10 @@
138 decimal_point = localeconv()->decimal_point;
139 #endif
140 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
141 - if (cantwrite(fp))
142 + if (cantwrite(fp)) {
143 + errno = EBADF;
144 return (EOF);
145 + }
146
147 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
148 if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
149 @@ -675,6 +727,9 @@
150 }
151 if (ch == '\0')
152 goto done;
153 +#ifdef ALTIVEC
154 + pct = fmt;
155 +#endif /* ALTIVEC */
156 fmt++; /* skip over '%' */
157
158 flags = 0;
159 @@ -683,6 +738,9 @@
160 prec = -1;
161 sign = '\0';
162 ox[1] = '\0';
163 +#ifdef ALTIVEC
164 + vsep = 'X'; /* Illegal value, changed to defaults later. */
165 +#endif /* ALTIVEC */
166
167 rflag: ch = *fmt++;
168 reswitch: switch (ch) {
169 @@ -698,6 +756,11 @@
170 case '#':
171 flags |= ALT;
172 goto rflag;
173 +#ifdef ALTIVEC
174 + case ',': case ';': case ':': case '_':
175 + vsep = ch;
176 + goto rflag;
177 +#endif /* ALTIVEC */
178 case '*':
179 /*-
180 * ``A negative field width argument is taken as a
181 @@ -793,6 +856,12 @@
182 flags |= LONGINT;
183 /*FALLTHROUGH*/
184 case 'c':
185 +#ifdef ALTIVEC
186 + if (flags & VECTOR) {
187 + SETVEC(vval);
188 + break;
189 + }
190 +#endif /* ALTIVEC */
191 if (flags & LONGINT) {
192 static const mbstate_t initial;
193 mbstate_t mbs;
194 @@ -817,6 +886,12 @@
195 /*FALLTHROUGH*/
196 case 'd':
197 case 'i':
198 +#ifdef ALTIVEC
199 + if (flags & VECTOR) {
200 + SETVEC(vval);
201 + break;
202 + }
203 +#endif /* ALTIVEC */
204 if (flags & INTMAX_SIZE) {
205 ujval = SJARG();
206 if ((intmax_t)ujval < 0) {
207 @@ -835,6 +910,13 @@
208 #ifndef NO_FLOATING_POINT
209 case 'a':
210 case 'A':
211 +#ifdef ALTIVEC
212 + if (flags & VECTOR) {
213 + flags |= FPT;
214 + SETVEC(vval);
215 + break;
216 + }
217 +#endif /* ALTIVEC */
218 if (ch == 'a') {
219 ox[1] = 'x';
220 xdigs = xdigs_lower;
221 @@ -866,6 +948,13 @@
222 goto fp_common;
223 case 'e':
224 case 'E':
225 +#ifdef ALTIVEC
226 + if (flags & VECTOR) {
227 + flags |= FPT;
228 + SETVEC(vval);
229 + break;
230 + }
231 +#endif /* ALTIVEC */
232 expchar = ch;
233 if (prec < 0) /* account for digit before decpt */
234 prec = DEFPREC + 1;
235 @@ -874,10 +963,24 @@
236 goto fp_begin;
237 case 'f':
238 case 'F':
239 +#ifdef ALTIVEC
240 + if (flags & VECTOR) {
241 + flags |= FPT;
242 + SETVEC(vval);
243 + break;
244 + }
245 +#endif /* ALTIVEC */
246 expchar = '\0';
247 goto fp_begin;
248 case 'g':
249 case 'G':
250 +#ifdef ALTIVEC
251 + if (flags & VECTOR) {
252 + flags |= FPT;
253 + SETVEC(vval);
254 + break;
255 + }
256 +#endif /* ALTIVEC */
257 expchar = ch - ('g' - 'e');
258 if (prec == 0)
259 prec = 1;
260 @@ -993,6 +1096,12 @@
261 flags |= LONGINT;
262 /*FALLTHROUGH*/
263 case 'o':
264 +#ifdef ALTIVEC
265 + if (flags & VECTOR) {
266 + SETVEC(vval);
267 + break;
268 + }
269 +#endif /* ALTIVEC */
270 if (flags & INTMAX_SIZE)
271 ujval = UJARG();
272 else
273 @@ -1007,6 +1116,12 @@
274 * defined manner.''
275 * -- ANSI X3J11
276 */
277 +#ifdef ALTIVEC
278 + if (flags & VECTOR) {
279 + SETVEC(vval);
280 + break;
281 + }
282 +#endif /* ALTIVEC */
283 ujval = (uintmax_t)(uintptr_t)GETARG(void *);
284 base = 16;
285 xdigs = xdigs_lower;
286 @@ -1056,6 +1171,12 @@
287 flags |= LONGINT;
288 /*FALLTHROUGH*/
289 case 'u':
290 +#ifdef ALTIVEC
291 + if (flags & VECTOR) {
292 + SETVEC(vval);
293 + break;
294 + }
295 +#endif /* ALTIVEC */
296 if (flags & INTMAX_SIZE)
297 ujval = UJARG();
298 else
299 @@ -1068,6 +1189,12 @@
300 case 'x':
301 xdigs = xdigs_lower;
302 hex:
303 +#ifdef ALTIVEC
304 + if (flags & VECTOR) {
305 + SETVEC(vval);
306 + break;
307 + }
308 +#endif /* ALTIVEC */
309 if (flags & INTMAX_SIZE)
310 ujval = UJARG();
311 else
312 @@ -1112,6 +1239,14 @@
313 if (size > BUF) /* should never happen */
314 abort();
315 break;
316 +#ifdef ALTIVEC
317 + case 'v':
318 + if (hasAltivec) {
319 + flags |= VECTOR;
320 + goto rflag;
321 + }
322 + /* drap through */
323 +#endif /* ALTIVEC */
324 default: /* "%?" prints ?, unless ? is NUL */
325 if (ch == '\0')
326 goto done;
327 @@ -1123,6 +1258,184 @@
328 break;
329 }
330
331 +#ifdef ALTIVEC
332 + if (flags & VECTOR) {
333 + /*
334 + * Do the minimum amount of work necessary to construct
335 + * a format specifier that can be used to recursively
336 + * call vfprintf() for each element in the vector.
337 + */
338 + int i, j; /* Counter. */
339 + int vcnt; /* Number of elements in vector. */
340 + char *vfmt; /* Pointer to format specifier. */
341 + char vfmt_buf[32]; /* Static buffer for format spec. */
342 + int vwidth = 0; /* Width specified via '*'. */
343 + int vprec = 0; /* Precision specified via '*'. */
344 + union { /* Element. */
345 + int i;
346 + float f;
347 + } velm;
348 + char *vstr; /* Used for asprintf(). */
349 + int vlen; /* Length returned by asprintf(). */
350 +
351 + /*
352 + * Set vfmt. If vfmt_buf may not be big enough,
353 + * malloc() space, taking care to free it later.
354 + */
355 + if (&fmt[-1] - pct < sizeof(vfmt_buf))
356 + vfmt = vfmt_buf;
357 + else
358 + vfmt = (char *)malloc(&fmt[-1] - pct + 1);
359 +
360 + /* Set the separator character, if not specified. */
361 + if (vsep == 'X') {
362 + if (ch == 'c')
363 + vsep = '\0';
364 + else
365 + vsep = ' ';
366 + }
367 +
368 + /* Create the format specifier. */
369 + for (i = j = 0; i < &fmt[-1] - pct; i++) {
370 + switch (pct[i]) {
371 + case ',': case ';': case ':': case '_':
372 + case 'v': case 'h': case 'l':
373 + /* Ignore. */
374 + break;
375 + case '*':
376 + if (pct[i - 1] != '.')
377 + vwidth = 1;
378 + else
379 + vprec = 1;
380 + /* FALLTHROUGH */
381 + default:
382 + vfmt[j++] = pct[i];
383 + }
384 + }
385 +
386 + /*
387 + * Determine the number of elements in the vector and
388 + * finish up the format specifier.
389 + */
390 + if (flags & SHORTINT) {
391 + if (ch != 'c')
392 + vfmt[j++] = 'h';
393 + vcnt = 8;
394 + } else if (flags & LONGINT) {
395 + if (ch != 'c')
396 + vfmt[j++] = 'l';
397 + vcnt = 4;
398 + } else {
399 + switch (ch) {
400 + case 'a':
401 + case 'A':
402 + case 'e':
403 + case 'E':
404 + case 'f':
405 + case 'g':
406 + case 'G':
407 + vcnt = 4;
408 + break;
409 + default:
410 + /*
411 + * The default case should never
412 + * happen.
413 + */
414 + case 'c':
415 + case 'd':
416 + case 'i':
417 + case 'u':
418 + case 'o':
419 + case 'p':
420 + case 'x':
421 + case 'X':
422 + vcnt = 16;
423 + }
424 + }
425 + vfmt[j++] = ch;
426 + vfmt[j++] = '\0';
427 +
428 +/* Get a vector element. */
429 +#define VPRINT(cnt, ind, args...) do { \
430 + if (flags & FPT) { \
431 + velm.f = vval.vfloatarg[ind]; \
432 + vlen = asprintf(&vstr, vfmt , ## args, velm.f); \
433 + } else { \
434 + switch (cnt) { \
435 + default: \
436 + /* The default case should never happen. */ \
437 + case 4: \
438 + velm.i = (unsigned)vval.vintarg[ind]; \
439 + break; \
440 + case 8: \
441 + velm.i = (unsigned short)vval.vshortarg[ind]; \
442 + break; \
443 + case 16: \
444 + velm.i = (unsigned char)vval.vchararg[ind]; \
445 + break; \
446 + } \
447 + vlen = asprintf(&vstr, vfmt , ## args, velm.i); \
448 + } \
449 + ret += vlen; \
450 + PRINT(vstr, vlen); \
451 + FLUSH(); \
452 + free(vstr); \
453 +} while (0)
454 +
455 + /* Actually print. */
456 + if (vwidth == 0) {
457 + if (vprec == 0) {
458 + /* First element. */
459 + VPRINT(vcnt, 0);
460 + for (i = 1; i < vcnt; i++) {
461 + /* Separator. */
462 + PRINT(&vsep, 1);
463 +
464 + /* Element. */
465 + VPRINT(vcnt, i);
466 + }
467 + } else {
468 + /* First element. */
469 + VPRINT(vcnt, 0, prec);
470 + for (i = 1; i < vcnt; i++) {
471 + /* Separator. */
472 + PRINT(&vsep, 1);
473 +
474 + /* Element. */
475 + VPRINT(vcnt, i, prec);
476 + }
477 + }
478 + } else {
479 + if (vprec == 0) {
480 + /* First element. */
481 + VPRINT(vcnt, 0, width);
482 + for (i = 1; i < vcnt; i++) {
483 + /* Separator. */
484 + PRINT(&vsep, 1);
485 +
486 + /* Element. */
487 + VPRINT(vcnt, i, width);
488 + }
489 + } else {
490 + /* First element. */
491 + VPRINT(vcnt, 0, width, prec);
492 + for (i = 1; i < vcnt; i++) {
493 + /* Separator. */
494 + PRINT(&vsep, 1);
495 +
496 + /* Element. */
497 + VPRINT(vcnt, i, width, prec);
498 + }
499 + }
500 + }
501 +#undef VPRINT
502 +
503 + if (vfmt != vfmt_buf)
504 + free(vfmt);
505 +
506 + continue;
507 + }
508 +#endif /* ALTIVEC */
509 /*
510 * All reasonable formats wind up here. At this point, `cp'
511 * points to a string which (if not flags&LADJUST) should be
512 @@ -1405,6 +1718,11 @@
513 if (flags & LONGINT)
514 ADDTYPE(T_WINT);
515 else
516 +#ifdef ALTIVEC
517 + if (flags & VECTOR)
518 + ADDTYPE(T_VECTOR);
519 + else
520 +#endif /* ALTIVEC */
521 ADDTYPE(T_INT);
522 break;
523 case 'D':
524 @@ -1412,6 +1730,11 @@
525 /*FALLTHROUGH*/
526 case 'd':
527 case 'i':
528 +#ifdef ALTIVEC
529 + if (flags & VECTOR)
530 + ADDTYPE(T_VECTOR);
531 + else
532 +#endif
533 ADDSARG();
534 break;
535 #ifndef NO_FLOATING_POINT
536 @@ -1422,6 +1745,11 @@
537 case 'f':
538 case 'g':
539 case 'G':
540 +#ifdef ALTIVEC
541 + if (flags & VECTOR)
542 + ADDTYPE(T_VECTOR);
543 + else
544 +#endif /* ALTIVEC */
545 if (flags & LONGDBL)
546 ADDTYPE(T_LONG_DOUBLE);
547 else
548 @@ -1450,9 +1778,19 @@
549 flags |= LONGINT;
550 /*FALLTHROUGH*/
551 case 'o':
552 +#ifdef ALTIVEC
553 + if (flags & VECTOR)
554 + ADDTYPE(T_VECTOR);
555 + else
556 +#endif /* ALTIVEC */
557 ADDUARG();
558 break;
559 case 'p':
560 +#ifdef ALTIVEC
561 + if (flags & VECTOR)
562 + ADDTYPE(T_VECTOR);
563 + else
564 +#endif /* ALTIVEC */
565 ADDTYPE(TP_VOID);
566 break;
567 case 'S':
568 @@ -1470,6 +1808,11 @@
569 case 'u':
570 case 'X':
571 case 'x':
572 +#ifdef ALTIVEC
573 + if (flags & VECTOR)
574 + ADDTYPE(T_VECTOR);
575 + else
576 +#endif /* ALTIVEC */
577 ADDUARG();
578 break;
579 default: /* "%?" prints ?, unless ? is NUL */
580 @@ -1555,6 +1898,12 @@
581 (*argtable) [n].longdoublearg = va_arg (ap, long double);
582 break;
583 #endif
584 +#ifdef ALTIVEC
585 + case T_VECTOR:
586 + if (hasAltivec)
587 + ap = getvec( &((*argtable) [n]), NULL, 0, ap );
588 + break;
589 +#endif /* ALTIVEC */
590 case TP_CHAR:
591 (*argtable) [n].pchararg = va_arg (ap, char *);
592 break;