c73433fce810cdd7de59af14328193b5c2589313
[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 (argv++, --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, argc--;
178                 if (!arg)
179                     usage();
180                 if (language)
181                     dup_err("languanges", language_names[(int)language], arg);
182
183 #define check_lang(x,v) if (!strcasecmp(arg,x)) language = v
184                 check_lang("c", lang_C);
185                 check_lang("ansi_c", lang_C);
186                 check_lang("ansi-c", lang_C);
187                 check_lang("krc", lang_KRC);
188                 check_lang("kr_c", lang_KRC);
189                 check_lang("kr-c", lang_KRC);
190                 check_lang("k&r-c", lang_KRC);
191                 check_lang("k&r_c", lang_KRC);
192                 check_lang("c++", lang_CPP);
193                 check_lang("cplusplus", lang_CPP);
194                 check_lang("c-plus-plus", lang_CPP);
195 #undef check_lang
196
197                 if (!language) {
198                     fprintf(stderr, "%s: unknown language name `%s'\n",
199                             whoami, arg);
200                     fprintf(stderr, "\tpick one of: C K&R-C\n");
201                     exit(1);
202                 }
203             } else if (strcmp(arg, "h") == 0) {
204                 arg = *++argv, argc--;
205                 if (!arg)
206                     usage();
207                 got_include = arg;
208             } else if (strcmp(arg, "p") == 0) {
209                 arg = *++argv, argc--;
210                 if (!arg)
211                     usage();
212                 got_prefix = arg;
213             } else if (strcmp(arg, "v") == 0) {
214                 arg = *++argv, argc--;
215                 if (arg == NULL) {
216                     fprintf(stderr, "%s: -v option requires an argument\n",
217                             whoami);
218                     usage();
219                     exit(1);
220                 }
221                 version = atoi(arg);
222                 if (version != 1 && version != 2) {
223                     fprintf(stderr, "%s: unknown control argument -`%s'\n",
224                             whoami, arg);
225                     usage();
226                     exit(1);
227                 }
228                 if (version == 2)
229                     use_msf = 1;
230             } else {
231                 fprintf(stderr, "%s: unknown control argument -`%s'\n",
232                         whoami, arg);
233                 usage();
234             }
235         }
236     }
237     if (!filename)
238         usage();
239     if (!got_language)
240         language = lang_C;
241     else if (language == lang_CPP) {
242         fprintf(stderr, "%s: Sorry, C++ support is not yet finished.\n",
243                 whoami);
244         exit(1);
245     }
246
247
248     p = strrchr(filename, '/');
249     if (p == NULL)
250         p = filename;
251     else
252         p++;
253     ename = xmalloc(strlen(p) + 5);
254     strcpy(ename, p);
255
256     /* Now, flush .et suffix if it exists.   */
257     p = strrchr(ename, '.');
258     if (p != NULL) {
259         if (strcmp(p, ".et") == 0)
260             *p = 0;
261     }
262
263     if (use_msf) {
264         sprintf(msf_file, "%s.msf", ename);
265     } else {
266         sprintf(c_file, "%s.c", ename);
267     }
268     if (got_include) {
269         sprintf(h_file, "%s.h", got_include);
270     } else {
271         sprintf(h_file, "%s.h", ename);
272     }
273     p = strrchr(filename, '.');
274     if (p == NULL) {
275         p = xmalloc(strlen(filename) + 4);
276         sprintf(p, "%s.et", filename);
277         filename = p;
278     }
279
280     sprintf(et_file, "%s/%s", got_prefix, filename);
281
282     yyin = fopen(et_file, "r");
283     if (!yyin) {
284         perror(et_file);
285         exit(1);
286     }
287
288     /* on NT, yyout is not initialized to stdout */
289     if (!yyout) {
290         yyout = stdout;
291     }
292
293     hfile = fopen(h_file, "w");
294     if (hfile == NULL) {
295         perror(h_file);
296         exit(1);
297     }
298     fprintf(hfile, warning, h_file);
299     if (got_include) {
300         char buffer[BUFSIZ];
301         char prolog_h_file[MAXPATHLEN];
302         FILE *prolog_hfile;
303         int count, written;
304
305         strcpy(prolog_h_file, got_prefix);
306         strcat(prolog_h_file, "/");
307         strcat(prolog_h_file, got_include);
308         strcat(prolog_h_file, ".p.h");
309         prolog_hfile = fopen(prolog_h_file, "r");
310         if (prolog_hfile) {
311             fprintf(stderr, "Including %s at beginning of %s file.\n",
312                     prolog_h_file, h_file);
313             fprintf(hfile, "/* Including %s at beginning of %s file. */\n\n",
314                     prolog_h_file, h_file);
315             do {
316                 count =
317                     fread(buffer, sizeof(char), sizeof(buffer), prolog_hfile);
318                 if (count == EOF) {
319                     perror(prolog_h_file);
320                     exit(1);
321                 }
322                 written = fwrite(buffer, sizeof(char), count, hfile);
323                 if (count != written) {
324                     perror(prolog_h_file);
325                     exit(1);
326                 }
327             } while (count > 0);
328             fprintf(hfile, "\n/* End of prolog file %s. */\n\n",
329                     prolog_h_file);
330         }
331     }
332
333     if (use_msf) {
334         msfile = fopen(msf_file, "w");
335         if (msfile == NULL) {
336             perror(msf_file);
337             exit(1);
338         }
339         fprintf(msfile, msf_warning, msf_file);
340     } else {
341         cfile = fopen(c_file, "w");
342         if (cfile == NULL) {
343             perror(c_file);
344             exit(1);
345         }
346         fprintf(cfile, warning, c_file);
347
348         /* prologue */
349         if (language == lang_C)
350             cpp = c_src_prolog;
351         else if (language == lang_KRC)
352             cpp = krc_src_prolog;
353         else
354             abort();
355         while (*cpp)
356             fputs(*cpp++, cfile);
357     }
358
359     /* parse it */
360     yyparse();
361     fclose(yyin);               /* bye bye input file */
362
363     if (!use_msf) {
364         fputs("    0\n};\n\n", cfile);
365         fprintf(cfile,
366                 "static const struct error_table et = { text, %ldL, %d };\n\n",
367                 (long int)table_number, current);
368         fputs("static struct et_list etlink = { 0, &et};\n\n", cfile);
369         fprintf(cfile, "void initialize_%s_error_table(void) {\n",
370                 table_name);
371         fputs("    afs_add_to_error_table(&etlink);\n", cfile);
372         fputs("}\n", cfile);
373         fclose(cfile);
374
375
376         fprintf(hfile, "extern void initialize_%s_error_table(void);\n",
377                 table_name);
378     } else {
379         fprintf(hfile, "#define initialize_%s_error_table(void)\n",
380                 table_name);
381     }
382
383     fprintf(hfile, "#define ERROR_TABLE_BASE_%s (%ldL)\n", table_name,
384             (long int)table_number);
385     /* compatibility... */
386     fprintf(hfile, "\n/* for compatibility with older versions... */\n");
387     fprintf(hfile, "#define init_%s_err_tbl initialize_%s_error_table\n",
388             table_name, table_name);
389     fprintf(hfile, "#define %s_err_base ERROR_TABLE_BASE_%s\n", table_name,
390             table_name);
391     fprintf(hfile, "\n/* for compatibility with other users... */\n");
392     lcstring(lcname, table_name, sizeof(lcname));
393     fprintf(hfile, "#define ERROR_TABLE_BASE_%s (%ldL)\n", lcname,
394             (long int)table_number);
395     fprintf(hfile, "#define init_%s_err_tbl initialize_%s_error_table\n",
396             lcname, table_name);
397     fprintf(hfile,
398             "#define initialize_%s_error_table initialize_%s_error_table\n",
399             lcname, table_name);
400     fprintf(hfile, "#define %s_err_base ERROR_TABLE_BASE_%s\n", lcname,
401             lcname);
402     fclose(hfile);              /* bye bye include file */
403     if (use_msf)
404         fclose(msfile);
405     return 0;
406 }
407
408 void
409 yyerror(const char *s)
410 {
411     fputs(s, stderr);
412     fprintf(stderr, "\nLine number %d; last token was '%s'\n", yylineno,
413             current_token);
414 }