]>
Commit | Line | Data |
---|---|---|
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; |