diff --git a/ChangeLog b/ChangeLog index 64bed644a..25c30456a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,89 @@ +Thu Jan 9 10:45:10 1997 Andrew McCallum + + * src/Connection.m ([Connection + -_getReceivedReplyRmcWithSequenceNumber:]): Break if the RunLoop + returns NO. (Reported by Richard Frith-Macdonald + .) + + * src/NSDictionary.m ([NSDictionary + +dictionaryWithContentsOfFile:]): Method implemented. + (From Scott Christley.) + + * src/NSString.m ([NSString -initWithFormat:arguments:]): Increase + BUFFER_EXTRA by a factor of 500. + + * src/Foundation/NSZone.h (ZoneLock): Don't prepend OBJC_MUTEX_T + with an underscore. + + * src/mframe.m (mframe_build_return): Change the way values of + type smaller than int are returned---don't offset into the int. + (Recommended by Richard Frith-Macdonald .) + +Wed Dec 04 12:39:24 1996 Scott Christley + + * src/Makefile.sed.nt: remove Foundation directory if it exists + before installing header files. Don't regenerate lex.sf.m. + * src/NSSet.m (-unionSet:): Implement method. + (-intersectSet:, -minusSet:): Implement methods. + * src/NSString.m (-initWithContentsOfFile:): Use Win32 specific + functions for file operations. + * src/md5.c: Include config header file. + * src/include/config-win32.h: vsprintf returns length on Win32. + * src/NSUser.m (NSHomeDirectoryForUser, NSUserName): Implement + Win32 specific versions. + +Thu Nov 21 12:00:44 1996 Scott Christley + + * src/include/NSDictionary.h (+dictionaryWithContentsOfFile:): New + method. + * src/proplist.l (COMMENT, LINE_COMMENT): Added lexical rules for + traditional C comments and ObjC line comments. Add carriage + return '\r' as part of whitespace rules. + * src/lex.pl.m: Regenerated with proplist.l changes. + * src/proplist.tab.m: Likewise. + * src/NSArray.m (-sortedArrayUsingSelector:): Implemented. + (-sortedArrayUsingFunction:context:): Implemented. + (-sortUsingFunction:context:): Implemented. + * checks/nsarray.m: Add tests for sorting methods. + +Tue Nov 19 09:06:00 1996 Richard Frith-Macdonald + + * src/ConnectedCoder.m: Release packet after invoking + initialisation method of super which retains it. To fix memory + leaks. + + * src/Connection.m (+rootProxyAtName:onHost:): Return nil if we + can't create port. + (-forwardForProxy:selector:argFrame:): Modified to cooperate + better with mframe_build_return() so that the created decoder is + released reliably. Fixes a memory leak. + (-_getReceivedReplyRmcWithSequenceNumber:): Added code to release + allocated NSDate object on exit - fixes a memory leak. + + * src/Decoder.m (-_coderCreateReferenceForObject:): Changed code + to release dummy object after insertion in array (which retains + it). fixes memory leak. + + * src/Encoder.m (-initForWritingToStream:withFormatVersion: + cStreamClass:cStreamFormatVersion:): Release stream after invoking + initialisation method of super which retains it. To fix memory + leaks. + + * src/KeyedCollection.m (-dealloc): Added call to + NSDeallocateObject() to ensure that the memory used by the + enumerator is released. + + * src/RunLoop.m: Changed code to get timers to work correctly and + enabled timer support by default. Fixed all the cases I could + spot where the '_current_mode' could be left in the wrong state. + Modified so that the object listening on a file descriptor need + not be the same as the object speaking on it. Added code to + release the enumerator state information for Bags after use - + fixes memory leak. + + * src/mframe.m (mframe_build_return): Modified to cooperate better + with [Connection -forwardForProxy:selector:argFrame:]. + Mon Jan 6 16:06:21 1997 Andrew McCallum * src/NSDictionary.m ([NSDictionary -initWithContentsOfFile:]): @@ -423,8 +509,8 @@ Wed Oct 16 10:01:23 1996 Scott Christley Tue Oct 1 12:56:09 1996 Nicholas Christopher - * NSString.m: Added initWithContentsOfFile: and - propertyListFromStringsFileFormat:. + * NSString.m: Implemented -initWithContentsOfFile: and + -propertyListFromStringsFileFormat:. * stringsfile.l, stringsfile.y: New files. Fri Oct 25 20:22:37 1996 Andrew McCallum diff --git a/Headers/gnustep/base/NSDictionary.h b/Headers/gnustep/base/NSDictionary.h index 3bebb13ba..55ffa9404 100644 --- a/Headers/gnustep/base/NSDictionary.h +++ b/Headers/gnustep/base/NSDictionary.h @@ -32,6 +32,7 @@ + allocWithZone: (NSZone*)zone; + dictionary; ++ dictionaryWithContentsOfFile:(NSString *)path; + dictionaryWithObjects: (id*)objects forKeys: (NSString**)keys count: (unsigned)count; + dictionaryWithObjects: (NSArray*)objects forKeys: (NSArray*)keys; diff --git a/Headers/gnustep/base/config-win32.h b/Headers/gnustep/base/config-win32.h index 857471f12..5386b0622 100644 --- a/Headers/gnustep/base/config-win32.h +++ b/Headers/gnustep/base/config-win32.h @@ -5,6 +5,7 @@ #define HAVE_STRING_H 1 #define HAVE_MEMORY_H 1 #define HAVE_VSPRINTF 1 +#define VSPRINTF_RETURNS_LENGTH 1 #define NeXT_cc 0 #define NeXT_runtime 0 diff --git a/Source/Makefile.sed.nt b/Source/Makefile.sed.nt index 3438f5747..06e852aee 100644 --- a/Source/Makefile.sed.nt +++ b/Source/Makefile.sed.nt @@ -36,6 +36,9 @@ s/@LIBOBJECTS_SO@// /lex.pl.m: proplist.l proplist.tab.h/,/proplist.l > $@/c\ lex.pl.m: proplist.l proplist.tab.h\ touch lex.pl.m +/lex.sf.m: stringsfile.l stringsfile.tab.h/,/stringsfile.l > $@/c\ +lex.sf.m: stringsfile.l stringsfile.tab.h\ + touch lex.sf.m /lib$(LIBRARY_NAME)$(LIBEXT):/,/$(RANLIB) lib$(LIBRARY_NAME)$(LIBEXT)/c\ lib$(LIBRARY_NAME)$(LIBEXT): $(HEADERS_INSTALL) $(OBJS_INSTALL) $(INIT_FILE_OBJ)\ $(AR) $(ARFLAGS) $(AROUT)lib1$(LIBEXT) $(GNU_OBJS)\ @@ -132,6 +135,7 @@ install: installdirs all\ $(INSTALL_DATA) $(srcdir)/gnustep/base/*.h $(includedir)/gnustep/base\ $(INSTALL_DATA) $(srcdir)/objc/*.h $(includedir)/objc\ $(INSTALL_DATA) include/config.h $(includedir)/gnustep/base/config.h\ + IF EXIST $(includedir)\\Foundation rm -rf $(includedir)/Foundation\ cp -r $(includedir)/gnustep/base $(includedir)/Foundation /for file in $(NEXTSTEP_HEADERS); do/,/done/c\ for %i in ( ${NEXTSTEP_HEADERS} ) do \\\ diff --git a/Source/NSArray.m b/Source/NSArray.m index 93a795c23..866d2e605 100644 --- a/Source/NSArray.m +++ b/Source/NSArray.m @@ -279,15 +279,21 @@ static Class NSMutableArray_concrete_class; - (NSArray*) sortedArrayUsingSelector: (SEL)comparator { - [self notImplemented:_cmd]; - return nil; + int compare(id elem1, id elem2, void* context) + { + return (int)[elem1 perform:comparator withObject:elem2]; + } + + return [self sortedArrayUsingFunction:compare context:NULL]; } - (NSArray*) sortedArrayUsingFunction: (int(*)(id,id,void*))comparator context: (void*)context { - [self notImplemented:_cmd]; - return nil; + id sortedArray = [[self mutableCopy] autorelease]; + + [sortedArray sortUsingFunction:comparator context:context]; + return [[sortedArray copy] autorelease]; } - (NSString*) componentsJoinedByString: (NSString*)separator @@ -563,7 +569,40 @@ static Class NSMutableArray_concrete_class; - (void) sortUsingFunction: (int(*)(id,id,void*))compare context: (void*)context { - [self notImplemented:_cmd]; + /* Shell sort algorithm taken from SortingInAction - a NeXT example */ +#define STRIDE_FACTOR 3 // good value for stride factor is not well-understood + // 3 is a fairly good choice (Sedgewick) + int c,d, stride; + BOOL found; + int count = [self count]; + + stride = 1; + while (stride <= count) + stride = stride * STRIDE_FACTOR + 1; + + while(stride > (STRIDE_FACTOR - 1)) { + // loop to sort for each value of stride + stride = stride / STRIDE_FACTOR; + for (c = stride; c < count; c++) { + found = NO; + d = c - stride; + while ((d >= 0) && !found) { + // move to left until correct place + id a = [self objectAtIndex:d + stride]; + id b = [self objectAtIndex:d]; + if ((*compare)(a, b, context) == NSOrderedAscending) { + [a retain]; + [b retain]; + [self replaceObjectAtIndex:d + stride withObject:b]; + [self replaceObjectAtIndex:d withObject:a]; + d -= stride; // jump by stride factor + [a release]; + [b release]; + } + else found = YES; + } + } + } } @end diff --git a/Source/NSSet.m b/Source/NSSet.m index 9bb349620..8286cd905 100644 --- a/Source/NSSet.m +++ b/Source/NSSet.m @@ -360,17 +360,30 @@ static Class NSMutableSet_concrete_class; - (void) unionSet: (NSSet*) other { - [self notImplemented:_cmd]; + id keys = [other objectEnumerator]; + id key; + + while ((key = [keys nextObject])) + [self addObject: key]; } - (void) intersectSet: (NSSet*) other { - [self notImplemented:_cmd]; + id keys = [self objectEnumerator]; + id key; + + while ((key = [keys nextObject])) + if ([other containsObject:key] == NO) + [self removeObject:key]; } - (void) minusSet: (NSSet*) other { - [self notImplemented:_cmd]; + id keys = [other objectEnumerator]; + id key; + + while ((key = [keys nextObject])) + [self removeObject:key]; } - (void) removeAllObjects diff --git a/Source/NSString.m b/Source/NSString.m index 35c6c75f7..28d0f72cb 100644 --- a/Source/NSString.m +++ b/Source/NSString.m @@ -288,23 +288,47 @@ handle_printf_atsign (FILE *stream, } - (id) initWithContentsOfFile: (NSString*)path -{ - struct stat buf; - int fd; - char *s; + { + /* xxx Maybe this should use StdioStream? */ +#ifdef __WIN32__ + NSMutableString *s = [NSMutableString stringWithCString:""]; + DWORD dwread; + char bytes[1024]; + BOOL res, done = NO; + HANDLE fd = CreateFile([path cString], GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); - stat ([path cString], &buf); + while (!done) + { + res = ReadFile(fd, bytes, 1023, &dwread, NULL); + bytes[dwread] = '\0'; + if ((res) && (dwread == 0)) + done = YES; + else + [s appendString: [NSString stringWithCString: bytes]]; + } + CloseHandle(fd); + [self initWithString: s]; + [s release]; + return self; +#else + int fd = open([path cString], O_RDONLY); + struct stat fstat_buf; + char* bytes = NULL; - OBJC_MALLOC (s, char, buf.st_size + 1); - fd = open ([path cString], O_RDONLY); - if ( fd < 0 ) - [NSException raise: NSGenericException - format: @"Could not open file %s", [path cString]]; + if((fd == -1) || (fstat(fd, &fstat_buf) == -1)) + return nil; - read (fd,(void *)s,buf.st_size); - s[buf.st_size] = (char)0; - - return [self initWithCStringNoCopy:s length: buf.st_size freeWhenDone: YES]; + OBJC_MALLOC(bytes, char, fstat_buf.st_size + 1); + if (read(fd, bytes, fstat_buf.st_size) != fstat_buf.st_size) { + OBJC_FREE(bytes); + return nil; + } + close(fd); + bytes[fstat_buf.st_size] = '\0'; + return [self initWithCStringNoCopy:bytes length:fstat_buf.st_size + freeWhenDone:YES]; +#endif } - (id) initWithData: (NSData*)data diff --git a/Source/NSUser.m b/Source/NSUser.m index 2c0a25fbe..fc37a626b 100644 --- a/Source/NSUser.m +++ b/Source/NSUser.m @@ -36,7 +36,14 @@ NSString * NSUserName () { #if __WIN32__ - return nil; + /* The GetUserName function returns the current user name */ + char buf[1024]; + DWORD n = 1024; + + if (GetUserName(buf, &n)) + return [NSString stringWithCString: buf]; + else + return [NSString stringWithCString: ""]; #elif __SOLARIS__ int uid = geteuid(); // get the effective user id struct passwd *pwent = getpwuid (uid); @@ -70,6 +77,28 @@ NSHomeDirectoryForUser (NSString *login_name) pw = getpwnam ([login_name cStringNoCopy]); return [NSString stringWithCString: pw->pw_dir]; #else - return nil; + /* Then environment variable HOMEPATH holds the home directory + for the user on Windows NT; Win95 has no concept of home. */ + char buf[1024], *nb; + DWORD n; + NSString *s; + + n = GetEnvironmentVariable("HOMEPATH", buf, 1024); + if (n > 1024) + { + /* Buffer not big enough, so dynamically allocate it */ + nb = (char *)malloc(sizeof(char)*(n+1)); + n = GetEnvironmentVariable("HOMEPATH", nb, n+1); + nb[n] = '\0'; + s = [NSString stringWithCString: nb]; + free(nb); + return s; + } + else + { + /* null terminate it and return the string */ + buf[n] = '\0'; + return [NSString stringWithCString: buf]; + } #endif } diff --git a/Source/md5.c b/Source/md5.c index 8b9e7b69d..f28777de9 100644 --- a/Source/md5.c +++ b/Source/md5.c @@ -20,6 +20,7 @@ /* Written by Ulrich Drepper . */ #include +#include #if STDC_HEADERS #include diff --git a/Source/proplist.l b/Source/proplist.l index 720d18de9..5bcd1ce3b 100644 --- a/Source/proplist.l +++ b/Source/proplist.l @@ -27,12 +27,14 @@ NSData * str2data(char * str); extern char plinput[]; extern char *plinputptr; extern char *plinputlim; + +static int level; %} /* pattern definitions */ -ws [ \t] +ws [ \t\r] nl \n -wsnl [ \t\n] +wsnl [ \t\r\n] hexdigit [0-9A-Fa-f] hexbyte {hexdigit}{2} hexword {hexbyte}{4} @@ -42,10 +44,14 @@ noquote [$./0-9A-Z_a-z] unqstring {noquote}+ hexdata \<{ws}*({hexword}{ws}*)*{hexnum}{0,1}{ws}*\> /* exclusive states */ -%x QUOTE +%x QUOTE COMMENT LINE_COMMENT /* rules section */ %% + +"/*" {++level; BEGIN COMMENT;} +"//" {BEGIN LINE_COMMENT;} + {qstring} { if(plleng==1) { BEGIN INITIAL; @@ -59,6 +65,13 @@ hexdata \<{ws}*({hexword}{ws}*)*{hexnum}{0,1}{ws}*\> } } +"*/" {if(!--level) BEGIN INITIAL;} +. ; +<> {return 0;} + +\n {BEGIN INITIAL;} +. ; + {unqstring} {return_nsstr(pltext);} {hexdata} {return_nsdata(pltext);} @@ -102,7 +115,7 @@ str2data (char *str) (ch = *str_ptr) != '>'; str_ptr++) { - if(ch==' ' || ch=='\n' || ch=='\t') + if(ch==' ' || ch=='\n' || ch=='\t' || ch=='\r') continue; /* ignore whitespace */ *buf_ptr = (char2num(ch))<<4; ch = *++str_ptr; @@ -145,6 +158,7 @@ unescstr (char *src) case 'a' : *dest_ptr = '\a'; break; case 'b' : *dest_ptr = '\b'; break; case 't' : *dest_ptr = '\t'; break; + case 'r' : *dest_ptr = '\r'; break; case 'n' : *dest_ptr = '\n'; break; case 'v' : *dest_ptr = '\v'; break; case 'f' : *dest_ptr = '\f'; break; diff --git a/Source/win32-entry.c b/Source/win32-entry.c index 2b3a87bad..2e9e05db0 100644 --- a/Source/win32-entry.c +++ b/Source/win32-entry.c @@ -58,10 +58,10 @@ WINBOOL WINAPI DLLMain(HANDLE hInst, ULONG ul_reason_for_call, _CRT_INIT(hInst, ul_reason_for_call, lpReserved); #endif /* __MS_WIN32__ */ + printf("GNUstep Base Library: process attach\n"); + /* Initialize the GNUstep Base Library runtime structures */ gnustep_base_init_runtime(); - - printf("GNUstep Base Library: process attach\n"); } if (ul_reason_for_call == DLL_PROCESS_DETACH) @@ -76,15 +76,15 @@ WINBOOL WINAPI DLLMain(HANDLE hInst, ULONG ul_reason_for_call, _CRT_INIT(hInst, ul_reason_for_call, lpReserved); #endif /* __MS_WIN32__ */ + printf("GNUstep Base Library: thread attach\n"); + /* Initialize the Library? -not for threads? */ gnustep_base_init_runtime(); - - printf("GNUstep Base Library: thread attach\n"); } if (ul_reason_for_call == DLL_THREAD_DETACH) { - printf("Objective-C runtime: thread detach\n"); + printf("GNUstep Base Library: thread detach\n"); } return TRUE; diff --git a/Testing/nsarray.m b/Testing/nsarray.m index e336204a2..a7514968f 100644 --- a/Testing/nsarray.m +++ b/Testing/nsarray.m @@ -113,13 +113,40 @@ main() } { + int compare(id elem1, id elem2, void* context) + { + return (int)[elem1 perform:@selector(compare:) withObject:elem2]; + } + // Deriving new arrays NSRange r = NSMakeRange(0, 3); - /* Still need to finish the sort* methods - [e sortedArrayUsingFunction: context:] - [e sortedArrayUsingSelector:] - */ + f = [NSMutableArray array]; + [f addObject: @"Lions"]; + [f addObject: @"Tigers"]; + [f addObject: @"Bears"]; + [f addObject: @"Penguins"]; + [f addObject: @"Giraffes"]; + + enumerator = [f objectEnumerator]; + while ((i = [enumerator nextObject])) + printf("%s ", [i cString]); + printf("\n"); + + printf("Method: -sortedArrayUsingSelector:\n"); + g = [f sortedArrayUsingSelector: @selector(compare:)]; + printf("Method: -sortedArrayUsingFunction:context:\n"); + h = [f sortedArrayUsingFunction: compare context: NULL]; + + enumerator = [g objectEnumerator]; + while ((i = [enumerator nextObject])) + printf("%s ", [i cString]); + printf("\n"); + + if (([g isEqualToArray: h]) && (![g isEqualToArray: f])) + printf("Sorted arrays are correct\n"); + else + printf("Error: Sorted arrays are not correct\n"); printf("Method: -subarrayWithRange:\n"); f = [e subarrayWithRange: r]; diff --git a/Testing/nsprocessinfo.m b/Testing/nsprocessinfo.m index 53aeced8a..b040677f1 100644 --- a/Testing/nsprocessinfo.m +++ b/Testing/nsprocessinfo.m @@ -11,19 +11,22 @@ int main(int argc, char *argv[]) NSString* aKey; NSEnumerator* enumerator; + printf("Host Name: %s\n",[[pi hostName] cString]); + printf("Process Name: %s\n",[[pi processName] cString]); + printf("Globally Unique String: %s\n",[[pi globallyUniqueString] cString]); + printf("\nProcess arguments\n"); + printf("%d argument(s)\n", [[pi arguments] count]); enumerator = [[pi arguments] objectEnumerator]; while ((aString = [enumerator nextObject])) printf("-->%s\n",[aString cString]); + printf("\nProcess environment\n"); + printf("%d environment variables(s)\n", [[pi environment] count]); enumerator = [[pi environment] keyEnumerator]; while ((aKey = [enumerator nextObject])) printf("++>%s=%s\n",[aKey cString],[[[pi environment] objectForKey:aKey] cString]); - - printf("==>%s\n",[[pi hostName] cString]); - printf("==>%s\n",[[pi processName] cString]); - printf("==>%s\n",[[pi globallyUniqueString] cString]); exit(0); }