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