Annotation of src/lib/libc/gen/fmtcheck.c, Revision 1.4
1.4 ! briggs 1: /* $NetBSD: fmtcheck.c,v 1.3 2000/11/16 02:10:18 matt Exp $ */
1.1 briggs 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: #if defined(LIBC_SCCS) && !defined(lint)
1.4 ! briggs 40: __RCSID("$NetBSD: fmtcheck.c,v 1.3 2000/11/16 02:10:18 matt Exp $");
1.1 briggs 41: #endif
42:
43: #include "namespace.h"
44:
1.3 matt 45: #include <stdio.h>
1.1 briggs 46: #include <string.h>
47: #include <ctype.h>
48:
49: #ifdef __weak_alias
50: __weak_alias(fmtcheck,__fmtcheck)
51: #endif
52:
53: enum __e_fmtcheck_types {
54: FMTCHECK_START,
55: FMTCHECK_SHORT,
56: FMTCHECK_INT,
57: FMTCHECK_LONG,
58: FMTCHECK_QUAD,
59: FMTCHECK_SHORTPOINTER,
60: FMTCHECK_INTPOINTER,
61: FMTCHECK_LONGPOINTER,
62: FMTCHECK_QUADPOINTER,
63: FMTCHECK_DOUBLE,
64: FMTCHECK_LONGDOUBLE,
65: FMTCHECK_STRING,
66: FMTCHECK_WIDTH,
67: FMTCHECK_PRECISION,
68: FMTCHECK_DONE,
69: FMTCHECK_UNKNOWN
70: };
71: typedef enum __e_fmtcheck_types EFT;
72:
73: #define RETURN(pf,f,r) do { \
74: *(pf) = (f); \
75: return r; \
76: } /*NOTREACHED*/ /*CONSTCOND*/ while (0)
77:
78: static EFT
79: get_next_format_from_precision(const char **pf)
80: {
81: int sh, lg, quad, longdouble;
82: const char *f;
83:
84: sh = lg = quad = longdouble = 0;
85:
86: f = *pf;
87: switch (*f) {
88: case 'h':
89: f++;
90: sh = 1;
91: break;
92: case 'l':
93: f++;
94: if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
95: if (*f == 'l') {
96: f++;
97: quad = 1;
98: } else {
99: lg = 1;
100: }
101: break;
102: case 'q':
103: f++;
104: quad = 1;
105: break;
106: case 'L':
107: f++;
108: longdouble = 1;
109: break;
110: default:
111: break;
112: }
113: if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
114: if (strchr("diouxX", *f)) {
115: if (longdouble)
116: RETURN(pf,f,FMTCHECK_UNKNOWN);
117: if (lg)
118: RETURN(pf,f,FMTCHECK_LONG);
119: if (quad)
120: RETURN(pf,f,FMTCHECK_QUAD);
121: RETURN(pf,f,FMTCHECK_INT);
122: }
123: if (*f == 'n') {
124: if (longdouble)
125: RETURN(pf,f,FMTCHECK_UNKNOWN);
126: if (sh)
127: RETURN(pf,f,FMTCHECK_SHORTPOINTER);
128: if (lg)
129: RETURN(pf,f,FMTCHECK_LONGPOINTER);
130: if (quad)
131: RETURN(pf,f,FMTCHECK_QUADPOINTER);
132: RETURN(pf,f,FMTCHECK_INTPOINTER);
133: }
134: if (strchr("DOU", *f)) {
135: if (sh + lg + quad + longdouble)
136: RETURN(pf,f,FMTCHECK_UNKNOWN);
137: RETURN(pf,f,FMTCHECK_LONG);
138: }
139: if (strchr("eEfg", *f)) {
140: if (longdouble)
141: RETURN(pf,f,FMTCHECK_LONGDOUBLE);
142: if (sh + lg + quad)
143: RETURN(pf,f,FMTCHECK_UNKNOWN);
144: RETURN(pf,f,FMTCHECK_DOUBLE);
145: }
146: if (*f == 'c') {
147: if (sh + lg + quad + longdouble)
148: RETURN(pf,f,FMTCHECK_UNKNOWN);
149: RETURN(pf,f,FMTCHECK_INT);
150: }
151: if (*f == 's') {
152: if (sh + lg + quad + longdouble)
153: RETURN(pf,f,FMTCHECK_UNKNOWN);
154: RETURN(pf,f,FMTCHECK_STRING);
155: }
156: if (*f == 'p') {
157: if (sh + lg + quad + longdouble)
158: RETURN(pf,f,FMTCHECK_UNKNOWN);
159: RETURN(pf,f,FMTCHECK_LONG);
160: }
161: RETURN(pf,f,FMTCHECK_UNKNOWN);
162: /*NOTREACHED*/
163: }
164:
165: static EFT
166: get_next_format_from_width(const char **pf)
167: {
168: const char *f;
169:
170: f = *pf;
171: if (*f == '.') {
172: f++;
173: if (*f == '*') {
174: RETURN(pf,f,FMTCHECK_PRECISION);
175: }
176: /* eat any precision (empty is allowed) */
177: while (isdigit(*f)) f++;
178: if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
179: }
180: RETURN(pf,f,get_next_format_from_precision(pf));
181: /*NOTREACHED*/
182: }
183:
184: static EFT
185: get_next_format(const char **pf, EFT eft)
186: {
187: int infmt;
188: const char *f;
189:
190: if (eft == FMTCHECK_WIDTH) {
191: (*pf)++;
192: return get_next_format_from_width(pf);
193: } else if (eft == FMTCHECK_PRECISION) {
194: (*pf)++;
195: return get_next_format_from_precision(pf);
196: }
197:
198: f = *pf;
199: infmt = 0;
200: while (!infmt) {
201: f = strchr(f, '%');
202: if (f == NULL)
203: RETURN(pf,f,FMTCHECK_DONE);
204: f++;
205: if (!*f)
206: RETURN(pf,f,FMTCHECK_UNKNOWN);
207: if (*f != '%')
208: infmt = 1;
209: else
210: f++;
211: }
212:
213: /* Eat any of the flags */
214: while (*f && (strchr("#0- +", *f)))
215: f++;
216:
217: if (*f == '*') {
218: RETURN(pf,f,FMTCHECK_WIDTH);
219: }
220: /* eat any width */
221: while (isdigit(*f)) f++;
222: if (!*f) {
223: RETURN(pf,f,FMTCHECK_UNKNOWN);
224: }
225:
226: RETURN(pf,f,get_next_format_from_width(pf));
227: /*NOTREACHED*/
228: }
229:
230: __const char *
1.2 briggs 231: fmtcheck(const char *f1, const char *f2)
1.1 briggs 232: {
233: const char *f1p, *f2p;
234: EFT f1t, f2t;
235:
236: if (!f1) return f2;
237:
238: f1p = f1;
239: f1t = FMTCHECK_START;
240: f2p = f2;
241: f2t = FMTCHECK_START;
242: while ((f1t = get_next_format(&f1p, f1t)) != FMTCHECK_DONE) {
243: if (f1t == FMTCHECK_UNKNOWN)
244: return f2;
245: f2t = get_next_format(&f2p, f2t);
246: if (f1t != f2t)
247: return f2;
248: }
249: return f1;
250: }
CVSweb <webmaster@jp.NetBSD.org>