From 44d1336beb1cf02c08a13429c60327db308104dc Mon Sep 17 00:00:00 2001 From: Adam Fedor Date: Fri, 15 Sep 2000 22:06:01 +0000 Subject: [PATCH] Port to MinGW git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@7524 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 17 ++ Source/NSFileHandle.m | 8 + Source/NSProcessInfo.m | 6 +- Source/NSTask.m | 457 ++++++++++++++++++++++++++----------- Source/libgnustep-base.def | 8 +- Source/win32-entry.m | 7 +- Tools/gdnc.m | 3 +- Tools/gdomap.c | 5 + configure | 13 +- configure.in | 3 + 10 files changed, 377 insertions(+), 150 deletions(-) diff --git a/ChangeLog b/ChangeLog index fcabea5db..df7d02b2d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2000-09-15 Adam Fedor + + * configure.in: Turn off enable_fake_main if on MinGW. + + * Source/WindowsFileHandle.m: New class. + * Source/NSFileHandle.m: Use it on MinGW + * Source/NSTask.m: Break into concrete subclasses for + Unix and Windows. + + * Source/NSProcessInfo.m: on MinGW, don't try to redefine + __argv, __argc, etc. + * Source/libgnustep_base_entry.m: Renamed from win32-entry.m + + * Tools/gdnc.m: Don't fork on MinGW + * Tools/gdomap.c: Define MINGW ifdef MINGW32. + + 2000-09-15 Richard Frith-Macdonald * Source/GSXML.m: made method names more consistent. diff --git a/Source/NSFileHandle.m b/Source/NSFileHandle.m index e48551282..91063de81 100644 --- a/Source/NSFileHandle.m +++ b/Source/NSFileHandle.m @@ -27,7 +27,11 @@ #include #include #include +#ifdef __MINGW__ +#include +#else #include +#endif static Class NSFileHandle_abstract_class = nil; static Class NSFileHandle_concrete_class = nil; @@ -39,7 +43,11 @@ static Class NSFileHandle_concrete_class = nil; if (self == [NSFileHandle class]) { NSFileHandle_abstract_class = self; +#ifdef __MINGW__ + NSFileHandle_concrete_class = [WindowsFileHandle class]; +#else NSFileHandle_concrete_class = [UnixFileHandle class]; +#endif } } diff --git a/Source/NSProcessInfo.m b/Source/NSProcessInfo.m index 979d2972b..fd48c9318 100644 --- a/Source/NSProcessInfo.m +++ b/Source/NSProcessInfo.m @@ -478,11 +478,7 @@ _gnu_noobjc_free_vars(void) #else /* !HAVE_PROC_FS || !HAVE_LOAD_METHOD */ #ifdef __MINGW__ -/* For WindowsAPI Library, we know the global variables */ -extern int __argc; -extern char** __argv; -extern char** _environ; - +/* For WindowsAPI Library, we know the global variables (argc, etc) */ + (void) initialize { if (self == [NSProcessInfo class]) diff --git a/Source/NSTask.m b/Source/NSTask.m index d08b5a3e4..7aa92eff7 100644 --- a/Source/NSTask.m +++ b/Source/NSTask.m @@ -42,10 +42,16 @@ #include #include -#include #include +#ifndef __MINGW__ +#include #include #include +#endif + +#if HAVE_WINDOWS_H +# include +#endif /* * If we don't have NFILE, default to 256 open descriptors. @@ -59,55 +65,45 @@ NSString *NSTaskDidTerminateNotification = @"NSTaskDidTerminateNotification"; static NSRecursiveLock *tasksLock = nil; static NSMapTable *activeTasks = 0; -@interface NSTask (Private) -- (void) _collectChild; -- (void) _sendNotification; -- (void) _terminatedChild: (int)status; -@end - -@implementation NSTask - static BOOL hadChildSignal = NO; static void handleSignal(int sig) { hadChildSignal = YES; } -BOOL -GSCheckTasks() +#ifdef __MINGW__ +@interface NSConcreteWindowsTask : NSTask { - BOOL found = NO; + PROCESS_INFORMATION proc_info; +} +@end +#define NSConcreteTask NSConcreteWindowsTask +#else +@interface NSConcreteUnixTask : NSTask +{ +} +@end +#define NSConcreteTask NSConcreteUnixTask +#endif - if (hadChildSignal) - { - int result; - int status; +@interface NSTask (Private) +- (NSString *) _fullLaunchPath; +- (void) _sendNotification; +- (void) _collectChild; +- (void) _terminatedChild: (int)status; +@end - hadChildSignal = NO; - do - { - result = waitpid(-1, &status, WNOHANG); - if (result > 0) - { - if (WIFEXITED(status)) - { - NSTask *t; +@implementation NSTask - [tasksLock lock]; - t = (NSTask*)NSMapGet(activeTasks, (void*)result); - [tasksLock unlock]; - if (t) - { - [t _terminatedChild: WEXITSTATUS(status)]; - found = YES; - } - } - } - } - while (result > 0); - } - return found; ++ (id)allocWithZone:(NSZone*)zone +{ + NSTask *task; + if (self == [NSTask class]) + task = (NSTask *)NSAllocateObject([NSConcreteTask class], 0, zone); + else + task = (NSTask *)NSAllocateObject(self, 0, zone); + return task; } + (void) initialize @@ -123,7 +119,9 @@ GSCheckTasks() } [gnustep_global_lock unlock]; +#ifndef __MINGW__ signal(SIGCHLD, handleSignal); +#endif } } @@ -354,16 +352,63 @@ GSCheckTasks() return; } +#ifndef __MINGW__ #ifdef HAVE_KILLPG killpg(_taskId, SIGINT); #else kill(-_taskId, SIGINT); #endif +#endif } - (void) launch { - NSMutableArray *toClose; + [self subclassResponsibility: _cmd]; +} + +- (void) terminate +{ + if (_hasLaunched == NO) + { + [NSException raise: NSInvalidArgumentException + format: @"NSTask - task has not yet launched"]; + } + if (_hasTerminated) + { + return; + } + + _hasTerminated = YES; +#ifndef __MINGW__ +#ifdef HAVE_KILLPG + killpg(_taskId, SIGTERM); +#else + kill(-_taskId, SIGTERM); +#endif +#endif +} + +- (void) waitUntilExit +{ + while ([self isRunning]) + { + NSDate *limit; + + /* + * Poll at 0.1 second intervals. + */ + limit = [[NSDate alloc] initWithTimeIntervalSinceNow: 0.1]; + [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode + beforeDate: limit]; + RELEASE(limit); + } +} +@end + +@implementation NSTask (Private) + +- (NSString *) _fullLaunchPath +{ NSFileManager *mgr = [NSFileManager defaultManager]; NSString *libs = [NSBundle _library_combo]; NSString *arch = [NSBundle _gnustep_target_dir]; @@ -372,26 +417,6 @@ GSCheckTasks() NSString *base_path; NSString *arch_path; NSString *full_path; - int pid; - const char *executable; - const char *path; - int idesc; - int odesc; - int edesc; - NSDictionary *e = [self environment]; - NSArray *k = [e allKeys]; - NSArray *a = [self arguments]; - int ec = [e count]; - int ac = [a count]; - const char *args[ac+2]; - const char *envl[ec+1]; - id hdl; - int i; - - if (_hasLaunched) - { - return; - } if (_launchPath == nil) { @@ -453,6 +478,245 @@ GSCheckTasks() } lpath = [lpath stringByStandardizingPath]; + return lpath; +} + +- (void) _sendNotification +{ + if (_hasNotified == NO) + { + NSNotification *n; + + _hasNotified = YES; + n = [NSNotification notificationWithName: NSTaskDidTerminateNotification + object: self + userInfo: nil]; + + [[NSNotificationQueue defaultQueue] enqueueNotification: n + postingStyle: NSPostASAP + coalesceMask: NSNotificationNoCoalescing + forModes: nil]; + } +} + +- (void) _collectChild +{ + [self subclassResponsibility: _cmd]; +} + +- (void) _terminatedChild: (int)status +{ + [tasksLock lock]; + NSMapRemove(activeTasks, (void*)_taskId); + [tasksLock unlock]; + _terminationStatus = status; + _hasCollected = YES; + _hasTerminated = YES; + if (_hasNotified == NO) + { + [self _sendNotification]; + } +} + +@end + +#ifdef __MINGW__ +@implementation NSConcreteWindowsTask + +BOOL +GSCheckTasks() +{ + /* FIXME: Implement */ + return YES; +} + +- (void) gcFinalize +{ + [super gcFinalize]; + if (proc_info.hProcess != NULL) + CloseHandle(proc_info.hProcess); + if (proc_info.hThread != NULL) + CloseHandle(proc_info.hThread); +} + +- (void) interrupt +{ +} + +- (void) terminate +{ + if (_hasLaunched == NO) + { + [NSException raise: NSInvalidArgumentException + format: @"NSTask - task has not yet launched"]; + } + if (_hasTerminated) + { + return; + } + + _hasTerminated = YES; + TerminateProcess(proc_info.hProcess, 10); +} + +- (void) launch +{ + STARTUPINFO start_info; + NSString *lpath; + NSString *arg; + NSEnumerator *arg_enum; + NSMutableString *args; + char *c_args; + int result; + + if (_hasLaunched) + { + return; + } + + lpath = [self _fullLaunchPath]; + args = [lpath mutableCopy]; + arg_enum = [[self arguments] objectEnumerator]; + while ((arg = [arg_enum nextObject])) + { + [args appendString: @" "]; + [args appendString: arg]; + } + c_args = objc_malloc([args cStringLength]+1); + [args getCString: c_args]; + + memset (&start_info, 0, sizeof(start_info)); + start_info.cb = sizeof(start_info); + start_info.dwFlags |= STARTF_USESTDHANDLES; + start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + start_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); + start_info.hStdError = GetStdHandle(STD_ERROR_HANDLE); + + result = CreateProcess([lpath cString], + c_args, + NULL, /* proc attrs */ + NULL, /* thread attrs */ + 1, /* inherit handles */ + 0, /* creation flags */ + NULL, /* env block */ + [[self currentDirectoryPath] cString], + &start_info, + &proc_info); + objc_free(c_args); + if (result == 0) + { + NSLog(@"Error launching task: %@", lpath); + return; + } + _taskId = proc_info.dwProcessId; + _hasLaunched = YES; + ASSIGN(_launchPath, lpath); // Actual path used. + + [tasksLock lock]; + NSMapInsert(activeTasks, (void*)_taskId, (void*)self); + [tasksLock unlock]; +} + +- (void) _collectChild +{ + if (_hasCollected == NO) + { + /* FIXME: Implement */ + } +} + +- (int) terminationStatus +{ + DWORD exit_code; + int result; + + [super terminationStatus]; + result = GetExitCodeProcess(proc_info.hProcess, &exit_code); + _terminationStatus = exit_code; + if (result == 0) + { + NSLog(@"Error getting exit code"); + return -1; + } + return exit_code; +} + +- (void) waitUntilExit +{ + DWORD result; + + result = WaitForSingleObject(proc_info.hProcess, INFINITE); +} + +@end + +#else /* !MINGW */ + +@implementation NSConcreteUnixTask + +BOOL +GSCheckTasks() +{ + BOOL found = NO; + + if (hadChildSignal) + { + int result; + int status; + + hadChildSignal = NO; + + do + { + result = waitpid(-1, &status, WNOHANG); + if (result > 0) + { + if (WIFEXITED(status)) + { + NSTask *t; + + [tasksLock lock]; + t = (NSTask*)NSMapGet(activeTasks, (void*)result); + [tasksLock unlock]; + if (t) + { + [t _terminatedChild: WEXITSTATUS(status)]; + found = YES; + } + } + } + } + while (result > 0); + } + return found; +} + +- (void) launch +{ + NSMutableArray *toClose; + NSString *lpath; + int pid; + const char *executable; + const char *path; + int idesc; + int odesc; + int edesc; + NSDictionary *e = [self environment]; + NSArray *k = [e allKeys]; + NSArray *a = [self arguments]; + int ec = [e count]; + int ac = [a count]; + const char *args[ac+2]; + const char *envl[ec+1]; + id hdl; + int i; + + if (_hasLaunched) + { + return; + } + + lpath = [self _fullLaunchPath]; executable = [lpath cString]; args[0] = executable; @@ -600,45 +864,6 @@ GSCheckTasks() } } -- (void) terminate -{ - if (_hasLaunched == NO) - { - [NSException raise: NSInvalidArgumentException - format: @"NSTask - task has not yet launched"]; - } - if (_hasTerminated) - { - return; - } - - _hasTerminated = YES; -#ifdef HAVE_KILLPG - killpg(_taskId, SIGTERM); -#else - kill(-_taskId, SIGTERM); -#endif -} - -- (void) waitUntilExit -{ - while ([self isRunning]) - { - NSDate *limit; - - /* - * Poll at 0.1 second intervals. - */ - limit = [[NSDate alloc] initWithTimeIntervalSinceNow: 0.1]; - [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode - beforeDate: limit]; - RELEASE(limit); - } -} -@end - -@implementation NSTask (Private) - - (void) _collectChild { if (_hasCollected == NO) @@ -677,37 +902,5 @@ GSCheckTasks() } } -- (void) _sendNotification -{ - if (_hasNotified == NO) - { - NSNotification *n; - - _hasNotified = YES; - n = [NSNotification notificationWithName: NSTaskDidTerminateNotification - object: self - userInfo: nil]; - - [[NSNotificationQueue defaultQueue] enqueueNotification: n - postingStyle: NSPostASAP - coalesceMask: NSNotificationNoCoalescing - forModes: nil]; - } -} - -- (void) _terminatedChild: (int)status -{ - [tasksLock lock]; - NSMapRemove(activeTasks, (void*)_taskId); - [tasksLock unlock]; - _terminationStatus = status; - _hasCollected = YES; - _hasTerminated = YES; - if (_hasNotified == NO) - { - [self _sendNotification]; - } -} - @end - +#endif /* !MINGW */ diff --git a/Source/libgnustep-base.def b/Source/libgnustep-base.def index 23c826ef5..e95f0b8bc 100644 --- a/Source/libgnustep-base.def +++ b/Source/libgnustep-base.def @@ -27,6 +27,7 @@ ; LIBRARY libgnustep-base EXPORTS +__objc_class_name_GSBaseDefaultObserver __objc_class_name_GSTcpHandle __objc_class_name_GSTcpPort __objc_class_name_NSArchiver @@ -56,7 +57,6 @@ __objc_class_name_NSConnection __objc_class_name_NSCountedSet __objc_class_name_NSData __objc_class_name_NSDataMalloc -__objc_class_name_NSDataMappedFile __objc_class_name_NSDataStatic __objc_class_name_NSMutableData __objc_class_name_NSMutableDataMalloc @@ -67,6 +67,8 @@ __objc_class_name_NSDate __objc_class_name_NSGDate __objc_class_name_NSDateFormatter __objc_class_name_GSDebugAlloc +__objc_class_name_NSDecimalNumber +__objc_class_name_NSDecimalNumberHandler __objc_class_name_NSDictionary __objc_class_name_NSDictionaryNonCore __objc_class_name_NSMutableDictionary @@ -126,6 +128,7 @@ __objc_class_name_NSUIntNumber __objc_class_name_NSLongNumber __objc_class_name_NSULongNumber __objc_class_name_NSLongLongNumber +__objc_class_name_NSNumberFormatter __objc_class_name_NSObject __objc_class_name__FastMallocBuffer __objc_class_name_NSPipe @@ -153,6 +156,7 @@ __objc_class_name_NSSet __objc_class_name_NSSetNonCore __objc_class_name_NSMutableString __objc_class_name_NSString +__objc_class_name_NSConcreteWindowsTask __objc_class_name_NSTask __objc_class_name_NSThread __objc_class_name_NSConcreteAbsoluteTimeZone @@ -178,4 +182,4 @@ __objc_class_name_NSPointValue __objc_class_name_NSPointerValue __objc_class_name_NSRectValue __objc_class_name_NSSizeValue -__objc_class_name_UnixFileHandle +__objc_class_name_WindowsFileHandle diff --git a/Source/win32-entry.m b/Source/win32-entry.m index e6158b94f..96224e568 100644 --- a/Source/win32-entry.m +++ b/Source/win32-entry.m @@ -23,6 +23,8 @@ #include #include +#include +#include /* Only if using Microsoft's tools and libraries */ #ifdef __MS_WIN32__ @@ -40,11 +42,6 @@ int _MB_init_runtime() } #endif /* __MS_WIN32__ */ -int gnustep_base_user_main(int argc, char *argv[], char *env[]) -{ - return 0; -} - LONG APIENTRY gnustep_base_socket_handler(HWND hWnd, UINT message, UINT wParam, LONG lParam); diff --git a/Tools/gdnc.m b/Tools/gdnc.m index de3e1fa79..ff808da9e 100644 --- a/Tools/gdnc.m +++ b/Tools/gdnc.m @@ -764,7 +764,7 @@ main(int argc, char** argv, char** env) shouldFork = NO; } RELEASE(pool); - +#ifndef __MINGW__ /* Don't fork on Win32 */ if (shouldFork) { switch (fork()) @@ -788,6 +788,7 @@ main(int argc, char** argv, char** env) exit(0); } } +#endif /* !MINGW */ { CREATE_AUTORELEASE_POOL(pool); diff --git a/Tools/gdomap.c b/Tools/gdomap.c index 96c57560a..bf00c0d3f 100644 --- a/Tools/gdomap.c +++ b/Tools/gdomap.c @@ -22,6 +22,11 @@ */ /* Ported to mingw 07/12/00 by Björn Giesler */ +#ifdef __MINGW32__ +#ifndef __MINGW__ +#define __MINGW__ +#endif +#endif #include #include diff --git a/configure b/configure index a1a127232..a5ce0c1e3 100755 --- a/configure +++ b/configure @@ -4314,6 +4314,9 @@ EOF fi fi +case "$target_os" in + mingw*) enable_fake_main=no; GS_FAKE_MAIN=0;; +esac echo "$ac_t""$enable_fake_main" 1>&6 @@ -4325,17 +4328,17 @@ for ac_hdr in libxml/xmlversion.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:4329: checking for $ac_hdr" >&5 +echo "configure:4332: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:4339: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:4342: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -4368,7 +4371,7 @@ if test $ac_cv_header_libxml_xmlversion_h = no; then HAVE_LIBXML=0 else cat > conftest.$ac_ext <&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:4383: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* diff --git a/configure.in b/configure.in index 83cb704a1..3b2b0b5b8 100644 --- a/configure.in +++ b/configure.in @@ -767,6 +767,9 @@ elif test "$enable_pass_arguments" = "no"; then AC_DEFINE(HAVE_PROC_FS_EXE_LINK) fi fi +case "$target_os" in + mingw*) enable_fake_main=no; GS_FAKE_MAIN=0;; +esac AC_SUBST(GS_FAKE_MAIN) AC_MSG_RESULT($enable_fake_main)