From fc772ee2e56c27fbf6189b123394ccb193b472b7 Mon Sep 17 00:00:00 2001 From: Richard Frith-MacDonald Date: Tue, 2 Mar 1999 08:58:30 +0000 Subject: [PATCH] Merged in 'dawn' CVS branch git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@3827 72102866-910b-0410-8b05-ffd578937521 --- ANNOUNCE | 9 +- AUTHORS | 34 +- ChangeLog | 39 ++ Documentation/GNUmakefile | 8 +- Documentation/base-desc.texi | 3 +- Documentation/gnustep-base.tmpl.texi | 6 - Documentation/news.tmpl.texi | 25 + Documentation/readme.tmpl.texi | 103 +--- Documentation/status.tmpl.texi | 98 ++-- Documentation/todo.tmpl.texi | 156 ------ Headers/gnustep/base/NSObject.h | 9 +- Headers/gnustep/base/NSPort.h | 33 +- Headers/gnustep/base/NSPortMessage.h | 8 +- Headers/gnustep/base/NSRunLoop.h | 2 +- Makefile.postamble | 34 -- NEWS | 20 +- README | 99 +--- Source/Makefile.postamble | 13 +- Source/NSConnection.m | 10 +- Source/NSPort.m | 45 +- Source/NSPortMessage.m | 82 ++-- Source/NSProcessInfo.m | 9 +- Source/NSRunLoop.m | 124 +++-- Source/TcpPort.m | 696 +++++++++++++++++++++++++++ Testing/client.m | 28 +- Version | 4 +- 26 files changed, 1090 insertions(+), 607 deletions(-) diff --git a/ANNOUNCE b/ANNOUNCE index 02c3f9102..8e7072830 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,7 +1,7 @@ Announcement ************ -The GNUstep Base Library, version 0.5.0, is now available. +The GNUstep Base Library, version 0.5.5, is now available. What is the GNUstep Base Library? ================================= @@ -14,8 +14,7 @@ network ports, remote object messaging support (distributed objects), event loops, and random number generators. It provides functionality that aims to implement the non-graphical -portion of the OpenStep standard. In many cases, the `NS*' classes are -implemented as wrappers around more featureful GNU classes. +portion of the OpenStep standard (the Foundation library). There is more information available at the GNUstep homepage at `http://www.gnustep.org'. @@ -23,8 +22,8 @@ implemented as wrappers around more featureful GNU classes. Where can you get it? How can you compile it? ============================================== - The gstepbase-0.5.0.tar.gz distribution file has been placed on -`ftp.gnu.org' in `pub/gnu'. + The gstepbase-0.5.5.tar.gz distribution file has been placed on +`ftp.gnu.org' in `pub/gnu/gstep'. The library requires gcc 2.8.0 or higher. Significant sections of the library do not work with the NeXT runtime, so we recommend using diff --git a/AUTHORS b/AUTHORS index d9e209e08..4c9c6e3b0 100644 --- a/AUTHORS +++ b/AUTHORS @@ -12,7 +12,6 @@ BinaryTreeNode.m CircularArray.m Collection.m ConnectedCoder.m -Connection.m Coder.m CStream.m Decoder.m @@ -25,22 +24,16 @@ Invocation.m KeyedCollection.m LinkedList.m LinkedListNode.m -Lock.m MachPort.m -Magnitude.m -MallocAddress.m MappedCollector.m MemoryStream.m -Notification.m NotificationDispatcher.m OrderedCollection.m Port.m -Proxy.m Queue.m RawCStream.m RBTree.m RBTreeNode.m -RNGAdditiveCongruential.m Set.m SplayTree.m Stack.m @@ -48,34 +41,23 @@ StdioStream.m Stream.m TcpPort.m TextCStream.m -Time.m UdpPort.m behavior.m preface.m mframe.m -HashTable.m -List.m -objc/HashTable.h -objc/List.h -NSAllocateObject.m -NSArchiver.m NSArray.m NSAutoreleasePool.m NSCoder.m NSCopyObject.m NSCountedSet.m NSData.m -NSDeallocateObject.m NSDictionary.m NSEnumerator.m NSGArchiver.m NSGArray.m -NSGCountedSet.m NSGCString.m -NSGDictionary.m NSGSet.m NSGString.m -NSInvocation.m NSMethodSignature.m NSNotification.m NSNotificationCenter.m @@ -93,16 +75,10 @@ NSUser.m Kresten Krab Thorup: GapArray.m objc-gnu2next.m -Storage.m -objc/Storage.h Adam Fedor: ostream.m -NXStringTable.m -NXStringTable_scan.c -objc/NXStringTable.h -NXStringTable_scan.l NSAssertionHandler.m NSBitmapCharSet.m NSBundle.m @@ -189,12 +165,17 @@ NSZone.m Richard Frith-Macdonald: UnixFileHandle.m NSData.m +NSDateFormatter.m NSDebug.m NSDistantObject.m NSDistributedLock.m +NSDistributedNotificationCenter.m NSFileHandle.m +NSFormatter.m +NSGDictionary.m NSPipe.m NSPort.m +NSPortNameServer.m NSProxy.m NSTask.m NSUndoManager.m @@ -209,3 +190,8 @@ NSGString.m Mike Kienenberger: NSProtocolChecker.m + + +Manuel Guesdon: +NSURL.m +NSURLHandle.m diff --git a/ChangeLog b/ChangeLog index f34452425..eb7041583 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,42 @@ +Tue Mar 2 08:04:00 1999 Richard Frith-Macdonald + + * Merge in 'dawn' CVS branch. + +1999-03-01 Adam Fedor + + * Update documentation. + +1999-02-28 Adam Fedor + + * Source/Makefile.postamble: Don't install services if not + root. (patches submitted by Christopher Seawood + ). + +Tue Feb 23 12:03:00 1999 Richard Frith-Macdonald + + * Source/include/NSObject.h: Fixed bugin in ASSIGNCOPY() macro and added + CREATE_AUTORELEASE_POOL() macro for libFoundation compatibility. + * Source/include/NSRunLoop.h: Added GCFinalization protocol. + * Source/NSRunLoop.m: Tidied a little, added GC macro use, fixed minor + bug, and added slight performance improvement. + +Mon Feb 22 5:40:00 1999 Richard Frith-Macdonald + + Merged in alterations from main cvs branch made to wrong place 'cos + dawn branch was already created :-( + * Source/NSData.m: preserve file attributes when writing atomically + * Source/NSUser.m: Bugfixes for consistent naming of current user. + * Source/NSUserDefaults.m: Bugfixes so that running apps as root + doesn't mess up defaults database. + * Source/NSFileManager.m: Create files with correct ownership when + process is setuid to root - and provide facility for NSData to do same. + * Source/NSArray.m: Merged enumerator bugfix - missing @end + +1999-02-22 Adam Fedor + + * Version: update version. + * Source/NSProcessInfo.m: Change missing main message. + Sun Feb 21 19:30:00 1999 Richard Frith-Macdonald * Source/NSFileManager.m: Attempt to fix problems with directory diff --git a/Documentation/GNUmakefile b/Documentation/GNUmakefile index e1436462e..73782cd9f 100644 --- a/Documentation/GNUmakefile +++ b/Documentation/GNUmakefile @@ -35,9 +35,9 @@ DOCUMENT_NAME = gnustep-base # The text documents to be generated DOCUMENT_TEXT_NAME = \ -TODO INSTALL NEWS CODING-STANDARDS README ANNOUNCE STATUS +INSTALL NEWS CODING-STANDARDS README ANNOUNCE -TOP_DOC_FILES = TODO INSTALL NEWS README ANNOUNCE STATUS +TOP_DOC_FILES = INSTALL NEWS README ANNOUNCE gnustep-base_TEXI_FILES = \ version.tmpl.texi \ @@ -47,9 +47,7 @@ announce.tmpl.texi \ coding-standards.tmpl.texi \ install.tmpl.texi \ news.tmpl.texi \ -readme.tmpl.texi \ -status.tmpl.texi \ -todo.tmpl.texi +readme.tmpl.texi TODO_TEXI_FILES = version.tmpl.texi TODO_TEXT_MAIN = todo.tmpl.texi diff --git a/Documentation/base-desc.texi b/Documentation/base-desc.texi index 04e6e6db1..9c2db2e74 100644 --- a/Documentation/base-desc.texi +++ b/Documentation/base-desc.texi @@ -6,5 +6,4 @@ remote object messaging support (distributed objects), event loops, and random number generators. It provides functionality that aims to implement the non-graphical -portion of the OpenStep standard. In many cases, the @samp{NS*} classes -are implemented as wrappers around more featureful GNU classes. +portion of the OpenStep standard (the Foundation library). diff --git a/Documentation/gnustep-base.tmpl.texi b/Documentation/gnustep-base.tmpl.texi index e9e304697..d6f86d6db 100644 --- a/Documentation/gnustep-base.tmpl.texi +++ b/Documentation/gnustep-base.tmpl.texi @@ -90,12 +90,6 @@ into another language, under the above conditions for modified versions. @c News @include news.texi -@c Status Report -@include status.texi - -@c The ToDo -@include todo.texi - @c Generate Short Contents @shortcontents diff --git a/Documentation/news.tmpl.texi b/Documentation/news.tmpl.texi index cc36413e8..5aba31ecf 100644 --- a/Documentation/news.tmpl.texi +++ b/Documentation/news.tmpl.texi @@ -7,6 +7,31 @@ The currently released version of the library is @samp{@value{GNUSTEP-BASE-VERSION}}. +@section Noteworthy changes in version @samp{0.5.5} + +Too many changes to mention in detail, but here is a list of a few: + +@itemize @bullet + +@item +Many base classes have been rewritten with tonnes of performance +improvements that in many cases make it as fast as or faster than the +NeXT implementation. + +@item +DO and archiving has received many improvements that help it work on a +variety of different platforms. + +@item +Configuration and compilation has been greatly improved and fool +proofed. + +@item +There are several new tools for handling services, defaults, and +pasteboards. + +@end itemize + @section Noteworthy changes in version @samp{0.5.1} @itemize @bullet diff --git a/Documentation/readme.tmpl.texi b/Documentation/readme.tmpl.texi index ee7e19ef6..f6896e956 100644 --- a/Documentation/readme.tmpl.texi +++ b/Documentation/readme.tmpl.texi @@ -21,107 +21,13 @@ will be forthcoming, but the library needs to settle first. For now I recommend reading the header files. The headers for the classes are in @file{./src/include}. -The FAQ contains an outline of the class heirarchy, as well as a -list of the differences between GNUstep and NeXT's implementation of -OpenStep, and GNUstep's improvements over NeXT's implementation. - -@section Overview of the classes - -Here is partial list of non-OpenStep classes, grouped by functionality. - -There are several GNU-specific protocols also. You can recognize the -protocols by their name: they all end with ``ing''. - -@itemize @bullet - -@item The collection objects all conform to the @samp{Collecting} -protocol. Reading @samp{src/include/Collecting.h} is a good place to -start. Protocols for collections that store their contents with keys -and with indices can be found in @samp{src/incliude/KeyedCollecting.h} and -@samp{src/include/IndexedCollecting.h} respectively. Examples of generic -collections are @samp{Set} and @samp{Bag}. The keyed collections are -@samp{Dictionary} and @samp{MappedCollector}. The classes @samp{Array}, -@samp{Queue}, @samp{GapArray}, @samp{LinkedList}, @samp{BinaryTree}, -@samp{RBTree} and @samp{SplayTree} are all indexed collections. - -@item The string objects conform to the @samp{String} protocol. -@samp{CString} provides an interface to strings based on ASCII bytes, -and is currently the only concrete subclass of String. The interface -between GNU @samp{String} and OpenStep's @samp{NSString} needs cleaning -up and will change. For now, I recommend using @samp{NSString}. - -@item The public magnitude classes are @samp{Time} and @samp{Random}. -The @samp{Random} class works in conjunction with pseudo-random number -generators that conform to the @samp{RandomGenerating} protocol. The -conforming class @samp{RNGBerkeley} provides identical behavior to the -BSD random() function. The class @samp{RNGAdditiveCongruential} is an -implementation of the additive congruential method. - -@item Stream objects provide a consistent interface for reading and -writing bytes. Read @samp{src/include/Stream.h} to get the general -idea. @samp{StdioStream} objects work with files, file descriptors, -FILE pointers and pipes to/from executables. @samp{MemoryStream} -objects work with memory buffers. - -@item CStream objects provide a way to write C variables to Stream -objects. Read @file{src/include/CStream.h} to understand the interface -of the abstract superclass. @samp{TextCStream} writes C variables in a -human-readable ASCII format that can be manipulated with a text editor -or with your choice of text-processing programs, like @samp{awk} or -@samp{perl}. @samp{BinaryCStream} writes C variables in a compact, -illegible stream of bytes. @samp{TextCStream} and @samp{BinaryCStream} -each write in machine-independant formats---so you can write on one -machine architecture, and successfully read on another. -@samp{RawCStream} is like @samp{BinaryCStream} accept it is -machine-dependant; it useful for efficient Distributed Objects -connections on the same machine. - -@item Coders provide a formatted way of writing Objective C objects to -CStream objects. After a coder is initialized with a stream, the coder -can encode/decode interconnected webs of Objective C objects and C types -and successfully keep track of complex interconnections between objects. -See @samp{src/include/Coder.h} for the abstract superclass interface; -see @samp{src/include/Coding.h} for the protocol adopted by objects that -read and write themselves using coders. @samp{Archiver} and -@samp{Unarchiver} are concrete subclasses that are used for -writing/reading with files. - -@samp{Coder}s and @samp{CStream}s and @samp{Stream}s can be mixed and -matched so that programmers can choose the destination and the format -separately. - -@ignore -@item @samp{Notification} -@samp{NotificationDispatcher} -@end ignore - -@item The distributed object support classes are @samp{NSConnection}, -@samp{NSProxy}, @samp{ConnectedCoder}, @samp{Port} and @samp{TcpPort}. -This version of the distributed objects only works with sockets. A Mach -port back-end should be on the way. - -@end itemize - -@section Test Programs - -Some of the programs I've used to test the library are in -@samp{./checks}. Many of them are pretty messy, (desperately trying to -tickle that late night bug), but at least they show some code that works -when the library compiles correctly. I'm looking for a volunteer to -write some nicely organized test cases using @samp{dejagnu}. Any -takers? - @section How can you help? @itemize @bullet -@item Read the projects and questions in the @samp{TODO} file. If you -can volunteer for any of the projects, or if you have any useful -comments send me email! - @item -Give me feedback! Tell me what you like; tell me what you think -could be better. Send me bug reports. +Give us feedback! Tell us what you like; tell us what you think +could be better. Send bug reports to @email{bug-gnustep@@gnu.org}. @item Donate classes. If you write classes that fit in the libgnustep-base @@ -131,9 +37,4 @@ framework, I'd be happy to include them. @example Happy hacking! - Andrew McCallum - mccallum@@gnu.org - - Adam Fedor - fedor@@gnu.org @end example diff --git a/Documentation/status.tmpl.texi b/Documentation/status.tmpl.texi index 8b494da63..68300e2f4 100644 --- a/Documentation/status.tmpl.texi +++ b/Documentation/status.tmpl.texi @@ -5,6 +5,10 @@ @include version.tmpl.texi @end ifset +The gnustep-base library is nearly complete, although a few things could +be fixed here and there and it could be ported to more systems. This +list is probably out of date. In the future we will be primarily adding +features and performance tuning. Please send corrections to @email{fedor@@gnu.org}. @emph{Key:} @@ -31,80 +35,62 @@ Unknown status. (Many classes do not raise the proper NSExceptions yet.) @table @strong -@item NSArchiver:: [8] - Doesn't yet call -awakeAfterUsingCoder:. +@item NSArchiver:: [9] @item NSArray:: [9] @item NSAssertionHandler:: [9] -@item NSAttributedString:: [8] +@item NSAttributedString:: [9] @item NSAutoreleasePool:: [9] But not exception- safe -@item NSBundle:: [8] -@item NSCalendarDate:: [7] -@item NSCharacterSet:: [8] - decomposableCharacterSet and illegalCharacter set missing -@item NSCoder:: [8] - Missing class name substitution methods. +@item NSBundle:: [9] +@item NSCalendarDate:: [8] +@item NSCharacterSet:: [9] +@item NSCoder:: [9] @item NSConditionLock:: [8] -@item NSConnection:: [7] - GNU Connection, however, needs: - @itemize @bullet - @item to handle retain/release/dealloc properly - @item to be integrated with NSInvocation - @item to incorporate futzing with low-level TCP-backend for better speed - @item to have UDP-backend work - @item to cache ConnectedCoder's for better speed - @item Thread-safety overhaul, this is major - @end itemize -@item NSCountedSet:: [8] -@item NSData:: [8] -@item NSDate:: [8] -@item NSDeserializer:: [7] -@item NSDictionary:: [8] -@item NSDistantObject:: [7] -@item NSDistributedLock:: [7] +@item NSConnection:: [9] +@item NSCountedSet:: [9] +@item NSData:: [9] +@item NSDate:: [9] +@item NSDeserializer:: [8] +@item NSDictionary:: [9] +@item NSDistantObject:: [8] +@item NSDistributedLock:: [9] @item NSEnumerator:: [9] @item NSException:: [9] But this needs integration with new, better @item NSFileHandle:: [9] @item NSFileManager:: [9] -@item NSHashTable:: [8] -@item NSHost:: [8] -@item NSInvocation:: [3] -@item NSLock:: [8] -@item NSMapTable:: [8] -@item NSMethodSignature:: [4] -@item NSMutableArray:: [8] -@item NSMutableCharacterSet:: [7] -@item NSMutableData:: [8] -@item NSMutableDictionary:: [8] -@item NSMutableSet:: [8] -@item NSMutableString:: [8] +@item NSHashTable:: [9] +@item NSHost:: [9] +@item NSInvocation:: [7] +@item NSLock:: [9] +@item NSMapTable:: [9] +@item NSMethodSignature:: [7] +@item NSMutableArray:: [9] +@item NSMutableCharacterSet:: [8] +@item NSMutableData:: [9] +@item NSMutableDictionary:: [9] +@item NSMutableSet:: [9] +@item NSMutableString:: [9] @item NSNotification:: [9] @item NSNotificationCenter:: [9] @item NSNotificationQueue:: [6] - Needs integration with NSRunLoop, and efficiency improvements @item NSNumber:: [9] @item NSObject:: [10] @item NSProcessInfo:: [9] -@item NSProxy:: [7] -@item NSRecursiveLock:: [8] -@item NSRunLoop:: [8] - NSTimer's not yet working, but everything else should be -@item NSScanner:: [8] -@item NSSerializer:: [7] -@item NSSet:: [8] -@item NSString:: [8] - Careful, relationship with GNU String is tricky; this could - also use fixing. +@item NSProxy:: [8] +@item NSRecursiveLock:: [9] +@item NSRunLoop:: [9] +@item NSScanner:: [9] +@item NSSerializer:: [8] +@item NSSet:: [9] +@item NSString:: [9] @item NSTask:: [8] @item NSThread:: [8] -@item NSTimeZone:: [8] -@item NSTimeZoneDetail:: [8] -@item NSTimer:: [6] - Working out bugs with returning doubles. -@item NSUnarchiver:: [8] - See NSArchvier -@item NSUserDefaults:: [8] +@item NSTimeZone:: [9] +@item NSTimeZoneDetail:: [9] +@item NSTimer:: [7] +@item NSUnarchiver:: [9] +@item NSUserDefaults:: [9] @item NSValue:: [9] @end table diff --git a/Documentation/todo.tmpl.texi b/Documentation/todo.tmpl.texi index 1e1d8525f..56b866260 100644 --- a/Documentation/todo.tmpl.texi +++ b/Documentation/todo.tmpl.texi @@ -10,161 +10,5 @@ @itemize @bullet -@item Implement Formatter classes (NSDateFormatter, etc) [5] (980722). - -@item Implement NSDecimalNumber stuff [5] (981119). - -@item Write tests for various classes using the testsuite built -by Richard Frith-Macdonald @email{richard@@brainstorm.co.uk}. Contact -him for details. [3, guile] (980629) - -@item Check that every class implements coding (correctly). [2, NSCoder] (980721) - contribute to the testuite. - -@item Check that every class implements copying (correctly) - i.e. non-mutable classes should just retain, etc. [1, NSCopying] (980721) - contribute to the testsuite. - -@item Check that every class raises the NSExceptions it is supposed to. -Change many NSParameterAssert()'s into NSAssert()'s with -explanations. [2, exceptions] (970101) - contribute to the testsuite. - -@item Improve initWithFormat related methods for NSString and find out how to implement the locale stuff [4 OPENSTEP/Rhapsody] (980712) - -@item Make gstep-base 64bit clean [5, 64bit machine] (980629) -Donating internet access to a 64bit machine for someone else to do the -work on would also be helpful. - -@item Make gstep-base smaller. Perhaps we can get rid of classes that -aren't strictly part of OpenStep and put them in an extensions-type -library. [5] (980629) - -@item Fix NSLog so it conforms to specs. Need to check that write to -stderr went ok, and if not write to syslog. Also need to serialize -output (with threads). [3, OpenStep specs, threads] (980220) - -@item Simplify NSException and NSAssertionHandler and make sure they -don't cause race conditions (if an exception is raised while processing -an exception. [4, exceptions, threads] (980220) - -@item Fix all the places marked FIXME or xxx. [3-9] (980629) - @end itemize - - -@ignore - -@c ================================================================== -@section Questions - -I would greatly appreciate your feedback on the questions -below. Please email your thoughts to mccallum@@gnu.ai.mit.edu. - -@itemize @bullet - -@item -I want to put method names in texinfo indices, but the colons in the -method names are interfering with info's notion of menu item names and -node names. Help. Any ideas? (Kresten?) - -@item -HashTable.m (-initKeyDesc:valueDesc:capacity:) I tried to make it -portable, but I didn't try very hard. Anyone want to send in fixes? - -@item -I fixed -emptyCopy in all the subclasses, but the -emptyCopy scheme -seems pretty fragile. How about calling -initFoo: inside -emptyCopy? -This way we avoid having yet another method in which instance vars -must be initialized to some consistent state. -allocCopy would never -even get called. <> - -@item -Does anyone really need the ability to set the collection element -comparison function independent of the -compare: method? - -@item -How about adding flexibity in the method name that a LinkedList sends a -LinkedListNode to get/set the link ivars. This would enable us to add a -node to more than one linked list. - -@item -Something like this needed? -- elementDidChange: (elt*)elementPtr; -Currently you have to remove, change, add, for some classes. - -@end itemize - - -@section Albin's To Do List - -I'm sure that there're other things to do, but these are the ones I know now: - -@subsection General - -@itemize @bullet -@item Make thread-safe all of my code that should be. -@item Fully annotate all of my headers. -@item Document my work and the use of its fruit. -@end itemize - -@subsection Critical - -@itemize @bullet -@item Code: -@itemize + -@item (@file{src/array.m}) @samp{objects_array_check} -@item (@file{src/array.m}) @samp{objects_array_map_elements} -@item (@file{src/cbs-char-p.m}) @samp{objects_char_p_describe} -@item (@file{src/cbs-int-p.m}) @samp{objects_int_p_describe} -@item (@file{src/cbs-int.m}) @samp{objects_int_describe} -@item (@file{src/hash.m}) @samp{_objects_hash_hash} -@item (@file{src/hash.m}) @samp{objects_hash_check} -@item (@file{src/hash.m}) @samp{objects_hash_description} -@item (@file{src/list.m}) @samp{objects_list_is_equal_to_list} -@item (@file{src/map.m}) @samp{_objects_map_hash} -@item (@file{src/map.m}) @samp{objects_map_check} -@item (@file{src/map.m}) @samp{objects_map_description} -@end itemize - -@item Correct: -@itemize + -@item (@file{src/array.m}) @samp{objects_array_dealloc} -@item (@file{src/cbs-int.m}) @samp{_GNUSTEP_BASE_NOT_AN_INT_MARKER} -@end itemize - -@item Improve the error handling of: -@itemize + -@item (@file{src/array.m}) @samp{_objects_array_insert_bucket} -@item (@file{src/hash.m}) @samp{objects_hash_add_element_known_absent} -@item (@file{src/list.m}) @samp{objects_list_at_index_insert_element} -@item (@file{src/map.m}) @samp{objects_map_at_key_put_value_known_absent} -@end itemize -@end itemize - -@subsection Not So Critical - -@itemize @bullet -@item Strengthen my resolve on the correctness of: -@itemize + -@item (@file{src/cbs-char-p.m}) @samp{_GNUSTEP_BASE_NOT_A_CHAR_P_MARKER} -@item (@file{src/cbs-id.m}) @samp{_GNUSTEP_BASE_NOT_AN_ID_MARKER} -@item (@file{src/cbs-int-p.m}) @samp{_GNUSTEP_BASE_NOT_AN_INT_P_MARKER} -@item (@file{src/cbs-int-p.m}) @samp{objects_int_p_is_equal} -@item (@file{src/cbs-void-p.m}) @samp{_GNUSTEP_BASE_NOT_A_VOID_P_MARKER} -@item (@file{src/hash.m}) @samp{objects_hash_rightsize} -@item (@file{src/hash.m}) @samp{objects_hash_all_elements} -@item (@file{src/map.m}) @samp{objects_map_rightsize} -@item (@file{src/map.m}) @samp{objects_map_all_keys} -@item (@file{src/map.m}) @samp{objects_map_all_values} -@end itemize - -@item Improve the efficiency of: -@itemize + -@item (@file{src/array.m}) @samp{_objects_array_insert_bucket} -@item (@file{src/hash.m}) @samp{objects_hash_minus_hash} -@item (@file{src/list.m}) @samp{objects_list_at_index_insert_list} -@end itemize -@end itemize - -@end ignore - - diff --git a/Headers/gnustep/base/NSObject.h b/Headers/gnustep/base/NSObject.h index 34c49b3d2..07c3c6076 100644 --- a/Headers/gnustep/base/NSObject.h +++ b/Headers/gnustep/base/NSObject.h @@ -231,8 +231,11 @@ extern NSRecursiveLock *gnustep_global_lock; #define AUTORELEASE(object) ((id)object) #define ASSIGN(object,value) (object = value) +#define ASSIGNCOPY(object,value) (object = [value copy]) #define DESTROY(object) (object = nil) +#define CREATE_AUTORELEASE_POOL(X) + #else #define RETAIN(object) [object retain] @@ -269,7 +272,7 @@ if (__value != object) \ { \ if (__value) \ { \ - [__value copy]; \ + __value = [__value copy]; \ } \ if (object) \ { \ @@ -285,6 +288,10 @@ if (__value != object) \ * object later. */ #define DESTROY(object) ([object release], object = nil) + +#define CREATE_AUTORELEASE_POOL(X) \ + NSAutoreleasePool *(X) = [NSAutoreleasePool new] + #endif #endif /* __NSObject_h_GNUSTEP_BASE_INCLUDE */ diff --git a/Headers/gnustep/base/NSPort.h b/Headers/gnustep/base/NSPort.h index 6adbef884..d8ab536e7 100644 --- a/Headers/gnustep/base/NSPort.h +++ b/Headers/gnustep/base/NSPort.h @@ -26,29 +26,46 @@ #include -@class NSMutableSet; +@class NSArray; +@class NSConnection; +@class NSDate; +@class NSRunLoop; +@class NSString; extern NSString *NSPortTimeoutException; /* OPENSTEP */ @interface NSPort : NSObject { - BOOL is_valid; - id delegate; + BOOL is_valid; + id delegate; } + (NSPort*) port; + (NSPort*) portWithMachPort: (int)machPort; -- delegate; +- (id) delegate; -- init; -- initWithMachPort: (int)machPort; +- (id) init; +- (id) initWithMachPort: (int)machPort; - (void) invalidate; - (BOOL) isValid; -- machPort; -- (void) setDelegate: anObject; +- (int) machPort; +- (void) setDelegate: (id)anObject; +#ifndef STRICT_OPENSTEP +- (void) addConnection: (NSConnection*)aConnection + toRunLoop: (NSRunLoop*)aLoop + forMode: (NSString*)aMode; +- (void) removeConnection: (NSConnection*)aConnection + fromRunLoop: (NSRunLoop*)aLoop + forMode: (NSString*)aMode; +- (unsigned) reservedSpaceLength; +- (void) sendBeforeDate: (NSDate*)when + components: (NSArray*)components + from: (NSPort*)receivingPort + reserved: (unsigned) length; +#endif @end #ifndef NO_GNUSTEP diff --git a/Headers/gnustep/base/NSPortMessage.h b/Headers/gnustep/base/NSPortMessage.h index 4eabc334b..5630eac12 100644 --- a/Headers/gnustep/base/NSPortMessage.h +++ b/Headers/gnustep/base/NSPortMessage.h @@ -29,8 +29,8 @@ @interface NSPortMessage : NSObject { - unsigned msgid; - NSMutableArray *components; + unsigned msgid; + NSMutableArray *components; } - (id) initWithMachMessage: (void*)buffer; - (id) initWithSendPort: (NSPort*)aPort @@ -42,6 +42,10 @@ - (NSPort*) receivePort; - (void) setMsgid: (unsigned)anId; - (unsigned) msgid; + +#ifndef NO_GNUSTEP +- (void) addComponent: (id)aComponent; +#endif @end #endif diff --git a/Headers/gnustep/base/NSRunLoop.h b/Headers/gnustep/base/NSRunLoop.h index a93a3440c..3b625bdd9 100644 --- a/Headers/gnustep/base/NSRunLoop.h +++ b/Headers/gnustep/base/NSRunLoop.h @@ -32,7 +32,7 @@ /* Mode strings. */ extern id NSDefaultRunLoopMode; -@interface NSRunLoop : NSObject +@interface NSRunLoop : NSObject { @private id _current_mode; @private NSMapTable *_mode_2_timers; diff --git a/Makefile.postamble b/Makefile.postamble index 128053dee..f5ed7a49b 100644 --- a/Makefile.postamble +++ b/Makefile.postamble @@ -74,7 +74,6 @@ after-distclean:: configure: configure.in autoconf - autoheader # Regenerate automatically generated files regenerate: stamp-regenerate @@ -84,36 +83,3 @@ stamp-regenerate: ChangeLog configure (cd $$i; $(MAKE) $(MAKEDEFINES) regenerate); \ done touch stamp-regenerate - -snapshot: - @echo Making $(PACKAGE_NAME) snapshot - cvs export -r snapshot-`date +%y%m%d` $(PACKAGE_NAME) - rm -f .name - echo $(PACKAGE_NAME)-`date +%y%m%d` >.name - rm -rf `cat .name` - mv $(PACKAGE_NAME) `cat .name` - tar -chvf `cat .name`.tar `cat .name` - rm -f `cat .name`.tar.gz - gzip -9 `cat .name`.tar - rm -rf `cat .name` - -dist: - @echo Making $(PACKAGE_NAME) release $(VERSION) - cvs export -r release-`echo $(VERSION) | tr . -` $(PACKAGE_NAME) - mv $(PACKAGE_NAME) $(PACKAGE_NAME)-$(VERSION) - tar -chvf $(PACKAGE_NAME)-$(VERSION).tar \ - $(PACKAGE_NAME)-$(VERSION) - rm -f $(PACKAGE_NAME)-$(VERSION).tar.gz - gzip -9 $(PACKAGE_NAME)-$(VERSION).tar - rm -rf $(PACKAGE_NAME)-$(VERSION) - -snapshot-rtag: - @echo Tagging current base HEAD for snapshot `date +%y%m%d` - cvs rtag snapshot-`date +%y%m%d` $(PACKAGE_NAME) - -dist-rtag: - @echo Tagging current base HEAD for release $(VERSION) - cvs rtag release-`echo $(VERSION) | tr . -` $(PACKAGE_NAME) - -rdiff: - cvs rdiff -u -r $(OLD) $(PACKAGE_NAME) diff --git a/NEWS b/NEWS index 73d2a5281..c4f2456ba 100644 --- a/NEWS +++ b/NEWS @@ -1,7 +1,25 @@ News **** -The currently released version of the library is `0.5.0'. +The currently released version of the library is `0.5.5'. + +Noteworthy changes in version `0.5.5' +===================================== + + Too many changes to mention in detail, but here is a list of a few: + + * Many base classes have been rewritten with tonnes of performance + improvements that in many cases make it as fast as or faster than + the NeXT implementation. + + * DO and archiving has received many improvements that help it work + on a variety of different platforms. + + * Configuration and compilation has been greatly improved and fool + proofed. + + * There are several new tools for handling services, defaults, and + pasteboards. Noteworthy changes in version `0.5.1' ===================================== diff --git a/README b/README index a337b38a3..8a6273960 100644 --- a/README +++ b/README @@ -9,8 +9,7 @@ remote object messaging support (distributed objects), event loops, and random number generators. It provides functionality that aims to implement the non-graphical -portion of the OpenStep standard. In many cases, the `NS*' classes are -implemented as wrappers around more featureful GNU classes. +portion of the OpenStep standard (the Foundation library). Here is some introductory info to get you started: @@ -30,106 +29,14 @@ documentation will be forthcoming, but the library needs to settle first. For now I recommend reading the header files. The headers for the classes are in `./src/include'. - The FAQ contains an outline of the class heirarchy, as well as a -list of the differences between GNUstep and NeXT's implementation of -OpenStep, and GNUstep's improvements over NeXT's implementation. - -Overview of the classes -======================= - - Here is partial list of non-OpenStep classes, grouped by -functionality. - - There are several GNU-specific protocols also. You can recognize the -protocols by their name: they all end with "ing". - - * The collection objects all conform to the `Collecting' protocol. - Reading `src/include/Collecting.h' is a good place to start. - Protocols for collections that store their contents with keys and - with indices can be found in `src/incliude/KeyedCollecting.h' and - `src/include/IndexedCollecting.h' respectively. Examples of - generic collections are `Set' and `Bag'. The keyed collections are - `Dictionary' and `MappedCollector'. The classes `Array', `Queue', - `GapArray', `LinkedList', `BinaryTree', `RBTree' and `SplayTree' - are all indexed collections. - - * The string objects conform to the `String' protocol. `CString' - provides an interface to strings based on ASCII bytes, and is - currently the only concrete subclass of String. The interface - between GNU `String' and OpenStep's `NSString' needs cleaning up - and will change. For now, I recommend using `NSString'. - - * The public magnitude classes are `Time' and `Random'. The - `Random' class works in conjunction with pseudo-random number - generators that conform to the `RandomGenerating' protocol. The - conforming class `RNGBerkeley' provides identical behavior to the - BSD random() function. The class `RNGAdditiveCongruential' is an - implementation of the additive congruential method. - - * Stream objects provide a consistent interface for reading and - writing bytes. Read `src/include/Stream.h' to get the general - idea. `StdioStream' objects work with files, file descriptors, - FILE pointers and pipes to/from executables. `MemoryStream' - objects work with memory buffers. - - * CStream objects provide a way to write C variables to Stream - objects. Read `src/include/CStream.h' to understand the interface - of the abstract superclass. `TextCStream' writes C variables in a - human-readable ASCII format that can be manipulated with a text - editor or with your choice of text-processing programs, like `awk' - or `perl'. `BinaryCStream' writes C variables in a compact, - illegible stream of bytes. `TextCStream' and `BinaryCStream' each - write in machine-independant formats--so you can write on one - machine architecture, and successfully read on another. - `RawCStream' is like `BinaryCStream' accept it is - machine-dependant; it useful for efficient Distributed Objects - connections on the same machine. - - * Coders provide a formatted way of writing Objective C objects to - CStream objects. After a coder is initialized with a stream, the - coder can encode/decode interconnected webs of Objective C objects - and C types and successfully keep track of complex - interconnections between objects. See `src/include/Coder.h' for - the abstract superclass interface; see `src/include/Coding.h' for - the protocol adopted by objects that read and write themselves - using coders. `Archiver' and `Unarchiver' are concrete subclasses - that are used for writing/reading with files. - - `Coder's and `CStream's and `Stream's can be mixed and matched so - that programmers can choose the destination and the format - separately. - - * The distributed object support classes are `NSConnection', - `NSProxy', `ConnectedCoder', `Port' and `TcpPort'. This version - of the distributed objects only works with sockets. A Mach port - back-end should be on the way. - -Test Programs -============= - - Some of the programs I've used to test the library are in -`./checks'. Many of them are pretty messy, (desperately trying to -tickle that late night bug), but at least they show some code that works -when the library compiles correctly. I'm looking for a volunteer to -write some nicely organized test cases using `dejagnu'. Any takers? - How can you help? ================= - * Read the projects and questions in the `TODO' file. If you can - volunteer for any of the projects, or if you have any useful - comments send me email! - - * Give me feedback! Tell me what you like; tell me what you think - could be better. Send me bug reports. + * Give us feedback! Tell us what you like; tell us what you think + could be better. Send bug reports to . * Donate classes. If you write classes that fit in the libgnustep-base framework, I'd be happy to include them. Happy hacking! - Andrew McCallum - mccallum@gnu.org - - Adam Fedor - fedor@gnu.org diff --git a/Source/Makefile.postamble b/Source/Makefile.postamble index b9ec4e0e9..92fa87b2d 100644 --- a/Source/Makefile.postamble +++ b/Source/Makefile.postamble @@ -58,19 +58,22 @@ after-install:: $(INSTALL_DATA) $(GNUSTEP_TARGET_CPU)/$(GNUSTEP_TARGET_OS)/mframe.h \ $(GNUSTEP_HEADERS)/$(GNUSTEP_TARGET_CPU)/$(GNUSTEP_TARGET_OS) if [ "$(INSTALL_ROOT_DIR)" = "" ]; then \ - if [ "`whoami`" != root ]; then \ - echo "WARNING: Please add the following lines yourself"; \ - fi; \ services=/etc/services; \ else \ mkdir -p $(INSTALL_ROOT_DIR)/etc; \ services=$(INSTALL_ROOT_DIR)/etc/services.add; \ - echo "GNUstep addons for /etc/services written to $$services"; \ fi; \ - if [ "`fgrep gdomap $$services 2>/dev/null`" = "" ]; then \ + if [ "`whoami`" != root ]; then \ + echo "WARNING: Please add the following lines to $$services"; \ + echo "gdomap 538/tcp # GNUstep distrib objects"; \ + echo "gdomap 538/udp # GNUstep distrib objects"; \ + else \ + if [ "`fgrep gdomap $$services 2>/dev/null`" = "" ]; then \ + echo "GNUstep addons for /etc/services written to $$services"; \ set -x; \ echo "gdomap 538/tcp # GNUstep distrib objects" >> $$services; \ echo "gdomap 538/udp # GNUstep distrib objects" >> $$services; \ + fi; \ fi # Things to do before uninstalling diff --git a/Source/NSConnection.m b/Source/NSConnection.m index 788b578ff..a2a2ed18b 100644 --- a/Source/NSConnection.m +++ b/Source/NSConnection.m @@ -47,6 +47,8 @@ #include #include #include +#include +#include #include NSString* NSConnectionReplyMode = @"NSConnectionReplyMode"; @@ -184,6 +186,7 @@ static unsigned local_object_counter = 0; @interface NSConnection (Private) - _superInit; +- (void) handlePortMessage: (NSPortMessage*)msg; + setDebug: (int)val; @end @@ -411,9 +414,14 @@ static int messages_received_count; return delegate; } +- (void) handlePortMessage: (NSPortMessage*)msg +{ + [self notImplemented: _cmd]; +} + - (BOOL) independantConversationQueueing { - return independant_queueing; + return independant_queueing; } - (void) enableMultipleThreads diff --git a/Source/NSPort.m b/Source/NSPort.m index fbdd6c103..8c027b3d7 100644 --- a/Source/NSPort.m +++ b/Source/NSPort.m @@ -22,6 +22,7 @@ */ #include +#include #include #include #include @@ -38,17 +39,17 @@ NSString *NSPortTimeoutException + (NSPort*) port { - return [[[NSPort alloc] init] autorelease]; + return AUTORELEASE([NSPort new]); } + (NSPort*) portWithMachPort: (int)machPort { - return [[[NSPort alloc] initWithMachPort: machPort] autorelease]; + return AUTORELEASE([[NSPort alloc] initWithMachPort: machPort]); } - (id) copyWithZone: (NSZone*)aZone { - return [self retain]; + return RETAIN(self); } - (id) delegate @@ -75,7 +76,7 @@ NSString *NSPortTimeoutException - (id) initWithMachPort: (int)machPort { - [self notImplemented: _cmd]; + [self shouldNotImplement: _cmd]; return nil; } @@ -96,10 +97,10 @@ NSString *NSPortTimeoutException return is_valid; } -- (id) machPort +- (int) machPort { - [self notImplemented: _cmd]; - return nil; + [self shouldNotImplement: _cmd]; + return 0; } - (void) release @@ -126,8 +127,38 @@ NSString *NSPortTimeoutException - (void) setDelegate: anObject { + NSAssert([anObject respondsToSelector: @selector(handlePortMessage:)], + NSInvalidArgumentException); delegate = anObject; } +- (void) addConnection: (NSConnection*)aConnection + toRunLoop: (NSRunLoop*)aLoop + forMode: (NSString*)aMode +{ + [self subclassResponsibility: _cmd]; +} + +- (void) removeConnection: (NSConnection*)aConnection + fromRunLoop: (NSRunLoop*)aLoop + forMode: (NSString*)aMode +{ + [self subclassResponsibility: _cmd]; +} + +- (unsigned) reservedSpaceLength +{ + [self subclassResponsibility: _cmd]; + return 0; +} + +- (void) sendBeforeDate: (NSDate*)when + components: (NSArray*)components + from: (NSPort*)receivingPort + reserved: (unsigned) length +{ + [self subclassResponsibility: _cmd]; +} + @end diff --git a/Source/NSPortMessage.m b/Source/NSPortMessage.m index 556e574b5..260788f8c 100644 --- a/Source/NSPortMessage.m +++ b/Source/NSPortMessage.m @@ -32,21 +32,21 @@ - (void) dealloc { - [components release]; - [super dealloc]; + RELEASE(components); + [super dealloc]; } /* PortMessages MUST be initialised with ports and data. */ - (id) init { - [self notImplemented: _cmd]; - return nil; + [self shouldNotImplement: _cmd]; + return nil; } - (id) initWithMachMessage: (void*)buffer { - [self notImplemented: _cmd]; - return nil; + [self shouldNotImplement: _cmd]; + return nil; } /* This is the designated initialiser. */ @@ -54,47 +54,61 @@ receivePort: (NSPort*)anotherPort components: (NSArray*)items { - self = [super init]; - if (self) { - components = [[NSMutableArray allocWithZone: [self zone]] - initWithCapacity: [items count] + 2]; - [components addObject: aPort]; - [components addObject: anotherPort]; - [components addObjectsFromArray: items]; + self = [super init]; + if (self) + { + components = [[NSMutableArray allocWithZone: [self zone]] + initWithCapacity: [items count] + 2]; + [components addObject: aPort]; + [components addObject: anotherPort]; + [components addObjectsFromArray: items]; } - return self; + return self; } -- (void) sendBeforeDate: (NSDate*)when +- (void) addComponent: (id)aComponent { - [self notImplemented: _cmd]; + NSAssert([aComponent isKindOfClass: [NSData class]] + || [aComponent isKindOfClass: [NSPort class]], + NSInvalidArgumentException); + [components addObject: aComponent]; } - (NSArray*) components { - NSRange r = NSMakeRange(2, [components count]-2); + NSRange r = NSMakeRange(2, [components count]-2); - return [components subarrayWithRange: r]; -} - -- (NSPort*) sendPort -{ - return [components objectAtIndex: 0]; -} - -- (NSPort*) receivePort -{ - return [components objectAtIndex: 1]; -} - -- (void) setMsgid: (unsigned)anId -{ - msgid = anId; + return [components subarrayWithRange: r]; } - (unsigned) msgid { - return msgid; + return msgid; +} + +- (NSPort*) receivePort +{ + return [components objectAtIndex: 1]; +} + +- (void) sendBeforeDate: (NSDate*)when +{ + NSPort *port = [self sendPort]; + + [port sendBeforeDate: when + components: [self components] + from: [self receivePort] + reserved: [port reservedSpaceLength]]; +} + +- (NSPort*) sendPort +{ + return [components objectAtIndex: 0]; +} + +- (void) setMsgid: (unsigned)anId +{ + msgid = anId; } @end diff --git a/Source/NSProcessInfo.m b/Source/NSProcessInfo.m index c3f541bcb..29053ac74 100644 --- a/Source/NSProcessInfo.m +++ b/Source/NSProcessInfo.m @@ -74,12 +74,11 @@ /* This error message should be called only if the private main function * was not executed successfully. This may heppen ONLY if onother library - * or kit defines its own main function (as libobjects does). + * or kit defines its own main function (as gnustep-base does). */ -#define _GNU_MISSING_MAIN_FUNCTION_CALL @"Libobjects internal error: \ -the private libobjects function to establish the argv and environment \ -variables was not called. Please contact Tuparev@EMBL-Heidelberg.de for \ -further information." +#define _GNU_MISSING_MAIN_FUNCTION_CALL @"GNUSTEP Internal Error: \ +The private GNUstep function to establish the argv and environment \ +variables was not called. Please report this error to bug-gnustep@gnu.org." /************************************************************************* *** _NSConcreteProcessInfo diff --git a/Source/NSRunLoop.m b/Source/NSRunLoop.m index acb90a3c5..613787525 100644 --- a/Source/NSRunLoop.m +++ b/Source/NSRunLoop.m @@ -107,10 +107,11 @@ static int debug_run_loop = 0; * NB. This class is private to NSRunLoop and must not be subclassed. */ -@interface RunLoopWatcher: NSObject +@interface RunLoopWatcher: NSObject { @public BOOL invalidated; + BOOL handleEvent; // New-style event handling void *data; id receiver; RunLoopEventType type; @@ -130,9 +131,9 @@ static int debug_run_loop = 0; - (void) dealloc { - [self invalidate]; - [limit release]; - [receiver release]; + [self gcFinalize]; + RELEASE(limit); + RELEASE(receiver); [super dealloc]; } @@ -144,8 +145,7 @@ static int debug_run_loop = 0; return; } - if ([receiver respondsToSelector: - @selector(receivedEvent:type:extra:forMode:)]) + if (handleEvent) { [receiver receivedEvent: data type: type extra: info forMode: mode]; } @@ -155,21 +155,27 @@ static int debug_run_loop = 0; { case ET_RDESC: case ET_RPORT: - [receiver readyForReadingOnFileDescriptor: (int)info]; + [receiver readyForReadingOnFileDescriptor: (int)(gsaddr)info]; break; case ET_WDESC: - [receiver readyForWritingOnFileDescriptor: (int)info]; + [receiver readyForWritingOnFileDescriptor: (int)(gsaddr)info]; break; } } } -- initWithType: (RunLoopEventType)aType - receiver: (id)anObj - data: (void*)item +- (void) gcFinalize +{ + [self invalidate]; +} + +- (id) initWithType: (RunLoopEventType)aType + receiver: (id)anObj + data: (void*)item { invalidated = NO; + switch (aType) { case ET_RDESC: type = aType; break; @@ -179,7 +185,12 @@ static int debug_run_loop = 0; [NSException raise: NSInvalidArgumentException format: @"NSRunLoop - unknown event type"]; } - receiver = [anObj retain]; + receiver = RETAIN(anObj); + if ([receiver respondsToSelector: + @selector(receivedEvent:type:extra:forMode:)]) + handleEvent = YES; + else + handleEvent = NO; data = item; return self; } @@ -224,7 +235,7 @@ static int debug_run_loop = 0; * messages which are due to be sent to objects once a particular * runloop iteration has passed. */ -@interface RunLoopPerformer: NSObject +@interface RunLoopPerformer: NSObject { SEL selector; id target; @@ -252,10 +263,10 @@ static int debug_run_loop = 0; - (void) dealloc { - [timer invalidate]; - [target release]; - [argument release]; - [modes release]; + [self gcFinalize]; + RELEASE(target); + RELEASE(argument); + RELEASE(modes); [super dealloc]; } @@ -264,13 +275,18 @@ static int debug_run_loop = 0; if (timer != nil) { timer = nil; - [[self retain] autorelease]; + AUTORELEASE(RETAIN(self)); [[[NSRunLoop currentInstance] _timedPerformers] removeObjectIdenticalTo: self]; } [target performSelector: selector withObject: argument]; } +- (void) gcFinalize +{ + [timer invalidate]; +} + - initWithSelector: (SEL)aSelector target: (id)aTarget argument: (id)anArgument @@ -281,8 +297,8 @@ static int debug_run_loop = 0; if (self) { selector = aSelector; - target = [aTarget retain]; - argument = [anArgument retain]; + target = RETAIN(aTarget); + argument = RETAIN(anArgument); order = theOrder; modes = [theModes copy]; } @@ -331,8 +347,8 @@ static int debug_run_loop = 0; NSMutableArray *array; int i; - [target retain]; - [arg retain]; + RETAIN(target); + RETAIN(arg); array = [[NSRunLoop currentInstance] _timedPerformers]; for (i = [array count]; i > 0; i--) { @@ -343,8 +359,8 @@ static int debug_run_loop = 0; [array removeObjectAtIndex: i-1]; } } - [arg release]; - [target release]; + RELEASE(arg); + RELEASE(target); } - (void) performSelector: (SEL)aSelector @@ -366,7 +382,7 @@ static int debug_run_loop = 0; selector: @selector(fire) userInfo: nil repeats: NO]]; - [item release]; + RELEASE(item); } - (void) performSelector: (SEL)aSelector @@ -398,7 +414,7 @@ static int debug_run_loop = 0; userInfo: nil repeats: NO]; [item setTimer: timer]; - [item release]; + RELEASE(item); for (i = 0; i < [modes count]; i++) { [loop addTimer: timer forMode: [modes objectAtIndex: i]]; @@ -438,8 +454,8 @@ static int debug_run_loop = 0; if (watchers == nil) { watchers = [NSMutableArray new]; - NSMapInsert (_mode_2_watchers, mode, watchers); - [watchers release]; + NSMapInsert(_mode_2_watchers, mode, watchers); + RELEASE(watchers); count = 0; } else @@ -592,7 +608,7 @@ static int debug_run_loop = 0; data: data]; /* Add the object to the array for the mode. */ [self _addWatcher:info forMode:mode]; - [info release]; /* Now held in array. */ + RELEASE(info); /* Now held in array. */ } } @@ -683,11 +699,12 @@ static int debug_run_loop = 0; /* Positive values are in the future. */ while (ti > 0 && mayDoMore == YES) { - id arp = [NSAutoreleasePool new]; + CREATE_AUTORELEASE_POOL(arp); + if (debug_run_loop) printf ("\tNSRunLoop run until date %f seconds from now\n", ti); mayDoMore = [self runMode: mode beforeDate: date]; - [arp release]; + RELEASE(arp); ti = [date timeIntervalSinceNow]; } } @@ -698,7 +715,7 @@ static int debug_run_loop = 0; @implementation NSRunLoop -+ currentRunLoop ++ (NSRunLoop*) currentRunLoop { static NSString *key = @"NSRunLoopThreadKey"; NSRunLoop* r; @@ -710,7 +727,7 @@ static int debug_run_loop = 0; { r = [NSRunLoop new]; [[t threadDictionary] setObject: r forKey: key]; - [r release]; + RELEASE(r); } return r; } @@ -722,7 +739,7 @@ static int debug_run_loop = 0; } /* This is the designated initializer. */ -- init +- (id) init { [super init]; _current_mode = NSDefaultRunLoopMode; @@ -736,12 +753,17 @@ static int debug_run_loop = 0; } - (void) dealloc +{ + [self gcFinalize]; + RELEASE(_performers); + RELEASE(_timedPerformers); + [super dealloc]; +} + +- (void) gcFinalize { NSFreeMapTable(_mode_2_timers); NSFreeMapTable(_mode_2_watchers); - [_performers release]; - [_timedPerformers release]; - [super dealloc]; } - (NSString*) currentMode @@ -762,7 +784,7 @@ static int debug_run_loop = 0; { timers = [Heap new]; NSMapInsert (_mode_2_timers, mode, timers); - [timers release]; + RELEASE(timers); } /* xxx Should we make sure it isn't already there? */ [timers addObject: timer]; @@ -801,7 +823,7 @@ static int debug_run_loop = 0; break; } - [min_timer retain]; + RETAIN(min_timer); [timers removeFirstObject]; /* Firing will also increment its fireDate, if it is repeating. */ [min_timer fire]; @@ -809,7 +831,7 @@ static int debug_run_loop = 0; { [timers addObject: min_timer]; } - [min_timer release]; + RELEASE(min_timer); min_timer = nil; [NSNotificationQueue runLoopASAP]; /* Post notifications. */ } @@ -871,11 +893,11 @@ static int debug_run_loop = 0; * If the watcher has been given a revised limit date - * re-insert it into the queue in the correct place. */ - [min_watcher retain]; + RETAIN(min_watcher); ASSIGN(min_watcher->limit, nxt); [watchers removeObjectAtIndex: 0]; [self _addWatcher: min_watcher forMode: mode]; - [min_watcher release]; + RELEASE(min_watcher); } else { @@ -1204,14 +1226,14 @@ static int debug_run_loop = 0; { id watcher = (id) NSMapGet (wfd_2_object, (void*)fd_index); NSAssert(watcher, NSInternalInconsistencyException); - [watcher eventFor:(void*)fd_index mode:_current_mode]; + [watcher eventFor: (void*)(gsaddr)fd_index mode: _current_mode]; [NSNotificationQueue runLoopASAP]; } if (FD_ISSET (fd_index, &read_fds)) { id watcher = (id) NSMapGet (rfd_2_object, (void*)fd_index); NSAssert(watcher, NSInternalInconsistencyException); - [watcher eventFor:(void*)fd_index mode:_current_mode]; + [watcher eventFor: (void*)(gsaddr)fd_index mode: _current_mode]; [NSNotificationQueue runLoopASAP]; } } @@ -1250,12 +1272,12 @@ static int debug_run_loop = 0; } /* Use the earlier of the two dates we have. */ - d = [[d earlierDate:date] retain]; + d = RETAIN([d earlierDate: date]); /* Wait, listening to our input sources. */ [self acceptInputForMode: mode beforeDate: d]; - [d release]; + RELEASE(d); return YES; } @@ -1297,8 +1319,8 @@ id NSDefaultRunLoopMode = @"NSDefaultRunLoopMode"; int count = [_performers count]; int i; - [target retain]; - [argument retain]; + RETAIN(target); + RETAIN(argument); for (i = count; i > 0; i--) { item = (RunLoopPerformer*)[_performers objectAtIndex:(i-1)]; @@ -1308,8 +1330,8 @@ id NSDefaultRunLoopMode = @"NSDefaultRunLoopMode"; [_performers removeObjectAtIndex:(i-1)]; } } - [argument release]; - [target release]; + RELEASE(argument); + RELEASE(target); } - (void) configureAsServer @@ -1353,7 +1375,7 @@ id NSDefaultRunLoopMode = @"NSDefaultRunLoopMode"; [_performers addObject:item]; } } - [item release]; + RELEASE(item); } - (void) removePort: (NSPort*)port diff --git a/Source/TcpPort.m b/Source/TcpPort.m index 949252486..dea2cbf74 100644 --- a/Source/TcpPort.m +++ b/Source/TcpPort.m @@ -44,6 +44,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -108,6 +112,698 @@ static int debug_tcp_port = 0; /* Private interfaces */ +@class GSTcpPort; + +typedef struct { + gsu32 sendAddr; + gsu32 recvAddr; + gsu16 sendPort; + gsu16 recvPort; + gsu32 mesgId; + gsu32 mesgElems; + gsu32 remaining; +} GSTcpHeader; + +@interface GSTcpHandle : NSObject +{ + int desc; // Unix file descriptor. + NSLock *myLock; // Lock for This handle. + unsigned rLength; // Length of item read so far. + NSPortMessage *rMsg; // Message in progress. + unsigned rItem; // Index of current message item. + NSMutableData *rHeader; // Buffer for item data. + unsigned wLength; + NSPortMessage *wMsg; + unsigned wItem; + NSHashTable *ports; +} + ++ (GSTcpHandle*) handleWithDescriptor: (int)descriptor; +- (void) addPort: (GSTcpPort*)p; +- (void) invalidate; +- (void) readData; +- (void) removePort: (GSTcpPort*)p; +- (void) writeData; +@end + +@implementation GSTcpHandle + +static NSRecursiveLock *tcpHandleLock = nil; +static NSHashTable *tcpHandleTable = 0; + ++ (id) allocWithZone: (NSZone*)zone +{ + [NSException raise: NSGenericException + format: @"attempt to alloc a GSTcpHandle!"]; + return nil; +} + ++ (void) initialize +{ + if (tcpHandleLock == nil) + { + [gnustep_global_lock lock]; + if (tcpHandleLock == nil) + { + tcpHandleLock = [NSRecursiveLock new]; + tcpHandleTable = + NSCreateHashTable(NSNonRetainedObjectHashCallBacks, 0); + } + [gnustep_global_lock unlock]; + } +} + ++ (GSTcpHandle*) handleWithDescriptor: (int)descriptor +{ + static GSTcpHandle *dummy = nil; + GSTcpHandle *handle; + + if (descriptor < 0) + { + NSLog(@"illegal descriptor (%d) for Tcp Handle", descriptor); + return nil; + } + + [tcpHandleLock lock]; + if (dummy == nil) + dummy = (GSTcpHandle*)NSAllocateObject(self, 0, NSDefaultMallocZone()); + + dummy->desc = descriptor; + handle = (GSTcpHandle*)NSHashGet(tcpHandleTable, (void*)dummy); + + if (handle == nil) + { + int e; + BOOL ok = YES; + + if ((e = fcntl(descriptor, F_GETFL, 0)) >= 0) + { + e |= NBLK_OPT; + if (fcntl(descriptor, F_SETFL, e) < 0) + { + NSLog(@"unable to set non-blocking mode - %s", strerror(errno)); + ok = NO; + } + } + else + { + NSLog(@"unable to get non-blocking mode - %s", strerror(errno)); + ok = NO; + } + + if (ok) + { + handle = (GSTcpHandle*)NSAllocateObject(self,0,NSDefaultMallocZone()); + handle->desc = descriptor; + handle->ports = + NSCreateHashTable(NSNonRetainedObjectHashCallBacks, 0); + NSHashInsert(tcpHandleTable, (void*)handle); + AUTORELEASE(handle); + } + } + [tcpHandleLock unlock]; + return handle; +} + +- (void) addPort: (GSTcpPort*)p +{ + [myLock lock]; + NSHashInsert(ports, (void*)p); + [myLock unlock]; +} + +- (void) gcFinalize +{ + [myLock lock]; + + [tcpHandleLock lock]; + NSHashRemove(tcpHandleTable, (void*)self); + [tcpHandleLock unlock]; + + (void) close(desc); + desc = -1; + + NSFreeHashTable(ports); + RELEASE(rHeader); + RELEASE(rMsg); + RELEASE(wMsg); + + [myLock unlock]; + RELEASE(myLock); +} + +- (unsigned) hash +{ + return (unsigned)desc; +} + +- (void) invalidate +{ + [myLock lock]; + [myLock unlock]; +} + +- (BOOL) isEqual: (id)anObject +{ + if (anObject == self) + return YES; + if ([anObject class] == [self class] + && ((GSTcpHandle*)anObject)->desc == desc) + return YES; + return NO; +} + +- (void) readData +{ + int result; + unsigned want; + void *bytes = 0; + + [myLock lock]; + + do + { + /* + * Get address and length of buffer for incoming data if we don't already + * have it from an earlier iteration of the loop. Create the buffer if + * necessary. + */ + if (bytes == 0) + { + if (rHeader == nil) + { + if (rItem == 0) + want = sizeof(GSTcpHeader); + else + want = 6; + + rHeader = [[NSMutableData alloc] initWithLength: want]; + bytes = [rHeader mutableBytes]; + rLength = 0; + } + else + { + want = [rHeader length]; + bytes = [rHeader mutableBytes]; + } + } + + /* + * Now we attempt to fill the buffer. + */ + result = read(desc, bytes + rLength, want - rLength); + if (result == 0) + { + NSLog(@"Unexpected EOF on descriptor %d", desc); + [self invalidate]; + } + else if (result < 0) + { + if (errno != EAGAIN) + { + NSLog(@"Error reading on descriptor %d - %s", + desc, strerror(errno)); + [self invalidate]; + } + } + else + { + rLength += result; + if (rLength == want) + { + if (rItem == 0) + { + if (want == sizeof(GSTcpHeader)) + { + } + else + { + } + } + else + { + } + } + } + } + while (result > 0); + + [myLock unlock]; +} + +- (void) release +{ + if ([self retainCount] == 1) + { + [super retain]; + [self gcFinalize]; + [super release]; + } + [super release]; +} + +- (void) removePort: (GSTcpPort*)p +{ + [myLock lock]; + NSHashRemove(ports, (void*)p); + [myLock unlock]; +} + +- (void) writeData +{ + [myLock lock]; + [myLock unlock]; +} +@end + + + +@interface GSTcpPort : NSPort +{ + NSRecursiveLock *myLock; + struct sockaddr_in addr; + int listener; + NSHashTable *handles; +} + ++ (GSTcpPort*) portWithNumber: (gsu16)number + onHost: (NSHost*)host + beforeDate: (NSDate*)limit; ++ (GSTcpPort*) portWithAddress: (struct sockaddr_in*)address + andHandle: (GSTcpHandle*)handle + beforeDate: (NSDate*)limit; + +- (void) addHandle: (GSTcpHandle*)h; +- (void) removeHandle: (GSTcpHandle*)h; +@end + +@implementation GSTcpPort + +static NSRecursiveLock *tcpPortLock = nil; +static NSMapTable *tcpPortMap = 0; +static GSTcpPort *dummyPort = nil; + ++ (void) initialize +{ + if (tcpPortLock == nil) + { + [gnustep_global_lock lock]; + if (tcpPortLock == nil) + { + tcpPortLock = [NSRecursiveLock new]; + tcpPortMap = NSCreateMapTable(NSIntMapKeyCallBacks, + NSNonOwnedPointerMapValueCallBacks, 0); + dummyPort = (GSTcpPort*)NSAllocateObject(self, 0, + NSDefaultMallocZone()); + } + [gnustep_global_lock unlock]; + } +} + ++ (GSTcpPort*) portWithAddress: (struct sockaddr_in*)sockaddr + andHandle: (GSTcpHandle*)handle + beforeDate: (NSDate*)limit +{ + GSTcpPort *port = nil; + NSMapTable *thePorts; + + [tcpPortLock lock]; + + thePorts = (NSMapTable*)NSMapGet(tcpPortMap, + (void*)(gsaddr)sockaddr->sin_port); + + if (thePorts == 0) + { + thePorts = NSCreateMapTable(NSIntMapKeyCallBacks, + NSNonOwnedPointerMapValueCallBacks, 0); + NSMapInsert(tcpPortMap, + (void*)(gsaddr)sockaddr->sin_port, + (void*)thePorts); + } + + port = (GSTcpPort*)NSMapGet(tcpPortMap, + (void*)(gsaddr)sockaddr->sin_addr.s_addr); + + if (port == nil) + { + port = (GSTcpPort*)NSAllocateObject(self,0,NSDefaultMallocZone()); + + port->listener = -1; + memcpy(&port->addr, sockaddr, sizeof(port->addr)); + port->myLock = [NSRecursiveLock new]; + port->handles = NSCreateHashTable(NSObjectHashCallBacks, 0); + NSMapInsert(thePorts, (void*)(gsaddr)sockaddr->sin_addr.s_addr, + (void*)port); + AUTORELEASE(port); + } + + if (port != nil && handle != nil) + { + NSHashInsert(port->handles, (void*)handle); + [handle addPort: port]; + } + + [tcpPortLock unlock]; + return port; +} + ++ (GSTcpPort*) portWithNumber: (gsu16)number + onHost: (NSHost*)host + beforeDate: (NSDate*)limit +{ + unsigned i; + GSTcpPort *port = nil; + NSHost *thisHost = [NSHost currentHost]; + NSArray *addresses; + NSMapTable *thePorts; + + if (host == nil) + { + host = thisHost; + } + addresses = [host addresses]; + if ([addresses count] == 0) + { + NSLog(@"attempt to get port on host with no IP address"); + return nil; + } + + [tcpPortLock lock]; + + memset(&dummyPort->addr, '\0', sizeof(dummyPort->addr)); + dummyPort->addr.sin_family = AF_INET; + dummyPort->addr.sin_port = GSSwapHostI16ToBig(number); + + /* + * Get the map table of ports with the specified number. + */ + thePorts = (NSMapTable*)NSMapGet(tcpPortMap, + (void*)(gsaddr)dummyPort->addr.sin_port); + + if (thePorts) + { + /* + * Check to see if we have a port for any one of the hosts IP addresses. + */ + for (i = 0; port == nil && i < [addresses count]; i++) + { + const char *a = [[addresses objectAtIndex: i] cString]; + +#ifndef HAVE_INET_ATON + dummyPort->sin_addr.s_addr = inet_addr(a); +#else + if (inet_aton(a, &dummyPort->addr.sin_addr) == 0) + { + NSLog(@"attempt to get port on host with bad address - '%s'", a); + continue; + } +#endif + port = (GSTcpPort*)NSMapGet(thePorts, + (void*)(gsaddr)dummyPort->addr.sin_addr.s_addr); + if (port != nil) + { + break; + } + } + } + + + if (port == nil) + { + if (host == thisHost) + { + int status = 1; + int desc; + + port = (GSTcpPort*)NSAllocateObject(self,0,NSDefaultMallocZone()); + port->listener = -1; + port->handles = + NSCreateHashTable(NSObjectHashCallBacks, 0); + + port->addr.sin_addr.s_addr = GSSwapHostI32ToBig(INADDR_ANY); + + if ((desc = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) + { + NSLog(@"unable to create socket - %s", strerror(errno)); + DESTROY(port); + } + else if (setsockopt(desc, SOL_SOCKET, SO_REUSEADDR, (char *)&status, + sizeof(status)) < 0) + { + (void) close(desc); + NSLog(@"unable to set reuse on socket - %s", strerror(errno)); + DESTROY(port); + } + else if (bind(desc, (struct sockaddr *)&port->addr, + sizeof(port->addr)) < 0) + { + NSLog(@"unable to bind to port %s:%d - %s", + inet_ntoa(port->addr.sin_addr), number, strerror(errno)); + (void) close(desc); + DESTROY(port); + } + else if (listen(desc, 5) < 0) + { + NSLog(@"unable to listen on port - %s", strerror(errno)); + (void) close(desc); + DESTROY(port); + } + else if (getsockname(desc, (struct sockaddr*)&port->addr, &i) < 0) + { + NSLog(@"unable to get socket name - %s", strerror(errno)); + (void) close(desc); + DESTROY(port); + } + else + { + port->listener = desc; + port->myLock = [NSRecursiveLock new]; + + /* + * Ok - now add the port for all the IP addresses it listens on. + */ + for (i = 0; i < [addresses count]; i++) + { + const char *a = [[addresses objectAtIndex: i] cString]; + gsaddr val; + +#ifndef HAVE_INET_ATON + dummyPort->addr.sin_addr.s_addr = inet_addr(a); +#else + if (inet_aton(a, &dummyPort->addr.sin_addr) == 0) + { + continue; + } +#endif + val = (gsaddr)dummyPort->addr.sin_addr.s_addr; + + if (thePorts == 0) + { + /* + * No known ports within this port number - + * create the map table to add the new port to. + */ + thePorts = NSCreateMapTable(NSIntMapKeyCallBacks, + NSNonOwnedPointerMapValueCallBacks, 0); + NSMapInsert(tcpPortMap, + (void*)(gsaddr)port->addr.sin_port, + (void*)thePorts); + } + NSMapInsert(thePorts, (void*)val, (void*)port); + } + } + } + else if (number != 0) /* Can't connect to port zero */ + { + for (i = 0; port == nil && i < [addresses count]; i++) + { + int desc; + const char *a = [[addresses objectAtIndex: i] cString]; + + port = (GSTcpPort*)NSAllocateObject(self,0,NSDefaultMallocZone()); + port->listener = -1; + +#ifndef HAVE_INET_ATON + port->addr.sin_addr.s_addr = inet_addr(a); +#else + if (inet_aton(a, &port->addr.sin_addr) == 0) + { + NSLog(@"opening port on host with bad address - '%s'", a); + continue; + } +#endif + + if ((desc = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) + { + NSLog(@"unable to create socket - %s", strerror(errno)); + DESTROY(port); + } + else if (connect(desc, (struct sockaddr*)&port->addr, + sizeof(port->addr)) < 0) + { + NSLog(@"unable to make connection to %s:%d - %s", a, + GSSwapBigI16ToHost(port->addr.sin_port), strerror(errno)); + DESTROY(port); + } + else + { + GSTcpHandle *handle; + + port->myLock = [NSRecursiveLock new]; + port->handles = + NSCreateHashTable(NSObjectHashCallBacks, 0); + handle = [GSTcpHandle handleWithDescriptor: desc]; + NSHashInsert(port->handles, (void*)handle); + if (thePorts == 0) + { + /* + * No known ports within this port number - + * create the map table to add the new port to. + */ + thePorts = NSCreateMapTable(NSIntMapKeyCallBacks, + NSNonOwnedPointerMapValueCallBacks, 0); + NSMapInsert(tcpPortMap, + (void*)(gsaddr)port->addr.sin_port, + (void*)thePorts); + } + NSMapInsert(thePorts, + (void*)(gsaddr)port->addr.sin_addr.s_addr, (void*)port); + } + } + } + AUTORELEASE(port); + } + + [tcpPortLock unlock]; + return port; +} + +- (void) addHandle: (GSTcpHandle*)h +{ + [myLock lock]; + NSHashInsert(handles, (void*)h); + [myLock unlock]; +} + +- (id) copyWithZone: (NSZone*)zone +{ + return RETAIN(self); +} + +- (void) gcFinalize +{ + [self invalidate]; +} + +- (unsigned) hash +{ + return (unsigned)(addr.sin_addr.s_addr ^ addr.sin_port); +} + +- (void) invalidate +{ + [myLock lock]; + + if ([self isValid]) + { + NSMapTable *thePorts; + NSArray *handleArray; + unsigned i; + + [tcpPortLock lock]; + thePorts = NSMapGet(tcpPortMap, (void*)(gsaddr)addr.sin_port); + if (thePorts) + { + gsaddr val; + + if (listener == -1) + { + val = (gsaddr)addr.sin_addr.s_addr; + NSMapRemove(thePorts, (void*)val); + } + else + { + unsigned i; + NSArray *addresses = [[NSHost currentHost] addresses]; + + for (i = 0; i < [addresses count]; i++) + { + const char *a = [[addresses objectAtIndex: i] cString]; + +#ifndef HAVE_INET_ATON + addr,sin_addr.s_addr = inet_addr(a); +#else + if (inet_aton(a, &addr.sin_addr) == 0) + { + continue; + } +#endif + val = (gsaddr)addr.sin_addr.s_addr; + NSMapRemove(thePorts, (void*)val); + } + } + } + [tcpPortLock unlock]; + + if (listener >= 0) + { + (void)close(listener); + listener = -1; + } + + handleArray = NSAllHashTableObjects(handles); + i = [handleArray count]; + while (i > 0) + { + GSTcpHandle *handle = [handleArray objectAtIndex: i]; + + [handle removePort: self]; + } + NSFreeHashTable(handles); + + [super invalidate]; + } + [myLock unlock]; + RELEASE(myLock); +} + +- (BOOL) isEqual: (id)anObject +{ + if (anObject == self) + return YES; + if ([anObject class] == [self class]) + { + GSTcpPort *o = (GSTcpPort*)anObject; + + if (o->addr.sin_port == addr.sin_port && + o->addr.sin_addr.s_addr == addr.sin_addr.s_addr) + return YES; + } + return NO; +} + +- (void) release +{ + if ([self retainCount] == 1) + { + [super retain]; + [self gcFinalize]; + [super release]; + } + [super release]; +} + +- (void) removeHandle: (GSTcpHandle*)h +{ + [myLock lock]; + NSHashRemove(handles, (void*)h); + [myLock unlock]; +} + +@end + + + @interface TcpInPort (Private) - (int) _port_socket; - (struct sockaddr_in*) _listeningSockaddr; diff --git a/Testing/client.m b/Testing/client.m index 7fa5663a4..3c5034365 100644 --- a/Testing/client.m +++ b/Testing/client.m @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -11,7 +12,10 @@ #include #include "server.h" -int main(int argc, char *argv[]) +@class TcpInPort; +@class PortDecoder; + +int main (int argc, char *argv[]) { id a; id p; @@ -36,13 +40,18 @@ int main(int argc, char *argv[]) const char *type; NSAutoreleasePool *arp = [NSAutoreleasePool new]; +GSDebugAllocationActive(YES); + [NSConnection setDebug: 10]; + [NSDistantObject setDebug: 10]; + [TcpInPort setDebug: 10]; + [Coder setDebugging:YES]; [BinaryCStream setDebugging:YES]; #if NeXT_runtime [NSDistantObject setProtocolForProxies:@protocol(AllProxies)]; #endif - +printf("oneway %d\n", _F_ONEWAY); if (argc > 1) { if (argc > 2) @@ -60,12 +69,16 @@ int main(int argc, char *argv[]) [c setReplyTimeout:180.0]; localObj = [[NSObject alloc] init]; [p outputStats:localObj]; +fprintf(stderr, "XXXXXXXXXXXXXXXXA %d\n", GSDebugAllocationCount([PortDecoder class])); + [p getLong:&i]; +fprintf(stderr,"XXXXXXXXXXXXXXXXB %d\n", GSDebugAllocationCount([PortDecoder class])); [p getLong:&i]; [p outputStats:localObj]; +fprintf(stderr,"XXXXXXXXXXXXXXXXC %d\n", GSDebugAllocationCount([PortDecoder class])); type = [c typeForSelector:sel_get_any_uid("name") remoteTarget:[p targetForProxy]]; +printf("XXXXXXXXXXXXXXXXD %d\n", GSDebugAllocationCount([PortDecoder class])); printf(">>type = %s\n", type); - printf(">>list proxy's hash is 0x%x\n", (unsigned)[p hash]); printf(">>list proxy's self is 0x%x = 0x%x\n", @@ -149,9 +162,11 @@ int main(int argc, char *argv[]) id remote_peer_obj = [p objectAt:j]; printf("triangle %d object proxy's hash is 0x%x\n", j, (unsigned)[remote_peer_obj hash]); +#if 0 /* xxx look at this again after we use release/retain everywhere */ if ([remote_peer_obj isProxy]) [remote_peer_obj release]; +#endif remote_peer_obj = [p objectAt:j]; printf("repeated triangle %d object proxy's hash is 0x%x\n", j, (unsigned)[remote_peer_obj hash]); @@ -170,9 +185,14 @@ int main(int argc, char *argv[]) printf("%s - %s\n", [k cString], [[v description] cString]); } + [arp release]; + arp = [NSAutoreleasePool new]; + printf("%d\n", [c retainCount]); + printf("%s\n", [[[c statistics] description] cString]); +// printf("%s\n", GSDebugAllocationList(YES)); + [NSRunLoop runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 20 * 60]]; [c invalidate]; - [arp release]; exit(0); } diff --git a/Version b/Version index 186f8cdef..ef82a0ae5 100644 --- a/Version +++ b/Version @@ -7,12 +7,12 @@ GCC_VERSION=2.8.0 # The version number of this release. MAJOR_VERSION=0 MINOR_VERSION=5 -SUBMINOR_VERSION=0 +SUBMINOR_VERSION=5 GNUSTEP_BASE_VERSION=${MAJOR_VERSION}.${MINOR_VERSION}.${SUBMINOR_VERSION} VERSION=${GNUSTEP_BASE_VERSION} GNUSTEP_BASE_FTP_MACHINE=ftp.gnu.org -GNUSTEP_BASE_FTP_DIRECTORY=pub/gnu +GNUSTEP_BASE_FTP_DIRECTORY=pub/gnu/gstep GNUSTEP_BASE_SNAP_FTP_MACHINE=alpha.gnu.org GNUSTEP_BASE_SNAP_FTP_DIRECTORY=gnu/gnustep