GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/yacc/main.c Lines: 91 137 66.4 %
Date: 2016-12-06 Branches: 49 109 45.0 %

Line Branch Exec Source
1
/* $OpenBSD: main.c,v 1.27 2015/10/10 14:23:47 deraadt Exp $	 */
2
/* $NetBSD: main.c,v 1.5 1996/03/19 03:21:38 jtc Exp $	 */
3
4
/*
5
 * Copyright (c) 1989 The Regents of the University of California.
6
 * All rights reserved.
7
 *
8
 * This code is derived from software contributed to Berkeley by
9
 * Robert Paul Corbett.
10
 *
11
 * Redistribution and use in source and binary forms, with or without
12
 * modification, are permitted provided that the following conditions
13
 * are met:
14
 * 1. Redistributions of source code must retain the above copyright
15
 *    notice, this list of conditions and the following disclaimer.
16
 * 2. Redistributions in binary form must reproduce the above copyright
17
 *    notice, this list of conditions and the following disclaimer in the
18
 *    documentation and/or other materials provided with the distribution.
19
 * 3. Neither the name of the University nor the names of its contributors
20
 *    may be used to endorse or promote products derived from this software
21
 *    without specific prior written permission.
22
 *
23
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33
 * SUCH DAMAGE.
34
 */
35
36
#include <sys/types.h>
37
#include <fcntl.h>
38
#include <paths.h>
39
#include <signal.h>
40
#include <stdlib.h>
41
#include <unistd.h>
42
#include "defs.h"
43
44
char dflag;
45
char lflag;
46
char rflag;
47
char tflag;
48
char vflag;
49
50
char *symbol_prefix;
51
char *file_prefix = "y";
52
53
int lineno;
54
int outline;
55
56
int explicit_file_name;
57
58
char *action_file_name;
59
char *code_file_name;
60
char *defines_file_name;
61
char *input_file_name = "";
62
char *output_file_name;
63
char *text_file_name;
64
char *union_file_name;
65
char *verbose_file_name;
66
67
FILE *action_file;	/* a temp file, used to save actions associated    */
68
			/* with rules until the parser is written	   */
69
FILE *code_file;	/* y.code.c (used when the -r option is specified) */
70
FILE *defines_file;	/* y.tab.h					   */
71
FILE *input_file;	/* the input file				   */
72
FILE *output_file;	/* y.tab.c					   */
73
FILE *text_file;	/* a temp file, used to save text until all	   */
74
			/* symbols have been defined			   */
75
FILE *union_file;	/* a temp file, used to save the union		   */
76
			/* definition until all symbol have been	   */
77
			/* defined					   */
78
FILE *verbose_file;	/* y.output					   */
79
80
int nitems;
81
int nrules;
82
int nsyms;
83
int ntokens;
84
int nvars;
85
86
int start_symbol;
87
char **symbol_name;
88
short *symbol_value;
89
short *symbol_prec;
90
char *symbol_assoc;
91
92
short *ritem;
93
short *rlhs;
94
short *rrhs;
95
short *rprec;
96
char *rassoc;
97
short **derives;
98
char *nullable;
99
100
void onintr(int);
101
void set_signals(void);
102
void usage(void);
103
void getargs(int, char *[]);
104
void create_file_names(void);
105
void open_files(void);
106
107
volatile sig_atomic_t sigdie;
108
109
void
110
done(int k)
111
21
{
112
21
	if (action_file)
113
21
		unlink(action_file_name);
114
21
	if (text_file)
115
21
		unlink(text_file_name);
116
21
	if (union_file)
117
11
		unlink(union_file_name);
118
21
	if (sigdie)
119
		_exit(k);
120
21
	exit(k);
121
}
122
123
124
void
125
onintr(int signo)
126
{
127
	sigdie = 1;
128
	done(1);
129
}
130
131
132
void
133
set_signals(void)
134
21
{
135
#ifdef SIGINT
136
21
	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
137
21
		signal(SIGINT, onintr);
138
#endif
139
#ifdef SIGTERM
140
21
	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
141
21
		signal(SIGTERM, onintr);
142
#endif
143
#ifdef SIGHUP
144
21
	if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
145
21
		signal(SIGHUP, onintr);
146
#endif
147
21
}
148
149
150
void
151
usage(void)
152
{
153
	fprintf(stderr, "usage: %s [-dlrtv] [-b file_prefix] [-o output_file] [-p symbol_prefix] file\n", __progname);
154
	exit(1);
155
}
156
157
158
void
159
getargs(int argc, char *argv[])
160
21
{
161
	int ch;
162
163
55
	while ((ch = getopt(argc, argv, "b:dlo:p:rtv")) != -1) {
164


13
		switch (ch) {
165
		case 'b':
166
			file_prefix = optarg;
167
			break;
168
169
		case 'd':
170
11
			dflag = 1;
171
11
			break;
172
173
		case 'l':
174
			lflag = 1;
175
			break;
176
177
		case 'o':
178
2
			output_file_name = optarg;
179
2
			explicit_file_name = 1;
180
2
			break;
181
182
		case 'p':
183
			symbol_prefix = optarg;
184
			break;
185
186
		case 'r':
187
			rflag = 1;
188
			break;
189
190
		case 't':
191
			tflag = 1;
192
			break;
193
194
		case 'v':
195
			vflag = 1;
196
			break;
197
198
		default:
199
			usage();
200
		}
201
	}
202
21
	argc -= optind;
203
21
	argv += optind;
204
205
21
	if (argc != 1)
206
		usage();
207
21
	if (strcmp(*argv, "-") == 0)
208
		input_file = stdin;
209
	else
210
21
		input_file_name = *argv;
211
21
}
212
213
214
void *
215
allocate(size_t n)
216
58463
{
217
	void *v;
218
219
58463
	v = NULL;
220
58463
	if (n) {
221
58463
		v = calloc(1, n);
222
58463
		if (!v)
223
			no_space();
224
	}
225
58463
	return (v);
226
}
227
228
#define TEMPNAME(s, c, d, l)	\
229
	(asprintf(&(s), "%.*s/yacc.%xXXXXXXXXXX", (int)(l), (d), (c)))
