]> git.saurik.com Git - apple/libc.git/blame_incremental - stdio/FreeBSD/printf-pos.c
Libc-997.1.1.tar.gz
[apple/libc.git] / stdio / FreeBSD / printf-pos.c
... / ...
CommitLineData
1/*-
2 * Copyright (c) 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 4. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93";
35#endif /* LIBC_SCCS and not lint */
36#include <sys/cdefs.h>
37__FBSDID("$FreeBSD: src/lib/libc/stdio/printf-pos.c,v 1.6 2009/03/02 04:07:58 das Exp $");
38
39/*
40 * This is the code responsible for handling positional arguments
41 * (%m$ and %m$.n$) for vfprintf() and vfwprintf().
42 */
43
44#include "namespace.h"
45#include <sys/types.h>
46
47#include <stdarg.h>
48#include <stddef.h>
49#include <stdint.h>
50#include <stdio.h>
51#include <stdlib.h>
52#include <string.h>
53#include <wchar.h>
54
55#include "un-namespace.h"
56#include "printflocal.h"
57
58/*
59 * Type ids for argument type table.
60 */
61enum typeid {
62 T_UNUSED, TP_SHORT, T_INT, T_U_INT, TP_INT,
63 T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG,
64 T_PTRDIFFT, TP_PTRDIFFT, T_SSIZET, T_SIZET, TP_SSIZET,
65 T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR,
66 T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR,
67#ifdef VECTORS
68 T_VECTOR,
69#endif
70};
71
72/* An expandable array of types. */
73struct typetable {
74 enum typeid *table; /* table of types */
75 enum typeid stattable[STATIC_ARG_TBL_SIZE];
76 int tablesize; /* current size of type table */
77 int tablemax; /* largest used index in table */
78 int nextarg; /* 1-based argument index */
79};
80
81static int __grow_type_table(struct typetable *);
82static void build_arg_table (struct typetable *, va_list, union arg **);
83
84/*
85 * Initialize a struct typetable.
86 */
87static inline void
88inittypes(struct typetable *types)
89{
90 int n;
91
92 types->table = types->stattable;
93 types->tablesize = STATIC_ARG_TBL_SIZE;
94 types->tablemax = 0;
95 types->nextarg = 1;
96 for (n = 0; n < STATIC_ARG_TBL_SIZE; n++)
97 types->table[n] = T_UNUSED;
98}
99
100/*
101 * struct typetable destructor.
102 */
103static inline void
104freetypes(struct typetable *types)
105{
106
107 if (types->table != types->stattable)
108 free (types->table);
109}
110
111/*
112 * Ensure that there is space to add a new argument type to the type table.
113 * Expand the table if necessary. Returns 0 on success.
114 */
115static inline int
116_ensurespace(struct typetable *types)
117{
118
119 if (types->nextarg >= types->tablesize) {
120 if (__grow_type_table(types))
121 return (-1);
122 }
123 if (types->nextarg > types->tablemax)
124 types->tablemax = types->nextarg;
125 return (0);
126}
127
128/*
129 * Add an argument type to the table, expanding if necessary.
130 * Returns 0 on success.
131 */
132static inline int
133addtype(struct typetable *types, enum typeid type)
134{
135
136 if (_ensurespace(types))
137 return (-1);
138 types->table[types->nextarg++] = type;
139 return (0);
140}
141
142static inline int
143addsarg(struct typetable *types, int flags)
144{
145
146 if (_ensurespace(types))
147 return (-1);
148 if (flags & INTMAXT)
149 types->table[types->nextarg++] = T_INTMAXT;
150 else if (flags & SIZET)
151 types->table[types->nextarg++] = T_SSIZET;
152 else if (flags & PTRDIFFT)
153 types->table[types->nextarg++] = T_PTRDIFFT;
154 else if (flags & LLONGINT)
155 types->table[types->nextarg++] = T_LLONG;
156 else if (flags & LONGINT)
157 types->table[types->nextarg++] = T_LONG;
158 else
159 types->table[types->nextarg++] = T_INT;
160 return (0);
161}
162
163static inline int
164adduarg(struct typetable *types, int flags)
165{
166
167 if (_ensurespace(types))
168 return (-1);
169 if (flags & INTMAXT)
170 types->table[types->nextarg++] = T_UINTMAXT;
171 else if (flags & SIZET)
172 types->table[types->nextarg++] = T_SIZET;
173 else if (flags & PTRDIFFT)
174 types->table[types->nextarg++] = T_SIZET;
175 else if (flags & LLONGINT)
176 types->table[types->nextarg++] = T_U_LLONG;
177 else if (flags & LONGINT)
178 types->table[types->nextarg++] = T_U_LONG;
179 else
180 types->table[types->nextarg++] = T_U_INT;
181 return (0);
182}
183
184/*
185 * Add * arguments to the type array.
186 */
187static inline int
188addaster(struct typetable *types, char **fmtp)
189{
190 char *cp;
191 int n2;
192
193 n2 = 0;
194 cp = *fmtp;
195 while (is_digit(*cp)) {
196 n2 = 10 * n2 + to_digit(*cp);
197 cp++;
198 }
199 if (*cp == '$') {
200 int hold = types->nextarg;
201 types->nextarg = n2;
202 if (addtype(types, T_INT))
203 return (-1);
204 types->nextarg = hold;
205 *fmtp = ++cp;
206 } else {
207 if (addtype(types, T_INT))
208 return (-1);
209 }
210 return (0);
211}
212
213static inline int
214addwaster(struct typetable *types, wchar_t **fmtp)
215{
216 wchar_t *cp;
217 int n2;
218
219 n2 = 0;
220 cp = *fmtp;
221 while (is_digit(*cp)) {
222 n2 = 10 * n2 + to_digit(*cp);
223 cp++;
224 }
225 if (*cp == '$') {
226 int hold = types->nextarg;
227 types->nextarg = n2;
228 if (addtype(types, T_INT))
229 return (-1);
230 types->nextarg = hold;
231 *fmtp = ++cp;
232 } else {
233 if (addtype(types, T_INT))
234 return (-1);
235 }
236 return (0);
237}
238
239/*
240 * Find all arguments when a positional parameter is encountered. Returns a
241 * table, indexed by argument number, of pointers to each arguments. The
242 * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
243 * It will be replaces with a malloc-ed one if it overflows.
244 * Returns 0 on success. On failure, returns nonzero and sets errno.
245 */
246__private_extern__ int
247__find_arguments (const char *fmt0, va_list ap, union arg **argtable)
248{
249 char *fmt; /* format string */
250 int ch; /* character from fmt */
251 int n; /* handy integer (short term usage) */
252 int error;
253 int flags; /* flags as above */
254 int width; /* width from format (%8d), or 0 */
255 struct typetable types; /* table of types */
256
257 fmt = (char *)fmt0;
258 inittypes(&types);
259 error = 0;
260
261 /*
262 * Scan the format for conversions (`%' character).
263 */
264 for (;;) {
265 while ((ch = *fmt) != '\0' && ch != '%')
266 fmt++;
267 if (ch == '\0')
268 goto done;
269 fmt++; /* skip over '%' */
270
271 flags = 0;
272 width = 0;
273
274rflag: ch = *fmt++;
275reswitch: switch (ch) {
276 case ' ':
277 case '#':
278 goto rflag;
279 case '*':
280 if ((error = addaster(&types, &fmt)))
281 goto error;
282 goto rflag;
283 case '-':
284 case '+':
285 case '\'':
286 goto rflag;
287 case '.':
288 if ((ch = *fmt++) == '*') {
289 if ((error = addaster(&types, &fmt)))
290 goto error;
291 goto rflag;
292 }
293 while (is_digit(ch)) {
294 ch = *fmt++;
295 }
296 goto reswitch;
297 case '0':
298 goto rflag;
299 case '1': case '2': case '3': case '4':
300 case '5': case '6': case '7': case '8': case '9':
301 n = 0;
302 do {
303 n = 10 * n + to_digit(ch);
304 ch = *fmt++;
305 } while (is_digit(ch));
306 if (ch == '$') {
307 types.nextarg = n;
308 goto rflag;
309 }
310 width = n;
311 goto reswitch;
312#ifndef NO_FLOATING_POINT
313 case 'L':
314 flags |= LONGDBL;
315 goto rflag;
316#endif
317 case 'h':
318 if (flags & SHORTINT) {
319 flags &= ~SHORTINT;
320 flags |= CHARINT;
321 } else
322 flags |= SHORTINT;
323 goto rflag;
324 case 'j':
325 flags |= INTMAXT;
326 goto rflag;
327 case 'l':
328 if (flags & LONGINT) {
329 flags &= ~LONGINT;
330 flags |= LLONGINT;
331 } else
332 flags |= LONGINT;
333 goto rflag;
334 case 'q':
335 flags |= LLONGINT; /* not necessarily */
336 goto rflag;
337 case 't':
338 flags |= PTRDIFFT;
339 goto rflag;
340 case 'z':
341 flags |= SIZET;
342 goto rflag;
343 case 'C':
344 flags |= LONGINT;
345 /*FALLTHROUGH*/
346 case 'c':
347 error = addtype(&types,
348#ifdef VECTORS
349 (flags & LONGINT) ? T_WINT : ((flags & VECTOR) ? T_VECTOR : T_INT));
350#else
351 (flags & LONGINT) ? T_WINT : T_INT);
352#endif
353 if (error)
354 goto error;
355 break;
356 case 'D':
357 flags |= LONGINT;
358 /*FALLTHROUGH*/
359 case 'd':
360 case 'i':
361#ifdef VECTORS
362 if (flags & VECTOR) {
363 if ((error = addtype(&types, T_VECTOR)))
364 goto error;
365 } else
366#endif
367 if ((error = addsarg(&types, flags)))
368 goto error;
369 break;
370#ifndef NO_FLOATING_POINT
371 case 'a':
372 case 'A':
373 case 'e':
374 case 'E':
375 case 'f':
376 case 'F':
377 case 'g':
378 case 'G':
379 error = addtype(&types,
380#ifdef VECTORS
381 (flags & VECTOR) ? T_VECTOR : ((flags & LONGDBL) ? T_LONG_DOUBLE : T_DOUBLE));
382#else
383 (flags & LONGDBL) ? T_LONG_DOUBLE : T_DOUBLE);
384#endif
385 if (error)
386 goto error;
387 break;
388#endif /* !NO_FLOATING_POINT */
389 case 'n':
390 if (flags & INTMAXT)
391 error = addtype(&types, TP_INTMAXT);
392 else if (flags & PTRDIFFT)
393 error = addtype(&types, TP_PTRDIFFT);
394 else if (flags & SIZET)
395 error = addtype(&types, TP_SSIZET);
396 else if (flags & LLONGINT)
397 error = addtype(&types, TP_LLONG);
398 else if (flags & LONGINT)
399 error = addtype(&types, TP_LONG);
400 else if (flags & SHORTINT)
401 error = addtype(&types, TP_SHORT);
402 else if (flags & CHARINT)
403 error = addtype(&types, TP_SCHAR);
404 else
405 error = addtype(&types, TP_INT);
406 if (error)
407 goto error;
408 continue; /* no output */
409 case 'O':
410 flags |= LONGINT;
411 /*FALLTHROUGH*/
412 case 'o':
413#ifdef VECTORS
414 if (flags & VECTOR) {
415 if ((error = addtype(&types, T_VECTOR)))
416 goto error;
417 } else
418#endif
419 if ((error = adduarg(&types, flags)))
420 goto error;
421 break;
422 case 'p':
423#ifdef VECTORS
424 if ((error = addtype(&types, (flags & VECTOR) ? T_VECTOR : TP_VOID)))
425#else
426 if ((error = addtype(&types, TP_VOID)))
427#endif
428 goto error;
429 break;
430 case 'S':
431 flags |= LONGINT;
432 /*FALLTHROUGH*/
433 case 's':
434 error = addtype(&types,
435 (flags & LONGINT) ? TP_WCHAR : TP_CHAR);
436 if (error)
437 goto error;
438 break;
439 case 'U':
440 flags |= LONGINT;
441 /*FALLTHROUGH*/
442 case 'u':
443 case 'X':
444 case 'x':
445#ifdef VECTORS
446 if (flags & VECTOR) {
447 if ((error = addtype(&types, T_VECTOR)))
448 goto error;
449 } else
450#endif
451 if ((error = adduarg(&types, flags)))
452 goto error;
453 break;
454 default: /* "%?" prints ?, unless ? is NUL */
455 if (ch == '\0')
456 goto done;
457 break;
458 }
459 }
460done:
461 build_arg_table(&types, ap, argtable);
462error:
463 freetypes(&types);
464 return (error || *argtable == NULL);
465}
466
467/* wchar version of __find_arguments. */
468__private_extern__ int
469__find_warguments (const wchar_t *fmt0, va_list ap, union arg **argtable)
470{
471 wchar_t *fmt; /* format string */
472 wchar_t ch; /* character from fmt */
473 int n; /* handy integer (short term usage) */
474 int error;
475 int flags; /* flags as above */
476 int width; /* width from format (%8d), or 0 */
477 struct typetable types; /* table of types */
478
479 fmt = (wchar_t *)fmt0;
480 inittypes(&types);
481 error = 0;
482
483 /*
484 * Scan the format for conversions (`%' character).
485 */
486 for (;;) {
487 while ((ch = *fmt) != '\0' && ch != '%')
488 fmt++;
489 if (ch == '\0')
490 goto done;
491 fmt++; /* skip over '%' */
492
493 flags = 0;
494 width = 0;
495
496rflag: ch = *fmt++;
497reswitch: switch (ch) {
498 case ' ':
499 case '#':
500 goto rflag;
501 case '*':
502 if ((error = addwaster(&types, &fmt)))
503 goto error;
504 goto rflag;
505 case '-':
506 case '+':
507 case '\'':
508 goto rflag;
509 case '.':
510 if ((ch = *fmt++) == '*') {
511 if ((error = addwaster(&types, &fmt)))
512 goto error;
513 goto rflag;
514 }
515 while (is_digit(ch)) {
516 ch = *fmt++;
517 }
518 goto reswitch;
519 case '0':
520 goto rflag;
521 case '1': case '2': case '3': case '4':
522 case '5': case '6': case '7': case '8': case '9':
523 n = 0;
524 do {
525 n = 10 * n + to_digit(ch);
526 ch = *fmt++;
527 } while (is_digit(ch));
528 if (ch == '$') {
529 types.nextarg = n;
530 goto rflag;
531 }
532 width = n;
533 goto reswitch;
534#ifndef NO_FLOATING_POINT
535 case 'L':
536 flags |= LONGDBL;
537 goto rflag;
538#endif
539 case 'h':
540 if (flags & SHORTINT) {
541 flags &= ~SHORTINT;
542 flags |= CHARINT;
543 } else
544 flags |= SHORTINT;
545 goto rflag;
546 case 'j':
547 flags |= INTMAXT;
548 goto rflag;
549 case 'l':
550 if (flags & LONGINT) {
551 flags &= ~LONGINT;
552 flags |= LLONGINT;
553 } else
554 flags |= LONGINT;
555 goto rflag;
556 case 'q':
557 flags |= LLONGINT; /* not necessarily */
558 goto rflag;
559 case 't':
560 flags |= PTRDIFFT;
561 goto rflag;
562 case 'z':
563 flags |= SIZET;
564 goto rflag;
565 case 'C':
566 flags |= LONGINT;
567 /*FALLTHROUGH*/
568 case 'c':
569 error = addtype(&types,
570 (flags & LONGINT) ? T_WINT : T_INT);
571 if (error)
572 goto error;
573 break;
574 case 'D':
575 flags |= LONGINT;
576 /*FALLTHROUGH*/
577 case 'd':
578 case 'i':
579 if ((error = addsarg(&types, flags)))
580 goto error;
581 break;
582#ifndef NO_FLOATING_POINT
583 case 'a':
584 case 'A':
585 case 'e':
586 case 'E':
587 case 'f':
588 case 'F':
589 case 'g':
590 case 'G':
591 error = addtype(&types,
592 (flags & LONGDBL) ? T_LONG_DOUBLE : T_DOUBLE);
593 if (error)
594 goto error;
595 break;
596#endif /* !NO_FLOATING_POINT */
597 case 'n':
598 if (flags & INTMAXT)
599 error = addtype(&types, TP_INTMAXT);
600 else if (flags & PTRDIFFT)
601 error = addtype(&types, TP_PTRDIFFT);
602 else if (flags & SIZET)
603 error = addtype(&types, TP_SSIZET);
604 else if (flags & LLONGINT)
605 error = addtype(&types, TP_LLONG);
606 else if (flags & LONGINT)
607 error = addtype(&types, TP_LONG);
608 else if (flags & SHORTINT)
609 error = addtype(&types, TP_SHORT);
610 else if (flags & CHARINT)
611 error = addtype(&types, TP_SCHAR);
612 else
613 error = addtype(&types, TP_INT);
614 if (error)
615 goto error;
616 continue; /* no output */
617 case 'O':
618 flags |= LONGINT;
619 /*FALLTHROUGH*/
620 case 'o':
621 if ((error = adduarg(&types, flags)))
622 goto error;
623 break;
624 case 'p':
625 if ((error = addtype(&types, TP_VOID)))
626 goto error;
627 break;
628 case 'S':
629 flags |= LONGINT;
630 /*FALLTHROUGH*/
631 case 's':
632 error = addtype(&types,
633 (flags & LONGINT) ? TP_WCHAR : TP_CHAR);
634 if (error)
635 goto error;
636 break;
637 case 'U':
638 flags |= LONGINT;
639 /*FALLTHROUGH*/
640 case 'u':
641 case 'X':
642 case 'x':
643 if ((error = adduarg(&types, flags)))
644 goto error;
645 break;
646 default: /* "%?" prints ?, unless ? is NUL */
647 if (ch == '\0')
648 goto done;
649 break;
650 }
651 }
652done:
653 build_arg_table(&types, ap, argtable);
654error:
655 freetypes(&types);
656 return (error || *argtable == NULL);
657}
658
659/*
660 * Increase the size of the type table. Returns 0 on success.
661 */
662static int
663__grow_type_table(struct typetable *types)
664{
665 enum typeid *const oldtable = types->table;
666 const int oldsize = types->tablesize;
667 enum typeid *newtable;
668 int n, newsize = oldsize * 2;
669
670 if (newsize < types->nextarg + 1)
671 newsize = types->nextarg + 1;
672 if (oldsize == STATIC_ARG_TBL_SIZE) {
673 if ((newtable = malloc(newsize * sizeof(enum typeid))) == NULL)
674 return (-1);
675 bcopy(oldtable, newtable, oldsize * sizeof(enum typeid));
676 } else {
677 newtable = realloc(oldtable, newsize * sizeof(enum typeid));
678 if (newtable == NULL)
679 return (-1);
680 }
681 for (n = oldsize; n < newsize; n++)
682 newtable[n] = T_UNUSED;
683
684 types->table = newtable;
685 types->tablesize = newsize;
686
687 return (0);
688}
689
690/*
691 * Build the argument table from the completed type table.
692 * On malloc failure, *argtable is set to NULL.
693 */
694static void
695build_arg_table(struct typetable *types, va_list ap, union arg **argtable)
696{
697 int n;
698
699 if (types->tablemax >= STATIC_ARG_TBL_SIZE) {
700 *argtable = (union arg *)
701 malloc (sizeof (union arg) * (types->tablemax + 1));
702 if (*argtable == NULL)
703 return;
704 }
705
706 (*argtable) [0].intarg = 0;
707 for (n = 1; n <= types->tablemax; n++) {
708 switch (types->table[n]) {
709 case T_UNUSED: /* whoops! */
710 (*argtable) [n].intarg = va_arg (ap, int);
711 break;
712 case TP_SCHAR:
713 (*argtable) [n].pschararg = va_arg (ap, signed char *);
714 break;
715 case TP_SHORT:
716 (*argtable) [n].pshortarg = va_arg (ap, short *);
717 break;
718 case T_INT:
719 (*argtable) [n].intarg = va_arg (ap, int);
720 break;
721 case T_U_INT:
722 (*argtable) [n].uintarg = va_arg (ap, unsigned int);
723 break;
724 case TP_INT:
725 (*argtable) [n].pintarg = va_arg (ap, int *);
726 break;
727 case T_LONG:
728 (*argtable) [n].longarg = va_arg (ap, long);
729 break;
730 case T_U_LONG:
731 (*argtable) [n].ulongarg = va_arg (ap, unsigned long);
732 break;
733 case TP_LONG:
734 (*argtable) [n].plongarg = va_arg (ap, long *);
735 break;
736 case T_LLONG:
737 (*argtable) [n].longlongarg = va_arg (ap, long long);
738 break;
739 case T_U_LLONG:
740 (*argtable) [n].ulonglongarg = va_arg (ap, unsigned long long);
741 break;
742 case TP_LLONG:
743 (*argtable) [n].plonglongarg = va_arg (ap, long long *);
744 break;
745 case T_PTRDIFFT:
746 (*argtable) [n].ptrdiffarg = va_arg (ap, ptrdiff_t);
747 break;
748 case TP_PTRDIFFT:
749 (*argtable) [n].pptrdiffarg = va_arg (ap, ptrdiff_t *);
750 break;
751 case T_SIZET:
752 (*argtable) [n].sizearg = va_arg (ap, size_t);
753 break;
754 case T_SSIZET:
755 (*argtable) [n].sizearg = va_arg (ap, ssize_t);
756 break;
757 case TP_SSIZET:
758 (*argtable) [n].pssizearg = va_arg (ap, ssize_t *);
759 break;
760 case T_INTMAXT:
761 (*argtable) [n].intmaxarg = va_arg (ap, intmax_t);
762 break;
763 case T_UINTMAXT:
764 (*argtable) [n].uintmaxarg = va_arg (ap, uintmax_t);
765 break;
766 case TP_INTMAXT:
767 (*argtable) [n].pintmaxarg = va_arg (ap, intmax_t *);
768 break;
769 case T_DOUBLE:
770#ifndef NO_FLOATING_POINT
771 (*argtable) [n].doublearg = va_arg (ap, double);
772#endif
773 break;
774 case T_LONG_DOUBLE:
775#ifndef NO_FLOATING_POINT
776 (*argtable) [n].longdoublearg = va_arg (ap, long double);
777#endif
778 break;
779#ifdef VECTORS
780 case T_VECTOR:
781 (*argtable) [n].vectorarg = va_arg (ap, VECTORTYPE);
782 break;
783#endif /* VECTORS */
784 case TP_CHAR:
785 (*argtable) [n].pchararg = va_arg (ap, char *);
786 break;
787 case TP_VOID:
788 (*argtable) [n].pvoidarg = va_arg (ap, void *);
789 break;
790 case T_WINT:
791 (*argtable) [n].wintarg = va_arg (ap, wint_t);
792 break;
793 case TP_WCHAR:
794 (*argtable) [n].pwchararg = va_arg (ap, wchar_t *);
795 break;
796 }
797 }
798}