clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name number.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/games/number/obj -resource-dir /usr/local/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/games/number/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/games/number/number.c
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | #include <ctype.h> |
33 | #include <err.h> |
34 | #include <stdio.h> |
35 | #include <stdlib.h> |
36 | #include <string.h> |
37 | #include <unistd.h> |
38 | |
39 | #define MAXNUM 65 /* Biggest number we handle. */ |
40 | #define LINELEN 256 |
41 | |
42 | static const char *const name1[] = { |
43 | "", "one", "two", "three", |
44 | "four", "five", "six", "seven", |
45 | "eight", "nine", "ten", "eleven", |
46 | "twelve", "thirteen", "fourteen", "fifteen", |
47 | "sixteen", "seventeen", "eighteen", "nineteen", |
48 | }, |
49 | *const name2[] = { |
50 | "", "ten", "twenty", "thirty", |
51 | "forty", "fifty", "sixty", "seventy", |
52 | "eighty", "ninety", |
53 | }, |
54 | *const name3[] = { |
55 | "hundred", "thousand", "million", "billion", |
56 | "trillion", "quadrillion", "quintillion", "sextillion", |
57 | "septillion", "octillion", "nonillion", "decillion", |
58 | "undecillion", "duodecillion", "tredecillion", "quattuordecillion", |
59 | "quindecillion", "sexdecillion", |
60 | "septendecillion", "octodecillion", |
61 | "novemdecillion", "vigintillion", |
62 | }; |
63 | |
64 | void convert(char *); |
65 | void convertexp(char *); |
66 | int number(const char *, int); |
67 | void pfract(int); |
68 | int unit(int, const char *); |
69 | __dead void usage(void); |
70 | |
71 | int lflag; |
72 | |
73 | int |
74 | main(int argc, char *argv[]) |
75 | { |
76 | int ch, first; |
77 | char line[LINELEN]; |
78 | |
79 | if (pledge("stdio", NULL) == -1) |
| 1 | Assuming the condition is false | |
|
| |
80 | err(1, "pledge"); |
81 | |
82 | lflag = 0; |
83 | while ((ch = getopt(argc, argv, "hl")) != -1) |
| 3 | | Assuming the condition is false | |
|
| 4 | | Loop condition is false. Execution continues on line 92 | |
|
84 | switch (ch) { |
85 | case 'l': |
86 | lflag = 1; |
87 | break; |
88 | case 'h': |
89 | default: |
90 | usage(); |
91 | } |
92 | argc -= optind; |
93 | argv += optind; |
94 | |
95 | if (*argv == NULL) |
| 5 | | Assuming the condition is false | |
|
| |
96 | for (first = 1; |
97 | fgets(line, sizeof(line), stdin) != NULL; first = 0) { |
98 | if (strchr(line, '\n') == NULL) |
99 | errx(1, "line too long."); |
100 | if (!first) |
101 | (void)printf("...\n"); |
102 | convert(line); |
103 | if (lflag) |
104 | (void)printf("\n"); |
105 | } |
106 | else |
107 | for (first = 1; *argv != NULL; first = 0, ++argv) { |
| 7 | | Loop condition is true. Entering loop body | |
|
108 | if (!first) |
| |
109 | (void)printf("...\n"); |
110 | convert(*argv); |
| |
111 | if (lflag) |
112 | (void)printf("\n"); |
113 | } |
114 | return 0; |
115 | } |
116 | |
117 | void |
118 | convert(char *line) |
119 | { |
120 | int flen, len, rval; |
121 | char *p, *fraction; |
122 | |
123 | |
124 | len = strlen(line) - 1; |
125 | while ((isblank((unsigned char)line[len])) || (line[len] == '\n')) |
| 10 | | Loop condition is false. Execution continues on line 127 | |
|
126 | line[len--] = '\0'; |
127 | while ((isblank((unsigned char)line[0])) || (line[0] == '\n')) |
| 11 | | Assuming the condition is false | |
|
| 12 | | Loop condition is false. Execution continues on line 129 | |
|
128 | line++; |
129 | if (strchr(line, 'e') || strchr(line, 'E')) |
| 13 | | Assuming the condition is false | |
|
| 14 | | Assuming the condition is false | |
|
| |
130 | convertexp(line); |
131 | else { |
132 | fraction = NULL; |
133 | for (p = line; *p != '\0' && *p != '\n'; ++p) { |
| 16 | | Assuming the condition is false | |
|
134 | if (isblank((unsigned char)*p)) |
135 | goto badnum; |
136 | if (isdigit((unsigned char)*p)) |
137 | continue; |
138 | switch (*p) { |
139 | case '.': |
140 | if (fraction != NULL) |
141 | goto badnum; |
142 | fraction = p + 1; |
143 | *p = '\0'; |
144 | break; |
145 | case '-': |
146 | case '+': |
147 | if (p == line) |
148 | break; |
149 | |
150 | default: |
151 | badnum: errx(1, "illegal number: %s", line); |
152 | break; |
153 | } |
154 | } |
155 | *p = '\0'; |
156 | |
157 | if ((len = strlen(line)) > MAXNUM || |
| 17 | | Assuming the condition is false | |
|
158 | ((fraction != NULL) && (flen = strlen(fraction)) > MAXNUM)) |
159 | errx(1, "number too long (max %d digits).", MAXNUM); |
160 | |
161 | if (*line == '-') { |
| |
162 | (void)printf("minus%s", lflag ? " " : "\n"); |
163 | ++line; |
164 | --len; |
165 | } |
166 | if (*line == '+') { |
| |
167 | (void)printf("plus%s", lflag ? " " : "\n"); |
168 | ++line; |
169 | --len; |
170 | } |
171 | |
172 | rval = len > 0 ? unit(len, line) : 0; |
| |
| |
| |
173 | if (fraction != NULL && flen != 0) |
174 | for (p = fraction; *p != '\0'; ++p) |
175 | if (*p != '0') { |
176 | if (rval) |
177 | (void)printf("%sand%s", |
178 | lflag ? " " : "", |
179 | lflag ? " " : "\n"); |
180 | if (unit(flen, fraction)) { |
181 | if (lflag) |
182 | (void)printf(" "); |
183 | pfract(flen); |
184 | rval = 1; |
185 | } |
186 | break; |
187 | } |
188 | if (!rval) |
189 | (void)printf("zero%s", lflag ? "" : ".\n"); |
190 | } |
191 | } |
192 | |
193 | void |
194 | convertexp(char *line) |
195 | { |
196 | char locline[LINELEN]; |
197 | char *part1, *part2, *part3, *part4; |
198 | char tmp[2]; |
199 | int i, j; |
200 | |
201 | (void)strlcpy(locline,line,LINELEN); |
202 | part3 = locline; |
203 | part2 = strsep(&part3, "eE"); |
204 | part4 = part3; |
205 | (void)strsep(&part4, "."); |
206 | if (part4) |
207 | errx(1, "illegal number: %s", line); |
208 | part1 = strsep(&part2, "."); |
209 | |
210 | |
211 | |
212 | j = strlen(line); |
213 | for (i = 0; i < j; i++) |
214 | if ((!isdigit((unsigned char)locline[i])) && (locline[i])) |
215 | if (((locline[i] != '+') && (locline[i] != '-')) || |
216 | ((i != 0) && (i != part3 - locline))) |
217 | errx(1, "illegal number: %s", line); |
218 | convert(part1); |
219 | printf("%s", lflag ? " " : ""); |
220 | if (part2 && part2[0]) { |
221 | (void)printf("point%s", lflag ? " " : "\n"); |
222 | j = strlen(part2); tmp[1] = '\0'; |
223 | for (i = 0 ; i < j; i++ ) { |
224 | tmp[0] = part2[i]; |
225 | convert(tmp); |
226 | (void)printf("%s", lflag ? " " : ""); |
227 | } |
228 | } |
229 | (void)printf("times ten to the%s", lflag ? " " : "\n"); |
230 | if (part3 && part3[0]) |
231 | convert(part3); |
232 | else |
233 | (void)printf("zero%s", lflag ? " " : ".\n"); |
234 | } |
235 | |
236 | int |
237 | unit(int len, const char *p) |
238 | { |
239 | int off, rval; |
240 | |
241 | rval = 0; |
242 | if (len > 3) { |
| |
| |
243 | if (len % 3) { |
244 | off = len % 3; |
245 | len -= off; |
246 | if (number(p, off)) { |
247 | rval = 1; |
248 | (void)printf(" %s%s", |
249 | name3[len / 3], lflag ? " " : ".\n"); |
250 | } |
251 | p += off; |
252 | } |
253 | for (; len > 3; p += 3) { |
254 | len -= 3; |
255 | if (number(p, 3)) { |
256 | rval = 1; |
257 | (void)printf(" %s%s", |
258 | name3[len / 3], lflag ? " " : ".\n"); |
259 | } |
260 | } |
261 | } |
262 | if (number(p, len)) { |
| |
263 | if (!lflag) |
264 | (void)printf(".\n"); |
265 | rval = 1; |
266 | } |
267 | return (rval); |
268 | } |
269 | |
270 | int |
271 | number(const char *p, int len) |
272 | { |
273 | int val, rval; |
274 | |
275 | rval = 0; |
276 | switch (len) { |
| 26 | | Control jumps to 'case 3:' at line 277 | |
|
277 | case 3: |
278 | if (*p != '0') { |
| |
279 | rval = 1; |
280 | (void)printf("%s hundred", name1[*p - '0']); |
| 28 | | 2nd function call argument is an uninitialized value |
|
281 | } |
282 | ++p; |
283 | |
284 | case 2: |
285 | val = (p[1] - '0') + (p[0] - '0') * 10; |
286 | if (val) { |
287 | if (rval) |
288 | (void)printf(" "); |
289 | if (val < 20) |
290 | (void)printf("%s", name1[val]); |
291 | else { |
292 | (void)printf("%s", name2[val / 10]); |
293 | if (val % 10) |
294 | (void)printf("-%s", name1[val % 10]); |
295 | } |
296 | rval = 1; |
297 | } |
298 | break; |
299 | case 1: |
300 | if (*p != '0') { |
301 | rval = 1; |
302 | (void)printf("%s", name1[*p - '0']); |
303 | } |
304 | } |
305 | return (rval); |
306 | } |
307 | |
308 | void |
309 | pfract(int len) |
310 | { |
311 | static const char *const pref[] = { "", "ten-", "hundred-" }; |
312 | |
313 | switch(len) { |
314 | case 1: |
315 | (void)printf("tenths%s", lflag ? "" : ".\n"); |
316 | break; |
317 | case 2: |
318 | (void)printf("hundredths%s", lflag ? "" : ".\n"); |
319 | break; |
320 | default: |
321 | (void)printf("%s%sths%s", pref[len % 3], name3[len / 3], |
322 | lflag ? "" : ".\n"); |
323 | break; |
324 | } |
325 | } |
326 | |
327 | void |
328 | usage(void) |
329 | { |
330 | (void)fprintf(stderr, "usage: %s [-l] [--] [# ...]\n", getprogname()); |
331 | exit(1); |
332 | } |