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