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