]> git.saurik.com Git - apple/libc.git/blame - stdio/FreeBSD/vfwprintf.c.patch
Libc-391.2.3.tar.gz
[apple/libc.git] / stdio / FreeBSD / vfwprintf.c.patch
CommitLineData
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;