ident-cleanup-20030619
[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 #ifdef AFS_AIX51_ENV
51 int yylineno = 0;
52 #else
53 extern int yylineno;
54 #endif
55
56 char * xmalloc (unsigned int size)
57 {
58     char * p = malloc (size);
59     if (!p) {
60         perror (whoami);
61         exit (1);
62     }
63     return p;
64 }
65
66 static int check_arg (char const *const *str_list, char const *arg)
67 {
68     while (*str_list)
69         if (!strcmp(arg, *str_list++))
70             return 1;
71     return 0;
72 }
73
74 static const char *const debug_args[] = {
75     "d",
76     "debug",
77     0,
78 };
79
80 static const char *const lang_args[] = {
81     "lang",
82     "language",
83     0,
84 };
85
86 static const char *const language_names[] = {
87     "C",
88     "K&R C",
89     "C++",
90     0,
91 };
92
93 static const char * const c_src_prolog[] = {
94     "#include <afs/param.h>\n",
95     "#include <afs/error_table.h>\n",
96     "static const char * const text[] = {\n",
97     0,
98 };
99
100 static const char * const krc_src_prolog[] = {
101     "#ifdef __STDC__\n",
102     "#define NOARGS void\n",
103     "#else\n",
104     "#define NOARGS\n",
105     "#define const\n",
106     "#endif\n\n",
107     "#include <afs/param.h>\n",
108     "#include <afs/error_table.h>\n",
109     "static const char * const text[] = {\n",
110     0,
111 };
112
113 static const char warning[] =
114     "/*\n * %s:\n * This file is automatically generated; please do not edit it.\n */\n";
115
116 static const char msf_warning[] =
117     "$ \n$ %s:\n$ This file is automatically generated; please do not edit it.\n$ \n$set 1\n";
118
119 /* pathnames */
120 char c_file[MAXPATHLEN];        /* output file */
121 char h_file[MAXPATHLEN];        /* output */
122 char msf_file[MAXPATHLEN];
123 char et_file[MAXPATHLEN];       /* full path to input file */
124
125 static void usage (void)
126 {
127     fprintf (stderr, "%s: usage: %s ERROR_TABLE [-debug] [-language LANG] [-h INCLUDE] [-p prefix] [-v version]\n",
128              whoami, whoami);
129     exit (1);
130 }
131
132 static void dup_err (char const *type, 
133         char const *one, 
134         char const *two)
135 {
136     fprintf (stderr, "%s: multiple %s specified: `%s' and `%s'\n",
137              whoami, type, one, two);
138     usage ();
139 }
140
141 #include "AFS_component_version_number.c"
142
143 int main (int argc, char **argv)
144 {
145     char *p, *ename;
146     char const * const *cpp;
147     int got_language = 0;
148     char *got_include = 0;
149     char *got_prefix = ".";
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 (argv++, --argc) {
174         char *arg = *argv;
175         if (arg[0] != '-') {
176             if (filename)
177                 dup_err ("filenames", filename, arg);
178             filename = arg;
179         }
180         else {
181             arg++;
182             if (check_arg (debug_args, arg))
183                 debug++;
184             else if (check_arg (lang_args, arg)) {
185                 got_language++;
186                 arg = *++argv, 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                 {
208                     fprintf (stderr, "%s: unknown language name `%s'\n",
209                              whoami, arg);
210                     fprintf (stderr, "\tpick one of: C K&R-C\n");
211                     exit (1);
212                 }
213             }
214             else if (strcmp (arg, "h") == 0) {
215                 arg = *++argv, argc--;
216                 if (!arg) usage ();
217                 got_include = arg;
218             }
219             else if (strcmp (arg, "p") == 0) {
220                 arg = *++argv, argc--;
221                 if (!arg) usage ();
222                 got_prefix = arg;
223             }
224             else if (strcmp (arg, "v") == 0) {
225                 arg = *++argv, argc--;
226                 version = atoi(arg);
227                 if (version != 1 && version != 2) {
228                     fprintf (stderr, "%s: unknown control argument -`%s'\n",
229                              whoami, arg);
230                     usage ();
231                     exit(1);
232                 }
233                 if (version == 2) use_msf = 1;
234             }
235             else {
236                 fprintf (stderr, "%s: unknown control argument -`%s'\n",
237                          whoami, arg);
238                 usage ();
239             }
240         }
241     }
242     if (!filename)
243         usage ();
244     if (!got_language)
245         language = lang_C;
246     else if (language == lang_CPP) {
247         fprintf (stderr, "%s: Sorry, C++ support is not yet finished.\n",
248                  whoami);
249         exit (1);
250     }
251
252
253     p = strrchr(filename, '/');
254     if (p == (char *)NULL)
255         p = filename;
256     else
257         p++;
258     ename = xmalloc (strlen(p) + 5);
259     strcpy (ename, p);
260
261     /* Now, flush .et suffix if it exists.   */
262     p = strrchr(ename, '.');
263     if (p != NULL) {
264         if (strcmp (p, ".et") == 0)
265             *p = 0;
266     }
267
268     if (use_msf) {
269         sprintf(msf_file, "%s.msf", ename);
270     }  else {
271         sprintf(c_file, "%s.c", ename);
272     }
273     if (got_include) {
274         sprintf(h_file, "%s.h", got_include);
275     } else {
276         sprintf(h_file, "%s.h", ename);
277     }
278     p = strrchr(filename, '.');
279     if (p == NULL)
280     {
281         p = xmalloc (strlen(filename) + 4);
282         sprintf(p, "%s.et", filename);
283         filename = p;
284     }
285
286     sprintf(et_file, "%s/%s", got_prefix, filename);
287
288     yyin = fopen(et_file, "r");
289     if (!yyin) {
290         perror(et_file);
291         exit(1);
292     }
293
294     /* on NT, yyout is not initialized to stdout */
295     if (!yyout) {
296         yyout = stdout;
297     }
298
299     hfile = fopen(h_file, "w");
300     if (hfile == (FILE *)NULL) {
301         perror(h_file);
302         exit(1);
303     }
304     fprintf (hfile, warning, h_file);
305     if (got_include) {
306         char  buffer[BUFSIZ];
307         char  prolog_h_file[MAXPATHLEN];
308         FILE *prolog_hfile;
309         int   count, written;
310
311         strcpy (prolog_h_file, got_prefix);
312         strcat (prolog_h_file, "/");
313         strcat (prolog_h_file, got_include);
314         strcat (prolog_h_file, ".p.h");
315         prolog_hfile = fopen(prolog_h_file, "r");
316         if (prolog_hfile) {
317             fprintf (stderr, "Including %s at beginning of %s file.\n", prolog_h_file, h_file);
318             fprintf (hfile, "/* Including %s at beginning of %s file. */\n\n",
319                      prolog_h_file, h_file);
320             do {
321                 count = 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", prolog_h_file);
333         }
334     }
335
336     if (use_msf) {
337         msfile = fopen(msf_file, "w");
338         if (msfile == (FILE *)NULL) {
339             perror(msf_file);
340             exit(1);
341         }
342         fprintf(msfile, msf_warning, msf_file);
343     } else {
344         cfile = fopen(c_file, "w");
345         if (cfile == (FILE *)NULL) {
346             perror(c_file);
347             exit(1);
348         }
349         fprintf (cfile, warning, c_file);
350
351         /* prologue */
352         if (language == lang_C)
353             cpp = c_src_prolog;
354         else if (language == lang_KRC)
355             cpp = krc_src_prolog;
356         else
357             abort ();
358         while (*cpp)
359             fputs (*cpp++, cfile);
360     }
361
362     /* parse it */
363     yyparse();
364     fclose(yyin);               /* bye bye input file */
365
366     if (!use_msf) {
367         fputs ("    0\n};\n\n", cfile);
368         fprintf(cfile,
369                 "static const struct error_table et = { text, %ldL, %d };\n\n",
370                 (long int) table_number, current);
371         fputs("static struct et_list etlink = { 0, &et};\n\n", cfile);
372         fprintf(cfile, "void initialize_%s_error_table(void) {\n", table_name);
373         fputs("    add_to_error_table(&etlink);\n", cfile);
374         fputs("}\n", cfile);
375         fclose(cfile);
376
377
378         fprintf (hfile, "extern void initialize_%s_error_table(void);\n",
379                  table_name);
380     } else {
381         fprintf (hfile, "#define initialize_%s_error_table(void)\n",
382                  table_name);
383     }
384
385     fprintf (hfile, "#define ERROR_TABLE_BASE_%s (%ldL)\n",
386              table_name, (long int) table_number);
387     /* compatibility... */
388     fprintf (hfile, "\n/* for compatibility with older versions... */\n");
389     fprintf (hfile, "#define init_%s_err_tbl initialize_%s_error_table\n",
390              table_name, table_name);
391     fprintf (hfile, "#define %s_err_base ERROR_TABLE_BASE_%s\n", table_name,
392              table_name);
393     fprintf (hfile, "\n/* for compatibility with other users... */\n");
394     lcstring (lcname, table_name, sizeof(lcname));
395     fprintf (hfile, "#define ERROR_TABLE_BASE_%s (%ldL)\n",
396              lcname, (long int) table_number);
397     fprintf (hfile, "#define init_%s_err_tbl initialize_%s_error_table\n",
398              lcname, table_name);
399     fprintf (hfile, "#define initialize_%s_error_table initialize_%s_error_table\n",
400              lcname, table_name);
401     fprintf (hfile, "#define %s_err_base ERROR_TABLE_BASE_%s\n", lcname,
402              lcname);
403     fclose(hfile);              /* bye bye include file */
404     if (use_msf)
405         fclose(msfile);
406     return 0;
407 }
408
409 void yyerror(const char *s)
410 {
411     fputs(s, stderr);
412     fprintf(stderr, "\nLine number %d; last token was '%s'\n",
413             yylineno, current_token);
414 }