This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH: Improve native Windows support on csl-arm-branch
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 23 Dec 2003 09:20:10 -0800
- Subject: PATCH: Improve native Windows support on csl-arm-branch
- Reply-to: mark at codesourcery dot com
This patch incorporates some work done mostly by Zack on the
csl-arm-branch. It makes GCC work much better when built as a native
Windows (rather than Cygwin) application. This patch is being
installed only on the csl-arm-branch because DJ didn't want the last
version in libiberty in its current form, and we've not done anything
since that point that would be likely to overcome DJ's objections.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2003-12-23 Zack Weinberg <zack@codesourcery.com>
Nathan Sidwell <nathan@codesourcery.com>
Mark Mitchell <mark@codesourcery.com>
* collect2.c (windows.h): Include.
(dup2): Remove.
(handler): Change prototype.
(unhandled_filter): New funciton.
(install_handlers): Likewise.
(disable_break): Likewise.
(enable_break): Likewise.
(main): Call install_handlers rather than signal directly.
(collect_execute): Use pexec.
(scan_prog_file): Likewise.
(scan_libraries): Likewise.
2003-12-23 Zack Weinberg <zack@codesourcery.com>
Nathan Sidwell <nathan@codesourcery.com>
Mark Mitchell <mark@codesourcery.com>
* libiberty.h (pmkpipe): New function.
(pexec): Likewise.
(pexec_set_program_name): Likewise.
(WIFSIGNALED): Define.
(WTERMSIG): Likewise.
(WIFEXITED): Likewise.
(WEXITSTATUS): Likewise.
(WSTOPSIG): Likewise.
(WCOREDUMP): Likewise.
2003-12-23 Zack Weinberg <zack@codesourcery.com>
Nathan Sidwell <nathan@codesourcery.com>
Mark Mitchell <mark@codesourcery.com>
* pex-common.c (STDERR_FILE_NO): Define.
* pex-win32.c: Rework extensively.
Index: gcc/collect2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/collect2.c,v
retrieving revision 1.154
diff -c -5 -p -r1.154 collect2.c
*** gcc/collect2.c 17 Oct 2003 11:27:13 -0000 1.154
--- gcc/collect2.c 23 Dec 2003 17:16:29 -0000
*************** Software Foundation, 59 Temple Place - S
*** 28,54 ****
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
! #include <signal.h>
! #if ! defined( SIGCHLD ) && defined( SIGCLD )
! # define SIGCHLD SIGCLD
! #endif
!
! #ifdef vfork /* Autoconf may define this to fork for us. */
! # define VFORK_STRING "fork"
#else
! # define VFORK_STRING "vfork"
! #endif
! #ifdef HAVE_VFORK_H
! #include <vfork.h>
! #endif
! #ifdef VMS
! #define vfork() (decc$$alloc_vfork_blocks() >= 0 ? \
! lib$get_current_invo_context(decc$$get_vfork_jmpbuf()) : -1)
! #endif /* VMS */
#ifndef LIBRARY_PATH_ENV
#define LIBRARY_PATH_ENV "LIBRARY_PATH"
#endif
--- 28,46 ----
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
! #ifdef _WIN32
! # define WIN32_LEAN_AND_MEAN
! # include <windows.h>
#else
! # include <signal.h>
! # if ! defined( SIGCHLD ) && defined( SIGCLD )
! # define SIGCHLD SIGCLD
! # endif
! #endif
#ifndef LIBRARY_PATH_ENV
#define LIBRARY_PATH_ENV "LIBRARY_PATH"
#endif
*************** static struct path_prefix libpath_lib_di
*** 247,257 ****
static struct path_prefix *libpaths[3] = {&cmdline_lib_dirs,
&libpath_lib_dirs, NULL};
static const char *const libexts[3] = {"a", "so", NULL}; /* possible library extensions */
#endif
! static void handler (int);
static int is_ctor_dtor (const char *);
static char *find_a_file (struct path_prefix *, const char *);
static void add_prefix (struct path_prefix *, const char *);
static void prefix_from_env (const char *, struct path_prefix *);
static void prefix_from_string (const char *, struct path_prefix *);
--- 239,259 ----
static struct path_prefix *libpaths[3] = {&cmdline_lib_dirs,
&libpath_lib_dirs, NULL};
static const char *const libexts[3] = {"a", "so", NULL}; /* possible library extensions */
#endif
! static void clean_up_temp_files (void);
! #ifdef _WIN32
! static BOOL WINAPI handler (DWORD);
! static LONG unhanded_filter (LPEXCEPTION_POINTERS);
! #else
! static void handler (int);
! #endif
! static void install_handlers (void);
! static void disable_break (void);
! static void enable_break (void);
!
static int is_ctor_dtor (const char *);
static char *find_a_file (struct path_prefix *, const char *);
static void add_prefix (struct path_prefix *, const char *);
static void prefix_from_env (const char *, struct path_prefix *);
static void prefix_from_string (const char *, struct path_prefix *);
*************** static int is_in_list (const char *, str
*** 288,317 ****
static void write_aix_file (FILE *, struct id *);
static char *resolve_lib_name (const char *);
#endif
static char *extract_string (const char **);
- #ifndef HAVE_DUP2
- static int
- dup2 (int oldfd, int newfd)
- {
- int fdtmp[256];
- int fdx = 0;
- int fd;
-
- if (oldfd == newfd)
- return oldfd;
- close (newfd);
- while ((fd = dup (oldfd)) != newfd && fd >= 0) /* good enough for low fd's */
- fdtmp[fdx++] = fd;
- while (fdx > 0)
- close (fdtmp[--fdx]);
-
- return fd;
- }
- #endif /* ! HAVE_DUP2 */
-
/* Delete tempfiles and exit function. */
void
collect_exit (int status)
{
--- 290,299 ----
*************** fancy_abort (void)
*** 405,415 ****
{
fatal ("internal error");
}
static void
! handler (int signo)
{
if (c_file != 0 && c_file[0])
maybe_unlink (c_file);
if (o_file != 0 && o_file[0])
--- 387,397 ----
{
fatal ("internal error");
}
static void
! clean_up_temp_files (void)
{
if (c_file != 0 && c_file[0])
maybe_unlink (c_file);
if (o_file != 0 && o_file[0])
*************** handler (int signo)
*** 420,434 ****
--- 402,522 ----
#ifdef COLLECT_EXPORT_LIST
if (export_file != 0 && export_file[0])
maybe_unlink (export_file);
#endif
+ }
+ /* Signal handling needs to be drastically different between Windows
+ and Unix. */
+ #ifdef _WIN32
+
+ static BOOL WINAPI
+ handler (DWORD signo ATTRIBUTE_UNUSED)
+ {
+ clean_up_temp_files ();
+ return FALSE; /* not handled - default handler will terminate process */
+ }
+
+ static LONG
+ unhandled_filter (LPEXCEPTION_POINTERS pointers ATTRIBUTE_UNUSED)
+ {
+ clean_up_temp_files ();
+ return EXCEPTION_CONTINUE_SEARCH; /* carry on and terminate process */
+ }
+
+
+ static void
+ install_handlers (void)
+ {
+ SetConsoleCtrlHandler (handler, TRUE);
+ /* This is not really the right way to do this; in fact I'm not
+ sure it will work. But it might. */
+ SetUnhandledExceptionFilter (unhandled_filter);
+ }
+
+ static void
+ disable_break (void)
+ {
+ /* This only works on Windows NT, and only disables CTRL-C;
+ CTRL-BREAK is not disabled (but does get caught by the handler). */
+ if (!(GetVersion() & 0x80000000))
+ SetConsoleCtrlHandler (NULL, TRUE);
+ }
+
+ static void
+ enable_break (void)
+ {
+ if (!(GetVersion() & 0x80000000))
+ SetConsoleCtrlHandler (NULL, FALSE);
+ }
+
+ #else /* not _WIN32 */
+
+ static void
+ handler (int signo)
+ {
+ clean_up_temp_files ();
signal (signo, SIG_DFL);
kill (getpid (), signo);
}
+ static void
+ install_handlers ()
+ {
+ #ifdef SIGQUIT
+ if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
+ signal (SIGQUIT, handler);
+ #endif
+ if (signal (SIGINT, SIG_IGN) != SIG_IGN)
+ signal (SIGINT, handler);
+ #ifdef SIGALRM
+ if (signal (SIGALRM, SIG_IGN) != SIG_IGN)
+ signal (SIGALRM, handler);
+ #endif
+ #ifdef SIGHUP
+ if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
+ signal (SIGHUP, handler);
+ #endif
+ if (signal (SIGSEGV, SIG_IGN) != SIG_IGN)
+ signal (SIGSEGV, handler);
+ #ifdef SIGBUS
+ if (signal (SIGBUS, SIG_IGN) != SIG_IGN)
+ signal (SIGBUS, handler);
+ #endif
+ #ifdef SIGCHLD
+ /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
+ receive the signal. A different setting is inheritable */
+ signal (SIGCHLD, SIG_DFL);
+ #endif
+ }
+
+ static void (*int_handler) PARAMS ((int));
+ #ifdef SIGQUIT
+ static void (*quit_handler) PARAMS ((int));
+ #endif
+
+ static void
+ disable_break ()
+ {
+ int_handler = (void (*) PARAMS ((int))) signal (SIGINT, SIG_IGN);
+ #ifdef SIGQUIT
+ quit_handler = (void (*) PARAMS ((int))) signal (SIGQUIT, SIG_IGN);
+ #endif
+ }
+
+ static void
+ enable_break ()
+ {
+ signal (SIGINT, int_handler);
+ #ifdef SIGQUIT
+ signal (SIGQUIT, quit_handler);
+ #endif
+ }
+
+ #endif /* not _WIN32 */
+
int
file_exists (const char *name)
{
return access (name, R_OK) == 0;
*************** main (int argc, char **argv)
*** 819,844 ****
char **object_lst;
const char **object;
int first_file;
int num_c_args = argc+9;
no_demangle = !! getenv ("COLLECT_NO_DEMANGLE");
/* Suppress demangling by the real linker, which may be broken. */
putenv (xstrdup ("COLLECT_NO_DEMANGLE="));
#if defined (COLLECT2_HOST_INITIALIZATION)
/* Perform system dependent initialization, if necessary. */
COLLECT2_HOST_INITIALIZATION;
#endif
- #ifdef SIGCHLD
- /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
- receive the signal. A different setting is inheritable */
- signal (SIGCHLD, SIG_DFL);
- #endif
-
gcc_init_libintl ();
/* Do not invoke xcalloc before this point, since locale needs to be
set first, in case a diagnostic is issued. */
--- 907,928 ----
char **object_lst;
const char **object;
int first_file;
int num_c_args = argc+9;
+ pexec_set_program_name (argv[0]);
+
no_demangle = !! getenv ("COLLECT_NO_DEMANGLE");
/* Suppress demangling by the real linker, which may be broken. */
putenv (xstrdup ("COLLECT_NO_DEMANGLE="));
#if defined (COLLECT2_HOST_INITIALIZATION)
/* Perform system dependent initialization, if necessary. */
COLLECT2_HOST_INITIALIZATION;
#endif
gcc_init_libintl ();
/* Do not invoke xcalloc before this point, since locale needs to be
set first, in case a diagnostic is issued. */
*************** main (int argc, char **argv)
*** 890,919 ****
c_ptr = (const char **) (c_argv = xcalloc (sizeof (char *), num_c_args));
if (argc < 2)
fatal ("no arguments");
! #ifdef SIGQUIT
! if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
! signal (SIGQUIT, handler);
! #endif
! if (signal (SIGINT, SIG_IGN) != SIG_IGN)
! signal (SIGINT, handler);
! #ifdef SIGALRM
! if (signal (SIGALRM, SIG_IGN) != SIG_IGN)
! signal (SIGALRM, handler);
! #endif
! #ifdef SIGHUP
! if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
! signal (SIGHUP, handler);
! #endif
! if (signal (SIGSEGV, SIG_IGN) != SIG_IGN)
! signal (SIGSEGV, handler);
! #ifdef SIGBUS
! if (signal (SIGBUS, SIG_IGN) != SIG_IGN)
! signal (SIGBUS, handler);
! #endif
/* Extract COMPILER_PATH and PATH into our prefix list. */
prefix_from_env ("COMPILER_PATH", &cpath);
prefix_from_env ("PATH", &path);
--- 974,984 ----
c_ptr = (const char **) (c_argv = xcalloc (sizeof (char *), num_c_args));
if (argc < 2)
fatal ("no arguments");
! install_handlers ();
/* Extract COMPILER_PATH and PATH into our prefix list. */
prefix_from_env ("COMPILER_PATH", &cpath);
prefix_from_env ("PATH", &path);
*************** do_wait (const char *prog)
*** 1490,1504 ****
/* Execute a program, and wait for the reply. */
void
collect_execute (const char *prog, char **argv, const char *redir)
{
- char *errmsg_fmt;
- char *errmsg_arg;
int redir_handle = -1;
- int stdout_save = -1;
- int stderr_save = -1;
if (vflag || debug)
{
char **p_argv;
const char *str;
--- 1555,1565 ----
*************** collect_execute (const char *prog, char
*** 1512,1564 ****
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 ("cannot find `%s'", prog);
if (redir)
! {
! /* Open response file. */
! redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT);
!
! /* Duplicate the stdout and stderr file handles
! so they can be restored later. */
! stdout_save = dup (STDOUT_FILENO);
! if (stdout_save == -1)
! fatal_perror ("redirecting stdout: %s", redir);
! stderr_save = dup (STDERR_FILENO);
! if (stderr_save == -1)
! fatal_perror ("redirecting stdout: %s", redir);
!
! /* Redirect stdout & stderr to our response file. */
! dup2 (redir_handle, STDOUT_FILENO);
! dup2 (redir_handle, STDERR_FILENO);
! }
!
! pid = pexecute (argv[0], argv, argv[0], NULL, &errmsg_fmt, &errmsg_arg,
! (PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH));
!
! if (redir)
! {
! /* Restore stdout and stderr to their previous settings. */
! dup2 (stdout_save, STDOUT_FILENO);
! dup2 (stderr_save, STDERR_FILENO);
! /* Close response file. */
! close (redir_handle);
! }
! if (pid == -1)
! fatal_perror (errmsg_fmt, errmsg_arg);
}
static void
fork_execute (const char *prog, char **argv)
{
--- 1573,1595 ----
fprintf (stderr, " %s", str);
fprintf (stderr, "\n");
}
/* 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 ("cannot find `%s'", prog);
if (redir)
! redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT);
! pid = pexec (argv[0], argv, 1, -1, redir_handle, -1);
! if (pid == -1)
! fatal_perror ("pexec");
}
static void
fork_execute (const char *prog, char **argv)
{
*************** write_aix_file (FILE *stream, struct id
*** 1982,1993 ****
destructor table has the same format, and begins at __DTOR_LIST__. */
static void
scan_prog_file (const char *prog_name, enum pass which_pass)
{
- void (*int_handler) (int);
- void (*quit_handler) (int);
char *real_nm_argv[4];
const char **nm_argv = (const char **) real_nm_argv;
int argc = 0;
int pipe_fd[2];
char *p, buf[1024];
--- 2013,2022 ----
*************** scan_prog_file (const char *prog_name, e
*** 2005,2015 ****
nm_argv[argc++] = NM_FLAGS;
nm_argv[argc++] = prog_name;
nm_argv[argc++] = (char *) 0;
! if (pipe (pipe_fd) < 0)
fatal_perror ("pipe");
inf = fdopen (pipe_fd[0], "r");
if (inf == (FILE *) 0)
fatal_perror ("fdopen");
--- 2034,2044 ----
nm_argv[argc++] = NM_FLAGS;
nm_argv[argc++] = prog_name;
nm_argv[argc++] = (char *) 0;
! if (pmkpipe (pipe_fd) < 0)
fatal_perror ("pipe");
inf = fdopen (pipe_fd[0], "r");
if (inf == (FILE *) 0)
fatal_perror ("fdopen");
*************** scan_prog_file (const char *prog_name, e
*** 2024,2065 ****
fprintf (stderr, " %s", str);
fprintf (stderr, "\n");
}
- fflush (stdout);
- fflush (stderr);
-
/* Spawn child nm on pipe. */
! pid = vfork ();
if (pid == -1)
! fatal_perror (VFORK_STRING);
!
! if (pid == 0) /* child context */
! {
! /* setup stdout */
! if (dup2 (pipe_fd[1], 1) < 0)
! fatal_perror ("dup2 %d 1", pipe_fd[1]);
!
! if (close (pipe_fd[0]) < 0)
! fatal_perror ("close %d", pipe_fd[0]);
!
! if (close (pipe_fd[1]) < 0)
! fatal_perror ("close %d", pipe_fd[1]);
!
! execv (nm_file_name, real_nm_argv);
! fatal_perror ("execv %s", nm_file_name);
! }
!
/* Parent context from here on. */
! int_handler = (void (*) (int)) signal (SIGINT, SIG_IGN);
! #ifdef SIGQUIT
! quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN);
! #endif
!
! if (close (pipe_fd[1]) < 0)
! fatal_perror ("close %d", pipe_fd[1]);
if (debug)
fprintf (stderr, "\nnm output with constructors/destructors.\n");
/* Read each line of nm output. */
--- 2053,2070 ----
fprintf (stderr, " %s", str);
fprintf (stderr, "\n");
}
/* Spawn child nm on pipe. */
! pid = pexec (nm_file_name, real_nm_argv, 0, -1, pipe_fd[1], -1);
!
if (pid == -1)
! fatal_perror ("pexec");
!
/* Parent context from here on. */
! disable_break ();
if (debug)
fprintf (stderr, "\nnm output with constructors/destructors.\n");
/* Read each line of nm output. */
*************** scan_prog_file (const char *prog_name, e
*** 2134,2147 ****
if (fclose (inf) != 0)
fatal_perror ("fclose");
do_wait (nm_file_name);
! signal (SIGINT, int_handler);
! #ifdef SIGQUIT
! signal (SIGQUIT, quit_handler);
! #endif
}
#if SUNOS4_SHARED_LIBRARIES
/* Routines to scan the SunOS 4 _DYNAMIC structure to find shared libraries
--- 2139,2149 ----
if (fclose (inf) != 0)
fatal_perror ("fclose");
do_wait (nm_file_name);
! enable_break ();
}
#if SUNOS4_SHARED_LIBRARIES
/* Routines to scan the SunOS 4 _DYNAMIC structure to find shared libraries
*************** scan_libraries (const char *prog_name)
*** 2414,2425 ****
static void
scan_libraries (const char *prog_name)
{
static struct head libraries; /* list of shared libraries found */
struct id *list;
- void (*int_handler) (int);
- void (*quit_handler) (int);
char *real_ldd_argv[4];
const char **ldd_argv = (const char **) real_ldd_argv;
int argc = 0;
int pipe_fd[2];
char buf[1024];
--- 2416,2425 ----
*************** scan_libraries (const char *prog_name)
*** 2434,2444 ****
ldd_argv[argc++] = ldd_file_name;
ldd_argv[argc++] = prog_name;
ldd_argv[argc++] = (char *) 0;
! if (pipe (pipe_fd) < 0)
fatal_perror ("pipe");
inf = fdopen (pipe_fd[0], "r");
if (inf == (FILE *) 0)
fatal_perror ("fdopen");
--- 2434,2444 ----
ldd_argv[argc++] = ldd_file_name;
ldd_argv[argc++] = prog_name;
ldd_argv[argc++] = (char *) 0;
! if (pmkpipe (pipe_fd) < 0)
fatal_perror ("pipe");
inf = fdopen (pipe_fd[0], "r");
if (inf == (FILE *) 0)
fatal_perror ("fdopen");
*************** scan_libraries (const char *prog_name)
*** 2453,2494 ****
fprintf (stderr, " %s", str);
fprintf (stderr, "\n");
}
- fflush (stdout);
- fflush (stderr);
-
/* Spawn child ldd on pipe. */
! pid = vfork ();
! if (pid == -1)
! fatal_perror (VFORK_STRING);
!
! if (pid == 0) /* child context */
! {
! /* setup stdout */
! if (dup2 (pipe_fd[1], 1) < 0)
! fatal_perror ("dup2 %d 1", pipe_fd[1]);
!
! if (close (pipe_fd[0]) < 0)
! fatal_perror ("close %d", pipe_fd[0]);
!
! if (close (pipe_fd[1]) < 0)
! fatal_perror ("close %d", pipe_fd[1]);
!
! execv (ldd_file_name, real_ldd_argv);
! fatal_perror ("execv %s", ldd_file_name);
! }
/* Parent context from here on. */
! int_handler = (void (*) (int))) signal (SIGINT, SIG_IGN;
! #ifdef SIGQUIT
! quit_handler = (void (*) (int))) signal (SIGQUIT, SIG_IGN;
! #endif
!
! if (close (pipe_fd[1]) < 0)
! fatal_perror ("close %d", pipe_fd[1]);
if (debug)
notice ("\nldd output with constructors/destructors.\n");
/* Read each line of ldd output. */
--- 2453,2470 ----
fprintf (stderr, " %s", str);
fprintf (stderr, "\n");
}
/* Spawn child ldd on pipe. */
! pexecute_pid = pexec (ldd_file_name, real_ldd_argv, 0, -1, infpipe[1], -1);
!
! if (pexecute_pid == -1)
! fatal_perror ("pexec");
/* Parent context from here on. */
! disable_break ();
if (debug)
notice ("\nldd output with constructors/destructors.\n");
/* Read each line of ldd output. */
*************** scan_libraries (const char *prog_name)
*** 2527,2541 ****
if (fclose (inf) != 0)
fatal_perror ("fclose");
do_wait (ldd_file_name);
! signal (SIGINT, int_handler);
! #ifdef SIGQUIT
! signal (SIGQUIT, quit_handler);
! #endif
!
/* now iterate through the library list adding their symbols to
the list. */
for (list = libraries.first; list; list = list->next)
scan_prog_file (list->name, PASS_LIB);
}
--- 2503,2513 ----
if (fclose (inf) != 0)
fatal_perror ("fclose");
do_wait (ldd_file_name);
! enable_break ();
/* now iterate through the library list adding their symbols to
the list. */
for (list = libraries.first; list; list = list->next)
scan_prog_file (list->name, PASS_LIB);
}
Index: include/libiberty.h
===================================================================
RCS file: /cvs/gcc/gcc/include/libiberty.h,v
retrieving revision 1.35
diff -c -5 -p -r1.35 libiberty.h
*** include/libiberty.h 15 May 2003 19:02:12 -0000 1.35
--- include/libiberty.h 23 Dec 2003 17:16:30 -0000
*************** extern char **dupargv PARAMS ((char **))
*** 72,82 ****
undefined, we haven't run the autoconf check so provide the
declaration without arguments. If it is 0, we checked and failed
to find the declaration so provide a fully prototyped one. If it
is 1, we found it so don't provide any declaration at all. */
#if !HAVE_DECL_BASENAME
! #if defined (__GNU_LIBRARY__ ) || defined (__linux__) || defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__NetBSD__) || defined (__CYGWIN__) || defined (__CYGWIN32__) || defined (HAVE_DECL_BASENAME)
extern char *basename PARAMS ((const char *));
#else
extern char *basename ();
#endif
#endif
--- 72,82 ----
undefined, we haven't run the autoconf check so provide the
declaration without arguments. If it is 0, we checked and failed
to find the declaration so provide a fully prototyped one. If it
is 1, we found it so don't provide any declaration at all. */
#if !HAVE_DECL_BASENAME
! #if defined (__GNU_LIBRARY__ ) || defined (__linux__) || defined (__FreeBSD__) || defined (__OpenBSD__) || defined(__NetBSD__) || defined (__CYGWIN__) || defined (__CYGWIN32__) || defined (__sun__) || defined (HAVE_DECL_BASENAME)
extern char *basename PARAMS ((const char *));
#else
extern char *basename ();
#endif
#endif
*************** extern void hex_init PARAMS ((void));
*** 272,284 ****
/* Execute a program. */
extern int pexecute PARAMS ((const char *, char * const *, const char *,
const char *, char **, char **, int));
! /* Wait for pexecute to finish. */
extern int pwait PARAMS ((int, int *, int));
#if !HAVE_DECL_ASPRINTF
/* Like sprintf but provides a pointer to malloc'd storage, which must
be freed by the caller. */
--- 272,339 ----
/* Execute a program. */
extern int pexecute PARAMS ((const char *, char * const *, const char *,
const char *, char **, char **, int));
! /* Slightly lower level routines which are more flexible than pexecute: */
! extern int pmkpipe PARAMS ((int[2]));
!
! extern int pexec PARAMS ((const char *, char * const *, int, int, int, int));
!
! /* Wait for a process created by pexecute or pexec to finish. */
extern int pwait PARAMS ((int, int *, int));
+
+ /* Set the program name used for error messages by pexec. */
+ extern void pexec_set_program_name PARAMS ((const char *));
+
+ #if !defined(_WIN32) || defined(__CYGWIN__)
+
+ #ifndef WIFSIGNALED
+ #define WIFSIGNALED(S) (((S) & 0xff) != 0 && ((S) & 0xff) != 0x7f)
+ #endif
+ #ifndef WTERMSIG
+ #define WTERMSIG(S) ((S) & 0x7f)
+ #endif
+ #ifndef WIFEXITED
+ #define WIFEXITED(S) (((S) & 0xff) == 0)
+ #endif
+ #ifndef WEXITSTATUS
+ #define WEXITSTATUS(S) (((S) & 0xff00) >> 8)
+ #endif
+ #ifndef WSTOPSIG
+ #define WSTOPSIG WEXITSTATUS
+ #endif
+ #ifndef WCOREDUMP
+ #define WCOREDUMP(S) ((S) & WCOREFLG)
+ #endif
+ #ifndef WCOREFLG
+ #define WCOREFLG 0200
+ #endif
+
+ #else /* defined(_WIN32) && ! defined(__CYGWIN__) */
+
+ #ifndef WIFSIGNALED
+ #define WIFSIGNALED(S) ((void)(S), 0)
+ #endif
+ #ifndef WTERMSIG
+ #define WTERMSIG(S) ((void)(S), 0)
+ #endif
+ #ifndef WIFEXITED
+ #define WIFEXITED(S) ((void)(S), 1)
+ #endif
+ #ifndef WEXITSTATUS
+ #define WEXITSTATUS(S) (S)
+ #endif
+ #ifndef WSTOPSIG
+ #define WSTOPSIG WEXITSTATUS
+ #endif
+ #ifndef WCOREDUMP
+ #define WCOREDUMP(S) ((void)(S), 0)
+ #endif
+
+ #endif
#if !HAVE_DECL_ASPRINTF
/* Like sprintf but provides a pointer to malloc'd storage, which must
be freed by the caller. */
Index: libiberty/pex-common.h
===================================================================
RCS file: /cvs/gcc/gcc/libiberty/pex-common.h,v
retrieving revision 1.1
diff -c -5 -p -r1.1 pex-common.h
*** libiberty/pex-common.h 24 Jan 2003 20:02:11 -0000 1.1
--- libiberty/pex-common.h 23 Dec 2003 17:16:30 -0000
*************** Boston, MA 02111-1307, USA. */
*** 31,40 ****
--- 31,43 ----
#define STDIN_FILE_NO 0
/* stdout file number. */
#define STDOUT_FILE_NO 1
+ /* stderr file number. */
+ #define STDERR_FILE_NO 2
+
/* value of `pipe': port index for reading. */
#define READ_PORT 0
/* value of `pipe': port index for writing. */
#define WRITE_PORT 1
Index: libiberty/pex-win32.c
===================================================================
RCS file: /cvs/gcc/gcc/libiberty/pex-win32.c,v
retrieving revision 1.3
diff -c -5 -p -r1.3 pex-win32.c
*** libiberty/pex-win32.c 5 Jul 2003 00:52:07 -0000 1.3
--- libiberty/pex-win32.c 23 Dec 2003 17:16:30 -0000
*************** License along with libiberty; see the fi
*** 19,250 ****
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "pex-common.h"
! #ifdef HAVE_STRING_H
! #include <string.h>
! #endif
! #ifdef HAVE_UNISTD_H
! #include <unistd.h>
! #endif
! #ifdef HAVE_SYS_WAIT_H
! #include <sys/wait.h>
! #endif
!
! #include <process.h>
#include <io.h>
#include <fcntl.h>
! #include <signal.h>
! /* mingw32 headers may not define the following. */
! #ifndef _P_WAIT
! # define _P_WAIT 0
! # define _P_NOWAIT 1
! # define _P_OVERLAY 2
! # define _P_NOWAITO 3
! # define _P_DETACH 4
!
! # define WAIT_CHILD 0
! # define WAIT_GRANDCHILD 1
! #endif
!
! /* This is a kludge to get around the Microsoft C spawn functions' propensity
! to remove the outermost set of double quotes from all arguments. */
!
! static const char * const *
! fix_argv (argvec)
! char **argvec;
! {
! int i;
! char * command0 = argvec[0];
!
! /* Ensure that the executable pathname uses Win32 backslashes. */
! for (; *command0 != '\0'; command0++)
! if (*command0 == '/')
! *command0 = '\\';
!
! for (i = 1; argvec[i] != 0; i++)
{
! int len, j;
! char *temp, *newtemp;
! temp = argvec[i];
! len = strlen (temp);
! for (j = 0; j < len; j++)
! {
! if (temp[j] == '"')
! {
! newtemp = xmalloc (len + 2);
! strncpy (newtemp, temp, j);
! newtemp [j] = '\\';
! strncpy (&newtemp [j+1], &temp [j], len-j);
! newtemp [len+1] = 0;
! temp = newtemp;
! len++;
! j++;
! }
! }
!
! argvec[i] = temp;
! }
!
! for (i = 0; argvec[i] != 0; i++)
! {
! if (strpbrk (argvec[i], " \t"))
! {
! int len, trailing_backslash;
! char *temp;
!
! len = strlen (argvec[i]);
! trailing_backslash = 0;
!
! /* There is an added complication when an arg with embedded white
! space ends in a backslash (such as in the case of -iprefix arg
! passed to cpp). The resulting quoted strings gets misinterpreted
! by the command interpreter -- it thinks that the ending quote
! is escaped by the trailing backslash and things get confused.
! We handle this case by escaping the trailing backslash, provided
! it was not escaped in the first place. */
! if (len > 1
! && argvec[i][len-1] == '\\'
! && argvec[i][len-2] != '\\')
! {
! trailing_backslash = 1;
! ++len; /* to escape the final backslash. */
! }
!
! len += 2; /* and for the enclosing quotes. */
!
! temp = xmalloc (len + 1);
! temp[0] = '"';
! strcpy (temp + 1, argvec[i]);
! if (trailing_backslash)
! temp[len-2] = '\\';
! temp[len-1] = '"';
! temp[len] = '\0';
! argvec[i] = temp;
}
}
! return (const char * const *) argvec;
}
- /* Win32 supports pipes */
int
pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
const char *program;
char * const *argv;
const char *this_pname ATTRIBUTE_UNUSED;
const char *temp_base ATTRIBUTE_UNUSED;
char **errmsg_fmt, **errmsg_arg;
int flags;
{
int pid;
! int pdes[2];
! int org_stdin = -1;
! int org_stdout = -1;
! int input_desc, output_desc;
!
! /* Pipe waiting from last process, to be used as input for the next one.
! Value is STDIN_FILE_NO if no pipe is waiting
! (i.e. the next command is the first of a group). */
! static int last_pipe_input;
! /* If this is the first process, initialize. */
if (flags & PEXECUTE_FIRST)
! last_pipe_input = STDIN_FILE_NO;
! input_desc = last_pipe_input;
! /* If this isn't the last process, make a pipe for its output,
! and record it as waiting to be the input to the next process. */
! if (! (flags & PEXECUTE_LAST))
{
! if (_pipe (pdes, 256, O_BINARY) < 0)
{
*errmsg_fmt = "pipe";
*errmsg_arg = NULL;
return -1;
}
! output_desc = pdes[WRITE_PORT];
! last_pipe_input = pdes[READ_PORT];
! }
! else
! {
! /* Last process. */
! output_desc = STDOUT_FILE_NO;
! last_pipe_input = STDIN_FILE_NO;
! }
!
! if (input_desc != STDIN_FILE_NO)
! {
! org_stdin = dup (STDIN_FILE_NO);
! dup2 (input_desc, STDIN_FILE_NO);
! close (input_desc);
}
! if (output_desc != STDOUT_FILE_NO)
! {
! org_stdout = dup (STDOUT_FILE_NO);
! dup2 (output_desc, STDOUT_FILE_NO);
! close (output_desc);
! }
! pid = (flags & PEXECUTE_SEARCH ? _spawnvp : _spawnv)
! (_P_NOWAIT, program, fix_argv(argv));
! if (input_desc != STDIN_FILE_NO)
! {
! dup2 (org_stdin, STDIN_FILE_NO);
! close (org_stdin);
! }
! if (output_desc != STDOUT_FILE_NO)
! {
! dup2 (org_stdout, STDOUT_FILE_NO);
! close (org_stdout);
! }
if (pid == -1)
{
! *errmsg_fmt = install_error_msg;
! *errmsg_arg = (char*) program;
! return -1;
}
return pid;
}
- /* MS CRTDLL doesn't return enough information in status to decide if the
- child exited due to a signal or not, rather it simply returns an
- integer with the exit code of the child; eg., if the child exited with
- an abort() call and didn't have a handler for SIGABRT, it simply returns
- with status = 3. We fix the status code to conform to the usual WIF*
- macros. Note that WIFSIGNALED will never be true under CRTDLL. */
-
int
pwait (pid, status, flags)
int pid;
int *status;
int flags ATTRIBUTE_UNUSED;
{
! int termstat;
!
! pid = _cwait (&termstat, pid, WAIT_CHILD);
!
! /* ??? Here's an opportunity to canonicalize the values in STATUS.
! Needed? */
!
! /* cwait returns the child process exit code in termstat.
! A value of 3 indicates that the child caught a signal, but not
! which one. Since only SIGABRT, SIGFPE and SIGINT do anything, we
! report SIGABRT. */
! if (termstat == 3)
! *status = SIGABRT;
! else
! *status = (((termstat) & 0xff) << 8);
return pid;
}
--- 19,413 ----
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "pex-common.h"
! #define WIN32_LEAN_AND_MEAN
! #include <windows.h>
#include <io.h>
#include <fcntl.h>
! #include <string.h>
! #include <stdlib.h>
! static const char *this_program;
! #define xclose(fd) do { \
! if (fd != -1) \
! { \
! _close (fd); \
! fd = -1; \
! } \
! } while (0)
!
! /* Returns a string containing a text error message, after a Windows
! "system call" failed. Caller is responsible for deallocating it
! (with LocalFree()). */
! static char *
! get_last_error_as_text ()
! {
! DWORD last_error = GetLastError();
! LPSTR result;
!
! /* We assume the error message belongs to 'the system' as opposed
! to some module (which we would have to load, and we don't know
! which one it is). */
! DWORD flags = (FORMAT_MESSAGE_ALLOCATE_BUFFER
! | FORMAT_MESSAGE_IGNORE_INSERTS
! | FORMAT_MESSAGE_FROM_SYSTEM);
!
! /* Default language. */
! DWORD langid = MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT);
!
! /* Yes, you are supposed to cast LPSTR* to LPSTR in the fifth
! argument. This interface is intrinsically type-unsafe. */
! FormatMessageA(flags, 0, last_error, langid, (LPSTR) &result, 0, 0);
!
! return result;
! }
!
! static char *
! argv_to_cmdline(argv)
! char *const *argv;
! {
! char *cmdline;
! char *p;
! size_t cmdline_len;
! int i, j;
!
! cmdline_len = 0;
! for (i = 0; argv[i]; i++)
! {
! /* We quote every last argument. This simplifies the problem;
! we need only escape embedded double-quote and backslash
! characters. */
! for (j = 0; argv[i][j]; j++)
! if (argv[i][j] == '\\' || argv[i][j] == '"')
! cmdline_len++;
! cmdline_len += j;
! cmdline_len += 3; /* for leading and trailing quotes and space */
! }
!
! cmdline = xmalloc (cmdline_len);
! p = cmdline;
! for (i = 0; argv[i]; i++)
{
! *p++ = '"';
! for (j = 0; argv[i][j]; j++)
! {
! if (argv[i][j] == '\\' || argv[i][j] == '"')
! *p++ = '\\';
! *p++ = argv[i][j];
! }
! *p++ = '"';
! *p++ = ' ';
! }
! p[-1] = '\0';
! return cmdline;
! }
! static const char *const
! std_suffixes[] = {
! ".com",
! ".exe",
! ".bat",
! ".cmd",
! 0
! };
! static const char *const
! no_suffixes[] = {
! "",
! 0
! };
! static char *
! find_executable (program, search)
! const char *program;
! int search;
! {
! char *full_executable;
! char *e;
! size_t fe_len;
! const char *path = 0;
! const char *const *ext;
! const char *p, *q;
! size_t proglen = strlen (program);
! int has_extension = !!strchr (program, '.');
! int has_slash = (strchr (program, '/') || strchr (program, '\\'));
! HANDLE h;
!
! if (has_slash)
! search = 0;
!
! if (search)
! path = getenv ("PATH");
! if (!path)
! path = "";
!
! fe_len = 0;
! for (p = path; *p; p = q)
! {
! q = p;
! while (*q != ';' && *q != '\0')
! q++;
! if ((size_t)(q - p) > fe_len)
! fe_len = q - p;
! if (*q == ';')
! q++;
! }
! fe_len = fe_len + 1 + proglen + (has_extension ? 1 : 5);
! full_executable = xmalloc (fe_len);
!
! p = path;
! do
! {
! q = p;
! while (*q != ';' && *q != '\0')
! q++;
!
! e = full_executable;
! memcpy (e, p, q - p);
! e += (q - p);
! if (q - p)
! *e++ = '\\';
! strcpy (e, program);
!
! if (*q == ';')
! q++;
!
! for (e = full_executable; *e; e++)
! if (*e == '/')
! *e = '\\';
!
! /* At this point, e points to the terminating NUL character for
! full_executable. */
! for (ext = has_extension ? no_suffixes : std_suffixes; *ext; ext++)
! {
! /* Remove any current extension. */
! *e = '\0';
! /* Add the new one. */
! strcat (full_executable, *ext);
!
! /* Attempt to open this file. */
! h = CreateFile (full_executable, GENERIC_READ,
! FILE_SHARE_READ | FILE_SHARE_WRITE,
! 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
! if (h != INVALID_HANDLE_VALUE)
! goto found;
}
+ p = q;
}
+ while (*p);
+ free (full_executable);
+ return 0;
+
+ found:
+ CloseHandle (h);
+ return full_executable;
+ }
! int
! pexec (program, argv, search, stdin_fd, stdout_fd, stderr_fd)
! const char *program;
! char *const *argv;
! int search;
! int stdin_fd;
! int stdout_fd;
! int stderr_fd;
! {
! char *cmdline = argv_to_cmdline (argv);
! char *executable = find_executable (program, search);
! STARTUPINFO si;
! PROCESS_INFORMATION pinf;
! HANDLE me;
!
! /* Canonicalize file descriptor arguments. */
! stdin_fd = (stdin_fd == STDIN_FILE_NO) ? -1 : stdin_fd;
! stdout_fd = (stdout_fd == STDOUT_FILE_NO) ? -1 : stdout_fd;
! stderr_fd = (stderr_fd == STDERR_FILE_NO) ? -1 : stderr_fd;
!
! memset (&si, 0, sizeof si);
! si.cb = sizeof si;
! si.dwFlags = STARTF_USESTDHANDLES;
!
! me = GetCurrentProcess();
!
! if (!DuplicateHandle (me,
! (stdin_fd == -1)
! ? GetStdHandle (STD_INPUT_HANDLE)
! : (HANDLE)_get_osfhandle (stdin_fd),
! me, &si.hStdInput,
! 0, TRUE, DUPLICATE_SAME_ACCESS))
! goto cleanup;
! if (!DuplicateHandle (me,
! (stdout_fd == -1)
! ? GetStdHandle (STD_OUTPUT_HANDLE)
! : (HANDLE)_get_osfhandle (stdout_fd),
! me, &si.hStdOutput,
! 0, TRUE, DUPLICATE_SAME_ACCESS))
! goto cleanup;
! if (!DuplicateHandle (me,
! (stderr_fd == -1)
! ? GetStdHandle (STD_ERROR_HANDLE)
! : (HANDLE)_get_osfhandle (stderr_fd),
! me, &si.hStdError,
! 0, TRUE, DUPLICATE_SAME_ACCESS))
! goto cleanup;
!
!
! if (!CreateProcess (executable, cmdline,
! 0, 0, TRUE, 0, 0, 0,
! &si, &pinf))
! goto cleanup;
!
! CloseHandle (pinf.hProcess);
! CloseHandle (pinf.hThread);
!
! done:
! /* Close file descriptors passed to the child (whether or not we
! managed to create a child). */
! xclose (stdin_fd);
! xclose (stdout_fd);
! xclose (stderr_fd);
!
! free (executable);
! free (cmdline);
!
! return pinf.dwProcessId;
!
! cleanup:
! {
! /* Error strings on win32 include newlines. */
! char *errstr = get_last_error_as_text ();
! fprintf (stderr, "%s tried to spawn %s but failed: %s",
! this_program, program, errstr);
! LocalFree (errstr);
! }
! CloseHandle (si.hStdInput);
! CloseHandle (si.hStdOutput);
! CloseHandle (si.hStdError);
! pinf.dwProcessId = -1;
! goto done;
! }
!
! /* MSVCRT's _pipe() creates pipes that can be inherited, which is not
! what we want, so we go directly to CreatePipe(). */
! int
! pmkpipe (thepipe)
! int thepipe[2];
! {
! HANDLE read_port;
! HANDLE write_port;
!
! if (!CreatePipe (&read_port, &write_port, 0, 0))
! return -1;
!
! thepipe[0] = _open_osfhandle ((long)read_port, _O_RDONLY);
! thepipe[1] = _open_osfhandle ((long)write_port, _O_WRONLY);
! if (thepipe[0] == -1 || thepipe[1] == -1)
! {
! if (thepipe[0] == -1)
! CloseHandle (read_port);
! else
! _close (thepipe[0]);
! if (thepipe[1] == -1)
! CloseHandle (write_port);
! else
! _close (thepipe[1]);
! return -1;
! }
! return 0;
}
int
pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
const char *program;
char * const *argv;
const char *this_pname ATTRIBUTE_UNUSED;
const char *temp_base ATTRIBUTE_UNUSED;
char **errmsg_fmt, **errmsg_arg;
int flags;
{
+ /* Pipe waiting from last process, to be used as input for the next
+ one. Value is -1 if no pipe is waiting (i.e. the next command is
+ the first of a group). */
+ static int last_pipe_input = -1;
+
int pid;
! int pdesc[2];
! int serrno;
! int child_stdin = -2, child_stdout = -2;
! /* If this is the first process, last_pipe_input ought to be -1. */
if (flags & PEXECUTE_FIRST)
! if (last_pipe_input != -1)
! abort ();
! child_stdin = last_pipe_input;
! /* If this is the last process, don't do anything with its output
! pipe. */
! if (flags & PEXECUTE_LAST)
! child_stdout = -1;
! else
{
! /* Create a pipe to go between this process and the next one in
! the pipeline. */
! if (pmkpipe (pdesc))
{
*errmsg_fmt = "pipe";
*errmsg_arg = NULL;
return -1;
}
! last_pipe_input = pdesc[READ_PORT];
! child_stdout = pdesc[WRITE_PORT];
}
! pid = pexec (program, argv, (flags & PEXECUTE_SEARCH),
! child_stdin, child_stdout, -1);
! serrno = errno;
! xclose (child_stdin);
! xclose (child_stdout);
! /* To prevent a file descriptor leak, close last_pipe_input if pexec
! failed. */
! if (pid == -1)
! xclose (last_pipe_input);
! errno = serrno;
if (pid == -1)
{
! *errmsg_fmt = "spawn";
! *errmsg_arg = NULL;
}
return pid;
}
int
pwait (pid, status, flags)
int pid;
int *status;
int flags ATTRIBUTE_UNUSED;
{
! HANDLE proch = OpenProcess (SYNCHRONIZE | PROCESS_QUERY_INFORMATION,
! FALSE, pid);
! if (proch == 0)
! return -1;
! if (WaitForSingleObject (proch, INFINITE) != WAIT_OBJECT_0)
! {
! CloseHandle (proch);
! return -1;
! }
+ GetExitCodeProcess (proch, (DWORD *)status);
+ CloseHandle (proch);
return pid;
+ }
+
+ void
+ pexec_set_program_name (name)
+ const char *name;
+ {
+ this_program = name;
}