GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/yacc/main.c Lines: 82 141 58.2 %
Date: 2017-11-13 Branches: 50 105 47.6 %

Line Branch Exec Source
1
/* $OpenBSD: main.c,v 1.29 2017/05/25 20:11:03 tedu 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
{
112
18
	if (action_file)
113
9
		unlink(action_file_name);
114
9
	if (text_file)
115
9
		unlink(text_file_name);
116
9
	if (union_file)
117
4
		unlink(union_file_name);
118
9
	if (sigdie)
119
		_exit(k);
120
	exit(k);
121
}
122
123
124
void
125
onintr(__unused int signo)
126
{
127
	sigdie = 1;
128
	done(1);
129
}
130
131
132
void
133
set_signals(void)
134
{
135
#ifdef SIGINT
136
18
	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
137
9
		signal(SIGINT, onintr);
138
#endif
139
#ifdef SIGTERM
140
9
	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
141
9
		signal(SIGTERM, onintr);
142
#endif
143
#ifdef SIGHUP
144
9
	if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
145
9
		signal(SIGHUP, onintr);
146
#endif
147
9
}
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
{
161
	int ch;
162
163
65
	while ((ch = getopt(argc, argv, "b:dlo:p:rtv")) != -1) {
164


19
		switch (ch) {
165
		case 'b':
166
2
			file_prefix = optarg;
167
2
			break;
168
169
		case 'd':
170
6
			dflag = 1;
171
6
			break;
172
173
		case 'l':
174
			lflag = 1;
175
			break;
176
177
		case 'o':
178
7
			output_file_name = optarg;
179
7
			explicit_file_name = 1;
180
7
			break;
181
182
		case 'p':
183
4
			symbol_prefix = optarg;
184
4
			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
9
	argc -= optind;
203
9
	argv += optind;
204
205
9
	if (argc != 1)
206
		usage();
207
9
	if (strcmp(*argv, "-") == 0)
208
		input_file = stdin;
209
	else
210
9
		input_file_name = *argv;
211
9
}
212
213
214
void *
215
allocate(size_t n)
216
{
217
	void *v;
218
219
	v = NULL;
220
67966
	if (n) {
221
33983
		v = calloc(1, n);
222
33983
		if (!v)
223
			no_space();
224
	}
225
33983
	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
{
234
	size_t len;
235
	char *tmpdir;
236
237
	tmpdir = _PATH_TMP;
238
239
18
	len = strlen(tmpdir);
240
9
	if (tmpdir[len - 1] == '/')
241
9
		len--;
242
243

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

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

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

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

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