1/* Id: driver.c,v 1.7 2011/06/03 15:34:01 plunky Exp */ 2/* $NetBSD: driver.c,v 1.1.1.1 2011/09/01 12:47:04 plunky Exp $ */ 3 4/*- 5 * Copyright (c) 2011 Joerg Sonnenberger <joerg@NetBSD.org>. 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 <sys/wait.h> 34#include <assert.h> 35#include <errno.h> 36#include <signal.h> 37#include <stdarg.h> 38#include <stdlib.h> 39#include <stdio.h> 40#include <string.h> 41#include <unistd.h> 42 43#include "driver.h" 44#include "xalloc.h" 45 46#include "config.h" 47 48static volatile sig_atomic_t exit_now; 49static volatile sig_atomic_t child; 50 51static void 52sigterm_handler(int signum) 53{ 54 exit_now = 1; 55 if (child) 56 kill(child, SIGTERM); 57} 58 59static const char versionstr[] = VERSSTR; 60 61enum phases { DEFAULT, PREPROCESS, COMPILE, ASSEMBLE, LINK } last_phase = 62 DEFAULT; 63 64const char *isysroot = NULL; 65const char *sysroot = ""; 66const char *preprocessor; 67const char *compiler; 68const char *assembler; 69const char *linker; 70 71struct strlist crtdirs; 72static struct strlist user_sysincdirs; 73struct strlist sysincdirs; 74struct strlist includes; 75struct strlist incdirs; 76struct strlist libdirs; 77struct strlist progdirs; 78struct strlist preprocessor_flags; 79struct strlist compiler_flags; 80struct strlist assembler_flags; 81struct strlist early_linker_flags; 82struct strlist middle_linker_flags; 83struct strlist late_linker_flags; 84struct strlist stdlib_flags; 85struct strlist early_program_csu_files; 86struct strlist late_program_csu_files; 87struct strlist early_dso_csu_files; 88struct strlist late_dso_csu_files; 89struct strlist temp_outputs; 90 91const char *final_output; 92static char *temp_directory; 93static struct strlist inputs; 94 95int pic_mode; /* 0: no PIC, 1: -fpic, 2: -fPIC */ 96int save_temps; 97int debug_mode; 98int profile_mode; 99int nostdinc; 100int nostdlib; 101int nostartfiles; 102int static_mode; 103int shared_mode; 104int use_pthread; 105int verbose_mode; 106 107void 108error(const char *fmt, ...) 109{ 110 va_list arg; 111 va_start(arg, fmt); 112 vfprintf(stderr, fmt, arg); 113 putc('\n', stderr); 114 va_end(arg); 115 exit(1); 116} 117 118static void 119warning(const char *fmt, ...) 120{ 121 va_list arg; 122 va_start(arg, fmt); 123 vfprintf(stderr, fmt, arg); 124 putc('\n', stderr); 125 va_end(arg); 126} 127 128static void 129set_last_phase(enum phases phase) 130{ 131 assert(phase != DEFAULT); 132 if (last_phase != DEFAULT && phase != last_phase) 133 error("conflicting compiler options specified"); 134 last_phase = phase; 135} 136 137static void 138expand_sysroot(void) 139{ 140 struct string *s; 141 struct strlist *lists[] = { &crtdirs, &sysincdirs, &incdirs, 142 &user_sysincdirs, &libdirs, &progdirs, NULL }; 143 const char *sysroots[] = { sysroot, isysroot, isysroot, isysroot, 144 sysroot, sysroot, NULL }; 145 size_t i, sysroot_len, value_len; 146 char *path; 147 148 assert(sizeof(lists) / sizeof(lists[0]) == 149 sizeof(sysroots) / sizeof(sysroots[0])); 150 151 for (i = 0; lists[i] != NULL; ++i) { 152 STRLIST_FOREACH(s, lists[i]) { 153 if (s->value[0] != '=') 154 continue; 155 sysroot_len = strlen(sysroots[i]); 156 /* Skipped '=' compensates additional space for '\0' */ 157 value_len = strlen(s->value); 158 path = xmalloc(sysroot_len + value_len); 159 memcpy(path, sysroots[i], sysroot_len); 160 memcpy(path + sysroot_len, s->value + 1, value_len); 161 free(s->value); 162 s->value = path; 163 } 164 } 165} 166 167static void 168missing_argument(const char *argp) 169{ 170 error("Option `%s' required an argument", argp); 171} 172 173static void 174split_and_append(struct strlist *l, char *arg) 175{ 176 char *next; 177 178 for (; arg != NULL; arg = NULL) { 179 next = strchr(arg, ','); 180 if (next != NULL) 181 *next++ = '\0'; 182 strlist_append(l, arg); 183 } 184} 185 186static int 187strlist_exec(struct strlist *l) 188{ 189 char **argv; 190 size_t argc; 191 int result; 192 193 strlist_make_array(l, &argv, &argc); 194 if (verbose_mode) { 195 printf("Calling "); 196 strlist_print(l, stdout); 197 printf("\n"); 198 } 199 200 if (exit_now) 201 return 1; 202 203 switch ((child = fork())) { 204 case 0: 205 execvp(argv[0], argv); 206 result = write(STDERR_FILENO, "Exec of ", 8); 207 result = write(STDERR_FILENO, argv[0], strlen(argv[0])); 208 result = write(STDERR_FILENO, "failed\n", 7); 209 (void)result; 210 _exit(127); 211 case -1: 212 error("fork failed"); 213 default: 214 while (waitpid(child, &result, 0) == -1 && errno == EINTR) 215 /* nothing */(void)0; 216 result = WEXITSTATUS(result); 217 if (result) 218 error("%s terminated with status %d", argv[0], result); 219 while (argc-- > 0) 220 free(argv[argc]); 221 free(argv); 222 break; 223 } 224 return exit_now; 225} 226 227static char * 228find_file(const char *file, struct strlist *path, int mode) 229{ 230 struct string *s; 231 char *f; 232 size_t lf, lp; 233 int need_sep; 234 235 lf = strlen(file); 236 STRLIST_FOREACH(s, path) { 237 lp = strlen(s->value); 238 need_sep = (lp && s->value[lp - 1] != '/') ? 1 : 0; 239 f = xmalloc(lp + lf + need_sep + 1); 240 memcpy(f, s->value, lp); 241 if (need_sep) 242 f[lp] = '/'; 243 memcpy(f + lp + need_sep, file, lf + 1); 244 if (access(f, mode) == 0) 245 return f; 246 free(f); 247 } 248 return xstrdup(file); 249} 250 251static char * 252output_name(const char *file, const char *new_suffix, int counter, int last) 253{ 254 const char *old_suffix; 255 char *name; 256 size_t lf, ls, len; 257 int counter_len; 258 259 if (last && final_output) 260 return xstrdup(final_output); 261 262 old_suffix = strrchr(file, '.'); 263 if (old_suffix != NULL && strchr(old_suffix, '/') != NULL) 264 old_suffix = NULL; 265 if (old_suffix == NULL) 266 old_suffix = file + strlen(file); 267 268 ls = strlen(new_suffix); 269 if (save_temps || last) { 270 lf = old_suffix - file; 271 name = xmalloc(lf + ls + 1); 272 memcpy(name, file, lf); 273 memcpy(name + lf, new_suffix, ls + 1); 274 return name; 275 } 276 if (temp_directory == NULL) { 277 const char *template; 278 char *path; 279 size_t template_len; 280 int need_sep; 281 282 template = getenv("TMPDIR"); 283 if (template == NULL) 284 template = "/tmp"; 285 template_len = strlen(template); 286 if (template_len && template[template_len - 1] == '/') 287 need_sep = 0; 288 else 289 need_sep = 1; 290 path = xmalloc(template_len + need_sep + 6 + 1); 291 memcpy(path, template, template_len); 292 if (need_sep) 293 path[template_len] = '/'; 294 memcpy(path + template_len + need_sep, "pcc-XXXXXX", 11); 295 if (mkdtemp(path) == NULL) 296 error("mkdtemp failed: %s", strerror(errno)); 297 temp_directory = path; 298 } 299 lf = strlen(temp_directory); 300 counter_len = snprintf(NULL, 0, "%d", counter); 301 if (counter_len < 1) 302 error("snprintf failure"); 303 len = lf + 1 + (size_t)counter_len + ls + 1; 304 name = xmalloc(len); 305 snprintf(name, len, "%s/%d%s", temp_directory, counter, new_suffix); 306 strlist_append(&temp_outputs, name); 307 return name; 308} 309 310static int 311preprocess_input(const char *file, char *input, char **output, 312 const char *suffix, int counter) 313{ 314 struct strlist args; 315 struct string *s; 316 char *out; 317 int retval; 318 319 strlist_init(&args); 320 strlist_append_list(&args, &preprocessor_flags); 321 STRLIST_FOREACH(s, &includes) { 322 strlist_append(&args, "-i"); 323 strlist_append(&args, s->value); 324 } 325 STRLIST_FOREACH(s, &incdirs) { 326 strlist_append(&args, "-I"); 327 strlist_append(&args, s->value); 328 } 329 STRLIST_FOREACH(s, &user_sysincdirs) { 330 strlist_append(&args, "-S"); 331 strlist_append(&args, s->value); 332 } 333 if (!nostdinc) { 334 STRLIST_FOREACH(s, &sysincdirs) { 335 strlist_append(&args, "-S"); 336 strlist_append(&args, s->value); 337 } 338 } 339 strlist_append(&args, input); 340 if (last_phase == PREPROCESS && final_output == NULL) 341 out = xstrdup("-"); 342 else 343 out = output_name(file, suffix, counter, 344 last_phase == PREPROCESS); 345 if (strcmp(out, "-")) 346 strlist_append(&args, out); 347 strlist_prepend(&args, find_file(preprocessor, &progdirs, X_OK)); 348 *output = out; 349 retval = strlist_exec(&args); 350 strlist_free(&args); 351 return retval; 352} 353 354static int 355compile_input(const char *file, char *input, char **output, 356 const char *suffix, int counter) 357{ 358 struct strlist args; 359 char *out; 360 int retval; 361 362 strlist_init(&args); 363 strlist_append_list(&args, &compiler_flags); 364 if (debug_mode) 365 strlist_append(&args, "-g"); 366 if (pic_mode) 367 strlist_append(&args, "-k"); 368 if (profile_mode) 369 warning("-pg is currently ignored"); 370 strlist_append(&args, input); 371 out = output_name(file, suffix, counter, last_phase == ASSEMBLE); 372 strlist_append(&args, out); 373 strlist_prepend(&args, find_file(compiler, &progdirs, X_OK)); 374 *output = out; 375 retval = strlist_exec(&args); 376 strlist_free(&args); 377 return retval; 378} 379 380static int 381assemble_input(const char *file, char *input, char **output, 382 const char *suffix, int counter) 383{ 384 struct strlist args; 385 char *out; 386 int retval; 387 388 strlist_init(&args); 389 strlist_append_list(&args, &assembler_flags); 390 strlist_append(&args, input); 391 out = output_name(file, ".o", counter, last_phase == COMPILE); 392 strlist_append(&args, "-o"); 393 strlist_append(&args, out); 394 strlist_prepend(&args, find_file(assembler, &progdirs, X_OK)); 395 *output = out; 396 retval = strlist_exec(&args); 397 strlist_free(&args); 398 return retval; 399} 400 401static int 402handle_input(const char *file) 403{ 404 static int counter; 405 const char *suffix; 406 char *src; 407 int handled, retval; 408 409 ++counter; 410 411 if (strcmp(file, "-") == 0) { 412 /* XXX see -x option */ 413 suffix = ".c"; 414 } else { 415 suffix = strrchr(file, '.'); 416 if (suffix != NULL && strchr(suffix, '/') != NULL) 417 suffix = NULL; 418 if (suffix == NULL) 419 suffix = ""; 420 } 421 422 src = xstrdup(file); 423 if (strcmp(suffix, ".c") == 0) { 424 suffix = ".i"; 425 retval = preprocess_input(file, src, &src, suffix, counter); 426 if (retval) 427 return retval; 428 handled = 1; 429 } else if (strcmp(suffix, ".S") == 0) { 430 suffix = ".s"; 431 retval = preprocess_input(file, src, &src, suffix, counter); 432 if (retval) 433 return retval; 434 handled = 1; 435 } 436 437 if (last_phase == PREPROCESS) 438 goto done; 439 440 if (strcmp(suffix, ".i") == 0) { 441 suffix = ".s"; 442 retval = compile_input(file, src, &src, suffix, counter); 443 if (retval) 444 return retval; 445 handled = 1; 446 } 447 if (last_phase == ASSEMBLE) 448 goto done; 449 450 if (strcmp(suffix, ".s") == 0) { 451 suffix = ".o"; 452 retval = assemble_input(file, src, &src, suffix, counter); 453 if (retval) 454 return retval; 455 handled = 1; 456 } 457 if (last_phase == COMPILE) 458 goto done; 459 if (strcmp(suffix, ".o") == 0) 460 handled = 1; 461 strlist_append(&middle_linker_flags, src); 462done: 463 if (handled) 464 return 0; 465 if (last_phase == LINK) 466 warning("unknown suffix %s, passing file down to linker", 467 suffix); 468 else 469 warning("unknown suffix %s, skipped", suffix); 470 free(src); 471 return 0; 472} 473 474static int 475run_linker(void) 476{ 477 struct strlist linker_flags; 478 struct strlist *early_csu, *late_csu; 479 struct string *s; 480 int retval; 481 482 if (final_output) { 483 strlist_prepend(&early_linker_flags, final_output); 484 strlist_prepend(&early_linker_flags, "-o"); 485 } 486 if (!nostdlib) 487 strlist_append_list(&late_linker_flags, &stdlib_flags); 488 if (!nostartfiles) { 489 if (shared_mode) { 490 early_csu = &early_dso_csu_files; 491 late_csu = &late_dso_csu_files; 492 } else { 493 early_csu = &early_program_csu_files; 494 late_csu = &late_program_csu_files; 495 } 496 STRLIST_FOREACH(s, early_csu) 497 strlist_append_nocopy(&middle_linker_flags, 498 find_file(s->value, &crtdirs, R_OK)); 499 STRLIST_FOREACH(s, late_csu) 500 strlist_append_nocopy(&late_linker_flags, 501 find_file(s->value, &crtdirs, R_OK)); 502 } 503 strlist_init(&linker_flags); 504 strlist_append_list(&linker_flags, &early_linker_flags); 505 strlist_append_list(&linker_flags, &middle_linker_flags); 506 strlist_append_list(&linker_flags, &late_linker_flags); 507 strlist_prepend(&linker_flags, find_file(linker, &progdirs, X_OK)); 508 509 retval = strlist_exec(&linker_flags); 510 511 strlist_free(&linker_flags); 512 return retval; 513} 514 515static void 516cleanup(void) 517{ 518 struct string *file; 519 520 STRLIST_FOREACH(file, &temp_outputs) { 521 if (unlink(file->value) == -1) 522 warning("removal of ``%s'' failed: %s", file->value, 523 strerror(errno)); 524 } 525 if (temp_directory && rmdir(temp_directory) == -1) 526 warning("removal of ``%s'' failed: %s", temp_directory, 527 strerror(errno)); 528} 529 530int 531main(int argc, char **argv) 532{ 533 struct string *input; 534 char *argp; 535 int retval; 536 537 strlist_init(&crtdirs); 538 strlist_init(&user_sysincdirs); 539 strlist_init(&sysincdirs); 540 strlist_init(&incdirs); 541 strlist_init(&includes); 542 strlist_init(&libdirs); 543 strlist_init(&progdirs); 544 strlist_init(&inputs); 545 strlist_init(&preprocessor_flags); 546 strlist_init(&compiler_flags); 547 strlist_init(&assembler_flags); 548 strlist_init(&early_linker_flags); 549 strlist_init(&middle_linker_flags); 550 strlist_init(&late_linker_flags); 551 strlist_init(&stdlib_flags); 552 strlist_init(&early_program_csu_files); 553 strlist_init(&late_program_csu_files); 554 strlist_init(&early_dso_csu_files); 555 strlist_init(&late_dso_csu_files); 556 strlist_init(&temp_outputs); 557 558 init_platform_specific(TARGOS, TARGMACH); 559 560 while (--argc) { 561 ++argv; 562 argp = *argv; 563 564 if (*argp != '-' || strcmp(argp, "-") == 0) { 565 strlist_append(&inputs, argp); 566 continue; 567 } 568 switch (argp[1]) { 569 case '-': 570 if (strcmp(argp, "--param") == 0) { 571 if (argc == 0) 572 missing_argument(argp); 573 --argc; 574 ++argv; 575 /* Unused */ 576 continue; 577 } 578 if (strncmp(argp, "--sysroot=", 10) == 0) { 579 sysroot = argp + 10; 580 continue; 581 } 582 if (strcmp(argp, "--version") == 0) { 583 printf("%s\n", versionstr); 584 exit(0); 585 } 586 break; 587 case 'B': 588 strlist_append(&crtdirs, argp); 589 strlist_append(&libdirs, argp); 590 strlist_append(&progdirs, argp); 591 continue; 592 case 'C': 593 if (argp[2] == '\0') { 594 strlist_append(&preprocessor_flags, argp); 595 continue; 596 } 597 break; 598 case 'c': 599 if (argp[2] == '\0') { 600 set_last_phase(COMPILE); 601 continue; 602 } 603 break; 604 case 'D': 605 strlist_append(&preprocessor_flags, argp); 606 if (argp[2] == '\0') { 607 if (argc == 0) 608 missing_argument(argp); 609 --argc; 610 ++argv; 611 strlist_append(&preprocessor_flags, argp); 612 } 613 continue; 614 case 'E': 615 if (argp[2] == '\0') { 616 set_last_phase(PREPROCESS); 617 continue; 618 } 619 break; 620 case 'f': 621 if (strcmp(argp, "-fpic") == 0) { 622 pic_mode = 1; 623 continue; 624 } 625 if (strcmp(argp, "-fPIC") == 0) { 626 pic_mode = 2; 627 continue; 628 } 629 /* XXX GCC options */ 630 break; 631 case 'g': 632 if (argp[2] == '\0') { 633 debug_mode = 1; 634 continue; 635 } 636 /* XXX allow variants like -g1? */ 637 break; 638 case 'I': 639 if (argp[2] == '\0') { 640 if (argc == 0) 641 missing_argument(argp); 642 --argc; 643 ++argv; 644 strlist_append(&incdirs, argp); 645 continue; 646 } 647 strlist_append(&incdirs, argp + 2); 648 continue; 649 case 'i': 650 if (strcmp(argp, "-isystem") == 0) { 651 if (argc == 0) 652 missing_argument(argp); 653 --argc; 654 ++argv; 655 strlist_append(&user_sysincdirs, argp); 656 continue; 657 } 658 if (strcmp(argp, "-include") == 0) { 659 if (argc == 0) 660 missing_argument(argp); 661 --argc; 662 ++argv; 663 strlist_append(&includes, argp); 664 continue; 665 } 666 if (strcmp(argp, "-isysroot") == 0) { 667 if (argc == 0) 668 missing_argument(argp); 669 --argc; 670 ++argv; 671 isysroot = argp; 672 continue; 673 } 674 /* XXX -idirafter */ 675 /* XXX -iquote */ 676 break; 677 case 'k': 678 if (argp[2] == '\0') { 679 pic_mode = 1; 680 continue; 681 } 682 break; 683 case 'M': 684 if (argp[2] == '\0') { 685 strlist_append(&preprocessor_flags, argp); 686 continue; 687 } 688 break; 689 case 'm': 690 /* XXX implement me */ 691 break; 692 case 'n': 693 if (strcmp(argp, "-nostdinc") == 0) { 694 nostdinc = 1; 695 continue; 696 } 697 if (strcmp(argp, "-nostdinc++") == 0) 698 continue; 699 if (strcmp(argp, "-nostdlib") == 0) { 700 nostdlib = 1; 701 nostartfiles = 1; 702 continue; 703 } 704 if (strcmp(argp, "-nostartfiles") == 0) { 705 nostartfiles = 1; 706 continue; 707 } 708 break; 709 case 'O': 710 if (argp[2] != '\0' && argp[3] != '\0') 711 break; 712 switch(argp[2]) { 713 case '2': 714 case '1': case '\0': 715 strlist_append(&compiler_flags, "-xtemps"); 716 strlist_append(&compiler_flags, "-xdeljumps"); 717 strlist_append(&compiler_flags, "-xinline"); 718 case '0': 719 continue; 720 } 721 break; 722 case 'o': 723 if (argp[2] == '\0') { 724 if (argc == 0) 725 missing_argument(argp); 726 --argc; 727 ++argv; 728 if (final_output) 729 error("Only one `-o' option allowed"); 730 final_output = *argv; 731 continue; 732 } 733 break; 734 case 'p': 735 if (argp[2] == '\0' || strcmp(argp, "-pg") == 0) { 736 profile_mode = 1; 737 continue; 738 } 739 if (strcmp(argp, "-pedantic") == 0) 740 continue; 741 if (strcmp(argp, "-pipe") == 0) 742 continue; /* XXX implement me */ 743 if (strcmp(argp, "-pthread") == 0) { 744 use_pthread = 1; 745 continue; 746 } 747 /* XXX -print-prog-name=XXX */ 748 /* XXX -print-multi-os-directory */ 749 break; 750 case 'r': 751 if (argp[2] == '\0') { 752 strlist_append(&middle_linker_flags, argp); 753 continue; 754 } 755 break; 756 case 'S': 757 if (argp[2] == '\0') { 758 set_last_phase(ASSEMBLE); 759 continue; 760 } 761 break; 762 case 's': 763 if (strcmp(argp, "-save-temps") == 0) { 764 save_temps = 1; 765 continue; 766 } 767 if (strcmp(argp, "-shared") == 0) { 768 shared_mode = 1; 769 continue; 770 } 771 if (strcmp(argp, "-static") == 0) { 772 static_mode = 1; 773 continue; 774 } 775 if (strncmp(argp, "-std=", 5) == 0) 776 continue; /* XXX sanitize me */ 777 break; 778 case 't': 779 if (argp[2] == '\0') { 780 strlist_append(&preprocessor_flags, argp); 781 continue; 782 } 783 case 'U': 784 strlist_append(&preprocessor_flags, argp); 785 if (argp[2] == '\0') { 786 if (argc == 0) 787 missing_argument(argp); 788 --argc; 789 ++argv; 790 strlist_append(&preprocessor_flags, argp); 791 } 792 continue; 793 case 'v': 794 if (argp[2] == '\0') { 795 verbose_mode = 1; 796 continue; 797 } 798 break; 799 case 'W': 800 if (strncmp(argp, "-Wa,", 4) == 0) { 801 split_and_append(&assembler_flags, argp + 4); 802 continue; 803 } 804 if (strncmp(argp, "-Wl,", 4) == 0) { 805 split_and_append(&middle_linker_flags, argp + 4); 806 continue; 807 } 808 if (strncmp(argp, "-Wp,", 4) == 0) { 809 split_and_append(&preprocessor_flags, argp + 4); 810 continue; 811 } 812 /* XXX warning flags */ 813 break; 814 case 'x': 815 /* XXX -x c */ 816 /* XXX -c assembler-with-cpp */ 817 break; 818 } 819 error("unknown flag `%s'", argp); 820 } 821 822 if (last_phase == DEFAULT) 823 last_phase = LINK; 824 825 if (verbose_mode) 826 printf("%s\n", versionstr); 827 828 if (isysroot == NULL) 829 isysroot = sysroot; 830 expand_sysroot(); 831 832 if (last_phase != LINK && final_output && !STRLIST_EMPTY(&inputs) && 833 !STRLIST_NEXT(STRLIST_FIRST(&inputs))) 834 error("-o specified with more than one input"); 835 836 if (last_phase == PREPROCESS && final_output == NULL) 837 final_output = "-"; 838 839 if (STRLIST_EMPTY(&inputs)) 840 error("No input specificed"); 841 842 retval = 0; 843 844 signal(SIGTERM, sigterm_handler); 845 846 STRLIST_FOREACH(input, &inputs) { 847 if (handle_input(input->value)) 848 retval = 1; 849 } 850 if (!retval && last_phase == LINK) { 851 if (run_linker()) 852 retval = 1; 853 } 854 855 if (exit_now) 856 warning("Received signal, terminating"); 857 858 cleanup(); 859 860 strlist_free(&crtdirs); 861 strlist_free(&user_sysincdirs); 862 strlist_free(&sysincdirs); 863 strlist_free(&incdirs); 864 strlist_free(&includes); 865 strlist_free(&libdirs); 866 strlist_free(&progdirs); 867 strlist_free(&inputs); 868 strlist_free(&preprocessor_flags); 869 strlist_free(&compiler_flags); 870 strlist_free(&assembler_flags); 871 strlist_free(&early_linker_flags); 872 strlist_free(&middle_linker_flags); 873 strlist_free(&late_linker_flags); 874 strlist_free(&stdlib_flags); 875 strlist_free(&early_program_csu_files); 876 strlist_free(&late_program_csu_files); 877 strlist_free(&early_dso_csu_files); 878 strlist_free(&late_dso_csu_files); 879 strlist_free(&temp_outputs); 880 881 return retval; 882} 883