|
|
1.1 ! root 1: /* Compiler driver program that can handle many languages. ! 2: Copyright (C) 1987 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GNU CC. ! 5: ! 6: GNU CC is distributed in the hope that it will be useful, ! 7: but WITHOUT ANY WARRANTY. No author or distributor ! 8: accepts responsibility to anyone for the consequences of using it ! 9: or for whether it serves any particular purpose or works at all, ! 10: unless he says so in writing. Refer to the GNU CC General Public ! 11: License for full details. ! 12: ! 13: Everyone is granted permission to copy, modify and redistribute ! 14: GNU CC, but only under the conditions described in the ! 15: GNU CC General Public License. A copy of this license is ! 16: supposed to have been given to you along with GNU CC so you ! 17: can know your rights and responsibilities. It should be in a ! 18: file named COPYING. Among other things, the copyright notice ! 19: and this notice must be preserved on all copies. */ ! 20: ! 21: ! 22: /* This program is the user interface to the C compiler and possibly to ! 23: other compilers. It is used because compilation is a complicated procedure ! 24: which involves running several programs and passing temporary files between ! 25: them, forwarding the users switches to those programs selectively, ! 26: and deleting the temporary files at the end. ! 27: ! 28: CC recognizes how to compile each input file by suffixes in the file names. ! 29: Once it knows which kind of compilation to perform, the procedure for ! 30: compilation is specified by a string called a "spec". ! 31: ! 32: Specs are strings containing lines, each of which (if not blank) ! 33: is made up of a program name, and arguments separated by spaces. ! 34: The program name must be exact and start from root, since no path ! 35: is searched and it is unreliable to depend on the current working directory. ! 36: Redirection of input or output is not supported; the subprograms must ! 37: accept filenames saying what files to read and write. ! 38: ! 39: In addition, the specs can contain %-sequences to substitute variable text ! 40: or for conditional text. Here is a table of all defined %-sequences. ! 41: Note that spaces are not generated automatically around the results of ! 42: expanding these sequences; therefore, you can concatenate them together ! 43: or with constant text in a single argument. ! 44: ! 45: %% substitute one % into the program name or argument. ! 46: %i substitute the name of the input file being processed. ! 47: %b substitute the basename of the input file being processed. ! 48: This is the substring up to (and not including) the last period. ! 49: %g substitute the temporary-file-name-base. This is a string chosen ! 50: once per compilation. Different temporary file names are made by ! 51: concatenation of constant strings on the end, as in `%g.s'. ! 52: %g also has the same effect of %d. ! 53: %d marks the argument containing or following the %d as a ! 54: temporary file name, so that that file will be deleted if CC exits ! 55: successfully. Unlike %g, this contributes no text to the argument. ! 56: %w marks the argument containing or following the %w as the ! 57: "output file" of this compilation. This puts the argument ! 58: into the sequence of arguments that %o will substitute later. ! 59: %o substitutes the names of all the output files, with spaces ! 60: automatically placed around them. You should write spaces ! 61: around the %o as well or the results are undefined. ! 62: %o is for use in the specs for running the linker. ! 63: Input files whose names have no recognized suffix are not compiled ! 64: at all, but they are included among the output files, so they will ! 65: be linked. ! 66: %p substitutes the standard macro predefinitions for the ! 67: current target machine. Use this when running cpp. ! 68: %s current argument is the name of a library file of some sort. ! 69: Search for that file in a standard list of directories ! 70: and substitute the full pathname found. ! 71: %a process ASM_SPEC as a spec. ! 72: This allows config.h to specify part of the spec for running as. ! 73: %l process LINK_SPEC as a spec. ! 74: %L process LIB_SPEC as a spec. ! 75: %S process STARTFILE_SPEC as a spec. Here S is literal. ! 76: %c process SIGNED_CHAR_SPEC as a spec. ! 77: %{S} substitutes the -S switch, if that switch was given to CC. ! 78: If that switch was not specified, this substitutes nothing. ! 79: Here S is a metasyntactic variable. ! 80: %{S*} substitutes all the switches specified to CC whose names start ! 81: with -S. This is used for -o, -D, -I, etc; switches that take ! 82: arguments. CC considers `-o foo' as being one switch whose ! 83: name starts with `o'. %{o*} would substitute this text, ! 84: including the space; thus, two arguments would be generated. ! 85: %{S:X} substitutes X, but only if the -S switch was given to CC. ! 86: %{!S:X} substitutes X, but only if the -S switch was NOT given to CC. ! 87: ! 88: The conditional text X in a %{S:X} or %{!S:X} construct may contain ! 89: other nested % constructs or spaces, or even newlines. ! 90: They are processed as usual, as described above. ! 91: ! 92: Note that it is built into CC which switches take arguments and which ! 93: do not. You might think it would be useful to generalize this to ! 94: allow each compiler's spec to say which switches take arguments. But ! 95: this cannot be done in a consistent fashion. CC cannot even decide ! 96: which input files have been specified without knowing which switches ! 97: take arguments, and it must know which input files to compile in order ! 98: to tell which compilers to run. ! 99: ! 100: CC also knows implicitly that arguments starting in `-l' are to ! 101: be treated as output files, and passed to the linker in their proper ! 102: position among the other output files. ! 103: ! 104: */ ! 105: ! 106: /* This defines which switches take arguments. */ ! 107: ! 108: #define SWITCH_TAKES_ARG(CHAR) \ ! 109: ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \ ! 110: || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \ ! 111: || (CHAR) == 'I' || (CHAR) == 'Y' || (CHAR) == 'm' \ ! 112: || (CHAR) == 'L') ! 113: ! 114: #include <stdio.h> ! 115: #include <sys/types.h> ! 116: #include <signal.h> ! 117: #include <sys/file.h> ! 118: #include "obstack.h" ! 119: #include "config.h" ! 120: ! 121: #ifdef USG ! 122: #define R_OK 4 ! 123: #define W_OK 2 ! 124: #define X_OK 1 ! 125: #define vfork fork ! 126: #endif ! 127: ! 128: #define obstack_chunk_alloc xmalloc ! 129: #define obstack_chunk_free free ! 130: extern int xmalloc (); ! 131: extern void free (); ! 132: ! 133: /* If a stage of compilation returns an exit status >= 1, ! 134: compilation of that file ceases. */ ! 135: ! 136: #define MIN_FATAL_STATUS 1 ! 137: ! 138: /* This is the obstack which we use to allocate many strings. */ ! 139: ! 140: struct obstack obstack; ! 141: ! 142: char *handle_braces (); ! 143: char *save_string (); ! 144: char *concat (); ! 145: int do_spec (); ! 146: int do_spec_1 (); ! 147: int give_string (); ! 148: char *find_file (); ! 149: ! 150: /* config.h can define ASM_SPEC to provide extra args to the assembler ! 151: or extra switch-translations. */ ! 152: #ifndef ASM_SPEC ! 153: #define ASM_SPEC "" ! 154: #endif ! 155: ! 156: /* config.h can define LINK_SPEC to provide extra args to the linker ! 157: or extra switch-translations. */ ! 158: #ifndef LINK_SPEC ! 159: #define LINK_SPEC "" ! 160: #endif ! 161: ! 162: /* config.h can define LIB_SPEC to override the default libraries. */ ! 163: #ifndef LIB_SPEC ! 164: #define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}" ! 165: #endif ! 166: ! 167: /* config.h can define STARTFILE_SPEC to override the default crt0 files. */ ! 168: #ifndef STARTFILE_SPEC ! 169: #define STARTFILE_SPEC \ ! 170: "%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}" ! 171: #endif ! 172: ! 173: /* This spec is used for telling cpp whether char is signed or not. */ ! 174: #define SIGNED_CHAR_SPEC \ ! 175: (DEFAULT_SIGNED_CHAR ? "%{funsigned-char:-D__CHAR_UNSIGNED__}" \ ! 176: : "%{!fsigned-char:-D__CHAR_UNSIGNED__}") ! 177: ! 178: /* This structure says how to run one compiler, and when to do so. */ ! 179: ! 180: struct compiler ! 181: { ! 182: char *suffix; /* Use this compiler for input files ! 183: whose names end in this suffix. */ ! 184: char *spec; /* To use this compiler, pass this spec ! 185: to do_spec. */ ! 186: }; ! 187: ! 188: /* Here are the specs for compiling files with various known suffixes. ! 189: A file that does not end in any of these suffixes will be passed ! 190: unchanged to the loader and nothing else will be done to it. */ ! 191: ! 192: struct compiler compilers[] = ! 193: { ! 194: {".c", ! 195: "cpp %{nostdinc} %{C} %{v} %{D*} %{U*} %{I*} %{M*} %{T} \ ! 196: -undef -D__GNU__ -D__GNUC__ %{ansi:-T -D__STRICT_ANSI__} %{!ansi:%p}\ ! 197: %c %{O:-D__OPTIMIZE__} %{traditional} %{pedantic} %{Wcomment} %{Wall}\ ! 198: %i %{!M*:%{!E:%g.cpp}}%{E:%{o*}}%{M*:%{o*}}\n\ ! 199: %{!M*:%{!E:cc1 %g.cpp %{!Q:-quiet} -dumpbase %i %{Y*} %{d*} %{m*} %{f*}\ ! 200: %{W*} %{w} %{pedantic} %{ansi}\ ! 201: %{O:-opt}%{!O:-noreg}\ ! 202: %{v:-version} %{g:-G}%{gg:-symout %g.sym} %{pg:-p} %{p}\ ! 203: %{S:%{o*}%{!o*:-o %b.s}}%{!S:-o %g.s}\n\ ! 204: %{!S:as %{R} %{j} %{J} %{h} %{d2} %a %{gg:-G %g.sym}\ ! 205: %g.s %{c:%{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o}\n }}}"}, ! 206: {".s", ! 207: "%{!S:as %{R} %{j} %{J} %{h} %{d2} %a \ ! 208: %i %{c:%{o*}%{!o*:-o %w%b.o}}%{!c:-o %d%w%b.o}\n }"}, ! 209: /* Mark end of table */ ! 210: {0, 0} ! 211: }; ! 212: ! 213: /* Here is the spec for running the linker, after compiling all files. */ ! 214: char *link_spec = "%{!c:%{!M*:%{!E:%{!S:ld %{o*} %l\ ! 215: %{A} %{d} %{e*} %{N} %{n} %{r} %{s} %{S} %{T*} %{t} %{u*} %{X} %{x} %{z}\ ! 216: %{y*} %{!nostdlib:%S} \ ! 217: %{L*} %o %{!nostdlib:gnulib%s %L}\n }}}}"; ! 218: /* %{L*} %o %{!nostdlib:gnulib%s %{g:-lg} %L}\n }}}}"; took out {g from above */ ! 219: ! 220: /* Record the names of temporary files we tell compilers to write, ! 221: and delete them at the end of the run. */ ! 222: ! 223: /* This is the common prefix we use to make temp file names. ! 224: It is chosen once for each run of this program. ! 225: It is substituted into a spec by %g. ! 226: Thus, all temp file names contain this prefix. ! 227: In practice, all temp file names start with this prefix. ! 228: The prefix starts with `/tmp'. */ ! 229: ! 230: char *temp_filename; ! 231: ! 232: /* Length of the prefix. */ ! 233: ! 234: int temp_filename_length; ! 235: ! 236: /* Define the list of temporary files to delete. */ ! 237: ! 238: struct temp_file ! 239: { ! 240: char *name; ! 241: struct temp_file *next; ! 242: int success_only; /* Nonzero means delete this file ! 243: only if compilation succeeds fully. */ ! 244: }; ! 245: ! 246: struct temp_file *temp_file_queue; ! 247: ! 248: /* Record FILENAME as a file to be deleted automatically. ! 249: SUCCESS_ONLY nonzero means delete it only if all compilation succeeds; ! 250: otherwise delete it in any case. */ ! 251: ! 252: void ! 253: record_temp_file (filename, success_only) ! 254: char *filename; ! 255: int success_only; ! 256: { ! 257: register struct temp_file *temp; ! 258: register char *name; ! 259: temp = (struct temp_file *) xmalloc (sizeof (struct temp_file)); ! 260: name = (char *) xmalloc (strlen (filename) + 1); ! 261: strcpy (name, filename); ! 262: temp->next = temp_file_queue; ! 263: temp->name = name; ! 264: temp->success_only = success_only; ! 265: temp_file_queue = temp; ! 266: } ! 267: ! 268: /* Delete all the temporary files whose names we previously recorded. ! 269: SUCCESS nonzero means "delete on success only" files should be deleted. */ ! 270: ! 271: void ! 272: delete_temp_files (success) ! 273: int success; ! 274: { ! 275: register struct temp_file *temp; ! 276: for (temp = temp_file_queue; temp; temp = temp->next) ! 277: if (success || ! temp->success_only) ! 278: { ! 279: #ifdef DEBUG ! 280: int i; ! 281: printf ("Delete %s? (y or n) ", temp->name); ! 282: fflush (stdout); ! 283: i = getchar (); ! 284: if (i != '\n') ! 285: while (getchar () != '\n') ; ! 286: if (i == 'y' || i == 'Y') ! 287: #endif /* DEBUG */ ! 288: unlink (temp->name); ! 289: } ! 290: temp_file_queue = 0; ! 291: } ! 292: ! 293: /* Compute a string to use as the base of all temporary file names. ! 294: It is substituted for %g. */ ! 295: ! 296: void ! 297: choose_temp_base () ! 298: { ! 299: register char *foo = "/tmp/ccXXXXXX"; ! 300: temp_filename = (char *) xmalloc (strlen (foo) + 1); ! 301: strcpy (temp_filename, foo); ! 302: mktemp (temp_filename); ! 303: temp_filename_length = strlen (temp_filename); ! 304: } ! 305: ! 306: /* Accumulate a command (program name and args), and run it. */ ! 307: ! 308: /* Vector of pointers to arguments in the current line of specifications. */ ! 309: ! 310: char **argbuf; ! 311: ! 312: /* Number of elements allocated in argbuf. */ ! 313: ! 314: int argbuf_length; ! 315: ! 316: /* Number of elements in argbuf currently in use (containing args). */ ! 317: ! 318: int argbuf_index; ! 319: ! 320: /* Flag indicating whether we should print the command and arguments */ ! 321: ! 322: unsigned char vflag; ! 323: ! 324: /* User-specified prefix to attach to command names, ! 325: or 0 if none specified. */ ! 326: ! 327: char *user_exec_prefix = 0; ! 328: ! 329: /* Default prefixes to attach to command names. */ ! 330: ! 331: char *standard_exec_prefix = "/usr/lib/gcc-"; ! 332: char *standard_exec_prefix_1 = "/usr/lib/gcc-"; ! 333: ! 334: char *standard_startfile_prefix = "/lib/"; ! 335: char *standard_startfile_prefix_1 = "/usr/lib/"; ! 336: ! 337: /* Clear out the vector of arguments (after a command is executed). */ ! 338: ! 339: void ! 340: clear_args () ! 341: { ! 342: argbuf_index = 0; ! 343: } ! 344: ! 345: /* Add one argument to the vector at the end. ! 346: This is done when a space is seen or at the end of the line. ! 347: If TEMPNAMEP is nonzero, this arg is a file that should be deleted ! 348: at the end of compilation. (If TEMPNAMEP is 2, delete the file ! 349: only if compilation is fully successful.) */ ! 350: ! 351: void ! 352: store_arg (arg, tempnamep) ! 353: char *arg; ! 354: int tempnamep; ! 355: { ! 356: if (argbuf_index + 1 == argbuf_length) ! 357: { ! 358: argbuf = (char **) realloc (argbuf, (argbuf_length *= 2) * sizeof (char *)); ! 359: } ! 360: ! 361: argbuf[argbuf_index++] = arg; ! 362: argbuf[argbuf_index] = 0; ! 363: ! 364: if (tempnamep) ! 365: record_temp_file (arg, tempnamep == 2); ! 366: } ! 367: ! 368: /* Execute the command specified by the arguments on the current line of spec. ! 369: Returns 0 if successful, -1 if failed. */ ! 370: ! 371: int ! 372: execute () ! 373: { ! 374: int pid; ! 375: int status; ! 376: int size; ! 377: char *temp; ! 378: int win = 0; ! 379: ! 380: size = strlen (standard_exec_prefix); ! 381: if (user_exec_prefix != 0 && strlen (user_exec_prefix) > size) ! 382: size = strlen (user_exec_prefix); ! 383: if (strlen (standard_exec_prefix_1) > size) ! 384: size = strlen (standard_exec_prefix_1); ! 385: size += strlen (argbuf[0]) + 1; ! 386: temp = (char *) alloca (size); ! 387: ! 388: /* Determine the filename to execute. */ ! 389: ! 390: if (user_exec_prefix) ! 391: { ! 392: strcpy (temp, user_exec_prefix); ! 393: strcat (temp, argbuf[0]); ! 394: win = (access (temp, X_OK) == 0); ! 395: } ! 396: ! 397: if (!win) ! 398: { ! 399: strcpy (temp, standard_exec_prefix); ! 400: strcat (temp, argbuf[0]); ! 401: win = (access (temp, X_OK) == 0); ! 402: } ! 403: ! 404: if (!win) ! 405: { ! 406: strcpy (temp, standard_exec_prefix_1); ! 407: strcat (temp, argbuf[0]); ! 408: win = (access (temp, X_OK) == 0); ! 409: } ! 410: ! 411: if (vflag) ! 412: { ! 413: int i; ! 414: for (i = 0; argbuf[i]; i++) ! 415: { ! 416: if (i == 0 && win) ! 417: fprintf (stderr, " %s", temp); ! 418: else ! 419: fprintf (stderr, " %s", argbuf[i]); ! 420: } ! 421: fprintf (stderr, "\n"); ! 422: fflush (stderr); ! 423: #ifdef DEBUG ! 424: fprintf (stderr, "\nGo ahead? (y or n) "); ! 425: fflush (stderr); ! 426: i = getchar (); ! 427: if (i != '\n') ! 428: while (getchar () != '\n') ; ! 429: if (i != 'y' && i != 'Y') ! 430: return 0; ! 431: #endif /* DEBUG */ ! 432: } ! 433: ! 434: #ifdef USG ! 435: pid = fork (); ! 436: if (pid < 0) ! 437: pfatal_with_name ("fork"); ! 438: #else ! 439: pid = vfork (); ! 440: if (pid < 0) ! 441: pfatal_with_name ("vfork"); ! 442: #endif ! 443: if (pid == 0) ! 444: { ! 445: if (win) ! 446: execv (temp, argbuf); ! 447: else ! 448: execvp (argbuf[0], argbuf); ! 449: perror_with_name (argbuf[0]); ! 450: _exit (65); ! 451: } ! 452: wait (&status); ! 453: if ((status & 0x7F) != 0) ! 454: fatal ("Program %s got fatal signal %d.", argbuf[0], (status & 0x7F)); ! 455: if (((status & 0xFF00) >> 8) >= MIN_FATAL_STATUS) ! 456: return -1; ! 457: return 0; ! 458: } ! 459: ! 460: /* Find all the switches given to us ! 461: and make a vector describing them. ! 462: The elements of the vector a strings, one per switch given. ! 463: If a switch uses the following argument, then the `part1' field ! 464: is the switch itself and the `part2' field is the following argument. */ ! 465: ! 466: struct switchstr ! 467: { ! 468: char *part1; ! 469: char *part2; ! 470: }; ! 471: ! 472: struct switchstr *switches; ! 473: ! 474: int n_switches; ! 475: ! 476: /* Also a vector of input files specified. */ ! 477: ! 478: char **infiles; ! 479: ! 480: int n_infiles; ! 481: ! 482: /* And a vector of corresponding output files is made up later. */ ! 483: ! 484: char **outfiles; ! 485: ! 486: char * ! 487: make_switch (p1, s1, p2, s2) ! 488: char *p1; ! 489: int s1; ! 490: char *p2; ! 491: int s2; ! 492: { ! 493: register char *new; ! 494: if (p2 && s2 == 0) ! 495: s2 = strlen (p2); ! 496: new = (char *) xmalloc (s1 + s2 + 2); ! 497: bcopy (p1, new, s1); ! 498: if (p2) ! 499: { ! 500: new[s1++] = ' '; ! 501: bcopy (p2, new + s1, s2); ! 502: } ! 503: new[s1 + s2] = 0; ! 504: return new; ! 505: } ! 506: ! 507: /* Create the vector `switches' and its contents. ! 508: Store its length in `n_switches'. */ ! 509: ! 510: void ! 511: process_command (argc, argv) ! 512: int argc; ! 513: char **argv; ! 514: { ! 515: register int i; ! 516: n_switches = 0; ! 517: n_infiles = 0; ! 518: ! 519: /* Scan argv twice. Here, the first time, just count how many switches ! 520: there will be in their vector, and how many input files in theirs. ! 521: Here we also parse the switches that cc itself uses (e.g. -v). */ ! 522: ! 523: for (i = 1; i < argc; i++) ! 524: { ! 525: if (argv[i][0] == '-' && argv[i][1] != 'l') ! 526: { ! 527: register char *p = &argv[i][1]; ! 528: register int c = *p; ! 529: ! 530: switch (c) ! 531: { ! 532: case 'B': ! 533: user_exec_prefix = p + 1; ! 534: break; ! 535: ! 536: case 'v': /* Print our subcommands and print versions. */ ! 537: vflag++; ! 538: n_switches++; ! 539: break; ! 540: ! 541: default: ! 542: n_switches++; ! 543: ! 544: if (SWITCH_TAKES_ARG (c) && p[1] == 0) ! 545: i++; ! 546: } ! 547: } ! 548: else ! 549: n_infiles++; ! 550: } ! 551: ! 552: /* Then create the space for the vectors and scan again. */ ! 553: ! 554: switches = ((struct switchstr *) ! 555: xmalloc ((n_switches + 1) * sizeof (struct switchstr))); ! 556: infiles = (char **) xmalloc ((n_infiles + 1) * sizeof (char *)); ! 557: n_switches = 0; ! 558: n_infiles = 0; ! 559: ! 560: /* This, time, copy the text of each switch and store a pointer ! 561: to the copy in the vector of switches. ! 562: Store all the infiles in their vector. */ ! 563: ! 564: for (i = 1; i < argc; i++) ! 565: { ! 566: if (argv[i][0] == '-' && argv[i][1] != 'l') ! 567: { ! 568: register char *p = &argv[i][1]; ! 569: register int c = *p; ! 570: ! 571: if (c == 'B') ! 572: continue; ! 573: switches[n_switches].part1 = p; ! 574: if (SWITCH_TAKES_ARG (c) && p[1] == 0) ! 575: switches[n_switches].part2 = argv[++i]; ! 576: else ! 577: switches[n_switches].part2 = 0; ! 578: n_switches++; ! 579: } ! 580: else ! 581: infiles[n_infiles++] = argv[i]; ! 582: } ! 583: ! 584: switches[n_switches].part1 = 0; ! 585: infiles[n_infiles] = 0; ! 586: } ! 587: ! 588: /* Process a spec string, accumulating and running commands. */ ! 589: ! 590: /* These variables describe the input file name. ! 591: input_file_number is the index on outfiles of this file, ! 592: so that the output file name can be stored for later use by %o. ! 593: input_basename is the start of the part of the input file ! 594: sans all directory names, and basename_length is the number ! 595: of characters starting there excluding the suffix .c or whatever. */ ! 596: ! 597: char *input_filename; ! 598: int input_file_number; ! 599: int input_filename_length; ! 600: int basename_length; ! 601: char *input_basename; ! 602: ! 603: /* These are variables used within do_spec and do_spec_1. */ ! 604: ! 605: /* Nonzero if an arg has been started and not yet terminated ! 606: (with space, tab or newline). */ ! 607: int arg_going; ! 608: ! 609: /* Nonzero means %d or %g has been seen; the next arg to be terminated ! 610: is a temporary file name. */ ! 611: int delete_this_arg; ! 612: ! 613: /* Nonzero means %w has been seen; the next arg to be terminated ! 614: is the output file name of this compilation. */ ! 615: int this_is_output_file; ! 616: ! 617: /* Nonzero means %s has been seen; the next arg to be terminated ! 618: is the name of a library file and we should try the standard ! 619: search dirs for it. */ ! 620: int this_is_library_file; ! 621: ! 622: /* Process the spec SPEC and run the commands specified therein. ! 623: Returns 0 if the spec is successfully processed; -1 if failed. */ ! 624: ! 625: int ! 626: do_spec (spec) ! 627: char *spec; ! 628: { ! 629: int value; ! 630: ! 631: clear_args (); ! 632: arg_going = 0; ! 633: delete_this_arg = 0; ! 634: this_is_output_file = 0; ! 635: this_is_library_file = 0; ! 636: ! 637: value = do_spec_1 (spec, 0); ! 638: if (value == 0) ! 639: value = do_spec_1 ("\n", 0); ! 640: return value; ! 641: } ! 642: ! 643: /* Process the sub-spec SPEC as a portion of a larger spec. ! 644: This is like processing a whole spec except that we do ! 645: not initialize at the beginning and we do not supply a ! 646: newline by default at the end. ! 647: INSWITCH nonzero means don't process %-sequences in SPEC; ! 648: in this case, % is treated as an ordinary character. ! 649: This is used while substituting switches. ! 650: INSWITCH nonzero also causes SPC not to terminate an argument. ! 651: ! 652: Value is zero unless a line was finished ! 653: and the command on that line reported an error. */ ! 654: ! 655: int ! 656: do_spec_1 (spec, inswitch) ! 657: char *spec; ! 658: int inswitch; ! 659: { ! 660: register char *p = spec; ! 661: register int c; ! 662: char *string; ! 663: ! 664: while (c = *p++) ! 665: /* If substituting a switch, treat all chars like letters. ! 666: Otherwise, NL, SPC, TAB and % are special. */ ! 667: switch (inswitch ? 'a' : c) ! 668: { ! 669: case '\n': ! 670: /* End of line: finish any pending argument, ! 671: then run the pending command if one has been started. */ ! 672: if (arg_going) ! 673: { ! 674: obstack_1grow (&obstack, 0); ! 675: string = obstack_finish (&obstack); ! 676: if (this_is_library_file) ! 677: string = find_file (string); ! 678: store_arg (string, delete_this_arg); ! 679: if (this_is_output_file) ! 680: outfiles[input_file_number] = string; ! 681: } ! 682: arg_going = 0; ! 683: if (argbuf_index) ! 684: { ! 685: int value = execute (); ! 686: if (value) ! 687: return value; ! 688: } ! 689: /* Reinitialize for a new command, and for a new argument. */ ! 690: clear_args (); ! 691: arg_going = 0; ! 692: delete_this_arg = 0; ! 693: this_is_output_file = 0; ! 694: this_is_library_file = 0; ! 695: break; ! 696: ! 697: case '\t': ! 698: case ' ': ! 699: /* Space or tab ends an argument if one is pending. */ ! 700: if (arg_going) ! 701: { ! 702: obstack_1grow (&obstack, 0); ! 703: string = obstack_finish (&obstack); ! 704: if (this_is_library_file) ! 705: string = find_file (string); ! 706: store_arg (string, delete_this_arg); ! 707: if (this_is_output_file) ! 708: outfiles[input_file_number] = string; ! 709: } ! 710: /* Reinitialize for a new argument. */ ! 711: arg_going = 0; ! 712: delete_this_arg = 0; ! 713: this_is_output_file = 0; ! 714: this_is_library_file = 0; ! 715: break; ! 716: ! 717: case '%': ! 718: switch (c = *p++) ! 719: { ! 720: case 0: ! 721: fatal ("Invalid specification! Bug in cc."); ! 722: ! 723: case 'i': ! 724: obstack_grow (&obstack, input_filename, input_filename_length); ! 725: arg_going = 1; ! 726: break; ! 727: ! 728: case 'b': ! 729: obstack_grow (&obstack, input_basename, basename_length); ! 730: arg_going = 1; ! 731: break; ! 732: ! 733: case 'p': ! 734: do_spec_1 (CPP_PREDEFINES, 0); ! 735: break; ! 736: ! 737: case 'g': ! 738: obstack_grow (&obstack, temp_filename, temp_filename_length); ! 739: delete_this_arg = 1; ! 740: arg_going = 1; ! 741: break; ! 742: ! 743: case 'd': ! 744: delete_this_arg = 2; ! 745: break; ! 746: ! 747: case 'w': ! 748: this_is_output_file = 1; ! 749: break; ! 750: ! 751: case 's': ! 752: this_is_library_file = 1; ! 753: break; ! 754: ! 755: case 'o': ! 756: { ! 757: register int f; ! 758: for (f = 0; f < n_infiles; f++) ! 759: store_arg (outfiles[f], 0); ! 760: } ! 761: break; ! 762: ! 763: case 'a': ! 764: do_spec_1 (ASM_SPEC, 0); ! 765: break; ! 766: ! 767: case 'c': ! 768: do_spec_1 (SIGNED_CHAR_SPEC, 0); ! 769: break; ! 770: ! 771: case 'l': ! 772: do_spec_1 (LINK_SPEC, 0); ! 773: break; ! 774: ! 775: case 'L': ! 776: do_spec_1 (LIB_SPEC, 0); ! 777: break; ! 778: ! 779: case 'S': ! 780: do_spec_1 (STARTFILE_SPEC, 0); ! 781: break; ! 782: ! 783: case '{': ! 784: p = handle_braces (p); ! 785: if (p == 0) ! 786: return -1; ! 787: break; ! 788: ! 789: case '%': ! 790: obstack_1grow (&obstack, '%'); ! 791: break; ! 792: ! 793: default: ! 794: abort (); ! 795: } ! 796: break; ! 797: ! 798: default: ! 799: /* Ordinary character: put it into the current argument. */ ! 800: obstack_1grow (&obstack, c); ! 801: arg_going = 1; ! 802: } ! 803: ! 804: return 0; /* End of string */ ! 805: } ! 806: ! 807: /* Return 0 if we call do_spec_1 and that returns -1. */ ! 808: ! 809: char * ! 810: handle_braces (p) ! 811: register char *p; ! 812: { ! 813: register char *q; ! 814: int negate = *p == '!'; ! 815: char *filter; ! 816: ! 817: if (negate) ++p; ! 818: ! 819: filter = p; ! 820: while (*p != ':' && *p != '}') p++; ! 821: if (*p != '}') ! 822: { ! 823: register int count = 1; ! 824: q = p + 1; ! 825: while (count > 0) ! 826: { ! 827: if (*q == '{') ! 828: count++; ! 829: else if (*q == '}') ! 830: count--; ! 831: else if (*q == 0) ! 832: abort (); ! 833: q++; ! 834: } ! 835: } ! 836: else ! 837: q = p + 1; ! 838: ! 839: if (p[-1] == '*' && p[0] == '}') ! 840: { ! 841: /* Substitute all matching switches as separate args. */ ! 842: register int i; ! 843: --p; ! 844: for (i = 0; i < n_switches; i++) ! 845: if (!strncmp (switches[i].part1, filter, p - filter)) ! 846: { ! 847: give_switch (i); ! 848: } ! 849: } ! 850: else ! 851: { ! 852: /* Test for presence of the specified switch. */ ! 853: register int i; ! 854: int present = 0; ! 855: ! 856: /* If name specified ends in *, as in {x*:...}, ! 857: check for presence of any switch name starting with x. */ ! 858: if (p[-1] == '*') ! 859: { ! 860: for (i = 0; i < n_switches; i++) ! 861: { ! 862: if (!strncmp (switches[i].part1, filter, p - filter - 1)) ! 863: { ! 864: present = 1; ! 865: break; ! 866: } ! 867: } ! 868: } ! 869: /* Otherwise, check for presence of exact name specified. */ ! 870: else ! 871: { ! 872: for (i = 0; i < n_switches; i++) ! 873: { ! 874: if (!strncmp (switches[i].part1, filter, p - filter) ! 875: && switches[i].part1[p - filter] == 0) ! 876: { ! 877: present = 1; ! 878: break; ! 879: } ! 880: } ! 881: } ! 882: ! 883: /* If it is as desired (present for %{s...}, absent for %{-s...}) ! 884: then substitute either the switch or the specified ! 885: conditional text. */ ! 886: if (present != negate) ! 887: { ! 888: if (*p == '}') ! 889: { ! 890: give_switch (i); ! 891: } ! 892: else ! 893: { ! 894: if (do_spec_1 (save_string (p + 1, q - p - 2), 0) < 0) ! 895: return 0; ! 896: } ! 897: } ! 898: } ! 899: ! 900: return q; ! 901: } ! 902: ! 903: /* Pass a switch to the current accumulating command ! 904: in the same form that we received it. ! 905: SWITCHNUM identifies the switch; it is an index into ! 906: the vector of switches gcc received, which is `switches'. ! 907: This cannot fail since it never finishes a command line. */ ! 908: ! 909: give_switch (switchnum) ! 910: int switchnum; ! 911: { ! 912: do_spec_1 ("-", 0); ! 913: do_spec_1 (switches[switchnum].part1, 1); ! 914: do_spec_1 (" ", 0); ! 915: if (switches[switchnum].part2 != 0) ! 916: { ! 917: do_spec_1 (switches[switchnum].part2, 1); ! 918: do_spec_1 (" ", 0); ! 919: } ! 920: } ! 921: ! 922: /* Search for a file named NAME trying various prefixes including the ! 923: user's -B prefix and some standard ones. ! 924: Return the absolute pathname found. If nothing is found, return NAME. */ ! 925: ! 926: char * ! 927: find_file (name) ! 928: char *name; ! 929: { ! 930: int size; ! 931: char *temp; ! 932: int win = 0; ! 933: ! 934: /* Compute maximum size of NAME plus any prefix we will try. */ ! 935: ! 936: size = strlen (standard_exec_prefix); ! 937: if (user_exec_prefix != 0 && strlen (user_exec_prefix) > size) ! 938: size = strlen (user_exec_prefix); ! 939: if (strlen (standard_exec_prefix_1) > size) ! 940: size = strlen (standard_exec_prefix_1); ! 941: if (strlen (standard_startfile_prefix) > size) ! 942: size = strlen (standard_startfile_prefix); ! 943: if (strlen (standard_startfile_prefix_1) > size) ! 944: size = strlen (standard_startfile_prefix_1); ! 945: size += strlen (name) + 1; ! 946: ! 947: temp = (char *) alloca (size); ! 948: ! 949: if (user_exec_prefix) ! 950: { ! 951: strcpy (temp, user_exec_prefix); ! 952: strcat (temp, name); ! 953: win = (access (temp, R_OK) == 0); ! 954: } ! 955: ! 956: if (!win) ! 957: { ! 958: strcpy (temp, standard_exec_prefix); ! 959: strcat (temp, name); ! 960: win = (access (temp, R_OK) == 0); ! 961: } ! 962: ! 963: if (!win) ! 964: { ! 965: strcpy (temp, standard_exec_prefix_1); ! 966: strcat (temp, name); ! 967: win = (access (temp, R_OK) == 0); ! 968: } ! 969: ! 970: if (!win) ! 971: { ! 972: strcpy (temp, standard_startfile_prefix); ! 973: strcat (temp, name); ! 974: win = (access (temp, R_OK) == 0); ! 975: } ! 976: ! 977: if (!win) ! 978: { ! 979: strcpy (temp, standard_startfile_prefix_1); ! 980: strcat (temp, name); ! 981: win = (access (temp, R_OK) == 0); ! 982: } ! 983: ! 984: if (!win) ! 985: { ! 986: strcpy (temp, "./"); ! 987: strcat (temp, name); ! 988: win = (access (temp, R_OK) == 0); ! 989: } ! 990: ! 991: if (win) ! 992: return save_string (temp, strlen (temp)); ! 993: return name; ! 994: } ! 995: ! 996: /* Name with which this program was invoked. */ ! 997: ! 998: char *programname; ! 999: ! 1000: /* On fatal signals, delete all the temporary files. */ ! 1001: ! 1002: void ! 1003: fatal_error (signum) ! 1004: int signum; ! 1005: { ! 1006: signal (signum, SIG_DFL); ! 1007: delete_temp_files (0); ! 1008: /* Get the same signal again, this time not handled, ! 1009: so its normal effect occurs. */ ! 1010: kill (getpid (), signum); ! 1011: } ! 1012: ! 1013: int ! 1014: main (argc, argv) ! 1015: int argc; ! 1016: char **argv; ! 1017: { ! 1018: register int i; ! 1019: int value; ! 1020: int nolink = 0; ! 1021: int error = 0; ! 1022: programname = argv[0]; ! 1023: ! 1024: if (signal (SIGINT, SIG_IGN) != SIG_IGN) ! 1025: signal (SIGINT, fatal_error); ! 1026: signal (SIGHUP, fatal_error); ! 1027: signal (SIGTERM, fatal_error); ! 1028: ! 1029: argbuf_length = 10; ! 1030: argbuf = (char **) xmalloc (argbuf_length * sizeof (char *)); ! 1031: ! 1032: obstack_init (&obstack); ! 1033: ! 1034: choose_temp_base (); ! 1035: ! 1036: /* Make a table of what switches there are (switches, n_switches). ! 1037: Make a table of specified input files (infiles, n_infiles). */ ! 1038: ! 1039: process_command (argc, argv); ! 1040: ! 1041: if (vflag) ! 1042: { ! 1043: extern char version_string[]; ! 1044: printf ("gcc version %s\n", version_string); ! 1045: if (n_infiles == 0) ! 1046: exit (0); ! 1047: } ! 1048: ! 1049: if (n_infiles == 0) ! 1050: fatal ("No source or object files specified."); ! 1051: ! 1052: /* Make a place to record the compiler output file names ! 1053: that correspond to the input files. */ ! 1054: ! 1055: outfiles = (char **) xmalloc (n_infiles * sizeof (char *)); ! 1056: bzero (outfiles, n_infiles * sizeof (char *)); ! 1057: ! 1058: for (i = 0; i < n_infiles; i++) ! 1059: { ! 1060: /* First figure out which compiler from the file's suffix. */ ! 1061: ! 1062: register struct compiler *cp; ! 1063: ! 1064: /* Tell do_spec what to substitute for %i. */ ! 1065: ! 1066: input_filename = infiles[i]; ! 1067: input_filename_length = strlen (input_filename); ! 1068: input_file_number = i; ! 1069: ! 1070: /* Use the same thing in %o, unless cp->spec says otherwise. */ ! 1071: ! 1072: outfiles[i] = input_filename; ! 1073: ! 1074: for (cp = compilers; cp->spec; cp++) ! 1075: { ! 1076: if (strlen (cp->suffix) < input_filename_length ! 1077: && !strcmp (cp->suffix, ! 1078: infiles[i] + input_filename_length ! 1079: - strlen (cp->suffix))) ! 1080: { ! 1081: /* Ok, we found an applicable compiler. Run its spec. */ ! 1082: /* First say how much of input_filename to substitute for %b */ ! 1083: register char *p; ! 1084: ! 1085: input_basename = input_filename; ! 1086: for (p = input_filename; *p; p++) ! 1087: if (*p == '/') ! 1088: input_basename = p + 1; ! 1089: basename_length = (input_filename_length - strlen (cp->suffix) ! 1090: - (input_basename - input_filename)); ! 1091: value = do_spec (cp->spec); ! 1092: if (value < 0) ! 1093: error = 1; ! 1094: break; ! 1095: } ! 1096: } ! 1097: ! 1098: /* If this file's name does not contain a recognized suffix, ! 1099: don't do anything to it, but do feed it to the link spec ! 1100: since its name is in outfiles. */ ! 1101: } ! 1102: ! 1103: /* Run ld to link all the compiler output files. */ ! 1104: ! 1105: if (! nolink && error == 0) ! 1106: { ! 1107: value = do_spec (link_spec); ! 1108: if (value < 0) ! 1109: error = 1; ! 1110: } ! 1111: ! 1112: /* Delete some or all of the temporary files we made. */ ! 1113: ! 1114: delete_temp_files (error == 0); ! 1115: ! 1116: exit (error); ! 1117: } ! 1118: ! 1119: xmalloc (size) ! 1120: int size; ! 1121: { ! 1122: register int value = malloc (size); ! 1123: if (value == 0) ! 1124: fatal ("Virtual memory full."); ! 1125: return value; ! 1126: } ! 1127: ! 1128: xrealloc (ptr, size) ! 1129: int ptr, size; ! 1130: { ! 1131: register int value = realloc (ptr, size); ! 1132: if (value == 0) ! 1133: fatal ("Virtual memory full."); ! 1134: return value; ! 1135: } ! 1136: ! 1137: fatal (msg, arg1, arg2) ! 1138: char *msg, *arg1, *arg2; ! 1139: { ! 1140: error (msg, arg1, arg2); ! 1141: delete_temp_files (); ! 1142: exit (1); ! 1143: } ! 1144: ! 1145: error (msg, arg1, arg2) ! 1146: char *msg, *arg1, *arg2; ! 1147: { ! 1148: fprintf (stderr, "%s: ", programname); ! 1149: fprintf (stderr, msg, arg1, arg2); ! 1150: fprintf (stderr, "\n"); ! 1151: } ! 1152: ! 1153: /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */ ! 1154: ! 1155: char * ! 1156: concat (s1, s2, s3) ! 1157: char *s1, *s2, *s3; ! 1158: { ! 1159: int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3); ! 1160: char *result = (char *) xmalloc (len1 + len2 + len3 + 1); ! 1161: ! 1162: strcpy (result, s1); ! 1163: strcpy (result + len1, s2); ! 1164: strcpy (result + len1 + len2, s3); ! 1165: *(result + len1 + len2 + len3) = 0; ! 1166: ! 1167: return result; ! 1168: } ! 1169: ! 1170: char * ! 1171: save_string (s, len) ! 1172: char *s; ! 1173: int len; ! 1174: { ! 1175: register char *result = (char *) xmalloc (len + 1); ! 1176: ! 1177: bcopy (s, result, len); ! 1178: result[len] = 0; ! 1179: return result; ! 1180: } ! 1181: ! 1182: pfatal_with_name (name) ! 1183: char *name; ! 1184: { ! 1185: extern int errno, sys_nerr; ! 1186: extern char *sys_errlist[]; ! 1187: char *s; ! 1188: ! 1189: if (errno < sys_nerr) ! 1190: s = concat ("", sys_errlist[errno], " for %s"); ! 1191: else ! 1192: s = "cannot open %s"; ! 1193: fatal (s, name); ! 1194: } ! 1195: ! 1196: perror_with_name (name) ! 1197: char *name; ! 1198: { ! 1199: extern int errno, sys_nerr; ! 1200: extern char *sys_errlist[]; ! 1201: char *s; ! 1202: ! 1203: if (errno < sys_nerr) ! 1204: s = concat ("", sys_errlist[errno], " for %s"); ! 1205: else ! 1206: s = "cannot open %s"; ! 1207: error (s, name); ! 1208: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.