Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/file/src/fmtcheck.c
39478 views
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
#ifndef lint
33
FILE_RCSID("@(#)$File: fmtcheck.c,v 1.6 2022/09/24 20:30:13 christos Exp $")
34
#endif /* lint */
35
36
#include <stdio.h>
37
#include <string.h>
38
#include <ctype.h>
39
40
enum __e_fmtcheck_types {
41
FMTCHECK_START,
42
FMTCHECK_SHORT,
43
FMTCHECK_INT,
44
FMTCHECK_LONG,
45
FMTCHECK_QUAD,
46
FMTCHECK_SHORTPOINTER,
47
FMTCHECK_INTPOINTER,
48
FMTCHECK_LONGPOINTER,
49
FMTCHECK_QUADPOINTER,
50
FMTCHECK_DOUBLE,
51
FMTCHECK_LONGDOUBLE,
52
FMTCHECK_STRING,
53
FMTCHECK_WIDTH,
54
FMTCHECK_PRECISION,
55
FMTCHECK_DONE,
56
FMTCHECK_UNKNOWN
57
};
58
typedef enum __e_fmtcheck_types EFT;
59
60
#define RETURN(pf,f,r) do { \
61
*(pf) = (f); \
62
return r; \
63
} /*NOTREACHED*/ /*CONSTCOND*/ while (0)
64
65
static EFT
66
get_next_format_from_precision(const char **pf)
67
{
68
int sh, lg, quad, longdouble;
69
const char *f;
70
71
sh = lg = quad = longdouble = 0;
72
73
f = *pf;
74
switch (*f) {
75
case 'h':
76
f++;
77
sh = 1;
78
break;
79
case 'l':
80
f++;
81
if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
82
if (*f == 'l') {
83
f++;
84
quad = 1;
85
} else {
86
lg = 1;
87
}
88
break;
89
case 'q':
90
f++;
91
quad = 1;
92
break;
93
case 'L':
94
f++;
95
longdouble = 1;
96
break;
97
#ifdef WIN32
98
case 'I':
99
f++;
100
if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
101
if (*f == '3' && f[1] == '2') {
102
f += 2;
103
} else if (*f == '6' && f[1] == '4') {
104
f += 2;
105
quad = 1;
106
}
107
#ifdef _WIN64
108
else {
109
quad = 1;
110
}
111
#endif
112
break;
113
#endif
114
default:
115
break;
116
}
117
if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
118
if (strchr("diouxX", *f)) {
119
if (longdouble)
120
RETURN(pf,f,FMTCHECK_UNKNOWN);
121
if (lg)
122
RETURN(pf,f,FMTCHECK_LONG);
123
if (quad)
124
RETURN(pf,f,FMTCHECK_QUAD);
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
RETURN(pf,f,FMTCHECK_INTPOINTER);
137
}
138
if (strchr("DOU", *f)) {
139
if (sh + lg + quad + longdouble)
140
RETURN(pf,f,FMTCHECK_UNKNOWN);
141
RETURN(pf,f,FMTCHECK_LONG);
142
}
143
if (strchr("eEfg", *f)) {
144
if (longdouble)
145
RETURN(pf,f,FMTCHECK_LONGDOUBLE);
146
if (sh + lg + quad)
147
RETURN(pf,f,FMTCHECK_UNKNOWN);
148
RETURN(pf,f,FMTCHECK_DOUBLE);
149
}
150
if (*f == 'c') {
151
if (sh + lg + quad + longdouble)
152
RETURN(pf,f,FMTCHECK_UNKNOWN);
153
RETURN(pf,f,FMTCHECK_INT);
154
}
155
if (*f == 's') {
156
if (sh + lg + quad + longdouble)
157
RETURN(pf,f,FMTCHECK_UNKNOWN);
158
RETURN(pf,f,FMTCHECK_STRING);
159
}
160
if (*f == 'p') {
161
if (sh + lg + quad + longdouble)
162
RETURN(pf,f,FMTCHECK_UNKNOWN);
163
RETURN(pf,f,FMTCHECK_LONG);
164
}
165
RETURN(pf,f,FMTCHECK_UNKNOWN);
166
/*NOTREACHED*/
167
}
168
169
static EFT
170
get_next_format_from_width(const char **pf)
171
{
172
const char *f;
173
174
f = *pf;
175
if (*f == '.') {
176
f++;
177
if (*f == '*') {
178
RETURN(pf,f,FMTCHECK_PRECISION);
179
}
180
/* eat any precision (empty is allowed) */
181
while (isdigit((unsigned char)*f)) f++;
182
if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
183
}
184
RETURN(pf,f,get_next_format_from_precision(pf));
185
/*NOTREACHED*/
186
}
187
188
static EFT
189
get_next_format(const char **pf, EFT eft)
190
{
191
int infmt;
192
const char *f;
193
194
if (eft == FMTCHECK_WIDTH) {
195
(*pf)++;
196
return get_next_format_from_width(pf);
197
} else if (eft == FMTCHECK_PRECISION) {
198
(*pf)++;
199
return get_next_format_from_precision(pf);
200
}
201
202
f = *pf;
203
infmt = 0;
204
while (!infmt) {
205
f = strchr(f, '%');
206
if (f == NULL)
207
RETURN(pf,f,FMTCHECK_DONE);
208
f++;
209
if (!*f)
210
RETURN(pf,f,FMTCHECK_UNKNOWN);
211
if (*f != '%')
212
infmt = 1;
213
else
214
f++;
215
}
216
217
/* Eat any of the flags */
218
while (*f && (strchr("#0- +", *f)))
219
f++;
220
221
if (*f == '*') {
222
RETURN(pf,f,FMTCHECK_WIDTH);
223
}
224
/* eat any width */
225
while (isdigit((unsigned char)*f)) f++;
226
if (!*f) {
227
RETURN(pf,f,FMTCHECK_UNKNOWN);
228
}
229
230
RETURN(pf,f,get_next_format_from_width(pf));
231
/*NOTREACHED*/
232
}
233
234
const char *
235
fmtcheck(const char *f1, const char *f2)
236
{
237
const char *f1p, *f2p;
238
EFT f1t, f2t;
239
240
if (!f1) return f2;
241
242
f1p = f1;
243
f1t = FMTCHECK_START;
244
f2p = f2;
245
f2t = FMTCHECK_START;
246
while ((f1t = get_next_format(&f1p, f1t)) != FMTCHECK_DONE) {
247
if (f1t == FMTCHECK_UNKNOWN)
248
return f2;
249
f2t = get_next_format(&f2p, f2t);
250
if (f1t != f2t)
251
return f2;
252
}
253
return f1;
254
}
255
256