Coverage Report

Created: 2022-09-30 06:06

/src/file/src/fmtcheck.c
Line
Count
Source (jump to first uncovered line)
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
323k
#define RETURN(pf,f,r) do { \
61
323k
      *(pf) = (f); \
62
323k
      return r; \
63
323k
           } /*NOTREACHED*/ /*CONSTCOND*/ while (0)
64
65
static EFT
66
get_next_format_from_precision(const char **pf)
67
92.5k
{
68
92.5k
  int   sh, lg, quad, longdouble;
69
92.5k
  const char  *f;
70
71
92.5k
  sh = lg = quad = longdouble = 0;
72
73
92.5k
  f = *pf;
74
92.5k
  switch (*f) {
75
0
  case 'h':
76
0
    f++;
77
0
    sh = 1;
78
0
    break;
79
630
  case 'l':
80
630
    f++;
81
630
    if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
82
630
    if (*f == 'l') {
83
630
      f++;
84
630
      quad = 1;
85
630
    } else {
86
0
      lg = 1;
87
0
    }
88
630
    break;
89
0
  case 'q':
90
0
    f++;
91
0
    quad = 1;
92
0
    break;
93
0
  case 'L':
94
0
    f++;
95
0
    longdouble = 1;
96
0
    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
91.8k
  default:
115
91.8k
    break;
116
92.5k
  }
117
92.5k
  if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
118
92.5k
  if (strchr("diouxX", *f)) {
119
62.8k
    if (longdouble)
120
0
      RETURN(pf,f,FMTCHECK_UNKNOWN);
121
62.8k
    if (lg)
122
0
      RETURN(pf,f,FMTCHECK_LONG);
123
62.8k
    if (quad)
124
630
      RETURN(pf,f,FMTCHECK_QUAD);
125
62.2k
    RETURN(pf,f,FMTCHECK_INT);
126
62.2k
  }
127
29.6k
  if (*f == 'n') {
128
0
    if (longdouble)
129
0
      RETURN(pf,f,FMTCHECK_UNKNOWN);
130
0
    if (sh)
131
0
      RETURN(pf,f,FMTCHECK_SHORTPOINTER);
132
0
    if (lg)
133
0
      RETURN(pf,f,FMTCHECK_LONGPOINTER);
134
0
    if (quad)
135
0
      RETURN(pf,f,FMTCHECK_QUADPOINTER);
136
0
    RETURN(pf,f,FMTCHECK_INTPOINTER);
137
0
  }
138
29.6k
  if (strchr("DOU", *f)) {
139
0
    if (sh + lg + quad + longdouble)
140
0
      RETURN(pf,f,FMTCHECK_UNKNOWN);
141
0
    RETURN(pf,f,FMTCHECK_LONG);
142
0
  }
143
29.6k
  if (strchr("eEfg", *f)) {
144
596
    if (longdouble)
145
0
      RETURN(pf,f,FMTCHECK_LONGDOUBLE);
146
596
    if (sh + lg + quad)
147
0
      RETURN(pf,f,FMTCHECK_UNKNOWN);
148
596
    RETURN(pf,f,FMTCHECK_DOUBLE);
149
596
  }
150
29.0k
  if (*f == 'c') {
151
211
    if (sh + lg + quad + longdouble)
152
0
      RETURN(pf,f,FMTCHECK_UNKNOWN);
153
211
    RETURN(pf,f,FMTCHECK_INT);
154
211
  }
155
28.8k
  if (*f == 's') {
156
28.8k
    if (sh + lg + quad + longdouble)
157
0
      RETURN(pf,f,FMTCHECK_UNKNOWN);
158
28.8k
    RETURN(pf,f,FMTCHECK_STRING);
159
28.8k
  }
160
0
  if (*f == 'p') {
161
0
    if (sh + lg + quad + longdouble)
162
0
      RETURN(pf,f,FMTCHECK_UNKNOWN);
163
0
    RETURN(pf,f,FMTCHECK_LONG);
164
0
  }
165
0
  RETURN(pf,f,FMTCHECK_UNKNOWN);
166
  /*NOTREACHED*/
167
0
}
168
169
static EFT
170
get_next_format_from_width(const char **pf)
171
92.5k
{
172
92.5k
  const char  *f;
173
174
92.5k
  f = *pf;
175
92.5k
  if (*f == '.') {
176
4.25k
    f++;
177
4.25k
    if (*f == '*') {
178
0
      RETURN(pf,f,FMTCHECK_PRECISION);
179
0
    }
180
    /* eat any precision (empty is allowed) */
181
4.53k
    while (isdigit((unsigned char)*f)) f++;
182
4.25k
    if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
183
4.25k
  }
184
92.5k
  RETURN(pf,f,get_next_format_from_precision(pf));
185
  /*NOTREACHED*/
186
92.5k
}
187
188
static EFT
189
get_next_format(const char **pf, EFT eft)
190
138k
{
191
138k
  int   infmt;
192
138k
  const char  *f;
193
194
138k
  if (eft == FMTCHECK_WIDTH) {
195
0
    (*pf)++;
196
0
    return get_next_format_from_width(pf);
197
138k
  } else if (eft == FMTCHECK_PRECISION) {
198
0
    (*pf)++;
199
0
    return get_next_format_from_precision(pf);
200
0
  }
201
202
138k
  f = *pf;
203
138k
  infmt = 0;
204
231k
  while (!infmt) {
205
138k
    f = strchr(f, '%');
206
138k
    if (f == NULL)
207
46.2k
      RETURN(pf,f,FMTCHECK_DONE);
208
92.5k
    f++;
209
92.5k
    if (!*f)
210
0
      RETURN(pf,f,FMTCHECK_UNKNOWN);
211
92.5k
    if (*f != '%')
212
92.5k
      infmt = 1;
213
0
    else
214
0
      f++;
215
92.5k
  }
216
217
  /* Eat any of the flags */
218
99.8k
  while (*f && (strchr("#0- +", *f)))
219
7.33k
    f++;
220
221
92.5k
  if (*f == '*') {
222
0
    RETURN(pf,f,FMTCHECK_WIDTH);
223
0
  }
224
  /* eat any width */
225
92.5k
  while (isdigit((unsigned char)*f)) f++;
226
92.5k
  if (!*f) {
227
0
    RETURN(pf,f,FMTCHECK_UNKNOWN);
228
0
  }
229
230
92.5k
  RETURN(pf,f,get_next_format_from_width(pf));
231
  /*NOTREACHED*/
232
92.5k
}
233
234
const char *
235
fmtcheck(const char *f1, const char *f2)
236
46.2k
{
237
46.2k
  const char  *f1p, *f2p;
238
46.2k
  EFT   f1t, f2t;
239
240
46.2k
  if (!f1) return f2;
241
242
46.2k
  f1p = f1;
243
46.2k
  f1t = FMTCHECK_START;
244
46.2k
  f2p = f2;
245
46.2k
  f2t = FMTCHECK_START;
246
92.5k
  while ((f1t = get_next_format(&f1p, f1t)) != FMTCHECK_DONE) {
247
46.2k
    if (f1t == FMTCHECK_UNKNOWN)
248
0
      return f2;
249
46.2k
    f2t = get_next_format(&f2p, f2t);
250
46.2k
    if (f1t != f2t)
251
0
      return f2;
252
46.2k
  }
253
46.2k
  return f1;
254
46.2k
}