]>
Commit | Line | Data |
---|---|---|
b168057a | 1 | /* Copyright (C) 1991-2015 Free Software Foundation, Inc. |
01c901a5 | 2 | This file is part of the GNU C Library. |
28f540f4 | 3 | |
01c901a5 | 4 | The GNU C Library is free software; you can redistribute it and/or |
41bdb6e2 AJ |
5 | modify it under the terms of the GNU Lesser General Public |
6 | License as published by the Free Software Foundation; either | |
7 | version 2.1 of the License, or (at your option) any later version. | |
28f540f4 | 8 | |
01c901a5 UD |
9 | The GNU C Library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
41bdb6e2 | 12 | Lesser General Public License for more details. |
28f540f4 | 13 | |
41bdb6e2 | 14 | You should have received a copy of the GNU Lesser General Public |
59ba27a6 PE |
15 | License along with the GNU C Library; if not, see |
16 | <http://www.gnu.org/licenses/>. */ | |
28f540f4 | 17 | |
28f540f4 RM |
18 | #include <stdio.h> |
19 | #include <printf.h> | |
a04e7405 | 20 | #include <stdlib.h> |
28f540f4 | 21 | #include <string.h> |
299a95b9 | 22 | #include <wchar.h> |
01c901a5 | 23 | #include <sys/param.h> |
299a95b9 | 24 | |
403e0597 UD |
25 | #include "../locale/localeinfo.h" |
26 | ||
299a95b9 RM |
27 | #ifndef COMPILE_WPRINTF |
28 | # define CHAR_T char | |
29 | # define UCHAR_T unsigned char | |
30 | # define INT_T int | |
31 | # define L_(Str) Str | |
32 | # define ISDIGIT(Ch) isdigit (Ch) | |
d64b6ad0 | 33 | # define ISASCII(Ch) isascii (Ch) |
4aebaa6b | 34 | # define MBRLEN(Cp, L, St) __mbrlen (Cp, L, St) |
299a95b9 | 35 | |
14c35863 | 36 | # define PUT(F, S, N) _IO_sputn (F, S, N) |
299a95b9 RM |
37 | # define PAD(Padchar) \ |
38 | if (width > 0) \ | |
d18ea0c5 | 39 | done += _IO_padn (s, Padchar, width) |
299a95b9 RM |
40 | #else |
41 | # define vfprintf vfwprintf | |
42 | # define CHAR_T wchar_t | |
43 | # define UCHAR_T uwchar_t | |
44 | # define INT_T wint_t | |
45 | # define L_(Str) L##Str | |
46 | # define ISDIGIT(Ch) iswdigit (Ch) | |
47 | ||
299a95b9 RM |
48 | # define PUT(F, S, N) _IO_sputn (F, S, N) |
49 | # define PAD(Padchar) \ | |
50 | if (width > 0) \ | |
51 | done += _IO_wpadn (s, Padchar, width) | |
299a95b9 | 52 | #endif |
28f540f4 | 53 | |
9c7ff11a | 54 | #define DONT_NEED_READ_INT |
a04e7405 | 55 | #include "printf-parse.h" |
28f540f4 | 56 | |
28f540f4 RM |
57 | |
58 | size_t | |
a04e7405 RM |
59 | parse_printf_format (fmt, n, argtypes) |
60 | const char *fmt; | |
61 | size_t n; | |
62 | int *argtypes; | |
28f540f4 | 63 | { |
a04e7405 RM |
64 | size_t nargs; /* Number of arguments. */ |
65 | size_t max_ref_arg; /* Highest index used in a positional arg. */ | |
66 | struct printf_spec spec; | |
3cc4a097 | 67 | const unsigned char *f = (const unsigned char *) fmt; |
28f540f4 | 68 | |
a04e7405 RM |
69 | nargs = 0; |
70 | max_ref_arg = 0; | |
28f540f4 | 71 | |
a04e7405 | 72 | /* Search for format specifications. */ |
c06b7169 | 73 | for (f = __find_specmb (f); *f != '\0'; f = spec.next_fmt) |
a04e7405 RM |
74 | { |
75 | /* Parse this spec. */ | |
c06b7169 | 76 | nargs += __parse_one_specmb (f, nargs, &spec, &max_ref_arg); |
28f540f4 | 77 | |
a04e7405 | 78 | /* If the width is determined by an argument this is an int. */ |
07a4742f | 79 | if (spec.width_arg != -1 && (size_t) spec.width_arg < n) |
a04e7405 | 80 | argtypes[spec.width_arg] = PA_INT; |
28f540f4 | 81 | |
a04e7405 | 82 | /* If the precision is determined by an argument this is an int. */ |
07a4742f | 83 | if (spec.prec_arg != -1 && (size_t) spec.prec_arg < n) |
a04e7405 | 84 | argtypes[spec.prec_arg] = PA_INT; |
28f540f4 | 85 | |
07a4742f | 86 | if ((size_t) spec.data_arg < n) |
a04e7405 | 87 | switch (spec.ndata_args) |
28f540f4 | 88 | { |
a04e7405 | 89 | case 0: /* No arguments. */ |
28f540f4 | 90 | break; |
a04e7405 RM |
91 | case 1: /* One argument; we already have the type. */ |
92 | argtypes[spec.data_arg] = spec.data_arg_type; | |
28f540f4 | 93 | break; |
a04e7405 RM |
94 | default: |
95 | /* We have more than one argument for this format spec. We must | |
96 | call the arginfo function again to determine all the types. */ | |
97 | (void) (*__printf_arginfo_table[spec.info.spec]) | |
9d26efa9 UD |
98 | (&spec.info, n - spec.data_arg, &argtypes[spec.data_arg], |
99 | &spec.size); | |
28f540f4 RM |
100 | break; |
101 | } | |
28f540f4 RM |
102 | } |
103 | ||
a04e7405 | 104 | return MAX (nargs, max_ref_arg); |
28f540f4 | 105 | } |