Bug Summary

File:build/gcc/genopinit.cc
Warning:line 241, column 52
Array subscript is undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-suse-linux -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name genopinit.cc -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -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 -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/buildworker/marxinbox-gcc-clang-static-analyzer/objdir/gcc -resource-dir /usr/lib64/clang/15.0.7 -D IN_GCC -D HAVE_CONFIG_H -D GENERATOR_FILE -I . -I build -I /buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc -I /buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/build -I /buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../include -I /buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../libcpp/include -internal-isystem /usr/bin/../lib64/gcc/x86_64-suse-linux/13/../../../../include/c++/13 -internal-isystem /usr/bin/../lib64/gcc/x86_64-suse-linux/13/../../../../include/c++/13/x86_64-suse-linux -internal-isystem /usr/bin/../lib64/gcc/x86_64-suse-linux/13/../../../../include/c++/13/backward -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib64/gcc/x86_64-suse-linux/13/../../../../x86_64-suse-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-narrowing -Wwrite-strings -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -fdeprecated-macro -fdebug-compilation-dir=/buildworker/marxinbox-gcc-clang-static-analyzer/objdir/gcc -ferror-limit 19 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=plist-html -analyzer-config silence-checkers=core.NullDereference -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /buildworker/marxinbox-gcc-clang-static-analyzer/objdir/clang-static-analyzer/2023-03-27-141847-20772-1/report-UZKLyw.plist -x c++ /buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/genopinit.cc
1/* Generate code to initialize optabs from machine description.
2 Copyright (C) 1993-2023 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 3, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
19
20
21#include "bconfig.h"
22#include "system.h"
23#include "coretypes.h"
24#include "tm.h"
25#include "rtl.h"
26#include "errors.h"
27#include "gensupport.h"
28
29
30#define DEF_RTL_EXPR(V, N, X, C) #V,
31
32static const char * const rtx_upname[] = {
33#include "rtl.def"
34};
35
36#undef DEF_RTL_EXPR
37
38/* Vector in which to collect insns that match. */
39static vec<optab_pattern> patterns;
40
41static void
42gen_insn (md_rtx_info *info)
43{
44 optab_pattern p;
45 if (find_optab (&p, XSTR (info->def, 0)(((info->def)->u.fld[0]).rt_str)))
46 patterns.safe_push (p);
47}
48
49static int
50pattern_cmp (const void *va, const void *vb)
51{
52 const optab_pattern *a = (const optab_pattern *)va;
53 const optab_pattern *b = (const optab_pattern *)vb;
54 return a->sort_num - b->sort_num;
55}
56
57static int
58optab_kind_cmp (const void *va, const void *vb)
59{
60 const optab_def *a = (const optab_def *)va;
61 const optab_def *b = (const optab_def *)vb;
62 int diff = a->kind - b->kind;
63 if (diff == 0)
64 diff = a->op - b->op;
65 return diff;
66}
67
68static int
69optab_rcode_cmp (const void *va, const void *vb)
70{
71 const optab_def *a = (const optab_def *)va;
72 const optab_def *b = (const optab_def *)vb;
73 return a->rcode - b->rcode;
74}
75
76static const char *header_file_name = "init-opinit.h";
77static const char *source_file_name = "init-opinit.c";
78
79static bool
80handle_arg (const char *arg)
81{
82 switch (arg[1])
83 {
84 case 'h':
85 header_file_name = &arg[2];
86 return true;
87 case 'c':
88 source_file_name = &arg[2];
89 return true;
90 default:
91 return false;
92 }
93}
94
95static FILE *
96open_outfile (const char *file_name)
97{
98 FILE *f = fopen (file_name, "w")fopen_unlocked (file_name, "w");
99 if (!f)
100 fatal ("cannot open file %s: %s", file_name, xstrerror (errno(*__errno_location ())));
101 fprintf (f,
102 "/* Generated automatically by the program `genopinit'\n"
103 " from the machine description file `md'. */\n\n");
104 return f;
105}
106
107/* Declare the maybe_code_for_* function for ONAME, and provide
108 an inline definition of the assserting code_for_* wrapper. */
109
110static void
111handle_overloaded_code_for (FILE *file, overloaded_name *oname)
112{
113 fprintf (file, "\nextern insn_code maybe_code_for_%s (", oname->name);
114 for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
115 fprintf (file, "%s%s", i == 0 ? "" : ", ", oname->arg_types[i]);
116 fprintf (file, ");\n");
117
118 fprintf (file, "inline insn_code\ncode_for_%s (", oname->name);
119 for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
120 fprintf (file, "%s%s arg%d", i == 0 ? "" : ", ", oname->arg_types[i], i);
121 fprintf (file, ")\n{\n insn_code code = maybe_code_for_%s (", oname->name);
122 for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
123 fprintf (file, "%sarg%d", i == 0 ? "" : ", ", i);
124 fprintf (file,
125 ");\n"
126 " gcc_assert (code != CODE_FOR_nothing);\n"
127 " return code;\n"
128 "}\n");
129}
130
131/* Declare the maybe_gen_* function for ONAME, and provide
132 an inline definition of the assserting gen_* wrapper. */
133
134static void
135handle_overloaded_gen (FILE *file, overloaded_name *oname)
136{
137 unsigned HOST_WIDE_INTlong seen = 0;
138 for (overloaded_instance *instance = oname->first_instance->next;
139 instance; instance = instance->next)
140 {
141 pattern_stats stats;
142 get_pattern_stats (&stats, XVEC (instance->insn, 1)(((instance->insn)->u.fld[1]).rt_rtvec));
143 unsigned HOST_WIDE_INTlong mask
144 = HOST_WIDE_INT_1U1UL << stats.num_generator_args;
145 if (seen & mask)
146 continue;
147
148 seen |= mask;
149
150 fprintf (file, "\nextern rtx maybe_gen_%s (", oname->name);
151 for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
152 fprintf (file, "%s%s", i == 0 ? "" : ", ", oname->arg_types[i]);
153 for (int i = 0; i < stats.num_generator_args; ++i)
154 fprintf (file, ", rtx");
155 fprintf (file, ");\n");
156
157 fprintf (file, "inline rtx\ngen_%s (", oname->name);
158 for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
159 fprintf (file, "%s%s arg%d", i == 0 ? "" : ", ",
160 oname->arg_types[i], i);
161 for (int i = 0; i < stats.num_generator_args; ++i)
162 fprintf (file, ", rtx x%d", i);
163 fprintf (file, ")\n{\n rtx res = maybe_gen_%s (", oname->name);
164 for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
165 fprintf (file, "%sarg%d", i == 0 ? "" : ", ", i);
166 for (int i = 0; i < stats.num_generator_args; ++i)
167 fprintf (file, ", x%d", i);
168 fprintf (file,
169 ");\n"
170 " gcc_assert (res);\n"
171 " return res;\n"
172 "}\n");
173 }
174}
175
176int
177main (int argc, const char **argv)
178{
179 FILE *h_file, *s_file;
180 unsigned int i, j, n, last_kind[5];
181 optab_pattern *p;
182
183 progname = "genopinit";
184
185 if (NUM_OPTABS
0.1
NUM_OPTABS is <= 65535
> 0xffff || MAX_MACHINE_MODE
0.2
MAX_MACHINE_MODE is < 255
>= 0xff)
1
Taking false branch
186 fatal ("genopinit range assumptions invalid");
187
188 if (!init_rtx_reader_args_cb (argc, argv, handle_arg))
2
Assuming the condition is false
3
Taking false branch
189 return (FATAL_EXIT_CODE1);
190
191 h_file = open_outfile (header_file_name);
192 s_file = open_outfile (source_file_name);
193
194 /* Read the machine description. */
195 md_rtx_info info;
196 while (read_md_rtx (&info))
4
Loop condition is false. Execution continues on line 209
197 switch (GET_CODE (info.def)((enum rtx_code) (info.def)->code))
198 {
199 case DEFINE_INSN:
200 case DEFINE_EXPAND:
201 gen_insn (&info);
202 break;
203
204 default:
205 break;
206 }
207
208 /* Sort the collected patterns. */
209 patterns.qsort (pattern_cmp)qsort (pattern_cmp);
210
211 /* Now that we've handled the "extra" patterns, eliminate them from
212 the optabs array. That way they don't get in the way below. */
213 n = num_optabs;
214 for (i = 0; i < n; )
5
Assuming 'i' is < 'n'
6
Loop condition is true. Entering loop body
9
Assuming 'i' is < 'n'
10
Loop condition is true. Entering loop body
13
Assuming 'i' is < 'n'
14
Loop condition is true. Entering loop body
17
Assuming 'i' is >= 'n'
18
Loop condition is false. Execution continues on line 223
215 if (optabs[i].base == NULLnullptr)
7
Assuming the condition is false
8
Taking false branch
11
Assuming the condition is false
12
Taking false branch
15
Assuming the condition is false
16
Taking false branch
216 optabs[i] = optabs[--n];
217 else
218 ++i;
219
220 /* Sort the (real) optabs. Better than forcing the optabs.def file to
221 remain sorted by kind. We also scrogged any real ordering with the
222 purging of the X patterns above. */
223 qsort (optabs, n, sizeof (optab_def), optab_kind_cmp)gcc_qsort (optabs, n, sizeof (optab_def), optab_kind_cmp);
224
225 fprintf (h_file, "#ifndef GCC_INSN_OPINIT_H\n");
226 fprintf (h_file, "#define GCC_INSN_OPINIT_H 1\n");
227
228 /* Emit the optab enumeration for the header file. */
229 fprintf (h_file, "enum optab_tag {\n");
230 for (i = j = 0; i < n; ++i)
19
Loop condition is true. Entering loop body
22
Loop condition is true. Entering loop body
25
Loop condition is true. Entering loop body
28
Loop condition is false. Execution continues on line 237
231 {
232 optabs[i].op = i;
233 fprintf (h_file, " %s,\n", optabs[i].name);
234 if (optabs[i].kind != j)
20
Assuming 'j' is not equal to field 'kind'
21
Taking true branch
23
Assuming 'j' is not equal to field 'kind'
24
Taking true branch
26
Assuming 'j' is not equal to field 'kind'
27
Taking true branch
235 last_kind[j++] = i - 1;
236 }
237 fprintf (h_file, " FIRST_CONV_OPTAB = %s,\n", optabs[last_kind[0]+1].name);
238 fprintf (h_file, " LAST_CONVLIB_OPTAB = %s,\n", optabs[last_kind[1]].name);
239 fprintf (h_file, " LAST_CONV_OPTAB = %s,\n", optabs[last_kind[2]].name);
240 fprintf (h_file, " FIRST_NORM_OPTAB = %s,\n", optabs[last_kind[2]+1].name);
241 fprintf (h_file, " LAST_NORMLIB_OPTAB = %s,\n", optabs[last_kind[3]].name);
29
Array subscript is undefined
242 fprintf (h_file, " LAST_NORM_OPTAB = %s\n", optabs[i-1].name);
243 fprintf (h_file, "};\n\n");
244
245 fprintf (h_file, "#define NUM_OPTABS %u\n", n);
246 fprintf (h_file, "#define NUM_CONVLIB_OPTABS %u\n",
247 last_kind[1] - last_kind[0]);
248 fprintf (h_file, "#define NUM_NORMLIB_OPTABS %u\n",
249 last_kind[3] - last_kind[2]);
250 fprintf (h_file, "#define NUM_OPTAB_PATTERNS %u\n",
251 (unsigned) patterns.length ());
252
253 fprintf (h_file,
254 "typedef enum optab_tag optab;\n"
255 "typedef enum optab_tag convert_optab;\n"
256 "typedef enum optab_tag direct_optab;\n"
257 "\n"
258 "struct optab_libcall_d\n"
259 "{\n"
260 " char libcall_suffix;\n"
261 " const char *libcall_basename;\n"
262 " void (*libcall_gen) (optab, const char *name,\n"
263 " char suffix, machine_mode);\n"
264 "};\n"
265 "\n"
266 "struct convert_optab_libcall_d\n"
267 "{\n"
268 " const char *libcall_basename;\n"
269 " void (*libcall_gen) (convert_optab, const char *name,\n"
270 " machine_mode, machine_mode);\n"
271 "};\n"
272 "\n"
273 "/* Given an enum insn_code, access the function to construct\n"
274 " the body of that kind of insn. */\n"
275 "#define GEN_FCN(CODE) (insn_data[CODE].genfun)\n"
276 "\n"
277 "#ifdef NUM_RTX_CODE\n"
278 "/* Contains the optab used for each rtx code, and vice-versa. */\n"
279 "extern const optab code_to_optab_[NUM_RTX_CODE];\n"
280 "extern const enum rtx_code optab_to_code_[NUM_OPTABS];\n"
281 "\n"
282 "static inline optab\n"
283 "code_to_optab (enum rtx_code code)\n"
284 "{\n"
285 " return code_to_optab_[code];\n"
286 "}\n"
287 "\n"
288 "static inline enum rtx_code\n"
289 "optab_to_code (optab op)\n"
290 "{\n"
291 " return optab_to_code_[op];\n"
292 "}\n");
293
294 for (overloaded_name *oname = rtx_reader_ptr->get_overloads ();
295 oname; oname = oname->next)
296 {
297 handle_overloaded_code_for (h_file, oname);
298 handle_overloaded_gen (h_file, oname);
299 }
300
301 fprintf (h_file,
302 "#endif\n"
303 "\n"
304 "extern const struct convert_optab_libcall_d convlib_def[NUM_CONVLIB_OPTABS];\n"
305 "extern const struct optab_libcall_d normlib_def[NUM_NORMLIB_OPTABS];\n"
306 "\n"
307 "/* Returns the active icode for the given (encoded) optab. */\n"
308 "extern enum insn_code raw_optab_handler (unsigned);\n"
309 "extern bool swap_optab_enable (optab, machine_mode, bool);\n"
310 "\n"
311 "/* Target-dependent globals. */\n"
312 "struct target_optabs {\n"
313 " /* Patterns that are used by optabs that are enabled for this target. */\n"
314 " bool pat_enable[NUM_OPTAB_PATTERNS];\n"
315 "\n"
316 " /* Index VOIDmode caches if the target supports vec_gather_load for any\n"
317 " vector mode. Every other index X caches specifically for mode X.\n"
318 " 1 means yes, -1 means no. */\n"
319 " signed char supports_vec_gather_load[NUM_MACHINE_MODES];\n"
320 " signed char supports_vec_scatter_store[NUM_MACHINE_MODES];\n"
321 "};\n"
322 "extern void init_all_optabs (struct target_optabs *);\n"
323 "extern bool partial_vectors_supported_p (void);\n"
324 "\n"
325 "extern struct target_optabs default_target_optabs;\n"
326 "extern struct target_optabs *this_fn_optabs;\n"
327 "#if SWITCHABLE_TARGET\n"
328 "extern struct target_optabs *this_target_optabs;\n"
329 "#else\n"
330 "#define this_target_optabs (&default_target_optabs)\n"
331 "#endif\n");
332
333 fprintf (s_file,
334 "#define IN_TARGET_CODE 1\n"
335 "#include \"config.h\"\n"
336 "#include \"system.h\"\n"
337 "#include \"coretypes.h\"\n"
338 "#include \"backend.h\"\n"
339 "#include \"predict.h\"\n"
340 "#include \"tree.h\"\n"
341 "#include \"rtl.h\"\n"
342 "#include \"alias.h\"\n"
343 "#include \"varasm.h\"\n"
344 "#include \"stor-layout.h\"\n"
345 "#include \"calls.h\"\n"
346 "#include \"memmodel.h\"\n"
347 "#include \"tm_p.h\"\n"
348 "#include \"flags.h\"\n"
349 "#include \"insn-config.h\"\n"
350 "#include \"expmed.h\"\n"
351 "#include \"dojump.h\"\n"
352 "#include \"explow.h\"\n"
353 "#include \"emit-rtl.h\"\n"
354 "#include \"stmt.h\"\n"
355 "#include \"expr.h\"\n"
356 "#include \"insn-codes.h\"\n"
357 "#include \"optabs.h\"\n"
358 "\n"
359 "struct optab_pat {\n"
360 " unsigned scode;\n"
361 " enum insn_code icode;\n"
362 "};\n\n");
363
364 fprintf (s_file,
365 "static const struct optab_pat pats[NUM_OPTAB_PATTERNS] = {\n");
366 for (i = 0; patterns.iterate (i, &p); ++i)
367 fprintf (s_file, " { %#08x, CODE_FOR_%s },\n", p->sort_num, p->name);
368 fprintf (s_file, "};\n\n");
369
370 fprintf (s_file, "void\ninit_all_optabs (struct target_optabs *optabs)\n{\n");
371 fprintf (s_file, " bool *ena = optabs->pat_enable;\n");
372 for (i = 0; patterns.iterate (i, &p); ++i)
373 fprintf (s_file, " ena[%u] = HAVE_%s;\n", i, p->name);
374 fprintf (s_file, "}\n\n");
375
376 fprintf (s_file,
377 "/* Returns TRUE if the target supports any of the partial vector\n"
378 " optabs: while_ult_optab, len_load_optab or len_store_optab,\n"
379 " for any mode. */\n"
380 "bool\npartial_vectors_supported_p (void)\n{\n");
381 bool any_match = false;
382 fprintf (s_file, "\treturn");
383 bool first = true;
384 for (i = 0; patterns.iterate (i, &p); ++i)
385 {
386#define CMP_NAME(N)!strncmp (p->name, (N), strlen ((N))) !strncmp (p->name, (N), strlen ((N)))
387 if (CMP_NAME("while_ult")!strncmp (p->name, ("while_ult"), strlen (("while_ult"))) || CMP_NAME ("len_load")!strncmp (p->name, ("len_load"), strlen (("len_load")))
388 || CMP_NAME ("len_store")!strncmp (p->name, ("len_store"), strlen (("len_store"))))
389 {
390 if (first)
391 fprintf (s_file, " HAVE_%s", p->name);
392 else
393 fprintf (s_file, " || HAVE_%s", p->name);
394 first = false;
395 any_match = true;
396 }
397 }
398 if (!any_match)
399 fprintf (s_file, " false");
400 fprintf (s_file, ";\n}\n");
401
402
403 /* Perform a binary search on a pre-encoded optab+mode*2. */
404 /* ??? Perhaps even better to generate a minimal perfect hash.
405 Using gperf directly is awkward since it's so geared to working
406 with strings. Plus we have no visibility into the ordering of
407 the hash entries, which complicates the pat_enable array. */
408 fprintf (s_file,
409 "static int\n"
410 "lookup_handler (unsigned scode)\n"
411 "{\n"
412 " int l = 0, h = ARRAY_SIZE (pats), m;\n"
413 " while (h > l)\n"
414 " {\n"
415 " m = (h + l) / 2;\n"
416 " if (scode == pats[m].scode)\n"
417 " return m;\n"
418 " else if (scode < pats[m].scode)\n"
419 " h = m;\n"
420 " else\n"
421 " l = m + 1;\n"
422 " }\n"
423 " return -1;\n"
424 "}\n\n");
425
426 fprintf (s_file,
427 "enum insn_code\n"
428 "raw_optab_handler (unsigned scode)\n"
429 "{\n"
430 " int i = lookup_handler (scode);\n"
431 " return (i >= 0 && this_fn_optabs->pat_enable[i]\n"
432 " ? pats[i].icode : CODE_FOR_nothing);\n"
433 "}\n\n");
434
435 fprintf (s_file,
436 "bool\n"
437 "swap_optab_enable (optab op, machine_mode m, bool set)\n"
438 "{\n"
439 " unsigned scode = (op << 16) | m;\n"
440 " int i = lookup_handler (scode);\n"
441 " if (i >= 0)\n"
442 " {\n"
443 " bool ret = this_fn_optabs->pat_enable[i];\n"
444 " this_fn_optabs->pat_enable[i] = set;\n"
445 " return ret;\n"
446 " }\n"
447 " else\n"
448 " {\n"
449 " gcc_assert (!set);\n"
450 " return false;\n"
451 " }\n"
452 "}\n\n");
453
454 /* C++ (even G++) does not support (non-trivial) designated initializers.
455 To work around that, generate these arrays programatically rather than
456 by our traditional multiple inclusion of def files. */
457
458 fprintf (s_file,
459 "const struct convert_optab_libcall_d "
460 "convlib_def[NUM_CONVLIB_OPTABS] = {\n");
461 for (i = last_kind[0] + 1; i <= last_kind[1]; ++i)
462 fprintf (s_file, " { %s, %s },\n", optabs[i].base, optabs[i].libcall);
463 fprintf (s_file, "};\n\n");
464
465 fprintf (s_file,
466 "const struct optab_libcall_d "
467 "normlib_def[NUM_NORMLIB_OPTABS] = {\n");
468 for (i = last_kind[2] + 1; i <= last_kind[3]; ++i)
469 fprintf (s_file, " { %s, %s, %s },\n",
470 optabs[i].suffix, optabs[i].base, optabs[i].libcall);
471 fprintf (s_file, "};\n\n");
472
473 fprintf (s_file, "enum rtx_code const optab_to_code_[NUM_OPTABS] = {\n");
474 for (i = 0; i < n; ++i)
475 fprintf (s_file, " %s,\n", rtx_upname[optabs[i].fcode]);
476 fprintf (s_file, "};\n\n");
477
478 qsort (optabs, n, sizeof (optab_def), optab_rcode_cmp)gcc_qsort (optabs, n, sizeof (optab_def), optab_rcode_cmp);
479
480 fprintf (s_file, "const optab code_to_optab_[NUM_RTX_CODE] = {\n");
481 for (j = 0; optabs[j].rcode == UNKNOWN; ++j)
482 continue;
483 for (i = 0; i < NON_GENERATOR_NUM_RTX_CODE((int) MATCH_OPERAND); ++i)
484 {
485 if (j < n && optabs[j].rcode == i)
486 fprintf (s_file, " %s,\n", optabs[j++].name);
487 else
488 fprintf (s_file, " unknown_optab,\n");
489 }
490 fprintf (s_file, "};\n\n");
491
492 fprintf (h_file, "#endif\n");
493 return (fclose (h_file) == 0 && fclose (s_file) == 0
494 ? SUCCESS_EXIT_CODE0 : FATAL_EXIT_CODE1);
495}