]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/libbsd/libbsd/lib/contrib/src/fmtcheck.c
Update
[l4.git] / l4 / pkg / libbsd / libbsd / lib / contrib / src / fmtcheck.c
1 /*-
2  * Copyright (c) 2000 The NetBSD Foundation, Inc.
3  * All rights reserved.
4  *
5  * This code was contributed to The NetBSD Foundation by Allen Briggs.
6  *
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  *
16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 /*      $NetBSD: fmtcheck.c,v 1.2 2000/11/01 01:17:20 briggs Exp $      */
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD: /repoman/r/ncvs/src/lib/libc/gen/fmtcheck.c,v 1.8 2005/03/21 08:00:55 das Exp $");
32
33 #include <stdio.h>
34 #include <string.h>
35 #include <ctype.h>
36
37 /* __weak_reference(__fmtcheck, fmtcheck); */
38
39 enum __e_fmtcheck_types {
40         FMTCHECK_START,
41         FMTCHECK_SHORT,
42         FMTCHECK_INT,
43         FMTCHECK_LONG,
44         FMTCHECK_QUAD,
45         FMTCHECK_PTRDIFFT,
46         FMTCHECK_SIZET,
47         FMTCHECK_SHORTPOINTER,
48         FMTCHECK_INTPOINTER,
49         FMTCHECK_LONGPOINTER,
50         FMTCHECK_QUADPOINTER,
51         FMTCHECK_PTRDIFFTPOINTER,
52         FMTCHECK_SIZETPOINTER,
53 #ifndef NO_FLOATING_POINT
54         FMTCHECK_DOUBLE,
55         FMTCHECK_LONGDOUBLE,
56 #endif
57         FMTCHECK_STRING,
58         FMTCHECK_WIDTH,
59         FMTCHECK_PRECISION,
60         FMTCHECK_DONE,
61         FMTCHECK_UNKNOWN
62 };
63 typedef enum __e_fmtcheck_types EFT;
64
65 #define RETURN(pf,f,r) do { \
66                         *(pf) = (f); \
67                         return r; \
68                        } /*NOTREACHED*/ /*CONSTCOND*/ while (0)
69
70 static EFT
71 get_next_format_from_precision(const char **pf)
72 {
73         int             sh, lg, quad, longdouble, ptrdifft, sizet;
74         const char      *f;
75
76         sh = lg = quad = longdouble = ptrdifft = sizet = 0;
77
78         f = *pf;
79         switch (*f) {
80         case 'h':
81                 f++;
82                 sh = 1;
83                 break;
84         case 'l':
85                 f++;
86                 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
87                 if (*f == 'l') {
88                         f++;
89                         quad = 1;
90                 } else {
91                         lg = 1;
92                 }
93                 break;
94         case 'q':
95                 f++;
96                 quad = 1;
97                 break;
98         case 't':
99                 f++;
100                 ptrdifft = 1;
101                 break;
102         case 'z':
103                 f++;
104                 sizet = 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                 if (ptrdifft)
122                         RETURN(pf,f,FMTCHECK_PTRDIFFT);
123                 if (sizet)
124                         RETURN(pf,f,FMTCHECK_SIZET);
125                 RETURN(pf,f,FMTCHECK_INT);
126         }
127         if (*f == 'n') {
128                 if (longdouble)
129                         RETURN(pf,f,FMTCHECK_UNKNOWN);
130                 if (sh)
131                         RETURN(pf,f,FMTCHECK_SHORTPOINTER);
132                 if (lg)
133                         RETURN(pf,f,FMTCHECK_LONGPOINTER);
134                 if (quad)
135                         RETURN(pf,f,FMTCHECK_QUADPOINTER);
136                 if (ptrdifft)
137                         RETURN(pf,f,FMTCHECK_PTRDIFFTPOINTER);
138                 if (sizet)
139                         RETURN(pf,f,FMTCHECK_SIZETPOINTER);
140                 RETURN(pf,f,FMTCHECK_INTPOINTER);
141         }
142         if (strchr("DOU", *f)) {
143                 if (sh + lg + quad + longdouble + ptrdifft + sizet)
144                         RETURN(pf,f,FMTCHECK_UNKNOWN);
145                 RETURN(pf,f,FMTCHECK_LONG);
146         }
147 #ifndef NO_FLOATING_POINT
148         if (strchr("aAeEfFgG", *f)) {
149                 if (longdouble)
150                         RETURN(pf,f,FMTCHECK_LONGDOUBLE);
151                 if (sh + lg + quad + ptrdifft + sizet)
152                         RETURN(pf,f,FMTCHECK_UNKNOWN);
153                 RETURN(pf,f,FMTCHECK_DOUBLE);
154         }
155 #endif
156         if (*f == 'c') {
157                 if (sh + lg + quad + longdouble + ptrdifft + sizet)
158                         RETURN(pf,f,FMTCHECK_UNKNOWN);
159                 RETURN(pf,f,FMTCHECK_INT);
160         }
161         if (*f == 's') {
162                 if (sh + lg + quad + longdouble + ptrdifft + sizet)
163                         RETURN(pf,f,FMTCHECK_UNKNOWN);
164                 RETURN(pf,f,FMTCHECK_STRING);
165         }
166         if (*f == 'p') {
167                 if (sh + lg + quad + longdouble + ptrdifft + sizet)
168                         RETURN(pf,f,FMTCHECK_UNKNOWN);
169                 RETURN(pf,f,FMTCHECK_LONG);
170         }
171         RETURN(pf,f,FMTCHECK_UNKNOWN);
172         /*NOTREACHED*/
173 }
174
175 static EFT
176 get_next_format_from_width(const char **pf)
177 {
178         const char      *f;
179
180         f = *pf;
181         if (*f == '.') {
182                 f++;
183                 if (*f == '*') {
184                         RETURN(pf,f,FMTCHECK_PRECISION);
185                 }
186                 /* eat any precision (empty is allowed) */
187                 while (isdigit(*f)) f++;
188                 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
189         }
190         RETURN(pf,f,get_next_format_from_precision(pf));
191         /*NOTREACHED*/
192 }
193
194 static EFT
195 get_next_format(const char **pf, EFT eft)
196 {
197         int             infmt;
198         const char      *f;
199
200         if (eft == FMTCHECK_WIDTH) {
201                 (*pf)++;
202                 return get_next_format_from_width(pf);
203         } else if (eft == FMTCHECK_PRECISION) {
204                 (*pf)++;
205                 return get_next_format_from_precision(pf);
206         }
207
208         f = *pf;
209         infmt = 0;
210         while (!infmt) {
211                 f = strchr(f, '%');
212                 if (f == NULL)
213                         RETURN(pf,f,FMTCHECK_DONE);
214                 f++;
215                 if (!*f)
216                         RETURN(pf,f,FMTCHECK_UNKNOWN);
217                 if (*f != '%')
218                         infmt = 1;
219                 else
220                         f++;
221         }
222
223         /* Eat any of the flags */
224         while (*f && (strchr("#'0- +", *f)))
225                 f++;
226
227         if (*f == '*') {
228                 RETURN(pf,f,FMTCHECK_WIDTH);
229         }
230         /* eat any width */
231         while (isdigit(*f)) f++;
232         if (!*f) {
233                 RETURN(pf,f,FMTCHECK_UNKNOWN);
234         }
235
236         RETURN(pf,f,get_next_format_from_width(pf));
237         /*NOTREACHED*/
238 }
239
240 __const char *
241 fmtcheck(const char *f1, const char *f2)
242 {
243         const char      *f1p, *f2p;
244         EFT             f1t, f2t;
245
246         if (!f1) return f2;
247         
248         f1p = f1;
249         f1t = FMTCHECK_START;
250         f2p = f2;
251         f2t = FMTCHECK_START;
252         while ((f1t = get_next_format(&f1p, f1t)) != FMTCHECK_DONE) {
253                 if (f1t == FMTCHECK_UNKNOWN)
254                         return f2;
255                 f2t = get_next_format(&f2p, f2t);
256                 if (f1t != f2t)
257                         return f2;
258         }
259         return f1;
260 }