1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2014 Emil Renner Berthing <systemd@esmil.dk>
8 With parts from the musl C library
9 Copyright 2005-2014 Rich Felker, et al.
11 systemd is free software; you can redistribute it and/or modify it
12 under the terms of the GNU Lesser General Public License as published by
13 the Free Software Foundation; either version 2.1 of the License, or
14 (at your option) any later version.
16 systemd is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Lesser General Public License for more details.
21 You should have received a copy of the GNU Lesser General Public License
22 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include "parse-printf-format.h"
32 static const char *consume_nonarg(const char *fmt)
37 } while (*fmt++ != '%');
41 static const char *consume_num(const char *fmt)
43 for (;*fmt >= '0' && *fmt <= '9'; fmt++)
48 static const char *consume_argn(const char *fmt, size_t *arg)
53 if (*p < '1' || *p > '9')
56 val = 10*val + (*p++ - '0');
57 } while (*p >= '0' && *p <= '9');
65 static const char *consume_flags(const char *fmt)
118 static const short pa_types[MAXTYPE] = {
123 [ULLONG] = PA_INT | PA_FLAG_LONG_LONG,
124 [LONG] = PA_INT | PA_FLAG_LONG,
125 [ULONG] = PA_INT | PA_FLAG_LONG,
126 [SHORT] = PA_INT | PA_FLAG_SHORT,
127 [USHORT] = PA_INT | PA_FLAG_SHORT,
130 [LLONG] = PA_INT | PA_FLAG_LONG_LONG,
131 [SIZET] = PA_INT | PA_FLAG_LONG,
132 [IMAX] = PA_INT | PA_FLAG_LONG_LONG,
133 [UMAX] = PA_INT | PA_FLAG_LONG_LONG,
134 [PDIFF] = PA_INT | PA_FLAG_LONG_LONG,
135 [UIPTR] = PA_INT | PA_FLAG_LONG,
137 [LDBL] = PA_DOUBLE | PA_FLAG_LONG_DOUBLE
140 #define S(x) [(x)-'A']
141 #define E(x) (STOP + (x))
143 static const unsigned char states[]['z'-'A'+1] = {
144 { /* 0: bare types */
145 S('d') = E(INT), S('i') = E(INT),
146 S('o') = E(UINT),S('u') = E(UINT),S('x') = E(UINT), S('X') = E(UINT),
147 S('e') = E(DBL), S('f') = E(DBL), S('g') = E(DBL), S('a') = E(DBL),
148 S('E') = E(DBL), S('F') = E(DBL), S('G') = E(DBL), S('A') = E(DBL),
149 S('c') = E(CHAR),S('C') = E(INT),
150 S('s') = E(PTR), S('S') = E(PTR), S('p') = E(UIPTR),S('n') = E(PTR),
152 S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE,
153 S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE
154 }, { /* 1: l-prefixed */
155 S('d') = E(LONG), S('i') = E(LONG),
156 S('o') = E(ULONG),S('u') = E(ULONG),S('x') = E(ULONG),S('X') = E(ULONG),
157 S('e') = E(DBL), S('f') = E(DBL), S('g') = E(DBL), S('a') = E(DBL),
158 S('E') = E(DBL), S('F') = E(DBL), S('G') = E(DBL), S('A') = E(DBL),
159 S('c') = E(INT), S('s') = E(PTR), S('n') = E(PTR),
161 }, { /* 2: ll-prefixed */
162 S('d') = E(LLONG), S('i') = E(LLONG),
163 S('o') = E(ULLONG),S('u') = E(ULLONG),
164 S('x') = E(ULLONG),S('X') = E(ULLONG),
166 }, { /* 3: h-prefixed */
167 S('d') = E(SHORT), S('i') = E(SHORT),
168 S('o') = E(USHORT),S('u') = E(USHORT),
169 S('x') = E(USHORT),S('X') = E(USHORT),
172 }, { /* 4: hh-prefixed */
173 S('d') = E(CHAR), S('i') = E(CHAR),
174 S('o') = E(UCHAR),S('u') = E(UCHAR),
175 S('x') = E(UCHAR),S('X') = E(UCHAR),
177 }, { /* 5: L-prefixed */
178 S('e') = E(LDBL),S('f') = E(LDBL),S('g') = E(LDBL), S('a') = E(LDBL),
179 S('E') = E(LDBL),S('F') = E(LDBL),S('G') = E(LDBL), S('A') = E(LDBL),
181 }, { /* 6: z- or t-prefixed (assumed to be same size) */
182 S('d') = E(PDIFF),S('i') = E(PDIFF),
183 S('o') = E(SIZET),S('u') = E(SIZET),
184 S('x') = E(SIZET),S('X') = E(SIZET),
186 }, { /* 7: j-prefixed */
187 S('d') = E(IMAX), S('i') = E(IMAX),
188 S('o') = E(UMAX), S('u') = E(UMAX),
189 S('x') = E(UMAX), S('X') = E(UMAX),
194 size_t parse_printf_format(const char *fmt, size_t n, int *types)
205 fmt = consume_nonarg(fmt);
213 fmt = consume_argn(fmt, &arg);
215 fmt = consume_flags(fmt);
219 fmt = consume_argn(fmt+1, &warg);
224 if (warg <= n && types[warg-1] == NONE)
227 fmt = consume_num(fmt);
233 fmt = consume_argn(fmt+1, &parg);
238 if (parg <= n && types[parg-1] == NONE)
243 fmt = consume_num(fmt);
246 /* length modifier and conversion specifier */
249 unsigned char c = *fmt++;
251 if (c < 'A' || c > 'z')
253 state = states[state]S(c);
256 } while (state < STOP);
258 if (state == E(NONE))
266 types[arg-1] = state - STOP;
271 for (i = 0; i < last; i++)
272 types[i] = pa_types[types[i]];
277 #endif // HAVE_PRINTF_H