1 /* $NetBSD: fmtcheck.c,v 1.8 2008/04/28 20:22:59 martin Exp $ */
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
7 * This code was contributed to The NetBSD Foundation by Allen Briggs.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
38 __weak_reference(__fmtcheck, fmtcheck);
39 const char * __fmtcheck(const char *, const char *);
41 enum __e_fmtcheck_types {
52 FMTCHECK_SHORTPOINTER,
56 FMTCHECK_INTMAXTPOINTER,
57 FMTCHECK_PTRDIFFTPOINTER,
58 FMTCHECK_SIZETPOINTER,
59 #ifndef NO_FLOATING_POINT
70 typedef enum __e_fmtcheck_types EFT;
84 #define RETURN(pf,f,r) do { \
87 } /*NOTREACHED*/ /*CONSTCOND*/ while (0)
90 get_next_format_from_precision(const char **pf)
92 enum e_modifier modifier;
99 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
104 modifier = MOD_SHORT;
109 modifier = MOD_INTMAXT;
113 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
127 modifier = MOD_PTRDIFFT;
131 modifier = MOD_SIZET;
135 modifier = MOD_LONGDOUBLE;
141 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
142 if (strchr("diouxX", *f)) {
145 RETURN(pf,f,FMTCHECK_LONG);
147 RETURN(pf,f,FMTCHECK_QUAD);
149 RETURN(pf,f,FMTCHECK_INTMAXT);
151 RETURN(pf,f,FMTCHECK_PTRDIFFT);
153 RETURN(pf,f,FMTCHECK_SIZET);
157 RETURN(pf,f,FMTCHECK_INT);
159 RETURN(pf,f,FMTCHECK_UNKNOWN);
165 RETURN(pf,f,FMTCHECK_CHARPOINTER);
167 RETURN(pf,f,FMTCHECK_SHORTPOINTER);
169 RETURN(pf,f,FMTCHECK_LONGPOINTER);
171 RETURN(pf,f,FMTCHECK_QUADPOINTER);
173 RETURN(pf,f,FMTCHECK_INTMAXTPOINTER);
175 RETURN(pf,f,FMTCHECK_PTRDIFFTPOINTER);
177 RETURN(pf,f,FMTCHECK_SIZETPOINTER);
179 RETURN(pf,f,FMTCHECK_INTPOINTER);
181 RETURN(pf,f,FMTCHECK_UNKNOWN);
184 if (strchr("DOU", *f)) {
185 if (modifier != MOD_NONE)
186 RETURN(pf,f,FMTCHECK_UNKNOWN);
187 RETURN(pf,f,FMTCHECK_LONG);
189 #ifndef NO_FLOATING_POINT
190 if (strchr("aAeEfFgG", *f)) {
193 RETURN(pf,f,FMTCHECK_LONGDOUBLE);
196 RETURN(pf,f,FMTCHECK_DOUBLE);
198 RETURN(pf,f,FMTCHECK_UNKNOWN);
205 RETURN(pf,f,FMTCHECK_WINTT);
207 RETURN(pf,f,FMTCHECK_INT);
209 RETURN(pf,f,FMTCHECK_UNKNOWN);
213 if (modifier != MOD_NONE)
214 RETURN(pf,f,FMTCHECK_UNKNOWN);
215 RETURN(pf,f,FMTCHECK_WINTT);
220 RETURN(pf,f,FMTCHECK_WSTRING);
222 RETURN(pf,f,FMTCHECK_STRING);
224 RETURN(pf,f,FMTCHECK_UNKNOWN);
228 if (modifier != MOD_NONE)
229 RETURN(pf,f,FMTCHECK_UNKNOWN);
230 RETURN(pf,f,FMTCHECK_WSTRING);
233 if (modifier != MOD_NONE)
234 RETURN(pf,f,FMTCHECK_UNKNOWN);
235 RETURN(pf,f,FMTCHECK_LONG);
237 RETURN(pf,f,FMTCHECK_UNKNOWN);
242 get_next_format_from_width(const char **pf)
250 RETURN(pf,f,FMTCHECK_PRECISION);
252 /* eat any precision (empty is allowed) */
253 while (isdigit(*f)) f++;
254 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
256 RETURN(pf,f,get_next_format_from_precision(pf));
261 get_next_format(const char **pf, EFT eft)
266 if (eft == FMTCHECK_WIDTH) {
268 return get_next_format_from_width(pf);
269 } else if (eft == FMTCHECK_PRECISION) {
271 return get_next_format_from_precision(pf);
279 RETURN(pf,f,FMTCHECK_DONE);
282 RETURN(pf,f,FMTCHECK_UNKNOWN);
289 /* Eat any of the flags */
290 while (*f && (strchr("#'0- +", *f)))
294 RETURN(pf,f,FMTCHECK_WIDTH);
297 while (isdigit(*f)) f++;
299 RETURN(pf,f,FMTCHECK_UNKNOWN);
302 RETURN(pf,f,get_next_format_from_width(pf));
307 __fmtcheck(const char *f1, const char *f2)
309 const char *f1p, *f2p;
315 f1t = FMTCHECK_START;
317 f2t = FMTCHECK_START;
318 while ((f1t = get_next_format(&f1p, f1t)) != FMTCHECK_DONE) {
319 if (f1t == FMTCHECK_UNKNOWN)
321 f2t = get_next_format(&f2p, f2t);