]>
Commit | Line | Data |
---|---|---|
04277e02 | 1 | /* Copyright (C) 1991-2019 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 | 15 | License along with the GNU C Library; if not, see |
5a82c748 | 16 | <https://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 | |
9d46370c | 59 | parse_printf_format (const char *fmt, size_t n, int *argtypes) |
28f540f4 | 60 | { |
a04e7405 RM |
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; | |
3cc4a097 | 64 | const unsigned char *f = (const unsigned char *) fmt; |
28f540f4 | 65 | |
a04e7405 RM |
66 | nargs = 0; |
67 | max_ref_arg = 0; | |
28f540f4 | 68 | |
a04e7405 | 69 | /* Search for format specifications. */ |
c06b7169 | 70 | for (f = __find_specmb (f); *f != '\0'; f = spec.next_fmt) |
a04e7405 RM |
71 | { |
72 | /* Parse this spec. */ | |
c06b7169 | 73 | nargs += __parse_one_specmb (f, nargs, &spec, &max_ref_arg); |
28f540f4 | 74 | |
a04e7405 | 75 | /* If the width is determined by an argument this is an int. */ |
07a4742f | 76 | if (spec.width_arg != -1 && (size_t) spec.width_arg < n) |
a04e7405 | 77 | argtypes[spec.width_arg] = PA_INT; |
28f540f4 | 78 | |
a04e7405 | 79 | /* If the precision is determined by an argument this is an int. */ |
07a4742f | 80 | if (spec.prec_arg != -1 && (size_t) spec.prec_arg < n) |
a04e7405 | 81 | argtypes[spec.prec_arg] = PA_INT; |
28f540f4 | 82 | |
07a4742f | 83 | if ((size_t) spec.data_arg < n) |
a04e7405 | 84 | switch (spec.ndata_args) |
28f540f4 | 85 | { |
a04e7405 | 86 | case 0: /* No arguments. */ |
28f540f4 | 87 | break; |
a04e7405 RM |
88 | case 1: /* One argument; we already have the type. */ |
89 | argtypes[spec.data_arg] = spec.data_arg_type; | |
28f540f4 | 90 | break; |
a04e7405 RM |
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]) | |
9d26efa9 UD |
95 | (&spec.info, n - spec.data_arg, &argtypes[spec.data_arg], |
96 | &spec.size); | |
28f540f4 RM |
97 | break; |
98 | } | |
28f540f4 RM |
99 | } |
100 | ||
a04e7405 | 101 | return MAX (nargs, max_ref_arg); |
28f540f4 | 102 | } |