public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* PATCH to support native Windows builds
@ 2004-06-11 22:31 Mark Mitchell
  2004-06-11 22:57 ` DJ Delorie
                   ` (3 more replies)
  0 siblings, 4 replies; 21+ messages in thread
From: Mark Mitchell @ 2004-06-11 22:31 UTC (permalink / raw)
  To: gcc-patches; +Cc: dj


This patch provides support for building GCC on native Windows (i.e.,
MinGW) as opposed to Cygwin.  

This patch has been in CodeSourcery's local trees for a long time, and
is on the csl-arm-branch.

The version attached here isn't quite ready for inclusion in GCC,
because (for example) there is no ChangeLog and some functions are
missing comments.  However, my understanding is that the last time
something like this patch was suggested, it was rejected by DJ, so,
before doing the clean-ups, I think we need to get agreement on the
general direction.

The basic change in this code is that some code in collect2.c is
abstracted out and placed in libiberty.  In particular, collect2.c
right now does the usual UNIX pipe/fork/dup2/exec sequence.  This, of
course, does not work on UNIX.  After the patch, libiberty provides
low-level "pmkpipe" and "pexec" functions which encapsulate this logic
for UNIX, and which can also be implemented for Windows.  The existing
high-level "pexecute" functions are still in libiberty; the patch is
intended not to remove or modifying existing libiberty interfaces.

My understanding is that DJ objected to this patch because DOS does
not have pipes.  Of course, this patch would not make the situation
any worse that it already is for DOS, since the code in collect2.c
already cannot be used on DOS.  The objection, I think, was that any
change to this stuff should be in some other direction that would work
better for DOS.  Zack Weinberg and Ian Lance Taylor spent some time
coming up with ideas in that direction, but it doesn't look like
anything definitive happened, and it's not clear that anyone is
motivated enough to spend the time to implement anything else.

My thinking is the following:

1. Windows is a very popular host system, and this patch would allow
   GCC to be built there more easily.

2. Existing DOS functionality would not be adversely affected.

3. There doesn't seem to be any major movement to implement a more
   DOS-compatible interface, so we're sitting on a good improvement in
   the hope that someone will someday present us with an even better
   one.

4. If someone comes up with a better way of doing this stuff that
   works better for DOS, we can always add that in later.

DJ, do you still object to this patch?  If so, would you please
articulate your reasons?

Thanks,

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: PATCH to support native Windows builds
  2004-06-11 22:31 PATCH to support native Windows builds Mark Mitchell
@ 2004-06-11 22:57 ` DJ Delorie
  2004-06-11 23:21   ` Mark Mitchell
  2004-06-11 23:50 ` Aaron W. LaFramboise
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 21+ messages in thread
From: DJ Delorie @ 2004-06-11 22:57 UTC (permalink / raw)
  To: mark; +Cc: gcc-patches


My original argument against it wasn't that it used pipes, but that it
added a platform-specific API to libiberty.  Since the purpose of
libiberty is to provide platform independence, that code just doesn't
belong in libiberty.  It is an invalid abstraction for libiberty, and
that is the key to my objection.

DOS is not the reason for my objection, just an example.

From what I recall of the topic, what you're really looking for is a
popen() equivalent without the shell tokenizing nightmare, right?  If
so, we just need to design an abstraction for WHAT you're trying to do
(run a command with redirected I/O), not HOW you're trying to do it
(pipe/fork/exec).  IIRC two alternate APIs were offered, we can
certainly try again, if first we can agree on a suitable abstraction
(what you're trying to do, vs how to do it).  Since pexecute already
knows how to pipe commands together, extending it to support I/O
attached to either end shouldn't be *that* hard.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: PATCH to support native Windows builds
  2004-06-11 22:57 ` DJ Delorie
@ 2004-06-11 23:21   ` Mark Mitchell
  2004-06-12  0:28     ` DJ Delorie
  0 siblings, 1 reply; 21+ messages in thread
From: Mark Mitchell @ 2004-06-11 23:21 UTC (permalink / raw)
  To: DJ Delorie; +Cc: gcc-patches

DJ Delorie wrote:

> My original argument against it wasn't that it used pipes, but that it
> added a platform-specific API to libiberty.  Since the purpose of
> libiberty is to provide platform independence, that code just doesn't
> belong in libiberty.  It is an invalid abstraction for libiberty, and
> that is the key to my objection.

OK, I understand.  Thanks for explaining.

