]>
git.saurik.com Git - apple/libc.git/blob - stdio/FreeBSD/printf-pos.c
2cae4e6e80b109e8e17a9cc4fc1535c8a1598ddc
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
69 /* An expandable array of types. */
71 enum typeid *table
; /* table of types */
72 enum typeid stattable
[STATIC_ARG_TBL_SIZE
];
73 int tablesize
; /* current size of type table */
74 int tablemax
; /* largest used index in table */
75 int nextarg
; /* 1-based argument index */
78 static int __grow_type_table(struct typetable
*);
79 static void build_arg_table (struct typetable
*, va_list, union arg
**);
82 * Initialize a struct typetable.
85 inittypes(struct typetable
*types
)
89 types
->table
= types
->stattable
;
90 types
->tablesize
= STATIC_ARG_TBL_SIZE
;
93 for (n
= 0; n
< STATIC_ARG_TBL_SIZE
; n
++)
94 types
->table
[n
] = T_UNUSED
;
98 * struct typetable destructor.
101 freetypes(struct typetable
*types
)
104 if (types
->table
!= types
->stattable
)
109 * Ensure that there is space to add a new argument type to the type table.
110 * Expand the table if necessary. Returns 0 on success.
113 _ensurespace(struct typetable
*types
)
116 if (types
->nextarg
>= types
->tablesize
) {
117 if (__grow_type_table(types
))
120 if (types
->nextarg
> types
->tablemax
)
121 types
->tablemax
= types
->nextarg
;
126 * Add an argument type to the table, expanding if necessary.
127 * Returns 0 on success.
130 addtype(struct typetable
*types
, enum typeid type
)
133 if (_ensurespace(types
))
135 types
->table
[types
->nextarg
++] = type
;
140 addsarg(struct typetable
*types
, int flags
)
143 if (_ensurespace(types
))
146 types
->table
[types
->nextarg
++] = T_INTMAXT
;
147 else if (flags
& SIZET
)
148 types
->table
[types
->nextarg
++] = T_SSIZET
;
149 else if (flags
& PTRDIFFT
)
150 types
->table
[types
->nextarg
++] = T_PTRDIFFT
;
151 else if (flags
& LLONGINT
)
152 types
->table
[types
->nextarg
++] = T_LLONG
;
153 else if (flags
& LONGINT
)
154 types
->table
[types
->nextarg
++] = T_LONG
;
156 types
->table
[types
->nextarg
++] = T_INT
;
161 adduarg(struct typetable
*types
, int flags
)
164 if (_ensurespace(types
))
167 types
->table
[types
->nextarg
++] = T_UINTMAXT
;
168 else if (flags
& SIZET
)
169 types
->table
[types
->nextarg
++] = T_SIZET
;
170 else if (flags
& PTRDIFFT
)
171 types
->table
[types
->nextarg
++] = T_SIZET
;
172 else if (flags
& LLONGINT
)
173 types
->table
[types
->nextarg
++] = T_U_LLONG
;
174 else if (flags
& LONGINT
)
175 types
->table
[types
->nextarg
++] = T_U_LONG
;
177 types
->table
[types
->nextarg
++] = T_U_INT
;
182 * Add * arguments to the type array.
185 addaster(struct typetable
*types
, char **fmtp
)
192 while (is_digit(*cp
)) {
193 n2
= 10 * n2
+ to_digit(*cp
);
197 int hold
= types
->nextarg
;
199 if (addtype(types
, T_INT
))
201 types
->nextarg
= hold
;
204 if (addtype(types
, T_INT
))
211 addwaster(struct typetable
*types
, wchar_t **fmtp
)
218 while (is_digit(*cp
)) {
219 n2
= 10 * n2
+ to_digit(*cp
);
223 int hold
= types
->nextarg
;
225 if (addtype(types
, T_INT
))
227 types
->nextarg
= hold
;
230 if (addtype(types
, T_INT
))
237 * Find all arguments when a positional parameter is encountered. Returns a
238 * table, indexed by argument number, of pointers to each arguments. The
239 * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
240 * It will be replaces with a malloc-ed one if it overflows.
241 * Returns 0 on success. On failure, returns nonzero and sets errno.
244 __find_arguments (const char *fmt0
, va_list ap
, union arg
**argtable
)
246 char *fmt
; /* format string */
247 int ch
; /* character from fmt */
248 int n
; /* handy integer (short term usage) */
250 int flags
; /* flags as above */
251 int width
; /* width from format (%8d), or 0 */
252 struct typetable types
; /* table of types */
259 * Scan the format for conversions (`%' character).
262 while ((ch
= *fmt
) != '\0' && ch
!= '%')
266 fmt
++; /* skip over '%' */
272 reswitch
: switch (ch
) {
277 if ((error
= addaster(&types
, &fmt
)))
285 if ((ch
= *fmt
++) == '*') {
286 if ((error
= addaster(&types
, &fmt
)))
290 while (is_digit(ch
)) {
296 case '1': case '2': case '3': case '4':
297 case '5': case '6': case '7': case '8': case '9':
300 n
= 10 * n
+ to_digit(ch
);
302 } while (is_digit(ch
));
309 #ifndef NO_FLOATING_POINT
315 if (flags
& SHORTINT
) {
325 if (flags
& LONGINT
) {
332 flags
|= LLONGINT
; /* not necessarily */
344 error
= addtype(&types
,
345 (flags
& LONGINT
) ? T_WINT
: T_INT
);
354 if ((error
= addsarg(&types
, flags
)))
357 #ifndef NO_FLOATING_POINT
365 error
= addtype(&types
,
366 (flags
& LONGDBL
) ? T_LONG_DOUBLE
: T_DOUBLE
);
370 #endif /* !NO_FLOATING_POINT */
373 error
= addtype(&types
, TP_INTMAXT
);
374 else if (flags
& PTRDIFFT
)
375 error
= addtype(&types
, TP_PTRDIFFT
);
376 else if (flags
& SIZET
)
377 error
= addtype(&types
, TP_SSIZET
);
378 else if (flags
& LLONGINT
)
379 error
= addtype(&types
, TP_LLONG
);
380 else if (flags
& LONGINT
)
381 error
= addtype(&types
, TP_LONG
);
382 else if (flags
& SHORTINT
)
383 error
= addtype(&types
, TP_SHORT
);
384 else if (flags
& CHARINT
)
385 error
= addtype(&types
, TP_SCHAR
);
387 error
= addtype(&types
, TP_INT
);
390 continue; /* no output */
395 if ((error
= adduarg(&types
, flags
)))
399 if ((error
= addtype(&types
, TP_VOID
)))
406 error
= addtype(&types
,
407 (flags
& LONGINT
) ? TP_WCHAR
: TP_CHAR
);
417 if ((error
= adduarg(&types
, flags
)))
420 default: /* "%?" prints ?, unless ? is NUL */
427 build_arg_table(&types
, ap
, argtable
);
430 return (error
|| *argtable
== NULL
);
433 /* wchar version of __find_arguments. */
435 __find_warguments (const wchar_t *fmt0
, va_list ap
, union arg
**argtable
)
437 wchar_t *fmt
; /* format string */
438 wchar_t ch
; /* character from fmt */
439 int n
; /* handy integer (short term usage) */
441 int flags
; /* flags as above */
442 int width
; /* width from format (%8d), or 0 */
443 struct typetable types
; /* table of types */
445 fmt
= (wchar_t *)fmt0
;
450 * Scan the format for conversions (`%' character).
453 while ((ch
= *fmt
) != '\0' && ch
!= '%')
457 fmt
++; /* skip over '%' */
463 reswitch
: switch (ch
) {
468 if ((error
= addwaster(&types
, &fmt
)))
476 if ((ch
= *fmt
++) == '*') {
477 if ((error
= addwaster(&types
, &fmt
)))
481 while (is_digit(ch
)) {
487 case '1': case '2': case '3': case '4':
488 case '5': case '6': case '7': case '8': case '9':
491 n
= 10 * n
+ to_digit(ch
);
493 } while (is_digit(ch
));
500 #ifndef NO_FLOATING_POINT
506 if (flags
& SHORTINT
) {
516 if (flags
& LONGINT
) {
523 flags
|= LLONGINT
; /* not necessarily */
535 error
= addtype(&types
,
536 (flags
& LONGINT
) ? T_WINT
: T_INT
);
545 if ((error
= addsarg(&types
, flags
)))
548 #ifndef NO_FLOATING_POINT
556 error
= addtype(&types
,
557 (flags
& LONGDBL
) ? T_LONG_DOUBLE
: T_DOUBLE
);
561 #endif /* !NO_FLOATING_POINT */
564 error
= addtype(&types
, TP_INTMAXT
);
565 else if (flags
& PTRDIFFT
)
566 error
= addtype(&types
, TP_PTRDIFFT
);
567 else if (flags
& SIZET
)
568 error
= addtype(&types
, TP_SSIZET
);
569 else if (flags
& LLONGINT
)
570 error
= addtype(&types
, TP_LLONG
);
571 else if (flags
& LONGINT
)
572 error
= addtype(&types
, TP_LONG
);
573 else if (flags
& SHORTINT
)
574 error
= addtype(&types
, TP_SHORT
);
575 else if (flags
& CHARINT
)
576 error
= addtype(&types
, TP_SCHAR
);
578 error
= addtype(&types
, TP_INT
);
581 continue; /* no output */
586 if ((error
= adduarg(&types
, flags
)))
590 if ((error
= addtype(&types
, TP_VOID
)))
597 error
= addtype(&types
,
598 (flags
& LONGINT
) ? TP_WCHAR
: TP_CHAR
);
608 if ((error
= adduarg(&types
, flags
)))
611 default: /* "%?" prints ?, unless ? is NUL */
618 build_arg_table(&types
, ap
, argtable
);
621 return (error
|| *argtable
== NULL
);
625 * Increase the size of the type table. Returns 0 on success.
628 __grow_type_table(struct typetable
*types
)
630 enum typeid *const oldtable
= types
->table
;
631 const int oldsize
= types
->tablesize
;
632 enum typeid *newtable
;
633 int n
, newsize
= oldsize
* 2;
635 if (newsize
< types
->nextarg
+ 1)
636 newsize
= types
->nextarg
+ 1;
637 if (oldsize
== STATIC_ARG_TBL_SIZE
) {
638 if ((newtable
= malloc(newsize
* sizeof(enum typeid))) == NULL
)
640 bcopy(oldtable
, newtable
, oldsize
* sizeof(enum typeid));
642 newtable
= realloc(oldtable
, newsize
* sizeof(enum typeid));
643 if (newtable
== NULL
)
646 for (n
= oldsize
; n
< newsize
; n
++)
647 newtable
[n
] = T_UNUSED
;
649 types
->table
= newtable
;
650 types
->tablesize
= newsize
;
656 * Build the argument table from the completed type table.
657 * On malloc failure, *argtable is set to NULL.
660 build_arg_table(struct typetable
*types
, va_list ap
, union arg
**argtable
)
664 if (types
->tablemax
>= STATIC_ARG_TBL_SIZE
) {
665 *argtable
= (union arg
*)
666 malloc (sizeof (union arg
) * (types
->tablemax
+ 1));
667 if (*argtable
== NULL
)
671 (*argtable
) [0].intarg
= 0;
672 for (n
= 1; n
<= types
->tablemax
; n
++) {
673 switch (types
->table
[n
]) {
674 case T_UNUSED
: /* whoops! */
675 (*argtable
) [n
].intarg
= va_arg (ap
, int);
678 (*argtable
) [n
].pschararg
= va_arg (ap
, signed char *);
681 (*argtable
) [n
].pshortarg
= va_arg (ap
, short *);
684 (*argtable
) [n
].intarg
= va_arg (ap
, int);
687 (*argtable
) [n
].uintarg
= va_arg (ap
, unsigned int);
690 (*argtable
) [n
].pintarg
= va_arg (ap
, int *);
693 (*argtable
) [n
].longarg
= va_arg (ap
, long);
696 (*argtable
) [n
].ulongarg
= va_arg (ap
, unsigned long);
699 (*argtable
) [n
].plongarg
= va_arg (ap
, long *);
702 (*argtable
) [n
].longlongarg
= va_arg (ap
, long long);
705 (*argtable
) [n
].ulonglongarg
= va_arg (ap
, unsigned long long);
708 (*argtable
) [n
].plonglongarg
= va_arg (ap
, long long *);
711 (*argtable
) [n
].ptrdiffarg
= va_arg (ap
, ptrdiff_t);
714 (*argtable
) [n
].pptrdiffarg
= va_arg (ap
, ptrdiff_t *);
717 (*argtable
) [n
].sizearg
= va_arg (ap
, size_t);
720 (*argtable
) [n
].sizearg
= va_arg (ap
, ssize_t
);
723 (*argtable
) [n
].pssizearg
= va_arg (ap
, ssize_t
*);
726 (*argtable
) [n
].intmaxarg
= va_arg (ap
, intmax_t);
729 (*argtable
) [n
].uintmaxarg
= va_arg (ap
, uintmax_t);
732 (*argtable
) [n
].pintmaxarg
= va_arg (ap
, intmax_t *);
735 #ifndef NO_FLOATING_POINT
736 (*argtable
) [n
].doublearg
= va_arg (ap
, double);
740 #ifndef NO_FLOATING_POINT
741 (*argtable
) [n
].longdoublearg
= va_arg (ap
, long double);
745 (*argtable
) [n
].pchararg
= va_arg (ap
, char *);
748 (*argtable
) [n
].pvoidarg
= va_arg (ap
, void *);
751 (*argtable
) [n
].wintarg
= va_arg (ap
, wint_t);
754 (*argtable
) [n
].pwchararg
= va_arg (ap
, wchar_t *);