# Patch created by Maciek
# Date: Sun Apr 25 01:13:29 WAST 2004
# Repository: pnet
# Comments:
# Added support for process spawning and pipe redirection on Windows (MinGW) in support/spawn.c; changed cscc/common/cc_main.c (SpawnOnPipe, ClosePipe) to wrap around the functions in spawn.c 
#### End of Preamble ####

#### Patch data follows ####
Index: ChangeLog
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/ChangeLog,v
retrieving revision 1.2928
diff -c -r1.2928 ChangeLog
*** ChangeLog	24 Apr 2004 13:41:22 -0000	1.2928
--- ChangeLog	24 Apr 2004 17:14:06 -0000
***************
*** 1,3 ****
--- 1,14 ----
+ 2004-04-25  Maciek Plewa <maciek@mil-sim.net>
+ 
+ 	* support/spawn.c: Add process spawning and pipe redirection
+ 	support for Windows native (MinGW). Add utility functions
+ 	build_command, winerror, checknt
+ 
+ 	* cscc/common/cc_main.c: Renamed LoadLibrary to
+ 	LoadLibraryCodeGen to prevent name conflict with Windows API;
+ 	modified SpawnOnPipe and ClosePipe to wrap around
+ 	ILSpawnProcessWithPipe and ILSpawnProcessWaitForExit
+ 	(support/spawn.c)
  
  2004-04-24  Gopal V <gopalv82@yahoo.com>
  
Index: cscc/common/cc_main.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/cscc/common/cc_main.c,v
retrieving revision 1.33
diff -c -r1.33 cc_main.c
*** cscc/common/cc_main.c	14 Mar 2004 02:54:45 -0000	1.33
--- cscc/common/cc_main.c	24 Apr 2004 17:14:22 -0000
***************
*** 20,25 ****
--- 20,27 ----
  
  #include "cc_main.h"
  #include "cc_preproc.h"
+ #include "il_utils.h"
+ 
  #ifdef HAVE_SYS_TYPES_H
  	#include <sys/types.h>
  #endif
***************
*** 367,373 ****
   * Load the contents of a library into the code generator's context.
   * Returns zero if the library load failed.
   */
