📄 gcc.c
字号:
intdo_spec (spec) char *spec;{ int value; clear_args (); arg_going = 0; delete_this_arg = 0; this_is_output_file = 0; this_is_library_file = 0; value = do_spec_1 (spec, 0); /* Force out any unfinished command. If -pipe, this forces out the last command if it ended in `|'. */ if (value == 0) { if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|")) argbuf_index--; if (argbuf_index > 0) value = execute (); } return value;}/* Process the sub-spec SPEC as a portion of a larger spec. This is like processing a whole spec except that we do not initialize at the beginning and we do not supply a newline by default at the end. INSWITCH nonzero means don't process %-sequences in SPEC; in this case, % is treated as an ordinary character. This is used while substituting switches. INSWITCH nonzero also causes SPC not to terminate an argument. Value is zero unless a line was finished and the command on that line reported an error. */intdo_spec_1 (spec, inswitch) char *spec; int inswitch;{ register char *p = spec; register int c; char *string; while (c = *p++) /* If substituting a switch, treat all chars like letters. Otherwise, NL, SPC, TAB and % are special. */ switch (inswitch ? 'a' : c) { case '\n': /* End of line: finish any pending argument, then run the pending command if one has been started. */ if (arg_going) { obstack_1grow (&obstack, 0); string = obstack_finish (&obstack); if (this_is_library_file) string = find_file (string); store_arg (string, delete_this_arg, this_is_output_file); if (this_is_output_file) outfiles[input_file_number] = string; } arg_going = 0; if (argbuf_index > 0 && !strcmp (argbuf[argbuf_index - 1], "|")) { int i; for (i = 0; i < n_switches; i++) if (!strcmp (switches[i].part1, "pipe")) break; /* A `|' before the newline means use a pipe here, but only if -pipe was specified. Otherwise, execute now and don't pass the `|' as an arg. */ if (i < n_switches) { switches[i].valid = 1; break; } else argbuf_index--; } if (argbuf_index > 0) { int value = execute (); if (value) return value; } /* Reinitialize for a new command, and for a new argument. */ clear_args (); arg_going = 0; delete_this_arg = 0; this_is_output_file = 0; this_is_library_file = 0; break; case '|': /* End any pending argument. */ if (arg_going) { obstack_1grow (&obstack, 0); string = obstack_finish (&obstack); if (this_is_library_file) string = find_file (string); store_arg (string, delete_this_arg, this_is_output_file); if (this_is_output_file) outfiles[input_file_number] = string; } /* Use pipe */ obstack_1grow (&obstack, c); arg_going = 1; break; case '\t': case ' ': /* Space or tab ends an argument if one is pending. */ if (arg_going) { obstack_1grow (&obstack, 0); string = obstack_finish (&obstack); if (this_is_library_file) string = find_file (string); store_arg (string, delete_this_arg, this_is_output_file); if (this_is_output_file) outfiles[input_file_number] = string; } /* Reinitialize for a new argument. */ arg_going = 0; delete_this_arg = 0; this_is_output_file = 0; this_is_library_file = 0; break; case '%': switch (c = *p++) { case 0: fatal ("Invalid specification! Bug in cc."); case 'b': obstack_grow (&obstack, input_basename, basename_length); arg_going = 1; break; case 'd': delete_this_arg = 2; break; case 'e': /* {...:%efoo} means report an error with `foo' as error message and don't execute any more commands for this file. */ { char *q = p; char *buf; while (*p != 0 && *p != '\n') p++; buf = (char *) alloca (p - q + 1); strncpy (buf, q, p - q); buf[p - q] = 0; error ("%s", buf); return -1; } break; case 'g': obstack_grow (&obstack, temp_filename, temp_filename_length); delete_this_arg = 1; arg_going = 1; break; case 'i': obstack_grow (&obstack, input_filename, input_filename_length); arg_going = 1; break; case 'o': { register int f; for (f = 0; f < n_infiles; f++) store_arg (outfiles[f], 0, 0); } break; case 's': this_is_library_file = 1; break; case 'W': { int index = argbuf_index; /* Handle the {...} following the %W. */ if (*p != '{') abort (); p = handle_braces (p + 1); if (p == 0) return -1; /* If any args were output, mark the last one for deletion on failure. */ if (argbuf_index != index) record_temp_file (argbuf[argbuf_index - 1], 0, 1); break; } case 'w': this_is_output_file = 1; break; case '{': p = handle_braces (p); if (p == 0) return -1; break; case '%': obstack_1grow (&obstack, '%'); break;/*** The rest just process a certain constant string as a spec. */ case '1': do_spec_1 (CC1_SPEC, 0); break; case 'a': do_spec_1 (ASM_SPEC, 0); break; case 'c': do_spec_1 (SIGNED_CHAR_SPEC, 0); break; case 'C': do_spec_1 (CPP_SPEC, 0); break; case 'l': do_spec_1 (LINK_SPEC, 0); break; case 'L': do_spec_1 (LIB_SPEC, 0); break; case 'G': do_spec_1 (LIBG_SPEC, 0); break; case 'p': do_spec_1 (CPP_PREDEFINES, 0); break; case 'P': { char *x = (char *) alloca (strlen (CPP_PREDEFINES) * 2 + 1); char *buf = x; char *y = CPP_PREDEFINES; /* Copy all of CPP_PREDEFINES into BUF, but put __ after every -D and at the end of each arg, */ while (1) { if (! strncmp (y, "-D", 2)) { *x++ = '-'; *x++ = 'D'; *x++ = '_'; *x++ = '_'; y += 2; } else if (*y == ' ' || *y == 0) { *x++ = '_'; *x++ = '_'; if (*y == 0) break; else *x++ = *y++; } else *x++ = *y++; } *x = 0; do_spec_1 (buf, 0); } break; case 'S': do_spec_1 (STARTFILE_SPEC, 0); break; case 'E': do_spec_1 (ENDFILE_SPEC, 0); break; default: abort (); } break; default: /* Ordinary character: put it into the current argument. */ obstack_1grow (&obstack, c); arg_going = 1; } return 0; /* End of string */}/* Return 0 if we call do_spec_1 and that returns -1. */char *handle_braces (p) register char *p;{ register char *q; char *filter; int pipe = 0; int negate = 0; if (*p == '|') /* A `|' after the open-brace means, if the test fails, output a single minus sign rather than nothing. This is used in %{|!pipe:...}. */ pipe = 1, ++p; if (*p == '!') /* A `!' after the open-brace negates the condition: succeed if the specified switch is not present. */ negate = 1, ++p; filter = p; while (*p != ':' && *p != '}') p++; if (*p != '}') { register int count = 1; q = p + 1; while (count > 0) { if (*q == '{') count++; else if (*q == '}') count--; else if (*q == 0) abort (); q++; } } else q = p + 1; if (p[-1] == '*' && p[0] == '}') { /* Substitute all matching switches as separate args. */ register int i; --p; for (i = 0; i < n_switches; i++) if (!strncmp (switches[i].part1, filter, p - filter)) give_switch (i); } else { /* Test for presence of the specified switch. */ register int i; int present = 0; /* If name specified ends in *, as in {x*:...}, check for presence of any switch name starting with x. */ if (p[-1] == '*') { for (i = 0; i < n_switches; i++) { if (!strncmp (switches[i].part1, filter, p - filter - 1)) { switches[i].valid = 1; present = 1; } } } /* Otherwise, check for presence of exact name specified. */ else { for (i = 0; i < n_switches; i++) { if (!strncmp (switches[i].part1, filter, p - filter) && switches[i].part1[p - filter] == 0) { switches[i].valid = 1; present = 1; break; } } } /* If it is as desired (present for %{s...}, absent for %{-s...}) then substitute either the switch or the specified conditional text. */ if (present != negate) { if (*p == '}') { give_switch (i); } else { if (do_spec_1 (save_string (p + 1, q - p - 2), 0) < 0) return 0; } } else if (pipe) { /* Here if a %{|...} conditional fails: output a minus sign, which means "standard output" or "standard input". */ do_spec_1 ("-", 0); } } return q;}/* Pass a switch to the current accumulating command in the same form that we received it. SWITCHNUM identifies the switch; it is an index into the vector of switches gcc received, which is `switches'. This cannot fail since it never finishes a command line. */give_switch (switchnum) int switchnum;{ do_spec_1 ("-", 0); do_spec_1 (switches[switchnum].part1, 1); do_spec_1 (" ", 0); if (switches[switchnum].part2 != 0) { do_spec_1 (switches[switchnum].part2, 1); do_spec_1 (" ", 0); } switches[switchnum].valid = 1;}/* Search for a file named NAME trying various prefixes including the user's -B prefix and some standard ones. Return the absolute pathname found. If nothing is found, return NAME. */char *find_file (name) char *name;{ int size; char *temp; int win = 0; /* Compute maximum size of NAME plus any prefix we will try. */ size = strlen (standard_exec_prefix); if (user_exec_prefix != 0 && strlen (user_exec_prefix) > size) size = strlen (user_exec_prefix); if (env_exec_prefix != 0 && strlen (env_exec_prefix) > size) size = strlen (env_exec_prefix); if (strlen (standard_exec_prefix) > size) size = strlen (standard_exec_prefix); if (strlen (standard_exec_prefix_1) > size) size = strlen (standard_exec_prefix_1); if (strlen (standard_startfile_prefix) > size) size = strlen (standard_startfile_prefix); if (strlen (standard_startfile_prefix_1) > size) size = strlen (standard_startfile_prefix_1); if (strlen (standard_startfile_prefix_2) > size) size = strlen (standard_startfile_prefix_2); if (machine_suffix) size += strlen (machine_suffix) + 1; size += strlen (name) + 1; temp = (char *) alloca (size); if (user_exec_prefix) { if (machine_suffix) { strcpy (temp, user_exec_prefix); strcat (temp, machine_suffix); strcat (temp, name); win = (access (temp, R_OK) == 0); } if (!win) { strcpy (temp, user_exec_prefix); strcat (temp, name); win = (access (temp, R_OK) == 0); } } if (!win && env_exec_prefix) { if (machine_suffix) { strcpy (temp, env_exec_prefix); strcat (temp, machine_suffix); strcat (temp, name); win = (access (temp, R_OK) == 0); } if (!win) { strcpy (temp, env_exec_prefix); strcat (temp, name); win = (access (temp, R_OK) == 0); } } if (!win) { if (machine_suffix) { strcpy (temp, standard_exec_prefix); strcat (temp, machine_suffix); strcat (temp, name); win = (access (temp, R_OK) == 0); } if (!win) { strcpy (temp, standard_exec_prefix); strcat (temp, name); win = (access (temp, R_OK) == 0); } } if (!win) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -