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