! static int LoadLibrary(const char *name, int nostdlib_flag, int later_load)
  {
  	int len;
  	int index;
--- 369,375 ----
   * Load the contents of a library into the code generator's context.
   * Returns zero if the library load failed.
   */
! static int LoadLibraryCodeGen(const char *name, int nostdlib_flag, int later_load)
  {
  	int len;
  	int index;
***************
*** 551,557 ****
  		{
  			name = "mscorlib";
  		}
! 		if(!LoadLibrary(name, 0, 0))
  		{
  			return 1;
  		}
--- 553,559 ----
  		{
  			name = "mscorlib";
  		}
! 		if(!LoadLibraryCodeGen(name, 0, 0))
  		{
  			return 1;
  		}
***************
*** 567,573 ****
  	/* Load all of the other libraries, in reverse order */
  	for(library = num_libraries - 1; library >= 0; --library)
  	{
! 		if(!LoadLibrary(libraries[library], nostdlib_flag, 0))
  		{
  			return 1;
  		}
--- 569,575 ----
  	/* Load all of the other libraries, in reverse order */
  	for(library = num_libraries - 1; library >= 0; --library)
  	{
! 		if(!LoadLibraryCodeGen(libraries[library], nostdlib_flag, 0))
  		{
  			return 1;
  		}
***************
*** 722,730 ****
   */
  static FILE *SpawnOnPipe(char **argv, int *pid)
  {
! #if defined(HAVE_FORK) && defined(HAVE_EXECV) && (defined(HAVE_WAITPID) || defined(HAVE_WAIT))
! 	int pipefds[2];
! 	FILE *file;
  
  	/* Report the command line if verbose mode is enabled */
  	if(verbose_mode == VERBOSE_CMDLINES)
--- 724,731 ----
   */
  static FILE *SpawnOnPipe(char **argv, int *pid)
  {
! 	FILE *file = 0;
! 	int tpid = 0;
  
  	/* Report the command line if verbose mode is enabled */
  	if(verbose_mode == VERBOSE_CMDLINES)
***************
*** 741,808 ****
  		putc('\n', stderr);
  	}
  
! 	/* Create a pipe to use to communicate with the child */
! 	if(pipe(pipefds) < 0)
! 	{
! 		perror("pipe");
! 		return 0;
! 	}
  
! 	/* Fork and create the child process */
! 	*pid = fork();
! 	if(*pid < 0)
! 	{
! 		/* We weren't able to fork the process */
! 		perror("fork");
! 		return 0;
! 	}
! 	else if(*pid == 0)
  	{
! 		/* We are in the child */
! 		dup2(pipefds[1], 1);
! 		close(pipefds[0]);
! 		close(pipefds[1]);
! 		execvp(argv[0], argv);
! 		perror("execvp");
! 		exit(1);
! 	}
! 	else
! 	{
! 		/* We are in the parent */
! 		close(pipefds[1]);
! 		file = fdopen(pipefds[0], "r");
! 		if(!file)
! 		{
! 			perror("fdopen");
! 		}
  		return file;
  	}
! 
! #else
! 	fputs("Don't know how to spawn child processes on this system\n", stderr);
! 	return 0;
! #endif
  }
  
! /*
!  * Close the pipe that was created by "SpawnOnPipe".
!  */
! static int ClosePipe(FILE *file, int pid)
! {
! #if defined(HAVE_FORK) && defined(HAVE_EXECV) && (defined(HAVE_WAITPID) || defined(HAVE_WAIT))
! 	int status = 1;
! 	fclose(file);
! #ifdef HAVE_WAITPID
! 	waitpid(pid, &status, 0);
! #else
! 	{
! 		int result;
! 		while((result = wait(&status)) != pid && result != -1)
! 		{
! 			/* Some other child fell: not the one we are interested in */
! 		}
! 	}
! #endif
  	if(WIFEXITED(status))
  	{
  		return (WEXITSTATUS(status) == 0);
--- 742,769 ----
  		putc('\n', stderr);
  	}
  
! 	tpid = ILSpawnProcessWithPipe(argv, (void **)&file);
  
! 	if ((file) && (tpid))
  	{
! 		*pid = tpid;
  		return file;
  	}
! 	else
! 		return 0;
  }
  
! /*
!  * Close the pipe that was created by "ILSpawnProcessWithPipe".
!  */
! static int ClosePipe(FILE *file, int pid, char *argv[])
! {
! 	int status = 0;
! 
! 	fclose(file);
! 
! 	status = ILSpawnProcessWaitForExit(pid, argv);
! 
  	if(WIFEXITED(status))
  	{
  		return (WEXITSTATUS(status) == 0);
***************
*** 811,820 ****
  	{
  		return 0;
  	}
! #else
! 	return 0;
! #endif
! }
  
  /*
   * Import the list of macros to undefine from the system "cpp"
--- 772,778 ----
  	{
  		return 0;
  	}
! }
  
  /*
   * Import the list of macros to undefine from the system "cpp"
***************
*** 1033,1039 ****
  		if(preprocess_flag)
  		{
  			CCHaveErrors |= Preprocess();
! 			if(!ClosePipe(file, pid))
  			{
  				CCHaveErrors |= 1;
  			}
--- 991,997 ----
  		if(preprocess_flag)
  		{
  			CCHaveErrors |= Preprocess();
! 			if(!ClosePipe(file, pid, argv))
  			{
  				CCHaveErrors |= 1;
  			}
***************
*** 1071,1077 ****
  	}
  	else if(fileIsPipe)
  	{
! 		if(!ClosePipe(file, pid))
  		{
  			CCHaveErrors |= 1;
  		}
--- 1029,1035 ----
  	}
  	else if(fileIsPipe)
  	{
! 		if(!ClosePipe(file, pid, argv))
  		{
  			CCHaveErrors |= 1;
  		}
***************
*** 1320,1326 ****
  
  int CCLoadLibrary(const char *name)
  {
! 	return LoadLibrary(name, nostdlib_flag, 1);
  }
  
  /*
--- 1278,1284 ----
  
  int CCLoadLibrary(const char *name)
  {
! 	return LoadLibraryCodeGen(name, nostdlib_flag, 1);
  }
  
  /*
Index: support/spawn.c
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnet/support/spawn.c,v
retrieving revision 1.9
diff -c -r1.9 spawn.c
*** support/spawn.c	15 May 2003 02:46:28 -0000	1.9
--- support/spawn.c	24 Apr 2004 17:14:46 -0000
***************
*** 21,30 ****
  #include "il_system.h"
  #include "il_utils.h"
  #include <stdio.h>
  #ifdef IL_WIN32_PLATFORM
  	#include <windows.h>
  	#include <process.h>
! #elif !defined(__palmos__)
  	#ifdef HAVE_SYS_TYPES_H
  		#include <sys/types.h>
  	#endif
--- 21,42 ----
  #include "il_system.h"
  #include "il_utils.h"
  #include <stdio.h>
+ 
+ #if defined(HAVE_FORK) && defined(HAVE_EXECV) && (defined(HAVE_WAITPID) || defined(HAVE_WAIT))
+ 	#define UNIX_SPAWN
+ #endif
+ 
  #ifdef IL_WIN32_PLATFORM
  	#include <windows.h>
+ 	#include <stdlib.h>
+ 	#include <stdio.h>
  	#include <process.h>
! 	#include <errno.h>
! 	#include <io.h>
! 	#include <fcntl.h> 
! #endif
! 
! #if !defined(__palmos__) && !defined(IL_WIN32_NATIVE)
  	#ifdef HAVE_SYS_TYPES_H
  		#include <sys/types.h>
  	#endif
***************
*** 34,65 ****
  	#ifdef HAVE_SYS_WAIT_H
  		#include <sys/wait.h>
  	#endif
- 	#ifndef WEXITSTATUS
- 		#define	WEXITSTATUS(status)		((unsigned)(status) >> 8)
- 	#endif
- 	#ifndef WIFEXITED
- 		#define	WIFEXITED(status)		(((status) & 255) == 0)
- 	#endif
- 	#ifndef WTERMSIG
- 		#define	WTERMSIG(status)		(((unsigned)(status)) & 0x7F)
- 	#endif
- 	#ifndef WIFSIGNALLED
- 		#define	WIFSIGNALLED(status)	(((status) & 255) != 0)
- 	#endif
- 	#ifndef WCOREDUMP
- 		#define	WCOREDUMP(status)		(((status) & 0x80) != 0)
- 	#endif
  	#include <signal.h>
  #endif
  
  #ifdef	__cplusplus
  extern	"C" {
  #endif
  
  #ifdef IL_WIN32_PLATFORM
  
  /*
   * Use Windows-specific functions to spawn child processes.
   */
  int ILSpawnProcess(char *argv[])
  {
--- 46,315 ----
  	#ifdef HAVE_SYS_WAIT_H
  		#include <sys/wait.h>
  	#endif
  	#include <signal.h>
  #endif
  
+ #ifndef WEXITSTATUS
+ 	#define	WEXITSTATUS(status)		((unsigned)(status) >> 8)
+ #endif
+ #ifndef WIFEXITED
+ 	#define	WIFEXITED(status)		(((status) & 255) == 0)
+ #endif
+ #ifndef WTERMSIG
+ 	#define	WTERMSIG(status)		(((unsigned)(status)) & 0x7F)
+ #endif
+ #ifndef WIFSIGNALLED
+ 	#define	WIFSIGNALLED(status)	(((status) & 255) != 0)
+ #endif
+ #ifndef WCOREDUMP
+ 	#define	WCOREDUMP(status)		(((status) & 0x80) != 0)
+ #endif
+ 
  #ifdef	__cplusplus
  extern	"C" {
  #endif
  
+ 
+ /* Given an array of arguments that one might pass to spawnv,
+    construct a command line that one might pass to CreateProcess.
+    Try to quote things appropriately.  
+ 
+    This file is part of GNU CVS.
+    Copyright (c) 1993-1994 Brian Berliner
+    Copyright (c) 1992 Brian Berliner and Jeff Polk
+    Copyright (c) 1989-1992, Brian Berliner
+    All Rights Reserved 
+ */
+ char *build_command (char **argv)
+ {
+     int len;
+ 
+     /* Compute the total length the command will have.  */
+     {
+         int i;
+ 
+ 	len = 0;
+         for (i = 0; argv[i]; i++)
+ 	{
+ 	    char *p;
+ 
+ 	    len += 2;  /* for the double quotes */
+ 
+ 	    for (p = argv[i]; *p; p++)
+ 	    {
+ 	        if (*p == '"')
+ 		    len += 2;
+ 		else
+ 		    len++;
+ 	    }
+ 	    len++;  /* for the space or the '\0'  */
+ 	}
+     }
+ 
+     {
+ 	/* The + 10 is in case len is 0.  */
+         char *command = (char *) malloc (len + 10);
+ 	int i;
+ 	char *p;
+ 
+ 	if (! command)
+ 	{
+ 	    errno = ENOMEM;
+ 	    return command;
+ 	}
+ 
+ 	p = command;
+         *p = '\0';
+ 	/* copy each element of argv to command, putting each command
+ 	   in double quotes, and backslashing any quotes that appear
+ 	   within an argument.  */
+ 	for (i = 0; argv[i]; i++)
+ 	{
+ 	    char *a;
+ 	    *p++ = '"';
+ 	    for (a = argv[i]; *a; a++)
+ 	    {
+ 	        if (*a == '"')
+ 		    *p++ = '\\', *p++ = '"';
+ 		else
+ 		    *p++ = *a;
+ 	    }
+ 	    *p++ = '"';
+ 	    *p++ = ' ';
+ 	}
+ 	if (p > command)
+ 	    p[-1] = '\0';
+ 
+         return command;
+     }
+ }
+ 
  #ifdef IL_WIN32_PLATFORM
  
+ #ifdef IL_WIN32_NATIVE
+ /* Checks if the operating system is Windows NT (NT/2000/XP/2003)
+    returns 1 if yes, or 0 if not */
+ int checknt()
+ {
+ 	OSVERSIONINFO osv;
+ 	osv.dwOSVersionInfoSize = sizeof(osv);
+ 	
+ 	GetVersionEx(&osv);
+ 
+ 	if (osv.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ 		return TRUE;
+ 	else
+ 		return FALSE;
+ }
+ 
+ /* perror for Windows - shows last Windows error message */
+ void winerror(const char *message)
+ {
+ 	LPVOID sysmsg;
+ 
+ 	FormatMessage(
+ 		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ 		NULL,
+ 		GetLastError(),
+ 		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ 		(LPTSTR) &sysmsg,
+ 		0,
+ 		NULL
+ 	);
+ 
+ 	fprintf(stderr, "%s: %s\n", message, (char *)sysmsg);
+ 
+ 	LocalFree(sysmsg);
+ }
+ 
+ /* Spawns a new process with argument list 'argv'
+  * and redirects its standard output to 'stream'
+  *
+  * Returns a handle of the newly created process
+  *  
+  * This function is for Windows (native)
+  */
+ int ILSpawnProcessWithPipe(char *argv[], void **stream)
+ {
+ 	STARTUPINFO si;
+ 	SECURITY_ATTRIBUTES sa;
+ 	SECURITY_DESCRIPTOR sd;
+ 	PROCESS_INFORMATION pi;
+ 	HANDLE read_pipe, write_pipe;
+ 
+ 	int fd, create;
+ 	char *command;
+ 
+ 	/* Turn argv into a form acceptable to CreateProcess.  */
+ 	command = build_command (argv); 
+ 
+ 	/* Set the length of the security attribute structure and allow
+ 	   the handle to be inherited by child processes */
+ 
+ 	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ 	sa.bInheritHandle = TRUE;
+ 
+ 	/* Use security descriptor for the new pipe on Windows NT-based systems */
+ 
+ 	if (checknt())
+ 	{
+ 		InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
+ 		SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
+ 		sa.lpSecurityDescriptor = &sd;
+ 	}
+ 	/* Pipe will use ACLs from default descriptor */
+ 	else
+ 		sa.lpSecurityDescriptor = NULL;
+ 
+ 	/* Create a new pipe with system's default buffer size */
+ 	if (!CreatePipe(&read_pipe, &write_pipe, &sa, 0))
+ 	{
+ 		winerror("CreatePipe");
+ 
+ 		CloseHandle(read_pipe);
+ 		CloseHandle(write_pipe);
+ 
+ 		return -1;
+ 	}
+ 
+ 	GetStartupInfo(&si);
+ 
+ 	/* Sets the standard output handle for the process to the
+ 	   handle specified in hStdOutput */
+ 	si.dwFlags = STARTF_USESTDHANDLES;
+ 
+ 	si.hStdOutput = write_pipe;
+ 
+ 	create = CreateProcess(
+ 		NULL,				// The full path of app to launch
+ 		command,					// Command line parameters
+ 		NULL,					// Default process security attributes
+ 		NULL,					// Default thread security attributes
+ 		TRUE,					// Inherit handles from the parent
+ 		0,						// Normal priority
+ 		NULL,					// Use the same environment as the parent
+ 		NULL,					// Use app's directory as current
+ 		&si,					// Startup Information
+ 		&pi);					// Process information stored upon return
+ 
+ 	if (!create)
+ 	{
+ 		winerror("CreateProcess");
+ 
+ 		CloseHandle(read_pipe);
+ 		CloseHandle(write_pipe);
+ 
+ 		return -1;
+ 	}
+ 
+ 	/* Associates a file descriptor with the stdout pipe */
+ 	fd = _open_osfhandle((LONG)read_pipe, _O_BINARY);
+ 
+ 	/* Close the handle that we're not going to use */
+ 	CloseHandle(write_pipe);
+ 
+ 	if (!fd)
+ 	{
+ 		perror("_open_osfhandle");
+ 		return -1;
+ 	}
+ 
+ 	/* Open the pipe stream using its file descriptor */
+ 	*stream = fdopen(fd, "r");
+ 
+ 	if(!(*stream))
+ 	{
+ 		perror("fdopen");
+ 		close(fd);
+ 		return -1;
+ 	}
+ 
+ 	return (int) pi.hProcess;
+ }
+ 
+ /* Wait for a process specified by pid to exit
+  * and return it's status code
+  *
+  * This function is for Windows (native)
+  */
+ int ILSpawnProcessWaitForExit(int pid, char *argv[])
+ {
+ 	int status = 0;
+ 
+ 	if (_cwait(&status, pid, _WAIT_CHILD) == pid)
+ 	{
+ 		return WEXITSTATUS((int)status);
+ 	}
+ 	else
+ 		return -1;
+ }
+ 
+ #endif // IL_WIN32_NATIVE
+ 
  /*
   * Use Windows-specific functions to spawn child processes.
+  *
+  * This function is for Cygwin and Windows native
   */
  int ILSpawnProcess(char *argv[])
  {
***************
*** 206,231 ****
  	return status;
  }
  
! int ILSpawnProcessWithPipe(char *argv[], void **stream)
! {
! 	/* Not supported */
! 	return 0;
! }
  
! int ILSpawnProcessWaitForExit(int pid, char *argv[])
  {
! 	/* Not supported */
! 	return 1;
  }
  
! #else
! #if defined(HAVE_FORK) && defined(HAVE_EXECV) && (defined(HAVE_WAITPID) || defined(HAVE_WAIT))
  
  /*
   * Determine if a signal is important enough to be reported.
   * Simple exits like SIGINT, SIGTERM, etc are not considered
   * important as they are "normal" ways to abort a process.
   */
  static int ImportantSignal(unsigned sig)
  {
  #ifdef SIGSEGV
--- 456,505 ----
  	return status;
  }
  
! #endif // IL_WIN32_PLATFORM
  
! #if defined(UNIX_PIPES) && !defined(IL_WIN32_CYGWIN)
! 
! 
! /*
!  * Use Unix-specific functions to spawn child processes.
!  */
! int ILSpawnProcess(char *argv[])
  {
! 	int pid = fork();
! 	if(pid < 0)
! 	{
! 		/* Could not fork the child process */
! 		perror("fork");
! 		return -1;
! 	}
! 	else if(pid == 0)
! 	{
! 		/* We are in the child process */
! 		execvp(argv[0], argv);
! 		perror(argv[0]);
! 		exit(1);
! 		return -1;		/* Keep the compiler happy */
! 	}
! 	else
! 	{
! 		/* We are in the parent process */
! 		return ILSpawnProcessWaitForExit(pid, argv);
! 	}
  }
  
! #endif // HAVE_FORK
! 
! #if defined(UNIX_PIPES) || defined(IL_WIN32_CYGWIN)
  
  /*
   * Determine if a signal is important enough to be reported.
   * Simple exits like SIGINT, SIGTERM, etc are not considered
   * important as they are "normal" ways to abort a process.
+  *
+  * This function is for UNIX and Cygwin
   */
+ 
  static int ImportantSignal(unsigned sig)
  {
  #ifdef SIGSEGV
***************
*** 249,281 ****
  	return 0;
  }
  
! /*
!  * Use Unix-specific functions to spawn child processes.
   */
- int ILSpawnProcess(char *argv[])
- {
- 	int pid = fork();
- 	if(pid < 0)
- 	{
- 		/* Could not fork the child process */
- 		perror("fork");
- 		return -1;
- 	}
- 	else if(pid == 0)
- 	{
- 		/* We are in the child process */
- 		execvp(argv[0], argv);
- 		perror(argv[0]);
- 		exit(1);
- 		return -1;		/* Keep the compiler happy */
- 	}
- 	else
- 	{
- 		/* We are in the parent process */
- 		return ILSpawnProcessWaitForExit(pid, argv);
- 	}
- }
- 
  int ILSpawnProcessWithPipe(char *argv[], void **stream)
  {
  	int pipefds[2];
--- 523,535 ----
  	return 0;
  }
  
! /* Spawns a new process with argument list 'argv'
!  * and redirects its standard output to 'stream'
!  *
!  * Returns a handle of the newly created process
!  *  
!  * This function is for UNIX and Cygwin
   */
  int ILSpawnProcessWithPipe(char *argv[], void **stream)
  {
  	int pipefds[2];
***************
*** 325,330 ****
--- 579,589 ----
  	}
  }
  
+ /* Wait for a process specified by pid to exit
+  * and return it's status code
+  *
+  * This function is for UNIX and Cygwin
+  */
  int ILSpawnProcessWaitForExit(int pid, char *argv[])
  {
  	int status = 1;
***************
*** 358,367 ****
  	}
  }
  
! #else
  
  /*
!  * We don't know how to spawn child processes on this system.
   */
  
  int ILSpawnProcess(char *argv[])
--- 617,630 ----
  	}
  }
  
! 
! #endif
! 
! #if !defined(UNIX_PIPES) && !defined(IL_WIN32_NATIVE) && !defined(IL_WIN32_CYGWIN)
  
  /*
!  * We don't support process spawning on systems other than Cygwin,
!  * native Windows or Unix (and compatible systems)
   */
  
  int ILSpawnProcess(char *argv[])
***************
*** 384,390 ****
  	return -1;
  }
  
- #endif
  #endif
  
  #ifdef	__cplusplus
--- 647,652 ----
#### End of Patch data ####