(I'm not entirely sure that this interface can't be implemented on all 
platforms of interest.  For example, the way I would implement it on 
DOS, would be to have a write to a pipe write to a temporary file, and 
then document the interface to say that there were limitations on these 
pipes made by "pmkpipe" relative to standard UNIX pipes.  In particular, 
on some systems the output buffer for writing to the pipe is unbounded 
-- no output will show up until the process exits.  That's sufficient 
for GCC.  But, if you're convinced this interface doesn't make sense on 
DOS, then I'll not argue the point.)

> DOS is not the reason for my objection, just an example.

Are there any other examples?

> From what I recall of the topic, what you're really looking for is a
> popen() equivalent without the shell tokenizing nightmare, right?  

Well, from a high level, what I'm looking for is "make GCC work on 
Windows (without Cygwin)".  Everything else is a detail. :-)

So, I'd be happy with any reasonable interface.  But, I'm not going to 
have the time to work out another interface, let alone implement and 
test it.  So, the question from my point of view is whether the 
community would rather have Windows support with the perhaps-imperfect 
CodeSourcery patch, or wait for something better.  To me, it seems like 
the tradeoffs are in favor of accepting the patch.

It sounds like you'd not object if we just put the pipe/exec code 
directly into collect2.c; then we'd not be polluting the libiberty 
interface.  The downside to that is that we'd have do duplicate code 
already in libiberty; pieces of pexecute would have to be copied into 
other code.  The CodeSourcery patch factors the code that's already in 
libiberty, there.

Why not just document these pexec/pmkpipe interfaces as unportable 
pieces of the libiberty interface?

-- 
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: PATCH to support native Windows builds
  2004-06-11 22:31 PATCH to support native Windows builds Mark Mitchell
  2004-06-11 22:57 ` DJ Delorie
@ 2004-06-11 23:50 ` Aaron W. LaFramboise
  2004-06-11 23:56   ` Zack Weinberg
  2004-06-12  0:01   ` Mark Mitchell
  2004-06-11 23:54 ` Paolo Carlini
  2004-06-12  0:53 ` Danny Smith
  3 siblings, 2 replies; 21+ messages in thread
From: Aaron W. LaFramboise @ 2004-06-11 23:50 UTC (permalink / raw)
  To: mark; +Cc: gcc-patches, dj

Mark Mitchell wrote:
> This patch provides support for building GCC on native Windows (i.e.,
> MinGW) as opposed to Cygwin.  

One concern I have is the Ctrl-C support.

Presently Ctrl-C support is broken on all of GCC under MinGW. 
Specifically, when you send a break from the console, it will the 
toplevel gcc but not any invoked subprocesses.  Does it make sense to 
hack it into just collect2 when it doesn't work anywhere else?

Maybe Ctrl-C support should wait until someone implements it, in 
general, for GCC?  Whatever turns out to be the working Ctrl-C 
implementation might be very different from what is being proposed in 
this patch.

Ctrl-C support, if added, probably would need to be involved with libiberty.

While I am not aware of anyone working on improving Ctrl-C, perhaps I 
personally might be interested in fixing this now that its come up.

Aaron W. LaFramboise

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: PATCH to support native Windows builds
  2004-06-11 22:31 PATCH to support native Windows builds Mark Mitchell
  2004-06-11 22:57 ` DJ Delorie
  2004-06-11 23:50 ` Aaron W. LaFramboise
@ 2004-06-11 23:54 ` Paolo Carlini
  2004-06-12  0:10   ` Mark Mitchell
  2004-06-12  0:53 ` Danny Smith
  3 siblings, 1 reply; 21+ messages in thread
From: Paolo Carlini @ 2004-06-11 23:54 UTC (permalink / raw)
  To: mark; +Cc: gcc-patches

Mark Mitchell wrote:

>This patch provides support for building GCC on native Windows (i.e.,
>MinGW) as opposed to Cygwin.
>
Mark, it looks like nobody wants to see the actual patch ;)
Out of curiosity, I would.

Paolo.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: PATCH to support native Windows builds
  2004-06-11 23:50 ` Aaron W. LaFramboise
@ 2004-06-11 23:56   ` Zack Weinberg
  2004-06-12  0:01   ` Mark Mitchell
  1 sibling, 0 replies; 21+ messages in thread
From: Zack Weinberg @ 2004-06-11 23:56 UTC (permalink / raw)
  To: Aaron W. LaFramboise; +Cc: mark, gcc-patches, dj

"Aaron W. LaFramboise" <aaronraolete36@aaronwl.com> writes:

> Mark Mitchell wrote:
>> This patch provides support for building GCC on native Windows (i.e.,
>> MinGW) as opposed to Cygwin.
>
> One concern I have is the Ctrl-C support.
>
> Presently Ctrl-C support is broken on all of GCC under
> MinGW. Specifically, when you send a break from the console, it will
> the toplevel gcc but not any invoked subprocesses.  Does it make sense
> to hack it into just collect2 when it doesn't work anywhere else?

The code that's under debate here is not the Ctrl-C support in
collect2.  That stuff is the minimum necessary to get GCC to build in
a cross-compile configuration with host=mingw; no one thinks it's
ideal, but we don't know how to do it right.

> While I am not aware of anyone working on improving Ctrl-C, perhaps I
> personally might be interested in fixing this now that its come up.

I'd be very glad if a competent Windows programmer would tackle this,
but please consider it a separate issue from the pexecute changes.

zw

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: PATCH to support native Windows builds
  2004-06-11 23:50 ` Aaron W. LaFramboise
  2004-06-11 23:56   ` Zack Weinberg
@ 2004-06-12  0:01   ` Mark Mitchell
  1 sibling, 0 replies; 21+ messages in thread
From: Mark Mitchell @ 2004-06-12  0:01 UTC (permalink / raw)
  To: Aaron W. LaFramboise; +Cc: gcc-patches, dj

Aaron W. LaFramboise wrote:

> Mark Mitchell wrote:
> 
>> This patch provides support for building GCC on native Windows (i.e.,
>> MinGW) as opposed to Cygwin.  
> 
> 
> One concern I have is the Ctrl-C support.

Well, we could leave that out of the version checked in, if that's an 
issue.  Basically, we're just trying to make it possible for other 
people to use GCC on MinGW.

-- 
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: PATCH to support native Windows builds
  2004-06-11 23:54 ` Paolo Carlini
@ 2004-06-12  0:10   ` Mark Mitchell
  0 siblings, 0 replies; 21+ messages in thread
From: Mark Mitchell @ 2004-06-12  0:10 UTC (permalink / raw)
  To: Paolo Carlini; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 350 bytes --]

Paolo Carlini wrote:

> Mark Mitchell wrote:
> 
>> This patch provides support for building GCC on native Windows (i.e.,
>> MinGW) as opposed to Cygwin.
>>
> Mark, it looks like nobody wants to see the actual patch ;)
> Out of curiosity, I would.

Didn't I attach it?  OK, here it is again.

-- 
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

[-- Attachment #2: diffs --]
[-- Type: text/plain, Size: 52045 bytes --]

Index: libiberty/pex-unix.c
===================================================================
RCS file: /cvs/gcc/gcc/libiberty/pex-unix.c,v
retrieving revision 1.1
retrieving revision 1.1.20.1
diff -c -5 -p -r1.1 -r1.1.20.1
*** libiberty/pex-unix.c	24 Jan 2003 20:02:11 -0000	1.1
--- libiberty/pex-unix.c	23 Dec 2003 21:43:48 -0000	1.1.20.1
*************** Boston, MA 02111-1307, USA.  */
*** 22,31 ****
--- 22,32 ----
  
  #include "pex-common.h"
  
  #include <stdio.h>
  #include <errno.h>
+ #include <fcntl.h>
  #ifdef NEED_DECLARATION_ERRNO
  extern int errno;
  #endif
  #ifdef HAVE_STRING_H
  #include <string.h>
*************** extern int errno;
*** 42,158 ****
  
  #ifndef HAVE_WAITPID
  #define waitpid(pid, status, flags) wait(status)
  #endif
  
! extern int execv ();
! extern int execvp ();
  
  int
! pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
       const char *program;
!      char * const *argv;
!      const char *this_pname;
!      const char *temp_base ATTRIBUTE_UNUSED;
!      char **errmsg_fmt, **errmsg_arg;
!      int flags;
  {
-   int (*func)() = (flags & PEXECUTE_SEARCH ? execvp : execv);
    int pid;
-   int pdes[2];
-   int input_desc, output_desc;
    int retries, sleep_interval;
-   /* 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) < 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;
!     }
  
    /* Fork a subprocess; wait and retry if it fails.  */
    sleep_interval = 1;
    pid = -1;
    for (retries = 0; retries < 4; retries++)
      {
        pid = fork ();
!       if (pid >= 0)
  	break;
        sleep (sleep_interval);
        sleep_interval *= 2;
      }
  
!   switch (pid)
      {
!     case -1:
!       *errmsg_fmt = "fork";
!       *errmsg_arg = NULL;
        return -1;
  
!     case 0: /* child */
!       /* Move the input and output pipes into place, if necessary.  */
!       if (input_desc != STDIN_FILE_NO)
! 	{
! 	  close (STDIN_FILE_NO);
! 	  dup (input_desc);
! 	  close (input_desc);
! 	}
!       if (output_desc != STDOUT_FILE_NO)
  	{
! 	  close (STDOUT_FILE_NO);
! 	  dup (output_desc);
! 	  close (output_desc);
  	}
  
!       /* Close the parent's descs that aren't wanted here.  */
!       if (last_pipe_input != STDIN_FILE_NO)
! 	close (last_pipe_input);
! 
!       /* Exec the program.  */
!       (*func) (program, argv);
! 
!       fprintf (stderr, "%s: ", this_pname);
!       fprintf (stderr, install_error_msg, program);
!       fprintf (stderr, ": %s\n", xstrerror (errno));
!       exit (-1);
!       /* NOTREACHED */
!       return 0;
! 
!     default:
!       /* In the parent, after forking.
! 	 Close the descriptors that we made for this child.  */
!       if (input_desc != STDIN_FILE_NO)
! 	close (input_desc);
!       if (output_desc != STDOUT_FILE_NO)
! 	close (output_desc);
  
!       /* Return child's process number.  */
!       return pid;
      }
  }
  
  int
  pwait (pid, status, flags)
       int pid;
--- 43,245 ----
  
  #ifndef HAVE_WAITPID
  #define waitpid(pid, status, flags) wait(status)
  #endif
  
! /* These are needed to prevent the build from bombing out on
!    platforms (such as embedded targets) where no pex-*.c
!    will work at all (but we try to build this one anyway).  */
! extern int execvp();
! extern int execv();
! 
! #define xdup2(a, b) do {				\
!   if (a != -1)						\
!     if (dup2 (a, b) < 0)				\
!       {							\
! 	fprintf (stderr, "%s: dup2(%d, %d): %s\n",	\
! 	         this_program, a, b, xstrerror(errno));	\
!         exit(127);					\
!       }							\
! } while (0);
! 
! #define xclose(fd) do {					\
!   if (fd != -1)						\
!     {							\
!       close (fd);					\
!       fd = -1;						\
!     }							\
! } while (0)
! 
! static const char *this_program = "<unknown>";
! 
! /* Execute PROGRAM with argument vector ARGV.  If SEARCH is false,
!    PROGRAM is expected to be a usable pathname already; otherwise it
!    is looked for in the locations specified by the PATH environment
!    variable (as per execvp).
! 
!    STDIN_FD, STDOUT_FD, and STDERR_FD are file descriptors which
!    should be established as the child process's stdin, stdout, or
!    stderr, respectively, or -1 if the child should inherit the
!    parent's value of that descriptor.  If any of these is not -1, it
!    should be a valid file descriptor marked close-on-exec.  */
  
  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;
  {
    int pid;
    int retries, sleep_interval;
  
!   /* 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;
! 
!   /* If exec fails, the child will write a message to stderr, using
!      fprintf.  It must therefore use exit(), not _exit().  So we have
!      to flush pending output here to avoid duplicate output.  */
!   fflush (NULL);
  
    /* Fork a subprocess; wait and retry if it fails.  */
    sleep_interval = 1;
    pid = -1;
    for (retries = 0; retries < 4; retries++)
      {
        pid = fork ();
!       if (__builtin_expect (pid >= 0, 1))
  	break;
        sleep (sleep_interval);
        sleep_interval *= 2;
      }
  
!   if (pid != 0)
      {
!       /* Parent; fork either succeeded or failed.  In either case we
! 	 close the file descriptors passed to the child, to make life
! 	 easier for callers.  Don't clobber errno while doing so. */
!       int serrno = errno;
!       xclose (stdin_fd);
!       xclose (stdout_fd);
!       xclose (stderr_fd);
!       errno = serrno;
!       
!       return pid;
!     }
! 
!   /* We are the child.  Set up I/O redirections and call exec.
!      FIXME: Report errors without calling fprintf() in the child
!      (so we can use vfork).  */
!   xdup2 (stdin_fd, STDIN_FILE_NO);
!   xdup2 (stdout_fd, STDOUT_FILE_NO);
!   xdup2 (stderr_fd, STDERR_FILE_NO);
! 
!   (search ? execvp : execv) (program, argv);
! 
!   /* If we got here exec failed.  */
! /*fprintf (stderr, install_error_msg,  XXX completely wrong format string */
!   fprintf (stderr, "%s tried to exec %s but failed (%s)\n",
! 	   this_program, program, xstrerror (errno));
!   exit (127);
! }
! 
! /* Create a pipe suitable for use with pexec - in particular, both
!    ends of the pipe are set close-on-exec.  Returns 0 if successful,
!    -1 otherwise.  Returns the pipe in the array argument, just as
!    pipe(2) does.  */
! 
! int
! pmkpipe (thepipe)
!      int thepipe[2];
! {
!   if (pipe (thepipe))
!     return -1;
! 
!   if (fcntl (thepipe[0], F_SETFD, FD_CLOEXEC)
!       || fcntl (thepipe[1], F_SETFD, FD_CLOEXEC))
!     {
!       int serrno = errno;
!       close (thepipe[0]);
!       close (thepipe[1]);
!       errno = serrno;
        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 0
! FILE* P = fopen("/dev/pts/1", "w");
! printf(P, "pex-unix.c:pexecute called with program %s\n", program);
! #endif
!   /* 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 = "fork";
!       *errmsg_arg = NULL;
      }
+ 
+   return pid;
  }
  
  int
  pwait (pid, status, flags)
       int pid;
*************** pwait (pid, status, flags)
*** 162,166 ****
--- 249,260 ----
    /* ??? Here's an opportunity to canonicalize the values in STATUS.
       Needed?  */
    pid = waitpid (pid, status, 0);
    return pid;
  }
+ 
+ void
+ pexec_set_program_name (name)
+      const char *name;
+ {
+   this_program = name;
+ }
Index: libiberty/pex-win32.c
===================================================================
RCS file: /cvs/gcc/gcc/libiberty/pex-win32.c,v
retrieving revision 1.3
retrieving revision 1.3.10.2
diff -c -5 -p -r1.3 -r1.3.10.2
*** libiberty/pex-win32.c	5 Jul 2003 00:52:07 -0000	1.3
--- libiberty/pex-win32.c	12 Feb 2004 04:48:13 -0000	1.3.10.2
*************** 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,425 ----
  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;
!   si.hStdInput = INVALID_HANDLE_VALUE;
!   si.hStdOutput = INVALID_HANDLE_VALUE;
!   si.hStdError = INVALID_HANDLE_VALUE;
! 
!   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.hThread);
!   
!  done:
!   /* Close file descriptors passed to the child (whether or not we
!      managed to create a child).  */
!   xclose (stdin_fd);
!   xclose (stdout_fd);
!   if (stderr_fd != stdout_fd)
!     xclose (stderr_fd);
!   if (si.hStdInput != INVALID_HANDLE_VALUE)
!     CloseHandle (si.hStdInput);
!   if (si.hStdOutput != INVALID_HANDLE_VALUE)
!     CloseHandle (si.hStdOutput);
!   if (si.hStdError != INVALID_HANDLE_VALUE)
!     CloseHandle (si.hStdError);
! 
!   free (executable);
!   free (cmdline);
! 
!   /* Treat the process handle as an integer.  It would be cleaner to
!      define a pid_t type that would be used by all libiberty callers;
!      that type would be HANDLE under Windows.  However, that would
!      require changing a lot of existing code.  */
!   if (sizeof (HANDLE) != sizeof (int))
!     abort ();
!   return (int) pinf.hProcess;
! 
!  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);
!   }
!   /* Fortuitously, INVALID_HANDLE_VALUE is -1, which is the
!      conventional error return value for pwait.  */
!   pinf.hProcess = INVALID_HANDLE_VALUE;
!   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;
  {
!   /* The return value from pexecute is actually a HANDLE.  */
!   HANDLE proch = (HANDLE) pid;
!   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;
+ }
Index: include/libiberty.h
===================================================================
RCS file: /cvs/gcc/gcc/include/libiberty.h,v
retrieving revision 1.35
retrieving revision 1.35.10.1
diff -c -5 -p -r1.35 -r1.35.10.1
*** include/libiberty.h	15 May 2003 19:02:12 -0000	1.35
--- include/libiberty.h	23 Dec 2003 17:25:29 -0000	1.35.10.1
*************** 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,285 ****
  /* 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.  */
  
  extern int asprintf PARAMS ((char **, const char *, ...)) ATTRIBUTE_PRINTF_2;
--- 272,340 ----
  /* 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.  */
  
  extern int asprintf PARAMS ((char **, const char *, ...)) ATTRIBUTE_PRINTF_2;
Index: gcc/collect2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/collect2.c,v
retrieving revision 1.154
retrieving revision 1.154.4.4
diff -c -5 -p -r1.154 -r1.154.4.4
*** gcc/collect2.c	17 Oct 2003 11:27:13 -0000	1.154
--- gcc/collect2.c	3 Mar 2004 16:02:17 -0000	1.154.4.4
*************** 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 **);
  \f
- #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 */
- \f
  /* Delete tempfiles and exit function.  */
  
  void
  collect_exit (int status)
  {
--- 290,299 ----
*************** fancy_abort (void)
*** 405,415 ****
  {
    fatal ("internal error");
  }
  \f
  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");
  }
  \f
  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 */
+ 
  \f
  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)
*** 882,919 ****
        if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
  	num_c_args++;
      }
    obstack_free (&temporary_obstack, temporary_firstobj);
  
!   /* -fno-exceptions -w */
!   num_c_args += 2;
  
    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);
  
--- 966,985 ----
        if (*q == '-' && (q[1] == 'm' || q[1] == 'f'))
  	num_c_args++;
      }
    obstack_free (&temporary_obstack, temporary_firstobj);
  
!   /* -fno-profile-arcs -fno-test-coverage -fno-branch-probabilities
!      -fno-exceptions -w */
!   num_c_args += 5;
  
    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;
--- 1560,1570 ----
*************** 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)
  {
--- 1578,1604 ----
  	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, S_IWUSR);
!       if (redir_handle == -1)
! 	fatal ("cannot open `%s' for writing", redir);
      }
  