230
231
void
232
create_file_names(void)
233
21
{
234
	size_t len;
235
	char *tmpdir;
236
237

21
	if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0')
238
21
		tmpdir = _PATH_TMP;
239
240
21
	len = strlen(tmpdir);
241
21
	if (tmpdir[len - 1] == '/')
242
21
		len--;
243
244

21
	if (TEMPNAME(action_file_name, 'a', tmpdir, len) == -1 ||
245
	    TEMPNAME(text_file_name, 'r', tmpdir, len) == -1 ||
246
	    TEMPNAME(union_file_name, 'u', tmpdir, len) == -1)
247
		no_space();
248
249
21
	if (output_file_name == NULL) {
250
19
		if (asprintf(&output_file_name, "%s%s", file_prefix, OUTPUT_SUFFIX)
251
		    == -1)
252
			no_space();
253
	}
254
21
	if (rflag) {
255
		if (asprintf(&code_file_name, "%s%s", file_prefix, CODE_SUFFIX) == -1)
256
			no_space();
257
	} else
258
21
		code_file_name = output_file_name;
259
260
21
	if (dflag) {
261
11
		if (explicit_file_name) {
262
			char *suffix;
263
264
2
			defines_file_name = strdup(output_file_name);
265
2
			if (defines_file_name == 0)
266
				no_space();
267
268
			/* does the output_file_name have a known suffix */
269



4
			if ((suffix = strrchr(output_file_name, '.')) != 0 &&
270
			    (!strcmp(suffix, ".c") ||	/* good, old-fashioned C */
271
			     !strcmp(suffix, ".C") ||	/* C++, or C on Windows */
272
			     !strcmp(suffix, ".cc") ||	/* C++ */
273
			     !strcmp(suffix, ".cxx") ||	/* C++ */
274
			     !strcmp(suffix, ".cpp"))) {/* C++ (Windows) */
275
2
				strncpy(defines_file_name, output_file_name,
276
					suffix - output_file_name + 1);
277
2
				defines_file_name[suffix - output_file_name + 1] = 'h';
278
2
				defines_file_name[suffix - output_file_name + 2] = '\0';
279
			} else {
280
				fprintf(stderr, "%s: suffix of output file name %s"
281
				 " not recognized, no -d file generated.\n",
282
					__progname, output_file_name);
283
				dflag = 0;
284
				free(defines_file_name);
285
				defines_file_name = 0;
286
			}
287
		} else {
288
9
			if (asprintf(&defines_file_name, "%s%s", file_prefix,
289
				     DEFINES_SUFFIX) == -1)
290
				no_space();
291
		}
292
	}
293
21
	if (vflag) {
294
		if (asprintf(&verbose_file_name, "%s%s", file_prefix,
295
			     VERBOSE_SUFFIX) == -1)
296
			no_space();
297
	}
298
21
}
299
300
301
void
302
open_files(void)
303
21
{
304
	int fd;
305
306
21
	create_file_names();
307
308
21
	if (input_file == 0) {
309
21
		input_file = fopen(input_file_name, "r");
310
21
		if (input_file == 0)
311
			open_error(input_file_name);
312
	}
313
21
	fd = mkstemp(action_file_name);
314

21
	if (fd == -1 || (action_file = fdopen(fd, "w")) == NULL)
315
		open_error(action_file_name);
316
317
21
	fd = mkstemp(text_file_name);
318

21
	if (fd == -1 || (text_file = fdopen(fd, "w")) == NULL)
319
		open_error(text_file_name);
320
321
21
	if (vflag) {
322
		verbose_file = fopen(verbose_file_name, "w");
323
		if (verbose_file == 0)
324
			open_error(verbose_file_name);
325
	}
326
21
	if (dflag) {
327
11
		defines_file = fopen(defines_file_name, "w");
328
11
		if (defines_file == NULL)
329
			open_write_error(defines_file_name);
330
11
		fd = mkstemp(union_file_name);
331

11
		if (fd == -1 || (union_file = fdopen(fd, "w")) == NULL)
332
			open_error(union_file_name);
333
	}
334
21
	output_file = fopen(output_file_name, "w");
335
21
	if (output_file == 0)
336
		open_error(output_file_name);
337
338
21
	if (rflag) {
339
		code_file = fopen(code_file_name, "w");
340
		if (code_file == 0)
341
			open_error(code_file_name);
342
	} else
343
21
		code_file = output_file;
344
21
}
345
346
347
int
348
main(int argc, char *argv[])
349
21
{
350
21
	if (pledge("stdio rpath wpath cpath", NULL) == -1)
351
		fatal("pledge: invalid arguments");
352
353
21
	set_signals();
354
21
	getargs(argc, argv);
355
21
	open_files();
356
21
	reader();
357
21
	lr0();
358
21
	lalr();
359
21
	make_parser();
360
21
	verbose();
361
21
	output();
362
21
	done(0);
363
	/* NOTREACHED */
364
	return (0);
365
}