1 | /* Copyright (C) 1991-2021 Free Software Foundation, Inc. |
2 | This file is part of the GNU C Library. |
3 | |
4 | The GNU C Library is free software; you can redistribute it and/or |
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. |
8 | |
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 |
12 | Lesser General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Lesser General Public |
15 | License along with the GNU C Library; if not, see |
16 | <https://www.gnu.org/licenses/>. */ |
17 | |
18 | #include <stdio.h> |
19 | #include <printf.h> |
20 | #include <stdlib.h> |
21 | #include <string.h> |
22 | #include <wchar.h> |
23 | #include <sys/param.h> |
24 | |
25 | #include "../locale/localeinfo.h" |
26 | |
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) |
33 | # define ISASCII(Ch) isascii (Ch) |
34 | # define MBRLEN(Cp, L, St) __mbrlen (Cp, L, St) |
35 | |
36 | # define PUT(F, S, N) _IO_sputn (F, S, N) |
37 | # define PAD(Padchar) \ |
38 | if (width > 0) \ |
39 | done += _IO_padn (s, Padchar, width) |
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 | |
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) |
52 | #endif |
53 | |
54 | #define DONT_NEED_READ_INT |
55 | #include "printf-parse.h" |
56 | |
57 | |
58 | size_t |
59 | parse_printf_format (const char *fmt, size_t n, int *argtypes) |
60 | { |
61 | size_t nargs; /* Number of arguments. */ |
62 | size_t max_ref_arg; /* Highest index used in a positional arg. */ |
63 | struct printf_spec spec; |
64 | const unsigned char *f = (const unsigned char *) fmt; |
65 | |
66 | nargs = 0; |
67 | max_ref_arg = 0; |
68 | |
69 | /* Search for format specifications. */ |
70 | for (f = __find_specmb (f); *f != '\0'; f = spec.next_fmt) |
71 | { |
72 | /* Parse this spec. */ |
73 | nargs += __parse_one_specmb (f, nargs, &spec, &max_ref_arg); |
74 | |
75 | /* If the width is determined by an argument, it is an int. */ |
76 | if (spec.width_arg != -1 && (size_t) spec.width_arg < n) |
77 | argtypes[spec.width_arg] = PA_INT; |
78 | |
79 | /* If the precision is determined by an argument, it is an int. */ |
80 | if (spec.prec_arg != -1 && (size_t) spec.prec_arg < n) |
81 | argtypes[spec.prec_arg] = PA_INT; |
82 | |
83 | if ((size_t) spec.data_arg < n) |
84 | switch (spec.ndata_args) |
85 | { |
86 | case 0: /* No arguments. */ |
87 | break; |
88 | case 1: /* One argument; we already have the type. */ |
89 | argtypes[spec.data_arg] = spec.data_arg_type; |
90 | break; |
91 | default: |
92 | /* We have more than one argument for this format spec. We must |
93 | call the arginfo function again to determine all the types. */ |
94 | (void) (*__printf_arginfo_table[spec.info.spec]) |
95 | (&spec.info, n - spec.data_arg, &argtypes[spec.data_arg], |
96 | &spec.size); |
97 | break; |
98 | } |
99 | } |
100 | |
101 | return MAX (nargs, max_ref_arg); |
102 | } |
103 | |