]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/file/src/fmtcheck.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / file / src / fmtcheck.c
1 /*      $NetBSD: fmtcheck.c,v 1.8 2008/04/28 20:22:59 martin 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  *
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
31 #include "file.h"
32
33 #include <stdio.h>
34 #include <string.h>
35 #include <ctype.h>
36
37 enum __e_fmtcheck_types {
38         FMTCHECK_START,
39         FMTCHECK_SHORT,
40         FMTCHECK_INT,
41         FMTCHECK_LONG,
42         FMTCHECK_QUAD,
43         FMTCHECK_SHORTPOINTER,
44         FMTCHECK_INTPOINTER,
45         FMTCHECK_LONGPOINTER,
46         FMTCHECK_QUADPOINTER,
47         FMTCHECK_DOUBLE,
48         FMTCHECK_LONGDOUBLE,
49         FMTCHECK_STRING,
50         FMTCHECK_WIDTH,
51         FMTCHECK_PRECISION,
52         FMTCHECK_DONE,
53         FMTCHECK_UNKNOWN
54 };
55 typedef enum __e_fmtcheck_types EFT;
56
57 #define RETURN(pf,f,r) do { \
58                         *(pf) = (f); \
59                         return r; \
60                        } /*NOTREACHED*/ /*CONSTCOND*/ while (0)
61
62 static EFT
63 get_next_format_from_precision(const char **pf)
64 {
65         int             sh, lg, quad, longdouble;
66         const char      *f;
67
68         sh = lg = quad = longdouble = 0;
69
70         f = *pf;
71         switch (*f) {
72         case 'h':
73                 f++;
74                 sh = 1;
75                 break;
76         case 'l':
77                 f++;
78                 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
79                 if (*f == 'l') {
80                         f++;
81                         quad = 1;
82                 } else {
83                         lg = 1;
84                 }
85                 break;
86         case 'q':
87                 f++;
88                 quad = 1;
89                 break;
90         case 'L':
91                 f++;
92                 longdouble = 1;
93                 break;
94         default:
95                 break;
96         }
97         if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
98         if (strchr("diouxX", *f)) {
99                 if (longdouble)
100                         RETURN(pf,f,FMTCHECK_UNKNOWN);
101                 if (lg)
102                         RETURN(pf,f,FMTCHECK_LONG);
103                 if (quad)
104                         RETURN(pf,f,FMTCHECK_QUAD);
105                 RETURN(pf,f,FMTCHECK_INT);
106         }
107         if (*f == 'n') {
108                 if (longdouble)
109                         RETURN(pf,f,FMTCHECK_UNKNOWN);
110                 if (sh)
111                         RETURN(pf,f,FMTCHECK_SHORTPOINTER);
112                 if (lg)
113                         RETURN(pf,f,FMTCHECK_LONGPOINTER);
114                 if (quad)
115                         RETURN(pf,f,FMTCHECK_QUADPOINTER);
116                 RETURN(pf,f,FMTCHECK_INTPOINTER);
117         }
118         if (strchr("DOU", *f)) {
119                 if (sh + lg + quad + longdouble)
120                         RETURN(pf,f,FMTCHECK_UNKNOWN);
121                 RETURN(pf,f,FMTCHECK_LONG);
122         }
123         if (strchr("eEfg", *f)) {
124                 if (longdouble)
125                         RETURN(pf,f,FMTCHECK_LONGDOUBLE);
126                 if (sh + lg + quad)
127                         RETURN(pf,f,FMTCHECK_UNKNOWN);
128                 RETURN(pf,f,FMTCHECK_DOUBLE);
129         }
130         if (*f == 'c') {
131                 if (sh + lg + quad + longdouble)
132                         RETURN(pf,f,FMTCHECK_UNKNOWN);
133                 RETURN(pf,f,FMTCHECK_INT);
134         }
135         if (*f == 's') {
136                 if (sh + lg + quad + longdouble)
137                         RETURN(pf,f,FMTCHECK_UNKNOWN);
138                 RETURN(pf,f,FMTCHECK_STRING);
139         }
140         if (*f == 'p') {
141                 if (sh + lg + quad + longdouble)
142                         RETURN(pf,f,FMTCHECK_UNKNOWN);
143                 RETURN(pf,f,FMTCHECK_LONG);
144         }
145         RETURN(pf,f,FMTCHECK_UNKNOWN);
146         /*NOTREACHED*/
147 }
148
149 static EFT
150 get_next_format_from_width(const char **pf)
151 {
152         const char      *f;
153
154         f = *pf;
155         if (*f == '.') {
156                 f++;
157                 if (*f == '*') {
158                         RETURN(pf,f,FMTCHECK_PRECISION);
159                 }
160                 /* eat any precision (empty is allowed) */
161                 while (isdigit((unsigned char)*f)) f++;
162                 if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
163         }
164         RETURN(pf,f,get_next_format_from_precision(pf));
165         /*NOTREACHED*/
166 }
167
168 static EFT
169 get_next_format(const char **pf, EFT eft)
170 {
171         int             infmt;
172         const char      *f;
173
174         if (eft == FMTCHECK_WIDTH) {
175                 (*pf)++;
176                 return get_next_format_from_width(pf);
177         } else if (eft == FMTCHECK_PRECISION) {
178                 (*pf)++;
179                 return get_next_format_from_precision(pf);
180         }
181
182         f = *pf;
183         infmt = 0;
184         while (!infmt) {
185                 f = strchr(f, '%');
186                 if (f == NULL)
187                         RETURN(pf,f,FMTCHECK_DONE);
188                 f++;
189                 if (!*f)
190                         RETURN(pf,f,FMTCHECK_UNKNOWN);
191                 if (*f != '%')
192                         infmt = 1;
193                 else
194                         f++;
195         }
196
197         /* Eat any of the flags */
198         while (*f && (strchr("#0- +", *f)))
199                 f++;
200
201         if (*f == '*') {
202                 RETURN(pf,f,FMTCHECK_WIDTH);
203         }
204         /* eat any width */
205         while (isdigit((unsigned char)*f)) f++;
206         if (!*f) {
207                 RETURN(pf,f,FMTCHECK_UNKNOWN);
208         }
209
210         RETURN(pf,f,get_next_format_from_width(pf));
211         /*NOTREACHED*/
212 }
213
214 const char *
215 fmtcheck(const char *f1, const char *f2)
216 {
217         const char      *f1p, *f2p;
218         EFT             f1t, f2t;
219
220         if (!f1) return f2;
221         
222         f1p = f1;
223         f1t = FMTCHECK_START;
224         f2p = f2;
225         f2t = FMTCHECK_START;
226         while ((f1t = get_next_format(&f1p, f1t)) != FMTCHECK_DONE) {
227                 if (f1t == FMTCHECK_UNKNOWN)
228                         return f2;
229                 f2t = get_next_format(&f2p, f2t);
230                 if (f1t != f2t)
231                         return f2;
232         }
233         return f1;
234 }