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