1 | /* Copyright (C) 1991-2023 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 | #include <printf.h> |
25 | |
26 | #include "../locale/localeinfo.h" |
27 | |
28 | #ifndef COMPILE_WPRINTF |
29 | # define CHAR_T char |
30 | # define UCHAR_T unsigned char |
31 | # define INT_T int |
32 | # define L_(Str) Str |
33 | # define ISDIGIT(Ch) isdigit (Ch) |
34 | # define ISASCII(Ch) isascii (Ch) |
35 | # define MBRLEN(Cp, L, St) __mbrlen (Cp, L, St) |
36 | |
37 | # define PUT(F, S, N) _IO_sputn (F, S, N) |
38 | # define PAD(Padchar) \ |
39 | if (width > 0) \ |
40 | done += _IO_padn (s, Padchar, width) |
41 | #else |
42 | # define vfprintf vfwprintf |
43 | # define CHAR_T wchar_t |
44 | # define UCHAR_T uwchar_t |
45 | # define INT_T wint_t |
46 | # define L_(Str) L##Str |
47 | # define ISDIGIT(Ch) iswdigit (Ch) |
48 | |
49 | # define PUT(F, S, N) _IO_sputn (F, S, N) |
50 | # define PAD(Padchar) \ |
51 | if (width > 0) \ |
52 | done += _IO_wpadn (s, Padchar, width) |
53 | #endif |
54 | |
55 | #define DONT_NEED_READ_INT |
56 | #include "printf-parse.h" |
57 | |
58 | |
59 | size_t |
60 | parse_printf_format (const char *fmt, size_t n, int *argtypes) |
61 | { |
62 | size_t nargs; /* Number of arguments. */ |
63 | size_t max_ref_arg; /* Highest index used in a positional arg. */ |
64 | struct printf_spec spec; |
65 | const unsigned char *f = (const unsigned char *) fmt; |
66 | bool failed; |
67 | |
68 | nargs = 0; |
69 | max_ref_arg = 0; |
70 | |
71 | /* Search for format specifications. */ |
72 | for (f = __find_specmb (f); *f != '\0'; f = spec.next_fmt) |
73 | { |
74 | /* Parse this spec. */ |
75 | nargs += __parse_one_specmb (f, nargs, &spec, &max_ref_arg, &failed); |
76 | |
77 | /* If the width is determined by an argument, it is an int. */ |
78 | if (spec.width_arg != -1 && (size_t) spec.width_arg < n) |
79 | argtypes[spec.width_arg] = PA_INT; |
80 | |
81 | /* If the precision is determined by an argument, it is an int. */ |
82 | if (spec.prec_arg != -1 && (size_t) spec.prec_arg < n) |
83 | argtypes[spec.prec_arg] = PA_INT; |
84 | |
85 | if ((size_t) spec.data_arg < n) |
86 | switch (spec.ndata_args) |
87 | { |
88 | case 0: /* No arguments. */ |
89 | break; |
90 | case 1: /* One argument; we already have the type. */ |
91 | argtypes[spec.data_arg] = spec.data_arg_type; |
92 | break; |
93 | default: |
94 | /* We have more than one argument for this format spec. We must |
95 | call the arginfo function again to determine all the types. */ |
96 | (void) (*__printf_arginfo_table[spec.info.spec]) |
97 | (&spec.info, n - spec.data_arg, &argtypes[spec.data_arg], |
98 | &spec.size); |
99 | break; |
100 | } |
101 | } |
102 | |
103 | return MAX (nargs, max_ref_arg); |
104 | } |
105 | |