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