]>
Commit | Line | Data |
---|---|---|
9385eb3d A |
1 | --- vfwprintf.c.orig Thu Jul 24 12:42:14 2003 |
2 | +++ vfwprintf.c Sun Aug 24 16:22:23 2003 | |
3 | @@ -70,9 +70,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 | @@ -92,7 +103,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 | @@ -100,6 +111,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 | @@ -110,7 +131,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 __sbprintf(FILE *, const wchar_t *, va_list); | |
62 | @@ -122,6 +147,37 @@ | |
63 | static void __find_arguments(const wchar_t *, 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 | * Helper function for `fprintf to unbuffered unix file': creates a | |
99 | * temporary buffer. We only work on write-only files; this avoids | |
100 | @@ -418,6 +474,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 | @@ -446,6 +511,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 | @@ -496,6 +564,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 | + wchar_t *pct; /* Pointer to '%' at beginning of specifier. */ | |
133 | + wchar_t 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 | @@ -525,6 +598,15 @@ | |
139 | ||
140 | static const wchar_t xdigs_lower[16] = L"0123456789abcdef"; | |
141 | static const wchar_t xdigs_upper[16] = L"0123456789ABCDEF"; | |
142 | +#ifdef HEXFLOAT | |
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 */ | |
151 | ||
152 | /* | |
153 | * BEWARE, these `goto error' on error, PRINT uses `n2' and | |
154 | @@ -553,15 +635,6 @@ | |
155 | } while(0) | |
156 | ||
157 | /* | |
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). | |
161 | - */ | |
162 | -#define GETARG(type) \ | |
163 | - ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \ | |
164 | - (nextarg++, va_arg(ap, type))) | |
165 | - | |
166 | - /* | |
167 | * To extend shorts properly, we need both signed and unsigned | |
168 | * argument extraction methods. | |
169 | */ | |
170 | @@ -612,7 +685,6 @@ | |
171 | val = GETARG (int); \ | |
172 | } | |
173 | ||
174 | - | |
175 | thousands_sep = '\0'; | |
176 | grouping = NULL; | |
177 | #ifdef FLOATING_POINT | |
178 | @@ -650,6 +722,9 @@ | |
179 | } | |
180 | if (ch == '\0') | |
181 | goto done; | |
182 | +#ifdef ALTIVEC | |
183 | + pct = fmt; | |
184 | +#endif /* ALTIVEC */ | |
185 | fmt++; /* skip over '%' */ | |
186 | ||
187 | flags = 0; | |
188 | @@ -658,6 +733,9 @@ | |
189 | prec = -1; | |
190 | sign = '\0'; | |
191 | ox[1] = '\0'; | |
192 | +#ifdef ALTIVEC | |
193 | + vsep = 'X'; /* Illegal value, changed to defaults later. */ | |
194 | +#endif /* ALTIVEC */ | |
195 | ||
196 | rflag: ch = *fmt++; | |
197 | reswitch: switch (ch) { | |
198 | @@ -673,6 +751,11 @@ | |
199 | case '#': | |
200 | flags |= ALT; | |
201 | goto rflag; | |
202 | +#ifdef ALTIVEC | |
203 | + case ',': case ';': case ':': case '_': | |
204 | + vsep = ch; | |
205 | + goto rflag; | |
206 | +#endif /* ALTIVEC */ | |
207 | case '*': | |
208 | /*- | |
209 | * ``A negative field width argument is taken as a | |
210 | @@ -770,8 +853,18 @@ | |
211 | case 'c': | |
212 | if (flags & LONGINT) | |
213 | *(cp = buf) = (wchar_t)GETARG(wint_t); | |
214 | +#ifdef ALTIVEC | |
215 | + else { | |
216 | + if (flags & VECTOR) { | |
217 | + SETVEC(vval); | |
218 | + break; | |
219 | + } | |
220 | + *(cp = buf) = (wchar_t)btowc(GETARG(int)); | |
221 | + } | |
222 | +#else /* ALTIVEC */ | |
223 | else | |
224 | *(cp = buf) = (wchar_t)btowc(GETARG(int)); | |
225 | +#endif /* ALTIVEC */ | |
226 | size = 1; | |
227 | sign = '\0'; | |
228 | break; | |
229 | @@ -780,6 +873,12 @@ | |
230 | /*FALLTHROUGH*/ | |
231 | case 'd': | |
232 | case 'i': | |
233 | +#ifdef ALTIVEC | |
234 | + if (flags & VECTOR) { | |
235 | + SETVEC(vval); | |
236 | + break; | |
237 | + } else | |
238 | +#endif /* ALTIVEC */ | |
239 | if (flags & INTMAX_SIZE) { | |
240 | ujval = SJARG(); | |
241 | if ((intmax_t)ujval < 0) { | |
242 | @@ -799,38 +898,74 @@ | |
243 | #ifdef HEXFLOAT | |
244 | case 'a': | |
245 | case 'A': | |
246 | +#ifdef ALTIVEC | |
247 | + if (flags & VECTOR) { | |
248 | + flags |= FPT; | |
249 | + SETVEC(vval); | |
250 | + break; | |
251 | + } | |
252 | +#endif /* ALTIVEC */ | |
253 | if (ch == 'a') { | |
254 | ox[1] = 'x'; | |
255 | - xdigs = xdigs_lower; | |
256 | + xdigs0 = xdigs_lower0; | |
257 | expchar = 'p'; | |
258 | } else { | |
259 | ox[1] = 'X'; | |
260 | - xdigs = xdigs_upper; | |
261 | + xdigs0 = xdigs_upper0; | |
262 | expchar = 'P'; | |
263 | } | |
264 | - /* | |
265 | - * XXX We don't actually have a conversion | |
266 | - * XXX routine for this yet. | |
267 | - */ | |
268 | + if (!hexfloat) { | |
269 | + hexfloat = malloc(hexfloatlen = HEXFLOATSTART); | |
270 | + if (!hexfloat) | |
271 | + goto error; | |
272 | + } | |
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); | |
277 | + if (hf == NULL) | |
278 | + goto error; | |
279 | + hexfloat = hf; | |
280 | + hexfloatlen = hlen; | |
281 | + } | |
282 | if (flags & LONGDBL) { | |
283 | - fparg.ldbl = (double)GETARG(long double); | |
284 | - dtoaresult = | |
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 */ | |
296 | } else { | |
297 | fparg.dbl = GETARG(double); | |
298 | - dtoaresult = | |
299 | - __hdtoa(fparg.dbl, xdigs, prec, | |
300 | - &expt, &signflag, &dtoaend); | |
301 | + prec = __hdtoa(fparg.dbl, xdigs0, prec, | |
302 | + hexfloat, &expt, &signflag, &dtoaend); | |
303 | + } | |
304 | + prec++; | |
305 | + if (expt == INT_MAX) { | |
306 | + ox[1] = 0; | |
307 | + hexfloat[1] = 0; | |
308 | + } else { | |
309 | + expt++; | |
310 | + *dtoaend = 0; | |
311 | + ndig = dtoaend - hexfloat; | |
312 | } | |
313 | if (convbuf != NULL) | |
314 | free(convbuf); | |
315 | - cp = convbuf = __mbsconv(dtoaresult, -1); | |
316 | - freedtoa(dtoaresult); | |
317 | - goto fp_begin; | |
318 | + cp = convbuf = __mbsconv(hexfloat, -1); | |
319 | + goto hex_begin; | |
320 | #endif | |
321 | case 'e': | |
322 | case 'E': | |
323 | +#ifdef ALTIVEC | |
324 | + if (flags & VECTOR) { | |
325 | + flags |= FPT; | |
326 | + SETVEC(vval); | |
327 | + break; | |
328 | + } | |
329 | +#endif /* ALTIVEC */ | |
330 | expchar = ch; | |
331 | if (prec < 0) /* account for digit before decpt */ | |
332 | prec = DEFPREC + 1; | |
333 | @@ -839,10 +974,24 @@ | |
334 | goto fp_begin; | |
335 | case 'f': | |
336 | case 'F': | |
337 | +#ifdef ALTIVEC | |
338 | + if (flags & VECTOR) { | |
339 | + flags |= FPT; | |
340 | + SETVEC(vval); | |
341 | + break; | |
342 | + } | |
343 | +#endif /* ALTIVEC */ | |
344 | expchar = '\0'; | |
345 | goto fp_begin; | |
346 | case 'g': | |
347 | case 'G': | |
348 | +#ifdef ALTIVEC | |
349 | + if (flags & VECTOR) { | |
350 | + flags |= FPT; | |
351 | + SETVEC(vval); | |
352 | + break; | |
353 | + } | |
354 | +#endif /* ALTIVEC */ | |
355 | expchar = ch - ('g' - 'e'); | |
356 | if (prec == 0) | |
357 | prec = 1; | |
358 | @@ -851,6 +1000,17 @@ | |
359 | prec = DEFPREC; | |
360 | if (convbuf != NULL) | |
361 | free(convbuf); | |
362 | +#if __TYPE_LONGDOUBLE_IS_DOUBLE | |
363 | + if (flags & LONGDBL) | |
364 | + fparg.ldbl = GETARG(long double); | |
365 | + else | |
366 | + fparg.dbl = GETARG(double); | |
367 | + dtoaresult = | |
368 | + dtoa(fparg.dbl, expchar ? 2 : 3, prec, | |
369 | + &expt, &signflag, &dtoaend); | |
370 | + if (expt == 9999) | |
371 | + expt = INT_MAX; | |
372 | +#else /* ! __TYPE_LONGDOUBLE_IS_DOUBLE */ | |
373 | if (flags & LONGDBL) { | |
374 | fparg.ldbl = GETARG(long double); | |
375 | dtoaresult = | |
376 | @@ -864,9 +1024,13 @@ | |
377 | if (expt == 9999) | |
378 | expt = INT_MAX; | |
379 | } | |
380 | +#endif /* __TYPE_LONGDOUBLE_IS_DOUBLE */ | |
381 | ndig = dtoaend - dtoaresult; | |
382 | cp = convbuf = __mbsconv(dtoaresult, -1); | |
383 | freedtoa(dtoaresult); | |
384 | +#ifdef HEXFLOAT | |
385 | +hex_begin: | |
386 | +#endif /* HEXFLOAT */ | |
387 | if (signflag) | |
388 | sign = '-'; | |
389 | if (expt == INT_MAX) { /* inf or nan */ | |
390 | @@ -959,6 +1123,12 @@ | |
391 | flags |= LONGINT; | |
392 | /*FALLTHROUGH*/ | |
393 | case 'o': | |
394 | +#ifdef ALTIVEC | |
395 | + if (flags & VECTOR) { | |
396 | + SETVEC(vval); | |
397 | + break; | |
398 | + } else | |
399 | +#endif /* ALTIVEC */ | |
400 | if (flags & INTMAX_SIZE) | |
401 | ujval = UJARG(); | |
402 | else | |
403 | @@ -973,6 +1143,12 @@ | |
404 | * defined manner.'' | |
405 | * -- ANSI X3J11 | |
406 | */ | |
407 | +#ifdef ALTIVEC | |
408 | + if (flags & VECTOR) { | |
409 | + SETVEC(vval); | |
410 | + break; | |
411 | + } | |
412 | +#endif /* ALTIVEC */ | |
413 | ujval = (uintmax_t)(uintptr_t)GETARG(void *); | |
414 | base = 16; | |
415 | xdigs = xdigs_lower; | |
416 | @@ -1025,6 +1201,12 @@ | |
417 | flags |= LONGINT; | |
418 | /*FALLTHROUGH*/ | |
419 | case 'u': | |
420 | +#ifdef ALTIVEC | |
421 | + if (flags & VECTOR) { | |
422 | + SETVEC(vval); | |
423 | + break; | |
424 | + } else | |
425 | +#endif /* ALTIVEC */ | |
426 | if (flags & INTMAX_SIZE) | |
427 | ujval = UJARG(); | |
428 | else | |
429 | @@ -1037,6 +1219,12 @@ | |
430 | case 'x': | |
431 | xdigs = xdigs_lower; | |
432 | hex: | |
433 | +#ifdef ALTIVEC | |
434 | + if (flags & VECTOR) { | |
435 | + SETVEC(vval); | |
436 | + break; | |
437 | + } else | |
438 | +#endif /* ALTIVEC */ | |
439 | if (flags & INTMAX_SIZE) | |
440 | ujval = UJARG(); | |
441 | else | |
442 | @@ -1081,6 +1269,14 @@ | |
443 | if (size > BUF) /* should never happen */ | |
444 | abort(); | |
445 | break; | |
446 | +#ifdef ALTIVEC | |
447 | + case 'v': | |
448 | + if (hasAltivec) { | |
449 | + flags |= VECTOR; | |
450 | + goto rflag; | |
451 | + } | |
452 | + /* drop through */ | |
453 | +#endif /* ALTIVEC */ | |
454 | default: /* "%?" prints ?, unless ? is NUL */ | |
455 | if (ch == '\0') | |
456 | goto done; | |
457 | @@ -1092,6 +1288,185 @@ | |
458 | break; | |
459 | } | |
460 | ||
461 | +#ifdef ALTIVEC | |
462 | + if (flags & VECTOR) { | |
463 | + /* | |
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. | |
467 | + */ | |
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. */ | |
475 | + int i; | |
476 | + float f; | |
477 | + } velm; | |
478 | + char *vstr; /* Used for asprintf(). */ | |
479 | + int vlen; /* Length returned by asprintf(). */ | |
480 | + | |
481 | + /* | |
482 | + * Set vfmt. If vfmt_buf may not be big enough, | |
483 | + * malloc() space, taking care to free it later. | |
484 | + */ | |
485 | + if (&fmt[-1] - pct < sizeof(vfmt_buf)) | |
486 | + vfmt = vfmt_buf; | |
487 | + else | |
488 | + vfmt = (char *)malloc(&fmt[-1] - pct + 1); | |
489 | + | |
490 | + /* Set the separator character, if not specified. */ | |
491 | + if (vsep == 'X') { | |
492 | + if (ch == 'c') | |
493 | + vsep = '\0'; | |
494 | + else | |
495 | + vsep = ' '; | |
496 | + } | |
497 | + | |
498 | + /* Create the format specifier. */ | |
499 | + for (i = j = 0; i < &fmt[-1] - pct; i++) { | |
500 | + switch (pct[i]) { | |
501 | + case ',': case ';': case ':': case '_': | |
502 | + case 'v': case 'h': case 'l': | |
503 | + /* Ignore. */ | |
504 | + break; | |
505 | + case '*': | |
506 | + if (pct[i - 1] != '.') | |
507 | + vwidth = 1; | |
508 | + else | |
509 | + vprec = 1; | |
510 | + /* FALLTHROUGH */ | |
511 | + default: | |
512 | + vfmt[j++] = pct[i]; | |
513 | + } | |
514 | + } | |
515 | + | |
516 | + /* | |
517 | + * Determine the number of elements in the vector and | |
518 | + * finish up the format specifier. | |
519 | + */ | |
520 | + if (flags & SHORTINT) { | |
521 | + vfmt[j++] = 'h'; | |
522 | + vcnt = 8; | |
523 | + } else if (flags & LONGINT) { | |
524 | + vfmt[j++] = 'l'; | |
525 | + vcnt = 4; | |
526 | + } else { | |
527 | + switch (ch) { | |
528 | + case 'a': | |
529 | + case 'A': | |
530 | + case 'e': | |
531 | + case 'E': | |
532 | + case 'f': | |
533 | + case 'g': | |
534 | + case 'G': | |
535 | + vcnt = 4; | |
536 | + break; | |
537 | + default: | |
538 | + /* | |
539 | + * The default case should never | |
540 | + * happen. | |
541 | + */ | |
542 | + case 'c': | |
543 | + case 'd': | |
544 | + case 'i': | |
545 | + case 'u': | |
546 | + case 'o': | |
547 | + case 'p': | |
548 | + case 'x': | |
549 | + case 'X': | |
550 | + vcnt = 16; | |
551 | + } | |
552 | + } | |
553 | + vfmt[j++] = ch; | |
554 | + vfmt[j++] = '\0'; | |
555 | + | |
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); \ | |
561 | + } else { \ | |
562 | + switch (cnt) { \ | |
563 | + default: \ | |
564 | + /* The default case should never happen. */ \ | |
565 | + case 4: \ | |
566 | + velm.i = (unsigned)vval.vintarg[ind]; \ | |
567 | + break; \ | |
568 | + case 8: \ | |
569 | + velm.i = (unsigned short)vval.vshortarg[ind]; \ | |
570 | + break; \ | |
571 | + case 16: \ | |
572 | + velm.i = (unsigned char)vval.vchararg[ind]; \ | |
573 | + break; \ | |
574 | + } \ | |
575 | + vlen = asprintf(&vstr, vfmt , ## args, velm.i); \ | |
576 | + } \ | |
577 | + ret += vlen; \ | |
578 | + PRINT(vstr, vlen); \ | |
579 | + free(vstr); \ | |
580 | +} while (0) | |
581 | + | |
582 | + /* Actually print. */ | |
583 | + if (vwidth == 0) { | |
584 | + if (vprec == 0) { | |
585 | + /* First element. */ | |
586 | + VPRINT(vcnt, 0); | |
587 | + for (i = 1; i < vcnt; i++) { | |
588 | + /* Separator. */ | |
589 | + if (vsep) | |
590 | + PRINT(&vsep, 1); | |
591 | + | |
592 | + /* Element. */ | |
593 | + VPRINT(vcnt, i); | |
594 | + } | |
595 | + } else { | |
596 | + /* First element. */ | |
597 | + VPRINT(vcnt, 0, prec); | |
598 | + for (i = 1; i < vcnt; i++) { | |
599 | + /* Separator. */ | |
600 | + if (vsep) | |
601 | + PRINT(&vsep, 1); | |
602 | + | |
603 | + /* Element. */ | |
604 | + VPRINT(vcnt, i, prec); | |
605 | + } | |
606 | + } | |
607 | + } else { | |
608 | + if (vprec == 0) { | |
609 | + /* First element. */ | |
610 | + VPRINT(vcnt, 0, width); | |
611 | + for (i = 1; i < vcnt; i++) { | |
612 | + /* Separator. */ | |
613 | + if (vsep) | |
614 | + PRINT(&vsep, 1); | |
615 | + | |
616 | + /* Element. */ | |
617 | + VPRINT(vcnt, i, width); | |
618 | + } | |
619 | + } else { | |
620 | + /* First element. */ | |
621 | + VPRINT(vcnt, 0, width, prec); | |
622 | + for (i = 1; i < vcnt; i++) { | |
623 | + /* Separator. */ | |
624 | + if (vsep) | |
625 | + PRINT(&vsep, 1); | |
626 | + | |
627 | + /* Element. */ | |
628 | + VPRINT(vcnt, i, width, prec); | |
629 | + } | |
630 | + } | |
631 | + } | |
632 | +#undef VPRINT | |
633 | + | |
634 | + if (vfmt != vfmt_buf) | |
635 | + free(vfmt); | |
636 | + | |
637 | + continue; | |
638 | + } | |
639 | +#endif /* ALTIVEC */ | |
640 | /* | |
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; | |
645 | if (sign) | |
646 | realsz++; | |
647 | - else if (ox[1]) | |
648 | + if (ox[1]) | |
649 | realsz += 2; | |
650 | ||
651 | prsize = width > realsz ? width : realsz; | |
652 | @@ -1123,9 +1498,9 @@ | |
653 | PAD(width - realsz, blanks); | |
654 | ||
655 | /* prefix */ | |
656 | - if (sign) { | |
657 | + if (sign) | |
658 | PRINT(&sign, 1); | |
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 */ | |
661 | ox[0] = '0'; | |
662 | PRINT(ox, 2); | |
663 | } | |
664 | @@ -1368,6 +1743,11 @@ | |
665 | if (flags & LONGINT) | |
666 | ADDTYPE(T_WINT); | |
667 | else | |
668 | +#ifdef ALTIVEC | |
669 | + if (flags & VECTOR) | |
670 | + ADDTYPE(T_VECTOR); | |
671 | + else | |
672 | +#endif /* ALTIVEC */ | |
673 | ADDTYPE(T_INT); | |
674 | break; | |
675 | case 'D': | |
676 | @@ -1387,6 +1767,11 @@ | |
677 | case 'f': | |
678 | case 'g': | |
679 | case 'G': | |
680 | +#ifdef ALTIVEC | |
681 | + if (flags & VECTOR) | |
682 | + ADDTYPE(T_VECTOR); | |
683 | + else | |
684 | +#endif /* ALTIVEC */ | |
685 | if (flags & LONGDBL) | |
686 | ADDTYPE(T_LONG_DOUBLE); | |
687 | else | |
688 | @@ -1415,9 +1800,19 @@ | |
689 | flags |= LONGINT; | |
690 | /*FALLTHROUGH*/ | |
691 | case 'o': | |
692 | +#ifdef ALTIVEC | |
693 | + if (flags & VECTOR) | |
694 | + ADDTYPE(T_VECTOR); | |
695 | + else | |
696 | +#endif /* ALTIVEC */ | |
697 | ADDUARG(); | |
698 | break; | |
699 | case 'p': | |
700 | +#ifdef ALTIVEC | |
701 | + if (flags & VECTOR) | |
702 | + ADDTYPE(T_VECTOR); | |
703 | + else | |
704 | +#endif /* ALTIVEC */ | |
705 | ADDTYPE(TP_VOID); | |
706 | break; | |
707 | case 'S': | |
708 | @@ -1435,6 +1830,11 @@ | |
709 | case 'u': | |
710 | case 'X': | |
711 | case 'x': | |
712 | +#ifdef ALTIVEC | |
713 | + if (flags & VECTOR) | |
714 | + ADDTYPE(T_VECTOR); | |
715 | + else | |
716 | +#endif /* ALTIVEC */ | |
717 | ADDUARG(); | |
718 | break; | |
719 | default: /* "%?" prints ?, unless ? is NUL */ | |
720 | @@ -1520,6 +1920,12 @@ | |
721 | (*argtable) [n].longdoublearg = va_arg (ap, long double); | |
722 | break; | |
723 | #endif | |
724 | +#ifdef ALTIVEC | |
725 | + case T_VECTOR: | |
726 | + if (hasAltivec) | |
727 | + ap = getvec( &((*argtable) [n]), NULL, 0, ap ); | |
728 | + break; | |
729 | +#endif /* ALTIVEC */ | |
730 | case TP_CHAR: | |
731 | (*argtable) [n].pchararg = va_arg (ap, char *); | |
732 | break; |