!   pid = pexec (argv[0], argv, 1, -1, redir_handle, redir_handle);
  
!   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];
--- 2022,2031 ----
*************** 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");
--- 2043,2053 ----
      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.  */
--- 2062,2079 ----
  	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
--- 2148,2158 ----
    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];
--- 2425,2434 ----
*************** 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");
--- 2443,2453 ----
  
    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.  */
--- 2462,2479 ----
  	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,2542 ****
    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);
  }
  
--- 2512,2523 ----
    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: gcc/system.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/system.h,v
retrieving revision 1.171
retrieving revision 1.171.4.3
diff -c -5 -p -r1.171 -r1.171.4.3
*** gcc/system.h	16 Oct 2003 18:05:57 -0000	1.171
--- gcc/system.h	3 Mar 2004 16:02:47 -0000	1.171.4.3
*************** extern int errno;
*** 249,280 ****
  
  #ifdef HAVE_SYS_WAIT_H
  #include <sys/wait.h>
  #endif
  
- #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
- 
  /* The HAVE_DECL_* macros are three-state, undefined, 0 or 1.  If they
     are defined to 0 then we must provide the relevant declaration
     here.  These checks will be in the undefined state while configure
     is running so be careful to test "defined (HAVE_DECL_*)".  */
  
--- 250,259 ----

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: PATCH to support native Windows builds
  2004-06-11 23:21   ` Mark Mitchell
@ 2004-06-12  0:28     ` DJ Delorie
  0 siblings, 0 replies; 21+ messages in thread
From: DJ Delorie @ 2004-06-12  0:28 UTC (permalink / raw)
  To: mark; +Cc: gcc-patches


> (I'm not entirely sure that this interface can't be implemented on
> all platforms of interest.  For example, the way I would implement
> it on DOS, would be to have a write to a pipe write to a temporary
> file, and then document the interface to say that there were
> limitations on these pipes made by "pmkpipe" relative to standard
> UNIX pipes.  In particular, on some systems the output buffer for
> writing to the pipe is unbounded -- no output will show up until the
> process exits.  That's sufficient for GCC.  But, if you're convinced
> this interface doesn't make sense on DOS, then I'll not argue the
> point.)

That's exactly what popen() in djgpp does.  But, popen has a matching
pclose, so we have an opportunity to run the program either before or
after doing all the File I/O, and the existing interface for popen is
sufficiently portable that it is meaningful as-is for djgpp.  We also
avoid the issue of reading and writing at the same time (deadlock is
automatically avoided too).  I'm not arguing against your ideas for
implementing the solution, just the interface to it.

Another thing is, if we don't *call* them pipes, we don't have to
document "limitations".  We call them something else, and document
what they *do* do.  It also stops people from bypassing the interface
and doing pipe-specific things with the file handles we give them.

If we had a popen() that took an argv[] instead of a char *, would
that be sufficient?

> > DOS is not the reason for my objection, just an example.
> 
> Are there any other examples?

I'm not aware of any off the top of my head, but any non-multitasking
platform would be.  AmigaOS may be one, as it has a completely
different abstraction for process creation.  VMS does too, but I
suspect it has pipes of a sort.

> It sounds like you'd not object if we just put the pipe/exec code 
> directly into collect2.c;

No, I have no objection to that.

> The downside to that is that we'd have do duplicate code already in
> libiberty; pieces of pexecute would have to be copied into other
> code.

Think of it as incentive not to forget this problem ;-)

> Why not just document these pexec/pmkpipe interfaces as unportable
> pieces of the libiberty interface?

I worry that it will remain "broken" long enough that fixing it
becomes infeasible.  Also, the usual slippery slope concerns.  If the
GCC community is willing to submit themselves to a nagging fprintf
each time pmkpipe() is called, maybe I'll change my mind.

Besides, marking something "unportable" in libiberty's interface just
admits that you did it wrong :-(

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: PATCH to support native Windows builds
  2004-06-11 22:31 PATCH to support native Windows builds Mark Mitchell
                   ` (2 preceding siblings ...)
  2004-06-11 23:54 ` Paolo Carlini
@ 2004-06-12  0:53 ` Danny Smith
  2004-06-12  1:08   ` Mark Mitchell
  3 siblings, 1 reply; 21+ messages in thread
From: Danny Smith @ 2004-06-12  0:53 UTC (permalink / raw)
  To: mark, gcc-patches; +Cc: dj

From: "Mark Mitchell"|
| This patch provides support for building GCC on native Windows (i.e.,
| MinGW) as opposed to Cygwin.

The attachment seems to be missing, so I can't comment on the details, but  I'm not sure
what you mean by a "native" build.

For last 4 years,  I have been bootstrapping gcc and building binutils with a native
(msvcrt.dll-dependent) gcc and binutils toolchain.  What is not "native" abouit my
builds is that I use the cygwin toolset to provide me with a posix-y shell and the
configury/make/test tools.  That is, I use cygwin's bash, sh, mount. make, autoconf,
tcl, etc, but not cygwin gcc or binutils.  Other people use a fork of the cygwin shell
environment, called msys, to build gcc "semi-natively".  I suspect that it could also
 be done using MS's  own posixy shell environment (I've forgotten what its called,
 something like SFU).
