]> git.saurik.com Git - apple/libc.git/blame - gen/FreeBSD/fmtcheck.c
Libc-1439.100.3.tar.gz
[apple/libc.git] / gen / FreeBSD / fmtcheck.c
CommitLineData
1f2f436a
A
1/* $NetBSD: fmtcheck.c,v 1.8 2008/04/28 20:22:59 martin Exp $ */
2
9385eb3d
A
3/*-
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code was contributed to The NetBSD Foundation by Allen Briggs.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
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.
9385eb3d
A
17 *
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.
29 */
30
9385eb3d 31#include <sys/cdefs.h>
1f2f436a 32__FBSDID("$FreeBSD: src/lib/libc/gen/fmtcheck.c,v 1.10 2009/06/23 23:52:12 delphij Exp $");
9385eb3d
A
33
34#include <stdio.h>
35#include <string.h>
36#include <ctype.h>
37
38__weak_reference(__fmtcheck, fmtcheck);
39
40enum __e_fmtcheck_types {
41 FMTCHECK_START,
42 FMTCHECK_SHORT,
43 FMTCHECK_INT,
1f2f436a 44 FMTCHECK_WINTT,
9385eb3d
A
45 FMTCHECK_LONG,
46 FMTCHECK_QUAD,
1f2f436a 47 FMTCHECK_INTMAXT,
3d9156a7
A
48 FMTCHECK_PTRDIFFT,
49 FMTCHECK_SIZET,
1f2f436a 50 FMTCHECK_CHARPOINTER,
9385eb3d
A
51 FMTCHECK_SHORTPOINTER,
52 FMTCHECK_INTPOINTER,
53 FMTCHECK_LONGPOINTER,
54 FMTCHECK_QUADPOINTER,
1f2f436a 55 FMTCHECK_INTMAXTPOINTER,
3d9156a7
A
56 FMTCHECK_PTRDIFFTPOINTER,
57 FMTCHECK_SIZETPOINTER,
58#ifndef NO_FLOATING_POINT
9385eb3d
A
59 FMTCHECK_DOUBLE,
60 FMTCHECK_LONGDOUBLE,
3d9156a7 61#endif
9385eb3d 62 FMTCHECK_STRING,
1f2f436a 63 FMTCHECK_WSTRING,
9385eb3d
A
64 FMTCHECK_WIDTH,
65 FMTCHECK_PRECISION,
66 FMTCHECK_DONE,
67 FMTCHECK_UNKNOWN
68};
69typedef enum __e_fmtcheck_types EFT;
70
1f2f436a
A
71enum e_modifier {
72 MOD_NONE,
73 MOD_CHAR,
74 MOD_SHORT,
75 MOD_LONG,
76 MOD_QUAD,
77 MOD_INTMAXT,
78 MOD_LONGDOUBLE,
79 MOD_PTRDIFFT,
80 MOD_SIZET,
81};
82
9385eb3d
A
83#define RETURN(pf,f,r) do { \
84 *(pf) = (f); \
85 return r; \
86 } /*NOTREACHED*/ /*CONSTCOND*/ while (0)
87
88static EFT
89get_next_format_from_precision(const char **pf)
90{
1f2f436a 91 enum e_modifier modifier;
9385eb3d
A
92 const char *f;
93
9385eb3d
A
94 f = *pf;
95 switch (*f) {
96 case 'h':
97 f++;
1f2f436a
A
98 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
99 if (*f == 'h') {
100 f++;
101 modifier = MOD_CHAR;
102 } else {
103 modifier = MOD_SHORT;
104 }
105 break;
106 case 'j':
107 f++;
108 modifier = MOD_INTMAXT;
9385eb3d
A
109 break;
110 case 'l':
111 f++;
112 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
113 if (*f == 'l') {
114 f++;
1f2f436a 115 modifier = MOD_QUAD;
9385eb3d 116 } else {
1f2f436a 117 modifier = MOD_LONG;
9385eb3d
A
118 }
119 break;
120 case 'q':
121 f++;
1f2f436a 122 modifier = MOD_QUAD;
9385eb3d 123 break;
3d9156a7
A
124 case 't':
125 f++;
1f2f436a 126 modifier = MOD_PTRDIFFT;
3d9156a7
A
127 break;
128 case 'z':
129 f++;
1f2f436a 130 modifier = MOD_SIZET;
3d9156a7 131 break;
9385eb3d
A
132 case 'L':
133 f++;
1f2f436a 134 modifier = MOD_LONGDOUBLE;
9385eb3d
A
135 break;
136 default:
1f2f436a 137 modifier = MOD_NONE;
9385eb3d
A
138 break;
139 }
140 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
141 if (strchr("diouxX", *f)) {
1f2f436a
A
142 switch (modifier) {
143 case MOD_LONG:
9385eb3d 144 RETURN(pf,f,FMTCHECK_LONG);
1f2f436a 145 case MOD_QUAD:
9385eb3d 146 RETURN(pf,f,FMTCHECK_QUAD);
1f2f436a
A
147 case MOD_INTMAXT:
148 RETURN(pf,f,FMTCHECK_INTMAXT);
149 case MOD_PTRDIFFT:
3d9156a7 150 RETURN(pf,f,FMTCHECK_PTRDIFFT);
1f2f436a 151 case MOD_SIZET:
3d9156a7 152 RETURN(pf,f,FMTCHECK_SIZET);
1f2f436a
A
153 case MOD_CHAR:
154 case MOD_SHORT:
155 case MOD_NONE:
156 RETURN(pf,f,FMTCHECK_INT);
157 default:
158 RETURN(pf,f,FMTCHECK_UNKNOWN);
159 }
9385eb3d
A
160 }
161 if (*f == 'n') {
1f2f436a
A
162 switch (modifier) {
163 case MOD_CHAR:
164 RETURN(pf,f,FMTCHECK_CHARPOINTER);
165 case MOD_SHORT:
9385eb3d 166 RETURN(pf,f,FMTCHECK_SHORTPOINTER);
1f2f436a 167 case MOD_LONG:
9385eb3d 168 RETURN(pf,f,FMTCHECK_LONGPOINTER);
1f2f436a 169 case MOD_QUAD:
9385eb3d 170 RETURN(pf,f,FMTCHECK_QUADPOINTER);
1f2f436a
A
171 case MOD_INTMAXT:
172 RETURN(pf,f,FMTCHECK_INTMAXTPOINTER);
173 case MOD_PTRDIFFT:
3d9156a7 174 RETURN(pf,f,FMTCHECK_PTRDIFFTPOINTER);
1f2f436a 175 case MOD_SIZET:
3d9156a7 176 RETURN(pf,f,FMTCHECK_SIZETPOINTER);
1f2f436a
A
177 case MOD_NONE:
178 RETURN(pf,f,FMTCHECK_INTPOINTER);
179 default:
180 RETURN(pf,f,FMTCHECK_UNKNOWN);
181 }
9385eb3d
A
182 }
183 if (strchr("DOU", *f)) {
1f2f436a 184 if (modifier != MOD_NONE)
9385eb3d
A
185 RETURN(pf,f,FMTCHECK_UNKNOWN);
186 RETURN(pf,f,FMTCHECK_LONG);
187 }
3d9156a7
A
188#ifndef NO_FLOATING_POINT
189 if (strchr("aAeEfFgG", *f)) {
1f2f436a
A
190 switch (modifier) {
191 case MOD_LONGDOUBLE:
9385eb3d 192 RETURN(pf,f,FMTCHECK_LONGDOUBLE);
1f2f436a
A
193 case MOD_LONG:
194 case MOD_NONE:
195 RETURN(pf,f,FMTCHECK_DOUBLE);
196 default:
9385eb3d 197 RETURN(pf,f,FMTCHECK_UNKNOWN);
1f2f436a 198 }
9385eb3d 199 }
3d9156a7 200#endif
9385eb3d 201 if (*f == 'c') {
1f2f436a
A
202 switch (modifier) {
203 case MOD_LONG:
204 RETURN(pf,f,FMTCHECK_WINTT);
205 case MOD_NONE:
206 RETURN(pf,f,FMTCHECK_INT);
207 default:
9385eb3d 208 RETURN(pf,f,FMTCHECK_UNKNOWN);
1f2f436a
A
209 }
210 }
211 if (*f == 'C') {
212 if (modifier != MOD_NONE)
213 RETURN(pf,f,FMTCHECK_UNKNOWN);
214 RETURN(pf,f,FMTCHECK_WINTT);
9385eb3d
A
215 }
216 if (*f == 's') {
1f2f436a
A
217 switch (modifier) {
218 case MOD_LONG:
219 RETURN(pf,f,FMTCHECK_WSTRING);
220 case MOD_NONE:
221 RETURN(pf,f,FMTCHECK_STRING);
222 default:
223 RETURN(pf,f,FMTCHECK_UNKNOWN);
224 }
225 }
226 if (*f == 'S') {
227 if (modifier != MOD_NONE)
9385eb3d 228 RETURN(pf,f,FMTCHECK_UNKNOWN);
1f2f436a 229 RETURN(pf,f,FMTCHECK_WSTRING);
9385eb3d
A
230 }
231 if (*f == 'p') {
1f2f436a 232 if (modifier != MOD_NONE)
9385eb3d
A
233 RETURN(pf,f,FMTCHECK_UNKNOWN);
234 RETURN(pf,f,FMTCHECK_LONG);
235 }
236 RETURN(pf,f,FMTCHECK_UNKNOWN);
237 /*NOTREACHED*/
238}
239
240static EFT
241get_next_format_from_width(const char **pf)
242{
243 const char *f;
244
245 f = *pf;
246 if (*f == '.') {
247 f++;
248 if (*f == '*') {
249 RETURN(pf,f,FMTCHECK_PRECISION);
250 }
251 /* eat any precision (empty is allowed) */
252 while (isdigit(*f)) f++;
253 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
254 }
255 RETURN(pf,f,get_next_format_from_precision(pf));
256 /*NOTREACHED*/
257}
258
259static EFT
260get_next_format(const char **pf, EFT eft)
261{
262 int infmt;
263 const char *f;
264
265 if (eft == FMTCHECK_WIDTH) {
266 (*pf)++;
267 return get_next_format_from_width(pf);
268 } else if (eft == FMTCHECK_PRECISION) {
269 (*pf)++;
270 return get_next_format_from_precision(pf);
271 }
272
273 f = *pf;
274 infmt = 0;
275 while (!infmt) {
276 f = strchr(f, '%');
277 if (f == NULL)
278 RETURN(pf,f,FMTCHECK_DONE);
279 f++;
280 if (!*f)
281 RETURN(pf,f,FMTCHECK_UNKNOWN);
282 if (*f != '%')
283 infmt = 1;
284 else
285 f++;
286 }
287
288 /* Eat any of the flags */
1f2f436a 289 while (*f && (strchr("#'0- +", *f)))
9385eb3d
A
290 f++;
291
292 if (*f == '*') {
293 RETURN(pf,f,FMTCHECK_WIDTH);
294 }
295 /* eat any width */
296 while (isdigit(*f)) f++;
297 if (!*f) {
298 RETURN(pf,f,FMTCHECK_UNKNOWN);
299 }
300
301 RETURN(pf,f,get_next_format_from_width(pf));
302 /*NOTREACHED*/
303}
304
1f2f436a 305const char *
9385eb3d
A
306__fmtcheck(const char *f1, const char *f2)
307{
308 const char *f1p, *f2p;
309 EFT f1t, f2t;
310
311 if (!f1) return f2;
312
313 f1p = f1;
314 f1t = FMTCHECK_START;
315 f2p = f2;
316 f2t = FMTCHECK_START;
317 while ((f1t = get_next_format(&f1p, f1t)) != FMTCHECK_DONE) {
318 if (f1t == FMTCHECK_UNKNOWN)
319 return f2;
320 f2t = get_next_format(&f2p, f2t);
321 if (f1t != f2t)
322 return f2;
323 }
324 return f1;
325}