]>
git.saurik.com Git - apple/libc.git/blob - stdio/FreeBSD/printf-pos.c
2 * Copyright (c) 1990, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
33 #if defined(LIBC_SCCS) && !defined(lint)
34 static 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 $");
40 * This is the code responsible for handling positional arguments
41 * (%m$ and %m$.n$) for vfprintf() and vfwprintf().
44 #include "namespace.h"
45 #include <sys/types.h>
55 #include "un-namespace.h"
56 #include "printflocal.h"
59 * Type ids for argument type table.
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
,
72 /* An expandable array of types. */
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 */
81 static int __grow_type_table(struct typetable
*);
82 static void build_arg_table (struct typetable
*, va_list, union arg
**);
85 * Initialize a struct typetable.
88 inittypes(struct typetable
*types
)
92 types
->table
= types
->stattable
;
93 types
->tablesize
= STATIC_ARG_TBL_SIZE
;
96 for (n
= 0; n
< STATIC_ARG_TBL_SIZE
; n
++)
97 types
->table
[n
] = T_UNUSED
;
101 * struct typetable destructor.
104 freetypes(struct typetable
*types
)
107 if (types
->table
!= types
->stattable
)
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.
116 _ensurespace(struct typetable
*types
)
119 if (types
->nextarg
>= types
->tablesize
) {
120 if (__grow_type_table(types
))
123 if (types
->nextarg
> types
->tablemax
)
124 types
->tablemax
= types
->nextarg
;
129 * Add an argument type to the table, expanding if necessary.
130 * Returns 0 on success.
133 addtype(struct typetable
*types
, enum typeid type
)
136 if (_ensurespace(types
))
138 types
->table
[types
->nextarg
++] = type
;
143 addsarg(struct typetable
*types
, int flags
)
146 if (_ensurespace(types
))
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
;
159 types
->table
[types
->nextarg
++] = T_INT
;
164 adduarg(struct typetable
*types
, int flags
)
167 if (_ensurespace(types
))
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
;
180 types
->table
[types
->nextarg
++] = T_U_INT
;
185 * Add * arguments to the type array.
188 addaster(struct typetable
*types
, char **fmtp
)
195 while (is_digit(*cp
)) {
196 n2
= 10 * n2
+ to_digit(*cp
);
200 int hold
= types
->nextarg
;
202 if (addtype(types
, T_INT
))
204 types
->nextarg
= hold
;
207 if (addtype(types
, T_INT
))
214 addwaster(struct typetable
*types
, wchar_t **fmtp
)
221 while (is_digit(*cp
)) {
222 n2
= 10 * n2
+ to_digit(*cp
);
226 int hold
= types
->nextarg
;
228 if (addtype(types
, T_INT
))
230 types
->nextarg
= hold
;
233 if (addtype(types
, T_INT
))
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.
246 __private_extern__
int
247 __find_arguments (const char *fmt0
, va_list ap
, union arg
**argtable
)
249 char *fmt
; /* format string */
250 int ch
; /* character from fmt */
251 int n
; /* handy integer (short term usage) */
253 int flags
; /* flags as above */
254 int width
; /* width from format (%8d), or 0 */
255 struct typetable types
; /* table of types */
262 * Scan the format for conversions (`%' character).
265 while ((ch
= *fmt
) != '\0' && ch
!= '%')
269 fmt
++; /* skip over '%' */
275 reswitch
: switch (ch
) {
280 if ((error
= addaster(&types
, &fmt
)))
288 if ((ch
= *fmt
++) == '*') {
289 if ((error
= addaster(&types
, &fmt
)))
293 while (is_digit(ch
)) {
299 case '1': case '2': case '3': case '4':
300 case '5': case '6': case '7': case '8': case '9':
303 n
= 10 * n
+ to_digit(ch
);
305 } while (is_digit(ch
));
312 #ifndef NO_FLOATING_POINT
318 if (flags
& SHORTINT
) {
328 if (flags
& LONGINT
) {
335 flags
|= LLONGINT
; /* not necessarily */
347 error
= addtype(&types
,
349 (flags
& LONGINT
) ? T_WINT
: ((flags
& VECTOR
) ? T_VECTOR
: T_INT
));
351 (flags
& LONGINT
) ? T_WINT
: T_INT
);
362 if (flags
& VECTOR
) {
363 if ((error
= addtype(&types
, T_VECTOR
)))
367 if ((error
= addsarg(&types
, flags
)))
370 #ifndef NO_FLOATING_POINT
379 error
= addtype(&types
,
381 (flags
& VECTOR
) ? T_VECTOR
: ((flags
& LONGDBL
) ? T_LONG_DOUBLE
: T_DOUBLE
));
383 (flags
& LONGDBL
) ? T_LONG_DOUBLE
: T_DOUBLE
);
388 #endif /* !NO_FLOATING_POINT */
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
);
405 error
= addtype(&types
, TP_INT
);
408 continue; /* no output */
414 if (flags
& VECTOR
) {
415 if ((error
= addtype(&types
, T_VECTOR
)))
419 if ((error
= adduarg(&types
, flags
)))
424 if ((error
= addtype(&types
, (flags
& VECTOR
) ? T_VECTOR
: TP_VOID
)))
426 if ((error
= addtype(&types
, TP_VOID
)))
434 error
= addtype(&types
,
435 (flags
& LONGINT
) ? TP_WCHAR
: TP_CHAR
);
446 if (flags
& VECTOR
) {
447 if ((error
= addtype(&types
, T_VECTOR
)))
451 if ((error
= adduarg(&types
, flags
)))
454 default: /* "%?" prints ?, unless ? is NUL */
461 build_arg_table(&types
, ap
, argtable
);
464 return (error
|| *argtable
== NULL
);
467 /* wchar version of __find_arguments. */
468 __private_extern__
int
469 __find_warguments (const wchar_t *fmt0
, va_list ap
, union arg
**argtable
)
471 wchar_t *fmt
; /* format string */
472 wchar_t ch
; /* character from fmt */
473 int n
; /* handy integer (short term usage) */
475 int flags
; /* flags as above */
476 int width
; /* width from format (%8d), or 0 */
477 struct typetable types
; /* table of types */
479 fmt
= (wchar_t *)fmt0
;
484 * Scan the format for conversions (`%' character).
487 while ((ch
= *fmt
) != '\0' && ch
!= '%')
491 fmt
++; /* skip over '%' */
497 reswitch
: switch (ch
) {
502 if ((error
= addwaster(&types
, &fmt
)))
510 if ((ch
= *fmt
++) == '*') {
511 if ((error
= addwaster(&types
, &fmt
)))
515 while (is_digit(ch
)) {
521 case '1': case '2': case '3': case '4':
522 case '5': case '6': case '7': case '8': case '9':
525 n
= 10 * n
+ to_digit(ch
);
527 } while (is_digit(ch
));
534 #ifndef NO_FLOATING_POINT
540 if (flags
& SHORTINT
) {
550 if (flags
& LONGINT
) {
557 flags
|= LLONGINT
; /* not necessarily */
569 error
= addtype(&types
,
570 (flags
& LONGINT
) ? T_WINT
: T_INT
);
579 if ((error
= addsarg(&types
, flags
)))
582 #ifndef NO_FLOATING_POINT
591 error
= addtype(&types
,
592 (flags
& LONGDBL
) ? T_LONG_DOUBLE
: T_DOUBLE
);
596 #endif /* !NO_FLOATING_POINT */
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
);
613 error
= addtype(&types
, TP_INT
);
616 continue; /* no output */
621 if ((error
= adduarg(&types
, flags
)))
625 if ((error
= addtype(&types
, TP_VOID
)))
632 error
= addtype(&types
,
633 (flags
& LONGINT
) ? TP_WCHAR
: TP_CHAR
);
643 if ((error
= adduarg(&types
, flags
)))
646 default: /* "%?" prints ?, unless ? is NUL */
653 build_arg_table(&types
, ap
, argtable
);
656 return (error
|| *argtable
== NULL
);
660 * Increase the size of the type table. Returns 0 on success.
663 __grow_type_table(struct typetable
*types
)
665 enum typeid *const oldtable
= types
->table
;
666 const int oldsize
= types
->tablesize
;
667 enum typeid *newtable
;
668 int n
, newsize
= oldsize
* 2;
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
)
675 bcopy(oldtable
, newtable
, oldsize
* sizeof(enum typeid));
677 newtable
= realloc(oldtable
, newsize
* sizeof(enum typeid));
678 if (newtable
== NULL
)
681 for (n
= oldsize
; n
< newsize
; n
++)
682 newtable
[n
] = T_UNUSED
;
684 types
->table
= newtable
;
685 types
->tablesize
= newsize
;
691 * Build the argument table from the completed type table.
692 * On malloc failure, *argtable is set to NULL.
695 build_arg_table(struct typetable
*types
, va_list ap
, union arg
**argtable
)
699 if (types
->tablemax
>= STATIC_ARG_TBL_SIZE
) {
700 *argtable
= (union arg
*)
701 malloc (sizeof (union arg
) * (types
->tablemax
+ 1));
702 if (*argtable
== NULL
)
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);
713 (*argtable
) [n
].pschararg
= va_arg (ap
, signed char *);
716 (*argtable
) [n
].pshortarg
= va_arg (ap
, short *);
719 (*argtable
) [n
].intarg
= va_arg (ap
, int);
722 (*argtable
) [n
].uintarg
= va_arg (ap
, unsigned int);
725 (*argtable
) [n
].pintarg
= va_arg (ap
, int *);
728 (*argtable
) [n
].longarg
= va_arg (ap
, long);
731 (*argtable
) [n
].ulongarg
= va_arg (ap
, unsigned long);
734 (*argtable
) [n
].plongarg
= va_arg (ap
, long *);
737 (*argtable
) [n
].longlongarg
= va_arg (ap
, long long);
740 (*argtable
) [n
].ulonglongarg
= va_arg (ap
, unsigned long long);
743 (*argtable
) [n
].plonglongarg
= va_arg (ap
, long long *);
746 (*argtable
) [n
].ptrdiffarg
= va_arg (ap
, ptrdiff_t);
749 (*argtable
) [n
].pptrdiffarg
= va_arg (ap
, ptrdiff_t *);
752 (*argtable
) [n
].sizearg
= va_arg (ap
, size_t);
755 (*argtable
) [n
].sizearg
= va_arg (ap
, ssize_t
);
758 (*argtable
) [n
].pssizearg
= va_arg (ap
, ssize_t
*);
761 (*argtable
) [n
].intmaxarg
= va_arg (ap
, intmax_t);
764 (*argtable
) [n
].uintmaxarg
= va_arg (ap
, uintmax_t);
767 (*argtable
) [n
].pintmaxarg
= va_arg (ap
, intmax_t *);
770 #ifndef NO_FLOATING_POINT
771 (*argtable
) [n
].doublearg
= va_arg (ap
, double);
775 #ifndef NO_FLOATING_POINT
776 (*argtable
) [n
].longdoublearg
= va_arg (ap
, long double);
781 (*argtable
) [n
].vectorarg
= va_arg (ap
, VECTORTYPE
);
785 (*argtable
) [n
].pchararg
= va_arg (ap
, char *);
788 (*argtable
) [n
].pvoidarg
= va_arg (ap
, void *);
791 (*argtable
) [n
].wintarg
= va_arg (ap
, wint_t);
794 (*argtable
) [n
].pwchararg
= va_arg (ap
, wchar_t *);