PageRenderTime 46ms CodeModel.GetById 14ms app.highlight 28ms RepoModel.GetById 1ms app.codeStats 0ms

/usr.bin/yacc/main.c

https://bitbucket.org/freebsd/freebsd-head/
C | 438 lines | 336 code | 61 blank | 41 comment | 99 complexity | ac53961b2f52d5dda8ce567d4c5f1df8 MD5 | raw file
  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 * 4. Neither the name of the University nor the names of its contributors
 17 *    may be used to endorse or promote products derived from this software
 18 *    without specific prior written permission.
 19 *
 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 30 * SUCH DAMAGE.
 31 */
 32
 33#if 0
 34#ifndef lint
 35static char sccsid[] = "@(#)main.c	5.5 (Berkeley) 5/24/93";
 36#endif
 37#endif
 38
 39#include <sys/cdefs.h>
 40__FBSDID("$FreeBSD$");
 41
 42#include <paths.h>
 43#include <signal.h>
 44#include <stdlib.h>
 45#include <string.h>
 46#include <unistd.h>
 47#include "defs.h"
 48
 49char dflag;
 50char lflag;
 51char rflag;
 52char tflag;
 53char vflag;
 54
 55const char *symbol_prefix;
 56const char *file_prefix = "y";
 57char temp_form[] = "yacc.XXXXXXXXXXX";
 58
 59int lineno;
 60int outline;
 61
 62char *action_file_name;
 63char *code_file_name;
 64char *defines_file_name;
 65const char *input_file_name = "";
 66char *output_file_name;
 67char *text_file_name;
 68char *union_file_name;
 69char *verbose_file_name;
 70
 71FILE *action_file;	/*  a temp file, used to save actions associated    */
 72			/*  with rules until the parser is written	    */
 73FILE *code_file;	/*  y.code.c (used when the -r option is specified) */
 74FILE *defines_file;	/*  y.tab.h					    */
 75FILE *input_file;	/*  the input file				    */
 76FILE *output_file;	/*  y.tab.c					    */
 77FILE *text_file;	/*  a temp file, used to save text until all	    */
 78			/*  symbols have been defined			    */
 79FILE *union_file;	/*  a temp file, used to save the union		    */
 80			/*  definition until all symbol have been	    */
 81			/*  defined					    */
 82FILE *verbose_file;	/*  y.output					    */
 83
 84int nitems;
 85int nrules;
 86int nsyms;
 87int ntokens;
 88int nvars;
 89
 90int   start_symbol;
 91char  **symbol_name;
 92short *symbol_value;
 93short *symbol_prec;
 94char  *symbol_assoc;
 95
 96short *ritem;
 97short *rlhs;
 98short *rrhs;
 99short *rprec;