|
| The version attached here isn't quite ready for inclusion in GCC,
| because (for example) there is no ChangeLog and some functions are
| missing comments.  However, my understanding is that the last time
| something like this patch was suggested, it was rejected by DJ, so,
| before doing the clean-ups, I think we need to get agreement on the
| general direction.
|
| The basic change in this code is that some code in collect2.c is
| abstracted out and placed in libiberty.  In particular, collect2.c
| right now does the usual UNIX pipe/fork/dup2/exec sequence.  This, of
| course, does not work on UNIX.  After the patch, libiberty provides
| low-level "pmkpipe" and "pexec" functions which encapsulate this logic
| for UNIX, and which can also be implemented for Windows.  The existing
| high-level "pexecute" functions are still in libiberty; the patch is
| intended not to remove or modifying existing libiberty interfaces.
|

FWIW, the  gcc-3.4.0 release candidate binaries provide by mingw.org have a working
collect2.  The patches to get it to work are based on Ian Lance Taylor's submission to
gcc-patches (the pex-read one), with a few tweaks from the csl-arm branch.

I tried the csl-arm patches adding low-level "pmkpipe" and "pexec" functions, but they
created
problem when running gcc from some IDE's and text editors that also redirected stderr
and stdout.  Even something  like gcc -v --help would lose the stderr output.  Ian's
patches,
using high level dup2 (rather than low level win32api functions) did not have that
problem.

There are still minor problems with signal handling.  If Ctrl-Brk is hit while collect2 is
running,
*.ld files are not  deleted.   But that is not a new problem,  the gcc driver doesn't
clean-up temp
files either withCtrl-Brk.

Here are the relevant Changelog excerpts from the mingw  sources. Are you interested in
a diff against trunk?

Danny

ChangeLog

2004-03-29  Danny Smith  <dannysmith@users.sourceforge,net>

        * collect2.c: Include pex-read.h.
        * system,h: (HOST_QUOTE_STR, HOST_QUOTE_CHAR.
        HOST_QUOTED_QUOTE_STR): New defines.
        * config/i386/xm-mingw32 (HOST_QUOTE_STR, HOST_QUOTE_CHAR.
        HOST_QUOTED_QUOTE_STR): Override defaults.
        * gcc.c (set_collect_gcc_options); Use HOST_QUOTE_STR,
        HOST_QUOTE_CHAR. HOST_QUOTED_QUOTE_STR.

2004-03-18  Danny Smith <dannysmith@users.sourceforge,net>

        Apply Ian Lance Taylor patch
        2004-03-17  Ian Lance Taylor  <ian@wasabisystems.com>

        * collect2.c (collect_status): New static function, broken out of
        collect_wait.
        (collect_wait): Call collect_status.
        (do_read_wait): New static function.
        (scan_prog_file): Call pex_read instead of pipe and vfork.
        (scan_libraries): Likewise.

        Backport from csl-arm-branch.
        2004-02-12  Mark Mithchell  <mmitchel@gcc.gnu.org>

        * collect2.c  (collect_execute): Pass third argument to open.
        * gcc.c (set_collect_gcc_options): Use double quotes instead of
        single quotes on Windows.
        * tlink.c (recompile_files): Do not assume that "rename" can
        overwrite an existing file.  Use "&&" as the command separator
        rather than ";".

libiberty/Changelog

2004-03-18  Danny Smith <dannysmith@users.sourceforge,net>

        Merge in libiberty from gcc trunk as at 2004-03-17.

        Apply Ian Lance Taylor patch
        2004-03-17  Ian Lance Taylor  <ian@wasabisystems.com>

        * pexrd-unix.c: New file.
        * pexrd-generic.c: New file.
        * configure.ac: Add either ./pexrd-unix.o or ./pexrd-generic.o to
        pexecute.
        * strerror.c: Redefine sys_nerr and sys_errlist before including
        ansidecl.h and libiberty.h.
        * /Makefile.in: Run maint-deps.
        (CFILES): Add pexrd-unix.c and pexrd-generic.c.
        (CONFIGURED_OFILES): Add ./pexrd-unix.o and ./pexrd-generic.o.
        * pexecute.txh: Document pex_read and pex_read_close.
        * configure: Regenerate.
        * functions.texi: Regenerate.

include/ChangeLog

2004-03-29  Danny Smith <dannysmith@users.sourceforge,net>

        * include/pex-read.h. New file. Declare pex_read, pex_read_close.

cp/ChangeLog

2004-03-29  Danny Smith <dannysmith@users.sourceforge,net>

        * repo.c (extract_string); Use HOST_QUOTE_STR,HOST_QUOTE_CHAR.
        HOST_QUOTED_QUOTE_STR.

2004-03-18  Danny Smith <dannysmith@users.sourceforge,net>

        Backport from csl-arm-branch.
        2004-02-12  Mark Mithchell  <mmitchel@gcc.gnu.org>

        * repo.c (IDENTIFIER_REPO_USED): Use tree flag 5.
        (IDENTIFIER_REPO_CHOSEN): Use tree flag 6.
        (extract_string): Use double quotes, rather than single quotes, on
        Windows.


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: PATCH to support native Windows builds
  2004-06-12  0:53 ` Danny Smith
@ 2004-06-12  1:08   ` Mark Mitchell
  2004-06-12  2:40     ` DJ Delorie
  2004-06-12 13:42     ` Danny Smith
  0 siblings, 2 replies; 21+ messages in thread
From: Mark Mitchell @ 2004-06-12  1:08 UTC (permalink / raw)
  To: Danny Smith; +Cc: gcc-patches, dj

> For last 4 years,  I have been bootstrapping gcc and building binutils with a native
> (msvcrt.dll-dependent) gcc and binutils toolchain.  

So, you made different changes to collect2.c than we did, or avoided 
using that code altogether -- which isn't possible for some cross 
compilers.

DJ's objections to the patch I posted are principled, but in my opinion, 
misguided.  Not being willing to expose internal libiberty interfaces to 
support Windows out of fear that these interfaces would not then be 
supported on DOS and/or AmigaOS strikes me as cutting off your nose to 
spite your face.

That said, I'm utterly dispassionate about how we get this done.  If 
there are problems with our patches (although our customers haven't told 
us about them), that's fine.  If there's a better interface, that's fine 
too.  If DJ will accept Ian's patches, that's fine by me.

The broader point is that there are patches out there that get GCC to 
work on Windows, without Cygwin, and that lots of people want to do 
that.  However, as a community, we seem to have failed to have gotten 
any such patch into GCC.  That means that multiple parties are creating 
and maintaining different patches to add this support.  And I'm not keen 
on spending a lot of time on working out another interface and more 
implementations; we've already got ways of doing this that (perhaps 
modulo a bug or two) work.

Danny, would you post the full patch so that DJ can more easily consier 
it?  DJ, will you accept Ian's patches?

If not, I guess I'll plan to put either Ian's patches or ours somewhere 
else in gcc, since DJ has indicated that he doesn't mind if we bypass 
libiberty.  Even this ugly alternative seems better than having lots of 
variants on this functionality out there in the world.

-- 
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: PATCH to support native Windows builds
  2004-06-12  1:08   ` Mark Mitchell
@ 2004-06-12  2:40     ` DJ Delorie
  2004-06-12  2:48       ` Mark Mitchell
  2004-06-12 13:42     ` Danny Smith
  1 sibling, 1 reply; 21+ messages in thread
From: DJ Delorie @ 2004-06-12  2:40 UTC (permalink / raw)
  To: mark; +Cc: gcc-patches


> DJ, will you accept Ian's patches?

Ian is a libiberty maintainer too, he does not need my permission.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: PATCH to support native Windows builds
  2004-06-12  2:40     ` DJ Delorie
@ 2004-06-12  2:48       ` Mark Mitchell
  2004-06-12  3:59         ` Ian Lance Taylor
  0 siblings, 1 reply; 21+ messages in thread
From: Mark Mitchell @ 2004-06-12  2:48 UTC (permalink / raw)
  To: DJ Delorie, Ian Lance Taylor; +Cc: gcc-patches

DJ Delorie wrote:

>>DJ, will you accept Ian's patches?
> 
> 
> Ian is a libiberty maintainer too, he does not need my permission.

Oh, well, then... :-)

Ian, can you check in your patches?  Is there any reason not to do that?

-- 
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: PATCH to support native Windows builds
  2004-06-12  2:48       ` Mark Mitchell
@ 2004-06-12  3:59         ` Ian Lance Taylor
  2004-06-12  4:23           ` Zack Weinberg
  0 siblings, 1 reply; 21+ messages in thread
From: Ian Lance Taylor @ 2004-06-12  3:59 UTC (permalink / raw)
  To: Mark Mitchell; +Cc: DJ Delorie, gcc-patches

Mark Mitchell <mark@codesourcery.com> writes:

> DJ Delorie wrote:
> 
> >>DJ, will you accept Ian's patches?
> > Ian is a libiberty maintainer too, he does not need my permission.
> 
> Oh, well, then... :-)
> 
> Ian, can you check in your patches?  Is there any reason not to do that?

