Mercurial > hg > CbC > GCC_original
diff gcc/collect-utils.c @ 16:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 84e7813d76e9 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gcc/collect-utils.c Fri Oct 27 22:46:09 2017 +0900 @@ -0,0 +1,228 @@ +/* Utility functions used by tools like collect2 and lto-wrapper. + Copyright (C) 2009-2017 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "intl.h" +#include "diagnostic.h" +#include "obstack.h" +#include "opts.h" +#include "options.h" +#include "simple-object.h" +#include "lto-section-names.h" +#include "collect-utils.h" + +static char *response_file; + +bool debug; +bool verbose; +bool save_temps; + + +/* Notify user of a non-error. */ +void +notice (const char *cmsgid, ...) +{ + va_list ap; + + va_start (ap, cmsgid); + vfprintf (stderr, _(cmsgid), ap); + va_end (ap); +} + +void +fatal_signal (int signum) +{ + signal (signum, SIG_DFL); + utils_cleanup (true); + /* Get the same signal again, this time not handled, + so its normal effect occurs. */ + kill (getpid (), signum); +} + +/* Wait for a process to finish, and exit if a nonzero status is found. */ + +int +collect_wait (const char *prog, struct pex_obj *pex) +{ + int status; + + if (!pex_get_status (pex, 1, &status)) + fatal_error (input_location, "can't get program status: %m"); + pex_free (pex); + + if (response_file && !save_temps) + { + unlink (response_file); + response_file = NULL; + } + + if (status) + { + if (WIFSIGNALED (status)) + { + int sig = WTERMSIG (status); + fatal_error (input_location, "%s terminated with signal %d [%s]%s", + prog, sig, strsignal (sig), + WCOREDUMP (status) ? ", core dumped" : ""); + } + + if (WIFEXITED (status)) + return WEXITSTATUS (status); + } + return 0; +} + +void +do_wait (const char *prog, struct pex_obj *pex) +{ + int ret = collect_wait (prog, pex); + if (ret != 0) + fatal_error (input_location, "%s returned %d exit status", prog, ret); +} + + +/* Execute a program, and wait for the reply. */ + +struct pex_obj * +collect_execute (const char *prog, char **argv, const char *outname, + const char *errname, int flags, bool use_atfile) +{ + struct pex_obj *pex; + const char *errmsg; + int err; + char *response_arg = NULL; + char *response_argv[3]; + + if (use_atfile && argv[0] != NULL) + { + /* If using @file arguments, create a temporary file and put the + contents of argv into it. Then change argv to an array corresponding + to a single argument @FILE, where FILE is the temporary filename. */ + + char **current_argv = argv + 1; + char *argv0 = argv[0]; + int status; + FILE *f; + + /* Note: we assume argv contains at least one element; this is + checked above. */ + + response_file = make_temp_file (""); + + f = fopen (response_file, "w"); + + if (f == NULL) + fatal_error (input_location, "could not open response file %s", + response_file); + + status = writeargv (current_argv, f); + + if (status) + fatal_error (input_location, "could not write to response file %s", + response_file); + + status = fclose (f); + + if (EOF == status) + fatal_error (input_location, "could not close response file %s", + response_file); + + response_arg = concat ("@", response_file, NULL); + response_argv[0] = argv0; + response_argv[1] = response_arg; + response_argv[2] = NULL; + + argv = response_argv; + } + + if (verbose || debug) + { + char **p_argv; + const char *str; + + if (argv[0]) + fprintf (stderr, "%s", argv[0]); + else + notice ("[cannot find %s]", prog); + + for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++) + fprintf (stderr, " %s", str); + + fprintf (stderr, "\n"); + } + + fflush (stdout); + fflush (stderr); + + /* If we cannot find a program we need, complain error. Do this here + since we might not end up needing something that we could not find. */ + + if (argv[0] == 0) + fatal_error (input_location, "cannot find '%s'", prog); + + pex = pex_init (0, "collect2", NULL); + if (pex == NULL) + fatal_error (input_location, "pex_init failed: %m"); + + errmsg = pex_run (pex, flags, argv[0], argv, outname, + errname, &err); + if (errmsg != NULL) + { + if (err != 0) + { + errno = err; + fatal_error (input_location, "%s: %m", _(errmsg)); + } + else + fatal_error (input_location, errmsg); + } + + free (response_arg); + + return pex; +} + +void +fork_execute (const char *prog, char **argv, bool use_atfile) +{ + struct pex_obj *pex; + + pex = collect_execute (prog, argv, NULL, NULL, + PEX_LAST | PEX_SEARCH, use_atfile); + do_wait (prog, pex); +} + +/* Delete tempfiles. */ + +void +utils_cleanup (bool from_signal) +{ + static bool cleanup_done = false; + + if (cleanup_done) + return; + + /* Setting cleanup_done prevents an infinite loop if one of the + calls to maybe_unlink fails. */ + cleanup_done = true; + + tool_cleanup (from_signal); +}