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