Sigh.  I worked out a set of patches which I thought were good, but
Zack wanted a different API:
    http://gcc.gnu.org/ml/gcc-patches/2004-04/msg00227.html

So I wrote a preliminary implementation using a version of the API he
suggested:
    http://gcc.gnu.org/ml/gcc-patches/2004-04/msg00872.html
and he wasn't that happy with it:
    http://gcc.gnu.org/ml/gcc-patches/2004-04/msg01044.html

So I kind of lost motivation, and then my job changed and I had less
time to work on gcc.

I personally understand DJ's objections to the older CodeSourcery
patches, and I personally think that any version of my patches would
be better.  But I also understand what Zack wants to do.  I just
haven't summoned up the activation energy to dive into this again.

Ian

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: PATCH to support native Windows builds
  2004-06-12  3:59         ` Ian Lance Taylor
@ 2004-06-12  4:23           ` Zack Weinberg
  2004-06-12  5:57             ` Mark Mitchell
  2004-06-12  6:02             ` Ian Lance Taylor
  0 siblings, 2 replies; 21+ messages in thread
From: Zack Weinberg @ 2004-06-12  4:23 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: Mark Mitchell, DJ Delorie, gcc-patches


I think you took my vague lack of enthusiasm for a rejection.  I'd be
fine with the second version of your patch.

zw

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: PATCH to support native Windows builds
  2004-06-12  4:23           ` Zack Weinberg
@ 2004-06-12  5:57             ` Mark Mitchell
  2004-06-12  7:06               ` Ian Lance Taylor
  2004-06-12  6:02             ` Ian Lance Taylor
  1 sibling, 1 reply; 21+ messages in thread
From: Mark Mitchell @ 2004-06-12  5:57 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: Ian Lance Taylor, DJ Delorie, gcc-patches

Zack Weinberg wrote:

> I think you took my vague lack of enthusiasm for a rejection.  I'd be
> fine with the second version of your patch.

Great.  Let's call that consensus and move on. :-)

Ian, would you mind checking one of these versions?

Thanks,

-- 
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: PATCH to support native Windows builds
  2004-06-12  4:23           ` Zack Weinberg
  2004-06-12  5:57             ` Mark Mitchell
@ 2004-06-12  6:02             ` Ian Lance Taylor
  2004-06-12  8:14               ` Zack Weinberg
  1 sibling, 1 reply; 21+ messages in thread
From: Ian Lance Taylor @ 2004-06-12  6:02 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: Mark Mitchell, DJ Delorie, gcc-patches

Zack Weinberg <zack@codesourcery.com> writes:

> I think you took my vague lack of enthusiasm for a rejection.  I'd be
> fine with the second version of your patch.

Actually, it was more like I thought your suggestion was good, and
it's obviously a good idea to get the API right from the start, but I
couldn't quite manage to push the work farther.

Ian

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: PATCH to support native Windows builds
  2004-06-12  5:57             ` Mark Mitchell
@ 2004-06-12  7:06               ` Ian Lance Taylor
  2004-06-12  8:12                 ` Mark Mitchell
  0 siblings, 1 reply; 21+ messages in thread
From: Ian Lance Taylor @ 2004-06-12  7:06 UTC (permalink / raw)
  To: Mark Mitchell; +Cc: Zack Weinberg, DJ Delorie, gcc-patches

Mark Mitchell <mark@codesourcery.com> writes:

> Zack Weinberg wrote:
> 
> > I think you took my vague lack of enthusiasm for a rejection.  I'd be
> > fine with the second version of your patch.
> 
> Great.  Let's call that consensus and move on. :-)
> 
> Ian, would you mind checking one of these versions?

OK, I will clean it up and check it in.

Ian

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: PATCH to support native Windows builds
  2004-06-12  7:06               ` Ian Lance Taylor
@ 2004-06-12  8:12                 ` Mark Mitchell
  0 siblings, 0 replies; 21+ messages in thread
From: Mark Mitchell @ 2004-06-12  8:12 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: Zack Weinberg, DJ Delorie, gcc-patches

>>Great.  Let's call that consensus and move on. :-)
>>
>>Ian, would you mind checking one of these versions?
> 
> 
> OK, I will clean it up and check it in.

Great!  Thanks to you, DJ, Zack, and Danny.

-- 
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: PATCH to support native Windows builds
  2004-06-12  6:02             ` Ian Lance Taylor
@ 2004-06-12  8:14               ` Zack Weinberg
  0 siblings, 0 replies; 21+ messages in thread
From: Zack Weinberg @ 2004-06-12  8:14 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: Mark Mitchell, DJ Delorie, gcc-patches

Ian Lance Taylor <ian@wasabisystems.com> writes:

> Zack Weinberg <zack@codesourcery.com> writes:
>
>> I think you took my vague lack of enthusiasm for a rejection.  I'd be
>> fine with the second version of your patch.
>
> Actually, it was more like I thought your suggestion was good, and
> it's obviously a good idea to get the API right from the start, but I
> couldn't quite manage to push the work farther.

Fair enough.  I reread the old thread and decided I'd been too
ambitious - it's enough to get the mingwin-hosted-cross-compiler
working, let's not try to fix specs at the same time. :)

zw

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: PATCH to support native Windows builds
  2004-06-12  1:08   ` Mark Mitchell
  2004-06-12  2:40     ` DJ Delorie
@ 2004-06-12 13:42     ` Danny Smith
  1 sibling, 0 replies; 21+ messages in thread
From: Danny Smith @ 2004-06-12 13:42 UTC (permalink / raw)
  To: Mark Mitchell; +Cc: Zack Weinberg, dj, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2806 bytes --]

From: "Mark Mitchell"
| Danny, would you post the full patch so that DJ can more easily consier
| it?

I may be too late for this, but this  works for me,  This has
been in mingw32 binary release candidate for 3.4.0 since early May, with
no bug reports.

I didn't know where to put declarations for pex_read, pex_read_close
 but at the time I wanted to make as private as possible, so I put into new header.

It may be more politically correct to change the HOST_QUOTE_STR,
HOST_QUOTE_CHAR.HOST_QUOTED_QUOTE_STR host macros in host hook
functions, but that seemed like overkill.

Patch against  truk is attached,  I've just bootstrapped c,c++ with this and regtested
with no new
regressions.  The tests using -frepo now pass.

Danny


ChangeLog


        Ian Lance Taylor  <ian@wasabisystems.com>

        * collect2.c (collect_status): New static function, broken out of
        collect_wait.
        (collect_wait): Call collect_status.
        (do_read_wait): New static function.
        (scan_prog_file): Call pex_read instead of pipe and vfork.
        (scan_libraries): Likewise.

        Mark Mithchell  <mmitchel@gcc.gnu.org>

        * collect2.c  (collect_execute): Pass third argument to open.
        * gcc.c (set_collect_gcc_options): Use HOST_QUOTE_STR,
        HOST_QUOTE_CHAR. HOST_QUOTED_QUOTE_STR.
        * tlink.c (recompile_files): Do not assume that "rename" can
        overwrite an existing file.  Use "&&" as the command separator
        rather than ";".

        Danny Smith  <dannysmith@users.sourceforge,net>

        * collect2.c: Include pex-read.h.
        (handler): Just raise (signo) if ! HAVE_KILL.
        * config.host (i[34567]86-*-mingw*): Host can use collect2.
        * system,h: (HOST_QUOTE_STR, HOST_QUOTE_CHAR.
        HOST_QUOTED_QUOTE_STR): New defines.
        * config/i386/xm-mingw32 (HOST_QUOTE_STR, HOST_QUOTE_CHAR.
        HOST_QUOTED_QUOTE_STR): Override defaults.


libiberty/Changelog

        Ian Lance Taylor  <ian@wasabisystems.com>

        * pexrd-unix.c: New file.
        * pexrd-generic.c: New file.
        * configure.ac: Add either ./pexrd-unix.o or ./pexrd-generic.o to
        pexecute.
        * /Makefile.in: Run maint-deps.
        (CFILES): Add pexrd-unix.c and pexrd-generic.c.
        (CONFIGURED_OFILES): Add ./pexrd-unix.o and ./pexrd-generic.o.
        * pexecute.txh: Document pex_read and pex_read_close.

include/ChangeLog

        Danny Smith <dannysmith@users.sourceforge,net>

        * include/pex-read.h. New file. Declare pex_read, pex_read_close.

cp/ChangeLog

        Mark Mithchell  <mmitchel@gcc.gnu.org>

        * repo.c (IDENTIFIER_REPO_USED): Use tree flag 5.
        (IDENTIFIER_REPO_CHOSEN): Use tree flag 6.
        (extract_string):Use HOST_QUOTE_STR,HOST_QUOTE_CHAR.
        HOST_QUOTED_QUOTE_STR.






