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