1/* $NetBSD: fmtcheck.c,v 1.2 2000/11/01 01:17:20 briggs Exp $ */
2
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.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the NetBSD
20 * Foundation, Inc. and its contributors.
21 * 4. Neither the name of The NetBSD Foundation nor the names of its
22 * contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#include <sys/cdefs.h>
39#ifndef lint
40static const char rcsid[] =
41 "$FreeBSD: head/lib/libc/gen/fmtcheck.c 81586 2001-08-13 14:06:34Z ru $";
42#endif /* not lint */
43
44#include "namespace.h"
45
46#include <stdio.h>
47#include <string.h>
48#include <ctype.h>
49
50#ifdef __weak_alias
51__weak_alias(fmtcheck,__fmtcheck)
52#endif
53
54enum __e_fmtcheck_types {
55 FMTCHECK_START,
56 FMTCHECK_SHORT,
57 FMTCHECK_INT,
58 FMTCHECK_LONG,
59 FMTCHECK_QUAD,
60 FMTCHECK_SHORTPOINTER,
61 FMTCHECK_INTPOINTER,
62 FMTCHECK_LONGPOINTER,
63 FMTCHECK_QUADPOINTER,
64 FMTCHECK_DOUBLE,
65 FMTCHECK_LONGDOUBLE,
66 FMTCHECK_STRING,
67 FMTCHECK_WIDTH,
68 FMTCHECK_PRECISION,
69 FMTCHECK_DONE,
70 FMTCHECK_UNKNOWN
71};
72typedef enum __e_fmtcheck_types EFT;
73
74#define RETURN(pf,f,r) do { \
75 *(pf) = (f); \
76 return r; \
77 } /*NOTREACHED*/ /*CONSTCOND*/ while (0)
78
79static EFT
80get_next_format_from_precision(const char **pf)
81{
82 int sh, lg, quad, longdouble;
83 const char *f;
84
85 sh = lg = quad = longdouble = 0;
86
87 f = *pf;
88 switch (*f) {
89 case 'h':
90 f++;
91 sh = 1;
92 break;
93 case 'l':
94 f++;
95 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
96 if (*f == 'l') {
97 f++;
98 quad = 1;
99 } else {
100 lg = 1;
101 }
102 break;
103 case 'q':
104 f++;
105 quad = 1;
106 break;
107 case 'L':
108 f++;
109 longdouble = 1;
110 break;
111 default:
112 break;
113 }
114 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
115 if (strchr("diouxX", *f)) {
116 if (longdouble)
117 RETURN(pf,f,FMTCHECK_UNKNOWN);
118 if (lg)
119 RETURN(pf,f,FMTCHECK_LONG);
120 if (quad)
121 RETURN(pf,f,FMTCHECK_QUAD);
122 RETURN(pf,f,FMTCHECK_INT);
123 }
124 if (*f == 'n') {
125 if (longdouble)
126 RETURN(pf,f,FMTCHECK_UNKNOWN);
127 if (sh)
128 RETURN(pf,f,FMTCHECK_SHORTPOINTER);
129 if (lg)
130 RETURN(pf,f,FMTCHECK_LONGPOINTER);
131 if (quad)
132 RETURN(pf,f,FMTCHECK_QUADPOINTER);
133 RETURN(pf,f,FMTCHECK_INTPOINTER);
134 }
135 if (strchr("DOU", *f)) {
136 if (sh + lg + quad + longdouble)
137 RETURN(pf,f,FMTCHECK_UNKNOWN);
138 RETURN(pf,f,FMTCHECK_LONG);
139 }
140 if (strchr("eEfg", *f)) {
141 if (longdouble)
142 RETURN(pf,f,FMTCHECK_LONGDOUBLE);
143 if (sh + lg + quad)
144 RETURN(pf,f,FMTCHECK_UNKNOWN);
145 RETURN(pf,f,FMTCHECK_DOUBLE);
146 }
147 if (*f == 'c') {
148 if (sh + lg + quad + longdouble)
149 RETURN(pf,f,FMTCHECK_UNKNOWN);
150 RETURN(pf,f,FMTCHECK_INT);
151 }
152 if (*f == 's') {
153 if (sh + lg + quad + longdouble)
154 RETURN(pf,f,FMTCHECK_UNKNOWN);
155 RETURN(pf,f,FMTCHECK_STRING);
156 }
157 if (*f == 'p') {
158 if (sh + lg + quad + longdouble)
159 RETURN(pf,f,FMTCHECK_UNKNOWN);
160 RETURN(pf,f,FMTCHECK_LONG);
161 }
162 RETURN(pf,f,FMTCHECK_UNKNOWN);
163 /*NOTREACHED*/
164}
165
166static EFT
167get_next_format_from_width(const char **pf)
168{
169 const char *f;
170
171 f = *pf;
172 if (*f == '.') {
173 f++;
174 if (*f == '*') {
175 RETURN(pf,f,FMTCHECK_PRECISION);
176 }
177 /* eat any precision (empty is allowed) */
178 while (isdigit(*f)) f++;
179 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
180 }
181 RETURN(pf,f,get_next_format_from_precision(pf));
182 /*NOTREACHED*/
183}
184
185static EFT
186get_next_format(const char **pf, EFT eft)
187{
188 int infmt;
189 const char *f;
190
191 if (eft == FMTCHECK_WIDTH) {
192 (*pf)++;
193 return get_next_format_from_width(pf);
194 } else if (eft == FMTCHECK_PRECISION) {
195 (*pf)++;
196 return get_next_format_from_precision(pf);
197 }
198
199 f = *pf;
200 infmt = 0;
201 while (!infmt) {
202 f = strchr(f, '%');
203 if (f == NULL)
204 RETURN(pf,f,FMTCHECK_DONE);
205 f++;
206 if (!*f)
207 RETURN(pf,f,FMTCHECK_UNKNOWN);
208 if (*f != '%')
209 infmt = 1;
210 else
211 f++;
212 }
213
214 /* Eat any of the flags */
215 while (*f && (strchr("#0- +", *f)))
216 f++;
217
218 if (*f == '*') {
219 RETURN(pf,f,FMTCHECK_WIDTH);
220 }
221 /* eat any width */
222 while (isdigit(*f)) f++;
223 if (!*f) {
224 RETURN(pf,f,FMTCHECK_UNKNOWN);
225 }
226
227 RETURN(pf,f,get_next_format_from_width(pf));
228 /*NOTREACHED*/
229}
230
231__const char *
232fmtcheck(const char *f1, const char *f2)
233{
234 const char *f1p, *f2p;
235 EFT f1t, f2t;
236
237 if (!f1) return f2;
238
239 f1p = f1;
240 f1t = FMTCHECK_START;
241 f2p = f2;
242 f2t = FMTCHECK_START;
243 while ((f1t = get_next_format(&f1p, f1t)) != FMTCHECK_DONE) {
244 if (f1t == FMTCHECK_UNKNOWN)
245 return f2;
246 f2t = get_next_format(&f2p, f2t);
247 if (f1t != f2t)
248 return f2;
249 }
250 return f1;
251}
2
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.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the NetBSD
20 * Foundation, Inc. and its contributors.
21 * 4. Neither the name of The NetBSD Foundation nor the names of its
22 * contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#include <sys/cdefs.h>
39#ifndef lint
40static const char rcsid[] =
41 "$FreeBSD: head/lib/libc/gen/fmtcheck.c 81586 2001-08-13 14:06:34Z ru $";
42#endif /* not lint */
43
44#include "namespace.h"
45
46#include <stdio.h>
47#include <string.h>
48#include <ctype.h>
49
50#ifdef __weak_alias
51__weak_alias(fmtcheck,__fmtcheck)
52#endif
53
54enum __e_fmtcheck_types {
55 FMTCHECK_START,
56 FMTCHECK_SHORT,
57 FMTCHECK_INT,
58 FMTCHECK_LONG,
59 FMTCHECK_QUAD,
60 FMTCHECK_SHORTPOINTER,
61 FMTCHECK_INTPOINTER,
62 FMTCHECK_LONGPOINTER,
63 FMTCHECK_QUADPOINTER,
64 FMTCHECK_DOUBLE,
65 FMTCHECK_LONGDOUBLE,
66 FMTCHECK_STRING,
67 FMTCHECK_WIDTH,
68 FMTCHECK_PRECISION,
69 FMTCHECK_DONE,
70 FMTCHECK_UNKNOWN
71};
72typedef enum __e_fmtcheck_types EFT;
73
74#define RETURN(pf,f,r) do { \
75 *(pf) = (f); \
76 return r; \
77 } /*NOTREACHED*/ /*CONSTCOND*/ while (0)
78
79static EFT
80get_next_format_from_precision(const char **pf)
81{
82 int sh, lg, quad, longdouble;
83 const char *f;
84
85 sh = lg = quad = longdouble = 0;
86
87 f = *pf;
88 switch (*f) {
89 case 'h':
90 f++;
91 sh = 1;
92 break;
93 case 'l':
94 f++;
95 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
96 if (*f == 'l') {
97 f++;
98 quad = 1;
99 } else {
100 lg = 1;
101 }
102 break;
103 case 'q':
104 f++;
105 quad = 1;
106 break;
107 case 'L':
108 f++;
109 longdouble = 1;
110 break;
111 default:
112 break;
113 }
114 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
115 if (strchr("diouxX", *f)) {
116 if (longdouble)
117 RETURN(pf,f,FMTCHECK_UNKNOWN);
118 if (lg)
119 RETURN(pf,f,FMTCHECK_LONG);
120 if (quad)
121 RETURN(pf,f,FMTCHECK_QUAD);
122 RETURN(pf,f,FMTCHECK_INT);
123 }
124 if (*f == 'n') {
125 if (longdouble)
126 RETURN(pf,f,FMTCHECK_UNKNOWN);
127 if (sh)
128 RETURN(pf,f,FMTCHECK_SHORTPOINTER);
129 if (lg)
130 RETURN(pf,f,FMTCHECK_LONGPOINTER);
131 if (quad)
132 RETURN(pf,f,FMTCHECK_QUADPOINTER);
133 RETURN(pf,f,FMTCHECK_INTPOINTER);
134 }
135 if (strchr("DOU", *f)) {
136 if (sh + lg + quad + longdouble)
137 RETURN(pf,f,FMTCHECK_UNKNOWN);
138 RETURN(pf,f,FMTCHECK_LONG);
139 }
140 if (strchr("eEfg", *f)) {
141 if (longdouble)
142 RETURN(pf,f,FMTCHECK_LONGDOUBLE);
143 if (sh + lg + quad)
144 RETURN(pf,f,FMTCHECK_UNKNOWN);
145 RETURN(pf,f,FMTCHECK_DOUBLE);
146 }
147 if (*f == 'c') {
148 if (sh + lg + quad + longdouble)
149 RETURN(pf,f,FMTCHECK_UNKNOWN);
150 RETURN(pf,f,FMTCHECK_INT);
151 }
152 if (*f == 's') {
153 if (sh + lg + quad + longdouble)
154 RETURN(pf,f,FMTCHECK_UNKNOWN);
155 RETURN(pf,f,FMTCHECK_STRING);
156 }
157 if (*f == 'p') {
158 if (sh + lg + quad + longdouble)
159 RETURN(pf,f,FMTCHECK_UNKNOWN);
160 RETURN(pf,f,FMTCHECK_LONG);
161 }
162 RETURN(pf,f,FMTCHECK_UNKNOWN);
163 /*NOTREACHED*/
164}
165
166static EFT
167get_next_format_from_width(const char **pf)
168{
169 const char *f;
170
171 f = *pf;
172 if (*f == '.') {
173 f++;
174 if (*f == '*') {
175 RETURN(pf,f,FMTCHECK_PRECISION);
176 }
177 /* eat any precision (empty is allowed) */
178 while (isdigit(*f)) f++;
179 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
180 }
181 RETURN(pf,f,get_next_format_from_precision(pf));
182 /*NOTREACHED*/
183}
184
185static EFT
186get_next_format(const char **pf, EFT eft)
187{
188 int infmt;
189 const char *f;
190
191 if (eft == FMTCHECK_WIDTH) {
192 (*pf)++;
193 return get_next_format_from_width(pf);
194 } else if (eft == FMTCHECK_PRECISION) {
195 (*pf)++;
196 return get_next_format_from_precision(pf);
197 }
198
199 f = *pf;
200 infmt = 0;
201 while (!infmt) {
202 f = strchr(f, '%');
203 if (f == NULL)
204 RETURN(pf,f,FMTCHECK_DONE);
205 f++;
206 if (!*f)
207 RETURN(pf,f,FMTCHECK_UNKNOWN);
208 if (*f != '%')
209 infmt = 1;
210 else
211 f++;
212 }
213
214 /* Eat any of the flags */
215 while (*f && (strchr("#0- +", *f)))
216 f++;
217
218 if (*f == '*') {
219 RETURN(pf,f,FMTCHECK_WIDTH);
220 }
221 /* eat any width */
222 while (isdigit(*f)) f++;
223 if (!*f) {
224 RETURN(pf,f,FMTCHECK_UNKNOWN);
225 }
226
227 RETURN(pf,f,get_next_format_from_width(pf));
228 /*NOTREACHED*/
229}
230
231__const char *
232fmtcheck(const char *f1, const char *f2)
233{
234 const char *f1p, *f2p;
235 EFT f1t, f2t;
236
237 if (!f1) return f2;
238
239 f1p = f1;
240 f1t = FMTCHECK_START;
241 f2p = f2;
242 f2t = FMTCHECK_START;
243 while ((f1t = get_next_format(&f1p, f1t)) != FMTCHECK_DONE) {
244 if (f1t == FMTCHECK_UNKNOWN)
245 return f2;
246 f2t = get_next_format(&f2p, f2t);
247 if (f1t != f2t)
248 return f2;
249 }
250 return f1;
251}