[-- Attachment #2: mingw-collect2.diff --]
[-- Type: text/plain, Size: 27080 bytes --]

? include/pex-read.h
? libiberty/pexrd-generic.c
? libiberty/pexrd-unix.c
Index: gcc/collect2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/collect2.c,v
retrieving revision 1.162
diff -c -3 -p -r1.162 collect2.c
*** gcc/collect2.c	10 Mar 2004 00:17:34 -0000	1.162
--- gcc/collect2.c	12 Jun 2004 09:10:21 -0000
*************** Software Foundation, 59 Temple Place - S
*** 30,53 ****
  #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
--- 30,41 ----
  #include "system.h"
  #include "coretypes.h"
  #include "tm.h"
+ 
  #include <signal.h>
  #if ! defined( SIGCHLD ) && defined( SIGCLD )
  #  define SIGCHLD SIGCLD
  #endif
  
  #ifndef LIBRARY_PATH_ENV
  #define LIBRARY_PATH_ENV "LIBRARY_PATH"
  #endif
*************** Software Foundation, 59 Temple Place - S
*** 55,60 ****
--- 43,49 ----
  #define COLLECT
  
  #include "collect2.h"
+ #include "pex-read.h"
  #include "demangle.h"
  #include "obstack.h"
  #include "intl.h"
*************** static char *find_a_file (struct path_pr
*** 254,260 ****
--- 243,251 ----
  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 collect_status (const char *, int status);
  static void do_wait (const char *);
+ static void do_read_wait (const char *, FILE *);
  static void fork_execute (const char *, char **);
  static void maybe_unlink (const char *);
  static void add_to_list (struct head *, const char *);
*************** handler (int signo)
*** 423,429 ****
--- 414,424 ----
  #endif
  
    signal (signo, SIG_DFL);
+ #if HAVE_KILL
    kill (getpid (), signo);
+ #else
+   raise (signo);
+ #endif
  }
  
  \f
*************** main (int argc, char **argv)
*** 1455,1468 ****
  }
  
  \f
! /* Wait for a process to finish, and exit if a nonzero status is found.  */
  
! int
! collect_wait (const char *prog)
  {
-   int status;
- 
-   pwait (pid, &status, 0);
    if (status)
      {
        if (WIFSIGNALED (status))
--- 1450,1460 ----
  }
  
  \f
! /* Handle error status returned by a finished process.  */
  
! static int
! collect_status (const char *prog, int status)
  {
    if (status)
      {
        if (WIFSIGNALED (status))
*************** collect_wait (const char *prog)
*** 1480,1485 ****
--- 1472,1488 ----
    return 0;
  }
  
+ /* Wait for a process to finish, and exit if a nonzero status is found.  */
+ 
+ int
+ collect_wait (const char *prog)
+ {
+   int status;
+ 
+   pwait (pid, &status, 0);
+   return collect_status (prog, status);
+ }
+ 
  static void
  do_wait (const char *prog)
  {
*************** do_wait (const char *prog)
*** 1491,1496 ****
--- 1494,1512 ----
      }
  }
  
+ static void
+ do_read_wait (const char *prog, FILE *inf)
+ {
+   int status;
+ 
+   pex_read_close (pid, inf, &status, 0);
+   status = collect_status (prog, status);
+   if (status != 0)
+     {
+       error ("%s returned %d exit status", prog, status);
+       collect_exit (status);
+     }
+ }
  \f
  /* Execute a program, and wait for the reply.  */
  
*************** collect_execute (const char *prog, char 
*** 1531,1537 ****
    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.  */
--- 1547,1553 ----
    if (redir)
      {
        /* Open response file.  */
!       redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT, S_IWUSR);
  
        /* Duplicate the stdout and stderr file handles
  	 so they can be restored later.  */
*************** scan_prog_file (const char *prog_name, e
*** 1994,2002 ****
    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];
    FILE *inf;
  
    if (which_pass == PASS_SECOND)
      return;
--- 2010,2019 ----
    char *real_nm_argv[4];
    const char **nm_argv = (const char **) real_nm_argv;
    int argc = 0;
    char *p, buf[1024];
    FILE *inf;
+   char *errmsg_fmt;
+   char *errmsg_arg;
  
    if (which_pass == PASS_SECOND)
      return;
*************** scan_prog_file (const char *prog_name, e
*** 2012,2024 ****
    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");
- 
    /* Trace if needed.  */
    if (vflag)
      {
--- 2029,2034 ----
*************** scan_prog_file (const char *prog_name, e
*** 2034,2069 ****
    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");
  
--- 2044,2059 ----
    fflush (stdout);
    fflush (stderr);
  
!   inf = pex_read (nm_file_name, real_nm_argv, nm_file_name, NULL,
! 		  &errmsg_fmt, &errmsg_arg, 0, &pid);
!   if (inf == (FILE *) 0)
!     fatal_perror (errmsg_fmt, errmsg_arg);
  
    int_handler  = (void (*) (int)) signal (SIGINT,  SIG_IGN);
  #ifdef SIGQUIT
    quit_handler = (void (*) (int)) signal (SIGQUIT, SIG_IGN);
  #endif
  
    if (debug)
      fprintf (stderr, "\nnm output with constructors/destructors.\n");
  
*************** scan_prog_file (const char *prog_name, e
*** 2136,2145 ****
    if (debug)
      fprintf (stderr, "\n");
  
!   if (fclose (inf) != 0)
!     fatal_perror ("fclose");
! 
!   do_wait (nm_file_name);
  
    signal (SIGINT,  int_handler);
  #ifdef SIGQUIT
--- 2126,2132 ----
    if (debug)
      fprintf (stderr, "\n");
  
!   do_read_wait (nm_file_name, inf);
  
    signal (SIGINT,  int_handler);
  #ifdef SIGQUIT
*************** scan_libraries (const char *prog_name)
*** 2163,2171 ****
    char *real_ldd_argv[4];
    const char **ldd_argv = (const char **) real_ldd_argv;
    int argc = 0;
-   int pipe_fd[2];
    char buf[1024];
    FILE *inf;
  
    /* If we do not have an `ldd', complain.  */
    if (ldd_file_name == 0)
--- 2150,2159 ----
    char *real_ldd_argv[4];
    const char **ldd_argv = (const char **) real_ldd_argv;
    int argc = 0;
    char buf[1024];
    FILE *inf;
+   char *errmsg_fmt;
+   char *errmsg_arg;
  
    /* If we do not have an `ldd', complain.  */
    if (ldd_file_name == 0)
*************** scan_libraries (const char *prog_name)
*** 2200,2225 ****
    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);
--- 2188,2197 ----
    fflush (stdout);
    fflush (stderr);
  
!   inf = pex_read (ldd_file_name, real_ldd_argv, ldd_file_name, NULL,
! 		  &errmsg_fmt, &errmsg_arg, 0, &pid);
!   if (inf == (FILE *) 0)
!     fatal_perror (errmsg_fmt, errmsg_arg);
  
    /* Parent context from here on.  */
    int_handler  = (void (*) (int)) signal (SIGINT,  SIG_IGN);
*************** scan_libraries (const char *prog_name)
*** 2227,2235 ****
    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");
  
--- 2199,2204 ----
*************** scan_libraries (const char *prog_name)
*** 2266,2275 ****
    if (debug)
      fprintf (stderr, "\n");
  
!   if (fclose (inf) != 0)
!     fatal_perror ("fclose");
! 
!   do_wait (ldd_file_name);
  
    signal (SIGINT,  int_handler);
  #ifdef SIGQUIT
--- 2235,2241 ----
    if (debug)
      fprintf (stderr, "\n");
  
!   do_read_wait (ldd_file_name, inf);
  
    signal (SIGINT,  int_handler);
  #ifdef SIGQUIT
Index: gcc/config.host
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config.host,v
retrieving revision 2.10
diff -c -3 -p -r2.10 config.host
*** gcc/config.host	5 Jun 2004 07:28:25 -0000	2.10
--- gcc/config.host	12 Jun 2004 09:10:21 -0000
*************** case ${host} in
*** 142,148 ****
      host_xm_file=i386/xm-mingw32.h
      host_xmake_file=i386/x-mingw32
      host_exeext=.exe
-     host_can_use_collect2=no
      out_host_hook_obj=host-mingw32.o
      ;;
    i[34567]86-*-uwin*)
--- 142,147 ----
Index: gcc/gcc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gcc.c,v
retrieving revision 1.424
diff -c -3 -p -r1.424 gcc.c
*** gcc/gcc.c	4 Jun 2004 20:13:14 -0000	1.424
--- gcc/gcc.c	12 Jun 2004 09:10:48 -0000
*************** compilation is specified by a string cal
*** 88,94 ****
  #ifdef HAVE_SYS_RESOURCE_H
  #include <sys/resource.h>
  #endif
! #if defined (HAVE_DECL_GETRUSAGE) && !HAVE_DECL_GETRUSAGE
  extern int getrusage (int, struct rusage *);
  #endif
  
--- 88,94 ----
  #ifdef HAVE_SYS_RESOURCE_H
  #include <sys/resource.h>
  #endif
! #if defined (HAVE_GETRUSAGE) && defined (HAVE_DECL_GETRUSAGE) && !HAVE_DECL_GETRUSAGE
  extern int getrusage (int, struct rusage *);
  #endif
  
*************** convert_filename (const char *name, int 
*** 3022,3029 ****
  #if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
    /* If there is no filetype, make it the executable suffix (which includes
       the ".").  But don't get confused if we have just "-o".  */
!   if (! do_exe || TARGET_EXECUTABLE_SUFFIX[0] == 0 || (len == 2 && name[0] == '-'))
!     return name;
  
    for (i = len - 1; i >= 0; i--)
      if (IS_DIR_SEPARATOR (name[i]))
--- 3022,3030 ----
  #if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
    /* If there is no filetype, make it the executable suffix (which includes
       the ".").  But don't get confused if we have just "-o".  */
!   if (! do_exe || TARGET_EXECUTABLE_SUFFIX[0] == 0
!       || (len == 2 && name[0] == '-'))
!    return name;
  
    for (i = len - 1; i >= 0; i--)
      if (IS_DIR_SEPARATOR (name[i]))
*************** process_command (int argc, const char **
*** 3236,3242 ****
  			  (argc + 1) * sizeof (argv[0]));
        new_argv[0] = new_argv0;
  
!       execvp (new_argv0, new_argv);
        fatal ("couldn't run `%s': %s", new_argv0, xstrerror (errno));
      }
  
--- 3237,3243 ----
  			  (argc + 1) * sizeof (argv[0]));
        new_argv[0] = new_argv0;
  
!       execvp (new_argv0, (const char *const *)new_argv);
        fatal ("couldn't run `%s': %s", new_argv0, xstrerror (errno));
      }
  
*************** warranty; not even for MERCHANTABILITY o
*** 3735,3741 ****
  		    }
  		}
  #endif
