Annotation of researchv10dc/cmd/gcc/gcc.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.