source: trunk/third/moira/util/et/compile_et.c @ 24319

Revision 24319, 6.9 KB checked in by broder, 14 years ago (diff)
New Moira snapshot from SVN.
Line 
1/*
2 *
3 * Copyright 1986, 1987, 1988
4 * by MIT Student Information Processing Board.
5 *
6 * For copyright info, see "mit-sipb-copyright.h".
7 *
8 */
9
10#include "mit-sipb-copyright.h"
11
12#include <sys/types.h>
13#include <sys/param.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17#include <errno.h>
18#include <unistd.h>
19
20static const char copyright[] =
21    "Copyright 1987,1988 by MIT Student Information Processing Board";
22
23static const char rcsid[] = "$Id: compile_et.c 3956 2010-01-05 20:56:56Z zacheiss $";
24
25enum lang {
26    lang_C,                     /* ANSI C (default) */
27    lang_KRC,                   /* C: ANSI + K&R */
28    lang_CPP                    /* C++ */
29};
30
31/* From gensym.y. */
32extern char *gensym(const char *x);
33extern int yyparse(void);
34extern char *current_token;
35extern int table_number, current;
36
37/* From et_lex.lex.l. */
38extern FILE *yyin;
39extern int num_lines;
40
41FILE *hfile;
42FILE *cfile;
43char *table_name = NULL;
44
45static int debug;                       /* dump debugging info? */
46static char *filename;                  /* error table source */
47static enum lang language;
48static const char *whoami;
49
50char *xmalloc(unsigned int size)
51{
52    char * p = malloc (size);
53
54    if (!p) {
55        perror (whoami);
56        exit (1);
57    }
58    return p;
59}
60
61static int check_arg(const char *const *str_list, const char *arg)
62{
63    while (*str_list)
64        if (!strcmp(arg, *str_list++))
65            return 1;
66    return 0;
67}
68
69static const char *const debug_args[] = {
70    "d",
71    "debug",
72    0,
73};
74
75static const char *const lang_args[] = {
76    "lang",
77    "language",
78    0,
79};
80
81static const char *const language_names[] = {
82    "C",
83    "K&R C",
84    "C++",
85    0,
86};
87
88static const char * const c_src_prolog[] = {
89    "static const char * const text[] = {\n",
90    0,
91};
92
93static 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    "static const char * const text[] = {\n",
101    0,
102};
103
104static const char *const struct_def[] = {
105    "struct error_table {\n",
106    "    char const * const * msgs;\n",
107    "    long base;\n",
108    "    int n_msgs;\n",
109    "};\n",
110    "struct et_list {\n",
111    "    struct et_list *next;\n",
112    "    const struct error_table * table;\n",
113    "};\n",
114    "extern struct et_list *_et_list;\n",
115    "\n", 0,
116};
117
118static const char warning[] =
119    "/*\n * %s:\n * This file is automatically generated; please do not edit it.\n */\n";
120
121/* pathnames */
122char c_file[MAXPATHLEN];        /* output file */
123char h_file[MAXPATHLEN];        /* output */
124
125static void usage() {
126    fprintf (stderr, "%s: usage: %s ERROR_TABLE\n",
127             whoami, whoami);
128    exit (1);
129}
130
131static void dup_err(const char *type, const char *one, const char *two)
132{
133    fprintf (stderr, "%s: multiple %s specified: `%s' and `%s'\n",
134             whoami, type, one, two);
135    usage ();
136}
137
138int main(int argc, char **argv)
139{
140    char *p, *ename;
141    int len;
142    char const * const *cpp;
143    int got_language = 0;
144
145    /* argument parsing */
146    debug = 0;
147    filename = 0;
148    whoami = argv[0];
149    p = strrchr (whoami, '/');
150    if (p)
151        whoami = p+1;
152    while (argv++, --argc) {
153        char *arg = *argv;
154        if (arg[0] != '-') {
155            if (filename)
156                dup_err ("filenames", filename, arg);
157            filename = arg;
158        }
159        else {
160            arg++;
161            if (check_arg (debug_args, arg))
162                debug++;
163            else if (check_arg (lang_args, arg)) {
164                got_language++;
165                arg = *++argv, argc--;
166                if (!arg)
167                    usage ();
168                if (language)
169                    dup_err ("languanges", language_names[(int)language], arg);
170#define check_lang(x,v) else if (!strcasecmp(arg,x)) language = v
171                check_lang ("c", lang_C);
172                check_lang ("ansi_c", lang_C);
173                check_lang ("ansi-c", lang_C);
174                check_lang ("krc", lang_KRC);
175                check_lang ("kr_c", lang_KRC);
176                check_lang ("kr-c", lang_KRC);
177                check_lang ("k&r-c", lang_KRC);
178                check_lang ("k&r_c", lang_KRC);
179                check_lang ("c++", lang_CPP);
180                check_lang ("cplusplus", lang_CPP);
181                check_lang ("c-plus-plus", lang_CPP);
182#undef check_lang
183                else {
184                    fprintf (stderr, "%s: unknown language name `%s'\n",
185                             whoami, arg);
186                    fprintf (stderr, "\tpick one of: C K&R-C\n");
187                    exit (1);
188                }
189            }
190            else {
191                fprintf (stderr, "%s: unknown control argument -`%s'\n",
192                         whoami, arg);
193                usage ();
194            }
195        }
196    }
197    if (!filename)
198        usage ();
199    if (!got_language)
200        language = lang_C;
201    else if (language == lang_CPP) {
202        fprintf (stderr, "%s: Sorry, C++ support is not yet finished.\n",
203                 whoami);
204        exit (1);
205    }
206
207    p = xmalloc (strlen (filename) + 5);
208    strcpy (p, filename);
209    filename = p;
210    p = strrchr(filename, '/');
211    if (p == NULL)
212        p = filename;
213    else
214        p++;
215    ename = p;
216    len = strlen (ename);
217    p += len - 3;
218    if (strcmp (p, ".et"))
219        p += 3;
220    *p++ = '.';
221    /* now p points to where "et" suffix should start */
222    /* generate new filenames */
223    strcpy (p, "c");
224    strcpy (c_file, ename);
225    *p = 'h';
226    strcpy (h_file, ename);
227    strcpy (p, "et");
228
229    yyin = fopen(filename, "r");
230    if (!yyin) {
231        perror(filename);
232        exit(1);
233    }
234
235    hfile = fopen(h_file, "w");
236    if (hfile == NULL) {
237        perror(h_file);
238        exit(1);
239    }
240    fprintf (hfile, warning, h_file);
241
242    cfile = fopen(c_file, "w");
243    if (cfile == NULL) {
244        perror(c_file);
245        exit(1);
246    }
247    fprintf (cfile, warning, c_file);
248
249    /* prologue */
250    if (language == lang_C)
251        cpp = c_src_prolog;
252    else if (language == lang_KRC)
253        cpp = krc_src_prolog;
254    else
255        abort ();
256    while (*cpp)
257        fputs (*cpp++, cfile);
258
259    /* parse it */
260    yyparse();
261    fclose(yyin);               /* bye bye input file */
262
263    fputs ("    0\n};\n\n", cfile);
264    for (cpp = struct_def; *cpp; cpp++)
265        fputs (*cpp, cfile);
266    fprintf(cfile,
267            "const struct error_table et_%s_error_table = { text, %ldL, %d };",
268            table_name, (long) table_number, current);
269    fputs("\n\nstatic struct et_list link = { 0, 0 };\n\n",
270          cfile);
271    fprintf(cfile, "void initialize_%s_error_table (%s) {\n",
272            table_name, (language == lang_C) ? "void" : "NOARGS");
273    fputs("    if (!link.table) {\n", cfile);
274    fputs("        link.next = _et_list;\n", cfile);
275    fprintf(cfile, "        link.table = &et_%s_error_table;\n", table_name);
276    fputs("        _et_list = &link;\n", cfile);
277    fputs("    }\n", cfile);
278    fputs("}\n", cfile);
279    fclose(cfile);
280
281    if (language == lang_KRC) {
282        fprintf (hfile, "extern void initialize_%s_error_table ();\n",
283                 table_name);
284    } else {
285        fprintf (hfile, "void initialize_%s_error_table (void);\n",
286                 table_name);
287    }
288    fprintf (hfile, "#define ERROR_TABLE_BASE_%s (%ldL)\n",
289             table_name, (long) table_number);
290    /* compatibility... */
291    fprintf (hfile, "\n/* for compatibility with older versions... */\n");
292    fprintf (hfile, "#define init_%s_err_tbl initialize_%s_error_table\n",
293             table_name, table_name);
294    fprintf (hfile, "#define %s_err_base ERROR_TABLE_BASE_%s\n", table_name,
295             table_name);
296    fclose(hfile);              /* bye bye include file */
297
298    return 0;
299}
300
301int yyerror(char *s)
302{
303    fputs(s, stderr);
304    fprintf(stderr, "\nLine number %d; last token was '%s'\n",
305            num_lines, current_token);
306    return 0;
307}
Note: See TracBrowser for help on using the repository browser.