! #if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) || defined(HAVE_TARGET_OBJECT_SUFFIX)
  	      if (p[1] == 0)
  		argv[i + 1] = convert_filename (argv[i + 1], ! have_c, 0);
  	      else
--- 3736,3742 ----
  		    }
  		}
  #endif
! #if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) || defined(HAVE_TARGET_OBJECT_SUFFIX) 
  	      if (p[1] == 0)
  		argv[i + 1] = convert_filename (argv[i + 1], ! have_c, 0);
  	      else
*************** set_collect_gcc_options (void)
*** 4172,4200 ****
        if (switches[i].live_cond == SWITCH_IGNORE)
  	continue;
  
!       obstack_grow (&collect_obstack, "'-", 2);
        q = switches[i].part1;
!       while ((p = strchr (q, '\'')))
  	{
  	  obstack_grow (&collect_obstack, q, p - q);
! 	  obstack_grow (&collect_obstack, "'\\''", 4);
  	  q = ++p;
  	}
        obstack_grow (&collect_obstack, q, strlen (q));
!       obstack_grow (&collect_obstack, "'", 1);
  
        for (args = switches[i].args; args && *args; args++)
  	{
! 	  obstack_grow (&collect_obstack, " '", 2);
  	  q = *args;
! 	  while ((p = strchr (q, '\'')))
  	    {
  	      obstack_grow (&collect_obstack, q, p - q);
! 	      obstack_grow (&collect_obstack, "'\\''", 4);
  	      q = ++p;
  	    }
  	  obstack_grow (&collect_obstack, q, strlen (q));
! 	  obstack_grow (&collect_obstack, "'", 1);
  	}
      }
    obstack_grow (&collect_obstack, "\0", 1);
--- 4173,4203 ----
        if (switches[i].live_cond == SWITCH_IGNORE)
  	continue;
  
!       obstack_grow (&collect_obstack, HOST_QUOTE_STR "-", 2);
        q = switches[i].part1;
!       while ((p = strchr (q, HOST_QUOTE_CHAR)))
  	{
  	  obstack_grow (&collect_obstack, q, p - q);
! 	  obstack_grow (&collect_obstack, HOST_QUOTED_QUOTE_STR, 
! 			strlen (HOST_QUOTED_QUOTE_STR));
  	  q = ++p;
  	}
        obstack_grow (&collect_obstack, q, strlen (q));
!       obstack_grow (&collect_obstack, HOST_QUOTE_STR, 1);
  
        for (args = switches[i].args; args && *args; args++)
  	{
! 	  obstack_grow (&collect_obstack, " " HOST_QUOTE_STR, 2);
  	  q = *args;
! 	  while ((p = strchr (q, HOST_QUOTE_CHAR)))
  	    {
  	      obstack_grow (&collect_obstack, q, p - q);
! 	      obstack_grow (&collect_obstack, HOST_QUOTED_QUOTE_STR,
! 			    strlen (HOST_QUOTED_QUOTE_STR));
  	      q = ++p;
  	    }
  	  obstack_grow (&collect_obstack, q, strlen (q));
! 	  obstack_grow (&collect_obstack, HOST_QUOTE_STR, 1);
  	}
      }
    obstack_grow (&collect_obstack, "\0", 1);
*************** do_spec_1 (const char *spec, int inswitc
*** 4779,4784 ****
--- 4782,4788 ----
  		    strncpy ((char *) temp_filename + basename_length, suffix,
  			     suffix_length);
  		    *((char *) temp_filename + temp_filename_length) = '\0';
+ 
  		    if (strcmp (temp_filename, input_filename) != 0)
  		      {
  			struct stat st_temp;
*************** do_spec_1 (const char *spec, int inswitc
*** 4795,4801 ****
  			   and we can do the stat for the temp_filename
  			   then the they could still refer to the same
  			   file if st_dev/st_ino's are the same.  */
- 
  			if (input_stat_set != 1
  			    || stat (temp_filename, &st_temp) < 0
  			    || input_stat.st_dev != st_temp.st_dev
--- 4799,4804 ----
Index: gcc/system.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/system.h,v
retrieving revision 1.213
diff -c -3 -p -r1.213 system.h
*** gcc/system.h	24 May 2004 10:50:40 -0000	1.213
--- gcc/system.h	12 Jun 2004 09:11:01 -0000
*************** extern int snprintf (char *, size_t, con
*** 476,481 ****
--- 476,503 ----
  #define HOST_BIT_BUCKET "/dev/null"
  #endif
  
+ /* Provide a default for alignment of address space when
+    reserving virtual memory. On most hosts this is pagesize,
+    but on some hosts it differs from the alignment required
+    when commiting virtual memory.  */
+ 
+ #ifndef HOST_MMAP_ALLOC_GRANULARITY
+ #define HOST_MMAP_ALLOC_GRANULARITY getpagesize()
+ #endif
+ 
+ /* Defaults for building quoted strings for COLLECT_GCC_OPTIONS
+    environment variable.  These work for POSIX-like hosts. */
+ 
+ #ifndef HOST_QUOTE_STR
+ #define HOST_QUOTE_STR "\'"
+ #endif
+ #ifndef HOST_QUOTE_CHAR
+ #define HOST_QUOTE_CHAR '\''
+ #endif
+ #ifndef HOST_QUOTED_QUOTE_STR
+ #define HOST_QUOTED_QUOTE_STR "'\\''"
+ #endif
+ 
  /* Be conservative and only use enum bitfields with GCC.
     FIXME: provide a complete autoconf test for buggy enum bitfields.  */
  
Index: gcc/tlink.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tlink.c,v
retrieving revision 1.55
diff -c -3 -p -r1.55 tlink.c
*** gcc/tlink.c	19 Jul 2003 14:47:14 -0000	1.55
--- gcc/tlink.c	12 Jun 2004 09:11:05 -0000
*************** recompile_files (void)
*** 463,473 ****
  	}
        fclose (stream);
        fclose (output);
!       rename (outname, f->key);
  
        obstack_grow (&temporary_obstack, "cd ", 3);
        obstack_grow (&temporary_obstack, f->dir, strlen (f->dir));
!       obstack_grow (&temporary_obstack, "; ", 2);
        obstack_grow (&temporary_obstack, c_file_name, strlen (c_file_name));
        obstack_1grow (&temporary_obstack, ' ');
        obstack_grow (&temporary_obstack, f->args, strlen (f->args));
--- 463,482 ----
  	}
        fclose (stream);
        fclose (output);
!       /* On Windows "rename" returns -1 and sets ERRNO to EACCESS if
! 	 the new file name already exists.  Therefore, we explicitly
! 	 remove the old file first.  */
!       if (remove (f->key) == -1)
! 	fatal_perror ("removing .rpo file");
!       if (rename (outname, f->key) == -1)
! 	fatal_perror ("renaming .rpo file");
  
        obstack_grow (&temporary_obstack, "cd ", 3);
        obstack_grow (&temporary_obstack, f->dir, strlen (f->dir));
!       /* Using ";" as a separator between commands does not work with
! 	 the Windows command shell.  Therefore, we use "&&" which
! 	 should work everywhere.  */
!       obstack_grow (&temporary_obstack, " && ", 4);
        obstack_grow (&temporary_obstack, c_file_name, strlen (c_file_name));
        obstack_1grow (&temporary_obstack, ' ');
        obstack_grow (&temporary_obstack, f->args, strlen (f->args));
Index: gcc/config/i386/xm-mingw32.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/xm-mingw32.h,v
retrieving revision 1.20
diff -c -3 -p -r1.20 xm-mingw32.h
*** gcc/config/i386/xm-mingw32.h	31 Jan 2004 02:06:57 -0000	1.20
--- gcc/config/i386/xm-mingw32.h	12 Jun 2004 09:11:58 -0000
*************** Software Foundation, 59 Temple Place - S
*** 27,29 ****
--- 27,35 ----
  
  /* This is the name of the null device on windows.  */
  #define HOST_BIT_BUCKET "nul"
+  
+ /* Windows way to build quoted strings for COLLECT_GCC_OPTIONS
+    environment variable.  */
+ #define HOST_QUOTE_STR "\""
+ #define HOST_QUOTE_CHAR '"'
+ #define HOST_QUOTED_QUOTE_STR "\"\\\"\""
Index: gcc/cp/repo.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/repo.c,v
retrieving revision 1.49
diff -c -3 -p -r1.49 repo.c
*** gcc/cp/repo.c	19 Dec 2003 23:28:09 -0000	1.49
--- gcc/cp/repo.c	12 Jun 2004 09:12:48 -0000
***************
*** 1,5 ****
  /* Code to maintain a C++ template repository.
!    Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003
     Free Software Foundation, Inc.
     Contributed by Jason Merrill (jason@cygnus.com)
  
--- 1,5 ----
  /* Code to maintain a C++ template repository.
!    Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004
     Free Software Foundation, Inc.
     Contributed by Jason Merrill (jason@cygnus.com)
  
*************** static const char *old_args, *old_dir, *
*** 53,60 ****
  
  static struct obstack temporary_obstack;
  
! #define IDENTIFIER_REPO_USED(NODE)   (TREE_LANG_FLAG_3 (NODE))
! #define IDENTIFIER_REPO_CHOSEN(NODE) (TREE_LANG_FLAG_4 (NODE))
  
  #if 0
  /* Record the flags used to compile this translation unit.  */
--- 53,60 ----
  
  static struct obstack temporary_obstack;
  
! #define IDENTIFIER_REPO_USED(NODE)   (TREE_LANG_FLAG_5 (NODE))
! #define IDENTIFIER_REPO_CHOSEN(NODE) (TREE_LANG_FLAG_6 (NODE))
  
  #if 0
  /* Record the flags used to compile this translation unit.  */
*************** extract_string (char **pp)
*** 223,229 ****
  	break;
        else if (! inside && c == '\\')
  	backquote = 1;
!       else if (c == '\'')
  	inside = !inside;
        else
  	obstack_1grow (&temporary_obstack, c);
--- 223,229 ----
  	break;
        else if (! inside && c == '\\')
  	backquote = 1;
!       else if (c == HOST_QUOTE_CHAR)
  	inside = !inside;
        else
  	obstack_1grow (&temporary_obstack, c);
Index: libiberty/Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/libiberty/Makefile.in,v
retrieving revision 1.101
diff -c -3 -p -r1.101 Makefile.in
*** libiberty/Makefile.in	25 May 2004 19:37:02 -0000	1.101
--- libiberty/Makefile.in	12 Jun 2004 09:14:03 -0000
*************** CFILES = alloca.c argv.c asprintf.c atex
*** 144,149 ****
--- 144,150 ----
  	partition.c							\
  	 pex-djgpp.c pex-mpw.c pex-msdos.c pex-os2.c			\
  	 pex-unix.c pex-win32.c						\
+ 	 pexrd-unix.c pexrd-generic.c					\
           physmem.c putenv.c						\
  	random.c regex.c rename.c rindex.c				\
  	safe-ctype.c setenv.c sigsetmask.c snprintf.c sort.c spaces.c	\
*************** $(CONFIGURED_OFILES): stamp-picdir
*** 790,795 ****
--- 791,810 ----
  	else true; fi
  	$(COMPILE.c) $(srcdir)/pex-win32.c $(OUTPUT_OPTION)
  
+ ./pexrd-generic.o: $(srcdir)/pexrd-generic.c config.h $(INCDIR)/ansidecl.h \
+ 	$(INCDIR)/libiberty.h $(srcdir)/pex-common.h  $(INCDIR)/pex-read.h
+ 	if [ x"$(PICFLAG)" != x ]; then \
+ 	  $(COMPILE.c) $(PICFLAG) $(srcdir)/pexrd-generic.c -o pic/$@; \
+ 	else true; fi
+ 	$(COMPILE.c) $(srcdir)/pexrd-generic.c $(OUTPUT_OPTION)
+ 
+ ./pexrd-unix.o: $(srcdir)/pexrd-unix.c config.h $(INCDIR)/ansidecl.h \
+ 	$(INCDIR)/libiberty.h $(srcdir)/pex-common.h  $(INCDIR)/pex-read.h
+ 	if [ x"$(PICFLAG)" != x ]; then \
+ 	  $(COMPILE.c) $(PICFLAG) $(srcdir)/pexrd-unix.c -o pic/$@; \
+ 	else true; fi
+ 	$(COMPILE.c) $(srcdir)/pexrd-unix.c $(OUTPUT_OPTION)
+ 
  ./physmem.o: $(srcdir)/physmem.c config.h $(INCDIR)/ansidecl.h \
  	$(INCDIR)/libiberty.h
  	if [ x"$(PICFLAG)" != x ]; then \
Index: libiberty/configure.ac
===================================================================
RCS file: /cvs/gcc/gcc/libiberty/configure.ac,v
retrieving revision 1.6
diff -c -3 -p -r1.6 configure.ac
*** libiberty/configure.ac	26 Apr 2004 14:21:49 -0000	1.6
--- libiberty/configure.ac	12 Jun 2004 09:14:26 -0000
*************** fi
*** 512,522 ****
  
  # Figure out which version of pexecute to use.
  case "${host}" in
!      *-*-mingw* | *-*-winnt*)	pexecute=./pex-win32.o  ;;
!      *-*-msdosdjgpp*)		pexecute=./pex-djgpp.o  ;;
!      *-*-msdos*)		pexecute=./pex-msdos.o  ;;
!      *-*-os2-emx*)		pexecute=./pex-os2.o    ;;
!      *)				pexecute=./pex-unix.o   ;;
  esac
  AC_SUBST(pexecute)
  
