1/* Id: driver.c */ 2/* $NetBSD: driver.c,v 1.1.1.1 2016/02/09 20:29:13 plunky Exp $ */ 3 4/*- 5 * Copyright (c) 2014 Iain Hibbert 6 * All rights reserved. 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 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33#include <errno.h> 34#include <libgen.h> 35#include <signal.h> 36#include <stdarg.h> 37#include <stdio.h> 38#include <stdlib.h> 39#include <string.h> 40#ifdef HAVE_UNISTD_H 41#include <unistd.h> 42#endif 43 44#include "driver.h" 45 46struct options opt; 47 48static int warnings; 49 50static const char versionstr[] = VERSSTR; 51 52static volatile sig_atomic_t exit_now; 53 54static void 55sigterm_handler(int signum) 56{ 57 exit_now = 1; 58} 59 60static const struct file_type { 61 const char ext[]; 62 const char next[]; 63 int (*exec)(void); 64} file_types[] = { 65 { "c", "i", exec_cpp }, 66 { "C", "I", exec_cpp }, 67 { "cc", "I", exec_cpp }, 68 { "cp", "I", exec_cpp }, 69 { "cpp", "I", exec_cpp }, 70 { "CPP", "I", exec_cpp }, 71 { "cxx", "I", exec_cpp }, 72 { "c++", "I", exec_cpp }, 73 { "F", "f", exec_cpp }, 74 { "S", "s", exec_cpp }, 75 { "i", "s", exec_ccom }, 76 { "I", "s", exec_cxxcom }, 77 { "ii", "s", exec_cxxcom }, 78 { "f", "s", exec_fcom }, 79 { "s, "o"", exec_asm }, 80}; 81 82static struct file_type * 83filetype(const char *name) 84{ 85 const char *p; 86 size_t i; 87 88 p = strrchr(file, '.'); 89 if (p != NULL) { 90 p++; 91 for (i = 0; i < ARRAYLEN(file_types); i++) { 92 if (strcmp(p, file_types[i].ext) == 0) 93 return &file_types[i]; 94 } 95 } 96 97 return NULL; 98} 99 100struct infile { 101 struct infile *next; 102 const char *file; 103 struct file_type *type; 104}; 105 106static struct { 107 struct infile *first; 108 struct infile **last; 109} infiles = { 110 .first = NULL, 111 .last = &infiles.first; 112}; 113 114static void 115add_infile(const char *file, struct file_type *type) 116{ 117 struct infile *in; 118 119 if (type == NULL) 120 type = filetype(file); 121 122 in = xmalloc(sizeof(struct infile)); 123 in->next = NULL; 124 in->file = file; 125 in->type = type; 126 127 *infiles->last = in; 128 infiles->last = &in->next; 129} 130 131static int 132inarray(const char *prog, const char **p) 133{ 134 for ( ; *p != NULL; p++) { 135 if (strcmp(prog, *p) == 0) 136 return 1; 137 } 138 139 return 0; 140} 141 142static void 143setup(const char *prog) 144{ 145 146 opt.prefix = list_alloc(); 147 opt.DIU = list_alloc(); 148 opt.asargs = list_alloc(); 149 opt.ldargs = list_alloc(); 150 opt.Wa = list_alloc(); 151 opt.Wl = list_alloc(); 152 opt.Wp = list_alloc(); 153 opt.include = list_alloc(); 154 155 if (prog_cpp != NULL && inarray(prog, cpp_names)) { 156 opt.E = 1; 157 } else if (prog_ccom != NULL && inarray(prog, cc_names)) { 158 opt.libc = 1; 159 } else if (prog_cxxcom != NULL && inarray(prog, cxx_names)) { 160 opt.libcxx = 1; 161 } else if (prog_fcom != NULL && inarray(prog, ftn_names)) { 162 opt.libf77 = 1; 163 } else { 164 error("unknown personality `%s'", prog); 165 } 166} 167 168static void 169cleanup(void) 170{ 171 const char **t; 172 173 for (t = list_array(temp_files); *t; t++) { 174 if (unlink(*t) == -1) 175 warning("removal of ``%s'' failed: %s", *t, 176 strerror(errno)); 177 } 178 179 if (temp_directory && rmdir(temp_directory) == -1) 180 warning("removal of ``%s'' failed: %s", temp_directory, 181 strerror(errno)); 182} 183 184int 185main(int argc, char *argv[]) 186{ 187 struct infile *in; 188 int rv; 189 190 setup(basename(argv[0])); 191 argv++; 192 193 while (argv[0] != NULL) { 194 if (argv[0][0] != '-' || argv[0][1] == '\0') 195 add_infile(argv[0], opt.language); 196 else if (add_option(argv[0], argv[1])) 197 argv++; 198 199 argv++; 200 } 201 202 if (opt.verbose) 203 printf("%s\n", versionstr); 204 205 if (warnings > 0) 206 exit(1); 207 208 /* 209 * setup defaults 210 */ 211 if (isysroot == NULL) 212 isysroot = sysroot; 213 expand_sysroot(); 214 215 signal(SIGTERM, sigterm_handler); 216 217 rv = 0; 218 for (in = infiles->first; in != NULL; in = in->next) 219 rv += do_file(in); 220 221 if (!rv && last_phase == LINK) { 222 if (run_linker()) 223 rv = 1; 224 } 225 226 if (exit_now) 227 warning("Received signal, terminating"); 228 229 cleanup(); 230 231 return rv; 232} 233 234void 235error(const char *fmt, ...) 236{ 237 va_list va; 238 239 va_start(va, fmt); 240 fprintf(stderr, "error: "); 241 vfprintf(stderr, fmt, va); 242 fprintf(stderr, "\n"); 243 va_end(va); 244 245 exit(1); 246} 247 248void 249warning(const char *fmt, ...) 250{ 251 va_list va; 252 253 va_start(va, fmt); 254 fprintf(stderr, "warning: "); 255 vfprintf(stderr, fmt, va); 256 fprintf(stderr, "\n"); 257 va_end(va); 258 259 warnings++; 260} 261