lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame^] | 1 | /* Copyright (C) 1991-2015 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 | <http://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 (fmt, n, argtypes) |
| 60 | const char *fmt; |
| 61 | size_t n; |
| 62 | int *argtypes; |
| 63 | { |
| 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; |
| 67 | const unsigned char *f = (const unsigned char *) fmt; |
| 68 | |
| 69 | nargs = 0; |
| 70 | max_ref_arg = 0; |
| 71 | |
| 72 | /* Search for format specifications. */ |
| 73 | for (f = __find_specmb (f); *f != '\0'; f = spec.next_fmt) |
| 74 | { |
| 75 | /* Parse this spec. */ |
| 76 | nargs += __parse_one_specmb (f, nargs, &spec, &max_ref_arg); |
| 77 | |
| 78 | /* If the width is determined by an argument this is an int. */ |
| 79 | if (spec.width_arg != -1 && (size_t) spec.width_arg < n) |
| 80 | argtypes[spec.width_arg] = PA_INT; |
| 81 | |
| 82 | /* If the precision is determined by an argument this is an int. */ |
| 83 | if (spec.prec_arg != -1 && (size_t) spec.prec_arg < n) |
| 84 | argtypes[spec.prec_arg] = PA_INT; |
| 85 | |
| 86 | if ((size_t) spec.data_arg < n) |
| 87 | switch (spec.ndata_args) |
| 88 | { |
| 89 | case 0: /* No arguments. */ |
| 90 | break; |
| 91 | case 1: /* One argument; we already have the type. */ |
| 92 | argtypes[spec.data_arg] = spec.data_arg_type; |
| 93 | break; |
| 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]) |
| 98 | (&spec.info, n - spec.data_arg, &argtypes[spec.data_arg], |
| 99 | &spec.size); |
| 100 | break; |
| 101 | } |
| 102 | } |
| 103 | |
| 104 | return MAX (nargs, max_ref_arg); |
| 105 | } |