xref: /dragonfly/lib/libc/stdio/printf-pos.c (revision cf515c3a6f3a8964ad592e524442bc628f8ed63b)
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
inittypes(struct typetable * types)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
freetypes(struct typetable * types)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
_ensurespace(struct typetable * types)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
addtype(struct typetable * types,enum typeid type)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
addsarg(struct typetable * types,int flags)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
adduarg(struct typetable * types,int flags)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
addaster(struct typetable * types,char ** fmtp)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
addwaster(struct typetable * types,wchar_t ** fmtp)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
__find_arguments(const char * fmt0,va_list ap,union arg ** argtable)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
__find_warguments(const wchar_t * fmt0,va_list ap,union arg ** argtable)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
__grow_type_table(struct typetable * types)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
build_arg_table(struct typetable * types,va_list ap,union arg ** argtable)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 }
750