]>
Commit | Line | Data |
---|---|---|
3d9156a7 | 1 | --- vfprintf.c.orig 2004-11-25 11:38:35.000000000 -0800 |
f74c7596 | 2 | +++ vfprintf.c 2005-02-24 15:16:20.000000000 -0800 |
3d9156a7 A |
3 | @@ -40,6 +40,8 @@ |
4 | #include <sys/cdefs.h> | |
5 | __FBSDID("$FreeBSD: src/lib/libc/stdio/vfprintf.c,v 1.68 2004/08/26 06:25:28 des Exp $"); | |
6 | ||
7 | +#include "xlocale_private.h" | |
8 | + | |
9 | /* | |
10 | * Actual printf innards. | |
11 | * | |
12 | @@ -58,6 +60,7 @@ | |
51631861 A |
13 | #include <stdlib.h> |
14 | #include <string.h> | |
15 | #include <wchar.h> | |
16 | +#include <errno.h> | |
17 | ||
18 | #include <stdarg.h> | |
19 | #include "un-namespace.h" | |
f74c7596 | 20 | @@ -66,6 +69,12 @@ |
9385eb3d A |
21 | #include "local.h" |
22 | #include "fvwrite.h" | |
23 | ||
f74c7596 A |
24 | +#ifdef ALTIVEC |
25 | +#include <machine/cpu_capabilities.h> | |
26 | + | |
27 | +#define VECTORTYPE vector unsigned char | |
28 | +#endif /* ALTIVEC */ | |
9385eb3d A |
29 | + |
30 | union arg { | |
31 | int intarg; | |
32 | u_int uintarg; | |
f74c7596 | 33 | @@ -93,6 +102,16 @@ |
9385eb3d A |
34 | #endif |
35 | wint_t wintarg; | |
36 | wchar_t *pwchararg; | |
f74c7596 | 37 | +#ifdef ALTIVEC |
9385eb3d A |
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]; | |
f74c7596 | 46 | +#endif /* ALTIVEC */ |
9385eb3d A |
47 | }; |
48 | ||
49 | /* | |
f74c7596 | 50 | @@ -103,19 +122,56 @@ |
9385eb3d A |
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, | |
f74c7596 | 54 | +#ifdef ALTIVEC |
9385eb3d | 55 | + T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR, T_VECTOR |
f74c7596 | 56 | +#else /* ! ALTIVEC */ |
9385eb3d | 57 | T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR |
f74c7596 | 58 | +#endif /* ALTIVEC */ |
9385eb3d A |
59 | }; |
60 | ||
61 | static int __sprint(FILE *, struct __suio *); | |
3d9156a7 A |
62 | -static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0); |
63 | +static int __sbprintf(FILE *, locale_t, const char *, va_list) __printflike(3, 0); | |
64 | static char *__ujtoa(uintmax_t, char *, int, int, const char *, int, char, | |
65 | const char *); | |
66 | static char *__ultoa(u_long, char *, int, int, const char *, int, char, | |
67 | const char *); | |
68 | -static char *__wcsconv(wchar_t *, int); | |
69 | +static char *__wcsconv(wchar_t *, int, locale_t); | |
9385eb3d A |
70 | static void __find_arguments(const char *, va_list, union arg **); |
71 | static void __grow_type_table(int, enum typeid **, int *); | |
72 | ||
f74c7596 A |
73 | + /* |
74 | + * Get the argument indexed by nextarg. If the argument table is | |
75 | + * built, use it to get the argument. If its not, get the next | |
76 | + * argument (and arguments must be gotten sequentially). | |
77 | + */ | |
78 | +#define GETARG(type) \ | |
79 | + ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \ | |
80 | + (nextarg++, va_arg(ap, type))) | |
81 | + | |
82 | +#ifdef ALTIVEC | |
83 | +#define hasAltivec (_cpu_capabilities & kHasAltivec) | |
84 | +/*----------------------------------------------------------------------- | |
85 | + * getvec() must be a real subroutine. If it is a #define, then __vfprintf() | |
86 | + * would have its calling sequence changed by Altivec so that a non-Altivec | |
87 | + * processor would crash on illegal instruction. By isolating the calling | |
88 | + * sequence in getvec(), __vprintf() is callable by a non-Altivec processor. | |
89 | + *-----------------------------------------------------------------------*/ | |
90 | +static va_list getvec(union arg *, const union arg *, int, va_list) __attribute__((noinline)); | |
91 | + | |
92 | +static va_list | |
93 | +getvec(union arg *dst, const union arg *argtable, int nextarg, va_list ap) | |
94 | +{ | |
95 | + dst->vectorarg = GETARG(VECTORTYPE); | |
96 | + return ap; | |
97 | +} | |
98 | + | |
99 | +#define SETVEC(dst) \ | |
100 | +{ \ | |
101 | + ap = getvec(&dst, argtable, nextarg, ap); \ | |
102 | + nextarg++; \ | |
103 | +} | |
104 | +#endif /* ALTIVEC */ | |
105 | + | |
106 | /* | |
107 | * Flush out all the vectors defined by the given uio, | |
108 | * then reset it so that it can be reused. | |
109 | @@ -141,7 +197,7 @@ | |
3d9156a7 A |
110 | * worries about ungetc buffers and so forth. |
111 | */ | |
112 | static int | |
113 | -__sbprintf(FILE *fp, const char *fmt, va_list ap) | |
114 | +__sbprintf(FILE *fp, locale_t loc, const char *fmt, va_list ap) | |
115 | { | |
116 | int ret; | |
117 | FILE fake; | |
f74c7596 | 118 | @@ -160,7 +216,7 @@ |
3d9156a7 A |
119 | fake._lbfsize = 0; /* not actually used, but Just In Case */ |
120 | ||
121 | /* do the work, then copy any error status */ | |
122 | - ret = __vfprintf(&fake, fmt, ap); | |
123 | + ret = __vfprintf(&fake, loc, fmt, ap); | |
124 | if (ret >= 0 && __fflush(&fake)) | |
125 | ret = EOF; | |
126 | if (fake._flags & __SERR) | |
f74c7596 | 127 | @@ -336,7 +392,7 @@ |
3d9156a7 A |
128 | * that the wide char. string ends in a null character. |
129 | */ | |
130 | static char * | |
131 | -__wcsconv(wchar_t *wcsarg, int prec) | |
132 | +__wcsconv(wchar_t *wcsarg, int prec, locale_t loc) | |
133 | { | |
134 | static const mbstate_t initial; | |
135 | mbstate_t mbs; | |
f74c7596 | 136 | @@ -354,7 +410,7 @@ |
3d9156a7 A |
137 | p = wcsarg; |
138 | mbs = initial; | |
139 | for (;;) { | |
140 | - clen = wcrtomb(buf, *p++, &mbs); | |
141 | + clen = wcrtomb_l(buf, *p++, &mbs, loc); | |
142 | if (clen == 0 || clen == (size_t)-1 || | |
143 | nbytes + clen > prec) | |
144 | break; | |
f74c7596 | 145 | @@ -363,7 +419,7 @@ |
3d9156a7 A |
146 | } else { |
147 | p = wcsarg; | |
148 | mbs = initial; | |
149 | - nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs); | |
150 | + nbytes = wcsrtombs_l(NULL, (const wchar_t **)&p, 0, &mbs, loc); | |
151 | if (nbytes == (size_t)-1) | |
152 | return (NULL); | |
153 | } | |
f74c7596 | 154 | @@ -378,7 +434,7 @@ |
3d9156a7 A |
155 | p = wcsarg; |
156 | mbs = initial; | |
157 | while (mbp - convbuf < nbytes) { | |
158 | - clen = wcrtomb(mbp, *p++, &mbs); | |
159 | + clen = wcrtomb_l(mbp, *p++, &mbs, loc); | |
160 | if (clen == 0 || clen == (size_t)-1) | |
161 | break; | |
162 | mbp += clen; | |
f74c7596 | 163 | @@ -402,7 +458,21 @@ |
3d9156a7 A |
164 | int ret; |
165 | ||
166 | FLOCKFILE(fp); | |
167 | - ret = __vfprintf(fp, fmt0, ap); | |
168 | + ret = __vfprintf(fp, __current_locale(), fmt0, ap); | |
169 | + FUNLOCKFILE(fp); | |
170 | + return (ret); | |
171 | +} | |
172 | + | |
173 | +int | |
174 | +vfprintf_l(FILE * __restrict fp, locale_t loc, const char * __restrict fmt0, | |
175 | + va_list ap) | |
176 | + | |
177 | +{ | |
178 | + int ret; | |
179 | + | |
180 | + NORMALIZE_LOCALE(loc); | |
181 | + FLOCKFILE(fp); | |
182 | + ret = __vfprintf(fp, loc, fmt0, ap); | |
183 | FUNLOCKFILE(fp); | |
184 | return (ret); | |
185 | } | |
f74c7596 | 186 | @@ -451,12 +521,15 @@ |
9385eb3d A |
187 | #define PTRDIFFT 0x800 /* ptrdiff_t */ |
188 | #define INTMAXT 0x1000 /* intmax_t */ | |
189 | #define CHARINT 0x2000 /* print char using int format */ | |
f74c7596 A |
190 | +#ifdef ALTIVEC |
191 | +#define VECTOR 0x4000 /* Altivec vector */ | |
192 | +#endif /* ALTIVEC */ | |
9385eb3d A |
193 | |
194 | /* | |
195 | * Non-MT-safe version | |
3d9156a7 A |
196 | */ |
197 | -int | |
198 | -__vfprintf(FILE *fp, const char *fmt0, va_list ap) | |
199 | +__private_extern__ int | |
200 | +__vfprintf(FILE *fp, locale_t loc, const char *fmt0, va_list ap) | |
201 | { | |
202 | char *fmt; /* format string */ | |
203 | int ch; /* character from fmt */ | |
f74c7596 | 204 | @@ -502,6 +575,11 @@ |
9385eb3d A |
205 | int nseps; /* number of group separators with ' */ |
206 | int nrepeats; /* number of repeats of the last group */ | |
207 | #endif | |
f74c7596 | 208 | +#ifdef ALTIVEC |
9385eb3d A |
209 | + union arg vval; /* Vector argument. */ |
210 | + char *pct; /* Pointer to '%' at beginning of specifier. */ | |
211 | + char vsep; /* Vector separator character. */ | |
212 | +#endif | |
213 | u_long ulval; /* integer arguments %[diouxX] */ | |
214 | uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */ | |
215 | int base; /* base for [diouxX] conversion */ | |
f74c7596 A |
216 | @@ -574,15 +652,6 @@ |
217 | } | |
218 | ||
219 | /* | |
220 | - * Get the argument indexed by nextarg. If the argument table is | |
221 | - * built, use it to get the argument. If its not, get the next | |
222 | - * argument (and arguments must be gotten sequentially). | |
223 | - */ | |
224 | -#define GETARG(type) \ | |
225 | - ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \ | |
226 | - (nextarg++, va_arg(ap, type))) | |
227 | - | |
228 | - /* | |
229 | * To extend shorts properly, we need both signed and unsigned | |
230 | * argument extraction methods. | |
231 | */ | |
232 | @@ -633,22 +702,23 @@ | |
9385eb3d A |
233 | val = GETARG (int); \ |
234 | } | |
235 | ||
236 | - | |
237 | thousands_sep = '\0'; | |
238 | grouping = NULL; | |
239 | convbuf = NULL; | |
3d9156a7 A |
240 | #ifndef NO_FLOATING_POINT |
241 | dtoaresult = NULL; | |
242 | - decimal_point = localeconv()->decimal_point; | |
243 | + decimal_point = localeconv_l(loc)->decimal_point; | |
51631861 A |
244 | #endif |
245 | /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */ | |
3d9156a7 A |
246 | - if (prepwrite(fp) != 0) |
247 | + if (prepwrite(fp) != 0) { | |
51631861 A |
248 | + errno = EBADF; |
249 | return (EOF); | |
250 | + } | |
251 | ||
252 | /* optimise fprintf(stderr) (and other unbuffered Unix files) */ | |
253 | if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && | |
3d9156a7 A |
254 | fp->_file >= 0) |
255 | - return (__sbprintf(fp, fmt0, ap)); | |
256 | + return (__sbprintf(fp, loc, fmt0, ap)); | |
257 | ||
258 | fmt = (char *)fmt0; | |
259 | argtable = NULL; | |
f74c7596 | 260 | @@ -675,6 +745,9 @@ |
9385eb3d A |
261 | } |
262 | if (ch == '\0') | |
263 | goto done; | |
f74c7596 | 264 | +#ifdef ALTIVEC |
9385eb3d | 265 | + pct = fmt; |
f74c7596 | 266 | +#endif /* ALTIVEC */ |
9385eb3d A |
267 | fmt++; /* skip over '%' */ |
268 | ||
269 | flags = 0; | |
f74c7596 | 270 | @@ -683,6 +756,9 @@ |
9385eb3d A |
271 | prec = -1; |
272 | sign = '\0'; | |
273 | ox[1] = '\0'; | |
f74c7596 | 274 | +#ifdef ALTIVEC |
9385eb3d | 275 | + vsep = 'X'; /* Illegal value, changed to defaults later. */ |
f74c7596 | 276 | +#endif /* ALTIVEC */ |
9385eb3d A |
277 | |
278 | rflag: ch = *fmt++; | |
279 | reswitch: switch (ch) { | |
f74c7596 | 280 | @@ -698,6 +774,11 @@ |
9385eb3d A |
281 | case '#': |
282 | flags |= ALT; | |
283 | goto rflag; | |
f74c7596 | 284 | +#ifdef ALTIVEC |
9385eb3d A |
285 | + case ',': case ';': case ':': case '_': |
286 | + vsep = ch; | |
287 | + goto rflag; | |
f74c7596 | 288 | +#endif /* ALTIVEC */ |
9385eb3d A |
289 | case '*': |
290 | /*- | |
291 | * ``A negative field width argument is taken as a | |
f74c7596 | 292 | @@ -718,8 +799,8 @@ |
3d9156a7 A |
293 | goto rflag; |
294 | case '\'': | |
295 | flags |= GROUPING; | |
296 | - thousands_sep = *(localeconv()->thousands_sep); | |
297 | - grouping = localeconv()->grouping; | |
298 | + thousands_sep = *(localeconv_l(loc)->thousands_sep); | |
299 | + grouping = localeconv_l(loc)->grouping; | |
300 | goto rflag; | |
301 | case '.': | |
302 | if ((ch = *fmt++) == '*') { | |
f74c7596 | 303 | @@ -793,14 +874,20 @@ |
59e0d9fe A |
304 | flags |= LONGINT; |
305 | /*FALLTHROUGH*/ | |
306 | case 'c': | |
f74c7596 A |
307 | +#ifdef ALTIVEC |
308 | + if (flags & VECTOR) { | |
309 | + SETVEC(vval); | |
59e0d9fe | 310 | + break; |
f74c7596 A |
311 | + } |
312 | +#endif /* ALTIVEC */ | |
59e0d9fe A |
313 | if (flags & LONGINT) { |
314 | static const mbstate_t initial; | |
315 | mbstate_t mbs; | |
3d9156a7 A |
316 | size_t mbseqlen; |
317 | ||
318 | mbs = initial; | |
319 | - mbseqlen = wcrtomb(cp = buf, | |
320 | - (wchar_t)GETARG(wint_t), &mbs); | |
321 | + mbseqlen = wcrtomb_l(cp = buf, | |
322 | + (wchar_t)GETARG(wint_t), &mbs, loc); | |
323 | if (mbseqlen == (size_t)-1) { | |
324 | fp->_flags |= __SERR; | |
325 | goto error; | |
f74c7596 | 326 | @@ -817,6 +904,12 @@ |
9385eb3d A |
327 | /*FALLTHROUGH*/ |
328 | case 'd': | |
329 | case 'i': | |
f74c7596 A |
330 | +#ifdef ALTIVEC |
331 | + if (flags & VECTOR) { | |
332 | + SETVEC(vval); | |
9385eb3d | 333 | + break; |
f74c7596 A |
334 | + } |
335 | +#endif /* ALTIVEC */ | |
9385eb3d A |
336 | if (flags & INTMAX_SIZE) { |
337 | ujval = SJARG(); | |
338 | if ((intmax_t)ujval < 0) { | |
f74c7596 | 339 | @@ -835,6 +928,13 @@ |
59e0d9fe | 340 | #ifndef NO_FLOATING_POINT |
9385eb3d A |
341 | case 'a': |
342 | case 'A': | |
f74c7596 | 343 | +#ifdef ALTIVEC |
9385eb3d A |
344 | + if (flags & VECTOR) { |
345 | + flags |= FPT; | |
f74c7596 | 346 | + SETVEC(vval); |
9385eb3d A |
347 | + break; |
348 | + } | |
f74c7596 | 349 | +#endif /* ALTIVEC */ |
9385eb3d A |
350 | if (ch == 'a') { |
351 | ox[1] = 'x'; | |
352 | xdigs = xdigs_lower; | |
f74c7596 | 353 | @@ -848,6 +948,12 @@ |
3d9156a7 A |
354 | prec++; |
355 | if (dtoaresult != NULL) | |
356 | freedtoa(dtoaresult); | |
357 | +#ifdef LDBL_COMPAT | |
358 | + fparg.dbl = GETARG(double); | |
359 | + dtoaresult = cp = | |
360 | + __hdtoa(fparg.dbl, xdigs, prec, | |
361 | + &expt, &signflag, &dtoaend); | |
362 | +#else /* !LDBL_COMPAT */ | |
363 | if (flags & LONGDBL) { | |
364 | fparg.ldbl = GETARG(long double); | |
365 | dtoaresult = cp = | |
f74c7596 | 366 | @@ -859,6 +965,7 @@ |
3d9156a7 A |
367 | __hdtoa(fparg.dbl, xdigs, prec, |
368 | &expt, &signflag, &dtoaend); | |
369 | } | |
370 | +#endif /* LDBL_COMPAT */ | |
371 | if (prec < 0) | |
372 | prec = dtoaend - cp; | |
373 | if (expt == INT_MAX) | |
f74c7596 | 374 | @@ -866,6 +973,13 @@ |
59e0d9fe | 375 | goto fp_common; |
9385eb3d A |
376 | case 'e': |
377 | case 'E': | |
f74c7596 | 378 | +#ifdef ALTIVEC |
9385eb3d A |
379 | + if (flags & VECTOR) { |
380 | + flags |= FPT; | |
f74c7596 | 381 | + SETVEC(vval); |
9385eb3d A |
382 | + break; |
383 | + } | |
f74c7596 | 384 | +#endif /* ALTIVEC */ |
9385eb3d A |
385 | expchar = ch; |
386 | if (prec < 0) /* account for digit before decpt */ | |
387 | prec = DEFPREC + 1; | |
f74c7596 | 388 | @@ -874,10 +988,24 @@ |
9385eb3d A |
389 | goto fp_begin; |
390 | case 'f': | |
391 | case 'F': | |
f74c7596 | 392 | +#ifdef ALTIVEC |
9385eb3d A |
393 | + if (flags & VECTOR) { |
394 | + flags |= FPT; | |
f74c7596 | 395 | + SETVEC(vval); |
9385eb3d A |
396 | + break; |
397 | + } | |
f74c7596 | 398 | +#endif /* ALTIVEC */ |
9385eb3d A |
399 | expchar = '\0'; |
400 | goto fp_begin; | |
401 | case 'g': | |
402 | case 'G': | |
f74c7596 | 403 | +#ifdef ALTIVEC |
9385eb3d A |
404 | + if (flags & VECTOR) { |
405 | + flags |= FPT; | |
f74c7596 | 406 | + SETVEC(vval); |
9385eb3d A |
407 | + break; |
408 | + } | |
f74c7596 | 409 | +#endif /* ALTIVEC */ |
9385eb3d A |
410 | expchar = ch - ('g' - 'e'); |
411 | if (prec == 0) | |
412 | prec = 1; | |
f74c7596 | 413 | @@ -886,6 +1014,14 @@ |
3d9156a7 A |
414 | prec = DEFPREC; |
415 | if (dtoaresult != NULL) | |
416 | freedtoa(dtoaresult); | |
417 | +#ifdef LDBL_COMPAT | |
418 | + fparg.dbl = GETARG(double); | |
419 | + dtoaresult = cp = | |
420 | + dtoa(fparg.dbl, expchar ? 2 : 3, prec, | |
421 | + &expt, &signflag, &dtoaend); | |
422 | + if (expt == 9999) | |
423 | + expt = INT_MAX; | |
424 | +#else /* !LDBL_COMPAT */ | |
425 | if (flags & LONGDBL) { | |
426 | fparg.ldbl = GETARG(long double); | |
427 | dtoaresult = cp = | |
f74c7596 | 428 | @@ -899,6 +1035,7 @@ |
3d9156a7 A |
429 | if (expt == 9999) |
430 | expt = INT_MAX; | |
431 | } | |
432 | +#endif /* LDBL_COMPAT */ | |
433 | fp_common: | |
434 | if (signflag) | |
435 | sign = '-'; | |
f74c7596 | 436 | @@ -993,6 +1130,12 @@ |
9385eb3d A |
437 | flags |= LONGINT; |
438 | /*FALLTHROUGH*/ | |
439 | case 'o': | |
f74c7596 A |
440 | +#ifdef ALTIVEC |
441 | + if (flags & VECTOR) { | |
442 | + SETVEC(vval); | |
9385eb3d | 443 | + break; |
f74c7596 A |
444 | + } |
445 | +#endif /* ALTIVEC */ | |
9385eb3d A |
446 | if (flags & INTMAX_SIZE) |
447 | ujval = UJARG(); | |
448 | else | |
f74c7596 | 449 | @@ -1007,6 +1150,12 @@ |
9385eb3d A |
450 | * defined manner.'' |
451 | * -- ANSI X3J11 | |
452 | */ | |
f74c7596 A |
453 | +#ifdef ALTIVEC |
454 | + if (flags & VECTOR) { | |
455 | + SETVEC(vval); | |
9385eb3d | 456 | + break; |
f74c7596 A |
457 | + } |
458 | +#endif /* ALTIVEC */ | |
9385eb3d A |
459 | ujval = (uintmax_t)(uintptr_t)GETARG(void *); |
460 | base = 16; | |
461 | xdigs = xdigs_lower; | |
f74c7596 | 462 | @@ -1025,7 +1174,7 @@ |
3d9156a7 A |
463 | if ((wcp = GETARG(wchar_t *)) == NULL) |
464 | cp = "(null)"; | |
465 | else { | |
466 | - convbuf = __wcsconv(wcp, prec); | |
467 | + convbuf = __wcsconv(wcp, prec, loc); | |
468 | if (convbuf == NULL) { | |
469 | fp->_flags |= __SERR; | |
470 | goto error; | |
f74c7596 | 471 | @@ -1056,6 +1205,12 @@ |
9385eb3d A |
472 | flags |= LONGINT; |
473 | /*FALLTHROUGH*/ | |
474 | case 'u': | |
f74c7596 A |
475 | +#ifdef ALTIVEC |
476 | + if (flags & VECTOR) { | |
477 | + SETVEC(vval); | |
9385eb3d | 478 | + break; |
f74c7596 A |
479 | + } |
480 | +#endif /* ALTIVEC */ | |
9385eb3d A |
481 | if (flags & INTMAX_SIZE) |
482 | ujval = UJARG(); | |
483 | else | |
f74c7596 | 484 | @@ -1068,6 +1223,12 @@ |
9385eb3d A |
485 | case 'x': |
486 | xdigs = xdigs_lower; | |
487 | hex: | |
f74c7596 A |
488 | +#ifdef ALTIVEC |
489 | + if (flags & VECTOR) { | |
490 | + SETVEC(vval); | |
9385eb3d | 491 | + break; |
f74c7596 A |
492 | + } |
493 | +#endif /* ALTIVEC */ | |
9385eb3d A |
494 | if (flags & INTMAX_SIZE) |
495 | ujval = UJARG(); | |
496 | else | |
f74c7596 | 497 | @@ -1112,6 +1273,14 @@ |
9385eb3d A |
498 | if (size > BUF) /* should never happen */ |
499 | abort(); | |
500 | break; | |
f74c7596 | 501 | +#ifdef ALTIVEC |
9385eb3d | 502 | + case 'v': |
f74c7596 A |
503 | + if (hasAltivec) { |
504 | + flags |= VECTOR; | |
505 | + goto rflag; | |
506 | + } | |
507 | + /* drap through */ | |
508 | +#endif /* ALTIVEC */ | |
9385eb3d A |
509 | default: /* "%?" prints ?, unless ? is NUL */ |
510 | if (ch == '\0') | |
511 | goto done; | |
f74c7596 | 512 | @@ -1123,6 +1292,184 @@ |
9385eb3d A |
513 | break; |
514 | } | |
515 | ||
f74c7596 | 516 | +#ifdef ALTIVEC |
9385eb3d A |
517 | + if (flags & VECTOR) { |
518 | + /* | |
519 | + * Do the minimum amount of work necessary to construct | |
520 | + * a format specifier that can be used to recursively | |
521 | + * call vfprintf() for each element in the vector. | |
522 | + */ | |
523 | + int i, j; /* Counter. */ | |
524 | + int vcnt; /* Number of elements in vector. */ | |
525 | + char *vfmt; /* Pointer to format specifier. */ | |
f74c7596 | 526 | + char vfmt_buf[32]; /* Static buffer for format spec. */ |
9385eb3d A |
527 | + int vwidth = 0; /* Width specified via '*'. */ |
528 | + int vprec = 0; /* Precision specified via '*'. */ | |
f74c7596 A |
529 | + union { /* Element. */ |
530 | + int i; | |
531 | + float f; | |
532 | + } velm; | |
9385eb3d A |
533 | + char *vstr; /* Used for asprintf(). */ |
534 | + int vlen; /* Length returned by asprintf(). */ | |
535 | + | |
536 | + /* | |
537 | + * Set vfmt. If vfmt_buf may not be big enough, | |
538 | + * malloc() space, taking care to free it later. | |
539 | + */ | |
f74c7596 | 540 | + if (&fmt[-1] - pct < sizeof(vfmt_buf)) |
9385eb3d A |
541 | + vfmt = vfmt_buf; |
542 | + else | |
f74c7596 | 543 | + vfmt = (char *)malloc(&fmt[-1] - pct + 1); |
9385eb3d A |
544 | + |
545 | + /* Set the separator character, if not specified. */ | |
546 | + if (vsep == 'X') { | |
547 | + if (ch == 'c') | |
548 | + vsep = '\0'; | |
549 | + else | |
550 | + vsep = ' '; | |
551 | + } | |
552 | + | |
553 | + /* Create the format specifier. */ | |
554 | + for (i = j = 0; i < &fmt[-1] - pct; i++) { | |
555 | + switch (pct[i]) { | |
556 | + case ',': case ';': case ':': case '_': | |
557 | + case 'v': case 'h': case 'l': | |
558 | + /* Ignore. */ | |
559 | + break; | |
560 | + case '*': | |
561 | + if (pct[i - 1] != '.') | |
562 | + vwidth = 1; | |
563 | + else | |
564 | + vprec = 1; | |
565 | + /* FALLTHROUGH */ | |
566 | + default: | |
567 | + vfmt[j++] = pct[i]; | |
568 | + } | |
569 | + } | |
570 | + | |
571 | + /* | |
572 | + * Determine the number of elements in the vector and | |
573 | + * finish up the format specifier. | |
574 | + */ | |
575 | + if (flags & SHORTINT) { | |
f74c7596 | 576 | + if (ch != 'c') |
59e0d9fe | 577 | + vfmt[j++] = 'h'; |
9385eb3d A |
578 | + vcnt = 8; |
579 | + } else if (flags & LONGINT) { | |
f74c7596 | 580 | + if (ch != 'c') |
7c78c529 | 581 | + vfmt[j++] = 'l'; |
f74c7596 | 582 | + vcnt = 4; |
9385eb3d A |
583 | + } else { |
584 | + switch (ch) { | |
585 | + case 'a': | |
586 | + case 'A': | |
587 | + case 'e': | |
588 | + case 'E': | |
589 | + case 'f': | |
590 | + case 'g': | |
591 | + case 'G': | |
592 | + vcnt = 4; | |
593 | + break; | |
594 | + default: | |
595 | + /* | |
596 | + * The default case should never | |
597 | + * happen. | |
598 | + */ | |
f74c7596 | 599 | + case 'c': |
9385eb3d A |
600 | + case 'd': |
601 | + case 'i': | |
602 | + case 'u': | |
603 | + case 'o': | |
f74c7596 | 604 | + case 'p': |
9385eb3d A |
605 | + case 'x': |
606 | + case 'X': | |
607 | + vcnt = 16; | |
608 | + } | |
609 | + } | |
610 | + vfmt[j++] = ch; | |
611 | + vfmt[j++] = '\0'; | |
612 | + | |
613 | +/* Get a vector element. */ | |
f74c7596 A |
614 | +#define VPRINT(cnt, ind, args...) do { \ |
615 | + if (flags & FPT) { \ | |
616 | + velm.f = vval.vfloatarg[ind]; \ | |
617 | + vlen = asprintf_l(&vstr, loc, vfmt , ## args, velm.f); \ | |
618 | + } else { \ | |
619 | + switch (cnt) { \ | |
620 | + default: \ | |
621 | + /* The default case should never happen. */ \ | |
622 | + case 4: \ | |
623 | + velm.i = (unsigned)vval.vintarg[ind]; \ | |
624 | + break; \ | |
625 | + case 8: \ | |
626 | + velm.i = (unsigned short)vval.vshortarg[ind]; \ | |
627 | + break; \ | |
628 | + case 16: \ | |
629 | + velm.i = (unsigned char)vval.vchararg[ind]; \ | |
630 | + break; \ | |
631 | + } \ | |
632 | + vlen = asprintf_l(&vstr, loc, vfmt , ## args, velm.i); \ | |
9385eb3d A |
633 | + } \ |
634 | + ret += vlen; \ | |
635 | + PRINT(vstr, vlen); \ | |
636 | + FLUSH(); \ | |
637 | + free(vstr); \ | |
638 | +} while (0) | |
639 | + | |
640 | + /* Actually print. */ | |
641 | + if (vwidth == 0) { | |
642 | + if (vprec == 0) { | |
643 | + /* First element. */ | |
f74c7596 | 644 | + VPRINT(vcnt, 0); |
9385eb3d A |
645 | + for (i = 1; i < vcnt; i++) { |
646 | + /* Separator. */ | |
f74c7596 | 647 | + PRINT(&vsep, 1); |
9385eb3d A |
648 | + |
649 | + /* Element. */ | |
f74c7596 | 650 | + VPRINT(vcnt, i); |
9385eb3d A |
651 | + } |
652 | + } else { | |
653 | + /* First element. */ | |
f74c7596 | 654 | + VPRINT(vcnt, 0, prec); |
9385eb3d A |
655 | + for (i = 1; i < vcnt; i++) { |
656 | + /* Separator. */ | |
f74c7596 | 657 | + PRINT(&vsep, 1); |
9385eb3d A |
658 | + |
659 | + /* Element. */ | |
f74c7596 | 660 | + VPRINT(vcnt, i, prec); |
9385eb3d A |
661 | + } |
662 | + } | |
663 | + } else { | |
664 | + if (vprec == 0) { | |
665 | + /* First element. */ | |
f74c7596 | 666 | + VPRINT(vcnt, 0, width); |
9385eb3d A |
667 | + for (i = 1; i < vcnt; i++) { |
668 | + /* Separator. */ | |
f74c7596 | 669 | + PRINT(&vsep, 1); |
9385eb3d A |
670 | + |
671 | + /* Element. */ | |
f74c7596 | 672 | + VPRINT(vcnt, i, width); |
9385eb3d A |
673 | + } |
674 | + } else { | |
675 | + /* First element. */ | |
f74c7596 | 676 | + VPRINT(vcnt, 0, width, prec); |
9385eb3d A |
677 | + for (i = 1; i < vcnt; i++) { |
678 | + /* Separator. */ | |
f74c7596 | 679 | + PRINT(&vsep, 1); |
9385eb3d A |
680 | + |
681 | + /* Element. */ | |
f74c7596 | 682 | + VPRINT(vcnt, i, width, prec); |
9385eb3d A |
683 | + } |
684 | + } | |
685 | + } | |
686 | +#undef VPRINT | |
687 | + | |
688 | + if (vfmt != vfmt_buf) | |
689 | + free(vfmt); | |
690 | + | |
691 | + continue; | |
692 | + } | |
f74c7596 | 693 | +#endif /* ALTIVEC */ |
9385eb3d A |
694 | /* |
695 | * All reasonable formats wind up here. At this point, `cp' | |
696 | * points to a string which (if not flags&LADJUST) should be | |
f74c7596 | 697 | @@ -1406,6 +1753,11 @@ |
9385eb3d A |
698 | if (flags & LONGINT) |
699 | ADDTYPE(T_WINT); | |
700 | else | |
f74c7596 | 701 | +#ifdef ALTIVEC |
9385eb3d A |
702 | + if (flags & VECTOR) |
703 | + ADDTYPE(T_VECTOR); | |
704 | + else | |
f74c7596 | 705 | +#endif /* ALTIVEC */ |
9385eb3d A |
706 | ADDTYPE(T_INT); |
707 | break; | |
708 | case 'D': | |
f74c7596 | 709 | @@ -1413,6 +1765,11 @@ |
9385eb3d A |
710 | /*FALLTHROUGH*/ |
711 | case 'd': | |
712 | case 'i': | |
f74c7596 | 713 | +#ifdef ALTIVEC |
9385eb3d A |
714 | + if (flags & VECTOR) |
715 | + ADDTYPE(T_VECTOR); | |
716 | + else | |
717 | +#endif | |
718 | ADDSARG(); | |
719 | break; | |
59e0d9fe | 720 | #ifndef NO_FLOATING_POINT |
f74c7596 | 721 | @@ -1423,6 +1780,11 @@ |
9385eb3d A |
722 | case 'f': |
723 | case 'g': | |
724 | case 'G': | |
f74c7596 | 725 | +#ifdef ALTIVEC |
9385eb3d A |
726 | + if (flags & VECTOR) |
727 | + ADDTYPE(T_VECTOR); | |
728 | + else | |
f74c7596 | 729 | +#endif /* ALTIVEC */ |
9385eb3d A |
730 | if (flags & LONGDBL) |
731 | ADDTYPE(T_LONG_DOUBLE); | |
732 | else | |
f74c7596 | 733 | @@ -1451,9 +1813,19 @@ |
9385eb3d A |
734 | flags |= LONGINT; |
735 | /*FALLTHROUGH*/ | |
736 | case 'o': | |
f74c7596 | 737 | +#ifdef ALTIVEC |
9385eb3d A |
738 | + if (flags & VECTOR) |
739 | + ADDTYPE(T_VECTOR); | |
740 | + else | |
f74c7596 | 741 | +#endif /* ALTIVEC */ |
9385eb3d A |
742 | ADDUARG(); |
743 | break; | |
744 | case 'p': | |
f74c7596 | 745 | +#ifdef ALTIVEC |
9385eb3d A |
746 | + if (flags & VECTOR) |
747 | + ADDTYPE(T_VECTOR); | |
748 | + else | |
f74c7596 | 749 | +#endif /* ALTIVEC */ |
9385eb3d A |
750 | ADDTYPE(TP_VOID); |
751 | break; | |
752 | case 'S': | |
f74c7596 | 753 | @@ -1471,6 +1843,11 @@ |
9385eb3d A |
754 | case 'u': |
755 | case 'X': | |
756 | case 'x': | |
f74c7596 | 757 | +#ifdef ALTIVEC |
9385eb3d A |
758 | + if (flags & VECTOR) |
759 | + ADDTYPE(T_VECTOR); | |
760 | + else | |
f74c7596 | 761 | +#endif /* ALTIVEC */ |
9385eb3d A |
762 | ADDUARG(); |
763 | break; | |
764 | default: /* "%?" prints ?, unless ? is NUL */ | |
f74c7596 | 765 | @@ -1537,7 +1914,7 @@ |
3d9156a7 A |
766 | (*argtable) [n].sizearg = va_arg (ap, size_t); |
767 | break; | |
768 | case TP_SIZET: | |
769 | - (*argtable) [n].psizearg = va_arg (ap, ssize_t *); | |
770 | + (*argtable) [n].psizearg = va_arg (ap, size_t *); | |
771 | break; | |
772 | case T_INTMAXT: | |
773 | (*argtable) [n].intmaxarg = va_arg (ap, intmax_t); | |
f74c7596 | 774 | @@ -1556,6 +1933,12 @@ |
9385eb3d A |
775 | (*argtable) [n].longdoublearg = va_arg (ap, long double); |
776 | break; | |
777 | #endif | |
f74c7596 | 778 | +#ifdef ALTIVEC |
9385eb3d | 779 | + case T_VECTOR: |
f74c7596 A |
780 | + if (hasAltivec) |
781 | + ap = getvec( &((*argtable) [n]), NULL, 0, ap ); | |
9385eb3d | 782 | + break; |
f74c7596 | 783 | +#endif /* ALTIVEC */ |
9385eb3d A |
784 | case TP_CHAR: |
785 | (*argtable) [n].pchararg = va_arg (ap, char *); | |
786 | break; |