100char  *rassoc;
101short **derives;
102char *nullable;
103
104static void create_file_names(void);
105static void getargs(int, char **);
106static void onintr(int);
107static void open_files(void);
108static void set_signals(void);
109static void usage(void);
110
111volatile sig_atomic_t sigdie;
112
113__dead2 void
114done(int k)
115{
116    if (action_file) { fclose(action_file); unlink(action_file_name); }
117    if (text_file) { fclose(text_file); unlink(text_file_name); }
118    if (union_file) { fclose(union_file); unlink(union_file_name); }
119    if (sigdie) { _exit(k); }
120    exit(k);
121}
122
123
124static void
125onintr(int signo __unused)
126{
127    sigdie = 1;
128    done(1);
129}
130
131
132static void
133set_signals(void)
134{
135#ifdef SIGINT
136    if (signal(SIGINT, SIG_IGN) != SIG_IGN)
137	signal(SIGINT, onintr);
138#endif
139#ifdef SIGTERM
140    if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
141	signal(SIGTERM, onintr);
142#endif
143#ifdef SIGHUP
144    if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
145	signal(SIGHUP, onintr);
146#endif
147}
148
149
150static void
151usage(void)
152{
153    fprintf(stderr, "%s\n%s\n",
154		"usage: yacc [-dlrtv] [-b file_prefix] [-o output_filename]",
155		"            [-p symbol_prefix] filename");
156    exit(1);
157}
158
159
160static void
161getargs(int argc, char *argv[])
162{
163    int ch;
164
165    while ((ch = getopt(argc, argv, "b:dlo:p:rtvy")) != -1)
166    {
167	switch (ch)
168	{
169	case 'b':
170	    file_prefix = optarg;
171	    break;
172
173	case 'd':
174	    dflag = 1;
175	    break;
176
177	case 'l':
178	    lflag = 1;
179	    break;
180
181	case 'o':
182	    output_file_name = optarg;
183	    break;
184
185	case 'p':
186	    symbol_prefix = optarg;
187	    break;
188
189	case 'r':
190	    rflag = 1;
191	    break;
192
193	case 't':
194	    tflag = 1;
195	    break;
196
197	case 'v':
198	    vflag = 1;
199	    break;
200
201	case 'y':
202	    /* for bison compatibility -- byacc is already POSIX compatible */
203	    break;
204
205	default:
206	    usage();
207	}
208    }
209
210    if (optind + 1 != argc)
211	usage();
212    if (strcmp(argv[optind], "-") == 0)
213	input_file = stdin;
214    else
215	input_file_name = argv[optind];
216}
217
218
219void *
220allocate(size_t n)
221{
222    void *p;
223
224    p = NULL;
225    if (n)
226    {
227	p = calloc(1, n);
228	if (!p) no_space();
229    }
230    return (p);
231}
232
233
234static void
235create_file_names(void)
236{
237    int i, len;
238    const char *tmpdir;
239
240    if (!(tmpdir = getenv("TMPDIR")))
241	tmpdir = _PATH_TMP;
242
243    len = strlen(tmpdir);
244    i = len + strlen(temp_form) + 1;
245    if (len && tmpdir[len-1] != '/')
246	++i;
247
248    action_file_name = malloc(i);
249    if (action_file_name == 0) no_space();
250    text_file_name = malloc(i);
251    if (text_file_name == 0) no_space();
252    union_file_name = malloc(i);
253    if (union_file_name == 0) no_space();
254
255    strcpy(action_file_name, tmpdir);
256    strcpy(text_file_name, tmpdir);
257    strcpy(union_file_name, tmpdir);
258
259    if (len && tmpdir[len - 1] != '/')
260    {
261	action_file_name[len] = '/';
262	text_file_name[len] = '/';
263	union_file_name[len] = '/';
264	++len;
265    }
266
267    strcpy(action_file_name + len, temp_form);
268    strcpy(text_file_name + len, temp_form);
269    strcpy(union_file_name + len, temp_form);
270
271    action_file_name[len + 5] = 'a';
272    text_file_name[len + 5] = 't';
273    union_file_name[len + 5] = 'u';
274
275    if (output_file_name != 0)
276    {
277	file_prefix = output_file_name;
278	len = strlen(file_prefix);
279    }
280    else
281    {
282	len = strlen(file_prefix);
283	output_file_name = malloc(len + 7);
284	if (output_file_name == 0)
285	    no_space();
286	strcpy(output_file_name, file_prefix);
287	strcpy(output_file_name + len, OUTPUT_SUFFIX);
288    }
289
290    if (rflag)
291    {
292	code_file_name = malloc(len + 8);
293	if (code_file_name == 0)
294	    no_space();
295	strcpy(code_file_name, file_prefix);
296	if (file_prefix == output_file_name)
297	{
298	    /*
299	     * XXX ".tab.c" here is OUTPUT_SUFFIX, but since its length is
300	     * in various magic numbers, don't bother using the macro.
301	     */
302	    if (len >= 6 && strcmp(code_file_name + len - 6, ".tab.c") == 0)
303		strcpy(code_file_name + len - 6, CODE_SUFFIX);
304	    else if (len >= 2 && strcmp(code_file_name + len - 2, ".c") == 0)
305		strcpy(code_file_name + len - 2, CODE_SUFFIX);
306	    else
307		strcpy(code_file_name + len, CODE_SUFFIX);
308	}
309	else
310	    strcpy(code_file_name + len, CODE_SUFFIX);
311    }
312    else
313	code_file_name = output_file_name;
314
315    if (dflag)
316    {
317	defines_file_name = malloc(len + 7);
318	if (defines_file_name == 0)
319	    no_space();
320	strcpy(defines_file_name, file_prefix);
321	if (file_prefix == output_file_name)
322	{
323#define BISON_DEFINES_SUFFIX  ".h"
324	    if (len >= 2 && strcmp(defines_file_name + len - 2, ".c") == 0)
325		strcpy(defines_file_name + len - 2, BISON_DEFINES_SUFFIX);
326	    else
327		strcpy(defines_file_name + len, BISON_DEFINES_SUFFIX);
328	}
329	else
330	    strcpy(defines_file_name + len, DEFINES_SUFFIX);
331    }
332
333    if (vflag)
334    {
335	verbose_file_name = malloc(len + 8);
336	if (verbose_file_name == 0)
337	    no_space();
338	strcpy(verbose_file_name, file_prefix);
339	if (file_prefix == output_file_name)
340	{
341	    if (len >= 6 && strcmp(verbose_file_name + len - 6, ".tab.c") == 0)
342		strcpy(verbose_file_name + len - 6, VERBOSE_SUFFIX);
343	    else if (len >= 2 && strcmp(verbose_file_name + len - 2, ".c") == 0)
344		strcpy(verbose_file_name + len - 2, VERBOSE_SUFFIX);
345	    else
346		strcpy(verbose_file_name + len, VERBOSE_SUFFIX);
347	}
348	else
349	    strcpy(verbose_file_name + len, VERBOSE_SUFFIX);
350    }
351}
352
353
354static void
355open_files(void)
356{
357    int fd;
358
359    create_file_names();
360
361    if (input_file == 0)
362    {
363	input_file = fopen(input_file_name, "r");
364	if (input_file == 0)
365	    open_error(input_file_name);
366    }
367
368    fd = mkstemp(action_file_name);
369    if (fd < 0 || (action_file = fdopen(fd, "w")) == NULL) {
370        if (fd >= 0)
371	    close(fd);
372	open_error(action_file_name);
373    }
374    fd = mkstemp(text_file_name);
375    if (fd < 0 || (text_file = fdopen(fd, "w")) == NULL) {
376        if (fd >= 0)
377	    close(fd);
378	open_error(text_file_name);
379    }
380    fd = mkstemp(union_file_name);
381    if (fd < 0 || (union_file = fdopen(fd, "w")) == NULL) {
382        if (fd >= 0)
383	    close(fd);
384	open_error(union_file_name);
385    }
386
387    text_file = fopen(text_file_name, "w");
388    if (text_file == 0)
389	open_error(text_file_name);
390
391    if (vflag)
392    {
393	verbose_file = fopen(verbose_file_name, "w");
394	if (verbose_file == 0)
395	    open_error(verbose_file_name);
396    }
397
398    if (dflag)
399    {
400	defines_file = fopen(defines_file_name, "w");
401	if (defines_file == 0)
402	    open_error(defines_file_name);
403	union_file = fopen(union_file_name, "w");
404	if (union_file ==  0)
405	    open_error(union_file_name);
406    }
407
408    output_file = fopen(output_file_name, "w");
409    if (output_file == 0)
410	open_error(output_file_name);
411
412    if (rflag)
413    {
414	code_file = fopen(code_file_name, "w");
415	if (code_file == 0)
416	    open_error(code_file_name);
417    }
418    else
419	code_file = output_file;
420}
421
422
423int
424main(int argc, char *argv[])
425{
426    set_signals();
427    getargs(argc, argv);
428    open_files();
429    reader();
430    lr0();
431    lalr();
432    make_parser();
433    verbose();
434    output();
435    done(0);
436    /*NOTREACHED*/
437    return (0);
438}