📄 gcc.c
字号:
static char *md_exec_prefix = MD_EXEC_PREFIX;#endif#ifndef STANDARD_STARTFILE_PREFIX#define STANDARD_STARTFILE_PREFIX "/usr/local/lib/"#endif /* !defined STANDARD_STARTFILE_PREFIX */#ifdef MD_STARTFILE_PREFIXstatic char *md_startfile_prefix = MD_STARTFILE_PREFIX;#endif#ifdef MD_STARTFILE_PREFIX_1static char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1;#endifstatic char *standard_startfile_prefix = STANDARD_STARTFILE_PREFIX;static char *standard_startfile_prefix_1 = "/lib/";static char *standard_startfile_prefix_2 = "/usr/lib/";#ifndef TOOLDIR_BASE_PREFIX#define TOOLDIR_BASE_PREFIX "/usr/local/"#endifstatic char *tooldir_base_prefix = TOOLDIR_BASE_PREFIX;static char *tooldir_prefix;/* Subdirectory to use for locating libraries. Set by set_multilib_dir based on the compilation options. */static char *multilib_dir;/* Clear out the vector of arguments (after a command is executed). */static voidclear_args (){ argbuf_index = 0;}/* Add one argument to the vector at the end. This is done when a space is seen or at the end of the line. If DELETE_ALWAYS is nonzero, the arg is a filename and the file should be deleted eventually. If DELETE_FAILURE is nonzero, the arg is a filename and the file should be deleted if this compilation fails. */static voidstore_arg (arg, delete_always, delete_failure) char *arg; int delete_always, delete_failure;{ if (argbuf_index + 1 == argbuf_length) argbuf = (char **) xrealloc (argbuf, (argbuf_length *= 2) * sizeof (char *)); argbuf[argbuf_index++] = arg; argbuf[argbuf_index] = 0; if (delete_always || delete_failure) record_temp_file (arg, delete_always, delete_failure);}/* Read compilation specs from a file named FILENAME, replacing the default ones. A suffix which starts with `*' is a definition for one of the machine-specific sub-specs. The "suffix" should be *asm, *cc1, *cpp, *link, *startfile, *signed_char, etc. The corresponding spec is stored in asm_spec, etc., rather than in the `compilers' vector. Anything invalid in the file is a fatal error. */static voidread_specs (filename, main_p) char *filename; int main_p;{ int desc; int readlen; struct stat statbuf; char *buffer; register char *p; if (verbose_flag) fprintf (stderr, "Reading specs from %s\n", filename); /* Open and stat the file. */ desc = open (filename, O_RDONLY, 0); if (desc < 0) pfatal_with_name (filename); if (stat (filename, &statbuf) < 0) pfatal_with_name (filename); /* Read contents of file into BUFFER. */ buffer = xmalloc ((unsigned) statbuf.st_size + 1); readlen = read (desc, buffer, (unsigned) statbuf.st_size); if (readlen < 0) pfatal_with_name (filename); buffer[readlen] = 0; close (desc); /* Scan BUFFER for specs, putting them in the vector. */ p = buffer; while (1) { char *suffix; char *spec; char *in, *out, *p1, *p2, *p3; /* Advance P in BUFFER to the next nonblank nocomment line. */ p = skip_whitespace (p); if (*p == 0) break; /* Is this a special command that starts with '%'? */ /* Don't allow this for the main specs file, since it would encourage people to overwrite it. */ if (*p == '%' && !main_p) { p1 = p; while (*p && *p != '\n') p++; p++; /* Skip '\n' */ if (!strncmp (p1, "%include", sizeof ("%include")-1) && (p1[sizeof "%include" - 1] == ' ' || p1[sizeof "%include" - 1] == '\t')) { char *new_filename; p1 += sizeof ("%include"); while (*p1 == ' ' || *p1 == '\t') p1++; if (*p1++ != '<' || p[-2] != '>') fatal ("specs %%include syntax malformed after %d characters", p1 - buffer + 1); p[-2] = '\0'; new_filename = find_a_file (&startfile_prefixes, p1, R_OK); read_specs (new_filename ? new_filename : p1, FALSE); continue; } else if (!strncmp (p1, "%include_noerr", sizeof "%include_noerr" - 1) && (p1[sizeof "%include_noerr" - 1] == ' ' || p1[sizeof "%include_noerr" - 1] == '\t')) { char *new_filename; p1 += sizeof "%include_noerr"; while (*p1 == ' ' || *p1 == '\t') p1++; if (*p1++ != '<' || p[-2] != '>') fatal ("specs %%include syntax malformed after %d characters", p1 - buffer + 1); p[-2] = '\0'; new_filename = find_a_file (&startfile_prefixes, p1, R_OK); if (new_filename) read_specs (new_filename, FALSE); else if (verbose_flag) fprintf (stderr, "Could not find specs file %s\n", p1); continue; } else if (!strncmp (p1, "%rename", sizeof "%rename" - 1) && (p1[sizeof "%rename" - 1] == ' ' || p1[sizeof "%rename" - 1] == '\t')) { int name_len; struct spec_list *sl; /* Get original name */ p1 += sizeof "%rename"; while (*p1 == ' ' || *p1 == '\t') p1++; if (! isalpha (*p1)) fatal ("specs %%rename syntax malformed after %d characters", p1 - buffer); p2 = p1; while (*p2 && !isspace (*p2)) p2++; if (*p2 != ' ' && *p2 != '\t') fatal ("specs %%rename syntax malformed after %d characters", p2 - buffer); name_len = p2 - p1; *p2++ = '\0'; while (*p2 == ' ' || *p2 == '\t') p2++; if (! isalpha (*p2)) fatal ("specs %%rename syntax malformed after %d characters", p2 - buffer); /* Get new spec name */ p3 = p2; while (*p3 && !isspace (*p3)) p3++; if (p3 != p-1) fatal ("specs %%rename syntax malformed after %d characters", p3 - buffer); *p3 = '\0'; for (sl = specs; sl; sl = sl->next) if (name_len == sl->name_len && !strcmp (sl->name, p1)) break; if (!sl) fatal ("specs %s spec was not found to be renamed", p1); if (strcmp (p1, p2) == 0) continue; if (verbose_flag) { fprintf (stderr, "rename spec %s to %s\n", p1, p2);#ifdef DEBUG_SPECS fprintf (stderr, "spec is '%s'\n\n", *(sl->ptr_spec));#endif } set_spec (p2, *(sl->ptr_spec)); if (sl->alloc_p) free (*(sl->ptr_spec)); *(sl->ptr_spec) = ""; sl->alloc_p = 0; continue; } else fatal ("specs unknown %% command after %d characters", p1 - buffer); } /* Find the colon that should end the suffix. */ p1 = p; while (*p1 && *p1 != ':' && *p1 != '\n') p1++; /* The colon shouldn't be missing. */ if (*p1 != ':') fatal ("specs file malformed after %d characters", p1 - buffer); /* Skip back over trailing whitespace. */ p2 = p1; while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t')) p2--; /* Copy the suffix to a string. */ suffix = save_string (p, p2 - p); /* Find the next line. */ p = skip_whitespace (p1 + 1); if (p[1] == 0) fatal ("specs file malformed after %d characters", p - buffer); p1 = p; /* Find next blank line. */ while (*p1 && !(*p1 == '\n' && p1[1] == '\n')) p1++; /* Specs end at the blank line and do not include the newline. */ spec = save_string (p, p1 - p); p = p1; /* Delete backslash-newline sequences from the spec. */ in = spec; out = spec; while (*in != 0) { if (in[0] == '\\' && in[1] == '\n') in += 2; else if (in[0] == '#') while (*in && *in != '\n') in++; else *out++ = *in++; } *out = 0; if (suffix[0] == '*') { if (! strcmp (suffix, "*link_command")) link_command_spec = spec; else set_spec (suffix + 1, spec); } else { /* Add this pair to the vector. */ compilers = ((struct compiler *) xrealloc (compilers, (n_compilers + 2) * sizeof (struct compiler))); compilers[n_compilers].suffix = suffix; bzero ((char *) compilers[n_compilers].spec, sizeof compilers[n_compilers].spec); compilers[n_compilers].spec[0] = spec; n_compilers++; bzero ((char *) &compilers[n_compilers], sizeof compilers[n_compilers]); } if (*suffix == 0) link_command_spec = spec; } if (link_command_spec == 0) fatal ("spec file has no spec for linking");}/* Record the names of temporary files we tell compilers to write, and delete them at the end of the run. *//* This is the common prefix we use to make temp file names. It is chosen once for each run of this program. It is substituted into a spec by %g. Thus, all temp file names contain this prefix. In practice, all temp file names start with this prefix. This prefix comes from the envvar TMPDIR if it is defined; otherwise, from the P_tmpdir macro if that is defined; otherwise, in /usr/tmp or /tmp; or finally the current directory if all else fails. */static char *temp_filename;/* Length of the prefix. */static int temp_filename_length;/* Define the list of temporary files to delete. */struct temp_file{ char *name; struct temp_file *next;};/* Queue of files to delete on success or failure of compilation. */static struct temp_file *always_delete_queue;/* Queue of files to delete on failure of compilation. */static struct temp_file *failure_delete_queue;/* Record FILENAME as a file to be deleted automatically. ALWAYS_DELETE nonzero means delete it if all compilation succeeds; otherwise delete it in any case. FAIL_DELETE nonzero means delete it if a compilation step fails; otherwise delete it in any case. */static voidrecord_temp_file (filename, always_delete, fail_delete) char *filename; int always_delete; int fail_delete;{ register char *name; name = xmalloc (strlen (filename) + 1); strcpy (name, filename); if (always_delete) { register struct temp_file *temp; for (temp = always_delete_queue; temp; temp = temp->next) if (! strcmp (name, temp->name)) goto already1; temp = (struct temp_file *) xmalloc (sizeof (struct temp_file)); temp->next = always_delete_queue; temp->name = name; always_delete_queue = temp; already1:; } if (fail_delete) { register struct temp_file *temp; for (temp = failure_delete_queue; temp; temp = temp->next) if (! strcmp (name, temp->name)) goto already2; temp = (struct temp_file *) xmalloc (sizeof (struct temp_file)); temp->next = failure_delete_queue; temp->name = name; failure_delete_queue = temp; already2:; }}/* Delete all the temporary files whose names we previously recorded. */static voiddelete_if_ordinary (name) char *name;{ struct stat st;#ifdef DEBUG int i, c; printf ("Delete %s? (y or n) ", name); fflush (stdout); i = getchar (); if (i != '\n') while ((c = getchar ()) != '\n' && c != EOF) ; if (i == 'y' || i == 'Y')#endif /* DEBUG */ if (stat (name, &st) >= 0 && S_ISREG (st.st_mode)) if (unlink (name) < 0) if (verbose_flag) perror_with_name (name);}static voiddelete_temp_files (){ register struct temp_file *temp; for (temp = always_delete_queue; temp; temp = temp->next) delete_if_ordinary (temp->name); always_delete_queue = 0;}/* Delete all the files to be deleted on error. */static voiddelete_failure_queue (){ register struct temp_file *temp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -