* 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 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 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 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 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: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 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 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 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 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).