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