Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / usr.bin / yacc / main.c
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Robert Paul Corbett.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by the University of
19  *      California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  * @(#) Copyright (c) 1989 The Regents of the University of California. All rights reserved.
37  * @(#)main.c   5.5 (Berkeley) 5/24/93
38  * $FreeBSD: src/usr.bin/yacc/main.c,v 1.12 2000/01/10 20:26:24 kris Exp $
39  * $DragonFly: src/usr.bin/yacc/main.c,v 1.2 2003/06/17 04:29:34 dillon Exp $
40  */
41
42 #include <signal.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <unistd.h>
46 #include "defs.h"
47
48 char dflag;
49 char lflag;
50 char rflag;
51 char tflag;
52 char vflag;
53
54 char *symbol_prefix;
55 char *file_prefix = "y";
56 char *temp_form = "yacc.XXXXXXXXXXX";
57
58 int lineno;
59 int outline;
60
61 char *action_file_name;
62 char *code_file_name;
63 char *defines_file_name;
64 char *input_file_name = "";
65 char *output_file_name;
66 char *text_file_name;
67 char *union_file_name;
68 char *verbose_file_name;
69
70 FILE *action_file;      /*  a temp file, used to save actions associated    */
71                         /*  with rules until the parser is written          */
72 FILE *code_file;        /*  y.code.c (used when the -r option is specified) */
73 FILE *defines_file;     /*  y.tab.h                                         */
74 FILE *input_file;       /*  the input file                                  */
75 FILE *output_file;      /*  y.tab.c                                         */
76 FILE *text_file;        /*  a temp file, used to save text until all        */
77                         /*  symbols have been defined                       */
78 FILE *union_file;       /*  a temp file, used to save the union             */
79                         /*  definition until all symbol have been           */
80                         /*  defined                                         */
81 FILE *verbose_file;     /*  y.output                                        */
82
83 int nitems;
84 int nrules;
85 int nsyms;
86 int ntokens;
87 int nvars;
88
89 int   start_symbol;
90 char  **symbol_name;
91 short *symbol_value;
92 short *symbol_prec;
93 char  *symbol_assoc;
94
95 short *ritem;
96 short *rlhs;
97 short *rrhs;
98 short *rprec;
99 char  *rassoc;
100 short **derives;
101 char *nullable;
102
103 static void create_file_names __P((void));
104 static void getargs __P((int, char **));
105 static void onintr __P((int));
106 static void open_files __P((void));
107 static void set_signals __P((void));
108 static void usage __P((void));
109
110
111 void
112 done(k)
113 int k;
114 {
115     if (action_file) { fclose(action_file); unlink(action_file_name); }
116     if (text_file) { fclose(text_file); unlink(text_file_name); }
117     if (union_file) { fclose(union_file); unlink(union_file_name); }
118     exit(k);
119 }
120
121
122 static void
123 onintr(signo)
124         int signo;
125 {
126     done(1);
127 }
128
129
130 static void
131 set_signals()
132 {
133 #ifdef SIGINT
134     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
135         signal(SIGINT, onintr);
136 #endif
137 #ifdef SIGTERM
138     if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
139         signal(SIGTERM, onintr);
140 #endif
141 #ifdef SIGHUP
142     if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
143         signal(SIGHUP, onintr);
144 #endif
145 }
146
147
148 static void
149 usage()
150 {
151     fprintf(stderr, "%s\n%s\n",
152                 "usage: yacc [-dlrtv] [-b file_prefix] [-o output_filename]",
153                 "            [-p symbol_prefix] filename");
154     exit(1);
155 }
156
157
158 static void
159 getargs(argc, argv)
160 int argc;
161 char *argv[];
162 {
163     register int i;
164     register char *s;
165
166     for (i = 1; i < argc; ++i)
167     {
168         s = argv[i];
169         if (*s != '-') break;
170         switch (*++s)
171         {
172         case '\0':
173             input_file = stdin;
174             if (i + 1 < argc) usage();
175             return;
176
177         case '-':
178             ++i;
179             goto no_more_options;
180
181         case 'b':
182             if (*++s)
183                  file_prefix = s;
184             else if (++i < argc)
185                 file_prefix = argv[i];
186             else
187                 usage();
188             continue;
189
190         case 'd':
191             dflag = 1;
192             break;
193
194         case 'l':
195             lflag = 1;
196             break;
197
198         case 'o':
199             if (*++s)
200                 output_file_name = s;
201             else if (++i < argc)
202                 output_file_name = argv[i];
203             else
204                 usage();
205             continue;
206
207         case 'p':
208             if (*++s)
209                 symbol_prefix = s;
210             else if (++i < argc)
211                 symbol_prefix = argv[i];
212             else
213                 usage();
214             continue;
215
216         case 'r':
217             rflag = 1;
218             break;
219
220         case 't':
221             tflag = 1;
222             break;
223
224         case 'v':
225             vflag = 1;
226             break;
227
228         default:
229             usage();
230         }
231
232         for (;;)
233         {
234             switch (*++s)
235             {
236             case '\0':
237                 goto end_of_option;
238
239             case 'd':
240                 dflag = 1;
241                 break;
242
243             case 'l':
244                 lflag = 1;
245                 break;
246
247             case 'r':
248                 rflag = 1;
249                 break;
250
251             case 't':
252                 tflag = 1;
253                 break;
254
255             case 'v':
256                 vflag = 1;
257                 break;
258
259             default:
260                 usage();
261             }
262         }
263 end_of_option:;
264     }
265
266 no_more_options:;
267     if (i + 1 != argc) usage();
268     input_file_name = argv[i];
269 }
270
271
272 char *
273 allocate(n)
274 unsigned n;
275 {
276     register char *p;
277
278     p = NULL;
279     if (n)
280     {
281         p = CALLOC(1, n);
282         if (!p) no_space();
283     }
284     return (p);
285 }
286
287
288 static void
289 create_file_names()
290 {
291     int i, len;
292     char *tmpdir;
293
294     tmpdir = getenv("TMPDIR");
295     if (tmpdir == 0) tmpdir = "/tmp";
296
297     len = strlen(tmpdir);
298     i = len + 17;
299     if (len && tmpdir[len-1] != '/')
300         ++i;
301
302     action_file_name = MALLOC(i);
303     if (action_file_name == 0) no_space();
304     text_file_name = MALLOC(i);
305     if (text_file_name == 0) no_space();
306     union_file_name = MALLOC(i);
307     if (union_file_name == 0) no_space();
308
309     strcpy(action_file_name, tmpdir);
310     strcpy(text_file_name, tmpdir);
311     strcpy(union_file_name, tmpdir);
312
313     if (len && tmpdir[len - 1] != '/')
314     {
315         action_file_name[len] = '/';
316         text_file_name[len] = '/';
317         union_file_name[len] = '/';
318         ++len;
319     }
320
321     strcpy(action_file_name + len, temp_form);
322     strcpy(text_file_name + len, temp_form);
323     strcpy(union_file_name + len, temp_form);
324
325     action_file_name[len + 5] = 'a';
326     text_file_name[len + 5] = 't';
327     union_file_name[len + 5] = 'u';
328
329     if (output_file_name != 0)
330     {
331         file_prefix = output_file_name;
332         len = strlen(file_prefix);
333     }
334     else
335     {
336         len = strlen(file_prefix);
337         output_file_name = MALLOC(len + 7);
338         if (output_file_name == 0)
339             no_space();
340         strcpy(output_file_name, file_prefix);
341         strcpy(output_file_name + len, OUTPUT_SUFFIX);
342     }
343
344     if (rflag)
345     {
346         code_file_name = MALLOC(len + 8);
347         if (code_file_name == 0)
348             no_space();
349         strcpy(code_file_name, file_prefix);
350         if (file_prefix == output_file_name)
351         {
352             /*
353              * XXX ".tab.c" here is OUTPUT_SUFFIX, but since its length is
354              * in various magic numbers, don't bother using the macro.
355              */
356             if (len >= 6 && strcmp(code_file_name + len - 6, ".tab.c") == 0)
357                 strcpy(code_file_name + len - 6, CODE_SUFFIX);
358             else if (len >= 2 && strcmp(code_file_name + len - 2, ".c") == 0)
359                 strcpy(code_file_name + len - 2, CODE_SUFFIX);
360             else
361                 strcpy(code_file_name + len, CODE_SUFFIX);
362         }
363         else
364             strcpy(code_file_name + len, CODE_SUFFIX);
365     }
366     else
367         code_file_name = output_file_name;
368
369     if (dflag)
370     {
371         defines_file_name = MALLOC(len + 7);
372         if (defines_file_name == 0)
373             no_space();
374         strcpy(defines_file_name, file_prefix);
375         if (file_prefix == output_file_name)
376         {
377 #define BISON_DEFINES_SUFFIX  ".h"
378             if (len >= 2 && strcmp(defines_file_name + len - 2, ".c") == 0)
379                 strcpy(defines_file_name + len - 2, BISON_DEFINES_SUFFIX);
380             else
381                 strcpy(defines_file_name + len, BISON_DEFINES_SUFFIX);
382         }
383         else
384             strcpy(defines_file_name + len, DEFINES_SUFFIX);
385     }
386
387     if (vflag)
388     {
389         verbose_file_name = MALLOC(len + 8);
390         if (verbose_file_name == 0)
391             no_space();
392         strcpy(verbose_file_name, file_prefix);
393         if (file_prefix == output_file_name)
394         {
395             if (len >= 6 && strcmp(verbose_file_name + len - 6, ".tab.c") == 0)
396                 strcpy(verbose_file_name + len - 6, VERBOSE_SUFFIX);
397             else if (len >= 2 && strcmp(verbose_file_name + len - 2, ".c") == 0)
398                 strcpy(verbose_file_name + len - 2, VERBOSE_SUFFIX);
399             else
400                 strcpy(verbose_file_name + len, VERBOSE_SUFFIX);
401         }
402         else
403             strcpy(verbose_file_name + len, VERBOSE_SUFFIX);
404     }
405 }
406
407
408 static void
409 open_files()
410 {
411     int fd;
412
413     create_file_names();
414
415     if (input_file == 0)
416     {
417         input_file = fopen(input_file_name, "r");
418         if (input_file == 0)
419             open_error(input_file_name);
420     }
421
422     fd = mkstemp(action_file_name);
423     if (fd < 0 || (action_file = fdopen(fd, "w")) == NULL) {
424         if (fd >= 0)
425             close(fd);
426         open_error(action_file_name);
427     }
428     fd = mkstemp(text_file_name);
429     if (fd < 0 || (text_file = fdopen(fd, "w")) == NULL) {
430         if (fd >= 0)
431             close(fd);
432         open_error(text_file_name);
433     }
434     fd = mkstemp(union_file_name);
435     if (fd < 0 || (union_file = fdopen(fd, "w")) == NULL) {
436         if (fd >= 0)
437             close(fd);
438         open_error(union_file_name);
439     }
440
441     text_file = fopen(text_file_name, "w");
442     if (text_file == 0)
443         open_error(text_file_name);
444
445     if (vflag)
446     {
447         verbose_file = fopen(verbose_file_name, "w");
448         if (verbose_file == 0)
449             open_error(verbose_file_name);
450     }
451
452     if (dflag)
453     {
454         defines_file = fopen(defines_file_name, "w");
455         if (defines_file == 0)
456             open_error(defines_file_name);
457         union_file = fopen(union_file_name, "w");
458         if (union_file ==  0)
459             open_error(union_file_name);
460     }
461
462     output_file = fopen(output_file_name, "w");
463     if (output_file == 0)
464         open_error(output_file_name);
465
466     if (rflag)
467     {
468         code_file = fopen(code_file_name, "w");
469         if (code_file == 0)
470             open_error(code_file_name);
471     }
472     else
473         code_file = output_file;
474 }
475
476
477 int
478 main(argc, argv)
479 int argc;
480 char *argv[];
481 {
482     set_signals();
483     getargs(argc, argv);
484     open_files();
485     reader();
486     lr0();
487     lalr();
488     make_parser();
489     verbose();
490     output();
491     done(0);
492     /*NOTREACHED*/
493     return (0);
494 }