Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / comerr / compile_et.c
1 /*
2 *
3 * Copyright 1986, 1987, 1988
4 * by MIT Student Information Processing Board.
5 *
6 * For copyright info, see "mit-sipb-cr.h".
7 *
8 */
9
10 #undef MEMORYLEAK
11 #include <afsconfig.h>
12 #include <afs/param.h>
13
14 #include <roken.h>
15 #include <afs/opr.h>
16
17 #include "mit-sipb-cr.h"
18 #include "internal.h"
19 #include "compiler.h"
20
21 extern char *current_token;
22 extern int table_number, current;
23 char buffer[BUFSIZ];
24 char *table_name = NULL;
25 FILE *hfile = NULL, *cfile = NULL, *msfile = NULL;
26 int version = 1;
27 int use_msf = 0;
28 int emit_source = 0;
29 int emit_header = 0;
30
31 /* lex stuff */
32 extern FILE *yyin;
33 extern FILE *yyout;
34 #ifdef AFS_AIX51_ENV
35 int yylineno = 0;
36 #else
37 extern int yylineno;
38 #endif
39
40 char *
41 xmalloc(unsigned int size)
42 {
43 char *p = malloc(size);
44 if (!p) {
45 perror(whoami);
46 exit(1);
47 }
48 return p;
49 }
50
51 static int
52 check_arg(char const *const *str_list, char const *arg)
53 {
54 while (*str_list)
55 if (!strcmp(arg, *str_list++))
56 return 1;
57 return 0;
58 }
59
60 static const char *const debug_args[] = {
61 "d",
62 "debug",
63 0,
64 };
65
66 static const char *const lang_args[] = {
67 "lang",
68 "language",
69 0,
70 };
71
72 static const char *const prefix_args[] = {
73 "p",
74 "prefix",
75 0,
76 };
77
78 static const char *const emit_args[] = {
79 "e",
80 "emit",
81 0,
82 };
83
84 static const char *const language_names[] = {
85 "C",
86 "K&R C",
87 "C++",
88 0,
89 };
90
91 static const char *const c_src_prolog[] = {
92 "#include <afs/error_table.h>\n",
93 "static const char * const text[] = {\n",
94 0,
95 };
96
97 static const char *const krc_src_prolog[] = {
98 "#ifdef __STDC__\n",
99 "#define NOARGS void\n",
100 "#else\n",
101 "#define NOARGS\n",
102 "#define const\n",
103 "#endif\n\n",
104 "#include <afs/param.h>\n",
105 "#include <afs/error_table.h>\n",
106 "static const char * const text[] = {\n",
107 0,
108 };
109
110 static const char warning[] =
111 "/*\n * %s:\n * This file is automatically generated; please do not edit it.\n */\n";
112
113 static const char msf_warning[] =
114 "$ \n$ %s:\n$ This file is automatically generated; please do not edit it.\n$ \n$set 1\n";
115
116 /* pathnames */
117 char c_file[MAXPATHLEN]; /* output file */
118 char h_file[MAXPATHLEN]; /* output */
119 char msf_file[MAXPATHLEN];
120
121 static void
122 usage(void)
123 {
124 fprintf(stderr,
125 "%s: usage: %s ERROR_TABLE [-debug] [-language LANG] [-h INCLUDE] [-p PREFIX] [-v VERSION] [-emit source|header]\n",
126 whoami, whoami);
127 exit(1);
128 }
129
130 static void
131 dup_err(char const *type, char const *one, char const *two)
132 {
133 fprintf(stderr, "%s: multiple %s specified: `%s' and `%s'\n", whoami,
134 type, one, two);
135 usage();
136 }
137
138 #include "AFS_component_version_number.c"
139
140 int
141 main(int argc, char **argv)
142 {
143 char *p, *ename;
144 char *et_file;
145 char const *const *cpp;
146 int got_language = 0;
147 char *got_include = 0;
148 char *got_prefix = ".";
149 int got_emit = 0;
150 char lcname[6];
151
152 #ifdef AFS_AIX32_ENV
153 /*
154 * The following signal action for AIX is necessary so that in case of a
155 * crash (i.e. core is generated) we can include the user's data section
156 * in the core dump. Unfortunately, by default, only a partial core is
157 * generated which, in many cases, isn't too useful.
158 */
159 struct sigaction nsa;
160
161 sigemptyset(&nsa.sa_mask);
162 nsa.sa_handler = SIG_DFL;
163 nsa.sa_flags = SA_FULLDUMP;
164 sigaction(SIGSEGV, &nsa, NULL);
165 #endif
166 /* argument parsing */
167 debug = 0;
168 filename = 0;
169 whoami = argv[0];
170 p = strrchr(whoami, '/');
171 if (p)
172 whoami = p + 1;
173 while (--argc) {
174 char *arg = *++argv;
175 if (arg[0] != '-') {
176 if (filename)
177 dup_err("filenames", filename, arg);
178 filename = arg;
179 } else {
180 arg++;
181 if (check_arg(debug_args, arg))
182 debug++;
183 else if (check_arg(lang_args, arg)) {
184 got_language++;
185 arg = *++argv;
186 argc--;
187 if (!arg)
188 usage();
189 if (language)
190 dup_err("languanges", language_names[(int)language], arg);
191
192 #define check_lang(x,v) if (!strcasecmp(arg,x)) language = v
193 check_lang("c", lang_C);
194 check_lang("ansi_c", lang_C);
195 check_lang("ansi-c", lang_C);
196 check_lang("krc", lang_KRC);
197 check_lang("kr_c", lang_KRC);
198 check_lang("kr-c", lang_KRC);
199 check_lang("k&r-c", lang_KRC);
200 check_lang("k&r_c", lang_KRC);
201 check_lang("c++", lang_CPP);
202 check_lang("cplusplus", lang_CPP);
203 check_lang("c-plus-plus", lang_CPP);
204 #undef check_lang
205
206 if (!language) {
207 fprintf(stderr, "%s: unknown language name `%s'\n",
208 whoami, arg);
209 fprintf(stderr, "\tpick one of: C K&R-C\n");
210 exit(1);
211 }
212 } else if (strcmp(arg, "h") == 0) {
213 arg = *++argv;
214 argc--;
215 if (!arg)
216 usage();
217 got_include = arg;
218 } else if (check_arg(prefix_args, arg)) {
219 arg = *++argv;
220 argc--;
221 if (!arg)
222 usage();
223 got_prefix = arg;
224 } else if (strcmp(arg, "v") == 0) {
225 arg = *++argv;
226 argc--;
227 if (arg == NULL) {
228 fprintf(stderr, "%s: -v option requires an argument\n",
229 whoami);
230 usage();
231 exit(1);
232 }
233 version = atoi(arg);
234 if (version != 1 && version != 2) {
235 fprintf(stderr, "%s: unknown control argument -`%s'\n",
236 whoami, arg);
237 usage();
238 exit(1);
239 }
240 if (version == 2)
241 use_msf = 1;
242 } else if (check_arg(emit_args, arg)) {
243 arg = *++argv;
244 argc--;
245 got_emit = 1;
246 if (!strcasecmp(arg, "source")) {
247 emit_source = 1;
248 } else if (!strcasecmp(arg, "c")) {
249 emit_source = 1;
250 } else if (!strcasecmp(arg, "header")) {
251 emit_header = 1;
252 } else if (!strcasecmp(arg, "h")) {
253 emit_header = 1;
254 } else {
255 fprintf(stderr, "%s: unknown emit argument - `%s'\n",
256 whoami, arg);
257 usage();
258 exit(1);
259 }
260 } else {
261 fprintf(stderr, "%s: unknown control argument -`%s'\n",
262 whoami, arg);
263 usage();
264 }
265 }
266 }
267 if (!filename)
268 usage();
269 if (!got_language)
270 language = lang_C;
271 else if (language == lang_CPP) {
272 fprintf(stderr, "%s: Sorry, C++ support is not yet finished.\n",
273 whoami);
274 exit(1);
275 }
276
277 if (!got_emit) {
278 emit_source = emit_header = 1; /* generate both by default */
279 }
280
281 p = strrchr(filename, '/');
282 if (p == NULL)
283 p = filename;
284 else
285 p++;
286 ename = xmalloc(strlen(p) + 5);
287 strcpy(ename, p);
288
289 /* Now, flush .et suffix if it exists. */
290 p = strrchr(ename, '.');
291 if (p != NULL) {
292 if (strcmp(p, ".et") == 0)
293 *p = 0;
294 }
295
296 if (emit_source) {
297 if (use_msf) {
298 sprintf(msf_file, "%s.msf", ename);
299 } else {
300 sprintf(c_file, "%s.c", ename);
301 }
302 }
303 if (emit_header) {
304 if (got_include) {
305 sprintf(h_file, "%s.h", got_include);
306 } else {
307 sprintf(h_file, "%s.h", ename);
308 }
309 }
310 p = strrchr(filename, '.');
311 if (p == NULL) {
312 p = xmalloc(strlen(filename) + 4);
313 sprintf(p, "%s.et", filename);
314 filename = p;
315 }
316
317 if (asprintf(&et_file, "%s/%s", got_prefix, filename) < 0) {
318 fprintf(stderr, "Couldn't allocate memory for filename\n");
319 exit(1);
320 }
321
322 yyin = fopen(et_file, "r");
323 if (!yyin) {
324 perror(et_file);
325 exit(1);
326 }
327
328 free(et_file);
329
330 /* on NT, yyout is not initialized to stdout */
331 if (!yyout) {
332 yyout = stdout;
333 }
334
335 if (emit_header) {
336 hfile = fopen(h_file, "w");
337 if (hfile == NULL) {
338 perror(h_file);
339 exit(1);
340 }
341 fprintf(hfile, warning, h_file);
342 }
343 if (emit_header && got_include) {
344 char buffer[BUFSIZ];
345 char prolog_h_file[MAXPATHLEN];
346 FILE *prolog_hfile;
347 int count, written;
348
349 strcpy(prolog_h_file, got_prefix);
350 strcat(prolog_h_file, "/");
351 strcat(prolog_h_file, got_include);
352 strcat(prolog_h_file, ".p.h");
353 prolog_hfile = fopen(prolog_h_file, "r");
354 if (prolog_hfile) {
355 fprintf(stderr, "Including %s at beginning of %s file.\n",
356 prolog_h_file, h_file);
357 fprintf(hfile, "/* Including %s at beginning of %s file. */\n\n",
358 prolog_h_file, h_file);
359 do {
360 count =
361 fread(buffer, sizeof(char), sizeof(buffer), prolog_hfile);
362 if (count == EOF) {
363 perror(prolog_h_file);
364 exit(1);
365 }
366 written = fwrite(buffer, sizeof(char), count, hfile);
367 if (count != written) {
368 perror(prolog_h_file);
369 exit(1);
370 }
371 } while (count > 0);
372 fprintf(hfile, "\n/* End of prolog file %s. */\n\n",
373 prolog_h_file);
374 }
375 }
376
377 if (emit_source && use_msf) {
378 msfile = fopen(msf_file, "w");
379 if (msfile == NULL) {
380 perror(msf_file);
381 exit(1);
382 }
383 fprintf(msfile, msf_warning, msf_file);
384 } else if (emit_source) {
385 cfile = fopen(c_file, "w");
386 if (cfile == NULL) {
387 perror(c_file);
388 exit(1);
389 }
390 fprintf(cfile, warning, c_file);
391
392 /* prologue */
393 if (language == lang_C)
394 cpp = c_src_prolog;
395 else if (language == lang_KRC)
396 cpp = krc_src_prolog;
397 else
398 abort();
399 while (*cpp)
400 fputs(*cpp++, cfile);
401 }
402
403 /* parse it */
404 yyparse();
405 fclose(yyin); /* bye bye input file */
406
407 if (!use_msf) {
408 if (cfile) {
409 fputs(" 0\n};\n\n", cfile);
410 fprintf(cfile,
411 "static const struct error_table et = { text, %ldL, %d };\n\n",
412 (long int)table_number, current);
413 fputs("static struct et_list etlink = { 0, &et};\n\n", cfile);
414 fprintf(cfile, "void initialize_%s_error_table(void) {\n",
415 table_name);
416 fputs(" afs_add_to_error_table(&etlink);\n", cfile);
417 fputs("}\n", cfile);
418 fclose(cfile);
419 }
420 if (hfile) {
421 fprintf(hfile, "extern void initialize_%s_error_table(void);\n",
422 table_name);
423 }
424 } else {
425 if (hfile) {
426 fprintf(hfile, "#define initialize_%s_error_table(void)\n",
427 table_name);
428 }
429 }
430
431 if (hfile) {
432 fprintf(hfile, "#define ERROR_TABLE_BASE_%s (%ldL)\n", table_name,
433 (long int)table_number);
434 /* compatibility... */
435 fprintf(hfile, "\n/* for compatibility with older versions... */\n");
436 fprintf(hfile, "#define init_%s_err_tbl initialize_%s_error_table\n",
437 table_name, table_name);
438 fprintf(hfile, "#define %s_err_base ERROR_TABLE_BASE_%s\n",
439 table_name, table_name);
440 fprintf(hfile, "\n/* for compatibility with other users... */\n");
441 lcstring(lcname, table_name, sizeof(lcname));
442 fprintf(hfile, "#define ERROR_TABLE_BASE_%s (%ldL)\n", lcname,
443 (long int)table_number);
444 fprintf(hfile, "#define init_%s_err_tbl initialize_%s_error_table\n",
445 lcname, table_name);
446 fprintf(hfile,
447 "#define initialize_%s_error_table initialize_%s_error_table\n",
448 lcname, table_name);
449 fprintf(hfile, "#define %s_err_base ERROR_TABLE_BASE_%s\n", lcname,
450 lcname);
451 fclose(hfile); /* bye bye include file */
452 }
453 if (msfile)
454 fclose(msfile);
455 return 0;
456 }
457
458 void
459 yyerror(const char *s)
460 {
461 fputs(s, stderr);
462 fprintf(stderr, "\nLine number %d; last token was '%s'\n", yylineno,
463 current_token);
464 }