--- 512,522 ----
  
  # Figure out which version of pexecute to use.
  case "${host}" in
!      *-*-mingw* | *-*-winnt*)	pexecute="./pex-win32.o ./pexrd-generic.o"  ;;
!      *-*-msdosdjgpp*)		pexecute="./pex-djgpp.o ./pexrd-generic.o"  ;;
!      *-*-msdos*)		pexecute="./pex-msdos.o ./pexrd-generic.o"  ;;
!      *-*-os2-emx*)		pexecute="./pex-os2.o   ./pexrd-generic.o"  ;;
!      *)				pexecute="./pex-unix.o  ./pexrd-unix.o"     ;;
  esac
  AC_SUBST(pexecute)
  
Index: libiberty/pexecute.txh
===================================================================
RCS file: /cvs/gcc/gcc/libiberty/pexecute.txh,v
retrieving revision 1.1
diff -c -3 -p -r1.1 pexecute.txh
*** libiberty/pexecute.txh	24 Jan 2003 20:02:11 -0000	1.1
--- libiberty/pexecute.txh	12 Jun 2004 09:20:30 -0000
***************
*** 1,4 ****
! @deftypefn Extension int pexecute (const char *@var{program}, char * const *@var{argv}, const char *@var{this_pname}, const char *@var{temp_base}, char **@var{errmsg_fmt}, char **@var{errmsg_arg}, int flags)
  
  Executes a program.
  
--- 1,4 ----
! @deftypefn Extension int pexecute (const char *@var{program}, char * const *@var{argv}, const char *@var{this_pname}, const char *@var{temp_base}, char **@var{errmsg_fmt}, char **@var{errmsg_arg}, int @var{flags})
  
  Executes a program.
  
*************** pfinish: finish generation of script
*** 61,63 ****
--- 61,99 ----
  
  pfinish is necessary for systems like MPW where a script is generated
  that runs the requested programs.
+ 
+ @end undocumented
+ 
+ @deftypefn Extension FILE* pex_read (const char *@var{program}, char * const *@var{argv}, const char *@var{this_pname}, const char *@var{temp_base}, char **@var{errmsg_fmt}, char **@var{errmsg_arg}, int @var{flags}, int *@var{pidptr})
+ 
+ Executes a program and returns a stdio file for the program's standard
+ output.  This is a safe version of the usual Unix function
+ @code{popen}.
+ 
+ The first seven parameters are the same as for @code{pexecute}.  The
+ last parameter returns a process identifier to be passed to
+ @code{pex_read_close}.
+ 
+ The only flags used for the @var{flags} parameter is
+ @code{PEXECUTE_SEARCH}.
+ 
+ Upon failure, @var{errmsg_fmt} and @var{errmsg_arg} are set to the
+ text of the error message with an optional argument (if not needed,
+ @var{errmsg_arg} is set to @code{NULL}), and @code{NULL} is returned.
+ @code{errno} is available to the caller to use.
+ 
+ @end deftypefn
+ 
+ @deftypefn Extension int pex_read_close (int @var{pid}, FILE *@var{file}, int *@var{status}, int @var{flags})
+ 
+ Close a file opened by @code{pex_read}, and wait for the subprocess to
+ complete.  The @var{pid} and @var{file} arguments should have been
+ obtained from a call to @code{pex_read}.
+ 
+ The result is the pid of the child reaped, or -1 for failure
+ (@code{errno} says why).
+ 
+ On a successful return, *@var{status} is set to the exit status of the
+ subprocess.
+ 
+ @end deftypefn

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2004-06-12  9:50 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-06-11 22:31 PATCH to support native Windows builds Mark Mitchell
2004-06-11 22:57 ` DJ Delorie
2004-06-11 23:21   ` Mark Mitchell
2004-06-12  0:28     ` DJ Delorie
2004-06-11 23:50 ` Aaron W. LaFramboise
2004-06-11 23:56   ` Zack Weinberg
2004-06-12  0:01   ` Mark Mitchell
2004-06-11 23:54 ` Paolo Carlini
2004-06-12  0:10   ` Mark Mitchell
2004-06-12  0:53 ` Danny Smith
2004-06-12  1:08   ` Mark Mitchell
2004-06-12  2:40     ` DJ Delorie
2004-06-12  2:48       ` Mark Mitchell
2004-06-12  3:59         ` Ian Lance Taylor
2004-06-12  4:23           ` Zack Weinberg
2004-06-12  5:57             ` Mark Mitchell
2004-06-12  7:06               ` Ian Lance Taylor
2004-06-12  8:12                 ` Mark Mitchell
2004-06-12  6:02             ` Ian Lance Taylor
2004-06-12  8:14               ` Zack Weinberg
2004-06-12 13:42     ` Danny Smith

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).