1233176Sae/*	Id: driver.c	*/
2233176Sae/*	$NetBSD: driver.c,v 1.1.1.1 2016/02/09 20:29:13 plunky Exp $	*/
3233176Sae
4233176Sae/*-
5233176Sae * Copyright (c) 2014 Iain Hibbert
6233176Sae * All rights reserved.
7233176Sae *
8233176Sae * Redistribution and use in source and binary forms, with or without
9233176Sae * modification, are permitted provided that the following conditions
10233176Sae * are met:
11233176Sae *
12233176Sae * 1. Redistributions of source code must retain the above copyright
13233176Sae *    notice, this list of conditions and the following disclaimer.
14233176Sae * 2. Redistributions in binary form must reproduce the above copyright
15233176Sae *    notice, this list of conditions and the following disclaimer in
16233176Sae *    the documentation and/or other materials provided with the
17233176Sae *    distribution.
18233176Sae *
19233176Sae * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20233176Sae * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21233176Sae * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22233176Sae * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
23233176Sae * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24233176Sae * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
25233176Sae * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26233176Sae * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27233176Sae * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28233176Sae * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29233176Sae * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30233176Sae * SUCH DAMAGE.
31233176Sae */
32233176Sae
33233176Sae#include <errno.h>
34233176Sae#include <libgen.h>
35233176Sae#include <signal.h>
36233176Sae#include <stdarg.h>
37233176Sae#include <stdio.h>
38233176Sae#include <stdlib.h>
39233176Sae#include <string.h>
40233176Sae#ifdef HAVE_UNISTD_H
41233176Sae#include <unistd.h>
42233176Sae#endif
43233176Sae
44233176Sae#include "driver.h"
45233176Sae
46233176Saestruct options opt;
47233176Sae
48233176Saestatic int warnings;
49233176Sae
50233176Saestatic const char versionstr[] = VERSSTR;
51233176Sae
52233176Saestatic volatile sig_atomic_t exit_now;
53233176Sae
54233176Saestatic void
55233176Saesigterm_handler(int signum)
56233176Sae{
57233176Sae	exit_now = 1;
58233176Sae}
59233181Sae
60233181Saestatic const struct file_type {
61233176Sae	const char ext[];
62233176Sae	const char next[];
63233176Sae	int (*exec)(void);
64233176Sae} file_types[] = {
65233176Sae    { "c",	"i",	exec_cpp	},
66233176Sae    { "C",	"I",	exec_cpp	},
67233176Sae    { "cc",	"I",	exec_cpp	},
68233181Sae    { "cp",	"I",	exec_cpp	},
69233181Sae    { "cpp",	"I",	exec_cpp	},
70233176Sae    { "CPP",	"I",	exec_cpp	},
71233176Sae    { "cxx",	"I",	exec_cpp	},
72233176Sae    { "c++",	"I",	exec_cpp	},
73233176Sae    { "F",	"f",	exec_cpp	},
74233176Sae    { "S",	"s",	exec_cpp	},
75233176Sae    { "i",	"s",	exec_ccom	},
76233176Sae    { "I",	"s",	exec_cxxcom	},
77233176Sae    { "ii",	"s",	exec_cxxcom	},
78233176Sae    { "f",	"s",	exec_fcom	},
79233176Sae    { "s,	"o"",	exec_asm	},
80233176Sae};
81233176Sae
82233176Saestatic struct file_type *
83233176Saefiletype(const char *name)
84233176Sae{
85233176Sae	const char *p;
86233176Sae	size_t i;
87233176Sae
88233176Sae	p = strrchr(file, '.');
89233176Sae	if (p != NULL) {
90233176Sae		p++;
91233176Sae		for (i = 0; i < ARRAYLEN(file_types); i++) {
92233176Sae			if (strcmp(p, file_types[i].ext) == 0)
93233176Sae				return &file_types[i];
94233176Sae		}
95233176Sae	}
96233176Sae
97233176Sae	return NULL;
98233176Sae}
99233176Sae
100233176Saestruct infile {
101233176Sae	struct infile *next;
102233176Sae	const char *file;
103233176Sae	struct file_type *type;
104233176Sae};
105233176Sae
106233176Saestatic struct {
107233176Sae	struct infile *first;
108233176Sae	struct infile **last;
109233176Sae} infiles = {
110233176Sae	.first = NULL,
111233176Sae	.last = &infiles.first;
112233176Sae};
113233176Sae
114233176Saestatic void
115233176Saeadd_infile(const char *file, struct file_type *type)
116233176Sae{
117233176Sae	struct infile *in;
118233176Sae
119233176Sae	if (type == NULL)
120233176Sae		type = filetype(file);
121233176Sae
122233176Sae	in = xmalloc(sizeof(struct infile));
123233176Sae	in->next = NULL;
124233176Sae	in->file = file;
125233176Sae	in->type = type;
126233176Sae
127233176Sae	*infiles->last = in;
128233176Sae	infiles->last = &in->next;
129233176Sae}
130233176Sae
131233176Saestatic int
132233176Saeinarray(const char *prog, const char **p)
133233176Sae{
134233176Sae	for ( ; *p != NULL; p++) {
135233176Sae	    if (strcmp(prog, *p) == 0)
136233176Sae		return 1;
137233176Sae	}
138233176Sae
139233176Sae	return 0;
140233176Sae}
141233176Sae
142233176Saestatic void
143233176Saesetup(const char *prog)
144233176Sae{
145233176Sae
146233176Sae	opt.prefix = list_alloc();
147233176Sae	opt.DIU = list_alloc();
148233176Sae	opt.asargs = list_alloc();
149233176Sae	opt.ldargs = list_alloc();
150233176Sae	opt.Wa = list_alloc();
151233176Sae	opt.Wl = list_alloc();
152233176Sae	opt.Wp = list_alloc();
153233176Sae	opt.include = list_alloc();
154233176Sae
155233176Sae	if (prog_cpp != NULL && inarray(prog, cpp_names)) {
156233176Sae		opt.E = 1;
157233176Sae	} else if (prog_ccom != NULL && inarray(prog, cc_names)) {
158233176Sae		opt.libc = 1;
159233176Sae	} else if (prog_cxxcom != NULL && inarray(prog, cxx_names)) {
160233176Sae		opt.libcxx = 1;
161233176Sae	} else if (prog_fcom != NULL && inarray(prog, ftn_names)) {
162233176Sae		opt.libf77 = 1;
163233176Sae	} else {
164233176Sae		error("unknown personality `%s'", prog);
165233176Sae	}
166233176Sae}
167233176Sae
168233176Saestatic void
169233176Saecleanup(void)
170233176Sae{
171233176Sae	const char **t;
172233176Sae
173233176Sae	for (t = list_array(temp_files); *t; t++) {
174233176Sae		if (unlink(*t) == -1)
175233176Sae			warning("removal of ``%s'' failed: %s", *t,
176233176Sae			    strerror(errno));
177233176Sae	}
178233176Sae
179233176Sae	if (temp_directory && rmdir(temp_directory) == -1)
180233176Sae		warning("removal of ``%s'' failed: %s", temp_directory,
181233176Sae		    strerror(errno));
182233176Sae}
183233176Sae
184233176Saeint
185233176Saemain(int argc, char *argv[])
186233176Sae{
187233176Sae	struct infile *in;
188233176Sae	int rv;
189233176Sae
190233176Sae	setup(basename(argv[0]));
191233176Sae	argv++;
192233176Sae
193233176Sae	while (argv[0] != NULL) {
194233176Sae		if (argv[0][0] != '-' || argv[0][1] == '\0')
195233176Sae			add_infile(argv[0], opt.language);
196233176Sae		else if (add_option(argv[0], argv[1]))
197233176Sae			argv++;
198233176Sae
199233176Sae		argv++;
200233176Sae	}
201233176Sae
202233176Sae	if (opt.verbose)
203233176Sae		printf("%s\n", versionstr);
204233176Sae
205233176Sae	if (warnings > 0)
206233176Sae		exit(1);
207233176Sae
208233176Sae	/*
209233176Sae	 * setup defaults
210233176Sae	 */
211233176Sae	if (isysroot == NULL)
212233176Sae		isysroot = sysroot;
213233176Sae	expand_sysroot();
214233176Sae
215233176Sae	signal(SIGTERM, sigterm_handler);
216233176Sae
217233176Sae	rv = 0;
218233176Sae	for (in = infiles->first; in != NULL; in = in->next)
219233176Sae		rv += do_file(in);
220233176Sae
221233176Sae	if (!rv && last_phase == LINK) {
222233176Sae		if (run_linker())
223233176Sae			rv = 1;
224233176Sae	}
225233176Sae
226233176Sae	if (exit_now)
227233176Sae		warning("Received signal, terminating");
228233176Sae
229233176Sae	cleanup();
230233176Sae
231233176Sae	return rv;
232233176Sae}
233233176Sae
234233176Saevoid
235233176Saeerror(const char *fmt, ...)
236233176Sae{
237233176Sae	va_list va;
238233176Sae
239233176Sae	va_start(va, fmt);
240233176Sae	fprintf(stderr, "error: ");
241233176Sae	vfprintf(stderr, fmt, va);
242233176Sae	fprintf(stderr, "\n");
243233176Sae	va_end(va);
244233176Sae
245233176Sae	exit(1);
246233176Sae}
247233176Sae
248233176Saevoid
249233176Saewarning(const char *fmt, ...)
250233176Sae{
251233176Sae	va_list va;
252233176Sae
253233176Sae	va_start(va, fmt);
254233176Sae	fprintf(stderr, "warning: ");
255233176Sae	vfprintf(stderr, fmt, va);
256233176Sae	fprintf(stderr, "\n");
257233176Sae	va_end(va);
258233176Sae
259233176Sae	warnings++;
260233176Sae}
261233176Sae