amd64: declare initializecpu outside of SMP
[dragonfly.git] / lib / libc / gen / fmtcheck.c
blobb1c96f003d77cc6ef7afcbc733f56a3e8f724cd0
1 /*-
2 * Copyright (c) 2000 The NetBSD Foundation, Inc.
3 * All rights reserved.
5 * This code was contributed to The NetBSD Foundation by Allen Briggs.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the NetBSD
18 * Foundation, Inc. and its contributors.
19 * 4. Neither the name of The NetBSD Foundation nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
35 * $NetBSD: fmtcheck.c,v 1.2 2000/11/01 01:17:20 briggs Exp $
36 * $FreeBSD: src/lib/libc/gen/fmtcheck.c,v 1.9 2008/08/02 06:02:42 das Exp $
37 * $DragonFly: src/lib/libc/gen/fmtcheck.c,v 1.3 2003/08/22 19:31:21 asmodai Exp $
40 #include <stdio.h>
41 #include <string.h>
42 #include <ctype.h>
44 __weak_reference(__fmtcheck, fmtcheck);
46 enum __e_fmtcheck_types {
47 FMTCHECK_START,
48 FMTCHECK_SHORT,
49 FMTCHECK_INT,
50 FMTCHECK_WINTT,
51 FMTCHECK_LONG,
52 FMTCHECK_QUAD,
53 FMTCHECK_INTMAXT,
54 FMTCHECK_PTRDIFFT,
55 FMTCHECK_SIZET,
56 FMTCHECK_CHARPOINTER,
57 FMTCHECK_SHORTPOINTER,
58 FMTCHECK_INTPOINTER,
59 FMTCHECK_LONGPOINTER,
60 FMTCHECK_QUADPOINTER,
61 FMTCHECK_INTMAXTPOINTER,
62 FMTCHECK_PTRDIFFTPOINTER,
63 FMTCHECK_SIZETPOINTER,
64 #ifndef NO_FLOATING_POINT
65 FMTCHECK_DOUBLE,
66 FMTCHECK_LONGDOUBLE,
67 #endif
68 FMTCHECK_STRING,
69 FMTCHECK_WSTRING,
70 FMTCHECK_WIDTH,
71 FMTCHECK_PRECISION,
72 FMTCHECK_DONE,
73 FMTCHECK_UNKNOWN
75 typedef enum __e_fmtcheck_types EFT;
77 enum e_modifier {
78 MOD_NONE,
79 MOD_CHAR,
80 MOD_SHORT,
81 MOD_LONG,
82 MOD_QUAD,
83 MOD_INTMAXT,
84 MOD_LONGDOUBLE,
85 MOD_PTRDIFFT,
86 MOD_SIZET,
89 #define RETURN(pf,f,r) do { \
90 *(pf) = (f); \
91 return r; \
92 } /*NOTREACHED*/ /*CONSTCOND*/ while (0)
94 static EFT
95 get_next_format_from_precision(const char **pf)
97 enum e_modifier modifier;
98 const char *f;
100 f = *pf;
101 switch (*f) {
102 case 'h':
103 f++;
104 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
105 if (*f == 'h') {
106 f++;
107 modifier = MOD_CHAR;
108 } else {
109 modifier = MOD_SHORT;
111 break;
112 case 'j':
113 f++;
114 modifier = MOD_INTMAXT;
115 break;
116 case 'l':
117 f++;
118 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
119 if (*f == 'l') {
120 f++;
121 modifier = MOD_QUAD;
122 } else {
123 modifier = MOD_LONG;
125 break;
126 case 'q':
127 f++;
128 modifier = MOD_QUAD;
129 break;
130 case 't':
131 f++;
132 modifier = MOD_PTRDIFFT;
133 break;
134 case 'z':
135 f++;
136 modifier = MOD_SIZET;
137 break;
138 case 'L':
139 f++;
140 modifier = MOD_LONGDOUBLE;
141 break;
142 default:
143 modifier = MOD_NONE;
144 break;
146 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
147 if (strchr("diouxX", *f)) {
148 switch (modifier) {
149 case MOD_LONG:
150 RETURN(pf,f,FMTCHECK_LONG);
151 case MOD_QUAD:
152 RETURN(pf,f,FMTCHECK_QUAD);
153 case MOD_INTMAXT:
154 RETURN(pf,f,FMTCHECK_INTMAXT);
155 case MOD_PTRDIFFT:
156 RETURN(pf,f,FMTCHECK_PTRDIFFT);
157 case MOD_SIZET:
158 RETURN(pf,f,FMTCHECK_SIZET);
159 case MOD_CHAR:
160 case MOD_SHORT:
161 case MOD_NONE:
162 RETURN(pf,f,FMTCHECK_INT);
163 default:
164 RETURN(pf,f,FMTCHECK_UNKNOWN);
167 if (*f == 'n') {
168 switch (modifier) {
169 case MOD_CHAR:
170 RETURN(pf,f,FMTCHECK_CHARPOINTER);
171 case MOD_SHORT:
172 RETURN(pf,f,FMTCHECK_SHORTPOINTER);
173 case MOD_LONG:
174 RETURN(pf,f,FMTCHECK_LONGPOINTER);
175 case MOD_QUAD:
176 RETURN(pf,f,FMTCHECK_QUADPOINTER);
177 case MOD_INTMAXT:
178 RETURN(pf,f,FMTCHECK_INTMAXTPOINTER);
179 case MOD_PTRDIFFT:
180 RETURN(pf,f,FMTCHECK_PTRDIFFTPOINTER);
181 case MOD_SIZET:
182 RETURN(pf,f,FMTCHECK_SIZETPOINTER);
183 case MOD_NONE:
184 RETURN(pf,f,FMTCHECK_INTPOINTER);
185 default:
186 RETURN(pf,f,FMTCHECK_UNKNOWN);
189 if (strchr("DOU", *f)) {
190 if (modifier != MOD_NONE)
191 RETURN(pf,f,FMTCHECK_UNKNOWN);
192 RETURN(pf,f,FMTCHECK_LONG);
194 #ifndef NO_FLOATING_POINT
195 if (strchr("aAeEfFgG", *f)) {
196 switch (modifier) {
197 case MOD_LONGDOUBLE:
198 RETURN(pf,f,FMTCHECK_LONGDOUBLE);
199 case MOD_LONG:
200 case MOD_NONE:
201 RETURN(pf,f,FMTCHECK_DOUBLE);
202 default:
203 RETURN(pf,f,FMTCHECK_UNKNOWN);
206 #endif
207 if (*f == 'c') {
208 switch (modifier) {
209 case MOD_LONG:
210 RETURN(pf,f,FMTCHECK_WINTT);
211 case MOD_NONE:
212 RETURN(pf,f,FMTCHECK_INT);
213 default:
214 RETURN(pf,f,FMTCHECK_UNKNOWN);
217 if (*f == 'C') {
218 if (modifier != MOD_NONE)
219 RETURN(pf,f,FMTCHECK_UNKNOWN);
220 RETURN(pf,f,FMTCHECK_WINTT);
222 if (*f == 's') {
223 switch (modifier) {
224 case MOD_LONG:
225 RETURN(pf,f,FMTCHECK_WSTRING);
226 case MOD_NONE:
227 RETURN(pf,f,FMTCHECK_STRING);
228 default:
229 RETURN(pf,f,FMTCHECK_UNKNOWN);
232 if (*f == 'S') {
233 if (modifier != MOD_NONE)
234 RETURN(pf,f,FMTCHECK_UNKNOWN);
235 RETURN(pf,f,FMTCHECK_WSTRING);
237 if (*f == 'p') {
238 if (modifier != MOD_NONE)
239 RETURN(pf,f,FMTCHECK_UNKNOWN);
240 RETURN(pf,f,FMTCHECK_LONG);
242 RETURN(pf,f,FMTCHECK_UNKNOWN);
243 /*NOTREACHED*/
246 static EFT
247 get_next_format_from_width(const char **pf)
249 const char *f;
251 f = *pf;
252 if (*f == '.') {
253 f++;
254 if (*f == '*') {
255 RETURN(pf,f,FMTCHECK_PRECISION);
257 /* eat any precision (empty is allowed) */
258 while (isdigit(*f)) f++;
259 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
261 RETURN(pf,f,get_next_format_from_precision(pf));
262 /*NOTREACHED*/
265 static EFT
266 get_next_format(const char **pf, EFT eft)
268 int infmt;
269 const char *f;
271 if (eft == FMTCHECK_WIDTH) {
272 (*pf)++;
273 return get_next_format_from_width(pf);
274 } else if (eft == FMTCHECK_PRECISION) {
275 (*pf)++;
276 return get_next_format_from_precision(pf);
279 f = *pf;
280 infmt = 0;
281 while (!infmt) {
282 f = strchr(f, '%');
283 if (f == NULL)
284 RETURN(pf,f,FMTCHECK_DONE);
285 f++;
286 if (!*f)
287 RETURN(pf,f,FMTCHECK_UNKNOWN);
288 if (*f != '%')
289 infmt = 1;
290 else
291 f++;
294 /* Eat any of the flags */
295 while (*f && (strchr("#'0- +", *f)))
296 f++;
298 if (*f == '*') {
299 RETURN(pf,f,FMTCHECK_WIDTH);
301 /* eat any width */
302 while (isdigit(*f)) f++;
303 if (!*f) {
304 RETURN(pf,f,FMTCHECK_UNKNOWN);
307 RETURN(pf,f,get_next_format_from_width(pf));
308 /*NOTREACHED*/
311 const char *
312 __fmtcheck(const char *f1, const char *f2)
314 const char *f1p, *f2p;
315 EFT f1t, f2t;
317 if (!f1) return f2;
319 f1p = f1;
320 f1t = FMTCHECK_START;
321 f2p = f2;
322 f2t = FMTCHECK_START;
323 while ((f1t = get_next_format(&f1p, f1t)) != FMTCHECK_DONE) {
324 if (f1t == FMTCHECK_UNKNOWN)
325 return f2;
326 f2t = get_next_format(&f2p, f2t);
327 if (f1t != f2t)
328 return f2;
330 return f1;