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