1 /* $NetBSD: fmtcheck.c,v 1.8 2008/04/28 20:22:59 martin Exp $ */
4 * SPDX-License-Identifier: BSD-2-Clause-NetBSD
6 * Copyright (c) 2000 The NetBSD Foundation, Inc.
9 * This code was contributed to The NetBSD Foundation by Allen Briggs.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
40 __weak_reference(__fmtcheck, fmtcheck);
41 const char * __fmtcheck(const char *, const char *);
43 enum __e_fmtcheck_types {
54 FMTCHECK_SHORTPOINTER,
58 FMTCHECK_INTMAXTPOINTER,
59 FMTCHECK_PTRDIFFTPOINTER,
60 FMTCHECK_SIZETPOINTER,
61 #ifndef NO_FLOATING_POINT
72 typedef enum __e_fmtcheck_types EFT;
86 #define RETURN(pf,f,r) do { \
89 } /*NOTREACHED*/ /*CONSTCOND*/ while (0)
92 get_next_format_from_precision(const char **pf)
94 enum e_modifier modifier;
101 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
106 modifier = MOD_SHORT;
111 modifier = MOD_INTMAXT;
115 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
129 modifier = MOD_PTRDIFFT;
133 modifier = MOD_SIZET;
137 modifier = MOD_LONGDOUBLE;
143 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
144 if (strchr("diouxX", *f)) {
147 RETURN(pf,f,FMTCHECK_LONG);
149 RETURN(pf,f,FMTCHECK_QUAD);
151 RETURN(pf,f,FMTCHECK_INTMAXT);
153 RETURN(pf,f,FMTCHECK_PTRDIFFT);
155 RETURN(pf,f,FMTCHECK_SIZET);
159 RETURN(pf,f,FMTCHECK_INT);
161 RETURN(pf,f,FMTCHECK_UNKNOWN);
167 RETURN(pf,f,FMTCHECK_CHARPOINTER);
169 RETURN(pf,f,FMTCHECK_SHORTPOINTER);
171 RETURN(pf,f,FMTCHECK_LONGPOINTER);
173 RETURN(pf,f,FMTCHECK_QUADPOINTER);
175 RETURN(pf,f,FMTCHECK_INTMAXTPOINTER);
177 RETURN(pf,f,FMTCHECK_PTRDIFFTPOINTER);
179 RETURN(pf,f,FMTCHECK_SIZETPOINTER);
181 RETURN(pf,f,FMTCHECK_INTPOINTER);
183 RETURN(pf,f,FMTCHECK_UNKNOWN);
186 if (strchr("DOU", *f)) {
187 if (modifier != MOD_NONE)
188 RETURN(pf,f,FMTCHECK_UNKNOWN);
189 RETURN(pf,f,FMTCHECK_LONG);
191 #ifndef NO_FLOATING_POINT
192 if (strchr("aAeEfFgG", *f)) {
195 RETURN(pf,f,FMTCHECK_LONGDOUBLE);
198 RETURN(pf,f,FMTCHECK_DOUBLE);
200 RETURN(pf,f,FMTCHECK_UNKNOWN);
207 RETURN(pf,f,FMTCHECK_WINTT);
209 RETURN(pf,f,FMTCHECK_INT);
211 RETURN(pf,f,FMTCHECK_UNKNOWN);
215 if (modifier != MOD_NONE)
216 RETURN(pf,f,FMTCHECK_UNKNOWN);
217 RETURN(pf,f,FMTCHECK_WINTT);
222 RETURN(pf,f,FMTCHECK_WSTRING);
224 RETURN(pf,f,FMTCHECK_STRING);
226 RETURN(pf,f,FMTCHECK_UNKNOWN);
230 if (modifier != MOD_NONE)
231 RETURN(pf,f,FMTCHECK_UNKNOWN);
232 RETURN(pf,f,FMTCHECK_WSTRING);
235 if (modifier != MOD_NONE)
236 RETURN(pf,f,FMTCHECK_UNKNOWN);
237 RETURN(pf,f,FMTCHECK_LONG);
239 RETURN(pf,f,FMTCHECK_UNKNOWN);
244 get_next_format_from_width(const char **pf)
252 RETURN(pf,f,FMTCHECK_PRECISION);
254 /* eat any precision (empty is allowed) */
255 while (isdigit(*f)) f++;
256 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
258 RETURN(pf,f,get_next_format_from_precision(pf));
263 get_next_format(const char **pf, EFT eft)
268 if (eft == FMTCHECK_WIDTH) {
270 return get_next_format_from_width(pf);
271 } else if (eft == FMTCHECK_PRECISION) {
273 return get_next_format_from_precision(pf);
281 RETURN(pf,f,FMTCHECK_DONE);
284 RETURN(pf,f,FMTCHECK_UNKNOWN);
291 /* Eat any of the flags */
292 while (*f && (strchr("#'0- +", *f)))
296 RETURN(pf,f,FMTCHECK_WIDTH);
299 while (isdigit(*f)) f++;
301 RETURN(pf,f,FMTCHECK_UNKNOWN);
304 RETURN(pf,f,get_next_format_from_width(pf));
309 __fmtcheck(const char *f1, const char *f2)
311 const char *f1p, *f2p;
317 f1t = FMTCHECK_START;
319 f2t = FMTCHECK_START;
320 while ((f1t = get_next_format(&f1p, f1t)) != FMTCHECK_DONE) {
321 if (f1t == FMTCHECK_UNKNOWN)
323 f2t = get_next_format(&f2p, f2t);