]> err.no Git - sope/commitdiff
bringing libFoundation-1.0.75 into the main branch
authorhelge <helge@e4a50df8-12e2-0310-a44c-efbce7f8a7e3>
Fri, 3 Jun 2005 14:21:09 +0000 (14:21 +0000)
committerhelge <helge@e4a50df8-12e2-0310-a44c-efbce7f8a7e3>
Fri, 3 Jun 2005 14:21:09 +0000 (14:21 +0000)
git-svn-id: http://svn.opengroupware.org/SOPE/trunk@830 e4a50df8-12e2-0310-a44c-efbce7f8a7e3

505 files changed:
libFoundation/ANNOUNCE [new file with mode: 0644]
libFoundation/AUTHORS [new file with mode: 0644]
libFoundation/COPYING [new file with mode: 0644]
libFoundation/ChangeLog [new file with mode: 0644]
libFoundation/Foundation/DefaultScannerHandler.m [new file with mode: 0644]
libFoundation/Foundation/FFCallInvocation.h [new file with mode: 0644]
libFoundation/Foundation/FFCallInvocation.m [new file with mode: 0644]
libFoundation/Foundation/FormatScanner.m [new file with mode: 0644]
libFoundation/Foundation/Foundation.h [new file with mode: 0644]
libFoundation/Foundation/GCArray.m [new file with mode: 0644]
libFoundation/Foundation/GCDictionary.m [new file with mode: 0644]
libFoundation/Foundation/GCObject.m [new file with mode: 0644]
libFoundation/Foundation/GNUmakefile [new file with mode: 0644]
libFoundation/Foundation/GNUmakefile.alone [new file with mode: 0644]
libFoundation/Foundation/GNUmakefile.postamble [new file with mode: 0644]
libFoundation/Foundation/GarbageCollector.m [new file with mode: 0644]
libFoundation/Foundation/NSAccount.h [new file with mode: 0644]
libFoundation/Foundation/NSAccount.m [new file with mode: 0644]
libFoundation/Foundation/NSAllocDebugZone.h [new file with mode: 0644]
libFoundation/Foundation/NSAllocDebugZone.m [new file with mode: 0644]
libFoundation/Foundation/NSArchiver.h [new file with mode: 0644]
libFoundation/Foundation/NSArchiver.m [new file with mode: 0644]
libFoundation/Foundation/NSArray.h [new file with mode: 0644]
libFoundation/Foundation/NSArray.m [new file with mode: 0644]
libFoundation/Foundation/NSAttributedString.h [new file with mode: 0644]
libFoundation/Foundation/NSAttributedString.m [new file with mode: 0644]
libFoundation/Foundation/NSAutoreleasePool.h [new file with mode: 0644]
libFoundation/Foundation/NSAutoreleasePool.m [new file with mode: 0644]
libFoundation/Foundation/NSBundle.h [new file with mode: 0644]
libFoundation/Foundation/NSBundle.m [new file with mode: 0644]
libFoundation/Foundation/NSByteOrder.h [new file with mode: 0644]
libFoundation/Foundation/NSCalendarDate.h [new file with mode: 0644]
libFoundation/Foundation/NSCalendarDate.m [new file with mode: 0644]
libFoundation/Foundation/NSCalendarDateScanf.h [new file with mode: 0644]
libFoundation/Foundation/NSCalendarDateScanf.m [new file with mode: 0644]
libFoundation/Foundation/NSCalendarDateScannerHandler.h [new file with mode: 0644]
libFoundation/Foundation/NSCalendarDateScannerHandler.m [new file with mode: 0644]
libFoundation/Foundation/NSCharacterSet.h [new file with mode: 0644]
libFoundation/Foundation/NSCharacterSet.m [new file with mode: 0644]
libFoundation/Foundation/NSClassDescription.h [new file with mode: 0644]
libFoundation/Foundation/NSClassDescription.m [new file with mode: 0644]
libFoundation/Foundation/NSClassicException.h [new file with mode: 0644]
libFoundation/Foundation/NSCoder.h [new file with mode: 0644]
libFoundation/Foundation/NSCoder.m [new file with mode: 0644]
libFoundation/Foundation/NSComparisonPredicate.h [new file with mode: 0644]
libFoundation/Foundation/NSComparisonPredicate.m [new file with mode: 0644]
libFoundation/Foundation/NSCompoundPredicate.h [new file with mode: 0644]
libFoundation/Foundation/NSCompoundPredicate.m [new file with mode: 0644]
libFoundation/Foundation/NSConcreteArray.h [new file with mode: 0644]
libFoundation/Foundation/NSConcreteArray.m [new file with mode: 0644]
libFoundation/Foundation/NSConcreteCharacterSet.h [new file with mode: 0644]
libFoundation/Foundation/NSConcreteCharacterSet.m [new file with mode: 0644]
libFoundation/Foundation/NSConcreteData.h [new file with mode: 0644]
libFoundation/Foundation/NSConcreteData.m [new file with mode: 0644]
libFoundation/Foundation/NSConcreteDate.h [new file with mode: 0644]
libFoundation/Foundation/NSConcreteDate.m [new file with mode: 0644]
libFoundation/Foundation/NSConcreteDictionary.h [new file with mode: 0644]
libFoundation/Foundation/NSConcreteDictionary.m [new file with mode: 0644]
libFoundation/Foundation/NSConcreteFileHandle.h [new file with mode: 0644]
libFoundation/Foundation/NSConcreteFileHandle.m [new file with mode: 0644]
libFoundation/Foundation/NSConcreteMutableDictionary.m [new file with mode: 0644]
libFoundation/Foundation/NSConcreteMutableString.m [new file with mode: 0644]
libFoundation/Foundation/NSConcreteNumber.h [new file with mode: 0644]
libFoundation/Foundation/NSConcreteNumber.m [new file with mode: 0644]
libFoundation/Foundation/NSConcreteNumber.m.sh [new file with mode: 0755]
libFoundation/Foundation/NSConcreteScanner.h [new file with mode: 0644]
libFoundation/Foundation/NSConcreteScanner.m [new file with mode: 0644]
libFoundation/Foundation/NSConcreteSet.h [new file with mode: 0644]
libFoundation/Foundation/NSConcreteSet.m [new file with mode: 0644]
libFoundation/Foundation/NSConcreteString.h [new file with mode: 0644]
libFoundation/Foundation/NSConcreteString.m [new file with mode: 0644]
libFoundation/Foundation/NSConcreteTimeZone.h [new file with mode: 0644]
libFoundation/Foundation/NSConcreteTimeZone.m [new file with mode: 0644]
libFoundation/Foundation/NSConcreteTimeZoneDetail.h [new file with mode: 0644]
libFoundation/Foundation/NSConcreteTimeZoneDetail.m [new file with mode: 0644]
libFoundation/Foundation/NSConcreteUTF16String.m [new file with mode: 0644]
libFoundation/Foundation/NSConcreteUnixTask.h [new file with mode: 0644]
libFoundation/Foundation/NSConcreteUnixTask.m [new file with mode: 0644]
libFoundation/Foundation/NSConcreteValue.h [new file with mode: 0644]
libFoundation/Foundation/NSConcreteValue.m [new file with mode: 0644]
libFoundation/Foundation/NSConcreteWindowsFileHandle.h [new file with mode: 0644]
libFoundation/Foundation/NSConcreteWindowsFileHandle.m [new file with mode: 0644]
libFoundation/Foundation/NSConcreteWindowsTask.h [new file with mode: 0644]
libFoundation/Foundation/NSConcreteWindowsTask.m [new file with mode: 0644]
libFoundation/Foundation/NSConnection.h [new file with mode: 0644]
libFoundation/Foundation/NSConnection.m [new file with mode: 0644]
libFoundation/Foundation/NSData.h [new file with mode: 0644]
libFoundation/Foundation/NSData.m [new file with mode: 0644]
libFoundation/Foundation/NSDate.h [new file with mode: 0644]
libFoundation/Foundation/NSDate.m [new file with mode: 0644]
libFoundation/Foundation/NSDateFormatter.h [new file with mode: 0644]
libFoundation/Foundation/NSDateFormatter.m [new file with mode: 0644]
libFoundation/Foundation/NSDebug.h [new file with mode: 0644]
libFoundation/Foundation/NSDebug.m [new file with mode: 0644]
libFoundation/Foundation/NSDecimal.h [new file with mode: 0644]
libFoundation/Foundation/NSDecimal.m [new file with mode: 0644]
libFoundation/Foundation/NSDecimalNumber.h [new file with mode: 0644]
libFoundation/Foundation/NSDecimalNumber.m [new file with mode: 0644]
libFoundation/Foundation/NSDefaultZone.h [new file with mode: 0644]
libFoundation/Foundation/NSDefaultZone.m [new file with mode: 0644]
libFoundation/Foundation/NSDictionary.h [new file with mode: 0644]
libFoundation/Foundation/NSDictionary.m [new file with mode: 0644]
libFoundation/Foundation/NSDistantObject.h [new file with mode: 0644]
libFoundation/Foundation/NSDistributedLock.h [new file with mode: 0644]
libFoundation/Foundation/NSDistributedLock.m [new file with mode: 0644]
libFoundation/Foundation/NSDistributedNotificationCenter.h [new file with mode: 0644]
libFoundation/Foundation/NSDistributedNotificationCenter.m [new file with mode: 0644]
libFoundation/Foundation/NSEnumerator.h [new file with mode: 0644]
libFoundation/Foundation/NSEnumerator.m [new file with mode: 0644]
libFoundation/Foundation/NSError.h [new file with mode: 0644]
libFoundation/Foundation/NSError.m [new file with mode: 0644]
libFoundation/Foundation/NSException.m [new file with mode: 0644]
libFoundation/Foundation/NSExceptionWithoutNested.h [new file with mode: 0644]
libFoundation/Foundation/NSExpression.h [new file with mode: 0644]
libFoundation/Foundation/NSExpression.m [new file with mode: 0644]
libFoundation/Foundation/NSFileHandle.h [new file with mode: 0644]
libFoundation/Foundation/NSFileHandle.m [new file with mode: 0644]
libFoundation/Foundation/NSFileManager.h [new file with mode: 0644]
libFoundation/Foundation/NSFileManager.m [new file with mode: 0644]
libFoundation/Foundation/NSFileURLHandle.h [new file with mode: 0644]
libFoundation/Foundation/NSFileURLHandle.m [new file with mode: 0644]
libFoundation/Foundation/NSFormatter.h [new file with mode: 0644]
libFoundation/Foundation/NSFormatter.m [new file with mode: 0644]
libFoundation/Foundation/NSFrameInvocation.h [new file with mode: 0644]
libFoundation/Foundation/NSFrameInvocation.m [new file with mode: 0644]
libFoundation/Foundation/NSFuncallException.h [new file with mode: 0644]
libFoundation/Foundation/NSGeometry.h [new file with mode: 0644]
libFoundation/Foundation/NSGeometry.m [new file with mode: 0644]
libFoundation/Foundation/NSHashMap.m [new file with mode: 0644]
libFoundation/Foundation/NSHashTable.h [new file with mode: 0644]
libFoundation/Foundation/NSHost.h [new file with mode: 0644]
libFoundation/Foundation/NSHost.m [new file with mode: 0644]
libFoundation/Foundation/NSInputStream.m [new file with mode: 0644]
libFoundation/Foundation/NSInvocation.h [new file with mode: 0644]
libFoundation/Foundation/NSInvocation.m [new file with mode: 0644]
libFoundation/Foundation/NSKeyValueCoding.h [new file with mode: 0644]
libFoundation/Foundation/NSLock.h [new file with mode: 0644]
libFoundation/Foundation/NSLock.m [new file with mode: 0644]
libFoundation/Foundation/NSMapTable.h [new file with mode: 0644]
libFoundation/Foundation/NSMappedData.h [new file with mode: 0644]
libFoundation/Foundation/NSMappedData.m [new file with mode: 0644]
libFoundation/Foundation/NSMessagePort.m [new file with mode: 0644]
libFoundation/Foundation/NSMethodSignature.h [new file with mode: 0644]
libFoundation/Foundation/NSMethodSignature.m [new file with mode: 0644]
libFoundation/Foundation/NSNotification.h [new file with mode: 0644]
libFoundation/Foundation/NSNotification.m [new file with mode: 0644]
libFoundation/Foundation/NSNotificationCenter.m [new file with mode: 0644]
libFoundation/Foundation/NSNotificationQueue.h [new file with mode: 0644]
libFoundation/Foundation/NSNotificationQueue.m [new file with mode: 0644]
libFoundation/Foundation/NSNull.h [new file with mode: 0644]
libFoundation/Foundation/NSNull.m [new file with mode: 0644]
libFoundation/Foundation/NSNumber.m [new file with mode: 0644]
libFoundation/Foundation/NSNumberFormatter.h [new file with mode: 0644]
libFoundation/Foundation/NSNumberFormatter.m [new file with mode: 0644]
libFoundation/Foundation/NSObjCRuntime.h [new file with mode: 0644]
libFoundation/Foundation/NSObjCRuntime.m [new file with mode: 0644]
libFoundation/Foundation/NSObject+PropLists.h [new file with mode: 0644]
libFoundation/Foundation/NSObject.h.in [new file with mode: 0644]
libFoundation/Foundation/NSObject.m [new file with mode: 0644]
libFoundation/Foundation/NSObjectAllocation.m [new file with mode: 0644]
libFoundation/Foundation/NSObjectInvocation.h [new file with mode: 0644]
libFoundation/Foundation/NSObjectInvocation.m [new file with mode: 0644]
libFoundation/Foundation/NSOutputStream.m [new file with mode: 0644]
libFoundation/Foundation/NSPathUtilities.h [new file with mode: 0644]
libFoundation/Foundation/NSPathUtilities.m [new file with mode: 0644]
libFoundation/Foundation/NSPipe.m [new file with mode: 0644]
libFoundation/Foundation/NSPort.h [new file with mode: 0644]
libFoundation/Foundation/NSPort.m [new file with mode: 0644]
libFoundation/Foundation/NSPortCoder.h [new file with mode: 0644]
libFoundation/Foundation/NSPortCoder.m [new file with mode: 0644]
libFoundation/Foundation/NSPortMessage.h [new file with mode: 0644]
libFoundation/Foundation/NSPortMessage.m [new file with mode: 0644]
libFoundation/Foundation/NSPortNameServer.h [new file with mode: 0644]
libFoundation/Foundation/NSPortNameServer.m [new file with mode: 0644]
libFoundation/Foundation/NSPosixFileDescriptor.h [new file with mode: 0644]
libFoundation/Foundation/NSPosixFileDescriptor.m [new file with mode: 0644]
libFoundation/Foundation/NSPredicate.h [new file with mode: 0644]
libFoundation/Foundation/NSPredicate.m [new file with mode: 0644]
libFoundation/Foundation/NSPredicateParser.m [new file with mode: 0644]
libFoundation/Foundation/NSProcessInfo.h [new file with mode: 0644]
libFoundation/Foundation/NSProcessInfo.m [new file with mode: 0644]
libFoundation/Foundation/NSProxy.h [new file with mode: 0644]
libFoundation/Foundation/NSProxy.m [new file with mode: 0644]
libFoundation/Foundation/NSRange.h [new file with mode: 0644]
libFoundation/Foundation/NSRange.m [new file with mode: 0644]
libFoundation/Foundation/NSRunLoop.h [new file with mode: 0644]
libFoundation/Foundation/NSRunLoop.m [new file with mode: 0644]
libFoundation/Foundation/NSScanner.h [new file with mode: 0644]
libFoundation/Foundation/NSScanner.m [new file with mode: 0644]
libFoundation/Foundation/NSScriptKeyValueCoding.h [new file with mode: 0644]
libFoundation/Foundation/NSSerialization.h [new file with mode: 0644]
libFoundation/Foundation/NSSerialization.m [new file with mode: 0644]
libFoundation/Foundation/NSSet.h [new file with mode: 0644]
libFoundation/Foundation/NSSet.m [new file with mode: 0644]
libFoundation/Foundation/NSSocketPort.m [new file with mode: 0644]
libFoundation/Foundation/NSSortDescriptor.h [new file with mode: 0644]
libFoundation/Foundation/NSSortDescriptor.m [new file with mode: 0644]
libFoundation/Foundation/NSStream.h [new file with mode: 0644]
libFoundation/Foundation/NSStream.m [new file with mode: 0644]
libFoundation/Foundation/NSString+StringEncoding.m [new file with mode: 0644]
libFoundation/Foundation/NSString.h [new file with mode: 0644]
libFoundation/Foundation/NSString.m [new file with mode: 0644]
libFoundation/Foundation/NSStringScanner.m [new file with mode: 0644]
libFoundation/Foundation/NSTask.h [new file with mode: 0644]
libFoundation/Foundation/NSTask.m [new file with mode: 0644]
libFoundation/Foundation/NSThread.h [new file with mode: 0644]
libFoundation/Foundation/NSThread.m [new file with mode: 0644]
libFoundation/Foundation/NSTimeZone.h [new file with mode: 0644]
libFoundation/Foundation/NSTimeZone.m [new file with mode: 0644]
libFoundation/Foundation/NSTimer.h [new file with mode: 0644]
libFoundation/Foundation/NSTimer.m [new file with mode: 0644]
libFoundation/Foundation/NSURL.h [new file with mode: 0644]
libFoundation/Foundation/NSURL.m [new file with mode: 0644]
libFoundation/Foundation/NSURLHandle.h [new file with mode: 0644]
libFoundation/Foundation/NSURLHandle.m [new file with mode: 0644]
libFoundation/Foundation/NSUndoManager.h [new file with mode: 0644]
libFoundation/Foundation/NSUndoManager.m [new file with mode: 0644]
libFoundation/Foundation/NSUserDefaults.h [new file with mode: 0644]
libFoundation/Foundation/NSUserDefaults.m [new file with mode: 0644]
libFoundation/Foundation/NSUtilities.h [new file with mode: 0644]
libFoundation/Foundation/NSUtilities.m [new file with mode: 0644]
libFoundation/Foundation/NSVMPage.m [new file with mode: 0644]
libFoundation/Foundation/NSValue.h [new file with mode: 0644]
libFoundation/Foundation/NSValue.m [new file with mode: 0644]
libFoundation/Foundation/NSZone.h [new file with mode: 0644]
libFoundation/Foundation/NSZone.m [new file with mode: 0644]
libFoundation/Foundation/PrintfFormatScanner.m [new file with mode: 0644]
libFoundation/Foundation/PrintfScannerHandler.m [new file with mode: 0644]
libFoundation/Foundation/PrivateThreadData.h [new file with mode: 0644]
libFoundation/Foundation/PrivateThreadData.m [new file with mode: 0644]
libFoundation/Foundation/PropertyListParser.h [new file with mode: 0644]
libFoundation/Foundation/PropertyListParser.m [new file with mode: 0644]
libFoundation/Foundation/PropertyListParserUnichar.m [new file with mode: 0644]
libFoundation/Foundation/StackZone.h [new file with mode: 0644]
libFoundation/Foundation/StackZone.m [new file with mode: 0644]
libFoundation/Foundation/UnixSignalHandler.h [new file with mode: 0644]
libFoundation/Foundation/UnixSignalHandler.m [new file with mode: 0644]
libFoundation/Foundation/behavior.m [new file with mode: 0644]
libFoundation/Foundation/byte_order.h [new file with mode: 0644]
libFoundation/Foundation/common.h [new file with mode: 0644]
libFoundation/Foundation/common.m [new file with mode: 0644]
libFoundation/Foundation/cvtutf.c [new file with mode: 0644]
libFoundation/Foundation/cvtutf.h [new file with mode: 0644]
libFoundation/Foundation/encoding.m [new file with mode: 0644]
libFoundation/Foundation/err.m [new file with mode: 0644]
libFoundation/Foundation/exceptions/EncodingFormatExceptions.h [new file with mode: 0644]
libFoundation/Foundation/exceptions/EncodingFormatExceptions.m [new file with mode: 0644]
libFoundation/Foundation/exceptions/FoundationException.h [new file with mode: 0644]
libFoundation/Foundation/exceptions/FoundationException.m [new file with mode: 0644]
libFoundation/Foundation/exceptions/FoundationExceptions.h [new file with mode: 0644]
libFoundation/Foundation/exceptions/GeneralExceptions.h [new file with mode: 0644]
libFoundation/Foundation/exceptions/GeneralExceptions.m [new file with mode: 0644]
libFoundation/Foundation/exceptions/NSCoderExceptions.h [new file with mode: 0644]
libFoundation/Foundation/exceptions/NSCoderExceptions.m [new file with mode: 0644]
libFoundation/Foundation/exceptions/NSFileHandleExceptions.h [new file with mode: 0644]
libFoundation/Foundation/exceptions/NSFileHandleExceptions.m [new file with mode: 0644]
libFoundation/Foundation/exceptions/NSInvocationExceptions.h [new file with mode: 0644]
libFoundation/Foundation/exceptions/NSInvocationExceptions.m [new file with mode: 0644]
libFoundation/Foundation/exceptions/NSValueExceptions.h [new file with mode: 0644]
libFoundation/Foundation/exceptions/NSValueExceptions.m [new file with mode: 0644]
libFoundation/Foundation/exceptions/StringExceptions.h [new file with mode: 0644]
libFoundation/Foundation/exceptions/StringExceptions.m [new file with mode: 0644]
libFoundation/Foundation/fhs.make [new file with mode: 0644]
libFoundation/Foundation/lfmemory.h.in [new file with mode: 0644]
libFoundation/Foundation/libFoundation.def [new file with mode: 0644]
libFoundation/Foundation/libFoundation.make.in [new file with mode: 0644]
libFoundation/Foundation/load.m [new file with mode: 0644]
libFoundation/Foundation/misc.m [new file with mode: 0644]
libFoundation/Foundation/objc-runtime.m [new file with mode: 0644]
libFoundation/Foundation/realpath.m [new file with mode: 0644]
libFoundation/Foundation/scanFloat.def [new file with mode: 0644]
libFoundation/Foundation/scanInt.def [new file with mode: 0644]
libFoundation/Foundation/thr-mach.m [new file with mode: 0644]
libFoundation/GNUmakefile [new file with mode: 0644]
libFoundation/GNUmakefile.alone [new file with mode: 0644]
libFoundation/INSTALL.txt [new file with mode: 0644]
libFoundation/NEWS [new file with mode: 0644]
libFoundation/README [new file with mode: 0644]
libFoundation/README.first [new file with mode: 0644]
libFoundation/README.gc [new file with mode: 0644]
libFoundation/README.mingw32 [new file with mode: 0644]
libFoundation/README.osx [new file with mode: 0644]
libFoundation/README.sparc [new file with mode: 0644]
libFoundation/Resources/CharacterSets/alphanumericCharacterSet.bitmap [new file with mode: 0644]
libFoundation/Resources/CharacterSets/controlCharacterSet.bitmap [new file with mode: 0644]
libFoundation/Resources/CharacterSets/decimalDigitCharacterSet.bitmap [new file with mode: 0644]
libFoundation/Resources/CharacterSets/decomposableCharacterSet.bitmap [new file with mode: 0644]
libFoundation/Resources/CharacterSets/emptyCharacterSet.bitmap [new file with mode: 0644]
libFoundation/Resources/CharacterSets/illegalCharacterSet.bitmap [new file with mode: 0644]
libFoundation/Resources/CharacterSets/letterCharacterSet.bitmap [new file with mode: 0644]
libFoundation/Resources/CharacterSets/lowercaseLetterCharacterSet.bitmap [new file with mode: 0644]
libFoundation/Resources/CharacterSets/nonBaseCharacterSet.bitmap [new file with mode: 0644]
libFoundation/Resources/CharacterSets/punctuationCharacterSet.bitmap [new file with mode: 0644]
libFoundation/Resources/CharacterSets/uppercaseLetterCharacterSet.bitmap [new file with mode: 0644]
libFoundation/Resources/CharacterSets/whitespaceAndNewlineCharacterSet.bitmap [new file with mode: 0644]
libFoundation/Resources/CharacterSets/whitespaceCharacterSet.bitmap [new file with mode: 0644]
libFoundation/Resources/Defaults/English.plist [new file with mode: 0644]
libFoundation/Resources/Defaults/French.plist [new file with mode: 0644]
libFoundation/Resources/Defaults/German.plist [new file with mode: 0644]
libFoundation/Resources/Defaults/NSGlobalDomain.plist [new file with mode: 0644]
libFoundation/Resources/Defaults/Romanian.plist [new file with mode: 0644]
libFoundation/Resources/GNUmakefile [new file with mode: 0644]
libFoundation/Resources/GNUmakefile.alone [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Asia/Calcutta [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Australia/NSW [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Australia/North [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Australia/Queensland [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Australia/South [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Australia/Tasmania [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Australia/Victoria [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Australia/West [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/CET [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/CLST [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/CST6CDT [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Canada/Atlantic [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Canada/Central [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Canada/East-Saskatchewan [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Canada/Eastern [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Canada/Mountain [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Canada/Newfoundland [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Canada/Pacific [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Canada/Yukon [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/EET [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/EST [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/EST5EDT [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Europe/Berlin [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Europe/Brussels [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Europe/Paris [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GB-Eire [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+0_30 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+1 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+10 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+10_30 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+11 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+11_30 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+12 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+13 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+14 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+1_30 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+2 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+2_30 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+3 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+3_30 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+4 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+4_30 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+5 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+5_30 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+6 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+6_30 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+7 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+7_30 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+8 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+8_30 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+9 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT+9_30 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT-0_30 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT-1 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT-10 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT-10_30 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT-11 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT-11_30 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT-12 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT-1_30 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT-2 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT-2_30 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT-3 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT-3_30 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT-4 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT-4_30 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT-5 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT-5_30 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT-6 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT-6_30 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT-7 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT-7_30 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT-8 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT-8_30 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT-9 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/GMT-9_30 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Greenwich [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/HST [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Iceland [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Japan [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/MET [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/MST [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/MST7MDT [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/NZ [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/PST8PDT [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Poland [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/RegionsDictionary [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/SAST [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/SGT [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Singapore [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/SystemV/AST4 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/SystemV/AST4ADT [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/SystemV/CST6 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/SystemV/CST6CDT [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/SystemV/EST5 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/SystemV/EST5EDT [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/SystemV/HST10 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/SystemV/MST7 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/SystemV/MST7MDT [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/SystemV/PST8 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/SystemV/PST8PDT [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/SystemV/YST9 [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/SystemV/YST9YDT [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Turkey [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/UCT [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/US/Arizona [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/US/Central [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/US/East-Indiana [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/US/Eastern [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/US/Hawaii [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/US/Mountain [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/US/Pacific [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/US/Pacific-New [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/US/Yukon [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/UTC [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/Universal [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/W-SU [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/WET [new file with mode: 0644]
libFoundation/Resources/TimeZoneInfo/create [new file with mode: 0644]
libFoundation/TODO [new file with mode: 0644]
libFoundation/Version [new file with mode: 0644]
libFoundation/aclocal.m4 [new file with mode: 0644]
libFoundation/config.guess [new file with mode: 0755]
libFoundation/config.h.in [new file with mode: 0644]
libFoundation/config.h.win32 [new file with mode: 0644]
libFoundation/config.mak.in [new file with mode: 0644]
libFoundation/config.mak.win32 [new file with mode: 0644]
libFoundation/config.sub [new file with mode: 0755]
libFoundation/config/alpha/linux-gnu.h [new file with mode: 0644]
libFoundation/config/generic/generic.h [new file with mode: 0644]
libFoundation/config/hppa/hppa.h [new file with mode: 0644]
libFoundation/config/i386/cygwin32.h [new file with mode: 0644]
libFoundation/config/i386/freebsd.h [new file with mode: 0644]
libFoundation/config/i386/gnu.h [new file with mode: 0644]
libFoundation/config/i386/i386.h [new file with mode: 0644]
libFoundation/config/i386/linux-gnu.h [new file with mode: 0644]
libFoundation/config/i386/linux.h [new file with mode: 0644]
libFoundation/config/i386/mingw32.h [new file with mode: 0644]
libFoundation/config/i386/nextstep3.h [new file with mode: 0644]
libFoundation/config/i386/nextstep4.h [new file with mode: 0644]
libFoundation/config/i386/openbsd3.7.h [new file with mode: 0644]
libFoundation/config/i386/solaris2.5.1.h [new file with mode: 0644]
libFoundation/config/i386/solaris2.9.h [new file with mode: 0644]
libFoundation/config/m68k/m68k.h [new file with mode: 0644]
libFoundation/config/m68k/nextstep3.h [new file with mode: 0644]
libFoundation/config/powerpc/powerpc.h [new file with mode: 0644]
libFoundation/config/powerpc64/gnu.h [new file with mode: 0644]
libFoundation/config/powerpc64/linux-gnu.h [new file with mode: 0644]
libFoundation/config/powerpc64/linux.h [new file with mode: 0644]
libFoundation/config/powerpc64/powerpc64.h [new file with mode: 0644]
libFoundation/config/sparc/solaris2.4.h [new file with mode: 0644]
libFoundation/config/sparc/sparc.h [new file with mode: 0644]
libFoundation/configure [new file with mode: 0755]
libFoundation/configure.bat [new file with mode: 0644]
libFoundation/configure.in [new file with mode: 0644]
libFoundation/debian/changelog [new file with mode: 0644]
libFoundation/debian/compat [new file with mode: 0644]
libFoundation/debian/control [new file with mode: 0644]
libFoundation/debian/copyright [new file with mode: 0644]
libFoundation/debian/docs [new file with mode: 0644]
libFoundation/debian/libfoundation-data.install [new file with mode: 0644]
libFoundation/debian/libfoundation-tools.install [new file with mode: 0644]
libFoundation/debian/libfoundation-tools.links [new file with mode: 0644]
libFoundation/debian/libfoundation1.0-dev.install [new file with mode: 0644]
libFoundation/debian/libfoundation1.0.install [new file with mode: 0644]
libFoundation/debian/rules [new file with mode: 0755]
libFoundation/doc/GNUmakefile [new file with mode: 0644]
libFoundation/doc/README [new file with mode: 0644]
libFoundation/doc/libFoundation.texi [new file with mode: 0644]
libFoundation/doc/signature-test.pl [new file with mode: 0644]
libFoundation/examples/Defaults.m [new file with mode: 0644]
libFoundation/examples/GNUmakefile [new file with mode: 0644]
libFoundation/examples/GNUmakefile.alone [new file with mode: 0644]
libFoundation/examples/chkdict.m [new file with mode: 0644]
libFoundation/examples/fhs.make [new file with mode: 0644]
libFoundation/examples/fmls.m [new file with mode: 0644]
libFoundation/examples/fmrm.m [new file with mode: 0644]
libFoundation/examples/printenv.m [new file with mode: 0644]
libFoundation/extensions/DefaultScannerHandler.h [new file with mode: 0644]
libFoundation/extensions/FormatScanner.h [new file with mode: 0644]
libFoundation/extensions/GCArray.h [new file with mode: 0644]
libFoundation/extensions/GCDictionary.h [new file with mode: 0644]
libFoundation/extensions/GCObject.h [new file with mode: 0644]
libFoundation/extensions/GarbageCollector.h [new file with mode: 0644]
libFoundation/extensions/NSException.h [new file with mode: 0644]
libFoundation/extensions/PrintfFormatScanner.h [new file with mode: 0644]
libFoundation/extensions/PrintfScannerHandler.h [new file with mode: 0644]
libFoundation/extensions/encoding.h [new file with mode: 0644]
libFoundation/extensions/exceptions/FoundationException.h [new file with mode: 0644]
libFoundation/extensions/exceptions/GeneralExceptions.h [new file with mode: 0644]
libFoundation/extensions/exceptions/NSCoderExceptions.h [new file with mode: 0644]
libFoundation/extensions/objc-runtime.h [new file with mode: 0644]
libFoundation/extensions/support.h [new file with mode: 0644]
libFoundation/gsfix.make.in [new file with mode: 0644]
libFoundation/install-sh [new file with mode: 0755]
libFoundation/libfoundation.spec [new file with mode: 0755]
libFoundation/misc/GNUmakefile [new file with mode: 0644]
libFoundation/misc/testnested.c [new file with mode: 0644]
libFoundation/misc/testurl.m [new file with mode: 0644]
libFoundation/mkinstalldirs [new file with mode: 0755]
libFoundation/sharedlib.mak [new file with mode: 0644]

diff --git a/libFoundation/ANNOUNCE b/libFoundation/ANNOUNCE
new file mode 100644 (file)
index 0000000..a8fe489
--- /dev/null
@@ -0,0 +1,141 @@
+
+We are pleased to announce you the availability of libFoundation 0.9.0, a
+free and almost complete implementation of Foundation Kit as defined by the
+OpenStep specifications, plus more classes that come with the newest releases
+of OPENSTEP 4.x and Rhapsody. It completely or almost completely
+implements the following classes:
+
+NSObject
+NSString, NSMutableString
+NSArray, NSMutableArray
+NSDictionary, NSMutableDictionary
+NSSet, NSMutableSet
+NSData, NSMutableData
+NSValue, NSNumber
+NSDate, NSCalendarDate, NSTimeZone
+NSCharacterSet
+NSEnumerator
+NSAutoreleasePool
+NSException
+NSNotification, NSNotificationCenter
+NSCoder, NSArchiver, NSUnarchiver
+NSScanner
+NSInvocation, NSMethodSignature
+NSFileManager
+NSBundle
+NSProcessInfo
+NSAccount
+NSDistributedLock
+NSPosixFileDescriptor, NSFileHandle, NSPipe
+NSTimer
+NSRunLoop
+NSThread, NSTask
+NSUserDefaults
+NSHost
+
+Some extensions to the OpenStep specification are also present. They
+include an extended exception handling mechanism, a garbage collector
+based on reference counting and a printf-like formatting class. In
+addition to the reference counting garbage collector, the 0.9.0
+release comes with support for the Boehm's garbage collector, which
+add true garbage collection to OpenStep applications.
+
+The exception handling mechanism is very similar with those found in
+Java and C++ and requires support for nested functions from the
+compiler. The garbage collectors adds the benefits of automatic or
+pseudo-automatic garbage collection to the OpenStep programs and it is
+fully integrated with OpenStep classes. The printf-like formatting
+class is a general purpose class that can be used to do various
+operations that require parsing of format strings like in
+printf(). This class is used for example to do all the formatting jobs
+in the NSString class in libFoundation.  There is another class
+UnixSignalHandler designed for giving an object-oriented approach to
+the Unix signal handling.
+
+These extensions are also available in a separate library for other
+OpenStep Foundation implementations; the current supported Foundation
+libraries are gnustep-base and the Foundation library in OPENSTEP
+4.x. We dropped the support for the buggy implementation of the
+Foundation library that comes with NeXTSTEP 3.3; sorry for this.
+
+The library requires GCC 2.8.1 or the EGCS 1.0.x compilers if you want
+true garbage collection support. Patches for both compilers are
+included in the distribution. If you don't need true garbage
+collection you can still use the 2.7.2.1 compiler with an Objective-C
+patch from
+
+ftp://alpha.gnu.org/gnu/gnustep/contrib/gcc-2.7.2.1-objc-970318.diff.gz
+ftp://ftp.net-community.com/pub/GNUstep/gcc-2.7.2.1-objc-970318.diff.gz
+
+On NeXTStep machines the library can also be compiled with NeXT
+Objective-C runtime besides the GNU runtime although the NeXT compiler
+is not supported. Note that the library does not currently compile
+with the NeXT runtime under OPENSTEP 4.x. In the future the OPENSTEP
+4.x and NeXTSTEP 3.3 platforms will be no longer supported.
+
+The library was ported on the following platforms:
+
+- m68k-next-nextstep3
+- i386-next-nextstep3
+- i386-pc-linux-gnu
+- i386-pc-cygwin32 (Windows NT)
+- i386-unknown-solaris2.5.1
+- sparc-sun-solaris2.5
+- alpha-unknown-linux-gnu
+- powerpc-ibm-aix4.1.5.0
+
+The library also runs with GNU runtime on OPENSTEP 4.x for Mach with
+the GNU compiler (not the native one). Anybody interested in the
+compiler for OPENSTEP 4.x please contact us.
+
+Support for Distributed Objects has been delayed until the next
+release. We plan to base the code upon the Corba's IIOP, so that
+OpenStep programs using libFoundation will be able to interoperate
+with Corba programs without changes through the Distributed Objects
+mechanism.
+
+
+Changes in version 0.9.0 since version 0.8.0:
+
+* The most important change is the support for Boehm's conservative
+  garbage collector, that makes the memory management much more easier
+  than the reference counting mechanism. Many thanks to Helge Hess
+  <helge@mdlink.de> for persuading me to implement this facility and
+  also for his support.
+
+* Some portions of the code have been optimized to gain speed: objects
+  that were previously allocated in some functions or methods at each
+  invocation have been allocated once per-thread.
+
+* The library has been ported to PowerPC running AIX 4.1.5. The port is
+  complete, it also includes the NSInvocation and NSMethodSignature
+  classes. Many thanks to Steven Besler <sbesler@exchange.ml.com> and
+  Leon Salvail <lsalvail@global-village.net> for supporting this work.
+
+* Added support for dynamically loading bundles when running in the
+  GNUstep environment.
+
+* The documentation is now written in Texinfo and we documented almost
+  all of the additional features libFoundation comes with in addition
+  to the OPENSTEP implementation.
+
+* Bug fixes in several classes, including NSArray, NSString and
+  UnixSignalHandler.
+
+
+Where you can get it?
+=====================
+
+You can download the source code from
+
+http://www.slip.net/~ovidiu/libFoundation/libFoundation-0.9.0.tar.gz
+ftp://alpha.gnu.org/gnu/gnustep/libFoundation-0.9.0.tar.gz
+ftp://ftp.gnustep.org/pub/gnustep/libFoundation-0.9.0.tar.gz
+ftp://ftp.net-community.com/pub/Free/libFoundation-0.8.0.tar.gz
+
+
+Happy hacking,
+
+Ovidiu Predescu <ovidiu@slip.net>
+Mircea Oancea <mircea@pathcom.com>
+
diff --git a/libFoundation/AUTHORS b/libFoundation/AUTHORS
new file mode 100644 (file)
index 0000000..4e8fcba
--- /dev/null
@@ -0,0 +1,31 @@
+
+The authors of this library are
+
+Ovidiu Predescu <ovidiu@slip.net> 
+Mircea Oancea <mircea@pathcom.com>
+Helge Hess <helge@mdlink.de>
+
+We would like to thank to Florin Mihaila for his ideas and for his support in
+putting our work in public domain and to Mihaela Mihaila, Stefan Popescu,
+Claudiu Cruceanu, Calin Gatina and Bogdan Baliuc for their work in the old
+library and for removing all those nasty bugs :-)!
+
+Many thanks to Helge Hess <hh@mdlink.de> for lots of ideas, bug
+reports and effective work. He is responsible for persuading me to
+integrate the Boehm's garbage collector and for the support of this
+integration.
+
+Special thanks to the following people:
+
+- Jeremy R. Bettis <jeremy@hksys.com> for the port on Windows NT using
+  the Cygnus tools
+- Aleksandr Savostyanov <sav@conextions.com> for completion of the port on
+  Solaris, many bug fixes and a lot of suggestions.
+- Paul H. Kenyon <phk@hksys.com> for fixes in NSString
+- Gregor Hoffleit <flight@mathi.uni-heidelberg.de> for suggestions and bug
+  fixes.
+- Marcus Mueller <znek@object-factory.com> for the port on FreeBSD
+- Steven Besler <sbesler@exchange.ml.com> and Leon Salvail
+  <lsalvail@global-village.net> for supporting the AIX port.
+
+Please send us your suggestions and problems you encountered.
diff --git a/libFoundation/COPYING b/libFoundation/COPYING
new file mode 100644 (file)
index 0000000..ea95187
--- /dev/null
@@ -0,0 +1,18 @@
+
+Copyright (C) 1995, 1996, 1997, 1998 Ovidiu Predescu and Mircea Oancea.
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for ANY purpose and without fee is hereby granted, provided
+that the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation. This software may be included in any commercial product
+provided that its distribution contain the libFoundation copyright notice
+and this permission notice.
+
+We disclaim all warranties with regard to this software, including all
+implied warranties of merchantability and fitness, in no event shall
+we be liable for any special, indirect or consequential damages or any
+damages whatsoever resulting from loss of use, data or profits, whether in
+an action of contract, negligence or other tortious action, arising out of
+or in connection with the use or performance of this software.
diff --git a/libFoundation/ChangeLog b/libFoundation/ChangeLog
new file mode 100644 (file)
index 0000000..f49f122
--- /dev/null
@@ -0,0 +1,3375 @@
+2005-06-02  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSURL.m: added +fileURLWithPath: (v1.0.75)
+
+2005-05-17  Frank Reppin  <frank@opengroupware.org>
+
+       * v1.0.74
+       
+       * added OpenBSD 3.7 config file
+       
+       * Foundation/NSExceptionWithoutNested.h: patched to work with current
+         gcc preprocessors (removed ## parameters)
+       
+2005-05-09  Helge Hess  <helge.hess@skyrix.com>
+
+       * configure.in: check whether GNUstep.sh was sourced prior
+         configuration but removed requirement to source GNUstep.sh during
+         compilation (gsfix.make file)
+
+       * GNUmakefile, Foundation/GNUmakefile: stop compilation if
+         GNUSTEP_SYSTEM_ROOT is not set
+
+2005-05-06  Helge Hess  <helge.hess@opengroupware.org>
+
+       * v1.0.73
+
+       * started workon NSExpression.[hm], NSPredicate*.[hm]
+
+       * Foundation/NSString.m: fixed some gcc 4.0 warnings
+
+2005-04-14  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSString.m: added -initWithBytes:length:encoding: and
+         -initWithBytesNoCopy:length:encoding:freeWhenDone: methods
+         (added in Panther) (v1.0.72)
+
+2005-03-31  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSURL.m ([NSString -urlScheme]): fixed an (incorrect!)
+         gcc warning on an uninitialized variable (v1.0.71)
+
+2005-03-25  Helge Hess  <helge.hess@opengroupware.org>
+
+       * Foundation/NSURL.m: fixed a parsing bug with HTTP URLs containing an
+         '@' in the path section, but not in the login/pwd one (v1.0.70)
+         
+2005-03-14  Helge Hess  <helge.hess@skyrix.com>
+
+       * v1.0.69
+
+       * Resources/Defaults/NSGlobalDomain.plist: changed default timezone
+         from MET to GMT
+         
+       * Foundation/NSUserDefaults.m: some code cleanups
+       
+2005-02-06  Helge Hess  <helge.hess@opengroupware.org>
+
+       * Resources/GNUmakefile: properly use GNUSTEP_INSTALLATION_DIR instead
+         of GNUSTEP_SYSTEM_ROOT in Resource install path (OGo bug #727)
+         (v1.0.68)
+
+2005-01-24  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * Foundation/NSString.m: fixed yet another range bug, this time in
+         compare:options:range:. The implication of this bug was that
+         -hasSuffix _never_ worked before which probably affects code outside
+         of lF (v1.0.67)
+
+2004-12-22  Florian G. Pflug  <fgp@phlo.org>
+
+       * Foundation/NSConcreteUnixTask.m: added a hack to avoid OGo bug #616
+         (some edge condition in child signal handling) (v1.0.66)
+
+2004-11-28  Helge Hess  <helge.hess@opengroupware.org>
+
+       * v1.0.65
+       
+       * added Unicode aware property list and strings file parser. The
+         parser is slower but required for OGo 1.0a which uses UTF-8 encoded
+         strings files. You can still enable the fast Latin1 parser by passing
+         use8bitstringsparser=yes to make
+       
+       * NSDictionary.m: subminor code cleanup
+
+2004-11-19  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * Foundation/NSProcessInfo.[hm]: added -(int)processIdentifier
+         (v1.0.64)
+
+2004-10-15  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * Foundation/NSConcreteMutableString.m: fixed
+         -rangeOfCharacterFromSet:options:range:  which didn't honour the
+         searchRange as it should. Applied some pretty printing and
+         simplified quite a bit of range operations by using foundation
+         macros for this purpose. Fixed typos in exception logs.  (v1.0.63)
+
+2004-10-06  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * Foundation/{NSString.m, NSConcreteString.m}: fixed
+         -rangeOfCharacterFromSet:options:range:  which didn't honour the
+         searchRange as it should. (v1.0.62)
+
+2004-10-06  Helge Hess  <helge.hess@skyrix.com>
+
+       * examples/GNUmakefile: added FHS pathes to SYSTEM_LIB_DIR, so that
+         GS dirs are searched first (v1.0.61)
+
+2004-09-30  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSURL.m: added parsing of user/password for generic URLs
+         (v1.0.60)
+
+2004-09-20  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * v1.0.59
+
+       * Foundation/NSBundle.[hm]: added some Cocoa additions,
+         -pathForResource:ofType:inDirectory:forLocalization: and
+         -pathsForResourcesOfType:inDirectory:forLocalization:. Please note
+         that the latter doesn't work at all, as the original implementation
+         of -pathsForResourcesOfType:inDirectory: is very incomplete.
+
+2004-09-14  Helge Hess  <helge.hess@opengroupware.org>
+
+       * examples/GNUmakefile: fixed a typo (OGo bug #913) (v1.0.58)
+
+2004-09-06  Helge Hess  <helge.hess@skyrix.com>
+
+       * v1.0.57
+
+       * examples/GNUmakefile (ADDITIONAL_LIB_DIRS): added missing
+         -L/usr/local/lib to pick up a libobjc installed there
+
+       * Foundation/NSBundle.m (+_fileResourceNamed:extension:inDirectory:):
+         catch nested calls to the function (helps with some broken setup
+         conditions)
+
+2004-08-29  Helge Hess  <helge.hess@opengroupware.org>
+
+       * Foundation/NSBundle.m: support "combo" bundles in flattened setups
+         (uses Info.plist to determine the NSExecutable), find libFoundation
+         resources in GNUSTEP_PATHPREFIX_LIST and GNUSTEP_PATHLIST (v1.0.56)
+
+       * Foundation/NSBundle.m ([NSBundle +isFlattenedDirLayout]): fixed a
+         small bug in flattened detection (v1.0.55)
+
+       * added hack to install libFoundation in FHS locations using, the
+         library, its headers, the tools and the resources will be installed
+         in FHS_INSTALL_ROOT if specified (eg make
+         FHS_INSTALL_ROOT=/usr/local) (v1.0.54)
+       
+       * v1.0.53
+
+       * Resources/GNUmakefile: added FHS_INSTALL_ROOT variable, when
+         compiling with "make FHS_INSTALL_ROOT=/usr/local", resources will be
+         copied to /usr/local/share/libFoundation
+
+       * Foundation/NSTimeZone.m ([NSTimeZone +defaultTimeZone]): detect an
+         endless recursion in the setup phase if the NSGlobalDomain property
+         list is broken
+
+       * Foundation/realpath.m: fixed a typo (resove=>resolve)
+
+       * Foundation/NSPathUtilities.m: added /usr/local/share/ and /usr/share
+         to some Library search paths, added support for GNUSTEP_PATHLIST in
+         addition to GNUSTEP_PATHPREFIX_LIST
+
+       * Foundation/NSBundle.m: assume flattened if no GNUSTEP_SYSTEM_ROOT is
+         set, also look for resources in /usr/local/share/libFoundation and
+         /usr/share/libFoundation, added +isFlattenedDirLayout method
+
+2004-07-25  Helge Hess  <helge.hess@opengroupware.org>
+
+       * Foundation/NSString.m(initWithUTF8String:): check cstr argument for
+         NULL pointer (would break on OSX?), set range location to NSNotFound
+         when nothing was found (not checked for full coverage) (v1.0.52)
+
+2004-07-23  Helge Hess  <helge.hess@opengroupware.org>
+
+       * Foundation/NSURL.h: added missing prototype for -initWithString: 
+         (v1.0.51)
+
+2004-07-21  Helge Hess  <helge.hess@skyrix.com>
+
+       * v1.0.50
+       
+       * Foundation/NSString.m: log an incompatibility with MacOSX
+       
+       * Foundation/NSObject.m: fixed a compilation warning with gcc 3.4 
+
+2004-07-20  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * Foundation/NSDebug.m: new file containing the function 
+         _NSPrintForDebugger() which is used by gdb to print Objective-C
+         objects via the builtin 'po' command. (v1.0.49)
+
+2004-06-24  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * Foundation/NSCalendarDate.m: fixed bug in -dateByAddingYears:...
+         where an edge case with negative month values was not being taken
+         into account. (v1.0.48)
+
+2004-06-02  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * Foundation/NSCalendarDateScanf.m: added private category to
+         NSScanner, implementing
+         -(BOOL)scanInt:(int *)_value exactNumberOfDigits:(unsigned int)_len;
+         which is used by NSCalendarDateScanf in order to correctly parse
+         formats which don't have break characters/delimiters between format
+         symbols. (v1.0.47)
+
+2004-05-24  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * Foundation/NSCalendarDate.m: implemented -(unsigned)hash (v1.0.46)
+
+2004-05-11  Helge Hess  <helge.hess@skyrix.com>
+
+       * added NSTimeZone.h to improve Cocoa compatibility (v1.0.45)
+
+2004-04-20  Helge Hess  <helge.hess@opengroupware.org>
+
+       * Foundation/NSCharacterSet.m (+characterSetWithContentsOfFile:):
+         avoid recursion if character set could not be loaded in the init
+         phase, match the Panther behaviour of returning an empty charset
+         if the file could not be loaded. Does not throw an exception anymore
+         (v1.0.44)
+
+2004-04-06  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSData.m: added support for OSX 10.2 method:
+         -initWithBytesNoCopy:length:freeWhenDone: (v1.0.43)
+
+2004-03-31  Helge Hess  <helge.hess@skyrix.com>
+
+       * examples/Defaults.m: minor code cleanups (v1.0.42)
+
+2004-03-31  Christian Kesselheim  <ckesselh@infeurope.lu>
+       
+       * examples/Defaults.m: minor patch to fix OGo bug #600
+
+2004-03-28  Helge Hess  <helge.hess@opengroupware.org>
+
+       * Foundation/NSPathUtilities.m: fixed some broken edge conditions in
+         -pathExtension and -lastPathComponent (if separators could not be 
+         found) (v1.0.41)
+
+2004-03-26  Helge Hess  <helge.hess@opengroupware.org>
+
+       * v1.0.40
+
+       * Foundation/NSCalendarDate.m(-compare:): fixed comparisons against
+         nil (now behaves like Cocoa and returns NSOrderedSame), replaced
+         assertion exception with an error log
+
+       * Foundation/NSDate.m: streamlined source formatting
+
+2004-03-18  Helge Hess  <helge.hess@skyrix.com>
+
+       * v1.0.39
+
+       * NSCalendarDate.m, NSConcreteTimeZone.m: minor cleanups and 
+         improvements
+       
+       * minor speed improvement for -timeZoneForSecondsFromGMT:, minor code
+         cleanups
+
+2004-02-18  Helge Hess  <helge.hess@opengroupware.org>
+
+       * added timezone info for Europe/Brussels (v1.0.38)
+
+2004-02-08  Helge Hess  <helge.hess@opengroupware.org>
+
+       * v1.0.37
+
+       * Foundation/NSConcreteString.m: use cached NSString class
+
+       * Foundation/NSDecimal.h: explicitly marked 'exponent' as a signed
+         char
+
+       * Foundation/NSString+StringEncoding.m: explicitly typed "char" as
+         "unsigned char" in some locations
+
+2004-02-01  Helge Hess  <helge.hess@opengroupware.org>
+
+       * examples/GNUmakefile: applied the patch provided by Sebastian Ley
+         to fix compilation with gstep-make 1.9 (v1.0.36)
+
+2004-01-11  Helge Hess  <helge.hess@opengroupware.org>
+
+       * Foundation/NSURL.m: fixed a binary bug in URL processing (v1.0.35)
+
+2004-01-07  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSConcreteMutableDictionary.m: added some selector caching
+         for keys (v1.0.34)
+
+2003-12-29  Helge Hess  <helge.hess@opengroupware.org>
+
+       * v1.0.33
+               
+       * Foundation/NSConcreteArray.m: minor optimizations/cleanups, cache
+         -release method in dealloc
+
+       * Foundation/NSZone.h, Foundation/NSObject.m: cache NSZone class in 
+         NSObject
+       
+       * Foundation/NSConcreteString.m: added various hardcoded methods to
+         some (final) string subclasses for speed (located using Valgrind)
+       
+2003-12-28  Helge Hess  <helge.hess@opengroupware.org>
+
+       * v1.0.32
+         
+       * Foundation/NSString.m: use static references to NSString class
+
+       * Foundation/NSConcreteMutableDictionary.m(mdGet): cross-call selector
+         caching of -hash and -isEqual:
+
+       * Foundation/NSConcreteString.m(hash): cross-call selector caching
+         
+       * Foundation/NSConcreteString.m(compare:options:range:): less calls to
+         objc_class_lookup (was 4.5% of the runtime), use own isKindOfClass 
+         implementation (~2% of the runtime?)
+
+2003-12-07  Nicola Pero  <n.pero@mi.flashnet.it>
+
+       * Foundation/GNUmakefile (libFoundation_LIBARIES_DEPEND_UPON): Added
+         dependency on libdl (v1.0.31)
+       
+2003-11-30  Helge Hess  <helge.hess@opengroupware.org>
+
+       * Foundation/NSBundle.m: fixed a bug introduced in v1.0.29 (sigh ..)
+         (v1.0.30)
+
+       * Foundation/NSBundle.m: now should properly detect a flattened
+         GNUstep environment (that is, look for the code in the proper
+         location if GNUSTEP_FLATTENED is set in the environment) (v1.0.29)
+
+2003-11-27  Helge Hess  <helge.hess@opengroupware.org>
+
+       * applied patches of Sebastian and Nicola (v1.0.28)
+
+Thu Nov 27 13:47:54 2003  Sebastian Ley <sebastian.ley@mmweg.rwth-aachen.de>
+
+       * GNUmakefile (after-install): Prefix libFoundation.make
+         installation directory with INSTALL_ROOT_DIR. 
+
+Thu Nov 27 01:28:06 2003  Nicola Pero  <n.pero@mi.flashnet.it>
+
+       * Foundation/GNUmakefile.postamble: Use MKDIRS and MKINSTALLDIRS.
+       
+       * examples/GNUmakefile (GNUSTEP_OBJ_DIR_NAME): Define as well as
+         GNUSTEP_OBJ_DIR, so that the hack works with old and modern
+         gnustep-makes.
+
+       * Foundation/libFoundation.make.in: Removed -ldl from system
+         linking flags.
+
+       * Foundation/libFoundation.make.in: Use the new header location
+         xxx/Library/Headers for new gnustep-makes, while still detecting
+         old gnustep-makes and using xxx/Headers for them.
+       
+       * Foundation/GNUmakefile.postamble (after-uninstall): Remove
+         libFoundation.make from Additional.
+       
+2003-11-24  Helge Hess  <helge.hess@opengroupware.org>
+
+       * Foundation/libFoundation.make.in: added -ldl to system linking
+         flags as suggested by Nicola (v1.0.27)
+
+       * Foundation/GNUmakefile.postamble: install libFoundation.make in 
+         $(INSTALL_ROOT_DIR)$(GNUSTEP_MAKEFILES)/Additional as suggested by
+         Nicola (v1.0.26)
+
+2003-11-17  Helge Hess  <helge.hess@opengroupware.org>
+
+       * Foundation/NSConcreteNumber.m: fixed bug introduced in v1.0.24 (wrong
+         string values were returned) (v1.0.25)
+
+2003-11-15  Helge Hess  <helge.hess@opengroupware.org>
+
+       * Foundation/NSConcreteNumber.m: various modifications to the concrete
+         numbers. They are not generated anymore from a shell script but are
+         now "handwritten". Included is a fix to some formatting of "%llu"
+         which resulted in just the string "lu" being printed in some parts of
+         the system. Added various tweaks to improve the performance of string
+         handling a lot (eg NSString class is cached, sprintf is used for
+         format generation instead of stringWithFormat, a static buffer is
+         used) (v1.0.24)
+
+2003-11-14  Helge Hess  <helge.hess@skyrix.com>
+
+       * v1.0.23
+
+       * config/i386: added solaris2.9.h (a copy of solaris2.5.1.h) 
+
+       * NSURL.m: improved description of NSURL objects
+
+2003-10-29  Helge Hess  <helge.hess@skyrix.com>
+
+       * v1.0.22
+
+       * started new classes: NSStream, NSInputStream, NSOutputStream, NSError
+         - so far no real implementation
+
+       * Foundation: added NSSortDescriptor.m and related methods based on
+         the implementation in skyrix-core
+
+Tue Oct 28 19:19:57 2003  Martin Hoerning  <martin@opengroupware.org>
+
+       * Foundation/NSCalendarDate.m: 
+        (dateByAddingYears:months:days:hours:minutes:seconds:)
+        fixed timeOfDay computation when changing timeZoneDetail
+        (v1.0.21)
+
+2003-09-07  Marcus Mueller <znek@mulle-kybernetik.com>
+
+       * GNUmakefile: prevent GNUmakefile from getting wiped out on distclean
+
+       * Foundation/GNUmakefile: Hardcoded OBJC_RUNTIME=GNU as all other
+         support has been removed anyways
+
+       * Foundation/libFoundation.make.in: Corrected AUXILIARY_CPPFLAGS to
+         include the correct path
+
+       * examples/GNUmakefile: Correctly set ADDITIONAL_INCLUDE_DIRS instead
+         of ADDITIONAL_CPPFLAGS (probably some old leftovers?). Also removed
+         support for 'nx' and removed removal of GNUmakefile at distclean
+
+2003-08-19  Helge Hess  <helge.hess@skyrix.com>
+
+       * v1.0.20
+
+       * Foundation/NSException.m ([NSException -raise]): fixed for broken
+         compilers (called -invokeUncaughtExceptionHandler instead of
+         -invokeUncaughtExceptionHandlerWithException:) 
+         (OpenBSD, may relate to OGo Bug 131)
+
+       * Foundation/NSExceptionWithoutNested.h: added prototypes for
+         -backtrace and -printBacktrace to fix warning
+
+2003-08-18  Helge Hess  <helge.hess@skyrix.com>
+
+       * let the makefiles grep the version from the "Version" file, so that
+         we don't need to remake the configure script each time we want to
+         increase the library subminor version (v1.0.19)
+
+2003-08-17  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSString.m: added implementation of 
+         -stringByTrimmingCharactersInSet: method provided by Max Berger and
+         fixed some trimming methods to use NSCharacterSet (v1.0.18)
+
+2003-08-08  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSUserDefaults.m ([NSUserDefaults -initWithPath:]): be
+         tolerant when reading the Languages default (OGo Bug #11) (v1.0.17)
+
+2003-08-04  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/load.m (objc_load_module): added dlopen patch provided
+         by Max Berger (v1.0.16)
+
+Tue Jul 29 17:04:14 2003  Helge Hess  <helge.hess@skyrix.com>
+
+       * applied autoconf patches provided by Marcus Mueller 
+         (znek@mulle-kybernetik.com) to clean up the configuration patches.
+         Note: from this point on the OGo libFoundation only works with
+         gstep-make (v1.0.15)
+
+2003-07-21  Helge Hess  <helge.hess@skyrix.com>
+
+       * v1.0.14
+
+       * applied small FreeBSD patch to aclocal.m4 provided by Marcus Mueller
+         (thanks!)
+
+       * Foundation/NSConcreteMutableString.m: fixed a cast warning
+
+Mon Jul 14 20:10:03 2003  Jan Reichmann  <jr@skyrix.com>
+
+       * Foundation/NSSet.m, Foundation/PrintfFormatScanner.m: 
+         use __va_copy to handle va_list arguments (needed for powerpc64 port)
+       
+2003-07-14  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSFileManager.m ([NSFileManager -removeFileAtPath:handler:]): 
+         use unlink() instead of remove() if we know that a path is a 
+         directory, this seems to workaround a bug in RH 9.0 glibc 2.3 ?
+         (v1.0.13)
+
+2003-06-13  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSString.m: fixed some unsigned/signed bugs introduced in
+         v1.0.10 (backward search for-loops usually check for "i >= 0" and
+         unsigned values are always >= 0 ...) (v1.0.12)
+
+2003-06-11  Jan Reichmann <jr@skyrix.com>
+
+       * Foundation/NSCalendarDate.m ([NSCalendarDate -initWithString:calendarFormat:locale:]): 
+         fixed a bug in parsing 2-digit years (year value was added twice 
+         leading to wrong 4-digit year values) (v1.0.11)
+
+2003-06-06  Jan Reichmann <jr@skyrix.com>
+
+       * v1.0.10
+       
+       * major fixes for gcc 3.3 compilation in almost any source file 
+         (signed/unsigned problems, THROW => -raise)
+
+       * Foundation/NSString.m: moved charset processing into a separate
+         file (NSString+Encoding.m)
+
+2003-04-26  Helge Hess  <helge.hess@skyrix.com>
+       
+       * Foundation/common.h, NSDictionary.m: added a macro to copy va_list 
+         structures (required for powerpc64) (v1.0.9)
+       
+2003-05-06  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSCalendarDate.m (MAX_YEAR): set back to 2038, since
+         the timezone files contain date values ending in 2037 (v1.0.8)
+
+2003-04-30  Helge Hess  <helge.hess@skyrix.com>
+       
+       * Foundation/NSCalendarDate.m (MAX_YEAR): configured 2030 as the
+         maximum year supported (was 2300) (v1.0.7)
+       
+2003-02-18  Helge Hess  <helge.hess@skyrix.com>
+
+       * examples/GNUmakefile.gnustep: added examples to makefile, the 
+         examples are only build when passing "examples=yes" to make
+
+2003-02-17  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSURL.m: do not default to port 80 for generic URLs (only
+         with HTTP URLs) (v1.0.6)
+
+2003-02-14  Helge Hess  <helge.hess@skyrix.com>
+       
+       * Resources/TimeZoneInfo: added CLST (Chile) and SAST (South Africa)
+         timezone files (v1.0.5)
+       
+2003-01-30  Helge Hess  <helge.hess@skyrix.com>
+
+       * v1.0.4
+       
+       * Foundation/NSURL.m: prepared _NSAbsoluteHTTPURL class for "httpu" 
+         requests
+       
+       * Foundation/NSTimeZone.m(+initialize): do not abort program if the
+         timezone information could not be found, instead log the problem
+         and continue (program will probably fail later)
+       
+       * Foundation/NSString.m: removed some aborts on positions that are
+         never entered
+       
+       * Foundation/NSArchiver.m:
+         replaced an abort() with a NSException (program was aborted when
+         reading some broken archives)
+       
+       * Foundation/NSCalendarDate.m:
+         instead of aborting the program a NSRangeException is thrown if too
+         large datevalues are passed to NSCalendarDate (eg year 5600)
+
+2003-01-20  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSDictionary.m: added small performance improvement for
+         empty dictionaries, added a log if an NSNull object is encoded in a
+         property list, use Calloc instead of Malloc for array allocations
+         (v1.0.3)
+       
+Thu Jan 16 15:19:16 2003    <jan@skyrix.com>
+       
+       * Foundation/NSString.m: fixed dataUsingEncoding, use dynamic 
+         allocation of memory for string-length > 200 bytes to prevent 
+         stack overflow (v1.0.2)
+
+Thu Jan  2 10:46:21 2003  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSFuncallException.h: added explicit macros for NSAssertX
+         to reduce compiler warnings introduced with gcc 3.2 (v1.0.1)
+
+2002-11-20  Helge Hess  <helge.hess@skyrix.com>
+       
+       * Foundation/NSURL.m: fixed a bug with invalid port numbers in
+         -absoluteString
+       
+2002-11-13  Helge Hess  <helge.hess@skyrix.com>
+       
+       * marked libFoundation 1.0.0 - it's stable for years now, should
+         become a proper stable version number
+       
+       **********************************************************************
+       
+       * NSURL: added support for login/password in HTTP URLs, use HTTP
+         URL class for https scheme URLs
+       
+       * added SGT (Singapure Time) as a copy of GMT+0800
+
+2002-10-28  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/GNUmakefile.gnustep: define SOVERSION to be major.minor
+         instead of just major
+
+Tue Oct 22 12:27:56 2002  Jan Reichmann  <jan@skyrix.com>
+
+       * Foundation/NSString.m: add complete ISO-Latin-9 and Windows-1252 
+         encoding support (v0.9.5)
+
+2002-10-21  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSString.m: changed so that ISO-Latin-1 is used if an
+         unknown encoding was found (before an NSAssert threw an exception
+         eg resulting in SuSE Bug 20913) (v0.9.4)
+
+2002-10-14  Helge Hess  <helge.hess@skyrix.com>
+       
+       * added timezone info for Europe/Berlin, Europe/Paris
+       
+       * added header file "NSScriptKeyValueCoding.h" as available in MacOSX
+
+2002-07-11  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSConcreteUTF16String.m: allow lossy conversion when
+         creating cString's. This way it doesn't immedialy break applications
+         on unicode strings but rather allows them to operate at least
+         partially (this "fix" is probably removed when all stuff is unicode
+         aware).
+
+2002-07-08  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSConcreteData.m: NSConcreteMutableData doesn't use 
+         add_behaviour anymore ... much easier to debug
+
+       * Foundation/NSData.m ([NSData -subdataWithRange:]): use zone of
+         parent object for allocation, not the default zone
+
+Mon Jul  8 15:15:46 2002  Jan Reichmann  <jan@skyrix.com>
+
+       * Foundation/NSUserDefaults.m: create default directories on demand 
+          (SuSE bug 16582)
+
+2002-07-08  Jan Reichmann  <jr@skyrix.com>
+
+       * Resources/TimeZoneInfo: added half-hour timezones (eg GMT+0330)
+
+2002-07-05  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSConcreteData.m: added -init method
+
+2002-06-18  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSURL.m ([NSURL -_pathForRelativeURL:]): fixed relative
+         path processing (a slash was always added)
+
+2002-06-13  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSTimeZone.m ([NSTimeZone +setDefaultTimeZone:]): do
+         not write default timezone into userdefaults
+       
+       * Foundation/NSConcreteMutableString.m ([NSMutableSimple -initWithString:]): 
+         method tried to create an instance of NSMutable8BitString, which is
+         an abstract class (jr, explain that to me !)
+
+2002-06-11  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSConcreteUTF16String.m ([NSInlineUTF -stringRepresentation]): 
+         added a preliminary implementation of -stringRepresentation (required
+         for logging of unicode strings)
+
+2002-06-10  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSString.m ([NSString -stringByAppendingString:]):
+         rewrote -stringByAppendingString:
+
+Mon Jun 10 11:24:27 2002  Jan41 Reichmann  <jan@skyrix.com>
+
+       * Foundation/NSConcreteMutableString.m: add initWithString for
+         MutableString (warning: has to be moved to TempStr.)
+
+Fri Jun  7 16:24:12 2002  Jan Reichmann  <jan@skyrix.com>
+
+       * Foundation/NSString.m ([NSString +availableStringEncodings]): added
+         some support for ISO Latin 9 (the charset containing the Euro sign)
+
+       * Foundation/NSConcreteUTF16String.m 
+         ([NSInlineUTF -initWithCharacters:length:]): 
+         fixed serious copying bug (only copied half of the string ...)
+
+2002-06-05  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSString.h: added NSISOLatin9StringEncoding constant
+
+       * Foundation/NSString.m ([NSMutableString -initWithCharacters:length:]):
+         added support for (lossy) conversion of Euro sign to Latin1
+
+       * Foundation/NSConcreteMutableString.m ([NSMutable -writeToFile:atomically:]): 
+         write data in defaultCStringEncoding instead of Latin1
+
+2002-06-04  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSString.m: fixed class-cluster bugs (isa was used
+         for +alloc instead of the cluster abstract class).
+
+2002-06-03  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/common.m (NSReadContentsOfFile): fixed gcc3 cpp bug
+
+2002-05-31  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/common.m: fixed for gcc 3.0 compilation
+
+Mon May  6 12:36:21 2002  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSURL.m ([_NSAbsoluteFileURL -absoluteString]): fixed bug,
+         did return file:/a.txt instead of file:///a.txt
+
+Mon Apr 29 15:35:29 2002  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSHost.m: added a -description
+
+Sun Apr 14 19:29:57 2002  Helge Hess  <helge.hess@skyrix.com>
+
+       * added fake NSAttributedString (not implemented ..) to be able to
+         compile EDInternet
+
+Fri Apr 12 19:39:46 2002  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NS*Exception.h: added NSParameterAssert, 
+         NSCParameterAssert
+
+       * Foundation/libFoundation.make.in (FND_DEFINE): defines -DGNUSTEP=1
+
+Fri Apr  5 14:55:23 2002  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSConcreteUnixTask.m: fixed yet another NSTask bug
+
+Wed Apr  3 10:33:38 2002  Helge Hess  <helge.hess@skyrix.com>
+
+       * Resources/GNUmakefile.gnustep: replaced GNUSTEP_LIBRARIES_ROOT
+         with GNUSTEP_SYSTEM_ROOT/Libraries to support gstep-make 1.3.0
+
+Thu Mar 14 13:48:03 2002  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSException.m: copies name and reason
+
+       * Foundation/NSFuncallException.h: fixed retain/release
+
+       * Foundation/NSException.m ([NSException +exceptionWithName:reason:userInfo:]): 
+         fixed -autorelease bug
+
+Wed Mar 13 11:19:22 2002  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSRunLoop.m: also flush Notification ASAP queue before
+         entering select()
+
+       * Foundation/NSConcreteUnixTask.m: fixed bug, pid-to-task map wasn't
+         properly teared down after task shutdown ...
+
+       * Foundation/NSConcreteUnixTask.m: can handle multiple childs exiting
+         at the same time now (check all tasks for termination on SIGCHLD)
+
+       * Foundation/UnixSignalHandler.m: save errno in signal handler
+
+Tue Mar 12 19:09:12 2002  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/UnixSignalHandler.m: fixed bug, _dispatch: was called
+         on UnixSignalHandler class, but defined as an instance method
+         which accessed 'self' (so self!=sharedHandler)
+
+       * Foundation/NSNotificationQueue.m: fixed bug, notification queues
+         didn't correctly register in the instance list ...
+       
+       * Foundation/NSConcreteUnixTask.m: do not "immediatly" notify if task
+         terminated (previously the notify code was run in a signal handler)
+
+       * Foundation/UnixSignalHandler.m: added logging/debugging, cleanups
+
+Fri Mar  8 17:25:35 2002  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSDictionary.m: applied SuSE patch to fix varargs on
+         powerpc
+
+Thu Feb 14 15:21:16 2002  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSUserDefaults.m ([NSUserDefaults +standardUserDefaults]):
+         look for defaults in GNUSTEP_DEFAULTS_ROOT
+
+Thu Feb  7 09:25:28 2002  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSArray.m(-sortUsingFunction:): added selector caching
+
+       * Foundation/NSArray.m(-sortedArrayUsingFunction:): improved memory
+         usage
+
+Mon Feb  4 17:07:43 2002  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSString.m ([NSTemporaryString -initWithCString:length:]):
+         fixed temporary string collect bug
+
+Fri Feb  1 11:17:21 2002  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSString.m: added support for single-char class
+
+       * Foundation/NSConcreteString.m: added concrete class for single
+         character strings
+
+Thu Jan 24 19:59:06 2002  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSCalendarDate.m ([NSCalendarDate -initWithString:calendarFormat:locale:]): 
+         release pool and date immediatly if string couldn't be parsed
+
+Wed Jan 16 16:42:33 2002  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSUserDefaults.m ([NSUserDefaults +standardUserDefaults]): 
+         search for user-defaults files in $GNUSTEP_USER_ROOT instead of
+         $HOME if GNUstep compilation is enabled
+
+Wed Dec 19 16:21:11 2001  Jan Reichmann  <jan@skyrix.com>
+
+       * Foundation/NSNotificationCenter.m: memory for object entries without 
+       observer will be freed
+
+Tue Dec 18 17:54:01 2001  Jan Reichmann  <jan@skyrix.com>
+
+       * Foundation/NSNotificationCenter.m: fixed HashTable initialisation bug
+
+Tue Dec 18 12:16:34 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSNotificationCenter.m: added some selector caching
+
+Mon Dec 17 19:15:47 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSObjectAllocation.m (NSExtraRefCount): replaced "int"
+         with "unsigned int"
+
+Tue Nov 27 18:57:02 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSBundle.m: added debugging info
+
+Tue Nov 27 13:00:14 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSAutoreleasePool.m, Foundation/NSObject.m:
+         speed optimized -autorelease (avoids method calls)
+
+Fri Nov 23 14:23:27 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSCalendarDate.m ([NSCalendarDate -initWithString:calendarFormat:locale:]):
+         added special handling for 2-digit years ...
+
+Wed Nov 21 16:07:11 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSCalendarDate.m: even more sanity checks ...
+
+Wed Nov 21 16:00:10 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSCalendarDate.m (Long2Date): added sanity check on year
+
+Tue Nov 13 17:58:37 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSString.m ([NSTemporaryString -initWithContentsOfFile:]): 
+         can detect/decode UTF-16 content
+
+Tue Nov 13 14:04:25 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/PropertyListParser.m: detect unicode plist files (files
+         starting with either FFFE or FEFF
+
+Fri Nov  9 13:24:33 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSBundle.m ([NSBundle -pathsForResourcesOfType:inDirectory:]): 
+         fixed retain bug
+
+Tue Nov  6 12:51:56 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSNull.m ([NSNull -stringRepresentation]): return '""', to
+         be valid in plists
+
+Tue Nov  6 12:51:02 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSString.m: enabled some unicode support (was marked
+         #if 0 ???)
+
+Mon Nov  5 14:55:55 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSNull.m: added -stringValue (empty string)
+
+Fri Nov  2 18:23:32 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSConcreteUTF16String.m: added
+         -getCString:maxLength:range:remainingRange:
+
+Fri Nov  2 18:20:00 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSConcreteString.m: moved unicode string implementation
+         to NSConcreteUTF16String
+
+Fri Nov  2 12:48:24 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSString.m ([NSString +initialize]): load LC_CTYPE and
+         LC_LOCALE from environment into C locale
+
+Thu Oct 25 09:47:37 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSString.m: zero-len strings result in 0 int/double/float
+         values
+
+Wed Oct 24 15:43:43 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSConcreteString.m (NSInlineUTF16String): implemented
+         getCString:, getCString:maxLength:
+       
+Tue Oct 23 14:49:25 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSConcreteTimeZone.m ([NSConcreteTimeZoneFile -timeZoneForDate:]): 
+         fixed RETAIN bug / leak
+
+Mon Oct 22 14:37:45 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSPathUtilities.m ([NSString -stringByStandardizingPath]): 
+         fixed bug, components-count wasn't adjusted after removing elements
+
+Thu Oct 18 16:15:40 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Resources/TimeZoneInfo/CET: fixed to use CET/CEST instead of MET
+
+Wed Oct 10 15:43:22 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSURL.m ([NSString -isAbsoluteURL]): support javascript:
+         scheme as absolute URL
+
+Mon Oct  1 16:57:14 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSURL.m: make absolute file-urls
+
+Mon Oct  1 12:29:55 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSUtilities.m: use fprintf(stderr) for printing log ...
+
+Tue Sep 25 11:58:41 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSConcreteArray.m: reduced msg-dispatch during remove
+
+Mon Sep  3 17:16:27 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSConcreteString.m(dataUsingEncoding): determine data
+         length using strlen instead of -cStringLength (buggy ???)
+
+Mon Aug 27 20:23:40 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSString.m: instantiate NSUTF16String if a unicode 
+         character is found ...
+
+       * Foundation/NSString.m ([NSString -copyWithZone:]): only retain the
+         (immutable) string and return self
+       
+Tue Aug 21 11:04:07 2001  Martin Hoerning  <mh@skyrix.com>
+
+       * Foundation/NSConcreteScanner.m ([NSConcreteScanner dealloc]): 
+           - added (memory bug fixed)
+
+Thu Aug 16 16:22:42 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/GCArray.m: fixed malloc/calloc calls with 0-size
+
+       * NSString, NSArray, NSDictionary, NSData: added 
+         -initWithContentsOfURL: and +*WithContentsOfURL: methods
+
+Tue Aug 14 16:14:08 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSBundle.m ([NSBundle +bundleWithPath:]): query cache,
+         use standard RC
+
+Mon Aug 13 17:17:43 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSString.m: fixed memory leak in NSInitStringWithData
+
+Sat Aug 11 13:53:40 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSAutoreleasePool.m: added -autoreleaseCount method
+
+Wed Aug  8 10:51:50 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/UnixSignalHandler.m ([UnixSignalHandlerListItem -invokeForSignal:]): 
+         use numberWithInt: instead of numberWithLong: for signal id
+
+Fri Jun 15 18:33:48 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSURL.m: added support for mailto URL
+
+Tue Jun 12 19:02:35 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/PropertyListParser.m: improved error output
+
+Tue Jun  5 16:07:25 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSString.m ([NSString -writeToFile:atomically:]): generate
+         data to write using -dataUsingEncoding:+defaultCStringEncoding
+
+Tue Jun  5 15:57:34 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSConcreteString.m: started UTF16 support
+
+Fri May 25 13:20:13 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSURL.m ([NSURL -initFileURLWithPath:]): renamed method
+
+Wed May 16 23:29:15 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSDecimalNumber.h: started NSDecimal/NSDecimalNumber
+
+Mon May 14 16:48:24 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSNumberFormatter.m: fixed bug in getObjectValue...
+
+Mon May 14 16:10:31 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSNumberFormatter.m: added capability to set decimal and
+         thousand separator in format string
+
+Mon May  7 08:58:59 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSArray.m: added -getObjects:range:
+
+Mon May  7 02:35:58 2001  Nicola Pero  <n.pero@mi.flashnet.it>
+
+        * Foundation/lfmemory.h.in (ASSIGN), (ASSIGNCOPY): Fixed - they
+        were *not* retaining the new value when the new value is an
+        expression which returns a different object each time that it is
+        computed.
+
+Mon May  7 00:04:04 2001  Nicola Pero  <n.pero@mi.flashnet.it>
+
+        * Foundation/NSScanner.m ([-scanCharactersFromSet:intoString:]):
+        Bug fix for the case there are only characters to be skipped: move
+        the scanning location after them.
+
+Sun May  6 22:46:22 2001  Nicola Pero  <n.pero@mi.flashnet.it>
+
+        * Foundation/NSArray.m ([NSArray -getObjects:]): Implemented.
+        * Foundation/NSArray.h ([NSArray -getObjects:]): Declared.
+
+Sun May  6 13:04:45 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSString.m: smaller perf-improvements in GS support
+
+Mon Apr 30 16:25:24 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSURL.m ([NSURL -_absoluteStringForRelativeURL:]): fixed 
+         bug with relative URL pathes
+
+Mon Apr 30 16:12:35 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSURL.m: added -initWithString:
+
+Sat Apr 21 12:40:12 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * configure.in: added checks for AR, LD, PERL as suggested by 
+         Andreas Voegele
+
+Thu Apr  5 12:03:31 2001  Helge Hess  <helge.hess@skyrix.com>
+
+       * Foundation/NSString.m: fixed bug in -UTF8String (str was not NULL
+         terminated)
+
+Thu Mar 15 14:06:14 2001  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSAccount.m ([NSUserAccount +initialize]): print warning if
+         password structure for current user could not be found
+
+Thu Mar 15 14:04:47 2001  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSAccount.m ([NSUserAccount -initWithPasswordStructure:]): 
+         graceful return with NULL structure as argument
+
+Mon Mar 12 18:12:40 2001  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSDefaultZone.m ([NSDefaultZone -realloc:size:]): catch
+         realloc with 0 extra bytes
+
+Mon Mar 12 18:11:35 2001  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSConcreteData.m ([NSConcreteMutableData -increaseCapacityBy:]): 
+         catch increase with 0 length
+
+       * Foundation/NSConcreteData.m ([NSConcreteMutableData -appendBytes:length:]):
+         catch appendBytes with 0 length
+
+Tue Feb 20 18:19:58 2001  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSString.m ([NSTemporaryString -initWithCharacters:length:]): 
+         fail gracefully on unicode characters
+
+Wed Feb 14 14:51:05 2001  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSNumberFormatter.m: relaxed format handling
+
+Tue Feb 13 19:27:06 2001  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSNumberFormatter.m ([NSNumberFormatter -stringForObjectValue:]): 
+       treat 'nil' values as double 0.0
+
+Thu Feb  8 18:05:52 2001  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSConcreteArray.m: fixed init bug in single-object array
+         (array could contain 'nil' values)
+
+Wed Feb  7 13:06:14 2001  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSURL.m ([_NSAbsoluteURL +URLWithString:]): allow file URL
+         strings starting with '/' (without scheme)
+
+Mon Jan 29 12:01:00 2001  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSInvocation.h: define _C_LNG_LNG if not defined by the
+         compiler (fix submitted by Elmar Ludwig)
+
+Thu Jan 25 13:57:04 2001  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/Foundation.h: added NSDateFormatter.h/NSNumberFormatter.h
+
+Tue Jan 16 12:41:50 2001  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSTimer.m ([NSTimer -description]): output [self fireDate]
+         instead of self->fireDate
+
+Mon Jan 15 20:14:56 2001  Helge Hess  <helge.hess@mdlink.de>
+
+       * moved to MOF3
+
+Thu Jan 11 11:49:05 2001  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSURL.m: added -isEqual:, -isEqualToURL:
+
+Wed Jan 10 16:48:51 2001  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/GNUmakefile.gnustep (libFoundation_OBJC_FILES): added
+         NSFileURLHandle.m
+
+Wed Jan 10 16:25:36 2001  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSURL.m: fixed bug in URL parser
+
+Tue Jan  9 18:08:09 2001  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSURL.m: added generic URL, added handle construction
+
+Tue Jan  2 14:01:30 2001  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSURL.m ([_NSAbsoluteFileURL +URLWithString:]): path is
+         standardized
+
+Tue Jan  2 13:48:11 2001  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSURL.m: fixed bug in File-URL
+
+Fri Dec 29 18:52:02 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSURL.m ([_NSAbsoluteHTTPURL +URLWithString:]): fixed bug
+
+Fri Dec 22 13:36:55 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSObject.h.in: changed inclusion of other headers (NSString,
+         NSProcessInfo is not included anymore)
+
+       * Foundation/NSString.h: removed inclusion of NSPathUtilities.h
+
+Fri Dec 22 12:07:49 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSObject.h.in: changed include order of headers
+
+Thu Dec 21 14:31:19 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSSet.m ([NSSet -isSubsetOfSet:]): fixed bug
+
+Wed Dec 13 21:22:59 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSURL.m: added some URL parsing, handling
+
+Thu Nov 30 18:03:33 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSSerialization.m: added fake NSSerializer/NSDeserializer
+         classes
+
+       * Foundation/NSValue.m: fixed bug in -isEqualToValue: reported by
+         Nicola Pero
+
+       * Foundation/NSFileManager.m ([NSFileManager -fileAttributesAtPath:traverseLink:]):
+         fixed to look at the 'traverseLink' flag (use lstat if the flag is NO)
+
+Thu Nov 30 04:46:59 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * added various methods to support JIGS
+
+       * Foundation/NSBundle.[hm]: added +allFrameworks fake method
+
+       * Foundation/NSConcreteNumber.m.sh: generate -valueBytes method
+
+Thu Nov 30 03:38:03 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/PropertyListParser.m: fixed serious property list parser
+         bug. If '*' occured inside of multiline comments, the parser ended
+         up in an endless loop.
+
+Thu Nov 30 00:54:19 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * added some GNUstep compatibility methods, functions, consts
+
+Wed Nov 29 14:15:39 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSString.m: fixed bug in UTF8 initialization
+
+Thu Oct 19 10:42:16 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * work on NSURL related classes
+
+Wed Oct  4 11:38:04 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSString.m: removed usage of stack-allocated buffers
+
+Tue Sep 26 20:37:23 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * added NSKeyValueCoding.h (added in MacOSX) [no implementation yet]
+
+       * added NSClassDescription class (added in MacOSX)
+
+Mon Sep 25 16:45:20 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * some modifications for Cygwin support
+
+       * Foundation/NSAccount.m: don't declare USER_INFO_11 on Windows
+
+       * added NSNull class (added in MacOSX)
+
+Wed Sep  6 21:19:39 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSConcreteString.m, Foundation/NSConcreteMutableString.m:
+         made 'char' types unsigned
+
+Wed Aug 30 11:16:53 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSInvocation.h: added runtime detection macros if not
+         compiling in the gstep-make environment
+
+       * Foundation/UnixSignalHandler.m: prefer sigaction over sigset
+
+       * fixed compilation bugs with gstep-make-less libFoundation
+
+Tue Aug 29 17:19:49 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSPathUtilities.m: added -pathsMatchingExtensions: method
+
+Tue Jun 13 18:07:11 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSString.m: caches class reference to NSString
+
+       * Foundation/NSArray.m: caches class references to NSArray,
+         NSConcreteArray, NSMutableArray and NSConcreteMutableArray
+
+       * Foundation/NSObjCRuntime.m, Foundation/NSString.m,
+         Foundation/PropertyListParser.m, Foundation/common.m: doesn't use stack
+         allocated buffers anymore
+
+       * Foundation/NSUtilities.m (NSLogv): optimized, caches Class objects
+         and doesn't make extensive use autorelease-pools anymore
+
+Fri Jun  9 17:30:49 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/PropertyListParser.m: fixed casting to void ..
+
+Wed May 24 15:14:52 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/PropertyListParser.m: add path info to exceptions in file
+         parsing functions
+
+       * Foundation/NSString.m: added +stringWithUTF8String:,
+         -initWithUTF8String: and -UTF8String methods
+
+Tue May 23 19:08:48 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/PropertyListParser.m: added duplicate key checks
+
+Wed May 10 16:52:25 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSConcreteString.m: added NSShortInline8BitString class,
+         for 8bit strings smaller than 255 chars (this saves 3 bytes per string)
+
+       * Foundation/NSString.m ([NSString +allocWithZone:]): caches ptr to
+         NSTemporaryString class
+
+       * Foundation/NSConcreteString.m: added some NSString cluster statistic
+         collection
+
+       * Foundation/NSString.m (NSTemporaryString): caches ptr to 
+         NSInline8BitString class
+
+       * Foundation/NSConcreteMutableString.m: doesn't use add_behaviour()
+         anymore
+
+       * Foundation/NSConcreteString.m: put concrete mutable strings into a
+         separate source file
+
+Mon May  8 14:42:23 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSUserDefaults.m: added new default keys
+
+       * Foundation/NSException.m: added new exception name constants
+
+       * Foundation/NSCharacterSet.h: added NSOpenStepUnicodeReservedBase
+
+       * Foundation/NSString.h: added new MacOSX encoding specifiers
+
+       * Foundation/NSInvocation.h: added NSObjCValue stuff
+
+       * added NSConnection and NSPortCoder dummy classes and files
+
+Wed May  3 18:21:06 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSConcreteTimeZone.m: added -copyWithZone: method (which
+         just returns self retained)
+
+       * Foundation/NSPosixFileDescriptor.m: added code to catch a lot of
+         lseek() errors (which were previously ignored)
+
+       * Foundation/NSPipe.m, Foundation/NSConcreteFileHandle.m:
+         added special file-handle class for Unix pipe's
+
+       * Foundation/NSConcreteFileHandle.m ([NSConcreteFileHandle -readDataOfLength:]): 
+         fixed bug with calls where length>LONG_MAX
+
+Fri Apr 28 14:13:44 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/FFCallInvocation.m ([FFCallInvocation -initWithSignature:]): 
+         fixed bug in call of objc_sizeof_type()
+
+Thu Apr 27 18:51:25 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSConcreteUnixTask.m ([NSConcreteUnixTask -_execChild]): 
+         use execvp if no environment was set
+
+Tue Apr 25 11:33:43 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSException.m: added ability to print backtraces using
+         gdb
+       
+       * Foundation/NSProcessInfo.m ([NSProcessInfo +initializeWithArguments:count:environment:]): 
+         store argv0 for gdb backtracing facility
+
+Thu Apr 20 15:09:09 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * added NSSocketPort,NSMessagePort classes (not yet finalized at all)
+
+Mon Apr 17 20:23:11 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSUserDefaults.[hm]: fixed spelling bug,
+         (synchronizeUserDefaults)
+
+Wed Apr 12 11:08:59 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSFileHandle.m, Foundation/NSHost.m: these two try to
+         startup winsock in +initialize
+
+Mon Apr 10 17:22:27 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * NSConcreteDictionary.m,NSConcreteMutableDictionary.m: customized
+         copy and mutable copy methods in concrete classes.
+
+Mon Apr 10 17:07:39 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * rewrote NSConcreteDictionary and NSConcreteMutableDictionary not to
+         use NSMapTable because of it's memory and callback overhead.
+         NSConcreteDictionary was renamed NSConcreteHashDictionary and
+         NSConcreteMutableDictionary was moved to a separate source file.
+
+Mon Apr 10 15:50:45 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSConcreteDictionary.m: NSMutableDictionary doesn't
+         inherit behaviour from NSDictionary anymore
+
+Tue Mar 28 16:09:01 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSObject.m ([NSObject -methodSignatureForSelector:]):
+         generates id-based signatures if no signature could be found in the
+         runtime
+
+Mon Mar 20 10:57:02 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSConcreteString.m (quoteString): fixed quoting bug in
+         generation of string representation ('\' wasn't replaced by '\\').
+
+       * Foundation/NSString.m, Foundation/NSConcreteString.m:
+         fixed bug in UTF8 encoding
+
+Tue Feb 29 12:06:13 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * GNUmakefile.gnustep, NSInvocation.m: added FFCallInvocation support
+
+       * added FFCallInvocation class, a concrete subclass of NSInvocation which
+         can use the ffcall library
+
+Tue Feb 29 11:45:56 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * configure.in, config.h.in, config.mak.in: added configuration for the
+         use of the ffcall library.
+
+Tue Feb 22 18:35:56 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/GarbageCollector.m: added methods to allow or deny GC
+       
+       * Foundation/NSNotificationCenter.m ([NSNotificationCenter -postNotification:]): 
+         disabled garbage collection during notification posting
+
+Mon Feb 21 14:12:42 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * removed calls to 'cString'
+
+Thu Feb 17 13:57:45 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSConcreteString.m ([-commonPrefixWithString:options:]): 
+         fixed bug, cleaned up
+
+       * Foundation/NSString.m ([NSString -commonPrefixWithString:options:]):
+         cleaned up implementation
+
+2000-02-17    <helge.hess@mdlink.de>
+
+       * added NSConcreteWindowsFileHandle.[hm]
+
+       * NSString.m: removed calls to 'cString'
+
+       * NSObject.m(-autorelease): caches a ptr to the NSAutoreleasePool class
+
+2000-02-15    <helge.hess@mdlink.de>
+
+       * fixed CR 'bugs' introduced during Win commit ..
+
+Thu Mar 10 20:51:13 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * a lot of mingw32 port work, lF is now able to compile as a DLL
+         using a special gstep-make
+       
+Wed Feb  9 18:25:43 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/GNUmakefile.alone: fixed bug introduced by adding cvtutf.c
+
+Wed Feb  9 17:27:31 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSConcreteString.m (quoteString): only quote newlines
+         and double-quotes
+
+Wed Feb  9 14:42:11 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * worked on mingw32 port (some fixes, support for new headers)
+
+Tue Feb  8 18:22:47 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSCalendarDate.m ([NSCalendarDate -initWithYear:month:day:hour:minute:second:timeZone:]): replaced year 0 with year 2000
+
+Mon Jan 24 15:46:44 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSString.m ([NSString +availableStringEncodings]): 
+         updated to Unicode, UTF8, Latin1 and ASCII
+       
+       * Foundation/NSString.m ([NSString +defaultCStringEncoding]): 
+         changed default encoding to ISOLatin1.
+
+       * Foundation/NSString.m ([NSString -dataUsingEncoding:allowLossyConversion:]): 
+         added several string encoding formats. Assumes that the environment
+         encoding is ISO Latin1.
+       
+       * Foundation/NSString.m ([NSMutableString -initWithData:encoding:]):
+         added decoding of UnicodeStringEncoding and UTF8StringEncoding
+         (both still limited since NSString can only hold 8-bit)
+
+Mon Jan 24 11:19:49 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation: added NSConnection.h and NSDistantObject.h (empty
+         files added for header-file compatibility)
+
+       * Foundation: added file NSDebug.h (available in both, gstep-base and
+         MacOSX-S
+
+       * Foundation/NSString: added GSAdditions category with 
+         stringWithoutPrefix: and stringWithoutSuffix: methods.
+
+       * Foundation/lfmemory.h.in: added DESTROY and ASSIGNCOPY macros to
+         be more compatible with GNUstep code
+
+Fri Jan 21 15:58:37 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSPathUtilities.m ([NSString +pathWithComponents:]): bugfix
+         (method was broken)
+
+Thu Jan 20 14:31:39 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSObjCRuntime.m: avoids usage of 'cString'
+
+Wed Jan 19 16:35:47 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * NSObject.h.in: include lfmemory.h from Foundation if GNUSTEP is not
+         defined (to support installations without GNUstep)
+
+Wed Jan 19 11:00:57 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSObjectAllocation.m: added allocation log facility
+         controlled via the 'NSLogAlloc' environment variable
+
+       * Foundation/common.h: added 'WITHOUT_ZONES' define to avoid the
+         management overhead of zones during memory allocation if they are
+         not used anyway
+
+       * Foundation/GNUmakefile.alone (HFILES): added lfmemory.h to HFILES
+         and delete it during distclean
+
+Fri Jan 14 20:46:20 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/common.m (Avsprintf): cache the object-format object
+
+       * Foundation/NSAutoreleasePool.m: added instance reuse cache for 
+       NSAutoreleasedPointer
+
+       * Foundation/NSNumber.m (makeInt): caches NSNumbers 0-63, added LRU
+       cache for smaller and bigger ones.
+
+       * Foundation/NSNumber.m ([NSTemporaryNumber -initWithBool:], [NSNumber +numberWithBool:): 
+         added shared objects for YES and NO (NSBoolNumber's ..)
+
+Thu Jan 13 19:27:27 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSObjectAllocation.m (NSDeallocateObject): added support
+         for zombie objects
+
+       * Foundation/*TimeZone*|*Date*: made tz details more smart about the
+         timezone they belong to.
+
+Wed Jan 12 18:05:50 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSConcreteTimeZone.m ([NSConcreteTimeZone -timeZoneForDate:]): added timeZoneForDate: (new in MacOSX-S)
+
+Mon Jan 10 13:05:28 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSScanner.m ([NSScanner -scanUpToString:intoString:]): 
+         modified to return YES only if there was a match (previously empty
+         strings counted as match too)
+
+       * sharedlib.mak (SHARED_LIB_LINK_CMD): fixed bug in linker call
+         (-W,l,soname= was used instead of -Wl,-soname=)
+
+Tue Jan  4 17:26:37 2000  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSString.m (-hasPrefix:,-hasSuffix:): modified to return
+         NO if the argument has zero length, as in MacOSXS
+
+Fri Dec 17 04:13:38 1999  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSPathUtilities.m ([NSString -stringByResolvingSymlinksInPath]): 
+         returns 'self' on error now, as described in MacOSXS documentation.
+         Adjusted other places in the lF to explicitly check whether the path
+         exists.
+
+       * Foundation/NSPathUtilities.m ([NSString -stringByStandardizingPath]): 
+         does not return 'nil', but 'self', if it cannot resolve the path
+       
+       * Foundation/NSString.m ([NSString -substringFromIndex:]): correctly
+         does range check now (length-index could go negative which is positive
+         in 'unsigned int' ..)
+
+       * common.h: changed name of function 'Free' to 'lfFree' since 'Free'
+         is often used by other C libraries (eg on MacOSXS).
+
+Wed Dec 15 03:24:04 1999  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/UnixSignalHandler.m: fixed bug introduced by new
+         -performSelector:withObject:
+
+       * Foundation/NSTask.m ([NSTask +launchedTaskWithLaunchPath:arguments:]):
+         make subtask's inherit the environment of the callee
+
+Thu Dec  9 15:30:59 1999  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSObject.m ([NSObject -performSelector:withObject:]):
+         changed to handle primitive argument types in target selector
+
+Thu Dec  9 01:59:24 1999  Helge Hess  <helge.hess@mdlink.de>
+
+       * added prototype of NSUndoManager (not implemented yet)
+
+Tue Dec  7 03:58:55 1999  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSObjectInvocation.m: added -description method
+
+Thu Nov 25 15:15:56 1999  Helge Hess  <helge.hess@mdlink.de>
+
+       * fixed stuff in property list generation
+       
+       * Foundation/PropertyListParser.m: separate break-chars for unquoted
+         strings
+
+       * Foundation/NSConcreteDictionary.m: better description in exception
+         if nil keys/objects are added to a dictionary
+
+Wed Nov 24 00:31:36 1999  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSBundle.m ([NSBundle -pathsForResourcesOfType:inDirectory:]): 
+         provided basic implementation for this method
+
+Mon Nov 22 16:58:52 1999  Helge Hess  <helge.hess@mdlink.de>
+
+       * NSDictionary, NSConcreteDictionary: fixed bugs related to 
+         NSSmallDictionary's (dictionaries smaller than 8 entries)
+
+Wed Nov 10 15:07:14 1999  Helge Hess  <helge.hess@mdlink.de>
+
+       * added format-scanner handlers that operate on NSEnumerator objects,
+         not on va_lists.
+
+Wed Nov  3 17:42:24 1999  Helge Hess  <helge.hess@mdlink.de>
+
+       * bug fixed examples/GNUmakefile.alone and Foundation/GNUmakefile.alone
+
+Tue Nov  2 23:55:04 1999  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSScanner.m ([NSScanner -scanCharactersFromSet:intoString:]): acknowledge charactersToBeSkipped
+
+       * Foundation/NSConcreteCharacterSet.m ([NSMutableBitmapCharacterSet -addCharactersInString:]): fixed out-of-range bug in for-loop
+
+Mon Nov  1 14:21:44 1999  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSDate.m ([NSDate +timeIntervalSinceReferenceDate]): 
+         fixed bug on Linux where gettimeofday() doesn't return timezone
+         correction
+
+Thu Sep 30 17:56:06 1999  Ovidiu Predescu  <ovidiu@cup.hp.com>
+
+       * Foundation/lfmemory.h.in: Added emacs variables so that the file
+       is recognized as an Objective-C file.
+
+       * configure.in: Recognize i686 machines.
+
+Thu Sep 16 18:21:02 1999  Helge Hess  <helge.hess@mdlink.de>
+
+       * Foundation/NSUserDefaults.m: added -setSearchList: method and
+         modified -searchList to return a non-mutable array
+
+Fri Sep 10 16:01:51 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSArray.m ([NSMutableArray +arrayWithContentsOfFile:]):
+         fixed bug (method sometimes created non-mutable arrays)
+
+       * Foundation/NSConcreteUnixTask.m: added -interrupt method (new in
+         MacOSX-S). Changed semantics of NSTaskDidTerminateNotification, which
+         is send always now (previously only when -terminate was called).
+
+Fri Sep  3 19:18:26 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSConcreteString.m (quoteString): fixed bug in this func
+
+Tue Aug 31 10:35:25 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSConcreteString.m(-stringRepresentation): bugfix:
+         some characters in string representations were not quoted correctly,
+         including '\', leading to incorrect plist output
+
+Mon Aug 30 15:20:26 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/PropertyListParser.m (_parseString): bugfix:
+         function didn't unquote '\r' in property-list strings
+
+Fri Aug 27 13:00:59 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSObjectInvocation.m: -invoke calls -forwardInvocation:
+         if the target has no matching method
+
+Thu Aug 26 10:31:09 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSRunLoop.m ([NSRunLoop -acceptInputForMode:beforeDate:]):
+         method doesn't catch exceptions anymore
+
+Wed Aug 25 18:21:27 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSMethodSignature.m: got -description method
+
+       * Foundation/NSFrameInvocation.m: verify signature before 'getting'
+         arguments
+
+Thu Jul 22 16:33:24 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * NSFrameInvocation.m, NSObjectInvocation.m: added method
+         -invokeWithTarget:lookupAtClass: (this is useful for interpreter 
+         bindings, too)
+
+       * NSFrameInvocation.m, NSObjectInvocation.m: added method
+         -superInvokeWithTarget: (this is useful for interpreter bindings)
+
+Fri Jul  2 19:40:42 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSZone.[hm]: avoid calling [NSZone defaultZone] in
+         NSZone* functions (because of GNU ObjC runtime deficiencies in
+         calling class methods ..)
+
+       * Foundation/NSArray.m, Foundation/NSConcreteArray.m:
+         avoid allocation of '0' sized malloc blocks
+
+       * Foundation/NSSet.m: fixed bugs in set operations
+
+       * Foundation/NSSet.m, Foundation/NSConcreteSet.m: changed -*copy* to
+         make a shallow copy, not a deep one (the elements are *not* copied).
+
+       * Foundation/NSConcreteSet.m ([NSCountedSet -initWithSet:copyItems:]):
+         fixed RC leak in copy-mode
+
+       * Foundation/NSConcreteSet.h, Foundation/GCDictionary.m: 
+         fixed enumerators to inherit from NSEnumerator
+
+Tue Jun 29 18:54:33 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSPathUtilities.m: added 
+         NSSearchPathForDirectoriesInDomains() function
+
+       * Foundation/NSPathUtilities.m: added NSOpenStepRootDirectory(),
+         NSStandardApplicationPaths() and NSStandardLibraryPaths() functions
+
+Thu Jun 24 13:04:11 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSConcreteString.m: fixed bug in -getCString:maxLength:...
+         (the trailing zero wasn't added)
+
+       * configure.in: replaced test's with '==' with '='
+
+Mon Jun 21 14:03:49 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/GNUmakefile: export NSCalendarDate.h
+
+Fri Jun 18 13:28:34 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * added NSPortNameServer, NSPort, NSPortMessage classes. Not implemented
+         yet
+
+       * configure.in, configure, config.h.in, config.make.in: removed --fast-rc
+
+Thu Jun 17 18:44:52 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/common.m (writeToFile): fixed bug, file was not
+         truncated, if already existent
+
+       * Foundation/NSCalendarDateScannerHandler.m: fixed bug in %z calendar
+         format (which is supposed to output (+/-)HHMM but did output
+         GMT(+/-)HHMM)
+
+Tue Jun 15 12:15:13 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSBundle.m: changed notifications to behave like on
+         MacOSX-S, notably only one notification is sent, if a bundle is loaded.
+
+Fri Jun  4 12:15:49 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSConcreteString.m: reenable old variant of NXConstantString
+         overloading because of runtime problems during dynamic loading with
+         the new approach
+
+       * Foundation/NSBundle.m: fixed problems with unresolved categories
+         (categories for which no class is yet registered)
+
+Tue Jun  1 13:57:51 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * configure.in, aclocal.m4: added (and use) the macro 
+         AC_COMPILE_CHECK_SIZEOF instead of AC_CHECK_SIZEOF (the macro is from
+         the autoconf macro repository)
+
+       * Foundation/NSBundle.m: LIB_FOUNDATION_RESOURCES_PATH is now splitted
+         using ';' on Windows (still ':' on Unix). This is required to be
+         able to include volumes in the path on Windows (eg 'C:\lF;D:\lF')
+
+       * renamed INSTALL to INSTALL.txt
+
+       * configure, configure.in: added checks for common C type sizes
+
+       * GNUmakefile.alone, GNUmakefile.gnustep: added NSObjectInvocation.m
+         and NSFrameInvocation.m
+
+       * NSInvocation.m, NSObject.m: NSInvocation became an abstract class
+         with two concrete subclasses: NSFrameInvocation for __builtin_apply*
+         based invocation and NSObjectInvocation for manual invocation 
+         (currently only available for methods taking object parameters).
+
+       * NSMethodSignature.m, NSObject.m: moved method signature cache to
+         from -methodSignatureForSelector: to the NSMethodSignature
+         constructor.
+
+Tue May 25 13:19:56 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * NSObject.m, NSProxy.m: use new NSExtraRefCount() instead of
+         NSGetExtraRefCount().
+
+       * NSHashMap.m, NSObject.h.in, NSZone.[hm], common.h, load.m: 
+         use lfmemory.h instead of objcgc.h
+
+       * GNUmakefile.postamble: install lfmemory.h in an architecture dependend
+         header directory
+
+       * GNUmakefile.alone, GNUmakefile.gnustep: added the concrete task
+         classes to the build process
+
+       * Foundation/NSHost.m: renamed method -initWithName: to
+         -initWithDottedRepresentation: because it conflicts with -initWithName:
+         of NSAutoreleasedPointer.
+
+       * configure.in, configure, config.h.in: added --fast-rc configuration
+         option. This
+         is used to make the RC macros directly access the RC instead of
+         calling the appropriate methods. This makes speedier but non-OpenStep
+         conform code (overriding the methods has no (or invalid) effect).
+
+       * removed file objgc.h.in and added new platform dependend memory file
+         lfmemory.h.in.
+
+       * NSObject.m, NSObjectAllocation.m, NSProxy.m, NSUtilities.h:
+         changed NSGetExtraRefCount() to NSExtraRefCount(). NSGetExtraRefCount()
+         is still available for linking old libraries.
+
+Fri May 21 12:16:51 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSTask.m: moved system specific parts out of NSTask.m.
+         NSTask.m only contains the abstract NSTask class and the new files
+         NSConcreteUnixTask.[hm] and NSConcreteWindowsTask.[hm] were added.
+
+Thu May 20 10:48:17 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSArray.m ([NSArray -componentsJoinedByString:]): returns
+         an empty string if the array contains no elements (previously returned
+         nil)
+
+       * Foundation/load.m: moved the #include's out of the function. This
+         produced coredumps in mingw32-egcs (the #include of windows.h in
+         the function)
+
+Mon May 10 19:15:08 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSFileManager.m: separate -createDirectory:atPath:
+         method for mingw32
+
+       * config.mak.in (LIBS): added some Windows libraries when linking for
+         mingw32
+
+Fri May  7 18:34:05 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSObject.m ([NSObject -methodSignatureForSelector:]): 
+         NSObject now caches method signature objects.
+
+       * configure.in: when compiling without gstep-make NSException.h is
+         now created by copying the real exception file instead of just linking
+         it. This is required for cygwin/mingw32 where linking does not work.
+
+Wed Apr 14 18:24:04 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * configure.in, config.h.in, configure, Foundation/config.h:
+         added --with-fast-strings option
+
+       * Foundation/NSConcreteDictionary.[hm], Foundation/NSDictionary.m: 
+         added capability to disable 'small-dictionary' concrete subclasses.
+
+Fri Apr  9 13:36:01 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * NSPathUtilities.m(-isAbsolutePath): on mingw32, check for ':' in path
+
+       * configure.in: catch some undefined variables by prefixing with 'x'
+
+       * NSProcessInfo.m: on mingw32 recognize both, slash and backslash, when
+         determining the process name.
+
+Fri April 8 08:21:07 1999 Ovidiu Predescu <ovidiu@cup.hp.com>
+
+        * objc-features.texi: Updated the URL to Boehm's GC page.
+
+Thu Apr  1 16:11:29 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * examples: added printenv tool. printenv prints out the environment
+         variables as returned by NSProcessInfo.
+
+Thu Apr  1 16:09:33 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/common.m (writeToFile): modified not to use 
+         NSPosixFileDescriptors (uses open()/CreateFile() instead).
+
+       * Foundation/NSFileManager.m: (not yet finished) support of
+         -movePath:.. and -copyPath:.. for mingw32
+
+       * Foundation/NSFileManager.m: fixed for mingw32
+
+       * Foundation/NSGeometry.m: renamed RECT and VALID functions to lfRECT
+         and lfVALID since they collide with windows.h types/functions.
+
+       * Foundation/NSString.m, Foundation/NSConcreteString.m, 
+         Foundation/NSData.m: use NSReadContentsOfFile() instead of
+         duplicated open/read/close sequences.
+
+       * Foundation/NSUserDefaults.m: various fixes, cleanups and warning
+         fprintf(stderr)'s.
+
+       * Foundation/NSVMPage.m: added separate getpagesize() function for
+         mingw32 compilation
+
+       * Foundation/PropertyListParser.m: print log if NSData of a property
+         list file could not be read in.
+
+       * Foundation/common.[hm]: added NSReadContentsOfFile() function that
+         read a whole file into a buffer allocated by NSZoneMalloc(). This
+         function is used by -initWithContentsOfFile: methods to avoid code
+         duplication. The function supports Windows file IO.
+
+       * Foundation/NSCharacterSet.m: added checks to warn if a set could
+         not be created from a data object.
+
+Wed Mar 31 16:54:02 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSAccount.m: added mingw32 support
+
+       * Foundation/NSUserDefaults.m: use NSHomeDirectory() instead of
+         NSHomeDirectoryForUser(NSUserName())
+
+       * Foundation/common.[hm]: added functions to convert between
+         Windows wide strings and NSString objects.
+
+       * Foundation/NSProcessInfo.m: improved mingw32 support
+
+       * Foundation/NSString.m: fixed some memory related bugs in string
+         methods
+
+Tue Mar 30 13:37:56 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * examples: added printenv tool
+
+       * configure.in, config.h.in: added check for objc_malloc
+
+       * README: updated email address of Ovidiu, added link to libFoundation
+         home page.
+
+       * examples/Defaults.m: check return value of -synchronize
+
+       * Foundation/NSUserDefaults.m: print warnings if unable to save changes
+         in persistent domains.
+
+       * Foundation/NSObject.h.in: only define ASSIGN,RETAIN macros if not
+         yet defined.
+
+Wed Mar 24 18:16:50 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSTimer.h: added -timeInterval method
+
+Sun Mar 21 17:23:07 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSCharacterSet.m: MT bugfix
+
+       * Foundation/libFoundation.make.in: fixed bug in makefile
+
+Fri Mar 19 12:52:11 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * added config/i386/mingw32.h (more or less a copy of cygwin.h)
+
+       * Foundation/NSAccount.m: prepared for Win32
+
+       * Foundation/NSHashMap.m: support for LIB_FOUNDATION_LEAK_GC
+
+       * Foundation/GNUmakefile.postamble: installs objcgc.h
+
+       * configure.in: generate objcgc.h from objcgc.h.in
+
+       * config.mak.in: added support for GC_INCLUDE_DIR, GC_LIB
+
+       * config.h.in: include gc.h/gc_typed.h from GC_INCLUDE_DIR determined
+         by configure
+
+       * Foundation/load.m: include objcgc.h instead of gc.h
+
+       * added Foundation/objcgc.h.in.
+
+       * Foundation/common.h: support for LIB_FOUNDATION_LEAK_GC, include 
+         objcgc.h instead of gc.h
+
+       * Foundation/UnixSignalHandler.m: currently unused on Mingw32, does not
+         break during compilation (print a warning on compile)
+
+       * Foundation/UnixSignalHandler.h: included signal.h instead of
+         sys/signal.h on mingw32
+
+       * Foundation/NSZone.h: include objcgc.h instead of gc.h
+
+       * Foundation/NSThread.m: support for Windows Sleep() function in mingw32
+
+       * Foundation/NSObjectAllocation.m: include objcgc.h instead of gc.h.
+         Support for LIB_FOUNDATION_LEAK_GC.
+
+       * Foundation/NSHost.m, Foundation/NSPosixFileDescriptor.m: include 
+         winsock.h if compiling for mingw32
+
+       * Foundation/NSConcreteFileHandle.m, Foundation/NSPipe.m,
+         Foundation/NSTask.m: prepared for 
+         mingw32 port (does compile on mingw32, but doesn't implement 
+         everything).
+
+       * Foundation/NSAllocDebugZone.m, Foundation/NSDefaultZone.m,
+         Foundation/NSVMPage.m, Foundation/NSZone.m, Foundation/StackZone.m: 
+         now uses objc_* memory management functions instead of stdlib ones.
+
+Thu Mar 18 15:34:43 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSFileManager.m ([NSFileManager -contentsAtPath:]):
+         implemented method using +[NSData dataWithContentsOfFile:]
+
+Wed Mar 17 19:02:56 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSDictionary.m(-copyWithZone:): bugfix. copy used current
+         class to create new object. This is invalid with mutable dictionaries,
+         the result of copy on a mutable dictionary is an immutable one.
+
+       * Foundation/NSArray.m(-copyWithZone:): copy did make a deep copy,
+         changed to shallow copy.
+
+       * configure.in: modified GC configuration. It's now possible to specify
+         the include path containing gc.h and the library containing GC
+         functions (usually libgc.a)
+
+       * Foundation/NSDate.m(+timeIntervalSinceReferenceDate): 
+         support for mingw32, uses GetSystemTime()
+       
+       * Foundation/NSNumberFormatter.m: use own index() function on mingw32
+       
+       * Foundation/NSPathUtilities.m: define PATH_MAX after including
+         common.h. 
+         NSTemporyDirectory() now returns C:\TEMP when compiling
+         to mingw32 (should use GetTempPath() function).
+         Vars pathSeparator and rootPath are set to '\' and 'C:\' on mingw32.
+       
+       * Foundation/NSUtilities.m, Foundation/NSProcessInfo.m: include 
+         windows.h if available, use GetCurrentProcessId() instead of getpid()
+         on mingw32
+
+       * Foundation/byte_order.h: include winsock.h if compiling to mingw32
+
+       * changed to configure scripts to support cross compilation, added
+         README.mingw32.
+
+Tue Feb 23 12:59:21 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSTask.m: fixed to be able to use both, NSPipe and NSTask.
+
+       * Foundation/NSConcreteDictionary.m, Foundation/NSDictionary.m: added 
+         new concrete classes for small, single and empty dictionaries.
+
+       * Foundation/NSCalendarDateScannerHandler.m: changed -AM_PM:scanner: 
+         that 12:00 is 12:00PM, not 12:00AM as previously.
+
+       * Foundation/NSCalendarDateScanf.m: changed -hour method to handle
+         '12:00 AM' for formats like '%I:%M %Z'. 12:00AM is equal to 0:00AM
+         and required by Sybase. Note that 12:00AM is before 12:00PM.
+         Previously 12:00AM became 12:00PM.
+
+Wed Jan 27 17:32:47 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSString: added +string method for NSString and
+         NSMutableString
+
+Wed Jan 27 17:05:13 1999  Ovidiu Predescu  <ovidiu@cup.hp.com>
+
+       * AUTHORS: Added Helge to the list of authors as he has
+       contributed with lots of development work recently.
+
+Wed Jan 27 16:20:39 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSConcreteDate.m ([NSConcreteDate -compare:]): fixed
+         method. NSDate's compare can now compare against NSCalendarDate.
+
+Mon Jan 25 11:24:13 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSException.m, Foundation/NSString.m, 
+         Foundation/NSTimeZone.m, Foundation/NSObject.m:
+         replaced printf(...) with fprintf(stderr, ...)
+
+       * Foundation/NSCalendarDate.m: changed NSCoding of NSCalendarDate to
+         use timezone abbreviations instead of timezone names.
+
+Thu Jan 21 14:53:07 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSUtilities.m: added NSHostByteOrder() function
+
+       * Foundation: added NSProxy class (not yet ready)
+
+Wed Jan 20 19:16:44 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSCalendarDateScannerHandler.m: changed formats for day
+         of month and hour to be 0 padded (format is %02d) as described
+         in the online docs from Apple.
+
+       * Foundation/PropertyListParser.m: check for 'nil' path argument
+         (returns immediatly nil), added missing mode argument for open()
+
+       * Foundation/NSUserDefaults.m: allow property list as default values
+         in command line user defaults
+
+       * Foundation/NSString.m: -initWithData:encoding: supported for
+         defaultCStringEncoding (otherwise notImplemented is called),
+         fixed RC bug in -stringByAppendingFormat:
+
+       * Foundation/NSRunLoop.m: support for -isAlive of file objects. Before
+         file objects are added to the select mask the isAlive method is
+         invoked to check whether the descriptor of the object is still valid.
+         This is necessary for sockets which may shutdown unrecognized and 
+         result in a endless loop of EBADF errors of the select() call.
+
+       * Foundation/NSConcreteString.m, Foundation/NSString.m: added missing 
+         mode argument to open call in -initWithContentsOfFile:.
+
+Tue Jan 19 20:23:22 1999  Ovidiu Predescu  <ovidiu@slip.net>
+
+       * Foundation/NSHost.m: Fixed for Linux as gethostbyaddr_r has a
+       different prototype.
+       * README.sparc: Reformatted for 80 columns.
+
+Tue Jan 19 11:38:09 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSCalendarDate.m (day_in_year): fixed bug, nDays[month]
+         was accessed instead of nDays[month - 1]
+
+Mon Jan 18 15:31:57 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/PropertyListParser.m (NSParsePropertyListFromFile): check
+         for nil path argument (immediatly returns nil if path is nil)
+
+Fri Jan 15 08:49:49 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSConcreteDictionary.[hm]: changed superclass of
+         _NSConcreteDictionaryKeyEnumerator and _NSDictionaryObjectEnumerator
+         from NSObject to NSEnumerator, added 
+         _NSConcreteSingleObjectDictionaryKeyEnumerator
+         added NSConcreteEmptyDictionary, NSConcreteSingleObjectDictionary
+         subclasses
+
+       * Foundation/NSConcreteArray.[hm]:
+         added NSConcreteEmptyArray and NSConcreteSingleObjectArray subclasses
+
+Wed Jan 13 19:21:38 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSFileManager.m (-_copyFile:toFile:handler:):
+         added missing zero in open() call.
+
+       * Foundation/NSHost.m: removed RC bugs in host object cache
+
+Mon Jan 11 19:23:07 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSCalendarDate.m: applied patch reported by
+         pascal@rossini.infopark.de. The patch fixes some incorrect
+         behaviour with leap years.
+
+Sun Jan 10 12:21:52 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSUtilities.m: added NSHostByteOrder() functions
+       
+       * Foundation: added NSByteOrder.h
+
+Sun Jan 10 03:43:15 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSUserDefaults.m ([NSUserDefaults -initWithPath:]): 
+         added support for NSArgumentDomain
+
+Fri Jan  8 14:18:35 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSDateFormatter.m ([NSDateFormatter
+       -stringForObjectValue:]): changed to format NSDate objects
+       (previously only NSCalendarDate's)
+
+Fri Jan  8 11:06:41 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSFileManager.m ([NSDirectoryEnumerator -dealloc]): 
+         fixed bug, [super dealloc] was not called.
+
+       * Foundation/NSDictionary.m: fixed RC bug in the -descriptionWi...
+         method.
+
+Wed Jan  6 13:23:54 1999  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSData.m: fixed RC bug in -initWithContentsOfMappedFile:,
+         the return value of the method was autoreleased
+
+Wed Dec 30 22:03:22 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation: added first implementation of NSNumberFormatter class
+
+Wed Dec 30 19:37:42 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSString.m: implemented -initWithCharacters.. for
+       characters below code value 128 (unicodes below 128 are equal to
+       ASCII code)
+
+Wed Dec 30 12:50:45 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSDateFormatter.m
+         ([NSDateFormatter -initWithDateFormat:allowNaturalLanguage:]): 
+         throw exception if a non-NSString and non-nil format is passed in.
+
+       * Foundation: added NSDateFormatter class
+
+Mon Dec 28 21:23:46 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSTask.m: added -description method
+
+Mon Dec 28 17:50:29 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSCalendarDate.m (day_in_year): fixed operator precedence
+         bug which leaded to incorrect results
+
+       * Foundation/NSTimeZone.m, Foundation/NSDate.h: 
+         added some new MacOSX methods
+
+       * Foundation/NSConcreteTimeZone.m: changed -init.. to copy strings
+
+       * Foundation/NSConcreteTimeZoneDetail.m: changed -dealloc to release
+         'name' ivar. Changed -init.. to copy strings.
+
+       * Foundation/NSCalendarDate.m: changed description methods to use
+         their own timeZoneDetail if no timeZone was passed as a parameter.
+
+       * Foundation/NSCalendarDate.m ([NSCalendarDate -setTimeZone:]):
+         fixed implementation, previous version allowed a 'nil' timezone
+         (which now gets a local timezone).
+
+       * Foundation/NSCalendarDate.m
+       ([NSCalendarDate
+       -initWithYear:month:day:hour:minute:second:timeZone:]): adjust
+       timeSinceRef to 'timeZone'
+
+       * Foundation/NSCalendarDate.m: fixed language bug (Thursday, not
+       Thusday)
+
+Wed Dec 23 11:16:15 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSThread.m: changed to throw an exception if the thread
+         couldn't be created.
+
+Mon Dec 21 14:40:01 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSArchiver.m: changed to make encoding of multiple
+       root objects possible. Changed to support archive-internal
+       references.
+
+Mon Dec 21 12:36:47 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSArchiver.m: replaced THROW's with +raise:format:,
+       bugfixes in decodeClass: class name was not freed and it didn't
+       support decoding of Nil classes.
+
+Mon Dec 21 12:14:16 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSData.m ([NSData -encodeWithCoder:]): fixed bug,
+       tried to encode &bytes as array of char. 'bytes' itself is already
+       the array of char (no need to take the address ..)
+
+       * Foundation/NSRunLoop.m ([NSRunLoop
+       -acceptInputForMode:beforeDate:]): take address of
+       'fileObjectsCopy' to avoid warning in exception handler
+
+       * Foundation/NSDate.m ([NSDate
+       -descriptionWithCalendarFormat:timeZone:locale:]): assign
+       'timeZone' parameter to calendar object created for output
+
+       * Foundation/NSCalendarDate.m: added -timeZone method, as
+       described in MacOSX docs (replaces -timeZoneDetail in
+       MacOSX). Changed -setCalendarFormat: to copy the parameter instead
+       of just retaining it.
+
+       * Foundation/NSBundle.m ([NSBundle -loadCode]): set 'load_Classes' NULL
+         after call to Free()
+
+       * Foundation/NSArchiver.m: small fix in +initialize
+
+       * Foundation/NSTimeZone.m ([NSTimeZone +defaultTimeZone]):
+         changed to return 'NSTimeZone' instead of 'NSTimeZoneDetail', as
+         described in MacOSX docs
+
+       * Foundation/NSDictionary.m, Foundation/NSArray.m, Foundation/NSData.m: 
+         cleanup, assign return value of nested '-init..' invocations to self.
+
+       * Foundation/NSCalendarDateScannerHandler.m: 
+         use detail of localTimeZone if no timezone was given to 
+         -initForCalendarDate:timeZoneDetail:. Array of fixed strings for
+         common output (minutes, seconds) to avoid constant creation of
+         string objects.
+
+Sat Dec 12 01:44:43 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSCalendarDate.m: changed incorrect correction of
+       timeSinceRef ivar (was corrected to timeZone), changed -compare:
+       to compare against all subclasses of NSDate, changed
+       +descriptionFor... to set the timeZone requested (and restore it
+       after string generation).
+
+Sat Dec 12 01:32:41 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSDate.m: timezone was corrected twice in 
+         +timeIntervalSinceReferenceDate
+
+       * Foundation/NSConcreteSet.m: added initWithCapacity: method to
+       NSMutableSet
+
+Wed Dec  2 05:09:04 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/GarbageCollector.m, Foundation/NSAllocDebugZone.m,
+         Foundation/NSNotificationCenter.m, NSThread.m:
+         replaced calls to perform: with performSelector:
+
+Wed Dec  2 05:05:47 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSCharacterSet.m: added +characterSetWithContensOfFile:,
+         +characterSetWithCharactersInString: and characterSetWithRange:
+         class methods to NSMutableCharacterSet.
+
+Wed Dec  2 03:29:17 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSObject.h.in: removed perform:.. methods from
+       NSObject protocol perform: is replaced by performSelector: and not
+       specified in MacOSX docs anymore
+
+Tue Dec  1 17:18:40 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * NSArchiver.[hm]: replaced with new version
+
+       * config.h.in, configure.in: added autoconf checks for
+         gethostbyname_r(), gethostbyaddr_r(), gethostent_r(), 
+         recreated configure
+
+       * added NSFormatter class (abstract class)
+
+Mon Nov 23 11:05:40 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSCalendarDateScanf.m ([NSCalendarDateScanf +initialize]):
+         fixed RC bug (the static variable 'blanks' was not retained),
+         avoid multiple +initialize invocations
+
+Sun Nov 22 22:23:21 1998  Ovidiu Predescu  <ovidiu@slip.net>
+
+       * config/i386/linux.h (FUNCTION_VALUE): Don't copy the return
+       value in case of structures and unions since the __builtin_apply
+       operation already puts the return value in the correct place.
+
+Sun Nov 22 16:19:11 1998  Ovidiu Predescu  <ovidiu@slip.net>
+
+       * Foundation/NSInvocation.m: Applied patch from Helge Hess to
+       handle seeting the return value without actually invoking the
+       action on target. This is useful for handling returning from DO
+       invocations at the client side.
+
+       * Foundation/NSString.m ([NSString
+       -propertyListFromStringsFileFormat]): Call
+       NSParseStringsFromString() instead of
+       NSParseDictionaryFromString(). Don't create a new mutable copy
+       from the returned dictionary since this is already mutable.
+
+       * Foundation/ProperyListParser.[hm]: Change the return type of
+       NSParseStrings* methods to be id instead of NSDictionary*.
+
+       * Foundation/ProperyListParser.[hm] (_valueOfHexChar): Explicitly
+       specify how the return value is computed.
+       (_parseData): Correctly compute the byte's value from the two
+       hexadecimal digits.
+
+Mon Nov 16 13:03:18 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSDictionary.m: copyWithZone: performed a deep-copy
+       by calling 'initWithDictionary:self copyItems:YES'. NSDictionary
+       'copy' methods are assumed to do a shallow copy, so it was changed
+       to copyItems:NO.
+
+Thu Nov 12 22:51:39 1998  Ovidiu Predescu  <ovidiu@slip.net>
+
+       * Foundation/GNUmakefile.gnustep: Removed the hard-coded
+       definitions of foundation, gui and backend.
+       * examples/GNUmakefile.gnustep: Likewise.
+
+Wed Nov 11 16:54:42 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/GNUmakefile.alone: added PropertyListParser.m
+
+Wed Nov  4 22:08:41 1998  Ovidiu Predescu  <ovidiu@slip.net>
+
+       * Foundation/GNUmakefile.alone (clean): Don't remove the
+       libFoundation.make.in file.
+
+Wed Nov  4 18:08:09 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * replaced '#import' in PropertyListParser.h with '#include'
+
+Wed Nov  4 15:07:12 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSObject.m: added +isKindOfClass: method
+
+Tue Nov  3 20:19:33 1998  Ovidiu Predescu  <ovidiu@slip.net>
+
+       * examples/GNUmakefile.alone ($(DEFAULTS)): Removed the dependency
+       on $(LIB)/*$(libext).
+
+Tue Nov  3 12:25:56 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSCharacterSet.m: fixed bug in
+       +characterSetWithCharactersInString: (only immutable charsets were
+       created).
+
+Thu Oct 22 19:50:06 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSMethodSignature.m: added getArgumentTypeAtIndex:, a
+       method which replaced argumentInfoAtIndex: in Rhapsody.
+
+Thu Oct 22 11:47:14 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * added README.sparc with hints about SPARC and Solaris problems
+
+Tue Oct 20 16:32:42 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSString.m: fixed bug in getCString. The terminating
+       NULL byte was set on [length-1] instead of [length]
+
+Tue Oct 20 09:31:00 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSRunLoop.m: modified to support other types of file
+       descriptor objects, not only NSPosixFileDescriptors. The runloop
+       sends out notifications if activity is found on an object other than a
+       NSPosixFileDescriptor.
+
+Tue Oct 20 09:17:40 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * Integrated the new property list parser with the property classes
+       NSString, NSArray and NSDictionary. Modified the makefiles to exclude
+       the old pccts-based parser.
+
+Tue Oct 20 09:05:47 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSThread.m: fixed bug. The autorelease pool was created
+       before the current thread was set. Because of this the pool had no
+       owner and broke in 'dealloc'.
+
+Mon Oct 19 14:00:51 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/PropertyListParser.m: fixed bug in isBreakChar() function
+
+Mon Oct 19 10:21:44 1998  Helge Hess  <helge@trex.mdlink.de>
+
+       * added hand-written property list parser: PropertyList.[hm]
+
+Mon Oct 19 04:44:08 1998  Ovidiu Predescu  <ovidiu@slip.net>
+
+       * doc/libFoundation.texi: Updated the release number.
+       * configure.in: Likewise.
+
+       * ANNOUNCE: Updated the documentation.
+       * INSTALL: Likewise.
+       * NEWS: Likewise.
+       * README: Likewise.
+       * README.gc: Likewise.
+
+Sun Oct 18 02:37:14 1998  Ovidiu Predescu  <ovidiu@slip.net>
+
+       * doc/libFoundation.texi: Changed the @url to @uref.
+       * Foundation/NSProcessInfo.m ([NSProcessInfo -globallyUniqueString]):
+       Fixed to generate a really unique string (bug report and fix from
+       Helge Hess).
+
+1998-10-14  Helge Hess  <helge@trex.mdlink.de>
+
+       * Foundation/NSConcreteString.m ([NS8BitString -initWithCoder:]):
+       RC bug-fix, 'self' was not released and the replacement object was
+       autoreleased.
+       ([NSMutable8BitString -initWithCoder:]): same fix as in NS8BitString.
+
+Fri Oct  9 05:09:25 1998  Ovidiu Predescu  <ovidiu@slip.net>
+
+       * sharedlib.mak: Search for linux as substring in the host OS type.
+
+       * Foundation/NSData.m ([NSData -deserializeDataAt:ofObjCType:atCursor:
+       context:]): Put a 0 after a decoded string (bug report from Helge
+       Hess).
+
+       * Foundation/common.m (Avsprintf): Create local objects for the
+       format and scanner to avoid multithreaded problems.
+       * Foundation/PrivateThreadData.h: Remove the objectFormat and
+       formatScanner private thread objects.
+       * Foundation/load.m: Include gc.h to get the dl functions defined
+       in libgc.a (Report from Helge Hess).
+
+Tue Jun 30 22:27:00 1998  Ovidiu Predescu  <ovidiu@aracnet.com>
+
+       * INSTALL: Updated the installation instructions.
+
+Tue Jun  2 18:48:41 1998  Ovidiu Predescu  <ovidiu@aracnet.com>
+
+       * doc/libFoundation.texi (Porting NSInvocation): Describe the
+       FRAME_SET_ARGUMENT and FRAME_GET_ARGUMENT macros.
+       * config/powerpc/powerpc.h: The initial implementation of the
+       NSInvocation's macros. Only Struct3 is not working properly in
+       testsuite.
+       * Foundation/NSInvocation.m (-invokeWithTarget:): Reworked to
+       support AIX; the code uses now objc_msg_sendv instead of
+       explicitly invoking __builtin_apply. This seems to make forwarding
+       using NSInvocation work.
+       * Foundation/NSBundle.m (-loadCode): Define environment only for
+       the GNUstep environment.
+
+Sun May 31 21:35:23 1998  Ovidiu Predescu  <ovidiu@aracnet.com>
+
+       * Foundation/NSScanner.m (-[NSScanner scanUpToString:intoString:]):
+       Return the remaining string if the searched string is not found.
+
+Fri May 29 13:49:09 1998  Ovidiu Predescu  <ovidiu@aracnet.com>
+
+       * Foundation/NSAccount.m (-[NSGroupAccount
+       initWithGroupStructure:]): Allocate the array on heap instead of
+       stack to avoid problems on AIX.
+       * Foundation/NSConcreteString.m: Create a new class
+       DummyNXConstantString used as a prototype for
+       NXConstantString. The dummy class is copied over to the real
+       constant string class in the +load method. This is done to avoid
+       linking errors on AIX and possibly on other systems (including
+       Windows). The old way defined a new NXConstantString class
+       inherited from NSString and we assumed this class takes precedence
+       in the linking process over to the one in libobjc. We now use the
+       class from libobjc but we modify this class to be inherited from
+       NSString.
+       * Foundation/NSException.m: Fixed the code that changes the top
+       level exception handler. The code is supposed to also work in a
+       multithreaded environment but is not yet tested.
+       * Foundation/PrivateThreadData.m: Changes to support the above fix.
+       * Foundation/NSString.m (substringFromRange:): Call
+       substringWithRange: and not substringFromRange: ;-).
+
+       * Resources/GNUmakefile.gnustep: New file based upon GNUmakefile.
+       * Resources/GNUmakefile.alone: New file based upon GNUmakefile. We
+       need to differentiate the installation process when the resources
+       are installed in a GNUstep environment and when they are alone.
+       * configure.in: Correctly create the makefile in the Resources
+       directory.
+
+       * config/powerpc/powerpc.h: New file. Figured out the
+       APPLY_RESULT_SIZE and the APPLY_ARGS_SIZE values.
+
+Wed May 27 21:16:53 1998  Ovidiu Predescu  <ovidiu@aracnet.com>
+
+       * Started the port to AIX 4.1.
+       * config.h.in (HAVE_SYS_STATVFS_H, HAVE_SYS_SELECT_H,
+       HAVE_STRINGS_H): New defines.
+       * configure.in: New check for for sys/statvfs.h, sys/select.h,
+       strings.h.
+       * Foundation/NSFileManager.m: Include sys/statvfs.h if exists.
+       * Foundation/NSRunLoop.m: Include sys/select.h.
+       * Foundation/NSStringPropList.g: Define
+       NSStringPropertyListParser_errors as a global symbol to avoid problems
+       on AIX.
+       * Foundation/NSThread.m: Include sys/select.h.
+       * pccts/antlr.h: Define zztoken as a global symbol.
+
+Thu May 21 14:45:43 1998  Ovidiu Predescu  <ovidiu@aracnet.com>
+
+       * doc/libFoundation.texi: Updated the documentation.
+       * Foundation/NSZone.m (+initialize): Comment out when using Boehm's GC.
+
+Wed May 20 14:25:58 1998  Ovidiu Predescu  <ovidiu@aracnet.com>
+
+       Fixed bug reports from Helge Hess <helge@mdlink.de>.
+       * Foundation/GCZone.h: Removed.
+       * Foundation/GCZone.m: Removed.
+       * Foundation/common.h: Moved the THROW calls to __raiseMemoryException
+       to eliminate recursive definition of memoryExhaustedException.
+       * Foundation/common.m (__raiseMemoryException): Defined.
+       * Foundation/NSZone.h: Define the NSZone functions to work
+       directly with the Boehm's GC functions and eliminate the GCZone
+       previously used.
+       * Foundation/NSZone.m: Don't create the GCZone anymore.
+
+       Incorporate some bug fixes from Helge Hess <helge@mdlink.de>.
+       * Foundation/NSConcreteString.m (initWithCapacity:): Use NSZoneFree
+       instead of Free.
+       * Foundation/NSPosixFileDescriptor.m (writeString:range:): Repeat
+       the write operation until all the bytes are written or an error
+       occurs.
+       * Foundation/NSProcessInfo.m (initializeWithArguments:count:
+       environment:): Use Malloc to allocate keys and vals instead of
+       MallocAtomic.
+
+Tue May 12 11:48:44 1998  Ovidiu Predescu  <ovidiu@aracnet.com>
+
+       * doc/libFoundation.texi: New file.
+       * doc/CodingRules.pod: Removed.
+       * doc/GarbageCollector.pod: Removed.
+       * doc/NSMethodSignature.pod: Removed.
+       * doc/NSZone.pod: Removed.
+       * doc/exceptions.pod: Removed.
+       * doc/objc-runtime.pod: Removed.
+       * doc/NSInvocation.pod: Removed.
+
+       * AUTHORS: Updated.
+       * INSTALL.gc: Updated.
+       * NEWS: Updated.
+       * README: Updated.
+       * README.gc: Updated.
+
+       * Foundation/NSObject.h.in: Moved the RETAIN, RELEASE, AUTORELEASE,
+       CREATE_AUTORELEASE_POOL and ASSIGN macros from common.h.
+       * Foundation/common.h: Removed the above macros.
+
+Tue Apr 14 22:55:17 1998  Ovidiu Predescu  <ovidiu@aracnet.com>
+
+       * Foundation/NSArray.m (lastObject): Return nil when the array is
+       empty instead of raising an exception.
+       * Foundation/NSHashMap.m: Fix copy/paste bugs that incorrectly
+       create hash and map tables with both keys and values invisible to
+       GC when only keys where requested invisible.
+       * Foundation/NSMapTable.h (NSCreateMapTableInvisibleKeysOrValues):
+       Fixed the naming of the arguments.
+       * Foundation/NSNotificationCenter.m: Renamed addObjectsInList to
+       addObjectsToList. Move nilObjectObservers initialization out of
+       Boehm'GC dependent code. Likewise for nullNameToObjects.
+       * Foundation/NSString.m (getCString): Add a leading 0 to the end
+       of the buffer. (Bug reports from Helge Hess <hh@mdlink.de>)
+
+       * Foundation/GarbageCollector.m: Added the code that
+       differentiates between the list nodes used to keep the objects and
+       observers to be finalized and informed respectively. This code was
+       somehow not included in the previous version.
+       (+initialize): Use the pointer semantics for the object values
+       kept inside postingObjectsToObservers.
+       * Foundation/NSObjectAllocation.m (NSAllocateObject): Generate an
+       error if the typed memory description for the class is not already
+       generated by the runtime system (this indicates a bug in the runtime
+       code).
+       * Foundation/NSTask.m: Remove code that's not used when compiling with
+       Boehm GC support.
+
+       * Foundation/PrivateThreadData.h: Optimize the printf-like
+       formatting by creating per-thread variables for the
+       all the time allocated objects.
+       * Foundation/PrivateThreadData.m: Create the above variables when
+       requested.
+       * Foundation/common.m (Avsprintf): Use the above cached variables
+       instead of creating them at each invocation of the function.
+
+       * Added emacs variable for the tab width to the local variables
+       section in all the files.
+
+Wed Apr  1 19:51:01 1998  Ovidiu Predescu  <ovidiu@aracnet.com>
+
+       * Foundation/NSUserDefaults.m (syncronizeStandardUserDefaults:):
+       Correct typo (bug report from Helge Hess <hh@mdlink.de>).
+
+Wed Apr  1 18:51:54 1998  Ovidiu Predescu  <ovidiu@aracnet.com>
+
+       Added emacs variables to all the files.
+
+       * TODO: Updated.
+       * Foundation/NSObjectAllocation.m: Reset the memory allocated by
+       GC_CALLOC_EXPLICTLY_TYPED because it seems this function doesn't work
+       as expected.
+       * common.h: (RETAIN, RELEASE, AUTORELEASE, CREATE_AUTORELEASE_POOL):
+       New macros.
+
+       Use the new macros above throughout all the files to be able to
+       disable the reference counting alocation mechanism when Boehm's
+       garbage collector is used.
+
+Wed Mar 11 22:59:39 1998  Ovidiu Predescu  <ovidiu@aracnet.com>
+
+       * Foundation/GNUmakefile.gnustep: Support the new 'gc' make variable.
+       When gc=yes the object files go into $processor/$os/${runtime}-gc.
+       * examples/GNUmakefile.gnustep: Likewise.
+       * Foundation/GarbageCollector.m (gcCollect): Commented out the printed
+       message.
+       * Foundation/NSObject.h.in: Remove the LIB_FOUNDATION_BOEHM_GC
+       definition, it is now passed by the makefile package.
+       * Foundation/NSProcessInfo.m: Set the _usesBoehmGC variable in case
+       it's not setup properly.
+       * Foundation/behavior.m (class_add_behavior): Fixed a potential bug.
+       * Foundation/libFoundation.make.in: Protect the file to multiple
+       inclusions. Define the LIBFOUNDATION_WITH_GC variable.
+       * extensions/FormatScanner.h: Make the booleans bitfields once the
+       bitfields are fully supported by the runtime.
+       * extensions/GCObject.h: Likewise.
+
+Wed Mar  4 22:40:35 1998  Ovidiu Predescu  <ovidiu@aracnet.com>
+
+       * Foundation/GarbageCollector.m (newNode): Use
+       GC_MALLOC_EXPLICTLY_TYPED and memset instead of
+       GC_CALLOC_EXPLICTLY_TYPED because the last one is different than
+       the expected behaviour.
+
+Wed Mar  4 16:25:40 1998  Ovidiu Predescu  <ovidiu@aracnet.com>
+
+       * Foundation/NSNotificationCenter.m (NSNotificationListItem): Add new
+       instance variable to keep track later of allocated instances.
+       (-[NSNotificationObserverRegister removeObserver:]): Changed the code
+       to use a linked list of ListItem instances instead of an array to avoid
+       allocating objects, which presents problems with GC finalization.
+       (NSNotificationObjectRegister): Changed objectObservers to a map table
+       to be able to use a map table enumerator directly. This eliminates the
+       need of creating an object for the enumerator, which has problems in
+       the presence of finalization.
+       (NSNotificationCenter): Likewise for nameToObjects.
+       * Foundation/GarbageCollector.m (-registerForFinalizationObserver:
+       selector:object:): Register finalizers only for instances because class
+       objects were not allocated by the garbage collector.
+       (unregisterObserver:forObjectFinalization:): Protect the code by
+       locking the global lock.
+
+       * Use the ASSIGN macro where is possible.
+
+Wed Mar  4 12:01:34 1998  Ovidiu Predescu  <ovidiu@aracnet.com>
+
+       * config.mak.in: Define _TS_ERRNO when compiling under Solaris.
+       * extensions/GarbageCollector.h: Added support for registering
+       observers of object finalization. Separated the interface for the
+       garbage collector using reference counting and the Boehm's
+       collector.
+       * extensions/GCObject.h: Temporary remove the structure to avoid the
+       problems with encoding of bitfields in runtime.
+       * extensions/FormatScanner.h: Likewise.
+       * Foundation/FormatScanner.m: Likewise.
+       * Foundation/common.h: Changed the test to use LIB_FOUNDATION_BOEHM_GC
+       instead of WITH_GC.
+       * Foundation/NSZone.m: Likewise.
+       * Foundation/NSObjectAllocation.m: Likewise.
+       * Foundation/NSObject.m: Likewise.
+       * Foundation/GarbageCollector.m: Likewise.
+       * Foundation/GCZone.m: Likewise.
+
+       * Foundation/NSZone.m: Print a warning message in case the the program
+       is linked with a non-garbage-collected aware version of runtime.
+       Implement -calloc: in terms of -malloc:.
+       * Foundation/NSObjectAllocation.m (NSAllocateObject): Use typed
+       allocation of objects.
+       (_do_finalize): Setup the isa pointer to the freed object class.
+       (__freedObjectClass): Made global variable.
+       * Foundation/NSNotificationCenter.m (+initialize): Set the 'observer'
+       variable as a GC invisible pointer.
+       (-removeObject:): New method.
+       (-init): Create the map table as partial invisible table.
+       (-addObserver:): Register the center for finalization notification.
+       (-objectWillFinalize:): New method.
+       (-observerWiFinalize:): New method.
+       * Foundation/NSMapTable.h (keysInvisible, valuesInvisible): New members
+       of the NSMapTable structure.
+       (NSCreateMapTableInvisibleKeysOrValues): New function.
+       * Foundation/NSHashTable.h (keysInvisible): New member of the
+       NSHashTable structure.
+       (NSCreateHashTableInvisibleKeys): New function.
+       * Foundation/NSHashMap.m: Support for the implementation of the above
+       functions.
+       * Foundation/NSDefaultZone.m (-mallocAtomic:): New method.
+       (-callocAtomic:byteSize:): Likewise.
+       * Foundation/GarbageCollector.m: Support code for registering and
+       unregistering observers of objects finalization. Separated the
+       implementation between the reference counting collector and the Boehm's
+       collector.
+
+Thu Feb 12 23:13:35 1998  Ovidiu Predescu <ovidiu@net-community.com>
+
+       * Foundation/GCAtomicZone.[hm]: Removed. Added the atomic allocation
+       methods to NSZone.
+
+Sun Feb  8 23:52:50 1998  Ovidiu Predescu <ovidiu@net-community.com>
+
+       Differentiate thoughout the whole library between normal and atomic
+       allocations.
+       * Foundation/FormatScanner.m: Use AtomicMalloc() instead of Malloc().
+       The same with AtomicCalloc() and Calloc().
+       * Foundation/GCArray.m: Likewise.
+       * Foundation/NSArray.m: Likewise.
+       * Foundation/NSBundle.m: Likewise.
+       * Foundation/NSCharacterSet.m: Likewise.
+       * Foundation/NSConcreteCharacterSet.m: Likewise.
+       * Foundation/NSConcreteData.m: Likewise.
+       * Foundation/NSConcreteFileHandle.m: Likewise.
+       * Foundation/NSConcreteString.m: Likewise.
+       * Foundation/NSData.m: Likewise.
+       * Foundation/NSDictionary.m: Likewise.
+       * Foundation/NSPosixFileDescriptor.m: Likewise.
+       * Foundation/NSSet.m: Likewise.
+       * Foundation/NSString.m: Likewise.
+       * Foundation/common.h: New AtomicMalloc() and AtomicCalloc() functions.
+       * Foundation/common.h (Strdup): Use AtomicMalloc().
+
+       * Foundation/NSZone.h (NSDefaultAtomicMallocZone, NSZoneAtomicMalloc,
+       NSZoneAtomicCalloc): New functions.
+
+       Moved the private NSThread variables in an object as instance variable.
+       * Foundation/NSAutoreleasePool.m: Use the new schema.
+       * Foundation/NSException.m: Likewise.
+       * Foundation/NSNotificationCenter.m: Likewise.
+       * Foundation/NSNotificationQueue.m: Likewise.
+       * Foundation/NSThread.h: Likewise.
+       * Foundation/NSThread.m: Likewise.
+
+       Optimization: cache the temporary string variables in a per thread
+       pool.
+       * Foundation/NSConcreteString.h (NSTemporaryString): next, new instance
+       variable.
+       * Foundation/NSString.m: Support code for the above caching schema.
+
+       * Foundation/GCAtomicZone.m: Use the equivalent macros so that is
+       possible to simply recompile with the appropriate flags and get the
+       debug versions of the Boehm's allocation functions.
+       * Foundation/GCZone.m: Likewise.
+
+       * Foundation/NSArchiver.m: Explicitly catch the exceptions generated
+       and release the pointers, as we may get pointers that are kept in a
+       map table but they are no longer available.
+       * Foundation/NSData.m: Likewise.
+
+       * Foundation/GarbageCollector.m: Added a definition for _usesBoehmGC
+       even if Boehm's GC is not available.
+       * Foundation/NSException.m: Log the exception's message using printf.
+       * Foundation/NSFileManager.m: Fixed misspelling.
+       * Foundation/NSObjectAllocation.m: The initial support code for
+       invoking a finalizer on an object.
+       * Foundation/NSUserDefaults.m: Added forgot -retain message. Assign
+       the global values to their variables immediately after the allocation
+       to avoid possible recursing in the same method.
+       * Foundation/behavior.m: Use objc_alloc and the friends instead of
+       Malloc and the rest because they can now be allocated from different
+       zones.
+       * examples/GNUmakefile.gnustep: Include libFoundation.make.
+
+       * config.mak.in: Moved the variables used in the standalone version
+       so that they don't override the GNUstep makefile package ones.
+       * configure.in: Fixed bug in assigning the value to the use_gnustep and
+       use_gc variables.
+       * Foundation/GNUmakefile.alone: Added PrivateThreadData.m.
+       * Foundation/GNUmakefile.gnustep: Likewise.
+       * Foundation/GNUmakefile.postamble (after-uninstall): New target to
+       remove libFoundation.make from the installation directory.
+
+Tue Feb  3 22:53:26 1998  Ovidiu Predescu <ovidiu@net-community.com>
+
+       * Foundation/GarbageCollector.m: Added a function hook that is called
+       when garbage collection takes place.
+       * Foundation/NSBundle.m: Initialize the global variables to NULL.
+       * Foundation/NSZone.h (defaultAtomicZone): New method.
+       * Foundation/NSZone.m: Implement the above method to return a
+       GCAtomicZone used to allocate atomic memory (memory that is not scanned
+       by garbage collector for pointers).
+
+Tue Feb  3 19:27:14 1998  Ovidiu Predescu  <ovidiu@net-community.com>
+
+       * configure.in: Properly check and output a message when using
+       Boehm's garbage collector.
+
+Tue Feb  3 07:04:04 1998  Ovidiu Predescu <ovidiu@net-community.com>
+
+       Integrated the Boehm's garbage collector.
+       * Foundation/GCZone.h: New file.
+       * Foundation/GCZone.m: New file.
+       * Foundation/GCAtomicZone.h: New file.
+       * Foundation/GCAtomicZone.m: New file.
+       * Foundation/libFoundation.make.in: New file.
+       * Foundation/NSObject.h.in: New file from NSObject.h.
+       * Foundation/NSObject.h: Removed.
+       * Foundation/libFoundation.make.in: New file.
+       * config.h.in: Added WITH_GC.
+       * config.mak.in: Likewise. Moved the version numbers in configure.in
+       and added support for automatically substituting them.
+       * configure.in: Support for substituting the version numbers in
+       config.make and NSObject.h. New flag --with-gc to build using the
+       Boehm's garbage collector.
+       * Foundation/GNUmakefile.alone: Remove NSObject.h and
+       libFoundation.make. Added GCZone and GCZAtomicZone.
+       * Foundation/GNUmakefile.gnustep: Likewise.
+       * extensions/GarbageCollector.h (+isBoehmGCAvailable, +usesBoehmGC):
+       New methods to determine at runtime the context in which we're running.
+       * Foundation/GarbageCollector.m: Use a mixed implementation, which
+       takes advantage of the Boehm's GC if present.
+       * Foundation/NSZone.h (+setDefaultZone:): New method.
+       * Foundation/NSZone.m: Added support for setting the default zone using
+       +setDefaultZone:.
+       * Foundation/NSDefaultZone.m: Removed unnecessary code.
+       * Foundation/NSObject.m: Skip the default implementation of -dealloc,
+       -autorelease and -retain when Boehm's GC is used.
+       * Foundation/NSObjectAllocation.m: Support for object allocation in
+       the presence of Boehm's GC. Skip the default action in
+       NSDeallocateObject(), NSDecrementExtraRefCountWasZero(),
+       NSIncrementExtraRefCount() and NSGetExtraRefCount().
+
+Fri Jan 29 13:17:37 1998  Ovidiu Predescu <ovidiu@net-community.com>
+
+       * Foundation/NSBundle.m: Added support for loading bundles when running
+       in the GNUstep environment.
+
+Fri Jan  9 11:27:27 1998  Ovidiu Predescu <ovidiu@net-community.com>
+
+       * Foundation/NSBundle.m: Fixed the searching of resources in a bundle
+       when working in a GNUstep environment.
+
+Tue Jan  6 09:51:20 1998  Ovidiu Predescu <ovidiu@net-community.com>
+
+       Incorporate patches from Marcus Mueller <znek@object-factory.com>.
+       * Foundation/common.h: Include stdio.h.
+       * Foundation/NSFileManager.h: Declare NSFileOwnerAccountName.
+       * Foundation/NSFileManager.m (fileAttributesAtPath:traverseLink:):
+       Add a new key, NSFileOwnerAccountName, in the returned dictionary.
+
+Wed Dec  3 13:55:00 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       * Foundation/NSObject.m: Check in a bunch of methods to see if selector
+       is null to avoid a crash when working with the GNU runtime.
+
+Mon Dec  1 15:18:33 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       * Foundation/common.m (hashpjw): Replaced by a better hash function
+       hashjb (from Dr. Dobb's Journal January/1998).
+       * Foundation/NSConcreteValue.m: Use the new hash function.
+       * Foundation/NSData.m: Likewise.
+       * Foundation/NSMethodSignature.m: Likewise.
+
+Tue Nov 25 09:28:09 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       Suggestions and bug fixes from Gregor Hoffleit
+       <flight@mathi.uni-heidelberg.de>.
+
+       * Foundation/UnixSignalHandler.m (addObserver:selector:forSignal:
+       immediatelyNotifyOnSignal:): Use sigemptyset to empty the signal action
+       set mask.
+
+       * Resources/GNUmakefile.alone: Removed.
+       * Resources/GNUmakefile.gnustep: Removed.
+       * Resources/GNUmakefile: New makefile that does not depend on how the
+       package was configured, for GNUstep or not.
+       * GNUmakefile.alone: Remove the GNUmakefile on distclean.
+       * GNUmakefile.gnustep: Likewise.
+       * Foundation/GNUmakefile.alone: Likewise.
+       * Foundation/GNUmakefile.postamble: Likewise.
+       * examples/GNUmakefile.alone: Likewise.
+       * examples/GNUmakefile.gnustep: Likewise.
+       * configure.in: Don't create the Resources/GNUmakefile from
+       GNUmakefile.gnustep.
+
+Sun Nov 16 22:22:15 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       * Public release 0.8.0.
+
+Sun Nov 16 20:12:05 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       * configure.in: Check for sigaction system call.
+       * config.h.in: Support the above check.
+       * config/i386/gnu.h: New file.
+       * Foundation/UnixSignalHandler.m: Use sigaction under linux instead of
+       signal because the later doesn't have the BSD semantics.
+
+Sat Nov 15 21:52:55 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       * config/alpha/linux-gnu.h: New  definitions needed by NSInvocation
+       and NSMethodSignature for the alpha processor.
+
+Sat Nov 15 15:50:10 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       Fixes from Aleksandr Savostyanov.
+       * config.mak.in: Add -D_REENTRANT on Solaris.
+       * Foundation/NSTask.m: Properly include the exception files.
+
+       * Foundation/NSFileManager.m (-findNextFile): Don't recurse into
+       subdirectories unless the recursive flag is set.
+
+Sat Nov 15 15:34:33 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       * Foundation/NSHost.m: Include <string.h>.
+       * Foundation/NSTask.m: Include <config.h> instead of
+       <Foundation/common.h> to avoid redefinition of MIN and MAX on some
+       systems. Cast integers to long first to avoid warnings on alpha.
+       * Foundation/UnixSignalHandler.m: Likewise.
+       * Foundation/common.h: Change the definition of MIN and MAX to use
+       typeof instead of typedef.
+
+Wed Nov 12 21:34:08 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       * configure.in: Checks for sigset.
+       * config.h.in: Support for the above check.
+       * Foundation/NSTask.m: Fixed the registering to UnixSignalHandler.
+       * Foundation/UnixSignalHandler.m: Use sigset on System V instead of
+       signal because the last one removes the handler after a signal is
+       executed.
+       (_execChild): Temporary disable signals before forking off the child
+       to make sure SIGCHLD is not raised before we have a chance to register
+       the task object.
+       * Foundation/load.m: The code for ELF systems also works under Solaris,
+       but GCC doesn't seem to define the __ELF__ variable.
+       * examples/Defaults.m: Move the format strings outside the exception
+       handler to workaround a bug in compiler.
+       * examples/GNUmakefile.gnustep: Added ADDITIONAL_CPPFLAGS.
+
+Tue Nov 11 22:16:39 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       Finished the implementation of NSTask and NSPipe.
+       * configure.in: Added checks for determining the signal handling
+       mechanism. Also for a POSIX sys/wait.h, for a working vfork and for
+       the pid_t definition.
+       * config.h.in: Support for the above checks.
+       * Foundation/NSPipe.m: Changed the implementation to be based on
+       NSFileHandle instead of NSPosixFileDescriptor.
+       * Foundation/NSTask.m: Properly handle SIGCHLD signals generated for
+       killed children. Generate exceptions if the state is not complete.
+       Use a concrete class. Handle NSPipes when they are setup as input,
+       output or error handles.
+
+       * Foundation/UnixSignalHandler.m: New class UnixSignalHandler to
+       handle the Unix signal stuff.
+       * Foundation/NSRunLoop.m (acceptInputForMode:beforeDate:): Break the
+       loop when listening for file descriptors input if a signal appears.
+
+       * Foundation/NSAccount.m: Made the implementation thread-safe.
+       * Foundation/NSFileManager.m: Likewise.
+       * Foundation/NSNotificationCenter.m: Likewise.
+       * Foundation/NSThread.h: Add the defaultCenter ivar. New methods
+       -defaultNotificationCenter and -setDefaultNotificationCenter:.
+       * Foundation/NSThread.m: Implementation of the above.
+
+       * Foundation/common.h: Move the ASSIGN macro here.
+       * Foundation/NSConcreteFileHandle.m: Removed the ASSIGN macro.
+       * Foundation/NSRunLoop.m: Likewise.
+       (runMode:beforeDate:): Move the calling of +[NSNotificationQueue
+       runLoopASAP] to acceptInputForMode:beforeDate:.
+       * Foundation/NSNotification.h: Removed the lock ivar.
+       * Foundation/NSProcessInfo.m (initializeWithArguments:count:
+       environment:): Fixed some memory allocation bugs.
+
+Tue Nov  4 23:11:32 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       * Foundation/NSAccount.m (+currentAccount): Create an account based on
+       the password structure rather than on the user id only.
+       * Foundation/NSAllocDebugZone.m (searchHash): Cast the pointer to long
+       instead of int.
+       * Foundation/NSArchiver.m (encodeValueOfObjCType:at:): Likewise.
+       * Foundation/NSObjectAllocation.m (NSDecrementExtraRefCountWasZero,
+       NSIncrementExtraRefCount, NSGetExtraRefCount): Likewise.
+       * Foundation/NSConcreteValue.m (-[NSConcreteObjCValue hash]): Use
+       hashpjw instead of the pointer to the type, which can vary. Also cast
+       pointer values to long before returning them from -hash in some other
+       classes.
+
+Tue Nov  3 22:14:10 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       * Foundation/NSHost.h: New file.
+       * Foundation/NSHost.m: New file.
+       * Foundation/NSPipe.m: New file.
+       * Foundation/NSTask.h: New file.
+       * Foundation/NSTask.m: New file.
+
+Mon Nov  3 00:09:13 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       Prepare the sources for the Alpha port.
+       * Foundation/NSAllocDebugZone.m: Cast pointers to long instead of int.
+       * Foundation/NSArray.m: Likewise.
+       * Foundation/NSHashMap.m: Likewise.
+       * Foundation/NSObject.m: Likewise.
+       * Foundation/NSString.m: Likewise.
+       * Foundation/NSAutoreleasePool.m: Use the %p specificator when
+       printf()-ing.
+       * Foundation/NSCalendarDate.m: Use a dummy va_list variable to pass
+       the arguments to stringWithFormat:arguments:.
+
+       Changed int to unsigned int to avoid compiler warnings with the newer
+       pre-2.8.0 compilers.
+       * Foundation/GCArray.m: Likewise.
+       * Foundation/GCDictionary.m: Likewise.
+       * Foundation/NSArchiver.m: Likewise.
+       * Foundation/NSCoder.m: Likewise.
+       * Foundation/NSConcreteCharacterSet.m: Likewise.
+       * Foundation/NSConcreteFileHandle.m: Likewise.
+       * Foundation/NSConcreteSet.m: Likewise.
+       * Foundation/NSConcreteTimeZone.m: Likewise.
+
+       * Foundation/NSInvocation.m (setArguments:atIndex:): Check
+       argumentLocation before copying to it.
+       * Foundation/NSLock.m (tryLockWhenCondition:): Use -tryLock instead of
+       duplicating the code (from Aleksandr Savostyanov).
+       * Foundation/NSPathUtilities.m (stringByStandardizingPath): Don't try
+       to see if the path exists or not because it could be a relative link
+       (observation from Aleksandr Savostyanov).
+       * Foundation/NSUtilities.m (NSLogv): Lock before writing to stdout.
+
+Mon Oct 27 00:26:14 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       Implemented a simple defaults tool.
+       * examples/Defaults.m: New file.
+       * examples/defaults.m: Removed.
+       * Foundation/NSUserDefaults.h: Added two new ivars, domainsToRemove and
+       dirtyDomains. Removed the dirty ivar.
+       * Foundation/NSUserDefaults.m: Deal with domains removal. Fixed and
+       optimized the code that synchonizes the persistent default domains.
+
+Fri Oct 24 12:49:46 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       * Foundation/NSRunLoop.m (runMode:beforeDate:): Temporary retain
+       limitDate so that it doesn't get released accidentally in
+       acceptInputForMode:beforeDate:. Bug report from Benhur Stein
+       <Benhur-de-Oliveira.Stein@imag.fr>.
+
+Tue Oct 21 23:49:40 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       Finished making the library thread-safe, using modified patches from
+       Aleksandr Savostyanov.
+       * Foundation/NSNotificationQueue.m: Made thread-safe.
+       * Foundation/NSObjectAllocation.m: Likewise.
+       * Foundation/NSObject.m: Lock the global lock when accessing
+       delayedExecutions dictionary.
+       * Foundation/NSThread.h: Added support for making other classes in
+       libFoundation thread-safe.
+       * Foundation/NSThread.m: Likewise.
+
+       * Foundation/NSPosixFileDescriptor.h: Added the 'owned' ivar to
+       properly close the file descriptor.
+       * Foundation/NSPosixFileDescriptor.m (-dealloc): New method.
+       Setup the owned ivar in various init methods.
+       * Foundation/NSProcessInfo.m: Make the name of the process being the
+       last component of the path.
+       * Foundation/NSRunLoop.m (limitDateForMode:): Catch all the exceptions
+       possibly generated by firing timers or executing operations unleashed
+       by activity on file descriptors.
+       * Foundation/NSValue.h: Declare -init methods for NSNumber.
+
+Tue Oct  7 17:06:19 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       * Support for the GNUstep makefile package.
+       * extensions/objc-runtime.h: Don't include the config.h file.
+       * Foundation/GarbageCollector.m: Include common.h to be provide the
+       necessary definitions to objc-runtime.h.
+       * Foundation/NSCoder.m: Likewise.
+       * Foundation/NSConcreteDictionary.m: Likewise.
+       * Foundation/NSLock.m: Likewise.
+       * Foundation/NSNotificationCenter.m: Likewise.
+       * Foundation/NSTimer.m: Likewise.
+       * Foundation/behavior.m: Likewise.
+       * Foundation/misc.m: Likewise.
+       * Foundation/NSLock.h: Make the runtime definitions opaques since we
+       no longer include the config.h file.
+       * Foundation/NSNotificationQueue.h: Add definition for the private
+       method taskNowMultiThreaded: to avoid compilation warnings.
+       * Foundation/NSRunLoop.h: Likewise.
+       * Foundation/NSRunLoop.m: Include here the objc-runtime.h file.
+       * Foundation/NSNotificationQueue.m: Implement taskNowMultiThreaded:.
+
+Sun Oct  5 20:27:10 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       * Foundation/NSBundle.m (_fileResourceNamed:extension:inDirectory:):
+       Use the Libraries/Resources/libFoundation in the GNUstep directory
+       tree.
+
+Thu Aug 21 11:48:03 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       * Foundation/NSCalendarDate.m (descriptionWithCalendarFormat:timeZone:
+       locale:): New method to avoid infinite recursion (patch from Aleksandr
+       Savostyanov).
+
+Wed Aug 20 14:24:15 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       * Foundation/NSPathUtilities.m: (pathWithComponents:): Reworked to
+       be simpler. (bug report from Aleksandr Savostyanov).
+       * Foundation/GNUmakefile: Changed to work with the supplied install-sh.
+
+Fri Aug  1 15:28:24 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       * Foundation/NSTimeZone.m: Replaced NSLog() with printf() to avoid
+       infinite recursion when the resource files are not found.
+       * Foundation/exceptions/GeneralExceptions.m (-[FileNotFoundException
+       initWithFilename:]): Don't use -stringWithFormat: to avoid infinite
+       recursion when resource files are not in the expected place.
+
+Fri Aug  1 10:32:47 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       * Foundation/NSHashMap.m (__NSHashGrow): Fixed hash value computation.
+       * Foundation/NSCalendarDate.m (-dateByAddingYears:months:days:hours:
+       minutes:seconds:): Fixed the name.
+       * Foundation/NSArray.m (makeObjectsPerformSelector:...): New methods.
+       * Foundation/NSSet.m (makeObjectsPerformSelector:...): New methods.
+       (Bug fixes from Aleksandr Savostyanov).
+
+Wed Jul  9 15:01:18 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       * Foundation/NSData.m (-[NSData hash]): New method.
+
+Fri Jun 13 19:01:27 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       * Foundation/scanInt.def: Fixed scanning of big numbers (bug report
+       from Balazs E. Pataki <pataki@next-1b.manuf.bme.hu>).
+
+Thu Jun 12 18:51:03 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       * Foundation/NSNotification.m (-dealloc): Also release object.
+
+Tue Jun 10 21:32:01 1997  Mircea Oancea <mircea@pathcom.com>
+
+       * Foundation/NSConcreteString.m (-[NS8BitString initWithCoder:]):
+       Allocate one more byte and set it to 0 (bug report from Chun, Sung Jin
+       <ninja@doolly.snu.ac.kr>).
+
+Tue Jun 10 15:14:49 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       * Foundation/NSAccount.m: Include common.h instead of config.h.
+       (-initWithPasswordStructure:): Duplicate the char* passwd structure
+       fields because of anoying anomalies when using them.
+       * Foundation/NSDistributedLock.m (-initWithPath:): Don't try to aquire
+       the lock here by creating the lock file, just store the file name.
+       * Foundation/NSFileManager.m: (-removeFileAtPath:handler:): Handle the
+       simple case when the file name is really a file, not a directory.
+       * Foundation/NSUserDefaults.m (-loadPersistentDomainNamed:): Replace
+       NSLog() with printf() calls to avoid recursion when resources are not
+       found.
+       (-savePersistentDomainNamed:): Likewise.
+       (-loadPersistentDomainNamed:): Don't try to lock when loading the
+       content of a file corresponding to a given domain. The locking schema
+       should be improved to be possible to determine if the application that
+       holds the lock is still alive, otherwise the lock should be removed.
+       (-savePersistentDomainNamed:): Likewise.
+       (-initWithPath:): Set appDomain to the name of the executable which is
+       the last component in the application's name.
+       * Foundation/common.m (writeToFile): Remove the destination file first
+       before renaming the source file to the destination one.
+
+Sun Jun  1 19:11:03 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       Initial implementation of NSFileHandle.
+       * Foundation/NSFileHandle.h: New file.
+       * Foundation/NSFileHandle.m: New file.
+       * Foundation/NSConcreteFileHandle.h: New file.
+       * Foundation/NSConcreteFileHandle.m: New file.
+       * Foundation/exceptions/NSFileHandleExceptions.h: New file.
+       * Foundation/exceptions/NSFileHandleExceptions.m: New file.
+       * Foundation/Foundation.h: Include NSFileHandle.h.
+       * Foundation/GNUmakefile: Add NSFileHandle, NSConcreteFileHandle and
+       NSFileHandleExceptions.
+       * Foundation/NSPosixFileDescriptor.m (-dealloc): Remove method.
+
+Thu May 30  6:28:52 1997  Ovidiu Predescu <ovidiu@net-community.com>
+
+       * Foundation/NSStringPropList.g: Add the / character to the characters
+       that are part of a string (suggestion from Aleksandr Savostyanov).
+       * Foundation/PrintfScannerHandler.m (-convertChar:scanner:): Change the
+       way characters are written to use sprintf(); this makes the code to
+       also work on Solaris (suggestion from Aleksandr Savostyanov).
+
+Thu May 29 18:53:52 1997  Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+       * Public release 0.7.1.
+
+Tue May 27  7:20:34 1997  Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+       * Foundation/NSString.m: Implemented some abstract methods for the
+       default encoding. These methods will be rewritten for Unicode but now
+       they allow user's concrete subclasses to work correctly. Patch from
+       Paul H. Kenyon <phk@hksys.com>.
+
+Mon May 26 10:04:18 1997  Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+       Fixed the way in which NSInvocation and NSTimer handle retain cycles.
+       * Foundation/NSInvocation.m (-invalidate): New method.
+       * Foundation/NSInvocation.m (-setTarget:): Retain the target if
+       arguments are retained.
+       * Foundation/NSTimer.m (-invalidate): Send -invalidate to invocation
+       ivar to break the retain cycle.
+
+Sat May 24 19:47:30 1997  Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+       * Foundation/NSInvocation.m (-_releaseArguments): Release the arguments
+       starting from 2 instead of 0; patch from Aleksandr Savostyanov.
+       * Foundation/NSPosixFileDescriptor.m (-setDelegate:): Don't retain the
+       delegate; patch from Aleksandr Savostyanov.
+       * Foundation/NSRunLoop.m (-[NSRunLoop acceptInputForMode:beforeDate:]):
+       Do not return from method if there are no input sources to listen to.
+       Avoid this way unnecesary computations when this method was called from
+       -runUntilDate: or -run. Patch from Aleksandr Savostyanov.
+
+Fri May 16 18:54:57 1997  Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+       * Foundation/NSGeometry.m (NSPointFromString, NSSizeFromString,
+       NSRectFromString): Implemented.
+       * Foundation/NSObject.m (-performSelector:,
+       -performSelector:withObject:, -performSelector:withObject:withObject:):
+       New methods.
+       * Foundation/NSObject.m (-performSelector:object:afterDelay:,
+       +cancelPreviousPerformRequestsWithTarget:selector:object:):
+       Implemented. _NSObjectDelayedExecutionHolder: New class used for
+       delayed execution of methods.
+
+Thu May 15 18:14:24 1997  Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+       * Foundation/NSDistributedLock.m (-initWithPath:): Check if the file
+       exists and create it otherwise.
+       * Foundation/NSFileManager.m (-createFileAtPath:contents:attributes:):
+       Check if the data the to be written has 0 length.
+
+Sun May 18 23:33:44 1997  Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+       * Foundation/NSPosixFileDescriptor.m: Finished the implementation.
+       * Foundation/NSRunLoop.h: Changed the API to work using
+       NSPosixFileDescriptors instead of the direct Unix file descriptor.
+       * Foundation/NSRunLoop.m: Likewise.
+
+Sat May 10  8:03:14 1997  Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+       * Foundation/NSObject.m (-release): Deallocate the object when the
+       reference count is 1 without decreasing it anymore, this ensures
+       OPENSTEP compatibility. Patch from Aleksandr Savostyanov.
+       * Foundation/GCObject.m (-release): Likewise.
+       * Foundation/NSRunLoop.m (-[NSRunLoop limitDateForMode:]): Reworked a
+       little based on Aleksandr Savostyanov's suggestion.
+
+Sat May  3  9:33:34 1997  Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+       * sharedlib.mak: Rules for making shared libraries under Solaris; patch
+       from Aleksandr Savostyanov.
+
+Thu May  1 13:54:34 1997  Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+       Support the new 970318 patch for compiler and runtime.
+       * configure.in: Check for the objc_thread_create() function.
+       * Foundation/NSThread.m: Create a new thread depending on the runtime
+       API (using either objc_thread_create or objc_thread_detach).
+
+Wed Apr 30  8:07:14 1997  Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+       * Foundation/NSString.m (-[NSString initWithFormat:arguments:]): Do
+       -collect after the -copyWithZone: operation; patch from Aleksandr
+       Savostyanov.
+
+Sat Apr 26 19:23:44 1997  Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+       * Foundation/NSObjectAllocation.m: Align RefObjectLayout structure
+       to the align of a double; patch from Aleksandr Savostyanov.
+
+Mon Apr 21 20:43:42 1997  Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+       * Foundation/NSExceptionWithoutNested.h: Fix the exception handling
+       macros because nested handlers were not supported as observed by
+       Florin Mihaila <phil@pathcom.com>.
+
+Thu Apr  3 10:45:32 1997  Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+       * Foundation/NSRunLoop.m: Finished the implementation.
+
+Sat Mar 22  8:45:10 1997  Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+       * Foundation/NSMethodSignature.m: Integrated Aleksandr Savostyanov's
+       changes for Solaris.
+       * Foundation/NSInvocation.m: Likewise.
+       * config/sparc/solaris2.4.h: Likewise.
+
+Sat Mar 15 10:33:20 1997  Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+       * Integrated the Jeremy Bettis' patch that make libFoundation compile
+       on Windows NT.
+
+Sat Mar  8 16:44:50 1997  Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+       * sharedlib.mak: Linux rule for shared libraries added.
+
+Sat Mar  8 13:41:08 1997  Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+       * sharedlib.mak: New file. Describes the commands to create a
+       shared library on each platform.
+       * Foundation/GNUmakefile: Added rules for creating shared libraries.
+       * configure.in: Added host variables to make information about target
+       machine available in config.mak. These variables are used by
+       sharedlib.mak to determine the commands used to create a shared lib.
+       * Foundation/NSString.h: -[NSString substringFromRange:]: New method.
+       * Foundation/NSString.m: Likewise.
+       * doc/CodingRules.pod: New file.
+       * Foundation/NSObject.h.in: Removed.
+       * Foundation/NSObject.h: Created from NSObject.h.in. The versioning
+       scheme has been changed to use major, minor and subminor numbers.
+
+Sun Feb 23 18:42:07 1997  Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+       * First public release: 0.7.
diff --git a/libFoundation/Foundation/DefaultScannerHandler.m b/libFoundation/Foundation/DefaultScannerHandler.m
new file mode 100644 (file)
index 0000000..5887635
--- /dev/null
@@ -0,0 +1,91 @@
+/* 
+   DefaultScannerHandler.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+           Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSString.h>
+#include <extensions/FormatScanner.h>
+#include <extensions/DefaultScannerHandler.h>
+
+@implementation DefaultScannerHandler
+
+- (id)init
+{
+    int i;
+    IMP unknownSpecifierIMP
+           = [self methodForSelector:@selector(unknownSpecifier:scanner:)];
+
+    for(i = 0; i < 256; i++)
+       specHandler[i] = unknownSpecifierIMP;
+    return self;
+}
+
+- (NSString *)unknownSpecifier:(void *)arg scanner:scanner
+{
+    char str[] = { [scanner characterSpecifier], 0 };
+    return [NSString stringWithCString:str];
+}
+
+- (NSString *)stringForArgument:(void *)arg scanner:scanner
+{
+    return (*specHandler[(int)[scanner characterSpecifier]])
+               (self, _cmd, arg, scanner);
+}
+
+@end /* DefaultScannerHandler */
+
+@implementation DefaultEnumScannerHandler
+
+- (id)init
+{
+    int i;
+    IMP unknownSpecifierIMP;
+
+    unknownSpecifierIMP =
+        [self methodForSelector:@selector(unknownSpecifier:scanner:)];
+    
+    for(i = 0; i < 256; i++)
+       self->specHandler[i] = unknownSpecifierIMP;
+    return self;
+}
+
+- (NSString *)unknownSpecifier:(void *)arg scanner:scanner
+{
+    char str[] = { [scanner characterSpecifier], 0 };
+    return [NSString stringWithCString:str];
+}
+
+- (NSString *)stringForArgument:(void *)arg scanner:scanner
+{
+    return (*specHandler[(int)[scanner characterSpecifier]])
+               (self, _cmd, arg, scanner);
+}
+
+@end /* DefaultEnumScannerHandler */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/FFCallInvocation.h b/libFoundation/Foundation/FFCallInvocation.h
new file mode 100644 (file)
index 0000000..29a6979
--- /dev/null
@@ -0,0 +1,61 @@
+/* 
+   NSFFCallInvocation.h
+
+   Copyright (C) 2000, MDlink online service center GmbH, Helge Hess
+   All rights reserved.
+   
+   Author: Helge Hess <helge.hess@mdlink.de>
+   
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+// $Id
+
+#ifndef __NSConcreteFFCallInvocation_H__
+#define __NSConcreteFFCallInvocation_H__
+
+#include <Foundation/NSInvocation.h>
+#include <config.h>
+#include <objc/encoding.h>
+#include <objc/objc-api.h>
+#include <avcall.h>
+#include <callback.h>
+
+@interface FFCallInvocation : NSInvocation
+{
+    const char *types;
+    void       *retvalue;
+    unsigned   retvalLen;
+    void       *buffer;
+    void       **idxToPtr;
+    unsigned   *idxToLen;
+}
+
+- (id)initWithSignature:(NSMethodSignature *)_signature;
+- (void)invalidate;
+
+@end
+
+extern void
+NSInvocationCallbackDispatcher(void *dispatchSelector, va_alist args);
+
+#endif /* __NSConcreteFFCallInvocation_H__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/FFCallInvocation.m b/libFoundation/Foundation/FFCallInvocation.m
new file mode 100644 (file)
index 0000000..1577299
--- /dev/null
@@ -0,0 +1,621 @@
+/* 
+   NSFFCallInvocation.m
+
+   Copyright (C) 2000, MDlink online service center GmbH, Helge Hess
+   All rights reserved.
+   
+   Author: Helge Hess <helge.hess@mdlink.de>
+   
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+// $Id$
+
+#include "FFCallInvocation.h"
+#include <Foundation/NSException.h>
+
+@interface NSInvocation(PrivateMethods)
+- (id)initWithSignature:(NSMethodSignature *)_signature;
+@end
+
+@interface FFCallInvocation(PrivateMethods)
+- (void)_releaseArguments;
+@end
+
+@implementation FFCallInvocation
+
+#if OBJC_METHOD_LOOKUP_HOOKS
+
+static void *cb;
+
+static IMP ffObjCMsgLookup(id self, SEL _cmd)
+{
+    /* invoked during method dispatch */
+    return cb;
+}
+static IMP ffClassGetMethod(Class clazz, SEL _cmd)
+{
+    /* invoked during method_get */
+    return cb;
+}
+
+static void freeCallback(void)
+{
+    if (cb) { free_callback(cb); cb = NULL; }
+}
+
++ (void)load
+{
+    cb = alloc_callback(&NSInvocationCallbackDispatcher,
+                        @selector(forwardInvocation:));
+    atexit(&freeCallback);
+    
+    __objc_msg_lookup       = ffObjCMsgLookup;
+    __objc_class_get_method = ffClassGetMethod;
+}
+#endif
+
++ (id)invocationWithMethodSignature:(NSMethodSignature *)_signature
+{
+    id o;
+    o = [[self alloc] initWithSignature:_signature];
+    AUTORELEASE(o);
+    return o;
+}
+
+- (id)init
+{
+    abort();
+    return nil;
+}
+- (id)initWithSignature:(NSMethodSignature *)_signature
+{
+    NSAssert(_signature, @"method signature required !");
+    
+    self->types = [_signature types];
+    
+    if ((self = [super initWithSignature:_signature])) {
+        /* setup argument buffers */
+        register const char *ltypes;
+        unsigned total, count;
+        
+        ltypes = self->types;
+    
+        /* alloc return buffer */
+        self->retvalLen = objc_sizeof_type(objc_skip_type_qualifiers(ltypes));
+        self->retvalue  = malloc(self->retvalLen);
+    
+        ltypes = objc_skip_argspec(ltypes); // skip retval
+        ltypes = objc_skip_argspec(ltypes); // skip self
+        ltypes = objc_skip_argspec(ltypes); // skip _cmd
+    
+        /* calc total buffer size & argument count */
+        for (total = 0, count = 0; *ltypes; ltypes = objc_skip_argspec(ltypes)) {
+            total += objc_sizeof_type(ltypes);
+            count++;
+        }
+    
+        /* reset type-ptr to arguments */
+        ltypes = self->types;
+        ltypes = objc_skip_argspec(ltypes); // skip retval
+        ltypes = objc_skip_argspec(ltypes); // skip self
+        ltypes = objc_skip_argspec(ltypes); // skip _cmd
+    
+        /* allocate arg buffer */
+        self->buffer   = malloc(total);
+        self->idxToPtr = malloc(sizeof(void *)   * count);
+        self->idxToLen = malloc(sizeof(unsigned) * count);
+        for (total = 0, count = 0; *ltypes; ltypes = objc_skip_argspec(ltypes)) {
+            self->idxToPtr[count] = self->buffer + total;
+            self->idxToLen[count] = objc_sizeof_type(ltypes);
+            total += self->idxToLen[count];
+            count++;
+        }
+    }
+    return self;
+}
+
+- (void)dealloc
+{
+    [self _releaseArguments];
+    
+    if (self->retvalue) free(self->retvalue);
+    if (self->buffer)   free(self->buffer);
+    if (self->idxToPtr) free(self->idxToPtr);
+    if (self->idxToLen) free(self->idxToLen);
+    [super dealloc];
+}
+
+static inline void
+_setArg(FFCallInvocation *self, SEL _cmd, void *_value, int _idx)
+{
+    switch (_idx) {
+        case 0:
+            [self setTarget:*(id *)_value];
+            break;
+        case 1:
+            [self setSelector:*(SEL *)_value];
+        default:
+            if (self->argumentsRetained) {
+                ; // not supported yet
+            }
+            _idx -= 2;
+            memcpy(self->idxToPtr[_idx], _value, self->idxToLen[_idx]);
+            break;
+    }
+}
+
+static inline void
+_getArg(FFCallInvocation *self, SEL _cmd, void *_value, int _idx)
+{
+    switch (_idx) {
+        case 0:
+            *(id *)_value = [self target];
+            break;
+        case 1:
+            *(SEL *)_value = [self selector];
+            break;
+        default:
+            _idx -= 2;
+            memcpy(_value, self->idxToPtr[_idx], self->idxToLen[_idx]);
+            break;
+    }
+}
+
+static inline void _getRetVal(FFCallInvocation *self, SEL _cmd, void *_value)
+{
+    memcpy(_value, self->retvalue, self->retvalLen);
+}
+
+- (void)setArgument:(void *)_value atIndex:(int)_idx
+{
+    _setArg(self, _cmd, _value, _idx);
+}
+- (void)getArgument:(void *)_value atIndex:(int)_idx
+{
+    _getArg(self, _cmd, _value, _idx);
+}
+
+- (void)_releaseArguments
+{
+    const char *ltypes;
+    unsigned   idx;
+    
+    if (!self->argumentsRetained) return;
+    self->argumentsRetained = NO;
+    
+    ltypes = self->types;
+    if ((*ltypes == _C_ID) || (*ltypes == _C_CLASS))
+        RELEASE(*(id *)self->retvalue);
+    
+    ltypes = objc_skip_argspec(ltypes); // skip retval
+    ltypes = objc_skip_argspec(ltypes); // skip 'self'
+    ltypes = objc_skip_argspec(ltypes); // skip _cmd
+    RELEASE(self->target);
+
+    for (idx = 2; *ltypes; idx++) {
+        if ((*ltypes == _C_ID) || (*ltypes == _C_CLASS)) {
+            id object;
+
+            _getArg(self, _cmd, &object, idx);
+            RELEASE(object);
+            break;
+        }
+        ltypes = objc_skip_argspec(ltypes);
+    }
+}
+
+- (void)retainArguments
+{
+    const char *ltypes;
+    unsigned   idx;
+  
+    if (self->argumentsRetained) return;
+    self->argumentsRetained = YES;
+    
+    ltypes = self->types;
+    if ((*ltypes == _C_ID) || (*ltypes == _C_CLASS))
+        RETAIN(*(id *)self->retvalue);
+    
+    ltypes = objc_skip_argspec(ltypes); // skip retval
+    ltypes = objc_skip_argspec(ltypes); // skip 'self'
+    ltypes = objc_skip_argspec(ltypes); // skip _cmd
+    RETAIN(self->target);
+  
+    for (idx = 2; *ltypes; idx++) {
+        if ((*ltypes == _C_ID) || (*ltypes == _C_CLASS)) {
+            id object;
+
+            _getArg(self, _cmd, &object, idx);
+            RETAIN(object);
+            break;
+        }
+        ltypes = objc_skip_argspec(ltypes);
+    }
+}
+
+- (void)setReturnValue:(void *)_value
+{
+    if (self->argumentsRetained) {
+        switch (*(self->types)) {
+            case _C_ID:
+            case _C_CLASS: {
+                id old = *(id *)self->retvalue;
+                RETAIN(*(id *)_value);
+                RELEASE(old);
+                break;
+            }
+        }
+    }
+    memcpy(self->retvalue, _value, self->retvalLen);
+}
+- (void)getReturnValue:(void *)_value
+{
+    _getRetVal(self, _cmd, _value);
+}
+
+/* invalidation */
+
+- (void)invalidate
+{
+    self->isValid = NO;
+    [self _releaseArguments];
+}
+
+/* invocation */
+
+- (void)invokeWithTarget:(id)_target
+{
+    IMP        method;
+    const char *ltypes;
+    av_alist   alist;
+    unsigned   idx;
+    
+    /* get the Objective-C type signature */
+  
+    ltypes  = self->types;
+    
+    /* find the function implementing the method */
+    
+    method =
+        method_get_imp(class_get_instance_method(*(Class *)_target, self->selector));
+    
+    /* if the method couldn't be found, forward the invocation */
+    
+    if (method == NULL) {
+        [_target forwardInvocation:self];
+        return;
+    }
+    
+    /* start with return type */
+  
+    switch (*ltypes) {
+        case _C_VOID:
+            av_start_void(alist, method);
+            break;
+    
+        case _C_ID:
+            av_start_ptr(alist, method, id, self->retvalue);
+            break;
+        case _C_CLASS:
+            av_start_ptr(alist, method, Class, self->retvalue);
+            break;
+        case _C_SEL:
+            av_start_ptr(alist, method, SEL, self->retvalue);
+            break;
+        case _C_CHARPTR:
+            av_start_ptr(alist, method, char *, self->retvalue);
+            break;
+        case _C_PTR:
+            av_start_ptr(alist, method, void *, self->retvalue);
+            break;
+    
+        case _C_CHR:
+            av_start_char(alist, method, self->retvalue);
+            break;
+        case _C_UCHR:
+            av_start_uchar(alist, method, self->retvalue);
+            break;
+    
+        case _C_SHT:
+            av_start_short(alist, method, self->retvalue);
+            break;
+        case _C_USHT:
+            av_start_ushort(alist, method, self->retvalue);
+            break;
+
+        case _C_LNG:
+        case _C_INT:
+            av_start_int(alist, method, self->retvalue);
+            break;
+        case _C_ULNG:
+        case _C_UINT:
+            av_start_uint(alist, method, self->retvalue);
+            break;
+    
+        case _C_FLT:
+            av_start_float(alist, method, self->retvalue);
+            break;
+        case _C_DBL:
+            av_start_double(alist, method, self->retvalue);
+            break;
+      
+        default:
+            fprintf(stderr, "Unsupported return type: '%s' !\n", ltypes);
+            fflush(stderr);
+            abort();
+    }
+  
+    /* push target & _cmd arguments */
+  
+    av_ptr(alist, id,  _target);
+    av_ptr(alist, SEL, self->selector);
+  
+    ltypes = objc_skip_argspec(ltypes); // skip retval
+    ltypes = objc_skip_argspec(ltypes); // skip self
+    ltypes = objc_skip_argspec(ltypes); // skip _cmd
+
+    /* process method arguments */
+  
+    for (idx = 0; *ltypes; idx++) {
+        register void     *ptr;
+        register unsigned len;
+
+        ptr = self->idxToPtr[idx];
+        len = self->idxToLen[idx];
+    
+        switch (*ltypes) {
+            case _C_CLASS:
+            case _C_ID: {
+                id o;
+                memcpy(&o, ptr, len);
+                av_ptr(alist, id, o);
+                break;
+            }
+            case _C_SEL: {
+                SEL s;
+                memcpy(&s, ptr, len);
+                av_ptr(alist, SEL, s);
+                break;
+            }
+
+            case _C_CHARPTR:
+            case _C_PTR: {
+                void *p;
+                memcpy(&p, ptr, len);
+                av_ptr(alist, void *, p);
+                break;
+            }
+      
+            case _C_CHR: {
+                char c;
+                memcpy(&c, ptr, len);
+                av_char(alist, c);
+                break;
+            }
+            case _C_UCHR: {
+                unsigned char c;
+                memcpy(&c, ptr, len);
+                av_uchar(alist, c);
+                break;
+            }
+      
+            case _C_SHT: {
+                short c;
+                memcpy(&c, ptr, len);
+                av_short(alist, c);
+                break;
+            }
+            case _C_USHT: {
+                unsigned short c;
+                memcpy(&c, ptr, len);
+                av_ushort(alist, c);
+                break;
+            }
+
+            case _C_LNG:
+            case _C_INT: {
+                int c;
+                memcpy(&c, ptr, len);
+                av_int(alist, c);
+                break;
+            }
+            case _C_ULNG:
+            case _C_UINT: {
+                unsigned int c;
+                memcpy(&c, ptr, len);
+                av_uint(alist, c);
+                break;
+            }
+      
+            case _C_FLT: {
+                float c;
+                memcpy(&c, ptr, len);
+                av_float(alist, c);
+                break;
+            }
+            case _C_DBL: {
+                double c;
+                memcpy(&c, ptr, len);
+                av_double(alist, c);
+                break;
+            }
+      
+            default:
+                fprintf(stderr, "Unsupported argument type: '%s' !\n", ltypes);
+                fflush(stderr);
+                abort();
+        }
+    
+        ltypes = objc_skip_argspec(ltypes);
+    }
+
+    /* invoke method */
+    av_call(alist);
+}
+
+- (NSString *)description
+{
+    char buf[1024];
+    sprintf(buf, "<%s[0x%08X]: target=0x%08X selector=%s sig=%s>",
+            class_get_class_name([self class]), (unsigned)self,
+            (unsigned)self->target, sel_get_name(self->selector),
+            self->types);
+  return [NSString stringWithCString:buf];
+}
+
+/* a dispatcher function for use with ffcall's callback */
+
+void NSInvocationCallbackDispatcher(void *dispatchSelector, va_alist args)
+{
+    static Class FFCallInvocationClass = Nil;
+    id                returnValue;
+    id                self;
+    SEL               _cmd;
+    NSMethodSignature *signature;
+    FFCallInvocation  *invocation;
+    const char *types;
+    unsigned idx;
+    
+    if (FFCallInvocationClass == Nil)
+        FFCallInvocationClass = [FFCallInvocation class];
+    
+    va_start_ptr(args, id);
+    self = va_arg_ptr(args, id);
+    _cmd = va_arg_ptr(args, SEL);
+    
+    /* method reflection */
+    
+    signature = [self methodSignatureForSelector:_cmd];
+    NSAssert(signature, @"missing signature for selector '%@'",
+             NSStringFromSelector(_cmd));
+
+    // NSLog(@"sel %@ sig %@", NSStringFromSelector(_cmd), signature);
+    
+    /* setup invocation object */
+    
+    invocation =
+        [[FFCallInvocationClass alloc] initWithSignature:signature];
+    
+    [invocation setTarget:self];
+    [invocation setSelector:_cmd];
+    
+    types = invocation->types;
+    types = objc_skip_argspec(types);
+    types = objc_skip_argspec(types);
+    types = objc_skip_argspec(types);
+    
+    for (idx = 2; *types; idx++) {
+        switch (*types) {
+            case _C_CLASS:
+            case _C_ID: {
+                id o = va_arg_ptr(args, id);
+                _setArg(invocation, _cmd, &o, idx);
+                break;
+            }
+            
+            case _C_SEL: {
+                SEL s = va_arg_ptr(args, SEL);
+                _setArg(invocation, _cmd, &s, idx);
+                break;
+            }
+            case _C_PTR: {
+                void *ptr = va_arg_ptr(args, void *);
+                _setArg(invocation, _cmd, &ptr, idx);
+                break;
+            }
+            case _C_CHARPTR: {
+                char *ptr = va_arg_ptr(args, char *);
+                _setArg(invocation, _cmd, &ptr, idx);
+                break;
+            }
+
+            case _C_CHR: {
+                char s = va_arg_char(args);
+                _setArg(invocation, _cmd, &s, idx);
+                break;
+            }
+            case _C_UCHR: {
+                unsigned char s = va_arg_uchar(args);
+                _setArg(invocation, _cmd, &s, idx);
+                break;
+            }
+            
+            case _C_SHT: {
+                short s = va_arg_short(args);
+                _setArg(invocation, _cmd, &s, idx);
+                break;
+            }
+            case _C_USHT: {
+                unsigned short s = va_arg_ushort(args);
+                _setArg(invocation, _cmd, &s, idx);
+                break;
+            }
+            
+            case _C_INT: {
+                int i = va_arg_int(args);
+                _setArg(invocation, _cmd, &i, idx);
+                break;
+            }
+            case _C_UINT: {
+                unsigned int i = va_arg_uint(args);
+                _setArg(invocation, _cmd, &i, idx);
+                break;
+            }
+        
+            case _C_FLT: {
+                float f = va_arg_float(args);
+                _setArg(invocation, _cmd, &f, idx);
+                break;
+            }
+            case _C_DBL: {
+                double d = va_arg_double(args);
+                _setArg(invocation, _cmd, &d, idx);
+                break;
+            }
+            
+            default:
+                fprintf(stderr, "Unsupported argument type: '%s' !\n", types);
+                fflush(stderr);
+                abort();
+        }
+      
+        types = objc_skip_argspec(types);
+    }
+    
+    /* forward */
+    
+    //[self performSelector:dispatchSelector withObject:invocation];
+    [self forwardInvocation:invocation];
+    
+    /* apply return value */
+    _getRetVal(invocation, _cmd, &returnValue);
+    
+    /* invalidate invocation object */
+    [invocation invalidate];
+    RELEASE(invocation);
+    
+    /* return from dispatcher */
+    va_return_ptr(args, id, returnValue);
+}
+
+@end /* FFCallInvocation */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/FormatScanner.m b/libFoundation/Foundation/FormatScanner.m
new file mode 100644 (file)
index 0000000..d0e0b57
--- /dev/null
@@ -0,0 +1,346 @@
+/* 
+   FormatScanner.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <ctype.h>
+
+#include "common.h"
+
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSValue.h>
+#include <Foundation/NSCharacterSet.h>
+
+#include <extensions/support.h>
+#include <extensions/FormatScanner.h>
+
+@implementation FormatScanner
+
+enum { SPECIFIER_SIZE = 1000 }; /* This value should be sufficient */
+
+- (id)init
+{
+    specifierSize = SPECIFIER_SIZE;
+    currentSpecifier = MallocAtomic(specifierSize);
+    allowFlags = YES;
+    allowWidth = YES;
+    allowPeriod = YES;
+    allowPrecision = YES;
+    allowModifier = YES;
+    return self;
+}
+
+- (void)dealloc
+{
+    lfFree(currentSpecifier);
+    RELEASE(handler);
+    [super dealloc];
+}
+
+- (void)setFormatScannerHandler:(id)anObject
+{
+    ASSIGN(self->handler, anObject);
+}
+
+- (id)setAllowOnlySpecifier:(BOOL)flag
+{
+    allowFlags     = !flag;
+    allowWidth     = !flag;
+    allowPeriod    = !flag;
+    allowPrecision = !flag;
+    allowModifier  = !flag;
+    return self;
+}
+
+- (id)setAllowFlags:(BOOL)flag {
+    allowFlags = flag;
+    return self;
+}
+- (BOOL)allowFlags {
+    return allowFlags;
+}
+
+- (id)setAllowWidth:(BOOL)flag {
+    allowWidth = flag;
+    return self;
+}
+- (BOOL)allowWidth {
+    return allowWidth;
+}
+
+- (id)setAllowPeriod:(BOOL)flag {
+    allowPeriod = flag;
+    return self;
+}
+- (BOOL)allowPeriod {
+    return allowPeriod;
+}
+
+- (id)setAllowPrecision:(BOOL)flag {
+    allowPrecision = flag;
+    return self;
+}
+- (BOOL)allowPrecision {
+    return allowPrecision;
+}
+
+- (id)setAllowModifier:(BOOL)flag {
+    allowModifier = flag;
+    return self;
+}
+- (BOOL)allowModifier {
+    return allowModifier;
+}
+
+- (id)formatScannerHandler {
+    return handler;
+}
+
+- (unsigned int)flags {
+    return self->flags;
+}
+- (int)width {
+    return self->width;
+}
+- (int)precision {
+    return self->precision;
+}
+- (char)modifier {
+    return self->modifier;
+}
+- (char)characterSpecifier {
+    return self->characterSpecifier;
+}
+- (const char *)currentSpecifier {
+    return self->currentSpecifier;
+}
+
+#define CHECK_END \
+    if(i >= length) { \
+        /* An unterminated specifier. Break the loop. */ \
+        [self handleOrdinaryString: \
+                    [NSString stringWithCString:currentSpecifier]]; \
+        goto _return; \
+    }
+
+/* Scans the format string looking after specifiers. Doesn't handle '*' as a
+   valid width or precision. */
+- (BOOL)parseFormatString:(NSString*)format context:(void *)context
+{
+    NSRange        searchRange, foundRange;
+    int            i, length;
+    unichar        ch;
+    NSCharacterSet *decimals;
+
+    i        = 0;
+    length   = [format length];
+    decimals = [NSCharacterSet decimalDigitCharacterSet];
+    
+    *currentSpecifier = 0;
+    specifierLen = 0;
+
+    while (i < length) {
+        searchRange.location = i;
+        searchRange.length = length - i;
+
+        foundRange = [format rangeOfString:@"%" options:0 range:searchRange];
+        if (foundRange.length == 0)
+            foundRange.location = length;
+        searchRange.length = foundRange.location - searchRange.location;
+
+        if (searchRange.length) {
+            if (![self handleOrdinaryString:
+                        [format substringWithRange:searchRange]])
+                return NO;
+        }
+
+        i = foundRange.location;
+        CHECK_END
+
+        i++;
+        strcpy(currentSpecifier, "%");
+        specifierLen = 1;
+        CHECK_END
+
+        flags = width = precision = modifier = characterSpecifier = 0;
+
+        /* Check for flags. */
+        if (self->allowFlags) {
+            for (; i < length; i++) {
+                ch = [format characterAtIndex:i];
+                switch(ch) {
+                    case '#':   strcat(currentSpecifier, "#");
+                                flags |= FS_ALTERNATE_FORM;
+                                break;
+                    case '0':   strcat(currentSpecifier, "0");
+                                flags |= FS_ZERO;
+                                break;
+                    case '-':   strcat(currentSpecifier, "-");
+                                flags |= FS_MINUS_SIGN;
+                                break;
+                    case '+':   strcat(currentSpecifier, "+");
+                                flags |= FS_PLUS_SIGN;
+                                break;
+                    case ' ':   strcat(currentSpecifier, " ");
+                                flags |= FS_BLANK;
+                                break;
+                    default:    goto quit;
+                }
+                if (++specifierLen == specifierSize) {
+                    currentSpecifier =
+                        Realloc(currentSpecifier,
+                                specifierSize += SPECIFIER_SIZE);
+                }
+            }
+        quit:
+            CHECK_END
+        }
+
+        /* Check for width. */
+        if (self->allowWidth) {
+            for(; i < length; i++) {
+                char str[2] = { 0, 0 };
+
+                ch = [format characterAtIndex:i];
+                if (![decimals characterIsMember:ch])
+                    break;
+                str[0] = ch;
+
+                strcat(currentSpecifier, str);
+                if(++specifierLen == specifierSize) {
+                    currentSpecifier =
+                        Realloc(currentSpecifier,
+                                specifierSize += SPECIFIER_SIZE);
+                }
+
+                width = 10 * width + (ch - '0');
+            }
+            CHECK_END
+        }
+
+        /* Check for period. */
+        if (self->allowPeriod) {
+            ch = [format characterAtIndex:i];
+            if(ch == '.') {
+                char str[2] = { ch, 0 };
+
+                strcat(currentSpecifier, str);
+                if(++specifierLen == specifierSize) {
+                    currentSpecifier =
+                        Realloc(currentSpecifier,
+                                specifierSize += SPECIFIER_SIZE);
+                }
+
+                i++;
+                CHECK_END
+            }
+        }
+
+        /* Check for precision. */
+        if (self->allowPrecision) {
+            for(; i < length; i++) {
+                char str[2] = { 0, 0 };
+
+                ch = [format characterAtIndex:i];
+                if (![decimals characterIsMember:ch])
+                    break;
+                str[0] = ch;
+
+                strcat(currentSpecifier, str);
+                if(++specifierLen == specifierSize) {
+                    currentSpecifier =
+                        Realloc(currentSpecifier,
+                                specifierSize += SPECIFIER_SIZE);
+                }
+                precision = 10 * precision + (ch - '0');
+            }
+            CHECK_END
+        }
+
+        /* Check for data-width modifier. */
+        if (allowModifier) {
+            ch = [format characterAtIndex:i];
+            if (ch == 'h' || ch == 'l') {
+                char str[2] = { ch, 0 };
+
+                strcat(currentSpecifier, str);
+                if (++specifierLen == specifierSize) {
+                    currentSpecifier =
+                        Realloc(currentSpecifier,
+                                specifierSize += SPECIFIER_SIZE);
+                }
+
+                modifier = ch;
+                i++;
+                CHECK_END
+            }
+        }
+
+        /* Finally, the conversion character. */
+        {
+            char str[2] = { 0, 0 };
+            ch = [format characterAtIndex:i];
+            str[0] = ch;
+
+            strcat(currentSpecifier, str);
+            if(++specifierLen == specifierSize) {
+                currentSpecifier =
+                    Realloc(currentSpecifier,
+                            specifierSize += SPECIFIER_SIZE);
+            }
+
+            characterSpecifier = ch;
+        }
+
+        if (![self handleFormatSpecifierWithContext:context])
+            return NO;
+
+        i++;
+        *currentSpecifier = 0;
+        specifierLen = 0;
+
+        CHECK_END
+    }
+
+_return:
+    return YES;
+}
+
+- (BOOL)handleOrdinaryString:(NSString*)string
+{
+    return YES;
+}
+
+- (BOOL)handleFormatSpecifierWithContext:(void*)context
+{
+    return YES;
+}
+
+@end /* FormatScanner */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/Foundation.h b/libFoundation/Foundation/Foundation.h
new file mode 100644 (file)
index 0000000..e18b4cd
--- /dev/null
@@ -0,0 +1,116 @@
+/* 
+   Foundation.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __Foundation_h__
+#define __Foundation_h__
+
+// ANSI C headers
+
+#include <math.h>
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <float.h>
+#include <limits.h>
+#include <locale.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+// OpenStep Foundation headers
+
+#include <Foundation/NSAccount.h>
+#include <Foundation/NSAttributedString.h>
+#include <Foundation/NSArchiver.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/NSBundle.h>
+#include <Foundation/NSCharacterSet.h>
+#include <Foundation/NSClassDescription.h>
+#include <Foundation/NSCoder.h>
+#include <Foundation/NSData.h>
+#include <Foundation/NSDate.h>
+#include <Foundation/NSDateFormatter.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSDistributedLock.h>
+#include <Foundation/NSEnumerator.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSFileHandle.h>
+#include <Foundation/NSFileManager.h>
+#include <Foundation/NSFormatter.h>
+#include <Foundation/NSGeometry.h>
+#include <Foundation/NSHashTable.h>
+#include <Foundation/NSHost.h>
+#include <Foundation/NSInvocation.h>
+#include <Foundation/NSKeyValueCoding.h>
+#include <Foundation/NSLock.h>
+#include <Foundation/NSMapTable.h>
+#include <Foundation/NSConnection.h>
+#include <Foundation/NSMethodSignature.h>
+#include <Foundation/NSNull.h>
+#include <Foundation/NSNumberFormatter.h>
+#include <Foundation/NSNotification.h>
+#include <Foundation/NSNotificationQueue.h>
+#include <Foundation/NSObjCRuntime.h>
+#include <Foundation/NSObject.h>
+#include <Foundation/NSPort.h>
+#include <Foundation/NSPortCoder.h>
+#include <Foundation/NSPortMessage.h>
+#include <Foundation/NSPortNameServer.h>
+#include <Foundation/NSPathUtilities.h>
+#include <Foundation/NSPosixFileDescriptor.h>
+#include <Foundation/NSProcessInfo.h>
+#include <Foundation/NSRange.h>
+#include <Foundation/NSRunLoop.h>
+#include <Foundation/NSScanner.h>
+#include <Foundation/NSSerialization.h>
+#include <Foundation/NSSet.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSTask.h>
+#include <Foundation/NSThread.h>
+#include <Foundation/NSTimer.h>
+#include <Foundation/NSUndoManager.h>
+#include <Foundation/NSUserDefaults.h>
+#include <Foundation/NSUtilities.h>
+#include <Foundation/NSURL.h>
+#include <Foundation/NSValue.h>
+#include <Foundation/NSZone.h>
+
+#define HAVE_NSNull             1
+#define HAVE_NSClassDescription 1
+#define HAVE_NSKeyValueCoding   1
+
+#endif /* __Foundation_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/GCArray.m b/libFoundation/Foundation/GCArray.m
new file mode 100644 (file)
index 0000000..ed54ae7
--- /dev/null
@@ -0,0 +1,342 @@
+/* 
+   GCArray.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <config.h>
+
+#include "common.h"
+#include <extensions/objc-runtime.h>
+#include <extensions/GCArray.h>
+#include <extensions/GCObject.h>
+#include <extensions/GarbageCollector.h>
+#include <extensions/NSException.h>
+#include <extensions/exceptions/GeneralExceptions.h>
+#include <Foundation/NSUtilities.h>
+
+@implementation GCArray
+
++ (void)initialize
+{
+    static BOOL initialized = NO;
+
+    if(!initialized) {
+       initialized = YES;
+       class_add_behavior(self, [GCObject class]);
+    }
+}
+
+- (id)initWithObjects:(id *)objects count:(unsigned int)count
+{
+    unsigned i;
+    
+    self->items =
+        Calloc(count > 0 ? count : 1, sizeof(id));
+    self->isGarbageCollectable =
+        CallocAtomic(count > 0 ? count : 1, sizeof(BOOL));
+    self->itemsCount = count;
+    for (i = 0; i < count; i++) {
+       if (!(items[i] = RETAIN(objects[i])))
+           [[[InvalidArgumentException alloc] 
+                   initWithReason:@"Nil object to be added in array"] raise];
+       else isGarbageCollectable[i] = [objects[i] isGarbageCollectable];
+    }
+    return self;
+}
+
+- (id)initWithArray:(NSArray*)anotherArray
+{
+    unsigned i, count = [anotherArray count];
+
+    self->items = Calloc(count > 0 ? count : 1, sizeof(id));
+    self->isGarbageCollectable =
+        CallocAtomic(count > 0 ? count : 1, sizeof(BOOL));
+    self->itemsCount = count;
+    for (i = 0; i < itemsCount; i++) {
+       items[i] = RETAIN([anotherArray objectAtIndex:i]);
+       isGarbageCollectable[i] = [items[i] isGarbageCollectable];
+    }
+    return self;
+}
+
+- (void)dealloc
+{
+    unsigned int index;
+
+    if ([GarbageCollector isGarbageCollecting]) {
+       for (index = 0; index < itemsCount; index++)
+           if(!isGarbageCollectable[index])
+               RELEASE(items[index]);
+    }
+    else {
+       for (index = 0; index < itemsCount; index++)
+           RELEASE(items[index]);
+    }
+
+    lfFree(items);
+    lfFree(isGarbageCollectable);
+    [super dealloc];
+}
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    if (NSShouldRetainWithZone(self, zone))
+       return RETAIN(self);
+    return [[GCArray allocWithZone:zone] initWithArray:self copyItems:YES];
+}
+
+- (id)mutableCopyWithZone:(NSZone*)zone
+{
+    return [[GCMutableArray allocWithZone:zone]
+               initWithArray:self copyItems:YES];
+}
+
+- (id)objectAtIndex:(unsigned int)index
+{
+    if (index >= itemsCount)
+       [[[RangeException alloc] 
+               initWithReason:@"objectAtIndex: in NSArray" 
+               size:itemsCount index:index] raise];
+    return items[index];
+}
+
+- (unsigned int)count
+{
+    return itemsCount;
+}
+
+- (unsigned int)indexOfObjectIdenticalTo:(id)anObject
+{
+    unsigned i;
+    for (i = 0; i < itemsCount; i++)
+       if (items[i] == anObject)
+               return i;
+    return NSNotFound;
+}
+
+- (void)gcDecrementRefCountOfContainedObjects
+{
+    int i, count;
+
+    for (i = 0, count = [self count]; i < count; i++)
+       if (isGarbageCollectable[i])
+           [[self objectAtIndex:i] gcDecrementRefCount];
+}
+
+- (BOOL)gcIncrementRefCountOfContainedObjects
+{
+    int i, count;
+
+    if ([(id)self gcAlreadyVisited])
+       return NO;
+    [(id)self gcSetVisited:YES];
+
+    for (i = 0, count = [self count]; i < count; i++)
+       if(isGarbageCollectable[i]) {
+           id object = [self objectAtIndex:i];
+           [object gcIncrementRefCount];
+           [object gcIncrementRefCountOfContainedObjects];
+       }
+    return YES;
+}
+
+- (Class)classForCoder
+{
+    return [GCArray class];
+}
+
+@end /* GCArray */
+
+
+@implementation GCMutableArray
+
++ (void)initialize
+{
+    static BOOL initialized = NO;
+    if(!initialized) {
+       initialized = YES;
+       class_add_behavior(self, [GCArray class]);
+    }
+}
+
+- (id)init
+{
+    return [self initWithCapacity:1];
+}
+
+- (id)initWithCapacity:(unsigned int)aNumItems
+{
+    if (aNumItems == 0) aNumItems = 16;
+    self->items = Calloc(aNumItems, sizeof(id));
+    self->isGarbageCollectable = CallocAtomic(aNumItems, sizeof(BOOL));
+    self->maxItems = aNumItems;
+    self->itemsCount = 0;
+    return self;
+}
+
+- (id)initWithObjects:(id *)objects count:(unsigned int)count
+{
+    unsigned i;
+    
+    self->maxItems = count > 0 ? count : 1;
+    self->items = Calloc(maxItems, sizeof(id));
+    self->isGarbageCollectable = CallocAtomic(maxItems, sizeof(BOOL));
+    self->itemsCount = count;
+    
+    for (i = 0; i < count; i++) {
+       if (!(items[i] = RETAIN(objects[i]))) {
+           [[[InvalidArgumentException alloc] 
+                   initWithReason:@"Nil object to be added in array"] raise];
+        }
+       else
+            isGarbageCollectable[i] = [objects[i] isGarbageCollectable];
+    }
+    return self;
+}
+
+- (id)initWithArray:(NSArray*)anotherArray
+{
+    unsigned i, count = [anotherArray count];
+
+    self->maxItems = count > 0 ? count : 1;
+    self->items = Calloc(self->maxItems, sizeof(id));
+    self->isGarbageCollectable = CallocAtomic(self->maxItems, sizeof(BOOL));
+    self->itemsCount = count;
+    for (i = 0; i < itemsCount; i++) {
+       items[i] = RETAIN([anotherArray objectAtIndex:i]);
+       isGarbageCollectable[i] = [items[i] isGarbageCollectable];
+    }
+    return self;
+}
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    return [[GCArray allocWithZone:zone] 
+               initWithArray:self copyItems:YES];
+}
+
+- (id)mutableCopyWithZone:(NSZone*)zone
+{
+    return [[GCMutableArray allocWithZone:zone] 
+               initWithArray:self copyItems:YES];
+}
+
+- (void)insertObject:(id)anObject atIndex:(unsigned int)index
+{
+    unsigned int i;
+    if (!anObject)
+       [[[InvalidArgumentException alloc] 
+               initWithReason:@"Nil object to be added in array"] raise];
+    if (index > itemsCount)
+       [[[RangeException alloc] 
+               initWithReason:@"insertObject:atIndex: in GCMutableArray" 
+               size:itemsCount index:index] raise];
+    if (itemsCount == maxItems) {
+       if (maxItems) {
+           maxItems += (maxItems >> 1) ? (maxItems >>1) : 1;
+       }
+       else {
+           maxItems = 1;
+       }
+       items = (id*)Realloc(items, sizeof(id) * maxItems);
+       isGarbageCollectable = (BOOL*)Realloc(isGarbageCollectable,
+                                             sizeof(BOOL) * maxItems);
+    }
+    for(i = itemsCount; i > index; i--) {
+       items[i] = items[i - 1];
+       isGarbageCollectable[i] = isGarbageCollectable[i - 1];
+    }
+    items[index] = RETAIN(anObject);
+    isGarbageCollectable[index] = [anObject isGarbageCollectable];
+    itemsCount++;
+}
+
+- (void)addObject:(id)anObject
+{
+    [self insertObject:anObject atIndex:itemsCount];
+}
+
+- (void)replaceObjectAtIndex:(unsigned int)index  withObject:(id)anObject
+{
+    if (!anObject)
+       [[[InvalidArgumentException alloc] 
+               initWithReason:@"Nil object to be added in array"] raise];
+    if (index >= itemsCount)
+       [[[RangeException alloc] 
+               initWithReason:@"GCMutableArray replaceObjectAtIndex" 
+               size:itemsCount index:index] raise];
+    ASSIGN(items[index], anObject);
+    isGarbageCollectable[index] = [anObject isGarbageCollectable];
+}
+
+- (void)removeObjectsFrom:(unsigned int)index
+       count:(unsigned int)count
+{
+    unsigned i;
+    if (index + count > itemsCount)
+       [[[RangeException alloc]
+               initWithReason:@"removeObjectsFrom:count: in GCMutableArray"
+               size:itemsCount index:index] raise];
+    if (!count)
+       return;
+    for (i = index; i < index + count; i++)
+       RELEASE(items[index]);
+
+    for (i = index + count; i < itemsCount; i++, index++) {
+       items[index] = items[i];
+       isGarbageCollectable[index] = isGarbageCollectable[i];
+    }
+    for (; index < itemsCount; index++)
+       items[index] = (id)0x3;
+
+    itemsCount -= count;
+}
+
+- (void)removeAllObjects
+{
+    [self removeObjectsFrom:0 count:itemsCount];
+}
+
+- (void)removeLastObject
+{
+    if (itemsCount)
+       [self removeObjectsFrom:(itemsCount - 1) count:1];
+}
+
+- (void)removeObjectAtIndex:(unsigned int)index
+{
+    [self removeObjectsFrom:index count:1];
+}
+
+- (Class)classForCoder
+{
+    return [GCMutableArray class];
+}
+
+@end /* GCMutableArray */
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/GCDictionary.m b/libFoundation/Foundation/GCDictionary.m
new file mode 100644 (file)
index 0000000..22d10e0
--- /dev/null
@@ -0,0 +1,347 @@
+/* 
+   GCDictionary.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <config.h>
+#include <Foundation/NSString.h>
+
+#include <extensions/objc-runtime.h>
+#include <extensions/GCDictionary.h>
+#include <extensions/NSException.h>
+#include <extensions/exceptions/GeneralExceptions.h>
+#include <extensions/GCObject.h>
+#include <extensions/GarbageCollector.h>
+#include "common.h"
+
+/*
+ * TODO: copyWithZone:
+ */
+
+@interface _GCDictionaryKeyEnumerator : NSEnumerator
+{
+    GCDictionary*      dict;
+    NSMapEnumerator    enumerator;
+}
+
+- (id)initWithDictionary:(id)_dict;
+- (id)nextObject;
+
+@end /* _GCDictionaryKeyEnumerator */
+
+@implementation _GCDictionaryKeyEnumerator
+
+- (id)initWithDictionary:(id)_dict
+{
+    dict = RETAIN(_dict);
+    enumerator = [dict __keyEnumerator];
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(dict);
+    [super dealloc];
+}
+
+- (id)nextObject
+{
+    GCObjectCollectable *keyStruct, *valueStruct;
+    return NSNextMapEnumeratorPair(&enumerator, 
+       (void**)&keyStruct, (void**)&valueStruct) ? keyStruct->object : nil;
+}
+
+@end /* _GCDictionaryKeyEnumerator */
+
+
+@implementation GCDictionary
+
+static unsigned __GCHashObject(NSMapTable *table,
+    const GCObjectCollectable* objectStruct)
+{
+    return [(NSObject*)(objectStruct->object) hash];
+}
+
+static BOOL __GCCompareObjects(
+    NSMapTable *table, 
+    const GCObjectCollectable* objectStruct1,
+    const GCObjectCollectable* objectStruct2)
+{
+    return [objectStruct1->object isEqual:objectStruct2->object];
+}
+
+static void __GCRetainObjects(NSMapTable *table,
+    const GCObjectCollectable* objectStruct)
+{
+    (void)RETAIN(objectStruct->object);
+}
+
+static void __GCReleaseObjects(NSMapTable *table,
+    GCObjectCollectable* objectStruct)
+{
+    if([GarbageCollector isGarbageCollecting]) {
+       if(!objectStruct->isGarbageCollectable)
+           RELEASE(objectStruct->object);
+    }
+    else
+       RELEASE(objectStruct->object);
+    lfFree(objectStruct);
+}
+
+static NSString* __GCDescribeObjects(NSMapTable *table,
+    const GCObjectCollectable* objectStruct)
+{
+    return [objectStruct->object description];
+}
+
+static const NSMapTableKeyCallBacks GCOwnedStructMapKeyCallBacks = {
+    (unsigned(*)(NSMapTable *, const void *))__GCHashObject,
+    (BOOL(*)(NSMapTable *, const void *, const void *))__GCCompareObjects,
+    (void (*)(NSMapTable *, const void *anObject))__GCRetainObjects,
+    (void (*)(NSMapTable *, void *anObject))__GCReleaseObjects,
+    (NSString *(*)(NSMapTable *, const void *))__GCDescribeObjects,
+    (const void *)NULL
+}; 
+
+static const NSMapTableValueCallBacks GCOwnedStructValueCallBacks = {
+    (void (*)(NSMapTable *, const void *))__GCRetainObjects,
+    (void (*)(NSMapTable *, void *))__GCReleaseObjects,
+    (NSString *(*)(NSMapTable *, const void *))__GCDescribeObjects
+}; 
+
++ (void)initialize
+{
+    static BOOL initialized = NO;
+
+    if(!initialized) {
+       initialized = YES;
+       class_add_behavior(self, [GCObject class]);
+    }
+}
+
+- (void)_createTableWithSize:(unsigned)size
+{
+    table = NSCreateMapTableWithZone(GCOwnedStructMapKeyCallBacks,
+                   GCOwnedStructValueCallBacks, size, [self zone]);
+}
+
+- (id)initWithDictionary:(NSDictionary*)dictionary
+{
+    id keys = [dictionary keyEnumerator];
+    id key;
+
+    [self _createTableWithSize:([dictionary count] * 4) / 3];
+
+    while ((key = [keys nextObject])) {
+       GCObjectCollectable* keyStruct = Malloc(sizeof(GCObjectCollectable));
+       GCObjectCollectable* valueStruct = Malloc(sizeof(GCObjectCollectable));
+       id value = [dictionary objectForKey:key];
+       keyStruct->object = key;
+       keyStruct->isGarbageCollectable = [key isGarbageCollectable];
+       valueStruct->object = value;
+       valueStruct->isGarbageCollectable = [value isGarbageCollectable];
+       NSMapInsert(table, keyStruct, valueStruct);
+    }
+    
+    return self;
+}
+
+- (id)initWithObjects:(id*)objects
+    forKeys:(id*)keys 
+    count:(unsigned int)count
+{
+    [self _createTableWithSize:(count * 4) / 3];
+
+    if (!count)
+       return self;
+    while(count--) {
+       GCObjectCollectable* keyStruct;
+       GCObjectCollectable* valueStruct;
+
+       if (!keys[count] || !objects[count])
+           [[[InvalidArgumentException alloc] 
+                   initWithReason:@"Nil object to be added in dictionary"] raise];
+       keyStruct = Malloc(sizeof(GCObjectCollectable));
+       valueStruct = Malloc(sizeof(GCObjectCollectable));
+       keyStruct->object = keys[count];
+       keyStruct->isGarbageCollectable = [keys[count] isGarbageCollectable];
+       valueStruct->object = objects[count];
+       valueStruct->isGarbageCollectable
+           = [objects[count] isGarbageCollectable];
+       NSMapInsert(table, keyStruct, valueStruct);
+    }
+    return self;
+}
+
+- (void)dealloc
+{
+    NSFreeMapTable(table);
+    [super dealloc];
+}
+
+- (NSEnumerator *)keyEnumerator
+{
+    return AUTORELEASE([[_GCDictionaryKeyEnumerator alloc]
+                           initWithDictionary:self]);    
+}
+
+- (id)objectForKey:(id)key
+{
+    GCObjectCollectable keyStruct = { key, 0 };
+    GCObjectCollectable* valueStruct = NSMapGet(table,
+                                               (void**)&keyStruct);
+    return valueStruct ? valueStruct->object : nil;
+}
+
+- (unsigned int)count
+{
+    return NSCountMapTable(table);
+}
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    if (NSShouldRetainWithZone(self, zone))
+       return RETAIN(self);
+    else return        [[GCDictionary alloc] initWithDictionary:self copyItems:YES];
+}
+
+- (id)mutableCopyWithZone:(NSZone*)zone
+{
+    return [[GCMutableDictionary allocWithZone:zone]
+               initWithDictionary:self];
+}
+
+/* Private */
+- (NSMapEnumerator)__keyEnumerator
+{
+    return NSEnumerateMapTable(table);
+}
+
+- (void)gcDecrementRefCountOfContainedObjects
+{
+    NSMapEnumerator enumerator = NSEnumerateMapTable(table);
+    GCObjectCollectable *keyStruct, *valueStruct;
+
+    while(NSNextMapEnumeratorPair(&enumerator,
+           (void**)&keyStruct, (void**)&valueStruct)) {
+       if(keyStruct->isGarbageCollectable)
+           [keyStruct->object gcDecrementRefCount];
+       if(valueStruct->isGarbageCollectable)
+           [valueStruct->object gcDecrementRefCount];
+    }
+}
+
+- (BOOL)gcIncrementRefCountOfContainedObjects
+{
+    NSMapEnumerator enumerator;
+    GCObjectCollectable *keyStruct, *valueStruct;
+
+    if([(id)self gcAlreadyVisited])
+       return NO;
+    [(id)self gcSetVisited:YES];
+
+    enumerator = NSEnumerateMapTable(table);
+    while(NSNextMapEnumeratorPair(&enumerator,
+           (void**)&keyStruct, (void**)&valueStruct)) {
+       if(keyStruct->isGarbageCollectable) {
+           [keyStruct->object gcIncrementRefCount];
+           [keyStruct->object gcIncrementRefCountOfContainedObjects];
+       }
+       if(valueStruct->isGarbageCollectable) {
+           [valueStruct->object gcIncrementRefCount];
+           [valueStruct->object gcIncrementRefCountOfContainedObjects];
+       }
+    }
+    return YES;
+}
+
+- (Class)classForCoder
+{
+    return [GCDictionary class];
+}
+
+@end /* GCDictionary */
+
+
+@implementation GCMutableDictionary
+
++ (void)initialize
+{
+    static BOOL initialized = NO;
+    if(!initialized) {
+       initialized = YES;
+       class_add_behavior(self, [GCDictionary class]);
+    }
+}
+
+- (id)init
+{
+    return [self initWithCapacity:0];
+}
+
+- (id)initWithCapacity:(unsigned int)aNumItems
+{
+    [(id)self _createTableWithSize:(aNumItems * 4) / 3];
+    return self;
+}
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    return [[GCDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (void)setObject:(id)anObject forKey:(id)aKey
+{
+    GCObjectCollectable *keyStruct = Malloc(sizeof(GCObjectCollectable));
+    GCObjectCollectable *valueStruct = Malloc(sizeof(GCObjectCollectable));
+
+    keyStruct->object = aKey;
+    keyStruct->isGarbageCollectable = [aKey isGarbageCollectable];
+    valueStruct->object = anObject;
+    valueStruct->isGarbageCollectable = [anObject isGarbageCollectable];
+    NSMapInsert(table, keyStruct, valueStruct);
+}
+
+- (void)removeObjectForKey:(id)key
+{
+    GCObjectCollectable keyStruct = { key, 0 };
+    NSMapRemove(table, (void**)&keyStruct);
+}
+
+- (void)removeAllObjects
+{
+    NSResetMapTable(table);
+}
+
+- (Class)classForCoder
+{
+    return [GCMutableDictionary class];
+}
+
+@end /* GCMutableDictionary */
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/GCObject.m b/libFoundation/Foundation/GCObject.m
new file mode 100644 (file)
index 0000000..624e432
--- /dev/null
@@ -0,0 +1,176 @@
+/* 
+   GCObject.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSUtilities.h>
+
+#include <extensions/GCObject.h>
+#include <extensions/GarbageCollector.h>
+#include <extensions/objc-runtime.h>
+
+
+@implementation GCObject
+
++ allocWithZone:(NSZone*)zone
+{
+    id newObject = [super allocWithZone:zone];
+    [GarbageCollector addObject:newObject];
+    ((GCObject*)newObject)->gcFlags.refCount = 1;
+    return newObject;
+}
+
+- copyWithZone:(NSZone*)zone
+{
+    id newObject = NSCopyObject(self, 0, zone);
+    [GarbageCollector addObject:newObject];
+    ((GCObject*)newObject)->gcFlags.refCount = 1;
+    return newObject;
+}
+
+- (oneway void)release
+{
+#if LIB_FOUNDATION_VERSION
+    extern BOOL __autoreleaseEnableCheck;
+
+    // check if retainCount is Ok
+    if (__autoreleaseEnableCheck) {
+       int toCome = [NSAutoreleasePool autoreleaseCountForObject:self];
+       if (toCome && toCome + 1 > [self retainCount]) {
+           NSLog(@"Release[%p] release check for object %@ "
+                  @"has %d references and %d pending calls to "
+                  @"release in autorelease pools\n", 
+                 self, self, [self retainCount], toCome);
+           return;
+       }
+    }
+#endif /* LIB_FOUNDATION_VERSION */
+
+    if(gcFlags.refCount > 0 && --gcFlags.refCount == 0) {
+       [GarbageCollector objectWillBeDeallocated:self];
+       [self dealloc];
+    }
+}
+
+- retain
+{
+    gcFlags.refCount++;
+    return self;
+}
+
+- (unsigned int)retainCount
+{
+    return gcFlags.refCount;
+}
+
+- gcSetNextObject:(id)anObject
+{
+    gcNextObject = anObject;
+    return self;
+}
+
+- gcSetPreviousObject:(id)anObject
+{
+    gcPreviousObject = anObject;
+    return self;
+}
+
+- (id)gcNextObject             { return gcNextObject; }
+- (id)gcPreviousObject         { return gcPreviousObject; }
+
+- (BOOL)gcAlreadyVisited
+{
+    return gcFlags.gcVisited;
+}
+
+- (void)gcSetVisited:(BOOL)flag
+{
+    gcFlags.gcVisited = flag;
+}
+
+- (void)gcDecrementRefCountOfContainedObjects
+{
+}
+
+- (BOOL)gcIncrementRefCountOfContainedObjects
+{
+    if(gcFlags.gcVisited)
+       return NO;
+    gcFlags.gcVisited = YES;
+    return YES;
+}
+
+- (BOOL)isGarbageCollectable
+{
+    return YES;
+}
+
+- (void)gcIncrementRefCount
+{
+   gcFlags.refCount++;
+}
+
+- (void)gcDecrementRefCount
+{
+   gcFlags.refCount--;
+}
+
++ error:(const char *)aString, ...
+{
+    va_list ap;
+
+    va_start(ap, aString);
+    vfprintf(stderr, aString, ap);
+    va_end(ap);
+    return self;
+}
+
+- doesNotRecognize:(SEL)aSelector
+{
+    return [isa error:"%s does not recognize selector %s\n",
+           object_get_class_name(self),
+           sel_get_name(aSelector)];
+}
+
+@end /* GCObject */
+
+@implementation NSObject (GarbageCollecting)
+
+- (BOOL)isGarbageCollectable
+{
+    return NO;
+}
+
+@end /* NSObject (GarbageCollecting) */
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/GNUmakefile b/libFoundation/Foundation/GNUmakefile
new file mode 100644 (file)
index 0000000..437a9f7
--- /dev/null
@@ -0,0 +1,228 @@
+# 
+#  GNUmakefile.gnustep
+#
+#  Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+#  All rights reserved.
+#
+#  Author: Ovidiu Predescu <ovidiu@net-community.com>
+#  Date: September 1997
+#
+#  This file is part of libFoundation.
+#
+#  Permission to use, copy, modify, and distribute this software and its
+#  documentation for any purpose and without fee is hereby granted, provided
+#  that the above copyright notice appear in all copies and that both that
+#  copyright notice and this permission notice appear in supporting
+#  documentation.
+#
+#  We disclaim all warranties with regard to this software, including all
+#  implied warranties of merchantability and fitness, in no event shall
+#  we be liable for any special, indirect or consequential damages or any
+#  damages whatsoever resulting from loss of use, data or profits, whether in
+#  an action of contract, negligence or other tortious action, arising out of
+#  or in connection with the use or performance of this software.
+#
+
+-include ../gsfix.make
+
+ifeq ($(GNUSTEP_SYSTEM_ROOT),)
+
+$(warning ERROR: Your $(GNUSTEP_SYSTEM_ROOT) environment variable is empty !)
+$(error Please try again after running ". $(GNUSTEP_MAKEFILES)/GNUstep.sh")
+
+else
+
+# ZNeK: hardcoded this due to removal of support for other runtimes
+OBJC_RUNTIME=GNU
+
+GNUSTEP_INSTALLATION_DIR = $(GNUSTEP_SYSTEM_ROOT)
+
+include libFoundation.make
+include $(GNUSTEP_MAKEFILES)/common.make
+-include $(GNUSTEP_TARGET_CPU)/$(GNUSTEP_TARGET_OS)/$(OBJC_RUNTIME)/config.mak
+include ../Version
+
+ifeq ($(gc), yes)
+ifeq ($(LIBFOUNDATION_WITH_GC), yes)
+# With a recent gnustep-make, we should redefine GNUSTEP_OBJ_DIR_NAME;
+# gnustep-make would recompute GNUSTEP_OBJ_DIR from that.  With an old
+# gnustep-make, we should redefine GNUSTEP_OBJ_DIR.  We redefine both
+# which works in all cases; this doesn't support GNUSTEP_BUILD_DIR
+# though.
+GNUSTEP_OBJ_DIR = $(GNUSTEP_OBJ_PREFIX)/$(GNUSTEP_TARGET_DIR)/$(OBJC_RUNTIME)-gc
+GNUSTEP_OBJ_DIR_NAME = $(GNUSTEP_OBJ_PREFIX)/$(GNUSTEP_TARGET_DIR)/$(OBJC_RUNTIME)-gc
+else # $(LIBFOUNDATION_WITH_GC) == no
+GNUSTEP_OBJ_DIR = $(GNUSTEP_OBJ_PREFIX)/$(GNUSTEP_TARGET_DIR)/$(OBJC_RUNTIME)
+GNUSTEP_OBJ_DIR_NAME = $(GNUSTEP_OBJ_PREFIX)/$(GNUSTEP_TARGET_DIR)/$(OBJC_RUNTIME)
+endif
+else # $(gc) == no
+GNUSTEP_OBJ_DIR = $(GNUSTEP_OBJ_PREFIX)/$(GNUSTEP_TARGET_DIR)/$(OBJC_RUNTIME)
+GNUSTEP_OBJ_DIR_NAME = $(GNUSTEP_OBJ_PREFIX)/$(GNUSTEP_TARGET_DIR)/$(OBJC_RUNTIME)
+endif
+
+LIBRARY_NAME = libFoundation
+
+libFoundation_DLL_DEF = libFoundation.def
+ifeq ($(GNUSTEP_TARGET_OS),mingw32)
+libFoundation_LIBRARIES_DEPEND_UPON += -lobjc
+endif
+ifeq ($(GNUSTEP_TARGET_OS),cygwin32)
+libFoundation_LIBRARIES_DEPEND_UPON += -lobjc
+ADDITIONAL_CPPFLAGS += -DWIN=1 -D__WIN32__=1
+endif
+
+libFoundation_HEADER_FILES_DIR = ..
+libFoundation_HEADER_FILES_INSTALL_DIR = /libFoundation
+
+ADDITIONAL_CPPFLAGS += -DLIB_FOUNDATION_LIBRARY=1 -DFD_WITH_GSMAKE=1
+
+ADDITIONAL_INCLUDE_DIRS = \
+       -I.. -I$(GNUSTEP_TARGET_CPU)/$(GNUSTEP_TARGET_OS)/$(OBJC_RUNTIME)
+
+libFoundation_C_FILES    += cvtutf.c
+libFoundation_OBJC_FILES += behavior.m objc-runtime.m common.m realpath.m \
+       load.m NSObject.m NSObjectAllocation.m NSObjCRuntime.m NSVMPage.m \
+       NSDebug.m NSException.m NSAutoreleasePool.m NSEnumerator.m \
+       NSUtilities.m NSHashMap.m NSRange.m NSGeometry.m \
+       NSZone.m NSDefaultZone.m NSAllocDebugZone.m StackZone.m \
+       NSArray.m NSConcreteArray.m NSDictionary.m NSConcreteDictionary.m \
+       NSConcreteMutableDictionary.m \
+       NSData.m NSConcreteData.m NSSet.m NSConcreteSet.m \
+       NSValue.m NSConcreteValue.m NSNumber.m NSConcreteNumber.m \
+       NSString.m NSString+StringEncoding.m NSConcreteString.m \
+       NSPathUtilities.m NSConcreteUTF16String.m \
+       NSConcreteMutableString.m NSAttributedString.m \
+       NSCoder.m NSArchiver.m NSSerialization.m \
+       NSCharacterSet.m NSConcreteCharacterSet.m \
+       NSMethodSignature.m NSInvocation.m \
+       NSNotification.m NSNotificationQueue.m NSNotificationCenter.m \
+       NSDate.m NSConcreteDate.m \
+       NSScanner.m NSConcreteScanner.m \
+       NSCalendarDate.m NSCalendarDateScannerHandler.m NSCalendarDateScanf.m \
+       NSTimeZone.m NSConcreteTimeZone.m NSConcreteTimeZoneDetail.m \
+       NSProcessInfo.m NSUserDefaults.m NSBundle.m \
+       NSThread.m PrivateThreadData.m NSLock.m NSDistributedLock.m \
+       NSRunLoop.m NSTimer.m \
+       FormatScanner.m PrintfFormatScanner.m \
+       DefaultScannerHandler.m PrintfScannerHandler.m \
+       NSPosixFileDescriptor.m NSFileHandle.m NSConcreteFileHandle.m \
+       NSMappedData.m NSAccount.m NSFileManager.m \
+       NSHost.m NSTask.m NSPipe.m UnixSignalHandler.m \
+       GarbageCollector.m GCObject.m GCArray.m GCDictionary.m \
+       NSFormatter.m NSNumberFormatter.m NSDateFormatter.m NSProxy.m \
+       NSFrameInvocation.m NSObjectInvocation.m \
+       NSPort.m NSPortNameServer.m NSPortMessage.m NSUndoManager.m \
+       NSConnection.m NSPortCoder.m NSURL.m NSURLHandle.m NSFileURLHandle.m \
+       NSNull.m NSClassDescription.m \
+       NSDecimal.m NSDecimalNumber.m NSSortDescriptor.m NSError.m \
+       NSStream.m NSInputStream.m NSOutputStream.m \
+       NSExpression.m NSPredicateParser.m \
+       NSPredicate.m NSComparisonPredicate.m NSCompoundPredicate.m
+
+ifeq ($(use8bitstringsparser),yes)
+libFoundation_OBJC_FILES += PropertyListParser.m
+else
+libFoundation_OBJC_FILES += PropertyListParserUnichar.m
+endif
+
+ifeq ($(GNUSTEP_TARGET_OS),mingw32)
+libFoundation_OBJC_FILES += \
+       NSConcreteWindowsTask.m         \
+       NSConcreteWindowsFileHandle.m
+else
+ifeq ($(GNUSTEP_TARGET_OS),cygwin32)
+libFoundation_OBJC_FILES += \
+       NSConcreteWindowsTask.m \
+       NSConcreteWindowsFileHandle.m
+else
+libFoundation_OBJC_FILES += NSConcreteUnixTask.m
+endif
+endif
+
+ifeq ($(WITH_FFCALL),yes)
+libFoundation_OBJC_FILES            += FFCallInvocation.m
+libFoundation_LIBRARIES_DEPEND_UPON += -lcallback -lavcall
+endif
+
+libFoundation_HEADER_FILES = NSObject.h NSException.h NSAutoreleasePool.h \
+       NSZone.h NSAllocDebugZone.h NSDefaultZone.h \
+       NSArray.h NSDictionary.h NSSet.h NSString.h NSData.h NSCharacterSet.h \
+       NSUtilities.h NSHashTable.h NSMapTable.h NSGeometry.h NSRange.h \
+       NSEnumerator.h NSScanner.h StackZone.h \
+       NSNotification.h NSNotificationQueue.h \
+       NSInvocation.h NSMethodSignature.h NSObjCRuntime.h \
+       NSProcessInfo.h NSUserDefaults.h NSBundle.h \
+       NSThread.h NSLock.h NSDistributedLock.h \
+       NSRunLoop.h NSTimer.h NSCalendarDate.h \
+       NSValue.h NSDate.h NSPosixFileDescriptor.h NSFileHandle.h \
+       NSHost.h NSTask.h UnixSignalHandler.h \
+       NSPathUtilities.h NSCoder.h NSArchiver.h NSSerialization.h \
+       NSConcreteArray.h NSConcreteCharacterSet.h NSConcreteData.h \
+       NSConcreteDate.h NSConcreteDictionary.h NSConcreteNumber.h \
+       NSConcreteSet.h NSConcreteString.h NSConcreteTimeZoneDetail.h \
+       NSConcreteValue.h NSAttributedString.h \
+       NSFormatter.h NSNumberFormatter.h NSDateFormatter.h NSProxy.h \
+       NSAccount.h NSFileManager.h NSByteOrder.h Foundation.h \
+       NSPort.h NSPortNameServer.h NSPortMessage.h NSUndoManager.h \
+       NSDebug.h NSConnection.h NSDistantObject.h NSPortCoder.h \
+       NSURL.h NSURLHandle.h NSNull.h NSClassDescription.h \
+       NSKeyValueCoding.h NSScriptKeyValueCoding.h \
+       NSDecimal.h NSDecimalNumber.h NSSortDescriptor.h NSStream.h \
+       NSError.h NSTimeZone.h \
+       NSExpression.h \
+       NSPredicate.h NSComparisonPredicate.h NSCompoundPredicate.h
+
+libFoundation_HEADER_FILES := \
+       $(addprefix Foundation/, $(libFoundation_HEADER_FILES))
+
+EXT_HFILES = objc-runtime.h encoding.h NSException.h \
+       GarbageCollector.h GCObject.h GCArray.h GCDictionary.h \
+       FormatScanner.h PrintfFormatScanner.h \
+       DefaultScannerHandler.h PrintfScannerHandler.h \
+       support.h \
+       $(addprefix exceptions/, FoundationException.h GeneralExceptions.h \
+           NSCoderExceptions.h)
+EXT_HFILES := $(addprefix extensions/, $(EXT_HFILES))
+
+libFoundation_HEADER_FILES += $(EXT_HFILES)
+
+EXCEPTION_MFILES = EncodingFormatExceptions.m FoundationException.m \
+       GeneralExceptions.m \
+       StringExceptions.m NSValueExceptions.m NSCoderExceptions.m \
+       NSInvocationExceptions.m NSFileHandleExceptions.m
+
+libFoundation_OBJC_FILES += $(addprefix exceptions/, $(EXCEPTION_MFILES))
+
+EXCEPTION_HFILES = $(EXCEPTION_MFILES:.m=.h) FoundationExceptions.h
+
+libFoundation_HEADER_FILES += \
+       $(addprefix Foundation/exceptions/, $(EXCEPTION_HFILES))
+
+# In case we use the Boehm's GC we should add libgc to the libraries as
+# we depend on it. This is used by some systems where creating a shared
+# library requires specifying the libraries it depends on (like OPENSTEP 4.x)
+
+ADDITIONAL_CPPFLAGS += -Wall -I$(GNUSTEP_TARGET_CPU)/$(GNUSTEP_TARGET_OS)
+
+libFoundation_SOVERSION=$(MAJOR_VERSION).$(MINOR_VERSION)
+
+# add the proper dynamic linking library, not being defined in current
+# gstep-make versions
+
+ifeq ($(GNUSTEP_TARGET_OS),linux-gnu)
+  libFoundation_LIBRARIES_DEPEND_UPON += -ldl
+endif
+
+ifeq ($(findstring solaris, $(GNUSTEP_TARGET_OS)), solaris)
+  libFoundation_LIBARIES_DEPEND_UPON += -ldl
+endif
+
+ifeq ($(findstring sysv4.2, $(GNUSTEP_TARGET_OS)), sysv4.2)
+  libFoundation_LIBRARIES_DEPEND_UPON += -ldl
+endif
+
+include $(GNUSTEP_MAKEFILES)/library.make
+
+include GNUmakefile.postamble
+
+endif
diff --git a/libFoundation/Foundation/GNUmakefile.alone b/libFoundation/Foundation/GNUmakefile.alone
new file mode 100644 (file)
index 0000000..958ae46
--- /dev/null
@@ -0,0 +1,281 @@
+# GNUmakefile.alone
+#
+# Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+# All rights reserved.
+#
+# Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+#
+# This file is part of libFoundation.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose and without fee is hereby granted, provided
+# that the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation.
+#
+# We disclaim all warranties with regard to this software, including all
+# implied warranties of merchantability and fitness, in no event shall
+# we be liable for any special, indirect or consequential damages or any
+# damages whatsoever resulting from loss of use, data or profits, whether in
+# an action of contract, negligence or other tortious action, arising out of
+# or in connection with the use or performance of this software.
+
+TOP    = ..
+INCLUDE        = $(TOP)/include
+LIB    = $(TOP)/lib
+
+include $(TOP)/config.mak
+include $(TOP)/sharedlib.mak
+
+.SUFFIXES:     .c .m .h $(objext)
+
+OBJDIR = obj
+TARGET = $(LIB)/$(LIB_FOUNDATION_NAME)
+
+ifeq ($(OBJC_RUNTIME), NeXT)
+MFILES = encoding.m misc.m thr-mach.m
+endif
+
+CFILES  += cvtutf.c
+MFILES += behavior.m objc-runtime.m common.m realpath.m load.m \
+       NSObject.m NSObjectAllocation.m NSObjCRuntime.m NSVMPage.m \
+       NSDebug.m NSException.m NSAutoreleasePool.m NSEnumerator.m \
+       NSUtilities.m NSHashMap.m NSRange.m NSGeometry.m \
+       NSZone.m NSDefaultZone.m NSAllocDebugZone.m StackZone.m \
+       NSArray.m NSConcreteArray.m NSDictionary.m NSConcreteDictionary.m \
+       NSConcreteMutableDictionary.m \
+       NSData.m NSConcreteData.m NSSet.m NSConcreteSet.m \
+       NSValue.m NSConcreteValue.m NSNumber.m NSConcreteNumber.m \
+       NSString.m NSString+DataEncoding.m NSConcreteString.m \
+       NSPathUtilities.m NSConcreteUTF16String.m \
+       NSConcreteMutableString.m \
+       NSCoder.m NSArchiver.m NSSerialization.m \
+       NSCharacterSet.m NSConcreteCharacterSet.m \
+       NSMethodSignature.m NSInvocation.m \
+       NSNotification.m NSNotificationQueue.m NSNotificationCenter.m \
+       NSDate.m NSConcreteDate.m \
+       NSScanner.m NSConcreteScanner.m \
+       NSCalendarDate.m NSCalendarDateScannerHandler.m NSCalendarDateScanf.m \
+       NSTimeZone.m NSConcreteTimeZone.m NSConcreteTimeZoneDetail.m \
+       NSProcessInfo.m NSUserDefaults.m NSBundle.m \
+       NSThread.m PrivateThreadData.m NSLock.m NSDistributedLock.m \
+       NSRunLoop.m NSTimer.m \
+       FormatScanner.m PrintfFormatScanner.m \
+       DefaultScannerHandler.m PrintfScannerHandler.m \
+       NSPosixFileDescriptor.m NSFileHandle.m NSConcreteFileHandle.m \
+       NSMappedData.m NSAccount.m NSFileManager.m \
+       NSHost.m NSTask.m NSPipe.m UnixSignalHandler.m \
+       GarbageCollector.m GCObject.m GCArray.m GCDictionary.m \
+       NSFormatter.m NSNumberFormatter.m NSDateFormatter.m \
+       PropertyListParser.m NSProxy.m \
+       NSConcreteUnixTask.m NSConcreteWindowsTask.m \
+       NSFrameInvocation.m NSObjectInvocation.m \
+       NSPort.m NSPortNameServer.m NSPortMessage.m NSUndoManager.m \
+       NSSocketPort.m NSMessagePort.m NSConnection.m NSPortCoder.m \
+       NSNull.m NSClassDescription.m \
+
+HFILES = NSObject.h lfmemory.h NSException.h NSAutoreleasePool.h \
+       NSZone.h NSAllocDebugZone.h NSDefaultZone.h \
+       NSArray.h NSDictionary.h NSSet.h NSString.h NSData.h NSCharacterSet.h \
+       NSUtilities.h NSHashTable.h NSMapTable.h NSGeometry.h NSRange.h \
+       NSEnumerator.h NSScanner.h StackZone.h \
+       NSNotification.h NSNotificationQueue.h \
+       NSInvocation.h NSMethodSignature.h NSObjCRuntime.h \
+       NSProcessInfo.h NSUserDefaults.h NSBundle.h \
+       NSThread.h NSLock.h NSDistributedLock.h \
+       NSRunLoop.h NSTimer.h NSCalendarDate.h \
+       NSValue.h NSDate.h NSPosixFileDescriptor.h NSFileHandle.h \
+       NSPathUtilities.h NSCoder.h NSArchiver.h NSSerialization.h \
+       NSHost.h NSTask.h UnixSignalHandler.h \
+       NSConcreteArray.h NSConcreteCharacterSet.h NSConcreteData.h \
+       NSConcreteDate.h NSConcreteDictionary.h NSConcreteNumber.h \
+       NSConcreteSet.h NSConcreteString.h NSConcreteTimeZoneDetail.h \
+       NSConcreteValue.h \
+       NSFormatter.h NSNumberFormatter.h NSDateFormatter.h NSProxy.h \
+       NSAccount.h NSFileManager.h NSByteOrder.h Foundation.h \
+       NSPort.h NSPortNameServer.h NSPortMessage.h NSUndoManager.h \
+       NSDebug.h NSConnection.h NSDistantObject.h NSPortCoder.h \
+       NSNull.h NSClassDescription.h \
+       NSKeyValueCoding.h NSScriptKeyValueCoding.h \
+
+EXT_HFILES = objc-runtime.h encoding.h NSException.h \
+       GarbageCollector.h GCObject.h GCArray.h GCDictionary.h \
+       FormatScanner.h PrintfFormatScanner.h \
+       DefaultScannerHandler.h PrintfScannerHandler.h \
+       support.h \
+       $(addprefix exceptions/, FoundationException.h GeneralExceptions.h \
+           NSCoderExceptions.h)
+
+EXCEPTION_MFILES = EncodingFormatExceptions.m FoundationException.m \
+       GeneralExceptions.m \
+       StringExceptions.m NSValueExceptions.m NSCoderExceptions.m \
+       NSInvocationExceptions.m NSFileHandleExceptions.m
+
+EXCEPTION_HFILES = $(EXCEPTION_MFILES:.m=.h) FoundationExceptions.h
+
+OFILES          = $(MFILES:.m=$(objext)) $(CFILES:.c=$(objext))
+EXCEPTION_OFILES = $(EXCEPTION_MFILES:.m=$(objext))
+
+# The `all' and `install' targets. On systems with shared libs, make them to
+# build shared libs by default. Otherwise the defaults are the normal libs.
+ifeq ($(HAVE_SHARED_LIBS), yes)
+all check check-all: shared
+install: install_shared
+else
+all check check-all: static
+install: install_static
+endif
+
+install_static: static headers install_static_lib
+
+install_shared: shared headers install_shared_lib
+
+uninstall:
+       rm -rf $(includedir)/Foundation
+       rm -rf $(includedir)/extensions
+       rm -f $(libdir)/$(LIB_FOUNDATION_NAME)
+
+realclean::
+       rm -f NSStringPropList.[cm] tokens.h err.m mode.h NSStringScanner.m \
+               parser.dlg err.m mode.h parser.dlg remap.h tokens.h
+
+
+#
+# Other targets
+#
+compile: $(addprefix $(OBJDIR)/, $(OFILES) $(EXCEPTION_OFILES))
+
+static: $(OBJDIR) $(TARGET)
+
+ifeq ($(HAVE_SHARED_LIBS), yes)
+shared: $(SHARED_OBJDIR)
+       @$(MAKE) shared_lib CC="$(CC) $(ADDITIONAL_CC_FLAGS)" \
+               libext=$(shared_libext) OBJDIR=$(SHARED_OBJDIR)
+
+shared_lib: $(LIB_FOUNDATION_NAME)
+       cp $^ ../lib/$^
+
+$(LIB_FOUNDATION_NAME): $(addprefix $(OBJDIR)/, $(OFILES) $(EXCEPTION_OFILES))
+       $(SHARED_LIB_LINK_CMD)
+
+install_shared_lib:
+       @$(MAKE) __install_shared_lib CC="$(CC) $(ADDITIONAL_CC_FLAGS)" \
+               libext=$(shared_libext)
+
+__install_shared_lib:
+       $(INSTALL_SHARED_LIB_CMD)
+
+else # HAVE_SHARED_LIBS = no
+shared: static
+
+install_shared: install_static
+
+endif # HAVE_SHARED_LIBS = no
+
+
+$(TARGET): $(addprefix $(OBJDIR)/, $(OFILES) $(EXCEPTION_OFILES))
+       rm -f $@
+ifneq ($(LIBTOOL),)
+       $(LIBTOOL) -o $@ $^
+else
+       $(AR) rc $@ $^
+       $(RANLIB) $@
+endif
+
+objects: $(OBJDIR) headers \
+               $(addprefix $(OBJDIR)/, $(OFILES) $(EXCEPTION_OFILES))
+
+headers: $(includedir)/Foundation/exceptions \
+       $(includedir)/extensions/exceptions \
+       $(addprefix $(includedir)/Foundation/, $(HFILES)) \
+       $(addprefix $(includedir)/Foundation/exceptions/, $(EXCEPTION_HFILES))\
+       $(addprefix $(includedir)/extensions/, $(EXT_HFILES)) \
+       exception_header_file
+
+install_static_lib: $(libdir) $(TARGET)
+       $(INSTALL_DATA) $(TARGET) $(libdir)/$(LIB_FOUNDATION_NAME)
+       $(RANLIB) $(libdir)/$(LIB_FOUNDATION_NAME)
+
+ifneq ($(SHARED_OBJDIR), $(OBJDIR))
+$(SHARED_OBJDIR):
+       mkdir $@
+endif
+
+$(OBJDIR):
+       mkdir $@
+
+CFLAGS += -I. -DRESOURCES_PATH=\"$(sharedstatedir)\"
+
+mfile_compile_cmd = \
+       $(CC) $(CFLAGS) $(DEBUGFLAGS) -c $< -o $(OBJDIR)/$(@F)
+
+$(addprefix $(OBJDIR)/, %$(objext)) : %.c
+       $(mfile_compile_cmd)
+
+$(addprefix $(OBJDIR)/, %$(objext)) : %.m
+       $(mfile_compile_cmd)
+
+$(addprefix $(OBJDIR)/, %$(objext)) : $(addprefix exceptions/, %.m)
+       $(mfile_compile_cmd)
+
+$(OBJDIR)/NSCharacterSet$(objext): NSCharacterSet.m
+       $(mfile_compile_cmd) -DRESOURCES_PATH=\"$(sharedstatedir)\"
+
+$(OBJDIR)/NSTimeZone$(objext): NSTimeZone.m
+       $(mfile_compile_cmd) -DRESOURCES_PATH=\"$(sharedstatedir)\"
+
+$(OBJDIR)/NSBundle$(objext): NSBundle.m
+       $(mfile_compile_cmd) -DRESOURCES_PATH=\"$(sharedstatedir)\"
+
+NSConcreteNumber.m: NSConcreteNumber.m.sh
+       ./NSConcreteNumber.m.sh >NSConcreteNumber.m
+
+
+ifeq ($(NO_NESTED_FUNCTIONS), yes)
+exception_header_file:
+        $(INSTALL_DATA) NSExceptionWithoutNested.h \
+           $(includedir)/Foundation/NSException.h
+else
+ifeq ($(BROKEN_COMPILER), yes)
+exception_header_file:
+        $(INSTALL_DATA) NSClassicException.h \
+           $(includedir)/Foundation/NSException.h
+else
+exception_header_file:
+        $(INSTALL_DATA) NSFuncallException.h \
+           $(includedir)/Foundation/NSException.h
+endif
+endif
+
+$(includedir)/extensions/objc-runtime.h:
+       sed "s^#include <config.h>^#define $(OBJC_RUNTIME)_RUNTIME 1^" ../extensions/objc-runtime.h >temp.h
+       $(INSTALL_DATA) temp.h $@
+       rm temp.h
+
+$(addprefix $(includedir)/Foundation/, %.h): %.h
+       $(INSTALL_DATA) $< $@
+
+$(addprefix $(INCLUDE)/Foundation/exceptions/, %.h): \
+               $(addprefix exceptions/, %.h)
+       $(INSTALL_DATA) $< $@
+
+$(addprefix $(includedir)/extensions/, %.h): ../extensions/%.h
+       $(INSTALL_DATA) $< $@
+
+$(includedir)/Foundation $(includedir)/Foundation/exceptions \
+    $(includedir)/extensions/exceptions $(libdir):
+       ../mkinstalldirs $@
+
+clean:
+       rm -rf $(OBJDIR) $(SHARED_OBJDIR)
+
+distclean: clean
+       rm -f NSException.h NSConcreteNumber.m GNUmakefile \
+           libFoundation.make NSObject.h lfmemory.h
+
+realclean:: distclean
+
+#
+# Dependencies
+#
+$(OBJDIR)/NSScanner$(objext): NSScanner.m scanInt.def scanFloat.def
diff --git a/libFoundation/Foundation/GNUmakefile.postamble b/libFoundation/Foundation/GNUmakefile.postamble
new file mode 100644 (file)
index 0000000..1c24d61
--- /dev/null
@@ -0,0 +1,71 @@
+#  GNUmakefile.postamble
+#
+#  Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+#  All rights reserved.
+#
+#  Author: Ovidiu Predescu <ovidiu@net-community.com>
+#  Date: October 1997
+#
+#  This file is part of libFoundation.
+#
+#  Permission to use, copy, modify, and distribute this software and its
+#  documentation for any purpose and without fee is hereby granted, provided
+#  that the above copyright notice appear in all copies and that both that
+#  copyright notice and this permission notice appear in supporting
+#  documentation.
+#
+#  We disclaim all warranties with regard to this software, including all
+#  implied warranties of merchantability and fitness, in no event shall
+#  we be liable for any special, indirect or consequential damages or any
+#  damages whatsoever resulting from loss of use, data or profits, whether in
+#  an action of contract, negligence or other tortious action, arising out of
+#  or in connection with the use or performance of this software.
+#
+
+TOP = ..
+
+before-all:: $(GNUSTEP_OBJ_DIR)/exceptions
+
+DIR_FD      = $(GNUSTEP_HEADERS)$(libFoundation_HEADER_FILES_INSTALL_DIR)
+DIR_EXT_EXC = $(DIR_FD)/extensions/exceptions
+DIR_FD_EXC  = $(DIR_FD)/Foundation/exceptions
+DIR_PLAT    = $(DIR_FD)/$(GNUSTEP_TARGET_CPU)/$(GNUSTEP_TARGET_OS)/$(OBJC_RUNTIME)
+
+$(DIR_FD) :
+       @(if [ ! -d $@ ]; then \
+         echo $(MKINSTALLDIRS) $@; \
+         $(MKINSTALLDIRS) $@; \
+       fi)
+
+$(DIR_EXT_EXC) $(DIR_FD_EXC) $(DIR_PLAT) : $(DIR_FD)
+       @(if [ ! -d $@ ]; then \
+         echo $(MKINSTALLDIRS) $@; \
+         $(MKINSTALLDIRS) $@; \
+       fi)
+
+before-install:: $(DIR_EXT_EXC) $(DIR_FD_EXC) $(DIR_PLAT)
+
+CTO = $(GNUSTEP_TARGET_CPU)/$(GNUSTEP_TARGET_OS)/$(OBJC_RUNTIME)
+
+after-install-patchit ::
+       $(INSTALL_DATA) $(CTO)/real_exception_file.h $(GNUSTEP_HEADERS)$(libFoundation_HEADER_FILES_INSTALL_DIR)/$(CTO)
+       $(INSTALL_DATA) $(CTO)/lfmemory.h $(GNUSTEP_HEADERS)$(libFoundation_HEADER_FILES_INSTALL_DIR)/$(CTO)
+       $(INSTALL_DATA) libFoundation.make $(INSTALL_ROOT_DIR)$(GNUSTEP_MAKEFILES)/Additional
+
+after-install :: after-install-patchit
+
+
+$(GNUSTEP_OBJ_DIR)/exceptions: $(GNUSTEP_OBJ_DIR)
+       @if [ ! -d $@ ]; then echo $(MKDIRS) $@; $(MKDIRS) $@; fi
+
+# DEPRECATED, we optimize for the classes now!
+#NSConcreteNumber.m: NSConcreteNumber.m.sh
+#      ./NSConcreteNumber.m.sh >NSConcreteNumber.m
+
+after-distclean::
+       rm -rf libFoundation.make NSObject.h
+
+after-uninstall::
+       rm -f $(GNUSTEP_MAKEFILES)/Additional/libFoundation.make
+
+include fhs.make
diff --git a/libFoundation/Foundation/GarbageCollector.m b/libFoundation/Foundation/GarbageCollector.m
new file mode 100644 (file)
index 0000000..dd8dd58
--- /dev/null
@@ -0,0 +1,481 @@
+/* 
+   GarbageCollector.m
+
+   Copyright (C) 1995-1998 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and
+   its documentation for any purpose and without fee is hereby
+   granted, provided that the above copyright notice appear in all
+   copies and that both that copyright notice and this permission
+   notice appear in supporting documentation.
+
+   We disclaim all warranties with regard to this software, including
+   all implied warranties of merchantability and fitness, in no event
+   shall we be liable for any special, indirect or consequential
+   damages or any damages whatsoever resulting from loss of use, data
+   or profits, whether in an action of contract, negligence or other
+   tortious action, arising out of or in connection with the use or
+   performance of this software.  */
+
+#include <Foundation/common.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSLock.h>
+#include <Foundation/NSUtilities.h>
+#include <extensions/objc-runtime.h>
+#include <extensions/GCObject.h>
+#include <extensions/GarbageCollector.h>
+
+#if LIB_FOUNDATION_BOEHM_GC
+# include <gc.h>
+# include <gc_typed.h>
+#endif
+
+static BOOL isGarbageCollecting = NO;
+
+#if LIB_FOUNDATION_BOEHM_GC
+BOOL _usesBoehmGC = YES;
+static GC_descr nodeDescriptor1;
+static GC_descr nodeDescriptor2;
+#else
+BOOL _usesBoehmGC = NO;
+#endif
+
+extern NSRecursiveLock* libFoundationLock;
+extern Class __freedObjectClass;
+
+
+/* Stuff used by the garbage collector based on reference counting. */
+
+@interface __DummyGCObject : GCObject
+@end
+
+@implementation __DummyGCObject
++ allocWithZone:(NSZone*)zone
+{
+    return NSAllocateObject(self, 0, zone);
+}
+
+- (void)dealloc
+{
+}
+@end
+
+
+/* The GCDoubleLinkedList is a double linked list which contains as
+    the first element a dummy GCObject. This object is always the head
+    of the list. A new element is introduced immediately after the
+    head. This way we don't need to keep track of the head of the list
+    when we remove an element. */
+@interface GCDoubleLinkedList : NSObject
+{
+    id list;
+}
+- (void)addObject:(id)anObject;
+- (void)removeObject:(id)anObject;
+- (id)firstObject;
+- (void)removeAllObjects;
+@end
+
+
+@implementation GCDoubleLinkedList
+
+- init
+{
+    list = [__DummyGCObject new];
+    return self;
+}
+
+- (void)addObject:(id)anObject
+{
+    id next = [list gcNextObject];
+
+    [list gcSetNextObject:anObject];
+    [anObject gcSetNextObject:next];
+    [next gcSetPreviousObject:anObject];
+    [anObject gcSetPreviousObject:list];
+}
+
+- (void)removeObject:(id)anObject
+{
+    id prev = [anObject gcPreviousObject];
+    id next = [anObject gcNextObject];
+
+    [prev gcSetNextObject:next];
+    [next gcSetPreviousObject:prev];
+}
+
+- (id)firstObject
+{
+    return [list gcNextObject];
+}
+
+- (void)removeAllObjects
+{
+    [list gcSetNextObject:nil];
+}
+
+@end
+
+
+@implementation GarbageCollector
+
+#if !LIB_FOUNDATION_BOEHM_GC
+static id gcObjectsToBeVisited;
+#else
+static NSMapTable* postingObjectsToObservers = NULL;
+        /* Posting object to double linked list of observers
+          (listOfObservers).  The first element in listOfObservers is
+          a dummy element, used just to make the removing process
+          easier. */
+
+static NSMapTable* observersToPostingObjectNodes = NULL;
+        /* Observer to double linked list of nodes in listOfObservers,
+          where the observer appears. */
+
+static void gcCollect(void)
+{
+    puts("GARBAGE COLLECTING ...");
+}
+#endif
+
++ (void)initialize
+{
+#if LIB_FOUNDATION_BOEHM_GC
+    extern void (*GC_start_call_back)(void);
+    GC_word mask1 = 0x7;
+    GC_word mask2 = 0x3;
+
+    GC_start_call_back = gcCollect;
+    postingObjectsToObservers = NSCreateMapTableInvisibleKeysOrValues
+        (NSNonOwnedPointerMapKeyCallBacks,
+         NSNonOwnedPointerMapValueCallBacks,
+         119, YES, NO);
+    observersToPostingObjectNodes = NSCreateMapTableInvisibleKeysOrValues
+        (NSNonOwnedPointerMapKeyCallBacks,
+         NSNonOwnedPointerMapValueCallBacks,
+         119, YES, NO);
+    GC_MALLOC(4);
+    nodeDescriptor1 = GC_make_descriptor (&mask1, 4);
+    nodeDescriptor2 = GC_make_descriptor (&mask2, 4);
+#else
+    gcObjectsToBeVisited = [GCDoubleLinkedList new];
+#endif
+}
+
++ (BOOL)usesBoehmGC
+{
+    return _usesBoehmGC;
+}
+
++ (void)collectGarbages
+{
+#if LIB_FOUNDATION_BOEHM_GC
+    isGarbageCollecting = YES;
+    GC_gcollect();
+    isGarbageCollecting = NO;
+    return;
+#else
+    id object;
+
+    isGarbageCollecting = YES;
+
+    /*  First pass. All the objects in the gcObjectsToBeVisited list
+       receive the -decrementRefCount message. Each object should
+       decrement the ref count of all objects contained. */
+    object = [gcObjectsToBeVisited firstObject];
+    while(object) {
+       [object gcDecrementRefCountOfContainedObjects];
+       [object gcSetVisited:NO];
+       object = [object gcNextObject];
+    };
+
+    /*  Second pass. All the objects in the gcObjectsToBeVisited list
+       that have the refCount greater than 0 receive the
+       -incrementRefCount message.  Each object should increment the
+       ref count of all objects contained.  Then it should send the
+       -incrementRefCount message to all objects contained. */
+    object = [gcObjectsToBeVisited firstObject];
+    while(object) {
+       if([object retainCount])
+           [object gcIncrementRefCountOfContainedObjects];
+       object = [object gcNextObject];
+    }
+
+    /*  Third pass. All the objects that still have the refCount equal
+       with 0 are part of cyclic graphs and none of the objects from
+       this graph are held by some object outside graph. These
+       objects receive the -dealloc message. In this method they
+       should send the -dealloc message to objects that are garbage
+       collectable. An object could be asked if it is garbage
+       collectable by sending it the -isGarbageCollectable
+       message. */
+    object = [gcObjectsToBeVisited firstObject];
+    while(object) {
+       if([object retainCount] == 0) {
+           id nextObject = [object gcNextObject];
+
+           /*  Remove object from gcObjectsToBeVisited list. We have
+               to keep the old nextObject because after removing the
+               object from list its nextObject is altered. */
+           [gcObjectsToBeVisited removeObject:object];
+           [object dealloc];
+           object = nextObject;
+       }
+       else object = [object gcNextObject];
+    }
+
+    isGarbageCollecting = NO;
+#endif
+}
+
+@end /* GarbageCollector */
+
+
+@implementation GarbageCollector (ReferenceCountingGC)
+
++ (void)addObject:(id)anObject
+{
+#if !LIB_FOUNDATION_BOEHM_GC
+    [gcObjectsToBeVisited addObject:anObject];
+#endif
+}
+
++ (void)objectWillBeDeallocated:(id)anObject
+{
+#if !LIB_FOUNDATION_BOEHM_GC
+  {
+    /*  We can remove without fear the object from its list because
+       the head of the list is always the same. */
+    id prev = [anObject gcPreviousObject];
+    id next = [anObject gcNextObject];
+    [prev gcSetNextObject:next];
+    [next gcSetPreviousObject:prev];
+  }
+#endif
+}
+
++ (BOOL)isGarbageCollecting            { return isGarbageCollecting; }
+
+@end /* GarbageCollector (ReferenceCountingGC) */
+
+
+
+#if LIB_FOUNDATION_BOEHM_GC
+
+typedef struct _DoubleLinkedListNode1 {
+    struct _DoubleLinkedListNode1* next;
+    struct _DoubleLinkedListNode1* prev;
+    void* node;
+    /* weak */ id postingObject;
+} DoubleLinkedListNode1;
+
+typedef struct _DoubleLinkedListNode2 {
+    struct _DoubleLinkedListNode2* next;
+    struct _DoubleLinkedListNode2* prev;
+    /* weak */ id observer;
+    /* weak */ SEL selector;
+} DoubleLinkedListNode2;
+
+/* We assume a double linked list always has a head, which is actually
+   not part of the useful information maintained by the list. */
+
+static void* newNode1 (void)
+{
+    void* node
+        = GC_MALLOC_EXPLICTLY_TYPED (sizeof (struct _DoubleLinkedListNode1),
+                                     nodeDescriptor1);
+    memset (node, 0, sizeof (struct _DoubleLinkedListNode1));
+    return node;
+}
+
+static void* newNode2 (void)
+{
+    void* node
+        = GC_MALLOC_EXPLICTLY_TYPED (sizeof (struct _DoubleLinkedListNode2),
+                                     nodeDescriptor2);
+    memset (node, 0, sizeof (struct _DoubleLinkedListNode2));
+    return node;
+}
+
+static void removeNode (void* node)
+{
+    DoubleLinkedListNode1* prev = ((DoubleLinkedListNode1*)node)->prev;
+    DoubleLinkedListNode1* next = ((DoubleLinkedListNode1*)node)->next;
+
+    prev->next = next;
+    if (next)
+        next->prev = prev;
+}
+
+
+@implementation GarbageCollector (BoehmGCSupport)
+
+static void _do_finalize_object (void* object, void* client_data)
+{
+    /* Temporary set GC_dont_gc to YES */
+    int old_GC_dont_gc = GC_dont_gc;
+    DoubleLinkedListNode2* head2;
+    
+    GC_dont_gc = YES;
+    
+    fprintf(stderr,
+            "_do_finalize_object %08x (%s)\n",
+            (unsigned)object, ((GarbageCollector*)object)->isa->name);
+    fflush(stderr);
+    
+    /* Inform the observers of object that it will finalize */
+    head2 = NSMapGet (postingObjectsToObservers, object);
+    if (head2) {
+        DoubleLinkedListNode2* node = head2->next;
+
+        while (node) {
+            [node->observer performSelector:node->selector withObject:object];
+            node = node->next;
+        }
+        NSMapRemove (postingObjectsToObservers, object);
+    }
+    
+    [GarbageCollector unregisterObserver:object forObjectFinalization:nil];
+    
+    if ([(id)object respondsToSelector:@selector(gcFinalize)])
+        [(id)object gcFinalize];
+    
+    /* Set the class of anObject to FREED_OBJECT. The further messages
+       to this object will cause an error to occur. */
+    ((GarbageCollector*)object)->isa = __freedObjectClass;
+    
+    /* Restore the value of GC_dont_gc */
+    GC_dont_gc = old_GC_dont_gc;
+}
+
++ (void)registerForFinalizationObserver:(id)observer
+  selector:(SEL)selector
+  object:(id)object
+{
+    DoubleLinkedListNode1 *head1, *node1;
+    DoubleLinkedListNode2 *head2, *node2;
+
+    [libFoundationLock lock];
+
+    /* First insert 'object' in the postingObjectsToObservers map
+       table. The value in the map table is a double linked list whose
+       elements are nodes that contain the observer and the selector.
+       The first element in this list is a dummy element. */
+    head2 = NSMapGet (postingObjectsToObservers, object);
+    if (!head2) {
+        head2 = newNode2 ();
+        NSMapInsert (postingObjectsToObservers, object, head2);
+    }
+
+    node2 = newNode2 ();
+    node2->next = head2->next;
+    if (node2->next)
+        node2->next->prev = node2;
+    node2->prev = head2;
+    node2->observer = observer;
+    node2->selector = selector;
+    head2->next = node2;
+
+    /* Now insert 'observer' in observersToPostingObjectNodes map
+       table. The value in the map table is a double linked list whose
+       elements are nodes that contain the posting object; the 'node'
+       field of all nodes except the head are the nodes in
+       listOfObservers where the observer appears. The first element of
+       this list is a dummy element. */
+    head1 = NSMapGet (observersToPostingObjectNodes, observer);
+    if (!head1) {
+        head1 = newNode1 ();
+        NSMapInsert (observersToPostingObjectNodes, observer, head1);
+    }
+
+    node1 = newNode1 ();
+    node1->next = head1->next;
+    if (node1->next)
+        node1->next->prev = node1;
+    node1->prev = head1;
+    node1->node = node2;
+    node1->postingObject = object;
+    head1->next = node1;
+
+    /* Register finalizer for both the object and the observer. Make
+       sure the object and observer are instances, class objects are
+       statically allocated, they are not allocated by the collector. */
+    if (CLS_ISCLASS(((GarbageCollector*)object)->isa))
+        GC_REGISTER_FINALIZER(object, _do_finalize_object, NULL, NULL, NULL);
+    if (CLS_ISCLASS(((GarbageCollector*)observer)->isa))
+        GC_REGISTER_FINALIZER(observer, _do_finalize_object, NULL, NULL, NULL);
+
+    [libFoundationLock unlock];
+}
+
++ (void)unregisterObserver:(id)observer
+     forObjectFinalization:(id)object
+{
+    DoubleLinkedListNode1* head1;
+
+    [libFoundationLock lock];
+
+    /* Remove the object from the list of observers in case it's
+       registered as observer. */
+    head1 = NSMapGet (observersToPostingObjectNodes, observer);
+    if (head1) {
+        DoubleLinkedListNode1* node = head1->next;
+
+        if (!object) { /* Remove all the occurrences of observer */
+            while (node) {
+                removeNode (node->node);
+                node = node->next;
+            }
+            NSMapRemove (observersToPostingObjectNodes, observer);
+        }
+        else {
+            while (node) {
+                DoubleLinkedListNode1* next = node->next;
+
+                if (node->postingObject == object) {
+                    removeNode (node->node);
+                    removeNode (node);
+                    break;
+                }
+                node = next;
+            }
+            
+            /* Remove the observer from the map table if there are no
+               other objects to listen for. */
+            if (!head1->next)
+                NSMapRemove (observersToPostingObjectNodes, observer);
+        }
+    }
+    
+    [libFoundationLock unlock];
+}
+
+static int denied = 0;
+
++ (void)allowGarbageCollection
+{
+    denied--;
+    if (denied <= 0) GC_dont_gc = 0;
+}
++ (void)denyGarbageCollection
+{
+    denied++;
+    if (denied > 0) GC_dont_gc = 1;
+}
+
+@end /* GarbageCollector (BoehmGCSupport) */
+
+#endif /* LIB_FOUNDATION_BOEHM_GC */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSAccount.h b/libFoundation/Foundation/NSAccount.h
new file mode 100644 (file)
index 0000000..6d34ec0
--- /dev/null
@@ -0,0 +1,77 @@
+/* 
+   NSAccount.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSAccount_h__
+#define __NSAccount_h__
+
+#include <Foundation/NSObject.h>
+
+@class NSString;
+@class NSArray;
+
+@interface NSAccount : NSObject
+
+// Creating an account
++ (id)currentAccount;
++ (id)accountWithName:(NSString*)name;
++ (id)accountWithNumber:(unsigned int)number;
+
+// Getting account information
+- (NSString*)accountName;
+- (unsigned)accountNumber;
+
+@end /* NSAccount */
+
+@interface NSUserAccount : NSAccount
+{
+    NSString     *name;
+    unsigned int userNumber;
+    NSString     *fullName;
+    NSString     *homeDirectory;
+}
+
+- (NSString*)fullName;
+- (NSString*)homeDirectory;
+
+@end /* NSUserAccount */
+
+@interface NSGroupAccount : NSAccount
+{
+    NSString     *name;
+    unsigned int groupNumber;
+    NSArray      *members;
+}
+
+- (NSArray*)members;
+
+@end /* NSGroupAccount */
+
+#endif /* __NSAccount_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSAccount.m b/libFoundation/Foundation/NSAccount.m
new file mode 100644 (file)
index 0000000..807c841
--- /dev/null
@@ -0,0 +1,490 @@
+/* 
+   NSAccount.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSDictionary.h>
+
+#include <sys/types.h>
+
+#if HAVE_PWD_H
+#  include <pwd.h>
+#endif
+
+#if HAVE_GRP_H
+#  include <grp.h>
+#endif
+
+#ifdef HAVE_LIBC_H
+#  include <libc.h>
+#else
+#  include <unistd.h>
+#endif
+
+#if HAVE_WINDOWS_H
+#  include <windows.h>
+#endif
+
+#ifdef __MINGW32__
+#  include <lmaccess.h>
+#  include <lmapibuf.h>
+#endif
+
+#if HAVE_LM_H
+#  include <lm.h>
+#else
+# if defined(__MINGW32__)
+#  if !HAVE_USER_INFO_11 && 0
+typedef struct _USER_INFO_11 {
+    LPWSTR    usri11_name;
+    LPWSTR    usri11_comment;
+    LPWSTR    usri11_usr_comment;
+    LPWSTR    usri11_full_name;
+    DWORD     usri11_priv;
+    DWORD     usri11_auth_flags;
+    DWORD     usri11_password_age;
+    LPWSTR    usri11_home_dir;
+    LPWSTR    usri11_parms;
+    DWORD     usri11_last_logon;
+    DWORD     usri11_last_logoff;
+    DWORD     usri11_bad_pw_count;
+    DWORD     usri11_num_logons;
+    LPWSTR    usri11_logon_server;
+    DWORD     usri11_country_code;
+    LPWSTR    usri11_workstations;
+    DWORD     usri11_max_storage;
+    DWORD     usri11_units_per_week;
+    PBYTE     usri11_logon_hours;
+    DWORD     usri11_code_page;
+} USER_INFO_11;
+#  endif
+# endif
+#endif
+
+#ifdef __MINGW32__
+struct passwd {
+    const char *pw_name;
+    int        pw_uid;
+};
+#endif
+
+#include <Foundation/NSString.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSUtilities.h>
+#include <Foundation/NSLock.h>
+
+#include "NSAccount.h"
+
+extern NSRecursiveLock *libFoundationLock;
+
+@implementation NSAccount
+
+// Creating an account
+
++ currentAccount 
+{
+    [self subclassResponsibility:_cmd];
+    return nil; 
+}
+
++ accountWithName:(NSString*)name
+{
+    [self subclassResponsibility:_cmd];
+    return nil; 
+}
+
++ accountWithNumber:(unsigned int)number
+{
+    [self subclassResponsibility:_cmd];
+    return nil; 
+}
+
+// Getting account information
+
+- (NSString*)accountName
+{
+    [self subclassResponsibility:_cmd];
+    return nil; 
+}
+
+- (unsigned)accountNumber
+{
+    [self subclassResponsibility:_cmd];
+    return 0; 
+}
+
+// Copying Protocol
+
+- (id)copy
+{
+    return RETAIN(self);
+}
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    return RETAIN(self);
+}
+
+@end /* NSAccount */
+
+/*
+ *  User Account
+ */
+
+@implementation NSUserAccount
+
+// Init & dealloc
+
+#if defined(__MINGW32__)
+- (id)initWithUserInfo11:(USER_INFO_11 *)_userInfo {
+    self->name =
+        RETAIN(NSWindowsWideStringToString(_userInfo->usri11_name));
+    self->fullName =
+        RETAIN(NSWindowsWideStringToString(_userInfo->usri11_full_name));
+
+    self->homeDirectory =
+        RETAIN(NSWindowsWideStringToString(_userInfo->usri11_home_dir));
+
+
+    if ([self->homeDirectory length] == 0) {
+        RELEASE(self->homeDirectory); self->homeDirectory = nil;
+        self->homeDirectory =
+            [[NSString alloc] initWithCString:getenv("HOME")];
+    }
+    
+    return self;
+}
+#endif
+
+#if defined(__MINGW32__)
+- (id)initWithUserName:(const char *)_name homeDirectory:(const char *)_home
+{
+    self->name          = _name ? [[NSString alloc] initWithCString:_name] : @"";
+    self->fullName      = [self->name retain];
+    self->homeDirectory = _home ? [[NSString alloc] initWithCString:_home] : @"";
+    self->userNumber    = 0;
+    return self;
+}
+#endif
+
+- (id)initWithPasswordStructure:(struct passwd*)ptr
+{
+    if (ptr == NULL) {
+      fprintf(stderr, "%s: missing password structure ..\n",
+              __PRETTY_FUNCTION__);
+      RELEASE(self);
+      return nil;
+    }
+
+    self->name =
+        RETAIN([NSString stringWithCStringNoCopy:Strdup(ptr->pw_name)
+                         freeWhenDone:YES]);
+#ifndef __MINGW32__
+    self->fullName =
+        RETAIN([NSString stringWithCStringNoCopy:Strdup(ptr->pw_gecos)
+                         freeWhenDone:YES]);
+    self->homeDirectory =
+        RETAIN([NSString stringWithCStringNoCopy:Strdup(ptr->pw_dir)
+                         freeWhenDone:YES]);
+#endif
+    
+    self->userNumber = ptr->pw_uid;
+
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(self->name);
+    RELEASE(self->fullName);
+    RELEASE(self->homeDirectory);
+    [super dealloc];
+}
+
+// Creating an account
+
+static NSUserAccount* currentUserAccount = nil;
+
++ (void)initialize
+{
+    static BOOL initialized = NO;
+
+    if (!initialized) {
+       [libFoundationLock lock];
+
+#ifndef __MINGW32__
+       /* Initialize the group account global variable */
+       [NSGroupAccount initialize];
+#endif
+
+#if defined(__MINGW32__)
+    {
+       char         n[60];
+       DWORD        len = 60;
+        WCHAR        wUserName[256];
+        USER_INFO_11 *userInfo = NULL;
+
+        /* get current user name */
+       GetUserName(n, &len);
+
+        /* convert current user name to UNICODE */
+        MultiByteToWideChar(CP_ACP,    /* ANSI Code Page */
+                            0,         /* no special conversion flags */
+                            n,         /* ANSI string */
+                            len,       /* length of ANSI string */
+                            wUserName, /* destination buffer */
+                            sizeof(wUserName) / sizeof(WCHAR) /* dest size */);
+
+        /* retrieve user information, level 11 is available for current user */
+        if (NetUserGetInfo(NULL,      /* localhost  */
+                           wUserName, /* user name  */
+                           11,        /* info level */
+                           (void*)&userInfo)) {
+            fprintf(stderr,
+                    "ERROR: could not retrieve info for user '%s' !\n",
+                    n);
+            currentUserAccount = [[self alloc] init];
+        }
+        else {
+            currentUserAccount = [[self alloc] initWithUserInfo11:userInfo];
+        }
+
+        /* release user info structure */
+        if (userInfo) {
+            NetApiBufferFree(userInfo);
+            userInfo = NULL;
+        }
+    }
+#elif HAVE_GETUID
+    {
+       struct passwd *ptr = getpwuid(getuid());
+        
+        if (ptr)
+            currentUserAccount = [[self alloc] initWithPasswordStructure:ptr];
+        else {
+            fprintf(stderr,
+                    "WARNING: libFoundation couldn't get passwd structure for "
+                    "current user (id=%i) !\n", getuid());
+            currentUserAccount = nil;
+        }
+    }
+#else
+#  error cannot find out current user account
+#endif
+       [libFoundationLock unlock];
+       initialized = YES;
+    }
+}
+
++ (id)currentAccount 
+{
+    return currentUserAccount;
+}
+
++ (id)accountWithName:(NSString *)aName
+{
+#if defined(__MINGW32__)
+    return AUTORELEASE([[self alloc]
+                              initWithUserName:[aName cString]
+                              homeDirectory:NULL]);
+#elif HAVE_GETPWNAM
+    struct passwd *ptr;
+    
+    [libFoundationLock lock];
+    ptr = getpwnam((char*)[aName cString]);
+    [libFoundationLock unlock];
+    return ptr
+        ? AUTORELEASE([[self alloc] initWithPasswordStructure:ptr])
+       : nil;
+#else
+    struct passwd pt;
+    pt.pw_name = [aName cString];
+    pt.pw_uid = 0;
+    return AUTORELEASE([[self alloc] initWithPasswordStructure:&pt]);
+#endif
+}
+
++ accountWithNumber:(unsigned int)number
+{
+#if HAVE_GETPWUID
+    struct passwd* ptr;
+
+    [libFoundationLock lock];
+    ptr = getpwuid(number);
+    [libFoundationLock unlock];
+
+    return ptr
+        ? AUTORELEASE([[self alloc] initWithPasswordStructure:ptr])
+       : nil;
+#else
+    return 0;
+#endif
+}
+
+// accessors
+
+- (NSString *)accountName {
+    return self->name;
+}
+- (unsigned)accountNumber {
+    return self->userNumber;
+}
+- (NSString *)fullName {
+    return self->fullName;
+}
+- (NSString *)homeDirectory {
+    return self->homeDirectory;
+}
+
+@end /* NSUserAccount */
+
+/*
+ *  Group Account
+ */
+
+@implementation NSGroupAccount
+
+#ifdef __MINGW32__
+
++ (id)currentAccount 
+{
+    return nil;
+}
+
++ (id)accountWithName:(NSString*)aName
+{
+    return nil;
+}
+
++ (id)accountWithNumber:(unsigned int)number
+{
+    return nil;
+}
+
+- (NSArray *)members
+{
+    return nil;
+}
+
+#else /* __MINGW32__ */
+
+// Init & dealloc
+
+- (id)initWithGroupStructure:(struct group*)ptr
+{
+    int cnt;
+
+    name = RETAIN([NSString stringWithCString:ptr->gr_name]);
+    groupNumber = ptr->gr_gid;
+
+    // count group members
+    for (cnt = 0; ptr->gr_mem[cnt]; cnt++)
+       ;
+    
+    {
+       NSString** array = Malloc (cnt * sizeof(id));
+       int i;
+       
+       for (i = 0; i < cnt; i++)
+           array[i] = [NSString stringWithCString:ptr->gr_mem[i]];
+       members = [[NSArray alloc] initWithObjects:array count:cnt];
+        lfFree (array);
+    }
+    
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(name);
+    RELEASE(members);
+    [super dealloc];
+}
+
+// Creating an account
+
+static NSGroupAccount* currentGroupAccount = nil;
+
++ (void)initialize
+{
+    static BOOL initialized = NO;
+
+    if (!initialized) {
+       [libFoundationLock lock];
+       currentGroupAccount = RETAIN([self accountWithNumber:getgid()]);
+       [libFoundationLock unlock];
+       initialized = YES;
+    }
+}
+
++ (id)currentAccount 
+{
+    return currentGroupAccount;
+}
+
++ (id)accountWithName:(NSString*)aName
+{
+    struct group* ptr;
+
+    [libFoundationLock lock];
+    ptr = getgrnam((char*)[aName cString]);
+    [libFoundationLock unlock];
+
+    return ptr
+        ? AUTORELEASE([[self alloc] initWithGroupStructure:ptr])
+       : nil;
+}
+
++ (id)accountWithNumber:(unsigned int)number
+{
+    struct group* ptr;
+
+    [libFoundationLock lock];
+    ptr = getgrgid(number);
+    [libFoundationLock unlock];
+
+    return ptr
+        ? AUTORELEASE([[self alloc] initWithGroupStructure:ptr])
+       : nil;
+}
+
+- (NSString*)accountName {
+    return self->name;
+}
+- (unsigned)accountNumber {
+    return self->groupNumber;
+}
+- (NSArray*)members {
+    return self->members;
+}
+
+#endif /* __MINGW32__ */
+
+@end /* NSGroupAccount */
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSAllocDebugZone.h b/libFoundation/Foundation/NSAllocDebugZone.h
new file mode 100644 (file)
index 0000000..3d15214
--- /dev/null
@@ -0,0 +1,92 @@
+/* 
+   NSAllocDebugZone.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+/*
+    Alloc debug serves to trace erroneous memory usage in the following
+    modes:
+       - use free() instead of Free()
+       - use Free() instead of free()
+       - check double deallocation
+       - check deallocation of non-existing pointers
+       - use a block past its margins
+       - list blocks allocated since mark
+       - stop when alloc-ing pointer marked
+       - do SYSTEM_MALLOC_CHECK and internal checks every * operation
+       - be able to control things from gdb
+       - be able to control things from environment variables
+    
+    AllocDebug is controlled by the following environment variables:
+       ALLOCDEBUG              
+           - must be set to something to use alloc debug zone
+       ALLOCDEBUG_STOP
+           - stop in debugger (SIGINT) when alloc-ing pointer number *
+           - nil or 0 means no stop
+       ALLOCDEBUG_COUNT
+           - number of passes inside allocation/deallocation functions
+           to SYSTEM_MALLOC_CHECK and internal check
+           - nil or 0 means no checks
+       ALLOCDEBUG_UPPER
+       ALLOCDEBUG_LOWER
+           - number of bytes to alloc at top/bottom of object block
+           - these bytes are set to a given value (0x88) and checked
+           at free and internal check to guard against using memory
+           past the limit.
+                   
+    AlloDebug provides these functions to be used from debugger (gdb)
+       debuggerStopMark(unsigned mark)
+           - overrides ALLOCDEBUG_STOP
+       debuggerCheckTime(unsigned count)
+           - overrides ALLOCDEBUG_COUNT
+       debuggerDescription(id obj)
+           - performs printf("%s\n", [obj description])
+       debuggerPerform(id obj, char* sel)
+           - performs [obj sel]
+       debuggerPerformWith(id obj, char* sel, id arg)
+           - performs [obj sel:(id)atoi(arg)]
+*/
+
+#ifndef __NSAllocDebugZone_h__
+#define __NSAllocDebugZone_h__
+
+#include <Foundation/NSObject.h>
+
+typedef enum {debugNone=0, debugAlloc=1} TDebugMode;
+
+@interface NSAllocDebugZone : NSZone
+@end
+
+void debuggerStopMark(unsigned mark);
+void debuggerCheckTime(unsigned count);
+void debuggerDescription(id obj);
+void debuggerPerform(id obj, char* sel);
+void debuggerPerformWith(id obj, char* sel, id arg);
+
+#endif /* __NSAllocDebugZone_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSAllocDebugZone.m b/libFoundation/Foundation/NSAllocDebugZone.m
new file mode 100644 (file)
index 0000000..19932f3
--- /dev/null
@@ -0,0 +1,545 @@
+/* 
+   NSAllocDebugZone.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <config.h>
+
+#if HAVE_STRING_H
+# include <string.h>
+#endif
+
+#if HAVE_MEMORY_H
+# include <memory.h>
+#endif
+
+#if !HAVE_MEMCPY
+# define memcpy(d, s, n)       bcopy((s), (d), (n))
+# define memmove(d, s, n)      bcopy((s), (d), (n))
+#endif
+
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#else
+extern void* malloc();
+extern void* calloc();
+extern void* realloc();
+extern void free();
+extern atoi();
+extern atol();
+#endif
+
+#ifdef HAVE_LIBC_H
+#include <libc.h>
+#else
+#include <unistd.h>
+#endif
+#include <signal.h>
+#include <stdarg.h>
+
+#if HAVE_PROCESS_H
+#include <process.h>
+#endif
+
+#include <extensions/objc-runtime.h>
+
+#include <Foundation/NSObject.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSAllocDebugZone.h>
+
+static void  initDebugger();
+static void* debugMalloc(unsigned size);
+static void* debugCalloc(unsigned elem, unsigned size);
+static void* debugRealloc(void* p, unsigned size);
+static void  debugFree(void* p);
+static BOOL  doConsistencyCheck();
+static BOOL  pointerInZone(void* p);
+
+@implementation NSAllocDebugZone
+
++ (id)alloc
+{
+    return [self allocZoneInstance];
+}
+
+- (id)init
+{
+    return [self initForSize:0 granularity:0 canFree:YES];
+}
+
+- (id)initForSize:(unsigned)startSize granularity:(unsigned)granularity
+    canFree:(BOOL)canFree
+{
+    name = @"Alloc Debug zone";
+    initDebugger(); 
+    return self;
+}
+
+- (void*)malloc:(unsigned)size
+{
+    return debugMalloc(size);
+}
+
+- (void*)calloc:(unsigned)count byteSize:(unsigned)size
+{
+    return debugCalloc(count, size);
+}
+
+- (void*)realloc:(void*)p size:(unsigned)size
+{
+    return debugRealloc(p, size);
+}
+
+- (void)freePointer:(void*)p
+{
+    debugFree(p);
+}
+
+- (void)recycle
+{
+}
+
+- (BOOL)checkZone
+{
+    return doConsistencyCheck();
+}
+
+- (BOOL)pointerInZone:(void*)pointer
+{
+    return pointerInZone(pointer);
+}
+
+@end /* NSAllocDebugZone */
+
+/* 
+ * Alloc-debug internals 
+ */
+#ifdef NeXT
+#define SYSEM_MALLOC_CHECK() NXMallocCheck()
+#else
+#define SYSEM_MALLOC_CHECK()
+#endif
+
+#define HASHSIZE 25013
+
+#define MOVEPTR(p,s) ((void*)((unsigned long)(p)+(s)))
+#define PTRSIZE(s) ((s)+upperHeader+lowerHeader)
+#define USER2REAL(p) MOVEPTR(p,-upperHeader)
+#define REAL2USER(p) MOVEPTR(p,+upperHeader)
+#define HOLD2REAL(p) MOVEPTR(p,-1)
+#define REAL2HOLD(p) MOVEPTR(p,+1)
+#define USER2HOLD(p) MOVEPTR(p,-upperHeader+1)
+#define HOLD2USER(p) MOVEPTR(p,+upperHeader-1)
+
+typedef struct _AllocDebugRecord {
+       void*   pointer;        /* The Pointer */
+       int     size;           /* The Pointer allocated size */
+       unsigned        mark;           /* Index of allocation */
+       struct _AllocDebugRecord *next; /* Next entry in list */
+} AllocDebugRecord;
+
+static unsigned        allocationMark;         /* allocation counter */
+static unsigned        allocationStop;         /* where to stop in allocator */
+static unsigned        allocationSignal;       /* whether to stop in allocator */
+       
+static AllocDebugRecord        **nodesTable;   /* pointers hashtable */
+static unsigned        nodesSize;              /* pointers hashtable size */
+static unsigned        nodesCount;             /* pointers in hashtable */
+       
+static unsigned        secureCheckCount;       /* calls to secure check */
+static unsigned        secureCheckTime;        /* number of calls to check */
+       
+static unsigned        upperHeader;            /* used for consistency check */
+static unsigned        lowerHeader;            /* used for consistency check */
+
+static void stopProgram();
+static void error(BOOL isWarning, char* format, ...);
+static void consistencyCheck();
+static void setMarkers(AllocDebugRecord* info);
+static BOOL checkMarkers(AllocDebugRecord* info);
+static void addHash(AllocDebugRecord* info);
+static void removeHash(AllocDebugRecord* info);
+static AllocDebugRecord* searchHash(void* p);
+static AllocDebugRecord* newInfo(void* p, unsigned size);
+static void freeInfo(AllocDebugRecord* info);
+
+/*
+ * Internal functions
+ */
+
+static void initDebugger()
+{
+    char* str;
+
+    nodesTable = objc_calloc(HASHSIZE, sizeof(AllocDebugRecord*));
+    nodesSize = HASHSIZE;
+    nodesCount = 0;
+    allocationMark = 1;
+
+    str = getenv("ALLOCDEBUG_MARK");
+    allocationStop = str ? atoi(str) : 0;
+
+    str = getenv("ALLOCDEBUG_STOP");
+    allocationSignal = str ? atoi(str) : 0;
+
+    str = getenv("ALLOCDEBUG_COUNT");
+    secureCheckTime = secureCheckCount = str ? atoi(str) : 0;
+
+    str = getenv("ALLOCDEBUG_UPPER");
+    upperHeader = str ? atoi(str) : 0;
+    str = getenv("ALLOCDEBUG_LOWER");
+    lowerHeader = str ? atoi(str) : 0;
+    
+    fprintf(stderr, "AllocDebug[00000]:Stop at %d, Check time %d, "
+           "Upper header %d, Lower header %d\n", allocationStop,
+           secureCheckTime, upperHeader, lowerHeader);
+}
+
+static void* debugMalloc(unsigned size)
+{
+    void* p;
+    AllocDebugRecord* info; 
+
+    p = objc_malloc(PTRSIZE(size));
+    memset(p, 1, PTRSIZE(size));
+    info = newInfo(REAL2HOLD(p), size);
+    info->mark = allocationMark++;
+    setMarkers(info);
+    addHash(info);
+    consistencyCheck();
+    return REAL2USER(p);
+}
+
+static void* debugCalloc(unsigned elem, unsigned size)
+{
+    void* p;
+    AllocDebugRecord* info; 
+
+    p = objc_malloc(PTRSIZE(size*elem));
+    memset(p, 0, PTRSIZE(size*elem));
+    info = newInfo(REAL2HOLD(p), size*elem);
+    info->mark = allocationMark++;
+    setMarkers(info);
+    addHash(info);
+    consistencyCheck();
+    return REAL2USER(p);
+}
+
+static void* debugRealloc(void* p, unsigned size)
+{
+    AllocDebugRecord* info; 
+
+    if (p)
+       info = searchHash(USER2HOLD(p));
+    else 
+           info = NULL;
+    
+    if (p && !info) {
+       error( NO, "AllocDebug[%05d]: "
+               "Attempt to realloc pointer %p not registered. "
+                   "Will use realloc()\n", allocationMark, p);
+       consistencyCheck();
+       return objc_realloc(p, size);
+    }
+    
+    if (info) {
+       checkMarkers(info);
+       removeHash(info);
+       p = HOLD2REAL(info->pointer);
+       p = objc_realloc(p,PTRSIZE(size));
+    }
+    else {
+       p = objc_malloc(PTRSIZE(size));
+       memset(p, 1, PTRSIZE(size));
+    }
+    
+    info = newInfo(REAL2HOLD(p),size);
+    info->mark = allocationMark++;
+    setMarkers(info);
+    addHash(info);
+    consistencyCheck();
+    return REAL2USER(p);
+}
+
+static void  debugFree(void* p)
+{
+    AllocDebugRecord* info; 
+
+    if (!p)
+       return;
+    
+    info = searchHash(USER2HOLD(p));
+    if (!info) {
+       error(NO, "AllocDebug[%05d]: "
+               "Attempt to free unregistered pointer %p. "
+               "Will not free anything.\n", allocationMark, p);
+       return;
+    }
+    
+    checkMarkers(info);
+    removeHash(info);
+    objc_free(HOLD2REAL(info->pointer));
+    freeInfo(info);
+    consistencyCheck();
+}
+
+static BOOL  pointerInZone(void* p)
+{
+    if (!p)
+       return NO;
+    
+    return searchHash(USER2HOLD(p)) != NULL;
+}
+
+static void stopProgram()
+{
+#if HAVE_KILL
+    kill(getpid(), SIGINT);
+#elif HAVE_RAISE
+    raise( SIGINT );
+#else
+#warning No kill and no raise
+#endif
+}
+
+static void error(BOOL isWarning, char* format, ...)
+{
+    va_list va;
+    
+    va_start(va, format);
+    vfprintf(stderr, format, va);
+    va_end(va);
+    
+    if (isWarning)
+       return;
+    if (allocationSignal)
+       stopProgram();
+}
+
+static void consistencyCheck()
+{
+    if (secureCheckTime && !--secureCheckCount) {
+       doConsistencyCheck();
+       secureCheckCount = secureCheckTime;
+    }
+}
+
+static BOOL doConsistencyCheck()
+{
+    unsigned i;
+    AllocDebugRecord* info;
+    BOOL ok = YES;
+    
+    for(i=0; i<nodesSize; i++)
+       for(info=nodesTable[i]; info; info=info->next)
+           ok = ok && checkMarkers(info);
+    return ok;
+}
+
+static void setMarkers(AllocDebugRecord* info)
+{
+    char* p = (char*)HOLD2REAL(info->pointer);
+    unsigned size = info->size;
+
+    if (upperHeader) {
+       memset(p, 0x88, upperHeader);
+    }
+    if (lowerHeader) {
+       memset(p+upperHeader+size, 0x88, lowerHeader);
+    }
+}
+
+static BOOL checkMarkers(AllocDebugRecord* info)
+{
+    char *q, *p = (char*)HOLD2REAL(info->pointer);
+    unsigned size = info->size;
+    BOOL ok = YES;
+
+    if (upperHeader) {
+       BOOL bad = NO;
+       for (q=p; q<p+upperHeader; q++)
+           if (*q != (char)0x88)
+               bad = YES;
+       if (bad) {
+           error(NO, "AllocDebug[%05d]: "
+                   "Upper marker for pointer %p is damaged\n",
+                   info->mark, REAL2USER(p));
+           ok = NO;
+       }
+    }
+
+    if (lowerHeader) {
+       BOOL bad = NO;
+       for (q=p+upperHeader+size; q<p+upperHeader+size+lowerHeader; q++)
+           if (*q != (char)0x88)
+               bad = YES;
+       if (bad) {
+           error(NO, "quit[%05d]: "
+                   "Lower marker for pointer %p is damaged\n",
+                   info->mark, REAL2USER(p));
+           ok = NO;
+       }
+    }
+    return ok;
+}
+
+static void addHash(AllocDebugRecord* info)
+{
+    AllocDebugRecord *buck;
+    void *ptr = info->pointer;
+    unsigned long index = (unsigned long)(ptr) % nodesSize;
+    
+    /* first check if not present */
+    for(buck=nodesTable[index]; buck; buck=buck->next) 
+       if (buck->pointer == ptr) {
+           error(YES, "AllocDebug[%05d]: "
+                   "Pointer %p was freed by free() directly before.\n",
+                   allocationMark, HOLD2USER(ptr));
+           break;
+       }
+
+    /* insert */
+    info->next=nodesTable[index];
+    nodesTable[index]=info;
+    nodesCount++;
+
+    if (info->mark == allocationStop) {
+       error(NO, "AllocDebug[%05d]: "
+               "Stoped at requested mark, pointer.\n",
+               allocationStop, HOLD2USER(ptr));
+    }
+}
+
+static void removeHash(AllocDebugRecord* info)
+{
+    AllocDebugRecord *buck, *del;
+    void *ptr = info->pointer;
+    unsigned long index = (unsigned long)(ptr) % nodesSize;
+
+    del = buck = nodesTable[index];
+    if(buck == info) 
+           nodesTable[index] = buck->next;
+    else 
+       for( ; buck->next; buck=buck->next)
+           if (buck->next == info) {
+               buck->next = buck->next->next;
+               break;
+           }
+    nodesCount--;
+}
+
+static AllocDebugRecord* searchHash(void* p)
+{
+    AllocDebugRecord *buck;
+    void *ptr = p;
+    unsigned index = (unsigned long)(ptr) % nodesSize;
+
+    /* find it */
+    for(buck=nodesTable[index]; buck; buck=buck->next)
+       if (buck->pointer==ptr)
+               return buck;
+    return NULL;
+}
+
+static AllocDebugRecord* newInfo(void* p, unsigned size)
+{
+    AllocDebugRecord* info = objc_calloc(1, sizeof(AllocDebugRecord));
+    
+    info->pointer = p;
+    info->size = size;
+
+    return info;
+}
+
+static void freeInfo(AllocDebugRecord* info)
+{
+    objc_free(info);
+}
+
+/*
+ * Public debugger functions
+ */
+
+void debuggerStopMark(unsigned mark)
+{
+    allocationStop = mark;
+}
+
+void debuggerCheckTime(unsigned count)
+{
+    secureCheckTime = count;
+}
+
+void debuggerCheckPointer(unsigned long ptr)
+{
+    AllocDebugRecord* info; 
+    void *p = (void*)ptr;
+    int sav = allocationSignal;
+    allocationSignal = 0;
+    
+    if (!p)
+       return;
+    
+    info = searchHash(USER2HOLD(p));
+    if (!info) {
+       error(NO, "AllocDebug[%05d]: "
+               "Attempt to check unregistered pointer %p.\n", 
+               allocationMark, p);
+       return;
+    }
+    
+    checkMarkers(info);
+    allocationSignal = sav;
+}
+
+void debuggerDescription(id obj)
+{
+    NSString* desc = [obj description];
+    fprintf(stderr, "Object %p description:\n%s\n", obj, [desc cString]);
+}
+
+void debuggerPerform(id obj, char* sel)
+{
+    SEL selector = sel_get_any_uid(sel);
+    if (selector) 
+       [obj performSelector:selector];
+    else
+       fprintf(stderr, "Object %p does not respond to '%s'\n", obj, sel);
+}
+
+void debuggerPerformWith(id obj, char* sel, id arg)
+{
+    SEL selector = sel_get_any_uid(sel);
+    if (selector) 
+       [obj performSelector:selector withObject:arg];
+    else
+       fprintf(stderr, "Object %p does not respond to '%s'\n", obj, sel);
+}
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSArchiver.h b/libFoundation/Foundation/NSArchiver.h
new file mode 100644 (file)
index 0000000..8e82666
--- /dev/null
@@ -0,0 +1,158 @@
+/* 
+   NSArchiver.h
+
+   Copyright (C) 1998 MDlink online service center, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess (helge@mdlink.de)
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+
+   The code is based on the NSArchiver class done by Ovidiu Predescu which has
+   the following Copyright/permission:
+   ---
+   The basic archiving algorithm is based on libFoundation's NSArchiver by
+   Ovidiu Predescu:
+   
+   NSArchiver.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+   ---
+*/
+// $Id$
+
+#ifndef __NSArchiver_H__
+#define __NSArchiver_H__
+
+#include <Foundation/NSCoder.h>
+#include <Foundation/NSSerialization.h>
+#include <Foundation/NSMapTable.h>
+#include <Foundation/NSHashTable.h>
+
+@interface NSArchiver : NSCoder < NSObjCTypeSerializationCallBack >
+{
+    NSHashTable *outObjects;          // objects written so far
+    NSHashTable *outConditionals;     // conditional objects
+    NSHashTable *outPointers;         // set of pointers
+    NSMapTable  *outClassAlias;       // class name -> archive name
+    NSMapTable  *replacements;        // src-object to replacement
+    NSMapTable  *outKeys;             // src-address -> archive-address
+    BOOL        traceMode;            // YES if finding conditionals
+    BOOL        didWriteHeader;
+    SEL         classForCoder;        // default: classForCoder:
+    SEL         replObjectForCoder;   // default: replacementObjectForCoder:
+    BOOL        encodingRoot;
+    int         archiveAddress;
+
+    // destination
+    NSMutableData *data;
+    void (*addData)(id, SEL, const void *, unsigned);
+    void (*serData)(id, SEL, const void *, const char *, id);
+}
+
+- (id)initForWritingWithMutableData:(NSMutableData*)mdata;
+
+/* Archiving Data */
++ (NSData*)archivedDataWithRootObject:(id)rootObject;
++ (BOOL)archiveRootObject:(id)rootObject toFile:(NSString*)path;
+
+/* Getting Data from the NSArchiver */
+- (NSMutableData *)archiverData;
+
+/* encoding */
+
+- (void)encodeConditionalObject:(id)_object;
+- (void)encodeRootObject:(id)_object;
+
+/* Substituting One Class for Another */
+
+- (NSString *)classNameEncodedForTrueClassName:(NSString *)_trueName;
+- (void)encodeClassName:(NSString *)_trueName intoClassName:(NSString *)_archiveName;
+// not supported yet: replaceObject:withObject:
+
+@end
+
+@interface NSUnarchiver : NSCoder < NSObjCTypeSerializationCallBack >
+{
+    unsigned    inArchiverVersion;    // archiver's version that wrote the data
+    NSMapTable  *inObjects;           // decoded objects: key -> object
+    NSMapTable  *inClasses;           // decoded classes: key -> class info
+    NSMapTable  *inPointers;          // decoded pointers: key -> pointer
+    NSMapTable  *inClassAlias;        // archive name -> decoded name
+    NSMapTable  *inClassVersions;     // archive name -> class info
+    NSZone      *objectZone;
+    BOOL        decodingRoot;
+    BOOL        didReadHeader;
+
+    // source
+    NSData       *data;
+    unsigned int cursor;
+    void (*getData)(id, SEL, void *, unsigned, unsigned *);
+    void (*deserData)(id, SEL, void *, const char *, unsigned *, id);
+}
+
+- (id)initForReadingWithData:(NSData*)data;
+
+/* Decoding Objects */
++ (id)unarchiveObjectWithData:(NSData*)data;
++ (id)unarchiveObjectWithFile:(NSString*)path;
+
+/* Managing an NSUnarchiver */
+
+- (BOOL)isAtEnd;
+- (NSZone *)objectZone;
+- (void)setObjectZone:(NSZone *)_zone;
+- (unsigned int)systemVersion;
+
+// decoding
+
+- (id)decodeObject;
+
+/* Substituting One Class for Another */
+
++ (NSString *)classNameDecodedForArchiveClassName:(NSString *)nameInArchive;
++ (void)decodeClassName:(NSString *)nameInArchive asClassName:(NSString *)trueName;
+- (NSString *)classNameDecodedForArchiveClassName:(NSString *)nameInArchive;
+- (void)decodeClassName:(NSString *)nameInArchive asClassName:(NSString *)trueName;
+// not supported yet: replaceObject:withObject:
+
+@end
+
+#endif /* __NSArchiver_H__ */
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSArchiver.m b/libFoundation/Foundation/NSArchiver.m
new file mode 100644 (file)
index 0000000..87f7dba
--- /dev/null
@@ -0,0 +1,1495 @@
+/* 
+   NSArchiver.m
+
+   Copyright (C) 1998 MDlink online service center, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess (helge@mdlink.de)
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+
+   The code is based on the NSArchiver class done by Ovidiu Predescu which has
+   the following Copyright/permission:
+   ---
+   The basic archiving algorithm is based on libFoundation's NSArchiver by
+   Ovidiu Predescu:
+   
+   NSArchiver.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+   ---
+*/
+// $Id$
+
+#include <Foundation/NSData.h>
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSUtilities.h>
+#include <extensions/objc-runtime.h>
+#include "NSArchiver.h"
+#include "common.h" // for Free
+
+#define ENCODE_AUTORELEASEPOOL 0
+#define ARCHIVE_DEBUGGING      0
+
+#define FINAL static inline
+
+typedef unsigned char NSTagType;
+
+#define REFERENCE 128
+#define VALUE     127
+
+static NSMapTableKeyCallBacks NSIdentityObjectMapKeyCallbacks = {
+  (unsigned(*)(NSMapTable *, const void *))          __NSHashPointer,
+  (BOOL(*)(NSMapTable *, const void *, const void *))__NSComparePointers,
+  (void (*)(NSMapTable *, const void *anObject))     __NSRetainObjects,
+  (void (*)(NSMapTable *, void *anObject))           __NSReleaseObjects,
+  (NSString *(*)(NSMapTable *, const void *))        __NSDescribePointers,
+  (const void *)NULL
+};
+
+FINAL BOOL isBaseType(const char *_type)
+{
+    switch (*_type) {
+        case _C_CHR: case _C_UCHR:
+        case _C_SHT: case _C_USHT:
+        case _C_INT: case _C_UINT:
+        case _C_LNG: case _C_ULNG:
+        case _C_FLT: case _C_DBL:
+            return YES;
+
+        default:
+            return NO;
+    }
+}
+
+FINAL BOOL isReferenceTag(NSTagType _tag)
+{
+    return (_tag & REFERENCE) ? YES : NO;
+}
+
+FINAL NSTagType tagValue(NSTagType _tag) {
+    return _tag & VALUE; // mask out bit 8
+}
+
+static const char *NSCoderSignature = "libFoundation NSArchiver";
+static int        NSCoderVersion    = 1100;
+
+@implementation NSArchiver
+
+- (id)initForWritingWithMutableData:(NSMutableData *)_data
+{
+    if ((self = [super init])) {
+        self->classForCoder      = @selector(classForCoder);
+        self->replObjectForCoder = @selector(replacementObjectForCoder:);
+        
+        self->outObjects      = NSCreateHashTable(NSNonOwnedPointerHashCallBacks, 119);
+        self->outConditionals = NSCreateHashTable(NSNonOwnedPointerHashCallBacks, 119);
+        self->outPointers     = NSCreateHashTable(NSNonOwnedPointerHashCallBacks, 0);
+        self->replacements    = NSCreateMapTable(NSIdentityObjectMapKeyCallbacks,
+                                                 NSObjectMapValueCallBacks,
+                                                 19);
+        self->outClassAlias   = NSCreateMapTable(NSObjectMapKeyCallBacks,
+                                                 NSObjectMapValueCallBacks,
+                                                 19);
+        self->outKeys         = NSCreateMapTable(NSObjectMapKeyCallBacks,
+                                                 NSIntMapValueCallBacks,
+                                                 119);
+
+        self->archiveAddress = 1;
+
+        self->data    = RETAIN(_data);
+        self->serData = (void *)
+            [self->data methodForSelector:@selector(serializeDataAt:ofObjCType:context:)];
+        self->addData = (void *)
+            [self->data methodForSelector:@selector(appendBytes:length:)];
+    }
+    return self;
+}
+
+- (id)init
+{
+    return [self initForWritingWithMutableData:[NSMutableData data]];
+}
+
++ (NSData *)archivedDataWithRootObject:(id)_root
+{
+    NSArchiver *archiver = AUTORELEASE([self new]);
+    NSData     *rdata    = nil;
+    
+    [archiver encodeRootObject:_root];
+    rdata = [archiver->data copy];
+    return AUTORELEASE(rdata);
+}
++ (BOOL)archiveRootObject:(id)_root toFile:(NSString *)_path
+{
+    NSData *rdata = [self archivedDataWithRootObject:_root];
+    return [rdata writeToFile:_path atomically:YES];
+}
+
+#if !LIB_FOUNDATION_BOEHM_GC
+- (void)dealloc
+{
+    RELEASE(self->data);
+    
+    if (self->outKeys)         NSFreeMapTable(self->outKeys);
+    if (self->outObjects)      NSFreeHashTable(self->outObjects);
+    if (self->outConditionals) NSFreeHashTable(self->outConditionals);
+    if (self->outPointers)     NSFreeHashTable(self->outPointers);
+    if (self->replacements)    NSFreeMapTable(self->replacements);
+    if (self->outClassAlias)   NSFreeMapTable(self->outClassAlias);
+  
+    [super dealloc];
+}
+#endif
+
+// ******************** Getting Data from the NSArchiver ******
+
+- (NSMutableData *)archiverData
+{
+    return self->data;
+}
+
+// ******************** archive id's **************************
+
+FINAL int _archiveIdOfObject(NSArchiver *self, id _object)
+{
+    if (_object == nil)
+        return 0;
+#if 1
+    else
+        return (int)_object;
+#else
+    else {
+        int archiveId;
+
+        archiveId = (int)NSMapGet(self->outKeys, _object);
+        if (archiveId == 0) {
+            archiveId = self->archiveAddress;
+            NSMapInsert(self->outKeys, _object, (void*)archiveId);
+#if ARCHIVE_DEBUGGING
+            NSLog(@"mapped 0x%08X => %i", _object, archiveId);
+#endif
+            self->archiveAddress++;
+        }
+
+        return archiveId;
+    }
+#endif
+}
+FINAL int _archiveIdOfClass(NSArchiver *self, Class _class)
+{
+    return _archiveIdOfObject(self, _class);
+}
+
+// ******************** primitive encoding ********************
+
+FINAL void _writeBytes(NSArchiver *self, const void *_bytes, unsigned _len);
+
+FINAL void _writeTag  (NSArchiver *self, NSTagType _tag);
+
+FINAL void _writeChar (NSArchiver *self, char _value);
+FINAL void _writeShort(NSArchiver *self, short _value);
+FINAL void _writeInt  (NSArchiver *self, int _value);
+FINAL void _writeLong (NSArchiver *self, long _value);
+FINAL void _writeFloat(NSArchiver *self, float _value);
+
+FINAL void _writeCString(NSArchiver *self, const char *_value);
+FINAL void _writeObjC(NSArchiver *self, const void *_value, const char *_type);
+
+// ******************** complex encoding **********************
+
+- (void)beginEncoding
+{
+    self->traceMode    = NO;
+    self->encodingRoot = YES;
+}
+- (void)endEncoding
+{
+#if 0
+    NSResetHashTable(self->outObjects);
+    NSResetHashTable(self->outConditionals);
+    NSResetHashTable(self->outPointers);
+    NSResetMapTable(self->outClassAlias);
+    NSResetMapTable(self->replacements);
+    NSResetMapTable(self->outKeys);
+#endif
+
+    self->traceMode      = NO;
+    self->encodingRoot   = NO;
+}
+
+- (void)writeArchiveHeader
+{
+    if (self->didWriteHeader == NO) {
+        _writeCString(self, NSCoderSignature);
+        _writeInt(self, NSCoderVersion);
+        self->didWriteHeader = YES;
+    }
+}
+- (void)writeArchiveTrailer
+{
+}
+
+- (void)traceObjectsWithRoot:(id)_root
+{
+    // encoding pass 1
+    NS_DURING {
+        self->traceMode = YES;
+        [self encodeObject:_root];
+    }
+    NS_HANDLER {
+        self->traceMode = NO;
+        NSResetHashTable(self->outObjects);
+        [localException raise];
+    }
+    NS_ENDHANDLER;
+    
+    self->traceMode = NO;
+    NSResetHashTable(self->outObjects);
+}
+
+- (void)encodeObjectsWithRoot:(id)_root
+{
+    // encoding pass 2
+    [self encodeObject:_root];
+}
+
+- (void)encodeRootObject:(id)_object
+{
+#if ENCODE_AUTORELEASEPOOL
+    NSAutoreleasePool *pool =
+        [[NSAutoreleasePool allocWithZone:[self zone]] init];
+#endif
+    
+    [self beginEncoding];
+
+    NS_DURING {
+        /*
+         * Prepare for writing the graph objects for which `rootObject' is the root
+         * node. The algorithm consists from two passes. In the first pass it
+         * determines the nodes so-called 'conditionals' - the nodes encoded *only*
+         * with -encodeConditionalObject:. They represent nodes that are not
+         * related directly to the graph. In the second pass objects are encoded
+         * normally, except for the conditional objects which are encoded as nil.
+         */
+
+        // pass1: start tracing for conditionals
+        [self traceObjectsWithRoot:_object];
+        
+        // pass2: start writing
+        [self writeArchiveHeader];
+        [self encodeObjectsWithRoot:_object];
+        [self writeArchiveTrailer];
+    }
+    NS_HANDLER {
+        [self endEncoding]; // release resources
+        [localException raise];
+    }
+    NS_ENDHANDLER;
+    
+    [self endEncoding]; // release resources
+
+#if ENCODE_AUTORELEASEPOOL
+    RELEASE(pool); pool = nil;
+#endif
+}
+
+- (void)encodeConditionalObject:(id)_object
+{
+    if (self->traceMode) { // pass 1
+        /*
+         * This is the first pass of the determining the conditionals
+         * algorithm. We traverse the graph and insert into the `conditionals'
+         * set. In the second pass all objects that are still in this set will
+         * be encoded as nil when they receive -encodeConditionalObject:. An
+         * object is removed from this set when it receives -encodeObject:.
+         */
+
+        if (_object) {
+            if (NSHashGet(self->outObjects, _object))
+                // object isn't conditional any more .. (was stored using encodeObject:)
+                ;
+            else if (NSHashGet(self->outConditionals, _object))
+                // object is already stored as conditional
+                ;
+            else
+                // insert object in conditionals set
+                NSHashInsert(self->outConditionals, _object);
+        }
+    }
+    else { // pass 2
+        BOOL isConditional;
+
+        isConditional = (NSHashGet(self->outConditionals, _object) != nil);
+
+        // If anObject is still in the `conditionals' set, it is encoded as nil.
+        [self encodeObject:isConditional ? nil : _object];
+    }
+}
+
+- (void)_traceObject:(id)_object
+{
+    if (_object == nil) // don't trace nil objects ..
+        return;
+
+    //NSLog(@"lookup 0x%08X in outObjs=0x%08X", _object, self->outObjects);
+    
+    if (NSHashGet(self->outObjects, _object) == nil) {
+        //NSLog(@"lookup failed, object wasn't traced yet !");
+        
+        // object wasn't traced yet
+        // Look-up the object in the `conditionals' set. If the object is
+        // there, then remove it because it is no longer a conditional one.
+        if (NSHashGet(self->outConditionals, _object)) {
+            // object was marked conditional ..
+            NSHashRemove(self->outConditionals, _object);
+        }
+        
+        // mark object as traced
+        NSHashInsert(self->outObjects, _object);
+        
+        if (object_is_instance(_object)) {
+            Class archiveClass = Nil;
+            id    replacement  = nil;
+            
+            replacement = [_object performSelector:self->replObjectForCoder
+                                   withObject:self];
+            
+            if (replacement != _object) {
+                NSMapInsert(self->replacements, _object, replacement);
+                _object = replacement;
+            }
+            
+            if (object_is_instance(_object)) {
+                archiveClass = [_object performSelector:self->classForCoder];
+            }
+            
+            [self encodeObject:archiveClass];
+            [_object encodeWithCoder:self];
+        }
+        else {
+            // there are no class-variables ..
+        }
+    }
+}
+- (void)_encodeObject:(id)_object
+{
+    NSTagType tag;
+    int       archiveId = _archiveIdOfObject(self, _object);
+
+    if (_object == nil) { // nil object or class
+        _writeTag(self, _C_ID | REFERENCE);
+        _writeInt(self, archiveId);
+        return;
+    }
+    
+    tag = object_is_instance(_object) ? _C_ID : _C_CLASS;
+    
+    if (NSHashGet(self->outObjects, _object)) { // object was already written
+        _writeTag(self, tag | REFERENCE);
+        _writeInt(self, archiveId);
+    }
+    else {
+        // mark object as written
+        NSHashInsert(self->outObjects, _object);
+
+        /*
+          if (tag == _C_CLASS) { // a class object
+          NGLogT(@"encoder", @"encoding class %s:%i ..",
+          class_get_class_name(_object), [_object version]);
+          }
+          else {
+          NGLogT(@"encoder", @"encoding object 0x%08X<%s> ..",
+          _object, class_get_class_name(*(Class *)_object));
+          }
+        */
+    
+        _writeTag(self, tag);
+        _writeInt(self, archiveId);
+
+        if (tag == _C_CLASS) { // a class object
+            NSString      *className;
+            unsigned      len;
+            unsigned char *buf;
+            
+            className = NSStringFromClass(_object);
+            className = [self classNameEncodedForTrueClassName:className];
+            len = [className cStringLength];
+            buf = malloc(len + 1);
+            [className getCString:buf]; buf[len] = '\0';
+            
+            _writeCString(self, buf);
+            _writeInt(self, [_object version]);
+            free(buf);
+        }
+        else {
+            Class archiveClass = Nil;
+            id    replacement  = nil;
+
+            replacement = NSMapGet(self->replacements, _object);
+            if (replacement) _object = replacement;
+
+            /*
+              _object = [_object performSelector:self->replObjectForCoder
+              withObject:self];
+            */
+            archiveClass = [_object performSelector:self->classForCoder];
+            
+            NSAssert(archiveClass, @"no archive class found ..");
+
+            [self encodeObject:archiveClass];
+            [_object encodeWithCoder:self];
+        }
+    }
+}
+
+- (void)encodeObject:(id)_object
+{
+    if (self->encodingRoot) {
+        [self encodeValueOfObjCType:
+                object_is_instance(_object) ? "@" : "#"
+              at:&_object];
+    }
+    else {
+        [self encodeRootObject:_object];
+    }
+}
+
+- (void)_traceValueOfObjCType:(const char *)_type at:(const void *)_value
+{
+    //NSLog(@"_tracing value at 0x%08X of type %s", _value, _type);
+    
+    switch (*_type) {
+        case _C_ID:
+        case _C_CLASS:
+            //NSLog(@"_traceObject 0x%08X", *(id *)_value);
+            [self _traceObject:*(id *)_value];
+            break;
+        
+        case _C_ARY_B: {
+            int        count     = atoi(_type + 1); // eg '[15I' => count = 15
+            const char *itemType = _type;
+            while(isdigit((int)*(++itemType))) ; // skip dimension
+            [self encodeArrayOfObjCType:itemType count:count at:_value];
+            break;
+        }
+
+        case _C_STRUCT_B: { // C-structure begin '{'
+            int offset = 0;
+
+            while ((*_type != _C_STRUCT_E) && (*_type++ != '=')); // skip "<name>="
+        
+            while (YES) {
+                [self encodeValueOfObjCType:_type at:((char *)_value) + offset];
+            
+                offset += objc_sizeof_type(_type);
+                _type  =  objc_skip_typespec(_type);
+            
+                if(*_type != _C_STRUCT_E) { // C-structure end '}'
+                    int align, remainder;
+                    
+                    align = objc_alignof_type(_type);
+                    if((remainder = offset % align))
+                        offset += (align - remainder);
+                }
+                else
+                    break;
+            }
+            break;
+        }
+    }
+}
+
+- (void)_encodeValueOfObjCType:(const char *)_type at:(const void *)_value
+{
+    //NGLogT(@"encoder", @"encoding value of ObjC-type '%s' at %i",
+    //       _type, [self->data length]);
+  
+    switch (*_type) {
+        case _C_ID:
+        case _C_CLASS:
+            // ?? Write another tag just to be possible to read using the
+            // ?? decodeObject method. (Otherwise a lookahead would be required)
+            // ?? _writeTag(self, *_type);
+            [self _encodeObject:*(id *)_value];
+            break;
+
+        case _C_ARY_B: {
+            int        count     = atoi(_type + 1); // eg '[15I' => count = 15
+            const char *itemType = _type;
+
+            while(isdigit((int)*(++itemType))) ; // skip dimension
+
+            // Write another tag just to be possible to read using the
+            // decodeArrayOfObjCType:count:at: method.
+            _writeTag(self, _C_ARY_B);
+            [self encodeArrayOfObjCType:itemType count:count at:_value];
+            break;
+        }
+
+        case _C_STRUCT_B: { // C-structure begin '{'
+            int offset = 0;
+
+            _writeTag(self, '{');
+
+            while ((*_type != _C_STRUCT_E) && (*_type++ != '=')); // skip "<name>="
+        
+            while (YES) {
+                [self encodeValueOfObjCType:_type at:((char *)_value) + offset];
+            
+                offset += objc_sizeof_type(_type);
+                _type  =  objc_skip_typespec(_type);
+            
+                if(*_type != _C_STRUCT_E) { // C-structure end '}'
+                    int align, remainder;
+                    
+                    align = objc_alignof_type(_type);
+                    if((remainder = offset % align))
+                        offset += (align - remainder);
+                }
+                else
+                    break;
+            }
+            break;
+        }
+
+        case _C_SEL:
+            _writeTag(self, _C_SEL);
+            _writeCString(self, (*(SEL *)_value) ? sel_get_name(*(SEL *)_value) : NULL);
+            break;
+      
+        case _C_PTR:
+            _writeTag(self, *_type);
+            _writeObjC(self, *(char **)_value, _type + 1);
+            break;
+        case _C_CHARPTR:
+            _writeTag(self, *_type);
+            _writeObjC(self, _value, _type);
+            break;
+      
+        case _C_CHR:    case _C_UCHR:
+        case _C_SHT:    case _C_USHT:
+        case _C_INT:    case _C_UINT:
+        case _C_LNG:    case _C_ULNG:
+        case _C_FLT:    case _C_DBL:
+            _writeTag(self, *_type);
+            _writeObjC(self, _value, _type);
+            break;
+      
+        default:
+            NSLog(@"unsupported C type %s ..", _type);
+            break;
+    }
+}
+
+- (void)encodeValueOfObjCType:(const char *)_type
+                           at:(const void *)_value
+{
+    if (self->traceMode) {
+        //NSLog(@"trace value at 0x%08X of type %s", _value, _type);
+        [self _traceValueOfObjCType:_type at:_value];
+    }
+    else {
+        if (self->didWriteHeader == NO)
+            [self writeArchiveHeader];
+  
+        [self _encodeValueOfObjCType:_type at:_value];
+    }
+}
+
+- (void)encodeArrayOfObjCType:(const char *)_type
+                        count:(unsigned int)_count
+                           at:(const void *)_array
+{
+
+    if ((self->didWriteHeader == NO) && (self->traceMode == NO))
+        [self writeArchiveHeader];
+
+    //NGLogT(@"encoder", @"%s array[%i] of ObjC-type '%s'",
+    //       self->traceMode ? "tracing" : "encoding", _count, _type);
+  
+    // array header
+    if (self->traceMode == NO) { // nothing is written during trace-mode
+        _writeTag(self, _C_ARY_B);
+        _writeInt(self, _count);
+    }
+
+    // Optimize writing arrays of elementary types. If such an array has to
+    // be written, write the type and then the elements of array.
+
+    if ((*_type == _C_ID) || (*_type == _C_CLASS)) { // object array
+        int i;
+
+        if (self->traceMode == NO)
+            _writeTag(self, *_type); // object array
+
+        for (i = 0; i < _count; i++)
+            [self encodeObject:((id *)_array)[i]];
+    }
+    else if ((*_type == _C_CHR) || (*_type == _C_UCHR)) { // byte array
+        if (self->traceMode == NO) {
+            //NGLogT(@"encoder", @"encode byte-array (base='%c', count=%i)", *_type, _count);
+
+            // write base type tag
+            _writeTag(self, *_type);
+
+            // write buffer
+            _writeBytes(self, _array, _count);
+        }
+    }
+    else if (isBaseType(_type)) {
+        if (self->traceMode == NO) {
+            unsigned offset, itemSize = objc_sizeof_type(_type);
+            int      i;
+
+            /*
+              NGLogT(@"encoder",
+              @"encode basetype-array (base='%c', itemSize=%i, count=%i)",
+              *_type, itemSize, _count);
+              */
+
+            // write base type tag
+            _writeTag(self, *_type);
+
+            // write contents
+            for (i = offset = 0; i < _count; i++, offset += itemSize)
+                _writeObjC(self, (char *)_array + offset, _type);
+        }
+    }
+    else { // encoded using normal method
+        IMP      encodeValue = NULL;
+        unsigned offset, itemSize = objc_sizeof_type(_type);
+        int      i;
+
+        encodeValue = [self methodForSelector:@selector(encodeValueOfObjCType:at:)];
+
+        for (i = offset = 0; i < _count; i++, offset += itemSize) {
+            encodeValue(self, @selector(encodeValueOfObjCType:at:),
+                        (char *)_array + offset, _type);
+        }
+    }
+}
+
+// Substituting One Class for Another
+
+- (NSString *)classNameEncodedForTrueClassName:(NSString *)_trueName
+{
+    NSString *name = NSMapGet(self->outClassAlias, _trueName);
+    return name ? name : _trueName;
+}
+- (void)encodeClassName:(NSString *)_name intoClassName:(NSString *)_archiveName
+{
+    NSMapInsert(self->outClassAlias, _name, _archiveName);
+}
+
+// ******************** primitive encoding ********************
+
+FINAL void _writeBytes(NSArchiver *self, const void *_bytes, unsigned _len)
+{
+    NSCAssert(self->traceMode == NO, @"nothing can be written during trace-mode ..");
+    self->addData(self->data, @selector(appendBytes:length:), _bytes, _len);
+}
+FINAL void _writeTag(NSArchiver *self, NSTagType _tag)
+{
+    unsigned char t = _tag;
+    NSCAssert(self, @"invalid self ..");
+    _writeBytes(self, &t, sizeof(t));
+}
+FINAL void _writeChar(NSArchiver *self, char _value)
+{
+    _writeBytes(self, &_value, sizeof(_value));
+}
+
+FINAL void _writeShort(NSArchiver *self, short _value)
+{
+    self->serData(self->data, @selector(serializeDataAt:ofObjCType:context:),
+                  &_value, @encode(short), self);
+}
+FINAL void _writeInt(NSArchiver *self, int _value)
+{
+    self->serData(self->data, @selector(serializeDataAt:ofObjCType:context:),
+                  &_value, @encode(int), self);
+}
+FINAL void _writeLong(NSArchiver *self, long _value)
+{
+    self->serData(self->data, @selector(serializeDataAt:ofObjCType:context:),
+                  &_value, @encode(long), self);
+}
+FINAL void _writeFloat(NSArchiver *self, float _value)
+{
+    self->serData(self->data, @selector(serializeDataAt:ofObjCType:context:),
+                  &_value, @encode(float), self);
+}
+
+FINAL void _writeCString(NSArchiver *self, const char *_value)
+{
+    self->serData(self->data, @selector(serializeDataAt:ofObjCType:context:),
+                  &_value, @encode(char *), self);
+}
+
+FINAL void _writeObjC(NSArchiver *self, const void *_value, const char *_type)
+{
+    if ((_value == NULL) || (_type == NULL))
+        return;
+
+    if (self->traceMode) {
+        // no need to track base-types in trace-mode
+    
+        switch (*_type) {
+            case _C_ID:
+            case _C_CLASS:
+            case _C_CHARPTR:
+            case _C_ARY_B:
+            case _C_STRUCT_B:
+            case _C_PTR:
+                self->serData(self->data, @selector(serializeDataAt:ofObjCType:context:),
+                              _value, _type, self);
+                break;
+
+            default:
+                break;
+        }
+    }
+    else {
+        self->serData(self->data, @selector(serializeDataAt:ofObjCType:context:),
+                      _value, _type, self);
+    }
+}
+
+// NSObjCTypeSerializationCallBack
+
+- (void)serializeObjectAt:(id *)_object
+               ofObjCType:(const char *)_type
+                 intoData:(NSMutableData *)_data
+{
+    NSAssert(((*_type == _C_ID) || (*_type == _C_CLASS)), @"unexpected type ..");
+
+    if (self->traceMode)
+        [self _traceObject:*_object];
+    else
+        [self _encodeObject:*_object];
+}
+- (void)deserializeObjectAt:(id *)_object
+        ofObjCType:(const char *)_type
+        fromData:(NSData *)_data
+        atCursor:(unsigned int *)_cursor
+{
+    [self doesNotRecognizeSelector:_cmd];
+}
+
+@end /* NSArchiver */
+
+@implementation NSUnarchiver
+
+static NSMapTable *classToAliasMappings = NULL; // archive name => decoded name
+
++ (void)initialize
+{
+    static BOOL isInitialized = NO;
+    if (!isInitialized) {
+        isInitialized = YES;
+
+        classToAliasMappings = NSCreateMapTable(NSObjectMapKeyCallBacks,
+                                                NSObjectMapValueCallBacks,
+                                                19);
+    }
+}
+  
+- (id)initForReadingWithData:(NSData*)_data
+{
+    if ((self = [super init])) {
+        self->inObjects       = NSCreateMapTable(NSIntMapKeyCallBacks,
+                                                 NSObjectMapValueCallBacks,
+                                                 119);
+        self->inClasses       = NSCreateMapTable(NSIntMapKeyCallBacks,
+                                                 NSObjectMapValueCallBacks,
+                                                 19);
+        self->inPointers      = NSCreateMapTable(NSIntMapKeyCallBacks,
+                                                 NSIntMapValueCallBacks,
+                                                 19);
+        self->inClassAlias    = NSCreateMapTable(NSObjectMapKeyCallBacks,
+                                                 NSObjectMapValueCallBacks,
+                                                 19);
+        self->inClassVersions = NSCreateMapTable(NSObjectMapKeyCallBacks,
+                                                 NSObjectMapValueCallBacks,
+                                                 19);
+        self->data = RETAIN(_data);
+        self->deserData = (void *)
+            [self->data methodForSelector:
+                 @selector(deserializeDataAt:ofObjCType:atCursor:context:)];
+        self->getData = (void *)
+            [self->data methodForSelector:@selector(deserializeBytes:length:atCursor:)];
+    }
+    return self;
+}
+
+/* Decoding Objects */
+
++ (id)unarchiveObjectWithData:(NSData*)_data
+{
+    NSUnarchiver *unarchiver = [[self alloc] initForReadingWithData:_data];
+    id           object      = [unarchiver decodeObject];
+
+    RELEASE(unarchiver); unarchiver = nil;
+  
+    return object;
+}
++ (id)unarchiveObjectWithFile:(NSString*)path
+{
+    NSData *rdata = [NSData dataWithContentsOfFile:path];
+    if (!rdata) return nil;
+    return [self unarchiveObjectWithData:rdata];
+}
+
+
+#if !LIB_FOUNDATION_BOEHM_GC
+- (void)dealloc
+{
+    RELEASE(self->data); self->data = nil;
+  
+    if (self->inObjects) {
+        NSFreeMapTable(self->inObjects); self->inObjects = NULL; }
+    if (self->inClasses) {
+        NSFreeMapTable(self->inClasses); self->inClasses = NULL; }
+    if (self->inPointers) {
+        NSFreeMapTable(self->inPointers); self->inPointers = NULL; }
+    if (self->inClassAlias) {
+        NSFreeMapTable(self->inClassAlias); self->inClassAlias = NULL; }
+    if (self->inClassVersions) {
+        NSFreeMapTable(self->inClassVersions); self->inClassVersions = NULL; }
+  
+    [super dealloc];
+}
+#endif
+
+/* Managing an NSUnarchiver */
+
+- (BOOL)isAtEnd
+{
+    return ([self->data length] <= self->cursor) ? YES : NO;
+}
+
+- (void)setObjectZone:(NSZone *)_zone
+{
+    self->objectZone = _zone;
+}
+- (NSZone *)objectZone
+{
+    return self->objectZone;
+}
+
+- (unsigned int)systemVersion
+{
+    return self->inArchiverVersion;
+}
+
+// ******************** primitive decoding ********************
+
+FINAL void _readBytes(NSUnarchiver *self, void *_bytes, unsigned _len);
+
+FINAL NSTagType _readTag(NSUnarchiver *self);
+
+FINAL char  _readChar (NSUnarchiver *self);
+FINAL short _readShort(NSUnarchiver *self);
+FINAL int   _readInt  (NSUnarchiver *self);
+FINAL long  _readLong (NSUnarchiver *self);
+FINAL float _readFloat(NSUnarchiver *self);
+
+FINAL char *_readCString(NSUnarchiver *self);
+FINAL void _readObjC(NSUnarchiver *self, void *_value, const char *_type);
+
+// ******************** complex decoding **********************
+
+- (void)decodeArchiveHeader
+{
+    if (self->didReadHeader == NO) {
+        char *archiver = _readCString(self);
+
+        self->inArchiverVersion = _readInt(self);
+
+        //NGLogT(@"decoder", @"decoding archive archived using '%s':%i ..",
+        //       archiver, archiverVersion);
+
+        if (strcmp(archiver, NSCoderSignature)) {
+            NSLog(@"WARNING: used a different archiver (signature %s:%i)",
+                  archiver, [self systemVersion]);
+        }
+        else if ([self systemVersion] != NSCoderVersion) {
+            NSLog(@"WARNING: used a different archiver version "
+                  @"(archiver=%i, unarchiver=%i)",
+                  [self systemVersion], NSCoderVersion);
+        }
+
+        if (archiver) {
+            lfFree(archiver);
+            archiver = NULL;
+        }
+        self->didReadHeader = YES;
+    }
+}
+
+- (void)beginDecoding
+{
+    //self->cursor = 0;
+    [self decodeArchiveHeader];
+}
+- (void)endDecoding
+{
+#if 0
+    NSResetMapTable(self->inObjects);
+    NSResetMapTable(self->inClasses);
+    NSResetMapTable(self->inPointers);
+    NSResetMapTable(self->inClassAlias);
+    NSResetMapTable(self->inClassVersions);
+#endif
+
+    self->decodingRoot = NO;
+}
+
+- (Class)_decodeClass:(BOOL)_isReference
+{
+    int   archiveId = _readInt(self);
+    Class result    = Nil;
+
+    if (archiveId == 0) // Nil class or unused conditional class
+        return nil;
+    
+    if (_isReference) {
+        NSAssert(archiveId, @"archive id is 0 !");
+        
+        result = (Class)NSMapGet(self->inClasses, (void *)archiveId);
+        if (result == nil)
+            result = (id)NSMapGet(self->inObjects, (void *)archiveId);
+        if (result == nil) {
+            [NSException raise:NSInconsistentArchiveException
+                         format:@"did not find referenced class %i.", archiveId];
+        }
+    }
+    else {
+        NSString *name   = NULL;
+        int      version = 0;
+        char     *cname  = _readCString(self);
+
+        if (cname == NULL) {
+            [NSException raise:NSInconsistentArchiveException
+                         format:@"could not decode class name."];
+        }
+        
+        name    = [NSString stringWithCString:cname];
+        version = _readInt(self);
+        lfFree(cname); cname = NULL;
+        
+        if ([name cStringLength] == 0) {
+            [NSException raise:NSInconsistentArchiveException
+                         format:@"could not allocate memory for class name."];
+        }
+
+        { // check whether the class is to be replaced
+            NSString *newName = NSMapGet(self->inClassAlias, name);
+      
+            if (newName)
+                name = newName;
+            else {
+                newName = NSMapGet(classToAliasMappings, name);
+                if (newName)
+                    name = newName;
+            }
+        }
+    
+        result = NSClassFromString(name);
+
+        if (result == Nil) {
+            [NSException raise:NSInconsistentArchiveException
+                         format:@"class doesn't exist in this runtime."];
+        }
+        name = nil;
+
+        if ([result version] != version) {
+            [NSException raise:NSInconsistentArchiveException
+                         format:@"class versions do not match."];
+        }
+
+        NSMapInsert(self->inClasses, (void *)archiveId, result);
+#if ARCHIVE_DEBUGGING
+        NSLog(@"read class %i => 0x%08X", archiveId, result);
+#endif
+    }
+  
+    NSAssert(result, @"Invalid state, class is Nil.");
+  
+    return result;
+}
+
+- (id)_decodeObject:(BOOL)_isReference
+{
+    // this method returns a retained object !
+    int archiveId = _readInt(self);
+    id  result    = nil;
+
+    if (archiveId == 0) // nil object or unused conditional object
+        return nil;
+
+    if (_isReference) {
+        NSAssert(archiveId, @"archive id is 0 !");
+        
+        result = (id)NSMapGet(self->inObjects, (void *)archiveId);
+        if (result == nil)
+            result = (id)NSMapGet(self->inClasses, (void *)archiveId);
+        
+        if (result == nil) {
+            [NSException raise:NSInconsistentArchiveException
+                         format:@"did not find referenced object %i.", archiveId];
+        }
+        result = RETAIN(result);
+    }
+    else {
+        Class class       = Nil;
+        id    replacement = nil;
+
+        // decode class info
+        [self decodeValueOfObjCType:"#" at:&class];
+        NSAssert(class, @"could not decode class for object.");
+    
+        result = [class allocWithZone:self->objectZone];
+        NSMapInsert(self->inObjects, (void *)archiveId, result);
+        
+#if ARCHIVE_DEBUGGING
+        NSLog(@"read object %i => 0x%08X", archiveId, result);
+#endif
+
+        replacement = [result initWithCoder:self];
+        if (replacement != result) {
+            /*
+              NGLogT(@"decoder",
+              @"object 0x%08X<%s> replaced by 0x%08X<%s> in initWithCoder:",
+              result, class_get_class_name(*(Class *)result),
+              replacement, class_get_class_name(*(Class *)replacement));
+            */
+
+            replacement = RETAIN(replacement);
+            NSMapRemove(self->inObjects, (void*)archiveId);
+            result = replacement;
+            NSMapInsert(self->inObjects, (void *)archiveId, result);
+            RELEASE(replacement);
+        }
+
+        replacement = [result awakeAfterUsingCoder:self];
+        if (replacement != result) {
+            /*
+              NGLogT(@"decoder",
+              @"object 0x%08X<%s> replaced by 0x%08X<%s> in awakeAfterUsingCoder:",
+              result, class_get_class_name(*(Class *)class),
+              replacement, class_get_class_name(*(Class *)replacement));
+            */
+      
+            replacement = RETAIN(replacement);
+            NSMapRemove(self->inObjects, (void*)archiveId);
+            result = replacement;
+            NSMapInsert(self->inObjects, (void *)archiveId, result);
+            RELEASE(replacement);
+        }
+
+        //NGLogT(@"decoder", @"decoded object 0x%08X<%@>",
+        //       (unsigned)result, NSStringFromClass([result class]));
+    }
+    
+    if (object_is_instance(result)) {
+        NSAssert3([result retainCount] > 0,
+                  @"invalid retain count %i for id=%i (%@) ..",
+                  [result retainCount],
+                  archiveId,
+                  NSStringFromClass([result class]));
+    }
+    return result;
+}
+
+- (id)decodeObject
+{
+    id result = nil;
+
+    [self decodeValueOfObjCType:"@" at:&result];
+  
+    // result is retained
+    return AUTORELEASE(result);
+}
+
+FINAL void _checkType(char _code, char _reqCode)
+{
+    if (_code != _reqCode) {
+        [NSException raise:NSInconsistentArchiveException
+                     format:@"expected different typecode"];
+    }
+}
+FINAL void _checkType2(char _code, char _reqCode1, char _reqCode2)
+{
+    if ((_code != _reqCode1) && (_code != _reqCode2)) {
+        [NSException raise:NSInconsistentArchiveException
+                     format:@"expected different typecode"];
+    }
+}
+
+- (void)decodeValueOfObjCType:(const char *)_type
+  at:(void *)_value
+{
+    BOOL      startedDecoding = NO;
+    NSTagType tag             = 0;
+    BOOL      isReference     = NO;
+
+    if (self->decodingRoot == NO) {
+        self->decodingRoot = YES;
+        startedDecoding = YES;
+        [self beginDecoding];
+    }
+
+    //NGLogT(@"decoder", @"cursor is now %i", self->cursor);
+  
+    tag         = _readTag(self);
+    isReference = isReferenceTag(tag);
+    tag         = tagValue(tag);
+
+#if ARCHIVE_DEBUGGING
+    NSLog(@"decoder: decoding tag '%s%c' type '%s'",
+           isReference ? "&" : "", tag, _type);
+#endif
+
+    switch (tag) {
+        case _C_ID:
+            _checkType2(*_type, _C_ID, _C_CLASS);
+            *(id *)_value = [self _decodeObject:isReference];
+            break;
+        case _C_CLASS:
+            _checkType2(*_type, _C_ID, _C_CLASS);
+            *(Class *)_value = [self _decodeClass:isReference];
+            break;
+
+        case _C_ARY_B: {
+            int        count     = atoi(_type + 1); // eg '[15I' => count = 15
+            const char *itemType = _type;
+
+            _checkType(*_type, _C_ARY_B);
+
+            while(isdigit((int)*(++itemType))) ; // skip dimension
+
+            [self decodeArrayOfObjCType:itemType count:count at:_value];
+            break;
+        }
+
+        case _C_STRUCT_B: {
+            int offset = 0;
+
+            _checkType(*_type, _C_STRUCT_B);
+      
+            while ((*_type != _C_STRUCT_E) && (*_type++ != '=')); // skip "<name>="
+        
+            while (YES) {
+                [self decodeValueOfObjCType:_type at:((char *)_value) + offset];
+            
+                offset += objc_sizeof_type(_type);
+                _type  =  objc_skip_typespec(_type);
+            
+                if(*_type != _C_STRUCT_E) { // C-structure end '}'
+                    int align, remainder;
+                    
+                    align = objc_alignof_type(_type);
+                    if((remainder = offset % align))
+                        offset += (align - remainder);
+                }
+                else
+                    break;
+            }
+            break;
+        }
+
+        case _C_SEL: {
+            char *name = NULL;
+      
+            _checkType(*_type, tag);
+
+            _readObjC(self, &name, @encode(char *));
+            *(SEL *)_value = name ? sel_get_any_uid(name) : NULL;
+            lfFree(name); name = NULL;
+        }
+
+        case _C_PTR:
+            _readObjC(self, *(char **)_value, _type + 1); // skip '^'
+            break;
+      
+        case _C_CHARPTR:
+        case _C_CHR:    case _C_UCHR:
+        case _C_SHT:    case _C_USHT:
+        case _C_INT:    case _C_UINT:
+        case _C_LNG:    case _C_ULNG:
+        case _C_FLT:    case _C_DBL:
+            _checkType(*_type, tag);
+            _readObjC(self, _value, _type);
+            break;
+      
+        default:
+            [NSException raise:NSInconsistentArchiveException
+                         format:@"unsupported typecode %i found.", tag];
+            break;
+    }
+
+    if (startedDecoding) {
+        [self endDecoding];
+        self->decodingRoot = NO;
+    }
+}
+
+- (void)decodeArrayOfObjCType:(const char *)_type
+  count:(unsigned int)_count
+  at:(void *)_array
+{
+    BOOL      startedDecoding = NO;
+    NSTagType tag   = _readTag(self);
+    int       count = _readInt(self);
+
+    if (self->decodingRoot == NO) {
+        self->decodingRoot = YES;
+        startedDecoding = YES;
+        [self beginDecoding];
+    }
+  
+    //NGLogT(@"decoder", @"decoding array[%i/%i] of ObjC-type '%s' array-tag='%c'",
+    //       _count, count, _type, tag);
+  
+    NSAssert(tag == _C_ARY_B, @"invalid type ..");
+    NSAssert(count == _count, @"invalid array size ..");
+
+    // Arrays of elementary types are written optimized: the type is written
+    // then the elements of array follow.
+    if ((*_type == _C_ID) || (*_type == _C_CLASS)) { // object array
+        int i;
+
+        //NGLogT(@"decoder", @"decoding object-array[%i] type='%s'", _count, _type);
+    
+        tag = _readTag(self); // object array
+        NSAssert(tag == *_type, @"invalid array element type ..");
+      
+        for (i = 0; i < _count; i++)
+            ((id *)_array)[i] = [self decodeObject];
+    }
+    else if ((*_type == _C_CHR) || (*_type == _C_UCHR)) { // byte array
+        tag = _readTag(self);
+        NSAssert((tag == _C_CHR) || (tag == _C_UCHR), @"invalid byte array type ..");
+
+        //NGLogT(@"decoder", @"decoding byte-array[%i] type='%s' tag='%c'",
+        //       _count, _type, tag);
+    
+        // read buffer
+        _readBytes(self, _array, _count);
+    }
+    else if (isBaseType(_type)) {
+        unsigned offset, itemSize = objc_sizeof_type(_type);
+        int      i;
+      
+        tag = _readTag(self);
+        NSAssert(tag == *_type, @"invalid array base type ..");
+
+        for (i = offset = 0; i < _count; i++, offset += itemSize)
+            _readObjC(self, (char *)_array + offset, _type);
+    }
+    else {
+        IMP      decodeValue = NULL;
+        unsigned offset, itemSize = objc_sizeof_type(_type);
+        int      i;
+
+        decodeValue = [self methodForSelector:@selector(decodeValueOfObjCType:at:)];
+    
+        for (i = offset = 0; i < count; i++, offset += itemSize) {
+            decodeValue(self, @selector(decodeValueOfObjCType:at:),
+                        (char *)_array + offset, _type);
+        }
+    }
+
+    if (startedDecoding) {
+        [self endDecoding];
+        self->decodingRoot = NO;
+    }
+}
+
+/* Substituting One Class for Another */
+
++ (NSString *)classNameDecodedForArchiveClassName:(NSString *)nameInArchive
+{
+    NSString *className = NSMapGet(classToAliasMappings, nameInArchive);
+    return className ? className : nameInArchive;
+}
+
++ (void)decodeClassName:(NSString *)nameInArchive
+            asClassName:(NSString *)trueName
+{
+    NSMapInsert(classToAliasMappings, nameInArchive, trueName);
+}
+
+- (NSString *)classNameDecodedForArchiveClassName:(NSString *)_nameInArchive
+{
+    NSString *className = NSMapGet(self->inClassAlias, _nameInArchive);
+    return className ? className : _nameInArchive;
+}
+- (void)decodeClassName:(NSString *)nameInArchive asClassName:(NSString *)trueName
+{
+    NSMapInsert(self->inClassAlias, nameInArchive, trueName);
+}
+
+// ******************** primitive decoding ********************
+
+FINAL void _readBytes(NSUnarchiver *self, void *_bytes, unsigned _len)
+{
+    self->getData(self->data, @selector(deserializeBytes:length:atCursor:),
+                  _bytes, _len, &(self->cursor));
+}
+
+FINAL NSTagType _readTag(NSUnarchiver *self)
+{
+    unsigned char c;
+    NSCAssert(self, @"invalid self ..");
+
+    _readBytes(self, &c, sizeof(c));
+    if (c == 0) {
+        [NSException raise:NSInconsistentArchiveException
+                     format:@"found invalid type tag (0)"];
+    }
+    return (NSTagType)c;
+}
+FINAL char _readChar(NSUnarchiver *self)
+{
+    char c;
+    _readBytes(self, &c, sizeof(c));
+    return c;
+}
+
+FINAL short _readShort(NSUnarchiver *self)
+{
+    short value;
+    self->deserData(self->data,
+                    @selector(deserializeDataAt:ofObjCType:atCursor:context:),
+                    &value, @encode(short), &(self->cursor), self);
+    return value;
+}
+FINAL int _readInt(NSUnarchiver *self)
+{
+    int value;
+    self->deserData(self->data,
+                    @selector(deserializeDataAt:ofObjCType:atCursor:context:),
+                    &value, @encode(int), &(self->cursor), self);
+    return value;
+}
+FINAL long _readLong (NSUnarchiver *self)
+{
+    long value;
+    self->deserData(self->data,
+                    @selector(deserializeDataAt:ofObjCType:atCursor:context:),
+                    &value, @encode(long), &(self->cursor), self);
+    return value;
+}
+FINAL float _readFloat(NSUnarchiver *self)
+{
+    float value;
+    self->deserData(self->data,
+                    @selector(deserializeDataAt:ofObjCType:atCursor:context:),
+                    &value, @encode(float), &(self->cursor), self);
+    return value;
+}
+
+FINAL char *_readCString(NSUnarchiver *self)
+{
+    char *value = NULL;
+    self->deserData(self->data,
+                    @selector(deserializeDataAt:ofObjCType:atCursor:context:),
+                    &value, @encode(char *), &(self->cursor), self);
+    return value;
+}
+
+FINAL void _readObjC(NSUnarchiver *self, void *_value, const char *_type)
+{
+    self->deserData(self->data,
+                    @selector(deserializeDataAt:ofObjCType:atCursor:context:),
+                    _value, _type,
+                    &(self->cursor),
+                    self);
+}
+
+// NSObjCTypeSerializationCallBack
+
+- (void)serializeObjectAt:(id *)_object
+  ofObjCType:(const char *)_type
+  intoData:(NSMutableData *)_data
+{
+    [self doesNotRecognizeSelector:_cmd];
+}
+
+- (void)deserializeObjectAt:(id *)_object
+  ofObjCType:(const char *)_type
+  fromData:(NSData *)_data
+  atCursor:(unsigned int *)_cursor
+{
+    NSTagType tag             = 0;
+    BOOL      isReference     = NO;
+
+    tag         = _readTag(self);
+    isReference = isReferenceTag(tag);
+    tag         = tagValue(tag);
+
+    NSCAssert(((*_type == _C_ID) || (*_type == _C_CLASS)),
+              @"unexpected type ..");
+  
+    switch (*_type) {
+        case _C_ID:
+            NSAssert((*_type == _C_ID) || (*_type == _C_CLASS), @"invalid type ..");
+            break;
+            *_object = [self _decodeObject:isReference];
+            break;
+        case _C_CLASS:
+            NSAssert((*_type == _C_ID) || (*_type == _C_CLASS), @"invalid type ..");
+            *_object = [self _decodeClass:isReference];
+            break;
+      
+        default:
+            [NSException raise:NSInconsistentArchiveException
+                         format:@"encountered type '%s' in object context",
+                           _type];
+            break;
+    }
+}
+
+@end /* NSUnarchiver */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSArray.h b/libFoundation/Foundation/NSArray.h
new file mode 100644 (file)
index 0000000..3916257
--- /dev/null
@@ -0,0 +1,191 @@
+/* 
+   NSArray.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSArray_h__
+#define __NSArray_h__
+
+#include <Foundation/NSObject.h>
+#include <Foundation/NSRange.h>
+
+@class NSString;
+@class NSEnumerator;
+@class NSDictionary;
+@class NSURL;
+
+@interface NSArray : NSObject <NSCoding, NSCopying, NSMutableCopying>
+
+/* Allocating and Initializing an Array */
++ (id)allocWithZone:(NSZone*)zone;
++ (id)array;
++ (id)arrayWithObject:(id)anObject;
++ (id)arrayWithObjects:(id)firstObj,...;
++ (id)arrayWithArray:(NSArray*)anotherArray;
++ (id)arrayWithContentsOfFile:(NSString *)fileName;
++ (id)arrayWithContentsOfURL:(NSURL *)_url;
++ (id)arrayWithObjects:(id*)objects count:(unsigned int)count;
+- (id)initWithArray:(NSArray*)anotherArray;
+- (id)initWithArray:(NSArray*)anotherArray copyItems:(BOOL)flag;
+- (id)initWithObjects:(id)firstObj,...;
+- (id)initWithObjects:(id *)objects count:(unsigned int)count;
+- (id)initWithContentsOfURL:(NSURL *)_url;
+
+/* Querying the Array */
+- (BOOL)containsObject:(id)anObject;
+- (unsigned int)count;
+- (unsigned int)indexOfObject:(id)anObject;
+- (unsigned int)indexOfObjectIdenticalTo:(id)anObject;
+- (unsigned int)indexOfObject:(id)anObject inRange:(NSRange)aRange;
+- (unsigned int)indexOfObjectIdenticalTo:(id)anObject inRange:(NSRange)aRange;
+- (id)lastObject;
+- (id)objectAtIndex:(unsigned int)index;
+- (void)getObjects:(id *)buffer;
+- (void)getObjects:(id *)buffer range:(NSRange)range;
+- (NSEnumerator*)objectEnumerator;
+- (NSEnumerator*)reverseObjectEnumerator;
+
+/* Sending Messages to Elements */
+- (void)makeObjectsPerformSelector:(SEL)aSelector;
+- (void)makeObjectsPerformSelector:(SEL)aSelector withObject:(id)anObject;
+/* Obsolete messages */
+- (void)makeObjectsPerform:(SEL)aSelector;
+- (void)makeObjectsPerform:(SEL)aSelector withObject:(id)anObject;
+
+/* Comparing Arrays */
+- (id)firstObjectCommonWithArray:(NSArray*)otherArray;
+- (BOOL)isEqualToArray:(NSArray*)otherArray;
+
+/* Deriving New Array */
+- (NSArray*)arrayByAddingObject:(id)anObject;
+- (NSArray*)arrayByAddingObjectsFromArray:(NSArray*)anotherArray;
+- (NSArray*)sortedArrayUsingFunction:
+  (int(*)(id element1, id element2, void *userData))comparator
+  context:(void*)context;
+- (NSArray*)sortedArrayUsingSelector:(SEL)comparator;
+- (NSArray*)subarrayWithRange:(NSRange)range;
+
+/* Joining String Elements */
+- (NSString*)componentsJoinedByString:(NSString*)separator;
+
+/* Creating a String Description of the Array */
+- (NSString*)description;
+- (NSString*)stringRepresentation;
+- (NSString*)descriptionWithLocale:(NSDictionary*)locale;
+- (NSString*)descriptionWithLocale:(NSDictionary*)locale
+   indent:(unsigned int)level;
+
+/* Write plist to file */
+- (BOOL)writeToFile:(NSString*)fileName atomically:(BOOL)flag;
+
+/* From adopted/inherited protocols */
+- (unsigned)hash;
+- (BOOL)isEqual:(id)anObject;
+
+@end
+
+/*
+ * Extensions to NSArray
+ */
+
+@interface NSArray (NSArrayExtensions)
+
+/* Sending Messages to Elements */
+- (void)makeObjectsPerform:(SEL)aSelector
+  withObject:(id)anObject1 withObject:(id)anObject2;
+
+/* Deriving New Arrays */
+- (NSArray*)map:(SEL)aSelector;
+- (NSArray*)map:(SEL)aSelector with:anObject;
+- (NSArray*)map:(SEL)aSelector with:anObject with:otherObject;
+
+- (NSArray*)arrayWithObjectsThat:(BOOL(*)(id anObject))comparator;
+- (NSArray*)map:(id(*)(id anObject))function
+  objectsThat:(BOOL(*)(id anObject))comparator;
+
+@end
+
+/*
+ * NSMutableArray class
+ */
+
+@interface NSMutableArray : NSArray
+
+/* Creating and Initializing an NSMutableArray */
++ (id)allocWithZone:(NSZone*)zone;
++ (id)arrayWithCapacity:(unsigned int)aNumItems;
+- (id)initWithCapacity:(unsigned int)aNumItems;
+- (id)init;
+
+/* Adding Objects */
+- (void)addObject:(id)anObject;
+- (void)addObjectsFromArray:(NSArray*)anotherArray;
+- (void)insertObject:(id)anObject atIndex:(unsigned int)index;
+
+/* Removing Objects */
+- (void)removeAllObjects;
+- (void)removeLastObject;
+- (void)removeObject:(id)anObject;
+- (void)removeObjectAtIndex:(unsigned int)index;
+- (void)removeObjectIdenticalTo:(id)anObject;
+- (void)removeObjectsFromIndices:(unsigned int*)indices
+  numIndices:(unsigned int)count;
+- (void)removeObjectsInArray:(NSArray*)otherArray;
+- (void)removeObject:(id)anObject inRange:(NSRange)aRange;
+- (void)removeObjectIdenticalTo:(id)anObject inRange:(NSRange)aRange;
+- (void)removeObjectsInRange:(NSRange)aRange;
+
+/* Sorting */
+- (void)sortUsingFunction:(int (*)(id ,id ,void*))compare
+       context:(void*)context;
+- (void)sortUsingSelector:(SEL)comparator;
+
+/* Replacing Objects */
+- (void)replaceObjectAtIndex:(unsigned int)index withObject:(id)anObject;
+- (void)replaceObjectsInRange:(NSRange)rRange
+  withObjectsFromArray:(NSArray*)anArray;
+- (void)replaceObjectsInRange:(NSRange)rRange
+  withObjectsFromArray:(NSArray*)anArray range:(NSRange)aRange;
+- (void)setArray:(NSArray*)otherArray;
+
+@end
+
+/*
+ * Extensions to NSArray
+ */
+
+@interface NSMutableArray (NSMutableArrayExtensions)
+
+/* Removing Objects */
+- (void)removeObjectsFrom:(unsigned int)index count:(unsigned int)count;
+- (void)removeObjectsThat:(BOOL(*)(id anObject))comparator;
+
+@end
+
+#endif /* __NSArray_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSArray.m b/libFoundation/Foundation/NSArray.m
new file mode 100644 (file)
index 0000000..a53114c
--- /dev/null
@@ -0,0 +1,1189 @@
+/* 
+   NSArray.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <Foundation/common.h>
+#include <Foundation/NSObject.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSRange.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSCoder.h>
+#include <Foundation/PropertyListParser.h>
+#include <Foundation/NSUtilities.h>
+#include <Foundation/NSURL.h>
+
+#include <Foundation/exceptions/GeneralExceptions.h>
+
+#include "NSConcreteArray.h"
+#include "NSObject+PropLists.h"
+
+/*
+ * NSArray Implementation
+ * 
+ * primary methods are
+ *     init
+ *     initWithObjects:count:
+ *     dealloc
+ *     count
+ *     objectAtIndex:
+ */
+
+@implementation NSArray
+
+static Class NSArrayClass         = Nil;
+static Class NSMutableArrayClass  = Nil;
+static Class NSConcreteArrayClass = Nil;
+
+/* Allocating and Initializing an Array */
+
++ (id)allocWithZone:(NSZone*)zone
+{
+    if (NSArrayClass == Nil)
+        NSArrayClass = [NSArray class];
+    if (NSConcreteArrayClass == Nil)
+        NSConcreteArrayClass = [NSConcreteArray class];
+    
+    return NSAllocateObject( (self == NSArrayClass) ? 
+                             NSConcreteArrayClass : self, 0, zone);
+}
+
++ (id)array
+{
+    return AUTORELEASE([[self alloc] init]);
+}
+
++ (id)arrayWithObject:(id)anObject
+{
+    return AUTORELEASE([[self alloc] initWithObjects:&anObject count:1]);
+}
+
++ (id)arrayWithObjects:(id)firstObj,...
+{
+    id array, obj, *objects;
+    va_list list;
+    unsigned int count;
+
+    va_start(list, firstObj);
+    for (count=0, obj = firstObj; obj; obj = va_arg(list,id))
+       count++;
+    va_end(list);
+
+    objects = Malloc(sizeof(id) * count);
+    {
+        va_start(list, firstObj);
+        for (count = 0, obj = firstObj; obj; obj = va_arg(list,id))
+            objects[count++] = obj;
+        va_end(list);
+
+        array = [[self alloc] initWithObjects:objects count:count];
+    }
+    lfFree(objects);
+    return AUTORELEASE(array);
+}
+
++ (id)arrayWithArray:(NSArray*)anotherArray
+{
+    return AUTORELEASE([[self alloc] initWithArray:anotherArray]);
+}
+
++ (id)arrayWithContentsOfFile:(NSString *)fileName
+{
+    volatile id plist = nil;
+
+    NSString *format = @"%@: Caught exception %@ with reason %@ ";
+    
+    NS_DURING {
+        plist = NSParsePropertyListFromFile(fileName);
+
+        if (NSArrayClass == Nil)
+            NSArrayClass = [NSArray class];
+        if (![plist isKindOfClass:NSArrayClass])
+            plist = nil;
+    } 
+    NS_HANDLER {
+        NSLog(format, self, [localException name], [localException reason]);
+        plist = nil;
+    }
+    NS_ENDHANDLER;
+    
+    return plist;
+}
++ (id)arrayWithContentsOfURL:(NSURL *)_url
+{
+    id plist;
+    
+    if ([_url isFileURL])
+        return [self arrayWithContentsOfFile:[_url path]];
+
+    if (NSArrayClass == Nil)
+        NSArrayClass = [NSArray class];
+    
+    plist = [[NSString stringWithContentsOfURL:_url] propertyList];
+    if (![plist isKindOfClass:NSArrayClass])
+        return nil;
+    return plist;
+}
+
++ (id)arrayWithObjects:(id*)objects count:(unsigned int)count
+{
+    return AUTORELEASE([[self alloc]
+                              initWithObjects:objects count:count]);
+}
+
+- (NSArray*)arrayByAddingObject:(id)anObject
+{
+    int i, count = [self count];
+    id array;
+    id *objects;
+
+    objects = Malloc(sizeof(id) * (count + 1));
+    {
+        for (i = 0; i < count; i++)
+            objects[i] = [self objectAtIndex:i];
+        objects[i] = anObject;
+        
+        if (NSArrayClass == Nil)
+            NSArrayClass = [NSArray class];
+        
+        array = AUTORELEASE([[NSArrayClass alloc]
+                                      initWithObjects:objects count:count+1]);
+    }
+    lfFree(objects);
+    return array;
+}
+
+- (NSArray*)arrayByAddingObjectsFromArray:(NSArray*)anotherArray;
+{
+    unsigned int i, count = [self count], another = [anotherArray count];
+    id array;
+    id *objects;
+
+    objects = Malloc(sizeof(id) * (count+another));
+    {
+        for (i = 0; i < count; i++)
+            objects[i] = [self objectAtIndex:i];
+        for (i = 0; i < another; i++)
+            objects[i + count] = [anotherArray objectAtIndex:i];
+        
+        if (NSArrayClass == Nil)
+            NSArrayClass = [NSArray class];
+        
+        array = AUTORELEASE([[NSArrayClass alloc]
+                                      initWithObjects:objects count:count + another]);
+    }    
+    lfFree(objects);
+    return array;
+}
+
+- (id)initWithArray:(NSArray*)anotherArray
+{
+    return [self initWithArray:anotherArray copyItems:NO];
+}
+
+- (id)initWithArray:(NSArray*)anotherArray copyItems:(BOOL)flag;
+{
+    unsigned int i, count = [anotherArray count];
+    id *objects;
+
+    if (count == 0)
+        return [self initWithObjects:NULL count:0];
+
+    objects = Malloc(sizeof(id) * count);
+    {
+        for (i = 0; i < count; i++) {
+            objects[i] = flag
+                ? [anotherArray objectAtIndex:i]
+                : AUTORELEASE([[anotherArray objectAtIndex:i] copyWithZone:NULL]);
+        }
+        self = [self initWithObjects:objects count:count];
+    }
+    lfFree(objects);
+
+    return self;
+}
+
+- (id)initWithObjects:(id)firstObj,...
+{
+    id obj, *objects;
+    va_list list;
+    unsigned int count;
+
+    va_start(list, firstObj);
+    for (count = 0, obj = firstObj; obj; obj = va_arg(list,id))
+       count++;
+    va_end(list);
+
+    objects = Malloc(sizeof(id) * count);
+    {
+        va_start(list, firstObj);
+        for (count = 0, obj = firstObj; obj; obj = va_arg(list,id))
+            objects[count++] = obj;
+        va_end(list);
+
+        self = [self initWithObjects:objects count:count];
+    }
+    lfFree(objects);
+    return self;
+}
+
+- (id)initWithObjects:(id*)objects count:(unsigned int)count
+{
+    [self subclassResponsibility:_cmd];
+    return self;
+}
+
+- (id)initWithContentsOfFile:(NSString*)fileName
+{
+    NSArray *plist;
+
+    if (NSArrayClass == Nil)
+        NSArrayClass = [NSArray class];
+    
+    if ((plist = [NSArrayClass arrayWithContentsOfFile:fileName])) {
+        return [self initWithArray:plist];
+    }
+    else {
+        self = AUTORELEASE(self);
+        return nil;
+    }
+}
+- (id)initWithContentsOfURL:(NSURL *)_url
+{
+    NSArray *plist;
+
+    if (NSArrayClass == Nil)
+        NSArrayClass = [NSArray class];
+    
+    if ((plist = [NSArrayClass arrayWithContentsOfURL:_url])) {
+        return [self initWithArray:plist];
+    }
+    else {
+        self = AUTORELEASE(self);
+        return nil;
+    }
+}
+
+/* Querying the Array */
+
+- (BOOL)containsObject:(id)anObject
+{
+    return ([self indexOfObject:anObject] == NSNotFound) ? NO : YES;
+}
+
+- (unsigned int)count
+{
+    [self subclassResponsibility:_cmd];
+    return 0;
+}
+
+- (unsigned int)indexOfObject:(id)anObject
+{
+    return [self indexOfObject:anObject
+           inRange:NSMakeRange(0, [self count])];
+}
+
+- (unsigned int)indexOfObjectIdenticalTo:(id)anObject;
+{
+    return [self indexOfObjectIdenticalTo:anObject
+           inRange:NSMakeRange(0, [self count])];
+}
+
+- (unsigned int)indexOfObject:(id)anObject inRange:(NSRange)aRange
+{
+    unsigned int index;
+    for (index = 0; index < aRange.length; index++)
+       if ([anObject isEqual:[self objectAtIndex:aRange.location+index]])
+           return aRange.location+index;
+    return NSNotFound;
+}
+
+- (unsigned int)indexOfObjectIdenticalTo:(id)anObject inRange:(NSRange)aRange
+{
+    unsigned int index;
+    for (index = 0; index < aRange.length; index++)
+       if (anObject == [self objectAtIndex:aRange.location+index])
+           return index;
+    return NSNotFound;
+}
+
+- (id)lastObject
+{
+    int count = [self count];
+
+    return count ? [self objectAtIndex:count - 1] : nil;
+}
+
+- (id)objectAtIndex:(unsigned int)index
+{
+    [self subclassResponsibility:_cmd];
+    return self;
+}
+
+- (void)getObjects:(id *)buffer
+{
+    unsigned i, count = [self count];
+    
+    for (i = 0; i < count; i++) {
+        buffer[i] = [self objectAtIndex: i];
+    }
+}
+- (void)getObjects:(id *)buffer range:(NSRange)range
+{
+    /* naive implementation, to be fixed ... */
+    return [[self subarrayWithRange:range] getObjects:buffer];
+}
+
+- (NSEnumerator *)objectEnumerator
+{
+    return AUTORELEASE([[_NSArrayEnumerator alloc]
+                           initWithArray:self reverse:NO]);
+}
+
+- (NSEnumerator *)reverseObjectEnumerator
+{
+    return AUTORELEASE([[_NSArrayEnumerator alloc]
+                           initWithArray:self reverse:YES]);
+}
+
+/* Sending Messages to Elements */
+
+- (void)makeObjectsPerformSelector:(SEL)aSelector
+{
+    unsigned int index, count = [self count];
+    for (index = 0; index < count; index++)
+       [[self objectAtIndex:index] performSelector:aSelector];
+}
+
+- (void)makeObjectsPerformSelector:(SEL)aSelector withObject:(id)anObject
+{
+    unsigned int index, count = [self count];
+    for (index = 0; index < count; index++)
+       [[self objectAtIndex:index]
+             performSelector:aSelector withObject:anObject];
+}
+
+/* Obsolete methods */
+- (void)makeObjectsPerform:(SEL)aSelector
+{
+    unsigned int index, count = [self count];
+    for (index = 0; index < count; index++)
+       [[self objectAtIndex:index] performSelector:aSelector];
+}
+
+- (void)makeObjectsPerform:(SEL)aSelector withObject:(id)anObject
+{
+    unsigned int index, count = [self count];
+    for (index = 0; index < count; index++)
+       [[self objectAtIndex:index]
+             performSelector:aSelector withObject:anObject];
+}
+
+/* Comparing Arrays */
+
+- (id)firstObjectCommonWithArray:(NSArray*)otherArray
+{
+    unsigned int index, count = [self count];
+    for (index = 0; index < count; index++) {
+       id object = [self objectAtIndex:index];
+       if ([otherArray containsObject:object])
+           return object;
+    }
+    return nil;
+}
+
+- (BOOL)isEqualToArray:(NSArray*)otherArray
+{
+    unsigned int index, count;
+    if( otherArray == self )
+       return YES;
+    if ([otherArray count] != (count = [self count]))
+       return NO;
+    for (index = 0; index < count; index++) {
+        register id o1, o2;
+        o1 = [self objectAtIndex:index];
+        o2 = [otherArray objectAtIndex:index];
+       if (![o1 isEqual:o2])
+           return NO;
+    }
+    return YES;
+}
+
+/* Deriving New Arrays */
+
+- (NSArray *)sortedArrayUsingFunction:
+           (int(*)(id element1, id element2, void *userData))comparator
+    context:(void *)context
+{
+    NSMutableArray *sortedArray;
+    NSArray        *result;
+    
+    sortedArray = [self mutableCopy];
+    [sortedArray sortUsingFunction:comparator context:context];
+    result = [sortedArray copy];
+    RELEASE(sortedArray);
+    return AUTORELEASE(result);
+}
+
+static int compare(id elem1, id elem2, void* comparator)
+{
+    return (int)(long)[elem1 performSelector:comparator withObject:elem2];
+}
+
+- (NSArray*)sortedArrayUsingSelector:(SEL)comparator
+    // Returns an array listing the receiver's elements in ascending order,
+    // as determined by the comparison method specified by the selector 
+    // comparator.
+{
+    return [self sortedArrayUsingFunction:compare context:(void*)comparator];
+}
+
+- (NSArray*)subarrayWithRange:(NSRange)range
+{
+    id array;
+    unsigned int index;
+    id *objects;
+
+    objects = Malloc(sizeof(id) * range.length);
+    {
+        for (index = 0; index < range.length; index++)
+            objects[index] = [self objectAtIndex:range.location+index];
+
+        if (NSArrayClass == Nil)
+            NSArrayClass = [NSArray class];
+           
+        array = AUTORELEASE([[NSArrayClass alloc]
+                                      initWithObjects:objects count:range.length]);
+    }
+    lfFree(objects);
+    return array;
+}
+    // Returns an array containing the receiver's elements
+    // that fall within the limits specified by range.
+
+/* Joining String Elements */
+
+- (NSString*)componentsJoinedByString:(NSString*)separator
+{
+    unsigned int index, count = [self count];
+
+    if (!separator)
+       separator = @"";
+
+    if (count > 0) {
+       NSMutableString* string = [NSMutableString new];
+        id elem;
+        SEL sel;
+        IMP imp;
+       CREATE_AUTORELEASE_POOL(pool);
+
+       elem = [self objectAtIndex:0];
+       sel = @selector(appendString:);
+       imp = [string methodForSelector:sel];
+
+       if (![elem isKindOfClass:[NSString class]])
+           elem = [elem description];
+
+       (*imp)(string, sel, elem);
+
+       for (index = 1; index < count; index++) {
+           elem = [self objectAtIndex:index];
+           if (![elem isKindOfClass:[NSString class]])
+               elem = [elem description];
+
+           (*imp)(string, sel, separator);
+           (*imp)(string, sel, elem);
+       }
+       RELEASE(pool);
+       return AUTORELEASE(string);
+    }
+
+    return @"";
+}
+
+/* Creating a String Description of the Array */
+
+- (NSString *)propertyListStringWithLocale:(NSDictionary *)_locale
+  indent:(unsigned int)_indent
+{
+    return [self descriptionWithLocale:_locale indent:_indent];
+}
+
+- (NSString*)descriptionWithLocale:(NSDictionary*)locale
+   indent:(unsigned int)indent;
+{
+    NSMutableString* description = [NSMutableString stringWithCString:"(\n"];
+    unsigned int indent1 = indent + 4;
+    NSMutableString* indentation
+           = [NSString stringWithFormat:
+                       [NSString stringWithFormat:@"%%%dc", indent1], ' '];
+    unsigned int count = [self count];
+    SEL sel = @selector(appendString:);
+    IMP imp = [description methodForSelector:sel];
+
+    if(count) {
+       id object;
+       id stringRepresentation;
+       unsigned int index;
+       CREATE_AUTORELEASE_POOL(pool);
+
+       object = [self objectAtIndex:0];
+        stringRepresentation = [object propertyListStringWithLocale:locale
+                                       indent:indent1];
+
+       (*imp)(description, sel, indentation);
+       (*imp)(description, sel, stringRepresentation);
+
+       for (index = 1; index < count; index++) {
+           object = [self objectAtIndex:index];
+
+            stringRepresentation = [object propertyListStringWithLocale:locale
+                                           indent:indent1];
+            
+           (*imp)(description, sel, @",\n");
+           (*imp)(description, sel, indentation);
+           (*imp)(description, sel, stringRepresentation);
+       }
+       RELEASE(pool);
+    }
+
+    (*imp)(description, sel, indent
+           ? [NSMutableString stringWithFormat:
+                       [NSString stringWithFormat:@"\n%%%dc)", indent], ' ']
+           : [NSMutableString stringWithCString:"\n)"]);
+    return description;
+}
+
+- (NSString*)descriptionWithLocale:(NSDictionary*)locale
+{
+    return [self descriptionWithLocale:locale indent:0];
+}
+
+- (NSString*)description
+{
+    return [self descriptionWithLocale:nil indent:0];
+}
+
+- (NSString*)stringRepresentation
+{
+    return [self descriptionWithLocale:nil indent:0];
+}
+
+/* Write plist to file */
+
+- (BOOL)writeToFile:(NSString*)fileName atomically:(BOOL)flag
+{
+    volatile BOOL success = NO;
+    
+    TRY {
+       id content = [self description];
+       success = [content writeToFile:fileName atomically:flag];
+    } END_TRY
+    OTHERWISE {
+       success = NO;
+    } END_CATCH
+    
+    return success;
+}
+
+/* From adopted/inherited protocols */
+
+- (unsigned)hash
+{
+    return [self count];
+}
+
+- (BOOL)isEqual:(id)anObject
+{
+    if (NSArrayClass == Nil)
+        NSArrayClass = [NSArray class];
+    
+    if (![anObject isKindOfClass:NSArrayClass])
+        return NO;
+    return [self isEqualToArray:anObject];
+}
+
+/* Copying */
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    if (NSShouldRetainWithZone(self, zone))
+       return RETAIN(self);
+    else {
+        if (NSArrayClass == Nil)
+            NSArrayClass = [NSArray class];
+        
+       return [[NSArrayClass allocWithZone:zone]
+                              initWithArray:self copyItems:NO];
+    }
+}
+
+- (id)mutableCopyWithZone:(NSZone*)zone
+{
+    if (NSMutableArrayClass == Nil)
+        NSMutableArrayClass = [NSMutableArray class];
+    return [[NSMutableArrayClass alloc] initWithArray:self];
+}
+
+/* Encoding */
+
+- (Class)classForCoder
+{
+    if (NSArrayClass == Nil)
+        NSArrayClass = [NSArray class];
+    return NSArrayClass;
+}
+
+- (void)encodeWithCoder:(NSCoder*)aCoder
+{
+    IMP imp = [aCoder methodForSelector:@selector(encodeObject:)];
+    int i, count = [self count];
+
+    [aCoder encodeValueOfObjCType:@encode(int) at:&count];
+    for(i = 0; i < count; i++)
+       (*imp)(aCoder, @selector(encodeObject:), [self objectAtIndex:i]);
+}
+
+- (id)initWithCoder:(NSCoder*)aDecoder
+{
+    IMP imp = [aDecoder methodForSelector:@selector(decodeObject)];
+    int i, count;
+
+    [aDecoder decodeValueOfObjCType:@encode(int) at:&count];
+    if (count > 0) {
+        id* objects;
+        objects = Malloc(sizeof(id) * count);
+        {
+            for(i = 0; i < count; i++)
+                objects[i] = (*imp)(aDecoder, @selector(decodeObject));
+
+            self = [self initWithObjects:objects count:count];
+        }
+        lfFree(objects);
+    }
+    else {
+        self = [self init]; // empty array
+    }
+    return self;
+}
+
+@end /* NSArray */
+
+/*
+ * Extensions to NSArray
+ */
+
+@implementation NSArray (NSArrayExtensions)
+
+/* Sending Messages to Elements */
+
+- (void)makeObjectsPerform:(SEL)aSelector
+  withObject:(id)anObject1 withObject:(id)anObject2
+{
+    unsigned int index, count = [self count];
+    for (index = 0; index < count; index++)
+       [[self objectAtIndex:index]
+         performSelector:aSelector withObject:anObject1 withObject:anObject2];
+}
+
+/* Deriving New Arrays */
+
+- (NSArray *)map:(SEL)aSelector
+{
+    unsigned int index, count = [self count];
+    id array;
+    if (NSMutableArrayClass == Nil)
+        NSMutableArrayClass = [NSMutableArray class];
+    array = [NSMutableArrayClass arrayWithCapacity:count];
+    
+    for (index = 0; index < count; index++) {
+       [array insertObject:[[self objectAtIndex:index]
+                               performSelector:aSelector]
+              atIndex:index];
+    }
+    return array;
+}
+
+- (NSArray *)map:(SEL)aSelector with:(id)anObject
+{
+    unsigned int index, count = [self count];
+    id array;
+    if (NSMutableArrayClass == Nil)
+        NSMutableArrayClass = [NSMutableArray class];
+    array = [NSMutableArrayClass arrayWithCapacity:count];
+    for (index = 0; index < count; index++) {
+       [array insertObject:[[self objectAtIndex:index]
+                               performSelector:aSelector withObject:anObject]
+               atIndex:index];
+    }
+    return array;
+}
+
+- (NSArray *)map:(SEL)aSelector with:(id)anObject with:(id)otherObject;
+{
+    unsigned int index, count = [self count];
+    id array;
+    if (NSMutableArrayClass == Nil)
+        NSMutableArrayClass = [NSMutableArray class];
+    array = [NSMutableArrayClass arrayWithCapacity:count];
+    for (index = 0; index < count; index++) {
+       [array insertObject:[[self objectAtIndex:index]
+         performSelector:aSelector withObject:anObject withObject:otherObject]
+               atIndex:index];
+    }
+    return array;
+}
+
+- (NSArray *)arrayWithObjectsThat:(BOOL(*)(id anObject))comparator;
+    // Returns an array listing the receiver's elements for that comparator
+    // function returns YES
+{
+    unsigned i, m, n = [self count];
+    id *objects;
+    id array;
+
+    objects = Malloc(sizeof(id) * n);
+    {
+        for (i = m = 0; i < n; i++) {
+            id obj = [self objectAtIndex:i];
+            if (comparator(obj))
+                objects[m++] = obj;
+        }
+        
+        array = AUTORELEASE([[[self class] alloc] initWithObjects:objects count:m]);
+    }
+    lfFree(objects);
+    return array;
+}
+
+- (NSArray *)map:(id(*)(id anObject))function
+  objectsThat:(BOOL(*)(id anObject))comparator;
+    // Returns an array listing the objects returned by function applied to
+    // objects for that comparator returns YES
+{
+    unsigned i, m, n = [self count];
+    id *objects;
+    id array;
+
+    objects = Malloc(sizeof(id) * n);
+    {
+        for (i = m = 0; i < n; i++) {
+            id obj = [self objectAtIndex:i];
+            if (comparator(obj))
+                objects[m++] = function(obj);
+        }
+    
+        array = AUTORELEASE([[[self class] alloc] initWithObjects:objects count:m]);
+    }
+    lfFree(objects);
+    return array;
+}
+
+@end
+
+/*
+ * NSMutableArray class
+ *
+ * primary methods are
+ *   init
+ *   initWithCapacity:
+ *   initWithObjects:count:
+ *   dealloc
+ *   count
+ *   objectAtIndex:
+ *   addObject:
+ *   replaceObjectAtIndex:withObject:
+ *   insertObject:atIndex:
+ *   removeObjectAtIndex:
+ */
+
+@implementation NSMutableArray
+
++ (id)arrayWithContentsOfFile:(NSString *)fileName
+{
+    id array;
+    
+    if ((array = [super arrayWithContentsOfFile:fileName])) {
+        if (NSMutableArrayClass == Nil)
+            NSMutableArrayClass = [NSMutableArray class];
+        
+        if (![array isKindOfClass:NSMutableArrayClass]) {
+            array = [[NSMutableArrayClass alloc] initWithArray:array];
+            array = AUTORELEASE(array);
+        }
+    }
+    return array;
+}
+
+/* Creating and Initializing an NSMutableArray */
+
++ (id)allocWithZone:(NSZone*)zone
+{
+    static Class NSConcreteMutableArrayClass = Nil;
+
+    if (NSMutableArrayClass == Nil)
+        NSMutableArrayClass = [NSMutableArray class];
+    if (NSConcreteMutableArrayClass == Nil)
+        NSConcreteMutableArrayClass = [NSConcreteMutableArray class];
+    
+    return NSAllocateObject( (self == NSMutableArrayClass) ? 
+                             NSConcreteMutableArrayClass : self, 0, zone);
+}
+
++ (id)arrayWithCapacity:(unsigned int)aNumItems
+{
+    return AUTORELEASE([[self alloc] initWithCapacity:aNumItems]);
+}
+
+- (id)init
+{
+    return [self initWithCapacity:0];
+}
+
+- (id)initWithCapacity:(unsigned int)aNumItems
+{
+    [self subclassResponsibility:_cmd];
+    return self;
+}
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    if (NSArrayClass == Nil)
+        NSArrayClass = [NSArray class];
+    return [[NSArrayClass alloc] initWithArray:self copyItems:YES];
+}
+
+/* Adding Objects */
+
+- (void)addObject:(id)anObject
+{
+    [self insertObject:anObject atIndex:[self count]];
+}
+
+- (void)addObjectsFromArray:(NSArray*)anotherArray
+{
+    unsigned int i, j, n;
+    n = [anotherArray count];
+    for (i = 0, j = [self count]; i < n; i++)
+       [self insertObject:[anotherArray objectAtIndex:i] atIndex:j++];
+}
+
+- (void)insertObject:(id)anObject atIndex:(unsigned int)index
+{
+    [self subclassResponsibility:_cmd];
+}
+
+/* Removing Objects */
+
+- (void)removeAllObjects
+{
+    int count = [self count];
+    while (--count >= 0)
+       [self removeObjectAtIndex:count];
+}
+
+- (void)removeLastObject
+{
+    [self removeObjectAtIndex:[self count]-1];
+}
+
+- (void)removeObject:(id)anObject
+{
+    unsigned int i, n;
+    n = [self count];
+    for (i = 0; i < n; i++) {
+       id obj = [self objectAtIndex:i];
+       if ([obj isEqual:anObject]) {
+           [self removeObjectAtIndex:i];
+           n--; i--;
+       }
+    }
+}
+
+- (void)removeObjectAtIndex:(unsigned int)index
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (void)removeObjectIdenticalTo:(id)anObject
+{
+    unsigned int i, n;
+    i = n = [self count];
+    for (i = 0; i < n; i++) {
+       id obj = [self objectAtIndex:i];
+       if (obj == anObject) {
+           [self removeObjectAtIndex:i];
+           n--; i--;
+       }
+    }
+}
+
+static int __cmp_unsigned_ints(unsigned int* i1, unsigned int* i2)
+{
+    return (*i1 == *i2) ? 0 : ((*i1 < *i2) ? -1 : +1);
+}
+
+- (void)removeObjectsFromIndices:(unsigned int*)indices
+  numIndices:(unsigned int)count;
+{
+    unsigned int *indexes;
+    int i;
+    
+    if (!count)
+       return;
+    
+    indexes = Malloc(count * sizeof(unsigned int));
+    {
+        memcpy(indexes, indices, count * sizeof(unsigned int));
+        qsort(indexes, count, sizeof(unsigned int),
+              (int(*)(const void *, const void*))__cmp_unsigned_ints);
+               
+        for (i = count - 1; i >= 0; i++)
+            [self removeObjectAtIndex:indexes[i]];
+    }
+    lfFree(indexes);
+}
+
+- (void)removeObjectsInArray:(NSArray*)otherArray
+{
+    unsigned int i, n = [otherArray count];
+    for (i = 0; i < n; i++)
+       [self removeObject:[otherArray objectAtIndex:i]];
+}
+
+- (void)removeObject:(id)anObject inRange:(NSRange)aRange
+{
+    unsigned int index;
+    for (index = aRange.location-1; index >= aRange.location; index--)
+       if ([anObject isEqual:[self objectAtIndex:index+aRange.location]])
+           [self removeObjectAtIndex:index+aRange.location];
+}
+
+- (void)removeObjectIdenticalTo:(id)anObject inRange:(NSRange)aRange
+{
+    unsigned int index;
+    for (index = aRange.location-1; index >= aRange.location; index--)
+       if (anObject == [self objectAtIndex:index+aRange.location])
+           [self removeObjectAtIndex:index+aRange.location];
+}
+
+- (void)removeObjectsInRange:(NSRange)aRange
+{
+    unsigned int index;
+    for (index = aRange.location-1; index >= aRange.location; index--)
+       [self removeObjectAtIndex:index+aRange.location];
+}
+
+/* Replacing Objects */
+
+- (void)replaceObjectAtIndex:(unsigned int)index  withObject:(id)anObject
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (void)replaceObjectsInRange:(NSRange)rRange
+  withObjectsFromArray:(NSArray*)anArray
+{
+    [self replaceObjectsInRange:rRange
+       withObjectsFromArray:anArray
+       range:NSMakeRange(0, [anArray count])];
+}
+
+- (void)replaceObjectsInRange:(NSRange)rRange
+  withObjectsFromArray:(NSArray*)anArray range:(NSRange)aRange
+{
+    unsigned int index;
+    [self removeObjectsInRange:rRange];
+    for (index = 0; index < aRange.length; index++)
+       [self insertObject:[anArray objectAtIndex:aRange.location+index]
+           atIndex:rRange.location+index];
+}
+
+- (void)setArray:(NSArray*)otherArray
+{
+    [self removeAllObjects];
+    [self addObjectsFromArray:otherArray];
+}
+
+- (void)sortUsingFunction:
+  (int(*)(id element1, id element2, void *userData))comparator
+  context:(void*)context
+{
+    /* 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)
+    register int c,d, stride;
+    BOOL found;
+    int  count;
+    id   (*objAtIdx)(id, SEL, unsigned int);
+    
+    if ((count = [self count]) < 2)
+        return;
+    
+    objAtIdx = (void *)[self methodForSelector:@selector(objectAtIndex:)];
+    
+    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
+               register id a =
+                    objAtIdx(self, @selector(objectAtIndex:), d + stride);
+               register id b =
+                    objAtIdx(self, @selector(objectAtIndex:), d);
+                
+               if ((*comparator)(a, b, context) == NSOrderedAscending) {
+#if !LIB_FOUNDATION_BOEHM_GC
+                    [a retain];
+                    [b retain];
+#endif
+                    
+                   [self replaceObjectAtIndex:(d + stride) withObject:b];
+                   [self replaceObjectAtIndex:d            withObject:a];
+                   d -= stride;                // jump by stride factor
+                    
+#if !LIB_FOUNDATION_BOEHM_GC
+                    [a release];
+                    [b release];
+#endif
+               }
+               else
+                    found = YES;
+           }
+       }
+    }
+}
+
+static int selector_compare(id elem1, id elem2, void* comparator)
+{
+    return (int)(long)[elem1 performSelector:(SEL)comparator withObject:elem2];
+}
+
+- (void)sortUsingSelector:(SEL)comparator
+{
+    [self sortUsingFunction:selector_compare context:(void*)comparator];
+}
+
+/* Encoding */
+- (Class)classForCoder
+{
+    if (NSMutableArrayClass == Nil)
+        NSMutableArrayClass = [NSMutableArray class];
+    return NSMutableArrayClass;
+}
+
+@end /* NSMutableArray */
+
+/*
+ * Extensions to NSArray
+ */
+
+@implementation NSMutableArray (NSMutableArrayExtensions)
+
+- (void)removeObjectsFrom:(unsigned int)index count:(unsigned int)count
+{
+    if (count) {
+       while (count--)
+       [self removeObjectAtIndex:index+count];
+    }
+}
+
+- (void)removeObjectsThat:(BOOL(*)(id anObject))comparator
+{
+    unsigned int index, count = [self count];
+    for (index = 0; index < count; index++)
+       if (comparator([self objectAtIndex:index])) {
+           [self removeObjectAtIndex:index];
+           index--; count--;
+       }
+}
+
+@end /* NSMutableArray(NSMutableArrayExtensions) */
+
+/*
+ * NSArrayEnumerator class
+ */
+
+@implementation _NSArrayEnumerator 
+
+- (id)initWithArray:(NSArray*)anArray reverse:(BOOL)isReverse
+{
+    unsigned count = [anArray count];
+    
+    self->reverse = isReverse;
+    self->array = RETAIN(anArray);
+    self->index = (reverse)
+        ? (count ? count - 1 : NSNotFound)
+        : (count ? 0 : NSNotFound);
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(self->array);
+    [super dealloc];
+}
+
+- (id)nextObject
+{
+    id object;
+
+    NSAssert(array, @"Invalid Array enumerator");
+    if (self->index == NSNotFound)
+       return nil;
+
+    object = [self->array objectAtIndex:index];
+    if (self->reverse) {
+        if (self->index == 0)
+            self->index = NSNotFound;
+        else
+            self->index--;
+    } else {
+        self->index++;
+        if (self->index >= [array count])
+            self->index = NSNotFound;
+    }
+    
+    return object;
+}
+
+@end /* _NSArrayEnumerator */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSAttributedString.h b/libFoundation/Foundation/NSAttributedString.h
new file mode 100644 (file)
index 0000000..e935026
--- /dev/null
@@ -0,0 +1,38 @@
+/* 
+   NSAttributedString.h
+
+   Copyright (C) 2002 Helge Hess.
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@skyrix.com>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSAttributedString_h__
+#define __NSAttributedString_h__
+
+/* not yet implemented, but required to compile some third party stuff .. */
+
+#include <Foundation/NSObject.h>
+
+@interface NSAttributedString : NSObject
+@end
+
+@interface NSMutableAttributedString : NSAttributedString
+@end
+
+#endif /* NSAttributedString */
diff --git a/libFoundation/Foundation/NSAttributedString.m b/libFoundation/Foundation/NSAttributedString.m
new file mode 100644 (file)
index 0000000..100a305
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+   NSAttributedString.m
+
+   Copyright (C) 2002 Helge Hess.
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@skyrix.com>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+/* not yet implemented, but required to compile some third party stuff .. */
+
+#include <Foundation/NSAttributedString.h>
+
+@implementation NSAttributedString
+@end
+
+@implementation NSMutableAttributedString
+@end
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSAutoreleasePool.h b/libFoundation/Foundation/NSAutoreleasePool.h
new file mode 100644 (file)
index 0000000..badecc8
--- /dev/null
@@ -0,0 +1,115 @@
+/* 
+   NSAutoreleasePool.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSAutoreleasePool_h__
+#define __NSAutoreleasePool_h__
+
+#include <Foundation/NSObject.h>
+
+typedef struct __NSAutoreleasePoolChunk {
+    int size;
+    int used;
+    struct __NSAutoreleasePoolChunk* next;
+    id objects[0];
+} NSAutoreleasePoolChunk;
+
+@interface NSAutoreleasePool : NSObject
+{
+@protected
+    NSAutoreleasePool      *parentPool;    // next pool up on stack 
+    int                    countOfObjects; // objects in pool
+    NSAutoreleasePoolChunk *firstChunk;           // first chunk of objects
+    NSAutoreleasePoolChunk *currentChunk;  // current chunk to add in
+    id                     ownerThread;    // thread that owns the pool
+}
+
+/* Class Initialization */
++ (void)taskNowMultiThreaded:notification;
+
+/* Instance initialization */
+- (id)init;
+
+/* Instance deallocation */
+- (void)dealloc;
+
+/* Notes that anObject should be released when the pool 
+   at the current top of the stack is freed */
++ (void)addObject:anObject;
+
+/* Notes that anObject must be released when pool is freed */
+- (void)addObject:anObject;
+
+/* Default pool */
++ (id)defaultPool;
+
+/*
+ * METHODS FOR DEBUGGING
+ */
+
+// Counts how many times anObject will receive 
+// -release due to all NSAutoreleasePools in current thread
++ (unsigned)autoreleaseCountForObject:anObject;
+
+// Counts how many times anObject will receive -release due to this pool
+- (unsigned)autoreleaseCountForObject:anObject;
+
+/* 
+ * When enabled, -release and -autorelease calls are checking whether 
+ * this object has been released too many times. This is done by searching 
+ * all the pools, and makes programs run very slowly; It is off by default 
+ */
++ (void)enableDoubleReleaseCheck:(BOOL)enable;
+        
+// When disabled, nothing added to pools is really released; 
+// By default is enabled
++ (void)enableRelease:(BOOL)enable;
+
+// When enables call -trash on add if countToBeReleased % trashLimit = 0
++ (void)setPoolCountThreshhold:(unsigned int)trash;
+
+// Called on exceding trashLimit
+- (id)trash;
+
+@end
+
+/*
+ * Class that handles C pointers release sending them Free()
+ */
+
+@interface NSAutoreleasedPointer : NSObject
+{
+    void *theAddress;
+}
++ (id)autoreleasePointer:(void*)address;
+- (id)initWithAddress:(void*)address;
+@end
+
+#endif /* __NSAutoreleasePool_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSAutoreleasePool.m b/libFoundation/Foundation/NSAutoreleasePool.m
new file mode 100644 (file)
index 0000000..9d9d437
--- /dev/null
@@ -0,0 +1,506 @@
+/* 
+   NSAutoreleasePool.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/NSThread.h>
+#include <Foundation/NSLock.h>
+
+#include <Foundation/NSException.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+#include "PrivateThreadData.h"
+
+//#define LOG_RELEASE       1
+//#define LOG_RELEASE_COUNT 1
+
+@implementation NSAutoreleasePool
+
+/* 
+ * Autorelease default parameters
+ */
+
+enum { CHUNK_SIZE = 1024 };
+
+/*
+ * Static variables
+ */
+
+// default pool (this should be per thread variable)
+static NSAutoreleasePool* defaultPool = nil;
+static BOOL isMultithreaded = NO;
+
+// call trash when adding object multiple of non 0 trashLimit
+static unsigned        trashLimit = 0;
+
+// really send release to objects in pools
+BOOL __autoreleaseEnableRelease = YES;
+
+// checks at add time if object is too many times in autorelease pools
+BOOL __autoreleaseEnableCheck   = NO;
+BOOL __autoreleaseEnableWarning = YES;
+
+/* 
+ * Instance initialization 
+ */
+
++ (void)taskNowMultiThreaded:notification
+{
+    NSThread* thread = [NSThread currentThread];
+    PrivateThreadData* threadData = [thread _privateThreadData];
+    NSAutoreleasePool* pool;
+    
+    for (pool = defaultPool; pool; pool = pool->parentPool)
+       pool->ownerThread = thread;
+    
+    [threadData setThreadDefaultAutoreleasePool:defaultPool];
+    defaultPool = nil;
+    isMultithreaded = YES;
+}
+
+- (id)init
+{
+    if (isMultithreaded) {
+       PrivateThreadData* threadData;
+
+       ownerThread = [NSThread currentThread];
+       threadData = [ownerThread _privateThreadData];
+       parentPool = [threadData threadDefaultAutoreleasePool];
+       [threadData setThreadDefaultAutoreleasePool:self];
+    }
+    else {
+       parentPool = defaultPool;
+       defaultPool = self;
+       ownerThread = nil;
+    }
+    countOfObjects = 0;
+    firstChunk = currentChunk = NULL;
+    return self;
+}
+
+/* 
+ * Instance deallocation 
+ */
+
+- (void)dealloc
+{
+    int i;
+    NSAutoreleasePoolChunk *ch;
+    NSAutoreleasePool      *pool;
+    PrivateThreadData      *threadData = nil;
+    
+    // What happens if someone pushes a pool in release ?
+    // One idea would be to add a pool in its parent and
+    // to extract if on deallocation but this would be inefficient
+    // Another would be to check again to release child pools after
+    // releasing all the objects in current pool
+    
+    // first release from top of autorelease stack to self
+    while (YES) {
+       if (isMultithreaded) {
+           if (ownerThread != [NSThread currentThread]) {
+               [[[InvalidUseOfMethodException alloc] initWithFormat:
+                   @"cannot release a NSAutoreleasePool in a different "
+                   @"thread than that it was initialized in"] raise];
+           }
+           threadData = [ownerThread _privateThreadData];
+           pool = [threadData threadDefaultAutoreleasePool];
+       }
+       else
+           pool = defaultPool;
+       
+       if (pool != self) {
+#if LOG_RELEASE_COUNT
+           NSLog(@"auto release child pool 0x%08X ..", pool);
+#endif
+           RELEASE(pool);
+           continue;
+       }
+       else
+           break;
+    }
+    
+    // send release to objects in pool
+    if (__autoreleaseEnableRelease)
+    {
+       register SEL   sel       = @selector(release);
+       register Class lastClass = Nil;
+       register IMP   release   = NULL;
+#if LOG_RELEASE
+       FILE *fh;
+       fh = fopen("/temp/autorelease.log", "a+");
+#endif
+       
+       for (ch = firstChunk, i = 0; ch; ch = ch->next)
+           i += ch->used;
+#if LOG_RELEASE
+       fprintf(fh, "releasing %i objects\n", i);
+#endif
+#if LOG_RELEASE_COUNT
+       printf("releasing %i objects\n", i);
+#endif
+       
+       // first empty the pools (this may add new pools)
+       for (ch = firstChunk; ch; ch = ch->next) {
+           for (i = 0; i < ch->used; i++) {
+               // warning: this may add objects in current pool
+               // what happens if someone pushes a pool ?
+               // one idea would be to add a pool in its parent and
+               // to extract if on deallocation but this would be inefficient
+               register id    obj;
+               register Class oc;
+               
+               obj = ch->objects[i];
+               if (obj == NULL) continue;
+               oc  = *(Class *)obj;
+               ch->objects[i] = NULL;
+
+#if LOG_RELEASE
+               fprintf(fh, "%-30s 0x%08X %2i - ",
+                       oc->name, (unsigned)obj, [obj retainCount]);
+#endif
+               
+               if (lastClass != oc) {
+                   lastClass = oc;
+                   release = objc_msg_lookup(obj, sel);
+#if LOG_RELEASE
+                   fprintf(fh, "cache miss");
+#endif
+               }
+#if LOG_RELEASE
+               else
+                   fprintf(fh, "cache hit");
+#endif
+#if LOG_RELEASE
+#if 0
+               if ([obj isKindOfClass:[NSString class]]) {
+                   char buf[202];
+
+                   [obj getCString:buf maxLength:200];
+                   buf[200] = '\0';
+                   fprintf(fh, "%i '%s'", [obj cStringLength], buf);
+               }
+#endif
+               fprintf(fh, "\n");
+#endif
+               
+               release(obj, sel);
+           }
+       }
+#if LOG_RELEASE
+       fclose(fh);
+#endif
+       // now pools are invalid an we should free them 
+       // should we maintain a cache of allocated pools ?
+       for (ch = firstChunk; ch;)
+       {
+           NSAutoreleasePoolChunk* tmp = ch->next;
+           lfFree(ch);
+           ch = tmp;
+       }
+    }
+    
+    // set default pool
+    if (isMultithreaded) {
+       if (!threadData)
+           threadData = [ownerThread _privateThreadData];
+       [threadData setThreadDefaultAutoreleasePool:parentPool];
+    }
+    else
+       defaultPool = parentPool;
+    
+    [super dealloc];
+}
+
+/* 
+ * Notes that aObject should be released when the pool 
+ * at the current top of the stack is freed 
+ * This is called by NSObject -autorelease.
+ */
+
+
+/* 
+ * Notes that aObject must be released when pool is freed 
+ */
+
+inline void NSAutoreleasePool_AddObject(NSAutoreleasePool *self, id aObject)
+{
+    // try to add in current chunk and alloc new chunk if neceessary
+    if (!self->firstChunk ||
+        (self->currentChunk->used >= self->currentChunk->size))
+    {
+       NSAutoreleasePoolChunk* ch;
+       
+       ch = Calloc(sizeof(NSAutoreleasePoolChunk)+CHUNK_SIZE*sizeof(id*), 1);
+       ch->size = CHUNK_SIZE;
+       ch->used = 0;
+       ch->next = NULL;
+       
+       if (!self->firstChunk)
+           self->firstChunk = self->currentChunk = ch;
+       else {
+           self->currentChunk->next = ch, self->currentChunk = ch;
+        }
+    }
+    // add in currentChunk
+    self->currentChunk->objects[(self->currentChunk->used)++] = aObject;
+    self->countOfObjects++;
+    
+    // check threshold
+    if (trashLimit) {
+       if (self->countOfObjects % trashLimit == 0) 
+           [self trash];
+    }
+}
+inline void NSAutoreleasePool_AutoreleaseObject(id aObject)
+{
+    NSAutoreleasePool *pool;
+    
+    pool = isMultithreaded
+       ? [[[NSThread currentThread] _privateThreadData]
+                      threadDefaultAutoreleasePool]
+       : defaultPool;
+    
+#if 0
+    // check if there is a pool in effect
+    if (pool == nil && __autoreleaseEnableWarning) {
+       fprintf(stderr, 
+           "Autorelease[0x%08x] with no pool in effect\n", 
+           (int)aObject);
+    }
+#endif
+    
+    // check if retainCount is Ok
+    if (__autoreleaseEnableCheck) {
+       unsigned int toCome =
+            [[NSAutoreleasePool class] autoreleaseCountForObject:aObject];
+        
+       if (toCome+1 > [aObject retainCount]) {
+           fprintf(stderr, 
+                    "Autorelease[%p<%s>] release check for object %s has %d "
+                    "references and %d pending calls to "
+                    "release in autorelease\n", 
+                    aObject, [NSStringFromClass([aObject class]) cString],
+                    [[aObject description] cString],
+                    [aObject retainCount], toCome);
+           return;
+       }
+    }
+    if (pool)
+        NSAutoreleasePool_AddObject(pool, aObject);
+    else {
+        fprintf(stderr,
+                "called -autorelease on object 0x%08X<%s> with no "
+                "autorelease pool in place, "
+                "will leak that memory !\n",
+                (unsigned int)aObject,
+                (*(struct objc_class **)aObject)->name);
+    }
+}
+
+- (void)addObject:(id)aObject
+{
+    NSAutoreleasePool_AddObject(self, aObject);
+}
+
++ (void)addObject:(id)aObject
+{
+    NSAutoreleasePool_AutoreleaseObject(aObject);
+}
+
+/* 
+ * Default pool 
+ */
+
++ (id)defaultPool
+{
+    return (isMultithreaded 
+       ? [[[NSThread currentThread] _privateThreadData]
+           threadDefaultAutoreleasePool]
+       : defaultPool);
+}
+
+/*
+ * METHODS FOR DEBUGGING
+ */
+
+/* 
+ * Counts how many times aObject willl receive -release due to all 
+ * NSAutoreleasePools 
+ */
+
++ (unsigned)autoreleaseCountForObject:(id)aObject
+{
+    int count = 0;
+    NSAutoreleasePool *pool;
+    for (pool = [self defaultPool]; pool; pool = pool->parentPool) {
+       count += [pool autoreleaseCountForObject:aObject];
+    }
+    return count;
+}
+
+/* 
+ * Counts how many times aObject willl receive -release due to this pool  
+ */
+
+- (unsigned)autoreleaseCountForObject:(id)anObject
+{
+    int i, count = 0;
+    NSAutoreleasePoolChunk*    ch;
+
+    for (ch = firstChunk; ch; ch = ch->next)
+       for (i = 0; i < ch->used; i++)
+           if (ch->objects[i] == anObject)
+               count++;
+    return count;
+}
+
+/*
+ * Counts how many autorelease calls are made in thise pool
+ */
+- (unsigned)autoreleaseCount
+{
+    int i, count = 0;
+    NSAutoreleasePoolChunk*    ch;
+
+    for (ch = firstChunk; ch; ch = ch->next)
+       for (i = 0; i < ch->used; i++)
+           if (ch->objects[i])
+               count++;
+    return count;
+}
+
+/* 
+ * When enabled, -release and -autorelease calls are checking whether 
+ * this object has been released too many times. This is done by searching 
+ * all the pools, and makes programs run very slowly; 
+ * It is off by default 
+ */
+
++ (void)enableDoubleReleaseCheck:(BOOL)enable
+{
+    __autoreleaseEnableCheck = enable;
+}
+
+/* 
+ * When disabled, nothing added to pools is really released; 
+ * By default is enabled 
+ */
+
++ (void)enableRelease:(BOOL)enable
+{
+    __autoreleaseEnableRelease = enable;
+}
+
+/* 
+ * When enables call -trash on add if countToBeReleased % trashLimit = 0 
+ */
+
++ (void)setPoolCountThreshhold:(unsigned int)trash
+{
+    trashLimit = trash;
+}
+
+/* 
+ * Called on exceding trashLimit 
+ */
+
+- (id)trash
+{
+    return self;
+}
+
+@end /* NSAutoreleasePool */
+
+/*
+ * Class that handles C pointers realease sending them Free()
+ */
+
+@implementation NSAutoreleasedPointer
+
+// THREADING
+#define AP_CACHE_SIZE 64
+static NSAutoreleasedPointer *ptrcache[AP_CACHE_SIZE] = {
+    nil, nil, nil, nil, nil, nil, nil, nil,
+    nil, nil, nil, nil, nil, nil, nil, nil,
+    nil, nil, nil, nil, nil, nil, nil, nil,
+    nil, nil, nil, nil, nil, nil, nil, nil,
+    nil, nil, nil, nil, nil, nil, nil, nil,
+    nil, nil, nil, nil, nil, nil, nil, nil,
+    nil, nil, nil, nil, nil, nil, nil, nil,
+    nil, nil, nil, nil, nil, nil, nil, nil,
+};
+
++ (id)autoreleasePointer:(void*)address
+{
+    NSAutoreleasedPointer *tmp;
+    register int i;
+
+    /* first look in cache */
+    for (i = 0, tmp = nil; (i < AP_CACHE_SIZE) && (tmp == nil); i++) {
+        if (ptrcache[i] != nil) {
+            tmp = ptrcache[i];
+            ptrcache[i] = nil;
+        }
+    }
+    
+    /* did not find instance in cache */
+    if (tmp == nil) {
+        tmp = [self alloc];
+    }
+
+    [tmp initWithAddress:address];
+    
+    return AUTORELEASE(tmp);
+}
+
+- (id)initWithAddress:(void*)address
+{
+    self->theAddress = address;
+    return self;
+}
+
+- (void)dealloc
+{
+    register int i;
+    lfFree(self->theAddress);
+    
+    /* place in cache if slot is available */
+    for (i = 0; i < AP_CACHE_SIZE; i++) {
+        if (ptrcache[i] == nil) {
+            ptrcache[i] = self;
+            return;
+        }
+    }
+    
+    /* cache is full, dealloc */
+    [super dealloc];
+}
+
+@end /* NSAutoreleasedPointer */
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSBundle.h b/libFoundation/Foundation/NSBundle.h
new file mode 100644 (file)
index 0000000..66315e7
--- /dev/null
@@ -0,0 +1,112 @@
+/* 
+   NSBundle.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSBundle_h__
+#define __NSBundle_h__
+
+#include <Foundation/NSObject.h>
+#include <Foundation/NSUtilities.h>
+
+@class NSString;
+@class NSArray;
+@class NSDictionary;
+@class NSMutableDictionary;
+
+@interface NSBundle : NSObject
+{
+    NSString            *fullPath;
+    NSDictionary        *infoDictionary;
+    Class               firstLoadedClass;
+    NSMutableDictionary *stringTables;
+    BOOL                codeLoaded;
+}
+
+// Initializing an NSBundle 
+
+- (id)initWithPath:(NSString*)path;
+
+// Getting an NSBundle 
+
++ (NSArray *)allBundles;
++ (NSArray *)allFrameworks;
++ (NSBundle *)bundleForClass:(Class)aClass;
++ (NSBundle *)bundleWithPath:(NSString*)path;
++ (NSBundle *)mainBundle;
+
+// Getting a Bundled Class 
+
+- (Class)classNamed:(NSString *)className;
+- (Class)principalClass;
+
+// loading the bundles executable code
+
+- (BOOL)load;
+
+// Finding a Resource 
+
++ (NSString *)pathForResource:(NSString *)name ofType:(NSString *)ext
+  inDirectories:(NSArray*)directories;
+- (NSString *)pathForResource:(NSString *)name ofType:(NSString *)ext;
+- (NSString *)pathForResource:(NSString *)name ofType:(NSString *)ext
+  inDirectory:(NSString *)bundlePath;
+- (NSString*)pathForResource:(NSString*)name ofType:(NSString*)ext
+  inDirectory:(NSString*)directory
+  forLocalization:(NSString*)localizationName;
+- (NSArray *)pathsForResourcesOfType:(NSString *)extension
+  inDirectory:(NSString *)bundlePath;
+- (NSArray *)pathsForResourcesOfType:(NSString *)extension
+  inDirectory:(NSString *)bundlePath
+  forLocalization:(NSString *)localizationName;
+
+- (NSString *)resourcePath;
+
+// Getting the Bundle Directory 
+
+- (NSString *)bundlePath;
+
+// Getting bundle information
+
+- (NSDictionary *)infoDictionary;
+
+// Managing Localized Resources
+
+- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)value
+  table:(NSString *)tableName;
+- (void)releaseStringtableCache;
+
+// Private methods
++ (NSString *)_fileResourceNamed:(NSString *)fileName
+  extension:(NSString *)extension
+  inDirectory:(NSString *)directoryName;
+
+@end /* NSBundle */
+
+#endif /* __NSBundle_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSBundle.m b/libFoundation/Foundation/NSBundle.m
new file mode 100644 (file)
index 0000000..10fc9a1
--- /dev/null
@@ -0,0 +1,930 @@
+/* 
+   NSBundle.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSBundle.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/NSProcessInfo.h>
+#include <Foundation/NSNotification.h>
+#include <Foundation/NSUserDefaults.h>
+#include <Foundation/NSFileManager.h>
+#include <Foundation/NSPathUtilities.h>
+#include <extensions/objc-runtime.h>
+
+/*
+ * Static class variables
+ */
+
+typedef struct {
+    Class    class;
+    Category *category;
+} LoadingClassCategory;
+
+static NSMapTable           *bundleClasses     = NULL; // class -> bundle mapping
+static NSMapTable           *bundleNames       = NULL; // path  -> bundle mapping
+static NSBundle             *mainBundle        = nil;  // application bundle
+static LoadingClassCategory*load_Classes      = NULL; // used while loading
+static int                  load_classes_size = 0;    // used while loading
+static int                  load_classes_used = 0;    // used while loading
+
+/*
+ * Private API
+ */
+
+@interface NSBundle (PrivateAPI)
+- (NSString*)pathForResource:(NSString*)name ofType:(NSString*)ext
+  inDirectory:(NSString*)directory
+  forLocalizations:(NSArray*)localizationNames;
+@end
+
+/*
+ * NSBundle methods
+ */
+
+@implementation NSBundle
+
+#if WITH_GNUSTEP
+static BOOL useGNUstepEnv = YES;
+#else
+static BOOL useGNUstepEnv = NO;
+#endif
+
+/* Library resource directory */
+
++ (NSArray *)_resourcesSearchPathes {
+    static NSArray *cachedPathes = nil;
+    NSDictionary   *env;
+    NSArray        *searchPaths;
+    NSString       *resourcesPathsString = nil;
+    id             resourcesPaths        = nil;
+    static BOOL isRunning = NO;
+
+    if (isRunning) {
+        fprintf(stderr, "WARNING(%s): nested call to function! (probably "
+                "some libFoundation setup issue)\n",
+                __PRETTY_FUNCTION__);
+        return nil;
+    }
+    
+    if (cachedPathes != nil)
+       return cachedPathes;
+    
+    isRunning = YES;
+    env = [[NSProcessInfo processInfo] environment];
+    
+#if WITH_GNUSTEP
+    {
+       NSMutableArray *ma;
+       id tmp;
+       
+       ma = [NSMutableArray arrayWithCapacity:16];
+       if ((tmp = [env objectForKey:@"GNUSTEP_PATHPREFIX_LIST"]) == nil)
+           tmp = [env objectForKey:@"GNUSTEP_PATHLIST"];
+       tmp = [tmp componentsSeparatedByString:@":"];
+       if ([tmp count] > 0) {
+           NSFileManager *fm;
+           int i;
+           
+           fm = [NSFileManager defaultManager];
+           for (i = 0; i < [tmp count]; i++) {
+               NSString *p;
+               
+               p = [tmp objectAtIndex:i];
+               p = [p stringByAppendingPathComponent:@"Libraries"];
+               p = [p stringByAppendingPathComponent:@"Resources"];
+               p = [p stringByAppendingPathComponent:@"libFoundation"];
+               if ([ma containsObject:p]) continue;
+               
+               [ma addObject:p];
+           }
+       }
+       [ma addObject:@"/usr/local/share/libFoundation"];
+       [ma addObject:@"/usr/share/libFoundation"];
+       
+       searchPaths = ma;
+    }
+#else
+    searchPaths = [NSArray arrayWithObject:@RESOURCES_PATH];
+#endif
+    
+    resourcesPathsString
+        = [env objectForKey:@"LIB_FOUNDATION_RESOURCES_PATH"];
+    if (resourcesPathsString) {
+#if defined(__WIN32__)
+        resourcesPaths=[resourcesPathsString componentsSeparatedByString:@";"];
+#else
+        resourcesPaths=[resourcesPathsString componentsSeparatedByString:@":"];
+#endif
+        resourcesPaths = AUTORELEASE([resourcesPaths mutableCopy]);
+        [resourcesPaths addObjectsFromArray:searchPaths];
+        searchPaths = resourcesPaths;
+    }
+    
+    cachedPathes = [searchPaths copy];
+    isRunning = NO;
+    return cachedPathes;
+}
+
++ (NSString*)_fileResourceNamed:(NSString*)fileName
+  extension:(NSString*)extension
+  inDirectory:(NSString*)directoryName
+{
+    NSFileManager  *fm;
+    int            i, count;
+    NSArray        *searchPaths;
+    
+    searchPaths = [self _resourcesSearchPathes];
+    
+    fm = [NSFileManager defaultManager];
+    for (i = 0, count = [searchPaths count]; i < count; i++) {
+       NSString *fullFilenamePath;
+       NSString *p;
+       
+       p = [searchPaths objectAtIndex:i];
+       p = [p stringByAppendingPathComponent:directoryName];
+       p = [p stringByAppendingPathComponent:fileName];
+       p = [p stringByAppendingPathExtension:extension];
+       
+        fullFilenamePath = [p stringByResolvingSymlinksInPath];
+       if (fullFilenamePath == nil)
+           continue;
+       if ([fullFilenamePath length] == 0)
+           continue;
+       
+       /* found it */
+       if ([fm fileExistsAtPath:fullFilenamePath])
+           return fullFilenamePath;
+    }
+    return nil;
+}
+
+// Bundle initialization
+
++ (void)initialize
+{
+    if (bundleClasses == NULL) {
+        bundleClasses =
+            NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks,
+                             NSNonRetainedObjectMapValueCallBacks, 23);
+    }
+    if (bundleNames == NULL) {
+        bundleNames = NSCreateMapTable(NSObjectMapKeyCallBacks,
+                                       NSNonRetainedObjectMapValueCallBacks, 23);
+    }
+}
+
+// Load info for bundle
+
+- (void)loadInfo
+{
+    NSString *file;
+
+    if (self->infoDictionary)
+        return;
+    
+    if (useGNUstepEnv)
+       file = [self pathForResource:@"Info-gnustep" ofType:@"plist"];
+    else
+       file = [self pathForResource:@"Info" ofType:@"plist"];
+    
+    if (file)
+        infoDictionary = RETAIN([[NSString stringWithContentsOfFile:file] 
+                                    propertyList]);
+    
+    if (infoDictionary == nil)
+        infoDictionary = [[NSDictionary alloc] init];
+}
+
+// Internal code loading
+
+static int debugBundles = -1;
+
+static void load_callback(Class class, Category* category)
+{
+    if (load_classes_used >= load_classes_size) {
+        load_classes_size += 128;
+        load_Classes = Realloc(load_Classes,
+            load_classes_size*sizeof(LoadingClassCategory));
+    }
+    load_Classes[load_classes_used].class    = class;
+    load_Classes[load_classes_used].category = category;
+
+    if (debugBundles == -1) {
+        debugBundles =
+            [[NSUserDefaults standardUserDefaults] boolForKey:@"DebugBundles"]
+            ? 1 : 0;
+    }
+    if (debugBundles) {
+        if (category) {
+            NSLog(@"dynamically loaded category %s(%s)",
+                  class
+                  ? (class->name ? class->name : "Nil")
+                  : (category->class_name ? category->class_name : "<Nil>"),
+                  category->category_name ? category->category_name : "<Nil>");
+            if (class == NULL) {
+                NSLog(@"WARNING: class %s of category %s wasn't resolved !",
+                      category->class_name ? category->class_name : "<Nil>",
+                      category->category_name?category->category_name:"<Nil>");
+            }
+        }
+        else if (class) {
+            NSLog(@"dynamically loaded class %s", class->name);
+        }
+    }
+    load_classes_used++;
+}
+
++ (BOOL)isFlattenedDirLayout 
+{
+    static BOOL  didCheck = NO;
+    static BOOL  isFlattened = NO;
+    NSDictionary *env;
+    id           tmp;
+    
+    if (didCheck) return isFlattened;
+    
+    if (!useGNUstepEnv) {
+       didCheck = YES;
+       isFlattened = YES;
+       return isFlattened;
+    }
+    
+    env = [[NSProcessInfo processInfo] environment];
+    tmp = [env objectForKey:@"GNUSTEP_FLATTENED"];
+    tmp = [tmp lowercaseString];
+    isFlattened = [tmp isEqual:@"yes"] || [tmp isEqual:@"1"];
+    if (!isFlattened) {
+       /* if no GNUstep env is set, assume flattened */
+       if ([[env objectForKey:@"GNUSTEP_SYSTEM_ROOT"] length] == 0)
+           isFlattened = YES;
+    }
+    didCheck = YES;
+    return isFlattened;
+}
+
+- (BOOL)loadCode
+{
+    extern int objc_load_module(const char*, void (*)(Class, Category*));
+    void           *lookupCallback = NULL;
+    int            i;
+    NSFileManager  *fm;
+    NSString       *file;
+    NSString       *rfile;
+    BOOL           status;
+    NSDictionary   *environment;
+    NSString       *tmp;
+    BOOL           isFlattened;
+    NSMutableArray *loadedClasses    = nil;
+    NSMutableArray *loadedCategories = nil;
+    
+    if (self->codeLoaded)
+        return YES;
+    
+    self->codeLoaded = YES;
+    isFlattened = [NSBundle isFlattenedDirLayout];
+    environment = useGNUstepEnv
+       ? [[NSProcessInfo processInfo] environment]
+       : nil;
+    
+    fm = [NSFileManager defaultManager];
+    
+    // Find file to load
+    if ((file = [[self infoDictionary] objectForKey:@"NSExecutable"]) != nil) {
+       if (!useGNUstepEnv || isFlattened) {
+           file = [fullPath stringByAppendingPathComponent:file];
+           if (useGNUstepEnv && ![fm fileExistsAtPath:file]) {
+               /* this happens for combo-bundles in flattened environments */
+               NSString *p;
+               
+               file = nil;
+               if ((p = [self pathForResource:@"Info" ofType:@"plist"])) {
+                   NSDictionary *info;
+                   
+                   info = [[NSDictionary alloc] initWithContentsOfFile:p];
+                   p = [[info objectForKey:@"NSExecutable"] copy];
+                   [info release];
+                   file = [fullPath stringByAppendingPathComponent:p];
+                   [p release];
+               }
+           }
+       }
+       else {
+           NSString *tvar;
+           
+           tvar = [environment objectForKey:@"GNUSTEP_HOST_CPU"];
+           tmp  = [fullPath stringByAppendingPathComponent:tvar];
+           tvar = [environment objectForKey:@"GNUSTEP_HOST_OS"];
+           tmp  = [tmp stringByAppendingPathComponent:tvar];
+           tvar = [environment objectForKey:@"LIBRARY_COMBO"];
+           tmp  = [tmp stringByAppendingPathComponent:tvar];
+           
+           file = [tmp stringByAppendingPathComponent:file];
+       }
+    }
+    else {
+       fprintf(stderr, "has no exe\n");
+       if (!useGNUstepEnv || isFlattened) {
+           tmp = [fullPath lastPathComponent];
+           tmp = [tmp stringByDeletingPathExtension];
+           file = [fullPath stringByAppendingPathComponent:tmp];
+       }
+       else {
+           tmp = [environment objectForKey:@"GNUSTEP_HOST_CPU"];
+           tmp = [fullPath stringByAppendingPathComponent:tmp];
+           tmp = [tmp stringByAppendingPathComponent:
+                          [environment objectForKey:@"GNUSTEP_HOST_OS"]];
+           tmp = [tmp stringByAppendingPathComponent:
+                          [environment objectForKey:@"LIBRARY_COMBO"]];
+           file = [tmp stringByAppendingPathComponent:
+                           [[fullPath lastPathComponent] 
+                                      stringByDeletingPathExtension]];
+       }
+    }
+    
+    rfile = [file stringByResolvingSymlinksInPath];
+    if (rfile != nil) {
+       if (![fm fileExistsAtPath:rfile]) rfile = nil;
+    }
+    if (rfile == nil) {
+        NSLog(@"%@: NSBundle: cannot find executable file %@%s",
+             [[NSProcessInfo processInfo] processName], 
+             file,
+             isFlattened ? " (flattened layout)" : " (combo layout)");
+        return NO;
+    }
+    
+    loadedClasses    = [NSMutableArray arrayWithCapacity:32];
+    loadedCategories = [NSMutableArray arrayWithCapacity:32];
+    
+    // Prepare to keep classes/categories loaded
+    load_classes_size = 128;
+    load_classes_used = 0;
+    load_Classes = Malloc(load_classes_size
+                                * sizeof(LoadingClassCategory));
+    
+    lookupCallback = _objc_lookup_class;
+    _objc_lookup_class = NULL;
+#ifdef __CYGWIN32__
+    file = [@"C:/cygwin" stringByAppendingString:file];
+#if 0
+    file = [[file componentsSeparatedByString:@"/"]
+                 componentsJoinedByString:@"\\"];
+#endif
+#endif
+    status = objc_load_module([file fileSystemRepresentation], load_callback);
+    _objc_lookup_class = lookupCallback;
+    
+    if (status) {
+        firstLoadedClass = Nil;
+        
+        for (i = 0; i < load_classes_used; i++) {
+            // get first class from bundle
+            if (firstLoadedClass == NULL) {
+                if (load_Classes[i].category == NULL)
+                    firstLoadedClass = load_Classes[i].class;
+            }
+            
+            // TODO - call class/category load method
+            
+            // insert in bundle hash
+            if (load_Classes[i].category == NULL)
+                NSMapInsert(bundleClasses, load_Classes[i].class, self);
+            
+            // register for notification
+            if (load_Classes[i].category == NULL) {
+                NSString *className = nil;
+                
+                className = [NSString stringWithCStringNoCopy:
+                                        (char *)(load_Classes[i].class->name)
+                                      freeWhenDone:NO];
+                [loadedClasses addObject:className];
+            }
+            else {
+                NSString *className    = nil;
+                NSString *categoryName = nil;
+
+                if (load_Classes[i].class) {
+                    className = [NSString stringWithCString:(char *)
+                                            (load_Classes[i].class->name)];
+                }
+#if 0 // class of category
+                else {
+                    className = [NSString stringWithCString:
+                                           load_Classes[i].category->class_name];
+                }
+#endif
+                
+                categoryName = [NSString stringWithCString:(char *)
+                                  load_Classes[i].category->category_name];
+
+                if (className) [loadedClasses addObject:className];
+                [loadedCategories addObject:categoryName];
+            }
+        }
+    }
+    
+    lfFree(load_Classes); load_Classes = NULL;
+
+    if (status) {
+      [[NSNotificationCenter defaultCenter] 
+          postNotificationName:@"NSBundleDidLoadNotification"
+          object:self
+          userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
+                                   loadedClasses,    @"NSLoadedClasses",
+                                   loadedCategories, @"NSLoadedCategories",
+                                   nil]];
+    }
+    return status;
+}
+
+- (BOOL)load
+{
+    /* load, as specified in MacOSX-S docs */
+    return [self loadCode];
+}
+
+// Initializing an NSBundle 
+
+static BOOL canReadDirectory(NSString* path)
+{
+    NSFileManager* fileManager = [NSFileManager defaultManager];
+    BOOL isDirectory;
+
+    if (![fileManager fileExistsAtPath:path isDirectory:&isDirectory]
+        || !isDirectory)
+        return NO;
+
+    return [fileManager isReadableFileAtPath:path];
+}
+
+static BOOL canReadFile(NSString *path)
+{
+    NSFileManager* fileManager = [NSFileManager defaultManager];
+
+    return [fileManager isReadableFileAtPath:path];
+}
+
+- (id)initWithPath:(NSString *)path
+{
+    NSBundle *old;
+
+    path = [path stringByResolvingSymlinksInPath];
+    if ((path == nil) || !canReadDirectory(path)) {
+        RELEASE(self);
+        return nil;
+    }
+    
+    old = (NSBundle *)NSMapGet(bundleNames, path);
+    if (old) {
+        (void)AUTORELEASE(self);
+        return RETAIN(old);
+    }
+    
+    NSMapInsert(bundleNames, path, self);
+    self->fullPath = RETAIN(path);
+    return self;
+}
+
+#if 0 /* the thing below can result in a memory leak if -initWithPath:
+         is used in client code ... */
+// TODO - now bundle is not capable of dealloc & code unloading
+
+- (id)retain
+{
+    return self;
+}
+- (id)autorelease
+{
+    return self;
+}
+- (void)release
+{
+}
+- (unsigned int)retainCount
+{
+    return 1;
+}
+#endif
+
+- (void)dealloc
+{
+    NSMapRemove(bundleNames, self->fullPath);
+    RELEASE(self->fullPath);
+    RELEASE(self->infoDictionary);
+    RELEASE(self->stringTables);
+    [super dealloc];
+}
+
+// Getting an NSBundle 
+
++ (NSArray *)allBundles
+{
+    NSMutableArray *bundles = [NSMutableArray arrayWithCapacity:64];
+    NSMapEnumerator e;
+    NSString *key;
+    NSBundle *value;
+
+    e = NSEnumerateMapTable(bundleNames);
+    while (NSNextMapEnumeratorPair(&e, (void**)&key, (void**)&value))
+        [bundles addObject:value];
+
+    return AUTORELEASE([bundles copy]);
+}
++ (NSArray *)allFrameworks
+{
+    return nil;
+}
+
++ (NSBundle *)bundleForClass:(Class)aClass
+{
+    NSBundle *bundle;
+    
+    if ((bundle = (NSBundle *)NSMapGet(bundleClasses, aClass)))
+        return bundle;
+    
+    return [self mainBundle];
+}
+
++ (NSBundle *)bundleWithPath:(NSString *)path
+{
+    if (path) {
+        NSBundle *bundle;
+
+        /* look in cache */
+        if ((bundle = (NSBundle *)NSMapGet(bundleNames, path)))
+            return bundle;
+    }
+    return AUTORELEASE([[self alloc] initWithPath:path]);
+}
+
++ (NSBundle *)mainBundle
+{
+    if (mainBundle == nil) {
+        NSString *path = [[[[NSProcessInfo processInfo] arguments]
+                              objectAtIndex:0]
+                              stringByDeletingLastPathComponent];
+        if ([path isEqual:@""])
+            path = @".";
+#if WITH_GNUSTEP
+        else if (![NSBundle isFlattenedDirLayout]) {
+            /* The path is the complete path to the executable, including the
+               processor, the OS and the library combo. Strip these directories
+               from the main bundle's path. */
+            path = [[[path stringByDeletingLastPathComponent]
+                           stringByDeletingLastPathComponent]
+                           stringByDeletingLastPathComponent];
+        }
+#endif
+        mainBundle = [[NSBundle alloc] initWithPath:path];
+    }
+    return mainBundle;
+}
+
+// Getting a Bundled Class 
+
+- (Class)classNamed:(NSString *)className
+{
+    Class class;
+
+    [self loadCode];
+    
+    class = NSClassFromString(className);
+    if (class != Nil && (NSBundle*)NSMapGet(bundleClasses, class) == self)
+        return class;
+
+    return nil;
+}
+
+- (Class)principalClass
+{
+    NSString *className;
+    Class    class;
+    
+    [self loadCode];
+    
+    className = [[self infoDictionary] objectForKey:@"NSPrincipalClass"];
+    
+    if ((class = NSClassFromString(className)) == Nil)
+        class = firstLoadedClass;
+    
+    if (class) {
+#if DEBUG
+        if (NSMapGet(bundleClasses, class) != self) {
+            NSLog(@"WARNING(%s): principal class %@ of bundle %@ "
+                  @"is not a class of the bundle !",
+                  __PRETTY_FUNCTION__, class, self);
+        }
+#endif
+    }
+    
+    return class;
+}
+
+// Finding a Resource 
+
++ (NSString*)pathForResource:(NSString*)name ofType:(NSString*)ext
+  inDirectories:(NSArray*)directories
+{
+    int i, n;
+    NSString* file;
+    CREATE_AUTORELEASE_POOL(pool);
+
+    if (ext)
+        name = [name stringByAppendingPathExtension:ext];
+    
+    n = [directories count];
+    
+    for (i = 0; i < n; i++) {
+        file = [[directories objectAtIndex:i]
+            stringByAppendingPathComponent:name];
+        if (canReadFile(file))
+            goto found;
+    }
+    
+    file = nil;
+    
+    found:
+    
+    (void)RETAIN(file);
+    RELEASE(pool);
+    
+    return AUTORELEASE(file);
+}
+
+- (NSString*)pathForResource:(NSString*)name ofType:(NSString*)ext
+  inDirectory:(NSString*)directory
+{
+  NSArray *languages = [[NSUserDefaults standardUserDefaults] 
+                                        stringArrayForKey:@"Languages"]; 
+  return [self pathForResource:name ofType:ext inDirectory:directory
+               forLocalizations:languages];
+}
+
+- (NSString*)pathForResource:(NSString*)name ofType:(NSString*)ext
+  inDirectory:(NSString*)directory
+  forLocalization:(NSString*)localizationName
+{
+  NSArray *languages = nil;
+
+  if(localizationName) {
+    languages = [NSArray arrayWithObject:localizationName];
+  }
+  return [self pathForResource:name ofType:ext inDirectory:directory
+              forLocalizations:languages];
+  
+}
+
+- (NSString*)pathForResource:(NSString*)name ofType:(NSString*)ext
+  inDirectory:(NSString*)directory
+  forLocalizations:(NSArray*)localizationNames
+{
+    int i, n;
+    NSString* path;
+    NSString* file;
+    NSMutableArray* languages;
+    CREATE_AUTORELEASE_POOL(pool);
+    
+    // Translate list by adding "lproj" extension
+    // {English, German, ...} to {English.lproj, German.lproj, ...}
+    languages = AUTORELEASE([localizationNames mutableCopy]);
+    if(languages)
+      n = [languages count];
+    else
+      n = 0;
+    for (i = 0; i < n; i++) {
+        file = [[languages objectAtIndex:i] 
+            stringByAppendingPathExtension:@"lproj"];
+        [languages replaceObjectAtIndex:i withObject:file];
+    }
+    
+    // make file name name.ext if extension is present
+    if (ext)
+        name = [name stringByAppendingPathExtension:ext];
+    
+    // look for fullPath/Resources/directory/...
+    path = [fullPath stringByAppendingPathComponent:@"Resources"];
+    if (directory && ![directory isEqualToString:@""])
+        path = [path stringByAppendingPathComponent:directory];
+    if (canReadDirectory(path)) {
+        // check languages
+        for (i = 0; i < n; i++) {
+            file = [[path stringByAppendingPathComponent:
+                [languages objectAtIndex:i]]
+                    stringByAppendingPathComponent:name];
+            if (canReadFile(file))
+                goto found;
+        }
+        // check base
+        file = [path stringByAppendingPathComponent:name];
+        if (canReadFile(file))
+            goto found;
+    }
+    
+    // look for fullPath/directory/...
+    if (directory && ![directory isEqualToString:@""])
+        path = [fullPath stringByAppendingPathComponent:directory];
+    else
+        path = fullPath;
+    if (canReadDirectory(path)) {
+        // check languages
+        for (i = 0; i < n; i++) {
+            file = [[path stringByAppendingPathComponent:
+                [languages objectAtIndex:i]]
+                    stringByAppendingPathComponent:name];
+            if (canReadFile(file))
+                goto found;
+        }
+        // check base
+        file = [path stringByAppendingPathComponent:name];
+        if (canReadFile(file))
+            goto found;
+    }
+
+    file = nil;
+    
+found:
+    
+    (void)RETAIN(file);
+    RELEASE(pool);
+    
+    return AUTORELEASE(file);
+}
+
+- (NSArray *)pathsForResourcesOfType:(NSString *)extension
+  inDirectory:(NSString *)bundlePath
+{
+  return [self pathsForResourcesOfType:extension inDirectory:bundlePath
+               forLocalization:nil];
+}
+
+- (NSArray *)pathsForResourcesOfType:(NSString *)extension
+  inDirectory:(NSString *)bundlePath
+  forLocalization:(NSString *)localizationName
+{
+    NSFileManager  *fm;
+    NSMutableArray *result = nil;
+    NSString       *path, *mainPath;
+    NSEnumerator   *contents;
+
+    fm     = [NSFileManager defaultManager];
+    result = [[NSMutableArray alloc] initWithCapacity:32];
+
+    /* look in bundle/Resources/$bundlePath/name.$extension */
+    mainPath = [self resourcePath];
+    if (bundlePath)
+        mainPath = [mainPath stringByAppendingPathComponent:bundlePath];
+    contents = [[fm directoryContentsAtPath:mainPath] objectEnumerator];
+    while ((path = [contents nextObject])) {
+        if ([[path pathExtension] isEqualToString:extension])
+            [result addObject:path];
+    }
+
+#if 0 // to be completed
+    /* look in bundle/Resources/$bundlePath/$Language.lproj/name.$extension */
+    mainPath = [self resourcePath];
+    if (bundlePath)
+        mainPath = [mainPath stringByAppendingPathComponent:bundlePath];
+    contents = [[fm directoryContentsAtPath:mainPath] objectEnumerator];
+    while ((path = [contents nextObject])) {
+        if ([[path pathExtension] isEqualToString:extension])
+            [result addObject:path];
+    }
+#endif
+
+    /* look in bundle/$bundlePath/name.$extension */
+    mainPath = self->fullPath;
+    if (bundlePath)
+        mainPath = [mainPath stringByAppendingPathComponent:bundlePath];
+    contents = [[fm directoryContentsAtPath:mainPath] objectEnumerator];
+    while ((path = [contents nextObject])) {
+        if ([[path pathExtension] isEqualToString:extension])
+            [result addObject:path];
+    }
+
+#if 0 // to be completed
+    /* look in bundle/$bundlePath/$Language.lproj/name.$extension */
+    mainPath = self->fullPath;
+    if (bundlePath)
+        mainPath = [mainPath stringByAppendingPathComponent:bundlePath];
+    contents = [[fm directoryContentsAtPath:mainPath] objectEnumerator];
+    while ((path = [contents nextObject])) {
+        if ([[path pathExtension] isEqualToString:extension])
+            [result addObject:path];
+    }
+#endif
+    {
+        NSArray *tmp;
+        tmp = [result copy];
+        RELEASE(result); result = nil;
+        return AUTORELEASE(tmp);
+    }
+}
+
+- (NSString*)pathForResource:(NSString*)name ofType:(NSString*)ext
+{
+    return [self pathForResource:name ofType:ext inDirectory:nil];
+}
+
+- (NSString*)resourcePath
+{
+    return [fullPath stringByAppendingPathComponent:@"Resources"];
+}
+
+// Getting bundle information
+
+- (NSDictionary*)infoDictionary
+{
+    [self loadInfo];
+    return infoDictionary;
+}
+
+// Getting the Bundle Directory 
+
+- (NSString*)bundlePath
+{
+    return fullPath;
+}
+
+// Managing Localized Resources
+
+- (NSString*)localizedStringForKey:(NSString*)key value:(NSString*)value
+  table:(NSString*)tableName
+{
+    NSDictionary* table;
+    NSString* string;
+
+    if (!stringTables)
+        stringTables = [NSMutableDictionary new];
+    
+    table = [stringTables objectForKey:tableName];
+    if (!table) {
+        string = [NSString stringWithContentsOfFile:
+                [self pathForResource:tableName ofType:@"strings"]];
+        if (!string)
+                return value;
+        table = [string propertyListFromStringsFileFormat];
+        if (table)
+            [stringTables setObject:table forKey:tableName];
+    }
+
+    string = [table objectForKey:key];
+    if (!string)
+        string = value;
+
+    return string;
+}
+
+- (void)releaseStringtableCache
+{
+    RELEASE(stringTables);
+    stringTables = nil;
+}
+
+- (NSString *)description
+{
+    /* Don't use -[NSString stringWithFormat:] method because it can cause
+       infinite recursion. */
+    char buffer[1024];
+    
+    sprintf (buffer,
+             "<%s %p fullPath: %s infoDictionary: %p loaded=%s>",
+             (char*)object_get_class_name(self),
+             self,
+             fullPath ? [fullPath cString] : "nil",
+             infoDictionary, self->codeLoaded ? "yes" : "no");
+
+    return [NSString stringWithCString:buffer];
+}
+
+@end /* NSBundle */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSByteOrder.h b/libFoundation/Foundation/NSByteOrder.h
new file mode 100644 (file)
index 0000000..7be776c
--- /dev/null
@@ -0,0 +1,44 @@
+/* 
+   NSByteOrder.h
+
+   Copyright (C) 1998 Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess helge@mdlink.de
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSByteOrder_h__
+#define __NSByteOrder_h__
+
+#include <Foundation/NSObject.h>
+
+enum NSByteOrder {
+    NS_UnknownByteOrder,
+    NS_LittleEndian,
+    NS_BigEndian
+};
+
+LF_EXPORT unsigned int NSHostByteOrder(void);
+
+#endif /* __NSByteOrder_h__ */
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSCalendarDate.h b/libFoundation/Foundation/NSCalendarDate.h
new file mode 100644 (file)
index 0000000..6c80aa3
--- /dev/null
@@ -0,0 +1,53 @@
+/* 
+   NSCalendarDate.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Private file used by NSCalendarDate related files.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSCalendarDate_h__
+#define __NSCalendarDate_h__
+
+#include <Foundation/NSDate.h>
+
+@interface NSCalendarDate (NSCalendarDateImplementation)
+
++ (NSString*)descriptionForCalendarDate:(NSCalendarDate*)date
+  withFormat:(NSString*)format
+  timeZoneDetail:(NSTimeZoneDetail*)detail
+  locale:(NSDictionary*)locale;
++ (NSString*)shortDayOfWeek:(int)day;
++ (NSString*)fullDayOfWeek:(int)day;
++ (NSString*)shortMonthOfYear:(int)day;
++ (NSString*)fullMonthOfYear:(int)day;
++ (int)decimalDayOfYear:(int)year month:(int)month day:(int)day;
+
+@end
+
+#endif /* __NSCalendarDate_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSCalendarDate.m b/libFoundation/Foundation/NSCalendarDate.m
new file mode 100644 (file)
index 0000000..2d4c5f5
--- /dev/null
@@ -0,0 +1,915 @@
+/* 
+   NSCalendarDate.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+          Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+          Florin Mihaila <phil@pathcom.com>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSDate.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/NSCoder.h>
+
+#include <extensions/PrintfFormatScanner.h>
+
+#include "NSConcreteDate.h"
+#include "NSCalendarDate.h"
+#include "NSCalendarDateScannerHandler.h"
+#include "NSCalendarDateScanf.h"
+
+#include <math.h>
+
+#define MIN_YEAR 1700
+#define MAX_YEAR 2038
+
+/*
+ * Functions to deal with date conversions (phil & miki)
+ * deal with dates in day:month:year reprezented in int form
+ * as days since year 1st Jan year 1 ac
+ */
+
+static int  AdjustDay(int month, int day, int year);
+static void DecDate(int *month, int *day, int *year);
+static void IncDate(int *month, int *day, int *year);
+static int  nr_nebisect(int a);
+static int  day_in_year(int month, int day, int year);
+static void Date2Long(int theMonth, int theDay, int theYear, long *theDate);
+static void Long2Date(long theDate, int*theMonth, int*theDay, int*theYear);
+static void SubFromDate(int *month, int *day, int *year, int dif);
+static void AddToDate(int *month, int *day, int *year, int dif);
+static void DecDate( int *month, int *day, int *year);
+static void IncDate( int *month, int *day, int *year);
+
+/*
+ * Magic conversion offsets
+ */
+
+#define DATE_OFFSET 730486     /* Number of days from January 1, 1
+                                  to January 1, 2001 */
+#define DAY_OFFSET 0
+
+/*
+ * NSCalendarDate implementation
+ */
+
+/* timeSinceRef is expressed in seconds relative to GMT from the reference day.
+   The timeSinceRef is adjusted to represent this value when a date is created
+   and a time zone is specified. Changing the time zone explicitly does not
+   modify the timeSinceRef value. Only the methods that work with time
+   components should take into consideration the time zone.
+*/
+
+@implementation NSCalendarDate
+
+static NSString* DEFAULT_FORMAT = @"%Y-%m-%d %H:%M:%S %z";
+static NSDictionary* defaultLocaleDictionary = nil;
+
++ (void)initialize
+{
+    id fullMonths[] = {
+       @"January", @"February", @"March", @"April", @"May", @"June", 
+       @"July", @"August", @"September", @"October", @"November", @"December"
+    };
+    id shortMonths[] = {
+       @"Jan", @"Feb", @"Mar", @"Apr", @"May", @"Jun",
+       @"Jul", @"Aug", @"Sep", @"Oct", @"Nov", @"Dec"
+    };
+    id fullDays[] = {
+       @"Sunday", @"Monday", @"Tuesday", @"Wednesday",
+       @"Thursday", @"Friday", @"Saturday"
+    };
+    id shortDays[] = {
+       @"Sun", @"Mon", @"Tue", @"Wed", @"Thu", @"Fri", @"Sat"
+    };
+    defaultLocaleDictionary
+      = RETAIN(([NSDictionary dictionaryWithObjectsAndKeys:
+       @"%a %b %d %H:%M:%S %z %Y", @"NSTimeDateFormatString",
+       [NSArray arrayWithObjects:@"AM", @"PM", nil], @"NSAMPMDesignation",
+       AUTORELEASE([[NSArray alloc] initWithObjects:fullMonths
+                count:sizeof(fullMonths) / sizeof(id)]), @"NSMonthNameArray",
+       AUTORELEASE([[NSArray alloc] initWithObjects:shortMonths
+                count:sizeof(shortMonths) / sizeof(id)]),
+               @"NSShortMonthNameArray",
+       AUTORELEASE([[NSArray alloc] initWithObjects:fullDays
+                count:sizeof(fullDays) / sizeof(id)]), @"NSWeekDayNameArray",
+       AUTORELEASE([[NSArray alloc] initWithObjects:shortDays
+                count:sizeof(shortDays) / sizeof(id)]),
+               @"NSShortWeekDayNameArray",
+               nil]));
+}
+
+/*
+ * Inherited from NSDate cluster
+ */
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    NSCalendarDate* date = [[self class] allocWithZone:zone];
+    
+    date->timeSinceRef   = timeSinceRef;
+    date->timeZoneDetail = RETAIN(timeZoneDetail);
+    date->formatString   = RETAIN(formatString);
+    return date;
+}
+
+- (void)dealloc
+{
+    RELEASE(timeZoneDetail);
+    RELEASE(formatString);
+    [super dealloc];
+}
+
+- (id)initWithTimeIntervalSinceReferenceDate:(NSTimeInterval)seconds
+{
+    [super init];
+    self->timeSinceRef   = seconds;
+    self->timeZoneDetail =
+        (id)[[NSTimeZone localTimeZone] timeZoneForDate:self];
+    self->timeZoneDetail = RETAIN(self->timeZoneDetail);
+    self->formatString = DEFAULT_FORMAT;
+    return self;
+}
+
+- (id)init
+{
+    return [self initWithTimeIntervalSinceReferenceDate:
+                   [NSDate timeIntervalSinceReferenceDate]];
+}
+
+- (void)setTimeIntervalSinceReferenceDate:(NSTimeInterval)seconds
+{
+    self->timeSinceRef = seconds;
+}
+- (NSTimeInterval)timeIntervalSinceReferenceDate
+{
+    return self->timeSinceRef;
+}
+
+- (unsigned)hash
+{
+    return (unsigned)self->timeSinceRef;
+}
+
+- (NSComparisonResult)compare:(NSDate *)other
+{
+    if ([other isKindOfClass:[NSDate class]]) {
+       NSTimeInterval diff
+           = timeSinceRef - [other timeIntervalSinceReferenceDate];
+
+       return (diff < 0 ?
+                 NSOrderedAscending
+               : (diff == 0 ? NSOrderedSame : NSOrderedDescending));
+    }
+    else if (other == nil) {
+       return NSOrderedSame;
+    }
+    
+    NSLog(@"ERROR(%s): Cannot compare NSCalendarDate with %@<%@>",
+         __PRETTY_FUNCTION__, other, NSStringFromClass([other class]));
+    return NSOrderedSame;
+}
+
+/*
+* NSCalendarDate methods
+*/
+
++ (id)calendarDate
+{
+    return AUTORELEASE([[self alloc] init]);
+}
+
++ (id)dateWithYear:(int)year month:(unsigned)month 
+  day:(unsigned)day hour:(unsigned)hour minute:(unsigned)minute 
+  second:(unsigned)second timeZone:(NSTimeZone *)aTimeZone
+{
+    return AUTORELEASE([[self alloc]
+                              initWithYear:year month:month day:day 
+                              hour:hour minute:minute second:second 
+                              timeZone:aTimeZone]); 
+}
+
++ (id)dateWithString:(NSString*)string
+{
+    return AUTORELEASE([[self alloc]
+           initWithString:string calendarFormat:nil locale:nil]);
+}
+
++ (id)dateWithString:(NSString*)string 
+  calendarFormat:(NSString*)format
+{
+    return AUTORELEASE([[self alloc] initWithString:string
+                                     calendarFormat:format locale:nil]);
+}
+
++ (id)dateWithString:(NSString*)string calendarFormat:(NSString*)format
+  locale:(NSDictionary*)locale
+{
+    return AUTORELEASE([[self alloc] initWithString:string
+                                     calendarFormat:format
+                                     locale:locale]);
+}
+
+- (id)initWithYear:(int)year month:(unsigned)month day:(unsigned)day 
+  hour:(unsigned)hour minute:(unsigned)minute second:(unsigned)second 
+  timeZone:(NSTimeZone*)timeZone
+{
+    // hour/minute is in timezone 'timeZone', not reference date
+    long date;
+    
+    if (year == 0) {
+        NSLog(@"ERROR(%s): replacing year 0 with year 2000!", 
+              __PRETTY_FUNCTION__);
+        year = 2000;
+    }
+    else if (year >= MAX_YEAR) {
+        NSLog(@"%s: got out of range year %i (<%i), returning nil!", 
+              __PRETTY_FUNCTION__, year, MAX_YEAR);
+        [self release];
+        return nil;
+    }
+#if DEBUG && 0
+    NSAssert((year < 2101) && (year >= 0), @"year %i ???", year);
+    
+    if ((month < 1) || (month > 12))
+        NSLog(@"WARNING(%s): month is %d", __PRETTY_FUNCTION__, month);
+    if ((day < 1) || (day > 365))
+        NSLog(@"WARNING(%s): day is %d", __PRETTY_FUNCTION__, day);
+#endif
+    
+    Date2Long(month, day, year, &date);
+    if (date == 0) {
+        RELEASE(self);
+        [NSException raise:NSRangeException
+                     format:
+                       @"could not calculate internal datevalue for "
+                       @"year=%i, month=%i, day=%i", year, month, day];
+        return nil;
+    }
+    
+    if (timeZone == nil)
+       timeZone = [NSTimeZone localTimeZone];
+
+    self->timeSinceRef   = ((NSTimeInterval)date - DATE_OFFSET) * 86400 +
+        hour * 3600 + minute * 60 + second;
+    
+    self->timeZoneDetail =  RETAIN([timeZone timeZoneForDate:self]);
+    self->timeSinceRef   -= [self->timeZoneDetail timeZoneSecondsFromGMT];
+    self->formatString   =  DEFAULT_FORMAT;
+    
+    return self;
+}
+
+- (id)initWithString:(NSString*)description
+{
+    return [self initWithString:description
+                calendarFormat:DEFAULT_FORMAT
+                locale:defaultLocaleDictionary];
+}
+
+- (id)initWithString:(NSString*)description calendarFormat:(NSString*)format
+{
+    return [self initWithString:description
+                calendarFormat:format
+                locale:defaultLocaleDictionary];
+}
+
+- (id)initWithString:(NSString*)description
+  calendarFormat:(NSString*)format
+  locale:(NSDictionary*)locale
+{
+    CREATE_AUTORELEASE_POOL(pool);
+    {
+        id formatScanner;
+        formatScanner = AUTORELEASE([NSCalendarDateScanf new]);
+
+        if (locale == nil)
+            locale = defaultLocaleDictionary;
+        if (format == nil)
+            format = DEFAULT_FORMAT;
+    
+        [formatScanner setString:description withLocale:locale];
+        
+        if ([formatScanner parseFormatString:format context:NULL]) {
+            int year;
+            
+            year = [formatScanner year];
+            
+            /* handle 2-digit years ... */
+            if (year >= 0 && year < 10)
+                /* 0-9 to 2000 till 2009 */
+                year += 2000;
+            else if (year >= 10 && year < 100)
+                /* 10-99 to 1910 till 1999 */
+                year += 1900;
+            else if (year >= 100 && year < 110)
+                /* 100-109 to 2000 till 2009 */
+                year += 1900;
+            
+            if (year < MIN_YEAR || year >= MAX_YEAR) {
+                NSLog(@"WARNING(%s): year %i "
+                      @"parsed from string '%@' looks "
+                      @"invalid (allowed range %i-%i), "
+                      @"refusing date creation ...",
+                      __PRETTY_FUNCTION__, year, description,
+                      MIN_YEAR, MAX_YEAR);
+                RELEASE(pool);
+                RELEASE(self);
+                return nil;
+            }
+            
+            self = [self initWithYear:year
+                         month:   [formatScanner month]
+                         day:     [formatScanner day]
+                         hour:    [formatScanner hour]
+                         minute:  [formatScanner minute]
+                         second:  [formatScanner second]
+                         timeZone:[formatScanner timeZone]];
+        }
+        else {
+            RELEASE(pool);
+            RELEASE(self);
+            return nil;
+        }
+        
+        ASSIGN(self->formatString, format);
+    }
+    RELEASE(pool);
+    return self;
+}
+
+- (NSTimeZoneDetail*)timeZoneDetail
+{
+    // not available in MacOSX anymore
+    return self->timeZoneDetail;
+}
+- (NSTimeZone *)timeZone
+{
+    return self->timeZoneDetail;
+}
+
+- (void)setTimeZone:(NSTimeZone *)timeZone
+{
+    self->timeZoneDetail = AUTORELEASE(self->timeZoneDetail);
+    self->timeZoneDetail = nil;
+    
+    if (timeZone)
+        self->timeZoneDetail = RETAIN([timeZone timeZoneForDate:self]);
+    else {
+        self->timeZoneDetail =
+            (id)[[NSTimeZone localTimeZone] timeZoneForDate:self];
+        self->timeZoneDetail = RETAIN(self->timeZoneDetail);
+    }
+}
+    
+- (NSString*)calendarFormat
+{
+    return self->formatString;
+}
+
+- (void)setCalendarFormat:(NSString*)format
+{
+    if (self->formatString != format) {
+        RELEASE(self->formatString); self->formatString = nil;
+        self->formatString = [format copyWithZone:[self zone]];
+    }
+}
+
+- (int)yearOfCommonEra
+{
+    NSTimeInterval tm = timeSinceRef + [timeZoneDetail timeZoneSecondsFromGMT];
+    long date = floor (tm / 86400) + DATE_OFFSET;
+    int d, m, y;
+    
+    Long2Date(date, &m, &d, &y);
+    return y;
+}
+
+- (int)monthOfYear
+{
+    NSTimeInterval tm = timeSinceRef + [timeZoneDetail timeZoneSecondsFromGMT];
+    long date = floor (tm / 86400) + DATE_OFFSET;
+    int d, m, y;
+
+    Long2Date(date, &m, &d, &y);
+    return m;
+}
+
+- (int)dayOfMonth
+{
+    NSTimeInterval tm = timeSinceRef + [timeZoneDetail timeZoneSecondsFromGMT];
+    long date = floor (tm / 86400) + DATE_OFFSET;
+    int d, m, y;
+
+    Long2Date(date, &m, &d, &y);
+    return d;
+}
+
+- (int)dayOfWeek
+{
+    NSTimeInterval tm = timeSinceRef + [timeZoneDetail timeZoneSecondsFromGMT];
+    long noOfDays = floor (tm / 86400) + DATE_OFFSET;
+    int dayOfWeek = abs (noOfDays) % 7 + DAY_OFFSET;
+
+    return dayOfWeek;
+}
+
+- (int)dayOfYear
+{
+    NSTimeInterval tm = timeSinceRef + [timeZoneDetail timeZoneSecondsFromGMT];
+    long date = floor(tm / 86400) + DATE_OFFSET;
+    int d, m, y;
+    
+    Long2Date(date, &m, &d, &y);
+    if (y == -1) {
+        NSLog(@"WARNING(%s): got -1 year-value for date's long (%i), "
+              @"denying calculation of dayOfYear ...",
+              __PRETTY_FUNCTION__, date);
+        return -1;
+    }
+    
+    return day_in_year(m, d, y);
+}
+
+- (int)hourOfDay
+{
+    NSTimeInterval tm = timeSinceRef + [timeZoneDetail timeZoneSecondsFromGMT];
+    NSTimeInterval tr = tm / 3600;
+    NSTimeInterval ti = floor(tr/24);
+    int ts = (tr - ti * 24);
+
+    return ts < 0 ? 24 + ts : ts;
+}
+
+- (int)minuteOfHour
+{
+    NSTimeInterval tm = timeSinceRef + [timeZoneDetail timeZoneSecondsFromGMT];
+    NSTimeInterval tr = tm / 60;
+    NSTimeInterval ti = floor (tr / 60);
+    int ts = (tr - ti * 60);
+
+    return ts < 0 ? 60 + ts : ts;
+}
+
+- (int)secondOfMinute
+{
+    NSTimeInterval tm = timeSinceRef + [timeZoneDetail timeZoneSecondsFromGMT];
+    NSTimeInterval ti = floor (tm / 60);
+    int ts = (tm - ti * 60);
+
+    return ts < 0 ? 60 + ts : ts;
+}
+
+- (NSCalendarDate *)addYear:(int)years month:(int)months day:(int)days
+  hour:(int)hours minute:(int)minutes second:(int)seconds
+{
+    // TODO: I guess this is a deprecated method? In which Foundation version
+    //       was this used? OpenStep?
+    return [self dateByAddingYears:years months:months days:days hours:hours
+                minutes:minutes seconds:seconds];
+}
+
+- (id)dateByAddingYears:(int)years months:(int)months days:(int)days
+  hours:(int)hours minutes:(int)minutes seconds:(int)seconds
+{
+    NSTimeInterval tm;
+    NSCalendarDate *date;
+    long           monthDayYear, hourMinuteSecond;
+    int            selfMonth, selfDay, selfYear;
+    NSTimeInterval newInterval;
+    
+    tm = (timeSinceRef + [timeZoneDetail timeZoneSecondsFromGMT]);
+    monthDayYear = floor(tm / 86400) + DATE_OFFSET;
+    Long2Date(monthDayYear, &selfMonth, &selfDay, &selfYear);
+    if (selfYear == -1) {
+        NSLog(@"WARNING(%s): got -1 year-value for date's long (%i), "
+              @"denying creation of date ...",
+              __PRETTY_FUNCTION__, monthDayYear);
+        return nil;
+    }
+    
+    hourMinuteSecond
+       = (long)(tm - 86400 * ((NSTimeInterval)monthDayYear - DATE_OFFSET));
+
+    /* Add day */
+    if (days >= 0)
+       AddToDate(&selfMonth, &selfDay, &selfYear, days);
+    else
+       SubFromDate(&selfMonth, &selfDay, &selfYear, -days);
+
+    /* Add month and year */
+    selfYear += months / 12 + years;
+    selfMonth += months % 12;
+
+    if (selfMonth > 12) {
+       selfYear++; selfMonth -= 12;
+    }
+    else if (selfMonth < 1) {
+        selfYear--;
+        selfMonth = (12 + selfMonth);
+    }
+    if (selfYear >= MAX_YEAR) {
+        NSLog(@"%s: got out of range year %i (<%i), added %i/%i/%i, "
+              @"returning nil!", __PRETTY_FUNCTION__, 
+              selfYear, MAX_YEAR, years, months, days);
+        return nil;
+    }
+    
+    /* Adjust the day */
+    selfDay = AdjustDay(selfMonth, selfDay, selfYear);
+
+    /* Convert the (month, day, year) to long */
+    Date2Long(selfMonth, selfDay, selfYear, &monthDayYear);
+    if (monthDayYear == 0) {
+        NSLog(@"WARNING(%s): got 0 long-value for year %i, month %i, day %i "
+              @"denying creation of date ...",
+              __PRETTY_FUNCTION__, selfYear, selfMonth, selfDay);
+        return nil;
+    }
+    
+    /* Compute the new interval */
+    newInterval = ((NSTimeInterval)monthDayYear - DATE_OFFSET) * 86400
+                   + hourMinuteSecond
+                   + hours * 3600 + minutes * 60 + seconds;
+
+    date = [[[self class] alloc] autorelease];
+    
+#if 1
+    /* mh: trying (version 1.0.21) */
+    /* mh's new code, first check whether it really works ... */
+    date->timeSinceRef = newInterval;
+    date->timeZoneDetail = [[timeZoneDetail timeZoneForDate:date] retain];
+    date->timeSinceRef =
+        newInterval - [date->timeZoneDetail timeZoneSecondsFromGMT];
+#else
+    date->timeSinceRef =
+        newInterval - [timeZoneDetail timeZoneSecondsFromGMT];
+
+    date->timeZoneDetail = RETAIN(timeZoneDetail);
+#endif
+    date->formatString   = [formatString copy];
+
+    return date;
+}
+
+- (NSString*)description
+{
+    return [NSCalendarDate descriptionForCalendarDate:self
+                           withFormat:self->formatString
+                           timeZoneDetail:self->timeZoneDetail
+                           locale:nil];
+}
+
+- (NSString*)descriptionWithLocale:(NSDictionary*)locale
+{
+    return [NSCalendarDate descriptionForCalendarDate:self
+                           withFormat:self->formatString
+                           timeZoneDetail:self->timeZoneDetail
+                           locale:locale];
+}
+
+- (NSString*)descriptionWithCalendarFormat:(NSString*)format
+{
+    return [NSCalendarDate descriptionForCalendarDate:self
+                           withFormat:format
+                           timeZoneDetail:self->timeZoneDetail
+                           locale:nil];
+}
+
+- (NSString*)descriptionWithCalendarFormat:(NSString*)format 
+  timeZone:(NSTimeZone*)timeZone
+{
+    return [NSCalendarDate descriptionForCalendarDate:self
+                           withFormat:format
+                           timeZoneDetail:
+                             timeZone
+                             ? (id)[timeZone timeZoneForDate:self]
+                             : (id)self->timeZoneDetail
+                           locale:nil];
+}
+
+- (NSString*)descriptionWithCalendarFormat:(NSString*)format
+  timeZone:(NSTimeZone*)timeZone
+  locale:(NSDictionary*)locale 
+{
+    return [NSCalendarDate descriptionForCalendarDate:self
+                           withFormat:format
+                           timeZoneDetail:
+                             timeZone
+                             ? (id)[timeZone timeZoneForDate:self]
+                             : (id)self->timeZoneDetail
+                           locale:locale];
+}
+
+- (NSString*)descriptionWithCalendarFormat:(NSString*)format
+  locale:(NSDictionary*)locale
+{
+    return [NSCalendarDate descriptionForCalendarDate:self
+                           withFormat:format
+                           timeZoneDetail:self->timeZoneDetail
+                           locale:locale];
+}
+
+/* Encoding */
+- (Class)classForCoder
+{
+    return [NSCalendarDate class];
+}
+
+- (void)encodeWithCoder:(NSCoder*)aCoder
+{
+    [aCoder encodeValueOfObjCType:@encode(NSTimeInterval)
+            at:&(self->timeSinceRef)];
+    [aCoder encodeObject:[self->timeZoneDetail abbreviationForDate:self]];
+    [aCoder encodeObject:self->formatString];
+}
+
+- (id)initWithCoder:(NSCoder*)aDecoder
+{
+    NSTimeZone* timeZone;
+
+    [aDecoder decodeValueOfObjCType:@encode(NSTimeInterval) at:&timeSinceRef];
+    timeZone = [NSTimeZone timeZoneWithAbbreviation:[aDecoder decodeObject]];
+    timeZoneDetail = RETAIN([timeZone timeZoneForDate:self]);
+    formatString   = RETAIN([aDecoder decodeObject]);
+    return self;
+}
+
+@end
+
+/*
+ * NSCalendarDateImplementation
+ */
+
+@implementation NSCalendarDate (NSCalendarDateImplementation)
+
++ (NSString *)descriptionForCalendarDate:(NSCalendarDate *)date
+  withFormat:(NSString *)format
+  timeZoneDetail:(NSTimeZoneDetail *)detail
+  locale:(NSDictionary *)locale
+{
+    id formatScanner  = [[PrintfFormatScanner alloc] init];
+    id scannerHandler = [NSCalendarDateScannerHandler alloc];
+    id string;
+
+    /* Use a dummy va_list so compilation doesn't crash under alpha */
+    va_list list;
+    
+    NSAssert(date,   @"missing date ..");
+
+    if (detail == nil)
+        detail = (id)[[NSTimeZone localTimeZone] timeZoneForDate:date];
+    //NSAssert(detail, @"missing timezone detail ..");
+    
+    [scannerHandler initForCalendarDate:date timeZoneDetail:detail];
+    [formatScanner setFormatScannerHandler:scannerHandler];
+    string = [formatScanner stringWithFormat:format arguments:list];
+    RELEASE(scannerHandler); scannerHandler = nil;
+    RELEASE(formatScanner);  formatScanner  = nil;
+    return string;
+}
+
++ (NSString*)shortDayOfWeek:(int)day
+{
+    return [[defaultLocaleDictionary objectForKey:@"NSShortWeekDayNameArray"]
+               objectAtIndex:day];
+}
+
++ (NSString*)fullDayOfWeek:(int)day
+{
+    return [[defaultLocaleDictionary objectForKey:@"NSWeekDayNameArray"]
+               objectAtIndex:day];
+}
+
++ (NSString*)shortMonthOfYear:(int)month
+{
+    return [[defaultLocaleDictionary objectForKey:@"NSShortMonthNameArray"]
+               objectAtIndex:month - 1];
+}
+
++ (NSString*)fullMonthOfYear:(int)month
+{
+    return [[defaultLocaleDictionary objectForKey:@"NSMonthNameArray"]
+               objectAtIndex:month - 1];
+}
+
++ (int)decimalDayOfYear:(int)year month:(int)month day:(int)day
+{
+    return day_in_year(month, day, year);
+}
+
+@end
+
+/*
+* Functions to deal with date conversions (phil & miki)
+* deal with dates in day:month:year reprezented in int form
+* as days since year 1st Jan year 1 ac
+*/
+
+static int nDays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+#define bisect(a)      ((a) % 4 == 0 && ((a) % 400 == 0 || (a) % 100 ))
+#define        nr_bisect(a)    ((a - 1) / 4 - nr_nebisect(a - 1))
+
+static int  AdjustDay(int month, int day, int year)
+{
+    if(bisect(year) && month == 2 && day >= 29)
+       return 29;
+    if (day > nDays[month - 1])
+       day = nDays[month - 1];
+    return day;
+}
+
+static int nr_nebisect(int a)
+{
+    int i;
+    int ret = 0;
+
+    for(i = 100; i <= a; i += 100)
+       ret += (i % 400 != 0);
+    return ret;
+}
+
+static int day_in_year(int month, int day, int year)
+{
+    int ret = day + ((month > 2 && bisect(year)) ? 1 : 0);
+    while (--month)
+       ret += nDays[month - 1];
+    return ret;
+}
+
+static void Date2Long(int theMonth, int theDay, int theYear, long *theDate)
+{
+    long base, offset = 0;
+    int i;
+    
+    /* sanity checks */
+    if (theYear < MIN_YEAR || theYear >= MAX_YEAR) {
+        NSLog(@"WARNING(%s): got passed a year %i (month=%i,day=%i) out of "
+              @"range %i-%i, this is probably an invalid value, "
+              @"converted to 0 !",
+              __PRETTY_FUNCTION__, theYear, theMonth, theDay,
+              MIN_YEAR, MAX_YEAR);
+        *theDate = 0;
+#if 0
+        abort();
+        return;
+#else
+       // TODO: HACK HACK HACK
+        theYear = 2037;
+#endif
+    }
+    
+    base = ((long)theYear - 1) * 365 + nr_bisect(theYear);
+    for (i = 1; i < theMonth; i++)
+       offset += nDays[i - 1];
+    offset += theDay;
+    if (theMonth > 2 && bisect(theYear))
+       offset++;
+    *theDate = base + offset;
+}
+
+static void Long2Date(long theDate, int *theMonth, int *theDay, int *theYear)
+{
+    int month = 1, day, year, offset, i, days = 0, dif;
+    long aproxDate;
+
+    year   = (theDate - 1) / 365 + 1;
+    offset = (theDate - 1) % 365 + 1;
+    for (i = 1; i <= 12; i++) {
+       month = i;
+       if (days + nDays[i - 1] >= offset)
+           break;
+       days += nDays[i - 1];
+    }
+    
+    day = offset - days;
+    Assert (day <= nDays[month - 1] && day > 0);
+    
+    Date2Long(month, day, year, &aproxDate);
+    if (aproxDate == 0) {
+        NSLog(@"WARNING(%s): got 0 long-value for year %i, month %i, day %i "
+              @"denying creation of date ...",
+              __PRETTY_FUNCTION__, year, month, day);
+        *theMonth = -1;
+        *theDay   = -1;
+        *theYear  = -1;
+#if ABORT_ON_ERRORS
+        abort();
+#endif
+        return;
+    }
+    
+    dif = aproxDate - theDate;
+    
+    if (dif < 0) {
+        printf("ERROR(%s): wrong dif %i: %li vs %li\n", __PRETTY_FUNCTION__,
+               dif, aproxDate, theDate);
+#if 0
+        Assert(dif >= 0);
+#else
+       // TODO: HACK HACK HACK
+#endif
+    }
+    
+    SubFromDate(&month, &day, &year, dif);
+    *theMonth = month;
+    *theDay   = day;
+    *theYear  = year;
+}
+
+static void SubFromDate(int *month, int *day, int *year, int dif)
+{
+    while (dif > 0) {
+       if (*day > dif) {
+           *day -= dif;
+           break;
+       }
+       dif -= *day;
+       *day = 1;
+       DecDate(month, day, year);
+    }
+}
+
+static void AddToDate(int *month, int *day, int *year, int dif)
+{
+    int rest, bi;
+
+    while (dif > 0) {
+       bi = bisect(*year);
+       if ((*day + dif <= nDays[*month - 1])
+               || (*month == 2 && bi && *day + dif <= 29)) {
+           (*day) += dif;
+           break;
+       }
+       rest = nDays[*month - 1] - (*day) + (*month == 2 && bi) + 1;
+       dif -= rest;
+       *day = nDays[*month - 1] + (*month == 2 && bi);
+       IncDate(month, day, year);
+    }
+}
+
+static void DecDate( int *month, int *day, int *year)
+{
+    (*day)--;
+    if (*day != 0)
+       return;
+    (*month)--;
+    if (*month != 0) {
+       if (*month == 2 && bisect(*year))
+           *day = 29;
+       else
+           *day = nDays[*month - 1];
+       return;
+    }
+    *month = 12;
+    *day = 31;
+    (*year)--;
+
+    Assert(*year != 0);
+}
+
+static void IncDate( int *month, int *day, int *year)
+{
+    (*day)++;
+    if (*day <= nDays[*month - 1] || 
+           (*month == 2 && bisect(*year) && *day == 29))
+       return;
+
+    *day = 1;
+    (*month)++;
+    if (*month <= 12)
+           return;
+    *month = 1;
+    (*year)++;
+    Assert(*year != 0);
+}
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSCalendarDateScanf.h b/libFoundation/Foundation/NSCalendarDateScanf.h
new file mode 100644 (file)
index 0000000..ff5e10b
--- /dev/null
@@ -0,0 +1,82 @@
+/* 
+   NSCalendarDateScanf.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSCalendarDateScanf_h__
+#define __NSCalendarDateScanf_h__
+
+#include <extensions/FormatScanner.h>
+
+@class NSString;
+@class NSMutableString;
+@class NSDictionary;
+@class NSTimeZone;
+@class NSScanner;
+
+/*
+ * This class is used internally by the NSCalendarDate class to parse
+ * a description that holds an external representation of a calendar date.
+ */
+
+@interface NSCalendarDateScanf : FormatScanner
+{
+    NSDictionary* locale;
+    NSMutableString* scannedString;
+    NSScanner* scanner;
+    NSScanner* temporary;
+
+    int year;
+    int month;
+    int day;
+    int hour;
+    int minute;
+    int second;
+    NSTimeZone* timeZone;
+
+    BOOL hourIsUnder12;
+    BOOL isPM;
+}
+
+- (BOOL)handleOrdinaryString:(NSString*)string;
+- (BOOL)handleFormatSpecifierWithContext:(void*)context;
+
+- setString:(NSString*)description withLocale:(NSDictionary*)locale;
+
+- (int)year;
+- (int)month;
+- (int)day;
+- (int)hour;
+- (int)minute;
+- (int)second;
+- (NSTimeZone*)timeZone;
+
+@end
+
+#endif /* __NSCalendarDateScanf_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSCalendarDateScanf.m b/libFoundation/Foundation/NSCalendarDateScanf.m
new file mode 100644 (file)
index 0000000..2b26832
--- /dev/null
@@ -0,0 +1,362 @@
+/* 
+   NSCalendarDateScanf.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSCharacterSet.h>
+#include <Foundation/NSDate.h>
+#include <Foundation/NSScanner.h>
+
+#include "NSCalendarDateScanf.h"
+
+@interface NSScanner (NSCalendarDateScanf)
+- (BOOL)scanInt:(int *)_value exactNumberOfDigits:(unsigned int)_exactLen;
+@end
+
+@implementation NSScanner (NSCalendarDateScanf)
+- (BOOL)scanInt:(int *)_value exactNumberOfDigits:(unsigned int)_exactLen {
+  static NSCharacterSet *decimals = nil;
+  id string = [self string];
+  unsigned int orig, location, last, result = 0;
+  unichar c;
+  unichar zeroChar = '0';
+
+  if ([self isAtEnd])
+    return NO;
+
+  /* First skip the blank characters */
+  [self scanCharactersFromSet:[self charactersToBeSkipped] intoString:NULL];
+
+  orig = [self scanLocation];
+  last = orig + _exactLen;
+
+  if ([string length] < last)
+    return NO;
+
+  if(decimals == nil)
+    decimals = [[NSCharacterSet decimalDigitCharacterSet] retain];
+
+  for(location = orig; location < last; location++) {
+    c = [string characterAtIndex:location];
+    if ([decimals characterIsMember:c]) {
+      result = result * 10 + (c - zeroChar);
+    }
+    else {
+      break;
+    }
+  }
+
+  if(location != orig)
+    [self setScanLocation:location];
+
+  if(location == last) {
+    *_value = result;
+    return YES;
+  }
+  return NO;
+}
+@end
+
+
+@implementation NSCalendarDateScanf
+
+static NSCharacterSet *blanks = nil;
+static id timeZoneCharSet = nil;
+
++ (void)initialize
+{
+    if (blanks == nil) {
+        blanks = [NSCharacterSet whitespaceAndNewlineCharacterSet];
+        blanks = RETAIN(blanks);
+
+        timeZoneCharSet = [NSMutableCharacterSet
+                             characterSetWithCharactersInString:@"+-"];
+        [timeZoneCharSet formUnionWithCharacterSet:
+                             [NSCharacterSet alphanumericCharacterSet]];
+        timeZoneCharSet = [timeZoneCharSet copy];
+    }
+}
+
+- (id)init
+{
+    /* Set an acceptable value for day. If it is not read from description this
+       prevents a failed assertion in NSCalendarDate. */
+    self = [super init];
+    self->day = 1;
+    self->scanner   = [[NSScanner allocWithZone:[self zone]] init];
+    self->temporary = [[NSScanner allocWithZone:[self zone]] init];
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(self->locale);
+    RELEASE(self->scannedString);
+    RELEASE(self->scanner);
+    RELEASE(self->temporary);
+    RELEASE(self->timeZone);
+
+    [super dealloc];
+}
+
+- (id)setString:(NSString *)description withLocale:(NSDictionary *)_locale
+{
+    ASSIGN(self->scannedString, (NSMutableString*)description);
+    ASSIGN(self->locale, _locale);
+
+    [scanner initWithString:scannedString];
+    [scanner scanCharactersFromSet:blanks intoString:NULL];
+
+    return self;
+}
+
+- (BOOL)handleOrdinaryString:(NSString *)string
+{
+    id substring;
+    NSRange range;
+
+    /* Skip the blanks in scannedString */
+    [scanner scanCharactersFromSet:blanks intoString:NULL];
+
+    /* Determine the substring from string that doesn't begin with blanks. */
+    [temporary initWithString:string];
+    [temporary setScanLocation:0];
+    [temporary scanCharactersFromSet:blanks intoString:NULL];
+    range.location = [temporary scanLocation];
+    if (range.location) {
+        range.length = [string length] - range.location;
+        substring = [string substringWithRange:range];
+    }
+    else
+        substring = string;
+
+    /* Match the current part of `scannedString' with `substring'. */
+    if ([scanner scanString:substring intoString:NULL])
+        return YES;
+
+    return NO;
+}
+
+- (int)_searchInArray:(NSArray*)array
+{
+    int i, count = [array count];
+
+    for (i = 0; i < count; i++) {
+        id name = [array objectAtIndex:i];
+
+        if ([scanner scanString:name intoString:NULL])
+            return i;
+    }
+
+    return -1;
+}
+
+/* This method skips the weekday name and the day of the year, so if you supply
+   a wrong name of day related to the actual date this will not be an error. */
+- (BOOL)handleFormatSpecifierWithContext:(void*)context
+{
+    char    specifier = [self characterSpecifier];
+    NSArray *days = nil;
+    NSArray *months = nil;
+    int     result;
+
+    /* Skip the blanks in scannedString */
+    [self->scanner scanCharactersFromSet:blanks intoString:NULL];
+
+    switch (specifier) {
+        case 'a': {
+            days = [locale objectForKey:@"NSShortWeekDayNameArray"];
+            if ((result = [self _searchInArray:days]) != -1)
+                return YES;
+            break;
+        }
+        case 'A': {
+            days = [locale objectForKey:@"NSWeekDayNameArray"];
+            if ((result = [self _searchInArray:days]) != -1)
+                return YES;
+            break;
+        }
+        case 'b': {
+            months = [locale objectForKey:@"NSShortMonthNameArray"];
+            if ((result = [self _searchInArray:months]) != -1) {
+                month = result + 1;
+                return YES;
+            }
+            break;
+        }
+        case 'B': {
+            months = [locale objectForKey:@"NSMonthNameArray"];
+            if ((result = [self _searchInArray:months]) != -1) {
+                month = result + 1;
+                return YES;
+            }
+            break;
+        }
+        case 'd': {
+            if ([self->scanner scanInt:&day exactNumberOfDigits:2])
+                return YES;
+            break;
+        }
+        case 'I':
+            self->hourIsUnder12 = YES;
+            /* No `break' here */
+        case 'H': {
+            if ([self->scanner scanInt:&(self->hour) exactNumberOfDigits:2])
+                return YES;
+            break;
+        }
+        case 'j': {
+            int dayOfYear;
+
+            if ([self->scanner scanInt:&dayOfYear exactNumberOfDigits:3]
+                && (dayOfYear >= 1 && dayOfYear <= 366))
+                return YES;
+            break;
+        }
+        case 'm': {
+            if ([self->scanner scanInt:&month exactNumberOfDigits:2] && (month >= 1 && month <= 12))
+                return YES;
+            break;
+        }
+        case 'M': {
+            if ([self->scanner scanInt:&minute exactNumberOfDigits:2] && (minute >= 0 && minute <= 59))
+                return YES;
+            break;
+        }
+        case 'p': {
+            NSArray* ampm = [locale objectForKey:@"NSAMPMDesignation"];
+            if ((result = [self _searchInArray:ampm]) != -1) {
+                isPM = (result == 1);
+                return YES;
+            }
+            break;
+        }
+        case 'S': {
+            if ([self->scanner scanInt:&second exactNumberOfDigits:2] && (second >= 0 && second <= 61))
+                return YES;
+            break;
+        }
+        case 'w': {
+            int weekday;
+
+            if ([self->scanner scanInt:&weekday exactNumberOfDigits:1] &&
+                (weekday >= 0 && weekday <= 6))
+                return YES;
+            break;
+        }
+        case 'Y': {
+            if ([self->scanner scanInt:&year exactNumberOfDigits:4])
+                return YES;
+            break;
+        }
+        case 'Z': {
+            NSString *timeZoneName;
+
+            if ([self->scanner scanCharactersFromSet:timeZoneCharSet
+                         intoString:&timeZoneName]) {
+                timeZone = [NSTimeZone timeZoneWithAbbreviation:timeZoneName];
+                (void)RETAIN(timeZone);
+                return YES;
+            }
+            break;
+        }
+        case 'z': {
+            int hourMinute, hours, minutes;
+            BOOL is_negative;
+
+            if ([self->scanner scanInt:&hourMinute]) {
+                is_negative = (hourMinute < 0);
+                hourMinute = abs (hourMinute);
+                hours = hourMinute / 100;
+                minutes = hourMinute % 100;
+                if (!(hours < 24 && minutes < 60))
+                    return NO;
+                hourMinute = (hours * 3600 + minutes * 60);
+                if (is_negative)
+                    hourMinute = -hourMinute;
+                timeZone = RETAIN([NSTimeZone
+                                      timeZoneForSecondsFromGMT:hourMinute]);
+                return YES;
+            }
+        }
+    }
+
+    return NO;
+}
+
+- (int)year
+{
+    return self->year;
+}
+- (int)month
+{
+    return self->month;
+}
+- (int)day
+{
+    return self->day;
+}
+
+- (int)hour
+{
+    register int realHour = self->hour;
+
+    if (self->hourIsUnder12) {
+        if(self->isPM) { // hour value is below 12, but PM is specified
+          if (realHour != 12)
+            realHour += 12;
+        }
+        else { // hour value is below 12, PM isn't specified
+          if (realHour == 12)
+            realHour = 0;
+        }
+    }
+    // else hour value is above 12
+    return realHour;
+}
+
+- (int)minute
+{
+    return self->minute;
+}
+- (int)second
+{
+    return self->second;
+}
+
+- (NSTimeZone *)timeZone
+{
+    return self->timeZone;
+}
+
+@end /* NSCalendarDateScanf */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSCalendarDateScannerHandler.h b/libFoundation/Foundation/NSCalendarDateScannerHandler.h
new file mode 100644 (file)
index 0000000..2319861
--- /dev/null
@@ -0,0 +1,90 @@
+/* 
+   NSCalendarDateScannerHandler.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSCalendarDateScannerHandler_h__
+#define __NSCalendarDateScannerHandler_h__
+
+#include <Foundation/NSCalendarDate.h>
+#include <extensions/DefaultScannerHandler.h>
+
+/*
+ * This class is used internally by the NSCalendarDate class to create a string
+ * representation from a calendar date object. The class that performs the
+ * reverse operation, i.e. parses a string description and initializes a
+ * calendar date object is the NSCalendarDateFormatScanner class.
+ */
+
+@interface NSCalendarDateScannerHandler : DefaultScannerHandler
+{
+    NSCalendarDate* date;
+    NSTimeZoneDetail* detail;
+
+    unsigned year;
+    unsigned month;
+    unsigned day;
+    unsigned hour;
+    unsigned minute;
+    unsigned second;
+    int timeZoneOffset;
+    unsigned weekDay;
+}
+
+- initForCalendarDate:(NSCalendarDate*)date
+  timeZoneDetail:(NSTimeZoneDetail*)detail;
+
+- (NSString*)shortDayOfWeek:(va_list*)pInt scanner:(FormatScanner*)scanner;
+- (NSString*)fullDayOfWeek:(va_list*)pInt scanner:(FormatScanner*)scanner;
+- (NSString*)shortMonthOfYear:(va_list*)pInt scanner:(FormatScanner*)scanner;
+- (NSString*)fullMonthOfYear:(va_list*)pInt scanner:(FormatScanner*)scanner;
+- (NSString*)localeFormatForDateAndTime:(va_list*)pInt
+  scanner:(FormatScanner*)scanner;
+- (NSString*)decimalDayOfMonth:(va_list*)pInt scanner:(FormatScanner*)scanner;
+- (NSString*)decimal24HourOfDay:(va_list*)pInt scanner:(FormatScanner*)scanner;
+- (NSString*)decimal12HourOfDay:(va_list*)pInt scanner:(FormatScanner*)scanner;
+- (NSString*)decimalDayOfYear:(va_list*)pInt scanner:(FormatScanner*)scanner;
+- (NSString*)decimalMonthOfYear:(va_list*)pInt scanner:(FormatScanner*)scanner;
+- (NSString*)decimalMinuteOfHour:(va_list*)pInt
+  scanner:(FormatScanner*)scanner;
+- (NSString*)AM_PM:(va_list*)pInt scanner:(FormatScanner*)scanner;
+- (NSString*)decimalSecondOfMinute:(va_list*)pInt
+  scanner:(FormatScanner*)scanner;
+- (NSString*)decimalDayOfWeek:(va_list*)pInt scanner:(FormatScanner*)scanner;
+- (NSString*)localeDate:(va_list*)pInt scanner:(FormatScanner*)scanner;
+- (NSString*)localeTime:(va_list*)pInt scanner:(FormatScanner*)scanner;
+- (NSString*)yearWithoutCentury:(va_list*)pInt scanner:(FormatScanner*)scanner;
+- (NSString*)yearWithCentury:(va_list*)pInt scanner:(FormatScanner*)scanner;
+- (NSString*)timeZoneName:(va_list*)pInt scanner:(FormatScanner*)scanner;
+- (NSString*)timeZoneOffsetFromGMT:(va_list*)pInt
+  scanner:(FormatScanner*)scanner;
+
+@end
+
+#endif /* __NSCalendarDateScannerHandler_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSCalendarDateScannerHandler.m b/libFoundation/Foundation/NSCalendarDateScannerHandler.m
new file mode 100644 (file)
index 0000000..3437feb
--- /dev/null
@@ -0,0 +1,259 @@
+/* 
+   NSCalendarDateScannerHandler.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <stdio.h>
+
+#include <Foundation/NSValue.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSCalendarDateScannerHandler.h>
+
+@implementation NSCalendarDateScannerHandler
+
+id twoDigit[] = {
+    @"00", @"01", @"02", @"03", @"04", @"05", @"06", @"07", @"08", @"09",
+    @"10", @"11", @"12", @"13", @"14", @"15", @"16", @"17", @"18", @"19",
+    @"20", @"21", @"22", @"23", @"24", @"25", @"26", @"27", @"28", @"29",
+    @"30", @"31", @"32", @"33", @"34", @"35", @"36", @"37", @"38", @"39",
+    @"40", @"41", @"42", @"43", @"44", @"45", @"46", @"47", @"48", @"49",
+    @"50", @"51", @"52", @"53", @"54", @"55", @"56", @"57", @"58", @"59",
+    @"60", @"61", @"62", @"63", @"64", @"65", @"66", @"67", @"68", @"69",
+    @"70", @"71", @"72", @"73", @"74", @"75", @"76", @"77", @"78", @"79",
+    @"80", @"81", @"82", @"83", @"84", @"85", @"86", @"87", @"88", @"89",
+    @"90", @"91", @"92", @"93", @"94", @"95", @"96", @"97", @"98", @"99",
+    nil
+};
+
+- init
+{
+    [super init];
+
+    specHandler['a']
+           = [self methodForSelector:@selector(shortDayOfWeek:scanner:)];
+    specHandler['A']
+           = [self methodForSelector:@selector(fullDayOfWeek:scanner:)];
+    specHandler['b']
+           = [self methodForSelector:@selector(shortMonthOfYear:scanner:)];
+    specHandler['B']
+           = [self methodForSelector:@selector(fullMonthOfYear:scanner:)];
+    specHandler['c']
+           = [self methodForSelector:
+                       @selector(localeFormatForDateAndTime:scanner:)];
+    specHandler['d']
+           = [self methodForSelector:@selector(decimalDayOfMonth:scanner:)];
+    specHandler['H']
+           = [self methodForSelector:@selector(decimal24HourOfDay:scanner:)];
+    specHandler['I']
+           = [self methodForSelector:@selector(decimal12HourOfDay:scanner:)];
+    specHandler['j']
+           = [self methodForSelector:@selector(decimalDayOfYear:scanner:)];
+    specHandler['m']
+           = [self methodForSelector:@selector(decimalMonthOfYear:scanner:)];
+    specHandler['M']
+           = [self methodForSelector:@selector(decimalMinuteOfHour:scanner:)];
+    specHandler['p']
+           = [self methodForSelector:@selector(AM_PM:scanner:)];
+    specHandler['S']
+           = [self methodForSelector:
+                       @selector(decimalSecondOfMinute:scanner:)];
+    specHandler['w']
+           = [self methodForSelector:@selector(decimalDayOfWeek:scanner:)];
+    specHandler['x']
+           = [self methodForSelector:@selector(localeDate:scanner:)];
+    specHandler['X']
+           = [self methodForSelector:@selector(localeTime:scanner:)];
+    specHandler['y']
+           = [self methodForSelector:@selector(yearWithoutCentury:scanner:)];
+    specHandler['Y']
+           = [self methodForSelector:@selector(yearWithCentury:scanner:)];
+    specHandler['Z']
+           = [self methodForSelector:@selector(timeZoneName:scanner:)];
+    specHandler['z']
+           = [self methodForSelector:
+                       @selector(timeZoneOffsetFromGMT:scanner:)];
+    return self;
+}
+
+- (id)initForCalendarDate:(NSCalendarDate*)_date
+  timeZoneDetail:(NSTimeZoneDetail*)_detail
+{
+    [self init];
+    self->date           = _date;
+    self->detail         = _detail;
+
+    if (self->detail == nil)
+        self->detail = (id)[[NSTimeZone localTimeZone] timeZoneForDate:_date];
+    
+    self->year           = [self->date yearOfCommonEra];
+    self->month          = [self->date monthOfYear];
+    self->day            = [self->date dayOfMonth];
+    self->hour           = [self->date hourOfDay];
+    self->minute         = [self->date minuteOfHour];
+    self->second         = [self->date secondOfMinute];
+    self->weekDay        = [self->date dayOfWeek];
+    self->timeZoneOffset = [self->detail timeZoneSecondsFromGMT];
+
+    return self;
+}
+
+- (NSString*)shortDayOfWeek:(va_list*)arg scanner:(FormatScanner*)scanner
+{
+    return [NSCalendarDate shortDayOfWeek:self->weekDay];
+}
+
+- (NSString*)fullDayOfWeek:(va_list*)arg scanner:(FormatScanner*)scanner
+{
+    return [NSCalendarDate fullDayOfWeek:self->weekDay];
+}
+
+- (NSString*)shortMonthOfYear:(va_list*)arg scanner:(FormatScanner*)scanner
+{
+    return [NSCalendarDate shortMonthOfYear:self->month];
+}
+
+- (NSString*)fullMonthOfYear:(va_list*)arg scanner:(FormatScanner*)scanner
+{
+    return [NSCalendarDate fullMonthOfYear:self->month];
+}
+
+- (NSString*)localeFormatForDateAndTime:(va_list*)arg
+  scanner:(FormatScanner*)scanner
+{
+    return [NSCalendarDate descriptionForCalendarDate:self->date
+                           withFormat:@"%X %x"
+                           timeZoneDetail:self->detail locale:nil];
+}
+
+- (NSString*)decimalDayOfMonth:(va_list*)arg scanner:(FormatScanner*)scanner
+{
+    char buffer[5];
+
+    sprintf (buffer, "%02d", self->day);
+    return [NSString stringWithCString:buffer];
+}
+
+- (NSString*)decimal24HourOfDay:(va_list*)arg scanner:(FormatScanner*)scanner
+{
+    char buffer[5];
+
+    sprintf (buffer, "%02d", self->hour);
+    return [NSString stringWithCString:buffer];
+}
+
+- (NSString*)decimal12HourOfDay:(va_list*)arg scanner:(FormatScanner*)scanner
+{
+    char buffer[5];
+
+    sprintf (buffer, "%02d", hour > 12 ? hour - 12 : hour);
+    return [NSString stringWithCString:buffer];
+}
+
+- (NSString*)decimalDayOfYear:(va_list*)arg scanner:(FormatScanner*)scanner
+{
+    char buffer[5];
+
+    sprintf (buffer, "%03d",
+            [NSCalendarDate decimalDayOfYear:year month:month day:day]);
+    return [NSString stringWithCString:buffer];
+}
+
+- (NSString*)decimalMonthOfYear:(va_list*)arg scanner:(FormatScanner*)scanner
+{
+    return twoDigit[self->month];
+}
+
+- (NSString*)decimalMinuteOfHour:(va_list*)arg scanner:(FormatScanner*)scanner
+{
+    return twoDigit[self->minute];
+}
+
+- (NSString*)AM_PM:(va_list*)arg scanner:(FormatScanner*)scanner
+{
+    return (hour >= 12) ? @"PM" : @"AM";
+}
+
+- (NSString*)decimalSecondOfMinute:(va_list*)arg
+  scanner:(FormatScanner*)scanner
+{
+    return twoDigit[self->second];
+}
+
+- (NSString*)decimalDayOfWeek:(va_list*)arg scanner:(FormatScanner*)scanner
+{
+    char buffer[5];
+
+    sprintf (buffer, "%d", self->weekDay);
+    return [NSString stringWithCString:buffer];
+}
+
+- (NSString*)localeDate:(va_list*)arg scanner:(FormatScanner*)scanner
+{
+    return [NSCalendarDate descriptionForCalendarDate:date
+                           withFormat:@"%b %d %Y"
+                           timeZoneDetail:self->detail
+                           locale:nil];
+}
+
+- (NSString*)localeTime:(va_list*)arg scanner:(FormatScanner*)scanner
+{
+    return [NSCalendarDate descriptionForCalendarDate:date
+                           withFormat:@"%H:%M:%S %z"
+                           timeZoneDetail:self->detail
+                           locale:nil];
+}
+
+- (NSString *)yearWithoutCentury:(va_list*)arg scanner:(FormatScanner*)scanner
+{
+    return twoDigit[self->year % 100];
+}
+
+- (NSString *)yearWithCentury:(va_list*)arg scanner:(FormatScanner*)scanner
+{
+    char buffer[5];
+    
+    sprintf (buffer, "%d", self->year);
+    return [NSString stringWithCString:buffer];
+}
+
+- (NSString*)timeZoneName:(va_list*)arg scanner:(FormatScanner*)scanner
+{
+    return [self->detail timeZoneAbbreviation];
+}
+
+- (NSString*)timeZoneOffsetFromGMT:(va_list*)arg
+  scanner:(FormatScanner*)scanner
+{
+    int i = self->timeZoneOffset > 0;
+    int j = (timeZoneOffset > 0 ? timeZoneOffset : -timeZoneOffset) / 60;
+    return [NSString stringWithFormat:@"%s%02d%02d",
+                                       i ? "+":"-", j / 60, j % 60];
+}
+
+@end /* NSCalendarDateScannerHandler */
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSCharacterSet.h b/libFoundation/Foundation/NSCharacterSet.h
new file mode 100644 (file)
index 0000000..07f0ab7
--- /dev/null
@@ -0,0 +1,109 @@
+/* 
+   NSCharacterSet.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSCharacterSet_h__
+#define __NSCharacterSet_h__
+
+#include <Foundation/NSObject.h>
+#include <Foundation/NSString.h>
+
+/*
+ * NSCharacterSet
+ */
+
+@interface NSCharacterSet : NSObject
+
+/* Creating a Standard Character Set */
+
++ (NSCharacterSet *)alphanumericCharacterSet;
++ (NSCharacterSet *)controlCharacterSet;
++ (NSCharacterSet *)decimalDigitCharacterSet;
++ (NSCharacterSet *)decomposableCharacterSet;
++ (NSCharacterSet *)illegalCharacterSet;
++ (NSCharacterSet *)letterCharacterSet;
++ (NSCharacterSet *)lowercaseLetterCharacterSet;
++ (NSCharacterSet *)nonBaseCharacterSet;
++ (NSCharacterSet *)uppercaseLetterCharacterSet;
++ (NSCharacterSet *)whitespaceAndNewlineCharacterSet;
++ (NSCharacterSet *)whitespaceCharacterSet;
++ (NSCharacterSet *)punctuationCharacterSet;
++ (NSCharacterSet *)emptyCharacterSet;
+
+/* Creating a Custom Character Set */
+
++ (NSCharacterSet *)characterSetWithContentsOfFile:(NSString*)fileName;
++ (NSCharacterSet *)characterSetWithBitmapRepresentation:(NSData*)data;
++ (NSCharacterSet *)characterSetWithCharactersInString:(NSString*)aString;
++ (NSCharacterSet *)characterSetWithRange:(NSRange)aRange;
+
+/* Getting a Binary Representation */
+
+- (NSData *)bitmapRepresentation;
+
+/* Testing Set Membership */
+
+- (BOOL)characterIsMember:(unichar)aCharacter;
+
+/* Inverting a Character Set */
+
+- (NSCharacterSet *)invertedSet;
+
+@end /* NSCharacterSet */
+
+/*
+ * NSMutableCharacterSet
+ */
+
+@interface NSMutableCharacterSet : NSCharacterSet
+
+/* Adding and Removing Characters */
+
+- (void)addCharactersInRange:(NSRange)aRange;
+- (void)addCharactersInString:(NSString*)aString;
+- (void)removeCharactersInRange:(NSRange)aRange;
+- (void)removeCharactersInString:(NSString*)aString;
+
+/* Combining Character Sets */
+
+- (void)formIntersectionWithCharacterSet:(NSCharacterSet*)otherSet;
+- (void)formUnionWithCharacterSet:(NSCharacterSet*)otherSet;
+
+/* Inverting a Character Set */
+
+- (void)invert;
+
+@end /* NSMutableCharacterSet */
+
+/* constants */
+
+enum { NSOpenStepUnicodeReservedBase = 0xF400 };
+
+#endif /* __NSCharacterSet_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSCharacterSet.m b/libFoundation/Foundation/NSCharacterSet.m
new file mode 100644 (file)
index 0000000..ddd219c
--- /dev/null
@@ -0,0 +1,391 @@
+/* 
+   NSCharacterSet.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSCharacterSet.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSData.h>
+#include <Foundation/NSCoder.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSLock.h>
+#include <Foundation/NSBundle.h>
+
+#include <Foundation/exceptions/GeneralExceptions.h>
+
+#include "NSConcreteCharacterSet.h"
+
+@implementation NSCharacterSet
+
+// Cluster allocation
+
++ (id)allocWithZone:(NSZone*)zone
+{
+    return NSAllocateObject( (self == [NSCharacterSet class]) ? 
+       [NSBitmapCharacterSet class] : self, 0, zone);
+}
+
+// Creating a shared Character Set from a standard file
+// We should mmap only ONE file and have a the sets initialized
+// with range subdata of the main file (range subdata of NSData must
+// not copy its data but retain its master data ...
+// In this case we need a dictionary to know the offset of each charset
+// in the BIG data; this approach should be very efficient on systems
+// that support mmap (in paged virtual memory systems)
+
+static NSMutableDictionary* predefinedCharacterSets = nil;
+
+extern NSRecursiveLock* libFoundationLock;
+
++ (NSCharacterSet *)characterSetWithContentsOfFile:(NSString *)fileName
+{
+    /*
+      Note: we need to be careful here, this has potential for
+            endless recursion!
+    */
+    NSCharacterSet *aSet;
+    
+    if (fileName == nil)
+       return nil;
+    
+    [libFoundationLock lock];
+    {
+        if (predefinedCharacterSets == nil) {
+           predefinedCharacterSets =
+                [[NSMutableDictionary alloc] initWithCapacity:12];
+        }
+        aSet = [predefinedCharacterSets objectForKey:fileName];
+    }
+    [libFoundationLock unlock];
+
+    if (aSet == nil) {
+       NSString *fullFilenamePath;
+       id data = nil;
+       
+       fullFilenamePath = [NSBundle _fileResourceNamed:fileName
+                                    extension:@"bitmap"
+                                    inDirectory:@"CharacterSets"];
+       
+       if (fullFilenamePath != nil)
+           data = [NSData dataWithContentsOfMappedFile:fullFilenamePath];
+
+       if (data == nil) {
+           /* Note: yes, this is weird, but matches Panther! */
+           data = [NSData data];
+       }
+        
+       aSet = AUTORELEASE([[NSBitmapCharacterSet alloc] 
+                               initWithBitmapRepresentation:data]);
+        if (aSet == nil) {
+           fprintf(stderr, 
+                   "ERROR(%s): could not create character set for "
+                   "data (0x%08X,len=%d) from file %s (%s)\n",
+                   __PRETTY_FUNCTION__,
+                   (unsigned int)data, [data length], [fileName cString],
+                   [fullFilenamePath cString]);
+        }
+        
+        [libFoundationLock lock];
+       [predefinedCharacterSets setObject:aSet forKey:fileName];
+        [libFoundationLock unlock];
+    }
+
+    return aSet;
+}
+
+// Creating a Standard Character Set 
+
++ (NSCharacterSet*)alphanumericCharacterSet
+{
+    return [self characterSetWithContentsOfFile:@"alphanumericCharacterSet"];
+}
+
++ (NSCharacterSet*)controlCharacterSet
+{
+    return [self characterSetWithContentsOfFile:@"controlCharacterSet"];
+}
+
++ (NSCharacterSet*)decimalDigitCharacterSet
+{
+    return [self characterSetWithContentsOfFile:@"decimalDigitCharacterSet"];
+}
+
++ (NSCharacterSet*)decomposableCharacterSet
+{
+    return [self characterSetWithContentsOfFile:@"decomposableCharacterSet"];
+}
+
++ (NSCharacterSet*)illegalCharacterSet
+{
+    return [self characterSetWithContentsOfFile:@"illegalCharacterSet"];
+}
+
++ (NSCharacterSet*)letterCharacterSet
+{
+    return [self characterSetWithContentsOfFile:@"letterCharacterSet"];
+}
+
++ (NSCharacterSet*)lowercaseLetterCharacterSet
+{
+    return [self characterSetWithContentsOfFile:@"lowercaseLetterCharacterSet"];
+}
+
++ (NSCharacterSet*)nonBaseCharacterSet
+{
+    return [self characterSetWithContentsOfFile:@"nonBaseCharacterSet"];
+}
+
++ (NSCharacterSet*)uppercaseLetterCharacterSet
+{
+    return [self characterSetWithContentsOfFile:@"uppercaseLetterCharacterSet"];
+}
+
++ (NSCharacterSet*)whitespaceAndNewlineCharacterSet
+{
+    return [self characterSetWithContentsOfFile:@"whitespaceAndNewlineCharacterSet"];
+}
+
++ (NSCharacterSet*)whitespaceCharacterSet
+{
+    return [self characterSetWithContentsOfFile:@"whitespaceCharacterSet"];
+}
+
++ (NSCharacterSet*)punctuationCharacterSet
+{
+    return [self characterSetWithContentsOfFile:@"punctuationCharacterSet"];
+}
+
++ (NSCharacterSet*)emptyCharacterSet
+{
+    return [self characterSetWithContentsOfFile:@"emptyCharacterSet"];
+}
+
+// Creating a Custom Character Set 
+
++ (NSCharacterSet*)characterSetWithBitmapRepresentation:(NSData*)data
+{
+    return AUTORELEASE([[NSBitmapCharacterSet alloc] 
+                           initWithBitmapRepresentation:data]);
+}
+
++ (NSCharacterSet*)characterSetWithCharactersInString:(NSString*)aString
+{
+    char*      bytes = CallocAtomic(1, BITMAPDATABYTES);
+    id         data;
+    int                i, count = [aString length];
+    unichar    c;
+
+    for (i = 0; i < count; i++) {
+        c = [aString characterAtIndex:i];
+        SETBIT(bytes, c);
+    }
+
+    data = [NSData dataWithBytesNoCopy:bytes 
+                   length:BITMAPDATABYTES];
+    return [self isKindOfClass:[NSMutableCharacterSet class]]
+        ? AUTORELEASE([[NSMutableBitmapCharacterSet alloc] 
+                          initWithBitmapRepresentation:data])
+        : AUTORELEASE([[NSBitmapCharacterSet alloc] 
+                          initWithBitmapRepresentation:data]);
+}
+
++ (NSCharacterSet*)characterSetWithRange:(NSRange)aRange
+{
+    return AUTORELEASE([[NSRangeCharacterSet alloc] initWithRange:aRange]);
+}
+
+// Getting a Binary Representation 
+
+- (NSData*)bitmapRepresentation
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+// Testing Set Membership 
+
+- (BOOL)characterIsMember:(unichar)aCharacter
+{
+    [self subclassResponsibility:_cmd];
+    return NO;
+}
+
+// Inverting a Character Set 
+
+- (NSCharacterSet*)invertedSet
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+// NSCopying
+
+- copyWithZone:(NSZone*)zone
+{
+    if (NSShouldRetainWithZone(self, zone))
+           return RETAIN(self);
+    else {
+           id data = [self bitmapRepresentation];
+           return [[NSCharacterSet alloc] initWithBitmapRepresentation:data];
+    }
+}
+
+- mutableCopyWithZone:(NSZone*)zone
+{
+    id data = [self bitmapRepresentation];
+    return RETAIN([NSMutableCharacterSet
+                      characterSetWithBitmapRepresentation:data]);
+}
+
+// NSArchiving
+
+- (Class)classForCoder
+{
+    return [NSCharacterSet class];
+}
+
+- (id)replacementObjectForCoder:(NSCoder*)coder
+{
+    if ([[self class] isKindOfClass:[NSMutableCharacterSet class]])
+       return [super replacementObjectForCoder:coder];
+    return self;
+}
+
+- initWithCoder:(NSCoder*)coder
+{
+    id data;
+    id new;
+
+    [coder decodeValueOfObjCType:@encode(id) at:&data];
+    new = [[[self class] alloc] initWithBitmapRepresentation:data];
+    [self dealloc];
+    return new;
+}
+
+- (void)encodeWithCoder:(NSCoder*)coder
+{
+    id data = [self bitmapRepresentation];
+    [coder encodeValueOfObjCType:@encode(id) at:&data];
+}
+
+@end /* NSCharacterSet */
+
+@implementation NSMutableCharacterSet
+
+// Cluster allocation
+
++ (id)allocWithZone:(NSZone*)zone
+{
+    return NSAllocateObject( (self == [NSMutableCharacterSet class]) ? 
+           [NSMutableBitmapCharacterSet class] : self, 0, zone);
+}
+
+// Creating a Custom Character Set 
+
++ (NSCharacterSet*)characterSetWithBitmapRepresentation:(NSData*)data
+{
+    return AUTORELEASE([[self alloc] initWithBitmapRepresentation:data]);
+}
+
++ (NSCharacterSet*)characterSetWithContentsOfFile:(NSString*)fileName
+{
+    NSCharacterSet *set = [super characterSetWithContentsOfFile:fileName];
+    return AUTORELEASE([set mutableCopy]);
+}
++ (NSCharacterSet*)characterSetWithCharactersInString:(NSString*)aString
+{
+    NSCharacterSet *set = [super characterSetWithCharactersInString:aString];
+    return AUTORELEASE([set mutableCopy]);
+}
++ (NSCharacterSet*)characterSetWithRange:(NSRange)aRange
+{
+    NSCharacterSet *set = [super characterSetWithRange:aRange];
+    return AUTORELEASE([set mutableCopy]);
+}
+
+// Adding and Removing Characters
+
+- (void)addCharactersInRange:(NSRange)aRange
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (void)addCharactersInString:(NSString*)aString
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (void)removeCharactersInRange:(NSRange)aRange
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (void)removeCharactersInString:(NSString*)aString
+{
+    [self subclassResponsibility:_cmd];
+}
+
+// Combining Character Sets
+
+- (void)formIntersectionWithCharacterSet:(NSCharacterSet*)otherSet
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (void)formUnionWithCharacterSet:(NSCharacterSet*)otherSet
+{
+    [self subclassResponsibility:_cmd];
+}
+
+// Inverting a Character Set
+
+- (void)invert
+{
+    [self subclassResponsibility:_cmd];
+}
+
+// NSCopying
+
+- copyWithZone:(NSZone*)zone
+{
+    id data = [self bitmapRepresentation];
+    return RETAIN([NSCharacterSet characterSetWithBitmapRepresentation:data]);
+}
+
+// NSArchiving
+
+- (Class)classForCoder
+{
+    return [NSMutableCharacterSet class];
+}
+
+@end /* NSMutableCharacterSet */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSClassDescription.h b/libFoundation/Foundation/NSClassDescription.h
new file mode 100644 (file)
index 0000000..4ed2c2c
--- /dev/null
@@ -0,0 +1,63 @@
+/* 
+   NSClassDescription.h
+
+   Copyright (C) 2000, MDlink online service center GmbH, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSClassDescription_h__
+#define __NSClassDescription_h__
+
+#include <Foundation/NSObject.h>
+
+@class NSArray, NSString;
+
+LF_EXPORT NSString *NSClassDescriptionNeededForClassNotification;
+
+@interface NSClassDescription : NSObject
+
+/* registry */
+
++ (NSClassDescription *)classDescriptionForClass:(Class)_class;
++ (void)registerClassDescription:(NSClassDescription *)_clazzDesc
+  forClass:(Class)_class;
++ (void)invalidateClassDescriptionCache;
+
+/* accessors */
+
+- (NSArray *)attributeKeys;
+- (NSArray *)toManyRelationshipKeys;
+- (NSArray *)toOneRelationshipKeys;
+- (NSString *)inverseForRelationshipKey:(NSString *)_key;
+
+@end
+
+@interface NSObject(ClassDescriptionForwards)
+
+- (NSClassDescription *)classDescription;
+
+- (NSArray *)attributeKeys;
+- (NSArray *)toManyRelationshipKeys;
+- (NSArray *)toOneRelationshipKeys;
+- (NSString *)inverseForRelationshipKey:(NSString *)_key;
+
+@end
+
+#endif /* __NSClassDescription_h__ */
diff --git a/libFoundation/Foundation/NSClassDescription.m b/libFoundation/Foundation/NSClassDescription.m
new file mode 100644 (file)
index 0000000..82e07df
--- /dev/null
@@ -0,0 +1,132 @@
+/* 
+   NSClassDescription.m
+
+   Copyright (C) 2000, MDlink online service center GmbH, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSClassDescription.h>
+#include <Foundation/NSNotification.h>
+#include <Foundation/NSString.h>
+#include <common.h>
+
+LF_DECLARE NSString *NSClassDescriptionNeededForClassNotification =
+  @"NSClassDescriptionNeededForClass";
+
+@implementation NSClassDescription
+
+static NSMapTable *classToDesc  = NULL; // THREAD
+
++ (void)initialize
+{
+  if (classToDesc == NULL) {
+    classToDesc = NSCreateMapTable(NSObjectMapKeyCallBacks,
+                                   NSObjectMapValueCallBacks,
+                                   32);
+  }
+}
+
+/* registry */
+
++ (NSClassDescription *)classDescriptionForClass:(Class)_class
+{
+  NSClassDescription *d;
+  
+  if ((d = NSMapGet(classToDesc, _class)))
+    return d;
+
+  [[NSNotificationCenter defaultCenter]
+                         postNotificationName:
+                           NSClassDescriptionNeededForClassNotification
+                         object:_class];
+  
+  return NSMapGet(classToDesc, _class);
+}
+
++ (void)registerClassDescription:(NSClassDescription *)_clazzDesc
+  forClass:(Class)_class
+{
+  if (_clazzDesc == nil)
+    return;
+
+  if (_class)
+    NSMapInsert(classToDesc,  _class, _clazzDesc);
+}
+
++ (void)invalidateClassDescriptionCache
+{
+  NSResetMapTable(classToDesc);
+}
+
+/* accessors */
+
+- (NSArray *)attributeKeys
+{
+  return nil;
+}
+
+- (NSArray *)toManyRelationshipKeys
+{
+  return nil;
+}
+- (NSArray *)toOneRelationshipKeys
+{
+  return nil;
+}
+- (NSString *)inverseForRelationshipKey:(NSString *)_key
+{
+  return nil;
+}
+
+@end /* NSClassDescription */
+
+@implementation NSObject(ClassDescriptionForwards)
+
+static Class NSClassDescriptionClass = Nil;
+
+- (NSClassDescription *)classDescription
+{
+  if (NSClassDescriptionClass == Nil)
+    NSClassDescriptionClass = [NSClassDescription class];
+  
+  return [NSClassDescriptionClass classDescriptionForClass:[self class]];
+}
+
+- (NSArray *)attributeKeys
+{
+  return [[self classDescription] attributeKeys];
+}
+
+- (NSArray *)toManyRelationshipKeys
+{
+  return [[self classDescription] toManyRelationshipKeys];
+}
+
+- (NSArray *)toOneRelationshipKeys
+{
+  return [[self classDescription] toOneRelationshipKeys];
+}
+
+- (NSString *)inverseForRelationshipKey:(NSString *)_key
+{
+  return [[self classDescription] inverseForRelationshipKey:_key];
+}
+
+@end /* NSObject(ClassDescriptionForwards) */
diff --git a/libFoundation/Foundation/NSClassicException.h b/libFoundation/Foundation/NSClassicException.h
new file mode 100644 (file)
index 0000000..8eb5bb6
--- /dev/null
@@ -0,0 +1,315 @@
+/* 
+   NSClassicException.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSException_h__
+#define __NSException_h__
+
+#include <setjmp.h>
+#include <stdarg.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSArray.h>
+
+@interface NSException : NSObject
+{
+    NSString*  name;
+    NSString*  reason;
+    NSDictionary* userInfo;
+}
+
+/* Class initalization */
++ (void)taskNowMultiThreaded:notification;
+
+/* Creating and Raising Exceptions */
++ (NSException*)exceptionWithName:(NSString*)name
+    reason:(NSString*)reason
+    userInfo:(NSDictionary*)userInfo;
++ (void)raise:(NSString *)name
+    format:(NSString *)format,...;
++ (void)raise:(NSString*)name
+    format:(NSString*)format
+    arguments:(va_list)argList;
+
+- (id)initWithName:(NSString*)name
+    reason:(NSString*)reason
+    userInfo:(NSDictionary*)userInfo;
+- (void)raise;
+
+/* Querying Exceptions */
+- (NSString*)name;
+- (NSString*)reason;
+- (NSDictionary*)userInfo;
+
+@end /* NSException */
+
+
+@interface NSException (Extensions)
+- (BOOL)exceptionIsKindOfClass:(Class)class;
+                               /* return [self isKindOfClass:class] */
+- (BOOL)exceptionIsIn:(NSArray*)exceptions;
+- (NSString*)errorString;
+- initWithFormat:(NSString*)format, ...;
+- setName:(NSString*)name;
+- setReason:(NSString*)reason;
+- setUserInfo:(NSDictionary*)userInfo;
+@end /* NSException (Extension) */
+
+
+typedef void NSUncaughtExceptionHandler(NSException *exception);
+
+NSUncaughtExceptionHandler *NSGetUncaughtExceptionHandler(void);
+void NSSetUncaughtExceptionHandler(NSUncaughtExceptionHandler *handler);
+
+/* Exception names */
+LF_EXPORT NSString *NSInconsistentArchiveException;
+LF_EXPORT NSString *NSGenericException;
+LF_EXPORT NSString *NSInternalInconsistencyException;
+LF_EXPORT NSString *NSInvalidArgumentException;
+LF_EXPORT NSString *NSMallocException;
+LF_EXPORT NSString *NSObjectInaccessibleException;
+LF_EXPORT NSString *NSObjectNotAvailableException;
+LF_EXPORT NSString *NSDestinationInvalidException;
+LF_EXPORT NSString *NSPortTimeoutException;
+LF_EXPORT NSString *NSInvalidSendPortException;
+LF_EXPORT NSString *NSInvalidReceivePortException;
+LF_EXPORT NSString *NSPortSendException;
+LF_EXPORT NSString *NSPortReceiveException;
+LF_EXPORT NSString *NSOldStyleException;
+LF_EXPORT NSString *NSRangeException;
+
+
+typedef struct _NSHandler
+{
+    struct _NSHandler* previousHandler;
+    jmp_buf            jmpState;
+    NSException*       exception;
+} NSHandler;
+
+LF_EXPORT void _NSAddHandler(NSHandler *handler);
+LF_EXPORT void _NSRemoveHandler(NSHandler *handler);
+
+/*  OpenStep macros for exception handling. */
+
+#define NS_DURING \
+({ \
+    __label__ _quit; \
+    NSHandler exceptionHandler; \
+    if(!setjmp(exceptionHandler.jmpState)) { \
+       _NSAddHandler(&exceptionHandler);
+
+#define NS_HANDLER \
+       _NSRemoveHandler(&exceptionHandler); \
+       goto _quit; /* to remove compiler warning about unused label*/ \
+    } \
+    else { \
+       NSException* localException = exceptionHandler.exception; \
+       _NSRemoveHandler(&exceptionHandler); \
+
+#define NS_ENDHANDLER \
+       localException = nil; /* Avoid compiler warning */ \
+    } \
+_quit: 0;\
+});
+
+#define NS_VALRETURN(value) \
+    ({_NSRemoveHandler(&exceptionHandler); return (value);})
+
+#define NS_VOIDRETURN \
+    ({_NSRemoveHandler(&exceptionHandler); return;})
+
+
+/*
+ * The new macros for handling exceptions.
+ */
+
+#define TRY \
+({ \
+    __label__ _quit; \
+    NSHandler exceptionHandler; \
+    volatile int __setjmp_ret = setjmp(exceptionHandler.jmpState); \
+    if(!__setjmp_ret) { \
+       _NSAddHandler(&exceptionHandler);
+
+#define END_TRY \
+       _NSRemoveHandler(&exceptionHandler); \
+       goto _quit; /* to remove compiler warning about unused label */ \
+    } \
+_quit: \
+    { \
+       void handler(NSException* localException) \
+       { \
+           BOOL _caught = NO; \
+           if(localException) \
+               _NSRemoveHandler(&exceptionHandler); \
+           if(!localException) {
+
+#define CATCH(exception_class) \
+           } else if([localException isKindOfClass:[exception_class class]]) { \
+               _caught = YES;
+
+#ifndef PRECOMP
+# define MULTICATCH(exception_classes...) \
+           } else if([localException exceptionIsIn: \
+                   [NSArray arrayWithObjects:##exception_classes, nil]]) { \
+               _caught = YES;
+#endif /* PRECOMP */
+
+#define OTHERWISE \
+           } else { \
+               _caught = YES;
+
+#define CLEANUP \
+           } \
+           if(localException && !_caught) {
+
+#define FINALLY \
+           } \
+           if(1) {
+
+#define END_CATCH \
+           } \
+           if(!localException) return; \
+           if(!_caught) \
+               [localException raise]; \
+           else RELEASE(localException); \
+       } \
+       handler(__setjmp_ret == 1 ? exceptionHandler.exception : nil); \
+    } \
+});
+
+    /*  Use BREAK inside a TRY block to get out of it */
+#define BREAK  ({_NSRemoveHandler(&exceptionHandler); goto _quit;})
+
+#ifndef PRECOMP
+    /*  If you want to generate an exception issue a THROW with the exception
+       an object derived from the NSException class. */
+# define THROW(exception...)   [##exception raise]
+#else
+# define THROW(exception)              [exception raise]
+#endif /* PRECOMP */
+
+    /*  If you want to reraise an exception inside an exception handler
+       just say RERAISE. */
+#define RERAISE                 THROW(localException)
+
+
+/*
+ * Assertions.
+ */
+
+#ifndef __FoundationException_definition__
+#define __FoundationException_definition__
+
+@interface FoundationException : NSException
+@end
+
+#endif /* __FoundationException_definition__ */
+
+@interface AssertException : FoundationException
+@end
+
+
+@interface NSAssertionHandler : NSObject
+
+/* Getting the Current Handler */
++ (NSAssertionHandler*)currentHandler;
+
+/* Handling Failures */
+- (void)handleFailureInFunction:(NSString*)functionName
+    file:(NSString*)fileName
+    lineNumber:(int)line
+    description:(NSString*)format,...;
+- (void)handleFailureInMethod:(SEL)selector
+    object:(id)object
+    file:(NSString*)fileName
+    lineNumber:(int)line
+    description:(NSString*)format,...;
+
+@end
+
+#ifndef PRECOMP
+
+#define NSAssert(condition, desc, arguments...) \
+    ({ if(!(condition)) \
+           [[NSAssertionHandler currentHandler] \
+                   handleFailureInMethod:_cmd \
+                   object:self \
+                   file:[NSString stringWithCString:__FILE__] \
+                   lineNumber:__LINE__ \
+                   description:(desc) , ##arguments]; \
+    0;})
+
+#define NSCAssert(condition, desc, arguments...) \
+    ({ if(!(condition)) \
+           [[NSAssertionHandler currentHandler] \
+                   handleFailureInFunction: \
+                       [NSString stringWithCString:__PRETTY_FUNCTION__] \
+                   file:[NSString stringWithCString:__FILE__] \
+                   lineNumber:__LINE__ \
+                   description:(desc) , ##arguments]; \
+    0;})
+
+#define Assert(condition) \
+    ({if(!(condition)) {\
+       NSLog([(@#condition) stringByPrependingString:@"Assertion failed: "]); \
+       THROW([AssertException new]); \
+    } \
+    0;})
+
+# define NSParameterAssert(condition) \
+    ({if(!(condition)) {\
+       NSLog([(@#condition) stringByPrependingString:@"Parameter Assertion failed: "]); \
+       THROW([AssertException new]); \
+    } \
+    0;})
+
+# define NSCParameterAssert(condition) \
+    ({if(!(condition)) {\
+       NSLog([(@#condition) stringByPrependingString:@"Parameter Assertion failed: "]); \
+       THROW([AssertException new]); \
+    } \
+    0;})
+
+#define NSAssert1(args...)     NSAssert(##args)
+#define NSAssert2(args...)     NSAssert(##args)
+#define NSAssert3(args...)     NSAssert(##args)
+#define NSAssert4(args...)     NSAssert(##args)
+#define NSAssert5(args...)     NSAssert(##args)
+
+#define NSCAssert1(args...)    NSCAssert(##args)
+#define NSCAssert2(args...)    NSCAssert(##args)
+#define NSCAssert3(args...)    NSCAssert(##args)
+#define NSCAssert4(args...)    NSCAssert(##args)
+#define NSCAssert5(args...)    NSCAssert(##args)
+
+#endif /* PRECOMP */
+
+
+#endif /* __NSException_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSCoder.h b/libFoundation/Foundation/NSCoder.h
new file mode 100644 (file)
index 0000000..f0793b9
--- /dev/null
@@ -0,0 +1,87 @@
+/* 
+   NSCoder.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSCoder_h__
+#define __NSCoder_h__
+
+#include <Foundation/NSObject.h>
+#include <Foundation/NSGeometry.h>
+
+@class NSData;
+
+@interface NSCoder : NSObject
+
+/* Encoding Data */
+- (void)encodeArrayOfObjCType:(const char*)types       
+       count:(unsigned int)count
+       at:(const void*)array;
+- (void)encodeBycopyObject:(id)anObject;
+- (void)encodeConditionalObject:(id)anObject;
+- (void)encodeDataObject:(NSData*)data;
+- (void)encodeObject:(id)anObject;
+- (void)encodePropertyList:(id)aPropertyList;
+- (void)encodeRootObject:(id)rootObject;
+- (void)encodeValueOfObjCType:(const char*)type
+       at:(const void*)address;
+- (void)encodeValuesOfObjCTypes:(const char*)types, ...;
+
+/* Encoding geometry types */
+- (void)encodePoint:(NSPoint)point;
+- (void)encodeSize:(NSSize)size;
+- (void)encodeRect:(NSRect)rect;
+
+/* Decoding Data */
+- (void)decodeArrayOfObjCType:(const char*)types
+       count:(unsigned)count
+       at:(void*)address;
+- (NSData*)decodeDataObject;
+- (id)decodeObject;
+- (id)decodePropertyList;
+- (void)decodeValueOfObjCType:(const char*)type
+       at:(void*)address;
+- (void)decodeValuesOfObjCTypes:(const char*)types, ...;
+
+/* Decoding geometry types */
+- (NSPoint)decodePoint;
+- (NSSize)decodeSize;
+- (NSRect)decodeRect;
+
+/* Managing Zones */
+- (NSZone*)objectZone;
+- (void)setObjectZone:(NSZone*)zone;
+
+/* Getting a Version */
+- (unsigned int)systemVersion;
+- (unsigned int)versionForClassName:(NSString*)className;
+
+@end
+
+#endif /* __NSCoder_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSCoder.m b/libFoundation/Foundation/NSCoder.m
new file mode 100644 (file)
index 0000000..fbb5728
--- /dev/null
@@ -0,0 +1,212 @@
+/* 
+   NSCoder.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include "common.h"
+
+#include <Foundation/NSCoder.h>
+#include <Foundation/NSZone.h>
+#include <extensions/objc-runtime.h>
+
+@implementation NSCoder
+
+- (void)encodeArrayOfObjCType:(const char*)types
+       count:(unsigned int)count
+       at:(const void*)array
+{
+    unsigned int i, offset, item_size = objc_sizeof_type(types);
+    IMP imp = [self methodForSelector:@selector(encodeValueOfObjCType:at:)];
+
+    for(i = offset = 0; i < count; i++, offset += item_size) {
+        (*imp)(self, @selector(encodeValueOfObjCType:at:),
+               types, (char*)array + offset);
+       types = objc_skip_typespec(types);
+       item_size = objc_sizeof_type(types);
+    }
+}
+
+- (void)encodeBycopyObject:(id)anObject
+{
+    [self encodeObject:anObject];
+}
+
+- (void)encodeConditionalObject:(id)anObject
+{
+    [self encodeObject:anObject];
+}
+
+- (void)encodeDataObject:(NSData*)data
+{
+    [self encodeObject:data];
+}
+
+- (void)encodeObject:(id)anObject
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (void)encodePropertyList:(id)aPropertyList
+{
+    [self encodeObject:aPropertyList];
+}
+
+- (void)encodeRootObject:(id)rootObject
+{
+    [self encodeObject:rootObject];
+}
+
+- (void)encodeValueOfObjCType:(const char*)type
+       at:(const void*)address
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (void)encodeValuesOfObjCTypes:(const char*)types, ...
+{
+    va_list ap;
+    IMP imp = [self methodForSelector:@selector(encodeValueOfObjCType:at:)];
+    
+    va_start(ap, types);
+    for(; types && *types; types = objc_skip_typespec(types)) {
+        (*imp)(self, @selector(encodeValueOfObjCType:at:),
+               types, va_arg(ap, void*));
+    }
+    va_end(ap);
+}
+
+- (void)encodePoint:(NSPoint)point
+{
+    [self encodeValueOfObjCType:@encode(NSPoint) at:&point];
+}
+
+- (void)encodeSize:(NSSize)size
+{
+    [self encodeValueOfObjCType:@encode(NSSize) at:&size];
+}
+
+- (void)encodeRect:(NSRect)rect
+{
+    [self encodeValueOfObjCType:@encode(NSRect) at:&rect];
+}
+
+- (void)decodeArrayOfObjCType:(const char*)types
+       count:(unsigned)count
+       at:(void*)address
+{
+    unsigned i, offset, item_size = objc_sizeof_type(types);
+    IMP imp = [self methodForSelector:@selector(decodeValueOfObjCType:at:)];
+
+    for(i = offset = 0; i < count; i++, offset += item_size) {
+        (*imp)(self, @selector(decodeValueOfObjCType:at:),
+               types, (char*)address + offset);
+       types = objc_skip_typespec(types);
+       item_size = objc_sizeof_type(types);
+    }
+}
+
+- (NSData*)decodeDataObject
+{
+    return [self decodeObject];
+}
+
+- (id)decodeObject
+{
+    return [self subclassResponsibility:_cmd];
+}
+
+- (id)decodePropertyList
+{
+    return [self decodeObject];
+}
+
+- (void)decodeValueOfObjCType:(const char*)type
+       at:(void*)address
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (void)decodeValuesOfObjCTypes:(const char*)types, ...
+{
+    va_list ap;
+    IMP imp = [self methodForSelector:@selector(decodeValueOfObjCType:at:)];
+
+    va_start(ap, types);
+    for(;types && *types; types = objc_skip_typespec(types))
+        (*imp)(self, @selector(decodeValueOfObjCType:at:),
+               types, va_arg(ap, void*));
+    va_end(ap);
+}
+
+- (NSPoint)decodePoint
+{
+    NSPoint point;
+
+    [self decodeValueOfObjCType:@encode(NSPoint) at:&point];
+    return point;
+}
+
+- (NSSize)decodeSize
+{
+    NSSize size;
+
+    [self decodeValueOfObjCType:@encode(NSSize) at:&size];
+    return size;
+}
+
+- (NSRect)decodeRect
+{
+    NSRect rect;
+
+    [self decodeValueOfObjCType:@encode(NSRect) at:&rect];
+    return rect;
+}
+
+- (NSZone*)objectZone
+{
+    return NSDefaultMallocZone();
+}
+
+- (void)setObjectZone:(NSZone*)zone
+{
+}
+
+- (unsigned int)systemVersion
+{
+    [self notImplemented:_cmd];
+    return 0;
+}
+
+- (unsigned int)versionForClassName:(NSString*)className
+{
+    [self subclassResponsibility:_cmd];
+    return 0;
+}
+
+@end /* NSCoder */
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSComparisonPredicate.h b/libFoundation/Foundation/NSComparisonPredicate.h
new file mode 100644 (file)
index 0000000..73536f9
--- /dev/null
@@ -0,0 +1,103 @@
+/* 
+   NSComparisonPredicate.h
+
+   Copyright (C) 2005, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@opengroupware.org>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSComparisonPredicate_H__
+#define __NSComparisonPredicate_H__
+
+#include <Foundation/NSPredicate.h>
+
+@class NSExpression;
+
+typedef enum {
+    NSDirectPredicateModifier = 0,
+    NSAllPredicateModifier,
+    NSAnyPredicateModifier
+} NSComparisonPredicateModifier;
+
+typedef enum {
+    NSLessThanPredicateOperatorType = 0,
+    NSLessThanOrEqualToPredicateOperatorType,
+    NSGreaterThanPredicateOperatorType,
+    NSGreaterThanOrEqualToPredicateOperatorType,
+    NSEqualToPredicateOperatorType,
+    NSNotEqualToPredicateOperatorType,
+    NSMatchesPredicateOperatorType,
+    NSLikePredicateOperatorType,
+    NSBeginsWithPredicateOperatorType,
+    NSEndsWithPredicateOperatorType,
+    NSInPredicateOperatorType,
+    NSCustomSelectorPredicateOperatorType
+} NSPredicateOperatorType;
+
+typedef enum {
+    NSCaseInsensitivePredicateOptions     = 0x01,
+    NSDiacriticInsensitivePredicateOption = 0x02
+} NSComparisonPredicateOptions;
+
+@interface NSComparisonPredicate : NSPredicate
+{
+    NSExpression *lhs;
+    NSExpression *rhs;
+    SEL          operator;
+}
+
++ (NSPredicate *)predicateWithLeftExpression:(NSExpression *)_lhs
+  rightExpression:(NSExpression *)_rhs
+  customSelector:(SEL)_selector;
++ (NSPredicate *)predicateWithLeftExpression:(NSExpression *)_lhs
+  rightExpression:(NSExpression *)_rhs
+  modifier:(NSComparisonPredicateModifier)_modifier
+  type:(NSPredicateOperatorType)_type
+  options:(unsigned)_options;
+
+- (id)initWithLeftExpression:(NSExpression *)_lhs
+  rightExpression:(NSExpression *)_rhs
+  customSelector:(SEL)_selector;
+- (id)initWithLeftExpression:(NSExpression *)_lhs
+  rightExpression:(NSExpression *)_rhs
+  modifier:(NSComparisonPredicateModifier)_modifier
+  type:(NSPredicateOperatorType)_type
+  options:(unsigned)_options;
+
+/* accessors */
+
+- (NSExpression *)leftExpression;
+- (NSExpression *)rightExpression;
+
+- (SEL)customSelector;
+
+- (NSComparisonPredicateModifier)comparisonPredicateModifier;
+- (NSPredicateOperatorType)predicateOperatorType;
+- (unsigned)options;
+
+@end
+
+#endif /* __NSComparisonPredicate_H__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSComparisonPredicate.m b/libFoundation/Foundation/NSComparisonPredicate.m
new file mode 100644 (file)
index 0000000..cb0ae83
--- /dev/null
@@ -0,0 +1,125 @@
+/* 
+   NSComparisonPredicate.m
+
+   Copyright (C) 2005, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@opengroupware.org>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include "NSComparisonPredicate.h"
+#include "NSExpression.h"
+#include "common.h"
+
+@implementation NSComparisonPredicate
+
++ (NSPredicate *)predicateWithLeftExpression:(NSExpression *)_lhs
+  rightExpression:(NSExpression *)_rhs
+  customSelector:(SEL)_selector
+{
+    return [[[self alloc] initWithLeftExpression:_lhs rightExpression:_rhs
+                         customSelector:_selector] autorelease];
+}
+
++ (NSPredicate *)predicateWithLeftExpression:(NSExpression *)_lhs
+  rightExpression:(NSExpression *)_rhs
+  modifier:(NSComparisonPredicateModifier)_modifier
+  type:(NSPredicateOperatorType)_type
+  options:(unsigned)_options
+{
+    return [[[self alloc] initWithLeftExpression:_lhs rightExpression:_rhs
+                         modifier:_modifier type:_type 
+                         options:_options] autorelease];
+}
+
+- (id)initWithLeftExpression:(NSExpression *)_lhs
+  rightExpression:(NSExpression *)_rhs
+  customSelector:(SEL)_selector
+{
+    if ((self = [super init]) != nil) {
+       self->lhs      = [_lhs retain];
+       self->rhs      = [_rhs retain];
+       self->operator = _selector;
+    }
+    return self;
+}
+
+- (id)initWithLeftExpression:(NSExpression *)_lhs
+  rightExpression:(NSExpression *)_rhs
+  modifier:(NSComparisonPredicateModifier)_modifier
+  type:(NSPredicateOperatorType)_type
+  options:(unsigned)_options
+{
+    return [self notImplemented:_cmd];
+}
+
+- (id)init
+{
+    return [self initWithLeftExpression:nil rightExpression:nil
+                customSelector:NULL];
+}
+
+- (void)dealloc
+{
+    [self->lhs release];
+    [self->rhs release];
+    [super dealloc];
+}
+
+/* accessors */
+
+- (NSExpression *)leftExpression
+{
+    return self->lhs;
+}
+- (NSExpression *)rightExpression
+{
+    return self->rhs;
+}
+
+- (SEL)customSelector
+{
+    return self->operator;
+}
+
+- (NSComparisonPredicateModifier)comparisonPredicateModifier
+{
+    // TODO
+    return 0;
+}
+
+- (NSPredicateOperatorType)predicateOperatorType
+{
+    // TODO
+    return 0;
+}
+
+- (unsigned)options
+{
+    // TODO
+    return 0;
+}
+
+@end /* NSComparisonPredicate */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSCompoundPredicate.h b/libFoundation/Foundation/NSCompoundPredicate.h
new file mode 100644 (file)
index 0000000..88fc3e8
--- /dev/null
@@ -0,0 +1,63 @@
+/* 
+   NSCompoundPredicate.h
+
+   Copyright (C) 2005, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@opengroupware.org>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSCompoundPredicate_H__
+#define __NSCompoundPredicate_H__
+
+#include <Foundation/NSPredicate.h>
+
+@class NSArray;
+
+typedef enum {
+    NSNotPredicateType = 0,
+    NSAndPredicateType,
+    NSOrPredicateType
+} NSCompoundPredicateType;
+
+@interface NSCompoundPredicate : NSPredicate
+{
+    NSCompoundPredicateType type;
+    NSArray *subs;
+}
+
++ (NSPredicate *)andPredicateWithSubpredicates:(NSArray *)_subs;
++ (NSPredicate *)orPredicateWithSubpredicates:(NSArray *)_subs;
++ (NSPredicate *)notPredicateWithSubpredicates:(NSArray *)_subs;
+- (id)initWithType:(NSCompoundPredicateType)_type subpredicates:(NSArray *)_s;
+
+/* accessors */
+
+- (NSCompoundPredicateType)compoundPredicateType;
+- (NSArray *)subpredicates;
+
+@end
+
+#endif /* __NSCompoundPredicate_H__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSCompoundPredicate.m b/libFoundation/Foundation/NSCompoundPredicate.m
new file mode 100644 (file)
index 0000000..f365db2
--- /dev/null
@@ -0,0 +1,127 @@
+/* 
+   NSCompoundPredicate.m
+
+   Copyright (C) 2005, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@opengroupware.org>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include "NSCompoundPredicate.h"
+#include "NSArray.h"
+#include "NSCoder.h"
+#include "common.h"
+
+@implementation NSCompoundPredicate
+
++ (NSPredicate *)andPredicateWithSubpredicates:(NSArray *)_subs
+{
+    return [[[self alloc] initWithType:NSAndPredicateType subpredicates:_subs]
+              autorelease];
+}
++ (NSPredicate *)orPredicateWithSubpredicates:(NSArray *)_subs
+{
+    return [[[self alloc] initWithType:NSOrPredicateType subpredicates:_subs]
+              autorelease];
+}
++ (NSPredicate *)notPredicateWithSubpredicates:(NSArray *)_subs
+{
+    return [[[self alloc] initWithType:NSNotPredicateType subpredicates:_subs] 
+              autorelease];
+}
+
+- (id)initWithType:(NSCompoundPredicateType)_type subpredicates:(NSArray *)_s
+{
+    if ((self = [super init]) != nil) {
+    }
+    return self;
+}
+- (id)init
+{
+    return [self initWithType:NSNotPredicateType subpredicates:nil];
+}
+
+- (void)dealloc
+{
+    [self->subs release];
+    [super dealloc];
+}
+
+/* accessors */
+
+- (NSCompoundPredicateType)compoundPredicateType
+{
+    return self->type;
+}
+
+- (NSArray *)subpredicates
+{
+    return self->subs;
+}
+
+/* evaluation */
+
+- (BOOL)evaluateWithObject:(id)_object
+{
+    unsigned i, count;
+    
+    for (i = 0, count = [self->subs count]; i < count; i++) {
+       BOOL ok;
+       
+       ok = [[self->subs objectAtIndex:i] evaluateWithObject:_object];
+       
+       /* Note: we treat NOT as a "AND (NOT x)*" */
+       if (self->type == NSNotPredicateType)
+           ok = ok ? NO : YES;
+       
+       if (self->type == NSOrPredicateType) {
+           if (ok) return YES; /* short circuit */
+       }
+       else { /* AND or AND-NOT */
+           if (!ok) return NO; /* short circuit */
+       }
+    }
+    
+    return YES; /* TOD: empty == YES? */
+}
+
+/* NSCoding */
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+    [super encodeWithCoder:aCoder];
+    [aCoder encodeValueOfObjCType:@encode(int) at:&(self->type)];
+    [aCoder encodeObject:self->subs];
+}
+- (id)initWithCoder:(NSCoder*)aDecoder
+{
+    if ((self = [super initWithCoder:aDecoder]) != nil) {
+       [aDecoder decodeValueOfObjCType:@encode(int) at:&(self->type)];
+       self->subs = [[aDecoder decodeObject] retain];
+    }
+    return self;
+}
+
+@end /* NSCompoundPredicate */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConcreteArray.h b/libFoundation/Foundation/NSConcreteArray.h
new file mode 100644 (file)
index 0000000..52971d4
--- /dev/null
@@ -0,0 +1,140 @@
+/* 
+   NSConcreteArray.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSConcreteArray_h__
+#define __NSConcreteArray_h__
+
+#include <Foundation/NSObject.h>
+#include <Foundation/NSRange.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSEnumerator.h>
+
+@class NSString;
+
+/*
+ * NSConcreteArray class
+ */
+
+@interface NSConcreteArray : NSArray
+{
+    id         *items;         // data of the array object
+    unsigned int itemsCount;   // Actual number of elements
+}
+
+- (id)init;
+- (id)initWithObjects:(id *)objects count:(unsigned int)count;
+- (id)initWithArray:(NSArray *)anotherArray;
+- (void)dealloc;
+
+- (id)objectAtIndex:(unsigned int)index;
+- (unsigned int)count;
+- (unsigned int)indexOfObjectIdenticalTo:(id)anObject;
+
+@end
+
+/*
+ * NSConcreteArray class
+ */
+
+@interface NSConcreteEmptyArray : NSArray
+{
+}
+
+- (id)init;
+- (id)initWithObjects:(id *)objects count:(unsigned int)count;
+- (id)initWithArray:(NSArray *)anotherArray;
+
+- (id)objectAtIndex:(unsigned int)index;
+- (unsigned int)count;
+- (unsigned int)indexOfObjectIdenticalTo:(id)anObject;
+
+@end
+
+/*
+ * NSConcreteSingleObjectArray class
+ */
+
+@interface NSConcreteSingleObjectArray : NSArray
+{
+    id item;
+}
+
+- (id)init;
+- (id)initWithObjects:(id *)objects count:(unsigned int)count;
+- (id)initWithArray:(NSArray *)anotherArray;
+
+- (id)objectAtIndex:(unsigned int)index;
+- (unsigned int)count;
+- (unsigned int)indexOfObjectIdenticalTo:(id)anObject;
+
+@end
+
+/*
+ * NSConcreteMutableArray class
+ */
+
+@interface NSConcreteMutableArray : NSMutableArray
+{
+    id         *items;         // data of the array object
+    unsigned   itemsCount;     // Actual number of elements
+    unsigned   maxItems;       // Maximum number of elements
+}
+
+- (id)init;
+- (id)initWithCapacity:(unsigned int)aNumItems;
+- (id)initWithObjects:(id *)objects count:(unsigned int)count;
+
+- (void)insertObject:(id)anObject atIndex:(unsigned int)index;
+- (void)replaceObjectAtIndex:(unsigned int)index withObject:(id)anObject;
+- (void)removeAllObjects;
+- (void)removeLastObject;
+- (void)removeObjectAtIndex:(unsigned int)index;
+- (void)removeObjectsFrom:(unsigned int)index count:(unsigned int)count;
+
+@end
+
+/*
+ * NSArrayEnumerator class
+ */
+
+@interface _NSArrayEnumerator : NSEnumerator
+{
+       NSArray *array;
+       unsigned int index;
+       BOOL reverse;
+}
+
+- (id)initWithArray:(NSArray*)anArray reverse:(BOOL)isReverse;
+- (id)nextObject;
+
+@end
+
+#endif /* __NSConcreteArray_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConcreteArray.m b/libFoundation/Foundation/NSConcreteArray.m
new file mode 100644 (file)
index 0000000..9a36091
--- /dev/null
@@ -0,0 +1,563 @@
+/* 
+   NSConcreteArray.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <stdio.h>
+
+#include <Foundation/common.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSException.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+
+#include <extensions/objc-runtime.h>
+
+#include "NSConcreteArray.h"
+
+#define DO_NOT_USE_ZONE 1
+
+static NSConcreteEmptyArray *sharedEmptyArray = nil;
+
+/*
+ * NSConcreteArray class
+ */
+
+@implementation NSConcreteArray
+
++ (void)initialize
+{
+    if (sharedEmptyArray == nil)
+        sharedEmptyArray = [[NSConcreteEmptyArray alloc] init];
+}
+
+- (id)init
+{
+    RELEASE(self);
+    return RETAIN(sharedEmptyArray);
+}
+
+- (id)initWithObjects:(id *)objects count:(unsigned int)count
+{
+    unsigned i;
+
+    if (count == 0) {
+        RELEASE(self);
+        return RETAIN(sharedEmptyArray);
+    }
+    else if (count == 1) {
+        RELEASE(self);
+        return [[NSConcreteSingleObjectArray alloc]
+                                             initWithObjects:objects count:1];
+    }
+    
+#if DO_NOT_USE_ZONE
+    self->items      = calloc(count, sizeof(id));
+#else
+    self->items      = NSZoneCalloc([self zone], sizeof(id), count);
+#endif
+    self->itemsCount = count;
+    for (i = 0; i < count; i++) {
+       if (!(self->items[i] = RETAIN(objects[i]))) {
+           [[[InvalidArgumentException alloc] 
+                   initWithReason:@"Nil object to be added in array"] raise];
+        }
+    }
+    return self;
+}
+
+- (id)initWithArray:(NSArray *)anotherArray
+{
+    unsigned i, count = [anotherArray count];
+
+    if (count == 0) {
+        RELEASE(self);
+        return RETAIN(sharedEmptyArray);
+    }
+    else if (count == 1) {
+        id item = [anotherArray objectAtIndex:0];
+        
+        RELEASE(self);
+        return [[NSConcreteSingleObjectArray alloc]
+                                             initWithObjects:&item count:1];
+    }
+    
+#if DO_NOT_USE_ZONE
+    self->items = calloc(count, sizeof(id));
+#else
+    self->items = NSZoneCalloc([self zone], sizeof(id), count);
+#endif
+    self->itemsCount = count;
+    for (i = 0; i < itemsCount; i++)
+       self->items[i] = RETAIN([anotherArray objectAtIndex:i]);
+    return self;
+}
+
+- (void)dealloc
+{
+    register signed int index; // Note: this limits the size of the array
+    
+    if ((index = self->itemsCount) > 0) {
+       /* 
+          Not using static cache because the array content is only similiar
+          inside a single collection, not across collections (arrays being
+          used in various contexts).
+          Hitrate of the cache is about 75% (including initial miss).
+       */
+       register Class LastClass  = Nil;
+       register IMP   objRelease = NULL;
+       
+       for (index--; index >= 0; index--) {
+           // TODO: cache RELEASE IMP
+#if LIB_FOUNDATION_BOEHM_GC
+           self->items[index] = nil;
+#else
+           register id obj = self->items[index];
+           
+           if (*(id *)obj != LastClass) {
+               LastClass = *(id *)obj;
+               objRelease = method_get_imp(object_is_instance(obj)
+                  ? class_get_instance_method(LastClass, @selector(release))
+                 : class_get_class_method(LastClass, @selector(release)));
+           }
+           
+           objRelease(obj, NULL /* dangerous? */);
+       }
+#endif
+    }
+    
+#if DO_NOT_USE_ZONE
+    if (self->items) free(self->items);
+#else
+    lfFree(self->items);
+#endif
+    [super dealloc];
+}
+
+/* Querying the Array */
+
+- (id)objectAtIndex:(unsigned int)index
+{
+    if (index >= self->itemsCount) {
+       [[[RangeException alloc] 
+               initWithReason:@"objectAtIndex: in NSArray" 
+               size:self->itemsCount index:index] raise];
+    }
+    return self->items[index];
+}
+
+- (unsigned int)count
+{
+    return self->itemsCount;
+}
+
+- (unsigned int)indexOfObjectIdenticalTo:(id)anObject
+{
+    unsigned i;
+    
+    for (i = 0; i < self->itemsCount; i++) {
+       if (items[i] == anObject)
+               return i;
+    }
+    return NSNotFound;
+}
+
+@end /* NSConcreteArray */
+
+/*
+ * NSConcreteEmptyArray class
+ */
+
+@implementation NSConcreteEmptyArray
+
+- (id)init
+{
+    return self;
+}
+- (id)initWithObjects:(id *)objects count:(unsigned int)count
+{
+    if (count > 0) {
+        RELEASE(self);
+        self = [[NSConcreteArray alloc] initWithObjects:objects count:count];
+    }
+    return self;
+}
+- (id)initWithArray:(NSArray *)anotherArray
+{
+    if ([anotherArray count] > 0) {
+        id tmp;
+        tmp = [[NSConcreteArray alloc] initWithArray:anotherArray];
+        RELEASE(self);
+        return tmp;
+    }
+    return self;
+}
+
+- (id)objectAtIndex:(unsigned int)index
+{
+    [[[RangeException alloc] 
+              initWithReason:@"objectAtIndex: in NSArray" size:0 index:index] raise];
+    return nil;
+}
+- (unsigned int)count
+{
+    return 0;
+}
+- (unsigned int)indexOfObjectIdenticalTo:(id)anObject
+{
+    return NSNotFound;
+}
+
+@end /* NSConcreteEmptyArray */
+
+/*
+ * NSConcreteSingleObjectArray class
+ */
+
+@implementation NSConcreteSingleObjectArray
+
++ (void)initialize {
+    // force setup of shared emtpy
+    if (sharedEmptyArray == nil)
+        sharedEmptyArray = [[NSConcreteEmptyArray alloc] init];
+}
+
+- (id)init
+{
+    RELEASE(self);
+    return RETAIN(sharedEmptyArray);
+}
+- (id)initWithObjects:(id *)objects count:(unsigned int)count
+{
+    if (count == 0) {
+        RELEASE(self);
+        return RETAIN(sharedEmptyArray);
+    }
+    if (count > 1) {
+        RELEASE(self);
+        self = [[NSConcreteArray allocWithZone:[self zone]]
+                                 initWithObjects:objects count:count];
+    }
+    
+    if ((self->item = objects[0]) == nil) {
+        [[[InvalidArgumentException alloc] 
+                   initWithReason:@"Nil object to be added in array"] raise];
+    }
+    self->item = RETAIN(self->item);
+    return self;
+}
+- (id)initWithArray:(NSArray *)anotherArray
+{
+    unsigned count = [anotherArray count];
+    
+    if (count == 0) {
+        RELEASE(self);
+        return RETAIN(sharedEmptyArray);
+    }
+    if (count > 1) {
+        RELEASE(self);
+        self = [[NSConcreteArray alloc] initWithArray:anotherArray];
+    }
+    
+    if ((self->item = [anotherArray objectAtIndex:0]) == nil) {
+        [[[InvalidArgumentException alloc] 
+                   initWithReason:@"Nil object to be added in array"] raise];
+    }
+    self->item = RETAIN(self->item);
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(self->item);
+    [super dealloc];
+}
+
+// query array
+
+- (id)objectAtIndex:(unsigned int)index
+{
+    if (index > 0) {
+      [[[RangeException alloc] 
+                initWithReason:@"objectAtIndex: in NSArray" size:1 index:index] raise];
+    }
+    return self->item;
+}
+- (unsigned int)count
+{
+    return 1;
+}
+- (unsigned int)indexOfObjectIdenticalTo:(id)anObject
+{
+    return (self->item == anObject) ? 0 : NSNotFound;
+}
+
+@end /* NSConcreteSingleObjectArray */
+
+/*
+ * NSConcreteMutableArray class
+ */
+
+@implementation NSConcreteMutableArray
+
++ (void)initialize
+{
+    static BOOL initialized = NO;
+    if(!initialized) {
+       initialized = YES;
+       class_add_behavior(self, [NSConcreteArray class]);
+    }
+}
+
+- (id)init
+{
+#if DO_NOT_USE_ZONE
+    self->items = calloc(1, sizeof(id));
+#else
+    self->items = NSZoneCalloc([self zone], 1, sizeof(id));
+#endif
+    self->maxItems   = 1;
+    self->itemsCount = 0;
+    return self;
+}
+
+- (id)initWithCapacity:(unsigned int)aNumItems
+{
+    self->maxItems = aNumItems ? aNumItems : 16;
+#if DO_NOT_USE_ZONE
+    self->items = calloc(self->maxItems, sizeof(id));
+#else
+    self->items = NSZoneCalloc([self zone], sizeof(id), self->maxItems);
+#endif
+    self->itemsCount = 0;
+    return self;
+}
+
+- (id)initWithObjects:(id *)objects count:(unsigned int)count
+{
+    unsigned i;
+
+    if (count > 0) {
+        self->maxItems   = count;
+        self->itemsCount = count;
+    }
+    else {
+        self->maxItems   = 1;
+        self->itemsCount = 0;
+    }
+    
+#if DO_NOT_USE_ZONE
+    self->items = calloc(self->maxItems, sizeof(id));
+#else
+    self->items = NSZoneCalloc([self zone], sizeof(id), self->maxItems);
+#endif
+
+    for (i = 0; i < count; i++) {
+       if ((self->items[i] = RETAIN(objects[i])) == nil) {
+           [[[InvalidArgumentException alloc] 
+                   initWithReason:@"Nil object to be added in array"] raise];
+        }
+    }
+    return self;
+}
+
+- (id)initWithArray:(NSArray *)anotherArray
+{
+    unsigned i, count = [anotherArray count];
+
+    if (count > 0) {
+        self->maxItems   = count;
+        self->itemsCount = count;
+    }
+    else {
+        self->maxItems   = 1;
+        self->itemsCount = 0;
+    }
+    
+#if DO_NOT_USE_ZONE
+    self->items = calloc(self->maxItems, sizeof(id));
+#else
+    self->items = NSZoneCalloc([self zone], sizeof(id), self->maxItems);
+#endif
+
+    for (i = 0; i < self->itemsCount; i++) {
+       self->items[i] = RETAIN([anotherArray objectAtIndex:i]);
+    }
+    return self;
+}
+
+- (void)dealloc
+{
+    /* basically a copy of the NSConcreteArray -dealloc, might use a macro */
+    register signed int index;
+    
+    if ((index = self->itemsCount) > 0) {
+       /* 
+          Not using static cache because the array content is only similiar
+          inside a single collection, not across collections (arrays being
+          used in various contexts).
+          Hitrate of the cache is about 75% including initial miss.
+       */
+       register Class LastClass  = Nil;
+       register IMP   objRelease = NULL;
+       
+       for (index--; index >= 0; index--) {
+           // TODO: cache RELEASE IMP
+#if LIB_FOUNDATION_BOEHM_GC
+           self->items[index] = nil;
+#else
+           register id obj = self->items[index];
+           
+           if (*(id *)obj != LastClass) {
+               LastClass = *(id *)obj;
+               objRelease = method_get_imp(object_is_instance(obj)
+                  ? class_get_instance_method(LastClass, @selector(release))
+                 : class_get_class_method(LastClass, @selector(release)));
+           }
+           
+           objRelease(obj, NULL /* dangerous? */);
+       }
+#endif
+    }
+
+#if DO_NOT_USE_ZONE
+    if (self->items) free(self->items);
+#else
+    lfFree(self->items);
+#endif
+    [super dealloc];
+}
+
+/* Altering the Array */
+
+- (void)insertObject:(id)anObject atIndex:(unsigned int)index
+{
+    unsigned int i;
+    
+    if (anObject == nil) {
+       [[[InvalidArgumentException alloc] 
+               initWithReason:@"Nil object to be added in array"] raise];
+    }
+    if (index > itemsCount) {
+       [[[RangeException alloc] 
+               initWithReason:@"__insertObject:atIndex: in NSMutableArray" 
+               size:itemsCount index:index] raise];
+    }
+
+    /* resize item array */
+    if (itemsCount == maxItems) {
+       if (maxItems != 0) {
+           maxItems += (maxItems >> 1) ? (maxItems >>1) : 1;
+       }
+       else {
+           maxItems = 1;
+       }
+       items = (id*)Realloc(items, sizeof(id) * maxItems);
+    }
+    
+    /* move items */
+    for(i = itemsCount; i > index; i--)
+       items[i] = items[i - 1];
+    
+    /* place new item */
+    items[index] = RETAIN(anObject);
+    itemsCount++;
+}
+
+- (void)replaceObjectAtIndex:(unsigned int)index  withObject:(id)anObject
+{
+    if (anObject == nil) {
+       [[[InvalidArgumentException alloc] 
+               initWithReason:@"Nil object to be added in array"] raise];
+    }
+    if (index >= self->itemsCount) {
+       [[[RangeException alloc] 
+               initWithReason:@"NSConcreteMutableArray replaceObjectAtIndex" 
+               size:self->itemsCount index:index] raise];
+    }
+    ASSIGN(self->items[index], anObject);
+}
+
+/* removing objects */
+
+static inline void
+_removeObjectsFrom(register NSConcreteMutableArray *self,
+                   register unsigned int index, register unsigned int count)
+{
+    register unsigned int i;
+    
+    if ((index + count) > self->itemsCount) {
+       [[[RangeException alloc]
+               initWithReason:@"removeObjectsFrom:count in NSMutableArray"
+               size:self->itemsCount index:(index + count)] raise];
+    }
+    if (count == 0)
+       return;
+
+#if !LIB_FOUNDATION_BOEHM_GC
+    // TODO: why autorelease?
+    for (i = index; i < index + count; i++)
+       [self->items[i] autorelease];
+#endif
+
+    for (i = index + count; i < self->itemsCount; i++, index++)
+       self->items[index] = self->items[i];
+    for (; index < self->itemsCount; index++) {
+#if DEBUG // better for crashing
+       self->items[index] = (id)0x3;
+#else // more stable against bugs
+        self->items[index] = nil;
+#endif
+    }
+
+    self->itemsCount -= count;
+}
+
+- (void)removeObjectsFrom:(unsigned int)index count:(unsigned int)count
+{
+    _removeObjectsFrom(self, index, count);
+}
+- (void)removeObjectsInRange:(NSRange)aRange
+{
+    _removeObjectsFrom(self, aRange.location, aRange.length);
+}
+- (void)removeAllObjects
+{
+    _removeObjectsFrom(self, 0, self->itemsCount);
+}
+- (void)removeLastObject
+{
+    if (self->itemsCount > 0) _removeObjectsFrom(self, (itemsCount - 1), 1);
+}
+- (void)removeObjectAtIndex:(unsigned int)index
+{
+    _removeObjectsFrom(self, index, 1);
+}
+
+@end /* NSConcreteMutableArray */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConcreteCharacterSet.h b/libFoundation/Foundation/NSConcreteCharacterSet.h
new file mode 100644 (file)
index 0000000..e854ab0
--- /dev/null
@@ -0,0 +1,98 @@
+/* 
+   NSConcreteCharacterSet.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef                __NSConcreteCharacterSet_h__
+#define                __NSConcreteCharacterSet_h__
+
+#define BITMAPDATABYTES 8192*sizeof(char)
+#define ISBITSET(v,n) ((((char*)v)[n/8] &   (1<<(n%8)))  ? YES : NO)
+#define SETBIT(v,n)    (((char*)v)[n/8] |=  (1<<(n%8))) 
+#define RESETBIT(v,n)  (((char*)v)[n/8] &= ~(1<<(n%8)))
+
+@interface NSRangeCharacterSet : NSCharacterSet
+{
+    NSRange    range;
+    BOOL       inverted;
+}
+- initWithRange:(NSRange)aRange;
+- initWithRange:(NSRange)aRange inverted:(BOOL)inv;
+- (NSData *)bitmapRepresentation;
+- (BOOL)characterIsMember:(unichar)aCharacter;
+- (NSCharacterSet *)invertedSet;
+@end /* NSBitmapCharacterSet */
+
+@interface NSStringCharacterSet : NSCharacterSet
+{
+    NSString*  string;
+    BOOL       inverted;
+}
+- initWithString:(NSString*)aString;
+- initWithString:(NSString*)aString inverted:(BOOL)inv;
+- (NSData *)bitmapRepresentation;
+- (BOOL)characterIsMember:(unichar)aCharacter;
+- (NSCharacterSet *)invertedSet;
+@end /* NSBitmapCharacterSet */
+
+@interface NSBitmapCharacterSet : NSCharacterSet
+{
+    id         data;
+    char*      bytes;
+    BOOL       inverted;
+}
+- initWithBitmapRepresentation:(id)data;
+- initWithBitmapRepresentation:(id)data inverted:(BOOL)inv;
+- (NSData *)bitmapRepresentation;
+- (BOOL)characterIsMember:(unichar)aCharacter;
+- (NSCharacterSet *)invertedSet;
+@end /* NSBitmapCharacterSet */
+
+@interface NSMutableBitmapCharacterSet : NSMutableCharacterSet
+{
+    id         data;
+    char*      bytes;
+    BOOL       inverted;
+}
+- initWithBitmapRepresentation:(id)data;
+- initWithBitmapRepresentation:(id)data inverted:(BOOL)inv;
+- (NSData *)bitmapRepresentation;
+- (BOOL)characterIsMember:(unichar)aCharacter;
+- (NSCharacterSet *)invertedSet;
+- (void)addCharactersInRange:(NSRange)aRange;
+- (void)addCharactersInString:(NSString *)aString;
+- (void)removeCharactersInRange:(NSRange)aRange;
+- (void)removeCharactersInString:(NSString *)aString;
+- (void)formIntersectionWithCharacterSet:(NSCharacterSet *)otherSet;
+- (void)formUnionWithCharacterSet:(NSCharacterSet *)otherSet;
+- (void)invert;
+@end /* NSMutableBitmapCharacterSet */
+
+#endif         /* __NSConcreteCharacterSet_h__ */
+
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConcreteCharacterSet.m b/libFoundation/Foundation/NSConcreteCharacterSet.m
new file mode 100644 (file)
index 0000000..68af5f1
--- /dev/null
@@ -0,0 +1,407 @@
+/* 
+   NSConcreteCharacterSet.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSCharacterSet.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSData.h>
+#include "NSConcreteCharacterSet.h"
+
+/*
+ * NSRangeCharacterSet
+ */
+
+@implementation NSRangeCharacterSet
+
+- init
+{
+    NSRange aRange = {0,0};
+    return [self initWithRange:aRange inverted:NO];
+}
+
+- initWithRange:(NSRange)aRange
+{
+    return [self initWithRange:aRange inverted:NO];
+}
+
+- initWithRange:(NSRange)aRange inverted:(BOOL)inv
+{
+    [super init];
+    range = aRange;
+    inverted = inv;
+    return self;
+}
+
+- (void)dealloc
+{
+    [super dealloc];
+}
+
+- (NSData *)bitmapRepresentation
+{
+    char* bytes = CallocAtomic(1, BITMAPDATABYTES);
+    unsigned i;
+    
+    for (i=MIN(range.location+range.length-1, BITMAPDATABYTES);
+               i >= range.location; i--)
+       SETBIT(bytes, i);
+    
+    return [NSData dataWithBytesNoCopy:bytes 
+           length:BITMAPDATABYTES];
+}
+
+- (BOOL)characterIsMember:(unichar)aCharacter
+{
+    return inverted ^ (range.location<=aCharacter &&
+           aCharacter<range.location+range.length);
+}
+
+- (NSCharacterSet *)invertedSet
+{
+    return AUTORELEASE([[NSRangeCharacterSet alloc]
+                           initWithRange:range inverted:!inverted]);
+}
+
+// NSCopying
+
+- copyWithZone:(NSZone*)zone
+{
+    if ([self zone] == zone)
+       return RETAIN(self);
+    else {
+       return [[NSRangeCharacterSet allocWithZone:zone]
+               initWithRange:range inverted:inverted];
+    }
+}
+
+@end /* NSRangeCharacterSet */
+
+/*
+ * NSStringCharacterSet
+ */
+
+@implementation NSStringCharacterSet
+
+- init
+{
+    return [self initWithString:@"" inverted:NO];
+}
+
+- initWithString:(NSString*)aString
+{
+    return [self initWithString:aString inverted:NO];
+}
+
+- initWithString:(NSString*)aString inverted:(BOOL)inv
+{
+    [super init];
+    string = [aString copy];
+    inverted = inv;
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(string);
+    [super dealloc];
+}
+
+- (NSData *)bitmapRepresentation
+{
+    char*      bytes = CallocAtomic(1, BITMAPDATABYTES);
+    int                i;
+    unichar    c;
+    
+    for (i=[string length]; i>=0; i--) {
+           c = [string characterAtIndex:i];
+       SETBIT(bytes, c);
+    }
+    
+    return [NSData dataWithBytesNoCopy:bytes 
+           length:BITMAPDATABYTES];
+}
+
+- (BOOL)characterIsMember:(unichar)aCharacter
+{
+    int i;
+    
+    for (i=[string length]; i>=0; i++)
+       if (aCharacter == [string characterAtIndex:i])
+           return !inverted;
+    return inverted;
+}
+
+- (NSCharacterSet *)invertedSet
+{
+    return AUTORELEASE([[NSStringCharacterSet alloc]
+                           initWithString:string inverted:!inverted]);
+}
+
+// NSCopying
+
+- copyWithZone:(NSZone*)zone
+{
+    if ([self zone] == zone)
+       return RETAIN(self);
+    else {
+       return [[NSStringCharacterSet allocWithZone:zone] 
+               initWithString:string];
+    }
+}
+
+@end /* NSStringCharacterSet */
+
+/*
+ * NSBitmapCharacterSet
+ */
+
+@implementation NSBitmapCharacterSet
+
+- init
+{
+    return [self initWithBitmapRepresentation:
+           [[NSCharacterSet emptyCharacterSet] bitmapRepresentation] 
+           inverted:NO];
+}
+
+- initWithBitmapRepresentation:(id)aData
+{
+    return [self initWithBitmapRepresentation:aData inverted:NO];
+}
+
+- initWithBitmapRepresentation:(id)aData inverted:(BOOL)inv
+{
+    [super init];
+    data = [aData copy];
+    bytes = (char*)[data bytes];
+    inverted = inv;
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(data);
+    [super dealloc];
+}
+
+- (NSData *)bitmapRepresentation
+{
+    if (inverted) {
+       char* theBytes = CallocAtomic(1, BITMAPDATABYTES);
+       unsigned i;
+       
+       for (i = 0; i < BITMAPDATABYTES; i++)
+           theBytes[i] = ~bytes[i];
+               
+       return [NSData dataWithBytesNoCopy:theBytes length:BITMAPDATABYTES];
+    }
+    return data;
+}
+
+- (BOOL)characterIsMember:(unichar)aCharacter
+{
+    return inverted ^ ISBITSET(bytes, aCharacter);
+}
+
+- (NSCharacterSet *)invertedSet
+{
+    return AUTORELEASE([[NSBitmapCharacterSet alloc]
+                           initWithBitmapRepresentation:data
+                           inverted:!inverted]);
+}
+
+// NSCopying
+
+- copyWithZone:(NSZone*)zone
+{
+    if ([self zone] == zone)
+       return RETAIN(self);
+    else {
+       id aData = [self bitmapRepresentation];
+       return [[NSBitmapCharacterSet allocWithZone:zone]
+               initWithBitmapRepresentation:aData];
+    }
+}
+
+@end /* NSBitmapCharacterSet */
+
+/*
+* NSMutableBitmapCharacterSet
+*/
+
+@implementation NSMutableBitmapCharacterSet
+
+- (id)init
+{
+    [super init];
+    self->data = [NSMutableData dataWithCapacity:BITMAPDATABYTES];
+    self->bytes = (char*)[self->data bytes];
+    return self;
+}
+
+- (id)initWithBitmapRepresentation:(id)aData
+{
+    return [self initWithBitmapRepresentation:aData inverted:NO];
+}
+
+- (id)initWithBitmapRepresentation:(id)aData inverted:(BOOL)inv
+{
+    if (aData == nil)
+       return [self init];
+    else {
+       self->data = [aData mutableCopyWithZone:[self zone]];
+       self->bytes = (char*)[self->data bytes];
+       if (inv)
+           [self invert];
+       return self;
+    }
+}
+
+- (void)dealloc
+{
+    RELEASE(self->data);
+    [super dealloc];
+}
+
+- (NSData *)bitmapRepresentation
+{
+    if (self->inverted) {
+       char* theBytes = CallocAtomic(1, BITMAPDATABYTES);
+       unsigned i;
+       
+       for (i = 0; i < BITMAPDATABYTES; i++)
+           theBytes[i] = ~bytes[i];
+               
+       return [NSData dataWithBytesNoCopy:theBytes length:BITMAPDATABYTES];
+    }
+    return self->data;
+}
+
+- (BOOL)characterIsMember:(unichar)aCharacter
+{
+    return inverted ^ ISBITSET(self->bytes, aCharacter);
+}
+
+- (NSCharacterSet *)invertedSet
+{
+    return AUTORELEASE([[NSBitmapCharacterSet alloc]
+                           initWithBitmapRepresentation:self->data
+                           inverted:!self->inverted]);
+}
+
+- (void)addCharactersInRange:(NSRange)aRange
+{
+    unsigned i;
+
+    for (i = MIN(aRange.location+aRange.length-1, BITMAPDATABYTES);
+         i >= aRange.location; i--) {
+       if (self->inverted)
+           RESETBIT(self->bytes, i);
+       else
+           SETBIT(self->bytes, i);
+    }
+}
+
+- (void)addCharactersInString:(NSString *)aString
+{
+    int i;
+    unichar c;
+    
+    for (i = ([aString length] - 1); i >= 0; i--) {
+       c = [aString characterAtIndex:i];
+       if (inverted)
+           RESETBIT(bytes, c);
+       else
+           SETBIT(bytes, c);
+    }
+}
+
+- (void)removeCharactersInRange:(NSRange)aRange
+{
+    unsigned i;
+
+    for (i=MIN(aRange.location+aRange.length-1, BITMAPDATABYTES);
+                   i >= aRange.location; i--)
+       if (inverted)
+           SETBIT(bytes, i);
+       else
+           RESETBIT(bytes, i);
+}
+
+- (void)removeCharactersInString:(NSString *)aString
+{
+    unsigned i;
+    unichar c;
+    
+    for (i=[aString length]; i >= 0; i--) {
+       c = [aString characterAtIndex:i];
+       if (inverted)
+           SETBIT(bytes, c);
+       else
+           RESETBIT(bytes, c);
+    }
+}
+
+- (void)formIntersectionWithCharacterSet:(NSCharacterSet *)otherSet
+{
+    id otherdata = [otherSet bitmapRepresentation];
+    char* otherbytes = (char*)[otherdata bytes];
+    unsigned i;
+    
+    if (inverted)
+       for (i=0; i < BITMAPDATABYTES; i++)
+           bytes[i] |= ~otherbytes[i];
+    else
+       for (i=0; i < BITMAPDATABYTES; i++)
+           bytes[i] &= otherbytes[i];
+}
+
+- (void)formUnionWithCharacterSet:(NSCharacterSet *)otherSet
+{
+    id otherdata = [otherSet bitmapRepresentation];
+    char* otherbytes = (char*)[otherdata bytes];
+    unsigned i;
+    
+    if (inverted)
+       for (i=0; i<BITMAPDATABYTES; i++)
+           bytes[i] &= ~otherbytes[i];
+    else
+       for (i=0; i<BITMAPDATABYTES; i++)
+           bytes[i] |= otherbytes[i];
+}
+
+- (void)invert
+{
+    inverted = !inverted;
+}
+
+@end /* NSMutableBitmapCharacterSet */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSConcreteData.h b/libFoundation/Foundation/NSConcreteData.h
new file mode 100644 (file)
index 0000000..a5f5376
--- /dev/null
@@ -0,0 +1,73 @@
+/* 
+   NSConcreteData.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSConcreteData_h__
+#define __NSConcreteData_h__
+
+#include <Foundation/NSData.h>
+
+/*
+ * Concrete data
+ */
+
+@interface NSConcreteData : NSData
+{
+    char         *bytes;
+    unsigned int length;
+}
+@end
+
+/*
+ * Subdata of a concrete data
+ */
+
+@interface NSConcreteDataRange : NSData
+{
+    char         *bytes;
+    unsigned int length;
+    NSData       *parent;
+}
+- (id)initWithData:(NSData*)data range:(NSRange)range;
+@end
+
+/*
+ * Mutable data
+ */
+
+@interface NSConcreteMutableData : NSMutableData
+{
+    char*              bytes;
+    unsigned int       length;
+    unsigned int       capacity;
+}
+@end
+
+#endif /* __NSConcreteData_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConcreteData.m b/libFoundation/Foundation/NSConcreteData.m
new file mode 100644 (file)
index 0000000..d284bd2
--- /dev/null
@@ -0,0 +1,244 @@
+/* 
+   NSConcreteData.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <extensions/objc-runtime.h>
+
+#include "NSConcreteData.h"
+
+/*
+ * Subdata of a concrete data
+ */
+
+@implementation NSConcreteDataRange
+
+- (id)initWithData:(NSData *)data range:(NSRange)range
+{
+    self->bytes  = (char *)[data bytes] + range.location;
+    self->length = range.length;
+    //range        = range;
+    self->parent = RETAIN(data);
+    return self;
+}
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    if ([self zone] == zone)
+       return RETAIN(self);
+    return [[NSData allocWithZone:zone]
+              initWithBytes:self->bytes length:self->length];
+}
+
+- (const void *)bytes
+{
+    return self->bytes;
+}
+
+- (unsigned int)length
+{
+    return self->length;
+}
+
+- (void)dealloc
+{
+    RELEASE(self->parent);
+    [super dealloc];
+}
+
+@end /* NSConcreteDataRange */
+
+/*
+* Concrete data
+*/
+
+@implementation NSConcreteData
+
+- (id)initWithBytes:(const void *)_bytes length:(unsigned int)_length
+{
+    void *copy_of_bytes = NSZoneMallocAtomic([self zone], _length);
+    memcpy(copy_of_bytes, _bytes, _length);
+    return [self initWithBytesNoCopy:copy_of_bytes length:_length];
+}
+
+- (id)initWithBytesNoCopy:(void*)_bytes
+    length:(unsigned int)_length
+{
+    self->length = _length;
+    self->bytes  = _bytes;
+    return self;
+}
+
+- (id)init
+{
+    return [self initWithBytesNoCopy:NULL length:0];
+}
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    static Class DataClass = Nil;
+    if ([self zone] == zone)
+       return RETAIN(self);
+    if (DataClass == Nil)
+       DataClass = [NSData class];
+    return [[DataClass allocWithZone:zone]
+              initWithBytes:self->bytes length:self->length];
+}
+
+- (const void *)bytes
+{
+    return self->bytes;
+}
+
+- (unsigned int)length
+{
+    return self->length;
+}
+
+- (void)dealloc
+{
+    if (self->bytes) lfFree(self->bytes);
+    [super dealloc];
+}
+
+@end /* NSConcreteData */
+
+/*
+* Mutable data
+*/
+
+@implementation NSConcreteMutableData
+
++ (void)initialize
+{
+    static BOOL initialized = NO;
+    if(!initialized) {
+       initialized = YES;
+       //class_add_behavior(self, [NSConcreteData class]);
+    }
+}
+
+- (id)initWithBytes:(const void *)_bytes length:(unsigned int)_length
+{
+    void *copy_of_bytes = NSZoneMallocAtomic([self zone], _length);
+    memcpy(copy_of_bytes, _bytes, _length);
+    return [self initWithBytesNoCopy:copy_of_bytes length:_length];
+}
+- (id)initWithBytesNoCopy:(void*)_bytes length:(unsigned int)_length {
+    self->length = self->capacity = _length;
+    self->bytes  = _bytes;
+    return self;
+}
+
+- (id)initWithCapacity:(unsigned int)_capacity
+{
+    if ((self = [self initWithLength:_capacity])) {
+       self->length = 0;
+    }
+    return self;
+}
+
+- (id)initWithLength:(unsigned int)_length
+{
+    self->capacity = self->length = _length;
+    self->bytes = NSZoneMallocAtomic([self zone], self->capacity);
+    memset(self->bytes, 0, self->capacity);
+    return self;
+}
+
+- (void)dealloc
+{
+    if (self->bytes) lfFree(self->bytes);
+    [super dealloc];
+}
+
+- (const void *)bytes
+{
+    return self->bytes;
+}
+
+- (unsigned int)length
+{
+    return self->length;
+}
+- (unsigned int)capacity
+{
+    return self->capacity;
+}
+
+- (void)increaseLengthBy:(unsigned int)extraLength
+{
+    if((length += extraLength) >= capacity) {
+       unsigned int extent = length - capacity;
+
+       bytes = NSZoneRealloc(
+           bytes ? NSZoneFromPointer(bytes) : [self zone],
+           bytes, length);
+       memset(bytes + capacity, 0, extent);
+       capacity = length;
+    }
+}
+
+- (void *)mutableBytes
+{
+    return self->bytes;
+}
+
+- (void)setLength:(unsigned int)_length
+{
+    if(_length <= capacity)
+       self->length = _length;
+    else
+        [self increaseLengthBy:(_length - self->length)];
+}
+
+- (void)increaseCapacityBy:(unsigned int)extraCapacity
+{
+    if (extraCapacity == 0)
+        return;
+    self->capacity += extraCapacity;
+    self->bytes = NSZoneRealloc(
+       self->bytes ? NSZoneFromPointer(self->bytes) : [self zone],
+       self->bytes, self->capacity);
+}
+
+- (void)appendBytes:(const void *)_bytes
+  length:(unsigned int)_length
+{
+    if (_length == 0)
+        return;
+    
+    if((self->length + _length) >= self->capacity)
+       [self increaseCapacityBy:(self->length + _length - self->capacity)];
+    memcpy(self->bytes + self->length, _bytes, _length);
+    self->length += _length;
+}
+
+@end /* NSConcreteMutableData */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConcreteDate.h b/libFoundation/Foundation/NSConcreteDate.h
new file mode 100644 (file)
index 0000000..23da0ff
--- /dev/null
@@ -0,0 +1,59 @@
+/* 
+   NSConcreteDate.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSConcreteDate_h__
+#define __NSConcreteDate_h__
+
+#include <Foundation/NSDate.h>
+
+#define UNIX_OFFSET            -978307200.0
+#define DISTANT_FUTURE 6307200000000.0
+#define DISTANT_PAST   -DISTANT_FUTURE
+
+/*
+ * NSConcreteDate, private subclass of NSDate
+ */
+
+@interface NSConcreteDate : NSDate
+{
+    NSTimeInterval timeSinceRef;
+}
+
+- init;
+- initWithTimeIntervalSinceReferenceDate:(NSTimeInterval)secsToBeAdded;
+- (id) copyWithZone: (NSZone*)zone;
+- (NSTimeInterval)timeIntervalSinceReferenceDate;
+- (void)setTimeIntervalSinceReferenceDate:(NSTimeInterval)secsToBeAdded;
+- (NSComparisonResult)compare:(NSDate *)other;
+
+@end
+
+#endif /* __NSConcreteDate_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConcreteDate.m b/libFoundation/Foundation/NSConcreteDate.m
new file mode 100644 (file)
index 0000000..2746e2a
--- /dev/null
@@ -0,0 +1,87 @@
+/* 
+   NSConcreteDate.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSException.h>
+
+#include "NSConcreteDate.h"
+
+@implementation NSConcreteDate
+
+- initWithTimeIntervalSinceReferenceDate:(NSTimeInterval)secsToBeAdded
+{
+    [super init];
+    timeSinceRef = secsToBeAdded;
+    return self;
+}
+
+- init
+{
+    [super init];
+    timeSinceRef = [NSDate timeIntervalSinceReferenceDate];
+    return self;
+}
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    if ([self zone] == zone)
+       return RETAIN(self);
+    return [[[self class] allocWithZone:zone]
+               initWithTimeIntervalSinceReferenceDate:timeSinceRef];
+}
+
+- (NSTimeInterval)timeIntervalSinceReferenceDate
+{
+    return timeSinceRef;
+}
+
+- (void)setTimeIntervalSinceReferenceDate:(NSTimeInterval)secsToBeAdded
+{
+    timeSinceRef = secsToBeAdded;
+}
+
+- (NSComparisonResult)compare:(NSDate*)other
+{
+    if ([other isKindOfClass:[NSDate class]]) {
+       NSTimeInterval diff
+           = timeSinceRef - [other timeIntervalSinceReferenceDate];
+
+       return (diff < 0 ?
+                 NSOrderedAscending
+               : (diff == 0 ? NSOrderedSame : NSOrderedDescending));
+    }
+
+    NSAssert(0, @"Cannot compare NSDate with %@", [other class]);
+    return NSOrderedSame;
+}
+
+@end
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSConcreteDictionary.h b/libFoundation/Foundation/NSConcreteDictionary.h
new file mode 100644 (file)
index 0000000..7dba87f
--- /dev/null
@@ -0,0 +1,207 @@
+/* 
+   NSConcreteDictionary.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSConcreteDictionary_h__
+#define __NSConcreteDictionary_h__
+
+#include <Foundation/NSUtilities.h>
+
+#define SMALL_NSDICTIONARY_SIZE 8
+
+/*
+ * NSConcreteHashDictionary class
+ */
+
+@interface NSConcreteHashDictionary : NSDictionary
+{
+    struct _NSMapNode **nodes;
+    unsigned int      hashSize;
+    unsigned int      itemsCount;
+}
+
+/* Allocating and Initializing an Dictionary */
+- (id)initWithObjects:(id*)objects forKeys:(id*)keys 
+  count:(unsigned int)count;
+- (id)initWithDictionary:(NSDictionary *)dictionary;
+
+/* Accessing keys and values */
+- (id)objectForKey:(id)aKey;
+- (unsigned int)count;
+- (NSEnumerator *)keyEnumerator;
+
+@end /* NSConcreteHashDictionary */
+
+/*
+ * NSConcreteEmptyDictionary class
+ */
+
+@interface NSConcreteEmptyDictionary : NSDictionary
+{
+}
+
+/* Allocating and Initializing an Dictionary */
+- (id)initWithObjects:(id*)objects forKeys:(id*)keys 
+  count:(unsigned int)count;
+- (id)initWithDictionary:(NSDictionary*)dictionary;
+
+/* Accessing keys and values */
+- (id)objectForKey:(id)aKey;
+- (unsigned int)count;
+- (NSEnumerator *)keyEnumerator;
+
+@end /* NSConcreteEmptyDictionary */
+
+/*
+ * NSConcreteSingleObjectDictionary class
+ */
+
+@interface NSConcreteSingleObjectDictionary : NSDictionary
+{
+    id key;
+    id value;
+}
+
+/* Allocating and Initializing an Dictionary */
+- (id)initWithObjects:(id*)objects forKeys:(id*)keys 
+  count:(unsigned int)count;
+- (id)initWithDictionary:(NSDictionary*)dictionary;
+
+/* Accessing keys and values */
+- (id)objectForKey:(id)aKey;
+- (unsigned int)count;
+- (NSEnumerator *)keyEnumerator;
+
+@end /* NSConcreteSingleObjectDictionary */
+
+#if defined(SMALL_NSDICTIONARY_SIZE)
+
+/*
+ * NSConcreteSmallDictionary class
+ */
+
+typedef struct _NSSmallDictionaryEntry {
+    unsigned hash;
+    id       key;
+    id       value;
+} NSSmallDictionaryEntry;
+
+@interface NSConcreteSmallDictionary : NSDictionary
+{
+    unsigned char          count;
+    NSSmallDictionaryEntry entries[1];
+}
+
+/* Allocating and Initializing an Dictionary */
+- (id)initWithObjects:(id*)objects forKeys:(id*)keys 
+  count:(unsigned int)count;
+- (id)initWithDictionary:(NSDictionary*)dictionary;
+
+/* Accessing keys and values */
+- (id)objectForKey:(id)aKey;
+- (unsigned int)count;
+- (NSEnumerator *)keyEnumerator;
+
+@end /* NSConcreteSmallDictionary */
+
+#endif
+
+/*
+ * NSConcreteMutableDictionary class
+ */
+
+@interface NSConcreteMutableDictionary : NSMutableDictionary
+{
+    struct _NSMapNode **nodes;
+    unsigned int      hashSize;
+    unsigned int      itemsCount;
+}
+
+/* Allocating and Initializing an Dictionary */
+- (id)init;
+- (id)initWithCapacity:(unsigned int)aNumItems;
+
+
+/* Modifying dictionary */
+- (void)setObject:(id)anObject forKey:(id)aKey;
+- (void)removeObjectForKey:(id)theKey;
+- (void)removeAllObjects;
+
+@end /* NSConcreteMutableDictionary */
+
+/*
+ * NSDictionary Enumerator classes
+ */
+
+@interface _NSDictionaryObjectEnumerator : NSEnumerator
+{
+    NSDictionary* dict;
+    NSEnumerator* keys;
+}
+
+- initWithDictionary:(NSDictionary*)_dict;
+- nextObject;
+
+@end /* _NSDictionaryObjectEnumerator */
+
+/*
+ * NSDictionary Enumerator classes
+ */
+
+@interface _NSConcreteSingleObjectDictionaryKeyEnumerator : NSEnumerator
+{
+    id nextObject;
+}
+
+- (id)initWithObject:(id)_object;
+- (id)nextObject;
+
+@end /* _NSConcreteSingleObjectDictionaryKeyEnumerator */
+
+#if defined(SMALL_NSDICTIONARY_SIZE)
+
+@interface _NSConcreteSmallDictionaryKeyEnumerator : NSEnumerator
+{
+    NSDictionary *dict;
+    NSSmallDictionaryEntry *currentEntry;
+    unsigned char count;
+}
+
+- (id)initWithDictionary:(NSConcreteSmallDictionary *)_dict
+  firstEntry:(NSSmallDictionaryEntry *)_firstEntry
+  count:(unsigned char)_count;
+
+- (id)nextObject;
+
+@end
+
+#endif /* SMALL_NSDICTIONARY_SIZE */
+
+#endif /* __NSConcreteDictionary_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConcreteDictionary.m b/libFoundation/Foundation/NSConcreteDictionary.m
new file mode 100644 (file)
index 0000000..8f9fe5f
--- /dev/null
@@ -0,0 +1,765 @@
+/* 
+   NSConcreteDictionary.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+   
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+           Helge Hess <helge.hess@skyrix.com>
+   
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <stdarg.h>
+#include <math.h>
+
+#include <Foundation/common.h>
+#include <Foundation/NSObject.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSException.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+
+#include <extensions/objc-runtime.h>
+
+#include "NSConcreteDictionary.h"
+
+@interface _NSConcreteHashDictionaryKeyEnumerator : NSEnumerator
+{
+    NSConcreteHashDictionary *dict;
+    struct _NSMapNode *node;
+    int                      bucket;
+}
+@end
+@interface _NSConcreteHashDictionaryObjectEnumerator : NSEnumerator
+{
+    NSConcreteHashDictionary *dict;
+    struct _NSMapNode *node;
+    int                      bucket;
+}
+@end
+
+static Class NSConcreteMutableDictionaryClass = Nil;
+static NSConcreteEmptyDictionary *sharedEmptyDict = nil;
+
+/*
+ * NSConcreteHashDictionary class
+ */
+
+@implementation NSConcreteHashDictionary
+
+static __inline__ int _getHashSize(NSConcreteHashDictionary *self)
+{
+    return self->hashSize;
+}
+
+static __inline__ struct _NSMapNode *
+_getNodeAt(NSConcreteHashDictionary *self, int idx)
+{
+    return self->nodes[idx];
+}
+
+static BOOL is_prime(unsigned n)
+{
+    int i, n2 = sqrt(n);
+
+    for(i = 2; i <= n2; i++)
+        if(n % i == 0)
+            return NO;
+    return YES;
+}
+static unsigned nextPrime(unsigned old_value)
+{
+    unsigned i, new_value = old_value | 1;
+
+    for (i = new_value; i >= new_value; i += 2)
+        if (is_prime(i))
+            return i;
+    return old_value;
+}
+static void dMapGrow(NSConcreteHashDictionary *table, unsigned newSize)
+{
+    unsigned i;
+    struct _NSMapNode **newNodeTable;
+    
+    newNodeTable =
+        NSZoneCalloc([table zone], newSize, sizeof(struct _NSMapNode*));
+    
+    for (i = 0; i < table->hashSize; i++) {
+       struct _NSMapNode *next, *node;
+       unsigned int h;
+        
+       node = table->nodes[i];
+       while (node) {
+           next = node->next;
+           h = [(id)node->key hash] % newSize;
+           node->next = newNodeTable[h];
+           newNodeTable[h] = node;
+           node = next;
+       }
+    }
+    NSZoneFree([table zone], table->nodes);
+    table->nodes    = newNodeTable;
+    table->hashSize = newSize;
+}
+
+static void dCheckMapTableFull(NSConcreteHashDictionary *table)
+{
+    if( ++(table->itemsCount) >= ((table->hashSize * 3) / 4)) {
+       unsigned newSize;
+        
+        newSize = nextPrime((table->hashSize * 4) / 3);
+       if(newSize != table->hashSize)
+           dMapGrow(table, newSize);
+    }
+}
+
+static __inline__ void
+dInsert(NSConcreteHashDictionary *table, id key, id value)
+{
+    unsigned int h;
+    struct _NSMapNode *node;
+    
+    h = [key hash] % table->hashSize;
+    
+    for (node = table->nodes[h]; node; node = node->next) {
+        /* might cache the selector .. */
+        if ([key isEqual:node->key])
+            break;
+    }
+    
+    /* Check if an entry for key exist in nodeTable. */
+    if (node) {
+        /* key exist. Set for it new value and return the old value of it. */
+       if (key != node->key) {
+            RETAIN(key);
+            RELEASE((id)node->key);
+       }
+       if (value != node->value) {
+            RETAIN(value);
+            RELEASE((id)node->value);
+       }
+       node->key   = key;
+       node->value = value;
+        return;
+    }
+    
+    /* key not found. Allocate a new bucket and initialize it. */
+    node = NSZoneMalloc([table zone], sizeof(struct _NSMapNode));
+    RETAIN(key);
+    RETAIN(value);
+    node->key   = (void*)key;
+    node->value = (void*)value;
+    node->next  = table->nodes[h];
+    table->nodes[h] = node;
+    
+    dCheckMapTableFull(table);
+}
+
+static __inline__ id dGet(NSConcreteHashDictionary *table, id key) {
+    struct _NSMapNode *node;
+    
+    node = table->nodes[[key hash] % table->hashSize];
+    for (; node; node = node->next) {
+        /* could cache method .. */
+        if ([key isEqual:node->key])
+            return node->value;
+    }
+    return nil;
+}
+
+static __inline__ void dRemove(NSConcreteHashDictionary *table, id key) {
+    unsigned int h;
+    struct _NSMapNode *node, *node1 = NULL;
+
+    if (key == nil)
+        return;
+
+    h = [key hash] % table->hashSize;
+    
+    // node point to current bucket, and node1 to previous bucket or to NULL
+    // if current node is the first node in the list 
+    
+    for (node = table->nodes[h]; node; node1 = node, node = node->next) {
+        /* could cache method .. */
+        if ([key isEqual:node->key]) {
+            RELEASE((id)node->key);
+            RELEASE((id)node->value);
+            
+            if (!node1)
+                table->nodes[h] = node->next;
+            else
+                node1->next = node->next;
+           NSZoneFree([table zone], node);
+           (table->itemsCount)--;
+           return;
+        }
+    }
+}
+
++ (void)initialize {
+    if (sharedEmptyDict == nil)
+        sharedEmptyDict = [[NSConcreteEmptyDictionary alloc] init];
+}
+
+/* Allocating and Initializing */
+
+- (id)init
+{
+    RELEASE(self);
+    return RETAIN(sharedEmptyDict);
+}
+
+- (id)initWithObjects:(id *)objects
+  forKeys:(id *)keys 
+  count:(unsigned int)count
+{
+    unsigned capacity;
+    
+    if (count == 0) {
+        RELEASE(self);
+        return RETAIN(sharedEmptyDict);
+    }
+    else if (count == 1) {
+        RELEASE(self);
+        return [[NSConcreteSingleObjectDictionary alloc]
+                   initWithObjects:objects forKeys:keys count:count];
+    }
+    
+    capacity = (count * 4) / 3;
+    capacity = capacity ? capacity : 13;
+    if (!is_prime(capacity))
+       capacity = nextPrime(capacity);
+    
+    self->hashSize   = capacity;
+    self->nodes      = NSZoneCalloc([self zone], capacity, sizeof(void *));
+    self->itemsCount = 0;
+    
+    while (count--) {
+       if (!keys[count] || !objects[count])
+           [[[InvalidArgumentException alloc] 
+                   initWithReason:@"Nil object to be added in dictionary"] raise];
+       dInsert(self, keys[count], objects[count]);
+    }
+    return self;
+}
+
+- (id)initWithDictionary:(NSDictionary *)dictionary
+{
+    NSEnumerator *keys;
+    id key;
+    unsigned capacity;
+    
+    capacity = [dictionary count] * 4 / 3;
+    capacity = capacity ? capacity : 13;
+    if (!is_prime(capacity))
+       capacity = nextPrime(capacity);
+
+    self->hashSize   = capacity;
+    self->nodes      = NSZoneCalloc([self zone], capacity, sizeof(void *));
+    self->itemsCount = 0;
+    
+    keys = [dictionary keyEnumerator];
+    while ((key = [keys nextObject]))
+       dInsert(self, key, [dictionary objectForKey:key]);
+    
+    return self;
+}
+
+- (void)dealloc
+{
+    if (self->itemsCount > 0) {
+        NSZone *z = [self zone];
+        unsigned i;
+        
+        for (i = 0; i < self->hashSize; i++) {
+            struct _NSMapNode *next, *node;
+            
+            node = self->nodes[i];
+            self->nodes[i] = NULL;             
+            while (node) {
+                RELEASE((id)node->key);
+                RELEASE((id)node->value);
+                next = node->next;
+                NSZoneFree(z, node);
+                node = next;
+            }
+        }
+        self->itemsCount = 0;
+    }
+    
+    if (self->nodes)
+        NSZoneFree([self zone], self->nodes);
+    [super dealloc];
+}
+
+/* Accessing keys and values */
+
+- (NSEnumerator *)keyEnumerator
+{
+    static Class KeyEnumClass = Nil;
+    if (KeyEnumClass == Nil)
+        KeyEnumClass = [_NSConcreteHashDictionaryKeyEnumerator class];
+    return AUTORELEASE([[KeyEnumClass alloc] initWithDictionary:self]);
+}
+- (NSEnumerator *)objectEnumerator
+{
+    return AUTORELEASE([[_NSConcreteHashDictionaryObjectEnumerator alloc]
+                           initWithDictionary:self]);
+}
+
+- (id)objectForKey:(id)aKey
+{
+    return dGet(self, aKey);
+}
+
+- (unsigned int)count
+{
+    return self->itemsCount;
+}
+
+@end /* NSConcreteHashDictionary */
+
+/*
+ * NSConcreteEmptyDictionary class
+ */
+
+@implementation NSConcreteEmptyDictionary
+
+/* Allocating and Initializing */
+
+- (id)init
+{
+    return [self initWithDictionary:nil];
+}
+
+- (id)initWithObjects:(id*)objects
+    forKeys:(id*)keys 
+    count:(unsigned int)_count
+{
+    if (_count > 1) {
+        RELEASE(self);
+        return [[NSConcreteHashDictionary alloc]
+                   initWithObjects:objects forKeys:keys count:_count];
+    }
+    else if (_count == 1) {
+        RELEASE(self);
+        return [[NSConcreteSingleObjectDictionary alloc]
+                   initWithObjects:objects forKeys:keys count:_count];
+    }
+    return self;
+}
+
+- (id)initWithDictionary:(NSDictionary*)dictionary
+{
+    unsigned count = [dictionary count];
+    
+    if (count > 1) {
+        RELEASE(self);
+        return [[NSConcreteHashDictionary alloc] initWithDictionary:dictionary];
+    }
+    else if (count == 1) {
+        RELEASE(self);
+        return [[NSConcreteSingleObjectDictionary alloc]
+                                                  initWithDictionary:dictionary];
+    }
+    return self;
+}
+
+/* Accessing keys and values */
+
+- (NSEnumerator *)keyEnumerator
+{
+    return AUTORELEASE([[_NSConcreteSingleObjectDictionaryKeyEnumerator alloc]
+                            initWithObject:nil]);
+}
+
+- (id)objectForKey:(id)aKey
+{
+    return nil;
+}
+
+- (unsigned int)count
+{
+    return 0;
+}
+
+/* NSCopying */
+
+- (id)mutableCopyWithZone:(NSZone *)_zone
+{
+    if (NSConcreteMutableDictionaryClass == Nil)
+        NSConcreteMutableDictionaryClass = [NSConcreteMutableDictionary class];
+    
+    return [[NSConcreteMutableDictionaryClass alloc] init];
+}
+
+@end /* NSConcreteEmptyDictionary */
+
+/*
+ * NSConcreteSingleObjectDictionary class
+ */
+
+@implementation NSConcreteSingleObjectDictionary
+
++ (void)initialize {
+    if (sharedEmptyDict == nil)
+        sharedEmptyDict = [[NSConcreteEmptyDictionary alloc] init];
+}
+
+/* Allocating and Initializing */
+
+- (id)init
+{
+    RELEASE(self);
+    return RETAIN(sharedEmptyDict);
+}
+
+- (id)initWithObjects:(id *)objects
+    forKeys:(id *)keys 
+    count:(unsigned int)_count
+{
+    if (_count == 0) {
+        RELEASE(self);
+        return RETAIN(sharedEmptyDict);
+    }
+    else if (_count > 1) {
+        RELEASE(self);
+        return [[NSConcreteHashDictionary alloc]
+                   initWithObjects:objects forKeys:keys count:_count];
+    }
+
+    if (*keys == nil) {
+        [[[InvalidArgumentException alloc] 
+                   initWithReason:@"Nil key to be added in dictionary"] raise];
+    }
+    if (*objects == nil) {
+        [[[InvalidArgumentException alloc] 
+                   initWithReason:@"Nil object to be added in dictionary"] raise];
+    }
+    self->key   = RETAIN(*keys);
+    self->value = RETAIN(*objects);
+    return self;
+}
+
+- (id)initWithDictionary:(NSDictionary*)dictionary
+{
+    unsigned count = [dictionary count];
+
+    if (count == 0) {
+        RELEASE(self);
+        return RETAIN(sharedEmptyDict);
+    }
+    else if (count > 1) {
+        RELEASE(self);
+        return [[NSConcreteHashDictionary alloc]
+                   initWithDictionary:dictionary];
+    }
+
+    self->key   = RETAIN([[dictionary keyEnumerator] nextObject]);
+    self->value = RETAIN([dictionary objectForKey:key]);
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(self->key);
+    RELEASE(self->value);
+    [super dealloc];
+}
+
+/* Accessing keys and values */
+
+- (NSEnumerator *)keyEnumerator
+{
+    return AUTORELEASE([[_NSConcreteSingleObjectDictionaryKeyEnumerator alloc]
+                            initWithObject:self->key]);
+}
+
+- (id)objectForKey:(id)aKey
+{
+    return ([self->key isEqual:aKey]) ? self->value : nil;
+}
+
+- (unsigned int)count
+{
+    return 1;
+}
+
+/* NSCopying */
+
+- (id)mutableCopyWithZone:(NSZone *)_zone
+{
+    if (NSConcreteMutableDictionaryClass == Nil)
+        NSConcreteMutableDictionaryClass = [NSConcreteMutableDictionary class];
+    return [[NSConcreteMutableDictionaryClass alloc]
+               initWithObjects:&(self->value) forKeys:&(self->key) count:1];
+}
+
+@end /* NSConcreteSingleObjectDictionary */
+
+#if defined(SMALL_NSDICTIONARY_SIZE)
+
+/*
+ * NSConcreteSmallDictionary class
+ */
+
+@implementation NSConcreteSmallDictionary
+
+- (id)init
+{
+    RELEASE(self);
+    return RETAIN(sharedEmptyDict);
+}
+
+- (id)initWithObjects:(id*)_objects forKeys:(id*)_keys 
+  count:(unsigned int)_count
+{
+    if (_count == 0) {
+        RELEASE(self);
+        return RETAIN(sharedEmptyDict);
+    }
+    else if (_count == 1) {
+        RELEASE(self);
+        return [[NSConcreteSingleObjectDictionary alloc]
+                   initWithObjects:_objects forKeys:_keys count:_count];
+    }
+    
+    NSAssert2(_count <= SMALL_NSDICTIONARY_SIZE,
+              @"too many objects for small dictionary (max=%i, count=%i)!",
+              SMALL_NSDICTIONARY_SIZE, _count);
+    self->count = _count;
+    
+    while(_count--) {
+       if ((_keys[_count] == nil) || (_objects[_count] == nil)) {
+           [[[InvalidArgumentException alloc] 
+                   initWithReason:@"Nil object to be added in dictionary"] raise];
+        }
+        self->entries[_count].key   = RETAIN(_keys[_count]);
+        self->entries[_count].hash  = [_keys[_count] hash];
+        self->entries[_count].value = RETAIN(_objects[_count]);
+    }
+    return self;
+}
+- (id)initWithDictionary:(NSDictionary*)dictionary
+{
+    NSEnumerator  *keys = [dictionary keyEnumerator];
+    unsigned char i;
+    
+    self->count = [dictionary count];
+    NSAssert2(self->count <= SMALL_NSDICTIONARY_SIZE,
+              @"too many objects for small dictionary (max=%i, count=%i)!",
+              SMALL_NSDICTIONARY_SIZE, self->count);
+
+    for (i = 0; i < self->count; i++) {
+        id key = [keys nextObject];
+        self->entries[i].key   = RETAIN(key);
+        self->entries[i].hash  = [key hash];
+        self->entries[i].value = RETAIN([dictionary objectForKey:key]);
+    }
+    return self;
+}
+
+- (void)dealloc {
+    unsigned char i;
+    for (i = 0; i < self->count; i++) {
+        RELEASE(self->entries[i].key);
+        RELEASE(self->entries[i].value);
+    }
+    [super dealloc];
+}
+
+- (id)objectForKey:(id)aKey
+{
+    register NSSmallDictionaryEntry *e = self->entries;
+    register signed char i;
+    register unsigned hash = [aKey hash];
+    
+    for (i = (self->count - 1); i >= 0; i--, e++) {
+        if (e->hash == hash) {
+            if (e->key == aKey)        return e->value;
+            if ([e->key isEqual:aKey]) return e->value;
+        }
+    }
+    return nil;
+}
+
+- (unsigned int)count
+{
+    return self->count;
+}
+- (NSEnumerator *)keyEnumerator
+{
+    return AUTORELEASE([[_NSConcreteSmallDictionaryKeyEnumerator alloc]
+                            initWithDictionary:self
+                            firstEntry:self->entries count:self->count]);
+}
+
+@end /* NSConcreteSmallDictionary */
+
+#endif /* SMALL_NSDICTIONARY_SIZE */
+
+@implementation _NSConcreteSingleObjectDictionaryKeyEnumerator
+
+- (id)initWithObject:(id)_object
+{
+    self->nextObject = RETAIN(_object);
+    return self;
+}
+- (void)dealloc {
+    RELEASE(self->nextObject);
+    [super dealloc];
+}
+
+- (id)nextObject
+{
+    id no = self->nextObject;
+    if (no) {
+        self->nextObject = AUTORELEASE(self->nextObject);
+        self->nextObject = nil;
+    }
+    return no;
+}
+
+@end
+
+#if defined(SMALL_NSDICTIONARY_SIZE)
+
+@implementation _NSConcreteSmallDictionaryKeyEnumerator
+
+- (id)initWithDictionary:(NSConcreteSmallDictionary *)_dict
+  firstEntry:(NSSmallDictionaryEntry *)_firstEntry
+  count:(unsigned char)_count
+{
+    self->dict         = RETAIN(_dict);
+    self->currentEntry = _firstEntry;
+    self->count        = _count;
+    return self;
+}
+
+- (void)dealloc {
+    RELEASE(self->dict);
+    [super dealloc];
+}
+
+- (id)nextObject {
+    if (self->count > 0) {
+        id obj;
+        obj = self->currentEntry->key;
+        self->currentEntry++;
+        self->count--;
+        return obj;
+    }
+    else
+        return nil;
+}
+
+@end /* _NSConcreteSmallDictionaryKeyEnumerator */
+
+#endif /* SMALL_NSDICTIONARY_SIZE */
+
+@implementation _NSConcreteHashDictionaryKeyEnumerator
+
+- (id)initWithDictionary:(NSConcreteHashDictionary *)_dict
+{
+    self->dict   = RETAIN(_dict);
+    self->node   = NULL;
+    self->bucket = -1;
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(dict);
+    [super dealloc];
+}
+
+- (id)nextObject
+{
+    if (self->node)
+       self->node = self->node->next;
+    
+    if (self->node == NULL) {
+       for(self->bucket++;
+            ((int)self->bucket) < _getHashSize(self->dict);
+            self->bucket++) {
+
+            if (_getNodeAt(self->dict, self->bucket)) {
+                self->node = _getNodeAt(self->dict, self->bucket);
+                break;
+           }
+        }
+       if (((int)self->bucket) >= _getHashSize(self->dict)) {
+           self->node = NULL;
+           self->bucket = (_getHashSize(self->dict) - 1);
+           return nil;
+       }
+    }
+    return self->node->key;
+}
+
+@end /* _NSConcreteHashDictionaryKeyEnumerator */
+
+@implementation _NSConcreteHashDictionaryObjectEnumerator
+
+- (id)initWithDictionary:(NSConcreteHashDictionary *)_dict
+{
+    self->dict   = RETAIN(_dict);
+    self->node   = NULL;
+    self->bucket = -1;
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(dict);
+    [super dealloc];
+}
+
+- (id)nextObject
+{
+    if (self->node)
+       self->node = self->node->next;
+    
+    if (self->node == NULL) {
+       for(self->bucket++;
+            ((int)self->bucket) < _getHashSize(self->dict);
+            self->bucket++) {
+
+            if (_getNodeAt(self->dict, self->bucket)) {
+                self->node = _getNodeAt(self->dict, self->bucket);
+                break;
+           }
+        }
+       if (((int)self->bucket) >= _getHashSize(self->dict)) {
+           self->node = NULL;
+           self->bucket = (_getHashSize(self->dict) - 1);
+           return nil;
+       }
+    }
+    return self->node->value;
+}
+
+@end /* _NSConcreteHashDictionaryObjectEnumerator */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSConcreteFileHandle.h b/libFoundation/Foundation/NSConcreteFileHandle.h
new file mode 100644 (file)
index 0000000..19a3c23
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+   NSConcreteFileHandle.h
+
+   Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@net-community.com>
+   Date: May 1997
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+#ifndef __NSConcreteFileHandle_h__
+#define __NSConcreteFileHandle_h__
+
+#include <Foundation/NSPosixFileDescriptor.h>
+#include <Foundation/NSFileHandle.h>
+
+@class NSPosixFileDescriptor;
+
+typedef enum {
+    NSFileHandleNoOperation = 0,
+    NSFileHandleAcceptOperation,
+    NSFileHandleReadOperation,
+    NSFileHandleReadToEndOfFileOperation
+} NSFileHandleOperation;
+
+typedef enum {
+    NSFileHandleNoType = 0,
+    NSFileHandleSocket,
+    NSFileHandleUnixFile
+} NSFileHandleType;
+
+@class NSArray;
+@class NSData;
+@class NSMutableData;
+
+@interface NSConcreteFileHandle : NSPosixFileDescriptor
+{
+    int                   blockSize;
+    BOOL                  closeOnDealloc;
+    BOOL                  isOpened;
+    NSFileHandleOperation operation;
+    NSFileHandleType      type;
+    NSArray               *modes;
+}
+
+/* Creating an NSFileHandle */
+- (id)initWithFileDescriptor:(int)fd;
+- (id)initWithFileDescriptor:(int)fd closeOnDealloc:(BOOL)flag;
+- (id)initWithPath:(NSString *)aPath flags:(int)flags createMode:(int)mode;
+
+@end
+
+
+@interface NSConcreteFileHandle (NSFileHandleOperations)
+
+/* Getting a file descriptor */
+- (int)fileDescriptor;
+
+/* Reading from an NSFileHandle */
+- (NSData *)availableData;
+- (NSData *)readDataToEndOfFile;
+- (NSData *)readDataOfLength:(unsigned int)length;
+
+/* Writing to an NSFileHandle */
+- (void)writeData:(NSData *)data;
+
+/* Communicating asynchronously in the background */
+- (void)acceptConnectionInBackgroundAndNotifyForModes:(NSArray *)modes;
+- (void)acceptConnectionInBackgroundAndNotify;
+- (void)readInBackgroundAndNotifyForModes:(NSArray *)modes;
+- (void)readInBackgroundAndNotify;
+- (void)readToEndOfFileInBackgroundAndNotifyForModes:(NSArray *)modes;
+- (void)readToEndOfFileInBackgroundAndNotify;
+
+/* Seeking within a file */
+- (unsigned long long)offsetInFile;
+- (unsigned long long)seekToEndOfFile;
+- (void)seekToFileOffset:(unsigned long long)offset;
+
+/* Operating on a file */
+- (void)closeFile;
+- (void)synchronizeFile;
+- (void)truncateFileAtOffset:(unsigned long long)offset;
+
+@end
+
+
+@interface NSNullDeviceFileHandle : NSFileHandle
+@end
+
+@interface NSConcretePipeFileHandle : NSFileHandle
+{
+    int  fd;
+    BOOL closeOnDealloc;
+}
+
+@end
+
+#endif /* __NSConcreteFileHandle_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConcreteFileHandle.m b/libFoundation/Foundation/NSConcreteFileHandle.m
new file mode 100644 (file)
index 0000000..96d26c6
--- /dev/null
@@ -0,0 +1,982 @@
+/*
+   NSConcreteFileHandle.m
+
+   Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@net-community.com>
+   Date: May 1997
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifdef __MINGW32__
+#  include <winsock.h>
+#else
+#  include <sys/un.h>
+#  include <netinet/in.h>
+#  include <sys/socket.h>
+#  include <sys/ioctl.h>
+
+enum {
+    non_blocking =
+#if O_NDELAY
+    O_NDELAY
+#elif FNDELAY
+    FNDELAY
+#elif O_NONBLOCK
+    O_NONBLOCK
+#endif
+};
+#endif
+
+#if HAVE_LIBC_H
+# include <libc.h>
+#else
+# include <unistd.h>
+#endif
+
+#include <Foundation/NSData.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSNotification.h>
+#include <Foundation/NSNotificationQueue.h>
+#include <Foundation/NSRunLoop.h>
+#include <Foundation/NSException.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+#include <Foundation/exceptions/NSFileHandleExceptions.h>
+#include "NSConcreteFileHandle.h"
+
+#if !defined(__MINGW32__) && 0
+
+static BOOL _isFdNonBlocking(int fd) {
+    unsigned fileStatus;
+    
+    fileStatus = fcntl (fd, F_GETFL, 0);
+    return (fileStatus & non_blocking) ? YES : NO;
+}
+
+static void _setFdBlocking(int fd, BOOL nonBlocking) {
+    int flags;
+
+    if ((flags = fcntl(fd, F_GETFL, 0)) >= 0) {
+        if (nonBlocking)
+            flags |= non_blocking;
+        else
+            flags &= ~non_blocking;
+
+        if (fcntl(fd, F_SETFL, flags) < 0)
+            NSLog(@"WARNING: fcntl() call failed: %s", strerror(errno));
+    }
+    else
+        NSLog(@"WARNING: fcntl() call failed: %s", strerror(errno));
+}
+
+#endif
+
+@implementation NSConcreteFileHandle
+
++ (id)fileHandleForReadingAtPath:(NSString*)path
+{
+    return AUTORELEASE([[self alloc]
+                           initWithPath:path flags:O_RDONLY createMode:0]);
+}
+
++ (id)fileHandleForWritingAtPath:(NSString*)path
+{
+    /* note: it's intended that flags do not include O_CREAT ! (see doc) */
+    return AUTORELEASE([[self alloc]
+                              initWithPath:path flags:O_WRONLY
+                              createMode:0]);
+}
+
++ (id)fileHandleForUpdatingAtPath:(NSString*)path
+{
+    /* note: it's intended that flags do not include O_CREAT ! (see doc) */
+    return AUTORELEASE([[self alloc]
+                              initWithPath:path flags:O_RDWR
+                              createMode:0]);
+}
+
+- (void)_determineFileType
+{
+    struct stat statbuf;
+
+    if (fstat (fd, &statbuf) == -1) {
+       NSLog (@"warning: cannot determine the type of file descriptor %d in"
+              @" NSFileHandle %x", fd, self);
+       type = NSFileHandleNoType;
+    }
+    else {
+#ifdef S_IFSOCK
+       if ((statbuf.st_mode & S_IFSOCK) == statbuf.st_mode)
+           type = NSFileHandleSocket;
+       else
+#endif
+#ifdef S_IFIFO
+       /* System V FIFOs, treat them as sockets since the system
+          calls that use them are similar. */
+       if ((statbuf.st_mode & S_IFIFO) == statbuf.st_mode)
+           type = NSFileHandleSocket;
+       else
+#endif
+           type = NSFileHandleUnixFile;
+
+#if 0
+       NSLog (@"file type is %s, mode = %o",
+              type == NSFileHandleUnixFile ? "file" : "socket",
+              statbuf.st_mode);
+#endif
+
+#if !defined(__MINGW32__)
+       /* Is st_blksize set on System V? */
+       blockSize = statbuf.st_blksize;
+       if (!blockSize)
+           blockSize = 4096;
+#else
+        blockSize = 4096;
+#endif
+    }
+}
+
+- (id)initWithFileDescriptor:(int)_fd
+{
+    return [self initWithFileDescriptor:_fd closeOnDealloc:NO];
+}
+
+- (id)initWithFileDescriptor:(int)_fd closeOnDealloc:(BOOL)flag
+{
+    self = [super initWithFileDescriptor:_fd];
+    if (!self)
+       return nil;
+
+    closeOnDealloc = flag;
+    isOpened = YES;
+    operation = NSFileHandleNoOperation;
+    [self _determineFileType];
+    [self setDelegate:self];
+    return self;
+}
+
+- (id)initWithPath:(NSString*)aPath flags:(int)flags createMode:(int)mode
+{
+    if ((self = [super initWithPath:aPath flags:flags createMode:mode])) {
+        closeOnDealloc = YES;
+        isOpened       = YES;
+        operation      = NSFileHandleNoOperation;
+        [self _determineFileType];
+        [self setDelegate:self];
+    }
+    return self;
+}
+
+- (void)dealloc
+{
+    if (closeOnDealloc && isOpened)
+      close (fd);
+    [super dealloc];
+}
+
+- (NSData *)availableData
+{
+    NSData* data;
+
+    /* Force the compiler to allocate `data' on stack */
+    *&data = nil;
+    
+    if (!isOpened) {
+       [[[NSFileHandleOperationException alloc]
+                   initWithFileHandle:self
+                   operation:@"Try to read from a closed file descriptor!"] raise];
+    }
+    
+    if (type == NSFileHandleUnixFile) {
+       data = [self readRestOfFile];
+    }
+    else if (type == NSFileHandleSocket) {
+       data = [self readDataOfLength:blockSize];
+    }
+    else
+       [[[NSFileHandleUnknownTypeException alloc]
+                       initWithFileHandle:self] raise];
+
+    return data;
+}
+
+- (NSData *)readDataToEndOfFile
+{
+    /*
+      invalid implementation, -readDataOfLength: only returns the
+      available bytes on sockets.
+    */
+    return [self readDataOfLength:UINT_MAX];
+}
+
+- (NSData *)readDataOfLength:(unsigned int)length
+{
+    NSData *data;
+
+    /* Force the compiler to allocate `data' on stack */
+    *&data = nil;
+
+    if (!isOpened) {
+       [[[NSFileHandleOperationException alloc]
+                   initWithFileHandle:self
+                   operation:@"Try to read from a closed file descriptor!"] raise];
+    }
+    
+    if (type == NSFileHandleUnixFile) {
+        if (length == UINT_MAX)
+            data = [self readFileLength:LONG_MAX];
+        else {
+            NSAssert(length < LONG_MAX,
+                     @"cannot handle read's with %d bytes",
+                     length);
+            data = [self readFileLength:length];
+        }
+    }
+    else if (type == NSFileHandleSocket) {
+       void *buffer;
+       int  howMany;
+
+       /* Force the compiler to allocate `buffer' on stack */
+       *&buffer = MallocAtomic(length);
+
+       howMany = read(fd, buffer, length);
+       if (howMany == -1) {
+           lfFree(buffer);
+           [[[NSFileHandleOperationException alloc]
+                     initWithFileHandle:self
+                     operation:@"Error while reading from socket!"] raise];
+       }
+       if (howMany < (int)length)
+           buffer = Realloc(buffer, howMany);
+       data = [NSData dataWithBytesNoCopy:buffer length:howMany];
+    }
+    else {
+       [[[NSFileHandleUnknownTypeException alloc]
+                       initWithFileHandle:self] raise];
+    }
+
+    return data;
+}
+
+- (void)writeData:(NSData*)data
+{
+    if (!isOpened) {
+       [[[NSFileHandleOperationException alloc]
+                   initWithFileHandle:self
+                   operation:@"Try to write in a closed file descriptor!"] raise];
+    }
+
+    TRY {
+       [super writeData:data];
+    } END_TRY
+    CATCH(PosixFileOperationException) {
+       [[[NSFileHandleUnknownTypeException alloc]
+                       initWithFileHandle:self] raise];
+    } END_CATCH
+}
+
+- (void)_registerToRunLoopForModes:(NSArray*)_modes
+{
+    NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
+    int i, count;
+
+    if (!_modes)
+       _modes = [NSArray arrayWithObject:[runLoop currentMode]];
+
+    ASSIGN(modes, _modes);
+
+    count = [modes count];
+    for (i = 0; i < count; i++)
+       [runLoop addPosixFileDescriptor:self forMode:[modes objectAtIndex:i]];
+}
+
+- (void)acceptConnectionInBackgroundAndNotifyForModes:(NSArray*)_modes
+{
+    if (!isOpened)
+       [[[NSFileHandleOperationException alloc]
+                 initWithFileHandle:self
+                 operation:@"Try to accept connections on a closed socket!"] raise];
+    if (operation != NSFileHandleNoOperation) {
+       NSString* reason = [NSString stringWithFormat:@"Another operation (%s)"
+                     @" is already in progress!",
+                     (operation == NSFileHandleAcceptOperation
+                      ? "accept"
+                      : (operation == NSFileHandleReadOperation
+                         ? "read"
+                         : (operation == NSFileHandleReadToEndOfFileOperation
+                            ? "read to end of file"
+                            : "unknown")))];
+       [[[NSFileHandleOperationException alloc]
+                 initWithFileHandle:self
+                 operation:reason] raise];
+    }
+
+    operation = NSFileHandleAcceptOperation;
+    fileActivity = NSPosixReadableActivity;
+
+    [self _registerToRunLoopForModes:_modes];
+}
+
+- (void)acceptConnectionInBackgroundAndNotify
+{
+    [self acceptConnectionInBackgroundAndNotifyForModes:nil];
+}
+
+- (void)readInBackgroundAndNotifyForModes:(NSArray*)_modes
+{
+    if (!isOpened) {
+       [[[NSFileHandleOperationException alloc]
+                 initWithFileHandle:self
+                 operation:@"Try to read in background from a closed file"
+                           @" descriptor!"] raise];
+    }
+    if (operation != NSFileHandleNoOperation) {
+       NSString* reason = [NSString stringWithFormat:@"Another operation (%s)"
+                     @" is already in progress!",
+                     (operation == NSFileHandleAcceptOperation
+                      ? "accept"
+                      : (operation == NSFileHandleReadOperation
+                         ? "read"
+                         : (operation == NSFileHandleReadToEndOfFileOperation
+                            ? "read to end of file"
+                            : "unknown")))];
+       [[[NSFileHandleOperationException alloc]
+                 initWithFileHandle:self
+                 operation:reason] raise];
+    }
+
+    operation = NSFileHandleReadOperation;
+    fileActivity = NSPosixReadableActivity;
+
+    [self _registerToRunLoopForModes:_modes];
+}
+
+- (void)readInBackgroundAndNotify
+{
+    [self readInBackgroundAndNotifyForModes:nil];
+}
+
+- (void)readToEndOfFileInBackgroundAndNotifyForModes:(NSArray*)_modes
+{
+    if (!isOpened)
+       [[[NSFileHandleOperationException alloc]
+                 initWithFileHandle:self
+                 operation:@"Try to read to end of file in background from a"
+                           @" closed file descriptor!"] raise];
+    if (operation != NSFileHandleNoOperation) {
+       NSString* reason = [NSString stringWithFormat:@"Another operation (%s)"
+                     @" is already in progress!",
+                     (operation == NSFileHandleAcceptOperation
+                      ? "accept"
+                      : (operation == NSFileHandleReadOperation
+                         ? "read"
+                         : (operation == NSFileHandleReadToEndOfFileOperation
+                            ? "read to end of file"
+                            : "unknown")))];
+       [[[NSFileHandleOperationException alloc]
+                 initWithFileHandle:self
+                 operation:reason] raise];
+    }
+
+    operation = NSFileHandleReadToEndOfFileOperation;
+    fileActivity = NSPosixReadableActivity;
+
+    [self _registerToRunLoopForModes:_modes];
+}
+
+- (void)readToEndOfFileInBackgroundAndNotify
+{
+    [self readToEndOfFileInBackgroundAndNotifyForModes:nil];
+}
+
+- (unsigned long long)offsetInFile
+{
+    if (!isOpened)
+       [[[NSFileHandleOperationException alloc]
+                 initWithFileHandle:self
+                 operation:@"Error getting the offset from a closed file!"] raise];
+    if (type != NSFileHandleUnixFile)
+       [[[NSFileHandleOperationException alloc]
+                 initWithFileHandle:self
+                 operation:@"Error getting an offset from a non-file!"] raise];
+
+    return [self filePosition];
+}
+
+- (unsigned long long)seekToEndOfFile
+{
+    if (!isOpened)
+       [[[NSFileHandleOperationException alloc]
+               initWithFileHandle:self
+               operation:@"Error seeking to end of file on a closed file!"] raise];
+    if (type != NSFileHandleUnixFile)
+       [[[NSFileHandleOperationException alloc]
+                 initWithFileHandle:self
+                 operation:@"Error seeking to end of file on a non-file!"] raise];
+
+    [self seekToEnd];
+    return [self offsetInFile];
+}
+
+- (void)seekToFileOffset:(unsigned long long)offset
+{
+    if (!isOpened)
+       [[[NSFileHandleOperationException alloc]
+               initWithFileHandle:self
+               operation:@"Error seeking to a position on a closed file!"] raise];
+    if (type != NSFileHandleUnixFile)
+       [[[NSFileHandleOperationException alloc]
+                 initWithFileHandle:self
+                 operation:@"Error seeking to a position on a non-file!"] raise];
+
+    [self seekToPosition:offset];
+}
+
+- (void)closeFile
+{
+    if (isOpened)
+       close (fd);
+
+    isOpened = NO;
+}
+
+- (void)truncateFileAtOffset:(unsigned long long)offset
+{
+    if (!isOpened)
+       [[[NSFileHandleOperationException alloc]
+               initWithFileHandle:self
+               operation:@"Error truncating a closed file!"] raise];
+    if (type != NSFileHandleUnixFile)
+       [[[NSFileHandleOperationException alloc]
+                 initWithFileHandle:self
+                 operation:@"Error truncating a non-file!"] raise];
+
+    [self truncateAtPosition:offset];
+}
+
+- (void)activity:(NSPosixFileActivities)activity
+  posixFileDescriptor:(NSPosixFileDescriptor*)fileDescriptor
+{
+    NSNotification* notification = nil;
+    NSDictionary* userInfo;
+
+    switch (activity) {
+       case NSPosixReadableActivity:
+           if (operation == NSFileHandleReadOperation) {
+               /* Try to avoid a blocking operation in case the file
+                  descriptor is a socket, so we differentiate here between
+                  normal files and sockets. */
+               NSData* data = nil;
+
+               if (type == NSFileHandleUnixFile) {
+                   /* Reading from files cannot block so do an unconditional
+                      read here. */
+                   data = [self readDataOfLength:blockSize];
+               }
+#if defined(WIN32)
+#  warning NSFileHandleSocket not supported in WIN32
+#else
+               else if (type == NSFileHandleSocket) {
+                   /* Determine if the file descriptor does nonblocking I/O.
+                      If it doesn't temporary change it to do, read as many
+                      bytes as possible and change it back to blocking I/O.
+                    */
+                   unsigned fileStatus = fcntl (fd, F_GETFL, 0);
+                   BOOL isNonBlocking = (fileStatus & non_blocking);
+                    
+                   /* Temporary set the file status to nonblocking I/O */
+                   if (!isNonBlocking) {
+                       if(fcntl(fd, F_SETFL, fileStatus|non_blocking) == -1) {
+                           NSLog (@"cannot set nonblocking status to file "
+                                  @"descriptor %d of NSFileHandle %x",
+                                  fd, self);
+                       }
+                   }
+
+                   data = [self readDataOfLength:blockSize];
+
+                   /* Restore the blocking I/O if it's the case */
+                   if (!isNonBlocking) {
+                       if(fcntl(fd, F_SETFL, fileStatus) == -1) {
+                           NSLog (@"cannot restore blocking status of file "
+                                  @"descriptor %d of NSFileHandle %x",
+                                  fd, self);
+                       }
+                   }
+               }
+#endif
+
+               userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
+                       data, NSFileHandleNotificationDataItem,
+                       modes, NSFileHandleNotificationMonitorModes,
+                       nil];
+               notification = [NSNotification notificationWithName:
+                                 NSFileHandleReadCompletionNotification
+                                               object:self
+                                               userInfo:userInfo];
+           }
+#if defined(__MINGW32__)
+#  warning NSFileHandleAcceptOperation not yet supported in mingw32
+#else
+           else if (operation == NSFileHandleAcceptOperation) {
+               NSFileHandle* newFileHandle;
+               union {
+                   struct sockaddr_in in_addr;
+                   struct sockaddr_un un_addr;
+               } sock_address;
+               unsigned len = sizeof(sock_address);
+               int newFd;
+
+               operation = NSFileHandleNoOperation;
+               newFd = accept (fd, (struct sockaddr*)&sock_address, &len);
+               newFileHandle = AUTORELEASE([[NSFileHandle alloc]
+                                                initWithFileDescriptor:newFd
+                                                closeOnDealloc:YES]);
+               userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
+                       newFileHandle, NSFileHandleNotificationFileHandleItem,
+                       modes, NSFileHandleNotificationMonitorModes,
+                       nil];
+               notification = [NSNotification notificationWithName:
+                                 NSFileHandleConnectionAcceptedNotification
+                                               object:self
+                                               userInfo:userInfo];
+           }
+#endif
+
+           else if (operation == NSFileHandleReadToEndOfFileOperation) {
+               NSData* data = nil;
+
+               /* We use a similar algorithm as above here to read from
+                  the file descriptor. */
+               if (type == NSFileHandleUnixFile) {
+                   /* Reading from files cannot block so do an unconditional
+                      read here. */
+                   data = [self readDataToEndOfFile];
+               }
+#if defined(__MINGW32__)
+#  warning NSFileHandleSocket not yet supported in mingw32
+#else
+               else if (type == NSFileHandleSocket) {
+                   unsigned fileStatus = fcntl (fd, F_GETFL, 0);
+                   BOOL isNonBlocking = (fileStatus & non_blocking);
+
+                   /* Determine if the file descriptor does nonblocking I/O.
+                      If it doesn't temporary change it to do, read as many
+                      bytes as possible and change it back to blocking I/O.
+                    */
+                   /* Temporary set the file status to nonblocking I/O */
+                   if (!isNonBlocking) {
+                       if(fcntl(fd, F_SETFL, fileStatus|non_blocking) == -1) {
+                           NSLog (@"cannot set nonblocking status to file "
+                                  @"descriptor %d of NSFileHandle %x",
+                                  fd, self);
+                       }
+                   }
+
+                   data = [self readDataToEndOfFile];
+
+                   /* Restore the blocking I/O if it's the case */
+                   if (!isNonBlocking) {
+                       if(fcntl(fd, F_SETFL, fileStatus) == -1) {
+                           NSLog (@"cannot restore blocking status of file "
+                                  @"descriptor %d of NSFileHandle %x",
+                                  fd, self);
+                       }
+                   }
+
+                   /* Post the notification */
+                   userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
+                           data, NSFileHandleNotificationDataItem,
+                           modes, NSFileHandleNotificationMonitorModes,
+                           nil];
+                   notification = [NSNotification notificationWithName:
+                         NSFileHandleReadToEndOfFileCompletionNotification
+                                                   object:self
+                                                   userInfo:userInfo];
+               }
+#endif
+           }
+           [[NSNotificationCenter defaultCenter]
+                   postNotification:notification];
+           [self ceaseMonitoringFileActivity];
+           break;
+
+       default:
+           break;
+    }
+}
+
+@end /* NSConcreteFileHandle */
+
+
+@implementation NSNullDeviceFileHandle
+
+- (NSData*)availableData
+{
+    return [NSData data];
+}
+
+- (NSData*)readDataToEndOfFile
+{
+    return [NSData data];
+}
+
+- (NSData*)readDataOfLength:(unsigned int)length
+{
+    return [NSData data];
+}
+
+- (void)writeData:(NSData*)data
+{}
+
+- (void)acceptConnectionInBackgroundAndNotifyForModes:(NSArray*)_modes
+{}
+
+- (void)acceptConnectionInBackgroundAndNotify
+{}
+
+- (void)readInBackgroundAndNotifyForModes:(NSArray*)_modes
+{}
+
+- (void)readInBackgroundAndNotify
+{}
+
+- (void)readToEndOfFileInBackgroundAndNotifyForModes:(NSArray*)_modes
+{}
+
+- (void)readToEndOfFileInBackgroundAndNotify
+{}
+
+- (unsigned long long)offsetInFile
+{
+    return -1;
+}
+
+- (unsigned long long)seekToEndOfFile
+{
+    return -1;
+}
+
+- (void)seekToFileOffset:(unsigned long long)offset
+{}
+
+- (void)synchronizeFile
+{}
+
+- (void)closeFile
+{}
+
+- (void)truncateFileAtOffset:(unsigned long long)offset
+{}
+
+- (int)fileDescriptor
+{
+    return -1;
+}
+
+@end /* NSNullDeviceFileHandle */
+
+@implementation NSConcretePipeFileHandle
+
+- (id)initWithFileDescriptor:(int)_fd
+{
+    return [self initWithFileDescriptor:_fd closeOnDealloc:NO];
+}
+- (id)initWithFileDescriptor:(int)_fd closeOnDealloc:(BOOL)_flag
+{
+    self->fd             = _fd;
+    self->closeOnDealloc = _flag;
+    return self;
+}
+
+- (void)dealloc
+{
+    if (self->closeOnDealloc && (self->fd != -1))
+        [self closeFile];
+    [super dealloc];
+}
+
+/* Getting a file descriptor */
+
+- (int)fileDescriptor
+{
+    return self->fd;
+}
+
+/* Reading from an NSFileHandle */
+
+- (NSData *)availableData
+{
+    NSData   *data;
+    unsigned fileStatus;
+    BOOL     isNonBlocking;
+    
+    /* Determine if the file descriptor does nonblocking I/O.
+       If it doesn't temporary change it to do, read as many
+       bytes as possible and change it back to blocking I/O.
+    */
+    fileStatus    = fcntl (fd, F_GETFL, 0);
+    isNonBlocking = (fileStatus & non_blocking);
+                    
+    /* Temporary set the file status to nonblocking I/O */
+    if (!isNonBlocking) {
+        if(fcntl(fd, F_SETFL, fileStatus|non_blocking) == -1) {
+            NSLog (@"cannot set nonblocking status to file "
+                   @"descriptor %d of NSFileHandle %x",
+                   fd, self);
+        }
+    }
+
+    data = [self readDataOfLength:4096];
+
+    /* Restore the blocking I/O if it's the case */
+    if (!isNonBlocking) {
+        if(fcntl(fd, F_SETFL, fileStatus) == -1) {
+            NSLog (@"cannot restore blocking status of file "
+                   @"descriptor %d of NSFileHandle %x",
+                   fd, self);
+        }
+    }
+    return data;
+}
+
+- (NSData *)readDataToEndOfFile
+{
+    NSMutableData *mdata;
+    NSData        *data;
+    char          buffer[2048];
+    
+    mdata = [[NSMutableData alloc] initWithCapacity:4096];
+
+    while (YES) {
+        size_t readLen;
+        
+        readLen = read(self->fd, buffer, sizeof(buffer));
+        
+        if (readLen == 0) {
+            /* EOF */
+            if ([mdata length] == 0) {
+                /* EOF on first read */
+                RELEASE(mdata);
+                return nil;
+            }
+            break;
+        }
+        else if ((int)readLen == -1) {
+            /* read failed */
+#if defined(EINTR)
+            if (errno == EINTR)
+                /* read() was interrupted */
+                continue;
+#endif
+#if defined(EAGAIN)
+            if (errno == EAGAIN)
+                /* read() was interrupted */
+                continue;
+#endif
+            
+            [[[PosixFileOperationException alloc]
+                             initWithFormat:@"could not read bytes"] raise];
+        }
+        else
+            [mdata appendBytes:buffer length:readLen];
+    }
+    
+    data = [mdata copy];
+    RELEASE(mdata);
+    return AUTORELEASE(data);
+}
+
+- (NSData *)readDataOfLength:(unsigned int)length
+{
+    NSMutableData *mdata;
+    NSData        *data;
+    unsigned int  bufSize = 2048 > length ? length : 2048;
+    unsigned int  totalRead;
+    char          buffer[bufSize];
+    
+    mdata = [[NSMutableData alloc] initWithCapacity:2048];
+    totalRead = 0;
+    
+    while (YES) {
+        size_t readLen, toBeRead;
+        
+        readLen  = bufSize;
+        toBeRead = length - totalRead;
+        if (toBeRead < readLen)
+            readLen = toBeRead;
+        
+        readLen = read(self->fd, buffer, readLen);
+        
+        if ((readLen == 0) && (totalRead == 0)) {
+            /* EOF on first read */
+            RELEASE(mdata);
+            return nil;
+        }
+        
+        if ((int)readLen == -1) {
+            /* read failed */
+#if defined(EINTR)
+            if (errno == EINTR)
+                /* read() was interrupted */
+                continue;
+#endif
+#if defined(EAGAIN)
+            if (errno == EAGAIN)
+                /* read() was interrupted */
+                continue;
+#endif
+            
+            [[[PosixFileOperationException alloc]
+                             initWithFormat:@"could not read bytes"] raise];
+        }
+        
+        if (readLen > 0) {
+            /* add read data to buffer */
+            [mdata appendBytes:buffer length:readLen];
+            totalRead += readLen;
+        }
+        
+        if ((readLen < bufSize) && (readLen > 0)) {
+            /* some bytes where available, return them */
+            break;
+        }
+        
+        if (readLen == 0)
+            /* EOF */
+            break;
+
+        /* all bytes where available, so continue */
+    }
+    
+    data = [mdata copy];
+    RELEASE(mdata);
+    return AUTORELEASE(data);
+}
+
+/* Writing to a pipe */
+
+- (void)writeData:(NSData *)_data
+{
+    const char *bytes;
+    size_t toGo;
+    
+    bytes = [_data bytes];
+    toGo  = [_data length];
+
+    while (toGo > 0) {
+        size_t didWrite;
+        
+        didWrite = write(self->fd, bytes, toGo);
+        if ((int)didWrite == -1) {
+            /* write failed */
+#if defined(EINTR)
+            if (errno == EINTR)
+                /* read() was interrupted */
+                continue;
+#endif
+#if defined(EAGAIN)
+            if (errno == EAGAIN)
+                /* read() was interrupted */
+                continue;
+#endif
+            
+            [[[PosixFileOperationException alloc]
+               initWithFormat:@"could not write %d bytes", [_data length]] raise];
+        }
+        toGo  -= didWrite;
+        bytes += didWrite;
+    }
+}
+
+/* Communicating asynchronously in the background */
+
+- (void)acceptConnectionInBackgroundAndNotifyForModes:(NSArray *)modes
+{
+    [self shouldNotImplement:_cmd];
+}
+- (void)acceptConnectionInBackgroundAndNotify
+{
+    [self shouldNotImplement:_cmd];
+}
+
+- (void)readInBackgroundAndNotifyForModes:(NSArray *)modes
+{
+    [self notImplemented:_cmd];
+}
+- (void)readInBackgroundAndNotify
+{
+    [self notImplemented:_cmd];
+}
+- (void)readToEndOfFileInBackgroundAndNotifyForModes:(NSArray *)modes
+{
+    [self notImplemented:_cmd];
+}
+- (void)readToEndOfFileInBackgroundAndNotify
+{
+    [self notImplemented:_cmd];
+}
+
+/* Seeking within a file (not implemented on pipe's) */
+
+- (unsigned long long)offsetInFile
+{
+    [self shouldNotImplement:_cmd];
+    return 0;
+}
+- (unsigned long long)seekToEndOfFile
+{
+    [self shouldNotImplement:_cmd];
+    return 0;
+}
+- (void)seekToFileOffset:(unsigned long long)offset
+{
+    [self shouldNotImplement:_cmd];
+}
+
+/* Operating on a file */
+
+- (void)closeFile
+{
+    close(self->fd);
+    self->fd = -1;
+}
+- (void)synchronizeFile
+{
+}
+- (void)truncateFileAtOffset:(unsigned long long)offset
+{
+    [self shouldNotImplement:_cmd];
+}
+
+@end /* NSConcretePipeFileHandle */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConcreteMutableDictionary.m b/libFoundation/Foundation/NSConcreteMutableDictionary.m
new file mode 100644 (file)
index 0000000..e90aad8
--- /dev/null
@@ -0,0 +1,582 @@
+/* 
+   NSConcreteDictionary.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+   
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+           Helge Hess <helge.hess@skyrix.com>
+   
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <stdarg.h>
+#include <math.h>
+
+#include <Foundation/common.h>
+#include <Foundation/NSObject.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSException.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+
+#include "NSConcreteDictionary.h"
+
+/*
+* NSConcreteMutableDictionary class
+*/
+
+@interface _NSConcreteMutableDictionaryKeyEnumerator : NSEnumerator
+{
+    NSConcreteMutableDictionary *dict;
+    struct _NSMapNode *node;
+    int                      bucket;
+}
+@end
+@interface _NSConcreteMutableDictionaryObjectEnumerator : NSEnumerator
+{
+    NSConcreteMutableDictionary *dict;
+    struct _NSMapNode *node;
+    int                      bucket;
+}
+@end
+
+@implementation NSConcreteMutableDictionary
+
+/* 
+   static method cache for keys, which are almost always NSStrings, so this
+   should give a very good hit rate.
+*/
+static Class        LastKeyClass = Nil;
+static BOOL         (*KeyEq)(id, SEL, id);
+static unsigned int (*KeyHash)(id, SEL);
+static IMP          KeyRetain;
+
+static __inline__ int _getHashSize(NSConcreteMutableDictionary *self)
+{
+    return self->hashSize;
+}
+
+static __inline__ struct _NSMapNode *
+_getNodeAt(NSConcreteMutableDictionary *self, int idx)
+{
+    return self->nodes[idx];
+}
+
+static BOOL is_prime(unsigned n)
+{
+    int i, n2 = sqrt(n);
+
+    for(i = 2; i <= n2; i++)
+        if(n % i == 0)
+            return NO;
+    return YES;
+}
+static unsigned nextPrime(unsigned old_value)
+{
+    unsigned i, new_value = old_value | 1;
+
+    for (i = new_value; i >= new_value; i += 2)
+        if (is_prime(i))
+            return i;
+    return old_value;
+}
+
+static void mdMapGrow(NSConcreteMutableDictionary *table, unsigned newSize)
+{
+    unsigned i;
+    struct _NSMapNode **newNodeTable;
+    
+    newNodeTable =
+        NSZoneCalloc([table zone], newSize, sizeof(struct _NSMapNode*));
+    
+    for (i = 0; i < table->hashSize; i++) {
+       struct _NSMapNode *next, *node;
+       unsigned int h;
+        
+       node = table->nodes[i];
+       while (node) {
+           next = node->next;
+           h = [(id)node->key hash] % newSize;
+           node->next = newNodeTable[h];
+           newNodeTable[h] = node;
+           node = next;
+       }
+    }
+    NSZoneFree([table zone], table->nodes);
+    table->nodes    = newNodeTable;
+    table->hashSize = newSize;
+}
+
+static void mdCheckMapTableFull(NSConcreteMutableDictionary *table)
+{
+    if( ++(table->itemsCount) >= ((table->hashSize * 3) / 4)) {
+       unsigned newSize;
+        
+        newSize = nextPrime((table->hashSize * 4) / 3);
+       if(newSize != table->hashSize)
+           mdMapGrow(table, newSize);
+    }
+}
+
+static __inline__ void
+mdInsert(NSConcreteMutableDictionary *table, id key, id value)
+{
+    unsigned int h;
+    struct _NSMapNode *node;
+    
+    if (*(Class *)key != LastKeyClass) {
+        LastKeyClass = *(Class *)key;
+        if (object_is_instance(key)) {
+            KeyEq   = (void *)method_get_imp(class_get_instance_method(
+                        LastKeyClass, @selector(isEqual:)));
+            KeyHash = (void *)method_get_imp(class_get_instance_method(
+                        LastKeyClass, @selector(hash)));
+            KeyRetain = method_get_imp(class_get_instance_method(
+                        LastKeyClass, @selector(retain)));
+        }
+        else {
+            KeyEq   = (void *)method_get_imp(class_get_class_method(
+                        LastKeyClass, @selector(isEqual:)));
+            KeyHash = (void *)method_get_imp(class_get_class_method(
+                        LastKeyClass, @selector(hash)));
+            KeyRetain = method_get_imp(class_get_class_method(
+                        LastKeyClass, @selector(retain)));
+        }
+    }
+    
+    h = KeyHash(key, NULL /* dangerous? */) % table->hashSize;
+    
+    for (node = table->nodes[h]; node; node = node->next) {
+        if (KeyEq(key, NULL /* dangerous? */, node->key))
+            break;
+    }
+    
+    /* Check if an entry for key exist in nodeTable. */
+    if (node) {
+        /* key exist. Set for it new value and return the old value of it. */
+       if (key != node->key) {
+            KeyRetain(key, NULL /* dangerous? */);
+            RELEASE((id)node->key);
+       }
+       if (value != node->value) {
+            RETAIN(value);
+            RELEASE((id)node->value);
+       }
+       node->key   = key;
+       node->value = value;
+        return;
+    }
+    
+    /* key not found. Allocate a new bucket and initialize it. */
+    node = NSZoneMalloc([table zone], sizeof(struct _NSMapNode));
+    node->key   = (void*)KeyRetain(key, NULL /* dangerous? */);
+    node->value = (void*)RETAIN(value);
+    node->next  = table->nodes[h];
+    table->nodes[h] = node;
+    
+    mdCheckMapTableFull(table);
+}
+
+static __inline__ id mdGet(NSConcreteMutableDictionary *table, id key) {
+    static Class LastKeyClass = Nil;
+    static unsigned int (*mhash)(id, SEL);
+    static BOOL (*meq)(id, SEL, id);
+    register struct _NSMapNode *node;
+    
+    if (key == nil)
+       // TODO: are nil-keys allowed in Cocoa? Maybe print a warning
+       return nil;
+    if (LastKeyClass != *(id *)key) {
+       LastKeyClass = *(id *)key;
+       mhash = (void *)method_get_imp(class_get_instance_method(LastKeyClass, 
+          @selector(hash)));
+       meq   = (void *)method_get_imp(class_get_instance_method(LastKeyClass, 
+          @selector(isEqual:)));
+    }
+    
+    node = table->nodes[mhash(key, NULL /* dangerous? */) % table->hashSize];
+    for (; node; node = node->next) {
+        /* could cache method .. */
+        if (meq(key, NULL /*dangerous?*/, node->key))
+            return node->value;
+    }
+    return nil;
+}
+
+static __inline__ void mdRemove(NSConcreteMutableDictionary *table, id key) {
+    unsigned int h;
+    struct _NSMapNode *node, *node1 = NULL;
+
+    if (key == nil)
+        return;
+
+    h = [key hash] % table->hashSize;
+    
+    // node point to current bucket, and node1 to previous bucket or to NULL
+    // if current node is the first node in the list 
+    
+    for (node = table->nodes[h]; node; node1 = node, node = node->next) {
+        /* could cache method .. */
+        if (![key isEqual:node->key])
+            continue;
+        
+        RELEASE((id)node->key);
+        RELEASE((id)node->value);
+            
+        if (!node1)
+            table->nodes[h] = node->next;
+        else
+            node1->next = node->next;
+        NSZoneFree([table zone], node);
+        (table->itemsCount)--;
+        return;
+    }
+}
+
+/* Allocating and Initializing */
+
+- (id)init
+{
+    return [self initWithCapacity:0];
+}
+
+- (id)initWithCapacity:(unsigned int)aNumItems
+{
+    unsigned capacity;
+
+    if (aNumItems != 0) {
+        capacity = (aNumItems * 4) / 3;
+        if (!is_prime(capacity))
+            capacity = nextPrime(capacity);
+    }
+    else {
+        capacity = 13;
+    }
+
+#if LOG_INIT_CAPACITY
+    printf("MDICT initWithCapacity:%i\n", capacity);
+#endif
+    
+    self->hashSize   = capacity;
+    self->nodes      = NSZoneCalloc([self zone], capacity, sizeof(void *));
+    self->itemsCount = 0;
+    return self;
+}
+
+- (id)initWithObjects:(id *)objects
+  forKeys:(id *)keys 
+  count:(unsigned int)count
+{
+    unsigned capacity;
+
+    if (count != 0) {
+        capacity = (count * 4) / 3;
+        if (!is_prime(capacity))
+            capacity = nextPrime(capacity);
+    }
+    else
+        capacity = 13;
+    
+#if LOG_INIT_CAPACITY
+    printf("MDICT initWithCapacity:%i\n", capacity);
+#endif
+    
+    self->hashSize   = capacity;
+    self->nodes      = NSZoneCalloc([self zone], capacity, sizeof(void *));
+    self->itemsCount = 0;
+    
+    if (count == 0)
+        return self;
+
+    while (count--) {
+        register id key, value;
+        
+       if ((key = keys[count]) == nil) {
+           [[[InvalidArgumentException alloc] 
+                   initWithReason:@"Nil key to be added in dictionary"] raise];
+        }
+       if ((value = objects[count]) == nil) {
+           [[[InvalidArgumentException alloc] 
+                   initWithReason:@"Nil value to be added in dictionary"] raise];
+        }
+        
+       mdInsert(self, key, value);
+    }
+    return self;
+}
+
+- (id)initWithDictionary:(NSDictionary *)dictionary
+{
+    unsigned     capacity;
+    NSEnumerator *keys;
+    id           key;
+
+    capacity = [dictionary count] * 4 / 3;
+    capacity = capacity != 0 ? capacity : 13;
+    if (!is_prime(capacity))
+       capacity = nextPrime(capacity);
+
+    self->hashSize   = capacity;
+    self->nodes      = NSZoneCalloc([self zone], capacity, sizeof(void *));
+    self->itemsCount = 0;
+    
+#if LOG_INIT_CAPACITY
+    printf("MDICT initWithCapacity:%i\n", capacity);
+#endif
+    
+    keys = [dictionary keyEnumerator];
+    while ((key = [keys nextObject]))
+       mdInsert(self, key, [dictionary objectForKey:key]);
+    
+    return self;
+}
+
+- (void)dealloc
+{
+    if (self->itemsCount > 0) {
+        NSZone *z = [self zone];
+        unsigned i;
+        
+        for (i = 0; i < self->hashSize; i++) {
+            struct _NSMapNode *next, *node;
+            
+            node = self->nodes[i];
+            self->nodes[i] = NULL;             
+            while (node) {
+#if !LIB_FOUNDATION_BOEHM_GC
+                [(id)node->key   release];
+                [(id)node->value release];
+#endif
+                next = node->next;
+                NSZoneFree(z, node);
+                node = next;
+            }
+        }
+        self->itemsCount = 0;
+    }
+    
+    if (self->nodes)
+        NSZoneFree([self zone], self->nodes);
+    [super dealloc];
+}
+
+/* Accessing keys and values */
+
+- (NSEnumerator *)keyEnumerator
+{
+    static Class KeyEnumClass = Nil;
+    if (KeyEnumClass == Nil)
+        KeyEnumClass = [_NSConcreteMutableDictionaryKeyEnumerator class];
+    return AUTORELEASE([[KeyEnumClass alloc] initWithDictionary:self]);
+}
+- (NSEnumerator *)objectEnumerator
+{
+    return AUTORELEASE([[_NSConcreteMutableDictionaryObjectEnumerator alloc]
+                           initWithDictionary:self]);
+}
+
+- (id)objectForKey:(id)aKey
+{
+    return mdGet(self, aKey);
+}
+
+- (unsigned int)count
+{
+    return self->itemsCount;
+}
+
+/* Modifying dictionary */
+
+- (void)setObject:(id)anObject forKey:(id)aKey
+{
+    if (aKey == nil) {
+       [[[InvalidArgumentException alloc]
+                   initWithFormat:
+                      @"nil key to be added in dictionary (object=0x%08X)",
+                      anObject] raise];
+    }
+    if (anObject == nil) {
+       [[[InvalidArgumentException alloc]
+                   initWithFormat:
+                      @"nil object to be added in dictionary (key=%@)",
+                      aKey] raise];
+    }
+    mdInsert(self, aKey, anObject);
+}
+
+- (void)removeObjectForKey:(id)aKey
+{
+    mdRemove(self, aKey);
+}
+
+- (void)removeAllObjects
+{
+    if (self->itemsCount > 0) {
+        NSZone *z = [self zone];
+        unsigned i;
+        
+        for (i = 0; i < self->hashSize; i++) {
+            struct _NSMapNode *next, *node;
+            
+            node = self->nodes[i];
+            self->nodes[i] = NULL;
+            while (node) {
+#if !LIB_FOUNDATION_BOEHM_GC
+                [(id)node->key   release];
+                [(id)node->value release];
+#endif
+                next = node->next;
+                NSZoneFree(z, node);
+                node = next;
+            }
+        }
+        self->itemsCount = 0;
+    }
+}
+
+/* NSCopying */
+
+- (id)copyWithZone:(NSZone *)_zone
+{
+    if (self->itemsCount == 0)
+        return [[NSConcreteMutableDictionary allocWithZone:_zone] init];
+    
+    if (self->itemsCount == 1) {
+        struct _NSMapNode *node  = NULL;
+        int              bucket = -1;
+        
+       for (bucket++; ((unsigned)bucket) < self->hashSize; bucket++) {
+            
+            if (_getNodeAt(self, bucket)) {
+                node = _getNodeAt(self, bucket);
+                break;
+           }
+        }
+       NSAssert(((unsigned)bucket) < self->hashSize,
+                 @"invalid hashtable state !");
+        
+        return [[NSConcreteSingleObjectDictionary allocWithZone:_zone]
+                                                  initWithObjects:
+                                                    (id *)&(node->value) 
+                                                  forKeys:(id *)&(node->key)
+                                                  count:1];
+    }
+    
+#if defined(SMALL_NSDICTIONARY_SIZE) && 0
+    if (self->itemsCount <= SMALL_NSDICTIONARY_SIZE) {
+        return [[NSConcreteSmallDictionary allocWithZone:_zone]
+                                           initWithDictionary:self
+                                           copyItems:NO];
+    }
+#endif
+    
+    return [[NSConcreteHashDictionary allocWithZone:_zone]
+                                      initWithDictionary:self copyItems:NO];
+}
+
+@end /* NSConcreteMutableDictionary */
+
+@implementation _NSConcreteMutableDictionaryKeyEnumerator
+
+- (id)initWithDictionary:(NSConcreteMutableDictionary *)_dict
+{
+    self->dict   = RETAIN(_dict);
+    self->node   = NULL;
+    self->bucket = -1;
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(dict);
+    [super dealloc];
+}
+
+- (id)nextObject
+{
+    if (self->node)
+       self->node = self->node->next;
+    
+    if (self->node == NULL) {
+       for(self->bucket++;
+            ((int)self->bucket) < _getHashSize(self->dict);
+            self->bucket++) {
+
+            if (_getNodeAt(self->dict, self->bucket)) {
+                self->node = _getNodeAt(self->dict, self->bucket);
+                break;
+           }
+        }
+       if (((int)self->bucket) >= _getHashSize(self->dict)) {
+           self->node = NULL;
+           self->bucket = (_getHashSize(self->dict) - 1);
+           return nil;
+       }
+    }
+    return self->node->key;
+}
+
+@end /* _NSConcreteMutableDictionaryKeyEnumerator */
+
+@implementation _NSConcreteMutableDictionaryObjectEnumerator
+
+- (id)initWithDictionary:(NSConcreteMutableDictionary *)_dict
+{
+    self->dict   = RETAIN(_dict);
+    self->node   = NULL;
+    self->bucket = -1;
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(dict);
+    [super dealloc];
+}
+
+- (id)nextObject
+{
+    if (self->node)
+       self->node = self->node->next;
+    
+    if (self->node == NULL) {
+       for (self->bucket++;
+             ((int)self->bucket) < _getHashSize(self->dict);
+             self->bucket++) {
+            if (_getNodeAt(self->dict, self->bucket)) {
+                self->node = _getNodeAt(self->dict, self->bucket);
+                break;
+           }
+        }
+       if (((int)self->bucket) >= _getHashSize(self->dict)) {
+           self->node = NULL;
+           self->bucket = (_getHashSize(self->dict) - 1);
+           return nil;
+       }
+    }
+    return self->node->value;
+}
+
+@end /* _NSConcreteMutableDictionaryObjectEnumerator */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConcreteMutableString.m b/libFoundation/Foundation/NSConcreteMutableString.m
new file mode 100644 (file)
index 0000000..442bf61
--- /dev/null
@@ -0,0 +1,819 @@
+/* 
+   NSMutableSimple8BitString.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSConcreteString.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/NSCoder.h>
+#include <Foundation/NSData.h>
+#include <Foundation/NSCharacterSet.h>
+#include <Foundation/exceptions/StringExceptions.h>
+#include <Foundation/common.h>
+#include <extensions/objc-runtime.h>
+
+@implementation NSMutable8BitString
+
++ (void)initialize
+{
+    static BOOL initialized = NO;
+
+    if(!initialized) {
+       initialized = YES;
+       class_add_behavior(self, [NS8BitString class]);
+    }
+}
+
+- (id)initWithString:(NSString*)aString
+{
+    if (![aString isKindOfClass:[NS8BitString class]] &&
+       ![aString isKindOfClass:[NSMutable8BitString class]])
+           return [super initWithString:(NSString*)aString];
+    
+    return [self initWithCString:[(id)aString __compact8BitBytes]
+       length:[aString cStringLength] copy:YES];
+}
+
+- (id)initWithContentsOfFile:(NSString *)_path
+{
+    unsigned char *bytes = NULL;
+    unsigned len;
+
+    if ((bytes = NSReadContentsOfFile(_path, 1, &len))) {
+        bytes[len] = '\0';
+        return [self initWithCString:bytes length:len copy:NO];
+    }    
+    else {
+        self = AUTORELEASE(self);
+        return nil;
+    }
+}
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    Class clazz;
+    int length = [self cStringLength];
+
+    clazz = (length < 255)
+        ? [NSShortInline8BitString class]
+        : [NSInline8BitString class];
+    
+    return [[clazz allocForCapacity:length zone:zone]
+                   initWithCString:[self __compact8BitBytes] length:length];
+}
+
+- (Class)classForCoder
+{
+    return [NSMutable8BitString class];
+}
+
+- (id)initWithCoder:(NSCoder*)aDecoder
+{
+    unsigned char *bytes;
+    int length;
+
+    RELEASE(self); self = nil;
+    
+    [aDecoder decodeValueOfObjCType:@encode(int) at:&length];
+    bytes = MallocAtomic (length);
+    [aDecoder decodeArrayOfObjCType:@encode(char) count:length at:bytes];
+    return [[NSMutableSimple8BitString alloc]
+               initWithCString:bytes length:length copy:NO];
+}
+
+- (NSData *)dataUsingEncoding:(NSStringEncoding)encoding
+  allowLossyConversion:(BOOL)flag;
+{
+    /* NSMutableSimple8BitString */
+    
+    if (encoding == [NSString defaultCStringEncoding]) {
+        unsigned      len;
+        unsigned char *buf;
+        
+        len = [self cStringLength];
+        buf = NSZoneMallocAtomic(NULL, len + 1);
+        [self getCString:buf]; buf[len] = '\0';
+        
+        return [NSData dataWithBytesNoCopy:buf length:len];
+    }
+    else if (encoding == NSASCIIStringEncoding) {
+        unsigned      len;
+        unsigned char *buf;
+        unsigned      i;
+        
+        len = [self cStringLength];
+        buf = NSZoneMallocAtomic(NULL, len + 1);
+        [self getCString:buf]; buf[len] = '\0';
+        
+        if (!flag) {
+            /* check for strict ANSI */
+            for (i = 0; i < len; i++)
+                if (buf[i] > 127) return nil;
+        }
+        return [NSData dataWithBytesNoCopy:buf length:len];
+    }
+    else
+        return [super dataUsingEncoding:encoding allowLossyConversion:flag];
+}
+
+/* NS8BitString class (formerly added using add_behaviour) */
+
+/* Accessing characters        */
+
+- (void)getCharacters:(unichar*)buffer range:(NSRange)aRange
+{
+    register unsigned int i = 0;
+    register unsigned char *bytes;
+    
+    if (aRange.location + aRange.length > [self cStringLength]) {
+       [[[IndexOutOfRangeException alloc] 
+           initWithFormat:@"range (%d,%d) in string %x of length %d",
+               aRange.location, aRange.length, self, [self cStringLength]] 
+            raise];
+    }
+    
+    bytes = [self __compact8BitBytes];
+    for (i = 0; i < aRange.length; i++)
+        buffer[i] = bytes[i];
+}
+
+/* Dividing strings */
+
+- (NSString *)substringWithRange:(NSRange)aRange
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+/* Finding characters and substrings */
+
+- (NSRange)rangeOfCharacterFromSet:(NSCharacterSet*)aSet
+  options:(unsigned int)mask range:(NSRange)aRange
+{
+    // ENCODINGS - this code applies to the system's default encoding
+    unsigned int i = 0;
+
+    IMP imp = [aSet methodForSelector:@selector(characterIsMember:)];
+    unsigned char *bytes = [self __compact8BitBytes];
+
+    if (NSMaxRange(aRange) > [self cStringLength]) {
+        [[[IndexOutOfRangeException alloc] initWithFormat:
+            @"range %@ not in string 0x%08x of length %d",
+            NSStringFromRange(aRange),
+            self,
+            [self cStringLength]]
+            raise];
+    }
+
+    if (mask & NSBackwardsSearch) {
+        for (i = aRange.length - 1; i >= aRange.location; i--) {
+            unichar c = bytes[i];
+           
+            if ((*imp)(aSet, @selector(characterIsMember:), c) ||
+                ((mask & NSCaseInsensitiveSearch) && 
+                 ((islower(c) &&
+                   (*imp)(aSet, @selector(characterIsMember:), toupper(c))) ||
+                  (isupper(c) &&
+                   (*imp)(aSet, @selector(characterIsMember:), tolower(c))))
+                 ))
+            {
+                return NSMakeRange(i, 1);
+            }
+        }
+    } 
+    else {
+        unsigned max = NSMaxRange(aRange);
+
+        for (i = aRange.location; i < max; i++) {
+            unichar c = bytes[i];
+            
+            if ((*imp)(aSet, @selector(characterIsMember:), c) ||
+                ((mask & NSCaseInsensitiveSearch) && 
+                 ((islower(c) &&
+                   (*imp)(aSet, @selector(characterIsMember:), toupper(c))) ||
+                  (isupper(c) &&
+                   (*imp)(aSet, @selector(characterIsMember:), tolower(c))))
+                 ))
+            {
+                return NSMakeRange(i, 1);
+            }
+        }
+    }
+    return NSMakeRange(NSNotFound, 0);
+}
+
+- (NSRange)rangeOfString:(NSString*)aString
+  options:(unsigned int)mask range:(NSRange)aRange
+{
+    // ENCODINGS - this code applies to the system's default encoding
+    NSRange       range;
+    unsigned char *mbytes;
+    unsigned char *abytes;
+    unsigned int  a;
+    
+    if (![aString isKindOfClass:[NS8BitString class]] &&
+       ![aString isKindOfClass:[NSMutable8BitString class]])
+           return [super rangeOfString:aString options:mask range:aRange];
+    
+    if (NSMaxRange(aRange) > [self cStringLength]) {
+        [[[IndexOutOfRangeException alloc] initWithFormat:
+            @"range %@ not in string 0x%08x of length %d",
+            NSStringFromRange(aRange),
+            self,
+            [self cStringLength]]
+            raise];
+    }
+
+    mbytes = [self __compact8BitBytes] + aRange.location;
+    abytes = [(id)aString __compact8BitBytes];
+    a = [aString cStringLength];
+    
+    if ((a == 0) || (aRange.length < a))
+        return NSMakeRange(0, 0);
+    
+    if (mask & NSAnchoredSearch)  {
+       range.location = aRange.location + 
+           ((mask & NSBackwardsSearch) ? aRange.length - a : 0);
+       range.length = a;
+       
+       if ([self compare:aString options:mask range:range] == NSOrderedSame)
+           return range;
+       else
+           return NSMakeRange(0,0);
+    }
+    
+    if (mask & NSBackwardsSearch) {    
+       if (mask & NSCaseInsensitiveSearch) {
+           /* Backward case insensitive */
+           unsigned char cf;
+            int n;
+
+            cf = islower(abytes[0]) ? toupper(abytes[0]) : abytes[0];
+            
+           for (n = aRange.length-a; n >= 0; n--) {
+               unsigned char cm =
+                    islower(mbytes[n]) ? toupper(mbytes[n]) : mbytes[n];
+               unsigned char ca = cf;
+                unsigned int  i;
+                
+               if (cm != ca)
+                   continue;
+               for (i = 1; i < a; i++) {
+                   cm = islower(mbytes[n+i]) ? 
+                       toupper(mbytes[n+i]) : mbytes[n+i];
+                   ca = islower(abytes[i]) ? toupper(abytes[i]) : abytes[i];
+                   if (cm != ca)
+                       break;
+               }
+               if (i == a) {
+                   range.location = aRange.location + n;
+                   range.length = a;
+                   return range;
+               }
+           }
+       }
+       else {
+           /* Backward case sensitive */
+            int n;
+           for (n = (aRange.length - a); n >= 0; n--) {
+                unsigned int i;
+                
+               if (mbytes[n] != abytes[0])
+                   continue;
+               for (i = 1; i < a; i++)
+                   if (mbytes[n+i] != abytes[i])
+                       break;
+               if (i == a) {
+                   range.location = aRange.location + n;
+                   range.length = a;
+                   return range;
+               }
+           }
+       }
+    }
+    else {
+       if (mask & NSCaseInsensitiveSearch) {
+           /* Forward case insensitive */
+            int n;
+           unsigned char cf;
+
+            cf = islower(abytes[0]) ? toupper(abytes[0]) : abytes[0];
+
+           for (n = 0; n + a <= aRange.length; n++) {
+               unsigned char cm, ca;
+                unsigned int i;
+               
+                cm = islower(mbytes[n]) ? toupper(mbytes[n]) : mbytes[n];
+                ca = cf;
+                
+               if (cm != ca)
+                   continue;
+               for (i = 1; i < a; i++) {
+                   cm = islower(mbytes[n+i]) ? 
+                       toupper(mbytes[n+i]) : mbytes[n+i];
+                   ca = islower(abytes[i]) ? toupper(abytes[i]) : abytes[i];
+                   if (cm != ca)
+                       break;
+               }
+               if (i == a) {
+                   range.location = aRange.location + n;
+                   range.length = a;
+                   return range;
+               }
+           }
+       }
+       else {
+           /* Forward case sensitive */
+            int n;
+            
+           for (n = 0; (n + a) <= aRange.length; n++) {
+                register unsigned int i;
+                
+               if (mbytes[n] != abytes[0])
+                   continue;
+               for (i = 1; i < a; i++)
+                   if (mbytes[n+i] != abytes[i])
+                       break;
+               if (i == a) {
+                   range.location = aRange.location + n;
+                   range.length   = a;
+                   return range;
+               }
+           }
+       }
+    }
+    
+    range.location = range.length = 0;
+    return range;
+}
+
+- (NSComparisonResult)compare:(NSString*)aString
+  options:(unsigned int)mask range:(NSRange)aRange
+{
+    // ENCODINGS - this code applies to the system's default encoding
+    unsigned char* mbytes;
+    unsigned char* abytes;
+    unsigned int i, n, a;
+
+    if (![aString isKindOfClass:[NS8BitString class]] &&
+       ![aString isKindOfClass:[NSMutable8BitString class]])
+           return [super compare:aString options:mask range:aRange];
+    
+    if (NSMaxRange(aRange) > [self cStringLength]) {
+        [[[IndexOutOfRangeException alloc] initWithFormat:
+            @"range %@ not in string 0x%08x of length %d",
+            NSStringFromRange(aRange),
+            self,
+            [self cStringLength]]
+            raise];
+    }
+    
+    mbytes = [self __compact8BitBytes] + aRange.location;
+    abytes = [(id)aString __compact8BitBytes];
+    
+    a = [aString cStringLength];
+    n = MIN(a, aRange.length);
+    
+    if (mask & NSCaseInsensitiveSearch) {
+       for (i = 0; i < n; i++) {
+           unsigned char cm = islower(mbytes[i]) ? toupper(mbytes[i]):mbytes[i];
+           unsigned char ca = islower(abytes[i]) ? toupper(abytes[i]):abytes[i];
+
+           if (cm < ca)
+               return NSOrderedAscending;
+           if (cm > ca)
+               return NSOrderedDescending;
+       }
+    }
+    else {
+       for (i = 0; i < n; i++) {
+           if (mbytes[i] < abytes[i])
+               return NSOrderedAscending;
+           if (mbytes[i] > abytes[i])
+               return NSOrderedDescending;
+       }
+    }
+    
+    if (aRange.length < a)
+       return NSOrderedAscending;
+    if (aRange.length > a)
+       return NSOrderedDescending;
+
+    return NSOrderedSame;
+}
+
+- (unsigned)hash
+{
+    unsigned char *bytes = [self __compact8BitBytes];
+    unsigned hash = 0, hash2;
+    int i, n = [self cStringLength];
+
+    for(i=0; i < n; i++) {
+        hash <<= 4;
+       // UNICODE - must use a for independent of composed characters
+        hash += bytes[i];
+        if((hash2 = hash & 0xf0000000))
+            hash ^= (hash2 >> 24) ^ hash2;
+    }
+    
+    return hash;
+}
+
+/* Getting a shared prefix */
+
+- (NSString *)commonPrefixWithString:(NSString*)aString
+  options:(unsigned int)mask
+{
+    // ENCODINGS - this code applies to the system's default encoding
+    NSRange range = {0, 0};
+    unsigned char *mbytes;
+    unsigned char *abytes;
+    int     mLen;
+    int     aLen;
+    int     i;
+
+    if (![aString isKindOfClass:[NS8BitString class]] &&
+       ![aString isKindOfClass:[NSMutable8BitString class]])
+           return [super commonPrefixWithString:aString options:mask];
+    
+    mLen   = [self cStringLength];
+    aLen   = [aString length];
+    mbytes = [self __compact8BitBytes];
+    abytes = [(NS8BitString *)aString __compact8BitBytes];
+
+    for (i = 0; (i < mLen) && (i < aLen); i++) {
+       unsigned char c1 = mbytes[i];
+       unsigned char c2 = abytes[i];
+        
+        if (mask & NSCaseInsensitiveSearch) {
+            c1 = tolower(c1);
+            c2 = tolower(c2);
+        }
+        if (c1 != c2)
+            break;
+    }
+    
+    range.length = i;
+    return [self substringWithRange:range];
+}
+
+/* Changing case */
+
+- (NSString *)capitalizedString
+{
+    // ENCODINGS - this code applies to the system's default encoding
+    int           i;
+    BOOL          f      = YES;
+    int           length = [self cStringLength];
+    unsigned char *bytes  = [self __compact8BitBytes];
+    unsigned char *chars  = MallocAtomic(sizeof(unichar)*(length+1));
+
+    for (i = 0; i < length; i++) {
+       unsigned char c = bytes[i];
+       
+       if (isspace(c))
+           f = YES;
+       
+       if (f) {
+           chars[i] = islower(c) ? toupper(c) : c;
+           f = NO;
+       }
+       else
+           chars[i] = isupper(c) ? tolower(c) : c;
+    }
+    chars[i] = 0;
+    
+    return AUTORELEASE([[NSOwned8BitString alloc]
+                           initWithCString:chars length:length copy:NO]);
+}
+
+- (NSString *)lowercaseString
+{
+    // ENCODINGS - this code applies to the system's default encoding
+    int           i, length;
+    unsigned char *bytes;
+    unsigned char *chars;
+    
+    length = [self cStringLength];
+    bytes  = [self __compact8BitBytes];
+    chars  = MallocAtomic(sizeof(unsigned char) * (length + 1));
+    
+    for (i = 0; i < length; i++) {
+       register unsigned char c = bytes[i];
+        
+        chars[i] = isupper(c) ? tolower(c) : c;
+    }
+    chars[i] = 0;
+
+    return AUTORELEASE([[NSOwned8BitString alloc]
+                           initWithCString:chars length:length copy:NO]);
+}
+
+- (NSString *)uppercaseString
+{
+    // ENCODINGS - this code applies to the system's default encoding
+    int i;
+    int length = [self cStringLength];
+    unsigned char *bytes = [self __compact8BitBytes];
+    unsigned char *chars = MallocAtomic(sizeof(unichar)*(length+1));
+
+    for (i = 0; i < length; i++) {
+       register unsigned char c = bytes[i];
+       chars[i] = islower(c) ? toupper(c) : c;
+    }
+    
+    chars[i] = 0;
+
+    return AUTORELEASE([[NSOwned8BitString alloc]
+                           initWithCString:chars length:length copy:NO]);
+}
+
+/* Working with C strings */
+
+- (void)getCString:(char *)buffer maxLength:(unsigned int)maxLength
+  range:(NSRange)aRange remainingRange:(NSRange *)leftoverRange
+{
+    unsigned char *bytes = [self __compact8BitBytes];
+    unsigned int toMove = MIN(maxLength, aRange.length);
+    unsigned int cLength = [self cStringLength];
+    
+    if (NSMaxRange(aRange) > cLength) {
+        [[[IndexOutOfRangeException alloc] initWithFormat:
+            @"range %@ not in string 0x%08x of length %d",
+            NSStringFromRange(aRange),
+            self,
+            cLength]
+            raise];
+    }
+    
+    if (leftoverRange) {
+        leftoverRange->location = aRange.location + toMove;
+        leftoverRange->length = cLength - leftoverRange->location;
+    }
+    memcpy(buffer, bytes + aRange.location, toMove);
+    if (toMove < maxLength)
+       buffer[toMove] = '\0';
+}
+
+- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)flag
+{
+    // UNICODE - remove this
+    NSData *data;
+    data = [self dataUsingEncoding:[NSString defaultCStringEncoding]];
+    return writeToFile(path, data, flag);
+}
+
+- (NSString *)stringRepresentation
+{
+    const unsigned char *cString;
+    int i, length;
+
+    cString = [self __compact8BitBytes];
+    length = [self cStringLength];
+
+    if (cString == NULL)    return @"\"\"";
+    if (cString[0] == '\0') return @"\"\"";
+
+    /* Check if the string can be parsed as a STRING token by the property list
+       parser. Otherwise we must enclose it in double quotes. */
+    if (lf_isPlistBreakChar(cString[0])) {
+        return lf_quoteString(cString, length);
+    }
+
+    for(i = 1; i < length; i++) {
+        if (lf_isPlistBreakChar(cString[i]))
+           return lf_quoteString(cString, length);
+    }
+
+    return self;
+}
+
+- (id)mutableCopyWithZone:(NSZone*)zone
+{
+    return [[NSMutableSimple8BitString allocWithZone:zone]
+       initWithCString:[self __compact8BitBytes]
+       length:[self cStringLength] copy:YES];
+}
+
+@end /* NSMutable8BitString */
+
+@implementation NSMutableSimple8BitString
+
+- (id)init
+{
+    self->cLength = 0;
+    return self;
+}
+
+- (id)initWithCapacity:(unsigned int)capacity
+{
+    self->cLength = 0;
+    self->cCapacity = capacity;
+    NSZoneFree([self zone], self->cString);
+    self->cString = NSZoneMallocAtomic([self zone], sizeof(char)*capacity);
+    return self;
+}
+
+- (id)initWithString:(NSString *)aString
+{
+    // TODO: jr: move to NSTemporaryMutableString
+    // TODO: hh: I do not understand this code, commented out ...
+#if 0
+    if ([aString isKindOfClass:[NS8BitString class]] ||
+       [aString isKindOfClass:[NSMutable8BitString class]]) {
+        NSMutable8BitString *str;
+
+        str = [[NSMutable8BitString allocWithZone:[self zone]]
+                                    initWithString:aString];
+        RELEASE(self);
+        return str;
+    }
+#endif
+    return [self initWithCString:(char *)[aString cString]
+                 length:[aString cStringLength] 
+                copy:YES];
+}
+
+
+- (id)initWithCString:(char *)byteString
+  length:(unsigned int)length
+  copy:(BOOL)flag
+{
+    if (flag) {
+       if (cCapacity < length) {
+           lfFree(self->cString);
+           self->cString = NSZoneMallocAtomic([self zone], sizeof(char)*length);
+           self->cCapacity = length;
+       }
+       self->cLength = length;
+       memcpy(self->cString, byteString, length);
+    }
+    else {
+       lfFree(cString);
+       cString = byteString;
+       cLength = cCapacity = length;
+    }
+    return self;
+}
+
+- (void)dealloc
+{
+    lfFree(cString);
+    [super dealloc];
+}
+
+- (const char*)cString
+{
+    unsigned char *str = MallocAtomic(sizeof(char)*(cLength + 1));
+
+    memcpy(str, cString, cLength);
+    str[cLength] = 0;
+#if !LIB_FOUNDATION_BOEHM_GC
+    [NSAutoreleasedPointer autoreleasePointer:str];
+#endif
+    return str;
+}
+
+- (unsigned int)cStringLength
+{
+    return self->cLength;
+}
+
+- (unsigned int)length
+{
+    return self->cLength;
+}
+
+- (unichar)characterAtIndex:(unsigned int)index
+{
+    if (index >= self->cLength) {
+       [[[IndexOutOfRangeException alloc] 
+           initWithFormat:@"index %d out of range in string %x of length %d",
+               index, self, self->cLength] raise];
+    }
+    // ENCODING
+    return self->cString[index];
+}
+
+- (NSString *)substringWithRange:(NSRange)aRange
+{
+    Class clazz;
+    
+    if (NSMaxRange(aRange) > self->cLength) {
+        [[[IndexOutOfRangeException alloc] initWithFormat:
+            @"range %@ not in string 0x%08x of length %d",
+            NSStringFromRange(aRange),
+            self,
+            self->cLength]
+            raise];
+    }
+
+    if (aRange.length == 0)
+        return @"";
+
+    clazz = aRange.length < 255
+        ? [NSShortInline8BitString class]
+        : [NSInline8BitString class];
+    
+    return AUTORELEASE([[clazz allocForCapacity:aRange.length zone:NULL] 
+                               initWithCString:(self->cString + aRange.location)
+                               length:aRange.length]);
+}
+
+- (char*)__compact8BitBytes
+{
+    return self->cString;
+}
+
+- (void)replaceCharactersInRange:(NSRange)aRange
+  withString:(NSString *)aString
+{
+    unsigned int strLength, iFrom, iTo;
+    int count;
+    
+    /* check range */
+    if (NSMaxRange(aRange) > self->cLength) {
+        [[[IndexOutOfRangeException alloc] initWithFormat:
+            @"range %@ not in string 0x%08x of length %d",
+            NSStringFromRange(aRange),
+            self,
+            self->cLength]
+            raise];
+    }
+    
+    strLength = [aString cStringLength];
+    /* if range is smaller than new string enough room */
+    if (aRange.length >= strLength) {
+        iFrom = aRange.location + aRange.length;
+        iTo   = aRange.location + strLength;
+        count = self->cLength - iFrom;
+        if (iFrom != iTo) {
+            register int i;
+            
+            for (i = 0; i < count; i++)
+                self->cString[iTo + i] = self->cString[iFrom + i];
+        }
+        self->cLength = self->cLength - aRange.length + strLength;
+    }
+    /* if range greater than new string */
+    else {
+        register int i;
+        
+       /* is there enough free space */
+       if ((cCapacity - cLength) < (strLength - aRange.length)) {
+           /* reallocation grow strategy */
+           cCapacity += MAX(cCapacity, 
+               (strLength - aRange.length) - (cCapacity - cLength));
+           cString = NSZoneRealloc(
+               cString ? NSZoneFromPointer(cString) : [self zone],
+               cString, sizeof(char)*cCapacity);
+       }
+       /* we have enough size */
+       count = self->cLength - aRange.location - aRange.length;
+       iFrom = self->cLength - 1;
+       iTo   = self->cLength + strLength - aRange.length - 1;
+       self->cLength += strLength - aRange.length;
+        
+       for (i = 0; i < count; i++)
+           self->cString[iTo - i] = self->cString[iFrom - i];
+    }
+    
+    /* move string in its position */
+    if (strLength) {
+       NSRange range = { 0, strLength };
+        
+       [aString getCString:(self->cString + aRange.location)
+                 maxLength:strLength
+                 range:range
+                 remainingRange:NULL];
+    }
+}
+
+@end /* NSMutableSimple8BitString */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConcreteNumber.h b/libFoundation/Foundation/NSConcreteNumber.h
new file mode 100644 (file)
index 0000000..d567a48
--- /dev/null
@@ -0,0 +1,111 @@
+/* 
+   NSConcreteNumber.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSValue.h>
+
+@interface NSBoolNumber : NSNumber
+{
+    BOOL data;
+}
+@end
+
+@interface NSCharNumber : NSNumber
+{
+    char data;
+}
+@end
+
+@interface NSUCharNumber : NSNumber
+{
+    unsigned char data;
+}
+@end
+
+@interface NSShortNumber : NSNumber
+{
+    short data;
+}
+@end
+
+@interface NSUShortNumber : NSNumber
+{
+    unsigned short data;
+}
+@end
+
+@interface NSIntNumber : NSNumber
+{
+    int data;
+}
+@end
+
+@interface NSUIntNumber : NSNumber
+{
+    unsigned int data;
+}
+@end
+
+@interface NSLongNumber : NSNumber
+{
+    long data;
+}
+@end
+
+@interface NSULongNumber : NSNumber
+{
+    unsigned long data;
+}
+@end
+
+@interface NSLongLongNumber : NSNumber
+{
+    long long data;
+}
+@end
+
+@interface NSULongLongNumber : NSNumber
+{
+    unsigned long long data;
+}
+@end
+
+@interface NSFloatNumber : NSNumber
+{
+    float data;
+}
+@end
+
+@interface NSDoubleNumber : NSNumber
+{
+    double data;
+}
+@end
+
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConcreteNumber.m b/libFoundation/Foundation/NSConcreteNumber.m
new file mode 100644 (file)
index 0000000..365565e
--- /dev/null
@@ -0,0 +1,2096 @@
+/*
+ * Author: mircea
+ */
+
+#include <Foundation/common.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSException.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+#include <Foundation/NSCoder.h>
+#include "NSConcreteNumber.h"
+
+static Class NSStringClass = Nil;
+
+static NSString *strValues[64] = {
+   @"0",  @"1",  @"2",  @"3",  @"4",  @"5",  @"6",  @"7",  @"8",  @"9",
+  @"10", @"11", @"12", @"13", @"14", @"15", @"16", @"17", @"18", @"19",
+  @"20", @"21", @"22", @"23", @"24", @"25", @"26", @"27", @"28", @"29",
+  @"30", @"31", @"32", @"33", @"34", @"35", @"36", @"37", @"38", @"39",
+  @"40", @"41", @"42", @"43", @"44", @"45", @"46", @"47", @"48", @"49",
+  @"50", @"51", @"52", @"53", @"54", @"55", @"56", @"57", @"58", @"59",
+  @"60", @"61", @"62", @"63"
+};
+#define CHK_STATIC_STR \
+  if (data >= 0 && data < 64) return strValues[(short)data];
+#define CHK_STATIC_USTR \
+  if (data < 64) return strValues[(short)data];
+
+static unsigned char buf[256];
+#define FMT_NUMSTR(__FMT__) \
+    if (NSStringClass == Nil) NSStringClass = [NSString class];\
+    sprintf(buf, __FMT__, data);\
+    return [NSStringClass stringWithCString:buf];
+
+@implementation NSBoolNumber
+
++ (id)allocWithZone:(NSZone *)zone
+{
+    return NSAllocateObject (self, 0, zone);
+}
+
+- initValue:(const void*)value withObjCType:(const char*)type;
+{
+    self = [super init];
+    data = *(BOOL*)value;
+    return self;
+}
+
+- (BOOL)boolValue
+{
+    return data;
+}
+
+- (char)charValue
+{
+    return data;
+}
+
+- (unsigned char)unsignedCharValue
+{
+    return data;
+}
+
+- (short)shortValue
+{
+    return data;
+}
+
+- (unsigned short)unsignedShortValue
+{
+    return data;
+}
+
+- (int)intValue
+{
+    return data;
+}
+
+- (unsigned int)unsignedIntValue
+{
+    return data;
+}
+
+- (long)longValue
+{
+    return data;
+}
+
+- (unsigned long)unsignedLongValue
+{
+    return data;
+}
+
+- (long long)longLongValue
+{
+    return data;
+}
+
+- (unsigned long long)unsignedLongLongValue
+{
+    return data;
+}
+
+- (float)floatValue
+{
+    return data;
+}
+
+- (double)doubleValue
+{
+    return data;
+}
+
+- (NSString *)descriptionWithLocale:(NSDictionary *)locale
+{
+    return data ? @"1" : @"0";
+}
+
+- (int)generality
+{
+    return 1;
+}
+
+- (NSComparisonResult)compare:(NSNumber *)otherNumber
+{
+    if (1 >= [otherNumber generality]) {
+       BOOL other_data = [otherNumber boolValue];
+
+       if (data == other_data)
+           return NSOrderedSame;
+       else
+           return (data < other_data) ?
+                     NSOrderedAscending
+                   : NSOrderedDescending;
+    }
+    else
+       return [otherNumber compare:self];
+}
+
+// Override these from NSValue
+
+- (void)getValue:(void*)value
+{
+    if (value == nil) {
+       [[[InvalidArgumentException new]
+               setReason:@"NULL buffer in -getValue"] raise];
+    }
+    else 
+       *(BOOL*)value = data;
+}
+- (void *)valueBytes
+{
+    return &(self->data);
+}
+
+- (const char*)objCType
+{
+    return @encode(BOOL);
+}
+
+// NSCopying
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    if ([self zone] == zone)
+       return RETAIN(self);
+    else
+       return [[[NSBoolNumber class] alloc]
+                   initValue:&data withObjCType:@encode(BOOL)];
+}
+
+// NSCoding
+
+- (Class)classForCoder
+{
+    return isa;
+}
+
+- (void)encodeWithCoder:(NSCoder*)coder
+{
+    [coder encodeValueOfObjCType:@encode(BOOL) at:&data];
+}
+
+- (id)initWithCoder:(NSCoder*)coder
+{
+    [coder decodeValueOfObjCType:@encode(BOOL) at:&data];
+    return self;
+}
+
+@end /* NSBoolNumber */
+
+
+@implementation NSCharNumber
+
++ (id)allocWithZone:(NSZone *)zone
+{
+    return NSAllocateObject (self, 0, zone);
+}
+
+- initValue:(const void*)value withObjCType:(const char*)type;
+{
+    self = [super init];
+    data = *(char*)value;
+    return self;
+}
+
+- (BOOL)boolValue
+{
+    return data;
+}
+
+- (char)charValue
+{
+    return data;
+}
+
+- (unsigned char)unsignedCharValue
+{
+    return data;
+}
+
+- (short)shortValue
+{
+    return data;
+}
+
+- (unsigned short)unsignedShortValue
+{
+    return data;
+}
+
+- (int)intValue
+{
+    return data;
+}
+
+- (unsigned int)unsignedIntValue
+{
+    return data;
+}
+
+- (long)longValue
+{
+    return data;
+}
+
+- (unsigned long)unsignedLongValue
+{
+    return data;
+}
+
+- (long long)longLongValue
+{
+    return data;
+}
+
+- (unsigned long long)unsignedLongLongValue
+{
+    return data;
+}
+
+- (float)floatValue
+{
+    return data;
+}
+
+- (double)doubleValue
+{
+    return data;
+}
+
+- (NSString *)descriptionWithLocale:(NSDictionary *)locale
+{
+    CHK_STATIC_STR;
+    FMT_NUMSTR("%d");
+}
+
+- (int)generality
+{
+    return 2;
+}
+
+- (NSComparisonResult)compare:(NSNumber *)otherNumber
+{
+    if (2 >= [otherNumber generality]) {
+       char other_data = [otherNumber charValue];
+
+       if (data == other_data)
+           return NSOrderedSame;
+       else
+           return (data < other_data) ?
+                     NSOrderedAscending
+                   : NSOrderedDescending;
+    }
+    else
+       return [otherNumber compare:self];
+}
+
+// Override these from NSValue
+
+- (void)getValue:(void*)value
+{
+    if (value == nil) {
+       [[[InvalidArgumentException new]
+               setReason:@"NULL buffer in -getValue"] raise];
+    }
+    else 
+       *(char*)value = data;
+}
+- (void *)valueBytes
+{
+    return &(self->data);
+}
+
+- (const char*)objCType
+{
+    return @encode(char);
+}
+
+// NSCopying
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    if ([self zone] == zone)
+       return RETAIN(self);
+    else
+       return [[[NSCharNumber class] alloc]
+                   initValue:&data withObjCType:@encode(char)];
+}
+
+// NSCoding
+
+- (Class)classForCoder
+{
+    return isa;
+}
+
+- (void)encodeWithCoder:(NSCoder*)coder
+{
+    [coder encodeValueOfObjCType:@encode(char) at:&data];
+}
+
+- (id)initWithCoder:(NSCoder*)coder
+{
+    [coder decodeValueOfObjCType:@encode(char) at:&data];
+    return self;
+}
+
+@end /* NSCharNumber */
+
+
+@implementation NSUCharNumber
+
++ (id)allocWithZone:(NSZone *)zone
+{
+    return NSAllocateObject (self, 0, zone);
+}
+
+- initValue:(const void*)value withObjCType:(const char*)type;
+{
+    self = [super init];
+    data = *(unsigned char*)value;
+    return self;
+}
+
+- (BOOL)boolValue
+{
+    return data;
+}
+
+- (char)charValue
+{
+    return data;
+}
+
+- (unsigned char)unsignedCharValue
+{
+    return data;
+}
+
+- (short)shortValue
+{
+    return data;
+}
+
+- (unsigned short)unsignedShortValue
+{
+    return data;
+}
+
+- (int)intValue
+{
+    return data;
+}
+
+- (unsigned int)unsignedIntValue
+{
+    return data;
+}
+
+- (long)longValue
+{
+    return data;
+}
+
+- (unsigned long)unsignedLongValue
+{
+    return data;
+}
+
+- (long long)longLongValue
+{
+    return data;
+}
+
+- (unsigned long long)unsignedLongLongValue
+{
+    return data;
+}
+
+- (float)floatValue
+{
+    return data;
+}
+
+- (double)doubleValue
+{
+    return data;
+}
+
+- (NSString *)descriptionWithLocale:(NSDictionary *)locale
+{
+    CHK_STATIC_USTR;
+    FMT_NUMSTR("%d");
+}
+
+- (int)generality
+{
+    return 3;
+}
+
+- (NSComparisonResult)compare:(NSNumber *)otherNumber
+{
+    if (3 >= [otherNumber generality]) {
+       unsigned char other_data = [otherNumber unsignedCharValue];
+
+       if (data == other_data)
+           return NSOrderedSame;
+       else
+           return (data < other_data) ?
+                     NSOrderedAscending
+                   : NSOrderedDescending;
+    }
+    else
+       return [otherNumber compare:self];
+}
+
+// Override these from NSValue
+
+- (void)getValue:(void*)value
+{
+    if (value == nil) {
+       [[[InvalidArgumentException new]
+               setReason:@"NULL buffer in -getValue"] raise];
+    }
+    else 
+       *(unsigned char*)value = data;
+}
+- (void *)valueBytes
+{
+    return &(self->data);
+}
+
+- (const char*)objCType
+{
+    return @encode(unsigned char);
+}
+
+// NSCopying
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    if ([self zone] == zone)
+       return RETAIN(self);
+    else
+       return [[[NSUCharNumber class] alloc]
+                   initValue:&data withObjCType:@encode(unsigned char)];
+}
+
+// NSCoding
+
+- (Class)classForCoder
+{
+    return isa;
+}
+
+- (void)encodeWithCoder:(NSCoder*)coder
+{
+    [coder encodeValueOfObjCType:@encode(unsigned char) at:&data];
+}
+
+- (id)initWithCoder:(NSCoder*)coder
+{
+    [coder decodeValueOfObjCType:@encode(unsigned char) at:&data];
+    return self;
+}
+
+@end /* NSUCharNumber */
+
+
+@implementation NSShortNumber
+
++ (id)allocWithZone:(NSZone *)zone
+{
+    return NSAllocateObject (self, 0, zone);
+}
+
+- initValue:(const void*)value withObjCType:(const char*)type;
+{
+    self = [super init];
+    data = *(short*)value;
+    return self;
+}
+
+- (BOOL)boolValue
+{
+    return data;
+}
+
+- (char)charValue
+{
+    return data;
+}
+
+- (unsigned char)unsignedCharValue
+{
+    return data;
+}
+
+- (short)shortValue
+{
+    return data;
+}
+
+- (unsigned short)unsignedShortValue
+{
+    return data;
+}
+
+- (int)intValue
+{
+    return data;
+}
+
+- (unsigned int)unsignedIntValue
+{
+    return data;
+}
+
+- (long)longValue
+{
+    return data;
+}
+
+- (unsigned long)unsignedLongValue
+{
+    return data;
+}
+
+- (long long)longLongValue
+{
+    return data;
+}
+
+- (unsigned long long)unsignedLongLongValue
+{
+    return data;
+}
+
+- (float)floatValue
+{
+    return data;
+}
+
+- (double)doubleValue
+{
+    return data;
+}
+
+- (NSString *)descriptionWithLocale:(NSDictionary *)locale
+{
+    CHK_STATIC_STR;
+    FMT_NUMSTR("%hd");
+}
+
+- (int)generality
+{
+    return 4;
+}
+
+- (NSComparisonResult)compare:(NSNumber *)otherNumber
+{
+    if (4 >= [otherNumber generality]) {
+       short other_data = [otherNumber shortValue];
+
+       if (data == other_data)
+           return NSOrderedSame;
+       else
+           return (data < other_data) ?
+                     NSOrderedAscending
+                   : NSOrderedDescending;
+    }
+    else
+       return [otherNumber compare:self];
+}
+
+// Override these from NSValue
+
+- (void)getValue:(void*)value
+{
+    if (value == nil) {
+       [[[InvalidArgumentException new]
+               setReason:@"NULL buffer in -getValue"] raise];
+    }
+    else 
+       *(short*)value = data;
+}
+- (void *)valueBytes
+{
+    return &(self->data);
+}
+
+- (const char*)objCType
+{
+    return @encode(short);
+}
+
+// NSCopying
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    if ([self zone] == zone)
+       return RETAIN(self);
+    else
+       return [[[NSShortNumber class] alloc]
+                   initValue:&data withObjCType:@encode(short)];
+}
+
+// NSCoding
+
+- (Class)classForCoder
+{
+    return isa;
+}
+
+- (void)encodeWithCoder:(NSCoder*)coder
+{
+    [coder encodeValueOfObjCType:@encode(short) at:&data];
+}
+
+- (id)initWithCoder:(NSCoder*)coder
+{
+    [coder decodeValueOfObjCType:@encode(short) at:&data];
+    return self;
+}
+
+@end /* NSShortNumber */
+
+
+@implementation NSUShortNumber
+
++ (id)allocWithZone:(NSZone *)zone
+{
+    return NSAllocateObject (self, 0, zone);
+}
+
+- initValue:(const void*)value withObjCType:(const char*)type;
+{
+    self = [super init];
+    data = *(unsigned short*)value;
+    return self;
+}
+
+- (BOOL)boolValue
+{
+    return data;
+}
+
+- (char)charValue
+{
+    return data;
+}
+
+- (unsigned char)unsignedCharValue
+{
+    return data;
+}
+
+- (short)shortValue
+{
+    return data;
+}
+
+- (unsigned short)unsignedShortValue
+{
+    return data;
+}
+
+- (int)intValue
+{
+    return data;
+}
+
+- (unsigned int)unsignedIntValue
+{
+    return data;
+}
+
+- (long)longValue
+{
+    return data;
+}
+
+- (unsigned long)unsignedLongValue
+{
+    return data;
+}
+
+- (long long)longLongValue
+{
+    return data;
+}
+
+- (unsigned long long)unsignedLongLongValue
+{
+    return data;
+}
+
+- (float)floatValue
+{
+    return data;
+}
+
+- (double)doubleValue
+{
+    return data;
+}
+
+- (NSString *)descriptionWithLocale:(NSDictionary *)locale
+{
+    CHK_STATIC_USTR;
+    FMT_NUMSTR("%hu");
+}
+
+- (int)generality
+{
+    return 5;
+}
+
+- (NSComparisonResult)compare:(NSNumber *)otherNumber
+{
+    if (5 >= [otherNumber generality]) {
+       unsigned short other_data = [otherNumber unsignedShortValue];
+
+       if (data == other_data)
+           return NSOrderedSame;
+       else
+           return (data < other_data) ?
+                     NSOrderedAscending
+                   : NSOrderedDescending;
+    }
+    else
+       return [otherNumber compare:self];
+}
+
+// Override these from NSValue
+
+- (void)getValue:(void*)value
+{
+    if (value == nil) {
+       [[[InvalidArgumentException new]
+               setReason:@"NULL buffer in -getValue"] raise];
+    }
+    else 
+       *(unsigned short*)value = data;
+}
+- (void *)valueBytes
+{
+    return &(self->data);
+}
+
+- (const char*)objCType
+{
+    return @encode(unsigned short);
+}
+
+// NSCopying
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    if ([self zone] == zone)
+       return RETAIN(self);
+    else
+       return [[[NSUShortNumber class] alloc]
+                   initValue:&data withObjCType:@encode(unsigned short)];
+}
+
+// NSCoding
+
+- (Class)classForCoder
+{
+    return isa;
+}
+
+- (void)encodeWithCoder:(NSCoder*)coder
+{
+    [coder encodeValueOfObjCType:@encode(unsigned short) at:&data];
+}
+
+- (id)initWithCoder:(NSCoder*)coder
+{
+    [coder decodeValueOfObjCType:@encode(unsigned short) at:&data];
+    return self;
+}
+
+@end /* NSUShortNumber */
+
+
+@implementation NSIntNumber
+
++ (id)allocWithZone:(NSZone *)zone
+{
+    return NSAllocateObject (self, 0, zone);
+}
+
+- initValue:(const void*)value withObjCType:(const char*)type;
+{
+    self = [super init];
+    data = *(int*)value;
+    return self;
+}
+
+- (BOOL)boolValue
+{
+    return data;
+}
+
+- (char)charValue
+{
+    return data;
+}
+
+- (unsigned char)unsignedCharValue
+{
+    return data;
+}
+
+- (short)shortValue
+{
+    return data;
+}
+
+- (unsigned short)unsignedShortValue
+{
+    return data;
+}
+
+- (int)intValue
+{
+    return data;
+}
+
+- (unsigned int)unsignedIntValue
+{
+    return data;
+}
+
+- (long)longValue
+{
+    return data;
+}
+
+- (unsigned long)unsignedLongValue
+{
+    return data;
+}
+
+- (long long)longLongValue
+{
+    return data;
+}
+
+- (unsigned long long)unsignedLongLongValue
+{
+    return data;
+}
+
+- (float)floatValue
+{
+    return data;
+}
+
+- (double)doubleValue
+{
+    return data;
+}
+
+- (NSString *)descriptionWithLocale:(NSDictionary *)locale
+{
+    CHK_STATIC_STR;
+    FMT_NUMSTR("%d");
+}
+
+- (int)generality
+{
+    return 6;
+}
+
+- (NSComparisonResult)compare:(NSNumber *)otherNumber
+{
+    if (6 >= [otherNumber generality]) {
+       int other_data = [otherNumber intValue];
+
+       if (data == other_data)
+           return NSOrderedSame;
+       else
+           return (data < other_data) ?
+                     NSOrderedAscending
+                   : NSOrderedDescending;
+    }
+    else
+       return [otherNumber compare:self];
+}
+
+// Override these from NSValue
+
+- (void)getValue:(void*)value
+{
+    if (value == nil) {
+       [[[InvalidArgumentException new]
+               setReason:@"NULL buffer in -getValue"] raise];
+    }
+    else 
+       *(int*)value = data;
+}
+- (void *)valueBytes
+{
+    return &(self->data);
+}
+
+- (const char*)objCType
+{
+    return @encode(int);
+}
+
+// NSCopying
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    if ([self zone] == zone)
+       return RETAIN(self);
+    else
+       return [[[NSIntNumber class] alloc]
+                   initValue:&data withObjCType:@encode(int)];
+}
+
+// NSCoding
+
+- (Class)classForCoder
+{
+    return isa;
+}
+
+- (void)encodeWithCoder:(NSCoder*)coder
+{
+    [coder encodeValueOfObjCType:@encode(int) at:&data];
+}
+
+- (id)initWithCoder:(NSCoder*)coder
+{
+    [coder decodeValueOfObjCType:@encode(int) at:&data];
+    return self;
+}
+
+@end /* NSIntNumber */
+
+
+@implementation NSUIntNumber
+
++ (id)allocWithZone:(NSZone *)zone
+{
+    return NSAllocateObject (self, 0, zone);
+}
+
+- initValue:(const void*)value withObjCType:(const char*)type;
+{
+    self = [super init];
+    data = *(unsigned int*)value;
+    return self;
+}
+
+- (BOOL)boolValue
+{
+    return data;
+}
+
+- (char)charValue
+{
+    return data;
+}
+
+- (unsigned char)unsignedCharValue
+{
+    return data;
+}
+
+- (short)shortValue
+{
+    return data;
+}
+
+- (unsigned short)unsignedShortValue
+{
+    return data;
+}
+
+- (int)intValue
+{
+    return data;
+}
+
+- (unsigned int)unsignedIntValue
+{
+    return data;
+}
+
+- (long)longValue
+{
+    return data;
+}
+
+- (unsigned long)unsignedLongValue
+{
+    return data;
+}
+
+- (long long)longLongValue
+{
+    return data;
+}
+
+- (unsigned long long)unsignedLongLongValue
+{
+    return data;
+}
+
+- (float)floatValue
+{
+    return data;
+}
+
+- (double)doubleValue
+{
+    return data;
+}
+
+- (NSString *)descriptionWithLocale:(NSDictionary *)locale
+{
+    CHK_STATIC_STR;
+    FMT_NUMSTR("%u");
+}
+
+- (int)generality
+{
+    return 7;
+}
+
+- (NSComparisonResult)compare:(NSNumber *)otherNumber
+{
+    if (7 >= [otherNumber generality]) {
+       unsigned int other_data = [otherNumber unsignedIntValue];
+
+       if (data == other_data)
+           return NSOrderedSame;
+       else
+           return (data < other_data) ?
+                     NSOrderedAscending
+                   : NSOrderedDescending;
+    }
+    else
+       return [otherNumber compare:self];
+}
+
+// Override these from NSValue
+
+- (void)getValue:(void*)value
+{
+    if (value == nil) {
+       [[[InvalidArgumentException new]
+               setReason:@"NULL buffer in -getValue"] raise];
+    }
+    else 
+       *(unsigned int*)value = data;
+}
+- (void *)valueBytes
+{
+    return &(self->data);
+}
+
+- (const char*)objCType
+{
+    return @encode(unsigned int);
+}
+
+// NSCopying
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    if ([self zone] == zone)
+       return RETAIN(self);
+    else
+       return [[[NSUIntNumber class] alloc]
+                   initValue:&data withObjCType:@encode(unsigned int)];
+}
+
+// NSCoding
+
+- (Class)classForCoder
+{
+    return isa;
+}
+
+- (void)encodeWithCoder:(NSCoder*)coder
+{
+    [coder encodeValueOfObjCType:@encode(unsigned int) at:&data];
+}
+
+- (id)initWithCoder:(NSCoder*)coder
+{
+    [coder decodeValueOfObjCType:@encode(unsigned int) at:&data];
+    return self;
+}
+
+@end /* NSUIntNumber */
+
+
+@implementation NSLongNumber
+
++ (id)allocWithZone:(NSZone *)zone
+{
+    return NSAllocateObject (self, 0, zone);
+}
+
+- initValue:(const void*)value withObjCType:(const char*)type;
+{
+    self = [super init];
+    data = *(long*)value;
+    return self;
+}
+
+- (BOOL)boolValue
+{
+    return data;
+}
+
+- (char)charValue
+{
+    return data;
+}
+
+- (unsigned char)unsignedCharValue
+{
+    return data;
+}
+
+- (short)shortValue
+{
+    return data;
+}
+
+- (unsigned short)unsignedShortValue
+{
+    return data;
+}
+
+- (int)intValue
+{
+    return data;
+}
+
+- (unsigned int)unsignedIntValue
+{
+    return data;
+}
+
+- (long)longValue
+{
+    return data;
+}
+
+- (unsigned long)unsignedLongValue
+{
+    return data;
+}
+
+- (long long)longLongValue
+{
+    return data;
+}
+
+- (unsigned long long)unsignedLongLongValue
+{
+    return data;
+}
+
+- (float)floatValue
+{
+    return data;
+}
+
+- (double)doubleValue
+{
+    return data;
+}
+
+- (NSString *)descriptionWithLocale:(NSDictionary *)locale
+{
+    CHK_STATIC_STR;
+    FMT_NUMSTR("%ld");
+}
+
+- (int)generality
+{
+    return 8;
+}
+
+- (NSComparisonResult)compare:(NSNumber *)otherNumber
+{
+    if (8 >= [otherNumber generality]) {
+       long other_data = [otherNumber longValue];
+
+       if (data == other_data)
+           return NSOrderedSame;
+       else
+           return (data < other_data) ?
+                     NSOrderedAscending
+                   : NSOrderedDescending;
+    }
+    else
+       return [otherNumber compare:self];
+}
+
+// Override these from NSValue
+
+- (void)getValue:(void*)value
+{
+    if (value == nil) {
+       [[[InvalidArgumentException new]
+               setReason:@"NULL buffer in -getValue"] raise];
+    }
+    else 
+       *(long*)value = data;
+}
+- (void *)valueBytes
+{
+    return &(self->data);
+}
+
+- (const char*)objCType
+{
+    return @encode(long);
+}
+
+// NSCopying
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    if ([self zone] == zone)
+       return RETAIN(self);
+    else
+       return [[[NSLongNumber class] alloc]
+                   initValue:&data withObjCType:@encode(long)];
+}
+
+// NSCoding
+
+- (Class)classForCoder
+{
+    return isa;
+}
+
+- (void)encodeWithCoder:(NSCoder*)coder
+{
+    [coder encodeValueOfObjCType:@encode(long) at:&data];
+}
+
+- (id)initWithCoder:(NSCoder*)coder
+{
+    [coder decodeValueOfObjCType:@encode(long) at:&data];
+    return self;
+}
+
+@end /* NSLongNumber */
+
+
+@implementation NSULongNumber
+
++ (id)allocWithZone:(NSZone *)zone
+{
+    return NSAllocateObject (self, 0, zone);
+}
+
+- initValue:(const void*)value withObjCType:(const char*)type;
+{
+    self = [super init];
+    data = *(unsigned long*)value;
+    return self;
+}
+
+- (BOOL)boolValue
+{
+    return data;
+}
+
+- (char)charValue
+{
+    return data;
+}
+
+- (unsigned char)unsignedCharValue
+{
+    return data;
+}
+
+- (short)shortValue
+{
+    return data;
+}
+
+- (unsigned short)unsignedShortValue
+{
+    return data;
+}
+
+- (int)intValue
+{
+    return data;
+}
+
+- (unsigned int)unsignedIntValue
+{
+    return data;
+}
+
+- (long)longValue
+{
+    return data;
+}
+
+- (unsigned long)unsignedLongValue
+{
+    return data;
+}
+
+- (long long)longLongValue
+{
+    return data;
+}
+
+- (unsigned long long)unsignedLongLongValue
+{
+    return data;
+}
+
+- (float)floatValue
+{
+    return data;
+}
+
+- (double)doubleValue
+{
+    return data;
+}
+
+- (NSString *)descriptionWithLocale:(NSDictionary *)locale
+{
+    CHK_STATIC_STR;
+    FMT_NUMSTR("%lu");
+}
+
+- (int)generality
+{
+    return 9;
+}
+
+- (NSComparisonResult)compare:(NSNumber *)otherNumber
+{
+    if (9 >= [otherNumber generality]) {
+       unsigned long other_data = [otherNumber unsignedLongValue];
+
+       if (data == other_data)
+           return NSOrderedSame;
+       else
+           return (data < other_data) ?
+                     NSOrderedAscending
+                   : NSOrderedDescending;
+    }
+    else
+       return [otherNumber compare:self];
+}
+
+// Override these from NSValue
+
+- (void)getValue:(void*)value
+{
+    if (value == nil) {
+       [[[InvalidArgumentException new]
+               setReason:@"NULL buffer in -getValue"] raise];
+    }
+    else 
+       *(unsigned long*)value = data;
+}
+- (void *)valueBytes
+{
+    return &(self->data);
+}
+
+- (const char*)objCType
+{
+    return @encode(unsigned long);
+}
+
+// NSCopying
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    if ([self zone] == zone)
+       return RETAIN(self);
+    else
+       return [[[NSULongNumber class] alloc]
+                   initValue:&data withObjCType:@encode(unsigned long)];
+}
+
+// NSCoding
+
+- (Class)classForCoder
+{
+    return isa;
+}
+
+- (void)encodeWithCoder:(NSCoder*)coder
+{
+    [coder encodeValueOfObjCType:@encode(unsigned long) at:&data];
+}
+
+- (id)initWithCoder:(NSCoder*)coder
+{
+    [coder decodeValueOfObjCType:@encode(unsigned long) at:&data];
+    return self;
+}
+
+@end /* NSULongNumber */
+
+
+@implementation NSLongLongNumber
+
++ (id)allocWithZone:(NSZone *)zone
+{
+    return NSAllocateObject (self, 0, zone);
+}
+
+- initValue:(const void*)value withObjCType:(const char*)type;
+{
+    self = [super init];
+    data = *(long long*)value;
+    return self;
+}
+
+- (BOOL)boolValue
+{
+    return data;
+}
+
+- (char)charValue
+{
+    return data;
+}
+
+- (unsigned char)unsignedCharValue
+{
+    return data;
+}
+
+- (short)shortValue
+{
+    return data;
+}
+
+- (unsigned short)unsignedShortValue
+{
+    return data;
+}
+
+- (int)intValue
+{
+    return data;
+}
+
+- (unsigned int)unsignedIntValue
+{
+    return data;
+}
+
+- (long)longValue
+{
+    return data;
+}
+
+- (unsigned long)unsignedLongValue
+{
+    return data;
+}
+
+- (long long)longLongValue
+{
+    return data;
+}
+
+- (unsigned long long)unsignedLongLongValue
+{
+    return data;
+}
+
+- (float)floatValue
+{
+    return data;
+}
+
+- (double)doubleValue
+{
+    return data;
+}
+
+- (NSString *)descriptionWithLocale:(NSDictionary *)locale
+{
+    CHK_STATIC_STR;
+    FMT_NUMSTR("%lld");
+}
+
+- (int)generality
+{
+    return 10;
+}
+
+- (NSComparisonResult)compare:(NSNumber *)otherNumber
+{
+    if (10 >= [otherNumber generality]) {
+       long long other_data = [otherNumber longLongValue];
+
+       if (data == other_data)
+           return NSOrderedSame;
+       else
+           return (data < other_data) ?
+                     NSOrderedAscending
+                   : NSOrderedDescending;
+    }
+    else
+       return [otherNumber compare:self];
+}
+
+// Override these from NSValue
+
+- (void)getValue:(void*)value
+{
+    if (value == nil) {
+       [[[InvalidArgumentException new]
+               setReason:@"NULL buffer in -getValue"] raise];
+    }
+    else 
+       *(long long*)value = data;
+}
+- (void *)valueBytes
+{
+    return &(self->data);
+}
+
+- (const char*)objCType
+{
+    return @encode(long long);
+}
+
+// NSCopying
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    if ([self zone] == zone)
+       return RETAIN(self);
+    else
+       return [[[NSLongLongNumber class] alloc]
+                   initValue:&data withObjCType:@encode(long long)];
+}
+
+// NSCoding
+
+- (Class)classForCoder
+{
+    return isa;
+}
+
+- (void)encodeWithCoder:(NSCoder*)coder
+{
+    [coder encodeValueOfObjCType:@encode(long long) at:&data];
+}
+
+- (id)initWithCoder:(NSCoder*)coder
+{
+    [coder decodeValueOfObjCType:@encode(long long) at:&data];
+    return self;
+}
+
+@end /* NSLongLongNumber */
+
+
+@implementation NSULongLongNumber
+
++ (id)allocWithZone:(NSZone *)zone
+{
+    return NSAllocateObject (self, 0, zone);
+}
+
+- initValue:(const void*)value withObjCType:(const char*)type;
+{
+    self = [super init];
+    data = *(unsigned long long*)value;
+    return self;
+}
+
+- (BOOL)boolValue
+{
+    return data;
+}
+
+- (char)charValue
+{
+    return data;
+}
+
+- (unsigned char)unsignedCharValue
+{
+    return data;
+}
+
+- (short)shortValue
+{
+    return data;
+}
+
+- (unsigned short)unsignedShortValue
+{
+    return data;
+}
+
+- (int)intValue
+{
+    return data;
+}
+
+- (unsigned int)unsignedIntValue
+{
+    return data;
+}
+
+- (long)longValue
+{
+    return data;
+}
+
+- (unsigned long)unsignedLongValue
+{
+    return data;
+}
+
+- (long long)longLongValue
+{
+    return data;
+}
+
+- (unsigned long long)unsignedLongLongValue
+{
+    return data;
+}
+
+- (float)floatValue
+{
+    return data;
+}
+
+- (double)doubleValue
+{
+    return data;
+}
+
+- (NSString *)descriptionWithLocale:(NSDictionary *)locale
+{
+    CHK_STATIC_STR;
+    FMT_NUMSTR("%llu");
+}
+
+- (int)generality
+{
+    return 11;
+}
+
+- (NSComparisonResult)compare:(NSNumber *)otherNumber
+{
+    if (11 >= [otherNumber generality]) {
+       unsigned long long other_data = [otherNumber unsignedLongLongValue];
+
+       if (data == other_data)
+           return NSOrderedSame;
+       else
+           return (data < other_data) ?
+                     NSOrderedAscending
+                   : NSOrderedDescending;
+    }
+    else
+       return [otherNumber compare:self];
+}
+
+// Override these from NSValue
+
+- (void)getValue:(void*)value
+{
+    if (value == nil) {
+       [[[InvalidArgumentException new]
+               setReason:@"NULL buffer in -getValue"] raise];
+    }
+    else 
+       *(unsigned long long*)value = data;
+}
+- (void *)valueBytes
+{
+    return &(self->data);
+}
+
+- (const char*)objCType
+{
+    return @encode(unsigned long long);
+}
+
+// NSCopying
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    if ([self zone] == zone)
+       return RETAIN(self);
+    else
+       return [[[NSULongLongNumber class] alloc]
+                   initValue:&data withObjCType:@encode(unsigned long long)];
+}
+
+// NSCoding
+
+- (Class)classForCoder
+{
+    return isa;
+}
+
+- (void)encodeWithCoder:(NSCoder*)coder
+{
+    [coder encodeValueOfObjCType:@encode(unsigned long long) at:&data];
+}
+
+- (id)initWithCoder:(NSCoder*)coder
+{
+    [coder decodeValueOfObjCType:@encode(unsigned long long) at:&data];
+    return self;
+}
+
+@end /* NSULongLongNumber */
+
+
+@implementation NSFloatNumber
+
++ (id)allocWithZone:(NSZone *)zone
+{
+    return NSAllocateObject (self, 0, zone);
+}
+
+- initValue:(const void*)value withObjCType:(const char*)type;
+{
+    self = [super init];
+    data = *(float*)value;
+    return self;
+}
+
+- (BOOL)boolValue
+{
+    return data;
+}
+
+- (char)charValue
+{
+    return data;
+}
+
+- (unsigned char)unsignedCharValue
+{
+    return data;
+}
+
+- (short)shortValue
+{
+    return data;
+}
+
+- (unsigned short)unsignedShortValue
+{
+    return data;
+}
+
+- (int)intValue
+{
+    return data;
+}
+
+- (unsigned int)unsignedIntValue
+{
+    return data;
+}
+
+- (long)longValue
+{
+    return data;
+}
+
+- (unsigned long)unsignedLongValue
+{
+    return data;
+}
+
+- (long long)longLongValue
+{
+    return data;
+}
+
+- (unsigned long long)unsignedLongLongValue
+{
+    return data;
+}
+
+- (float)floatValue
+{
+    return data;
+}
+
+- (double)doubleValue
+{
+    return data;
+}
+
+- (NSString *)descriptionWithLocale:(NSDictionary *)locale
+{
+    FMT_NUMSTR("%0.7g");
+}
+
+- (int)generality
+{
+    return 12;
+}
+
+- (NSComparisonResult)compare:(NSNumber *)otherNumber
+{
+    if (12 >= [otherNumber generality]) {
+       float other_data = [otherNumber floatValue];
+
+       if (data == other_data)
+           return NSOrderedSame;
+       else
+           return (data < other_data) ?
+                     NSOrderedAscending
+                   : NSOrderedDescending;
+    }
+    else
+       return [otherNumber compare:self];
+}
+
+// Override these from NSValue
+
+- (void)getValue:(void*)value
+{
+    if (value == nil) {
+       [[[InvalidArgumentException new]
+               setReason:@"NULL buffer in -getValue"] raise];
+    }
+    else 
+       *(float*)value = data;
+}
+- (void *)valueBytes
+{
+    return &(self->data);
+}
+
+- (const char*)objCType
+{
+    return @encode(float);
+}
+
+// NSCopying
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    if ([self zone] == zone)
+       return RETAIN(self);
+    else
+       return [[[NSFloatNumber class] alloc]
+                   initValue:&data withObjCType:@encode(float)];
+}
+
+// NSCoding
+
+- (Class)classForCoder
+{
+    return isa;
+}
+
+- (void)encodeWithCoder:(NSCoder*)coder
+{
+    [coder encodeValueOfObjCType:@encode(float) at:&data];
+}
+
+- (id)initWithCoder:(NSCoder*)coder
+{
+    [coder decodeValueOfObjCType:@encode(float) at:&data];
+    return self;
+}
+
+@end /* NSFloatNumber */
+
+
+@implementation NSDoubleNumber
+
++ (id)allocWithZone:(NSZone *)zone
+{
+    return NSAllocateObject (self, 0, zone);
+}
+
+- initValue:(const void*)value withObjCType:(const char*)type;
+{
+    self = [super init];
+    data = *(double*)value;
+    return self;
+}
+
+- (BOOL)boolValue
+{
+    return data;
+}
+
+- (char)charValue
+{
+    return data;
+}
+
+- (unsigned char)unsignedCharValue
+{
+    return data;
+}
+
+- (short)shortValue
+{
+    return data;
+}
+
+- (unsigned short)unsignedShortValue
+{
+    return data;
+}
+
+- (int)intValue
+{
+    return data;
+}
+
+- (unsigned int)unsignedIntValue
+{
+    return data;
+}
+
+- (long)longValue
+{
+    return data;
+}
+
+- (unsigned long)unsignedLongValue
+{
+    return data;
+}
+
+- (long long)longLongValue
+{
+    return data;
+}
+
+- (unsigned long long)unsignedLongLongValue
+{
+    return data;
+}
+
+- (float)floatValue
+{
+    return data;
+}
+
+- (double)doubleValue
+{
+    return data;
+}
+
+- (NSString *)descriptionWithLocale:(NSDictionary *)locale
+{
+    FMT_NUMSTR("%0.16g");
+}
+
+- (int)generality
+{
+    return 13;
+}
+
+- (NSComparisonResult)compare:(NSNumber *)otherNumber
+{
+    if (13 >= [otherNumber generality]) {
+       double other_data = [otherNumber doubleValue];
+
+       if (data == other_data)
+           return NSOrderedSame;
+       else
+           return (data < other_data) ?
+                     NSOrderedAscending
+                   : NSOrderedDescending;
+    }
+    else
+       return [otherNumber compare:self];
+}
+
+// Override these from NSValue
+
+- (void)getValue:(void*)value
+{
+    if (value == nil) {
+       [[[InvalidArgumentException new]
+               setReason:@"NULL buffer in -getValue"] raise];
+    }
+    else 
+       *(double*)value = data;
+}
+- (void *)valueBytes
+{
+    return &(self->data);
+}
+
+- (const char*)objCType
+{
+    return @encode(double);
+}
+
+// NSCopying
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    if ([self zone] == zone)
+       return RETAIN(self);
+    else
+       return [[[NSDoubleNumber class] alloc]
+                   initValue:&data withObjCType:@encode(double)];
+}
+
+// NSCoding
+
+- (Class)classForCoder
+{
+    return isa;
+}
+
+- (void)encodeWithCoder:(NSCoder*)coder
+{
+    [coder encodeValueOfObjCType:@encode(double) at:&data];
+}
+
+- (id)initWithCoder:(NSCoder*)coder
+{
+    [coder decodeValueOfObjCType:@encode(double) at:&data];
+    return self;
+}
+
+@end /* NSDoubleNumber */
+
diff --git a/libFoundation/Foundation/NSConcreteNumber.m.sh b/libFoundation/Foundation/NSConcreteNumber.m.sh
new file mode 100755 (executable)
index 0000000..98d4b67
--- /dev/null
@@ -0,0 +1,214 @@
+#!/bin/sh
+
+echo "THIS SCRIPT IS DEPRECATED!"
+exit 10
+
+template ()
+{
+NAME=$1
+C=$2
+METHOD=$3
+FORMAT=$4
+GENERALITY=$5
+
+cat <<EOF
+
+/*
+ *  DO NOT EDIT! GENERATED AUTOMATICALLY FROM NSConcreteNumber.m.sh.
+ *  ${NAME} concrete number
+ */
+
+@implementation NS${NAME}Number
+
++ (id)allocWithZone:(NSZone*)zone
+{
+    return NSAllocateObject (self, 0, zone);
+}
+
+- initValue:(const void*)value withObjCType:(const char*)type;
+{
+    self = [super init];
+    data = *(${C}*)value;
+    return self;
+}
+
+- (BOOL)boolValue
+{
+    return data;
+}
+
+- (char)charValue
+{
+    return data;
+}
+
+- (unsigned char)unsignedCharValue
+{
+    return data;
+}
+
+- (short)shortValue
+{
+    return data;
+}
+
+- (unsigned short)unsignedShortValue
+{
+    return data;
+}
+
+- (int)intValue
+{
+    return data;
+}
+
+- (unsigned int)unsignedIntValue
+{
+    return data;
+}
+
+- (long)longValue
+{
+    return data;
+}
+
+- (unsigned long)unsignedLongValue
+{
+    return data;
+}
+
+- (long long)longLongValue
+{
+    return data;
+}
+
+- (unsigned long long)unsignedLongLongValue
+{
+    return data;
+}
+
+- (float)floatValue
+{
+    return data;
+}
+
+- (double)doubleValue
+{
+    return data;
+}
+
+- (NSString *)descriptionWithLocale:(NSDictionary *)locale
+{
+    if (NSStringClass == Nil) NSStringClass = [NSString class];
+    return [NSStringClass stringWithFormat:@${FORMAT}, data];
+}
+
+- (int)generality
+{
+    return ${GENERALITY};
+}
+
+- (NSComparisonResult)compare:(NSNumber*)otherNumber
+{
+    if([self generality] >= [otherNumber generality]) {
+       ${C} other_data = [otherNumber ${METHOD}Value];
+
+       if (data == other_data)
+           return NSOrderedSame;
+       else
+           return (data < other_data) ?
+                     NSOrderedAscending
+                   : NSOrderedDescending;
+    }
+    else
+       return [otherNumber compare:self];
+}
+
+// Override these from NSValue
+
+- (void)getValue:(void*)value
+{
+    if (value == nil) {
+       [[[InvalidArgumentException new]
+               setReason:@"NULL buffer in -getValue"] raise];
+    }
+    else 
+       *(${C}*)value = data;
+}
+- (void *)valueBytes
+{
+    return &(self->data);
+}
+
+- (const char*)objCType
+{
+    return @encode(${C});
+}
+
+// NSCopying
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    if ([self zone] == zone)
+       return RETAIN(self);
+    else
+       return [[[NS${NAME}Number class] alloc]
+                   initValue:&data withObjCType:@encode(${C})];
+}
+
+// NSCoding
+
+- (Class)classForCoder
+{
+    return isa;
+}
+
+- (void)encodeWithCoder:(NSCoder*)coder
+{
+    [coder encodeValueOfObjCType:@encode(${C}) at:&data];
+}
+
+- (id)initWithCoder:(NSCoder*)coder
+{
+    [coder decodeValueOfObjCType:@encode(${C}) at:&data];
+    return self;
+}
+
+@end /* NS${NAME}Number */
+
+EOF
+}
+
+#
+# Generate common part
+#
+
+cat <<EOF
+/*
+ * Author: mircea
+ */
+
+#include <Foundation/common.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSException.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+#include <Foundation/NSCoder.h>
+#include "NSConcreteNumber.h"
+
+static Class NSStringClass = Nil;
+
+EOF
+
+template Bool  "BOOL"          bool            '"%d"'          1
+template Char  "char"          char            '"%d"'          2
+template UChar "unsigned char" unsignedChar    '"%d"'          3
+template Short "short"         short           '"%hd"'         4
+template UShort        "unsigned short" unsignedShort  '"%hu"'         5
+template Int   "int"           int             '"%d"'          6
+template UInt  "unsigned int"  unsignedInt     '"%u"'          7
+template Long  "long"          long            '"%ld"'         8
+template ULong "unsigned long" unsignedLong    '"%lu"'         9
+template LongLong "long long"  longLong        '"%lld"'        10
+template ULongLong "unsigned long long"        unsignedLongLong '"%llu"' 11
+template Float "float"         float           '"%0.7g"'       12
+template Double        "double"        double          '"%0.16g"'      13
diff --git a/libFoundation/Foundation/NSConcreteScanner.h b/libFoundation/Foundation/NSConcreteScanner.h
new file mode 100644 (file)
index 0000000..190d232
--- /dev/null
@@ -0,0 +1,63 @@
+/* 
+   NSConcreteScanner.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSConcreteScanner_h__
+#define __NSConcreteScanner_h__
+
+#include <Foundation/NSScanner.h>
+
+@class NSDictionary;
+@class NSString;
+@class NSCharacterSet;
+
+@interface NSConcreteScanner : NSScanner
+{
+    NSDictionary   *locale;
+    NSString       *string;
+    unsigned int   scanLocation;
+    BOOL           caseSensitive;
+    NSCharacterSet *skipSet;
+}
+
+- (id)initWithString:(NSString*)string;
+- (NSString*)string;
+- (void)setScanLocation:(unsigned int)index;
+- (unsigned int)scanLocation;
+- (void)setCaseSensitive:(BOOL)flag;
+- (BOOL)caseSensitive;
+- (void)setCharactersToBeSkipped:(NSCharacterSet*)skipSet;
+- (NSCharacterSet*)charactersToBeSkipped;
+- (void)setLocale:(NSDictionary*)locale;
+- (NSDictionary*)locale;
+
+@end
+
+#endif /* __NSConcreteScanner_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConcreteScanner.m b/libFoundation/Foundation/NSConcreteScanner.m
new file mode 100644 (file)
index 0000000..3d0f281
--- /dev/null
@@ -0,0 +1,96 @@
+/* 
+   NSConcreteScanner.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSCharacterSet.h>
+#include "NSConcreteScanner.h"
+
+@implementation NSConcreteScanner
+
+- (id)initWithString:(NSString*)_string
+{
+    ASSIGN(self->string, _string);
+    return self;
+}
+
+#if !LIB_FOUNDATION_BOEHM_GC
+- (void)dealloc {
+    RELEASE(self->string);
+    RELEASE(self->locale);
+    RELEASE(self->skipSet);
+    [super dealloc];
+}
+#endif
+
+- (NSString *)string
+{
+    return self->string;
+}
+
+- (void)setScanLocation:(unsigned int)index
+{
+    self->scanLocation = index;
+}
+- (unsigned int)scanLocation
+{
+    return self->scanLocation;
+}
+
+- (void)setCaseSensitive:(BOOL)flag
+{
+    self->caseSensitive = flag;
+}
+- (BOOL)caseSensitive
+{
+    return self->caseSensitive;
+}
+
+- (void)setCharactersToBeSkipped:(NSCharacterSet *)_skipSet
+{
+    ASSIGN(self->skipSet, _skipSet);
+}
+- (NSCharacterSet *)charactersToBeSkipped
+{
+    return self->skipSet;
+}
+
+- (void)setLocale:(NSDictionary *)_locale
+{
+    ASSIGN(self->locale, _locale);
+}
+- (NSDictionary *)locale
+{
+    return self->locale;
+}
+
+@end /* NSConcreteScanner */
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSConcreteSet.h b/libFoundation/Foundation/NSConcreteSet.h
new file mode 100644 (file)
index 0000000..c5f893a
--- /dev/null
@@ -0,0 +1,120 @@
+/* 
+   NSConcreteSet.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSConcreteSet_h__
+#define __NSConcreteSet_h__
+
+#include <Foundation/NSSet.h>
+#include <Foundation/NSEnumerator.h>
+#include <Foundation/NSUtilities.h>
+
+/*
+ * Concrete class for NSSet
+ */
+
+@interface NSConcreteSet : NSSet
+{
+    NSHashTable* table;
+}
+
+/* Allocating and Initializing */
+
+- (id)init;
+- (id)initWithObjects:(id*)objects count:(unsigned int)count;
+- (id)initWithSet:(NSSet *)set copyItems:(BOOL)flag;
+
+/* Accessing keys and values */
+
+- (unsigned int)count;
+- (id)member:(id)anObject;
+- (NSEnumerator *)objectEnumerator;
+
+/* Private methods */
+
+- (void)__setObjectEnumerator:(void*)en;
+
+@end
+
+/*
+ * Concrete class for NSMutableSet
+ */
+
+@interface NSConcreteMutableSet : NSMutableSet
+{
+    NSHashTable* table;
+}
+
+/* Allocating and Initializing */
+
+- (id)init;
+- (id)initWithObjects:(id*)objects count:(unsigned int)count;
+- (id)initWithSet:(NSSet *)set copyItems:(BOOL)flag;
+
+/* Accessing keys and values */
+
+- (unsigned int)count;
+- (id)member:(id)anObject;
+- (NSEnumerator *)objectEnumerator;
+
+/* Add and remove entries */
+
+- (void)addObject:(id)object;
+- (void)removeObject:(id)object;
+- (void)removeAllObjects;
+
+/* Private methods */
+
+- (void)__setObjectEnumerator:(void*)en;
+
+@end
+
+/*
+ * _NSConcreteSetEnumerator class
+ */
+
+typedef enum {setEnumHash, setEnumMap} SetEnumMode;
+
+@interface _NSConcreteSetEnumerator : NSEnumerator
+{
+    id set;
+    SetEnumMode        mode;
+    union {
+       NSMapEnumerator  map;
+       NSHashEnumerator hash;
+    } enumerator;
+}
+
+- (id)initWithSet:(NSSet*)_set mode:(SetEnumMode)_mode;
+- (id)nextObject;
+
+@end /* _NSConcreteSetEnumerator */
+
+#endif /* __NSConcreteSet_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConcreteSet.m b/libFoundation/Foundation/NSConcreteSet.m
new file mode 100644 (file)
index 0000000..0a8afc6
--- /dev/null
@@ -0,0 +1,409 @@
+/* 
+   NSConcreteSet.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <stdarg.h>
+
+#include <Foundation/common.h>
+#include <Foundation/NSObject.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSValue.h>
+
+#include <Foundation/NSException.h>
+#include "NSConcreteSet.h"
+
+/*
+ * NSConcreteSet
+ */
+
+@implementation NSConcreteSet
+
+/* Allocating and Initializing */
+
+- (id)init
+{
+    self->table =
+        NSCreateHashTableWithZone(NSObjectHashCallBacks, 0, [self zone]);
+    return self;
+}
+
+- (id)initWithObjects:(id *)objects count:(unsigned int)count
+{
+    unsigned i;
+    
+    self->table =
+        NSCreateHashTableWithZone(NSObjectHashCallBacks, count, [self zone]);
+    for (i = 0; i < count; i++) {
+       NSHashInsert(self->table, objects[i]);
+    }
+    return self;
+}
+
+- (id)initWithSet:(NSSet *)set copyItems:(BOOL)flag
+{
+    id en = [set objectEnumerator];
+    id obj;
+    
+    self->table = NSCreateHashTableWithZone(NSObjectHashCallBacks, 
+                                            [set count], [self zone]);
+    while((obj = [en nextObject])) {
+        obj = flag ? [obj copy] : obj;
+       NSHashInsert(self->table, obj);
+        if (flag) RELEASE(obj);
+    }
+    return self;
+}
+
+/* Destroying */
+
+- (void)dealloc
+{
+    NSFreeHashTable(self->table);
+    [super dealloc];
+}
+
+/* Copying */
+
+- (id)copy
+{
+    return RETAIN(self);
+}
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    return (zone == [self zone])
+        ? RETAIN(self)
+        : [[NSConcreteSet allocWithZone:zone] initWithSet:self copyItems:NO];
+}
+
+/* Accessing keys and values */
+
+- (unsigned int)count
+{
+    return NSCountHashTable(table);
+}
+
+- (id)member:(id)anObject
+{
+    return (NSObject*)NSHashGet(table, anObject);
+}
+
+/* Entries */
+
+- (NSEnumerator *)objectEnumerator
+{
+    return AUTORELEASE([[_NSConcreteSetEnumerator alloc]
+                           initWithSet:self mode:setEnumHash]);
+}
+
+/* Private methods */
+
+- (void)__setObjectEnumerator:(void*)en;
+{
+    *((NSHashEnumerator*)en) = NSEnumerateHashTable(table);
+}
+
+@end /* NSConcreteSet */
+
+/*
+ * NSConcreteMutableSet
+ */
+@implementation NSConcreteMutableSet
+
+/* Allocating and Initializing */
+
+
+- (id)init
+{
+    self->table =
+        NSCreateHashTableWithZone(NSObjectHashCallBacks, 0, [self zone]);
+    return self;
+}
+
+- (id)initWithCapacity:(unsigned)_capacity
+{
+    self->table = NSCreateHashTableWithZone(NSObjectHashCallBacks, 
+                                            _capacity, [self zone]);
+    return self;
+}
+
+- (id)initWithObjects:(id*)objects count:(unsigned int)count
+{
+    unsigned i;
+    
+    self->table = NSCreateHashTableWithZone(NSObjectHashCallBacks, 
+                                            count, [self zone]);
+    for (i = 0; i < count; i++)
+       NSHashInsert(self->table, objects[i]);
+    return self;
+}
+
+- (id)initWithSet:(NSSet *)set copyItems:(BOOL)flag
+{
+    id en = [set objectEnumerator];
+    id obj;
+    
+    table = NSCreateHashTableWithZone(NSObjectHashCallBacks, 
+                                       [set count], [self zone]);
+    while((obj = [en nextObject])) {
+        obj = flag ? [obj copy] : obj;
+       NSHashInsert(table, obj);
+        if (flag) RELEASE(obj);
+    }
+    return self;
+}
+
+/* Destroying */
+
+- (void)dealloc
+{
+    NSFreeHashTable(self->table);
+    [super dealloc];
+}
+
+/* Accessing keys and values */
+
+- (unsigned int)count
+{
+    return NSCountHashTable(self->table);
+}
+
+- (id)member:(id)anObject
+{
+    return (NSObject*)NSHashGet(self->table, anObject);
+}
+
+/* Entries */
+
+- (NSEnumerator *)objectEnumerator
+{
+    return AUTORELEASE([[_NSConcreteSetEnumerator alloc]
+                           initWithSet:self mode:setEnumHash]);
+}
+
+/* Add and remove entries */
+
+- (void)addObject:(id)object
+{
+    NSHashInsert(self->table, object);
+}
+
+- (void)removeObject:(id)object
+{
+    NSHashRemove(self->table, object);
+}
+
+- (void)removeAllObjects
+{
+    NSResetHashTable(self->table);
+}
+
+/* Private methods */
+
+- (void)__setObjectEnumerator:(void*)en;
+{
+    *((NSHashEnumerator*)en) = NSEnumerateHashTable(self->table);
+}
+
+@end /* NSConcreteMutableSet */
+
+/*
+ * NSCountedSet
+ */
+
+@implementation NSCountedSet
+
+/* Allocating and Initializing */
+
+- (id)init
+{
+    return [self initWithCapacity:0];
+}
+
+- (id)initWithObjects:(id*)objects count:(unsigned int)count
+{
+    unsigned i;
+    self = [self initWithCapacity:count];
+    for (i = 0; i < count; i++)
+       [self addObject:objects[i]];
+    return self;
+}
+
+- (id)initWithSet:(NSSet *)set copyItems:(BOOL)flag
+{
+    id en = [set objectEnumerator];
+    id obj;
+    
+    self = [self initWithCapacity:[set count]];
+    while((obj = [en nextObject])) {
+        obj = flag ? [obj copy] : obj; /* copy returns retained object */
+       [self addObject:obj];
+        if (flag) RELEASE(obj);
+    }
+    return self;
+}
+
+- (id)initWithCapacity:(unsigned int)aNumItems
+{
+    self->table =
+        NSCreateMapTableWithZone(NSObjectMapKeyCallBacks,
+                                 NSIntMapValueCallBacks,
+                                 aNumItems, [self zone]);
+    return self;
+}
+
+/* Destroying */
+
+- (void)dealloc
+{
+    NSFreeMapTable(self->table);
+    [super dealloc];
+}
+
+/* Copying */
+
+- (id)mutableCopyWithZone:(NSZone *)zone
+{
+    return [[NSCountedSet allocWithZone:zone] initWithSet:self copyItems:NO];
+}
+
+/* Accessing keys and values */
+
+- (unsigned int)count
+{
+    return NSCountMapTable(table);
+}
+
+- (id)member:(id)anObject
+{
+    id key, value;
+    return NSMapMember(table, (void*)anObject, (void**)&key, (void**)&value)
+        ? key : nil;
+}
+
+- (unsigned)countForObject:(id)anObject
+{
+    return (unsigned)(unsigned long)NSMapGet(table, anObject);
+}
+
+- (NSEnumerator *)objectEnumerator
+{
+    return AUTORELEASE([[_NSConcreteSetEnumerator alloc]
+                           initWithSet:self mode:setEnumMap]);
+}
+
+/* Add and remove entries */
+
+- (void)addObject:(id)object
+{
+    register unsigned long objectCount;
+    /* get old object count */
+    objectCount = (unsigned long)NSMapGet(table, object);
+    objectCount++;
+    /* store new object count */
+    NSMapInsert(table, object, (void *)objectCount);
+}
+
+- (void)removeObject:(id)object
+{
+    NSMapRemove(table, object);
+}
+
+- (void)removeAllObjects
+{
+    NSResetMapTable(table);
+}
+
+- (NSString *)descriptionWithLocale:(NSDictionary*)locale
+   indent:(unsigned int)level;
+{
+    NSMutableDictionary* dict
+        = [NSMutableDictionary dictionaryWithCapacity:[self count]];
+    NSEnumerator* enumerator = [self objectEnumerator];
+    id key;
+    
+    while((key = [enumerator nextObject]))
+       [dict setObject:
+               [NSNumber numberWithUnsignedInt:[self countForObject:key]] 
+           forKey:key];
+    
+    return [dict descriptionWithLocale:locale indent:level];
+}
+
+/* Private methods */
+
+- (void)__setObjectEnumerator:(void*)en;
+{
+    *((NSMapEnumerator*)en) = NSEnumerateMapTable(table);
+}
+
+@end
+
+/*
+ * _NSConcreteSetEnumerator
+ */
+
+@implementation _NSConcreteSetEnumerator
+
+- (id)initWithSet:(NSSet*)_set mode:(SetEnumMode)_mode;
+{
+    self->set = RETAIN(_set);
+    self->mode = _mode;
+    if (self->mode == setEnumHash)
+       [set __setObjectEnumerator:&(self->enumerator.hash)];
+    if (self->mode == setEnumMap)
+       [set __setObjectEnumerator:&(self->enumerator.map)];
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(self->set);
+    [super dealloc];
+}
+
+- (id)nextObject
+{
+    if (mode == setEnumHash) {
+       return (id)NSNextHashEnumeratorItem(&(self->enumerator.hash));
+    }
+    if (mode == setEnumMap) {
+       id key, value;
+        
+       return NSNextMapEnumeratorPair(&(self->enumerator.map),
+                                       (void**)&key,(void**)&value)==YES
+            ? key : nil;
+    }
+    return nil;
+}
+
+@end /* _NSConcreteSetEnumerator */
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConcreteString.h b/libFoundation/Foundation/NSConcreteString.h
new file mode 100644 (file)
index 0000000..27d1add
--- /dev/null
@@ -0,0 +1,231 @@
+/* 
+   NSConcreteString.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef  __NSConcreteString_h__
+#define  __NSConcreteString_h__
+
+#include <Foundation/NSString.h>
+
+/*
+  Abstract classes for 8 bit strings in the default encoding
+
+  NSObject
+    NSTemporaryString
+      NSMutableTemporaryString
+    NSString
+      NS8BitString
+        NSInline8BitString
+        NSShortInline8BitString
+        NSCharacter8BitString
+        NSNonOwned8BitString
+          NSOwned8BitString
+            NSOwnedOpen8BitString
+          NXConstantString
+          NSNonOwnedOpen8BitString
+            NSRange8BitString
+      NSUTF16String
+        NSInlineUTF16String
+      NSMutableString
+        NSMutable8BitString
+          NSMutableSimple8BitString
+*/
+
+/*
+ * Classes used to allocate concrete instances upon initWith* methods
+ */
+
+/* Used for allocating immutable instances from NSString */
+
+@interface NSTemporaryString : NSObject
+{
+    NSZone *_zone;
+    id     next;
+}
+
++ (id)allocWithZone:(NSZone*)zone;
+- (NSZone*)zone;
+
+/* initWith* methods from NSString */
+
+- (id)init;
+- (id)initWithCharacters:(const unichar*)chars length:(unsigned int)length;
+- (id)initWithCharactersNoCopy:(unichar*)chars length:(unsigned int)length 
+  freeWhenDone:(BOOL)flag;
+- (id)initWithCString:(const char*)byteString;
+- (id)initWithCString:(const char*)byteString length:(unsigned int)length;
+- (id)initWithCStringNoCopy:(char*)byteString freeWhenDone:(BOOL)flag;
+- (id)initWithCStringNoCopy:(char*)byteString length:(unsigned int)length 
+  freeWhenDone:(BOOL)flag;
+- (id)initWithString:(NSString*)aString;
+- (id)initWithFormat:(NSString*)format, ...;
+- (id)initWithFormat:(NSString*)format arguments:(va_list)argList;
+- (id)initWithFormat:(NSString*)format
+  locale:(NSDictionary*)dictionary, ...;
+- (id)initWithFormat:(NSString*)format 
+  locale:(NSDictionary*)dictionary arguments:(va_list)argList; 
+- (id)initWithData:(NSData*)data encoding:(NSStringEncoding)encoding;
+- (id)initWithContentsOfFile:(NSString*)path;
+
+@end
+
+/* Used for allocating mutable instances from NSMutableString */
+
+@interface NSMutableTemporaryString : NSTemporaryString
+- (id)initWithCapacity:(unsigned int)capacity;
+@end
+
+/*
+ * Classes for 8Bit strings
+ */
+
+/* Abstract immutable class */
+@interface NS8BitString : NSString
+- (void)getCharacters:(unichar*)buffer range:(NSRange)aRange;
+- (NSString*)substringWithRange:(NSRange)aRange;
+- (NSRange)rangeOfCharacterFromSet:(NSCharacterSet*)aSet
+  options:(unsigned int)mask range:(NSRange)aRange;
+- (NSRange)rangeOfString:(NSString*)aString
+  options:(unsigned int)mask range:(NSRange)aRange;
+- (NSComparisonResult)compare:(NSString*)aString
+  options:(unsigned int)mask range:(NSRange)aRange;
+- (unsigned)hash;
+- (NSString*)commonPrefixWithString:(NSString*)aString
+  options:(unsigned int)mask;
+- (NSString*)capitalizedString;
+- (NSData*)dataUsingEncoding:(NSStringEncoding)encoding
+  allowLossyConversion:(BOOL)flag;
+- (NSString*)lowercaseString;
+- (NSString*)uppercaseString;
+- (void)getCString:(char*)buffer maxLength:(unsigned int)maxLength
+  range:(NSRange)aRange remainingRange:(NSRange*)leftoverRange;
+- (BOOL)writeToFile:(NSString*)path atomically:(BOOL)flag;
+- (NSString*)stringRepresentation;
+@end
+
+@interface NS8BitString(NS8BitString)
+- (id)initWithCString:(char*)byteString 
+  length:(unsigned int)length copy:(BOOL)flag;
+- (const char*)cString;
+- (unsigned int)cStringLength;
+- (char*)__compact8BitBytes;
+@end
+
+@interface NSUTF16String : NSString
+@end
+
+@interface NSInlineUTF16String : NSUTF16String
+{
+    int           length;
+    unsigned char *cString;
+    unichar       chars[1];
+}
++ (id)allocForCapacity:(unsigned int)_length zone:(NSZone *)_zone;
+@end
+
+/* Abstract mutable class */
+@interface NSMutable8BitString : NSMutableString
+@end
+
+@interface NSMutable8BitString(NS8BitString)
+- (id)initWithCString:(char*)byteString 
+  length:(unsigned int)length copy:(BOOL)flag;
+- (id)initWithCapacity:(unsigned int)capacity;
+- (char*)__compact8BitBytes;
+@end
+
+/* Immutable. Holds its characters in the instance, zero terminated */
+@interface NSInline8BitString : NS8BitString /* final */
+{
+    int           cLength;
+    unsigned char cString[1];
+}
++ (id)allocForCapacity:(unsigned int)length zone:(NSZone*)zone;
+@end
+
+/* Immutable. Holds its characters in the instance, zero terminated */
+@interface NSShortInline8BitString : NS8BitString /* final */
+{
+    unsigned char cLength;
+    unsigned char cString[1];
+}
++ (id)allocForCapacity:(unsigned int)length zone:(NSZone*)zone;
+@end
+
+/* Immutable. Holds a single character in the instance, zero terminated */
+@interface NSCharacter8BitString : NS8BitString /* final */
+{
+    unsigned char c[2];
+}
+@end
+
+/* Immutable. Holds non owned pointer characters, zero terminated */
+@interface NSNonOwned8BitString : NS8BitString
+{
+    unsigned char *cString;
+    unsigned int  cLength;
+}
+@end
+
+/* Immutable. Holds owned pointer characters, zero terminated */
+@interface NSOwned8BitString : NSNonOwned8BitString
+@end
+
+/* Immutable. Constant (compiler generated), zero terminated */
+@interface NXConstantString : NSNonOwned8BitString
+@end
+
+/* Immutable. Holds non owned pointer characters, not zero terminated */
+@interface NSNonOwnedOpen8BitString : NSNonOwned8BitString
+@end
+
+/* Immutable. Holds owned pointer characters, not zero terminated */
+@interface NSOwnedOpen8BitString : NSOwned8BitString /* final */
+@end
+
+/* Immutable. Used for substring from a constant string */
+@interface NSRange8BitString : NSNonOwnedOpen8BitString /* final */
+{
+    NS8BitString *parent;
+}
+- (id)initWithString:(NSString*)aParent 
+  bytes:(char*)bytes length:(unsigned int)length;
+@end
+
+/* Mutable 8 bit string, not zero terminated */
+@interface NSMutableSimple8BitString : NSMutable8BitString
+{
+    unsigned char *cString;
+    unsigned int  cLength;
+    unsigned int  cCapacity;
+}
+@end
+
+#endif /* __NSConcreteString_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConcreteString.m b/libFoundation/Foundation/NSConcreteString.m
new file mode 100644 (file)
index 0000000..5924254
--- /dev/null
@@ -0,0 +1,1670 @@
+/* 
+   NSConcreteString.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <config.h>
+
+#include <ctype.h>
+
+#include <Foundation/common.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSData.h>
+#include <Foundation/NSCoder.h>
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/NSException.h>
+#include <Foundation/exceptions/StringExceptions.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+
+#include <Foundation/NSCharacterSet.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSConcreteString.h>
+
+#include <extensions/objc-runtime.h>
+
+#define COLLECT_STRING_CLUSTER_STATISTICS 0
+#define PERF_8BIT_USE_OPT_COMPARE   1
+#define PERF_SHTIN_USE_OWN_HASH     1
+#define PERF_SHTIN_USE_OWN_EQUAL    1
+#define PERF_SHTIN_USE_OWN_GETCHARS 1
+
+static Class NS8BitStringClass          = Nil;
+static Class NSMutable8BitStringClass   = Nil;
+static Class NSShtInline8BitStringClass = Nil;
+static Class NSInline8BitStringClass    = Nil;
+static Class NSDataClass                = Nil;
+static Class NSStringClass              = Nil;
+
+#if COLLECT_STRING_CLUSTER_STATISTICS
+static unsigned int NS8BitString_dealloc_count             = 0;
+static unsigned int NSInline8BitString_dealloc_count       = 0;
+static unsigned int NSInline8BitString_total_len           = 0;
+static unsigned int NSShortInline8BitString_dealloc_count  = 0;
+static unsigned int NSShortInline8BitString_total_len      = 0;
+static unsigned int NSNonOwned8BitString_dealloc_count     = 0;
+static unsigned int NSNonOwned8BitString_total_len         = 0;
+static unsigned int NSOwned8BitString_dealloc_count        = 0;
+static unsigned int NSOwned8BitString_total_len            = 0;
+static unsigned int NSNonOwnedOpen8BitString_dealloc_count = 0;
+static unsigned int NSNonOwnedOpen8BitString_total_len     = 0;
+static unsigned int NSOwnedOpen8BitString_dealloc_count    = 0;
+static unsigned int NSOwnedOpen8BitString_total_len        = 0;
+static unsigned int NSRange8BitString_dealloc_count        = 0;
+static unsigned int NSRange8BitString_total_len            = 0;
+
+@implementation NSString(ClusterStatistics)
+
++ (void)printStatistics
+{
+    fprintf(stderr,
+            "NSString class cluster statistics:\n"
+            "  dealloc counts:\n"
+            "    NS8BitString:                 %d\n"
+            "      NSInline8BitString:         %d\n"
+            "      NSShortInline8BitString:    %d\n"
+            "      NSNonOwned8BitString:       %d\n"
+            "        NSOwned8BitString:        %d\n"
+            "          NSOwnedOpen8BitString:  %d\n"
+            "        NSNonOwnedOpen8BitString: %d\n"
+            "          NSRange8BitString:      %d\n"
+            "  avg len (dealloc statistics):\n"
+            "    NS8BitString:\n"
+            "      NSInline8BitString:         %d\n"
+            "      NSShortInline8BitString:    %d\n"
+            "      NSNonOwned8BitString:       %d\n"
+            "        NSOwned8BitString:        %d\n"
+            "          NSOwnedOpen8BitString:  %d\n"
+            "        NSNonOwnedOpen8BitString: %d\n"
+            "          NSRange8BitString:      %d\n"
+            ,
+            NS8BitString_dealloc_count,
+            NSInline8BitString_dealloc_count,
+            NSShortInline8BitString_dealloc_count,
+            NSNonOwned8BitString_dealloc_count,
+            NSOwned8BitString_dealloc_count,
+            NSOwnedOpen8BitString_dealloc_count,
+            NSNonOwnedOpen8BitString_dealloc_count,
+            NSRange8BitString_dealloc_count,
+            NSInline8BitString_dealloc_count
+              ? NSInline8BitString_total_len / NSInline8BitString_dealloc_count
+              : 0,
+            NSShortInline8BitString_dealloc_count
+              ? NSShortInline8BitString_total_len /
+                NSShortInline8BitString_dealloc_count
+              : 0,
+            NSNonOwned8BitString_dealloc_count
+              ? NSNonOwned8BitString_total_len/NSNonOwned8BitString_dealloc_count
+              : 0,
+            NSOwned8BitString_dealloc_count
+              ? NSOwned8BitString_total_len / NSOwned8BitString_dealloc_count
+              : 0,
+            NSOwnedOpen8BitString_dealloc_count
+              ? NSOwnedOpen8BitString_total_len /
+                NSOwnedOpen8BitString_dealloc_count
+              : 0,
+            NSNonOwnedOpen8BitString_dealloc_count
+              ? NSNonOwnedOpen8BitString_total_len /
+                NSNonOwnedOpen8BitString_dealloc_count
+              : 0,
+            NSRange8BitString_dealloc_count
+              ? NSRange8BitString_total_len / NSRange8BitString_dealloc_count
+              : 0
+            );
+}
+- (void)printStatistics
+{
+    [NSString printStatistics];
+}
+
+@end
+#endif /* COLLECT_STRING_CLUSTER_STATISTICS */
+
+@implementation NS8BitString
+
++ (void)initialize 
+{
+    NS8BitStringClass          = [NS8BitString             class];
+    NSMutable8BitStringClass   = [NSMutable8BitStringClass class];
+    NSShtInline8BitStringClass = [NSShortInline8BitString  class];
+    NSInline8BitStringClass    = [NSInline8BitStringClass  class];
+    NSDataClass                = [NSData                   class];
+    NSStringClass              = [NSString                 class];
+}
+
+#if COLLECT_STRING_CLUSTER_STATISTICS
+- (void)dealloc
+{
+    NS8BitString_dealloc_count++;
+    [super dealloc];
+}
+#endif
+
+/* Accessing characters        */
+
+- (void)getCharacters:(unichar *)buffer
+{
+    register unsigned int i = 0, l;
+    register unsigned char *bytes;
+    
+    if ((l = [self cStringLength]) == 0)
+       return;
+    
+    bytes = [self __compact8BitBytes];
+    for (i = 0; i < l; i++)
+        buffer[i] = (unichar)bytes[i];
+}
+- (void)getCharacters:(unichar *)buffer range:(NSRange)aRange
+{
+    register unsigned int i = 0;
+    unsigned char *bytes;
+    
+    if (aRange.location + aRange.length > [self cStringLength]) {
+       [[[IndexOutOfRangeException alloc] 
+           initWithFormat:@"range (%d,%d) in string %x of length %d",
+               aRange.location, aRange.length, self, [self cStringLength]]
+            raise];
+    }
+    
+    bytes = [self __compact8BitBytes];
+    for (i = 0; i < aRange.length; i++)
+        buffer[i] = bytes[i];
+}
+
+/* Dividing strings */
+
+- (NSString *)substringWithRange:(NSRange)aRange
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+/* Finding characters and substrings */
+
+- (NSRange)rangeOfCharacterFromSet:(NSCharacterSet*)aSet
+  options:(unsigned int)mask range:(NSRange)aRange
+{
+    // ENCODINGS - this code applies to the system's default encoding
+    unsigned int i = 0;
+
+    IMP imp = [aSet methodForSelector:@selector(characterIsMember:)];
+    unsigned char *bytes = [self __compact8BitBytes];
+
+    if (NSMaxRange(aRange) > [self cStringLength]) {
+       [[[IndexOutOfRangeException alloc] 
+           initWithFormat:@"range %@ not in string 0x%08x of length %d",
+               NSStringFromRange(aRange), self, [self cStringLength]] 
+            raise];
+    }
+
+    if (mask & NSBackwardsSearch) {
+       for (i = aRange.length - 1; i >= aRange.location; i--) {
+           unichar c = bytes[i];
+           
+           if ((*imp)(aSet, @selector(characterIsMember:), c) ||
+               ((mask & NSCaseInsensitiveSearch) && 
+                ((islower(c) &&
+                 (*imp)(aSet, @selector(characterIsMember:), toupper(c))) ||
+                (isupper(c) &&
+                 (*imp)(aSet, @selector(characterIsMember:), tolower(c))))
+                )) {
+                   return NSMakeRange(i, 1);
+               }
+       }
+    } 
+    else {
+        unsigned max = NSMaxRange(aRange);
+       for (i = aRange.location; i < max; i++) {
+           unichar c = bytes[i];
+
+           if ((*imp)(aSet, @selector(characterIsMember:), c) ||
+               ((mask & NSCaseInsensitiveSearch) && 
+                ((islower(c) &&
+                 (*imp)(aSet, @selector(characterIsMember:), toupper(c))) ||
+                (isupper(c) &&
+                 (*imp)(aSet, @selector(characterIsMember:), tolower(c))))
+                )) {
+          return NSMakeRange(i, 1);
+               }
+       }
+    }
+    
+    return NSMakeRange(NSNotFound, 0);
+}
+
+- (NSRange)rangeOfString:(NSString*)aString
+  options:(unsigned int)mask range:(NSRange)aRange
+{
+    // ENCODINGS - this code applies to the system's default encoding
+    NSRange       range;
+    unsigned char *mbytes;
+    unsigned char *abytes;
+    unsigned int  a;
+    
+    if (![aString isKindOfClass:NS8BitStringClass] &&
+       ![aString isKindOfClass:NSMutable8BitStringClass])
+           return [super rangeOfString:aString options:mask range:aRange];
+    
+    if ((aRange.location + aRange.length) > [self cStringLength]) {
+       [[[IndexOutOfRangeException alloc] 
+           initWithFormat:@"range (%d,%d) in string %x of length %d",
+               aRange.location, aRange.length, self, [self cStringLength]] 
+            raise];
+    }
+
+    mbytes = [self __compact8BitBytes] + aRange.location;
+    abytes = [(id)aString __compact8BitBytes];
+    a = [aString cStringLength];
+    
+    if ((a == 0) || (aRange.length < a))
+        return NSMakeRange(0, 0);
+    
+    if (mask & NSAnchoredSearch)  {
+       range.location = aRange.location + 
+           ((mask & NSBackwardsSearch) ? aRange.length - a : 0);
+       range.length = a;
+       
+       if ([self compare:aString options:mask range:range] == NSOrderedSame)
+           return range;
+       else
+           return NSMakeRange(0,0);
+    }
+    
+    if (mask & NSBackwardsSearch) {    
+       if (mask & NSCaseInsensitiveSearch) {
+           /* Backward case insensitive */
+           unsigned char cf;
+            int n;
+
+            cf = islower(abytes[0]) ? toupper(abytes[0]) : abytes[0];
+            
+           for (n = aRange.length-a; n >= 0; n--) {
+               unsigned char cm =
+                    islower(mbytes[n]) ? toupper(mbytes[n]) : mbytes[n];
+               unsigned char ca = cf;
+                unsigned int i;
+                
+               if (cm != ca)
+                   continue;
+               for (i = 1; i < a; i++) {
+                   cm = islower(mbytes[n+i]) ? 
+                       toupper(mbytes[n+i]) : mbytes[n+i];
+                   ca = islower(abytes[i]) ? toupper(abytes[i]) : abytes[i];
+                   if (cm != ca)
+                       break;
+               }
+               if (i == a) {
+                   range.location = aRange.location + n;
+                   range.length = a;
+                   return range;
+               }
+           }
+       }
+       else {
+           /* Backward case sensitive */
+            int n;
+           for (n = (aRange.length - a); n >= 0; n--) {
+                unsigned int i;
+                
+               if (mbytes[n] != abytes[0])
+                   continue;
+               for (i = 1; i < a; i++)
+                   if (mbytes[n+i] != abytes[i])
+                       break;
+               if (i == a) {
+                   range.location = aRange.location + n;
+                   range.length = a;
+                   return range;
+               }
+           }
+       }
+    }
+    else {
+       if (mask & NSCaseInsensitiveSearch) {
+           /* Forward case insensitive */
+            int n;
+           unsigned char cf;
+
+            cf = islower(abytes[0]) ? toupper(abytes[0]) : abytes[0];
+
+           for (n = 0; n + a <= aRange.length; n++) {
+               unsigned char cm, ca;
+                unsigned int i;
+               
+                cm = islower(mbytes[n]) ? toupper(mbytes[n]) : mbytes[n];
+                ca = cf;
+                
+               if (cm != ca)
+                   continue;
+               for (i = 1; i < a; i++) {
+                   cm = islower(mbytes[n+i]) ? 
+                       toupper(mbytes[n+i]) : mbytes[n+i];
+                   ca = islower(abytes[i]) ? toupper(abytes[i]) : abytes[i];
+                   if (cm != ca)
+                       break;
+               }
+               if (i == a) {
+                   range.location = aRange.location + n;
+                   range.length = a;
+                   return range;
+               }
+           }
+       }
+       else {
+           /* Forward case sensitive */
+            int n;
+            
+           for (n = 0; (n + a) <= aRange.length; n++) {
+                unsigned int i;
+                
+               if (mbytes[n] != abytes[0])
+                   continue;
+               for (i = 1; i < a; i++)
+                   if (mbytes[n+i] != abytes[i])
+                       break;
+               if (i == a) {
+                   range.location = aRange.location + n;
+                   range.length   = a;
+                   return range;
+               }
+           }
+       }
+    }
+    
+    range.location = range.length = 0;
+    return range;
+}
+
+- (NSComparisonResult)compare:(NSString *)aString
+  options:(unsigned int)mask range:(NSRange)aRange
+{
+    // ENCODINGS - this code applies to the system's default encoding
+    register unsigned char *mbytes;
+    register unsigned char *abytes;
+    unsigned int   i, n, a;
+    
+#if PERF_8BIT_USE_OPT_COMPARE /* optimized */
+    register Class clazz;
+    
+    if (aString == nil) /* TODO: hh: AFAIK nil is not allowed in Cocoa? */
+       return NSOrderedDescending;
+    else if (aString == self)
+       return NSOrderedSame;
+    i = 0;
+    for (clazz = *(id *)aString; clazz; clazz = class_get_super_class(clazz)) {
+       if (clazz == NS8BitStringClass || clazz == NSMutable8BitStringClass) {
+           i = 1;
+           break;
+       }
+    }
+    if (i == 0)
+       return [super compare:aString options:mask range:aRange];
+#else
+    if (![aString isKindOfClass:NS8BitStringClass] &&
+       ![aString isKindOfClass:NSMutable8BitStringClass]) {
+       return [super compare:aString options:mask range:aRange];
+    }
+#endif
+    
+    if (aRange.location + aRange.length > [self cStringLength]) {
+       [[[IndexOutOfRangeException alloc] 
+           initWithFormat:@"range (%d,%d) in string %x of length %d",
+               aRange.location, aRange.length, self, [self cStringLength]]
+            raise];
+    }
+
+    mbytes = [self __compact8BitBytes] + aRange.location;
+    abytes = [(id)aString __compact8BitBytes];
+    
+    a = [aString cStringLength];
+    n = MIN(a, aRange.length);
+    
+    if (mask & NSCaseInsensitiveSearch) {
+       for (i = 0; i < n; i++) {
+           register unsigned char cm = 
+               islower(mbytes[i]) ? toupper(mbytes[i]):mbytes[i];
+           register unsigned char ca = 
+               islower(abytes[i]) ? toupper(abytes[i]):abytes[i];
+
+           if (cm < ca)
+               return NSOrderedAscending;
+           if (cm > ca)
+               return NSOrderedDescending;
+       }
+    }
+    else {
+       for (i = 0; i < n; i++) {
+           if (mbytes[i] < abytes[i])
+               return NSOrderedAscending;
+           if (mbytes[i] > abytes[i])
+               return NSOrderedDescending;
+       }
+    }
+    
+    if (aRange.length < a)
+       return NSOrderedAscending;
+    if (aRange.length > a)
+       return NSOrderedDescending;
+
+    return NSOrderedSame;
+}
+
+- (unsigned)hash
+{
+    static Class LastClass = Nil;
+    static unsigned char *(*compact)(id, SEL) = NULL;
+    static unsigned int  (*cstrlen)(id, SEL)  = NULL;
+    register unsigned char *bytes;
+    register unsigned      hash = 0, hash2;
+    int i, n;
+    
+#if GNU_RUNTIME /* selector caching */
+    if (LastClass != *(id *)self) {
+       LastClass = *(id *)self;
+       compact = (void *)method_get_imp(class_get_instance_method(LastClass, 
+          @selector(__compact8BitBytes)));
+       cstrlen = (void *)method_get_imp(class_get_instance_method(LastClass, 
+          @selector(cStringLength)));
+    }
+    bytes = compact(self, NULL /* dangerous? */);
+    n     = cstrlen(self, NULL /* dangerous? */);
+#else
+    bytes = [self __compact8BitBytes];
+    n     = [self cStringLength];
+#endif
+    
+    for (i = 0; i < n; i++) {
+        hash <<= 4;
+       // UNICODE - must use a for independent of composed characters
+        hash += bytes[i];
+        if ((hash2 = hash & 0xf0000000))
+            hash ^= (hash2 >> 24) ^ hash2;
+    }
+    
+    return hash;
+}
+
+/* Getting a shared prefix */
+
+- (NSString *)commonPrefixWithString:(NSString*)aString
+  options:(unsigned int)mask
+{
+    // ENCODINGS - this code applies to the system's default encoding
+    NSRange range = {0, 0};
+    unsigned char *mbytes;
+    unsigned char *abytes;
+    int           mLen, aLen, i;
+    
+    if (![aString isKindOfClass:NS8BitStringClass] &&
+       ![aString isKindOfClass:NSMutable8BitStringClass]) {
+           return [super commonPrefixWithString:aString options:mask];
+    }
+    
+    mLen   = [self cStringLength];
+    aLen   = [aString length];
+    mbytes = [self __compact8BitBytes];
+    abytes = [(NS8BitString *)aString __compact8BitBytes];
+
+    for (i = 0; (i < mLen) && (i < aLen); i++) {
+       unsigned char c1 = mbytes[i];
+       unsigned char c2 = abytes[i];
+        
+        if (mask & NSCaseInsensitiveSearch) {
+            c1 = tolower(c1);
+            c2 = tolower(c2);
+        }
+        if (c1 != c2)
+            break;
+    }
+    
+    range.length = i;
+    return [self substringWithRange:range];
+}
+
+/* Changing case */
+
+- (NSString *)capitalizedString
+{
+    // ENCODINGS - this code applies to the system's default encoding
+    int            i;
+    BOOL           f      = YES;
+    int            length = [self cStringLength];
+    unsigned char* bytes  = [self __compact8BitBytes];
+    unsigned char* chars  = MallocAtomic(sizeof(unichar)*(length+1));
+
+    for (i = 0; i < length; i++) {
+       unsigned char c = bytes[i];
+       
+       if (isspace(c))
+           f = YES;
+       
+       if (f) {
+           chars[i] = islower(c) ? toupper(c) : c;
+           f = NO;
+       }
+       else
+           chars[i] = isupper(c) ? tolower(c) : c;
+    }
+    chars[i] = 0;
+    
+    return AUTORELEASE([[NSOwned8BitString alloc]
+                           initWithCString:chars length:length copy:NO]);
+}
+
+- (NSString *)lowercaseString
+{
+    // ENCODINGS - this code applies to the system's default encoding
+    int i;
+    int length = [self cStringLength];
+    unsigned char *bytes = [self __compact8BitBytes];
+    unsigned char *chars = MallocAtomic(sizeof(unichar)*(length+1));
+
+    for (i = 0; i < length; i++) {
+       register unsigned char c = bytes[i];
+       chars[i] = isupper(c) ? tolower(c) : c;
+    }
+    chars[i] = 0;
+
+    return AUTORELEASE([[NSOwned8BitString alloc]
+                           initWithCString:chars length:length copy:NO]);
+}
+
+- (NSString *)uppercaseString
+{
+    // ENCODINGS - this code applies to the system's default encoding
+    int i;
+    int length = [self cStringLength];
+    unsigned char *bytes = [self __compact8BitBytes];
+    unsigned char *chars = MallocAtomic(sizeof(unichar)*(length+1));
+
+    for (i = 0; i < length; i++) {
+       register unsigned char c = bytes[i];
+       chars[i] = islower(c) ? toupper(c) : c;
+    }
+    
+    chars[i] = 0;
+    
+    return AUTORELEASE([[NSOwned8BitString alloc]
+                           initWithCString:chars length:length copy:NO]);
+}
+
+/* Working with C strings */
+
+- (void)getCString:(char *)buffer maxLength:(unsigned int)maxLength
+  range:(NSRange)aRange remainingRange:(NSRange*)leftoverRange
+{
+    unsigned char* bytes = [self __compact8BitBytes];
+    unsigned int toMove = MIN(maxLength, aRange.length);
+    unsigned int cLength = [self cStringLength];
+    
+    if (aRange.location + aRange.length > cLength) {
+       [[[IndexOutOfRangeException alloc] 
+           initWithFormat:@"range (%d,%d) in string %x of length %d",
+               aRange.location, aRange.length, self, cLength] raise];
+    }
+
+    if (leftoverRange) {
+       leftoverRange->location = aRange.location + toMove;
+       leftoverRange->length = cLength - leftoverRange->location;
+    }
+    memcpy(buffer, bytes + aRange.location, toMove);
+    if (toMove < maxLength)
+       buffer[toMove] = '\0';
+}
+
+- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)flag
+{
+    // UNICODE - remove this
+    NSData *data;
+    data = [self dataUsingEncoding:[NSString defaultCStringEncoding]];
+    return writeToFile(path, data, flag);
+}
+
+- (Class)classForCoder
+{
+    return NS8BitStringClass;
+}
+
+- (void)encodeWithCoder:(NSCoder*)aCoder
+{
+    const unsigned char* bytes = [self __compact8BitBytes];
+    int length = [self cStringLength];
+    
+    [aCoder encodeValueOfObjCType:@encode(int) at:&length];
+    [aCoder encodeArrayOfObjCType:@encode(char) count:length at:bytes];
+}
+
+- (id)initWithCoder:(NSCoder*)aDecoder
+{
+    unsigned char *bytes;
+    int length;
+
+    RELEASE(self); self = nil;
+
+    [aDecoder decodeValueOfObjCType:@encode(int) at:&length];
+    bytes = MallocAtomic (length + 1);
+    [aDecoder decodeArrayOfObjCType:@encode(char) count:length at:bytes];
+    bytes[length] = '\0';
+    return [[NSOwned8BitString alloc] initWithCString:bytes length:length copy:NO];
+}
+
+- (NSString *)stringRepresentation
+{
+    const unsigned char *cString;
+    int i, length;
+
+    cString = [self __compact8BitBytes];
+    length = [self cStringLength];
+    
+    if (cString == NULL)    return @"\"\"";
+    if (length  == 0)       return @"\"\"";
+    if (cString[0] == '\0') return @"\"\"";
+    
+    /* Check if the string can be parsed as a STRING token by the property list
+       parser. Otherwise we must enclose it in double quotes. */
+    if (lf_isPlistBreakChar(cString[0])) {
+        return lf_quoteString(cString, length);
+    }
+
+    for(i = 1; i < length; i++) {
+        if (lf_isPlistBreakChar(cString[i]))
+           return lf_quoteString(cString, length);
+    }
+
+    return self;
+}
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    register Class clazz;
+    int length;
+    
+    if (NSShouldRetainWithZone(self, zone))
+       return RETAIN(self);
+
+    length = [self cStringLength];
+    
+    clazz = length < 255
+        ? NSShtInline8BitStringClass
+        : NSInline8BitStringClass;
+    
+    return [[clazz allocForCapacity:length zone:zone]
+                   initWithCString:[self __compact8BitBytes] length:length];
+}
+
+- (NSData *)dataUsingEncoding:(NSStringEncoding)encoding
+  allowLossyConversion:(BOOL)flag;
+{
+    /* NS8BitString */
+    if (encoding == [NSStringClass defaultCStringEncoding]) {
+        unsigned      len;
+        unsigned char *buf = NULL;
+        
+        len  = [self cStringLength];
+        buf = NSZoneMalloc(NULL, sizeof(unsigned char) * len + 1);
+        [self getCString:buf];
+        buf[len] = '\0';
+        return [NSDataClass dataWithBytesNoCopy:buf length:strlen(buf)];
+    }
+    if (encoding == NSASCIIStringEncoding) {
+        register unsigned len = [self cStringLength];
+        register unsigned i;
+        register unsigned char *buf;
+            
+        buf = NSZoneMalloc(NULL, sizeof(char) * len + 1);
+        buf[len] = '\0';
+            
+        [self getCString:buf];            
+        if (!flag) {
+            /* check for strict ASCII */
+            for (i = 0; i < len; i++)
+                if (buf[i] > 127) return nil;
+        }
+        return [NSDataClass dataWithBytesNoCopy:buf length:len];
+    }
+
+    return [super dataUsingEncoding:encoding allowLossyConversion:flag];
+}
+
+- (id)mutableCopyWithZone:(NSZone*)zone
+{
+    return [[NSMutableSimple8BitString allocWithZone:zone]
+       initWithCString:[self __compact8BitBytes]
+       length:[self cStringLength] copy:YES];
+}
+
+@end /* NS8BitString */
+
+/*
+ * Null terminated CString containing characters inline
+ */
+@implementation NSInline8BitString /* final */
+
++ (id)allocForCapacity:(unsigned int)capacity zone:(NSZone *)zone
+{
+    NSInline8BitString *str = NSAllocateObject(self, capacity, zone);
+    str->cLength = -1;
+    return str;
+}
+
+- (id)init
+{
+    if (self->cLength != -1) {
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"cannot send %s to non-mutable instance", sel_get_name(_cmd)] 
+            raise];
+    }
+    self->cLength = 0;
+    self->cString[0] = 0;
+    return self;
+}
+
+- (id)initWithCString:(const char*)byteString length:(unsigned int)length
+{
+    if (self->cLength != -1) {
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"cannot send %s to non-mutable instance", sel_get_name(_cmd)] 
+            raise];
+    }
+    self->cLength = length;
+    memcpy(self->cString, byteString, length);
+    self->cString[length] = 0;
+    return self;
+}
+- (id)initWithCharacters:(const unichar *)chars length:(unsigned int)length
+{
+    /* it must be ensured that char values are below 256 by the cluster ! */
+    register unsigned i;
+    if (self->cLength != -1) {
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"cannot send %s to non-mutable instance", sel_get_name(_cmd)]
+            raise];
+    }
+    
+    for (i = 0; i < length; i++)
+        self->cString[i] = chars[i];
+    self->cString[i] = '\0';
+    self->cLength = i;
+    return self;
+}
+
+#if COLLECT_STRING_CLUSTER_STATISTICS
+- (void)dealloc
+{
+    NSInline8BitString_dealloc_count++;
+    NSInline8BitString_total_len += self->cLength == -1 ? 0 : self->cLength;
+    [super dealloc];
+}
+#endif
+
+- (const char *)cString
+{
+    return self->cString;
+}
+
+- (unsigned int)cStringLength
+{
+    return (self->cLength == -1) ? 0 : self->cLength;
+}
+
+- (unsigned int)length
+{
+    return (self->cLength == -1) ? 0 : self->cLength;
+}
+
+- (unichar)characterAtIndex:(unsigned int)index
+{
+    if (self->cLength == -1 || (int)index >= self->cLength) {
+       [[[IndexOutOfRangeException alloc] 
+           initWithFormat:@"index %d out of range in string %x of length %d",
+               index, self, self->cLength] raise];
+    }
+    // ENCODING
+    return self->cString[index];
+}
+
+- (NSString *)substringWithRange:(NSRange)aRange
+{
+    if (aRange.location + aRange.length > (unsigned)self->cLength) {
+       [[[IndexOutOfRangeException alloc] 
+           initWithFormat:@"range (%d,%d) in string %x of length %d",
+               aRange.location, aRange.length, self, cLength] raise];
+    }
+    if (aRange.length == 0)
+       return @"";
+
+    return AUTORELEASE([[NSRange8BitString alloc]
+                           initWithString:self
+                           bytes:(self->cString + aRange.location)
+                           length:aRange.length]);
+}
+
+- (char *)__compact8BitBytes
+{
+    return self->cString;
+}
+
+- (unsigned)hash
+{
+    register unsigned char *bytes;
+    register unsigned      hash = 0, hash2;
+    int i, n;
+    
+    bytes = self->cString;
+    n     = (self->cLength == -1) ? 0 : self->cLength;
+    
+    for (i = 0; i < n; i++) {
+        hash <<= 4;
+       // UNICODE - must use a for independent of composed characters
+        hash += bytes[i];
+        if ((hash2 = hash & 0xf0000000))
+            hash ^= (hash2 >> 24) ^ hash2;
+    }
+    
+    return hash;
+}
+
+@end /* NSInline8BitString */
+
+@implementation NSShortInline8BitString /* final */
+
++ (id)allocForCapacity:(unsigned int)capacity zone:(NSZone*)zone
+{
+    NSShortInline8BitString *str = NSAllocateObject(self, capacity, zone);
+    str->cLength = 255;
+    return str;
+}
+
+- (id)init
+{
+    if (self->cLength != 255) {
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"cannot send %s to non-mutable instance", sel_get_name(_cmd)]
+            raise];
+    }
+    self->cLength = 0;
+    self->cString[0] = 0;
+    return self;
+}
+
+- (id)initWithCString:(const char*)byteString length:(unsigned int)length
+{
+    if (self->cLength != 255) {
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"cannot send %s to non-mutable instance", sel_get_name(_cmd)] 
+            raise];
+    }
+    self->cLength = length;
+    memcpy(self->cString, byteString, length);
+    self->cString[length] = 0;
+    return self;
+}
+- (id)initWithCharacters:(const unichar *)chars length:(unsigned int)length
+{
+    /* it must be ensured that char values are below 256 by the cluster ! */
+    register unsigned i;
+    if (self->cLength != 255) {
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"cannot send %s to non-mutable instance", sel_get_name(_cmd)] 
+            raise];
+    }
+    
+    for (i = 0; i < length; i++)
+        self->cString[i] = chars[i];
+    self->cString[i] = '\0';
+    self->cLength = i;
+    return self;
+}
+
+#if COLLECT_STRING_CLUSTER_STATISTICS
+- (void)dealloc
+{
+    NSShortInline8BitString_dealloc_count++;
+    NSShortInline8BitString_total_len +=
+        self->cLength == 255 ? 0 : self->cLength;
+    [super dealloc];
+}
+#endif
+
+- (const char *)cString
+{
+    return self->cString;
+}
+
+- (unsigned int)cStringLength
+{
+    return (self->cLength == 255) ? 0 : self->cLength;
+}
+
+- (unsigned int)length
+{
+    return (self->cLength == 255) ? 0 : self->cLength;
+}
+
+- (unichar)characterAtIndex:(unsigned int)index
+{
+    if ((self->cLength == 255) || (index >= self->cLength)) {
+       [[[IndexOutOfRangeException alloc] 
+           initWithFormat:@"index %d out of range in string %x of length %d",
+               index, self, self->cLength] raise];
+    }
+    // ENCODING
+    return self->cString[index];
+}
+
+#if PERF_SHTIN_USE_OWN_GETCHARS
+- (void)getCharacters:(unichar *)buffer
+{
+    register signed short i;
+    
+    i = self->cLength;
+    if ((i == 255) || (i == 0)) /* empty string */
+       return;
+    
+    for (i--; i >= 0; i--)
+       buffer[i] = (unichar)(self->cString[i]);
+}
+- (void)getCharacters:(unichar *)buffer range:(NSRange)aRange
+{
+    register unsigned int i = 0, l;
+    
+    i = aRange.location;
+    l = i + aRange.length;
+    if (l > ((self->cLength == 255) ? 0 : self->cLength)) {
+       [[[IndexOutOfRangeException alloc] 
+           initWithFormat:@"range (%d,%d) in string %x of length %d",
+               aRange.location, aRange.length, self, [self length]] raise];
+    }
+    
+    for (; i < l; i++)
+       buffer[i] = (unichar)(self->cString[i]);
+}
+#endif
+
+- (NSString *)substringWithRange:(NSRange)aRange
+{
+    if (aRange.location + aRange.length > self->cLength)
+       [[[IndexOutOfRangeException alloc] 
+           initWithFormat:@"range (%d,%d) in string %x of length %d",
+               aRange.location, aRange.length, self, cLength] raise];
+
+    if (aRange.length == 0)
+       return @"";
+
+    return AUTORELEASE([[NSRange8BitString alloc]
+                           initWithString:self
+                           bytes:(self->cString + aRange.location)
+                           length:aRange.length]);
+}
+
+- (char *)__compact8BitBytes
+{
+    return self->cString;
+}
+
+- (NSComparisonResult)compare:(NSString *)aString
+  options:(unsigned int)mask range:(NSRange)aRange
+{
+    // ENCODINGS - this code applies to the system's default encoding
+    register unsigned char *mbytes, *abytes;
+    register Class clazz;
+    unsigned int   i, n, a;
+    
+#if 1 /* optimized */
+    if (aString == nil) /* TODO: hh: AFAIK nil is not allowed in Cocoa? */
+       return NSOrderedDescending;
+    else if (aString == self)
+       return NSOrderedSame;
+    i = 0;
+    for (clazz = *(id *)aString; clazz; clazz = class_get_super_class(clazz)) {
+       if (clazz == NS8BitStringClass || clazz == NSMutable8BitStringClass) {
+           i = 1;
+           break;
+       }
+    }
+    if (i == 0)
+       return [super compare:aString options:mask range:aRange];
+#else
+    if (![aString isKindOfClass:NS8BitStringClass] &&
+       ![aString isKindOfClass:NSMutable8BitStringClass]) {
+       return [super compare:aString options:mask range:aRange];
+    }
+#endif
+    
+    if ((aRange.location + aRange.length) > 
+       ((self->cLength == 255) ? 0 : self->cLength)) {
+       [[[IndexOutOfRangeException alloc] 
+           initWithFormat:@"range (%d,%d) in string %x of length %d",
+               aRange.location, aRange.length, self, [self cStringLength]]
+            raise];
+    }
+
+    mbytes = self->cString + aRange.location;
+    abytes = [(id)aString __compact8BitBytes];
+    
+    a = [aString cStringLength];
+    n = MIN(a, aRange.length);
+    
+    if (mask & NSCaseInsensitiveSearch) {
+       for (i = 0; i < n; i++) {
+           register unsigned char cm = 
+               islower(mbytes[i]) ? toupper(mbytes[i]):mbytes[i];
+           register unsigned char ca = 
+               islower(abytes[i]) ? toupper(abytes[i]):abytes[i];
+
+           if (cm < ca)
+               return NSOrderedAscending;
+           if (cm > ca)
+               return NSOrderedDescending;
+       }
+    }
+    else {
+       for (i = 0; i < n; i++) {
+           if (mbytes[i] < abytes[i])
+               return NSOrderedAscending;
+           if (mbytes[i] > abytes[i])
+               return NSOrderedDescending;
+       }
+    }
+    
+    if (aRange.length < a)
+       return NSOrderedAscending;
+    if (aRange.length > a)
+       return NSOrderedDescending;
+
+    return NSOrderedSame;
+}
+
+#if PERF_SHTIN_USE_OWN_HASH
+- (unsigned)hash
+{
+    /* 
+       according to Valgrind this takes 3.13% of the runtime, can this be 
+       further optimized without breaking dictionary performance due to
+       broken hash values?
+    */
+    register unsigned char *bytes;
+    register unsigned      hash = 0, hash2;
+    register int i, n;
+    
+    bytes = self->cString;
+    n     = (self->cLength == 255) ? 0 : self->cLength;
+    
+    for (i = 0; i < n; i++) {
+        hash <<= 4;
+       // UNICODE - must use a for independent of composed characters
+        hash += bytes[i];
+        if ((hash2 = hash & 0xf0000000))
+            hash ^= (hash2 >> 24) ^ hash2;
+    }
+    
+    return hash;
+}
+#endif
+
+#if PERF_SHTIN_USE_OWN_EQUAL
+- (BOOL)isEqual:(id)aString
+{
+    register unsigned char *mbytes, *abytes;
+    register Class clazz;
+    unsigned int   i, n, a;
+    NSRange range;
+    
+    if (self == aString)
+       return YES;
+    else if (aString == nil)
+       return NO;
+    
+    i = 0; n = 0;
+    if (*(id *)aString == *(id *)self) { /* exactly the same class */
+       i = 1; /* is NSString subclass             */
+       n = 1; /* is 8-bit string subclass         */
+       a = 1; /* is exactly the same string class */
+    }
+    else {
+       a = 0;
+       for (clazz=*(id *)aString; clazz; clazz=class_get_super_class(clazz)) {
+           if (clazz==NS8BitStringClass || clazz==NSMutable8BitStringClass) {
+               i = 1; // is NSString subclass
+               n = 1; // is 8-bit string subclass
+               break;
+           }
+           if (clazz == NSStringClass) {
+               i = 1; // is NSString subclass 
+               n = 0; // is not an 8-bit string subclass
+               break;
+           }
+       }
+       if (i == 0) // not a NSString subclass
+           return NO;
+    }
+    range.length = (self->cLength == 255) ? 0 : self->cLength;
+    if (n == 0) { // is not an 8-bit string subclass, use compare
+       range.location = 0;
+       return [self compare:aString options:0 range:range] == NSOrderedSame;
+    }
+    
+    /* other string is 8 bit */
+    
+    if (a == 1) { /* exact string class, do not call method */
+       a = (((NSShortInline8BitString *)aString)->cLength == 255) 
+           ? 0 
+           : ((NSShortInline8BitString *)aString)->cLength;
+       if (a != range.length)
+           /* strings differ in length */
+           return NO;
+    }
+    else if ((a = [aString cStringLength]) != range.length)
+       /* strings differ in length */
+       return NO;
+    
+    /* same length */
+    
+    mbytes = self->cString;
+    abytes = [(id)aString __compact8BitBytes];
+    
+    /* using memcmp is probably faster than looping on our own */
+    return memcmp(self->cString, abytes, a) == 0 ? YES : NO;
+}
+#endif
+
+@end /* NSShortInline8BitString */
+
+@implementation NSCharacter8BitString /* final */
+
+- (id)init
+{
+    self->c[0] = '\0';
+    self->c[1] = '\0';
+    return self;
+}
+
+- (id)initWithCString:(const char*)byteString length:(unsigned int)_length
+{
+    if (_length != 1) {
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"%@ can only handle a singe char", [self class]] raise];
+    }
+    self->c[0] = byteString[0];
+    self->c[1] = '\0';
+    
+    return self;
+}
+- (id)initWithCharacters:(const unichar *)chars length:(unsigned int)_length
+{
+    if (_length != 1) {
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"%@ can only handle a singe char", [self class]] raise];
+    }
+    self->c[0] = (char)chars[0];
+    self->c[1] = '\0';
+    
+    return self;
+}
+
+- (const char *)cString
+{
+    return &(self->c[0]);
+}
+
+- (unsigned int)cStringLength
+{
+  return 1;
+}
+
+- (unsigned int)length
+{
+  return 1;
+}
+
+- (unichar)characterAtIndex:(unsigned int)index
+{
+    if (index != 0) {
+       [[[IndexOutOfRangeException alloc] 
+           initWithFormat:@"index %d out of range in string %x of length 1",
+               index, self] raise];
+    }
+    // ENCODING
+    return self->c[0];
+}
+
+- (NSString *)substringWithRange:(NSRange)aRange
+{
+  if (aRange.location == 0 && aRange.length == 1)
+    return self;
+  if (aRange.length == 0)
+    return @"";
+
+  [[[IndexOutOfRangeException alloc] 
+         initWithFormat:@"range (%d,%d) in string %x of length 1",
+         aRange.location, aRange.length, self] raise];
+  return nil;
+}
+
+- (char *)__compact8BitBytes
+{
+    return &(self->c[0]);
+}
+
+- (unsigned)hash
+{
+    register unsigned hash = 0, hash2;
+    
+    hash <<= 4;
+    // UNICODE - must use a for independent of composed characters
+    hash += self->c[0];
+    if ((hash2 = hash & 0xf0000000))
+       hash ^= (hash2 >> 24) ^ hash2;
+    
+    return hash;
+}
+
+@end /* NSCharacter8BitString */
+
+
+/*
+ * String containing non-owned, zero termintated c-string
+ */
+
+@implementation NSNonOwned8BitString
+
+- (id)init
+{
+    if (self->cLength || self->cString) {
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"cannot send %s to non-mutable instance", sel_get_name(_cmd)]
+            raise];
+    }
+    self->cLength = 0;
+    self->cString = "";
+    return self;
+}
+
+- (id)initWithCString:(char *)byteString
+  length:(unsigned int)length copy:(BOOL)flag
+{
+    if (self->cLength || self->cString) {
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"cannot send %s to non-mutable instance", sel_get_name(_cmd)]
+            raise];
+    }
+    if (flag) {
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"cannot send %s with flag set to YES to %@ to instance", 
+           sel_get_name(_cmd), NSStringFromClass([self class])] raise];
+    }
+    cLength = length;
+    cString = byteString;
+    return self;
+}
+
+#if COLLECT_STRING_CLUSTER_STATISTICS
+- (void)dealloc
+{
+    NSNonOwned8BitString_dealloc_count++;
+    NSNonOwned8BitString_total_len += self->cLength;
+    [super dealloc];
+}
+#endif
+
+- (const char *)cString
+{
+    return self->cString;
+}
+
+- (unsigned int)cStringLength
+{
+    return self->cLength;
+}
+
+- (unsigned int)length
+{
+    return self->cLength;
+}
+
+- (unichar)characterAtIndex:(unsigned int)index
+{
+    if ((int)self->cLength == -1 || (index >= (unsigned)self->cLength)) {
+       [[[IndexOutOfRangeException alloc] 
+           initWithFormat:@"index %d out of range in string %x of length %d",
+               index, self, cLength] raise];
+    }
+    // ENCODING
+    return self->cString[index];
+}
+
+- (NSString *)substringWithRange:(NSRange)aRange
+{
+    if (aRange.location + aRange.length > cLength) {
+       [[[IndexOutOfRangeException alloc] 
+                  initWithFormat:@"range (%d,%d) in string %x of length %d",
+                  aRange.location, aRange.length, self, cLength] raise];
+    }
+    
+    if (aRange.length == 0)
+       return @"";
+
+    return AUTORELEASE([[NSRange8BitString alloc]
+                           initWithString:self
+                           bytes:cString + aRange.location
+                           length:aRange.length]);
+}
+
+- (char*)__compact8BitBytes
+{
+    return self->cString;
+}
+
+@end /* NSNonOwned8BitString */
+
+@implementation NSOwned8BitString
+
+- (id)init
+{
+    if (self->cLength || self->cString) {
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"cannot send %s to non-mutable instance", sel_get_name(_cmd)] 
+            raise];
+    }
+
+    self->cLength = 0;
+    self->cString = NSZoneMallocAtomic([self zone], sizeof(char));
+    self->cString[0] = 0;
+    return self;
+}
+
+- (id)initWithCString:(char*)byteString
+  length:(unsigned int)length
+  copy:(BOOL)flag
+{
+    if (self->cLength != 0 || self->cString != NULL) {
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"cannot send %s to non-mutable instance", sel_get_name(_cmd)]
+            raise];
+    }
+
+    self->cLength = length;
+    if (flag) {
+       self->cString = NSZoneMallocAtomic([self zone], sizeof(char)*(length+1));
+       memcpy(self->cString, byteString, length);
+       self->cString[self->cLength] = 0;
+    }
+    else
+       self->cString = byteString;
+    return self;
+}
+
+- (void)dealloc
+{
+#if COLLECT_STRING_CLUSTER_STATISTICS
+    NSOwned8BitString_dealloc_count++;
+    NSOwned8BitString_total_len += self->cLength;
+#endif
+    lfFree(self->cString);
+    [super dealloc];
+}
+
+@end /* NSOwned8BitString */
+
+#if 1
+@implementation NXConstantString
+
+- (oneway void)release
+{
+}
+
+- (id)retain
+{
+    return self;
+}
+
+- (unsigned)retainCount
+{
+    return 1;
+}
+
+- (id)autorelease
+{
+    return self;
+}
+
+- (void)dealloc
+{
+    [self shouldNotImplement:_cmd];
+}
+
+@end /* NXConstantString */
+#else
+@interface DummyNXConstantString : NSNonOwned8BitString
+@end
+
+@implementation DummyNXConstantString
+- (oneway void)release
+{
+}
+
+- (id)retain
+{
+    return self;
+}
+
+- (unsigned)retainCount
+{
+    return 1;
+}
+
+- (id)autorelease
+{
+    return self;
+}
+
+- (void)dealloc
+{
+    [self shouldNotImplement:_cmd];
+}
+
++ (void)load
+{
+    static BOOL didLoad = NO;
+
+    if (!didLoad) {
+        Class metaClass;
+        Class constantStringClass;
+        Class constantStringMetaClass;
+
+        didLoad = YES;
+
+        metaClass               = ((DummyNXConstantString*)self)->isa;
+        constantStringClass     = objc_lookup_class ("NXConstantString");
+        constantStringMetaClass = constantStringClass->class_pointer;
+        
+        memcpy(constantStringClass,     self,      sizeof (struct objc_class));
+        memcpy(constantStringMetaClass, metaClass, sizeof (struct objc_class));
+        
+        constantStringClass->name
+            = constantStringMetaClass->name
+            = "NXConstantString";
+
+        class_add_behavior(constantStringClass, self);
+    }
+}
+
+@end /* DummyNXConstantString */
+#endif
+
+@implementation NSNonOwnedOpen8BitString
+
+#if COLLECT_STRING_CLUSTER_STATISTICS
+- (void)dealloc
+{
+    NSNonOwnedOpen8BitString_dealloc_count++;
+    NSNonOwnedOpen8BitString_total_len += self->cLength;
+    [super dealloc];
+}
+#endif
+
+- (const char*)cString
+{
+    unsigned char *str;
+    
+    str = NSZoneMallocAtomic([self zone], sizeof(char)*(self->cLength + 1));
+    memcpy(str, self->cString, self->cLength);
+    str[cLength] = 0;
+#if !LIB_FOUNDATION_BOEHM_GC
+    [NSAutoreleasedPointer autoreleasePointer:str];
+#endif
+    return str;
+}
+
+@end /* NSNonOwnedOpen8BitString */
+
+@implementation NSOwnedOpen8BitString /* final */
+
+#if COLLECT_STRING_CLUSTER_STATISTICS
+- (void)dealloc
+{
+    NSOwnedOpen8BitString_dealloc_count++;
+    NSOwnedOpen8BitString_total_len += self->cLength;
+    [super dealloc];
+}
+#endif
+
+- (id)initWithCString:(char *)byteString
+  length:(unsigned int)length copy:(BOOL)flag
+{
+    if (self->cLength || self->cString) {
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"cannot send %s to non-mutable instance", sel_get_name(_cmd)] 
+            raise];
+    }
+    if (length != 0 && byteString == NULL) {
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"passed NULL cstring to %s with a non-null length (%i)!", 
+            sel_get_name(_cmd), length]
+            raise];
+    }
+    
+    if (strlen(byteString) < length) {
+        printf("LENGTH DIFFERS: %i vs %i\n", strlen(byteString), length);
+        abort();
+    }
+    
+    self->cLength = length;
+    if (flag) {
+        /* TODO: this is not tracked in dealloc? */
+       self->cString = 
+            NSZoneMallocAtomic([self zone], sizeof(char)*(length + 1));
+       memcpy(cString, byteString, length);
+        cString[length] = 0;
+    }
+    else
+       self->cString = byteString;
+    return self;
+}
+
+- (const char *)cString
+{
+    unsigned char *str = MallocAtomic(sizeof(char)*(self->cLength + 1));
+    
+    memcpy(str, self->cString, self->cLength);
+    str[self->cLength] = 0;
+#if !LIB_FOUNDATION_BOEHM_GC
+    [NSAutoreleasedPointer autoreleasePointer:str];
+#endif
+    return str;
+}
+
+@end /* NSOwnedOpen8BitString */
+
+@implementation NSRange8BitString /* final */
+
+- (id)initWithString:(NSString *)aParent 
+  bytes:(char *)bytes length:(unsigned int)length
+{
+    if (self->cLength != 0 || self->cString != NULL) {
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"cannot send %s to non-mutable instance", sel_get_name(_cmd)]
+            raise];
+    }
+    
+    self->cString = bytes;
+    self->cLength = length;
+    self->parent  = RETAIN(aParent);
+    return self;
+}
+
+- (void)dealloc
+{
+#if COLLECT_STRING_CLUSTER_STATISTICS
+    NSRange8BitString_dealloc_count++;
+    NSRange8BitString_total_len += self->cLength;
+#endif
+    RELEASE(self->parent);
+    [super dealloc];
+}
+
+- (NSString *)substringWithRange:(NSRange)aRange
+{
+    if (aRange.location + aRange.length > cLength) {
+       [[[IndexOutOfRangeException alloc] 
+                  initWithFormat:@"range (%d,%d) in string %x of length %d",
+                  aRange.location, aRange.length, self, cLength] raise];
+    }
+    
+    if (aRange.length == 0)
+       return @"";
+
+    return AUTORELEASE([[NSRange8BitString alloc] 
+                           initWithString:parent
+                           bytes:cString+aRange.location 
+                           length:aRange.length]);
+}
+
+- (unsigned)hash
+{
+    register unsigned char *bytes;
+    register unsigned      hash = 0, hash2;
+    int i, n;
+    
+    bytes = self->cString;
+    n     = self->cLength;
+    
+    for (i = 0; i < n; i++) {
+        hash <<= 4;
+       // UNICODE - must use a for independent of composed characters
+        hash += bytes[i];
+        if ((hash2 = hash & 0xf0000000))
+            hash ^= (hash2 >> 24) ^ hash2;
+    }
+    
+    return hash;
+}
+
+@end /* NSRange8BitString */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConcreteTimeZone.h b/libFoundation/Foundation/NSConcreteTimeZone.h
new file mode 100644 (file)
index 0000000..bc0a8e9
--- /dev/null
@@ -0,0 +1,134 @@
+/* 
+   NSConcreteTimeZone.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSConcreteTimeZone_h__
+#define __NSConcreteTimeZone_h__
+
+#include <Foundation/NSDate.h>
+
+@class NSString;
+@class NSArray;
+@class NSMutableArray;
+
+@interface NSConcreteTimeZone : NSTimeZone
+{
+    NSString* name;
+    NSArray*  timeZoneDetails;
+}
++ timeZoneWithOffset:(int)seconds;
+- initWithName:(NSString*)name;
+- (NSString*)timeZoneName;
+- (NSArray*)timeZoneDetailArray;
+@end
+
+@interface NSConcreteTimeZoneFile : NSConcreteTimeZone
+{
+    NSString*       filename;
+    NSMutableArray* transitions;
+}
+- initFromFile:(NSString*)filename withName:(NSString*)name;
+
+- (NSArray*)timeZoneDetailArray;
+- (NSString*)filename;
+
+/* Private methods */
+- (void)_initFromFile;
+- detailWithName:(NSString*)name;
+- (NSArray*)transitions;
+@end
+
+
+/* Below are the classes used to represent a time zone description file.
+   The transitions and rules from the time zone file are stored in the
+   `transitions' array in a NSConcreteTimeZoneFile instance. Each transition
+   is represented by a NSTimeZoneTransitionDate instance. Each rule is
+   represented by a NSTimeZoneTransitionRule instance.
+
+   When -timeZoneDetailForDate: message is sent to a NSConcreteTimeZoneFile
+   object, it searches the argument date in the `transitions' array for a
+   matching date or for the dates it is in between. The comparison is made
+   by sending the -compare: message. A rule object responds to this message
+   by comparing the argument date with is start and end dates. After a
+   transition object was identified it receives the message -detailForDate:
+   to obtain the time zone detail object that will be finally returned.
+*/
+
+@class NSTimeZoneRule;
+
+@interface NSTimeZoneTransitionDate : NSObject
+{
+    NSCalendarDate *date;
+    id             detail;
+}
++ (NSTimeZoneTransitionDate *)transitionDateFromPropertyList:(id)plist
+  timezone:(id)tz;
+- (id)initWithDate:(NSDate *)date detail:detail;
+- (id)detailForDate:(NSCalendarDate *)date;
+- (NSCalendarDate *)date;
+- (NSComparisonResult)compare:(id)tranDateOrTranRule;
+
+- detailAfterLastDate;
+@end
+
+@interface NSTimeZoneTransitionRule : NSObject
+{
+    NSCalendarDate *startDate;
+    NSCalendarDate *endDate;
+    NSTimeZoneRule *startRule;
+    NSTimeZoneRule *endRule;
+}
++ (NSTimeZoneTransitionRule*)transitionRuleFromPropertyList:(id)plist
+  timezone:(id)tz;
+- (id)detailForDate:(NSCalendarDate*)date;
+- (NSComparisonResult)compare:tranDateOrTranRule;
+- (NSCalendarDate*)startDate;
+- (NSCalendarDate*)endDate;
+
+- detailAfterLastDate;
+@end
+
+@interface NSTimeZoneRule : NSObject
+{
+    int monthOfYear;
+    int weekOfMonth;
+    int dayOfWeek;
+    int hours;
+    int minutes;
+    int seconds;
+    id  detail;
+}
++ (NSTimeZoneRule*)ruleFromPropertyList:(id)plist
+  timezone:(id)tz;
+- (NSCalendarDate*)dateInYear:(int)year;
+- detail;
+@end
+
+#endif /* __NSConcreteTimeZone_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConcreteTimeZone.m b/libFoundation/Foundation/NSConcreteTimeZone.m
new file mode 100644 (file)
index 0000000..3b8e4e2
--- /dev/null
@@ -0,0 +1,792 @@
+/* 
+   NSConcreteTimeZone.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSDate.h>
+#include <Foundation/NSScanner.h>
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/NSCharacterSet.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSUtilities.h>
+
+#include "NSConcreteTimeZone.h"
+#include "NSConcreteTimeZoneDetail.h"
+
+static NSString* FORMAT = @"%a %b %d %H:%M:%S %Y";
+static NSString* FORMAT2 = @"%a %b %d %H:%M:%S %Y GMT";
+static BOOL warnings = NO;
+
+@implementation NSConcreteTimeZone
+
++ (id)allocWithZone:(NSZone *)zone
+{
+    return NSAllocateObject(self, 0, zone);
+}
+
++ (id)timeZoneWithOffset:(int)time
+{
+    NSConcreteTimeZone *timezone;
+    int                hour, minute, second;
+    BOOL               isNegative;
+    NSTimeZoneDetail   *detail;
+    
+    timezone   = [[self alloc] init];
+    isNegative = (time < 0);
+    
+    time   = abs (time);
+    hour   = time / 3600;
+    minute = (time - hour * 3600) / 60;
+    second = time - hour * 3600 - minute * 60;
+    
+    timezone->name = RETAIN(([NSString stringWithFormat:@"GMT%c%02d%02d%02d",
+                                   (isNegative ? '-' : '+'),
+                                   hour,
+                                   minute,
+                                   second]));
+    
+    detail = [[NSConcreteTimeZoneDetail alloc]
+                                        initWithAbbreviation:nil
+                                        secondsFromGMT:time
+                                        isDaylightSaving:NO
+                                        name:timezone->name
+                                        parentZone:timezone];
+    
+    timezone->timeZoneDetails = RETAIN([NSArray arrayWithObject:detail]);
+    RELEASE(detail); detail = nil;
+    
+    return timezone;
+}
+
+- (id)initWithName:(NSString *)_name
+{
+    if (self->name != _name) {
+        RELEASE(self->name); self->name = nil;
+        self->name = [_name copyWithZone:[self zone]];
+    }
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(name);
+    RELEASE(timeZoneDetails);
+    [super dealloc];
+}
+
+- (NSString *)timeZoneName
+{
+    return name;
+}
+- (NSArray *)timeZoneDetailArray
+{
+    return timeZoneDetails;
+}
+
+- (NSTimeZone *)timeZoneForDate:(NSDate *)date
+{
+    /* new in MacOSX-S */
+    return [timeZoneDetails objectAtIndex:0];
+}
+
+/* NSCopying */
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    /* TimeZone's are immutable, right ? hh */
+    return RETAIN(self);
+}
+
+@end /* NSConcreteTimeZone */
+
+
+@implementation NSConcreteTimeZoneFile
+
+static NSTimeZone* gmtTimeZone = nil;
+
++ (void)initialize
+{
+    gmtTimeZone = RETAIN([NSConcreteTimeZone timeZoneWithOffset:0]);
+}
+
+- (id)initFromFile:(NSString *)_filename withName:(NSString *)_name
+{
+    [self initWithName:_name];
+    ASSIGNCOPY(self->filename, _filename);
+    return self;
+}
+
+- (void)_initFromFile
+{
+    id propertyList, detailsDict, rulesArray, transitionsArray;
+    int i = 0, count;
+    NSEnumerator* enumerator;
+    id detailName, detailDict;
+    id *details;
+    CREATE_AUTORELEASE_POOL(pool);
+    
+    propertyList = [[NSString stringWithContentsOfFile:filename]
+                              propertyList];
+    detailsDict = AUTORELEASE([[propertyList objectForKey:@"details"]
+                                  mutableCopy]);
+    rulesArray       = [propertyList objectForKey:@"rules"];
+    transitionsArray = [propertyList objectForKey:@"transitions"];
+    count            = [detailsDict count];
+    details          = alloca(count * sizeof (id));
+    enumerator       = [detailsDict keyEnumerator];
+
+    while ((detailName = [enumerator nextObject])) {
+       detailDict = [detailsDict objectForKey:detailName];
+       details[i++]
+           = [NSConcreteTimeZoneDetail detailFromPropertyList:detailDict
+                                       name:detailName
+                                        parentZone:self];
+    }
+    timeZoneDetails = [[NSArray alloc] initWithObjects:details count:i];
+    
+    transitions
+        = RETAIN([NSMutableArray arrayWithCapacity:
+                               [rulesArray count] + [transitionsArray count]]);
+    for (i = 0, count = [rulesArray count]; i < count; i++) {
+       [transitions addObject:
+               [NSTimeZoneTransitionRule transitionRuleFromPropertyList:
+                                             [rulesArray objectAtIndex:i]
+                                         timezone:self]];
+    }
+
+    for (i = 0, count = [transitionsArray count]; i < count; i++) {
+       [transitions addObject:
+               [NSTimeZoneTransitionDate transitionDateFromPropertyList:
+                                             [transitionsArray objectAtIndex:i]
+                                         timezone:self]];
+    }
+    
+    /* Now the transitions array contains NSTimeZoneTransitionRule and
+       NSTimeZoneTransitionDate objects. We sort these instances in ascending
+       order because the algorithm in timeZoneDetailForDate: is based on this
+       fact. It is an error to have transition dates included in the time
+       covered by a rule and also to have overlaping rules. */
+
+    /* Turn on the warnings during sort */
+    warnings = YES;
+    [transitions sortUsingSelector:@selector(compare:)];
+    warnings = NO;
+
+    RELEASE(pool);
+}
+
+- (id)detailWithName:(NSString *)detailName
+{
+    int i, count = [timeZoneDetails count];
+
+    for (i = 0; i < count; i++) {
+       id detail;
+
+        detail = [timeZoneDetails objectAtIndex:i];
+       if ([detailName isEqual:[detail name]])
+           return detail;
+    }
+    return nil;
+}
+
+- (void)dealloc
+{
+    RELEASE(filename);
+    RELEASE(transitions);
+    [super dealloc];
+}
+
+- (NSArray *)timeZoneDetailArray
+{
+    if (!timeZoneDetails)
+       [self _initFromFile];
+    return timeZoneDetails;
+}
+
+- (NSTimeZone *)timeZoneForDate:(NSDate *)date
+{
+    int down, up, i = 0;
+    /* Create a transition date instance to be the key for searching in the
+       transitions array. */
+    NSTimeZoneTransitionDate *tranDate;
+    NSComparisonResult       result;
+    id                       detail;
+    
+    if (!date)
+       return nil;
+
+    if (!timeZoneDetails)
+       [self _initFromFile];
+
+    if (![transitions count])
+       return [timeZoneDetails objectAtIndex:0];
+
+    tranDate = AUTORELEASE([[NSTimeZoneTransitionDate alloc]
+                               initWithDate:date detail:nil]);
+    down = 0;
+    up = [transitions count] - 1;
+
+    /* First check with the head and the end of the interval. */
+    if ([tranDate compare:[transitions objectAtIndex:0]]
+           == NSOrderedAscending) {
+       /* Find a detail that has no saving time in effect and return it. */
+       int count = [timeZoneDetails count];
+
+       for (i = 0; i < count; i++) {
+           detail = [timeZoneDetails objectAtIndex:i];
+           if (![detail isDaylightSavingTimeZone])
+               return detail;
+       }
+       /* If we cannot find such a detail just return nil. */
+       return nil;
+    }
+
+    if ([tranDate compare:[transitions objectAtIndex:up]]
+           == NSOrderedDescending)
+       return [[transitions objectAtIndex:up] detailAfterLastDate];
+
+    /* Use a binary search algorithm to find the position. */
+    i = (down + up) / 2;
+    while (down <= up) {
+       result = [tranDate compare:[transitions objectAtIndex:i]];
+       if (result == NSOrderedSame)
+           break;
+       else if (result == NSOrderedAscending)
+           up = i - 1;
+       else if (result == NSOrderedDescending)
+           down = i + 1;
+       i = (down + up) / 2;
+    }
+    
+    /* Send the -detailForDate: message to the transition object at index i */
+    if (![date isKindOfClass:[NSCalendarDate class]]) {
+        date = [[NSCalendarDate alloc]
+                                initWithTimeIntervalSinceReferenceDate:
+                                  [date timeIntervalSinceReferenceDate]];
+        [(NSCalendarDate *)date setTimeZone:self];
+        AUTORELEASE(date);
+    }
+    return [[transitions objectAtIndex:i] detailForDate:(NSCalendarDate *)date];
+}
+
+- (NSString *)filename
+{
+    return self->filename;
+}
+- (NSArray *)transitions
+{
+    return self->transitions;
+}
+
+@end /* NSConcreteTimeZoneFile */
+
+
+@implementation NSTimeZoneTransitionDate
+
++ (NSTimeZoneTransitionDate *)transitionDateFromPropertyList:(id)plist
+  timezone:(id)tz
+{
+    NSTimeZoneTransitionDate *tranDate;
+    NSString *dateString;
+    NSString *detailName;
+
+    tranDate   = AUTORELEASE([[self alloc] init]);
+    dateString = [plist objectForKey:@"date"];
+    
+    tranDate->date = RETAIN([NSCalendarDate dateWithString:dateString
+                                            calendarFormat:FORMAT]);
+    if (!tranDate->date)
+       NSLog (@"Unable to parse transition date from '%@'!", [tz filename]);
+
+    detailName = [plist objectForKey:@"detail"];
+    if (!detailName)
+       NSLog (@"No detail is specified for transition with date '%@' in "
+               @"'%@'!",  dateString, [tz filename]);
+    else {
+       tranDate->detail = [tz detailWithName:detailName];
+       if (!tranDate->detail)
+           NSLog (@"No detail '%@' in '%@'!", detailName, [tz filename]);
+    }
+
+    return tranDate;
+}
+
+- (id)initWithDate:(NSDate *)_date detail:(id)_detail
+{
+    self->detail = RETAIN(_detail);
+    if ([_date isKindOfClass:[NSCalendarDate class]])
+        self->date = RETAIN(_date);
+    else {
+        self->date = [[NSCalendarDate alloc]
+                                      initWithTimeIntervalSinceReferenceDate:
+                                        [_date timeIntervalSinceReferenceDate]];
+        if (_detail)
+            [self->date setTimeZone:_detail];
+    }
+    return self;
+}
+
+- (id)detailForDate:(NSDate *)date
+{
+    return self->detail;
+}
+
+- (void)dealloc
+{
+    RELEASE(self->date);
+    RELEASE(self->detail);
+    [super dealloc];
+}
+
+- (NSCalendarDate *)date
+{
+    return self->date;
+}
+
+- (NSComparisonResult)compare:(id)tranDateOrTranRule
+{
+    NSComparisonResult result;
+
+    /* Send the comparision to TransitionRule and return the negated result */
+    if ([tranDateOrTranRule isKindOfClass:[NSTimeZoneTransitionRule class]])
+       return -[tranDateOrTranRule compare:self];
+
+    if ([tranDateOrTranRule isKindOfClass:isa]) {
+       if (tranDateOrTranRule == self)
+           return NSOrderedSame;
+       else {
+           result = [date compare:[tranDateOrTranRule date]];
+           if (warnings && result == NSOrderedSame)
+               NSLog (@"Duplicate dates for transitions '%@' and '%@'",
+                       self, tranDateOrTranRule);
+           return result;
+       }
+    }
+
+    NSAssert (0, @"Cannot compare NSTimeZoneTransitionDate with %@",
+               [tranDateOrTranRule class]);
+    return NSOrderedSame;
+}
+
+- (NSString *)description
+{
+    return [NSString stringWithFormat:@"{ date = \"%@\"; detail = %@; }",
+                       [date descriptionWithCalendarFormat:FORMAT2],
+                       [[detail timeZoneAbbreviation] stringRepresentation]];
+}
+
+- detailAfterLastDate
+{
+    return detail;
+}
+
+@end /* NSTimeZoneTransitionDate */
+
+
+@implementation NSTimeZoneTransitionRule
+
++ (NSTimeZoneTransitionRule *)transitionRuleFromPropertyList:(id)plist
+  timezone:(id)tz
+{
+    NSTimeZoneTransitionRule* tranRule = AUTORELEASE([self new]);
+    NSArray* transitionsArray = [plist objectForKey:@"transitions"];
+    NSCalendarDate *date1, *date2;
+
+    date1 = [NSCalendarDate dateWithString:[plist objectForKey:@"startDate"]
+                         calendarFormat:FORMAT];
+    if (!date1)
+       NSLog (@"Unable to parse start date from '%@'!", [tz filename]);
+
+    date2 = [NSCalendarDate dateWithString:[plist objectForKey:@"endDate"]
+                         calendarFormat:FORMAT];
+    if (!date2)
+       NSLog (@"Unable to parse end date from '%@'!", [tz filename]);
+
+    if (date1 && date2 && [date1 compare:date2] != NSOrderedAscending)
+       NSLog (@"Start date '%@' should be less than end date '%@'",
+               [plist objectForKey:@"startDate"],
+               [plist objectForKey:@"endDate"]);
+
+    tranRule->startRule
+       = RETAIN([NSTimeZoneRule ruleFromPropertyList:
+                                     [transitionsArray objectAtIndex:0]
+                                 timezone:tz]);
+    tranRule->endRule
+       = RETAIN([NSTimeZoneRule ruleFromPropertyList:
+                                     [transitionsArray objectAtIndex:1]
+                                 timezone:tz]);
+    tranRule->startDate = RETAIN(date1);
+    tranRule->endDate = RETAIN(date2);
+
+    return tranRule;
+}
+
+- (id)detailForDate:(NSCalendarDate *)date
+{
+    int            year;
+    NSCalendarDate *startDateInYear;
+    NSCalendarDate *endDateInYear;
+
+    year            = [date yearOfCommonEra];
+    startDateInYear = [startRule dateInYear:year];
+    endDateInYear   = [endRule dateInYear:year];
+    
+    /* Check to see if date is outside the domain of this rule. Compare only
+       with endDate, because the comparison with startDate was performed in
+       timeZoneDetailForDate: method. */
+    if ([endDate compare:date] == NSOrderedAscending) {
+       /* Date is to the right of time interval of this rule. */
+       return [endRule detail];
+    }
+    
+    if ([date compare:startDateInYear] == NSOrderedAscending) {
+       /* Date is before the first change in year, so is after the last change
+          in the preceding year. */
+       return [endRule detail];
+    }
+    else if ([date compare:endDateInYear] == NSOrderedAscending) {
+       /* Date is between the two dates of the year. */
+       return [startRule detail];
+    }
+    else {
+       /* Date is after the second change in the year */
+       return [endRule detail];
+    }
+}
+
+- (NSDate *)startDate
+{
+    return self->startDate;
+}
+- (NSDate *)endDate
+{
+    return self->endDate;
+}
+
+- (NSComparisonResult)relativePositionOfDate:(NSDate *)date
+{
+    NSComparisonResult result;
+
+    result = [endDate compare:date];
+    if (result == NSOrderedAscending)
+       return NSOrderedAscending;
+
+    /* Date is less than or equal with endDate. Test with startDate. */
+    result = [startDate compare:date];
+    if (result == NSOrderedSame || result == NSOrderedAscending) {
+       /* Date is between startDate and endDate. */
+       return NSOrderedSame;
+    }
+    else {
+       /* Date is less than startDate */
+       return NSOrderedDescending;
+    }
+}
+
+- (NSComparisonResult)compare:(id)tranDateOrTranRule
+{
+    /* If the object is a date return its position relative to start and end
+       date. Note that we should return the value of comparison relative to
+       self. */
+    if ([tranDateOrTranRule isKindOfClass:[NSTimeZoneTransitionDate class]]) {
+       NSDate             *date = [tranDateOrTranRule date];
+       NSComparisonResult result;
+
+       result = [endDate compare:date];
+
+       if (result == NSOrderedAscending || result == NSOrderedSame) {
+           /* Date is greater than or equal with endDate so we consider the
+              date greater than the interval time of self. */
+           return NSOrderedAscending;
+       }
+       else {
+           /* Date is less than endDate. Compare date with startDate. */
+           result = [startDate compare:date];
+           if (result == NSOrderedAscending || result == NSOrderedSame) {
+               /* Date is between startDate and endDate. This is an error
+                  since we require dates to not be included in time intervals
+                  of rules. */
+               if (warnings) {
+                   NSLog (@"Date '%@' is included in the time interval "
+                           @"described by rule %@",
+                           [date descriptionWithCalendarFormat:FORMAT2
+                                  timeZone:nil locale:nil],
+                           self);
+                }
+               return NSOrderedSame;
+           }
+           else {
+               /* Date is less than or equal with startDate so we consider the
+                  interval greater than date. */
+               return NSOrderedDescending;
+           }
+       }
+    }
+    else if ([tranDateOrTranRule isKindOfClass:isa]) {
+       /* Determine the relative position of the other's time interval
+          comparative with self. */
+       NSComparisonResult result1;
+       NSComparisonResult result2;
+
+       result1 = [self relativePositionOfDate:[tranDateOrTranRule startDate]];
+       result2 = [self relativePositionOfDate:[tranDateOrTranRule endDate]];
+
+       if (result1 != result2) {
+           /* We have two overlaping intervals */
+           if (warnings)
+               NSLog (@"Time intervals or rules '%@' and '%@' overlap!",
+                       self, tranDateOrTranRule);
+           return NSOrderedSame;
+       }
+       else {
+           /* We have result1 == result2. We should also check if they are
+              equal with NSOrderedSame, which means the second interval in
+              inside self. */
+           if (result1 == NSOrderedSame) {
+               if (warnings)
+                   NSLog (@"Time interval of '%@' is inside '%@'",
+                           tranDateOrTranRule, self);
+               return NSOrderedSame;
+           }
+           return result1;
+       }
+    }
+    else
+       NSAssert (0, @"Cannot compare NSTimeZoneTransitionRule with %@",
+                   [tranDateOrTranRule class]);
+    return NSOrderedSame;
+}
+
+- detailAfterLastDate
+{
+    return [endRule detail];
+}
+
+- (NSString*)descriptionWithIndent:(unsigned)indent
+{
+    id plist = [NSMutableDictionary dictionaryWithCapacity:3];
+    id tranArray = [NSMutableArray arrayWithCapacity:2];
+
+    [plist setObject:[startDate descriptionWithCalendarFormat:FORMAT2]
+          forKey:@"startDate"];
+    [plist setObject:[endDate descriptionWithCalendarFormat:FORMAT2]
+          forKey:@"endDate"];
+    [plist setObject:tranArray forKey:@"transitions"];
+
+    [tranArray addObject:startRule];
+    [tranArray addObject:endRule];
+
+    return [plist descriptionWithIndent:indent];
+}
+
+- (NSString *)description
+{
+    return [self descriptionWithIndent:0];
+}
+
+@end /* NSTimeZoneTransitionRule */
+
+
+@implementation NSTimeZoneRule
+
++ (NSTimeZoneRule *)ruleFromPropertyList:(id)plist
+  timezone:(id)tz
+{
+    id months[] = {
+       @"January", @"February", @"March", @"April", @"May", @"June", 
+       @"July", @"August", @"September", @"October", @"November", @"December"
+    };
+    id days[] = {
+       @"Sunday", @"Monday", @"Tuesday", @"Wednesday",
+       @"Thusday", @"Friday", @"Saturday"
+    };
+    id weeks[] = {
+       @"first", @"second", @"third", @"fourth", @"last"
+    };
+    NSTimeZoneRule* rule = AUTORELEASE([self new]);
+    NSString* dateString = [plist objectForKey:@"date"];
+    NSCharacterSet* blanks = [NSCharacterSet whitespaceCharacterSet];
+    NSScanner* scanner;
+    NSString* monthName;
+    NSString* weekName;
+    NSString* dayName;
+    NSString* detailName;
+    unsigned i;
+
+    if (!dateString) {
+       NSLog (@"No date rule specified in '%@'!", [tz filename]);
+       return rule;
+    }
+
+    scanner = [NSScanner scannerWithString:dateString];
+    if ([scanner scanUpToString:@"/" intoString:&monthName]
+       && [scanner scanString:@"/" intoString:NULL]
+       && [scanner scanUpToCharactersFromSet:blanks intoString:&weekName]
+       && [scanner scanUpToString:@"/" intoString:&dayName]
+       && [scanner scanString:@"/" intoString:NULL]
+       && [scanner scanInt:&rule->hours]
+       && [scanner scanString:@":" intoString:NULL]
+       && [scanner scanInt:&rule->minutes]
+       && [scanner scanString:@":" intoString:NULL]
+       && [scanner scanInt:&rule->seconds]) {
+
+       for (i = 0; i < sizeof (months) / sizeof (id); i++)
+           if ([monthName isEqual:months[i]]) {
+               rule->monthOfYear = i + 1;
+               break;
+           }
+       if (rule->monthOfYear == -1)
+           NSLog (@"Unknown month name '%@' in '%@'",
+                   monthName, [tz filename]);
+
+       for (i = 0; i < sizeof (weeks) / sizeof (id); i++)
+           if ([weekName isEqual:weeks[i]]) {
+               rule->weekOfMonth = i;
+               break;
+           }
+       if (rule->weekOfMonth == -1)
+           NSLog (@"Unknown week name '%@' in '%@'", weekName, [tz filename]);
+
+       for (i = 0; i < sizeof (days) / sizeof (id); i++)
+           if ([dayName isEqual:days[i]]) {
+               rule->dayOfWeek = i;
+               break;
+           }
+       if (rule->dayOfWeek == -1)
+           NSLog (@"Unknown day name '%@' in '%@'", dayName, [tz filename]);
+
+       if (rule->hours < 0 || rule->hours > 23)
+           NSLog (@"Hours should be between 0 and 23 in '%@'", [tz filename]);
+
+       if (rule->minutes < 0 || rule->minutes > 59)
+           NSLog (@"Minutes should be between 0 and 59 in '%@'",
+                   [tz filename]);
+
+       if (rule->seconds < 0 || rule->seconds > 59)
+           NSLog (@"Seconds should be between 0 and 59 in '%@'",
+                   [tz filename]);
+    }
+    else
+       NSLog (@"Unable to parse date rule from '%@'!", [tz filename]);
+
+    detailName = [plist objectForKey:@"detail"];
+    if (!detailName)
+       NSLog (@"No detail is specified for rule with date '%@' in '%@'!",
+                   dateString, [tz filename]);
+    else {
+       rule->detail = [tz detailWithName:detailName];
+       if (!rule->detail)
+           NSLog (@"No detail '%@' in '%@'!", detailName, [tz filename]);
+    }
+
+    return rule;
+}
+
+- (id)init
+{
+    self->monthOfYear = -1;
+    self->weekOfMonth = -1;
+    self->dayOfWeek   = -1;
+    self->hours       = -1;
+    self->minutes     = -1;
+    self->seconds     = -1;
+    return self;
+}
+
+- (NSCalendarDate *)dateInYear:(int)year
+{
+    NSCalendarDate* firstOfMonth
+       = [NSCalendarDate dateWithYear:year month:monthOfYear day:1 hour:hours
+                         minute:minutes second:seconds timeZone:gmtTimeZone];
+    int firstOfMonthInWeekDay = [firstOfMonth dayOfWeek];
+    int additionalDays = 0;
+    int nDays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+#define isLeap(y) \
+       ((y) % 4 == 0 && ((y) % 400 == 0 || (y) % 100 ))
+
+    if (firstOfMonthInWeekDay != dayOfWeek) {
+       /* Add the number needed to have the same day of week as rule says */
+       if (dayOfWeek < firstOfMonthInWeekDay)
+           additionalDays = 7 - (firstOfMonthInWeekDay - dayOfWeek);
+       else additionalDays = (dayOfWeek - firstOfMonthInWeekDay);
+    }
+    /* Add the number of days according to the number of weeks in month */
+    additionalDays += 7 * weekOfMonth;
+    if (isLeap (year))
+       nDays[1]++;
+    if (additionalDays > nDays[monthOfYear]) {
+       if (weekOfMonth == 4)
+           additionalDays -= 7;
+       else
+           NSAssert (0, @"additionalDays is greater than %d and week in "
+                       @"month is different than last", additionalDays);
+    }
+
+    /* Adjust additionalDays if it's greater than the number of days in month
+       and weekOfMonth is last. */
+
+    /* Return the date with the number of additional days added to it. */
+    return [firstOfMonth dateByAddingYears:0 months:0 days:additionalDays
+                   hours:0 minutes:0 seconds:0];
+#undef isLeap
+}
+
+- (NSString *)description
+{
+    id months[] = {
+       @"January", @"February", @"March", @"April", @"May", @"June", 
+       @"July", @"August", @"September", @"October", @"November", @"December"
+    };
+    id days[] = {
+       @"Sunday", @"Monday", @"Tuesday", @"Wednesday",
+       @"Thusday", @"Friday", @"Saturday"
+    };
+    id weeks[] = {
+       @"first", @"second", @"third", @"fourth", @"last"
+    };
+
+    return [NSString stringWithFormat:@"{ date = \"%@/%@ %@/%d:%02d:%02d\"; "
+                       @"detail = %@; }",
+                       months[monthOfYear - 1],
+                       weeks[weekOfMonth],
+                       days[dayOfWeek],
+                       hours,
+                       minutes,
+                       seconds,
+                       [[detail timeZoneAbbreviation] stringRepresentation]];
+}
+
+- detail               { return detail; }
+
+@end /* NSTimeZoneRule */
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSConcreteTimeZoneDetail.h b/libFoundation/Foundation/NSConcreteTimeZoneDetail.h
new file mode 100644 (file)
index 0000000..0631f7b
--- /dev/null
@@ -0,0 +1,73 @@
+/* 
+   NSConcreteTimeZoneDetail.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+          Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSConcreteTimeZoneDetail_h__
+#define __NSConcreteTimeZoneDetail_h__
+
+#include <Foundation/NSDate.h>
+
+@class NSString;
+
+@interface NSConcreteTimeZoneDetail : NSTimeZoneDetail
+{
+    NSString   *abbreviation;
+    NSString   *name;  // not necessarily the same as abbreviation (see HST)
+    int        offsetFromGMT;
+    BOOL       isDST;
+    NSTimeZone *parentZone; // non-retained !
+}
+
+// initializing
++ (id)detailFromPropertyList:(id)propList name:(NSString*)name
+  parentZone:(NSTimeZone *)_zone;
+
+- (id)initWithAbbreviation:(NSString*)anAbbreviation
+  secondsFromGMT:(int)aDifference
+  isDaylightSaving:(BOOL)aDst
+  name:(NSString *)name
+  parentZone:(NSTimeZone *)_zone;
+
+// querying
+- (BOOL)isDaylightSavingTimeZone;
+- (NSString *)timeZoneAbbreviation;
+- (NSString *)name;
+- (int)timeZoneSecondsFromGMT;
+
+// archiving
+- (NSString *)description;
+
+// Private
++ (int)_offsetFromString:(NSString*)string;
+
+@end
+
+#endif /* __NSConcreteTimeZoneDetail_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConcreteTimeZoneDetail.m b/libFoundation/Foundation/NSConcreteTimeZoneDetail.m
new file mode 100644 (file)
index 0000000..3536890
--- /dev/null
@@ -0,0 +1,197 @@
+/* 
+   NSConcreteTimeZoneDetail.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+          Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSScanner.h>
+#include <Foundation/NSCoder.h>
+
+#include "NSConcreteTimeZoneDetail.h"
+
+@implementation NSConcreteTimeZoneDetail
+
++ (id)detailFromPropertyList:(id)propList name:(NSString*)_name
+  parentZone:(NSTimeZone *)_zone
+{
+    id   abbrev;
+    int  offset;
+    BOOL _isDST;
+    
+    abbrev = [propList objectForKey:@"abbrev"];
+    offset = [self _offsetFromString:[propList objectForKey:@"offset"]];
+    _isDST = [[propList objectForKey:@"isDST"] isEqual:@"1"];
+#if 0
+    printf("%s is DST %s -> %s\n",
+           [abbrev cString],
+           [[propList objectForKey:@"isDST"] cString],
+           _isDST ? "yes" : "no");
+#endif
+    return AUTORELEASE([[self alloc]
+                              initWithAbbreviation:abbrev
+                              secondsFromGMT:offset
+                              isDaylightSaving:_isDST
+                              name:_name
+                              parentZone:_zone]);
+}
+
+- (id)initWithAbbreviation:(NSString *)anAbbreviation
+  secondsFromGMT:(int)aDifference
+  isDaylightSaving:(BOOL)aDst
+  name:(NSString *)_name
+  parentZone:(NSTimeZone *)_zone
+{
+    [super init];
+    self->abbreviation  = [anAbbreviation copyWithZone:[self zone]];
+    self->name          = [_name          copyWithZone:[self zone]];
+    self->offsetFromGMT = aDifference;
+    self->isDST         = aDst;
+    self->parentZone    = _zone;
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(self->abbreviation);
+    RELEASE(self->name);
+    [super dealloc];
+}
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    if ([self zone] == zone)
+       return RETAIN(self);
+    return [[[self class] alloc]
+                   initWithAbbreviation:self->abbreviation
+                   secondsFromGMT:self->offsetFromGMT
+                   isDaylightSaving:self->isDST
+                   name:self->name
+                   parentZone:self->parentZone];
+}
+
+- (BOOL)isDaylightSavingTimeZone
+{
+    return self->isDST;
+}
+- (NSString *)timeZoneAbbreviation
+{
+    return self->abbreviation;
+}
+- (NSString *)name
+{
+    return self->name;
+}
+- (int)timeZoneSecondsFromGMT
+{
+    return self->offsetFromGMT;
+}
+- (NSString *)timeZoneName
+{
+    return self->name;
+}
+- (NSArray *)timeZoneDetailArray
+{
+    return [self->parentZone timeZoneDetailArray];
+}
+
+- (NSTimeZone *)timeZoneForDate:(NSDate *)date
+{
+    /* new in MacOSXS */
+#if 0
+    NSLog(@"detail for %@, tz %@, self %@",
+          date, self->parentZone, self);
+#endif
+    return [self->parentZone timeZoneForDate:date];
+}
+
+- (NSString *)description
+{
+    int offset = abs(offsetFromGMT);
+    int hours = offset / 3600;
+    int minutes = (offset - 3600 * hours) / 60;
+    int seconds = (offset - 3600 * hours - 60 * minutes);
+
+    return [NSString stringWithFormat:@"%@ %c%02d:%02d:%02d",
+                       abbreviation,
+                       offsetFromGMT < 0 ? '-' : '+',
+                       hours, 
+                       minutes,
+                       seconds];
+}
+
++ (int)_offsetFromString:(NSString*)string
+{
+    NSScanner *scanner;
+    int       hours, minutes, seconds, offset;
+    BOOL      isNegative, errors;
+
+    scanner = [NSScanner scannerWithString:string];
+    errors  = NO;
+    if ([scanner scanInt:&hours]
+       && [scanner scanString:@":" intoString:NULL]
+       && [scanner scanInt:&minutes]
+       && [scanner scanString:@":" intoString:NULL]
+       && [scanner scanInt:&seconds]) {
+
+       isNegative = (hours < 0);
+       hours = abs(hours);
+
+       if (hours < 0 || hours > 23) {
+           NSLog (@"Hours should be between 0 and 23 in '%@'", string);
+           errors = YES;
+       }
+
+       if (minutes < 0 || minutes > 59) {
+           NSLog (@"Minutes should be between 0 and 59 in '%@'", string);
+           errors = YES;
+       }
+
+       if (seconds < 0 || seconds > 59) {
+           NSLog (@"Seconds should be between 0 and 59 in '%@'", string);
+           errors = YES;
+       }
+
+       if (errors)
+           return 0;
+
+       offset = 3600 * hours + 60 * minutes + seconds;
+       return isNegative ? -offset : offset;
+    }
+    else {
+       NSLog (@"Cannot parse offset definition '%@'", string);
+       return 0;
+    }
+}
+
+@end /* NSConcreteTimeZoneDetail */
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSConcreteUTF16String.m b/libFoundation/Foundation/NSConcreteUTF16String.m
new file mode 100644 (file)
index 0000000..9fbbc27
--- /dev/null
@@ -0,0 +1,302 @@
+/* 
+   NSConcreteString.m
+
+   Copyright (C) 2001 Helge Hess.
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@skyrix.com>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <config.h>
+
+#include <ctype.h>
+
+#include <Foundation/common.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSData.h>
+#include <Foundation/NSCoder.h>
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/NSException.h>
+#include <Foundation/exceptions/StringExceptions.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+
+#include <Foundation/NSCharacterSet.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSConcreteString.h>
+
+#include <extensions/objc-runtime.h>
+
+@implementation NSUTF16String
+
+/* working with encodings */
+
+- (BOOL)canBeConvertedToEncoding:(NSStringEncoding)_encoding
+{
+    switch(_encoding) {
+        case NSUnicodeStringEncoding:
+        case NSISOLatin1StringEncoding:
+        case NSASCIIStringEncoding:
+        case NSUTF8StringEncoding:
+            return YES;
+        default:
+            return [super canBeConvertedToEncoding:_encoding];
+    }
+}
+
+@end /* NSUTF16String */
+
+extern int NSConvertUTF16toUTF8(unichar             **sourceStart,
+                                const unichar       *sourceEnd, 
+                                unsigned char       **targetStart,
+                                const unsigned char *targetEnd);
+
+@implementation NSInlineUTF16String
+
++ (id)allocForCapacity:(unsigned int)_capacity zone:(NSZone *)_zone
+{
+    NSInlineUTF16String *str;
+    
+    str =
+        (id)NSAllocateObject(self, ((_capacity + 1) * sizeof(unichar)), _zone);
+    str->length = -1;
+    return str;
+}
+
+- (id)init
+{
+    if (self->length != -1) {
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"cannot send %s to non-mutable instance", sel_get_name(_cmd)] 
+            raise];
+    }
+    self->length = 0;
+    self->chars[0] = 0;
+    return self;
+}
+
+- (id)initWithCharacters:(const unichar *)_chars length:(unsigned int)_length
+{
+    if (self->length != -1) {
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"cannot send %s to non-mutable instance", sel_get_name(_cmd)] 
+            raise];
+    }
+    memcpy(self->chars, _chars, _length * sizeof(unichar));
+    
+    self->length = _length;
+    self->chars[_length] = 0;
+    return self;
+}
+
+- (void)dealloc
+{
+    if (self->cString) free(self->cString);
+    [super dealloc];
+}
+
+/* cString */
+
+- (const char *)cString
+{
+    if (self->length == 0)
+        return "";
+    
+    if (self->cString == NULL) {
+        NSData   *data;
+        unsigned len;
+        
+        data = [self dataUsingEncoding:[NSString defaultCStringEncoding]
+                    allowLossyConversion:YES];
+        if (data == nil) return NULL;
+        
+        if ((len = [data length]) == 0)
+            return "";
+        
+        self->cString = malloc(len + 3);
+        [data getBytes:self->cString];
+        self->cString[len] = '\0';
+    }
+    return self->cString;
+}
+- (unsigned int)cStringLength
+{
+    const unsigned char *cstr;
+    
+    if ((cstr = [self cString]))
+        return strlen(cstr);
+    return 0;
+}
+
+- (void)getCString:(char *)_buf
+{
+    strcpy(_buf, [self cString]);
+}
+- (void)getCString:(char *)_buf maxLength:(unsigned int)_maxLength
+{
+    strncpy(_buf, [self cString], _maxLength);
+    _buf[_maxLength - 1] = '\0';
+}
+- (void)getCString:(char*)buffer maxLength:(unsigned int)maxLength
+  range:(NSRange)aRange remainingRange:(NSRange *)leftoverRange
+{
+    unsigned int toMove, i, cLength;
+    const unsigned char *cstr;
+    
+    cstr = [self cString];
+    
+    toMove  = MIN(maxLength, aRange.length);
+    cLength = [self cStringLength];
+    
+    if (aRange.location + aRange.length > cLength) {
+       [[[IndexOutOfRangeException alloc]
+           initWithFormat:@"range (%d,%d) in string %x of length %d",
+               aRange.location, aRange.length, self, cLength] raise];
+    }
+
+    if (leftoverRange) {
+       leftoverRange->location = aRange.location + toMove;
+       leftoverRange->length = cLength - leftoverRange->location;
+    }
+    for (i = 0; i < toMove; i++)
+        buffer[i] = cstr[aRange.location + i];
+
+    if (toMove < maxLength)
+       buffer[toMove] = '\0';
+}
+
+/* unicode */
+
+- (unsigned int)length
+{
+    return self->length;
+}
+
+- (unichar)characterAtIndex:(unsigned int)_index
+{
+    if ((self->length == -1) || (_index >= self->length)) {
+       [[[IndexOutOfRangeException alloc] 
+           initWithFormat:@"index %d out of range in string %x of length %d",
+               _index, self, self->length] raise];
+    }
+    // ENCODING
+    return self->chars[_index];
+}
+
+- (void)getCharacters:(unichar *)_buffer range:(NSRange)_range
+{
+    if (_range.location + _range.length > self->length) {
+       [[[IndexOutOfRangeException alloc] 
+           initWithFormat:@"range (%d,%d) in string %x of length %d",
+               _range.location, _range.length, self, self->length] raise];
+    }
+    if (_range.length == 0)
+       return;
+    
+    memcpy(_buffer, &(self->chars[_range.location]), 
+          _range.length * sizeof(unichar));
+}
+
+- (NSData *)dataUsingUTF8EncodingAllowLossyConversion:(BOOL)_flag
+{
+        unsigned char *buf;
+        unsigned      bufLen;
+        int           result;
+        unsigned int  len;
+
+        len = self->length;
+            
+        /* empty UTF16 becomes empty UTF8 .. */
+        if (len == 0) return [NSData data];
+        
+        bufLen = (len + (len / 2));
+        buf    = NSZoneMallocAtomic(NULL, bufLen + 1);
+        
+        do {
+            unichar       *start16, *end16;
+            unsigned char *start, *end;
+            
+            start16 = &(self->chars[0]);
+            end16   = self->chars + len;
+            start   = &(buf[0]);
+            end     = start + bufLen;
+            
+            result = NSConvertUTF16toUTF8(&start16, end16, &start, end);
+                
+            NSAssert(result != 1, @"not enough chars in source buffer !");
+                
+            if (result == 2) {
+                /* not enough memory in target buffer */
+                bufLen *= 2;
+                buf = NSZoneRealloc(NULL, buf, bufLen + 1);
+            }
+            else {
+                len = start - buf;
+                break;
+            }
+        }
+        while (1);
+       
+        return [NSData dataWithBytesNoCopy:buf length:len];
+}
+
+- (NSData *)dataUsingEncoding:(NSStringEncoding)_encoding
+  allowLossyConversion:(BOOL)_flag
+{
+    if (_encoding == NSUnicodeStringEncoding) {
+        if (self->length == 0) return [NSData data];
+        
+        return [NSData dataWithBytes:self->chars
+                       length:(self->length * sizeof(unichar))];
+    }
+    if (_encoding == NSUTF8StringEncoding)
+        return [self dataUsingUTF8EncodingAllowLossyConversion:_flag];
+    
+    return [super dataUsingEncoding:_encoding allowLossyConversion:_flag];
+}
+
+- (NSStringEncoding)fastestEncoding
+{
+    return NSUnicodeStringEncoding;
+}
+- (NSStringEncoding)smallestEncoding
+{
+    return NSUTF8StringEncoding;
+}
+
+/* NSObject protocol */
+
+- (NSString *)stringRepresentation
+{
+    /*
+      an implementation of this method must quote the string for
+      use in property lists.
+    */
+    // TODO: to be fixed (should return a unicode string-representation ...)  !!!
+    return [[NSString stringWithCString:[self cString]]
+                     stringRepresentation];
+}
+
+@end /* NSInlineUTF16String */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConcreteUnixTask.h b/libFoundation/Foundation/NSConcreteUnixTask.h
new file mode 100644 (file)
index 0000000..f5eb131
--- /dev/null
@@ -0,0 +1,44 @@
+/* 
+   NSConcreteUnixTask.h
+
+   Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@net-community.com>
+
+   Based on the code written by Aleksandr Savostyanov <sav@conextions.com>.
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSTask.h>
+
+@interface NSConcreteUnixTask : NSTask
+{
+@private
+    pid_t        pid;
+    NSString     *taskPath;
+    NSString     *currentDirectory;
+    NSArray      *taskArguments;
+    NSDictionary *taskEnvironment;
+    int          status;
+    id           standardInput;  // either NSPipe or NSFileHandle
+    id           standardOutput; // either NSPipe or NSFileHandle
+    id           standardError;  // either NSPipe or NSFileHandle
+    BOOL         isRunning;
+    BOOL         childHasFinished;
+}
+@end
diff --git a/libFoundation/Foundation/NSConcreteUnixTask.m b/libFoundation/Foundation/NSConcreteUnixTask.m
new file mode 100644 (file)
index 0000000..93042c9
--- /dev/null
@@ -0,0 +1,747 @@
+/* 
+   NSConcreteUnixTask.m
+
+   Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@net-community.com>
+
+   Based on the code written by Aleksandr Savostyanov <sav@conextions.com>.
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+
+#include <config.h>
+#include <extensions/objc-runtime.h>
+#include <Foundation/NSUserDefaults.h>
+
+#ifdef HAVE_LIBC_H
+#  include <libc.h>
+#else
+#  include <unistd.h>
+#endif
+
+#if HAVE_VFORK_H
+# include <vfork.h>
+#endif
+
+#include <errno.h>
+#include <signal.h>
+
+#include <sys/types.h>
+
+#if HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+# define WAIT_TYPE int
+#else
+  /* Old BSD union wait */
+# define WAIT_TYPE union wait
+
+# ifndef WEXITSTATUS
+#  define WEXITSTATUS(stat_val) (int)(WIFEXITED(stat_val) \
+                                       ? (((stat_val.w_status) >> 8) & 0377) \
+                                       : -1)
+# endif
+#endif
+
+#ifndef WEXITSTATUS
+# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
+#endif
+
+#ifndef WIFEXITED
+# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
+
+#if !defined(__MINGW32__)
+#  include <sys/resource.h>
+#endif
+
+#if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+#if HAVE_SYS_TIME_H
+# include <sys/time.h> /* for struct timeval */
+#endif
+
+#include <Foundation/common.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/NSDate.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSFileHandle.h>
+#include <Foundation/NSFileManager.h>
+#include <Foundation/NSMapTable.h>
+#include <Foundation/NSNotification.h>
+#include <Foundation/NSRunLoop.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSValue.h>
+#include <Foundation/UnixSignalHandler.h>
+#include "NSConcreteUnixTask.h"
+
+#include <Foundation/exceptions/GeneralExceptions.h>
+
+static NSMapTable *unixProcessToTask = NULL;
+static BOOL gotSIGCHLD = NO;
+
+@interface NSConcreteUnixTask(Privates)
++ (void)_processExitCodes;
++ (void)_safePoint;
+- (void)_safePoint;
+@end
+
+@implementation NSConcreteUnixTask
+
+static int debugNSTask = -1;
+
++ (void)initialize
+{
+    static BOOL initialized = NO;
+    
+    if (!initialized) {
+        UnixSignalHandler *ush;
+       initialized = YES;
+        
+       unixProcessToTask = NSCreateMapTable (NSIntMapKeyCallBacks,
+                                   NSNonRetainedObjectMapValueCallBacks, 19);
+        
+        ush = [UnixSignalHandler sharedHandler];
+        
+#if !defined(__MINGW32__)
+#  if defined(SIGCHLD)
+       [ush addObserver:self
+             selector:@selector(_childFinished:)
+             forSignal:SIGCHLD
+             immediatelyNotifyOnSignal:NO];
+       [ush addObserver:self
+             selector:@selector(_sigchldImmediate:)
+             forSignal:SIGCHLD
+             immediatelyNotifyOnSignal:YES];
+#  elif defined(SIGCLD)
+       [ush addObserver:self
+             selector:@selector(_childFinished:)
+             forSignal:SIGCLD
+             immediatelyNotifyOnSignal:NO];
+       [ush addObserver:self
+             selector:@selector(_sigchldImmediate:)
+             forSignal:SIGCLD
+             immediatelyNotifyOnSignal:YES];
+#  else
+#    erro how to watch for SIGCHLD on this platform ???
+#endif
+#endif /* !__MINGW32__ */
+    }
+}
+
+- (id)init
+{
+    if ((self = [super init])) {
+        if (debugNSTask == -1) {
+            debugNSTask = [[NSUserDefaults standardUserDefaults]
+                                           boolForKey:@"NSDebugTask"] ? 1 : 0;
+        }
+    }
+    return self;
+}
+
+- (void)dealloc
+{
+    if (self->pid && self->isRunning) {
+       NSMapRemove (unixProcessToTask, (void*)(long)pid);
+    }
+    
+    RELEASE(self->taskPath);
+    RELEASE(self->currentDirectory);
+    RELEASE(self->taskArguments);
+    RELEASE(self->taskEnvironment);
+    RELEASE(self->standardInput);
+    RELEASE(self->standardOutput);
+    RELEASE(self->standardError);
+    [super dealloc];
+}
+
+- (void)setLaunchPath:(NSString*)path
+{
+    if (self->isRunning || self->childHasFinished) {
+        [NSException raise:NSInvalidArgumentException
+                     format:@"task is already launched."];
+    }
+    ASSIGN(self->taskPath, path);
+}
+
+- (void)setArguments:(NSArray*)arguments
+{
+    if (self->isRunning || self->childHasFinished) {
+        [NSException raise:NSInvalidArgumentException
+                     format:@"task is already launched."];
+    }
+    ASSIGN(taskArguments, arguments);
+}
+
+- (void)setEnvironment:(NSDictionary*)dict
+{
+    if (self->isRunning || self->childHasFinished) {
+        [NSException raise:NSInvalidArgumentException
+                     format:@"task is already launched."];
+    }
+    ASSIGN(self->taskEnvironment, dict);
+}
+
+- (void)setCurrentDirectoryPath:(NSString*)path
+{
+    if (self->isRunning || self->childHasFinished) {
+        [NSException raise:NSInvalidArgumentException
+                     format:@"task is already launched."];
+    }
+    ASSIGN(currentDirectory, path);
+}
+
+- (void)setStandardInput:(id)input
+{
+    if (self->isRunning || self->childHasFinished) {
+        [NSException raise:NSInvalidArgumentException
+                     format:@"task is already launched."];
+    }
+    ASSIGN(self->standardInput, input);
+}
+- (id)standardInput
+{
+    return self->standardInput;
+}
+
+- (void)setStandardOutput:(id)output
+{
+    if (self->isRunning || self->childHasFinished) {
+        [NSException raise:NSInvalidArgumentException
+                     format:@"task is already launched."];
+    }
+    ASSIGN(self->standardOutput, output);
+}
+- (id)standardOutput
+{
+    return self->standardOutput;
+}
+
+- (void)setStandardError:(id)error
+{
+    if (self->isRunning || self->childHasFinished) {
+        [NSException raise:NSInvalidArgumentException
+                     format:@"task is already launched."];
+    }
+    ASSIGN(self->standardError, error);
+}
+- (id)standardError
+{
+    return self->standardError;
+}
+
+- (NSString *)launchPath
+{
+    return self->taskPath;
+}
+- (NSArray *)arguments
+{
+    return self->taskArguments;
+}
+- (NSDictionary *)environment
+{
+    return self->taskEnvironment;
+}
+- (NSString *)currentDirectoryPath
+{
+    return self->currentDirectory;
+}
+
+- (BOOL)isRunning
+{
+    return self->isRunning;
+}
+- (unsigned int)processId
+{
+    return self->pid;
+}
+
+- (void)_execChild
+{
+    int          i, count, fd;
+    char         *path, **parg;
+    NSEnumerator *enumerator;
+
+    if (self->standardInput) {
+        int fd;
+        
+       close(0);
+
+        fd = [self->standardInput isKindOfClass:[NSPipe class]]
+            ? [[self->standardInput fileHandleForReading] fileDescriptor]
+            : [self->standardInput fileDescriptor];
+        dup2(fd, 0);
+    }
+    if (self->standardOutput) {
+       close(1);
+        fd = [self->standardOutput isKindOfClass:[NSPipe class]]
+            ? [[self->standardOutput fileHandleForWriting] fileDescriptor]
+            : [self->standardOutput fileDescriptor];
+        dup2(fd, 1);
+    }
+    if (self->standardError) {
+       close(2);
+        fd = [self->standardError isKindOfClass:[NSPipe class]]
+            ? [[self->standardError fileHandleForWriting] fileDescriptor]
+            : [self->standardError fileDescriptor];
+        dup2(fd, 2);
+    }
+
+    // close all descriptors but stdin, stdout and stderr (0,1 and 2)
+    // (this close procedure includes the pipe descriptors !)
+#if !defined(__MINGW32__)
+    for (fd = 3; fd < NOFILE; fd++)
+       close(fd);
+#endif
+
+    if (self->currentDirectory)
+       chdir([self->currentDirectory cString]);
+
+    count   = [taskArguments count];
+    parg    = (char**)Malloc ((count + 2) * sizeof(void*));
+    parg[0] = Strdup ([self->taskPath cString]);
+    for (i = 0; i < count; i++)
+       parg[i + 1] = Strdup ([[taskArguments objectAtIndex:i] cString]);
+    parg[count + 1] = NULL;
+    
+    path = Strdup ([self->taskPath cString]);
+    
+    if (taskEnvironment) {
+        char **penv;
+        
+        count = [taskEnvironment count];
+        penv = (char**)Malloc ((count + 1) * sizeof(void*));
+        enumerator = [taskEnvironment keyEnumerator];
+        for (i = 0; i < count; i++) {
+            NSString* key = [enumerator nextObject];
+            const char* keyCString = [key cString];
+            const char* valueCString = [[taskEnvironment objectForKey:key]
+                                                         cString];
+            char buffer[Strlen(keyCString) + Strlen(valueCString) + 2];
+
+            sprintf (buffer, "%s=%s", keyCString, valueCString);
+            penv[i] = Strdup (buffer);
+        }
+        penv[count] = NULL;
+        
+        if (execve (path, parg, penv) == -1) {
+            NSLog(@"Can't launch the child process, exec() failed!",
+                  strerror (errno));
+        }
+        lfFree(penv);
+    }
+    else {
+        if (execvp (path, parg) == -1) {
+            NSLog(@"Can't launch the child process, exec() failed!: %s",
+                  strerror (errno));
+        }
+    }
+    lfFree(parg);
+}
+
+#if !defined(__MINGW32__)
+
++ (void)_safePoint {
+    if (gotSIGCHLD) [self _processExitCodes];
+}
+- (void)_safePoint {
+    [[self class] _safePoint];
+}
+
++ (void)_processExitCodes {
+    /* Note: this may not allocate memory if
+       +doesNotifyNotificationObserversInSignalHandler
+       returns YES.
+       (it shouldn't)
+    */
+    WAIT_TYPE          s;
+    pid_t              unixPid;
+    NSConcreteUnixTask *task;
+    UnixSignalHandler  *ush;
+    NSMapEnumerator    e;
+    extern BOOL UnixSignalHandlerIsProcessing;
+    
+    if (UnixSignalHandlerIsProcessing) {
+        /* not really allowed to call print in a sig handler ... */
+        fprintf(stderr,"%s: called in sig handler context ...\n",
+                __PRETTY_FUNCTION__);
+        fflush(stderr);
+        return;
+    }
+    
+    ush = [UnixSignalHandler sharedHandler];
+    [ush blockSignal:SIGCHLD];
+    gotSIGCHLD = NO; /* reset signal handler flag */
+    
+#if 1
+    /* process all SIGCHLD signals */
+    if (unixProcessToTask) {
+        NSMutableArray *toBeNotified = nil;
+        int left = 0, terminated = 0;
+        
+        e = NSEnumerateMapTable(unixProcessToTask); // THREAD ?
+        
+        while (NSNextMapEnumeratorPair(&e,(void*)&unixPid,(void*)&task)) {
+            pid_t res;
+            
+            if (!task->isRunning) continue;
+            
+            res = waitpid(unixPid, &s, WNOHANG);
+            
+            if (res == unixPid) {
+                if (WIFEXITED(s))
+                    task->status = WEXITSTATUS(s);
+                else {
+                    /* task abnormally returned */
+                    task->status = -1;
+                }
+                
+                /* mark task object as terminated */
+                task->isRunning        = NO;
+                task->childHasFinished = YES;
+                
+                /* later post a notification ... */
+                if (toBeNotified == nil)
+                    toBeNotified = [NSMutableArray arrayWithCapacity:16];
+                [toBeNotified addObject:task];
+                
+                terminated++;
+            }
+            else if (res == 0) {
+                /* task is still running :-) */
+                left++;
+            }
+            else if (res == -1) {
+                /* error */
+                if (errno != ECHILD /* child isn't up yet ;-) */) {
+                    fprintf(stderr,
+                            "ERROR(%s): waitpid(%u): %i %s\n",
+                            __PRETTY_FUNCTION__,
+                            unixPid, errno, strerror(errno));
+                    fflush(stderr);
+                }
+            }
+            else {
+                /* different pid ??? */
+                fprintf(stderr,
+                        "ERROR(%s): waitpid(%u) returned a different pid %u\n",
+                        __PRETTY_FUNCTION__,
+                        unixPid, res);
+                fflush(stderr);
+            }
+        }
+        
+        if (terminated > 1 || debugNSTask) {
+            fprintf(stderr,
+                    "%s: %i task%s running, %i task%s terminated\n",
+                    __PRETTY_FUNCTION__,
+                    left,       (left==1?"":"s"),
+                    terminated, (terminated==1?"":"s"));
+        }
+        
+        /* post notifications */
+        if (toBeNotified) {
+            NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+            NSEnumerator *e;
+            
+            e = [toBeNotified objectEnumerator];
+            while ((task = [e nextObject])) {
+                /* should we delay posting to the runloop queue ASAP ? */
+                
+                if (task->pid) {
+                    NSMapRemove(unixProcessToTask, (void*)(long)task->pid);
+                    task->pid = 0;
+                }
+                
+                [nc postNotificationName:NSTaskDidTerminateNotification
+                    object:task];
+            }
+        }
+    }
+    else {
+        NSLog(@"ERROR(%s): missing unixProcessToTask ...",
+              __PRETTY_FUNCTION__);
+    }
+#else
+    /* process a single SIGCHLD signal */
+    unixPid = wait(&s);
+    
+    if ((long)unixPid != -1) {
+        /* lookup the task object of the terminated child */
+        if ((task = NSMapGet(unixProcessToTask, (void*)(long)unixPid)) == nil)
+            return;
+        
+        /* if task terminated via _exit(), retrieve and set the exit status */
+        if (WIFEXITED(s))
+            task->status = WEXITSTATUS(s);
+    
+        /* mark task object as terminated */
+        task->isRunning        = NO;
+        task->childHasFinished = YES;
+    
+        /* post notification that task did terminate (new in MacOSX-S) */
+        [[NSNotificationCenter defaultCenter]
+                               postNotificationName:
+                               NSTaskDidTerminateNotification
+                               object:task];
+    }
+#endif
+    [ush enableSignal:SIGCHLD];
+}
+
++ (void)_sigchldImmediate:(int)signum
+{
+    /*
+      Do NOT do anything in this immediate signal handler !!!,
+      just set flags etc ...
+    */
+#if DEBUG && 0
+    /* this is disallowed in sighandlers !!! only for debugging */
+    if (!gotSIGCHLD)
+        printf("SIGCHLD ...\n");
+    else
+        printf("SIGCHLD (was set) ...\n");
+#endif
+    gotSIGCHLD = YES;
+}
++ (void)_childFinished:(int)signum
+{
+    /* 
+       Florian:
+       We don't use self here because it sometimes isn't actually "self" (It's
+       NSFrameInvocation)
+       Seems like there are problems with the UnixSignalHandler code
+       
+       HH:
+       I have no idea how this can ever happen. My guess is that your GCC
+       break-optimizes the code since I _never_ had this issue.
+       
+       Note that signal handlers run with a different stack.
+    */
+#if 1
+    [NSConcreteUnixTask _processExitCodes];
+#else
+    [self _processExitCodes];
+#endif
+}
+
+#endif /* !defined(__MINGW32__) */
+
+- (void)launch
+{
+    if (self->taskPath == nil) {
+       [[[InvalidArgumentException alloc]
+                 initWithReason:@"the task's executable name is not setup!"] raise];
+    }
+
+    if (![[NSFileManager defaultManager]
+                         isExecutableFileAtPath:self->taskPath]){
+       [[[InvalidArgumentException alloc]
+                 initWithReason:@"the task's path is not executable!"] raise];
+    }
+    
+    if (isRunning)
+       return;
+    
+    status = 0;
+
+#if defined(SIGCHLD)
+    [[UnixSignalHandler sharedHandler] blockSignal:SIGCHLD];
+#elif defined(SIGCLD)
+    [[UnixSignalHandler sharedHandler] blockSignal:SIGCLD];
+#endif
+
+#if defined(__MINGW32__)
+#  warning NSTask not supported yet with mingw32
+#else
+
+#ifdef linux
+    self->pid = fork();
+#else
+    self->pid = vfork();
+#endif
+    
+    switch (self->pid) {
+       case -1:        /* error */
+           NSLog(@"Can't launch the child process, vfork() failed: %s!",
+                 strerror (errno));
+           break;
+
+       case 0:
+#if defined(SIGCHLD)
+           [[UnixSignalHandler sharedHandler] enableSignal:SIGCHLD];
+#elif defined(SIGCLD)
+           [[UnixSignalHandler sharedHandler] enableSignal:SIGCLD];
+#endif
+           [self _execChild];
+           break;
+            
+       default:
+           isRunning = YES;
+           NSMapInsert (unixProcessToTask, (void*)(long)pid, self);
+#if defined(SIGCHLD)
+           [[UnixSignalHandler sharedHandler] enableSignal:SIGCHLD];
+#elif defined(SIGCLD)
+           [[UnixSignalHandler sharedHandler] enableSignal:SIGCLD];
+#endif
+            // close handles of pipes
+            if ([self->standardInput isKindOfClass:[NSPipe class]])
+                [[self->standardInput fileHandleForReading] closeFile];
+            else
+                [self->standardInput closeFile];
+            
+            if ([self->standardOutput isKindOfClass:[NSPipe class]])
+                [[self->standardOutput fileHandleForWriting] closeFile];
+            else
+                [self->standardOutput closeFile];
+                
+            if ([self->standardError isKindOfClass:[NSPipe class]])
+                [[self->standardError fileHandleForWriting] closeFile];
+            else
+                [self->standardError closeFile];
+
+           break;
+    }
+    
+    [self _safePoint];
+#endif /* !MINGW32 */
+}
+
+- (void)terminate
+{
+    [self _safePoint];
+    
+    if (self->childHasFinished) {
+       /* -terminate has been already sent and the child finished */
+       return;
+    }
+
+#if 0 // HH: this is wrong, the task could have terminated itself before ...
+    if (!self->isRunning) {
+       [([[InvalidArgumentException alloc]
+                   initWithReason:@"task has not been launched yet!"] raise];
+    }
+#endif
+
+#if !defined(__MINGW32__)
+    /* send SIGTERM to process */
+    if (self->pid)
+       kill(self->pid, SIGTERM);
+
+    [self _safePoint];
+#if 0
+    /*
+      Ovidiu wrote:
+       Post the termination notification. A better idea would be to post this
+       notification after the child has exited, by adding the task object
+       as an observer to UnixSignalHandler in the signal handler function.
+       But we keep here the same semantics with that in documentation.
+
+      Helge says: ;-)
+       That's now the case in MacOSX-S. The notification is posted when the
+       child did exit.
+    */
+    [[NSNotificationCenter defaultCenter]
+       postNotification:
+           [NSNotification notificationWithName:NSTaskDidTerminateNotification
+                           object:self]];
+#endif
+#endif /* !MINGW32 */
+}
+
+- (void)interrupt
+{
+    [self _safePoint];
+    if (self->childHasFinished) {
+       /* -terminate has been already sent and the child finished */
+       return;
+    }
+
+    if (!self->isRunning) {
+       [[[InvalidArgumentException alloc]
+                   initWithReason:@"task has not been launched yet!"] raise];
+    }
+
+#if !defined(__MINGW32__)
+    /* send interrupt signal to process */
+    if (pid)
+       kill(pid, SIGINT);
+    [self _safePoint];
+#endif
+}
+
+- (int)terminationStatus
+{
+    [self _safePoint];
+    if (self->isRunning) {
+       [[[InvalidArgumentException alloc]
+                 initWithReason:@"task is still running!"] raise];
+    }
+    return status;
+}
+
+- (void)waitUntilExit
+{
+    NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
+    
+    [self _safePoint];
+    
+    while (self->isRunning) {
+       NSDate *aDate;
+       CREATE_AUTORELEASE_POOL(pool);
+        {
+            [self _safePoint];
+            aDate = [runLoop limitDateForMode:NSDefaultRunLoopMode];
+            [self _safePoint];
+            [runLoop acceptInputForMode:NSDefaultRunLoopMode beforeDate:aDate];
+            [self _safePoint];
+        }
+       RELEASE(pool);
+    }
+}
+
+/* description */
+
+- (NSString *)description
+{
+    /* Don't use -[NSString stringWithFormat:] method because it can cause
+       infinite recursion. */
+    char buffer[512];
+
+    sprintf(buffer,
+            "<0x%08X<%s> isRunning=%s childHasFinished=%s pid=%d>",
+            (unsigned)self, (char*)object_get_class_name(self),
+            self->isRunning ? "YES" : "NO",
+            self->childHasFinished ? "YES" : "NO",
+            (unsigned)self->pid);
+    return [NSString stringWithCString:buffer];
+}
+
+@end /* NSConcreteUnixTask */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConcreteValue.h b/libFoundation/Foundation/NSConcreteValue.h
new file mode 100644 (file)
index 0000000..f160601
--- /dev/null
@@ -0,0 +1,82 @@
+/* 
+   NSConcreteValue.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSConcreteValue_h__
+#define __NSConcreteValue_h__
+
+#include <Foundation/NSValue.h>
+#include <Foundation/NSGeometry.h>
+
+@interface NSConcreteValue : NSValue
+
++ allocForType:(const char*)type zone:(NSZone*)zone;
+- (id)initValue:(const void*)value withObjCType:(const char*)type;
+
+@end
+
+@interface NSConcreteObjCValue : NSConcreteValue
+{
+    char* objctype;
+    char  data[0];
+}
+@end
+
+@interface NSNonretainedObjectValue : NSConcreteValue
+{
+    id data;
+}
+@end
+
+@interface NSPointerValue : NSConcreteValue
+{
+    void *data;
+}
+@end
+
+@interface NSRectValue : NSConcreteValue
+{
+    NSRect data;
+}
+@end
+
+@interface NSSizeValue : NSConcreteValue
+{
+    NSSize data;
+}
+@end
+
+@interface NSPointValue : NSConcreteValue
+{
+    NSPoint data;
+}
+@end
+
+#endif /* __NSConcreteValue_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConcreteValue.m b/libFoundation/Foundation/NSConcreteValue.m
new file mode 100644 (file)
index 0000000..8a10613
--- /dev/null
@@ -0,0 +1,621 @@
+/* 
+   NSConcreteValue.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSCoder.h>
+#include <Foundation/NSZone.h>
+#include <Foundation/NSGeometry.h>
+#include <Foundation/NSUtilities.h>
+#include <Foundation/exceptions/NSValueExceptions.h>
+
+#include <extensions/objc-runtime.h>
+
+#include "NSConcreteValue.h"
+
+/*
+ * Abstract superclass of concrete value classes
+ */
+
+@implementation NSConcreteValue
+
++ allocForType:(const char*)type zone:(NSZone*)zone
+{
+    int dataSize = objc_sizeof_type(type);
+    id  value = NSAllocateObject([NSConcreteObjCValue class], dataSize, zone);
+
+    return value;
+}
+
+- initValue:(const void*)value withObjCType:(const char*)type
+{
+    [self subclassResponsibility:_cmd];
+    return self;
+}
+
+- (void*)valueBytes
+{
+    [self subclassResponsibility:_cmd];
+    return NULL;
+}
+
+- (id)nonretainedObjectValue
+{
+    [[[NSValueException new]
+           setReason:@"this value does not contain an id type value"] raise];
+    return nil;
+}
+
+- (void*)pointerValue
+{
+    [[[NSValueException new]
+           setReason:@"this value does not contain a void* value"] raise];
+    return NULL;
+}
+
+- (NSRect)rectValue
+{
+    [[[NSValueException new]
+           setReason:@"this value does not contain a NSRect"] raise];
+    return NSMakeRect(0,0,0,0);
+}
+- (NSSize)sizeValue
+{
+    [[[NSValueException new]
+           setReason:@"this value does not contain a NSSize"] raise];
+    return NSMakeSize(0,0);
+}
+- (NSPoint)pointValue
+{
+    [[[NSValueException new]
+           setReason:@"this value does not contain a NSPoint"] raise];
+   return NSMakePoint(0,0);
+}
+
+@end
+
+/*
+ * Any type concrete value class
+ */
+
+@implementation NSConcreteObjCValue
+
+// Allocating and Initializing 
+
+- initValue:(const void*)value withObjCType:(const char*)type
+{
+    int        size;
+    
+    if (!value || !type) 
+       [[[NSValueException new]
+               setReason:@"null value or type"] raise];
+               
+    self = [super init];
+    objctype = Strdup(type);
+    size = objc_sizeof_type(type);
+    memcpy(data, value, size);
+    return self;
+}
+
+- (void)dealloc
+{
+    lfFree(objctype);
+    [super dealloc];
+}
+
+// NSCopying
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    if (NSShouldRetainWithZone(self, zone))
+       return RETAIN(self);
+    else
+       return [[NSConcreteObjCValue allocForType:objctype zone:zone]
+                   initValue:(void*)data withObjCType:objctype];
+}
+
+// Accessing Data 
+
+- (void*)valueBytes
+{
+    return data;
+}
+
+- (void)getValue:(void*)value
+{
+    if (!value)
+       [[[NSValueException new]
+               setReason:@"NULL buffer in -getValue"] raise];
+    else 
+       memcpy(value, data, objc_sizeof_type(objctype));
+}
+
+- (const char*)objCType
+{
+    return objctype;
+}
+- (void*)pointerValue
+{
+    if (*objctype != _C_PTR)
+       [[[NSValueException new]
+               setReason:@"this value does not contain a pointer"] raise];
+    return *((void **)data);
+} 
+
+- (NSRect)rectValue
+{
+    if (Strcmp(objctype, @encode(NSRect)))
+       [[[NSValueException new]
+               setReason:@"this value does not contain a NSRect object"] raise];
+    return *((NSRect*)data);
+}
+- (NSSize)sizeValue
+{
+    if (Strcmp(objctype, @encode(NSSize)))
+       [[[NSValueException new]
+               setReason:@"this value does not contain a NSSize object"] raise];
+    return *((NSSize*)data);
+}
+- (NSPoint)pointValue
+{
+    if (Strcmp(objctype, @encode(NSPoint)))
+       [[[NSValueException new]
+               setReason:@"this value does not contain a NSPoint object"] raise];
+    return *((NSPoint*)data);
+}
+
+- (unsigned)hash
+{
+    return hashjb (objctype, Strlen (objctype));
+}
+
+- (NSString*)description
+{
+    return [NSString stringWithFormat:@"<Value with objc type '%s'>", 
+       [self objCType]];
+}
+
+@end /* NSConcreteObjCValue */
+
+/*
+ * Non retained object concrete value
+ */
+
+@implementation NSNonretainedObjectValue
+
+// Allocating and Initializing 
+
+- (id)initValue:(const void *)value withObjCType:(const char *)type
+{
+    data = *(id*)value;
+    return self;
+}
+
+- (BOOL)isEqual:(NSValue*)aValue
+{
+    return Strcmp([self objCType], [aValue objCType]) == 0
+           && [[self nonretainedObjectValue]
+                   isEqual:[aValue nonretainedObjectValue]];
+}
+
+// NSCopying
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    if (NSShouldRetainWithZone(self, zone))
+       return RETAIN(self);
+    else
+       return [[NSNonretainedObjectValue alloc]
+               initValue:(void*)&data withObjCType:NULL];
+}
+
+// Accessing Data 
+
+- (void*)valueBytes
+{
+    return &data;
+}
+
+- (void)getValue:(void*)value
+{
+    if (!value)
+       [[[NSValueException new]
+               setReason:@"NULL buffer in -getValue"] raise];
+    else 
+       *(id*)value = data;
+}
+
+- (const char*)objCType
+{
+    return @encode(id);
+}
+-(id)nonretainedObjectValue;
+{
+    return data;
+} 
+
+- (unsigned)hash
+{
+    return (unsigned long)data;
+}
+
+- (NSString*)description
+{
+    return [NSString stringWithFormat:@"<Value with object %@>", data];
+}
+
+/* NSCoding */
+
+- (Class)classForCoder
+{
+    return isa;
+}
+
+- (void)encodeWithCoder:(NSCoder*)coder
+{
+    [coder encodeValueOfObjCType:@encode(id) at:&data];
+}
+
+- (id)initWithCoder:(NSCoder*)coder
+{
+    [coder decodeValueOfObjCType:@encode(id) at:&data];
+    return self;
+}
+
+@end /* NSNonretainedObjectValue */
+
+/*
+ * Void Pointer concrete value
+ */
+
+@implementation NSPointerValue
+
+// Allocating and Initializing 
+
+- initValue:(const void*)value withObjCType:(const char*)type
+{
+    data = *(void**)value;
+    return self;
+}
+
+// NSCopying
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    if (NSShouldRetainWithZone(self, zone))
+       return RETAIN(self);
+    else
+       return [[NSNonretainedObjectValue alloc]
+                   initValue:(void*)&data withObjCType:NULL];
+}
+
+// Accessing Data 
+
+- (void*)valueBytes
+{
+    return &data;
+}
+
+- (void)getValue:(void*)value
+{
+    if (!value)
+       [[[NSValueException new]
+               setReason:@"NULL buffer in -getValue"] raise];
+    else 
+           *(void**)value = data;
+}
+
+- (const char*)objCType
+{
+    return @encode(void*);
+}
+- (void*)pointerValue;
+{
+    return data;
+} 
+
+- (unsigned)hash
+{
+    return (unsigned long)data;
+}
+
+- (NSString*)description
+{
+    return [NSString stringWithFormat:@"<Value with pointer 0x%08x>", data];
+}
+
+@end /* NSPointerValue */
+
+/*
+ * NSRect concrete value
+ */
+
+@implementation NSRectValue
+
+// Allocating and Initializing 
+
+- initValue:(const void*)value withObjCType:(const char*)type
+{
+    data = *(NSRect*)value;
+    return self;
+}
+
+// NSCopying
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    if (NSShouldRetainWithZone(self, zone))
+       return RETAIN(self);
+    else
+       return [[NSRectValue alloc]
+               initValue:(void*)&data withObjCType:NULL];
+}
+
+// Accessing Data 
+
+- (void*)valueBytes
+{
+    return &data;
+}
+
+- (void)getValue:(void*)value
+{
+    if (!value)
+       [[[NSValueException new]
+               setReason:@"NULL buffer in -getValue"] raise];
+    else 
+       *(NSRect*)value = data;
+}
+
+- (const char*)objCType
+{
+    return @encode(NSRect);
+}
+- (NSRect)rectValue;
+{
+    return data;
+} 
+
+- (unsigned)hash
+{
+    return (unsigned)(data.origin.x + data.origin.y
+           + data.size.width + data.size.height);
+}
+
+- (NSString*)description
+{
+    return [NSString stringWithFormat:@"<Value with rect %@>",
+       NSStringFromRect(data)];
+}
+
+/* NSCoding */
+
+- (Class)classForCoder
+{
+    return isa;
+}
+
+- (void)encodeWithCoder:(NSCoder*)coder
+{
+    [coder encodeValueOfObjCType:@encode(NSRect) at:&data];
+}
+
+- (id)initWithCoder:(NSCoder*)coder
+{
+    [coder decodeValueOfObjCType:@encode(NSRect) at:&data];
+    return self;
+}
+
+@end /* NSRectValue */
+
+/*
+ * NSSize concrete value
+ */
+
+@implementation NSSizeValue
+
+// Allocating and Initializing 
+
+- initValue:(const void*)value withObjCType:(const char*)type
+{
+    data = *(NSSize*)value;
+    return self;
+}
+
+// NSCopying
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    if (NSShouldRetainWithZone(self, zone))
+       return RETAIN(self);
+    else
+       return [[NSSizeValue alloc]
+                   initValue:(void*)&data withObjCType:NULL];
+}
+
+// Accessing Data 
+
+- (void*)valueBytes
+{
+    return &data;
+}
+
+- (void)getValue:(void*)value
+{
+    if (!value)
+       [[[NSValueException new]
+               setReason:@"NULL buffer in -getValue"] raise];
+    else 
+       *(NSSize*)value = data;
+}
+
+- (const char*)objCType
+{
+    return @encode(NSSize);
+}
+- (NSPoint)pointValue;
+{
+    return NSMakePoint(data.width, data.height);
+} 
+
+- (NSSize)sizeValue;
+{
+    return data;
+} 
+
+- (unsigned)hash
+{
+    return (unsigned)(data.width + data.height);
+}
+
+- (NSString*)description
+{
+    return [NSString stringWithFormat:@"<Value with size %@>",
+       NSStringFromSize(data)];
+}
+
+/* NSCoding */
+
+- (Class)classForCoder
+{
+    return isa;
+}
+
+- (void)encodeWithCoder:(NSCoder*)coder
+{
+    [coder encodeValueOfObjCType:@encode(NSSize) at:&data];
+}
+
+- (id)initWithCoder:(NSCoder*)coder
+{
+    [coder decodeValueOfObjCType:@encode(NSSize) at:&data];
+    return self;
+}
+
+@end /* NSSizeValue */
+
+/*
+ * NSPoint concrete value
+ */
+
+@implementation NSPointValue
+
+// Allocating and Initializing 
+
+- initValue:(const void*)value withObjCType:(const char*)type
+{
+    data = *(NSPoint*)value;
+    return self;
+}
+
+// NSCopying
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    if (NSShouldRetainWithZone(self, zone))
+       return RETAIN(self);
+    else
+       return [[NSPointValue alloc]
+                   initValue:(void*)&data withObjCType:NULL];
+}
+
+// Accessing Data 
+
+- (void*)valueBytes
+{
+    return &data;
+}
+
+- (void)getValue:(void*)value
+{
+    if (!value)
+       [[[NSValueException new]
+               setReason:@"NULL buffer in -getValue"] raise];
+    else 
+       *(NSPoint*)value = data;
+}
+
+- (const char*)objCType
+{
+    return @encode(NSPoint);
+}
+- (NSPoint)pointValue;
+{
+    return data;
+} 
+
+- (NSSize)sizeValue;
+{
+    return NSMakeSize(data.x, data.y);
+} 
+
+- (unsigned)hash
+{
+    return (unsigned)(data.x + data.y);
+}
+
+- (NSString*)description
+{
+    return [NSString stringWithFormat:@"<Value with point %@>",
+       NSStringFromPoint(data)];
+}
+
+/* NSCoding */
+
+- (Class)classForCoder
+{
+    return isa;
+}
+
+- (void)encodeWithCoder:(NSCoder*)coder
+{
+    [coder encodeValueOfObjCType:@encode(NSPoint) at:&data];
+}
+
+- (id)initWithCoder:(NSCoder*)coder
+{
+    [coder decodeValueOfObjCType:@encode(NSPoint) at:&data];
+    return self;
+}
+
+@end /* NSPointValue */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSConcreteWindowsFileHandle.h b/libFoundation/Foundation/NSConcreteWindowsFileHandle.h
new file mode 100644 (file)
index 0000000..68d0dc9
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+   NSConcreteFileHandle.h
+
+   Copyright (C) 2000 Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+   Date: Feb 2000
+   
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+#ifndef __NSConcreteWindowsFileHandle_h__
+#define __NSConcreteWindowsFileHandle_h__
+
+#include <Foundation/NSFileHandle.h>
+#include <config.h>
+
+#ifdef HAVE_WINDOWS_H
+#  include <windows.h>
+#endif
+
+@interface NSConcreteWindowsFileHandle : NSFileHandle
+{
+    HANDLE handle;
+    BOOL   closeOnDealloc;
+}
+
+@end
+
+#endif /* __NSConcreteWindowsFileHandle_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConcreteWindowsFileHandle.m b/libFoundation/Foundation/NSConcreteWindowsFileHandle.m
new file mode 100644 (file)
index 0000000..fc15078
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+   NSConcreteFileHandle.m
+
+   Copyright (C) 2000 Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+   Date: Feb 2000
+   
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <config.h>
+#include <Foundation/common.h>
+
+#include "NSConcreteWindowsFileHandle.h"
+#include <Foundation/NSPathUtilities.h>
+#include <Foundation/NSException.h>
+#include "exceptions/NSFileHandleExceptions.h"
+#include <Foundation/NSString.h>
+#include <Foundation/NSData.h>
+
+#ifdef HAVE_WINDOWS_H
+#  include <windows.h>
+#endif
+
+@implementation NSConcreteWindowsFileHandle
+
++ (id)fileHandleForReadingAtPath:(NSString *)path
+{
+    HANDLE fh;
+
+    fh = CreateFile([path fileSystemRepresentation],
+                   GENERIC_READ,
+                   FILE_SHARE_READ,
+                   NULL /* no security */,
+                   OPEN_EXISTING,
+                   FILE_ATTRIBUTE_NORMAL,
+                   NULL /* no attr template */);
+    if (fh == INVALID_HANDLE_VALUE)
+       return nil;
+    
+    return
+       AUTORELEASE([[self alloc] initWithNativeHandle:fh closeOnDealloc:YES]);
+}
++ (id)fileHandleForWritingAtPath:(NSString *)path
+{
+    HANDLE fh;
+
+    fh = CreateFile([path fileSystemRepresentation],
+                   GENERIC_WRITE,
+                   0 /* do not share */,
+                   NULL /* no security */,
+                   CREATE_ALWAYS,
+                   FILE_ATTRIBUTE_NORMAL,
+                   NULL /* no attr template */);
+    if (fh == INVALID_HANDLE_VALUE)
+       return nil;
+    
+    return
+       AUTORELEASE([[self alloc] initWithNativeHandle:fh closeOnDealloc:YES]);
+}
++ (id)fileHandleForUpdatingAtPath:(NSString *)path
+{
+    HANDLE fh;
+
+    fh = CreateFile([path fileSystemRepresentation],
+                   GENERIC_WRITE,
+                   0    /* do not share */,
+                   NULL /* no security */,
+                   OPEN_ALWAYS,
+                   FILE_ATTRIBUTE_NORMAL,
+                   NULL /* no attr template */);
+    if (fh == INVALID_HANDLE_VALUE)
+       return nil;
+    
+    return
+       AUTORELEASE([[self alloc] initWithNativeHandle:fh closeOnDealloc:YES]);
+}
+
+- (id)initWithNativeHandle:(void *)_handle closeOnDealloc:(BOOL)_flag
+{
+    self->handle         = _handle;
+    self->closeOnDealloc = _flag;
+    return self;
+}
+
+- (id)initWithNativeHandle:(void *)_handle
+{
+    return [self initWithNativeHandle:_handle closeOnDealloc:NO];
+}
+
+- (void)dealloc
+{
+    if ((self->handle != NULL) && (self->closeOnDealloc))
+       CloseHandle(self->handle);
+    [super dealloc];
+}
+
+/* Reading from an NSFileHandle */
+
+- (NSData *)availableData
+{
+    /* should be improved for sockets .. */
+    return [self readDataToEndOfFile];
+}
+- (NSData *)readDataToEndOfFile
+{
+    return [self readDataOfLength:UINT_MAX];
+}
+
+- (NSData *)readDataOfLength:(unsigned int)length
+{
+    LPVOID buf, ptr;
+    DWORD  readCount;
+
+    if (self->handle == NULL ) {
+       THROW([[NSFileHandleOperationException alloc]
+                   initWithFileHandle:self
+                   operation:@"Try to write in a closed file handle!"]);
+    }
+    
+    if (length == 0) return [NSData data];
+    
+    ptr = buf = NSZoneMallocAtomic(NULL, length);
+    readCount = 0;
+    while (readCount < length) {
+       DWORD readBytes;
+       
+       if (ReadFile(self->handle, ptr,
+                    (length - readCount), &readBytes,
+                    NULL)) {
+           readCount += readBytes;
+           ptr       += readBytes;
+       }
+       else {
+           DWORD err = GetLastError();
+
+           if (err == ERROR_HANDLE_EOF)
+               break;
+           
+           [NSFileHandleOperationException raise:@"ReadException"
+                        format:@"could not write data: %i", err];
+       }
+    }
+    return [NSData dataWithBytesNoCopy:buf length:readCount];
+}
+
+/* Writing to an NSFileHandle */
+
+- (void)writeData:(NSData *)data
+{
+    LPCVOID buf;
+    DWORD   count;
+    DWORD   written;
+
+    if (self->handle == NULL ) {
+       THROW([[NSFileHandleOperationException alloc]
+                   initWithFileHandle:self
+                   operation:@"Try to write in a closed file handle!"]);
+    }
+    
+    buf   = [data bytes];
+    count = [data length];
+    
+    while (count > 0) {
+       if (WriteFile(self->handle, buf, count, &written, NULL)) {
+           count -= written;
+           buf   += written;
+       }
+       else {
+           DWORD err = GetLastError();
+           [NSFileHandleOperationException raise:@"WriteException"
+                        format:@"could not write data: %i", err];
+       }
+    }
+}
+
+@end /* NSConcreteWindowsFileHandle */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConcreteWindowsTask.h b/libFoundation/Foundation/NSConcreteWindowsTask.h
new file mode 100644 (file)
index 0000000..804bbc0
--- /dev/null
@@ -0,0 +1,51 @@
+/* 
+   NSConcreteWindowsTask.h
+   
+   Copyright (C) 1999 Helge Hess and MDlink online service center GmbH
+   All rights reserved.
+   
+   Author: Helge Hess <helge.hess@mdlink.de>
+   
+   This file is part of libFoundation.
+   
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+   
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSConcreteWindowsTask_H__
+#define __NSConcreteWindowsTask_H__
+
+#include <Foundation/NSTask.h>
+
+#include <config.h>
+
+#if defined(HAVE_WINDOWS_H)
+#  include <windows.h>
+
+@interface NSConcreteWindowsTask : NSTask
+{
+  PROCESS_INFORMATION pi;
+  NSString     *taskPath;
+  NSString     *currentDirectory;
+  NSArray      *taskArguments;
+  NSDictionary *taskEnvironment;
+  id           standardInput;  // either NSPipe or NSFileHandle
+  id           standardOutput; // either NSPipe or NSFileHandle
+  id           standardError;  // either NSPipe or NSFileHandle
+}
+
+@end
+
+#endif /* HAVE_WINDOWS_H */
+
+#endif /* __NSConcreteWindowsTask_H__ */
diff --git a/libFoundation/Foundation/NSConcreteWindowsTask.m b/libFoundation/Foundation/NSConcreteWindowsTask.m
new file mode 100644 (file)
index 0000000..efad023
--- /dev/null
@@ -0,0 +1,220 @@
+/* 
+   NSConcreteWindowsTask.m
+   
+   Copyright (C) 1999 Helge Hess and MDlink online service center GmbH
+   All rights reserved.
+   
+   Author: Helge Hess <helge.hess@mdlink.de>
+   
+   This file is part of libFoundation.
+   
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+   
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include "NSConcreteWindowsTask.h"
+#include <Foundation/NSArray.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSPathUtilities.h>
+
+#if defined(HAVE_WINDOWS_H)
+#  include <windows.h>
+
+@implementation NSConcreteWindowsTask
+
+- (id)init
+{
+  ZeroMemory(&self->pi, sizeof(self->pi));
+  return self;
+}
+
+- (void)gcFinalize
+{
+  if (self->pi.hProcess != NULL)
+    CloseHandle(self->pi.hProcess);
+  if (self->pi.hThread != NULL)
+    CloseHandle(self->pi.hThread);
+}
+- (void)dealloc
+{
+  [self gcFinalize];
+  RELEASE(self->taskPath);
+  RELEASE(self->currentDirectory);
+  RELEASE(self->taskArguments);
+  RELEASE(self->taskEnvironment);
+  RELEASE(self->standardInput);
+  RELEASE(self->standardOutput);
+  RELEASE(self->standardError);
+  [super dealloc];
+}
+
+/* plain accessors (should catch exceptions) */
+
+- (void)setLaunchPath:(NSString *)path
+{
+    ASSIGN(self->taskPath, path);
+}
+- (NSString *)launchPath
+{
+    return self->taskPath;
+}
+
+- (void)setArguments:(NSArray *)arguments
+{
+    ASSIGN(self->taskArguments, arguments);
+}
+- (NSArray *)arguments
+{
+    return self->taskArguments;
+}
+
+- (void)setEnvironment:(NSDictionary *)dict
+{
+    ASSIGN(self->taskEnvironment, dict);
+}
+- (NSDictionary *)environment
+{
+    return self->taskEnvironment;
+}
+
+- (void)setCurrentDirectoryPath:(NSString *)path
+{
+    ASSIGN(self->currentDirectory, path);
+}
+- (NSString *)currentDirectoryPath
+{
+    return self->currentDirectory;
+}
+
+- (void)setStandardInput:(id)input
+{
+    ASSIGN(self->standardInput, input);
+}
+- (id)standardInput
+{
+    return self->standardInput;
+}
+
+- (void)setStandardOutput:(id)output
+{
+    ASSIGN(self->standardOutput, output);
+}
+- (id)standardOutput
+{
+    return self->standardOutput;
+}
+
+- (void)setStandardError:(id)error
+{
+    ASSIGN(self->standardError, error);
+}
+- (id)standardError
+{
+    return self->standardError;
+}
+
+/* Win32 specific info */
+
+- (HANDLE)processHandle
+{
+  return self->pi.hProcess;
+}
+- (HANDLE)threadHandle
+{
+  return self->pi.hThread;
+}
+
+/* implementation */
+
+- (void)terminate
+{
+  BOOL ok;
+
+  ok = TerminateProcess([self processHandle], 10);
+}
+- (int)terminationStatus
+{
+  DWORD exitCode;
+  BOOL  ok;
+  
+  ok = GetExitCodeProcess([self processHandle], &exitCode);
+  if (ok)
+    return exitCode;
+  else {
+    NSLog(@"Couldn't get exit code of process !");
+    return -1;
+  }
+}
+
+- (void)waitUntilExit
+{
+  DWORD result;
+  
+  switch (result = WaitForSingleObject([self processHandle], INFINITE)) {
+  case WAIT_ABANDONED:
+  case WAIT_OBJECT_0:
+  case WAIT_TIMEOUT:
+    break;
+  }
+}
+- (unsigned int)processId
+{
+  return (unsigned int)self->pi.dwProcessId;
+}
+
+- (void)launch
+{
+  BOOL ok;
+  STARTUPINFO startUpInfo;
+  NSMutableString *cmdline;
+  NSEnumerator    *e;
+  NSString        *tmp;
+  char            *ccmdline;
+
+  cmdline = [[self launchPath] mutableCopy];
+  e = [[self arguments] objectEnumerator];
+  while ((tmp = [e nextObject])) {
+    [cmdline appendString:@" "];
+    [cmdline appendString:tmp]; /* should quote tmp first ! */
+  }
+  ccmdline = objc_malloc([cmdline cStringLength] + 1);
+  [cmdline getCString:ccmdline];
+  RELEASE(cmdline); cmdline = NULL;
+
+  ZeroMemory(&startUpInfo, sizeof(startUpInfo));
+  startUpInfo.cb = sizeof(startUpInfo);
+  startUpInfo.dwFlags |= STARTF_USESTDHANDLES;
+  startUpInfo.hStdInput  = GetStdHandle(STD_INPUT_HANDLE);
+  startUpInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
+  startUpInfo.hStdError  = GetStdHandle(STD_ERROR_HANDLE);
+  
+  ok = CreateProcess([[self launchPath] cString], ccmdline,
+                    NULL      /* proc attrs */,
+                    NULL      /* thread attrs */,
+                    1         /* inherit handles */,
+                    0         /* creation flags */,
+                    NULL      /* env block */,
+                    [[self currentDirectoryPath] cString],
+                    &startUpInfo,
+                    &(self->pi));
+  objc_free(ccmdline);
+  if (!ok) {
+    NSLog(@"Couldn't launch task: %@ !", [self launchPath]);
+    return;
+  }
+}
+
+@end /* NSConcreteWindowsTask */
+
+#endif /* HAVE_WINDOWS_H */
diff --git a/libFoundation/Foundation/NSConnection.h b/libFoundation/Foundation/NSConnection.h
new file mode 100644 (file)
index 0000000..ce37481
--- /dev/null
@@ -0,0 +1,57 @@
+/* 
+   NSConnection.h
+
+   Copyright (C) 2000 MDlink GmbH, Helge Hess.
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSConnection_H__
+#define __NSConnection_H__
+
+#include <Foundation/NSObject.h>
+
+@class NSString, NSPortNameServer, NSDistantObject;
+
+LF_EXPORT NSString *NSConnectionDidDieNotification;
+LF_EXPORT NSString *NSFailedAuthenticationException;
+
+@interface NSConnection : NSObject
+
+- (void)setRootObject:(id)_object;
+- (id)rootObject;
+
+- (BOOL)registerName:(NSString *)_name;
+- (BOOL)registerName:(NSString *)_name withNameServer:(NSPortNameServer *)_ns;
++ (NSDistantObject *)rootProxyForConnectionWithRegisteredName:(NSString *)_name
+  host:(NSString *)_hostName
+  usingNameServer:(NSPortNameServer *)_ns;
++ (NSDistantObject *)rootProxyForConnectionWithRegisteredName:(NSString *)_name
+  host:(NSString *)_hostName;
+
+@end
+
+#endif /* __NSConnection_H__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSConnection.m b/libFoundation/Foundation/NSConnection.m
new file mode 100644 (file)
index 0000000..0f78205
--- /dev/null
@@ -0,0 +1,80 @@
+/* 
+   NSConnection.m
+
+   Copyright (C) 2000 MDlink GmbH, Helge Hess.
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSConnection.h>
+#include <Foundation/NSPortNameServer.h>
+#include <Foundation/NSString.h>
+#include <common.h>
+
+LF_DECLARE NSString *NSConnectionDidDieNotification  = @"NSConnectionDidDieNotificationName";
+LF_DECLARE NSString *NSFailedAuthenticationException = @"NSFailedAuthenticationExceptionName";
+
+@implementation NSConnection
+
+/* name service */
+
+- (BOOL)registerName:(NSString *)_name
+{
+    return [self registerName:_name
+                 withNameServer:[NSPortNameServer defaultPortNameServer]];
+}
+- (BOOL)registerName:(NSString *)_name withNameServer:(NSPortNameServer *)_ns
+{
+    [self notImplemented:_cmd];
+    return NO;
+}
+
++ (NSDistantObject *)rootProxyForConnectionWithRegisteredName:(NSString *)_name
+  host:(NSString *)_hostName
+  usingNameServer:(NSPortNameServer *)_ns
+{
+    return [self notImplemented:_cmd];
+}
++ (NSDistantObject *)rootProxyForConnectionWithRegisteredName:(NSString *)_name
+  host:(NSString *)_hostName
+{
+    return [self rootProxyForConnectionWithRegisteredName:_name
+                 host:_hostName
+                 usingNameServer:[NSPortNameServer defaultPortNameServer]];
+}
+
+/* object management */
+
+- (void)setRootObject:(id)_object
+{
+    [self notImplemented:_cmd];
+}
+- (id)rootObject
+{
+    return [self notImplemented:_cmd];
+}
+
+@end /* NSConnection */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSData.h b/libFoundation/Foundation/NSData.h
new file mode 100644 (file)
index 0000000..385caed
--- /dev/null
@@ -0,0 +1,148 @@
+/* 
+   NSData.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSData_h__
+#define __NSData_h__
+
+#include <Foundation/NSObject.h>
+#include <Foundation/NSRange.h>
+#include <Foundation/NSSerialization.h>
+
+@class NSZone;
+@class NSURL;
+@class NSString;
+
+@interface NSData : NSObject <NSCoding, NSCopying, NSMutableCopying>
+
+/* Allocating and Initializing an NSData Object */
++ (id)allocWithZone:(NSZone*)zone;
++ (id)data;
++ (id)dataWithBytes:(const void*)bytes
+  length:(unsigned int)length;
++ (id)dataWithBytesNoCopy:(void*)bytes
+  length:(unsigned int)length;
++ (id)dataWithContentsOfFile:(NSString *)path;
++ (id)dataWithContentsOfURL:(NSURL *)_url;
++ (id)dataWithContentsOfMappedFile:(NSString *)path;
++ (id)dataWithData:(NSData *)aData;
+- (id)initWithBytes:(const void*)bytes
+  length:(unsigned int)length;
+- (id)initWithBytesNoCopy:(void*)bytes
+  length:(unsigned int)length;
+- (id)initWithContentsOfFile:(NSString *)path;
+- (id)initWithContentsOfURL:(NSURL *)_url;
+- (id)initWithContentsOfMappedFile:(NSString *)path;
+- (id)initWithData:(NSData *)data;
+
+- (id)initWithBytesNoCopy:(void *)_bytes length:(unsigned)_length 
+  freeWhenDone:(BOOL)_freeMemory;
+
+/* Accessing Data */
+- (const void*)bytes;
+- (NSString *)description;
+- (void)getBytes:(void *)buffer;
+- (void)getBytes:(void *)buffer
+       length:(unsigned int)length;
+- (void)getBytes:(void *)buffer
+       range:(NSRange)aRange;
+- (NSData *)subdataWithRange:(NSRange)aRange;
+
+/* Querying a Data Object */
+- (BOOL)isEqualToData:(NSData*)other;
+- (unsigned int)length;
+
+/* Storing Data */
+- (BOOL)writeToFile:(NSString*)path
+       atomically:(BOOL)useAuxiliaryFile;
+
+/* Deserializing Data */
+- (unsigned int)deserializeAlignedBytesLengthAtCursor:(unsigned int*)cursor;
+- (void)deserializeBytes:(void*)buffer
+       length:(unsigned int)bytes
+       atCursor:(unsigned int*)cursor;
+- (void)deserializeDataAt:(void*)data
+       ofObjCType:(const char*)type
+       atCursor:(unsigned int*)cursor
+       context:(id <NSObjCTypeSerializationCallBack>)callback;
+- (int)deserializeIntAtCursor:(unsigned int*)cursor;
+- (int)deserializeIntAtIndex:(unsigned int)index;
+- (void)deserializeInts:(int*)intBuffer
+       count:(unsigned int)numInts
+       atCursor:(unsigned int*)cursor;
+- (void)deserializeInts:(int*)intBuffer
+       count:(unsigned int)numInts
+       atIndex:(unsigned int)index;
+
+@end /* NSData */
+
+
+@interface NSMutableData : NSData
+
+/* Creating an NSMutableData Object */
++ (id)allocWithZone:(NSZone*)zone;
++ (id)dataWithCapacity:(unsigned int)numBytes;
++ (id)dataWithLength:(unsigned int)length;
+- (id)initWithCapacity:(unsigned int)capacity;
+- (id)initWithLength:(unsigned int)length;
+
+/* Adjusting Capacity */
+- (void)increaseLengthBy:(unsigned int)extraLength;
+- (void*)mutableBytes;
+- (void)setLength:(unsigned int)length;
+
+/* Appending Data */
+- (void)appendBytes:(const void*)bytes
+       length:(unsigned int)length;
+- (void)appendData:(NSData*)other;
+
+/* Modifying Data */
+- (void)replaceBytesInRange:(NSRange)aRange
+       withBytes:(const void*)bytes;
+- (void)resetBytesInRange:(NSRange)aRange;
+- (void)setData:(NSData*)aData;
+
+/* Serializing Data */
+- (void)serializeAlignedBytesLength:(unsigned int)length;
+- (void)serializeDataAt:(const void*)data
+       ofObjCType:(const char*)type
+       context:(id <NSObjCTypeSerializationCallBack>)callback;
+- (void)serializeInt:(int)value;
+- (void)serializeInt:(int)value
+       atIndex:(unsigned int)index;
+- (void)serializeInts:(int*)intBuffer
+       count:(unsigned int)numInts;
+- (void)serializeInts:(int*)intBuffer
+       count:(unsigned int)numInts
+       atIndex:(unsigned int)index;
+
+@end /* NSMutableData */
+
+#endif /* __NSData_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSData.m b/libFoundation/Foundation/NSData.m
new file mode 100644 (file)
index 0000000..caa7920
--- /dev/null
@@ -0,0 +1,755 @@
+/* 
+   NSData.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSData.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSPosixFileDescriptor.h>
+#include <Foundation/NSCoder.h>
+#include <Foundation/NSURL.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+
+#include <extensions/objc-runtime.h>
+
+#include "byte_order.h"
+#include "NSConcreteData.h"
+#include <Foundation/NSUtilities.h>
+
+@implementation NSData
+
++ (id)allocWithZone:(NSZone*)zone
+{
+    return NSAllocateObject(((self == [NSData class]) ? 
+           [NSConcreteData class] : self), 0, zone);
+}
+
++ (id)data
+{
+    return AUTORELEASE([[self allocWithZone:NSDefaultMallocZone()]
+                           initWithBytes:NULL length:0]);
+}
+
++ (id)dataWithBytes:(const void*)bytes
+    length:(unsigned int)length
+{
+    return AUTORELEASE([[self allocWithZone:NSDefaultMallocZone()]
+                           initWithBytes:bytes length:length]);
+}
+
++ (id)dataWithBytesNoCopy:(void*)bytes
+    length:(unsigned int)length
+{
+    return AUTORELEASE([[self allocWithZone:NSDefaultMallocZone()]
+                           initWithBytesNoCopy:bytes 
+                           length:length]);
+}
+
++ (id)dataWithContentsOfFile:(NSString*)path
+{
+    return AUTORELEASE([[self allocWithZone:NSDefaultMallocZone()]
+                           initWithContentsOfFile:path]);
+}
++ (id)dataWithContentsOfURL:(NSURL *)_url
+{
+    return AUTORELEASE([[self allocWithZone:NSDefaultMallocZone()]
+                           initWithContentsOfURL:_url]);
+}
+
++ (id)dataWithContentsOfMappedFile:(NSString*)path
+{
+    NSPosixFileDescriptor* descriptor;
+    NSRange range = {0, 0};
+    
+    descriptor = AUTORELEASE([[NSPosixFileDescriptor alloc]
+                                 initWithPath:path]);
+    range.length = [descriptor fileLength];    
+
+    return [descriptor mapFileRange:range];
+}
+
++ (id)dataWithData:(NSData *)aData
+{
+    return AUTORELEASE([[self alloc] initWithData:aData]);
+}
+
+- (id)initWithBytes:(const void*)bytes
+    length:(unsigned int)length
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+- (id)initWithBytesNoCopy:(void*)bytes
+    length:(unsigned int)length
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+- (id)initWithContentsOfFile:(NSString*)_path
+{
+    char     *bytes = NULL;
+    unsigned len;
+
+    if ((bytes = NSReadContentsOfFile(_path, 0, &len))) {
+        return [self initWithBytesNoCopy:bytes length:len];
+    }
+    else {
+        self = AUTORELEASE(self);
+        return nil;
+    }
+}
+- (id)initWithContentsOfURL:(NSURL *)_url
+{
+    if ([_url isFileURL])
+        return [self initWithContentsOfFile:[_url path]];
+    
+    return [self initWithData:[_url resourceDataUsingCache:NO]];
+}
+
+- (id)initWithContentsOfMappedFile:(NSString*)path
+{
+#if defined(__MINGW32__)
+    return [self initWithContentsOfFile:path];
+#else
+    NSPosixFileDescriptor* descriptor;
+    NSRange range = {0, 0};
+    
+    descriptor = AUTORELEASE([[NSPosixFileDescriptor alloc]
+                                 initWithPath:path]);
+    range.length = [descriptor fileLength];    
+
+    RELEASE(self); self = nil;
+    self = [descriptor mapFileRange:range];
+    return RETAIN(self);
+#endif
+}
+
+- (id)initWithData:(NSData *)data
+{
+    return [self initWithBytes:[data bytes] length:[data length]];
+}
+
+- (id)initWithBytesNoCopy:(void *)_bytes length:(unsigned)_length 
+  freeWhenDone:(BOOL)_freeMemory
+{
+    // new in OSX 10.2
+    // TODO: inefficient for freemem==NO case
+    return (_freeMemory)
+        ? [self initWithBytesNoCopy:_bytes length:_length]
+        : [self initWithBytes:_bytes length:_length];
+}
+
+/* copying */
+
+- (id)copy
+{
+    return [self copyWithZone:NSDefaultMallocZone()];
+}
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    return [[NSData allocWithZone:zone] initWithData:self];
+}
+
+- (id)mutableCopy
+{
+    return [self mutableCopyWithZone:NSDefaultMallocZone()];
+}
+
+- (id)mutableCopyWithZone:(NSZone*)zone
+{
+    return [[NSMutableData allocWithZone:zone] initWithData:self];
+}
+
+- (const void*)bytes
+{
+    [self subclassResponsibility:_cmd];
+    return NULL;
+}
+
+- (NSString*)description
+{
+    unsigned     i;
+    unsigned int length       = [self length];
+    const char   *bytes       = [self bytes];
+    unsigned int final_length = 4 + 2 * length + 1 + length / 4;
+    char         *description = MallocAtomic(final_length);
+    char         *temp        = description + 1;
+
+    description[0] = 0;
+    Strcat(description, "<");
+    for(i = 0; i < length; i++, temp += 2) {
+       if (i % 4 == 0)
+           *temp++ = ' ';
+       sprintf (temp, "%02X", (unsigned char)((char*)bytes)[i]);
+    }
+    strcat(temp, " >");
+    *(temp += 2) = 0;
+    return [NSString stringWithCStringNoCopy:description freeWhenDone:YES];
+}
+
+- (void)getBytes:(void*)buffer
+{
+    memcpy(buffer, [self bytes], [self length]);
+}
+
+- (void)getBytes:(void*)buffer
+  length:(unsigned int)_length
+{
+    if(_length > [self length])
+       [[RangeException new] raise];
+    else memcpy(buffer, [self bytes], _length);
+}
+
+- (void)getBytes:(void*)buffer
+  range:(NSRange)aRange
+{
+    unsigned int length = [self length];
+
+    if(aRange.location > length
+           || aRange.length > length
+           || aRange.location + aRange.length > length)
+       [[RangeException new] raise];
+    else
+        memcpy(buffer, [self bytes] + aRange.location, aRange.length);
+}
+
+- (NSData *)subdataWithRange:(NSRange)aRange
+{
+    return AUTORELEASE([[NSConcreteDataRange
+                            allocWithZone:[self zone]]
+                           initWithData:self range:aRange]);
+}
+
+- (unsigned)hash
+{
+    return hashjb([self bytes], [self length]);
+}
+
+- (BOOL)isEqualToData:(NSData*)other
+{
+    if([self length] == [other length])
+       return memcmp([self bytes], [other bytes], [self length]) == 0;
+    else return NO;
+}
+
+- (BOOL)isEqual:(id)anObject
+{
+    if([anObject isKindOfClass:[NSData class]])
+       return [self isEqualToData:anObject];
+    else return NO;
+}
+
+- (unsigned int)length
+{
+    [self subclassResponsibility:_cmd];
+    return 0;
+}
+
+- (BOOL)writeToFile:(NSString*)path
+  atomically:(BOOL)useAuxiliaryFile
+{
+    return writeToFile(path, self, useAuxiliaryFile);
+}
+
+- (unsigned int)deserializeAlignedBytesLengthAtCursor:(unsigned int*)cursor
+{
+    return *cursor;
+}
+
+- (void)deserializeBytes:(void*)buffer
+  length:(unsigned int)bytes
+  atCursor:(unsigned int*)cursor
+{
+    NSRange range = { *cursor, bytes };
+    [self getBytes:buffer range:range];
+    *cursor += bytes;
+}
+
+- (void)deserializeDataAt:(void*)data
+  ofObjCType:(const char*)type
+  atCursor:(unsigned int*)cursor
+  context:(id <NSObjCTypeSerializationCallBack>)callback
+{
+    if(!type || !data)
+       return;
+
+    switch(*type) {
+       case _C_ID: {
+           [callback deserializeObjectAt:data ofObjCType:type
+                   fromData:self atCursor:cursor];
+           break;
+       }
+       case _C_CHARPTR: {
+           volatile int len = [self deserializeIntAtCursor:cursor];
+
+           /* This statement, by taking the address of `type', forces the
+               compiler to not allocate `type' into a register */
+           *(void**)data = &type;
+
+           if(len == -1) {
+               *(const char**)data = NULL;
+               return;
+           }
+
+           *(char**)data = MallocAtomic(len + 1);
+            (*(char **)data)[len] = 0;
+           TRY {
+               [self deserializeBytes:*(char**)data
+                               length:len
+                             atCursor:cursor];
+           } END_TRY
+           OTHERWISE {
+               lfFree (*(char**)data);
+               RERAISE;
+           } END_CATCH
+    
+           break;
+       }
+       case _C_ARY_B: {
+           int i, count, offset, itemSize;
+           const unsigned char* itemType;
+    
+           count = Atoi(type + 1);
+           itemType = type;
+           while(isdigit(*++itemType));
+               itemSize = objc_sizeof_type(itemType);
+
+               for(i = offset = 0; i < count; i++, offset += itemSize)
+                   [self deserializeDataAt:(char*)data + offset
+                                   ofObjCType:itemType
+                                   atCursor:cursor
+                                   context:callback];
+           break;
+       }
+       case _C_STRUCT_B: {
+           int offset = 0;
+           int align, rem;
+
+           while(*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
+           while(1) {
+               [self deserializeDataAt:((char*)data) + offset
+                       ofObjCType:type
+                       atCursor:cursor
+                       context:callback];
+               offset += objc_sizeof_type(type);
+               type = objc_skip_typespec(type);
+               if(*type != _C_STRUCT_E) {
+                   align = objc_alignof_type(type);
+                   if((rem = offset % align))
+                       offset += align - rem;
+               }
+               else break;
+           }
+           break;
+        }
+        case _C_PTR: {
+           *(char**)data = Malloc(objc_sizeof_type(++type));
+           TRY {
+               [self deserializeDataAt:*(char**)data
+                       ofObjCType:type
+                       atCursor:cursor
+                       context:callback];
+           } END_TRY
+           OTHERWISE {
+               lfFree (*(char**)data);
+               RERAISE;
+           } END_CATCH
+
+           break;
+        }
+       case _C_CHR:
+       case _C_UCHR: {
+           [self deserializeBytes:data
+                 length:sizeof(unsigned char)
+                 atCursor:cursor];
+           break;
+       }
+        case _C_SHT:
+       case _C_USHT: {
+           [self deserializeBytes:data
+                 length:sizeof(unsigned short)
+                 atCursor:cursor];
+           break;
+       }
+        case _C_INT:
+       case _C_UINT: {
+           [self deserializeBytes:data
+                 length:sizeof(unsigned int)
+                 atCursor:cursor];
+           break;
+       }
+        case _C_LNG:
+       case _C_ULNG: {
+           [self deserializeBytes:data
+                 length:sizeof(unsigned long)
+                 atCursor:cursor];
+           break;
+       }
+        case _C_FLT: {
+           [self deserializeBytes:data
+                 length:sizeof(float)
+                 atCursor:cursor];
+           break;
+       }
+        case _C_DBL: {
+           [self deserializeBytes:data
+                 length:sizeof(double)
+                 atCursor:cursor];
+           break;
+       }
+        default:
+           [[[UnknownTypeException alloc] initForType:type] raise];
+    }
+}
+
+- (int)deserializeIntAtCursor:(unsigned int*)cursor
+{
+    unsigned int ni, result;
+
+    [self deserializeBytes:&ni length:sizeof(unsigned int) atCursor:cursor];
+    result = network_int_to_host (ni);
+    return result;
+}
+
+- (int)deserializeIntAtIndex:(unsigned int)index
+{
+    unsigned int ni, result;
+
+    [self deserializeBytes:&ni length:sizeof(unsigned int) atCursor:&index];
+    result = network_int_to_host (ni);
+    return result;
+}
+
+- (void)deserializeInts:(int*)intBuffer
+  count:(unsigned int)numInts
+  atCursor:(unsigned int*)cursor
+{
+    unsigned i;
+
+    [self deserializeBytes:&intBuffer
+         length:numInts * sizeof(unsigned int)
+         atCursor:cursor];
+    for (i = 0; i < numInts; i++)
+       intBuffer[i] = network_int_to_host (intBuffer[i]);
+}
+
+- (void)deserializeInts:(int*)intBuffer
+  count:(unsigned int)numInts
+  atIndex:(unsigned int)index
+{
+    unsigned i;
+
+    [self deserializeBytes:&intBuffer
+                   length:numInts * sizeof(int)
+                   atCursor:&index];
+    for (i = 0; i < numInts; i++)
+       intBuffer[i] = network_int_to_host (intBuffer[i]);
+}
+
+- (Class)classForCoder
+{
+    return [NSData class];
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+    const char* bytes = [self bytes];
+    unsigned int length = [self length];
+
+    [aCoder encodeValueOfObjCType:@encode(unsigned int) at:&length];
+    [aCoder encodeArrayOfObjCType:@encode(char) count:length at:bytes];
+}
+
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+    char* bytes;
+    unsigned int length;
+
+    [aDecoder decodeValueOfObjCType:@encode(unsigned int) at:&length];
+    bytes = MallocAtomic (length);
+    [aDecoder decodeArrayOfObjCType:@encode(char) count:length at:bytes];
+    return [self initWithBytesNoCopy:bytes length:length];
+}
+
+@end /* NSData */
+
+
+@implementation NSMutableData
+
++ (id)allocWithZone:(NSZone*)zone
+{
+    return NSAllocateObject(((self == [NSMutableData class]) ? 
+           [NSConcreteMutableData class] : self), 0, zone);
+}
+
++ (id)dataWithCapacity:(unsigned int)numBytes
+{
+    return AUTORELEASE([[self allocWithZone:NSDefaultMallocZone()]
+                           initWithCapacity:numBytes]);
+}
+
++ (id)dataWithLength:(unsigned int)length
+{
+    return AUTORELEASE([[self allocWithZone:NSDefaultMallocZone()]
+                           initWithLength:length]);
+}
+
+- (id)initWithCapacity:(unsigned int)capacity
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+- (id)initWithLength:(unsigned int)length
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+- (NSData*)subdataWithRange:(NSRange)aRange
+{
+    char* buffer = MallocAtomic(aRange.length);
+
+    [self getBytes:buffer range:aRange];
+    return AUTORELEASE([[NSData alloc]
+                           initWithBytesNoCopy:buffer length:aRange.length]);
+}
+
+- (void)increaseLengthBy:(unsigned int)extraLength
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (void*)mutableBytes
+{
+    [self subclassResponsibility:_cmd];
+    return NULL;
+}
+
+- (void)setLength:(unsigned int)length
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (void)appendBytes:(const void*)_bytes
+    length:(unsigned int)_length
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (void)appendData:(NSData*)other
+{
+    [self appendBytes:[other bytes] length:[other length]];
+}
+
+- (void)replaceBytesInRange:(NSRange)aRange
+    withBytes:(const void*)bytes
+{
+    unsigned int length = [self length];
+
+    if(aRange.location > length
+               || aRange.length > length
+               || aRange.location + aRange.length > length)
+       [[RangeException new] raise];
+    else {
+       char* mBytes = [self mutableBytes];
+       memcpy(mBytes + aRange.location, bytes, aRange.length);
+    }
+}
+
+- (void)setData:(NSData*)aData
+{
+    [self setLength:[aData length]];
+    [self replaceBytesInRange:NSMakeRange(0, [self length])
+       withBytes:[aData bytes]];
+}
+
+- (void)resetBytesInRange:(NSRange)aRange
+{
+    unsigned int length = [self length];
+
+    if(aRange.location > length
+               || aRange.length > length
+               || aRange.location + aRange.length > length)
+       [[RangeException new] raise];
+    else {
+       char* mBytes = [self mutableBytes];
+       memset(mBytes + aRange.location, 0, aRange.length); 
+    }
+}
+
+- (void)serializeAlignedBytesLength:(unsigned int)length
+{
+}
+
+- (void)serializeDataAt:(const void*)data
+  ofObjCType:(const char*)type
+  context:(id <NSObjCTypeSerializationCallBack>)callback
+{
+    if(!data || !type)
+           return;
+
+    switch(*type) {
+        case _C_ID: {
+           [callback serializeObjectAt:(id*)data
+                       ofObjCType:type
+                       intoData:self];
+           break;
+       }
+        case _C_CHARPTR: {
+           int len;
+
+           if(!*(void**)data) {
+               [self serializeInt:-1];
+               return;
+           }
+
+           len = Strlen(*(void**)data);
+           [self serializeInt:len];
+           [self appendBytes:*(void**)data length:len];
+
+           break;
+       }
+        case _C_ARY_B: {
+            int i, offset, itemSize, count = Atoi(type + 1);
+            const unsigned char* itemType = type;
+
+            while(isdigit(*++itemType));
+               itemSize = objc_sizeof_type(itemType);
+
+               for(i = offset = 0; i < count; i++, offset += itemSize)
+                   [self serializeDataAt:(char*)data + offset
+                           ofObjCType:itemType
+                           context:callback];
+
+               break;
+        }
+        case _C_STRUCT_B: {
+            int offset = 0;
+            int align, rem;
+
+            while(*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
+            while(1) {
+                [self serializeDataAt:((char*)data) + offset
+                       ofObjCType:type
+                       context:callback];
+                offset += objc_sizeof_type(type);
+                type = objc_skip_typespec(type);
+                if(*type != _C_STRUCT_E) {
+                    align = objc_alignof_type(type);
+                    if((rem = offset % align))
+                        offset += align - rem;
+                }
+                else break;
+            }
+            break;
+        }
+       case _C_PTR:
+           [self serializeDataAt:*(char**)data
+                   ofObjCType:++type context:callback];
+           break;
+        case _C_CHR:
+       case _C_UCHR:
+           [self appendBytes:data length:sizeof(unsigned char)];
+           break;
+       case _C_SHT:
+       case _C_USHT: {
+           [self appendBytes:data length:sizeof(unsigned short)];
+           break;
+       }
+       case _C_INT:
+       case _C_UINT: {
+           [self appendBytes:data length:sizeof(unsigned int)];
+           break;
+       }
+       case _C_LNG:
+       case _C_ULNG: {
+           [self appendBytes:data length:sizeof(unsigned long)];
+           break;
+       }
+       case _C_FLT: {
+           [self appendBytes:data length:sizeof(float)];
+           break;
+       }
+       case _C_DBL: {
+           [self appendBytes:data length:sizeof(double)];
+           break;
+       }
+       default:
+           [[[UnknownTypeException alloc] initForType:type] raise];
+    }
+}
+
+- (void)serializeInt:(int)value
+{
+    unsigned int ni = host_int_to_network (value);
+    [self appendBytes:&ni length:sizeof(unsigned int)];
+}
+
+- (void)serializeInt:(int)value atIndex:(unsigned int)index
+{
+    unsigned int ni = host_int_to_network (value);
+    NSRange range = { index, sizeof(int) };
+    [self replaceBytesInRange:range withBytes:&ni];
+}
+
+- (void)serializeInts:(int*)intBuffer count:(unsigned int)numInts
+{
+    unsigned i;
+    SEL selector = @selector (serializeInt:);
+    IMP imp = [self methodForSelector:selector];
+
+    for (i = 0; i < numInts; i++)
+       (*imp)(self, selector, intBuffer[i]);
+}
+
+- (void)serializeInts:(int*)intBuffer
+  count:(unsigned int)numInts
+  atIndex:(unsigned int)index
+{
+    unsigned i;
+    SEL selector = @selector (serializeInt:atIndex:);
+    IMP imp = [self methodForSelector:selector];
+
+    for (i = 0; i < numInts; i++)
+       (*imp)(self, selector, intBuffer[i], index++);
+}
+
+- (Class)classForCoder
+{
+    return [NSMutableData class];
+}
+
+@end /* NSMutableData */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSDate.h b/libFoundation/Foundation/NSDate.h
new file mode 100644 (file)
index 0000000..5e4b096
--- /dev/null
@@ -0,0 +1,246 @@
+/* 
+   NSDate.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSDate_h__
+#define __NSDate_h__
+
+#include <Foundation/NSObject.h>
+
+#ifndef NSTimeInterval__defined
+#define NSTimeInterval__defined
+typedef double NSTimeInterval;
+#endif
+
+@class NSArray, NSDictionary, NSString, NSCalendarDate;
+@class NSTimeZone, NSTimeZoneDetail;
+
+/* 
+This module implements the 'date and time' concept.  Features:
+    - it is easy to compare dates and deal with time intervals;
+    - fast (can use the native representation);
+    - accuracy (other date representations can be added to the framework);
+    - can support user-oriented representations (Gregorian, etc ...);
+    - dates are immutable;
+    - an absolute reference date to ease conversion to other representations; 
+Our absolute reference date is the first instant of Jan 1st, 2001.
+All representations must be able to convert to/from that absolute reference.
+We ignore leap second accounting (e.g. pretend that they don't happen).
+Our reference date corresponds to 978307200 seconds after the UNIX base (e.g.
+1/1/1970 to 1/1/2001 is (31*365 + 8 (leaps: 1972, .., 2000))*24*60*60)
+
+Another interesting number is the number of seconds to the Julian Epoch, 
+JD 0.0 = 12 noon on 1 Jan 4713 B.C.E., which is -51909.5L*24*60*60
+*/
+
+/*
+ * NSDate abstract class
+ */
+
+@interface NSDate : NSObject <NSCopying, NSCoding>
+
+/* Creating an NSDate Object */
++ allocWithZone:(NSZone*)zone;
++ (id)date;
++ (id)dateWithTimeIntervalSinceNow:(NSTimeInterval)secs;    
++ (id)dateWithTimeIntervalSinceReferenceDate:(NSTimeInterval)secs;
++ (id)dateWithTimeIntervalSince1970:(NSTimeInterval)seconds;
++ (id)distantFuture;
++ (id)distantPast;
+
+- (id)init;
+- (id)initWithTimeIntervalSinceReferenceDate:(NSTimeInterval)secsToBeAdded;
+- (id)initWithString:(NSString*)description;
+- (id)initWithTimeInterval:(NSTimeInterval)secsToBeAdded 
+  sinceDate:(NSDate*)anotherDate;
+- (id)initWithTimeIntervalSinceNow:(NSTimeInterval)secsToBeAddedToNow;
+- (id)initWithTimeIntervalSince1970:(NSTimeInterval)seconds;
+
+/* Representing Dates */
+- (NSString*)description;
+- (NSString*)descriptionWithCalendarFormat:(NSString*)formatString
+  timeZone:(NSTimeZone*)aTimeZone locale:(NSDictionary*)localeDictionary;
+- (NSString*)descriptionWithLocale:(NSDictionary*)localeDictionary;
+
+/* Adding and Getting Intervals */
++ (NSTimeInterval)timeIntervalSinceReferenceDate;
+- (NSTimeInterval)timeIntervalSinceReferenceDate;
+- (NSTimeInterval)timeIntervalSinceDate:(NSDate*)anotherDate;
+- (NSTimeInterval)timeIntervalSinceNow;
+- (id)addTimeInterval:(NSTimeInterval)seconds;
+- (NSTimeInterval)timeIntervalSince1970;
+
+/* Comparing Dates */
+- (NSDate *)earlierDate:(NSDate *)anotherDate;
+- (NSDate *)laterDate:(NSDate *)anotherDate;
+- (NSComparisonResult)compare:(id)other;
+- (BOOL)isEqualToDate:other;
+
+/* Converting to an NSCalendar Object */
+- (id)dateWithCalendarFormat:(NSString*)formatString
+  timeZone:(NSTimeZone*)timeZone;
+
+/* new in MacOSX */
++ (id)dateWithNaturalLanguageString:(NSString *)_string;
++ (id)dateWithNaturalLanguageString:(NSString *)_string
+  locale:(NSDictionary *)_locale;
+
+@end
+
+/*
+ * Time Zone Classes 
+ */
+
+@class NSTimeZoneDetail;
+
+@interface NSTimeZone: NSObject <NSCoding>
+
++ (void)setDefaultTimeZone:(NSTimeZone*)aTimeZone;
++ (NSTimeZone*)defaultTimeZone;
++ (NSTimeZone*)localTimeZone;
++ (NSDictionary*)abbreviationDictionary;
++ (NSArray*)timeZoneArray;
++ (NSTimeZone*)timeZoneWithName:(NSString*)aTimeZoneName;
++ (NSTimeZone*)timeZoneWithAbbreviation:(NSString*)abbreviation;
++ (NSTimeZone*)timeZoneForSecondsFromGMT:(int)seconds;
+
+- (NSString *)timeZoneName;
+- (NSArray *)timeZoneDetailArray;
+
+// new methods in MacOSX
+
+- (NSString *)abbreviation;
+- (NSString *)abbreviationForDate:(NSDate *)_date;
+- (BOOL)isDaylightSavingTime;
+- (BOOL)isDaylightSavingTimeForDate:(NSDate *)_date;
+- (int)secondsFromGMT;
+- (int)secondsFromGMTForDate:(NSDate *)_date;
+- (NSTimeZone *)timeZoneForDate:(NSDate *)date;
+
+- (int)timeZoneSecondsFromGMT;
+- (NSString *)timeZoneAbbreviation;
+- (BOOL)isDaylightSavingTimeZone;
+@end
+
+@interface NSTimeZoneDetail : NSTimeZone /* deprecated in MacOSXS */
+@end
+
+/*
+ * Calendar Utilities
+ */
+
+
+/* 
+    Calendar formatting
+    %% encode a '%' character
+    %a abbreviated weekday name
+    %A full weekday name
+    %b abbreviated month name
+    %B full month name
+    %c shorthand for %X %x, the locale format for date and time
+    %d day of the month as a decimal number (01-31)
+    %H hour based on a 24-hour clock as a decimal number (00-23)
+    %I hour based on a 12-hour clock as a decimal number (01-12)
+    %j day of the year as a decimal number (001-366)
+    %m month as a decimal number (01-12)
+    %M minute as a decimal number (00-59)
+    %p AM/PM designation associated with a 12-hour clock
+    %S second as a decimal number (00-61)
+    %w weekday as a decimal number (0-6), where Sunday is 0
+    %x date using the date representation for the locale
+    %X time using the time representation for the locale
+    %y year without century (00-99)
+    %Y year with century (e.g. 1990)
+    %Z time zone name
+
+    and additionally
+    %z timezone offset in hours & minutes from GMT (HHMM)
+    
+    as a convenience, a '.' before the format characters dHIjmMSy will
+    suppress the leading 0, a ' ' (space) will preserve the normal field
+    width and supply spaces instead of 0's.
+*/
+   
+@interface NSCalendarDate : NSDate 
+{
+    NSTimeInterval   timeSinceRef;
+    NSTimeZoneDetail *timeZoneDetail;
+    NSString         *formatString;
+}
+
++ (id)calendarDate;
++ (id)dateWithYear:(int)year month:(unsigned)month 
+  day:(unsigned)day hour:(unsigned)hour minute:(unsigned)minute 
+  second:(unsigned)second timeZone:(NSTimeZone*)aTimeZone;
++ (id)dateWithString:(NSString*)string;
++ (id)dateWithString:(NSString*)description calendarFormat:(NSString*)format;
++ (id)dateWithString:(NSString*)description calendarFormat:(NSString*)format
+  locale:(NSDictionary*)locale;
+
+- initWithYear:(int)year month:(unsigned)month day:(unsigned)day 
+  hour:(unsigned)hour minute:(unsigned)minute second:(unsigned)second 
+  timeZone:(NSTimeZone*)aTimeZone;
+- initWithString:(NSString*)description;
+- initWithString:(NSString*)description
+  calendarFormat:(NSString*)format;
+- initWithString:(NSString*)description
+  calendarFormat:(NSString*)format
+  locale:(NSDictionary*)locale;
+
+- (NSTimeZoneDetail*)timeZoneDetail; // not available in MacOSX
+- (NSTimeZone *)timeZone;
+- (void)setTimeZone:(NSTimeZone*)aTimeZone;     
+- (NSString*)calendarFormat;
+- (void)setCalendarFormat:(NSString*)format;
+
+- (int)yearOfCommonEra;
+- (int)monthOfYear;
+- (int)dayOfMonth;
+- (int)dayOfWeek;
+- (int)dayOfYear;
+- (int)hourOfDay;
+- (int)minuteOfHour;
+- (int)secondOfMinute;
+
+- (NSCalendarDate*)addYear:(int)year month:(int)month day:(int)day
+  hour:(int)hour minute:(int)minute second:(int)second;
+- (id)dateByAddingYears:(int)year months:(int)months days:(int)days 
+  hours:(int)hours minutes:(int)minutes seconds:(int)seconds;
+
+- (NSString*)description;
+- (NSString*)descriptionWithCalendarFormat:(NSString*)format;
+- (NSString*)descriptionWithCalendarFormat:(NSString*)format 
+  timeZone:(NSTimeZone*)timeZone;
+- (NSString*)descriptionWithCalendarFormat:(NSString*)format
+  locale:(NSDictionary*)locale;
+
+@end
+
+#endif /* __NSDate_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSDate.m b/libFoundation/Foundation/NSDate.m
new file mode 100644 (file)
index 0000000..4d2d82c
--- /dev/null
@@ -0,0 +1,408 @@
+/* 
+   NSDate.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include "common.h"
+
+#if HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#include <time.h>
+
+#if HAVE_LIBC_H
+# include <libc.h>
+#else
+# include <unistd.h>
+#endif
+
+#if HAVE_WINDOWS_H
+# include <windows.h>
+#endif
+
+#include <Foundation/NSString.h>
+#include <Foundation/NSDate.h>
+#include <Foundation/NSCoder.h>
+#include <Foundation/NSUtilities.h>
+
+#include "NSConcreteDate.h"
+#include "NSCalendarDate.h"
+
+#if HAVE_GETLOCALTIME || defined(__MINGW32__)
+static void Date2Long(int theMonth, int theDay, int theYear, long *theDate);
+#define DATE_OFFSET 730486  /* Number of days from January 1, 1
+                        to January 1, 2001 */
+#endif
+
+@implementation NSDate
+
+static NSDate *distantFuture = nil, *distantPast = nil;
+
+#if defined(__svr4__)
++ (void)initialize {
+    tzset();
+}
+#endif
+
++ (id)allocWithZone:(NSZone *)zone
+{
+    return NSAllocateObject( (self == [NSDate class]) ? 
+           [NSConcreteDate class] : self, 0, zone);
+}
+
++ (NSDate *)date
+{
+    return AUTORELEASE([[self alloc] init]);
+}
+
++ (NSDate *)dateWithTimeIntervalSinceNow:(NSTimeInterval)secs
+{
+    return AUTORELEASE([[self alloc] initWithTimeIntervalSinceNow:secs]);
+}
+
++ (NSDate *)dateWithTimeIntervalSinceReferenceDate:(NSTimeInterval)secs
+{
+    return AUTORELEASE([[self alloc]
+                           initWithTimeIntervalSinceReferenceDate:secs]);
+}
+
++ (NSDate *)dateWithTimeIntervalSince1970:(NSTimeInterval)seconds
+{
+    return AUTORELEASE([[self alloc] initWithTimeIntervalSince1970:seconds]);
+}
+
++ (NSDate *)distantFuture
+{
+    if (distantFuture == nil) {
+        distantFuture = [[self alloc]
+                       initWithTimeIntervalSinceReferenceDate:DISTANT_FUTURE];
+    }
+    return distantFuture;
+}
+
++ (NSDate *)distantPast
+{
+    if (distantPast == nil) {
+        distantPast = [[self alloc] 
+                         initWithTimeIntervalSinceReferenceDate:DISTANT_PAST];
+    }
+    return distantPast;
+}
+
+- (id)init
+{
+    return [super init];
+}
+
+- (id)initWithTimeIntervalSinceReferenceDate:(NSTimeInterval)secsToBeAdded
+{
+    [self subclassResponsibility:_cmd];
+    return self;
+}
+
+- (id)initWithString:(NSString *)description
+{
+    id cal = [[NSCalendarDate alloc] initWithString:description];
+    [self initWithTimeIntervalSinceReferenceDate:
+           [cal timeIntervalSinceReferenceDate]];
+    RELEASE(cal); cal = nil;
+    return self;
+}
+
+- (NSDate *)initWithTimeInterval:(NSTimeInterval)secsToBeAdded 
+       sinceDate:(NSDate *)anotherDate
+{
+    return [self initWithTimeIntervalSinceReferenceDate:
+           (secsToBeAdded + [anotherDate timeIntervalSinceReferenceDate])];
+}
+
+- (NSDate *)initWithTimeIntervalSinceNow:(NSTimeInterval)secsToBeAddedToNow
+{
+    [self initWithTimeIntervalSinceReferenceDate:
+       (secsToBeAddedToNow + [NSDate timeIntervalSinceReferenceDate])];
+    return self;
+}
+
+- (id)initWithTimeIntervalSince1970:(NSTimeInterval)seconds
+{
+    [self initWithTimeIntervalSinceReferenceDate: seconds + UNIX_OFFSET];
+    return self;
+}
+
+/* Copying */
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    if (NSShouldRetainWithZone(self, zone))
+       return RETAIN(self);
+    else
+       return [[[self class] alloc] initWithTimeIntervalSinceReferenceDate:
+               [self timeIntervalSinceReferenceDate]];
+}
+
+/* Representing Dates */
+
+- (NSString *)propertyListStringWithLocale:(NSDictionary *)_locale
+  indent:(unsigned int)_indent
+{
+    return [[self descriptionWithLocale:_locale] stringRepresentation];
+}
+
+- (NSString *)stringRepresentation {
+    return [[self description] stringRepresentation];
+}
+
+- (NSString *)description
+{
+    return [[NSCalendarDate dateWithTimeIntervalSinceReferenceDate:
+               [self timeIntervalSinceReferenceDate]] description];
+}      
+
+- (NSString *)descriptionWithCalendarFormat:(NSString *)formatString
+       timeZone:(NSTimeZone *)aTimeZone
+       locale:(NSDictionary *)locale   
+{
+    id calendar = [NSCalendarDate dateWithTimeIntervalSinceReferenceDate:
+       [self timeIntervalSinceReferenceDate]];
+    [calendar setTimeZone:aTimeZone];
+    return [calendar descriptionWithCalendarFormat:formatString
+       timeZone:aTimeZone locale:locale];
+} 
+
+- (NSString *)descriptionWithLocale:(NSDictionary *)locale
+{
+    id calendar = [NSCalendarDate dateWithTimeIntervalSinceReferenceDate:
+       [self timeIntervalSinceReferenceDate]];
+    return [calendar descriptionWithLocale:locale];
+}
+
+/* Adding and Getting Intervals */
+
++ (NSTimeInterval)timeIntervalSinceReferenceDate
+{
+#if HAVE_GETTIMEOFDAY
+    /* eg: used on SuSE Linux */
+    NSTimeInterval  theTime = UNIX_OFFSET;
+    struct timeval  tp;
+    struct timezone tzp = { 0, 0 };
+
+    gettimeofday(&tp, &tzp);
+
+    /* theTime contains 1970 (Unix ref time) and gets added seconds and micros */
+    theTime += tp.tv_sec;
+    theTime += (double)tp.tv_usec / 1000000.0;
+
+#if 0 && defined(__svr4__)
+    {
+        extern time_t timezone, altzone;
+        theTime -= (double)altzone;
+    }
+#else
+#  if !defined(__linux__)
+    /* this is not to be used on Linux, see 'gettimeofday' man page */
+    theTime -= tzp.tz_minuteswest * 60 + (tzp.tz_dsttime ? 3600 : 0);
+#  endif
+#endif
+
+    return theTime;
+
+#elif HAVE_GETLOCALTIME
+
+    NSTimeInterval  theTime = 0;
+    SYSTEMTIME      tp;
+    long            date;
+
+    GetLocalTime(&tp);
+    Date2Long(tp.wMonth, tp.wDay, tp.wYear, &date);
+
+    theTime = ((NSTimeInterval)date - DATE_OFFSET) * 86400 +
+        tp.wHour * 3600 + tp.wMinute * 60 + tp.wSecond +
+        tp.wMilliseconds / 1000.0 ;
+    return theTime;
+
+#elif defined(__MINGW32__)
+    NSTimeInterval theTime = 0;
+    SYSTEMTIME     tp;
+    long           date;
+
+    GetSystemTime(&tp);
+    Date2Long(tp.wMonth, tp.wDay, tp.wYear, &date);
+
+    theTime = ((NSTimeInterval)date - DATE_OFFSET) * 86400 +
+        tp.wHour * 3600 + tp.wMinute * 60 + tp.wSecond +
+        tp.wMilliseconds / 1000.0 ;
+    return theTime;
+#else
+#error no time function
+#endif
+}
+
+- (NSTimeInterval)timeIntervalSinceReferenceDate
+{
+    [self subclassResponsibility:_cmd];
+    return 0;
+}
+
+- (NSTimeInterval)timeIntervalSinceDate:(NSDate *)anotherDate;
+{
+    return [self timeIntervalSinceReferenceDate] -
+           [anotherDate timeIntervalSinceReferenceDate];
+}
+
+- (NSTimeInterval)timeIntervalSinceNow
+{
+    return [self timeIntervalSinceReferenceDate] -
+           [NSDate timeIntervalSinceReferenceDate];
+}
+
+- (id)addTimeInterval:(NSTimeInterval)seconds
+{
+    return AUTORELEASE([[[self class] alloc]
+                           initWithTimeInterval:seconds sinceDate:self]);
+}
+
+- (NSTimeInterval)timeIntervalSince1970
+{
+    return [self timeIntervalSinceReferenceDate] - UNIX_OFFSET;
+}
+
+/* Comparing Dates */
+
+- (NSDate *)earlierDate:(NSDate *)anotherDate
+{
+    if (!anotherDate) return self;
+
+    return [self compare:anotherDate] == NSOrderedAscending?
+           self : anotherDate;
+}
+
+- (NSDate *)laterDate:(NSDate *)anotherDate
+{
+    if (!anotherDate) return self;
+
+    return [self compare:anotherDate] == NSOrderedAscending ?
+           anotherDate : self;
+}
+
+- (NSComparisonResult)compare:(NSDate *)other
+{
+    [self subclassResponsibility:_cmd];
+    return NSOrderedSame;
+}
+
+- (BOOL)isEqual:other
+{
+    return [other isKindOfClass:[NSDate class]] &&
+          [self isEqualToDate:other];
+}
+
+- (BOOL)isEqualToDate:other
+{
+    return [self compare:other] == NSOrderedSame;
+}
+
+/* Converting to an NSCalendar Object */
+- (NSCalendarDate *)dateWithCalendarFormat:(NSString *)aFormatString
+       timeZone:(NSTimeZone *)aTimeZone
+{
+    id new = AUTORELEASE([[NSCalendarDate alloc] 
+                             initWithTimeIntervalSinceReferenceDate:
+                                 [self timeIntervalSinceReferenceDate]]);
+    [new setCalendarFormat:aFormatString];
+    [new setTimeZone:aTimeZone];
+    return new;
+}
+
+/* new in MacOSX */
++ (id)dateWithNaturalLanguageString:(NSString *)_string
+{
+    return [self dateWithNaturalLanguageString:_string
+                 locale:nil];
+}
+
++ (id)dateWithNaturalLanguageString:(NSString *)_string
+  locale:(NSDictionary *)_locale
+{
+    return [self notImplemented:_cmd];
+}
+
+/* Encoding */
+- (Class)classForCoder
+{
+    return [NSDate class];
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+    NSTimeInterval timeDiff = [self timeIntervalSinceReferenceDate];
+
+    [aCoder encodeValueOfObjCType:@encode(NSTimeInterval) at:&timeDiff];
+}
+
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+    NSTimeInterval timeDiff;
+
+    [aDecoder decodeValueOfObjCType:@encode(NSTimeInterval) at:&timeDiff];
+    [self initWithTimeIntervalSinceReferenceDate:timeDiff];
+    return self;
+}
+
+@end /* NSDate */
+
+#if HAVE_GETLOCALTIME || defined(__MINGW32__)
+
+static int nDays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+#define bisect(a)   ((a) % 4 == 0 && ((a) % 400 == 0 || (a) % 100 ))
+#define nr_bisect(a)    ((a - 1) / 4 - nr_nebisect(a - 1))
+
+static int nr_nebisect(int a)
+{
+    int i;
+    int ret = 0;
+
+    for(i = 100; i <= a; i += 100)
+    ret += (i % 400 != 0);
+    return ret;
+}
+
+static void Date2Long(int theMonth, int theDay, int theYear, long *theDate)
+{
+    long base, offset = 0;
+    int i;
+
+    base = ((long)theYear - 1) * 365 + nr_bisect(theYear);
+    for (i = 1; i < theMonth; i++)
+    offset += nDays[i - 1];
+    offset += theDay;
+    if (theMonth > 2 && bisect(theYear))
+    offset++;
+    *theDate = base + offset;
+}
+#endif
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSDateFormatter.h b/libFoundation/Foundation/NSDateFormatter.h
new file mode 100644 (file)
index 0000000..86e48d4
--- /dev/null
@@ -0,0 +1,53 @@
+/* 
+   NSDateFormatter.h
+
+   Copyright (C) 1998 MDlink online service center, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess (helge@mdlink.de)
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+// $Id$
+
+#ifndef __NSDateFormatter_h__
+#define __NSDateFormatter_h__
+
+#include <Foundation/NSFormatter.h>
+
+@class NSDate, NSCalendarDate;
+
+@interface NSDateFormatter : NSFormatter < NSCopying, NSCoding >
+{
+  NSString *format;
+  BOOL     allowsNaturalLanguage;
+}
+
+- (id)initWithDateFormat:(NSString *)_format allowNaturalLanguage:(BOOL)_flag;
+
+- (NSString *)dateFormat;
+- (BOOL)allowsNaturalLanguage;
+
+@end
+
+#endif
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSDateFormatter.m b/libFoundation/Foundation/NSDateFormatter.m
new file mode 100644 (file)
index 0000000..ac9a22d
--- /dev/null
@@ -0,0 +1,149 @@
+/* 
+   NSDateFormatter.m
+
+   Copyright (C) 1998 MDlink online service center, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess (helge@mdlink.de)
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+// $Id$
+
+#include <Foundation/common.h>
+#include <Foundation/NSCoder.h>
+#include <Foundation/NSDate.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+#include <Foundation/NSDateFormatter.h>
+#include <Foundation/NSUtilities.h>
+
+@implementation NSDateFormatter
+
+- (id)initWithDateFormat:(NSString *)_format allowNaturalLanguage:(BOOL)_flag
+{
+    if ((_format != nil) && ![_format isKindOfClass:[NSString class]]) {
+        [[[InvalidArgumentException alloc]
+             initWithReason:@"calendar format needs to be a string !"] raise];
+    }
+    
+    self->format                = [_format copyWithZone:[self zone]];
+    self->allowsNaturalLanguage = _flag;
+    return self;
+}
+- (id)init
+{
+    return [self initWithDateFormat:nil allowNaturalLanguage:NO];
+}
+
+- (void)dealloc
+{
+    RELEASE(self->format);
+    [super dealloc];
+}
+
+- (NSString *)dateFormat
+{
+    return self->format;
+}
+- (BOOL)allowsNaturalLanguage
+{
+    return self->allowsNaturalLanguage;
+}
+
+// object => string
+
+- (NSString *)stringForObjectValue:(id)_object
+{
+    if ([_object respondsToSelector:@selector(descriptionWithCalendarFormat:)]) {
+        // NSCalendarDate
+        return [_object descriptionWithCalendarFormat:self->format];
+    }
+    else if ([_object respondsToSelector: 
+                @selector(descriptionWithCalendarFormat:timeZone:locale:)]) {
+        // NSDate
+        return [_object descriptionWithCalendarFormat:self->format
+                        timeZone:nil
+                        locale:nil];
+    }
+    else {
+        // not a date
+        return nil;
+    }
+}
+
+// string => object
+
+- (BOOL)getObjectValue:(id *)_object
+  forString:(NSString *)_string
+  errorDescription:(NSString **)_error
+{
+    *_object = [NSCalendarDate dateWithString:_string
+                               calendarFormat:self->format];
+    if (*_object)
+        return YES;
+
+    if (self->allowsNaturalLanguage)
+        *_error = @"Natural language parsing not implemented";
+    else
+        *_error = @"Could not parse date";
+
+#if HAVE_LOCALIZED_STRING
+    *_error = NSLocalizedString(*_error);
+#endif
+    
+    return NO;
+}
+
+// NSCopying
+
+- (id)copyWithZone:(NSZone *)_zone
+{
+    // formatters are immutable objects
+    if (NSShouldRetainWithZone(self, _zone))
+        return self;
+    else {
+        return [[[self class]
+                       allocWithZone:_zone]
+                       initWithDateFormat:self->format
+                       allowNaturalLanguage:self->allowsNaturalLanguage];
+    }
+}
+
+// NSCoding
+
+- (void)encodeWithCoder:(NSCoder *)_coder
+{
+    [_coder encodeObject:self->format];
+    [_coder encodeValueOfObjCType:@encode(BOOL)
+            at:&(self->allowsNaturalLanguage)];
+}
+
+- (id)initWithCoder:(NSCoder *)_coder
+{
+    self->format = [[_coder decodeObject] copyWithZone:[self zone]];
+    [_coder decodeValueOfObjCType:@encode(BOOL)
+            at:&(self->allowsNaturalLanguage)];
+    return self;
+}
+
+@end
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSDebug.h b/libFoundation/Foundation/NSDebug.h
new file mode 100644 (file)
index 0000000..d57b1eb
--- /dev/null
@@ -0,0 +1,38 @@
+/* 
+   NSDebug.h
+
+   Copyright (C) 2000 MDlink GmbH, Helge Hess.
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSDebug_H__
+#define __NSDebug_H__
+
+/* GNUstep base library compatibility fake's */
+
+#define NSDebugLog(format, args...)
+#define NSDebugFLog(format, args...)
+#define NSDebugMLog(format, args...)
+
+#define NSDebugLLog(level, format, args...)
+#define NSDebugFLLog(level, format, args...)
+#define NSDebugMLLog(level, format, args...)
+
+#endif /* __NSDebug_H__ */
diff --git a/libFoundation/Foundation/NSDebug.m b/libFoundation/Foundation/NSDebug.m
new file mode 100644 (file)
index 0000000..d0b0257
--- /dev/null
@@ -0,0 +1,36 @@
+/* 
+   NSDebug.m
+
+   Copyright (C) 2004 Marcus Mueller
+   All rights reserved.
+
+   Author: Marcus Mueller <znek@mulle-kybernetik.com>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+
+#include "NSString.h"
+
+
+const char *_NSPrintForDebugger(id _obj)
+{
+  if(_obj && [_obj respondsToSelector:@selector(description)]) {
+    return [[_obj description] cString];
+  }
+  return NULL;
+}
+
diff --git a/libFoundation/Foundation/NSDecimal.h b/libFoundation/Foundation/NSDecimal.h
new file mode 100644 (file)
index 0000000..16f8b7b
--- /dev/null
@@ -0,0 +1,91 @@
+/* 
+   NSDecimal.h
+
+   Copyright (C) 2001, MDlink online service center GmbH, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSDecimal_h__
+#define __NSDecimal_h__
+
+#include <Foundation/NSObject.h>
+
+@class NSString, NSDictionary;
+
+/* not fixed yet */
+
+typedef enum {
+  NSRoundPlain,
+  NSRoundDown,
+  NSRoundUp,
+  NSRoundBankers
+} NSRoundingMode;
+
+typedef enum {
+  NSCalculationOK,
+  NSCalculationLossOfPrecision,
+  NSCalculationOverflow,
+  NSCalculationUnderflow,
+  NSCalculationDivideByZero,
+  NSCalculationNotImplemented
+} NSCalculationError;
+
+typedef struct {
+  unsigned long long mantissa;
+  signed char        exponent;
+  BOOL               isNegative;
+} NSDecimal;
+
+/* operations */
+
+NSCalculationError NSDecimalAdd
+(NSDecimal *result, const NSDecimal *l, const NSDecimal *r, NSRoundingMode rmod);
+NSCalculationError NSDecimalSubtract
+(NSDecimal *result, const NSDecimal *l, const NSDecimal *r, NSRoundingMode rmod);
+NSCalculationError NSDecimalDivide
+(NSDecimal *result, const NSDecimal *l, const NSDecimal *r, NSRoundingMode rmod);
+NSCalculationError NSDecimalMultiply
+(NSDecimal *result, const NSDecimal *l, const NSDecimal *r, NSRoundingMode rmod);
+
+NSCalculationError NSDecimalMultiplyByPowerOf10
+(NSDecimal *result, const NSDecimal *n, short p, NSRoundingMode rmod);
+
+NSCalculationError NSDecimalPower
+(NSDecimal *result, const NSDecimal *n, unsigned int p, NSRoundingMode rmod);
+
+/* comparisons */
+
+NSComparisonResult NSDecimalCompare(const NSDecimal *l, const NSDecimal *r);
+BOOL NSDecimalIsNotANumber(const NSDecimal *decimal);
+
+/* misc */
+
+void NSDecimalRound
+(NSDecimal *result, const NSDecimal *n, int scale, NSRoundingMode rmode);
+
+void NSDecimalCompact(NSDecimal *number);
+void NSDecimalCopy(NSDecimal *dest, const NSDecimal *src);
+
+NSCalculationError NSDecimalNormalize
+(NSDecimal *number1, NSDecimal *number2, NSRoundingMode rmod);
+
+NSString *NSDecimalString(const NSDecimal *decimal, NSDictionary *locale);
+
+#endif /* __NSDecimal_h__ */
diff --git a/libFoundation/Foundation/NSDecimal.m b/libFoundation/Foundation/NSDecimal.m
new file mode 100644 (file)
index 0000000..61ee185
--- /dev/null
@@ -0,0 +1,227 @@
+/* 
+   NSDecimal.m
+
+   Copyright (C) 2001, MDlink online service center GmbH, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSDecimal.h>
+#include <Foundation/NSString.h>
+#include <common.h>
+#include <math.h>
+
+/* operations */
+
+NSCalculationError NSDecimalAdd
+(NSDecimal *res, const NSDecimal *_l, const NSDecimal *_r, NSRoundingMode rmod)
+{
+  /* WARNING: no overflow checks ... */
+  NSCalculationError e;
+  NSDecimal l, r;
+  
+  NSDecimalCopy(&l, _l);
+  NSDecimalCopy(&r, _r);
+  
+  if ((e = NSDecimalNormalize(&l, &r, rmod)) != NSCalculationOK)
+    return e;
+  
+  res->exponent = l.exponent;
+  
+  if (l.isNegative == r.isNegative) {
+    /* both are positive or both are negative */
+    res->mantissa   = l.mantissa + r.mantissa;
+    res->isNegative = l.isNegative;
+  }
+  else {
+    /* one is negative, subtraction */
+    
+    if (l.isNegative) {
+      /* switch positions ... */
+      NSDecimal swap;
+      
+      NSDecimalCopy(&swap, &l);
+      NSDecimalCopy(&l, &r);
+      NSDecimalCopy(&r, &swap);
+    }
+    
+    /* now l is positive and r is negative */
+    if (l.mantissa == r.mantissa) {
+      /* x - x = 0 */
+      res->mantissa   = 0;
+      res->exponent   = l.exponent;
+      res->isNegative = NO;
+    }
+    else if (l.mantissa > r.mantissa) {
+      res->mantissa   = l.mantissa - r.mantissa;
+      res->exponent   = l.exponent;
+      res->isNegative = NO;
+    }
+    else {
+      res->mantissa   = r.mantissa - l.mantissa;
+      res->exponent   = l.exponent;
+      res->isNegative = YES;
+    }
+  }
+  
+  return NSCalculationOK;
+}
+
+NSCalculationError NSDecimalSubtract
+(NSDecimal *result, const NSDecimal *l, const NSDecimal *r, NSRoundingMode rmod)
+{
+  /* negate rightside, then add */
+  NSDecimal d;
+  
+  NSDecimalCopy(&d, r);
+  d.isNegative = r->isNegative ? NO : YES;
+  
+  return NSDecimalAdd(result, l, &d, rmod);
+}
+
+NSCalculationError NSDecimalMultiply
+(NSDecimal *res, const NSDecimal *_l, const NSDecimal *_r, NSRoundingMode rmod)
+{
+  /* WARNING: no overflow checks ... */
+  NSCalculationError e;
+  NSDecimal l, r;
+  
+  NSDecimalCopy(&l, _l);
+  NSDecimalCopy(&r, _r);
+  
+  if ((e = NSDecimalNormalize(&l, &r, rmod)) != NSCalculationOK)
+    return e;
+  
+  res->exponent   = l.exponent;
+  res->mantissa   = l.mantissa * r.mantissa;
+  res->isNegative = l.isNegative==r.isNegative ? NO : YES;
+  
+  return NSCalculationOK;
+}
+
+NSCalculationError NSDecimalDivide
+(NSDecimal *result, const NSDecimal *l, const NSDecimal *r, NSRoundingMode rmod)
+{
+  if (r->mantissa == 0)
+    return NSCalculationDivideByZero;
+  
+  return NSCalculationNotImplemented;
+}
+
+NSCalculationError NSDecimalMultiplyByPowerOf10
+(NSDecimal *result, const NSDecimal *n, short p, NSRoundingMode rmod)
+{
+  /* simple left shift .. */
+  if (n->exponent + p > 127)
+    return NSCalculationOverflow;
+  if (n->exponent + p < -128)
+    return NSCalculationUnderflow;
+  
+  NSDecimalCopy(result, n);
+  result->exponent += p;
+  return NSCalculationNotImplemented;
+}
+
+NSCalculationError NSDecimalPower
+(NSDecimal *result, const NSDecimal *n, unsigned int p, NSRoundingMode rmod)
+{
+  return NSCalculationNotImplemented;
+}
+
+/* comparisons */
+
+NSComparisonResult NSDecimalCompare(const NSDecimal *l, const NSDecimal *r)
+{
+  if (l == r) return NSOrderedSame;
+  return NSOrderedAscending;
+}
+
+BOOL NSDecimalIsNotANumber(const NSDecimal *decimal)
+{
+  return NO;
+}
+
+/* misc */
+
+void NSDecimalRound
+(NSDecimal *result, const NSDecimal *n, int scale, NSRoundingMode rmode)
+{
+}
+
+void NSDecimalCompact(NSDecimal *number)
+{
+}
+
+void NSDecimalCopy(NSDecimal *dest, const NSDecimal *src)
+{
+  memcpy(dest, src, sizeof(NSDecimal));
+}
+
+NSCalculationError NSDecimalNormalize
+(NSDecimal *number1, NSDecimal *number2, NSRoundingMode rmod)
+{
+  if (number1->exponent == number2->exponent)
+    return NSCalculationOK;
+  
+  return NSCalculationNotImplemented;
+}
+
+NSString *NSDecimalString(const NSDecimal *_num, NSDictionary *locale)
+{
+  NSString *s;
+  
+  s = [NSString stringWithFormat:@"%si",
+                  _num->isNegative ? "-" : "",
+                  (int)_num->mantissa];
+  
+  if (_num->exponent >= 0) {
+    /* add exp zeros to the end */
+    switch (_num->exponent) {
+      case 0: break;
+      case 1: s = [s stringByAppendingString:@"0"]; break;
+      case 2: s = [s stringByAppendingString:@"00"]; break;
+      case 3: s = [s stringByAppendingString:@"000"]; break;
+      case 4: s = [s stringByAppendingString:@"0000"]; break;
+      default: {
+        int i;
+        for (i = 0; i < _num->exponent; i++)
+          s = [s stringByAppendingString:@"0"];
+        break;
+      }
+    }
+  }
+  else {
+    /* insert a decimal separator */
+    unsigned len;
+    
+    len = [s length];
+
+    /* TO BE COMPLETED !!! */
+
+    {
+      double d;
+      d = ((double)_num->mantissa) * pow(10, _num->exponent);
+      s = [NSString stringWithFormat:@"%s%g",
+                      _num->isNegative ? "-" : "",
+                      d];
+    }
+  }
+  
+  return s;
+}
diff --git a/libFoundation/Foundation/NSDecimalNumber.h b/libFoundation/Foundation/NSDecimalNumber.h
new file mode 100644 (file)
index 0000000..6354443
--- /dev/null
@@ -0,0 +1,110 @@
+/* 
+   NSDecimalNumber.h
+
+   Copyright (C) 2001, MDlink online service center GmbH, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSDecimalNumber_h__
+#define __NSDecimalNumber_h__
+
+#include <Foundation/NSValue.h>
+#include <Foundation/NSDecimal.h>
+
+@class NSDecimalNumber, NSString, NSDictionary;
+
+@protocol NSDecimalNumberBehaviors
+
+- (NSDecimalNumber *)exceptionDuringOperation:(SEL)method
+  error:(NSCalculationError)_error
+  leftOperand:(NSDecimalNumber *)_lhs
+  rightOperand:(NSDecimalNumber *)_rhs;
+
+- (NSRoundingMode)roundingMode;
+
+- (short)scale;
+
+@end
+
+@interface NSDecimalNumber : NSNumber
+{
+  NSDecimal decimal;
+}
+
++ (void)setDefaultBehavior:(id<NSDecimalNumberBehaviors>)_beh;
++ (id<NSDecimalNumberBehaviors>)defaultBehavior;
+
++ (NSDecimalNumber *)zero;
++ (NSDecimalNumber *)one;
++ (NSDecimalNumber *)notANumber;
++ (NSDecimalNumber *)maximumDecimalNumber;
++ (NSDecimalNumber *)minimumDecimalNumber;
+
++ (NSDecimalNumber *)decimalNumberWithDecimal:(NSDecimal)_num;
++ (NSDecimalNumber *)decimalNumberWithMantissa:(unsigned long long)_mantissa
+  exponent:(short)_exp
+  isNegative:(BOOL)_flag;
+
++ (NSDecimalNumber *)decimalNumberWithString:(NSString *)_s;
++ (NSDecimalNumber *)decimalNumberWithString:(NSString *)_s
+  locale:(NSDictionary *)_locale;
+
+- (id)initWithDecimal:(NSDecimal)_num;
+- (id)initWithMantissa:(unsigned long long)_mantissa
+  exponent:(short)_exp
+  isNegative:(BOOL)_flag;
+- (id)initWithString:(NSString *)_s;
+- (id)initWithString:(NSString *)_s locale:(NSDictionary *)_locale;
+
+/* operations */
+
+- (NSDecimalNumber *)decimalNumberByAdding:(NSDecimalNumber *)_num;
+- (NSDecimalNumber *)decimalNumberBySubtracting:(NSDecimalNumber *)_num;
+- (NSDecimalNumber *)decimalNumberByMultiplyingBy:(NSDecimalNumber *)_num;
+- (NSDecimalNumber *)decimalNumberByDividingBy:(NSDecimalNumber *)_num;
+
+- (NSDecimalNumber *)decimalNumberByAdding:(NSDecimalNumber *)_num
+  withBehavior:(id<NSDecimalNumberBehaviors>)_beh;
+- (NSDecimalNumber *)decimalNumberBySubtracting:(NSDecimalNumber *)_num
+  withBehavior:(id<NSDecimalNumberBehaviors>)_beh;
+- (NSDecimalNumber *)decimalNumberByMultiplyingBy:(NSDecimalNumber *)_num
+  withBehavior:(id<NSDecimalNumberBehaviors>)_beh;
+- (NSDecimalNumber *)decimalNumberByDividingBy:(NSDecimalNumber *)_num
+  withBehavior:(id<NSDecimalNumberBehaviors>)_beh;
+
+/* values */
+
+- (NSDecimal)decimalValue;
+- (double)doubleValue;
+
+/* comparison */
+
+- (NSComparisonResult)compare:(NSNumber *)_num;
+
+/* description */
+
+- (NSString *)descriptionWithLocale:(NSDictionary *)_locale;
+
+@end
+
+@interface NSDecimalNumberHandler : NSObject < NSDecimalNumberBehaviors >
+@end
+
+#endif /* __NSDecimalNumber_h__ */
diff --git a/libFoundation/Foundation/NSDecimalNumber.m b/libFoundation/Foundation/NSDecimalNumber.m
new file mode 100644 (file)
index 0000000..c014d9e
--- /dev/null
@@ -0,0 +1,669 @@
+/* 
+   NSDecimalNumber.m
+
+   Copyright (C) 2001, MDlink online service center GmbH, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSDecimalNumber.h>
+#include <Foundation/NSUtilities.h>
+#include <common.h>
+#include <math.h>
+
+@interface NSDecimalZeroNumber : NSDecimalNumber
+@end
+
+@interface NSDecimalOneNumber : NSDecimalNumber
+@end
+
+@interface NSDecimalNotANumber : NSDecimalNumber
+@end
+
+@implementation NSDecimalNumber
+
+static id<NSObject,NSDecimalNumberBehaviors> defBehavior = nil; // THREAD
+static NSDecimalNumber *zero = nil; // THREAD
+static NSDecimalNumber *one  = nil; // THREAD
+static NSDecimalNumber *nan  = nil; // THREAD
+
++ (void)setDefaultBehavior:(id<NSDecimalNumberBehaviors>)_beh
+{
+  ASSIGN(defBehavior, _beh);
+}
++ (id<NSDecimalNumberBehaviors>)defaultBehavior
+{
+  return defBehavior;
+}
+
++ (NSDecimalNumber *)zero
+{
+  if (zero == nil)
+    zero = [[NSDecimalZeroNumber alloc] init];
+  return zero;
+}
++ (NSDecimalNumber *)one
+{
+  if (one == nil)
+    one = [[NSDecimalOneNumber alloc] init];
+  return one;
+}
++ (NSDecimalNumber *)notANumber
+{
+  if (nan == nil)
+    nan = [[NSDecimalNotANumber alloc] init];
+  return nan;
+}
+
++ (NSDecimalNumber *)maximumDecimalNumber
+{
+  return [self notImplemented:_cmd];
+}
++ (NSDecimalNumber *)minimumDecimalNumber
+{
+  return [self notImplemented:_cmd];
+}
+
++ (NSDecimalNumber *)decimalNumberWithDecimal:(NSDecimal)_num
+{
+  return AUTORELEASE([[self alloc] initWithDecimal:_num]);
+}
++ (NSDecimalNumber *)decimalNumberWithMantissa:(unsigned long long)_mantissa
+  exponent:(short)_exp
+  isNegative:(BOOL)_flag
+{
+  return AUTORELEASE([[self alloc] initWithMantissa:_mantissa
+                                   exponent:_exp isNegative:_flag]);
+}
+
++ (NSDecimalNumber *)decimalNumberWithString:(NSString *)_s
+{
+  return AUTORELEASE([[self alloc] initWithString:_s]);
+}
++ (NSDecimalNumber *)decimalNumberWithString:(NSString *)_s
+  locale:(NSDictionary *)_locale
+{
+  return AUTORELEASE([[self alloc] initWithString:_s locale:_locale]);
+}
+
++ (NSDecimalNumber *)decimalNumberWithNumber:(NSNumber *)_number
+{
+  /* TO BE FIXED ! */
+  return (id)[self numberWithDouble:[_number doubleValue]];
+}
+
+- (id)initWithDecimal:(NSDecimal)_num
+{
+  /* designated initializer */
+  if (_num.exponent == 0) {
+    if (_num.mantissa == 0) {
+      RELEASE(self);
+      if (zero) return RETAIN(zero);
+      return [[[self class] zero] retain];
+    }
+    else if (_num.mantissa == 1) {
+      RELEASE(self);
+      if (one) return RETAIN(one);
+      return [[[self class] one] retain];
+    }
+  }
+  
+  self->decimal = _num;
+  return self;
+}
+- (id)init
+{
+  return [self initWithMantissa:0 exponent:0 isNegative:NO];
+}
+
+- (id)initWithMantissa:(unsigned long long)_mantissa
+  exponent:(short)_exp
+  isNegative:(BOOL)_flag
+{
+  NSDecimal d;
+  d.mantissa   = _mantissa;
+  d.exponent   = _exp;
+  d.isNegative = _flag ? YES : NO;
+  return [self initWithDecimal:d];
+}
+
+- (id)initWithString:(NSString *)_s locale:(NSDictionary *)_locale
+{
+  return [self initWithDouble:[_s doubleValue]];
+}
+- (id)initWithString:(NSString *)_s
+{
+  return [self initWithString:_s locale:nil];
+}
+
+/* integer init's */
+
+- (id)initWithBool:(BOOL)value
+{
+  return [self initWithInt:value ? 1 : 0];
+}
+- (id)initWithChar:(char)value
+{
+  return [self initWithInt:value];
+}
+- (id)initWithUnsignedChar:(unsigned char)value
+{
+  return [self initWithInt:value];
+}
+- (id)initWithShort:(short)value
+{
+  return [self initWithInt:value];
+}
+- (id)initWithUnsignedShort:(unsigned short)value
+{
+  return [self initWithInt:value];
+}
+
+- (id)initWithInt:(int)value
+{
+  NSDecimal d;
+  d.exponent   = 0;
+  if (value < 0) {
+    d.mantissa   = -value;
+    d.isNegative = YES;
+  }
+  else {
+    d.mantissa   = value;
+    d.isNegative = NO;
+  }
+  return [self initWithDecimal:d];
+}
+- (id)initWithUnsignedInt:(unsigned int)value
+{
+  NSDecimal d;
+  d.exponent   = 0;
+  d.mantissa   = value;
+  d.isNegative = NO;
+  return [self initWithDecimal:d];
+}
+
+- (id)initWithLong:(long)value
+{
+  NSDecimal d;
+  d.exponent   = 0;
+  if (value < 0) {
+    d.mantissa   = -value;
+    d.isNegative = YES;
+  }
+  else {
+    d.mantissa   = value;
+    d.isNegative = NO;
+  }
+  return [self initWithDecimal:d];
+}
+- (id)initWithUnsignedLong:(unsigned long)value
+{
+  NSDecimal d;
+  d.exponent   = 0;
+  d.mantissa   = value;
+  d.isNegative = NO;
+  return [self initWithDecimal:d];
+}
+
+- (id)initWithLongLong:(long long)value
+{
+  NSDecimal d;
+  d.exponent   = 0;
+  if (value < 0) {
+    d.mantissa   = -value;
+    d.isNegative = YES;
+  }
+  else {
+    d.mantissa   = value;
+    d.isNegative = NO;
+  }
+  return [self initWithDecimal:d];
+}
+- (id)initWithUnsignedLongLong:(unsigned long long)value
+{
+  NSDecimal d;
+  d.exponent   = 0;
+  d.mantissa   = value;
+  d.isNegative = NO;
+  return [self initWithDecimal:d];
+}
+
+/* floating point inits */
+
+- (id)initWithFloat:(float)value
+{
+  return [self initWithDouble:(double)value];
+}
+- (id)initWithDouble:(double)value
+{
+  char buf[128];
+  char      *comma, *start;
+  NSDecimal d;
+  
+  /* TODO: snprintf doesn't seem to exist on Solaris 2.5, add to configure */
+  if (snprintf(buf, sizeof(buf), "%g", value) < 1) {
+    RELEASE(self);
+    return nil;
+  }
+  
+  d.isNegative = value < 0.0 ? YES : NO;
+  
+  start = d.isNegative ? &(buf[1]) : buf; /* strip the minus */
+  
+  if ((comma = index(buf, '.'))) {
+    /* decimal sep */
+    unsigned long int vk, nk;
+    *comma = '\0';
+    comma++;
+    sscanf(start, "%lu", &vk);
+    sscanf(comma, "%lu", &nk);
+    d.exponent = strlen(comma);
+    d.mantissa = vk * d.exponent + nk;
+  }
+  else {
+    /* no decimal sep */
+    unsigned long int vk;
+    sscanf(start, "%lu", &vk);
+    d.exponent = 0;
+    d.mantissa = vk;
+  }
+  return [self initWithDecimal:d];
+}
+
+/* type */
+
+- (const char *)objCType
+{
+  return "d";
+}
+
+/* values */
+
+- (int)intValue
+{
+  if (self->decimal.exponent == 0) {
+    return self->decimal.isNegative
+      ? -(self->decimal.mantissa)
+      : self->decimal.mantissa;
+  }
+  return [self doubleValue];
+}
+- (BOOL)boolValue
+{
+  return [self intValue] ? YES : NO;
+}
+- (char)charValue
+{
+  return [self intValue];
+}
+- (unsigned char)unsignedCharValue
+{
+  return [self intValue];
+}
+- (short)shortValue
+{
+  return [self intValue];
+}
+- (unsigned short)unsignedShortValue
+{
+  return [self intValue];
+}
+
+- (unsigned int)unsignedIntValue
+{
+  if (self->decimal.exponent == 0 && !self->decimal.isNegative)
+    return self->decimal.mantissa;
+  return [self doubleValue];
+}
+- (long)longValue
+{
+  return [self doubleValue];
+}
+- (unsigned long)unsignedLongValue
+{
+  if (self->decimal.exponent == 0 && !self->decimal.isNegative)
+    return self->decimal.mantissa;
+  return [self doubleValue];
+}
+- (long long)longLongValue
+{
+  return [self doubleValue];
+}
+- (unsigned long long)unsignedLongLongValue
+{
+  if (self->decimal.exponent == 0 && !self->decimal.isNegative)
+    return self->decimal.mantissa;
+  return [self doubleValue];
+}
+- (float)floatValue
+{
+  return [self doubleValue];
+}
+
+- (double)doubleValue
+{
+  double d;
+  
+  d = (self->decimal.exponent == 0)
+    ? (double)self->decimal.mantissa
+    : ((double)self->decimal.mantissa) * pow(10, self->decimal.exponent);
+  
+  if (self->decimal.isNegative) d = -d;
+  
+  return d;
+}
+
+- (NSDecimal)decimalValue
+{
+  return self->decimal;
+}
+
+/* operations */
+
+- (NSDecimalNumber *)decimalNumberByAdding:(NSDecimalNumber *)_num
+{
+  return [self decimalNumberByAdding:_num withBehavior:defBehavior];
+}
+- (NSDecimalNumber *)decimalNumberBySubtracting:(NSDecimalNumber *)_num
+{
+  return [self decimalNumberBySubtracting:_num withBehavior:defBehavior];
+}
+- (NSDecimalNumber *)decimalNumberByMultiplyingBy:(NSDecimalNumber *)_num
+{
+  return [self decimalNumberByMultiplyingBy:_num withBehavior:defBehavior];
+}
+- (NSDecimalNumber *)decimalNumberByDividingBy:(NSDecimalNumber *)_num
+{
+  return [self decimalNumberByDividingBy:_num withBehavior:defBehavior];
+}
+
+- (NSDecimalNumber *)decimalNumberByAdding:(NSDecimalNumber *)_num
+  withBehavior:(id<NSDecimalNumberBehaviors>)_beh
+{
+  NSDecimal          res, r;
+  NSCalculationError err;
+  
+  r = [_num decimalValue];
+  
+  err = NSDecimalAdd(&res, &(self->decimal), &r, [_beh roundingMode]);
+  
+  if (err != NSCalculationOK) {
+    return [_beh exceptionDuringOperation:_cmd
+                 error:err
+                 leftOperand:self
+                 rightOperand:_num];
+  }
+  
+  return [NSDecimalNumber decimalNumberWithDecimal:res];
+}
+
+- (NSDecimalNumber *)decimalNumberBySubtracting:(NSDecimalNumber *)_num
+  withBehavior:(id<NSDecimalNumberBehaviors>)_beh
+{
+  NSDecimal          res, r;
+  NSCalculationError err;
+  
+  r = [_num decimalValue];
+  
+  err = NSDecimalSubtract(&res, &(self->decimal), &r, [_beh roundingMode]);
+  
+  if (err != NSCalculationOK) {
+    return [_beh exceptionDuringOperation:_cmd
+                 error:err
+                 leftOperand:self
+                 rightOperand:_num];
+  }
+  
+  return [NSDecimalNumber decimalNumberWithDecimal:res];
+}
+
+- (NSDecimalNumber *)decimalNumberByMultiplyingBy:(NSDecimalNumber *)_num
+  withBehavior:(id<NSDecimalNumberBehaviors>)_beh
+{
+  NSDecimal          res, r;
+  NSCalculationError err;
+  
+  r = [_num decimalValue];
+  
+  err = NSDecimalMultiply(&res, &(self->decimal), &r, [_beh roundingMode]);
+  
+  if (err != NSCalculationOK) {
+    return [_beh exceptionDuringOperation:_cmd
+                 error:err
+                 leftOperand:self
+                 rightOperand:_num];
+  }
+  
+  return [NSDecimalNumber decimalNumberWithDecimal:res];
+}
+
+- (NSDecimalNumber *)decimalNumberByDividingBy:(NSDecimalNumber *)_num
+  withBehavior:(id<NSDecimalNumberBehaviors>)_beh
+{
+  NSDecimal          res, r;
+  NSCalculationError err;
+  
+  r = [_num decimalValue];
+  
+  err = NSDecimalDivide(&res, &(self->decimal), &r, [_beh roundingMode]);
+  
+  if (err != NSCalculationOK) {
+    return [_beh exceptionDuringOperation:_cmd
+                 error:err
+                 leftOperand:self
+                 rightOperand:_num];
+  }
+  
+  return [NSDecimalNumber decimalNumberWithDecimal:res];
+}
+
+/* comparison */
+
+- (NSComparisonResult)compareWithDecimalNumber:(NSDecimalNumber *)_num
+{
+  return NSOrderedSame;
+}
+- (NSComparisonResult)compare:(NSNumber *)_num
+{
+  NSDecimalNumber *num;
+  
+  if (_num == self) return NSOrderedSame;
+  
+  if ([_num isKindOfClass:[NSDecimalNumber class]])
+    num = (NSDecimalNumber *)_num;
+  else
+    num = [NSDecimalNumber decimalNumberWithNumber:_num];
+  
+  return [self compareWithDecimalNumber:num];
+}
+
+/* description */
+
+- (NSString *)stringValue
+{
+  return [self description];
+}
+
+- (NSString *)descriptionWithLocale:(NSDictionary *)_locale
+{
+  return NSDecimalString(&(self->decimal), _locale);
+}
+
+- (NSString *)description
+{
+  return [self descriptionWithLocale:nil];
+}
+
+@end /* NSDecimalNumber */
+
+@implementation NSDecimalZeroNumber
+
+- (id)init
+{
+  self->decimal.exponent   = 0;
+  self->decimal.mantissa   = 0;
+  self->decimal.isNegative = NO;
+  return self;
+}
+
+/* operations */
+
+- (NSDecimalNumber *)decimalNumberByAdding:(NSDecimalNumber *)_num
+  withBehavior:(id<NSDecimalNumberBehaviors>)_beh
+{
+  return _num;
+}
+
+- (NSDecimalNumber *)decimalNumberBySubtracting:(NSDecimalNumber *)_num
+  withBehavior:(id<NSDecimalNumberBehaviors>)_beh
+{
+  NSDecimal d;
+  d = [_num decimalValue];
+  d.isNegative = d.isNegative ? NO : YES;
+  return [NSDecimalNumber decimalNumberWithDecimal:d];
+}
+
+- (NSDecimalNumber *)decimalNumberByMultiplyingBy:(NSDecimalNumber *)_num
+  withBehavior:(id<NSDecimalNumberBehaviors>)_beh
+{
+  return self;
+}
+
+- (NSDecimalNumber *)decimalNumberByDividingBy:(NSDecimalNumber *)_num
+  withBehavior:(id<NSDecimalNumberBehaviors>)_beh
+{
+  /* should check for _num==zero ??? */
+  return self;
+}
+
+/* description */
+
+- (NSString *)descriptionWithLocale:(NSDictionary *)_locale
+{
+  return @"0";
+}
+- (NSString *)description
+{
+  return @"0";
+}
+
+@end /* NSDecimalZeroNumber */
+
+@implementation NSDecimalOneNumber
+
+- (id)init
+{
+  self->decimal.mantissa   = 1;
+  self->decimal.exponent   = 0;
+  self->decimal.isNegative = NO;
+  return self;
+}
+
+/* operations */
+
+- (NSDecimalNumber *)decimalNumberByAdding:(NSDecimalNumber *)_num
+  withBehavior:(id<NSDecimalNumberBehaviors>)_beh
+{
+  return _num;
+}
+
+- (NSDecimalNumber *)decimalNumberByMultiplyingBy:(NSDecimalNumber *)_num
+  withBehavior:(id<NSDecimalNumberBehaviors>)_beh
+{
+  /* 1 * x = x */
+  return _num;
+}
+
+/* description */
+
+- (NSString *)descriptionWithLocale:(NSDictionary *)_locale
+{
+  return @"1";
+}
+- (NSString *)description
+{
+  return @"1";
+}
+
+@end /* NSDecimalOneNumber */
+
+@implementation NSDecimalNotANumber
+
+- (id)init
+{
+  self->decimal.mantissa   = 1;
+  self->decimal.exponent   = 0;
+  self->decimal.isNegative = NO;
+  return self;
+}
+
+/* operations */
+
+- (NSDecimalNumber *)decimalNumberByAdding:(NSDecimalNumber *)_num
+  withBehavior:(id<NSDecimalNumberBehaviors>)_beh
+{
+  return self;
+}
+- (NSDecimalNumber *)decimalNumberBySubtracting:(NSDecimalNumber *)_num
+  withBehavior:(id<NSDecimalNumberBehaviors>)_beh
+{
+  return self;
+}
+
+- (NSDecimalNumber *)decimalNumberByMultiplyingBy:(NSDecimalNumber *)_num
+  withBehavior:(id<NSDecimalNumberBehaviors>)_beh
+{
+  return self;
+}
+
+- (NSDecimalNumber *)decimalNumberByDividingBy:(NSDecimalNumber *)_num
+  withBehavior:(id<NSDecimalNumberBehaviors>)_beh
+{
+  /* should check for 0-divide ?? */
+  return self;
+}
+
+/* description */
+
+- (NSString *)descriptionWithLocale:(NSDictionary *)_locale
+{
+  return @"NaN";
+}
+
+@end /* NSDecimalNotANumber */
+
+@implementation NSDecimalNumberHandler
+
+- (NSDecimalNumber *)exceptionDuringOperation:(SEL)method
+  error:(NSCalculationError)_error
+  leftOperand:(NSDecimalNumber *)_lhs
+  rightOperand:(NSDecimalNumber *)_rhs
+{
+  return nil;
+}
+
+- (NSRoundingMode)roundingMode {
+  return NSRoundBankers;
+}
+
+- (short)scale {
+  return 0;
+}
+
+@end /* NSDecimalNumberHandler */
diff --git a/libFoundation/Foundation/NSDefaultZone.h b/libFoundation/Foundation/NSDefaultZone.h
new file mode 100644 (file)
index 0000000..7e22b91
--- /dev/null
@@ -0,0 +1,40 @@
+/* 
+   NSDefaultZone.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSDefaultZone_h__
+#define __NSDefaultZone_h__
+
+#include <Foundation/NSZone.h>
+
+@interface NSDefaultZone : NSZone
+@end
+
+#endif /* __NSDefaultZone_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSDefaultZone.m b/libFoundation/Foundation/NSDefaultZone.m
new file mode 100644 (file)
index 0000000..2d71dca
--- /dev/null
@@ -0,0 +1,215 @@
+/* 
+   NSDefaultZone.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <config.h>
+
+#if HAVE_STRING_H
+# include <string.h>
+#endif
+
+#if HAVE_MEMORY_H
+# include <memory.h>
+#endif
+
+#if !HAVE_MEMCPY
+# define memcpy(d, s, n)       bcopy((s), (d), (n))
+# define memmove(d, s, n)      bcopy((s), (d), (n))
+#endif
+
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#else
+extern void* malloc();
+extern void* calloc();
+extern void* realloc();
+extern void free();
+extern atoi();
+extern atol();
+#endif
+
+#include <Foundation/common.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSException.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+
+#include <extensions/objc-runtime.h>
+
+#include "NSDefaultZone.h"
+
+#if DEBUG
+extern FILE *logAlloc;
+#endif
+
+@implementation NSDefaultZone
+
+static inline void _memoryExhausted(void **p, unsigned size)
+{
+    static unsigned memErrorCount = 0;
+
+    fprintf(stderr,
+            "WARNING: memory exhausted (%i bytes could not be allocated)\n",
+            size);
+    
+    memErrorCount++;
+    [[RETAIN(memoryExhaustedException) setPointer:p memorySize:size] raise];
+}
+
++ (id)alloc
+{
+    return [self allocZoneInstance];
+}
+
+- (id)init
+{
+    return [self initForSize:0 granularity:0 canFree:YES];
+}
+
+- (id)initForSize:(unsigned)startSize granularity:(unsigned)granularity
+  canFree:(BOOL)canFree
+{
+    RELEASE(name);
+    name = @"Default zone";
+    return self;
+}
+
+- (void*)malloc:(unsigned)size
+{
+    void *p = objc_malloc(size);
+
+#if DEBUG
+    if ((logAlloc != (void*)-1) && (logAlloc != NULL)) {
+        fprintf(logAlloc,
+                "zmalloc: 0x%08X size=%d zone=0x%08X\n",
+                (unsigned)p, size, (unsigned)self);
+    }
+#endif
+    
+    if (p == NULL) _memoryExhausted(&p, size);
+    return p;
+}
+
+- (void*)mallocAtomic:(unsigned)size
+{
+    void* p = objc_malloc(size);
+
+#if DEBUG
+    if ((logAlloc != (void*)-1) && (logAlloc != NULL)) {
+        fprintf(logAlloc,
+                "zmalloc-a: 0x%08X size=%d zone=0x%08X\n",
+                (unsigned)p, size, (unsigned)self);
+    }
+#endif
+    
+    if (p == NULL) _memoryExhausted(&p, size);
+    return p;
+}
+
+- (void*)calloc:(unsigned)count byteSize:(unsigned)size
+{
+    void* p = objc_calloc(count, size);
+
+#if DEBUG
+    if ((logAlloc != (void*)-1) && (logAlloc != NULL)) {
+        fprintf(logAlloc,
+                "zcalloc: 0x%08X size=%d (%d * %d) zone=0x%08X\n",
+                (unsigned)p, count*size, count, size, (unsigned)self);
+    }
+#endif
+    
+    if (p == NULL) _memoryExhausted(&p, size);
+    return p;
+}
+
+- (void*)callocAtomic:(unsigned)count byteSize:(unsigned)size
+{
+    void* p = objc_calloc(count, size);
+
+#if DEBUG
+    if ((logAlloc != (void*)-1) && (logAlloc != NULL)) {
+        fprintf(logAlloc,
+                "zcalloc-a: 0x%08X size=%d (%d * %d) zone=0x%08X\n",
+                (unsigned)p, count*size, count, size, (unsigned)self);
+    }
+#endif
+    
+    if (p == NULL) _memoryExhausted(&p, size);
+    return p;
+}
+
+- (void*)realloc:(void*)p size:(unsigned)size
+{
+    void* new_p;
+    
+    if (size == 0) return p;
+    
+    new_p = p ? objc_realloc(p, size) : objc_malloc (size);
+    
+#if DEBUG
+    if ((logAlloc != (void*)-1) && (logAlloc != NULL)) {
+        fprintf(logAlloc,
+                "zrealloc: 0x%08X->0x%08X size=%d zone=0x%08X\n",
+                (unsigned)p, (unsigned)new_p, size, (unsigned)self);
+    }
+#endif
+    
+    if (new_p == NULL) _memoryExhausted(&new_p, size);
+    return new_p;
+}
+
+- (void)recycle
+{
+}
+
+- (void)freePointer:(void*)p
+{
+    if (p) {
+#if DEBUG
+        if ((logAlloc != (void*)-1) && (logAlloc != NULL)) {
+            fprintf(logAlloc, "zfree: 0x%08X zone=0x%08X\n",
+                    (unsigned)p, (unsigned)self);
+        }
+#endif
+       objc_free(p);
+        p = NULL;
+    }
+}
+
+- (BOOL)checkZone
+{
+    return YES;
+}
+
+- (BOOL)pointerInZone:(void*)pointer
+{
+    return YES;
+}
+
+@end /* NSDefaultZone */
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSDictionary.h b/libFoundation/Foundation/NSDictionary.h
new file mode 100644 (file)
index 0000000..de1b8bc
--- /dev/null
@@ -0,0 +1,135 @@
+/* 
+   NSDictionary.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSDictionary_h__
+#define __NSDictionary_h__
+
+#include <Foundation/NSObject.h>
+#include <Foundation/NSUtilities.h>
+
+@class NSString;
+@class NSArray;
+@class NSEnumerator;
+@class NSURL;
+
+/*
+ * NSDictionary class
+ */
+
+@interface NSDictionary : NSObject <NSCoding, NSCopying, NSMutableCopying>
+
+/* Creating and Initializing an NSDictionary */
+
++ (id)allocWithZone:(NSZone*)zone;
++ (id)dictionary;
++ (id)dictionaryWithContentsOfFile:(NSString *)path;
++ (id)dictionaryWithContentsOfURL:(NSURL *)_url;
++ (id)dictionaryWithObjects:(NSArray*)objects forKeys:(NSArray*)keys;
++ (id)dictionaryWithObjects:(id*)objects forKeys:(id*)keys
+  count:(unsigned int)count;
++ (id)dictionaryWithObjectsAndKeys:(id)firstObject, ...;
++ (id)dictionaryWithDictionary:(NSDictionary*)aDict;
++ (id)dictionaryWithObject:object forKey:key;
+- (id)initWithContentsOfFile:(NSString*)path;
+- (id)initWithContentsOfURL:(NSURL *)_url;
+- (id)initWithDictionary:(NSDictionary*)dictionary;
+- (id)initWithDictionary:(NSDictionary*)dictionary copyItems:(BOOL)flag;
+- (id)initWithObjectsAndKeys:(id)firstObject,...;
+- (id)initWithObjects:(NSArray*)objects forKeys:(NSArray*)keys;
+- (id)initWithObjects:(id*)objects forKeys:(id*)keys
+  count:(unsigned int)count;
+
+/* Accessing Keys and Values */
+
+- (NSArray*)allKeys;
+- (NSArray*)allKeysForObject:(id)object;
+- (NSArray*)allValues;
+- (NSEnumerator*)keyEnumerator;
+- (NSEnumerator*)objectEnumerator;
+- (id)objectForKey:(id)aKey;
+- (NSArray*)objectsForKeys:(NSArray*)keys notFoundMarker:notFoundObj;
+
+/* Counting Entries */
+
+- (unsigned int)count;
+
+/* Comparing Dictionaries */
+
+- (BOOL)isEqualToDictionary:(NSDictionary*)other;
+
+/* Storing Dictionaries */
+
+- (NSString*)description;
+- (NSString*)descriptionInStringsFileFormat;
+- (NSString*)descriptionWithLocale:(NSDictionary*)localeDictionary;
+- (NSString*)descriptionWithLocale:(NSDictionary*)localeDictionary
+  indent:(unsigned int)level;
+- (BOOL)writeToFile:(NSString*)path atomically:(BOOL)useAuxiliaryFile;
+
+/* From adopted/inherited protocols */
+
+- (unsigned)hash;
+- (BOOL)isEqual:(id)anObject;
+
+@end /* NSDictionary */
+
+/*
+ * Extensions to NSDictionary
+ */
+
+@interface NSDictionary(NSDictionaryExtensions)
+
+- (id)initWithObjectsAndKeys:(id)firstObject arguments:(va_list)argList;
+
+@end;
+
+/*
+ * NSMutableDictionary class
+ */
+
+@interface NSMutableDictionary : NSDictionary
+
++ (id)allocWithZone:(NSZone*)zone;
++ (id)dictionaryWithCapacity:(unsigned int)aNumItems;
+- (id)initWithCapacity:(unsigned int)aNumItems;
+
+/* Adding and Removing Entries */
+
+- (void)addEntriesFromDictionary:(NSDictionary*)otherDictionary;
+- (void)removeAllObjects;
+- (void)removeObjectForKey:(id)theKey;
+- (void)removeObjectsForKeys:(NSArray*)keyArray;
+- (void)setObject:(id)anObject forKey:(id)aKey;
+- (void)setDictionary:(NSDictionary*)otherDictionary;
+
+@end /* NSMutableDictionary */
+
+#endif /* __NSDictionary_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSDictionary.m b/libFoundation/Foundation/NSDictionary.m
new file mode 100644 (file)
index 0000000..5794aba
--- /dev/null
@@ -0,0 +1,830 @@
+/* 
+   NSDictionary.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include <Foundation/common.h>
+#include <Foundation/NSObject.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSData.h>
+#include <Foundation/NSRange.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSCoder.h>
+#include <Foundation/NSURL.h>
+#include <Foundation/NSNull.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+#include <Foundation/PropertyListParser.h>
+
+#include "NSConcreteDictionary.h"
+#include "NSObject+PropLists.h"
+
+
+@interface __KeyValueDescription : NSObject
+{
+@public
+    NSString* keyDescription;
+    NSString* valueDescription;
+}
+@end /* __KeyValueDescription */
+
+@implementation __KeyValueDescription
+- (NSComparisonResult)compare:(__KeyValueDescription*)other
+{
+    return [keyDescription compare:other->keyDescription];
+}
+@end /* __KeyValueDescription */
+
+
+/*
+ * NSDictionary class
+ */
+
+@implementation NSDictionary
+
+/* Creating and Initializing an NSDictionary */
+
++ (id)allocWithZone:(NSZone *)zone
+{
+    return NSAllocateObject( (self == [NSDictionary class]) ? 
+           [NSConcreteHashDictionary class] : self, 0, zone);
+}
++ (id)allocWithZone:(NSZone *)_zone forCapacity:(unsigned)_capacity {
+    if (self == [NSDictionary class]) {
+        switch (_capacity) {
+            case 0:
+                return NSAllocateObject([NSConcreteEmptyDictionary class],
+                                        0, _zone);
+            case 1:
+                return NSAllocateObject([NSConcreteSingleObjectDictionary class],
+                                        0, _zone);
+            default:
+#if defined(SMALL_NSDICTIONARY_SIZE)
+                if (_capacity <= SMALL_NSDICTIONARY_SIZE) {
+                    return NSAllocateObject([NSConcreteSmallDictionary class],
+                                            sizeof(NSSmallDictionaryEntry) *
+                                            _capacity,
+                                            _zone);
+                }
+                else
+                    return NSAllocateObject([NSConcreteHashDictionary class],
+                                            0, _zone);
+#else
+                return NSAllocateObject([NSConcreteHashDictionary class], 0, _zone);
+#endif
+        }
+    }
+    else
+        return NSAllocateObject(self, 0, _zone);
+}
+
++ (id)dictionary
+{
+    return AUTORELEASE([[self allocWithZone:NULL forCapacity:0]
+                              initWithDictionary:nil]);
+}
+
++ (id)dictionaryWithContentsOfFile:(NSString*)path
+{
+    volatile id plist = nil;
+
+    NSString *format = @"%@: file=%@, caught exception %@ with reason %@ ";
+    
+    NS_DURING {
+        plist = NSParsePropertyListFromFile(path);
+
+        if (![plist isKindOfClass:[NSDictionary class]])
+            plist = nil;
+        else if (![plist isKindOfClass:[NSMutableDictionary class]])
+            plist = AUTORELEASE([plist mutableCopy]);
+    }
+    NS_HANDLER {
+        NSLog(format, self, path,
+              [localException name], [localException reason]);
+        plist = nil;
+    }
+    NS_ENDHANDLER;
+
+    return plist;
+}
++ (id)dictionaryWithContentsOfURL:(NSURL *)_url
+{
+    id plist;
+    
+    if ([_url isFileURL])
+        return [self dictionaryWithContentsOfFile:[_url path]];
+    
+    plist = [[NSString stringWithContentsOfURL:_url] propertyList];
+    if (![plist isKindOfClass:[NSDictionary class]])
+        return nil;
+    return plist;
+}
+
++ (id)dictionaryWithObjects:(NSArray*)objects forKeys:(NSArray*)keys
+{
+    return AUTORELEASE([[self allocWithZone:NULL forCapacity:[keys count]]
+                              initWithObjects:objects forKeys:keys]);
+}
+
++ (id)dictionaryWithObjects:(id*)objects forKeys:(id*)keys
+  count:(unsigned int)count;
+{
+    return AUTORELEASE([[self allocWithZone:NULL forCapacity:count]
+                           initWithObjects:objects forKeys:keys count:count]);
+}
+
++ (id)dictionaryWithObjectsAndKeys:(id)firstObject, ...
+{
+    id dict = [self alloc];
+    va_list va;
+    
+    va_start(va, firstObject);
+    dict = [dict initWithObjectsAndKeys:firstObject arguments:va];
+    va_end(va);
+    
+    return AUTORELEASE(dict);
+}
+
++ (id)dictionaryWithDictionary:(NSDictionary*)aDict
+{
+    return AUTORELEASE([[self allocWithZone:NULL forCapacity:[aDict count]]
+                              initWithDictionary:aDict]);
+}
+
++ (id)dictionaryWithObject:object forKey:key
+{
+    return AUTORELEASE([[self allocWithZone:NULL forCapacity:1]
+                           initWithObjects:&object forKeys:&key count:1]);
+}
+
+- (id)initWithContentsOfFile:(NSString *)fileName
+{
+    NSDictionary *plist;
+    
+    if ((plist = [NSDictionary dictionaryWithContentsOfFile:fileName])) {
+        return [self initWithDictionary:plist];
+    }
+    else {
+        self = AUTORELEASE(self);
+        return nil;
+    }
+}
+- (id)initWithContentsOfURL:(NSURL *)_url
+{
+    NSDictionary *plist;
+    
+    if ((plist = [NSDictionary dictionaryWithContentsOfURL:_url])) {
+        return [self initWithDictionary:plist];
+    }
+    else {
+        self = AUTORELEASE(self);
+        return nil;
+    }
+}
+
+- (id)initWithDictionary:(NSDictionary*)dictionary copyItems:(BOOL)flag
+{
+    NSEnumerator* keye = [dictionary keyEnumerator];
+    unsigned count = [dictionary count];
+
+    id *keys   = Calloc(count, sizeof(id));
+    id *values = Calloc(count, sizeof(id));
+    id key;
+    
+    count = 0;
+    while ((key = [keye nextObject])) {
+       keys[count] = key;
+       values[count] = [dictionary objectForKey:key];
+       if (flag) {
+           keys[count]   = AUTORELEASE([keys[count]   copyWithZone:NULL]);
+           values[count] = AUTORELEASE([values[count] copyWithZone:NULL]);
+       }
+       count++;
+    }
+    
+    self = [self initWithObjects:values forKeys:keys count:count];
+    
+    lfFree(keys);   key = NULL;
+    lfFree(values); values = NULL;
+    return self;
+}
+
+- (id)initWithDictionary:(NSDictionary*)dictionary
+{
+    return [self initWithDictionary:dictionary copyItems:NO];
+}
+
+- (id)initWithObjectsAndKeys:(id)firstObject,...
+{
+    va_list va;
+    
+    va_start(va, firstObject);
+    self = [self initWithObjectsAndKeys:firstObject arguments:va];
+    va_end(va);
+    
+    return self;
+}
+
+- (id)initWithObjects:(NSArray *)objects forKeys:(NSArray *)keys
+{
+    unsigned int i, count = [objects count];
+    id *mkeys;
+    id *mobjs;
+    
+    if (count != [keys count]) {
+       [[[InvalidArgumentException alloc] initWithReason:
+               @"NSDictionary initWithObjects:forKeys must \
+                   have both arguments of the same size"] raise];
+    }
+    mkeys = Calloc(count, sizeof(id));
+    mobjs = Calloc(count, sizeof(id));
+    
+    for (i = 0; i < count; i++) {
+       mkeys[i] = [keys    objectAtIndex:i];
+       mobjs[i] = [objects objectAtIndex:i];
+    }
+    
+    self = [self initWithObjects:mobjs forKeys:mkeys count:count];
+    
+    lfFree(mkeys); mkeys = NULL;
+    lfFree(mobjs); mobjs = NULL;
+    return self;
+}
+
+- (id)initWithObjects:(id *)objects forKeys:(id *)keys 
+  count:(unsigned int)count
+{
+    [self subclassResponsibility:_cmd];
+    return self;
+}
+
+/* Accessing Keys and Values */
+
+static NSArray *emptyArray = nil;
+
+- (NSArray *)allKeys
+{
+    id array;
+    id *objs;
+    id keys = [self keyEnumerator];
+    id key;
+    unsigned int index = 0, lcount;
+
+    if ((lcount = [self count]) == 0) {
+       if (emptyArray == nil) emptyArray = [[NSArray alloc] init];
+       return emptyArray;
+    }
+    
+    objs = Calloc(lcount, sizeof(id));
+    {
+        while ((key = [keys nextObject]))
+            objs[index++] = key;
+    
+        array = AUTORELEASE([[NSArray alloc] initWithObjects:objs count:index]);
+    }
+    lfFree(objs);
+    return array;
+}
+
+- (NSArray *)allKeysForObject:(id)object
+{
+    id array;
+    id *objs;
+    id keys = [self keyEnumerator];
+    id key;
+    unsigned int index = 0, lcount;
+    
+    if ((lcount = [self count]) == 0) {
+       if (emptyArray == nil) emptyArray = [[NSArray alloc] init];
+       return emptyArray;
+    }
+    
+    objs = Calloc(lcount, sizeof(id));
+    {
+        while ((key = [keys nextObject])) {
+            if ([object isEqual:[self objectForKey:key]])
+                objs[index++] = key;
+        }
+       
+        array = AUTORELEASE([[NSArray alloc] initWithObjects:objs count:index]);
+    }
+    lfFree(objs);
+    return array;
+}
+
+- (NSArray *)allValues
+{
+    id array;
+    id *objs;
+    id keys = [self objectEnumerator];
+    id obj;
+    unsigned int index = 0, lcount;
+
+    if ((lcount = [self count]) == 0) {
+       if (emptyArray == nil) emptyArray = [[NSArray alloc] init];
+       return emptyArray;
+    }
+    
+    objs = Calloc(lcount, sizeof(id));
+    {
+        while ((obj = [keys nextObject]))
+            objs[index++] = obj;
+    
+        array = AUTORELEASE([[NSArray alloc] initWithObjects:objs count:index]);
+    }
+    lfFree(objs);
+    return array;
+}
+
+- (NSEnumerator *)keyEnumerator
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+- (NSEnumerator*)objectEnumerator
+{
+    return AUTORELEASE([[_NSDictionaryObjectEnumerator alloc]
+                           initWithDictionary:self]);
+}
+
+- (id)objectForKey:(id)aKey;
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+- (NSArray *)objectsForKeys:(NSArray *)keys notFoundMarker:(id)notFoundObj
+{
+    unsigned count, i;
+    id  *objs;
+    id  ret;
+
+    if ((count = [keys count]) == 0) {
+       if (emptyArray == nil) emptyArray = [[NSArray alloc] init];
+       return emptyArray;
+    }
+    
+    objs = Calloc(count, sizeof(id));
+    {
+        for (i = 0; i < count; i++) {
+            id ret;
+            
+            ret = [keys objectAtIndex:i];
+#if DEBUG
+            NSAssert1(ret, @"got no key for index %d", i);
+#endif
+            ret = [self objectForKey:ret];
+            objs[i] = ret ? ret : notFoundObj;
+        }
+        
+        ret = AUTORELEASE([[NSArray alloc] initWithObjects:objs count:count]);
+    }
+    lfFree(objs);
+    return ret;
+}
+
+/* Counting Entries */
+
+- (unsigned int)count;
+{
+    [self subclassResponsibility:_cmd];
+    return 0;
+}
+
+/*
+ * Comparing Dictionaries
+ */
+
+- (BOOL)isEqualToDictionary:(NSDictionary*)other
+{
+    id keys, key;
+    if( other == self )
+       return YES;
+    if ([self count] != [other count] || other == nil)
+       return NO;
+    keys = [self keyEnumerator];
+    while ((key = [keys nextObject]))
+       if ([[self objectForKey:key] isEqual:[other objectForKey:key]]==NO)
+           return NO;
+    return YES;
+}
+
+/* Storing Dictionaries */
+
+- (NSString *)propertyListStringWithLocale:(NSDictionary *)_locale
+  indent:(unsigned int)_indent
+{
+    return [self descriptionWithLocale:_locale indent:_indent];
+}
+
+- (NSString*)descriptionWithLocale:(NSDictionary*)locale
+  indent:(unsigned int)indent;
+{
+    static NSNull  *null = nil;
+    id             key, value;
+    NSEnumerator   *enumerator;
+    unsigned       indent1 = indent + 4;
+    NSMutableArray *keyDescriptions;
+    SEL sel;
+    IMP imp;
+    __KeyValueDescription *descHolder;
+    NSMutableString *description, *indentation;
+#if !LIB_FOUNDATION_BOEHM_GC
+    NSAutoreleasePool *pool = nil;
+#endif
+    
+    if(![self count])
+       return @"{}";
+    
+    if (null == nil) null = [[NSNull null] retain];
+    
+    description = [NSMutableString stringWithCString:"{\n"];
+    indentation = [NSString stringWithFormat:
+                              [NSString stringWithFormat:@"%%%dc", indent1], ' '];
+#if !LIB_FOUNDATION_BOEHM_GC
+    pool = [[NSAutoreleasePool alloc] init];
+#endif
+
+    enumerator = [self keyEnumerator];
+    keyDescriptions = [NSMutableArray arrayWithCapacity:[self count]];
+
+    while ((key = [enumerator nextObject])) {
+       descHolder = [__KeyValueDescription alloc];
+       value = [self objectForKey:key];
+
+#if DEBUG
+        NSAssert3(value, @"got no value for key %@ in 0x%08X<%@>",
+                  key, self, NSStringFromClass([self class]));
+#endif
+        descHolder->keyDescription =
+            [key propertyListStringWithLocale:locale indent:indent1];
+       
+       if (value == null) {
+#if DEBUG
+           NSLog(@"WARNING(%s): "
+                 @"encoding NSNull in property list for key %@ !",
+                 __PRETTY_FUNCTION__, key);
+#endif
+           descHolder->valueDescription = @"\"\"";
+       }
+       else {
+           descHolder->valueDescription =
+               [value propertyListStringWithLocale:locale indent:indent1];
+       }
+       
+#if DEBUG && 0        
+       NSAssert2([descHolder->keyDescription isKindOfClass:[NSString class]],
+                  @"key-desc is class %@ (k=%@), should be NSString",
+                  NSStringFromClass([descHolder->keyDescription class]),
+                  key);
+        
+       NSAssert2([descHolder->valueDescription isKindOfClass:[NSString class]],
+                  @"value-desc is class %@ (v=%@), should be NSString",
+                  NSStringFromClass([descHolder->valueDescription class]),
+                  value);
+#endif
+       [keyDescriptions addObject:descHolder];
+       RELEASE(descHolder);
+    }
+    
+    [keyDescriptions sortUsingSelector:@selector(compare:)];
+
+    sel = @selector(appendString:);
+    imp = [description methodForSelector:sel];
+    NSAssert(imp != NULL, @"got no IMP for -appendString ...");
+    
+    enumerator = [keyDescriptions objectEnumerator];
+    while((descHolder = [enumerator nextObject])) {
+       (*imp)(description, sel, indentation);
+       (*imp)(description, sel, descHolder->keyDescription);
+       (*imp)(description, sel, @" = ");
+       (*imp)(description, sel, descHolder->valueDescription);
+       (*imp)(description, sel, @";\n");
+    }
+    (*imp)(description, sel, indent
+           ? [NSMutableString stringWithFormat:
+                       [NSString stringWithFormat:@"%%%dc}", indent], ' ']
+           : [NSMutableString stringWithCString:"}"]);
+
+    RELEASE(pool);
+
+    return description;
+}
+
+- (NSString *)descriptionInStringsFileFormat
+{
+    static Class NSStringClass = Nil;
+    id key, value;
+    NSMutableArray* keys;
+    NSEnumerator* enumerator;
+    NSMutableString* description = AUTORELEASE([NSMutableString new]);
+    CREATE_AUTORELEASE_POOL(pool);
+    
+    if (NSStringClass == Nil) NSStringClass = [NSString class];
+    keys = AUTORELEASE([[self allKeys] mutableCopy]);
+    [keys sortUsingSelector:@selector(compare:)];
+    
+    enumerator = [keys objectEnumerator];
+    while((key = [enumerator nextObject])) {
+       value = [self objectForKey:key];
+       
+       NSAssert([key   isKindOfClass:NSStringClass], @"key is not a string !");
+       NSAssert([value isKindOfClass:NSStringClass], @"value is not a string !");
+       
+       [description appendString:[key stringRepresentation]];
+       [description appendString:@" = "];
+       [description appendString:[value stringRepresentation]];
+       [description appendString:@";\n"];
+    }
+    RELEASE(pool);
+
+    return description;
+}
+
+- (NSString *)descriptionWithLocale:(NSDictionary*)locale
+{
+    return [self descriptionWithLocale:locale indent:0];
+}
+
+- (NSString *)description
+{
+    return [self descriptionWithLocale:nil indent:0];
+}
+
+- (NSString *)stringRepresentation
+{
+    return [self descriptionWithLocale:nil indent:0];
+}
+
+- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile
+{
+    NSString *description;
+    
+    description = [self description];
+    
+    return [description writeToFile:path atomically:useAuxiliaryFile];
+}
+
+/* From adopted/inherited protocols */
+
+- (unsigned)hash
+{
+    return [self count];
+}
+
+- (BOOL)isEqual:(id)anObject
+{
+    if ([anObject isKindOfClass:[NSDictionary class]] == NO)
+       return NO;
+    return [self isEqualToDictionary:anObject];
+}
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    return (NSShouldRetainWithZone(self, zone))
+       ? RETAIN(self)
+        : [[NSDictionary allocWithZone:zone]
+                         initWithDictionary:self copyItems:NO];
+}
+
+- (id)mutableCopyWithZone:(NSZone*)zone
+{
+    return [[NSMutableDictionary allocWithZone:zone]
+                                 initWithDictionary:self];
+}
+
+- (Class)classForCoder
+{
+    return [NSDictionary class];
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+    int count = [self count];
+    NSEnumerator* enumerator = [self keyEnumerator];
+    id key, value;
+
+    [aCoder encodeValueOfObjCType:@encode(int) at:&count];
+    while((key = [enumerator nextObject])) {
+       value = [self objectForKey:key];
+       [aCoder encodeObject:key];
+       [aCoder encodeObject:value];
+    }
+}
+
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+    int count;
+
+    [aDecoder decodeValueOfObjCType:@encode(int) at:&count];
+    if (count > 0) {
+        id  *keys, *values;
+        int i;
+        
+        keys   = Calloc(count, sizeof(id));
+        values = Calloc(count, sizeof(id));
+        
+        for(i = 0; i < count; i++) {
+            keys[i]   = [aDecoder decodeObject];
+            values[i] = [aDecoder decodeObject];
+        }
+
+        self = [self initWithObjects:values forKeys:keys count:count];
+
+        lfFree(keys);   keys   = NULL;
+        lfFree(values); values = NULL;
+    }
+    else {
+        self = [self init];
+    }
+    return self;
+}
+
+@end /* NSDictionary */
+
+/*
+ * Extensions to NSDictionary
+ */
+
+@implementation NSDictionary(NSDictionaryExtensions)
+
+- (id)initWithObjectsAndKeys:(id)firstObject arguments:(va_list)argList
+{
+    id      object;
+    id      *ka, *oa;
+    va_list va;
+    int     count = 0;
+    
+    lfCopyVA(va, argList);
+    
+    for (object = firstObject; object; object = va_arg(va,id)) {
+       if (!va_arg(va,id)) {
+           [[[InvalidArgumentException alloc] 
+                initWithReason:@"Nil key to be added in dictionary"] raise];
+       }
+       count++;
+    }
+    
+    ka = Calloc(count, sizeof(id));
+    oa = Calloc(count, sizeof(id));
+    
+    for (count=0, object=firstObject; object; object=va_arg(argList,id)) {
+       ka[count] = va_arg(argList,id);
+       oa[count] = object;
+       count++;
+    }
+
+    self = [self initWithObjects:oa forKeys:ka count:count];
+
+    lfFree(ka); ka = NULL;
+    lfFree(oa); oa = NULL;
+    return self;
+}
+
+@end /* NSDictionaryExtensions(NSDictionaryExtensions) */
+
+/*
+ * NSMutableDictionary class
+ */
+
+@implementation NSMutableDictionary
+
+/* Creating and Initializing an NSDictionary */
+
++ (id)allocWithZone:(NSZone *)zone
+{
+    return NSAllocateObject( (self == [NSMutableDictionary class]) ? 
+           [NSConcreteMutableDictionary class] : self, 0, zone);
+}
++ (id)allocWithZone:(NSZone *)zone forCapacity:(unsigned)_capacity {
+    return NSAllocateObject( (self == [NSMutableDictionary class]) ? 
+           [NSConcreteMutableDictionary class] : self, 0, zone);
+}
+
++ (id)dictionaryWithCapacity:(unsigned int)aNumItems
+{
+    return AUTORELEASE([[self allocWithZone:NULL forCapacity:aNumItems]
+                              initWithCapacity:aNumItems]);
+}
+
+- (id)initWithCapacity:(unsigned int)aNumItems
+{
+    [self subclassResponsibility:_cmd];
+    return self;
+}
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    return [[NSDictionary allocWithZone:zone]
+       initWithDictionary:self copyItems:NO];
+}
+
+/* Adding and Removing Entries */
+
+- (void)addEntriesFromDictionary:(NSDictionary*)otherDictionary
+{
+    id nodes = [otherDictionary keyEnumerator];
+    id key;
+    
+    while ((key = [nodes nextObject]))
+       [self setObject:[otherDictionary objectForKey:key] forKey:key];
+}
+
+- (void)removeAllObjects
+{
+    id keys = [self keyEnumerator];
+    id key;
+
+    while ((key=[keys nextObject]))
+       [self removeObjectForKey:key];
+}
+
+- (void)removeObjectForKey:(id)theKey
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (void)removeObjectsForKeys:(NSArray*)keyArray
+{
+    unsigned int index, count = [keyArray count];
+    for (index = 0; index<count; index++)
+       [self removeObjectForKey:[keyArray objectAtIndex:index]];
+}
+
+- (void)setObject:(id)anObject forKey:(id)aKey
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (void)setDictionary:(NSDictionary*)otherDictionary
+{
+    [self removeAllObjects];
+    [self addEntriesFromDictionary:otherDictionary];
+}
+
+- (Class)classForCoder
+{
+    return [NSMutableDictionary class];
+}
+
+@end /* NSMutableDictionary */
+
+/*
+ * NSDictionary Enumerator classes
+ */
+
+@implementation _NSDictionaryObjectEnumerator
+
+- (id)initWithDictionary:(NSDictionary*)_dict
+{
+    self->dict = RETAIN(_dict);
+    self->keys = RETAIN([_dict keyEnumerator]);
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(self->dict);
+    RELEASE(self->keys);
+    [super dealloc];
+}
+
+- (id)nextObject
+{
+    return [dict objectForKey:[keys nextObject]];
+}
+
+@end /* _NSDictionaryObjectEnumerator */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSDistantObject.h b/libFoundation/Foundation/NSDistantObject.h
new file mode 100644 (file)
index 0000000..474dc78
--- /dev/null
@@ -0,0 +1,28 @@
+/* 
+   NSDistantObject.h
+
+   Copyright (C) 2000 MDlink GmbH, Helge Hess.
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSDistantObject_H__
+#define __NSDistantObject_H__
+
+#endif /* __NSDistantObject_H__ */
diff --git a/libFoundation/Foundation/NSDistributedLock.h b/libFoundation/Foundation/NSDistributedLock.h
new file mode 100644 (file)
index 0000000..d3b44cc
--- /dev/null
@@ -0,0 +1,62 @@
+/* 
+   NSDistributedLock.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSDistributedLock_h__
+#define __NSDistributedLock_h__
+
+#include <Foundation/NSObject.h>
+
+@class NSString;
+@class NSDate;
+
+@interface NSDistributedLock : NSObject
+{
+    NSString *path;
+    BOOL     locked;
+}
+
+// Creating an NSDistributedLock
++ (NSDistributedLock *)lockWithPath:(NSString *)aPath;
+- (NSDistributedLock *)initWithPath:(NSString *)aPath;
+
+// Acquiring a lock
+- (BOOL)tryLock;
+
+// Relinquishing a lock
+- (void)breakLock;
+- (void)unlock;
+
+// Getting lock information
+- (NSDate *)lockDate;
+
+@end /* NSDistributedLock */
+
+#endif         /* __NSDistributedLock_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSDistributedLock.m b/libFoundation/Foundation/NSDistributedLock.m
new file mode 100644 (file)
index 0000000..acf9414
--- /dev/null
@@ -0,0 +1,116 @@
+/* 
+   NSDistributedLock.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSData.h>
+#include <Foundation/NSDate.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSDistributedLock.h>
+#include <Foundation/NSValue.h>
+#include <Foundation/NSPathUtilities.h>
+
+#include <fcntl.h>
+#include <errno.h>
+
+#define PERMS 0666
+
+@implementation NSDistributedLock
+
+// Creating an NSDistributedLock
+
++ (NSDistributedLock *)lockWithPath:(NSString *)aPath
+{
+    return AUTORELEASE([[self alloc] initWithPath:aPath]);
+}
+
+- (NSDistributedLock *)initWithPath:(NSString *)aPath
+{
+    self->path   = [aPath copyWithZone:[aPath zone]];
+    self->locked = NO;
+    return self;
+}
+
+// Acquiring a lock
+
+- (BOOL)tryLock
+{
+    int fd;
+    
+    /* This open operation is atomic: it will either create a file if it
+       doesn't exist already or return an error if it exists. */
+    fd = open([path fileSystemRepresentation], O_RDWR|O_CREAT|O_EXCL, PERMS);
+    if (fd < 0) {
+       if (errno != EEXIST) {
+           [NSException raise:NSGenericException 
+                         format:@"%s", strerror(errno)];
+        }
+       return NO;
+    }
+    close(fd);
+    
+    self->locked = YES;
+    
+    return YES;
+}
+
+// Relinquishing a lock
+
+- (void)breakLock
+{
+    /* Don't care about errors */
+    unlink([path fileSystemRepresentation]);
+    self->locked = NO;
+}
+
+- (void)unlock
+{
+    if (!self->locked)
+       [NSException raise:NSGenericException format:@"not locked"];
+    if (unlink([path fileSystemRepresentation]) < 0)
+       [NSException raise:NSGenericException format:@"%s", strerror(errno)];
+    self->locked = NO;
+}
+
+// Getting lock information
+
+- (NSDate *)lockDate
+{
+    struct stat statbuf;
+    
+    if (stat([path fileSystemRepresentation], &statbuf) < 0)
+       return nil;
+
+    return [NSDate dateWithTimeIntervalSince1970:statbuf.st_mtime];
+}
+
+@end /* NSDistributedLock */
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSDistributedNotificationCenter.h b/libFoundation/Foundation/NSDistributedNotificationCenter.h
new file mode 100644 (file)
index 0000000..7afb729
--- /dev/null
@@ -0,0 +1,70 @@
+/* 
+   NSDistributedNotification.h
+
+   Copyright (C) 1999 MDlink online service center, Helge Hess
+   All rights reserved.
+   
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSDistributedNotificationCenter_H__
+#define __NSDistributedNotificationCenter_H__
+
+#include <Foundation/NSNotification.h>
+
+@class NSString;
+
+LF_EXPORT NSString *NSLocalNotificationCenterType;
+
+typedef enum {
+  NSNotificationSuspensionBehaviorDrop,
+  NSNotificationSuspensionBehaviorCoalesce,
+  NSNotificationSuspensionBehaviorHold,
+  NSNotificationSuspensionBehaviorDeliverImmediatly
+} NSNotificationSuspensionBehavior;
+
+@interface NSDistributedNotificationCenter : NSNotificationCenter
+
++ (NSDistributedNotificationCenter *)notificationCenterForType:(NSString *)_type;
+
+/* observers */
+
+- (void)addObserver:(id)_observer selector:(SEL)_selector
+  name:(NSString *)_notificationName object:(NSString *)_object
+  suspensionBehavior:(NSNotificationSuspensionBehavior)_suspensionBehaviour;
+
+/* posting */
+
+- (void)postNotificationName:(NSString *)_name object:(id)_object
+  userInfo:(NSDictionary *)_ui deliverImmediatly:(BOOL)_flag;
+
+/* suspension */
+
+- (void)setSuspended:(BOOL)_flag;
+- (BOOL)suspended;
+
+@end
+
+#endif /* __NSDistributedNotificationCenter_H__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSDistributedNotificationCenter.m b/libFoundation/Foundation/NSDistributedNotificationCenter.m
new file mode 100644 (file)
index 0000000..2237168
--- /dev/null
@@ -0,0 +1,123 @@
+/* 
+   NSDistributedNotification.m
+
+   Copyright (C) 1999 MDlink online service center, Helge Hess
+   All rights reserved.
+   
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include "NSDistributedNotificationCenter.h"
+
+NSString *NSLocalNotificationCenterType = @"NSLocalNotificationCenter";
+
+// MT
+static NSDistributedNotificationCenter *defaultCenter = nil;
+
+@implementation NSDistributedNotificationCenter
+
++ (NSDistributedNotificationCenter *)notificationCenterForType:(NSString *)_type
+{
+    if ([_type isEqualToString:NSLocalNotificationCenterType]) {
+        if (defaultCenter == nil)
+            defaultCenter = [[self alloc] init];
+        return defaultCenter;
+    }
+    else
+        return nil;
+}
+
++ (NSNotificationCenter *)defaultCenter
+{
+    return [self notificationCenterForType:NSLocalNotificationCenterType];
+}
+
+/* observers */
+
+- (void)addObserver:(id)_observer selector:(SEL)_selector
+  name:(NSString *)_notificationName object:(NSString *)_object
+  suspensionBehavior:(NSNotificationSuspensionBehavior)_suspbehave
+{
+    [self notImplemented:_cmd];
+}
+
+- (void)addObserver:(id)_observer selector:(SEL)_selector
+  name:(NSString *)_notificationName object:(id)_object
+{
+    [self addObserver:_object selector:_selector
+          name:_notificationName object:_object
+          suspensionBehavior:NSNotificationSuspensionBehaviorCoalesce];
+}
+
+- (void)removeObserver:(id)observer 
+  name:(NSString*)notificationName object:(id)object
+{
+    [self notImplemented:_cmd];
+}
+
+/* posting */
+
+- (void)postNotificationName:(NSString *)_name object:(id)_object
+  userInfo:(NSDictionary *)_ui deliverImmediatly:(BOOL)_flag
+{
+    [self notImplemented:_cmd];
+}
+
+- (void)postNotificationName:(NSString *)_name object:(id)_object
+{
+    [self postNotificationName:_name
+          object:_object
+          userInfo:nil
+          deliverImmediatly:NO];
+}
+
+- (void)postNotificationName:(NSString *)_name object:(id)_object
+  userInfo:(NSDictionary *)_userInfo
+{
+    [self postNotificationName:_name
+          object:_object
+          userInfo:_userInfo
+          deliverImmediatly:NO];
+}
+
+- (void)postNotification:(NSNotification *)_notification
+{
+    [self postNotificationName:[_notification name]
+          object:[_notification object]
+          userInfo:[_notification userInfo]
+          deliverImmediatly:NO];
+}
+
+/* suspension */
+
+- (void)setSuspended:(BOOL)_flag
+{
+}
+- (BOOL)suspended
+{
+    return NO;
+}
+
+@end /* NSDistributedNotificationCenter */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSEnumerator.h b/libFoundation/Foundation/NSEnumerator.h
new file mode 100644 (file)
index 0000000..58350dd
--- /dev/null
@@ -0,0 +1,47 @@
+/* 
+   NSEnumerator.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSEnumerator_h__
+#define __NSEnumerator_h__
+
+#include <Foundation/NSObject.h>
+
+/*
+ * Gneric class to serve as super for various container enumerators
+ */
+
+@interface NSEnumerator : NSObject
+
+- (id)nextObject;
+
+@end
+
+#endif /* __NSEnumerator_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSEnumerator.m b/libFoundation/Foundation/NSEnumerator.m
new file mode 100644 (file)
index 0000000..1d2a498
--- /dev/null
@@ -0,0 +1,42 @@
+/* 
+   NSEnumerator.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSEnumerator.h>
+
+@implementation NSEnumerator
+
+- nextObject
+{
+    [self subclassResponsibility:_cmd];
+    return self;
+}
+
+@end
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSError.h b/libFoundation/Foundation/NSError.h
new file mode 100644 (file)
index 0000000..cdd4dff
--- /dev/null
@@ -0,0 +1,43 @@
+/* 
+   NSError.h
+
+   Copyright (C) 2003 SKYRIX Software AG, Helge Hess.
+   All rights reserved.
+   
+   Author: Helge Hess <helge.hess@opengroupware.org>
+   
+   This file is part of libFoundation.
+   
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+   
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSError_H__
+#define __NSError_H__
+
+#include <Foundation/NSObject.h>
+
+@interface NSError : NSObject
+{
+}
+
+@end
+
+#endif /* __NSError_H__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSError.m b/libFoundation/Foundation/NSError.m
new file mode 100644 (file)
index 0000000..04bcd44
--- /dev/null
@@ -0,0 +1,37 @@
+/* 
+   NSError.m
+
+   Copyright (C) 2003 SKYRIX Software AG, Helge Hess.
+   All rights reserved.
+   
+   Author: Helge Hess <helge.hess@opengroupware.org>
+   
+   This file is part of libFoundation.
+   
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+   
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSError.h>
+#include <common.h>
+
+@implementation NSError
+
+@end /* NSError */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSException.m b/libFoundation/Foundation/NSException.m
new file mode 100644 (file)
index 0000000..ca6ad1e
--- /dev/null
@@ -0,0 +1,696 @@
+/* 
+   NSException.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+
+#ifdef HAVE_LIBC_H
+# include <libc.h>
+#else /* GNU CC comes with unistd.h */
+# include <unistd.h>
+#endif
+
+#if HAVE_STRING_H
+# include <string.h>
+#endif
+#if HAVE_MEMORY_H
+# include <memory.h>
+#endif
+
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#else
+extern char* getenv(char*);
+#endif
+
+#include <stdio.h>
+#include <signal.h>
+
+#include <Foundation/common.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSThread.h>
+#include <Foundation/NSData.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+
+#include "PrivateThreadData.h"
+
+#define HAVE_GDB 0
+#if !defined(__WIN32__) && HAVE_GDB && DEBUG
+#  define WITH_GDB_BACKTRACE 1
+#endif
+
+void _default_exception_handler(NSException* exception)
+{
+    fprintf(stderr, "Uncatched Objective-C exception:\n");
+    fprintf(stderr, "%s\n", [[exception errorString] cString]);
+
+    [NSException printBacktrace];
+    
+    if(getenv("CRASH_WITH_ABORT"))
+       abort();
+    else
+        exit(1);
+}
+
+#ifdef BROKEN_COMPILER
+static NSUncaughtExceptionHandler* uncaughtHandler = _default_exception_handler;
+#endif
+
+static NSHandler firstExceptionHandler;
+static NSHandler* lastHandler = NULL;
+static BOOL isMultiThreaded = NO;
+
+void _init_first_exception_handler(NSHandler* handler)
+{
+static BOOL initialized = NO;
+    if (!initialized) {
+            handler->previousHandler = NULL;
+            memset(&(handler->jmpState), 0, sizeof(jmp_buf));
+#ifndef BROKEN_COMPILER
+            handler->handler = _default_exception_handler;
+#endif
+    }
+}
+
+void _NSAddHandler(NSHandler *exHandler)
+{
+    if (!isMultiThreaded) {
+        if(!lastHandler) {
+            /* We were called for the first time. */
+            [NSException initialize];
+        }
+        exHandler->previousHandler = lastHandler;
+        lastHandler = exHandler;
+    } else {
+        NSHandler *aHandler;
+       PrivateThreadData* threadData = [[NSThread currentThread]
+                                               _privateThreadData];
+
+        aHandler = [threadData threadDefaultExceptionHandler];
+        exHandler->previousHandler = aHandler;
+        [threadData setThreadDefaultExceptionHandler:exHandler];
+    }
+}
+
+void _NSRemoveHandler(NSHandler *handler)
+{
+    if (!isMultiThreaded) {
+        lastHandler = lastHandler->previousHandler;
+    } else {
+       PrivateThreadData* threadData = [[NSThread currentThread]
+                                               _privateThreadData];
+        NSHandler *aHandler;
+
+        aHandler = [threadData threadDefaultExceptionHandler];
+       [threadData
+               setThreadDefaultExceptionHandler:aHandler->previousHandler];
+    }
+}
+
+@implementation NSException
+
++ (void)initialize
+{
+    static BOOL initialized = NO;
+
+    if(!initialized) {
+       initialized = YES;
+       [NSAssertionHandler initialize];
+        _init_first_exception_handler(&firstExceptionHandler);
+        lastHandler = &firstExceptionHandler;
+    }
+}
+
++ (void)taskNowMultiThreaded:notification
+{
+    [[[NSThread currentThread] _privateThreadData]
+           setThreadDefaultExceptionHandler:lastHandler];
+    lastHandler = NULL;
+    isMultiThreaded = YES;
+}
+
++ (NSException *)exceptionWithName:(NSString *)_name
+  reason:(NSString *)_reason
+  userInfo:(NSDictionary *)_userInfo
+{
+    return [[[self alloc]
+                   initWithName:_name reason:_reason userInfo:_userInfo]
+                   autorelease];
+}
+
++ (void)raise:(NSString *)_name
+  format:(NSString *)_format,...
+{
+    va_list ap;
+    
+    va_start(ap, _format);
+    [self raise:_name format:_format arguments:ap];
+    va_end(ap);
+}
+
++ (void)raise:(NSString *)_name
+  format:(NSString *)_format
+  arguments:(va_list)argList
+{
+  NSException *exception = [self exceptionWithName:_name
+                                 reason:Avsprintf(_format, argList)
+                                 userInfo:nil];
+  [exception raise];
+}
+
+- (id)initWithName:(NSString*)_name
+  reason:(NSString*)_reason
+  userInfo:(NSDictionary*)_userInfo
+{
+    self->name     = [_name   copy];
+    self->reason   = [_reason copy];
+    self->userInfo = RETAIN(_userInfo);
+    
+    return self;
+}
+
+- (void)raise
+{
+    NSHandler         *ex;
+    PrivateThreadData *threadData = nil;
+    
+    if (!isMultiThreaded)
+        ex = lastHandler;
+    else {
+        threadData = [[NSThread currentThread] _privateThreadData];
+        ex = [threadData threadDefaultExceptionHandler];
+    }
+    
+    if (ex == NULL) {
+       fprintf (stderr, "Uncaught exception %s\n",
+                [[self errorString] cString]);
+       abort();
+    }
+
+    self = RETAIN(self); // handler needs to release localException !
+    
+#ifdef BROKEN_COMPILER
+    if (ex->previousHandler == NULL) {
+        if (!isMultiThreaded)
+            uncaughtHandler(self);
+        else
+            [threadData invokeUncaughtExceptionHandlerWithException:self];
+    }
+    else {
+       ex->exception = self;
+       longjmp(ex->jmpState, 1);
+    }
+#else
+    (ex->handler)(self);
+#endif
+}
+
+- (void)dealloc
+{
+    RELEASE(self->name);
+    RELEASE(self->reason);
+    RELEASE(self->userInfo);
+    [super dealloc];
+}
+
+- (NSString *)name
+{
+    return self->name ? self->name : NSStringFromClass(isa);
+}
+
+- (NSString *)reason
+{
+    return self->reason;
+}
+- (NSDictionary *)userInfo
+{
+    return self->userInfo;
+}
+
+- (NSString *)descriptionWithLocale:(NSDictionary *)locale
+{
+    return [NSString stringWithFormat:
+       @"(Exception name:%@ class:%@ reason:%@ info:%@)",
+       name ? name : @"<nil>",
+       NSStringFromClass(isa),
+       reason ? reason : @"<nil>",
+       userInfo ? [userInfo descriptionWithLocale:locale] : @"<nil>"];
+}
+
+- (NSString *)description
+{
+    return [self descriptionWithLocale:nil];
+}
+
+@end /* NSException */
+
+
+@implementation NSException (Extensions)
+
+- (BOOL)exceptionIsKindOfClass:(Class)class
+{
+    return [self isKindOfClass:class];
+}
+
+- (BOOL)exceptionIsIn:(NSArray*)exceptions
+{
+    int i, n = [exceptions count];
+
+    for(i = 0; i < n; i++)
+       if([self exceptionIsKindOfClass:[[exceptions objectAtIndex:i] class]])
+           return YES;
+    return NO;
+}
+
+- (NSString *)errorString
+{
+    /* Don't use -[NSString stringWithFormat:] method because it can cause
+       infinite recursion. */
+    char buffer[1024];
+    
+    sprintf(buffer, "exceptionClass %s\nReason: %s\nUserInfo: %s\n",
+            [[[self class] description] cString],
+            ([self reason] ? [[self reason] cString] : "null reason"),
+            ([self userInfo]
+             ? [[[self userInfo] description] cString]
+             : "no userinfo"));
+    return [NSString stringWithCString:buffer];
+}
+
+- (id)initWithFormat:(NSString *)format, ...
+{
+    va_list ap;
+
+    va_start(ap, format);
+    self->reason = [[NSString alloc] initWithFormat:format arguments:ap];
+    va_end(ap);
+    return self;
+}
+
+- (id)initWithFormat:(NSString *)format arguments:(va_list)ap
+{
+    self->reason = [[NSString alloc] initWithFormat:format arguments:ap];
+    return self;
+}
+
+- (id)setName:(NSString *)_name
+{
+    ASSIGN(self->name, _name);
+    return self;
+}
+
+- (id)setReason:(NSString *)_reason
+{
+    ASSIGN(self->reason, _reason);
+    return self;
+}
+
+- (id)setUserInfo:(NSDictionary *)_userInfo
+{
+    ASSIGN(self->userInfo, _userInfo);
+    return self;
+}
+
+@end /* NSException (Extensions) */
+
+
+LF_DECLARE NSString *NSInconsistentArchiveException = @"Archive is inconsistent";
+LF_DECLARE NSString *NSGenericException            = @"Generic exception";
+LF_DECLARE NSString *NSInternalInconsistencyException = @"Internal inconsistency";
+LF_DECLARE NSString *NSInvalidArgumentException    = @"Invalid argument";
+LF_DECLARE NSString *NSMallocException             = @"Memory exhausted";
+LF_DECLARE NSString *NSObjectInaccessibleException = @"Object inaccessible";
+LF_DECLARE NSString *NSObjectNotAvailableException = @"Object not available";
+LF_DECLARE NSString *NSDestinationInvalidException = @"Destination invalid";
+LF_DECLARE NSString *NSPortTimeoutException        = @"Port timeout";
+LF_DECLARE NSString *NSInvalidSendPortException    = @"Invalid send port";
+LF_DECLARE NSString *NSInvalidReceivePortException = @"Invalid receive port";
+LF_DECLARE NSString *NSPortSendException           = @"Port send failed";
+LF_DECLARE NSString *NSPortReceiveException        = @"Port receive failed";
+LF_DECLARE NSString *NSOldStyleException           = @"Old style exception";
+LF_DECLARE NSString *NSRangeException              = @"Range exception";
+
+
+NSUncaughtExceptionHandler *NSGetUncaughtExceptionHandler(void)
+{
+    [NSException initialize];
+
+    if (!isMultiThreaded) {
+#ifdef BROKEN_COMPILER
+        return uncaughtHandler;
+#else
+        return firstExceptionHandler.handler;
+#endif
+    }
+    else
+        return [[[NSThread currentThread] _privateThreadData]
+                   uncaughtExceptionHandler];
+}
+
+void NSSetUncaughtExceptionHandler(NSUncaughtExceptionHandler *handler)
+{
+    [NSException initialize];
+
+    if (!isMultiThreaded) {
+#ifdef BROKEN_COMPILER
+        uncaughtHandler = handler;
+#else
+        firstExceptionHandler.handler = handler;
+#endif
+    }
+    else
+        [[[NSThread currentThread] _privateThreadData]
+            setUncaughtExceptionHandler:handler];
+}
+
+
+/*
+* Assertions.
+*/
+
+@implementation NSAssertionHandler
+
+static id currentHandler = nil;
+
++ (void)initialize
+{
+    static BOOL initialized = NO;
+
+    if(!initialized) {
+       initialized = YES;
+       currentHandler = [[self alloc] init];
+       [NSException initialize];
+    }
+}
+
++ (NSAssertionHandler*)currentHandler
+{
+    return currentHandler;
+}
+
+- (void)handleFailureInFunction:(NSString*)functionName
+    file:(NSString*)fileName
+    lineNumber:(int)line
+    description:(NSString*)format,...
+{
+    va_list ap;
+
+    va_start(ap, format);
+    NSLog(@"Assertion failed in file %@, line %d, function %@:",
+                           fileName, line, functionName);
+    NSLogv(format, ap);
+    [[[AssertException alloc] initWithFormat:format arguments:ap] raise];
+    va_end(ap);
+}
+
+- (void)handleFailureInMethod:(SEL)selector
+    object:(id)object
+    file:(NSString*)fileName
+    lineNumber:(int)line
+    description:(NSString*)format,...
+{
+    va_list ap;
+
+    va_start(ap, format);
+    NSLog(@"Assertion failed in file %@, line %d, method %@:",
+           fileName, line, NSStringFromSelector(selector));
+    NSLogv(format, ap);
+    [[[AssertException alloc] initWithFormat:format arguments:ap] raise];
+    va_end(ap);
+}
+
+@end /* NSAssertionHandler */
+
+
+/* backtracing stuff */
+
+#if WITH_GDB_BACKTRACE
+
+#if HAVE_SYS_TIME_H
+# include <sys/time.h> /* for struct timeval */
+#endif
+#if HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+@implementation NSException(Backtrace)
+
+/* print program backtrace using gdb */
+
+extern volatile BOOL _libFoundation_backtraceFinished;
+volatile BOOL _libFoundation_backtraceFinished = YES;
+
+extern char *_libFoundation_argv0;
+
+static BOOL  _st_done = NO; /* signals whether gdb did exit  */
+static pid_t pid      = 0;  /* pid of program being debugged */
+static char  btPath[512] = { '\0' }; /* path to backtrace-file        */
+
+static void gdbSigChild(int signum)
+{
+    /* invoked if gdb exits */
+    _st_done = YES;
+}
+static void backtraceProcess(void)
+{
+    char *gdbCommands[] = {
+        "backtrace\n",
+        "p _libFoundation_backtraceFinished = 0\n",
+        "detach\n",
+        "quit\n",
+        NULL
+    };
+    int    inPipe[2], outPipe[2];
+    pid_t  gdbPid;
+    
+    /* hook in gdb-exit handler */
+    signal(SIGCHLD, gdbSigChild);
+
+    if (pipe(inPipe) != 0) {
+        /* pipe setup failed */
+        goto failedExit;
+    }
+    if (pipe(outPipe) != 0) {
+        /* pipe setup failed */
+        goto failedExit;
+    }
+    
+    if ((gdbPid = fork()) > 0) {
+        /* gdb handler (IO) process */
+        fd_set fdset;
+        int    i;
+        BOOL   foundHash, lastNewline;
+        int    logfd;
+        
+        /* send commands to gdb */
+        for (i = 0; gdbCommands[i]; i++)
+            write(inPipe[1], gdbCommands[i], strlen(gdbCommands[i]));
+        
+        /* init vars */
+        FD_ZERO(&fdset);
+        FD_SET(outPipe[0], &fdset);
+        foundHash   = NO;
+        lastNewline = NO;
+
+        logfd = 1;
+        if (btPath[0] != '\0') {
+            /* log to file */
+            logfd = open(btPath, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+            if (logfd < 0)
+                /* open failed, log to stdout .. */
+                logfd = 1;
+        }
+        
+        /* IO loop (while gdb did not exit) */
+        while (!_st_done) {
+            fd_set         readset;
+            struct timeval tv;
+            int            numSelected;
+            
+            readset = fdset;
+            tv.tv_sec  = 1; /* one second timeout */
+            tv.tv_usec = 0;
+            
+            numSelected = select(FD_SETSIZE, &readset, NULL, NULL, &tv);
+            if (numSelected == -1)
+                /* select failed */
+                break;
+
+            if (numSelected > 0) {
+                char c;
+                
+                if (!(FD_ISSET(outPipe[0], &readset)))
+                    continue;
+
+                /* read a byte */
+                if (!read(outPipe[0], &c, 1))
+                    continue;
+
+                //fputc(c, stdout);
+                
+                if (!foundHash) {
+                    if (c == '#') {
+                        foundHash = YES;
+                        write(logfd, &c, 1);
+                    }
+                    else if (lastNewline) {
+                        /* a 'hashline' followed by a newline */
+                        lastNewline = NO;
+                        if (c != '(')
+                            /* continuation line */
+                            foundHash = YES;
+                    }
+                }
+                else {
+                    write(logfd, &c, 1);
+                    
+                    if ((c == '\n') || (c == '\r')) {
+                        foundHash = NO;
+                        lastNewline = YES;
+                    }
+                }
+            }
+        }
+        if (logfd > 2)
+            close(logfd);
+    }
+    else if (gdbPid == 0) {
+        /* gdb itself */
+        char *argv[4];
+        char ppid[8];
+        
+        sprintf(ppid, "%d", pid);
+        argv[0] = "gdb";
+        argv[1] = _libFoundation_argv0; /* path to program being debugged */
+        argv[2] = &(ppid[0]);
+        argv[3] = NULL;
+        
+        /* map stdio to pipe handled by handler process */
+        close(0); close(1); close(2);
+        dup2(inPipe[0],  0);
+        dup2(outPipe[1], 1);
+        dup2(outPipe[1], 2);
+        
+        /* load & run gdb */
+        execvp(argv[0], &(argv[0]));
+
+        /* if we get here, an error occured */
+        goto failedExit;
+    }
+    else {
+        /* gdb fork failed */
+        goto failedExit;
+    }
+
+    return;
+ failedExit:
+    perror("sth failed ..");
+    kill(pid, 9);
+    _exit(0);
+}
+
+static BOOL storeBacktrace = YES;
+
++ (NSString *)backtrace
+{
+    pid_t backtracePid;
+    pid = getpid(); /* store pid of program being debugged */
+    if (storeBacktrace)
+        sprintf(btPath, "/tmp/backtrace.pid_%d", pid);
+    else
+        btPath[0] = '\0';
+    
+    /* fork backtrace process */
+
+    if ((backtracePid = fork()) > 0) {
+        /* process being debugged .. */
+        int btStatus;
+        
+        /* loop until gdb flags exit (by setting that global) */
+        while (_libFoundation_backtraceFinished)
+            ;
+        _libFoundation_backtraceFinished = YES;
+        
+        /* wait for IO handler */
+        waitpid(backtracePid, &btStatus, 0);
+        
+        /* load backtrace file */
+        if (storeBacktrace) {
+            NSData   *data;
+            NSString *p;
+            
+            p = [[NSString alloc] initWithCString:btPath];
+            data = [[NSString alloc] initWithContentsOfFile:p];
+            RELEASE(p);
+            return AUTORELEASE(data);
+        }
+    }
+    else if (backtracePid == 0) {
+        /* run backtrace process */
+        backtraceProcess();
+        /* should never return */
+        exit(0);
+    }
+    else {
+        /* could not fork gdb */
+    }
+    pid = 0;
+    return nil;
+}
++ (void)printBacktrace
+{
+    BOOL oldVal = storeBacktrace;
+    storeBacktrace = NO;
+    [self backtrace];
+    storeBacktrace = oldVal;
+}
+
+@end /* NSException(Backtrace) */
+
+#else
+
+@implementation NSException(Backtrace)
+
++ (NSString *)backtrace
+{
+    return nil;
+}
++ (void)printBacktrace
+{
+}
+
+@end
+
+#endif
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSExceptionWithoutNested.h b/libFoundation/Foundation/NSExceptionWithoutNested.h
new file mode 100644 (file)
index 0000000..0526703
--- /dev/null
@@ -0,0 +1,301 @@
+/* 
+   NSExceptionWithoutNested.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSException_h__
+#define __NSException_h__
+
+#include <setjmp.h>
+#include <stdarg.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSArray.h>
+
+@class NSNotification, NSString, NSDictionary;
+
+@interface NSException : NSObject
+{
+    NSString     *name;
+    NSString     *reason;
+    NSDictionary *userInfo;
+}
+
+/* Class initalization */
++ (void)taskNowMultiThreaded:(NSNotification *)notification;
+
+/* Creating and Raising Exceptions */
++ (NSException *)exceptionWithName:(NSString*)name
+  reason:(NSString*)reason
+  userInfo:(NSDictionary *)userInfo;
++ (void)raise:(NSString *)name
+  format:(NSString *)format,...;
++ (void)raise:(NSString *)name
+  format:(NSString *)format
+  arguments:(va_list)argList;
+
+- (id)initWithName:(NSString*)name
+  reason:(NSString *)reason
+  userInfo:(NSDictionary *)userInfo;
+- (void)raise;
+
+/* Querying Exceptions */
+- (NSString*)name;
+- (NSString*)reason;
+- (NSDictionary*)userInfo;
+
+@end /* NSException */
+
+
+@interface NSException (Extensions)
+- (BOOL)exceptionIsKindOfClass:(Class)class;
+                               /* return [self isKindOfClass:class] */
+- (BOOL)exceptionIsIn:(NSArray*)exceptions;
+- (NSString*)errorString;
+- initWithFormat:(NSString*)format, ...;
+- setName:(NSString*)name;
+- setReason:(NSString*)reason;
+- setUserInfo:(NSDictionary*)userInfo;
+@end /* NSException (Extension) */
+
+@interface NSException (Backtrace)
++ (NSString *)backtrace;
++ (void)printBacktrace;
+@end /* NSException(Backtrace) */
+
+typedef void NSUncaughtExceptionHandler(NSException *exception);
+
+NSUncaughtExceptionHandler *NSGetUncaughtExceptionHandler(void);
+void NSSetUncaughtExceptionHandler(NSUncaughtExceptionHandler *handler);
+
+/* Exception names */
+LF_EXPORT NSString *NSInconsistentArchiveException;
+LF_EXPORT NSString *NSGenericException;
+LF_EXPORT NSString *NSInternalInconsistencyException;
+LF_EXPORT NSString *NSInvalidArgumentException;
+LF_EXPORT NSString *NSMallocException;
+LF_EXPORT NSString *NSObjectInaccessibleException;
+LF_EXPORT NSString *NSObjectNotAvailableException;
+LF_EXPORT NSString *NSDestinationInvalidException;
+LF_EXPORT NSString *NSPortTimeoutException;
+LF_EXPORT NSString *NSInvalidSendPortException;
+LF_EXPORT NSString *NSInvalidReceivePortException;
+LF_EXPORT NSString *NSPortSendException;
+LF_EXPORT NSString *NSPortReceiveException;
+LF_EXPORT NSString *NSOldStyleException;
+LF_EXPORT NSString *NSRangeException;
+
+
+typedef struct _NSHandler
+{
+    struct _NSHandler* previousHandler;
+    jmp_buf            jmpState;
+    NSException*       exception;
+} NSHandler;
+
+LF_EXPORT void _NSAddHandler(NSHandler *handler);
+LF_EXPORT void _NSRemoveHandler(NSHandler *handler);
+
+/*  OpenStep macros for exception handling. */
+
+#define NS_DURING \
+({ \
+    __label__ _quit; \
+    NSHandler exceptionHandler; \
+    if(!setjmp(exceptionHandler.jmpState)) { \
+       _NSAddHandler(&exceptionHandler);
+
+#define NS_HANDLER \
+       _NSRemoveHandler(&exceptionHandler); \
+       goto _quit; /* to remove compiler warning about unused label*/ \
+    } \
+    else { \
+       NSException* localException = exceptionHandler.exception; \
+       _NSRemoveHandler(&exceptionHandler); \
+
+#define NS_ENDHANDLER \
+       localException = nil; /* Avoid compiler warning */ \
+    } \
+_quit: 0;\
+});
+
+#define NS_VALRETURN(value) \
+    ({_NSRemoveHandler(&exceptionHandler); return (value);})
+
+#define NS_VOIDRETURN \
+    ({_NSRemoveHandler(&exceptionHandler); return;})
+
+
+/*
+ * The new macros for handling exceptions.
+ */
+
+#define TRY \
+    NS_DURING
+
+#define END_TRY \
+    NS_HANDLER { \
+       BOOL _caught = NO; \
+       if (0) {
+
+#define CATCH(exception_class) \
+    } else if ([localException isKindOfClass:[exception_class class]]) { \
+       _caught = YES;
+
+#define MULTICATCH(exception_classes...) \
+    } else if([localException exceptionIsIn: \
+           [NSArray arrayWithObjects:##exception_classes, nil]]) { \
+       _caught = YES;
+
+#define OTHERWISE \
+    } else { \
+       _caught = YES;
+
+#define CLEANUP \
+# error "CLEANUP not supported"
+
+#define FINALLY \
+# error "FINALLY not supported"
+
+#define END_CATCH \
+       } \
+       if (!_caught) \
+           [localException raise]; \
+    } \
+    NS_ENDHANDLER
+
+
+    /*  Use BREAK inside a TRY block to get out of it */
+#define BREAK  ({_NSRemoveHandler(&exceptionHandler); goto _quit;})
+
+#ifndef PRECOMP
+    /*  If you want to generate an exception issue a THROW with the exception
+       an object derived from the NSException class. */
+# define THROW(exception...)   [exception raise]
+#else
+# define THROW(exception)              [exception raise]
+#endif /* PRECOMP */
+
+    /*  If you want to reraise an exception inside an exception handler
+       just say RERAISE. */
+#define RERAISE                 THROW(localException)
+
+
+/*
+ * Assertions.
+ */
+
+#ifndef __FoundationException_definition__
+#define __FoundationException_definition__
+
+@interface FoundationException : NSException
+@end
+
+#endif /* __FoundationException_definition__ */
+
+@interface AssertException : FoundationException
+@end
+
+
+@interface NSAssertionHandler : NSObject
+
+/* Getting the Current Handler */
++ (NSAssertionHandler*)currentHandler;
+
+/* Handling Failures */
+- (void)handleFailureInFunction:(NSString*)functionName
+    file:(NSString*)fileName
+    lineNumber:(int)line
+    description:(NSString*)format,...;
+- (void)handleFailureInMethod:(SEL)selector
+    object:(id)object
+    file:(NSString*)fileName
+    lineNumber:(int)line
+    description:(NSString*)format,...;
+
+@end
+
+#ifndef PRECOMP
+
+#define NSAssert(condition, desc, arguments...) \
+    ({ if(!(condition)) \
+           [[NSAssertionHandler currentHandler] \
+                   handleFailureInMethod:_cmd \
+                   object:self \
+                   file:[NSString stringWithCString:__FILE__] \
+                   lineNumber:__LINE__ \
+                   description:(desc) , ##arguments]; \
+    0;})
+
+#define NSCAssert(condition, desc, arguments...) \
+    ({ if(!(condition)) \
+           [[NSAssertionHandler currentHandler] \
+                   handleFailureInFunction: \
+                       [NSString stringWithCString:__PRETTY_FUNCTION__] \
+                   file:[NSString stringWithCString:__FILE__] \
+                   lineNumber:__LINE__ \
+                   description:(desc) , ##arguments]; \
+    0;})
+
+#define Assert(condition) \
+    ({if(!(condition)) {\
+       NSLog([(@#condition) stringByPrependingString:@"Assertion failed: "]); \
+       THROW([AssertException new]); \
+    } \
+    0;})
+
+# define NSParameterAssert(condition) \
+    ({if(!(condition)) {\
+       NSLog([(@#condition) stringByPrependingString:@"Parameter Assertion failed: "]); \
+       THROW([AssertException new]); \
+    } \
+    0;})
+
+# define NSCParameterAssert(condition) \
+    ({if(!(condition)) {\
+       NSLog([(@#condition) stringByPrependingString:@"Parameter Assertion failed: "]); \
+       THROW([AssertException new]); \
+    } \
+    0;})
+
+#define NSAssert1(args...)     NSAssert(args)
+#define NSAssert2(args...)     NSAssert(args)
+#define NSAssert3(args...)     NSAssert(args)
+#define NSAssert4(args...)     NSAssert(args)
+#define NSAssert5(args...)     NSAssert(args)
+
+#define NSCAssert1(args...)    NSCAssert(args)
+#define NSCAssert2(args...)    NSCAssert(args)
+#define NSCAssert3(args...)    NSCAssert(args)
+#define NSCAssert4(args...)    NSCAssert(args)
+#define NSCAssert5(args...)    NSCAssert(args)
+
+#endif /* PRECOMP */
+
+
+#endif /* __NSException_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSExpression.h b/libFoundation/Foundation/NSExpression.h
new file mode 100644 (file)
index 0000000..a40090f
--- /dev/null
@@ -0,0 +1,74 @@
+/* 
+   NSExpression.h
+
+   Copyright (C) 2005, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@opengroupware.org>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSExpression_H__
+#define __NSExpression_H__
+
+#include <Foundation/NSObject.h>
+
+typedef enum {
+    NSConstantValueExpressionType = 0,
+    NSEvaluatedObjectExpressionType,
+    NSVariableExpressionType,
+    NSKeyPathExpressionType,
+    NSFunctionExpressionType
+} NSExpressionType;
+
+@class NSString, NSArray, NSMutableDictionary;
+
+@interface NSExpression : NSObject < NSCoding, NSCopying >
+
++ (NSExpression *)expressionForConstantValue:(id)_value;
++ (NSExpression *)expressionForEvaluatedObject;
++ (NSExpression *)expressionForFunction:(NSString *)_f arguments:(NSArray *)_a;
++ (NSExpression *)expressionForKeyPath:(NSString *)_keyPath;
++ (NSExpression *)expressionForVariable:(NSString *)_varName;
+
+- (id)initWithExpressionType:(NSExpressionType)_type;
+
+/* accessors */
+
+- (id)constantValue;
+- (NSExpressionType)expressionType;
+
+- (NSString *)keyPath;
+- (NSExpression *)operand;
+- (NSString *)function;
+- (NSString *)variable;
+- (NSArray *)arguments;
+
+/* evaluation */
+
+- (id)expressionValueWithObject:(id)_object context:(NSMutableDictionary *)_cx;
+
+@end
+
+#endif /* __NSExpression_H__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSExpression.m b/libFoundation/Foundation/NSExpression.m
new file mode 100644 (file)
index 0000000..1496fcc
--- /dev/null
@@ -0,0 +1,382 @@
+/* 
+   NSExpression.m
+
+   Copyright (C) 2005, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@opengroupware.org>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include "NSExpression.h"
+
+@class NSString, NSArray;
+
+@interface NSSelfExpression : NSExpression
+@end
+
+@interface NSConstantValueExpression : NSExpression
+{
+@public
+    id value;
+}
+@end
+
+@interface NSKeyPathExpression : NSExpression
+{
+@public
+    NSString *keyPath;
+}
+@end
+
+@interface NSVariableExpression : NSExpression
+{
+@public
+    NSString *varname;
+}
+@end
+
+@interface NSFunctionExpression : NSExpression
+{
+@public
+    NSString *funcname;
+    NSArray  *parameters;
+}
+@end
+
+#include "NSCoder.h"
+#include "NSArray.h"
+#include "NSDictionary.h"
+#include "NSKeyValueCoding.h"
+#include "common.h"
+
+@implementation NSExpression
+
++ (NSExpression *)expressionForConstantValue:(id)_value
+{
+    NSConstantValueExpression *e;
+    
+    e = [[[NSConstantValueExpression alloc] 
+            initWithExpressionType:NSConstantValueExpressionType]
+            autorelease];
+    e->value = [_value retain];
+    return e;
+}
+
++ (NSExpression *)expressionForEvaluatedObject
+{
+    static NSSelfExpression *me = nil; // THREAD?
+    if (me == nil) {
+       me = [[NSSelfExpression alloc] initWithExpressionType:
+                                          NSEvaluatedObjectExpressionType];
+    }
+    return me;
+}
+
++ (NSExpression *)expressionForFunction:(NSString *)_f arguments:(NSArray *)_a
+{
+    NSFunctionExpression *e;
+
+    e = [[[NSFunctionExpression alloc] 
+            initWithExpressionType:NSFunctionExpressionType] autorelease];
+    e->funcname   = [_f copy];
+    e->parameters = [_a retain];
+    return e;
+}
+
++ (NSExpression *)expressionForKeyPath:(NSString *)_keyPath
+{
+    NSKeyPathExpression *e;
+    
+    e = [[[NSKeyPathExpression alloc] 
+            initWithExpressionType:NSKeyPathExpressionType] autorelease];
+    e->keyPath = [_keyPath copy];
+    return e;
+}
+
++ (NSExpression *)expressionForVariable:(NSString *)_varName
+{
+    NSVariableExpression *e;
+
+    e = [[[NSVariableExpression alloc] 
+            initWithExpressionType:NSVariableExpressionType] autorelease];
+    e->varname = [_varName copy];
+    return e;
+}
+
+
+- (id)initWithExpressionType:(NSExpressionType)_type
+{
+    if ((self = [super init]) != nil) {
+    }
+    return self;
+}
+- (id)init
+{
+    return [self initWithExpressionType:NSConstantValueExpressionType];
+}
+
+/* accessors */
+
+- (NSExpressionType)expressionType
+{
+    return NSConstantValueExpressionType;
+}
+
+- (NSExpression *)operand
+{
+    // TODO: explain
+    return nil;
+}
+
+- (id)constantValue
+{
+    return nil;
+}
+
+- (NSString *)keyPath
+{
+    return nil;
+}
+
+- (NSString *)variable
+{
+    return nil;
+}
+
+- (NSString *)function
+{
+    return nil;
+}
+- (NSArray *)arguments
+{
+    return nil;
+}
+
+/* evaluation */
+
+- (id)expressionValueWithObject:(id)_obj context:(NSMutableDictionary *)_ctx
+{
+    return nil;
+}
+
+/* NSCoding */
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+}
+- (id)initWithCoder:(NSCoder*)aDecoder
+{
+    return self;
+}
+
+/* NSCopying */
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    /* NSExpression objects are immutable! */
+    return [self retain];
+}
+
+@end /* NSExpression */
+
+
+@implementation NSSelfExpression
+
+/* evaluation */
+
+- (id)expressionValueWithObject:(id)_obj context:(NSMutableDictionary *)_ctx
+{
+    return _obj;
+}
+
+@end /* NSSelfExpression */
+
+
+@implementation NSConstantValueExpression
+
+- (void)dealloc
+{
+    [self->value release];
+    [super dealloc];
+}
+
+/* accessors */
+
+- (id)constantValue
+{
+    return self->value;
+}
+
+/* evaluation */
+
+- (id)expressionValueWithObject:(id)_obj context:(NSMutableDictionary *)_ctx
+{
+    return self->value;
+}
+
+/* NSCoding */
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+    [super encodeWithCoder:aCoder];
+    [aCoder encodeObject:self->value];
+}
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+    if ((self = [super initWithCoder:aDecoder]) != nil) {
+       self->value = [[aDecoder decodeObject] retain];
+    }
+    return self;
+}
+
+@end /* NSConstantValueExpression */
+
+
+@implementation NSKeyPathExpression
+
+- (void)dealloc
+{
+    [self->keyPath release];
+    [super dealloc];
+}
+
+/* accessors */
+
+- (NSString *)keyPath
+{
+    return self->keyPath;
+}
+
+/* evaluation */
+
+- (id)expressionValueWithObject:(id)_obj context:(NSMutableDictionary *)_ctx
+{
+    return [_obj valueForKeyPath:self->keyPath];
+}
+
+/* NSCoding */
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+    [super encodeWithCoder:aCoder];
+    [aCoder encodeObject:self->keyPath];
+}
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+    if ((self = [super initWithCoder:aDecoder]) != nil) {
+       self->keyPath = [[aDecoder decodeObject] copy];
+    }
+    return self;
+}
+
+@end /* NSKeyPathExpression */
+
+
+@implementation NSVariableExpression
+
+- (void)dealloc
+{
+    [self->varname release];
+    [super dealloc];
+}
+
+/* evaluation */
+
+- (id)expressionValueWithObject:(id)_obj context:(NSMutableDictionary *)_ctx
+{
+    // TODO: correct? Remove support for ctx pathes?
+    return [_ctx valueForKeyPath:self->varname];
+}
+
+/* accessors */
+
+- (NSString *)variable
+{
+    return self->varname;
+}
+
+/* NSCoding */
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+    [super encodeWithCoder:aCoder];
+    [aCoder encodeObject:self->varname];
+}
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+    if ((self = [super initWithCoder:aDecoder]) != nil) {
+       self->varname = [[aDecoder decodeObject] copy];
+    }
+    return self;
+}
+
+@end /* NSVariableExpression */
+
+
+@implementation NSFunctionExpression
+
+- (void)dealloc
+{
+    [self->funcname   release];
+    [self->parameters release];
+    [super dealloc];
+}
+
+/* accessors */
+
+- (NSString *)function
+{
+    return self->funcname;
+}
+- (NSArray *)arguments
+{
+    return self->parameters;
+}
+
+/* evaluation */
+
+- (id)expressionValueWithObject:(id)_obj context:(NSMutableDictionary *)_ctx
+{
+    return [self notImplemented:_cmd];
+}
+
+/* NSCoding */
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+    [super encodeWithCoder:aCoder];
+    [aCoder encodeObject:self->funcname];
+    [aCoder encodeObject:self->parameters];
+}
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+    if ((self = [super initWithCoder:aDecoder]) != nil) {
+       self->funcname   = [[aDecoder decodeObject] copy];
+       self->parameters = [[aDecoder decodeObject] retain];
+    }
+    return self;
+}
+
+@end /* NSFunctionExpression */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSFileHandle.h b/libFoundation/Foundation/NSFileHandle.h
new file mode 100644 (file)
index 0000000..5ddce09
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+   NSFileHandle.h
+
+   Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@net-community.com>
+   Date: May 1997
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+#ifndef __NSFileHandle_h__
+#define __NSFileHandle_h__
+
+#include <Foundation/NSObject.h>
+
+@class NSString;
+@class NSData;
+@class NSArray;
+
+@interface NSFileHandle : NSObject
+
+/* Getting an NSFileHandle */
++ (id)fileHandleForReadingAtPath:(NSString*)path;
++ (id)fileHandleForWritingAtPath:(NSString*)path;
++ (id)fileHandleForUpdatingAtPath:(NSString*)path;
++ (id)fileHandleWithStandardInput;
++ (id)fileHandleWithStandardOutput;
++ (id)fileHandleWithStandardError;
++ (id)fileHandleWithNullDevice;
+
+@end
+
+
+@interface NSFileHandle (NSFileHandleInitialization)
+
+/* Creating an NSFileHandle */
+- (id)initWithFileDescriptor:(int)fd;
+- (id)initWithFileDescriptor:(int)fd closeOnDealloc:(BOOL)flag;
+
+#if defined(WIN32)
+- (id)initWithNativeHandle:(void *)_handle;
+- (id)initWithNativeHandle:(void *)_handle closeOnDealloc:(BOOL)flag;
+#endif /* WIN32 */
+
+@end
+
+
+@interface NSFileHandle (NSFileHandleOperations)
+
+/* Getting a file descriptor */
+- (int)fileDescriptor;
+#if defined(WIN32)
+- (void *)nativeHandle;
+#endif /* WIN32 */
+
+/* Reading from an NSFileHandle */
+- (NSData *)availableData;
+- (NSData *)readDataToEndOfFile;
+- (NSData *)readDataOfLength:(unsigned int)length;
+
+/* Writing to an NSFileHandle */
+- (void)writeData:(NSData*)data;
+
+/* Communicating asynchronously in the background */
+- (void)acceptConnectionInBackgroundAndNotifyForModes:(NSArray*)modes;
+- (void)acceptConnectionInBackgroundAndNotify;
+- (void)readInBackgroundAndNotifyForModes:(NSArray*)modes;
+- (void)readInBackgroundAndNotify;
+- (void)readToEndOfFileInBackgroundAndNotifyForModes:(NSArray*)modes;
+- (void)readToEndOfFileInBackgroundAndNotify;
+
+/* Seeking within a file */
+- (unsigned long long)offsetInFile;
+- (unsigned long long)seekToEndOfFile;
+- (void)seekToFileOffset:(unsigned long long)offset;
+
+/* Operating on a file */
+- (void)closeFile;
+- (void)synchronizeFile;
+- (void)truncateFileAtOffset:(unsigned long long)offset;
+
+@end
+
+
+@interface NSPipe : NSObject
+
++ (id)pipe;
+
+- (NSFileHandle *)fileHandleForReading;
+- (NSFileHandle *)fileHandleForWriting;
+
+- (id)init;
+
+@end
+
+
+/* Notifications posted by NSFileHandle */
+LF_EXPORT NSString *NSFileHandleConnectionAcceptedNotification;
+LF_EXPORT NSString *NSFileHandleReadCompletionNotification;
+LF_EXPORT NSString *NSFileHandleReadToEndOfFileCompletionNotification;
+
+
+/* Keys for accessing user info dictionary */
+
+LF_EXPORT NSString *NSFileHandleNotificationFileHandleItem;
+    /* The new file handle object obtained after an accept operation. */
+
+LF_EXPORT NSString *NSFileHandleNotificationDataItem;
+    /* The data object containing the data read from the file descriptor by 
+       a background read operation. */
+
+LF_EXPORT NSString *NSFileHandleNotificationMonitorModes;
+    /* The run loop modes in which the notification can be posted. */
+
+#endif /* __NSFileHandle_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSFileHandle.m b/libFoundation/Foundation/NSFileHandle.m
new file mode 100644 (file)
index 0000000..e1c064b
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+   NSFileHandle.m
+
+   Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@net-community.com>
+   Date: May 1997
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+
+#include <fcntl.h>
+#include <sys/types.h>
+
+#include <Foundation/NSFileHandle.h>
+#include "NSConcreteFileHandle.h"
+
+@implementation NSFileHandle
+
+static NSFileHandle *nullDevice = nil;
+
++ (void)initialize
+{
+#ifdef WIN32
+    static WSADATA wsaData;
+    WSAStartup(MAKEWORD(1, 1), &wsaData);
+#endif
+}
+
++ (id)allocWithZone:(NSZone*)zone
+{
+    return (self == [NSFileHandle class])
+       ? [NSConcreteFileHandle allocWithZone:zone] 
+       : NSAllocateObject(self, 0, zone);
+}
+
++ (id)fileHandleForReadingAtPath:(NSString*)path
+{
+    return [NSConcreteFileHandle fileHandleForReadingAtPath:path];
+}
++ (id)fileHandleForWritingAtPath:(NSString*)path
+{
+    return [NSConcreteFileHandle fileHandleForWritingAtPath:path];
+}
++ (id)fileHandleForUpdatingAtPath:(NSString*)path
+{
+    return [NSConcreteFileHandle fileHandleForUpdatingAtPath:path];
+}
+
+#ifdef __MINGW32__
+
++ (id)fileHandleWithStandardInput
+{
+    return AUTORELEASE([[self alloc] initWithNativeHandle:
+                                        GetStdHandle(STD_INPUT_HANDLE)]);
+}
++ (id)fileHandleWithStandardOutput
+{
+    return AUTORELEASE([[self alloc] initWithNativeHandle:
+                                        GetStdHandle(STD_OUTPUT_HANDLE)]);
+}
++ (id)fileHandleWithStandardError
+{
+    return AUTORELEASE([[self alloc] initWithNativeHandle:
+                                        GetStdHandle(STD_ERROR_HANDLE)]);
+}
+
+#else /* !__MINGW32__ */
+
++ (id)fileHandleWithStandardInput
+{
+    return AUTORELEASE([[self alloc] initWithFileDescriptor:0]);
+}
+
++ (id)fileHandleWithStandardOutput
+{
+    return AUTORELEASE([[self alloc] initWithFileDescriptor:1]);
+}
+
++ (id)fileHandleWithStandardError
+{
+    return AUTORELEASE([[self alloc] initWithFileDescriptor:2]);
+}
+
+#endif /* !__MINGW32__ */
+
++ (id)fileHandleWithNullDevice
+{
+    if (!nullDevice)
+        nullDevice = [NSNullDeviceFileHandle new];
+
+    return nullDevice;
+}
+
+@end /* NSFileHandle */
+
+
+LF_DECLARE NSString *NSFileHandleConnectionAcceptedNotification
+    = @"NSFileHandleConnectionAcceptedNotification";
+
+LF_DECLARE NSString *NSFileHandleReadCompletionNotification
+    = @"NSFileHandleReadCompletionNotification";
+
+LF_DECLARE NSString *NSFileHandleReadToEndOfFileCompletionNotification
+    = @"NSFileHandleReadToEndOfFileCompletionNotification";
+
+LF_DECLARE NSString *NSFileHandleNotificationFileHandleItem
+    = @"NSFileHandleNotificationFileHandleItem";
+
+LF_DECLARE NSString *NSFileHandleNotificationDataItem
+    = @"NSFileHandleNotificationDataItem";
+
+NSString* NSFileHandleNotificationMonitorModes
+    = @"NSFileHandleNotificationMonitorModes";
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSFileManager.h b/libFoundation/Foundation/NSFileManager.h
new file mode 100644 (file)
index 0000000..5a5c712
--- /dev/null
@@ -0,0 +1,192 @@
+/* 
+   NSFileManager.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSFileManager_h__
+#define __NSFileManager_h__
+
+#include <Foundation/NSObject.h>
+#include <Foundation/NSUtilities.h>
+#include <Foundation/NSDictionary.h>
+
+#if defined(__MINGW32__)
+#  include <windows.h>
+#endif
+
+@class NSNumber;
+@class NSString;
+@class NSData;
+@class NSDate;
+@class NSArray;
+@class NSMutableArray;
+
+@class NSDirectoryEnumerator;
+
+@interface NSFileManager : NSObject
+
+// Getting the default manager
++ (NSFileManager*)defaultManager;
+
+// Directory operations
+- (BOOL)changeCurrentDirectoryPath:(NSString*)path;
+- (BOOL)createDirectoryAtPath:(NSString*)path
+  attributes:(NSDictionary*)attributes;
+- (NSString*)currentDirectoryPath;
+
+// File operations
+- (BOOL)copyPath:(NSString*)source toPath:(NSString*)destination
+  handler:handler;
+- (BOOL)movePath:(NSString*)source toPath:(NSString*)destination 
+  handler:handler;
+- (BOOL)linkPath:(NSString*)source toPath:(NSString*)destination
+  handler:handler;
+- (BOOL)removeFileAtPath:(NSString*)path
+  handler:handler;
+- (BOOL)createFileAtPath:(NSString*)path contents:(NSData*)contents
+  attributes:(NSDictionary*)attributes;
+
+// Getting and comparing file contents 
+- (NSData*)contentsAtPath:(NSString*)path;
+- (BOOL)contentsEqualAtPath:(NSString*)path1 andPath:(NSString*)path2;
+
+// Determining access to files
+- (BOOL)fileExistsAtPath:(NSString*)path;
+- (BOOL)fileExistsAtPath:(NSString*)path isDirectory:(BOOL*)isDirectory;
+- (BOOL)isReadableFileAtPath:(NSString*)path;
+- (BOOL)isWritableFileAtPath:(NSString*)path;
+- (BOOL)isExecutableFileAtPath:(NSString*)path;
+- (BOOL)isDeletableFileAtPath:(NSString*)path;
+
+// Getting and setting attributes
+- (NSDictionary*)fileAttributesAtPath:(NSString*)path traverseLink:(BOOL)flag;
+- (NSDictionary*)fileSystemAttributesAtPath:(NSString*)path;
+- (BOOL)changeFileAttributes:(NSDictionary*)attributes atPath:(NSString*)path;
+
+// Discovering directory contents
+- (NSArray*)directoryContentsAtPath:(NSString*)path;
+- (NSDirectoryEnumerator*)enumeratorAtPath:(NSString*)path;
+- (NSArray*)subpathsAtPath:(NSString*)path;
+
+// Symbolic-link operations
+- (BOOL)createSymbolicLinkAtPath:(NSString*)path
+  pathContent:(NSString*)otherPath;
+- (NSString*)pathContentOfSymbolicLinkAtPath:(NSString*)path;
+
+// Converting file-system representations
+- (const char*)fileSystemRepresentationWithPath:(NSString*)path;
+- (NSString*)stringWithFileSystemRepresentation:(const char*)string
+  length:(unsigned int)len;
+
+@end /* NSFileManager */
+
+
+@interface NSObject (NSFileManagerHandler)
+- (BOOL)fileManager:(NSFileManager*)fileManager
+  shouldProceedAfterError:(NSDictionary*)errorDictionary;
+- (void)fileManager:(NSFileManager*)fileManager
+  willProcessPath:(NSString*)path;
+@end
+
+
+@interface NSDirectoryEnumerator : NSEnumerator
+{
+    NSMutableArray *enumStack;
+    NSMutableArray *pathStack;
+    NSString       *currentFileName;
+    NSString       *currentFilePath;
+    NSString       *topPath;
+    struct {
+       BOOL isRecursive:1;
+       BOOL isFollowing:1;
+   } flags;
+}
+
+// Initializing
+- (id)initWithDirectoryPath:(NSString *)path 
+  recurseIntoSubdirectories:(BOOL)recurse
+  followSymlinks:(BOOL)follow
+  prefixFiles:(BOOL)prefix;
+
+// Getting attributes
+- (NSDictionary *)directoryAttributes;
+- (NSDictionary *)fileAttributes;
+
+// Skipping subdirectories
+- (void)skipDescendents;
+
+@end /* NSDirectoryEnumerator */
+
+/* File Attributes */
+
+LF_EXPORT NSString *NSFileSize;
+LF_EXPORT NSString *NSFileModificationDate;
+LF_EXPORT NSString *NSFileOwnerAccountNumber;
+LF_EXPORT NSString *NSFileOwnerAccountName;
+LF_EXPORT NSString *NSFileGroupOwnerAccountNumber;
+LF_EXPORT NSString *NSFileGroupOwnerAccountName;
+LF_EXPORT NSString *NSFileReferenceCount;
+LF_EXPORT NSString *NSFileIdentifier;
+LF_EXPORT NSString *NSFileDeviceIdentifier;
+LF_EXPORT NSString *NSFilePosixPermissions;
+LF_EXPORT NSString *NSFileType;
+
+/* File Types */
+
+LF_EXPORT NSString *NSFileTypeDirectory;
+LF_EXPORT NSString *NSFileTypeRegular;
+LF_EXPORT NSString *NSFileTypeSymbolicLink;
+LF_EXPORT NSString *NSFileTypeSocket;
+LF_EXPORT NSString *NSFileTypeFifo;
+LF_EXPORT NSString *NSFileTypeCharacterSpecial;
+LF_EXPORT NSString *NSFileTypeBlockSpecial;
+LF_EXPORT NSString *NSFileTypeUnknown;
+
+/* FileSystem Attributes */
+
+LF_EXPORT NSString *NSFileSystemFileNumber;
+LF_EXPORT NSString *NSFileSystemSize;
+LF_EXPORT NSString *NSFileSystemFreeSize;
+LF_EXPORT NSString *NSFileSystemNodes;
+LF_EXPORT NSString *NSFileSystemFreeNodes;
+LF_EXPORT NSString *NSFileSystemNumber;
+
+/* Easy access to attributes in a dictionary */
+
+@interface NSDictionary(NSFileAttributes)
+- (NSNumber*)fileSize;
+- (NSString*)fileType;
+- (NSNumber*)fileOwnerAccountNumber;
+- (NSNumber*)fileGroupOwnerAccountNumber;
+- (NSDate*)fileModificationDate;
+- (NSNumber*)filePosixPermissions;
+@end
+
+
+#endif /* __NSFileManager_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSFileManager.m b/libFoundation/Foundation/NSFileManager.m
new file mode 100644 (file)
index 0000000..786e074
--- /dev/null
@@ -0,0 +1,1671 @@
+/* 
+   NSFileManager.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+          Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+           Helge Hess <helge@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <objc/objc.h>
+
+#include <stdio.h>
+
+/* determine directory reading files */
+
+#if defined(HAVE_DIRENT_H)
+#  include <dirent.h>
+#elif defined(HAVE_SYS_DIR_H)
+#  include <sys/dir.h>
+#elif defined(HAVE_SYS_NDIR_H)
+#  include <sys/ndir.h>
+#elif defined(HAVE_NDIR_H)
+#  include <ndir.h>
+#elif defined(HAVE_DIR_H)
+#  include <dir.h>
+#endif
+
+#if defined(HAVE_WINDOWS_H)
+#  include <windows.h>
+#endif
+
+#if !defined(_POSIX_VERSION)
+#  if defined(NeXT)
+#    define DIR_enum_item struct direct
+#  endif
+#endif
+
+#if !defined(DIR_enum_item)
+#  define DIR_enum_item struct dirent
+#endif
+
+#define DIR_enum_state DIR
+
+/* determine filesystem max path length */
+
+#if defined(_POSIX_VERSION) || defined(__WIN32__)
+# include <limits.h>                   /* for PATH_MAX */
+# if defined(__MINGW32__)
+#   include <sys/utime.h>
+# else
+#   include <utime.h>
+# endif
+#else
+# if HAVE_SYS_PARAM_H
+#  include <sys/param.h>               /* for MAXPATHLEN */
+# endif
+#endif
+
+#ifndef PATH_MAX
+# ifdef _POSIX_VERSION
+#  define PATH_MAX _POSIX_PATH_MAX
+# else
+#  ifdef MAXPATHLEN
+#   define PATH_MAX MAXPATHLEN
+#  else
+#   define PATH_MAX 1024
+#  endif
+# endif
+#endif
+
+/* determine if we have statfs struct and function */
+
+#ifdef HAVE_SYS_STATFS_H
+# include <sys/statfs.h>
+#endif
+
+#ifdef HAVE_SYS_STATVFS_H
+# include <sys/statvfs.h>
+#endif
+
+#ifdef HAVE_SYS_VFS_H
+# include <sys/vfs.h>
+#endif
+
+#if HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+
+#include <fcntl.h>
+
+#if HAVE_UTIME_H
+# include <utime.h>
+#endif
+
+/* include usual headers */
+
+#include <Foundation/NSArray.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSData.h>
+#include <Foundation/NSDate.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSValue.h>
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/NSPathUtilities.h>
+#include <Foundation/NSThread.h>
+#include <Foundation/NSLock.h>
+#include <Foundation/NSNotification.h>
+#include <Foundation/NSFileManager.h>
+#include <Foundation/NSException.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+
+@interface NSFileManager (PrivateMethods)
+
+/* Copies the contents of source file to destination file. Assumes source
+   and destination are regular files or symbolic links. */
+- (BOOL)_copyFile:(NSString*)source toFile:(NSString*)destination
+  handler:handler;
+
+/* Recursively copies the contents of source directory to destination. */
+- (BOOL)_copyPath:(NSString*)source toPath:(NSString*)destination
+  handler:handler;
+
+@end /* NSFileManager (PrivateMethods) */
+
+
+/*
+ * NSFileManager implementation
+ */
+
+@implementation NSFileManager
+
+// Getting the default manager
+
+static BOOL isMultithreaded = NO;
+static NSFileManager* defaultManager = nil;
+
++ (void)initialize
+{
+    static BOOL initialized = NO;
+
+    if (!initialized) {
+       defaultManager = [[self alloc] init];
+       [[NSNotificationCenter defaultCenter]
+           addObserver:self
+           selector:@selector(taskNowMultiThreaded:)
+           name:NSWillBecomeMultiThreadedNotification
+           object:nil];
+       initialized = YES;
+    }
+}
+
++ (void)taskNowMultiThreaded:notification
+{
+    NSThread* currentThread = [NSThread currentThread];
+
+    [[currentThread threadDictionary]
+       setObject:AUTORELEASE(defaultManager) forKey:@"DefaultNSFileManager"];
+    defaultManager = nil;
+    isMultithreaded = YES;
+}
+
+extern NSRecursiveLock* libFoundationLock;
+
++ (NSFileManager*)defaultManager
+{
+    if (isMultithreaded) {
+       NSThread* currentThread = [NSThread currentThread];
+       id manager;
+
+       [libFoundationLock lock];
+        {
+            manager = [[currentThread threadDictionary]
+                                      objectForKey:@"DefaultNSFileManager"];
+            if (!manager) {
+                manager = AUTORELEASE([[self alloc] init]);
+                [[currentThread threadDictionary]
+                                setObject:manager
+                                forKey:@"DefaultNSFileManager"];
+            }
+        }
+       [libFoundationLock unlock];
+
+       return manager;
+    } 
+    else
+       return defaultManager;
+}
+
+// Directory operations
+
+- (BOOL)changeCurrentDirectoryPath:(NSString*)path
+{
+    const char* cpath = [self fileSystemRepresentationWithPath:path];
+
+#if defined(__MINGW32__)
+    return SetCurrentDirectory(cpath) == TRUE ? YES : NO;
+#else
+    return (chdir(cpath) == 0);
+#endif
+}
+
+#if defined(__MINGW32__)
+- (BOOL)createDirectoryAtPath:(NSString*)path
+  attributes:(NSDictionary*)attributes
+{
+    NSEnumerator *paths = [[path pathComponents] objectEnumerator];
+    NSString     *subPath;
+    NSString     *completePath = nil;
+
+    while ((subPath = [paths nextObject])) {
+        BOOL isDir = NO;
+
+        completePath = (completePath == nil)
+            ? subPath
+            : [completePath stringByAppendingPathComponent:subPath];
+
+        if ([self fileExistsAtPath:completePath isDirectory:&isDir]) {
+            if (!isDir) {
+                fprintf(stderr,
+                        "WARNING: during creation of directory %s:"
+                        " sub path %s exists, but is not a directory !",
+                      [path cString], [completePath cString]);
+            }
+        }
+        else {
+            const char *cpath;
+            
+            cpath = [self fileSystemRepresentationWithPath:completePath];
+            if (CreateDirectory(cpath, NULL) == FALSE)
+                // creation failed
+                return NO;
+        }
+    }
+
+    // change attributes of last directory
+    return [self changeFileAttributes:attributes
+                 atPath:path];
+}
+
+#else
+
+- (BOOL)createDirectoryAtPath:(NSString*)path
+  attributes:(NSDictionary*)attributes
+{
+    const char* cpath;
+    char        dirpath[PATH_MAX+1];
+    struct stat statbuf;
+    int         len, cur;
+    
+    cpath = [self fileSystemRepresentationWithPath:path];
+    len = Strlen(cpath);
+    if (len > PATH_MAX)
+       // name too long
+       return NO;
+    
+    if (Strcmp(cpath, "/") == 0 || len == 0)
+       // cannot use "/" or "" as a new dir path
+       return NO;
+    
+    strcpy(dirpath, cpath);
+    dirpath[len] = '\0';
+    if (dirpath[len-1] == '/')
+       dirpath[len-1] = '\0';
+    cur = 0;
+    
+    do {
+       // find next path separator
+       while (dirpath[cur] != '/' && cur < len)
+           cur++;
+
+       // if first char is '/' then again; (cur == len) -> last component
+       if (cur == 0) {
+           cur++;
+           continue;
+       }
+       // check if path from 0 to cur is valid
+       dirpath[cur] = '\0';
+       if (stat(dirpath, &statbuf) == 0) {
+           if (cur == len)
+               return NO; // already existing last path
+       }
+       else {
+           // make new directory
+#if MKDIR_HAS_TWO_ARGS || defined(__CYGWIN32__)
+           if (mkdir(dirpath, 0777) != 0)
+#else
+           if (mkdir(dirpath) != 0)
+#endif
+               return NO; // could not create component
+           // if last directory and attributes then change
+           if (cur == len && attributes)
+               return [self changeFileAttributes:attributes 
+                   atPath:[self stringWithFileSystemRepresentation:dirpath
+                       length:cur]];
+       }
+       dirpath[cur] = '/';
+       cur++;
+    } while (cur < len);
+    
+    return YES;
+}
+#endif /* __MINGW32__ */
+
+- (NSString*)currentDirectoryPath
+{
+#if defined(__MINGW32__)
+    unsigned char *buf = objc_atomic_malloc(2048);
+    DWORD         len = GetCurrentDirectory(2046, buf);
+
+    if (len > 2046) {
+        buf = objc_realloc(buf, len + 2);
+        len = GetCurrentDirectory(len, buf);
+    }
+    if (len == 0) return nil;
+    self = [NSString stringWithCString:buf length:len];
+    objc_free(buf);
+    return self;
+#else
+    char path[PATH_MAX];
+#if defined(HAVE_GETCWD)
+    if (getcwd(path, PATH_MAX-1) == NULL)
+       return nil;
+#else
+    if (getwd(path) == NULL)
+       return nil;
+#endif /* HAVE_GETCWD */
+    return [self stringWithFileSystemRepresentation:path length:Strlen(path)];
+#endif /* __MINGW32__ */
+}
+
+// File operations
+
+- (BOOL)copyPath:(NSString*)source toPath:(NSString*)destination
+  handler:handler
+{
+    BOOL         sourceIsDir;
+    NSDictionary *attributes;
+
+    if (![self fileExistsAtPath:source isDirectory:&sourceIsDir])
+        // source must exist
+       return NO;
+
+    if ([self fileExistsAtPath:destination])
+        // destination must not exist
+       return NO;
+
+#if defined(__MINGW32__)
+    if (!CopyFile([self fileSystemRepresentationWithPath:source],
+                  [self fileSystemRepresentationWithPath:destination],
+                  FALSE /* overwrite if dest exists */)) {
+        if (handler) {
+            NSDictionary *errorInfo
+                = [NSDictionary dictionaryWithObjectsAndKeys:
+                                source,              @"Path",
+                                destination,         @"ToPath",
+                                @"cannot copy file", @"Error",
+                                nil];
+            if ([handler fileManager:self shouldProceedAfterError:errorInfo])
+                return YES;
+        }
+        return NO;
+    }
+    return YES;
+#else
+    attributes = [self fileAttributesAtPath:source traverseLink:NO];
+
+    if (sourceIsDir) {
+       /* If destination directory is a descendant of source directory copying
+           isn't possible. */
+       if ([[destination stringByAppendingString:@"/"]
+                          hasPrefix:[source stringByAppendingString:@"/"]])
+           return NO;
+
+       [handler fileManager:self willProcessPath:destination];
+       if (![self createDirectoryAtPath:destination attributes:attributes]) {
+           if (handler) {
+               NSDictionary* errorInfo
+                   = [NSDictionary dictionaryWithObjectsAndKeys:
+                       destination,                @"Path",
+                       @"cannot create directory", @"Error",
+                       nil];
+               return [handler fileManager:self
+                               shouldProceedAfterError:errorInfo];
+           }
+           else
+               return NO;
+       }
+    }
+
+    if (sourceIsDir) {
+       if (![self _copyPath:source toPath:destination handler:handler])
+           return NO;
+       else {
+           [self changeFileAttributes:attributes atPath:destination];
+           return YES;
+       }
+    }
+    else {
+       [handler fileManager:self willProcessPath:source];
+       if (![self _copyFile:source toFile:destination handler:handler])
+           return NO;
+       else {
+           [self changeFileAttributes:attributes atPath:destination];
+           return YES;
+       }
+    }
+    return NO;
+#endif
+}
+
+- (BOOL)movePath:(NSString*)source toPath:(NSString*)destination 
+  handler:(id)handler
+{
+    BOOL       sourceIsDir;
+    const char *sourcePath;
+    const char *destPath;
+#if !defined(__MINGW32__)
+    NSString* destinationParent;
+    unsigned int sourceDevice, destinationDevice;
+#endif
+
+    sourcePath = [self fileSystemRepresentationWithPath:source];
+    destPath   = [self fileSystemRepresentationWithPath:destination];
+    
+    if (![self fileExistsAtPath:source isDirectory:&sourceIsDir])
+        // source does not exist
+       return NO;
+
+    if ([self fileExistsAtPath:destination])
+        // destination does already exist
+       return NO;
+
+#if defined(__MINGW32__)
+    /*
+      Special handling for directories is required !
+      (See MoveFile on msdn)
+    */
+    if (!MoveFile(sourcePath, destPath)) {
+        if (handler) {
+            NSDictionary *errorInfo
+                = [NSDictionary dictionaryWithObjectsAndKeys:
+                                source,              @"Path",
+                                destination,         @"ToPath",
+                                @"cannot move file", @"Error",
+                                nil];
+            if ([handler fileManager:self shouldProceedAfterError:errorInfo])
+                return YES;
+        }
+        return NO;
+    }
+    return YES;
+#else
+    /* Check to see if the source and destination's parent are on the same
+       physical device so we can perform a rename syscall directly. */
+    sourceDevice = [[[self fileSystemAttributesAtPath:source]
+                           objectForKey:NSFileSystemNumber]
+                           unsignedIntValue];
+    destinationParent = [destination stringByDeletingLastPathComponent];
+    if ([destinationParent isEqual:@""])
+       destinationParent = @".";
+    destinationDevice
+       = [[[self fileSystemAttributesAtPath:destinationParent]
+                 objectForKey:NSFileSystemNumber]
+                 unsignedIntValue];
+
+    if (sourceDevice != destinationDevice) {
+       /* If destination directory is a descendant of source directory moving
+           isn't possible. */
+       if (sourceIsDir && [[destination stringByAppendingString:@"/"]
+                           hasPrefix:[source stringByAppendingString:@"/"]])
+           return NO;
+
+       if ([self copyPath:source toPath:destination handler:handler]) {
+           NSDictionary* attributes;
+
+           attributes = [self fileAttributesAtPath:source traverseLink:NO];
+           [self changeFileAttributes:attributes atPath:destination];
+           return [self removeFileAtPath:source handler:handler];
+       }
+       else
+           return NO;
+    }
+    else {
+       /* source and destination are on the same device so we can simply
+          invoke rename on source. */
+       [handler fileManager:self willProcessPath:source];
+       if (rename (sourcePath, destPath) == -1) {
+           if (handler) {
+               NSDictionary* errorInfo
+                   = [NSDictionary dictionaryWithObjectsAndKeys:
+                       source, @"Path",
+                       destination, @"ToPath",
+                       @"cannot move file", @"Error",
+                       nil];
+               if ([handler fileManager:self
+                            shouldProceedAfterError:errorInfo])
+                   return YES;
+           }
+           return NO;
+       }
+       return YES;
+    }
+#endif
+    return NO;
+}
+
+- (BOOL)linkPath:(NSString*)source toPath:(NSString*)destination
+  handler:handler
+{
+    // TODO
+    [self notImplemented:_cmd];
+    return NO;
+}
+
+- (BOOL)removeFileAtPath:(NSString *)path
+  handler:(id)handler
+{
+    // TODO: this method should be cleaned up !!!
+    NSDirectoryEnumerator *enumerator;
+    NSString              *dirEntry;
+    NSString              *completeFilename;
+    NSString              *fileType;
+    NSDictionary          *attributes;
+    const char            *cpath;
+    BOOL                  pathIsDir, fileExists;
+    CREATE_AUTORELEASE_POOL(pool);
+    
+    if (path == nil)
+       [[InvalidArgumentException new] raise];
+    
+    if ([path isEqual:@"."] || [path isEqual:@".."])
+       [[InvalidArgumentException new] raise];
+
+    fileExists = [self fileExistsAtPath:path isDirectory:&pathIsDir];
+    if (!fileExists)
+       return NO;
+
+    [handler fileManager:self willProcessPath:path];
+
+    if (!pathIsDir) {
+       cpath = [self fileSystemRepresentationWithPath:path];
+
+#if defined(__MINGW32__)
+        if (DeleteFile(cpath) == FALSE)
+#else
+        if (unlink(cpath)) /* use unlink, we know it's a file */
+#endif
+        {
+           if (handler) {
+               NSDictionary *errorInfo;
+                errorInfo =
+                   [NSDictionary dictionaryWithObjectsAndKeys:
+                                    path ? path : @"<nil>", @"Path",
+                                    @"cannot remove file", @"Error",
+                                    nil];
+               if (![handler fileManager:self
+                             shouldProceedAfterError:errorInfo])
+                   return NO;
+
+                /* intended fall-through ? [is this really correct?] */
+           }
+           else
+               return NO;
+       }
+        else
+            return YES;
+    }
+    else {
+        enumerator = [self enumeratorAtPath:path];
+        while ((dirEntry = [enumerator nextObject])) {
+       attributes = [enumerator fileAttributes];
+       fileType = [attributes objectForKey:NSFileType];
+       completeFilename = [path stringByAppendingPathComponent:dirEntry];
+    
+       if ([fileType isEqual:NSFileTypeDirectory]) {
+           /* Skip the descendants of this directory so they will not be
+              present in further steps. */
+           [enumerator skipDescendents];
+       }
+    
+       if (![self removeFileAtPath:completeFilename handler:handler])
+           return NO;
+        }
+    
+    
+       if (rmdir([self fileSystemRepresentationWithPath:path])) {
+           if (handler) {
+               NSDictionary *errorInfo;
+    
+                    errorInfo =
+                   [NSDictionary dictionaryWithObjectsAndKeys:
+                                        path ? path : @"<nil>", @"Path",
+                                        @"cannot remove directory", @"Error",
+                                        nil];
+               if (![handler fileManager:self
+                             shouldProceedAfterError:errorInfo])
+                   return NO;
+           }
+           else
+               return NO;
+       }
+    }
+    
+    RELEASE(pool);
+
+    return YES;
+}
+
+- (BOOL)createFileAtPath:(NSString*)path contents:(NSData*)contents
+  attributes:(NSDictionary*)attributes
+{
+#if defined(__MINGW32__)
+    HANDLE fh;
+
+    fh = CreateFile([self fileSystemRepresentationWithPath:path],
+                    GENERIC_WRITE,
+                    0,    // fdwShareMode
+                    NULL, // security attributes
+                    CREATE_ALWAYS,
+                    FILE_ATTRIBUTE_NORMAL,
+                    NULL);
+    if (fh == INVALID_HANDLE_VALUE)
+        return NO;
+    else {
+        DWORD len     = [contents length];
+        DWORD written = 0;
+
+        if (len)
+            WriteFile(fh, [contents bytes], len, &written, NULL);
+        CloseHandle(fh);
+
+        if (![self changeFileAttributes:attributes atPath:path])
+            return NO;
+
+        return written == len ? YES : NO;
+    }
+#else
+    int fd, len, written;
+
+    fd = open ([self fileSystemRepresentationWithPath:path],
+               O_WRONLY|O_TRUNC|O_CREAT, 0644);
+    if (fd < 0)
+       return NO;
+
+    if (![self changeFileAttributes:attributes atPath:path]) {
+       close (fd);
+       return NO;
+    }
+
+    len = [contents length];
+    if (len)
+       written = write (fd, [contents bytes], len);
+    else
+       written = 0;
+    close (fd);
+
+    return written == len;
+#endif
+}
+
+// Getting and comparing file contents
+
+- (NSData*)contentsAtPath:(NSString*)path
+{
+    return [NSData dataWithContentsOfFile:path];
+}
+
+- (BOOL)contentsEqualAtPath:(NSString*)path1 andPath:(NSString*)path2
+{
+    // TODO
+    [self notImplemented:_cmd];
+    return NO;
+}
+
+// Detemining access to files
+
+- (BOOL)fileExistsAtPath:(NSString*)path
+{
+    return [self fileExistsAtPath:path isDirectory:NULL];
+}
+
+#if defined(__MINGW32__)
+- (BOOL)fileExistsAtPath:(NSString*)path isDirectory:(BOOL*)isDirectory
+{
+    DWORD result;
+    if (path == NULL) return NO;
+    result = GetFileAttributes([self fileSystemRepresentationWithPath:path]);
+    if (result == -1)
+        return NO;
+
+    if (isDirectory)
+        *isDirectory = (result & FILE_ATTRIBUTE_DIRECTORY) ? YES : NO;
+    return YES;
+}
+
+- (BOOL)isReadableFileAtPath:(NSString*)path
+{
+    DWORD result;
+    if (path == NULL) return NO;
+    result = GetFileAttributes([self fileSystemRepresentationWithPath:path]);
+    if (result == -1)
+        return NO;
+    return YES;
+}
+- (BOOL)isWritableFileAtPath:(NSString*)path
+{
+    DWORD result;
+    if (path == NULL) return NO;
+    result = GetFileAttributes([self fileSystemRepresentationWithPath:path]);
+    if (result == -1)
+        return NO;
+
+    return (result & FILE_ATTRIBUTE_READONLY) ? NO : YES;
+}
+- (BOOL)isExecutableFileAtPath:(NSString*)path
+{
+    // naive, is there a better way ?
+    if ([self isReadableFileAtPath:path]) {
+        return [[path pathExtension] isEqualToString:@"exe"];
+    }
+    else
+        return NO;
+}
+- (BOOL)isDeletableFileAtPath:(NSString*)path
+{
+    // TODO - handle directories
+    return [self isWritableFileAtPath:path];
+}
+
+#else
+- (BOOL)fileExistsAtPath:(NSString*)path isDirectory:(BOOL*)isDirectory
+{
+    struct stat statbuf;
+    const char* cpath = [self fileSystemRepresentationWithPath:path];
+
+    if (stat(cpath, &statbuf) != 0)
+       return NO;
+    
+    if (isDirectory)
+       *isDirectory = ((statbuf.st_mode & S_IFMT) == S_IFDIR);
+    return YES;
+}
+
+- (BOOL)isReadableFileAtPath:(NSString*)path
+{
+    const char* cpath = [self fileSystemRepresentationWithPath:path];
+    
+    return (access(cpath, R_OK) == 0);
+}
+
+- (BOOL)isWritableFileAtPath:(NSString*)path
+{
+    const char* cpath = [self fileSystemRepresentationWithPath:path];
+    
+    return (access(cpath, W_OK) == 0);
+}
+
+- (BOOL)isExecutableFileAtPath:(NSString*)path
+{
+    const char* cpath = [self fileSystemRepresentationWithPath:path];
+    
+    return (access(cpath, X_OK) == 0);
+}
+
+- (BOOL)isDeletableFileAtPath:(NSString*)path
+{
+    // TODO - handle directories
+    const char* cpath;
+    
+    cpath = [self fileSystemRepresentationWithPath:
+       [path stringByDeletingLastPathComponent]];
+    
+    if (access(cpath, X_OK | W_OK) != 0)
+       return NO;
+
+    cpath = [self fileSystemRepresentationWithPath:path];
+
+    return  (access(cpath, X_OK | W_OK) == 0);
+}
+#endif    
+
+- (NSDictionary*)fileAttributesAtPath:(NSString*)path traverseLink:(BOOL)flag
+{
+    struct stat statbuf;
+    const char* cpath = [self fileSystemRepresentationWithPath:path];
+    int mode;
+#if HAVE_GETPWUID
+    struct passwd *pw;
+#endif
+    int count = 10;
+
+    id  values[11];
+    id keys[11] = {
+        NSFileSize,
+        NSFileModificationDate,
+        NSFileOwnerAccountNumber,
+        NSFileGroupOwnerAccountNumber,
+        NSFileReferenceCount,
+        NSFileIdentifier,
+        NSFileDeviceIdentifier,
+        NSFilePosixPermissions,
+        NSFileType,
+        NSFileOwnerAccountName
+    };
+
+#ifdef S_IFLNK
+    if (flag) {
+        /* traverseLink */
+        if (stat(cpath, &statbuf) != 0)
+            return nil;
+    }
+    else {
+        /* do not traverseLink */
+        if (lstat(cpath, &statbuf) != 0)
+            return nil;
+    }
+#else
+    if (stat(cpath, &statbuf) != 0)
+       return nil;
+#endif
+    
+    values[0] = [NSNumber numberWithUnsignedLongLong:statbuf.st_size];
+    values[1] = [NSDate dateWithTimeIntervalSince1970:statbuf.st_mtime];
+    values[2] = [NSNumber numberWithUnsignedInt:statbuf.st_uid];
+    values[3] = [NSNumber numberWithUnsignedInt:statbuf.st_gid];
+    values[4] = [NSNumber numberWithUnsignedInt:statbuf.st_nlink];
+    values[5] = [NSNumber numberWithUnsignedLong:statbuf.st_ino];
+    values[6] = [NSNumber numberWithUnsignedInt:statbuf.st_dev];
+    values[7] = [NSNumber numberWithUnsignedInt:statbuf.st_mode];
+    
+    mode = statbuf.st_mode & S_IFMT;
+
+    if      (mode == S_IFREG)  values[8] = NSFileTypeRegular;
+    else if (mode == S_IFDIR)  values[8] = NSFileTypeDirectory;
+    else if (mode == S_IFCHR)  values[8] = NSFileTypeCharacterSpecial;
+    else if (mode == S_IFBLK)  values[8] = NSFileTypeBlockSpecial;
+#ifdef S_IFLNK
+    else if (mode == S_IFLNK)  values[8] = NSFileTypeSymbolicLink;
+#endif
+    else if (mode == S_IFIFO)  values[8] = NSFileTypeFifo;
+#ifdef S_IFSOCK
+    else if (mode == S_IFSOCK) values[8] = NSFileTypeSocket;
+#endif
+    else                       values[8] = NSFileTypeUnknown;
+    count = 9;
+    
+#if HAVE_GETPWUID
+    pw = getpwuid(statbuf.st_uid);
+    
+    if (pw) {
+       values[count] = [NSString stringWithCString:pw->pw_name];
+        count++;
+    }
+#endif
+    
+    return AUTORELEASE([[NSDictionary alloc]
+                           initWithObjects:values forKeys:keys count:count]);
+}
+
+- (NSDictionary*)fileSystemAttributesAtPath:(NSString*)path
+{
+#if HAVE_SYS_VFS_H || HAVE_SYS_STATFS_H
+    struct stat statbuf;
+#if HAVE_STATVFS
+    struct statvfs statfsbuf;
+#else
+    struct statfs statfsbuf;
+#endif
+    long long totalsize, freesize;
+    const char* cpath = [self fileSystemRepresentationWithPath:path];
+    
+    id  values[5];
+    id keys[5] = {
+        NSFileSystemSize,
+        NSFileSystemFreeSize,
+        NSFileSystemNodes,
+        NSFileSystemFreeNodes,
+        NSFileSystemNumber
+    };
+    
+    if (stat(cpath, &statbuf) != 0)
+       return nil;
+
+#if HAVE_STATVFS
+    if (statvfs(cpath, &statfsbuf) != 0)
+       return nil;
+#else
+    if (statfs(cpath, &statfsbuf) != 0)
+       return nil;
+#endif
+
+    totalsize = statfsbuf.f_bsize * statfsbuf.f_blocks;
+    freesize = statfsbuf.f_bsize * statfsbuf.f_bfree;
+    
+    values[0] = [NSNumber numberWithLongLong:totalsize];
+    values[1] = [NSNumber numberWithLongLong:freesize];
+    values[2] = [NSNumber numberWithLong:statfsbuf.f_files];
+    values[3] = [NSNumber numberWithLong:statfsbuf.f_ffree];
+    values[4] = [NSNumber numberWithUnsignedInt:statbuf.st_dev];
+    
+    return AUTORELEASE([[NSDictionary alloc]
+                           initWithObjects:values forKeys:keys count:5]);
+#else
+    return nil;
+#endif
+}
+
+- (BOOL)changeFileAttributes:(NSDictionary*)attributes atPath:(NSString*)path
+{
+    const char* cpath = [self fileSystemRepresentationWithPath:path];
+    NSNumber* num;
+    NSDate* date;
+    BOOL allOk = YES;
+    
+#if HAVE_CHOWN
+    num = [attributes objectForKey:NSFileOwnerAccountNumber];
+    if (num) {
+       allOk &= (chown(cpath, [num intValue], -1) == 0);
+    }
+    
+    num = [attributes objectForKey:NSFileGroupOwnerAccountNumber];
+    if (num) {
+       allOk &= (chown(cpath, -1, [num intValue]) == 0);
+    }
+#endif
+    
+    num = [attributes objectForKey:NSFilePosixPermissions];
+    if (num) {
+       allOk &= (chmod(cpath, [num intValue]) == 0);
+    }
+    
+    date = [attributes objectForKey:NSFileModificationDate];
+    if (date) {
+       struct stat sb;
+#if defined(_POSIX_VERSION) || defined(__WIN32__)
+       struct utimbuf ub;
+#else
+       time_t ub[2];
+#endif
+
+       if (stat(cpath, &sb) != 0)
+           allOk = NO;
+       else {
+#if defined(_POSIX_VERSION) || defined(__WIN32__)
+           ub.actime = sb.st_atime;
+           ub.modtime = [date timeIntervalSince1970];
+           allOk &= (utime(cpath, &ub) == 0);
+#else
+           ub[0] = sb.st_atime;
+           ub[1] = [date timeIntervalSince1970];
+           allOk &= (utime((char*)cpath, ub) == 0);
+#endif
+       }
+    }
+    
+    return allOk;
+}
+
+// Discovering directory contents
+
+- (NSArray *)directoryContentsAtPath:(NSString *)path
+{
+    NSDirectoryEnumerator* direnum;
+    NSMutableArray* content;
+    BOOL isDir;
+    
+    if (![self fileExistsAtPath:path isDirectory:&isDir] || !isDir)
+       return nil;
+    
+    direnum = [[NSDirectoryEnumerator alloc]
+       initWithDirectoryPath:path 
+       recurseIntoSubdirectories:NO
+       followSymlinks:NO
+       prefixFiles:NO];
+    content = AUTORELEASE([[NSMutableArray alloc] init]);
+    
+    while ((path = [direnum nextObject]))
+       [content addObject:path];
+
+    RELEASE(direnum); direnum = nil;
+
+    return content;
+}
+
+- (NSDirectoryEnumerator*)enumeratorAtPath:(NSString*)path
+{
+    return AUTORELEASE([[NSDirectoryEnumerator alloc]
+                           initWithDirectoryPath:path 
+                           recurseIntoSubdirectories:YES
+                           followSymlinks:NO
+                           prefixFiles:YES]);
+}
+
+- (NSArray*)subpathsAtPath:(NSString*)path
+{
+    NSDirectoryEnumerator* direnum;
+    NSMutableArray* content;
+    BOOL isDir;
+    
+    if (![self fileExistsAtPath:path isDirectory:&isDir] || !isDir)
+       return nil;
+    
+    direnum = [[NSDirectoryEnumerator alloc]
+       initWithDirectoryPath:path 
+       recurseIntoSubdirectories:YES
+       followSymlinks:NO
+       prefixFiles:YES];
+    content = AUTORELEASE([[NSMutableArray alloc] init]);
+    
+    while ((path = [direnum nextObject]))
+       [content addObject:path];
+
+    RELEASE(direnum); direnum = nil;
+
+    return content;
+}
+
+// Symbolic-link operations
+
+- (BOOL)createSymbolicLinkAtPath:(NSString*)path
+  pathContent:(NSString*)otherPath
+{
+#if HAVE_SYMLINK
+    const char* lpath = [self fileSystemRepresentationWithPath:path];
+    const char* npath = [self fileSystemRepresentationWithPath:otherPath];
+    
+    return (symlink(lpath, npath) == 0);
+#else
+       [[InvalidArgumentException new] raise];
+    return NO;
+#endif
+}
+
+- (NSString*)pathContentOfSymbolicLinkAtPath:(NSString*)path
+{
+#if HAVE_READLINK
+    char  lpath[PATH_MAX];
+    const char* cpath = [self fileSystemRepresentationWithPath:path];
+    int   llen = readlink(cpath, lpath, PATH_MAX-1);
+    
+    if (llen > 0)
+       return [self stringWithFileSystemRepresentation:lpath length:llen];
+    else
+#endif
+       return nil;
+}
+
+// Converting file-system representations
+
+- (const char*)fileSystemRepresentationWithPath:(NSString*)path
+{
+    return [path cString];
+}
+
+- (NSString*)stringWithFileSystemRepresentation:(const char*)string
+  length:(unsigned int)len
+{
+    return [NSString stringWithCString:string length:len];
+}
+
+@end /* NSFileManager */
+
+/*
+ * NSDirectoryEnumerator implementation
+ */
+
+@implementation NSDirectoryEnumerator
+
+#if defined(__MINGW32__)
+
+typedef struct _MingDIR {
+    HANDLE          handle;
+    WIN32_FIND_DATA info;
+    int             dirCount;
+} MingDIR;
+
+static inline MingDIR *ming_opendir(const char *cstr) {
+    DWORD result;
+    
+    if (cstr == NULL)
+        return NULL;
+
+    result = GetFileAttributes(cstr);
+    if (result == 0xFFFFFFFF) {
+        NSLog(@"ERROR: could not get file attributes of path '%s'", cstr);
+        return NULL;
+    }
+
+    if (result & FILE_ATTRIBUTE_DIRECTORY) {
+        MingDIR *dir = objc_atomic_malloc(sizeof(MingDIR));
+        int     len  = strlen(cstr);
+        char    *buf = objc_atomic_malloc(len + 10);
+
+        strcpy(buf, cstr);
+        if (len > 0) {
+            if (buf[len - 1] == '\\')
+                strcat(buf, "*");
+            else
+                strcat(buf, "\\*");
+        }
+        else
+            strcat(buf, "\\*");
+
+        dir->dirCount = 0;
+        dir->handle = FindFirstFile(buf, &(dir->info));
+       objc_free(buf); buf = NULL;
+        if (dir->handle == INVALID_HANDLE_VALUE) {
+            objc_free(dir); dir = NULL;
+            return NULL;
+        }
+        return dir;
+    }
+    else {
+        // not a directory
+        NSLog(@"ERROR: path '%s' is not a directory !", cstr);
+        return NULL;
+    }
+}
+static inline void ming_closedir(MingDIR *dir) {
+    if (dir) {
+        if (dir->handle != INVALID_HANDLE_VALUE) {
+            FindClose(dir->handle);
+            dir->handle = INVALID_HANDLE_VALUE;
+        }
+        free(dir);
+    }
+}
+
+static inline WIN32_FIND_DATA *ming_readdir(MingDIR *dir) {
+    if (dir->dirCount == 0) {
+        // first entry
+        dir->dirCount += 1;
+        return &(dir->info);
+    }
+    else if (dir->handle != INVALID_HANDLE_VALUE) {
+        if (FindNextFile(dir->handle, &(dir->info)) == FALSE) {
+            FindClose(dir->handle);
+            dir->handle = INVALID_HANDLE_VALUE;
+            return NULL;
+        }
+        dir->dirCount += 1;
+        return &(dir->info);
+    }
+    else // directory closed
+        return NULL;
+}
+
+#endif
+
+// Implementation dependent methods
+
+/* 
+  recurses into directory `path' 
+       - pushes relative path (relative to root of search) on pathStack
+       - pushes system dir enumerator on enumPath 
+*/
+- (void)recurseIntoDirectory:(NSString*)path relativeName:(NSString*)name
+{
+    const char* cpath;
+#if defined(__MINGW32__)
+    MingDIR *dir;
+#elif HAVE_OPENDIR
+    DIR *dir;
+#endif
+
+    cpath = [[NSFileManager defaultManager]
+                            fileSystemRepresentationWithPath:path];
+
+    if (cpath == NULL)
+       [[InvalidArgumentException new] raise];
+
+#if defined(__MINGW32__)
+    if ((dir = ming_opendir(cpath))) {
+         [pathStack addObject:name];
+         [enumStack addObject:[NSValue valueWithPointer:dir]];
+    }
+#elif HAVE_OPENDIR
+    if ((dir = opendir(cpath))) {
+       [pathStack addObject:name];
+       [enumStack addObject:[NSValue valueWithPointer:dir]];
+    }
+#else
+    [[InvalidArgumentException new] raise];
+#endif
+}
+
+/*
+  backtracks enumeration to the previous dir
+       - pops current dir relative path from pathStack
+       - pops system dir enumerator from enumStack
+       - sets currentFile* to nil
+*/
+- (void)backtrack
+{
+#if defined(__MINGW32__)
+    ming_closedir((MingDIR *)[[enumStack lastObject] pointerValue]);
+#elif HAVE_OPENDIR
+    closedir((DIR *)[[enumStack lastObject] pointerValue]);
+#else
+    [[InvalidArgumentException new] raise];
+#endif
+    [enumStack removeLastObject];
+    [pathStack removeLastObject];
+    RELEASE(currentFileName); currentFileName = nil;
+    RELEASE(currentFilePath); currentFilePath = nil;
+}
+
+/*
+  finds the next file according to the top enumerator
+       - if there is a next file it is put in currentFile
+       - if the current file is a directory and if isRecursive calls 
+           recurseIntoDirectory:currentFile
+       - if the current file is a symlink to a directory and if isRecursive 
+           and isFollowing calls recurseIntoDirectory:currentFile
+       - if at end of current directory pops stack and attempts to
+           find the next entry in the parent
+       - sets currentFile to nil if there are no more files to enumerate
+*/
+- (void)findNextFile
+{
+    NSFileManager   *manager = [NSFileManager defaultManager];
+#if defined(__MINGW32__)
+    MingDIR         *dir;
+    WIN32_FIND_DATA *dirbuf;
+#elif HAVE_OPENDIR
+    DIR_enum_state  *dir;
+    DIR_enum_item   *dirbuf;
+#endif
+#if defined(__MINGW32__)
+    DWORD           fileAttributes;
+#else
+    struct stat            statbuf;
+#endif
+    const char      *cpath;
+    
+    RELEASE(self->currentFileName); self->currentFileName = nil;
+    RELEASE(self->currentFilePath); self->currentFilePath = nil;
+    
+    while ([self->pathStack count]) {
+#if defined(__MINGW32__)
+        dir = (MingDIR *)[[self->enumStack lastObject] pointerValue];
+        dirbuf = ming_readdir(dir);
+
+        if (dirbuf == NULL) {
+            // If we reached the end of this directory, go back to the upper one
+            [self backtrack];
+            continue;
+        }
+       /* Skip "." and ".." directory entries */
+       if (Strcmp(dirbuf->cFileName, ".") == 0 || 
+           Strcmp(dirbuf->cFileName, "..") == 0)
+               continue;
+
+       self->currentFileName = [manager
+               stringWithFileSystemRepresentation:dirbuf->cFileName
+               length:Strlen(dirbuf->cFileName)];
+#elif HAVE_OPENDIR
+       dir    = (DIR*)[[enumStack lastObject] pointerValue];
+       dirbuf = readdir(dir);
+
+       /* If we reached the end of this directory, go back to the upper one */
+       if (dirbuf == NULL) {
+           [self backtrack];
+           continue;
+       }
+
+       /* Skip "." and ".." directory entries */
+       if (Strcmp(dirbuf->d_name, ".") == 0 || 
+           Strcmp(dirbuf->d_name, "..") == 0)
+               continue;
+       // Name of current file
+       self->currentFileName = [manager
+               stringWithFileSystemRepresentation:dirbuf->d_name
+               length:Strlen(dirbuf->d_name)];
+#else
+       [[InvalidArgumentException new] raise];
+#endif
+       self->currentFileName
+            = RETAIN([[pathStack lastObject]
+                         stringByAppendingPathComponent:self->currentFileName]);
+        
+       // Full path of current file
+       self->currentFilePath
+            = RETAIN([self->topPath stringByAppendingPathComponent:
+                                      self->currentFileName]);
+        
+       // Check if directory
+       cpath = [manager fileSystemRepresentationWithPath:currentFilePath];
+        
+       // Do not follow links
+#ifdef S_IFLNK
+       if (!flags.isFollowing) {
+           if (lstat(cpath, &statbuf) < 0) {
+               NSLog (@"cannot lstat file '%s'", cpath);
+               continue;
+           }
+           // If link then return it as link
+           if (S_IFLNK == (S_IFMT & statbuf.st_mode)) 
+               break;
+       }
+#endif
+
+#if defined(__MINGW32__)
+        if ((fileAttributes = GetFileAttributes(cpath)) == 0xFFFFFFFF)
+            // could not get file attributes
+           continue;
+
+        if (self->flags.isRecursive) {
+            if (fileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+                [self recurseIntoDirectory:self->currentFilePath 
+                      relativeName:self->currentFileName];
+            }
+        }
+#else
+       // Follow links - check for directory
+       if (stat(cpath, &statbuf) < 0)
+            // could not stat file
+           continue;
+
+       if (S_IFDIR == (S_IFMT & statbuf.st_mode) && self->flags.isRecursive) {
+           [self recurseIntoDirectory:self->currentFilePath 
+                  relativeName:self->currentFileName];
+       }
+#endif
+       break;
+    }
+}
+
+// Initializing
+
+- (id)initWithDirectoryPath:(NSString*)path 
+  recurseIntoSubdirectories:(BOOL)recurse
+  followSymlinks:(BOOL)follow
+  prefixFiles:(BOOL)prefix
+{
+    self->pathStack = [[NSMutableArray allocWithZone:[self zone]] init];
+    self->enumStack = [[NSMutableArray allocWithZone:[self zone]] init];
+    self->flags.isRecursive = recurse;
+    self->flags.isFollowing = follow;
+    
+    self->topPath = [path copyWithZone:[self zone]];
+    [self recurseIntoDirectory:path relativeName:@""];
+    
+    return self;
+}
+
+- (void)dealloc
+{
+    while ([self->pathStack count])
+       [self backtrack];
+    
+    RELEASE(self->pathStack);
+    RELEASE(self->enumStack);
+    RELEASE(self->currentFileName);
+    RELEASE(self->currentFilePath);
+    RELEASE(self->topPath);
+
+    [super dealloc];
+}
+
+// Getting attributes
+
+- (NSDictionary *)directoryAttributes
+{
+    return [[NSFileManager defaultManager]
+                           fileAttributesAtPath:self->currentFilePath
+                           traverseLink:self->flags.isFollowing];
+}
+
+- (NSDictionary*)fileAttributes
+{
+    return [[NSFileManager defaultManager]
+                           fileAttributesAtPath:self->currentFilePath
+                           traverseLink:self->flags.isFollowing];
+}
+
+// Skipping subdirectories
+
+- (void)skipDescendents
+{
+    if ([self->pathStack count])
+       [self backtrack];
+}
+
+// Enumerate next
+
+- (id)nextObject
+{
+    [self findNextFile];
+    return self->currentFileName;
+}
+
+@end /* NSDirectoryEnumerator */
+
+/*
+ * Attributes dictionary access
+ */
+
+@implementation NSDictionary(NSFileAttributes)
+
+- (NSNumber *)fileSize
+{
+    return [self objectForKey:NSFileSize];
+}
+- (NSString *)fileType;
+{
+    return [self objectForKey:NSFileType];
+}
+- (NSNumber *)fileOwnerAccountNumber;
+{
+    return [self objectForKey:NSFileOwnerAccountNumber];
+}
+- (NSNumber *)fileGroupOwnerAccountNumber;
+{
+    return [self objectForKey:NSFileGroupOwnerAccountNumber];
+}
+- (NSDate *)fileModificationDate;
+{
+    return [self objectForKey:NSFileModificationDate];
+}
+- (NSNumber *)filePosixPermissions;
+{
+    return [self objectForKey:NSFilePosixPermissions];
+}
+@end
+
+/*
+ * File attributes names
+ */
+
+/* File Attributes */
+
+LF_DECLARE NSString *NSFileSize                    = @"NSFileSize";
+LF_DECLARE NSString *NSFileModificationDate        = @"NSFileModificationDate";
+LF_DECLARE NSString *NSFileOwnerAccountNumber      = @"NSFileOwnerAccountNumber";
+LF_DECLARE NSString *NSFileOwnerAccountName        = @"NSFileOwnerAccountName";
+LF_DECLARE NSString *NSFileGroupOwnerAccountNumber = @"NSFileGroupOwnerAccountNumber";
+LF_DECLARE NSString *NSFileGroupOwnerAccountName   = @"NSFileGroupOwnerAccountName";
+LF_DECLARE NSString *NSFileReferenceCount          = @"NSFileReferenceCount";
+LF_DECLARE NSString *NSFileIdentifier              = @"NSFileIdentifier";
+LF_DECLARE NSString *NSFileDeviceIdentifier        = @"NSFileDeviceIdentifier";
+LF_DECLARE NSString *NSFilePosixPermissions        = @"NSFilePosixPermissions";
+LF_DECLARE NSString *NSFileType                    = @"NSFileType";
+
+/* File Types */
+
+LF_DECLARE NSString *NSFileTypeDirectory           = @"NSFileTypeDirectory";
+LF_DECLARE NSString *NSFileTypeRegular             = @"NSFileTypeRegular";
+LF_DECLARE NSString *NSFileTypeSymbolicLink        = @"NSFileTypeSymbolicLink";
+LF_DECLARE NSString *NSFileTypeSocket              = @"NSFileTypeSocket";
+LF_DECLARE NSString *NSFileTypeFifo                = @"NSFileTypeFifo";
+LF_DECLARE NSString *NSFileTypeCharacterSpecial    = @"NSFileTypeCharacterSpecial";
+LF_DECLARE NSString *NSFileTypeBlockSpecial        = @"NSFileTypeBlockSpecial";
+LF_DECLARE NSString *NSFileTypeUnknown             = @"NSFileTypeUnknown";
+
+/* FileSystem Attributes */
+
+LF_DECLARE NSString *NSFileSystemFileNumber        = @"NSFileSystemFileNumber";
+LF_DECLARE NSString *NSFileSystemSize              = @"NSFileSystemSize";
+LF_DECLARE NSString *NSFileSystemFreeSize          = @"NSFileSystemFreeSize";
+LF_DECLARE NSString *NSFileSystemNodes             = @"NSFileSystemNodes";
+LF_DECLARE NSString *NSFileSystemFreeNodes         = @"NSFileSystemFreeNodes";
+LF_DECLARE NSString *NSFileSystemNumber            = @"NSFileSystemNumber";
+
+@implementation NSFileManager (PrivateMethods)
+
+- (BOOL)_copyFile:(NSString*)source toFile:(NSString*)destination
+  handler:handler
+{
+    NSDictionary* attributes;
+    int i, bufsize = 8096;
+    int sourceFd, destFd, fileSize, fileMode;
+    int rbytes, wbytes;
+    char buffer[bufsize];
+
+    /* Assumes source is a file and exists! */
+    NSAssert1 ([self fileExistsAtPath:source],
+               @"source file '%@' does not exist!", source);
+
+    attributes = [self fileAttributesAtPath:source traverseLink:NO];
+    NSAssert1 (attributes, @"could not get the attributes for file '%@'",
+               source);
+
+    fileSize = [[attributes objectForKey:NSFileSize] intValue];
+    fileMode = [[attributes objectForKey:NSFilePosixPermissions] intValue];
+
+    /* Open the source file. In case of error call the handler. */
+    sourceFd = open([self fileSystemRepresentationWithPath:source], O_RDONLY, 0);
+    if (sourceFd < 0) {
+       if (handler) {
+           NSDictionary* errorInfo
+               = [NSDictionary dictionaryWithObjectsAndKeys:
+                       source, @"Path",
+                       @"cannot open file for reading", @"Error",
+                       nil];
+           return [handler fileManager:self
+                           shouldProceedAfterError:errorInfo];
+       }
+       else
+           return NO;
+    }
+
+    /* Open the destination file. In case of error call the handler. */
+    destFd = open([self fileSystemRepresentationWithPath:destination],
+                 O_WRONLY|O_CREAT|O_TRUNC, fileMode);
+    if (destFd < 0) {
+       if (handler) {
+           NSDictionary* errorInfo
+               = [NSDictionary dictionaryWithObjectsAndKeys:
+                       destination, @"ToPath",
+                       @"cannot open file for writing", @"Error",
+                       nil];
+           close (sourceFd);
+           return [handler fileManager:self
+                           shouldProceedAfterError:errorInfo];
+       }
+       else
+           return NO;
+    }
+
+    /* Read bufsize bytes from source file and write them into the destination
+       file. In case of errors call the handler and abort the operation. */
+    for (i = 0; i < fileSize; i += rbytes) {
+       rbytes = read (sourceFd, buffer, bufsize);
+       if (rbytes < 0) {
+           if (handler) {
+               NSDictionary* errorInfo
+                   = [NSDictionary dictionaryWithObjectsAndKeys:
+                           source, @"Path",
+                           @"cannot read from file", @"Error",
+                           nil];
+               close (sourceFd);
+               close (destFd);
+               return [handler fileManager:self
+                               shouldProceedAfterError:errorInfo];
+           }
+           else
+               return NO;
+       }
+
+       wbytes = write (destFd, buffer, rbytes);
+       if (wbytes != rbytes) {
+           if (handler) {
+               NSDictionary* errorInfo
+                   = [NSDictionary dictionaryWithObjectsAndKeys:
+                           source, @"Path",
+                           destination, @"ToPath",
+                           @"cannot write to file", @"Error",
+                           nil];
+               close (sourceFd);
+               close (destFd);
+               return [handler fileManager:self
+                               shouldProceedAfterError:errorInfo];
+           }
+           else
+               return NO;
+       }
+    }
+    close (sourceFd);
+    close (destFd);
+
+    return YES;
+}
+
+- (BOOL)_copyPath:(NSString*)source
+  toPath:(NSString*)destination
+  handler:handler
+{
+    NSDirectoryEnumerator* enumerator;
+    NSString* dirEntry;
+    NSString* sourceFile;
+    NSString* fileType;
+    NSString* destinationFile;
+    NSDictionary* attributes;
+    CREATE_AUTORELEASE_POOL(pool);
+
+    enumerator = [self enumeratorAtPath:source];
+    while ((dirEntry = [enumerator nextObject])) {
+       attributes = [enumerator fileAttributes];
+       fileType = [attributes objectForKey:NSFileType];
+       sourceFile = [source stringByAppendingPathComponent:dirEntry];
+       destinationFile
+               = [destination stringByAppendingPathComponent:dirEntry];
+
+       [handler fileManager:self willProcessPath:sourceFile];
+       if ([fileType isEqual:NSFileTypeDirectory]) {
+           if (![self createDirectoryAtPath:destinationFile
+                       attributes:attributes]) {
+               if (handler) {
+                   NSDictionary* errorInfo
+                       = [NSDictionary dictionaryWithObjectsAndKeys:
+                               destinationFile, @"Path",
+                               @"cannot create directory", @"Error",
+                               nil];
+                   if (![handler fileManager:self
+                                 shouldProceedAfterError:errorInfo])
+                       return NO;
+               }
+               else
+                   return NO;
+           }
+           else {
+               [enumerator skipDescendents];
+               if (![self _copyPath:sourceFile toPath:destinationFile
+                           handler:handler])
+                   return NO;
+           }
+       }
+       else if ([fileType isEqual:NSFileTypeRegular]) {
+           if (![self _copyFile:sourceFile toFile:destinationFile
+                       handler:handler])
+               return NO;
+       }
+       else if ([fileType isEqual:NSFileTypeSymbolicLink]) {
+           if (![self createSymbolicLinkAtPath:destinationFile
+                       pathContent:sourceFile]) {
+               if (handler) {
+                   NSDictionary* errorInfo
+                       = [NSDictionary dictionaryWithObjectsAndKeys:
+                               sourceFile, @"Path",
+                               destinationFile, @"ToPath",
+                               @"cannot create symbolic link", @"Error",
+                               nil];
+                   if (![handler fileManager:self
+                                 shouldProceedAfterError:errorInfo])
+                       return NO;
+               }
+               else
+                   return NO;
+           }
+       }
+       else {
+           NSLog(@"cannot copy file '%@' of type '%@'", sourceFile, fileType);
+       }
+       [self changeFileAttributes:attributes atPath:destinationFile];
+    }
+    RELEASE(pool);
+
+    return YES;
+}
+
+@end /* NSFileManager (PrivateMethods) */
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSFileURLHandle.h b/libFoundation/Foundation/NSFileURLHandle.h
new file mode 100644 (file)
index 0000000..d402365
--- /dev/null
@@ -0,0 +1,50 @@
+/* 
+   NSFileURLHandle.h
+
+   Copyright (C) 2000 MDlink GmbH, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSFileURLHandle_H__
+#define __NSFileURLHandle_H__
+
+#include <Foundation/NSURLHandle.h>
+
+@class NSDictionary;
+
+@interface NSFileURLHandle : NSURLHandle
+{
+    NSURLHandleStatus status;
+    NSDictionary      *props;
+    NSData            *data;
+    NSString          *path;
+    BOOL              cacheData;
+}
+
+@end
+
+#endif /* __NSFileURLHandle_H__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSFileURLHandle.m b/libFoundation/Foundation/NSFileURLHandle.m
new file mode 100644 (file)
index 0000000..6b1410d
--- /dev/null
@@ -0,0 +1,156 @@
+/* 
+   NSFileURLHandle.m
+
+   Copyright (C) 2000 MDlink GmbH, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include "NSFileURLHandle.h"
+#include <Foundation/NSURL.h>
+#include <Foundation/NSFileManager.h>
+#include <Foundation/NSData.h>
+#include <Foundation/NSException.h>
+
+@implementation NSFileURLHandle
+
++ (BOOL)canInitWithURL:(NSURL *)_url
+{
+    return [_url isFileURL];
+}
+
+- (id)initWithURL:(NSURL *)_url cached:(BOOL)_flag
+{
+    NSAssert([_url isFileURL],
+             @"file handle can only load 'file' URLs (%@)", _url);
+    self->path      = [[_url path] copy];
+    self->cacheData = _flag;
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(self->data);
+    RELEASE(self->path);
+    RELEASE(self->props);
+    [super dealloc];
+}
+
+/* path */
+
+- (NSString *)filePath
+{
+    return self->path;
+}
+- (NSFileManager *)fileManager
+{
+    return [NSFileManager defaultManager];
+}
+
+/* loading */
+
+- (NSData *)loadInForeground
+{
+    NSData *ldata;
+    
+    RELEASE(self->data); self->data = nil;
+    
+    ldata = [NSData dataWithContentsOfFile:[self filePath]];
+    
+    self->status = (ldata)
+        ? NSURLHandleLoadSucceeded
+        : NSURLHandleLoadFailed;
+
+    if (self->cacheData)
+        self->data = RETAIN(ldata);
+    
+    return ldata;
+}
+- (NSURLHandleStatus)status
+{
+    return self->status;
+}
+
+/* reading data */
+
+- (NSData *)resourceData
+{
+    if (self->cacheData && (self->data != nil))
+        return self->data;
+
+    return [self loadInForeground];
+}
+- (void)flushCachedData
+{
+    self->status = NSURLHandleNotLoaded;
+    RELEASE(self->props); self->props = nil;
+    RELEASE(self->data);  self->data  = nil;
+}
+
+/* writing data */
+
+- (BOOL)writeData:(NSData *)_data
+{
+    if (_data == nil)
+        return YES;
+
+    return [_data writeToFile:[self filePath] atomically:YES];
+}
+
+/* properties */
+
+- (id)propertyForKey:(NSString *)_propertyKey
+{
+    if (self->props == nil) {
+        self->props = [[[self fileManager]
+                              fileAttributesAtPath:[self filePath]
+                              traverseLink:YES]
+                              copy];
+    }
+    return [self->props objectForKey:_propertyKey];
+}
+
+- (id)propertyForKeyIfAvailable:(NSString *)_propertyKey
+{
+    return [self->props objectForKey:_propertyKey];
+}
+
+- (BOOL)writeProperty:(id)_propValue forKey:(NSString *)_propertyKey
+{
+    NSDictionary *attrs;
+    
+    if ((_propertyKey == nil) || (_propValue == nil))
+        return NO;
+
+    RELEASE(self->props); self->props = nil;
+
+    attrs = [NSDictionary dictionaryWithObject:_propValue forKey:_propertyKey];
+    
+    return [[self fileManager] changeFileAttributes:attrs
+                               atPath:[self filePath]];
+}
+
+@end /* NSFileURLHandle */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSFormatter.h b/libFoundation/Foundation/NSFormatter.h
new file mode 100644 (file)
index 0000000..12a19e7
--- /dev/null
@@ -0,0 +1,70 @@
+/* 
+   NSFormatter.h
+
+   Copyright (C) 1998 MDlink online service center, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess (helge@mdlink.de)
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+// $Id$
+
+#ifndef __NSFormatter_h__
+#define __NSFormatter_h__
+
+#include <Foundation/NSObject.h>
+
+@class NSString;
+
+#if HAVE_ATTRIBUTED_STRING
+@class NSAttributedString;
+#endif
+
+@interface NSFormatter : NSObject
+{
+}
+
+#if HAVE_ATTRIBUTED_STRING
+- (NSAttributedString *)attributedStringForObjectValue:(id)_object
+  withDefaultAttributes:(NSDictionary *)_attributes;
+#endif
+
+// object => string
+
+- (NSString *)editingStringForObjectValue:(id)_object;
+- (NSString *)stringForObjectValue:(id)_object;
+
+// string => object
+
+- (BOOL)getObjectValue:(id *)_object
+  forString:(NSString *)_string
+  errorDescription:(NSString **)_error;
+
+- (BOOL)isPartialStringValid:(NSString *)_partialString
+  newEditingString:(NSString **)_newString
+  errorDescription:(NSString **)_error;
+
+@end
+
+#endif
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSFormatter.m b/libFoundation/Foundation/NSFormatter.m
new file mode 100644 (file)
index 0000000..70932c0
--- /dev/null
@@ -0,0 +1,78 @@
+/* 
+   NSFormatter.m
+
+   Copyright (C) 1998 MDlink online service center, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess (helge@mdlink.de)
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+// $Id$
+
+#include "common.h"
+#include "NSFormatter.h"
+
+@implementation NSFormatter
+
+#if HAVE_ATTRIBUTED_STRING
+- (NSAttributedString *)attributedStringForObjectValue:(id)_object
+  withDefaultAttributes:(NSDictionary *)_attributes
+{
+    return [NSAttributedString attributedStringWithString:
+                                 [self stringForObjectValue]
+                               attributes:_attributes];
+}
+#endif
+
+// object => string
+
+- (NSString *)editingStringForObjectValue:(id)_object
+{
+    return [self stringForObjectValue:_object];
+}
+
+- (NSString *)stringForObjectValue:(id)_object
+{
+    return [self subclassResponsibility:_cmd];
+}
+
+// string => object
+
+- (BOOL)getObjectValue:(id *)_object
+  forString:(NSString *)_string
+  errorDescription:(NSString **)_error
+{
+    [self subclassResponsibility:_cmd];
+    return NO;
+}
+
+- (BOOL)isPartialStringValid:(NSString *)_partialString
+  newEditingString:(NSString **)_newString
+  errorDescription:(NSString **)_error
+{
+    // is this correct ?
+    // (or should we call 'subclassResponsibility:..', or something similiar ?)
+    return YES;
+}
+
+@end
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSFrameInvocation.h b/libFoundation/Foundation/NSFrameInvocation.h
new file mode 100644 (file)
index 0000000..d44e988
--- /dev/null
@@ -0,0 +1,53 @@
+/* 
+   NSFrameInvocation.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+           Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __Foundation_NSFrameInvocation_H__
+#define __Foundation_NSFrameInvocation_H__
+
+#include <Foundation/NSInvocation.h>
+
+@interface NSFrameInvocation : NSInvocation
+{
+@private
+    arglist_t frame;
+    void      *returnValue;
+    retval_t  returnFrame;
+    BOOL      ownsFrame;
+    BOOL      ownsReturnValue;
+}
+
+- (void)invokeWithTarget:(id)_target lookupAtClass:(Class)_class;
+- (void)superInvokeWithTarget:(id)_target;
+
+@end
+
+#endif /* __Foundation_NSFrameInvocation_H__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSFrameInvocation.m b/libFoundation/Foundation/NSFrameInvocation.m
new file mode 100644 (file)
index 0000000..4e7ab00
--- /dev/null
@@ -0,0 +1,501 @@
+/* 
+   NSFrameInvocation.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+           Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+
+#if HAVE_STRING_H
+# include <string.h>
+#endif
+
+#if HAVE_MEMORY_H
+# include <memory.h>
+#endif
+
+#if !HAVE_MEMCPY
+# define memcpy(d, s, n)       bcopy((s), (d), (n))
+# define memmove(d, s, n)      bcopy((s), (d), (n))
+#endif
+
+#include <Foundation/NSException.h>
+#include <Foundation/NSInvocation.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+#include <Foundation/exceptions/NSInvocationExceptions.h>
+
+#include <extensions/objc-runtime.h>
+
+#include "NSFrameInvocation.h"
+
+/*
+ * Will set *seltype to point to the type of the nth argument, excluding
+ * from type the type specifiers.
+ */
+static void* get_nth_argument(arglist_t argframe, NSArgumentInfo argInfo)
+{
+    const char* t = objc_skip_typespec(argInfo.type);
+
+    if(*t == '+')
+       return argframe->arg_regs + argInfo.offset;
+    else
+       return argframe->arg_ptr +
+           (argInfo.offset - OBJC_FORWARDING_STACK_OFFSET);
+}
+
+@implementation NSFrameInvocation
+
+- (void)_releaseArguments
+{
+    if (self->argumentsRetained) {
+       self->argumentsRetained = 0;
+       RELEASE(self->target);
+       if (frame && signature) {
+           int index, numberOfArguments = [signature numberOfArguments];
+
+           for(index = 2; index < numberOfArguments; index++) {
+               NSArgumentInfo argInfo = [signature argumentInfoAtIndex:index];
+               if(*argInfo.type == _C_CHARPTR) {
+                   char* str;
+                   [self getArgument:&str atIndex:index];
+                   lfFree(str);
+               }
+               else if(*argInfo.type == _C_ID) {
+                   id object;
+                   [self getArgument:&object atIndex:index];
+                   RELEASE(object);
+               }
+           }
+       }
+    }
+}
+
+- (void)_verifySignature
+{
+    struct objc_method_description* mth;
+    
+    if(self->target == nil)
+       [[NullTargetException new] raise];
+
+    if(self->selector == NULL)
+       [[NullSelectorException new] raise];
+
+    mth = (struct objc_method_description*)
+       (CLS_ISCLASS(((struct objc_class*)self->target)->class_pointer)
+         ? class_get_instance_method(
+           ((struct objc_class*)target)->class_pointer, self->selector)
+        : class_get_class_method(
+           ((struct objc_class*)target)->class_pointer, self->selector));
+
+    if (mth) {
+        /* a method matching the selector does exist */
+        const char *types;
+        
+        self->selector = mth ? mth->name : (SEL)0;
+
+        if(self->selector == NULL)
+            [[NullSelectorException new] raise];
+
+        types = mth->types;
+        if(types == NULL)
+            [[[CouldntGetTypeForSelector alloc] initForSelector:selector] raise];
+
+        if(self->signature) {
+            if(!sel_types_match(types, [signature types]))
+                [[[TypesDontMatchException alloc]
+                          initWithTypes:types :[signature types]] raise];
+        }
+        else {
+            self->signature = [NSMethodSignature signatureWithObjCTypes:types];
+            self->signature = RETAIN(self->signature);
+        }
+    }
+    else {
+        /* no method matching the selector does exist */
+        self->signature =
+            [self->target methodSignatureForSelector:self->selector];
+        self->signature = RETAIN(self->signature);
+    }
+
+    if (self->signature == NULL)
+       [[[CouldntGetTypeForSelector alloc] initForSelector:selector] raise];
+}
+
+- (void)invalidate
+{
+    if (self->isValid) {
+       [self _releaseArguments];
+       self->isValid = 0;
+    }
+}
+
+- (void)dealloc
+{
+    if (self->isValid)
+       [self _releaseArguments];
+    if(self->frame && self->ownsFrame) {
+       lfFree(((arglist_t)self->frame)->arg_ptr);
+       lfFree(self->frame);
+    }
+    lfFree(self->returnFrame);
+#ifndef __alpha__
+    /* Temporary comment this out on Alpha machines since it makes the programs
+       crash; don't ask me why ;-) */
+    if(self->ownsReturnValue)
+       lfFree(self->returnValue);
+#endif
+    [super dealloc];
+}
+
+static inline void _setupFrame(NSFrameInvocation *self)
+{
+    /* Set up a new frame */
+    int stack_argsize = [self->signature sizeOfStackArguments];
+
+    NSCAssert(self->frame == NULL, @"frame already setup ..");
+
+    self->frame = (arglist_t)NSZoneCalloc([self zone], APPLY_ARGS_SIZE, 1);
+    self->frame->arg_ptr = stack_argsize
+        ? NSZoneCalloc([self zone], stack_argsize, 1)
+        : NULL;
+    self->ownsFrame = 1;
+}
+
+static inline void
+_fixReturnValue(NSFrameInvocation *self, const char *retType, int retSize)
+{
+    if(!self->returnFrame && retSize)
+       self->returnFrame = NSZoneCalloc([self zone], APPLY_RESULT_SIZE, 1);
+
+    if(!self->ownsFrame) {
+       /*  Was called from the forward:: method. If the original method
+           returns a struct by value, then we must set the returnValue to
+           the address of the structure value. Otherwise the returnValue
+           will still have the null value. */
+       if (*retType != _C_VOID)
+           self->returnValue = GET_STRUCT_VALUE_ADDRESS(self->frame, retType);
+    }
+    if(!self->returnValue && retSize) {
+       self->ownsReturnValue = YES;
+       self->returnValue = NSZoneCalloc([self zone], retSize, 1);
+       if (*retType != _C_VOID)
+           SET_STRUCT_VALUE_ADDRESS(self->frame, self->returnValue, retType);
+    }
+}
+
+- (void)getArgument:(void*)argumentLocation atIndex:(int)index
+{
+    [self _verifySignature];
+    
+    NSAssert(self->signature, @"You must previously set the signature object");
+    NSAssert(self->frame,     @"You must previously set the arguments frame");
+
+    if((unsigned)index >= [signature numberOfArguments]) {
+       [[[IndexOutOfRangeException alloc]
+                     initForSize:[signature numberOfArguments] index:index] raise];
+       return;
+    }
+    else {
+       NSArgumentInfo argInfo = [signature argumentInfoAtIndex:index];
+       void* frameData = get_nth_argument(frame, argInfo);
+
+#ifdef FRAME_GET_ARGUMENT
+        FRAME_GET_ARGUMENT(frameData, argumentLocation, argInfo);
+#else /* !FRAME_GET_ARGUMENT */
+# if WORDS_BIGENDIAN
+       if(argInfo.size < sizeof(void*))
+           memcpy(argumentLocation,
+                   ((char*)frameData) + sizeof(void*) - argInfo.size,
+                   argInfo.size);
+       else
+# endif /* WORDS_BIGENDIAN */
+            memcpy(argumentLocation, frameData, argInfo.size);
+#endif /* FRAME_GET_ARGUMENT */
+    }          
+}
+
+- (void)setArgument:(void*)argumentLocation atIndex:(int)index
+{
+    /* If the argument to be set is not the target, verify the signature */
+    if(index)
+        [self _verifySignature];
+
+    if(!frame)
+        _setupFrame(self);
+
+    if(index >= (int)[signature numberOfArguments])
+       [[[IndexOutOfRangeException alloc]
+                   initForSize:[signature numberOfArguments] index:index] raise];
+    else {
+       if (argumentLocation) {
+            NSArgumentInfo argInfo = [signature argumentInfoAtIndex:index];
+            void* frameData = get_nth_argument(frame, argInfo);
+
+#ifdef FRAME_SET_ARGUMENT
+            FRAME_SET_ARGUMENT(frameData, argumentLocation, argInfo);
+#else /* !FRAME_SET_ARGUMENT */
+# if WORDS_BIGENDIAN
+            if(argInfo.size < sizeof(void*))
+                memcpy(((char*)frameData) + sizeof(void*) - argInfo.size,
+                       argumentLocation,
+                       argInfo.size);
+            else
+# endif /* WORDS_BIGENDIAN */
+                memcpy(frameData, argumentLocation, argInfo.size);
+#endif /* !FRAME_SET_ARGUMENT */
+        }
+    }
+}
+
+- (void)getReturnValue:(void*)retLoc
+{
+    const char* retType;
+    int retLength;
+
+    NSAssert(signature, @"You must previously set the signature object");
+    NSAssert(frame, @"You must previously set the arguments frame,"
+             @"either by invoking -invoke or -invokeWithTarget: methods");
+
+    retType = [signature methodReturnType];
+    if(*retType != _C_VOID) {
+       retLength = [signature methodReturnLength];
+       memcpy(retLoc, returnValue, retLength);
+    }
+}
+
+- (void)setReturnValue:(void*)retLoc
+{
+    const char* retType;
+    int retSize;
+
+    [self _verifySignature];
+
+    NSAssert(signature, @"You must previously set the signature object");
+    NSAssert(frame,     @"You must previously set the arguments frame");
+
+    retType = [signature methodReturnType];
+    retSize = [signature methodReturnLength];
+
+    if (returnValue == NULL) {
+        // this is executed if the invocation wasn't invoked
+        // (but dispatched in user code, like in DO)
+        _fixReturnValue(self, retType, retSize);
+    }
+    
+    if(*retType != _C_VOID) {
+#if 0 && WORDS_BIGENDIAN
+       if(retSize < sizeof(void*)) {
+           *(void**)returnValue = 0;
+           memcpy(returnValue, ((char*)retLoc) + sizeof(void*) - retSize, retSize);
+       }
+       else
+#endif
+#if WORDS_BIGENDIAN
+       if(retSize < sizeof(void*))
+           retSize = sizeof(void*);
+#endif
+       memcpy(returnValue, retLoc, retSize);
+    }
+    FUNCTION_SET_VALUE(retType, frame, returnFrame, returnValue);
+}
+
+- (void)retainArguments
+{
+    int index, numberOfArguments;
+
+    NSAssert(signature, @"You must previously set the signature object");
+
+    if (self->argumentsRetained)
+       return;
+
+    self->argumentsRetained = 1;
+    (void)RETAIN(self->target);
+    numberOfArguments = [signature numberOfArguments];
+    if (numberOfArguments <= 2)
+       return;
+
+    NSAssert(frame, @"You must previously set the arguments frame");
+
+    for(index = 2; index < numberOfArguments; index++) {
+       NSArgumentInfo argInfo = [signature argumentInfoAtIndex:index];
+        
+       if(*argInfo.type == _C_CHARPTR) {
+           char* str;
+           [self getArgument:&str atIndex:index];
+           str = Strdup(str);
+           [self setArgument:&str atIndex:index];
+       }
+       else if(*argInfo.type == _C_ID) {
+           id object;
+           [self getArgument:&object atIndex:index];
+           (void)RETAIN(object);
+       }
+    }
+}
+
+- (void)invokeWithTarget:(id)_target
+{
+    id         old_target = target;
+    retval_t   retframe;
+    const char *retType;
+    int        retSize;
+
+    /*  Set the target. We assign '_target' to 'target' because some
+        of the NSInvocation's methods assume a valid target. */
+    target = _target;
+    [self _verifySignature];
+
+    if((frame == NULL) && [signature numberOfArguments] > 2)
+       [[FrameIsNotSetupException new] raise];
+
+    if(frame == NULL)
+        _setupFrame(self);
+
+    retType = [signature methodReturnType];
+    retSize = [signature methodReturnLength];
+    _fixReturnValue(self, retType, retSize);
+
+    /* Restore the old target. */
+    target = old_target;
+
+#if GNU_RUNTIME
+    {
+        Method *m;
+        const char *type;
+
+        m = class_get_instance_method(*(Class *)_target, selector);
+        
+        *((id*)method_get_first_argument (m, frame, &type)) = _target;
+        *((SEL*)method_get_next_argument (frame, &type)) = selector;
+        retframe = __builtin_apply((apply_t)m->method_imp, 
+                                   frame,
+                                   method_get_sizeof_arguments(m));
+    }
+#else /* !GNU_RUNTIME */
+    retframe = objc_msg_sendv(_target, selector, frame);
+#endif /* !GNU_RUNTIME */
+
+    if (retSize) {
+        FUNCTION_VALUE(retType, frame, retframe, returnValue);
+        memcpy(returnFrame, retframe, APPLY_RESULT_SIZE);
+    }
+}
+
+- (void)invokeWithTarget:(id)_target lookupAtClass:(Class)_class
+{
+    id         old_target = target;
+    retval_t   retframe;
+    const char *retType;
+    int        retSize;
+
+    /*  Set the target. We assign '_target' to 'target' because some
+        of the NSInvocation's methods assume a valid target. */
+    target = _target;
+    [self _verifySignature];
+
+    if((frame == NULL) && [signature numberOfArguments] > 2)
+       [[FrameIsNotSetupException new] raise];
+
+    if(frame == NULL)
+        _setupFrame(self);
+
+    retType = [signature methodReturnType];
+    retSize = [signature methodReturnLength];
+    _fixReturnValue(self, retType, retSize);
+
+    /* Restore the old target. */
+    target = old_target;
+
+#if GNU_RUNTIME
+    {
+        Method *m;
+        const char *type;
+
+        m = class_get_instance_method(_class, selector);
+        
+        *((id*)method_get_first_argument (m, frame, &type)) = _target;
+        *((SEL*)method_get_next_argument (frame, &type)) = selector;
+        retframe = __builtin_apply((apply_t)m->method_imp, 
+                                   frame,
+                                   method_get_sizeof_arguments(m));
+    }
+#else /* !GNU_RUNTIME */
+#warning "super invocation supported with GNU runtime only !"
+    abort();
+    /* retframe = objc_msg_sendv(_target, selector, frame); */
+#endif /* !GNU_RUNTIME */
+
+    if (retSize) {
+        FUNCTION_VALUE(retType, frame, retframe, returnValue);
+        memcpy(returnFrame, retframe, APPLY_RESULT_SIZE);
+    }
+}
+- (void)superInvokeWithTarget:(id)_target
+{
+    [self invokeWithTarget:_target
+          lookupAtClass:(*(Class *)_target)->super_class];
+}
+
+- (NSString*)description
+{
+    /* Don't use -[NSString stringWithFormat:] method because it can cause
+       infinite recursion. */
+    char buffer[1024];
+
+    sprintf (buffer, "<%s %p selector: %s target: %s>", \
+                (char*)object_get_class_name(self), \
+                self, \
+                selector ? [NSStringFromSelector(selector) cString] : "nil", \
+                target ? [NSStringFromClass([target class]) cString] : "nil" \
+                );
+
+    return [NSString stringWithCString:buffer];
+}
+
+@end /* NSInvocation */
+
+
+@implementation NSFrameInvocation (Extensions)
+
+- (void)setArgumentFrame:(void*)_frame
+{
+    self->frame     = _frame;
+    self->ownsFrame = 0;
+}
+
+- (retval_t)returnFrame
+{
+    return self->returnFrame;
+}
+- (void*)returnValue
+{
+    return self->returnValue;
+}
+
+@end /* NSInvocation (Extensions) */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSFuncallException.h b/libFoundation/Foundation/NSFuncallException.h
new file mode 100644 (file)
index 0000000..79012e0
--- /dev/null
@@ -0,0 +1,391 @@
+/* 
+   NSFuncallException.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSException_h__
+#define __NSException_h__
+
+#include <setjmp.h>
+#include <stdarg.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSArray.h>
+
+@class NSDictionary;
+
+@interface NSException : NSObject
+{
+    NSString     *name;
+    NSString     *reason;
+    NSDictionary *userInfo;
+}
+
+/* Creating and Raising Exceptions */
+
++ (NSException *)exceptionWithName:(NSString *)name
+  reason:(NSString *)reason
+  userInfo:(NSDictionary *)userInfo;
++ (void)raise:(NSString *)name
+  format:(NSString *)format,...;
++ (void)raise:(NSString *)name
+  format:(NSString *)format
+  arguments:(va_list)argList;
+
+- (id)initWithName:(NSString *)name
+  reason:(NSString *)reason
+  userInfo:(NSDictionary *)userInfo;
+- (void)raise;
+
+/* Querying Exceptions */
+
+- (NSString *)name;
+- (NSString *)reason;
+- (NSDictionary *)userInfo;
+
+@end /* NSException */
+
+
+@interface NSException (Extensions)
+- (BOOL)exceptionIsKindOfClass:(Class)class;
+                       /* return [self isKindOfClass:class] */
+- (BOOL)exceptionIsIn:(NSArray *)exceptions;
+- (NSString *)errorString;
+- (id)initWithFormat:(NSString *)format, ...;
+- (id)initWithFormat:(NSString *)format arguments:(va_list)ap;
+- (id)setName:(NSString *)name;
+- (id)setReason:(NSString *)reason;
+- (id)setUserInfo:(NSDictionary *)userInfo;
+@end /* NSException (Extension) */
+
+@interface NSException (Backtrace)
++ (NSString *)backtrace;
++ (void)printBacktrace;
+@end /* NSException(Backtrace) */
+
+typedef void NSUncaughtExceptionHandler(NSException *exception);
+
+NSUncaughtExceptionHandler *NSGetUncaughtExceptionHandler(void);
+void NSSetUncaughtExceptionHandler(NSUncaughtExceptionHandler *handler);
+
+/* Exception names */
+LF_EXPORT NSString *NSInconsistentArchiveException;
+LF_EXPORT NSString *NSGenericException;
+LF_EXPORT NSString *NSInternalInconsistencyException;
+LF_EXPORT NSString *NSInvalidArgumentException;
+LF_EXPORT NSString *NSMallocException;
+LF_EXPORT NSString *NSObjectInaccessibleException;
+LF_EXPORT NSString *NSObjectNotAvailableException;
+LF_EXPORT NSString *NSDestinationInvalidException;
+LF_EXPORT NSString *NSPortTimeoutException;
+LF_EXPORT NSString *NSInvalidSendPortException;
+LF_EXPORT NSString *NSInvalidReceivePortException;
+LF_EXPORT NSString *NSPortSendException;
+LF_EXPORT NSString *NSPortReceiveException;
+LF_EXPORT NSString *NSOldStyleException;
+LF_EXPORT NSString *NSRangeException;
+
+/*  OpenStep macros for exception handling.
+    Use the ones defined below instead. */
+
+#define NS_DURING      TRY {
+
+#define NS_HANDLER     } END_TRY OTHERWISE {
+
+#define NS_ENDHANDLER  } END_CATCH
+
+#define NS_VALRETURN(value) \
+    ({_NSRemoveHandler(&exceptionHandler); handler(nil); return (value);})
+
+#define NS_VOIDRETURN \
+    ({_NSRemoveHandler(&exceptionHandler); handler(nil); return;})
+
+typedef void (*THandlerFunction)(id);
+
+typedef struct _NSHandler
+{
+    struct _NSHandler *previousHandler;
+    jmp_buf          jmpState;
+    THandlerFunction  handler;
+} NSHandler;
+
+LF_EXPORT void _NSAddHandler(NSHandler *handler);
+LF_EXPORT void _NSRemoveHandler(NSHandler *handler);
+
+
+/*
+ * The new macros for handling exceptions.
+ */
+
+#define TRY \
+{ \
+    auto void handler(); \
+    NSHandler exceptionHandler; \
+\
+    int _dummy = \
+    ({ \
+       __label__ _quit; \
+       if(!setjmp(exceptionHandler.jmpState)) { \
+           exceptionHandler.handler = handler; \
+           _NSAddHandler(&exceptionHandler);
+
+#define END_TRY \
+           _NSRemoveHandler(&exceptionHandler); \
+           handler(nil); \
+           goto _quit; /* to remove compiler warning about unused label*/ \
+       }; \
+       _quit: 0; \
+    }); \
+    void handler(NSException *localException) \
+    { \
+       BOOL _caught = NO; \
+        RETAIN(localException);\
+       if (localException != nil) \
+           _NSRemoveHandler(&exceptionHandler); \
+       if (localException == nil) { _dummy++;
+
+#define CATCH(exception_class) \
+       } else if([localException exceptionIsKindOfClass:[exception_class class]]) { \
+           _caught = YES;
+
+#ifndef PRECOMP
+# define MULTICATCH(exception_classes...) \
+       } else if ([localException exceptionIsIn: \
+                   [NSArray arrayWithObjects:##exception_classes, nil]]) { \
+           _caught = YES;
+#endif /* PRECOMP */
+
+#define OTHERWISE \
+       } else { \
+           _caught = YES;
+
+#define CLEANUP \
+       } \
+       if(localException && !_caught) {
+
+#define FINALLY \
+       } \
+       if(1) {
+
+#define END_CATCH \
+       } \
+       if (localException==nil) return; \
+       if (!_caught) \
+           [localException raise]; \
+       else {\
+           RELEASE(localException); \
+           longjmp(exceptionHandler.jmpState, 1); \
+       }\
+    } \
+}
+
+
+/*  Use BREAK inside a TRY block to get out of it */
+#define BREAK  ({_NSRemoveHandler(&exceptionHandler); goto _quit;})
+
+#ifndef PRECOMP
+/*  If you want to generate an exception issue a THROW with the exception
+    an object derived from the NSException class. */
+# define THROW(exception...)   [##exception raise]
+#else
+# define THROW(exception)      [exception raise]
+#endif /* PRECOMP */
+
+/*  If you want to reraise an exception inside an exception handler
+    just say RERAISE. */
+#define RERAISE                 [localException raise]
+
+
+
+/*
+ * Assertions.
+ */
+
+#ifndef __FoundationException_definition__
+#define __FoundationException_definition__
+
+@interface FoundationException : NSException
+@end
+
+#endif /* __FoundationException_definition__ */
+
+@interface AssertException : FoundationException
+@end
+
+
+@interface NSAssertionHandler : NSObject
+
+/* Getting the Current Handler */
++ (NSAssertionHandler*)currentHandler;
+
+/* Handling Failures */
+- (void)handleFailureInFunction:(NSString*)functionName
+    file:(NSString*)fileName
+    lineNumber:(int)line
+    description:(NSString*)format,...;
+- (void)handleFailureInMethod:(SEL)selector
+    object:(id)object
+    file:(NSString*)fileName
+    lineNumber:(int)line
+    description:(NSString*)format,...;
+
+@end
+
+
+#ifndef PRECOMP
+# define NSAssert(condition, desc, arguments...) \
+    ({ if(!(condition)) \
+           [[NSAssertionHandler currentHandler] \
+                   handleFailureInMethod:_cmd \
+                   object:self \
+                   file:[NSString stringWithCString:__FILE__] \
+                   lineNumber:__LINE__ \
+                   description:(desc) , ##arguments]; \
+    0;})
+
+# define NSCAssert(condition, desc, arguments...) \
+    ({ if(!(condition)) \
+           [[NSAssertionHandler currentHandler] \
+                   handleFailureInFunction: \
+                       [NSString stringWithCString:__PRETTY_FUNCTION__] \
+                   file:[NSString stringWithCString:__FILE__] \
+                   lineNumber:__LINE__ \
+                   description:(desc) , ##arguments]; \
+    0;})
+
+# define Assert(condition) \
+    ({if(!(condition)) {\
+       NSLog([(@#condition) stringByPrependingString:@"Assertion failed: "]); \
+       [[AssertException new] raise]; \
+    } \
+    0;})
+
+# define NSParameterAssert(condition) \
+    ({if(!(condition)) {\
+       NSLog([(@#condition) stringByPrependingString:@"Parameter Assertion failed: "]); \
+       [[AssertException new] raise]; \
+    } \
+    0;})
+
+# define NSCParameterAssert(condition) \
+    ({if(!(condition)) {\
+       NSLog([(@#condition) stringByPrependingString:@"Parameter Assertion failed: "]); \
+       [[AssertException new] raise]; \
+    } \
+    0;})
+
+# define NSAssert1(condition, desc, a1) \
+    ({ if(!(condition)) \
+           [[NSAssertionHandler currentHandler] \
+                   handleFailureInMethod:_cmd object:self \
+                   file:[NSString stringWithCString:__FILE__] \
+                   lineNumber:__LINE__ \
+                   description:(desc) , a1]; \
+    0;})
+# define NSAssert2(condition, desc, a1, a2) \
+    ({ if(!(condition)) \
+           [[NSAssertionHandler currentHandler] \
+                   handleFailureInMethod:_cmd object:self \
+                   file:[NSString stringWithCString:__FILE__] \
+                   lineNumber:__LINE__ \
+                   description:(desc) , a1, a2]; \
+    0;})
+# define NSAssert3(condition, desc, a1, a2, a3) \
+    ({ if(!(condition)) \
+           [[NSAssertionHandler currentHandler] \
+                   handleFailureInMethod:_cmd object:self \
+                   file:[NSString stringWithCString:__FILE__] \
+                   lineNumber:__LINE__ \
+                   description:(desc) , a1, a2, a3]; \
+    0;})
+# define NSAssert4(condition, desc, a1, a2, a3, a4) \
+    ({ if(!(condition)) \
+           [[NSAssertionHandler currentHandler] \
+                   handleFailureInMethod:_cmd object:self \
+                   file:[NSString stringWithCString:__FILE__] \
+                   lineNumber:__LINE__ \
+                   description:(desc) , a1, a2, a3, a4]; \
+    0;})
+# define NSAssert5(condition, desc, a1, a2, a3, a4, a5) \
+    ({ if(!(condition)) \
+           [[NSAssertionHandler currentHandler] \
+                   handleFailureInMethod:_cmd object:self \
+                   file:[NSString stringWithCString:__FILE__] \
+                   lineNumber:__LINE__ \
+                   description:(desc) , a1, a2, a3, a4, a5]; \
+    0;})
+
+# define NSCAssert1(condition, desc, a1) \
+    ({ if(!(condition)) \
+           [[NSAssertionHandler currentHandler] \
+                   handleFailureInFunction: \
+                       [NSString stringWithCString:__PRETTY_FUNCTION__] \
+                   file:[NSString stringWithCString:__FILE__] \
+                   lineNumber:__LINE__ \
+                   description:(desc) , a1]; \
+    0;})
+# define NSCAssert2(condition, desc, a1, a2) \
+    ({ if(!(condition)) \
+           [[NSAssertionHandler currentHandler] \
+                   handleFailureInFunction: \
+                       [NSString stringWithCString:__PRETTY_FUNCTION__] \
+                   file:[NSString stringWithCString:__FILE__] \
+                   lineNumber:__LINE__ \
+                   description:(desc) , a1, a2]; \
+    0;})
+# define NSCAssert3(condition, desc, a1, a2, a3) \
+    ({ if(!(condition)) \
+           [[NSAssertionHandler currentHandler] \
+                   handleFailureInFunction: \
+                       [NSString stringWithCString:__PRETTY_FUNCTION__] \
+                   file:[NSString stringWithCString:__FILE__] \
+                   lineNumber:__LINE__ \
+                   description:(desc) , a1, a2, a3]; \
+    0;})
+# define NSCAssert4(condition, desc, a1, a2, a3, a4) \
+    ({ if(!(condition)) \
+           [[NSAssertionHandler currentHandler] \
+                   handleFailureInFunction: \
+                       [NSString stringWithCString:__PRETTY_FUNCTION__] \
+                   file:[NSString stringWithCString:__FILE__] \
+                   lineNumber:__LINE__ \
+                   description:(desc) , a1, a2, a3, a4]; \
+    0;})
+# define NSCAssert5(condition, desc, a1, a2, a3, a4, a5) \
+    ({ if(!(condition)) \
+           [[NSAssertionHandler currentHandler] \
+                   handleFailureInFunction: \
+                       [NSString stringWithCString:__PRETTY_FUNCTION__] \
+                   file:[NSString stringWithCString:__FILE__] \
+                   lineNumber:__LINE__ \
+                   description:(desc) , a1, a2, a3, a4, a5]; \
+    0;})
+
+#endif /* PRECOMP */
+
+#endif /* __NSException_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSGeometry.h b/libFoundation/Foundation/NSGeometry.h
new file mode 100644 (file)
index 0000000..79cfecc
--- /dev/null
@@ -0,0 +1,102 @@
+/* 
+   NSGeometry.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSGeometry_h__
+#define __NSGeometry_h__
+
+#include <objc/objc.h>
+
+/* Geometry */
+
+@class NSString;
+
+typedef struct _NSPoint {float x; float y;} NSPoint;
+typedef struct _NSSize  {float width; float height;} NSSize;
+typedef struct _NSRect {NSPoint origin;NSSize size;} NSRect;
+
+typedef enum {NSMinXEdge, NSMinYEdge,  NSMaxXEdge, NSMaxYEdge} NSRectEdge;
+
+// Constants
+
+#define NSZeroPoint ((NSPoint){0,0})
+#define NSZeroRect ((NSRect){{0,0},{0,0}})
+#define NSZeroSize ((NSSize){0,0})
+
+// Create Basic Structures
+LF_EXPORT NSPoint      NSMakePoint(float x, float y);
+LF_EXPORT NSSize       NSMakeSize(float w, float h);
+LF_EXPORT NSRect       NSMakeRect(float x, float y, float w, float h);
+
+// Get a Rectangle's Coordinates
+LF_EXPORT float NSMaxX(NSRect aRect);
+LF_EXPORT float NSMaxY(NSRect aRect);
+LF_EXPORT float NSMidX(NSRect aRect);
+LF_EXPORT float NSMidY(NSRect aRect);
+LF_EXPORT float NSMinX(NSRect aRect);
+LF_EXPORT float NSMinY(NSRect aRect);
+LF_EXPORT float NSWidth(NSRect aRect);
+LF_EXPORT float NSHeight(NSRect aRect);
+
+// Modify a Copy of a Rectangle
+LF_EXPORT NSRect       NSInsetRect(NSRect aRect, float dX, float dY);
+LF_EXPORT NSRect       NSOffsetRect(NSRect aRect, float dx, float dy);
+LF_EXPORT void         NSDivideRect(NSRect aRect, NSRect *slice, NSRect *remainder,
+                            float amount, NSRectEdge edge);
+LF_EXPORT NSRect       NSIntegralRect(NSRect aRect);
+
+// Compute a Third Rectangle from Two Rectangles
+LF_EXPORT NSRect       NSUnionRect(NSRect aRect, NSRect bRect);
+LF_EXPORT NSRect   NSIntersectionRect (NSRect aRect, NSRect bRect);
+
+
+// Test Geometric Relationships
+LF_EXPORT BOOL         NSEqualRects(NSRect aRect, NSRect bRect);
+LF_EXPORT BOOL         NSEqualSizes(NSSize aSize, NSSize bSize);
+LF_EXPORT BOOL         NSEqualPoints(NSPoint aPoint, NSPoint bPoint);
+LF_EXPORT BOOL         NSIsEmptyRect(NSRect aRect);
+LF_EXPORT BOOL         NSMouseInRect(NSPoint aPoint, NSRect aRect, BOOL flipped);
+LF_EXPORT BOOL         NSPointInRect(NSPoint aPoint, NSRect aRect);
+LF_EXPORT BOOL         NSContainsRect(NSRect aRect, NSRect bRect);
+LF_EXPORT BOOL NSIntersectsRect(NSRect aRect, NSRect bRect);
+
+// Get a String Representation
+
+LF_EXPORT NSString* NSStringFromPoint(NSPoint aPoint);
+LF_EXPORT NSString* NSStringFromRect(NSRect aRect);
+LF_EXPORT NSString* NSStringFromSize(NSSize aSize);
+
+// Make from String Representation
+
+LF_EXPORT NSPoint      NSPointFromString(NSString* string);
+LF_EXPORT NSSize       NSSizeFromString(NSString* string);
+LF_EXPORT NSRect       NSRectFromString(NSString* string);
+
+#endif /* __NSGeometry_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSGeometry.m b/libFoundation/Foundation/NSGeometry.m
new file mode 100644 (file)
index 0000000..37f7d68
--- /dev/null
@@ -0,0 +1,437 @@
+/* 
+   NSGeometry.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <math.h>
+#include <Foundation/common.h>
+#include <Foundation/NSGeometry.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSScanner.h>
+
+/*
+ * Useful inline functions
+ */
+
+static inline NSRect lfRECT(float x, float y, float w, float h)
+{
+    NSRect rect = {{x,y},{w,h}};
+    return rect;
+}
+
+static inline BOOL lfVALID(NSRect aRect)
+{
+    return (aRect.size.width > 0 && aRect.size.height > 0);
+}
+
+/*
+ * Create Basic Structures
+ */
+
+NSPoint        NSMakePoint(float x, float y)
+{
+    NSPoint point = {x,y};
+    return point;
+}
+
+NSSize NSMakeSize(float w, float h)
+{
+    NSSize size = {w,h};
+    return size;
+}
+
+NSRect NSMakeRect(float x, float y, float w, float h)
+{
+    NSRect rect = {{x,y},{w,h}};
+    return rect;
+}
+
+/* 
+ * Get a Rectangle's Coordinates
+ */
+
+float NSMaxX(NSRect aRect)
+{
+    return aRect.origin.x + aRect.size.width;
+}
+
+float NSMaxY(NSRect aRect)
+{
+    return aRect.origin.y + aRect.size.height;
+}
+
+float NSMidX(NSRect aRect)
+{
+    return aRect.origin.x + aRect.size.width / 2.0;
+}
+
+float NSMidY(NSRect aRect)
+{
+    return aRect.origin.y + aRect.size.height / 2.0;
+}
+
+float NSMinX(NSRect aRect)
+{
+    return aRect.origin.x;
+}
+
+float NSMinY(NSRect aRect)
+{
+    return aRect.origin.y;
+}
+
+float NSWidth(NSRect aRect)
+{
+    return aRect.size.width;
+}
+
+float NSHeight(NSRect aRect)
+{
+    return aRect.size.height;
+}
+
+/*
+ * Modify a Copy of a Rectangle
+ */
+
+NSRect NSInsetRect(NSRect aRect, float dX, float dY)
+{
+    return lfRECT(aRect.origin.x+dX,aRect.origin.y+dY,
+           aRect.size.width-2*dX,aRect.size.height-2*dY);
+}
+
+NSRect NSOffsetRect(NSRect aRect, float dX, float dY)
+{
+    return lfRECT(aRect.origin.x+dX, aRect.origin.y+dY,
+           aRect.size.width, aRect.size.height);
+}
+
+void NSDivideRect(NSRect aRect, NSRect *slice, NSRect *remainder,
+                  float amount, NSRectEdge edge)
+{
+    NSRect dummySlice, dummyRemainder;
+    
+    if (!slice)
+       slice = &dummySlice;
+    if (!remainder)
+       remainder = &dummyRemainder;
+    
+    switch (edge) {
+       case (NSMinXEdge):
+           if (amount > aRect.size.width) {
+               *slice = aRect;
+               *remainder = lfRECT(aRect.origin.x + aRect.size.width,
+                               aRect.origin.y, 
+                               0, aRect.size.height);
+           }
+           else {
+               *slice = lfRECT(aRect.origin.x, aRect.origin.y, 
+                               amount, aRect.size.height);
+               *remainder = lfRECT(aRect.origin.x+amount, aRect.origin.y, 
+                               aRect.size.width-amount, aRect.size.height);
+           }
+           break;
+       case (NSMinYEdge):
+               if (amount > aRect.size.height) {
+                   *slice = aRect;
+                   *remainder = lfRECT(aRect.origin.x, 
+                                   aRect.origin.y+aRect.size.height,
+                                   aRect.size.width, 0);
+               }
+               else {
+                   *slice = lfRECT(aRect.origin.x, aRect.origin.y, 
+                               aRect.size.width, amount);
+                   *remainder = lfRECT(aRect.origin.x,
+                                   aRect.origin.y+amount, 
+                                   aRect.size.width,
+                                   aRect.size.height-amount);
+               }
+               break;
+       case (NSMaxXEdge):
+               if (amount > aRect.size.width) {
+                   *slice = aRect;
+                   *remainder = lfRECT(aRect.origin.x, aRect.origin.y, 
+                                   0, aRect.size.height);
+               }
+               else {
+                   *slice = lfRECT(aRect.origin.x+aRect.size.width-amount,
+                                   aRect.origin.y, amount, aRect.size.height);
+                   *remainder = lfRECT(aRect.origin.x, aRect.origin.y, 
+                                   aRect.size.width-amount,
+                                   aRect.size.height);
+               }
+               break;
+       case (NSMaxYEdge):
+               if (amount > aRect.size.height) {
+                   *slice = aRect;
+                   *remainder = lfRECT(aRect.origin.x, aRect.origin.y, 
+                                   aRect.size.width, 0);
+               }
+               else {
+                   *slice = lfRECT(aRect.origin.x, 
+                                   aRect.origin.y+aRect.size.height-amount, 
+                                   aRect.size.width, amount);
+                   *remainder = NSMakeRect(aRect.origin.x, aRect.origin.y, 
+                                           aRect.size.width,
+                                           aRect.size.height-amount);
+               }
+               break;
+       default:
+           ;
+    }
+}
+
+NSRect NSIntegralRect(NSRect aRect)
+{
+    aRect.origin.x = floor(aRect.origin.x);
+    aRect.origin.y = floor(aRect.origin.y);
+    aRect.size.width = ceil(aRect.size.width);
+    aRect.size.height = ceil(aRect.size.height);
+    
+    if (lfVALID(aRect))
+       return aRect;
+    else
+       return lfRECT(0,0,0,0);
+}
+
+/* 
+* Compute a third rectangle from two rectangles 
+*/
+
+NSRect NSUnionRect(NSRect aRect, NSRect bRect)
+{
+    float mx, my, Mx, My;
+    
+    if (!lfVALID(aRect) && !lfVALID(bRect))
+       return lfRECT(0,0,0,0);
+    if (!lfVALID(aRect)) 
+       return bRect;
+    if (!lfVALID(bRect))
+       return aRect;
+    
+    mx = MIN(aRect.origin.x, bRect.origin.x); 
+    my = MIN(aRect.origin.y, bRect.origin.y); 
+    Mx = MAX(aRect.origin.x+aRect.size.width, 
+           bRect.origin.x+bRect.size.width);
+    My = MAX(aRect.origin.y+aRect.size.height, 
+           bRect.origin.y+bRect.size.height);
+    
+    return lfRECT(mx, my, Mx-mx, My-my);
+}
+
+NSRect NSIntersectionRect (NSRect aRect, NSRect bRect)
+{
+    NSRect rect;
+    
+    if (NSMaxX(aRect) <= NSMinX(bRect) ||
+           NSMaxX(bRect) <= NSMinX(aRect) ||
+           NSMaxY(aRect) <= NSMinY(bRect) ||
+           NSMaxY(bRect) <= NSMinY(aRect))
+           return lfRECT(0, 0, 0, 0);
+    
+    if (NSMinX(aRect) <= NSMinX(bRect)) {
+       rect.size.width = MIN(NSMaxX(aRect), NSMaxX(bRect)) - NSMinX(bRect);
+       rect.origin.x = NSMinX(bRect);
+    } else {
+       rect.size.width = MIN(NSMaxX(aRect), NSMaxX(bRect)) - NSMinX(aRect);
+       rect.origin.x = NSMinX(aRect);
+    }
+    
+    if (NSMinY(aRect) <= NSMinY(bRect)) {
+       rect.size.height = MIN(NSMaxY(aRect), NSMaxY(bRect)) - NSMinY(bRect);
+       rect.origin.y = NSMinY(bRect);
+    } else {
+       rect.size.height = MIN(NSMaxY(aRect), NSMaxY(bRect)) - NSMinY(aRect);
+       rect.origin.y = NSMinY(aRect);
+    }
+    
+    return rect;
+}
+
+/* 
+* Test geometrical relationships 
+*/
+
+BOOL NSEqualRects(NSRect aRect, NSRect bRect)
+{
+    return (aRect.origin.x == bRect.origin.x &&
+                   aRect.origin.y == bRect.origin.y &&
+                   aRect.size.width == bRect.size.width &&
+                   aRect.size.height == bRect.size.height) ? YES : NO;
+}
+
+BOOL NSEqualSizes(NSSize aSize, NSSize bSize)
+{
+    return ((aSize.width == bSize.width) && (aSize.height == bSize.height));
+}
+
+BOOL NSEqualPoints(NSPoint aPoint, NSPoint bPoint)
+{
+    return ((aPoint.x == bPoint.x) && (aPoint.y == bPoint.y));
+}
+
+BOOL NSIsEmptyRect(NSRect aRect)
+{
+    return !lfVALID(aRect);
+}
+
+BOOL NSMouseInRect(NSPoint aPoint, NSRect aRect, BOOL flipped)
+{
+    if (flipped)
+       return ((aPoint.x >= aRect.origin.x) 
+               && (aPoint.y  >= aRect.origin.y)
+               && (aPoint.x  <  aRect.origin.x+aRect.size.width)
+               && (aPoint.y  <  aRect.origin.y+aRect.size.height));
+    else
+       return ((aPoint.x >= aRect.origin.x)
+               && (aPoint.y  >  aRect.origin.y)
+               && (aPoint.x  <  aRect.origin.x+aRect.size.width)
+               && (aPoint.y  <= aRect.origin.y+aRect.size.height));
+}
+
+BOOL NSPointInRect(NSPoint aPoint, NSRect aRect)
+{
+    return ((aPoint.x >= aRect.origin.x) 
+           && (aPoint.y  >= aRect.origin.y)
+           && (aPoint.x  <  aRect.origin.x+aRect.size.width)
+           && (aPoint.y  <  aRect.origin.y+aRect.size.height));
+}
+
+BOOL NSContainsRect(NSRect aRect, NSRect bRect)
+{
+    if (!lfVALID(bRect))
+       return NO;
+    
+    return ((NSMinX(aRect) < NSMinX(bRect)) &&
+                   (NSMinY(aRect) < NSMinY(bRect)) &&
+                   (NSMaxX(aRect) > NSMaxX(bRect)) &&
+                   (NSMaxY(aRect) > NSMaxY(bRect)));
+}
+
+/*
+ * Get a String Representation
+ */
+
+NSString* NSStringFromPoint(NSPoint aPoint)
+{
+    return [NSString stringWithFormat:@"{x=%f; y=%f}", 
+           aPoint.x, aPoint.y];
+}
+
+NSString* NSStringFromSize(NSSize aSize)
+{
+    return [NSString stringWithFormat:@"{width=%f; height=%f}", 
+           aSize.width, aSize.height];
+}
+
+NSString* NSStringFromRect(NSRect aRect)
+{
+    return [NSString stringWithFormat:@"{x=%f; y=%f; width=%f; height=%f}", 
+           aRect.origin.x, aRect.origin.y, 
+           aRect.size.width, aRect.size.height];
+}
+
+/*
+ * Reading from string representation
+ */
+
+NSPoint        NSPointFromString(NSString* string)
+{
+    NSScanner* scanner = [NSScanner scannerWithString:string];
+    NSPoint point;
+
+    if ([scanner scanString:@"{" intoString:NULL]
+       && [scanner scanString:@"x" intoString:NULL]
+       && [scanner scanString:@"=" intoString:NULL]
+       && [scanner scanFloat:&point.x]
+       && [scanner scanString:@";" intoString:NULL]
+
+       && [scanner scanString:@"y" intoString:NULL]
+       && [scanner scanString:@"=" intoString:NULL]
+       && [scanner scanFloat:&point.y]
+       && [scanner scanString:@"}" intoString:NULL])
+
+       return point;
+    else
+       return NSMakePoint(0, 0);
+}
+
+NSSize NSSizeFromString(NSString* string)
+{
+    NSScanner* scanner = [NSScanner scannerWithString:string];
+    NSSize size;
+
+    if ([scanner scanString:@"{" intoString:NULL]
+
+       && [scanner scanString:@"width" intoString:NULL]
+       && [scanner scanString:@"=" intoString:NULL]
+       && [scanner scanFloat:&size.width]
+       && [scanner scanString:@";" intoString:NULL]
+
+       && [scanner scanString:@"height" intoString:NULL]
+       && [scanner scanString:@"=" intoString:NULL]
+       && [scanner scanFloat:&size.height]
+       && [scanner scanString:@"}" intoString:NULL])
+
+       return size;
+    else
+       return NSMakeSize(0, 0);
+}
+
+NSRect NSRectFromString(NSString* string)
+{
+    NSScanner* scanner = [NSScanner scannerWithString:string];
+    NSRect rect;
+
+    if ([scanner scanString:@"{" intoString:NULL]
+       && [scanner scanString:@"x" intoString:NULL]
+       && [scanner scanString:@"=" intoString:NULL]
+       && [scanner scanFloat:&rect.origin.x]
+       && [scanner scanString:@";" intoString:NULL]
+
+       && [scanner scanString:@"y" intoString:NULL]
+       && [scanner scanString:@"=" intoString:NULL]
+       && [scanner scanFloat:&rect.origin.y]
+       && [scanner scanString:@";" intoString:NULL]
+
+       && [scanner scanString:@"width" intoString:NULL]
+       && [scanner scanString:@"=" intoString:NULL]
+       && [scanner scanFloat:&rect.size.width]
+       && [scanner scanString:@";" intoString:NULL]
+
+       && [scanner scanString:@"height" intoString:NULL]
+       && [scanner scanString:@"=" intoString:NULL]
+       && [scanner scanFloat:&rect.size.height]
+       && [scanner scanString:@"}" intoString:NULL])
+
+       return rect;
+    else
+       return NSMakeRect(0, 0, 0, 0);
+}
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSHashMap.m b/libFoundation/Foundation/NSHashMap.m
new file mode 100644 (file)
index 0000000..222ddf8
--- /dev/null
@@ -0,0 +1,1241 @@
+/* 
+   NSHashMap.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+          Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <math.h>
+
+#include <Foundation/common.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSUtilities.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+#include "lfmemory.h"
+
+static void __NSHashGrow(NSHashTable *table, unsigned newSize);
+static void __NSMapGrow(NSMapTable *table, unsigned newSize);
+
+#if LIB_FOUNDATION_BOEHM_GC || LIB_FOUNDATION_LEAK_GC
+/* Bucket descriptor for hash tables */
+static GC_descr hashBucketKeyInvisible = 0;
+
+/* Bucket descriptors for map tables */
+static GC_descr mapBucketKeyInvisible = 0;
+static GC_descr mapBucketValueInvisible = 0;
+static GC_descr mapBucketKeyValueInvisible = 0;
+#endif
+
+/*
+ *  Hash and Map Table utilities
+ */
+
+static BOOL is_prime(unsigned n)
+{
+    int i, n2 = sqrt(n);
+
+    for(i = 2; i <= n2; i++)
+        if(n % i == 0)
+            return NO;
+    return YES;
+}
+
+static unsigned nextPrime(unsigned old_value)
+{
+    unsigned i, new_value = old_value | 1;
+
+    for(i = new_value; i >= new_value; i += 2)
+        if(is_prime(i))
+            return i;
+    return old_value;
+}
+
+/* Check if nodeTable isn't full. */
+static void __NSCheckHashTableFull(NSHashTable* table)
+{
+    if( ++(table->itemsCount) >= ((table->hashSize * 3) / 4)) {
+       unsigned newSize = nextPrime((table->hashSize * 4) / 3);
+       if(newSize != table->hashSize)
+           __NSHashGrow(table, newSize);
+    }
+}
+
+static void __NSCheckMapTableFull(NSMapTable* table)
+{
+    if( ++(table->itemsCount) >= ((table->hashSize * 3) / 4)) {
+       unsigned newSize = nextPrime((table->hashSize * 4) / 3);
+       if(newSize != table->hashSize)
+           __NSMapGrow(table, newSize);
+    }
+}
+
+/*
+ * NSHashTable functions
+ */
+
+/* Create a Table */
+LF_DECLARE NSHashTable *NSCreateHashTable(NSHashTableCallBacks callBacks, 
+                                         unsigned capacity)
+{
+    return NSCreateHashTableWithZone(callBacks, capacity, NULL);
+}
+
+static NSHashTable*
+_NSCreateHashTableWithZone(NSHashTableCallBacks callBacks, 
+       unsigned capacity, NSZone *zone, BOOL keysInvisible)
+{
+    NSHashTable* table = NSZoneMalloc(zone, sizeof(NSHashTable));
+
+#if LIB_FOUNDATION_BOEHM_GC || LIB_FOUNDATION_LEAK_GC
+    /* Create the descriptor used by the bucket whose key is uncollectable */
+    if (!hashBucketKeyInvisible) {
+        GC_word bm = 0x4;
+        hashBucketKeyInvisible = GC_make_descriptor (&bm, 2);
+    }
+#endif
+    
+    capacity = capacity ? capacity : 13;
+    if (!is_prime(capacity))
+       capacity = nextPrime(capacity);
+
+    table->hashSize = capacity;
+    table->nodes = NSZoneCalloc(zone, table->hashSize, sizeof(void*));
+    table->itemsCount = 0;
+    table->callbacks = callBacks;
+    table->zone = zone ? zone : NSDefaultMallocZone();
+    if (table->callbacks.hash == NULL)
+       table->callbacks.hash = 
+           (unsigned(*)(NSHashTable*, const void*))__NSHashPointer;
+    if (table->callbacks.isEqual == NULL)
+       table->callbacks.isEqual = 
+       (BOOL(*)(NSHashTable*, const void*, const void*)) __NSComparePointers;
+    if (table->callbacks.retain == NULL)
+       table->callbacks.retain = 
+           (void(*)(NSHashTable*, const void*))__NSRetainNothing;
+    if (table->callbacks.release == NULL)
+       table->callbacks.release = 
+           (void(*)(NSHashTable*, void*))__NSReleaseNothing;
+    if (table->callbacks.describe == NULL)
+       table->callbacks.describe = 
+           (NSString*(*)(NSHashTable*, const void*))__NSDescribePointers;
+    table->keysInvisible = keysInvisible;
+    return table;
+}
+
+LF_EXPORT
+NSHashTable *NSCreateHashTableWithZone(NSHashTableCallBacks callBacks, 
+                                      unsigned capacity, NSZone *zone)
+{
+  return _NSCreateHashTableWithZone (callBacks, capacity, zone, NO);
+}
+
+/* Create a hash table whose keys are not collectable */
+LF_DECLARE
+NSHashTable *NSCreateHashTableInvisibleKeys(NSHashTableCallBacks callBacks,
+                                           unsigned capacity)
+{
+  return _NSCreateHashTableWithZone (callBacks, capacity, NULL, YES);
+}
+
+LF_DECLARE
+NSHashTable *NSCopyHashTableWithZone(NSHashTable *table, NSZone *zone)
+{
+    NSHashTable *new;
+    struct _NSHashNode *oldnode, *newnode;
+    unsigned i;
+    
+    zone = zone ? zone : NSDefaultMallocZone();
+    new = NSZoneMalloc(zone, sizeof(NSHashTable));
+    new->zone = zone;
+    new->hashSize = table->hashSize;
+    new->itemsCount = table->itemsCount;
+    new->callbacks = table->callbacks;
+    new->nodes = NSZoneCalloc(zone, new->hashSize, sizeof(void*));
+    
+    for (i = 0; i < new->hashSize; i++) {
+       for (oldnode = table->nodes[i]; oldnode; oldnode = oldnode->next) {
+#if LIB_FOUNDATION_BOEHM_GC || LIB_FOUNDATION_LEAK_GC
+           if (table->keysInvisible)
+               newnode =
+                 GC_MALLOC_EXPLICTLY_TYPED (sizeof (struct _NSHashNode),
+                                             hashBucketKeyInvisible);
+           else
+#endif
+               newnode = NSZoneMalloc(zone, sizeof(struct _NSHashNode));
+           newnode->key = oldnode->key;
+           newnode->next = new->nodes[i];
+           new->nodes[i] = newnode;
+           table->callbacks.retain(new, oldnode->key);
+       }
+    }
+    
+    return new;
+}
+
+/* Free a Table */
+LF_DECLARE void NSFreeHashTable(NSHashTable *table)
+{
+    NSResetHashTable(table);
+    NSZoneFree(table->zone, table->nodes);
+    NSZoneFree(table->zone, table);
+}
+
+LF_DECLARE void NSResetHashTable(NSHashTable *table)
+{
+    unsigned i;
+
+    if (!table->itemsCount)
+        return;
+
+    for(i=0; i < table->hashSize; i++) {
+       struct _NSHashNode *next, *node;
+       
+       node = table->nodes[i];
+       table->nodes[i] = NULL;         
+       while (node) {
+           table->callbacks.release(table, node->key);
+           next = node->next;
+           NSZoneFree(table->zone, node);
+           node = next;
+       }
+    }
+    table->itemsCount = 0;
+}
+
+/* Compare Two Tables */
+LF_DECLARE BOOL NSCompareHashTables(NSHashTable *table1, NSHashTable *table2)
+{
+    unsigned i;
+    struct _NSHashNode *node1;
+    
+    if (table1->hashSize != table2->hashSize)
+       return NO;
+    for (i=0; i<table1->hashSize; i++) {
+       for (node1 = table1->nodes[i]; node1; node1 = node1->next) {
+           if (NSHashGet(table2, node1->key) == NULL)
+               return NO;
+       }
+    }
+    return YES;;
+}      
+
+/* Get the Number of Items */
+LF_DECLARE unsigned NSCountHashTable(NSHashTable *table)
+{
+    return table->itemsCount;
+}
+
+/* Retrieve Items */
+LF_DECLARE void *NSHashGet(NSHashTable *table, const void *pointer)
+{
+    struct _NSHashNode* node = table->nodes[
+               table->callbacks.hash(table, pointer) % table->hashSize];
+    for(; node; node = node->next)
+        if(table->callbacks.isEqual(table, pointer, node->key))
+            return node->key;
+    return NULL;
+}
+
+LF_DECLARE NSArray *NSAllHashTableObjects(NSHashTable *table)
+{
+    id array = [NSMutableArray arrayWithCapacity:table->itemsCount];
+    struct _NSHashNode *node;
+    unsigned i;
+
+    for(i=0; i < table->hashSize; i++)
+       for(node=table->nodes[i]; node; node=node->next)
+               [array addObject:(NSObject*)(node->key)];
+    return array;
+}
+
+LF_DECLARE NSHashEnumerator NSEnumerateHashTable(NSHashTable *table)
+{
+    NSHashEnumerator en;
+    en.table = table;
+    en.node = NULL;
+    en.bucket = -1;
+    return en;
+}
+
+LF_DECLARE void *NSNextHashEnumeratorItem(NSHashEnumerator *en)
+{
+    if(en->node)
+       en->node = en->node->next;
+    if(en->node == NULL) {
+       for(en->bucket++; ((unsigned)en->bucket)<en->table->hashSize; en->bucket++)
+           if (en->table->nodes[en->bucket]) {
+                   en->node = en->table->nodes[en->bucket];
+                   break;
+           };
+       if (((unsigned)en->bucket) >= en->table->hashSize) {
+           en->node = NULL;
+           en->bucket = en->table->hashSize-1;
+           return NULL;
+       }
+    }
+    return en->node->key;
+}
+
+/* Add or Remove an Item */
+static void __NSHashGrow(NSHashTable *table, unsigned newSize)
+{
+    unsigned i;
+    struct _NSHashNode** newNodeTable = NSZoneCalloc(table->zone, 
+       newSize, sizeof(struct _NSHashNode*));
+    
+    for(i = 0; i < table->hashSize; i++) {
+       struct _NSHashNode *next, *node;
+       unsigned int h;
+
+       node = table->nodes[i];
+       while(node) {
+           next = node->next;
+           h = table->callbacks.hash(table, node->key) % newSize;
+           node->next = newNodeTable[h];
+           newNodeTable[h] = node;
+           node = next;
+       }
+    }
+    NSZoneFree(table->zone, table->nodes);
+       table->nodes = newNodeTable;
+    table->hashSize = newSize;
+}
+
+LF_DECLARE void NSHashInsert(NSHashTable *table, const void *pointer)
+{
+    unsigned int h;
+    struct _NSHashNode *node;
+
+    if (pointer == nil)
+       [[[InvalidArgumentException alloc] initWithReason:
+               @"Nil object to be added in NSHashTable"] raise];
+
+    h = table->callbacks.hash(table, pointer) % table->hashSize;
+    for(node = table->nodes[h]; node; node = node->next)
+        if(table->callbacks.isEqual(table, pointer, node->key))
+            break;
+
+    /* Check if an entry for key exist in nodeTable. */
+    if(node) {
+        /* key exist. Set for it new value and return the old value of it. */
+       if (pointer != node->key) {
+           table->callbacks.retain(table, pointer);
+           table->callbacks.release(table, node->key);
+       }
+       node->key = (void*)pointer;
+        return;
+    }
+
+    /* key not found. Allocate a new bucket and initialize it. */
+#if LIB_FOUNDATION_BOEHM_GC || LIB_FOUNDATION_LEAK_GC
+    if (table->keysInvisible)
+        node = GC_MALLOC_EXPLICTLY_TYPED (sizeof (struct _NSHashNode),
+                                          hashBucketKeyInvisible);
+    else
+#endif
+    node = NSZoneMalloc(table->zone, sizeof(struct _NSHashNode));
+
+    table->callbacks.retain(table, pointer);
+    node->key = (void*)pointer;
+    node->next = table->nodes[h];
+    table->nodes[h] = node;
+
+    __NSCheckHashTableFull(table);
+}
+
+LF_DECLARE
+void NSHashInsertKnownAbsent(NSHashTable *table, const void *pointer)
+{
+    unsigned int h;
+    struct _NSHashNode *node;
+
+    if (pointer == nil)
+       [[[InvalidArgumentException alloc] initWithReason:
+               @"Nil object to be added in NSHashTable"] raise];
+
+    h = table->callbacks.hash(table, pointer) % table->hashSize;
+    for(node = table->nodes[h]; node; node = node->next)
+        if(table->callbacks.isEqual(table, pointer, node->key))
+            break;
+
+    /* Check if an entry for key exist in nodeTable. */
+    if(node) 
+       [[[InvalidArgumentException alloc] initWithReason:
+               @"Nil object already existing in NSHashTable"] raise];
+
+    /* key not found. Allocate a new bucket and initialize it. */
+#if LIB_FOUNDATION_BOEHM_GC || LIB_FOUNDATION_LEAK_GC
+    if (table->keysInvisible)
+        node = GC_MALLOC_EXPLICTLY_TYPED (sizeof (struct _NSHashNode),
+                                          hashBucketKeyInvisible);
+    else
+#endif
+    node = NSZoneMalloc(table->zone, sizeof(struct _NSHashNode));
+
+    table->callbacks.retain(table, pointer);
+    node->key = (void*)pointer;
+    node->next = table->nodes[h];
+    table->nodes[h] = node;
+
+    __NSCheckHashTableFull(table);
+}
+
+LF_DECLARE void *NSHashInsertIfAbsent(NSHashTable *table, const void *pointer)
+{
+    unsigned int h;
+    struct _NSHashNode *node;
+
+    if (pointer == nil)
+       [[[InvalidArgumentException alloc] initWithReason:
+               @"Nil object to be added in NSHashTable"] raise];
+
+    h = table->callbacks.hash(table, pointer) % table->hashSize;
+    for(node = table->nodes[h]; node; node = node->next)
+        if(table->callbacks.isEqual(table, pointer, node->key))
+            break;
+
+    /* Check if an entry for key exist in nodeTable. */
+    if(node)
+       return node->key;
+       
+    /* key not found. Allocate a new bucket and initialize it. */
+#if LIB_FOUNDATION_BOEHM_GC || LIB_FOUNDATION_LEAK_GC
+    if (table->keysInvisible)
+        node = GC_MALLOC_EXPLICTLY_TYPED (sizeof (struct _NSHashNode),
+                                          hashBucketKeyInvisible);
+    else
+#endif
+    node = NSZoneMalloc(table->zone, sizeof(struct _NSHashNode));
+    table->callbacks.retain(table, pointer);
+    node->key = (void*)pointer;
+    node->next = table->nodes[h];
+    table->nodes[h] = node;
+
+    __NSCheckHashTableFull(table);
+    
+    return NULL;
+}
+
+LF_DECLARE void NSHashRemove(NSHashTable *table, const void *pointer)
+{
+    unsigned int h;
+    struct _NSHashNode *node, *node1 = NULL;
+
+    if (pointer == nil)
+           return;
+
+    h = table->callbacks.hash(table, pointer) % table->hashSize;
+
+    // node point to current bucket, and node1 to previous bucket or to NULL
+    // if current node is the first node in the list 
+
+    for(node = table->nodes[h]; node; node1 = node, node = node->next)
+        if(table->callbacks.isEqual(table, pointer, node->key)) {
+           table->callbacks.release(table, node->key);
+            if(!node1)
+                table->nodes[h] = node->next;
+            else
+                node1->next = node->next;
+           NSZoneFree(table->zone, node);
+           (table->itemsCount)--;
+           return;
+        }
+}
+
+/* Get a String Representation */
+LF_DECLARE NSString *NSStringFromHashTable(NSHashTable *table)
+{
+    id ret = [NSMutableString new];
+    unsigned i;
+    struct _NSHashNode *node;
+    
+    for (i=0; i<table->hashSize; i++)
+       for (node = table->nodes[i]; node; node = node->next) {
+           [ret appendString:table->callbacks.describe(table, node->key)];
+           [ret appendString:@" "];
+       }
+    
+    return ret;
+}
+
+/* 
+ * Map Table Functions 
+ */
+
+/* Create a Table */
+LF_DECLARE
+NSMapTable *NSCreateMapTable(NSMapTableKeyCallBacks keyCallbacks, 
+                            NSMapTableValueCallBacks valueCallbacks,
+                            unsigned capacity)
+{
+    return NSCreateMapTableWithZone(keyCallbacks, valueCallbacks, capacity, NULL);
+}
+
+LF_DECLARE
+NSMapTable *_NSCreateMapTableWithZone(NSMapTableKeyCallBacks   keyCallbacks, 
+                                     NSMapTableValueCallBacks valueCallbacks,
+                                     unsigned capacity,
+                                     NSZone   *zone,
+                                     BOOL     keysInvisible,
+                                     BOOL     valuesInvisible)
+{
+    NSMapTable *table = NSZoneMalloc(zone, sizeof(NSMapTable));
+
+#if LIB_FOUNDATION_BOEHM_GC || LIB_FOUNDATION_LEAK_GC
+    if (!mapBucketKeyInvisible) {
+        GC_word bm1 = 0x6, bm2 = 0x5, bm3 = 0x4;
+        
+        mapBucketKeyInvisible      = GC_make_descriptor (&bm1, 3);
+       mapBucketValueInvisible    = GC_make_descriptor (&bm2, 3);
+       mapBucketKeyValueInvisible = GC_make_descriptor (&bm3, 3);
+    }
+#endif
+
+    capacity = capacity ? capacity : 13;
+    if (!is_prime(capacity))
+       capacity = nextPrime(capacity);
+
+    table->hashSize = capacity;
+    table->nodes = NSZoneCalloc(zone, table->hashSize, sizeof(void*));
+    table->itemsCount = 0;
+    table->keyCallbacks = keyCallbacks;
+    table->valueCallbacks = valueCallbacks;
+    table->zone = zone ? zone : NSDefaultMallocZone();
+    if (table->keyCallbacks.hash == NULL)
+       table->keyCallbacks.hash = 
+               (unsigned(*)(NSMapTable*, const void*))__NSHashPointer;
+    if (table->keyCallbacks.isEqual == NULL)
+       table->keyCallbacks.isEqual = 
+       (BOOL(*)(NSMapTable*, const void*, const void*)) __NSComparePointers;
+    if (table->keyCallbacks.retain == NULL)
+       table->keyCallbacks.retain = 
+           (void(*)(NSMapTable*, const void*))__NSRetainNothing;
+    if (table->keyCallbacks.release == NULL)
+       table->keyCallbacks.release = 
+           (void(*)(NSMapTable*, void*))__NSReleaseNothing;
+    if (table->keyCallbacks.describe == NULL)
+       table->keyCallbacks.describe = 
+           (NSString*(*)(NSMapTable*, const void*))__NSDescribePointers;
+    if (table->valueCallbacks.retain == NULL)
+       table->valueCallbacks.retain = 
+           (void(*)(NSMapTable*, const void*))__NSRetainNothing;
+    if (table->valueCallbacks.release == NULL)
+       table->valueCallbacks.release = 
+           (void(*)(NSMapTable*, void*))__NSReleaseNothing;
+    if (table->valueCallbacks.describe == NULL)
+       table->valueCallbacks.describe = 
+           (NSString*(*)(NSMapTable*, const void*))__NSDescribePointers;
+    table->keysInvisible = keysInvisible;
+    table->valuesInvisible = valuesInvisible;
+    return table;
+}
+
+LF_DECLARE
+NSMapTable *NSCreateMapTableWithZone(NSMapTableKeyCallBacks keyCallbacks, 
+                                    NSMapTableValueCallBacks valueCallbacks,
+                                    unsigned capacity,
+                                    NSZone *zone)
+{
+    return _NSCreateMapTableWithZone (keyCallbacks, valueCallbacks,
+                                     capacity, zone, NO, NO);
+}
+
+LF_DECLARE NSMapTable *NSCreateMapTableInvisibleKeysOrValues(
+    NSMapTableKeyCallBacks keyCallbacks, 
+    NSMapTableValueCallBacks valueCallbacks,
+    unsigned capacity,
+    BOOL keysInvisible,
+    BOOL valuesInvisible)
+{
+    return _NSCreateMapTableWithZone (keyCallbacks, valueCallbacks,
+                                     capacity, NULL,
+                                     keysInvisible, valuesInvisible);
+}
+
+LF_DECLARE NSMapTable *NSCopyMapTableWithZone(NSMapTable *table, NSZone *zone)
+{
+    NSMapTable *new;
+    struct _NSMapNode *oldnode, *newnode;
+    unsigned i;
+    
+    zone = zone ? zone : NSDefaultMallocZone();
+    new = NSZoneMalloc(zone, sizeof(NSMapTable));
+    new->zone = zone;
+    new->hashSize = table->hashSize;
+    new->itemsCount = table->itemsCount;
+    new->keyCallbacks = table->keyCallbacks;
+    new->valueCallbacks = table->valueCallbacks;
+    new->nodes = NSZoneCalloc(zone, new->hashSize, sizeof(void*));
+    
+    for (i=0; i<new->hashSize; i++) {
+       for (oldnode = table->nodes[i]; oldnode; oldnode = oldnode->next) {
+#if LIB_FOUNDATION_BOEHM_GC || LIB_FOUNDATION_LEAK_GC
+           if (table->keysInvisible && table->valuesInvisible)
+               newnode =
+                 GC_MALLOC_EXPLICTLY_TYPED (sizeof (struct _NSMapNode),
+                                             mapBucketKeyValueInvisible);
+           else if (table->keysInvisible)
+               newnode =
+                 GC_MALLOC_EXPLICTLY_TYPED (sizeof (struct _NSMapNode),
+                                             mapBucketKeyInvisible);
+           else if (table->valuesInvisible)
+               newnode =
+                 GC_MALLOC_EXPLICTLY_TYPED (sizeof (struct _NSMapNode),
+                                             mapBucketValueInvisible);
+           else
+#endif
+               newnode = NSZoneMalloc(zone, sizeof(struct _NSMapNode));
+           newnode->key = oldnode->key;
+           newnode->value = oldnode->value;
+           newnode->next = new->nodes[i];
+           new->nodes[i] = newnode;
+           table->keyCallbacks.retain(new, oldnode->key);
+           table->valueCallbacks.retain(new, oldnode->value);
+       }
+    }
+    
+    return new;
+}
+
+/* Free a Table */
+LF_DECLARE void NSFreeMapTable(NSMapTable *table)
+{
+    NSResetMapTable(table);
+    NSZoneFree(table->zone, table->nodes);
+    NSZoneFree(table->zone, table);
+}
+
+LF_DECLARE void NSResetMapTable(NSMapTable *table)
+{
+    unsigned i;
+
+    if (!table->itemsCount)
+        return;
+    
+    for(i=0; i < table->hashSize; i++) {
+       struct _NSMapNode *next, *node;
+       
+       node = table->nodes[i];
+       table->nodes[i] = NULL;         
+       while (node) {
+           table->keyCallbacks.release(table, node->key);
+           table->valueCallbacks.release(table, node->value);
+           next = node->next;
+           NSZoneFree(table->zone, node);
+           node = next;
+       }
+    }
+    table->itemsCount = 0;
+}
+
+/* Compare Two Tables */
+LF_DECLARE BOOL NSCompareMapTables(NSMapTable *table1, NSMapTable *table2)
+{
+    unsigned i;
+    struct _NSMapNode *node1;
+    
+    if (table1->hashSize != table2->hashSize)
+       return NO;
+    for (i=0; i<table1->hashSize; i++) {
+       for (node1 = table1->nodes[i]; node1; node1 = node1->next) {
+           if (NSMapGet(table2, node1->key) != node1->value)
+               return NO;
+       }
+    }
+    return YES;
+}
+
+/* Get the Number of Items */
+LF_DECLARE unsigned NSCountMapTable(NSMapTable *table)
+{
+    return table->itemsCount;
+}
+
+/* Retrieve Items */
+LF_DECLARE BOOL NSMapMember(NSMapTable *table, const void *key, 
+                           void **originalKey, void **value)
+{
+    struct _NSMapNode* node = table->nodes[
+               table->keyCallbacks.hash(table, key) % table->hashSize];
+    for(; node; node = node->next)
+        if(table->keyCallbacks.isEqual(table, key, node->key)) {
+            *originalKey = node->key;
+           *value = node->value;
+           return YES;
+       }
+    return NO;
+}
+
+LF_DECLARE void *NSMapGet(NSMapTable *table, const void *key)
+{
+    struct _NSMapNode* node = table->nodes[
+               table->keyCallbacks.hash(table, key) % table->hashSize];
+    for(; node; node = node->next)
+        if(table->keyCallbacks.isEqual(table, key, node->key))
+            return node->value;
+    return NULL;
+}
+
+LF_DECLARE NSMapEnumerator NSEnumerateMapTable(NSMapTable *table)
+{
+    NSMapEnumerator en;
+    en.table = table;
+    en.node = NULL;
+    en.bucket = -1;
+    return en;
+}
+
+LF_DECLARE BOOL NSNextMapEnumeratorPair(NSMapEnumerator *en, 
+                                       void **key, void **value)
+{
+    if(en->node)
+       en->node = en->node->next;
+    if(en->node == NULL) {
+       for(en->bucket++; ((unsigned)en->bucket)<en->table->hashSize; en->bucket++)
+           if (en->table->nodes[en->bucket]) {
+                   en->node = en->table->nodes[en->bucket];
+                   break;
+           }
+       if (((unsigned)en->bucket) >= en->table->hashSize) {
+           en->node = NULL;
+           en->bucket = en->table->hashSize-1;
+           return NO;
+       }
+    }
+    *key = en->node->key;
+    *value = en->node->value;
+    return YES;
+}
+
+LF_DECLARE NSArray *NSAllMapTableKeys(NSMapTable *table)
+{
+    id array = [NSMutableArray arrayWithCapacity:table->itemsCount];
+    struct _NSMapNode *node;
+    unsigned i;
+
+    for(i=0; i < table->hashSize; i++)
+       for(node=table->nodes[i]; node; node=node->next)
+           [array addObject:(NSObject*)(node->key)];
+    return array;
+}
+
+LF_DECLARE NSArray *NSAllMapTableValues(NSMapTable *table)
+{
+    id array = [NSMutableArray arrayWithCapacity:table->itemsCount];
+    struct _NSMapNode *node;
+    unsigned i;
+
+    for(i=0; i < table->hashSize; i++)
+       for(node=table->nodes[i]; node; node=node->next)
+           [array addObject:(NSObject*)(node->value)];
+    return array;
+}
+
+/* Add or Remove an Item */
+static void __NSMapGrow(NSMapTable *table, unsigned newSize)
+{
+    unsigned i;
+    struct _NSMapNode** newNodeTable = NSZoneCalloc(table->zone,
+       newSize, sizeof(struct _NSMapNode*));
+
+    for(i = 0; i < table->hashSize; i++) {
+       struct _NSMapNode *next, *node;
+       unsigned int h;
+
+       node = table->nodes[i];
+       while(node) {
+           next = node->next;
+           h = table->keyCallbacks.hash(table, node->key) % newSize;
+           node->next = newNodeTable[h];
+           newNodeTable[h] = node;
+           node = next;
+       }
+    }
+    NSZoneFree(table->zone, table->nodes);
+    table->nodes = newNodeTable;
+    table->hashSize = newSize;
+}
+
+LF_DECLARE void NSMapInsert(NSMapTable *table, const void *key, const void *value)
+{
+    unsigned int h;
+    struct _NSMapNode *node;
+
+    if (key == table->keyCallbacks.notAKeyMarker)
+       [[[InvalidArgumentException alloc] initWithReason:
+               @"Invalid key to be added in NSMapTable"] raise];
+
+    h = table->keyCallbacks.hash(table, key) % table->hashSize;
+    for(node = table->nodes[h]; node; node = node->next)
+        if(table->keyCallbacks.isEqual(table, key, node->key))
+            break;
+
+    /* Check if an entry for key exist in nodeTable. */
+    if(node) {
+        /* key exist. Set for it new value and return the old value of it. */
+       if (key != node->key) {
+           table->keyCallbacks.retain(table, key);
+           table->keyCallbacks.release(table, node->key);
+       }
+       if (value != node->value) {
+           table->valueCallbacks.retain(table, value);
+           table->valueCallbacks.release(table, node->value);
+       }
+       node->key   = (void*)key;
+       node->value = (void*)value;
+        return;
+    }
+
+    /* key not found. Allocate a new bucket and initialize it. */
+#if LIB_FOUNDATION_BOEHM_GC || LIB_FOUNDATION_LEAK_GC
+    if (table->keysInvisible && table->valuesInvisible)
+        node =
+         GC_MALLOC_EXPLICTLY_TYPED (sizeof (struct _NSMapNode),
+                                     mapBucketKeyValueInvisible);
+    else if (table->keysInvisible)
+        node =
+         GC_MALLOC_EXPLICTLY_TYPED (sizeof (struct _NSMapNode),
+                                     mapBucketKeyInvisible);
+    else if (table->valuesInvisible)
+        node =
+         GC_MALLOC_EXPLICTLY_TYPED (sizeof (struct _NSMapNode),
+                                     mapBucketValueInvisible);
+    else
+#endif
+        node = NSZoneMalloc(table->zone, sizeof(struct _NSMapNode));
+
+    table->keyCallbacks.retain(table, key);
+    table->valueCallbacks.retain(table, value);
+    node->key = (void*)key;
+    node->value = (void*)value;
+    node->next = table->nodes[h];
+    table->nodes[h] = node;
+
+    __NSCheckMapTableFull(table);
+}
+
+LF_DECLARE void *NSMapInsertIfAbsent(NSMapTable *table, const void *key, 
+                                    const void *value)
+{
+    unsigned int h;
+    struct _NSMapNode *node;
+
+    if (key == table->keyCallbacks.notAKeyMarker)
+       [[[InvalidArgumentException alloc] initWithReason:
+               @"Invalid key to be added in NSMapTable"] raise];
+
+    h = table->keyCallbacks.hash(table, key) % table->hashSize;
+    for(node = table->nodes[h]; node; node = node->next)
+        if(table->keyCallbacks.isEqual(table, key, node->key))
+            break;
+
+    /* Check if an entry for key exist in nodeTable. */
+    if(node) {
+        return node->key;
+    }
+
+    /* key not found. Allocate a new bucket and initialize it. */
+#if LIB_FOUNDATION_BOEHM_GC || LIB_FOUNDATION_LEAK_GC
+    if (table->keysInvisible && table->valuesInvisible)
+        node =
+         GC_MALLOC_EXPLICTLY_TYPED (sizeof (struct _NSMapNode),
+                                     mapBucketKeyValueInvisible);
+    else if (table->keysInvisible)
+        node =
+         GC_MALLOC_EXPLICTLY_TYPED (sizeof (struct _NSMapNode),
+                                     mapBucketKeyInvisible);
+    else if (table->valuesInvisible)
+        node =
+         GC_MALLOC_EXPLICTLY_TYPED (sizeof (struct _NSMapNode),
+                                     mapBucketValueInvisible);
+    else
+#endif
+        node = NSZoneMalloc(table->zone, sizeof(struct _NSMapNode));
+
+    table->keyCallbacks.retain(table, key);
+    table->valueCallbacks.retain(table, value);
+    node->key = (void*)key;
+    node->value = (void*)value;
+    node->next = table->nodes[h];
+    table->nodes[h] = node;
+
+    __NSCheckMapTableFull(table);
+
+    return NULL;
+}
+
+LF_DECLARE void NSMapInsertKnownAbsent(NSMapTable *table, const void *key, 
+                                      const void *value)
+{
+    unsigned int h;
+    struct _NSMapNode *node;
+
+    if (key == table->keyCallbacks.notAKeyMarker)
+       [[[InvalidArgumentException alloc] initWithReason:
+               @"Invalid key to be added in NSMapTable"] raise];
+
+    h = table->keyCallbacks.hash(table, key) % table->hashSize;
+    for(node = table->nodes[h]; node; node = node->next)
+        if(table->keyCallbacks.isEqual(table, key, node->key))
+            break;
+
+    /* Check if an entry for key exist in nodeTable. */
+    if(node) 
+       [[[InvalidArgumentException alloc] initWithReason:
+               @"Nil object already existing in NSMapTable"] raise];
+
+    /* key not found. Allocate a new bucket and initialize it. */
+#if LIB_FOUNDATION_BOEHM_GC || LIB_FOUNDATION_LEAK_GC
+    if (table->keysInvisible && table->valuesInvisible)
+        node =
+         GC_MALLOC_EXPLICTLY_TYPED (sizeof (struct _NSMapNode),
+                                     mapBucketKeyValueInvisible);
+    else if (table->keysInvisible)
+        node =
+         GC_MALLOC_EXPLICTLY_TYPED (sizeof (struct _NSMapNode),
+                                     mapBucketKeyInvisible);
+    else if (table->valuesInvisible)
+        node =
+         GC_MALLOC_EXPLICTLY_TYPED (sizeof (struct _NSMapNode),
+                                     mapBucketValueInvisible);
+    else
+#endif
+        node = NSZoneMalloc(table->zone, sizeof(struct _NSMapNode));
+
+    table->keyCallbacks.retain(table, key);
+    table->valueCallbacks.retain(table, value);
+    node->key = (void*)key;
+    node->value = (void*)value;
+    node->next = table->nodes[h];
+    table->nodes[h] = node;
+
+    __NSCheckMapTableFull(table);
+}
+
+LF_DECLARE void NSMapRemove(NSMapTable *table, const void *key)
+{
+    unsigned int h;
+    struct _NSMapNode *node, *node1 = NULL;
+
+    if (key == nil)
+           return;
+
+    h = table->keyCallbacks.hash(table, key) % table->hashSize;
+
+    // node point to current bucket, and node1 to previous bucket or to NULL
+    // if current node is the first node in the list 
+
+    for(node = table->nodes[h]; node; node1 = node, node = node->next)
+        if(table->keyCallbacks.isEqual(table, key, node->key)) {
+           table->keyCallbacks.release(table, node->key);
+           table->valueCallbacks.release(table, node->value);
+            if(!node1)
+                table->nodes[h] = node->next;
+            else
+                node1->next = node->next;
+           NSZoneFree(table->zone, node);
+           (table->itemsCount)--;
+           return;
+        }
+}
+
+LF_DECLARE NSString *NSStringFromMapTable(NSMapTable *table)
+{
+    id ret = [NSMutableString new];
+    unsigned i;
+    struct _NSMapNode *node;
+    
+    for (i=0; i<table->hashSize; i++)
+       for (node = table->nodes[i]; node; node = node->next) {
+           [ret appendString:table->keyCallbacks.describe(table, node->key)];
+           [ret appendString:@"="];
+           [ret appendString:table->valueCallbacks.describe(table, node->value)];
+           [ret appendString:@"\n"];
+       }
+    
+    return ret;
+}
+
+/*
+ * Convenience functions
+ */
+LF_DECLARE unsigned __NSHashObject(void *table, const void *anObject)
+{
+    return (unsigned)[(id)anObject hash];
+}
+
+LF_DECLARE unsigned __NSHashPointer(void *table, const void *anObject)
+{
+    return (unsigned)((long)anObject / 4);
+}
+
+LF_DECLARE unsigned __NSHashInteger(void *table, const void *anObject)
+{
+    return (unsigned)(long)anObject;
+}
+
+/* From Aho, Sethi & Ullman: Principles of compiler design. */
+LF_DECLARE unsigned __NSHashCString(void *table, const void *aString)
+{
+    register const char* p = (char*)aString;
+    register unsigned hash = 0, hash2;
+    register int i, n = Strlen((char*)aString);
+
+    for(i=0; i < n; i++) {
+        hash <<= 4;
+        hash += *p++;
+        if((hash2 = hash & 0xf0000000))
+            hash ^= (hash2 >> 24) ^ hash2;
+    }
+    return hash;
+}
+
+LF_DECLARE BOOL __NSCompareObjects(void *table, 
+                                  const void *anObject1,
+                                  const void *anObject2)
+{
+    return [(NSObject*)anObject1 isEqual:(NSObject*)anObject2];
+}
+
+LF_DECLARE BOOL __NSComparePointers(void *table, 
+                                   const void *anObject1,
+                                   const void *anObject2)
+{
+    return anObject1 == anObject2;
+}
+
+LF_DECLARE BOOL __NSCompareInts(void *table, 
+                               const void *anObject1, const void *anObject2)
+{
+    return anObject1 == anObject2;
+}
+
+LF_DECLARE BOOL __NSCompareCString(void *table, 
+                                  const void *anObject1,
+                                  const void *anObject2)
+{
+    return Strcmp((char*)anObject1, (char*)anObject2) == 0;
+}
+
+LF_DECLARE void __NSRetainNothing(void *table, const void *anObject)
+{
+}
+
+LF_DECLARE void __NSRetainObjects(void *table, const void *anObject)
+{
+    (void)RETAIN((NSObject*)anObject);
+}
+
+LF_DECLARE void __NSReleaseNothing(void *table, void *anObject)
+{
+}
+
+LF_DECLARE void __NSReleaseObjects(void *table, void *anObject)
+{
+    RELEASE((NSObject*)anObject);
+}
+
+LF_DECLARE void __NSReleasePointers(void *table, void *anObject)
+{
+    lfFree(anObject);
+}
+
+LF_DECLARE NSString* __NSDescribeObjects(void *table, const void *anObject)
+{
+    return [(NSObject*)anObject description];
+}
+
+LF_DECLARE NSString* __NSDescribePointers(void *table, const void *anObject)
+{
+    return [NSString stringWithFormat:@"%p", anObject];
+}
+
+LF_DECLARE NSString* __NSDescribeInts(void *table, const void *anObject)
+{
+    return [NSString stringWithFormat:@"%ld", (long)anObject];
+}
+
+/*
+* NSHashTable predefined callbacks
+*/
+
+LF_DECLARE const NSHashTableCallBacks NSIntHashCallBacks = { 
+    (unsigned(*)(NSHashTable*, const void*))__NSHashInteger, 
+    (BOOL(*)(NSHashTable*, const void*, const void*))__NSCompareInts, 
+    (void(*)(NSHashTable*, const void*))__NSRetainNothing, 
+    (void(*)(NSHashTable*, void*))__NSReleaseNothing, 
+    (NSString*(*)(NSHashTable*, const void*))__NSDescribeInts 
+};
+
+LF_DECLARE const NSHashTableCallBacks NSNonOwnedPointerHashCallBacks = { 
+    (unsigned(*)(NSHashTable*, const void*))__NSHashPointer, 
+    (BOOL(*)(NSHashTable*, const void*, const void*))__NSComparePointers, 
+    (void(*)(NSHashTable*, const void*))__NSRetainNothing, 
+    (void(*)(NSHashTable*, void*))__NSReleaseNothing, 
+    (NSString*(*)(NSHashTable*, const void*))__NSDescribePointers 
+};
+
+LF_DECLARE const NSHashTableCallBacks NSNonRetainedObjectHashCallBacks = { 
+    (unsigned(*)(NSHashTable*, const void*))__NSHashObject, 
+    (BOOL(*)(NSHashTable*, const void*, const void*))__NSCompareObjects, 
+    (void(*)(NSHashTable*, const void*))__NSRetainNothing, 
+    (void(*)(NSHashTable*, void*))__NSReleaseNothing, 
+    (NSString*(*)(NSHashTable*, const void*))__NSDescribeObjects 
+};
+LF_DECLARE const NSHashTableCallBacks NSObjectHashCallBacks = { 
+    (unsigned(*)(NSHashTable*, const void*))__NSHashObject, 
+    (BOOL(*)(NSHashTable*, const void*, const void*))__NSCompareObjects, 
+    (void(*)(NSHashTable*, const void*))__NSRetainObjects, 
+    (void(*)(NSHashTable*, void*))__NSReleaseObjects, 
+    (NSString*(*)(NSHashTable*, const void*))__NSDescribeObjects 
+};
+
+LF_DECLARE const NSHashTableCallBacks NSOwnedObjectIdentityHashCallBacks = { 
+    (unsigned(*)(NSHashTable*, const void*))__NSHashPointer, 
+    (BOOL(*)(NSHashTable*, const void*, const void*))__NSComparePointers, 
+    (void(*)(NSHashTable*, const void*))__NSRetainObjects, 
+    (void(*)(NSHashTable*, void*))__NSReleaseObjects, 
+    (NSString*(*)(NSHashTable*, const void*))__NSDescribeObjects 
+};
+
+LF_DECLARE const NSHashTableCallBacks NSOwnedPointerHashCallBacks = { 
+    (unsigned(*)(NSHashTable*, const void*))__NSHashObject, 
+    (BOOL(*)(NSHashTable*, const void*, const void*))__NSCompareObjects, 
+    (void(*)(NSHashTable*, const void*))__NSRetainNothing, 
+    (void(*)(NSHashTable*, void*))__NSReleasePointers, 
+    (NSString*(*)(NSHashTable*, const void*))__NSDescribePointers 
+};
+
+LF_DECLARE const NSHashTableCallBacks NSPointerToStructHashCallBacks = { 
+    (unsigned(*)(NSHashTable*, const void*))__NSHashPointer, 
+    (BOOL(*)(NSHashTable*, const void*, const void*))__NSComparePointers, 
+    (void(*)(NSHashTable*, const void*))__NSRetainNothing, 
+    (void(*)(NSHashTable*, void*))__NSReleasePointers, 
+    (NSString*(*)(NSHashTable*, const void*))__NSDescribePointers 
+};
+
+/*
+* NSMapTable predefined callbacks
+*/
+
+LF_DECLARE const NSMapTableKeyCallBacks NSIntMapKeyCallBacks = {
+    (unsigned(*)(NSMapTable *, const void *))__NSHashInteger,
+    (BOOL(*)(NSMapTable *, const void *, const void *))__NSCompareInts,
+    (void (*)(NSMapTable *, const void *anObject))__NSRetainNothing,
+    (void (*)(NSMapTable *, void *anObject))__NSReleaseNothing,
+    (NSString *(*)(NSMapTable *, const void *))__NSDescribeInts,
+    (const void *)NULL
+};
+
+LF_DECLARE const NSMapTableValueCallBacks NSIntMapValueCallBacks = {
+    (void (*)(NSMapTable *, const void *))__NSRetainNothing,
+    (void (*)(NSMapTable *, void *))__NSReleaseNothing,
+    (NSString *(*)(NSMapTable *, const void *))__NSDescribeInts
+};
+
+LF_DECLARE const NSMapTableKeyCallBacks NSNonOwnedPointerMapKeyCallBacks = {
+    (unsigned(*)(NSMapTable *, const void *))__NSHashPointer,
+    (BOOL(*)(NSMapTable *, const void *, const void *))__NSComparePointers,
+    (void (*)(NSMapTable *, const void *anObject))__NSRetainNothing,
+    (void (*)(NSMapTable *, void *anObject))__NSReleaseNothing,
+    (NSString *(*)(NSMapTable *, const void *))__NSDescribePointers,
+    (const void *)NULL
+}; 
+
+LF_DECLARE const NSMapTableKeyCallBacks NSNonOwnedCStringMapKeyCallBacks = {
+    (unsigned(*)(NSMapTable *, const void *))__NSHashCString,
+    (BOOL(*)(NSMapTable *, const void *, const void *))__NSCompareCString,
+    (void (*)(NSMapTable *, const void *anObject))__NSRetainNothing,
+    (void (*)(NSMapTable *, void *anObject))__NSReleaseNothing,
+    (NSString *(*)(NSMapTable *, const void *))__NSDescribePointers,
+    (const void *)NULL
+}; 
+
+LF_DECLARE const NSMapTableValueCallBacks NSNonOwnedPointerMapValueCallBacks = {
+    (void (*)(NSMapTable *, const void *))__NSRetainNothing,
+    (void (*)(NSMapTable *, void *))__NSReleaseNothing,
+    (NSString *(*)(NSMapTable *, const void *))__NSDescribePointers
+};
+
+LF_DECLARE const NSMapTableKeyCallBacks NSNonOwnedPointerOrNullMapKeyCallBacks = {
+    (unsigned(*)(NSMapTable *, const void *))__NSHashPointer,
+    (BOOL(*)(NSMapTable *, const void *, const void *))__NSComparePointers,
+    (void (*)(NSMapTable *, const void *anObject))__NSRetainNothing,
+    (void (*)(NSMapTable *, void *anObject))__NSReleaseNothing,
+    (NSString *(*)(NSMapTable *, const void *))__NSDescribePointers,
+    (const void *)NSNotAPointerMapKey
+};
+
+LF_DECLARE const NSMapTableKeyCallBacks NSNonRetainedObjectMapKeyCallBacks = {
+    (unsigned(*)(NSMapTable *, const void *))__NSHashObject,
+    (BOOL(*)(NSMapTable *, const void *, const void *))__NSCompareObjects,
+    (void (*)(NSMapTable *, const void *anObject))__NSRetainNothing,
+    (void (*)(NSMapTable *, void *anObject))__NSReleaseNothing,
+    (NSString *(*)(NSMapTable *, const void *))__NSDescribeObjects,
+    (const void *)NULL
+};
+
+LF_DECLARE const NSMapTableValueCallBacks NSNonRetainedObjectMapValueCallBacks = {
+    (void (*)(NSMapTable *, const void *))__NSRetainNothing,
+    (void (*)(NSMapTable *, void *))__NSReleaseNothing,
+    (NSString *(*)(NSMapTable *, const void *))__NSDescribeObjects
+}; 
+
+LF_DECLARE const NSMapTableKeyCallBacks NSObjectMapKeyCallBacks = {
+    (unsigned(*)(NSMapTable *, const void *))__NSHashObject,
+    (BOOL(*)(NSMapTable *, const void *, const void *))__NSCompareObjects,
+    (void (*)(NSMapTable *, const void *anObject))__NSRetainObjects,
+    (void (*)(NSMapTable *, void *anObject))__NSReleaseObjects,
+    (NSString *(*)(NSMapTable *, const void *))__NSDescribeObjects,
+    (const void *)NULL
+}; 
+
+LF_DECLARE const NSMapTableValueCallBacks NSObjectMapValueCallBacks = {
+    (void (*)(NSMapTable *, const void *))__NSRetainObjects,
+    (void (*)(NSMapTable *, void *))__NSReleaseObjects,
+    (NSString *(*)(NSMapTable *, const void *))__NSDescribeObjects
+}; 
+
+LF_DECLARE const NSMapTableKeyCallBacks NSOwnedPointerMapKeyCallBacks = {
+    (unsigned(*)(NSMapTable *, const void *))__NSHashPointer,
+    (BOOL(*)(NSMapTable *, const void *, const void *))__NSComparePointers,
+    (void (*)(NSMapTable *, const void *anObject))__NSRetainNothing,
+    (void (*)(NSMapTable *, void *anObject))__NSReleasePointers,
+    (NSString *(*)(NSMapTable *, const void *))__NSDescribePointers,
+    (const void *)NULL
+};
+
+LF_DECLARE const NSMapTableValueCallBacks NSOwnedPointerMapValueCallBacks = {
+    (void (*)(NSMapTable *, const void *))__NSRetainNothing,
+    (void (*)(NSMapTable *, void *))__NSReleasePointers,
+    (NSString *(*)(NSMapTable *, const void *))__NSDescribePointers
+}; 
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSHashTable.h b/libFoundation/Foundation/NSHashTable.h
new file mode 100644 (file)
index 0000000..9c6a0e2
--- /dev/null
@@ -0,0 +1,118 @@
+/* 
+   NSHashTable.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSHashTable_h__
+#define __NSHashTable_h__
+
+#include <Foundation/NSObject.h>
+
+@class NSArray;
+
+struct _NSHashTable;
+
+typedef struct _NSHashTableCallBacks {
+    unsigned (*hash)(struct _NSHashTable *table, const void *anObject);
+    BOOL (*isEqual)(struct _NSHashTable *table, 
+           const void *anObject1, const void *anObject2);
+    void (*retain)(struct _NSHashTable *table, const void *anObject);
+    void (*release)(struct _NSHashTable *table, void *anObject);
+    NSString  *(*describe)(struct _NSHashTable *table, const void *anObject);
+} NSHashTableCallBacks;
+
+struct _NSHashNode {
+    void               *key;
+    struct _NSHashNode         *next;
+};
+
+typedef struct _NSHashTable {
+    struct _NSHashNode **nodes;
+    unsigned int       hashSize;
+    unsigned int       itemsCount;
+    NSHashTableCallBacks callbacks;
+    NSZone*            zone;
+    BOOL               keysInvisible;
+} NSHashTable;
+
+typedef struct _NSHashEnumerator {
+    struct _NSHashTable        *table;
+    struct _NSHashNode *node;
+    int                        bucket;
+} NSHashEnumerator;
+
+/* Predefined callback sets */
+LF_EXPORT const NSHashTableCallBacks NSIntHashCallBacks;
+LF_EXPORT const NSHashTableCallBacks NSNonOwnedPointerHashCallBacks; 
+LF_EXPORT const NSHashTableCallBacks NSNonRetainedObjectHashCallBacks; 
+LF_EXPORT const NSHashTableCallBacks NSObjectHashCallBacks; 
+LF_EXPORT const NSHashTableCallBacks NSOwnedObjectIdentityHashCallBacks; 
+LF_EXPORT const NSHashTableCallBacks NSOwnedPointerHashCallBacks; 
+LF_EXPORT const NSHashTableCallBacks NSPointerToStructHashCallBacks; 
+
+/* Hash Table Functions */
+
+/* Create a Table */
+NSHashTable *NSCreateHashTable(NSHashTableCallBacks callBacks, 
+       unsigned capacity);
+NSHashTable *NSCreateHashTableWithZone(NSHashTableCallBacks callBacks, 
+       unsigned capacity, NSZone *zone);
+NSHashTable *NSCopyHashTableWithZone(NSHashTable *table, 
+       NSZone *zone);
+
+/* Create a hash table whose keys are not collectable */
+NSHashTable *NSCreateHashTableInvisibleKeys(NSHashTableCallBacks callBacks,
+                                               unsigned capacity);
+
+/* Free a Table */
+void NSFreeHashTable(NSHashTable *table); 
+void NSResetHashTable(NSHashTable *table); 
+
+/* Compare Two Tables */
+BOOL NSCompareHashTables(NSHashTable *table1, NSHashTable *table2);    
+
+/* Get the Number of Items */
+unsigned NSCountHashTable(NSHashTable *table);
+
+/* Retrieve Items */
+void *NSHashGet(NSHashTable *table, const void *pointer);
+NSArray *NSAllHashTableObjects(NSHashTable *table);
+NSHashEnumerator NSEnumerateHashTable(NSHashTable *table);
+void *NSNextHashEnumeratorItem(NSHashEnumerator *enumerator);
+
+/* Add or Remove an Item */
+void NSHashInsert(NSHashTable *table, const void *pointer);
+void NSHashInsertKnownAbsent(NSHashTable *table, const void *pointer);
+void *NSHashInsertIfAbsent(NSHashTable *table, const void *pointer);
+void NSHashRemove(NSHashTable *table, const void *pointer);
+
+/* Get a String Representation */
+NSString *NSStringFromHashTable(NSHashTable *table);
+
+#endif /* __NSHashTable_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSHost.h b/libFoundation/Foundation/NSHost.h
new file mode 100644 (file)
index 0000000..c8cd30e
--- /dev/null
@@ -0,0 +1,63 @@
+/* 
+   NSHost.h
+
+   Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Aleksandr Savostyanov <sav@conextions.com>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSHost_h__
+#define __NSHost_h__
+
+#include <Foundation/NSObject.h>
+
+@class NSString, NSArray, NSMutableArray;
+
+@interface NSHost : NSObject 
+{
+    NSMutableArray *names;
+    NSMutableArray *addresses;
+}
+
++ (NSHost *)currentHost;
++ (NSHost *)hostWithName:(NSString *)name;
++ (NSHost *)hostWithAddress:(NSString *)address;
+
++ (void)setHostCacheEnabled:(BOOL)flag;
++ (BOOL)isHostCacheEnabled;
++ (void)flushHostCache;
+
+- (BOOL)isEqualToHost:(NSHost *)aHost;
+
+- (NSString *)name;
+- (NSArray *)names;
+
+- (NSString *)address;
+- (NSArray *)addresses;
+
+@end
+
+#endif /* __NSHost_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSHost.m b/libFoundation/Foundation/NSHost.m
new file mode 100644 (file)
index 0000000..f29ebb4
--- /dev/null
@@ -0,0 +1,347 @@
+/* 
+   NSHost.m
+
+   Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Aleksandr Savostyanov <sav@conextions.com>
+   Author: Ovidiu Predescu <ovidiu@net-community.com>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <config.h>
+
+#ifdef HAVE_LIBC_H
+# include <libc.h>
+#else
+# include <unistd.h>
+#endif
+
+#if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <string.h>
+
+#if HAVE_WINDOWS_H
+#  include <windows.h>
+#endif
+
+#if defined(__MINGW32__)
+#  include <winsock.h>
+#else
+#  include <netdb.h>
+#  include <sys/socket.h>
+#  include <arpa/inet.h>
+#endif
+
+#include <Foundation/common.h>
+#include <Foundation/NSHost.h>
+#include <Foundation/NSObject.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSLock.h>
+#include <Foundation/NSNotification.h>
+#include <Foundation/NSThread.h>
+
+extern NSRecursiveLock* libFoundationLock;
+
+@interface NSHost(Private)
+- (id)initWithHostEntity:(struct hostent *)hostEntity;
+- (id)initWithName:(NSString*)name;
+- (id)initWithDottedRepresentation:(NSString*)address;
+@end
+
+@implementation NSHost
+
+static BOOL                cacheEnabled = YES;
+static NSMutableDictionary *hostsByName = nil;
+static NSMutableDictionary *hostsByAddress = nil;
+static NSRecursiveLock     *hostsLock = nil;
+
++ (void)initialize
+{
+#ifdef __MINGW32__
+    static WSADATA wsaData;
+    WSAStartup(MAKEWORD(1, 1), &wsaData);
+#endif
+    hostsByName = [NSMutableDictionary new];
+    hostsByAddress = [NSMutableDictionary new];
+    [[NSNotificationCenter defaultCenter]
+       addObserver:self
+       selector:@selector(taskNowMultiThreaded:)
+       name:NSWillBecomeMultiThreadedNotification
+       object:nil];
+}
+
++ (void)taskNowMultiThreaded:(NSNotification*)notification
+{
+    hostsLock = [NSRecursiveLock new];
+}
+
++ (NSHost *)currentHost
+{
+    char buffer[1024];
+    NSString *hostName;
+    gethostname(buffer, 1024);
+    hostName = [NSString stringWithCString:buffer];
+    return [NSHost hostWithName:hostName];
+}
+
++ (NSHost *)hostWithName:(NSString *)name
+{
+    return AUTORELEASE([[NSHost alloc] initWithName:name]);
+}
+
++ (NSHost *)hostWithAddress:(NSString *)address
+{
+    return AUTORELEASE([[NSHost alloc] initWithDottedRepresentation:address]);
+}
+
++ (void)setHostCacheEnabled:(BOOL)flag
+{
+    cacheEnabled = flag;
+}
+
++ (BOOL)isHostCacheEnabled
+{
+    return cacheEnabled;
+}
+
++ (void)flushHostCache
+{
+    [hostsByName    removeAllObjects];
+    [hostsByAddress removeAllObjects];
+}
+
+- (void) dealloc
+{
+    RELEASE(self->names);
+    RELEASE(self->addresses);
+    [super dealloc];
+}
+
+- (BOOL)isEqualToHost:(NSHost *)aHost
+{
+    NSArray *theAddresses;
+    int i, count;
+
+    theAddresses = [aHost addresses];
+    count = [theAddresses count];
+    for (i = 0; i < count; i++) {
+        if ([self->addresses containsObject:[theAddresses objectAtIndex:i]])
+           return YES;
+    }
+
+    return NO;
+}
+
+- (BOOL)isEqual:(id)anotherHost
+{
+    return [self isEqualToHost:anotherHost];
+}
+
+- (NSString *)name
+{
+    if ([self->names count])
+        return [self->names objectAtIndex:0];
+    return nil;
+}
+
+- (NSArray *)names
+{
+    return self->names;
+}
+
+- (NSString *)address
+{
+    if ([self->addresses count])
+        return [self->addresses objectAtIndex:0];
+    return nil;
+}
+
+- (NSArray *)addresses
+{
+    return self->addresses;
+}
+
+/* description */
+
+- (NSString *)description
+{
+    return [NSString stringWithFormat:@"<0x%08X[%@]: names=%@, addresses=%@>",
+                       self, NSStringFromClass([self class]),
+                       [self->names componentsJoinedByString:@","],
+                       [self->addresses componentsJoinedByString:@","]];
+}
+
+@end /* NSHost */
+
+@implementation NSHost(Private)
+
+- (id)initWithName:(NSString*)name
+{
+#if HAVE_GETHOSTBYNAME_R && !defined(linux)
+    struct hostent hostEntity;
+    int            hErrno;
+    // size as described in "UNIX Network Programming" by Richard Stevens
+    char           buffer[8192]; 
+#else
+    struct hostent *hostEntity;
+#endif
+
+    if (cacheEnabled) {
+       NSHost* host;
+
+       [hostsLock lock];
+       host = [hostsByName objectForKey:name];
+       [hostsLock unlock];
+       if (host) {
+            RELEASE(self);
+           return RETAIN(host);
+        }
+    }
+
+#if HAVE_GETHOSTBYNAME_R && !defined(linux)
+    if (gethostbyname_r([name cString], &hostEntity,
+                        buffer, sizeof(buffer), &hErrno) == NULL) {
+        RELEASE(self);
+        return nil;
+    }
+
+    self = [self initWithHostEntity:&hostEntity];
+#else
+    [libFoundationLock lock];
+    hostEntity = gethostbyname((char*)[name cString]);
+    if (!hostEntity) {
+        RELEASE(self);
+        [libFoundationLock unlock];
+        return nil;
+    }
+
+    self = [self initWithHostEntity:hostEntity];
+    [libFoundationLock unlock];
+#endif
+
+    return self;
+}
+
+- (id)initWithDottedRepresentation:(NSString*)address
+{
+#if HAVE_GETHOSTBYADDR_R && !defined(linux)
+    struct hostent hostEntity;
+    int            hErrno;
+    // as described in "UNIX Network Programming" by Richard Stevens
+    char           buffer[8192]; 
+#else
+    struct hostent *hostEntity;
+#endif
+    struct in_addr ipAddress;
+
+    if (cacheEnabled) {
+       NSHost* host;
+
+       [hostsLock lock];
+       host = [hostsByAddress objectForKey:address];
+       [hostsLock unlock];
+       if (host) {
+            RELEASE(self);
+           return RETAIN(host);
+        }
+    }
+
+    ipAddress.s_addr = inet_addr((char*)[address cString]);
+    if (ipAddress.s_addr == (unsigned long)-1) {
+        RELEASE(self);
+        return nil;
+    }
+
+#if HAVE_GETHOSTBYADDR_R && !defined(linux)
+    if (gethostbyaddr_r((char*)&ipAddress, sizeof(ipAddress), AF_INET,
+                        &hostEntity, buffer, sizeof(buffer), &hErrno) == NULL) {
+        RELEASE(self);
+        return nil;
+    }
+    self = [self initWithHostEntity:&hostEntity];
+#else
+    [libFoundationLock lock];
+    hostEntity = gethostbyaddr((char*)&ipAddress, sizeof(ipAddress), AF_INET);
+    if (!hostEntity) {
+        RELEASE(self);
+        [libFoundationLock unlock];
+        return nil;
+    }
+    self = [self initWithHostEntity:hostEntity];
+    [libFoundationLock unlock];
+#endif
+
+    return self;
+}
+
+- (id)initWithHostEntity:(struct hostent *)hostEntity
+{
+    char **ptr;
+    struct in_addr ipAddress;
+
+    self->names = [[NSMutableArray alloc] init];
+    [self->names addObject:[NSString stringWithCString:hostEntity->h_name]];
+
+    ptr = hostEntity->h_aliases;
+    while(*ptr) {
+        [self->names addObject:[NSString stringWithCString:*ptr]];
+        ptr++;
+    }
+
+    self->addresses = [[NSMutableArray alloc] init];
+    ptr = hostEntity->h_addr_list;
+    while(*ptr) {
+        memcpy(&ipAddress, *ptr, hostEntity->h_length);
+        [self->addresses addObject:
+                     [NSString stringWithCString:inet_ntoa(ipAddress)]];
+        ptr++;
+    }
+
+    if (cacheEnabled) {
+       int i, count;
+
+       [hostsLock lock];
+       for (i = 0, count = [self->names count]; i < count; i++) {
+           [hostsByName setObject:self forKey:[self->names objectAtIndex:i]];
+        }
+       for (i = 0, count = [self->addresses count]; i < count; i++) {
+           [hostsByAddress setObject:self
+                            forKey:[self->addresses objectAtIndex:i]];
+        }
+       [hostsLock unlock];
+    }
+
+    return self;
+}
+
+@end /* NSHost(Private) */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSInputStream.m b/libFoundation/Foundation/NSInputStream.m
new file mode 100644 (file)
index 0000000..75580a0
--- /dev/null
@@ -0,0 +1,76 @@
+/* 
+   NSInpuStream.m
+
+   Copyright (C) 2003 SKYRIX Software AG, Helge Hess.
+   All rights reserved.
+   
+   Author: Helge Hess <helge.hess@opengroupware.org>
+   
+   This file is part of libFoundation.
+   
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+   
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSStream.h>
+#include <common.h>
+
+@implementation NSInputStream
+
+/* TODO: this is probably a class cluster? */
+
++ (id)inputStreamWithData:(NSData *)_data 
+{
+    return [[[self alloc] initWithData:_data] autorelease];
+}
++ (id)inputStreamWithFileAtPath:(NSString *)_path
+{
+    return [[[self alloc] initWithFileAtPath:_path] autorelease];
+}
+
+- (id)initWithData:(NSData *)_data
+{
+    [self release];
+    return [self notImplemented:_cmd];
+}
+- (id)initWithFileAtPath:(NSString *)_path
+{
+    [self release];
+    return [self notImplemented:_cmd];
+}
+
+/* operations */
+
+- (int)read:(void *)_buf maxLength:(unsigned int)_len
+{
+    return -1;
+}
+
+- (BOOL)getBuffer:(void **)_buf length:(unsigned int *)_len
+{
+    return NO;
+}
+
+- (BOOL)hasBytesAvailable
+{
+    return NO;
+}
+
+@end /* NSInputStream */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSInvocation.h b/libFoundation/Foundation/NSInvocation.h
new file mode 100644 (file)
index 0000000..3e94264
--- /dev/null
@@ -0,0 +1,155 @@
+/* 
+   NSInvocation.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSInvocation_h__
+#define __NSInvocation_h__
+
+#ifndef GNUSTEP
+#  if !NEXT_RUNTIME
+#    define GNU_RUNTIME 1
+#  endif
+#endif
+
+#include <Foundation/NSMethodSignature.h>
+
+@interface NSInvocation : NSObject
+{
+    SEL               selector;
+    id                target;
+    NSMethodSignature *signature;
+    BOOL              argumentsRetained;
+    BOOL              isValid;
+}
+
+/* Creating Invocations */
+
++ (NSInvocation *)invocationWithMethodSignature:(NSMethodSignature *)sig;
+
+/* Managing Invocation Arguments */
+
+- (BOOL)argumentsRetained;
+- (void)retainArguments;
+- (NSMethodSignature *)methodSignature;
+
+- (void)setArgument:(void *)argumentLocation atIndex:(int)index;
+- (void)getArgument:(void *)argumentLocation atIndex:(int)index;
+
+- (void)setReturnValue:(void *)retLoc;
+- (void)getReturnValue:(void *)retLoc;
+
+- (void)setSelector:(SEL)selector;
+- (SEL)selector;
+
+- (void)setTarget:(id)target;
+- (id)target;
+
+/* Dispatching an Invocation */
+
+- (void)invoke;
+- (void)invokeWithTarget:(id)target;
+
+@end
+
+
+@interface NSInvocation (Extensions)
+- (void)setArgumentFrame:(void*)frame;
+- (retval_t)returnFrame;
+- (void*)returnValue;
+@end /* NSInvocation (Extensions) */
+
+/* typing stuff (added in MacOSX) */
+
+#if GNU_RUNTIME
+#  include <objc/objc-api.h>
+#  ifndef _C_LNG_LNG
+#    define _C_LNG_LNG  'q' /* old versions of gcc do not define this */
+#    define _C_ULNG_LNG 'Q'
+#  endif
+#endif
+
+enum _NSObjCValueType {
+#if GNU_RUNTIME
+    NSObjCNoType       = 0,
+    NSObjCVoidType     = _C_VOID,
+    NSObjCCharType     = _C_CHR,
+    NSObjCShortType    = _C_SHT,
+    NSObjCLongType     = _C_LNG,
+    NSObjCLonglongType = _C_LNG_LNG,
+    NSObjCFloatType    = _C_FLT,
+    NSObjCDoubleType   = _C_DBL,
+    NSObjCSelectorType = _C_SEL,
+    NSObjCObjectType   = _C_ID,
+    NSObjCStructType   = _C_STRUCT_B,
+    NSObjCPointerType  = _C_PTR,
+    NSObjCStringType   = _C_CHARPTR,
+    NSObjCArrayType    = _C_ARY_B,
+    NSObjCUnionType    = _C_UNION_B,
+    NSObjCBitfield     = _C_BFLD
+#elif NEXT_RUNTIME
+    NSObjCNoType       = 0,
+    NSObjCVoidType     = 'v',
+    NSObjCCharType     = 'c',
+    NSObjCShortType    = 's',
+    NSObjCLongType     = 'l',
+    NSObjCLonglongType = 'q',
+    NSObjCFloatType    = 'f',
+    NSObjCDoubleType   = 'd',
+    NSObjCSelectorType = ':',
+    NSObjCObjectType   = '@',
+    NSObjCStructType   = '{',
+    NSObjCPointerType  = '^',
+    NSObjCStringType   = '*',
+    NSObjCArrayType    = '[',
+    NSObjCUnionType    = '(',
+    NSObjCBitfield     = 'b'
+#else
+#   error unsupported ObjC runtime !!!
+#endif
+};
+
+typedef struct {
+    enum _NSObjCValueType type;
+    union {
+        char      charValue;
+        short     shortValue;
+        long      longValue;
+        long long longlongValue;
+        float     floatValue;
+        double    doubleValue;
+        SEL       selectorValue;
+        id        objectValue;
+        void      *pointerValue;
+        void      *structLocation;
+        char      *cStringLocation;
+    } value;
+} NSObjCValue;
+
+#endif /* __NSInvocation_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSInvocation.m b/libFoundation/Foundation/NSInvocation.m
new file mode 100644 (file)
index 0000000..236ced1
--- /dev/null
@@ -0,0 +1,198 @@
+/* 
+   NSInvocation.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSInvocation.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+#include <Foundation/exceptions/NSInvocationExceptions.h>
+#include <extensions/objc-runtime.h>
+
+#if WITH_FFCALL
+#  include "FFCallInvocation.h"
+#else
+#  include "NSFrameInvocation.h"
+#  include "NSObjectInvocation.h"
+#endif
+
+@implementation NSInvocation
+
+- (id)initWithSignature:(NSMethodSignature *)_signature
+{
+    self->signature = RETAIN(_signature);
+    self->isValid   = 1;
+    return self;
+}
+
++ (NSInvocation *)invocationWithMethodSignature:(NSMethodSignature *)sig
+{
+    NSInvocation *invocation;
+#if !WITH_FFCALL
+    const char *retType;
+#endif
+
+    if (sig == nil) {
+      [[[InvalidArgumentException new]
+                setReason:@"passed 'nil' signature to "
+                          @"invocationWithMethodSignature:"] raise];
+    }
+
+#if WITH_FFCALL
+    invocation = [[FFCallInvocation alloc] initWithSignature:sig];
+#else
+    retType = [sig methodReturnType];
+    if (*retType == _C_VOID || *retType == _C_ID || *retType == _C_CLASS) {
+        register int argCount;
+        
+        if ((argCount = [sig numberOfArguments]) > 1) {
+            register const char *types = [sig types];
+            register int i;
+            BOOL allObjects = YES;
+        
+            types = objc_skip_argspec(types); // skip return value
+            NSAssert1(*types == _C_ID || *types == _C_CLASS,
+                      @"invalid self type (%s)", types);
+            types = objc_skip_argspec(types); // skip self
+            NSAssert1(*types == _C_SEL, @"invalid _cmd type (%s)", types);
+            types = objc_skip_argspec(types); // skip _cmd
+            argCount -= 2;
+
+            // check whether all 
+            for (i = 0; (i < argCount) && allObjects; i++) {
+                switch (*types) {
+                    case _C_ID:
+                    case _C_CLASS:
+                        break;
+                        
+                    default:
+                        allObjects = NO;
+                        break;
+                }
+                types = objc_skip_argspec(types);
+            }
+            
+            if (allObjects) {
+                invocation = [[NSObjectInvocation allocForArgumentCount:argCount
+                                                  zone:nil]
+                                                  initWithSignature:sig];
+                return AUTORELEASE(invocation);
+            }
+        }
+    }
+    
+    invocation = [[NSFrameInvocation alloc] initWithSignature:sig];
+#endif
+    return AUTORELEASE(invocation);
+}
+
+- (void)dealloc
+{
+    RELEASE(self->signature);
+    [super dealloc];
+}
+
+// arguments
+
+- (void)setTarget:(id)_target
+{
+    if (self->argumentsRetained)
+       ASSIGN(self->target, _target);
+    else
+        self->target = _target;
+}
+- (id)target
+{
+    return self->target;
+}
+
+- (void)setSelector:(SEL)_selector
+{
+    self->selector = _selector;
+}
+- (SEL)selector
+{
+    return self->selector;
+}
+
+- (void)setArgument:(void *)_value atIndex:(int)_idx
+{
+    [self subclassResponsibility:_cmd];
+}
+- (void)getArgument:(void *)_value atIndex:(int)_idx
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (void)retainArguments
+{
+    [self subclassResponsibility:_cmd];
+}
+- (BOOL)argumentsRetained
+{
+    return self->argumentsRetained ? YES : NO;
+}
+
+- (NSMethodSignature *)methodSignature
+{
+    return self->signature;
+}
+
+// return values
+
+- (void)setReturnValue:(void *)_value
+{
+    [self subclassResponsibility:_cmd];
+}
+- (void)getReturnValue:(void *)_value
+{
+    [self subclassResponsibility:_cmd];
+}
+
+// validation
+
+- (void)invalidate
+{
+    [self subclassResponsibility:_cmd];
+}
+
+// invoking
+
+- (void)invokeWithTarget:(id)_target
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (void)invoke
+{
+    [self invokeWithTarget:self->target];
+}
+
+@end
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSKeyValueCoding.h b/libFoundation/Foundation/NSKeyValueCoding.h
new file mode 100644 (file)
index 0000000..6070dcb
--- /dev/null
@@ -0,0 +1,73 @@
+/* 
+   NSKeyValueCoding.h
+
+   Copyright (C) 2000, MDlink online service center GmbH, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSKeyValueCoding_h__
+#define __NSKeyValueCoding_h__
+
+#include <Foundation/NSObject.h>
+
+@interface NSObject(NSKeyValueCoding)
+
+/* settings */
+
++ (BOOL)accessInstanceVariablesDirectly;
++ (BOOL)useStoredAccessor;
+
+/* KVC */
+
+- (void)takeValue:(id)_value forKey:(NSString *)_key;
+- (id)valueForKey:(NSString *)_key;
+
+/* stored values */
+
+- (void)takeStoredValue:(id)_value forKey:(NSString *)_key;
+- (id)storedValueForKey:(NSString *)_key;
+
+@end
+
+@interface NSObject(KeyPaths)
+
+- (void)takeValue:(id)_value forKeyPath:(NSString *)_keyPath;
+- (id)valueForKeyPath:(NSString *)_keyPath;
+
+@end
+
+@class NSArray, NSDictionary;
+
+@interface NSObject(KeySets)
+
+- (void)takeValuesFromDictionary:(NSDictionary *)_dictionary;
+- (NSDictionary *)valuesForKeys:(NSArray *)_keys;
+
+@end
+
+@interface NSObject(NSKeyValueCodingErrorHandling)
+
+- (void)handleTakeValue:(id)_value forUnboundKey:(NSString *)_key;
+- (id)handleQueryWithUnboundKey:(NSString *)_key;
+- (void)unableToSetNullForKey:(NSString *)_key;
+
+@end
+
+#endif /* __NSKeyValueCoding_h__ */
diff --git a/libFoundation/Foundation/NSLock.h b/libFoundation/Foundation/NSLock.h
new file mode 100644 (file)
index 0000000..8eeb53a
--- /dev/null
@@ -0,0 +1,85 @@
+/* 
+   NSLock.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSLock_h__
+#define __NSLock_h__
+
+#include <Foundation/NSObject.h>
+
+@class NSDate;
+
+/* Protocol for thread/task locks */
+
+@protocol NSLocking
+- (void)lock;
+- (void)unlock;    
+@end
+
+/* Lock that can be locked only once (maximum depth one) */
+
+@interface NSLock : NSObject <NSLocking> 
+{
+    struct objc_mutex* mutex;
+}
+- (BOOL)tryLock;
+- (BOOL)lockBeforeDate:(NSDate *)limit;
+       
+@end
+
+/* Lock that can be locked multiple times by the same process */
+
+@interface NSRecursiveLock : NSObject <NSLocking>
+{
+    struct objc_mutex* mutex;
+}
+- (BOOL)tryLock;
+- (BOOL)lockBeforeDate:(NSDate *)limit;
+@end
+
+/* Condition lock is a lock-ed access to a condition variable */
+
+@interface NSConditionLock : NSObject <NSLocking>
+{
+    struct objc_mutex* mutex;
+    struct objc_condition* condition;
+    volatile int value;
+}
+- (id)initWithCondition:(int)aCondition;
+- (int)condition;
+- (void)lockWhenCondition:(int)aCondition;
+- (BOOL)lockBeforeDate:(NSDate *)limit;
+- (BOOL)lockWhenCondition:(int)aCondition beforeDate:(NSDate *)limit;
+- (BOOL)tryLock;
+- (BOOL)tryLockWhenCondition:(int)aCondition;
+- (void)unlockWithCondition:(int)aCondition;
+@end
+
+#endif /* __NSLock_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSLock.m b/libFoundation/Foundation/NSLock.m
new file mode 100644 (file)
index 0000000..cc50727
--- /dev/null
@@ -0,0 +1,291 @@
+/* 
+   NSLock.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSLock.h>
+
+#include <Foundation/NSException.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+#include <extensions/objc-runtime.h>
+#include <config.h>
+
+NSRecursiveLock* libFoundationLock = nil;
+
+/*
+ * NSLock - lock of depth limited to 1
+ */
+
+@implementation NSLock
+
+- init
+{
+    mutex = objc_mutex_allocate();
+    if (!mutex) {
+       RELEASE(self);
+       return nil;
+    }
+    return self;
+}
+
+- (void)dealloc
+{
+    if (mutex)
+       objc_mutex_deallocate(mutex);
+    [super dealloc];
+}
+
+- (void)lock
+{
+    if (objc_mutex_lock(mutex) > 1) {
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"attempt to lock a simple lock (NSLock) multiple times"] raise];
+    }
+}
+
+- (BOOL)tryLock
+{
+    int depth = objc_mutex_trylock(mutex);
+    
+    if (depth > 1) {
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"attempt to lock a simple lock (NSLock) multiple times"] raise];
+    }
+    
+    return depth == 1 ? YES : NO;
+}
+
+- (BOOL)lockBeforeDate:(NSDate *)limit
+{
+    // TODO: Temporary implementation
+    [self lock];
+    return YES;
+}
+
+- (void)unlock
+{
+    if (objc_mutex_unlock(mutex) < 0) {
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"attempt to unlock a lock not owned by the current thread"] raise];
+    }
+}
+
+@end /* NSLock */
+
+/*
+ * NSLock - lock of unlimited (MAX_INT) depth
+ */
+
+@implementation NSRecursiveLock
+
+- init
+{
+    mutex = objc_mutex_allocate();
+    if (!mutex) {
+       RELEASE(self);
+       return nil;
+    }
+    return self;
+}
+
+- (void)dealloc
+{
+    if (mutex)
+       objc_mutex_deallocate(mutex);
+    [super dealloc];
+}
+
+- (void)lock
+{
+    if (objc_mutex_lock(mutex) < 0)
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"attempt to lock an invalid lock"] raise];
+}
+
+- (BOOL)tryLock
+{
+    return objc_mutex_trylock(mutex) > 0 ? YES : NO;
+}
+
+- (BOOL)lockBeforeDate:(NSDate *)limit
+{
+    // TODO: Temporary implementation
+    [self lock];
+    return YES;
+}
+
+- (void)unlock
+{
+    if (objc_mutex_unlock(mutex) < 0)
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"attempt to unlock a lock not owned by the current thread"] raise];
+}
+
+@end /* NSRecursiveLock:NSObject */
+
+/*
+ * Condition lock
+ */
+
+@implementation NSConditionLock
+
+- init
+{
+    return [self initWithCondition:0];
+}
+
+- initWithCondition:(int)aCondition
+{
+    mutex = objc_mutex_allocate();
+    if (!mutex) {
+       RELEASE(self);
+       return nil;
+    }
+    condition = objc_condition_allocate();
+    if (!condition) {
+       RELEASE(self);
+       return nil;
+    }
+    value = aCondition;
+    return self;
+}
+
+- (void)dealloc
+{
+    if (condition)
+       objc_condition_deallocate(condition);
+    if (mutex)
+       objc_mutex_deallocate(mutex);
+    [super dealloc];
+}
+
+- (int)condition
+{
+    return value;
+}
+
+- (void)lock
+{
+    if (objc_mutex_lock(mutex) < 0)
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"attempt to lock an invalid lock"] raise];
+}
+
+- (void)lockWhenCondition:(int)aCondition
+{
+    int depth;
+    
+    // Try to lock the mutex
+    depth = objc_mutex_lock(mutex);
+
+    // Return on error
+    if (depth == -1)
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"attempt to lock an invalid lock"] raise];
+           
+    // Error if recursive lock and condition is false 
+    if ((depth > 1) && (value != aCondition))
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"attempt to lock a condition lock multiple times"
+           @"with a different condition value"] raise];
+
+    // Wait condition
+    while (value != aCondition)
+           objc_condition_wait(condition, mutex);
+}
+
+- (BOOL)lockBeforeDate:(NSDate *)limit
+{
+    // TODO: Temporary implementation
+    [self lock];
+    return YES;
+}
+
+- (BOOL)lockWhenCondition:(int)aCondition beforeDate:(NSDate *)limit
+{
+    // TODO: Temporary implementation
+    [self lockWhenCondition:aCondition];
+    return YES;
+}
+
+- (BOOL)tryLock
+{
+    return objc_mutex_trylock(mutex) > 0 ? YES : NO;
+}
+
+- (BOOL)tryLockWhenCondition:(int)aCondition
+{
+    if (![self tryLock])
+       return NO;
+    
+    if (value != aCondition) {
+       objc_mutex_unlock(mutex);
+       return NO;
+    }
+    
+    return YES;
+}
+
+- (void)unlock
+{
+    if (objc_mutex_unlock(mutex) < 0)
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"attempt to unlock a lock not owned by the current thread"] raise];
+}
+
+- (void)unlockWithCondition:(int)aCondition
+{
+    int depth;
+    
+    // Try to lock the mutex again
+    depth = objc_mutex_trylock(mutex);
+    
+    // Another thread has the lock so abort
+    if (depth == -1)
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"attempt to lock an invalid lock"] raise];
+    
+    // If the depth is only 1 then we just acquired
+    // the lock above, bogus unlock so abort
+    if (depth == 1)
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"attempt to unlock with condition a lock "
+           @"not owned by the current thread"] raise];
+    
+    value = aCondition;
+    
+    // Wake up threads waiting a condition to happen
+    objc_condition_broadcast(condition);
+    // This is a valid unlock so set the condition and unlock twice
+    objc_mutex_unlock(mutex);
+    objc_mutex_unlock(mutex);
+}
+
+@end /* NSConditionLock:NSObject */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSMapTable.h b/libFoundation/Foundation/NSMapTable.h
new file mode 100644 (file)
index 0000000..ac1e5c3
--- /dev/null
@@ -0,0 +1,150 @@
+/* 
+   NSMapTable.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSMapTable_h__
+#define __NSMapTable_h__
+
+#include <Foundation/NSObject.h>
+
+@class NSArray;
+
+struct _NSMapTable;
+
+struct _NSMapNode {
+    void *key;
+    void *value;
+    struct _NSMapNode *next;
+};
+
+typedef struct _NSMapTableKeyCallBacks {
+    unsigned (*hash)(struct _NSMapTable *table, const void *anObject);
+    BOOL (*isEqual)(struct _NSMapTable *table, const void *anObject1, 
+           const void *anObject2);
+    void (*retain)(struct _NSMapTable *table, const void *anObject);
+    void (*release)(struct _NSMapTable *table, void *anObject);
+    NSString  *(*describe)(struct _NSMapTable *table, const void *anObject);
+    const void *notAKeyMarker;
+} NSMapTableKeyCallBacks;
+
+typedef struct _NSMapTableValueCallBacks {
+    void (*retain)(struct _NSMapTable *table, const void *anObject);
+    void (*release)(struct _NSMapTable *table, void *anObject);
+    NSString  *(*describe)(struct _NSMapTable *table, const void *anObject);
+} NSMapTableValueCallBacks;
+
+typedef struct _NSMapTable {
+    struct _NSMapNode  **nodes;
+    unsigned int       hashSize;
+    unsigned int       itemsCount;
+    NSMapTableKeyCallBacks keyCallbacks;
+    NSMapTableValueCallBacks valueCallbacks;
+    NSZone             *zone;
+    BOOL               keysInvisible;
+    BOOL               valuesInvisible;
+} NSMapTable;
+
+typedef struct NSMapEnumerator {
+    struct _NSMapTable *table;
+    struct _NSMapNode  *node;
+    int                        bucket;
+} NSMapEnumerator;
+
+#define NSNotAnIntMapKey MAXINT
+#define NSNotAPointerMapKey ((long)1)
+
+/* Predefined callback sets */
+LF_EXPORT const NSMapTableKeyCallBacks   NSIntMapKeyCallBacks; 
+LF_EXPORT const NSMapTableValueCallBacks NSIntMapValueCallBacks; 
+LF_EXPORT const NSMapTableKeyCallBacks   NSNonOwnedPointerMapKeyCallBacks; 
+LF_EXPORT const NSMapTableKeyCallBacks   NSNonOwnedCStringMapKeyCallBacks; 
+LF_EXPORT const NSMapTableValueCallBacks NSNonOwnedPointerMapValueCallBacks;
+LF_EXPORT const NSMapTableKeyCallBacks   NSNonOwnedPointerOrNullMapKeyCallBacks; 
+LF_EXPORT const NSMapTableKeyCallBacks   NSNonRetainedObjectMapKeyCallBacks; 
+LF_EXPORT const NSMapTableValueCallBacks NSNonRetainedObjectMapValueCallBacks; 
+LF_EXPORT const NSMapTableKeyCallBacks   NSObjectMapKeyCallBacks; 
+LF_EXPORT const NSMapTableValueCallBacks NSObjectMapValueCallBacks; 
+LF_EXPORT const NSMapTableKeyCallBacks   NSOwnedPointerMapKeyCallBacks; 
+LF_EXPORT const NSMapTableValueCallBacks NSOwnedPointerMapValueCallBacks; 
+
+/* Map Table Functions */
+
+/* Create a Table */
+NSMapTable *NSCreateMapTable(NSMapTableKeyCallBacks keyCallBacks, 
+       NSMapTableValueCallBacks valueCallBacks,
+       unsigned capacity);
+NSMapTable *NSCreateMapTableWithZone(NSMapTableKeyCallBacks keyCallBacks, 
+       NSMapTableValueCallBacks valueCallBacks,
+       unsigned capacity,
+       NSZone *zone);
+
+NSMapTable* NSCreateMapTableInvisibleKeysOrValues (
+   NSMapTableKeyCallBacks keyCallBacks,
+   NSMapTableValueCallBacks valueCallBacks,
+   unsigned capacity,
+   BOOL keysInvisible,
+   BOOL valuesInvisible);
+
+NSMapTable *NSCopyMapTableWithZone(NSMapTable *table, NSZone *zone);
+
+/* Free a Table */
+void NSFreeMapTable(NSMapTable *table);
+void NSResetMapTable(NSMapTable *table);
+
+/* Compare Two Tables */
+BOOL NSCompareMapTables(NSMapTable *table1, NSMapTable *table2);
+
+/* Get the Number of Items */
+unsigned NSCountMapTable(NSMapTable *table);
+
+/* Retrieve Items */
+BOOL NSMapMember(NSMapTable *table, const void *key, 
+       void **originalKey,
+       void **value);
+void *NSMapGet(NSMapTable *table, const void *key);
+NSMapEnumerator NSEnumerateMapTable(NSMapTable *table);
+BOOL NSNextMapEnumeratorPair(NSMapEnumerator *enumerator, 
+       void **key,
+       void **value);
+NSArray *NSAllMapTableKeys(NSMapTable *table);
+NSArray *NSAllMapTableValues(NSMapTable *table);
+
+/* Add or Remove an Item */
+void NSMapInsert(NSMapTable *table, const void *key, const void *value);
+void *NSMapInsertIfAbsent(NSMapTable *table,
+       const void *key,
+       const void *value);
+void NSMapInsertKnownAbsent(NSMapTable *table,
+       const void *key, 
+       const void *value);
+void NSMapRemove(NSMapTable *table, const void *key);
+NSString *NSStringFromMapTable(NSMapTable *table);
+
+#endif /* __NSMapTable_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSMappedData.h b/libFoundation/Foundation/NSMappedData.h
new file mode 100644 (file)
index 0000000..6a16be0
--- /dev/null
@@ -0,0 +1,52 @@
+/* 
+   NSMappedData.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSMappedData_h__
+#define __NSMappedData_h__
+
+#include <Foundation/NSData.h>
+
+/*
+ * Read-only mapped data
+ */
+
+@interface NSMappedData : NSData
+{
+    char*              bytes;
+    unsigned int       length;
+    unsigned int       capacity;
+    id                 file;
+}
+- (id)initWithPosixFileDescriptor:(NSPosixFileDescriptor*)descriptor
+  range:(NSRange)range;
+@end
+
+#endif /* __NSMappedData_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSMappedData.m b/libFoundation/Foundation/NSMappedData.m
new file mode 100644 (file)
index 0000000..f8d44ed
--- /dev/null
@@ -0,0 +1,141 @@
+/* 
+   NSMappedData.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSPosixFileDescriptor.h>
+#include <Foundation/NSException.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+
+#ifdef NeXT /* NeXT Mach map_fd() */
+# include <mach/mach.h>
+# include <libc.h>
+#elif defined(HAVE_MMAP) /* Posix mmap() */
+#  include <sys/types.h>
+#  include <sys/mman.h>
+#  include <unistd.h>
+#else  /* No file mapping available */
+#endif
+
+#include "NSMappedData.h"
+
+/*
+ * Read-only mapped data
+ */
+
+@implementation NSMappedData
+
+- (id)initWithPosixFileDescriptor:(NSPosixFileDescriptor*)descriptor
+  range:(NSRange)range
+{
+    file = RETAIN(descriptor);
+
+    if (range.location + range.length > [file fileLength])
+       [[[RangeException alloc]
+               initWithReason:@"invalid range to be mapped" 
+               size:[file fileLength] 
+               index:range.location+range.length] raise];
+
+    length = capacity = range.length;
+    [file seekToPosition:range.location];
+
+    if (!length)
+       return self;
+
+#ifdef NeXT    
+    /* NeXt Mach map_fd() */
+    {
+       kern_return_t r;
+
+       r = map_fd([file fileDescriptor], (vm_offset_t)0, 
+           (vm_offset_t*)(&bytes), TRUE, (vm_size_t)length);
+       if (r != KERN_SUCCESS) {
+           bytes = NULL;
+           AUTORELEASE(self);
+           return nil;
+       }
+       return self;
+    }
+#elif defined(HAVE_MMAP)
+    /* Posix mmap() */
+    {
+       bytes = mmap(0, length, PROT_READ, MAP_SHARED,
+                    [file fileDescriptor], 0);
+       if ((int)bytes == -1) {
+           bytes = NULL;
+           (void)AUTORELEASE(self);
+           return nil;
+       }
+       return self;
+    }
+#else  
+    /* No file mapping available */
+    {
+       bytes = MallocAtomic (length);
+       [file readBytes:bytes range:range];
+       return self;
+    }
+#endif
+}
+
+- (void)dealloc
+{
+#ifdef NeXT    
+    /* NeXt Mach map_fd() */
+    if (bytes && length)
+       vm_deallocate(task_self(), (vm_address_t)bytes, length);
+#elif defined(HAVE_MMAP)
+    /* Posix mmap() */
+    if (bytes && length)
+       munmap(bytes, length);
+#else  
+    /* No file mapping available */
+    lfFree(bytes);
+#endif
+    RELEASE(file);
+    [super dealloc];
+}
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    return RETAIN(self);
+}
+
+- (const void*)bytes
+{
+    return bytes;
+}
+
+- (unsigned int)length
+{
+    return length;
+}
+
+@end /* NSMappedData */
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSMessagePort.m b/libFoundation/Foundation/NSMessagePort.m
new file mode 100644 (file)
index 0000000..0fd9d4f
--- /dev/null
@@ -0,0 +1,28 @@
+/* 
+   NSMessagePort.h
+
+   Copyright (C) 2000 Helge Hess.
+   All rights reserved.
+
+   Author: Helge Hess <hh@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSPort.h>
+
+@implementation NSMessagePort
+@end /* NSMessagePort */
diff --git a/libFoundation/Foundation/NSMethodSignature.h b/libFoundation/Foundation/NSMethodSignature.h
new file mode 100644 (file)
index 0000000..c485c5f
--- /dev/null
@@ -0,0 +1,75 @@
+/* 
+   NSMethodSignature.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSMethodSignature_h__
+#define __NSMethodSignature_h__
+
+#include <Foundation/NSObject.h>
+
+typedef struct {
+    int        offset;
+    int        size;
+    const char* type;
+} NSArgumentInfo;
+
+@interface NSMethodSignature : NSObject
+{
+    char *types;
+    int  numberOfArguments;
+}
+
++ (NSMethodSignature*)signatureWithObjCTypes:(const char*)types;
+
+- (NSArgumentInfo)argumentInfoAtIndex:(unsigned)index;
+- (const char *)getArgumentTypeAtIndex:(unsigned int)_index; // new in Rhapsody
+
+- (unsigned)frameLength;
+- (BOOL)isOneway;
+- (unsigned)methodReturnLength;
+- (const char*)methodReturnType;
+- (unsigned)numberOfArguments;
+@end
+
+@interface NSMethodSignature (Extensions)
+- (const char *)types;
+- (unsigned)sizeOfStackArguments;
+- (unsigned)sizeOfRegisterArguments;
+- (unsigned)typeSpecifiersOfArgumentAt:(int)index;
+- (BOOL)isInArgumentAt:(int)index;
+- (BOOL)isOutArgumentAt:(int)index;
+- (BOOL)isBycopyArgumentAt:(int)index;
+@end
+
+@interface NSMethodSignature(GNUstepCompatibility)
+- (const char *)methodType;
+@end
+
+#endif /* __NSMethodSignature_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSMethodSignature.m b/libFoundation/Foundation/NSMethodSignature.m
new file mode 100644 (file)
index 0000000..cb3b573
--- /dev/null
@@ -0,0 +1,296 @@
+/* 
+   NSMethodSignature.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <config.h>
+#include <Foundation/common.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSLock.h>
+#include <Foundation/NSMethodSignature.h>
+#include <Foundation/NSMapTable.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+
+#include <extensions/objc-runtime.h>
+
+#define WITH_METHOD_SIGNATURE_CACHE 1
+
+/*
+ * Return the type of the nth argument. The target and selector are not
+ * counted as arguments.
+ */
+static const char*
+get_nth_argument_type_with_qualifiers(char* types, int index)
+{
+    const char* seltype = types;
+
+    // skip return type
+    seltype = objc_skip_argspec(seltype);
+
+    while(index--)
+        seltype = objc_skip_argspec(seltype);
+
+    return seltype;
+}
+
+static const char*
+get_nth_argument_type(char* types, int index)
+{
+    return objc_skip_type_qualifiers(
+                get_nth_argument_type_with_qualifiers(types, index));
+}
+
+static NSString*
+isolate_type(const char* types)
+{
+    const char* p = objc_skip_typespec(types);
+    return [NSString stringWithCString:types length:(unsigned)(p - types)];
+}
+
+@implementation NSMethodSignature
+
+#if WITH_METHOD_SIGNATURE_CACHE
+static NSMapTable *methodSignatureCache = NULL;
+#endif
+
++ (void)initialize {
+#if WITH_METHOD_SIGNATURE_CACHE
+    if (methodSignatureCache == NULL) {
+        methodSignatureCache =
+            NSCreateMapTable(NSNonOwnedCStringMapKeyCallBacks,
+                             NSObjectMapValueCallBacks,
+                             64);
+    }
+#endif
+}
+
++ (NSMethodSignature*)signatureWithObjCTypes:(const char*)_types
+{
+    extern NSLock       *libFoundationLock;
+    NSMethodSignature   *signature;
+    const unsigned char *p;
+
+    if(_types == NULL) {
+       [[[InvalidArgumentException new]
+               setReason:@"Null types passed to signatureWithObjCTypes:"] raise];
+       return nil;
+    }
+
+#if WITH_METHOD_SIGNATURE_CACHE
+    [libFoundationLock lock];
+    signature = NSMapGet(methodSignatureCache, _types);
+    signature = RETAIN(signature);
+    [libFoundationLock unlock];
+    if (signature) 
+        return AUTORELEASE(signature);
+#endif
+
+    signature = AUTORELEASE([NSMethodSignature alloc]);
+    NSAssert(signature, @"couldn't allocate method signature");
+
+    /* Determine if _types also contains the position info. If not, determine
+       a new one. This encoding is used later instead of original one. */
+    p = objc_skip_typespec(_types);
+    if(!isdigit(*p)) {
+       CUMULATIVE_ARGS cumulative_args;
+       int stack_argsize = 0;
+       id encoding = AUTORELEASE([NSMutableString new]);
+       const char* retval = _types;
+
+       /* Skip returned value. */
+       _types = objc_skip_typespec(_types);
+
+       signature->numberOfArguments = 0;
+
+       INIT_CUMULATIVE_ARGS(cumulative_args);
+       while(*_types) {
+           [encoding appendString:
+                   FUNCTION_ARG_ENCODING(cumulative_args,
+                                       isolate_type(_types),
+                                       stack_argsize)];
+           _types = objc_skip_typespec(_types);
+           signature->numberOfArguments++;
+       }
+       encoding = [NSString stringWithFormat:@"%@%d%@",
+                               isolate_type(retval), stack_argsize, encoding];
+       signature->types = Strdup([encoding cString]);
+    }
+    else {
+       signature->types = Strdup(_types);
+
+       /* Compute no of arguments. The first type is the return type. */
+       for(signature->numberOfArguments = -1;
+                   *_types; signature->numberOfArguments++)
+           _types = objc_skip_argspec(_types);
+    }
+
+#if WITH_METHOD_SIGNATURE_CACHE
+    [libFoundationLock lock];
+    NSMapInsert(methodSignatureCache, _types, signature);
+    [libFoundationLock unlock];
+#endif
+    
+    return signature;
+}
+
+- (void)dealloc
+{
+    lfFree(self->types);
+    [super dealloc];
+}
+
+- (unsigned)hash
+{
+    return hashjb(self->types, Strlen(self->types));
+}
+
+- (BOOL)isEqual:(id)anotherSignature
+{
+    if (self == anotherSignature) return YES;
+    if (![anotherSignature isKindOfClass:self->isa]) return NO;
+    if (Strcmp(self->types, [anotherSignature types]) != 0) return NO;
+    return YES;
+}
+
+- (NSArgumentInfo)argumentInfoAtIndex:(unsigned)index
+{
+    NSArgumentInfo argInfo;
+    argInfo.type   = get_nth_argument_type(self->types, index);
+    argInfo.size   = objc_sizeof_type(argInfo.type);
+    argInfo.offset = Atoi(objc_skip_typespec(argInfo.type));
+    return argInfo;
+}
+
+- (const char *)getArgumentTypeAtIndex:(unsigned int)_index
+{
+    return get_nth_argument_type(self->types, _index);
+}
+
+- (unsigned)frameLength
+{
+    return [self sizeOfStackArguments];
+}
+
+- (BOOL)isOneway
+{
+    return objc_get_type_qualifiers(types) & _F_ONEWAY;
+}
+
+- (unsigned)methodReturnLength
+{
+    const char* ptypes = objc_skip_type_qualifiers(self->types);
+    int size = 0;
+
+    if (*ptypes != _C_VOID)
+       size = objc_sizeof_type (ptypes);
+    return size;
+}
+
+- (const char*)methodReturnType
+{
+    return objc_skip_type_qualifiers(self->types);
+}
+
+- (unsigned)numberOfArguments
+{
+    return self->numberOfArguments;
+}
+
+/* description */
+
+- (NSString *)description
+{
+    /* Don't use -[NSString stringWithFormat:] method because it can cause
+       infinite recursion. */
+    char buffer[512];
+
+    sprintf (buffer, "<%s %p types=%s>",
+             (char*)object_get_class_name(self), self, self->types);
+    return [NSString stringWithCString:buffer];
+}
+
+@end /* NSMethodSignature */
+
+
+@implementation NSMethodSignature (Extensions)
+
+- (const char *)types
+{
+    return self->types;
+}
+- (const char *)methodType
+{
+    /* for GNUstep compatibility */
+    return self->types;
+}
+
+- (unsigned)sizeOfStackArguments
+{
+    const char* ptype = objc_skip_typespec(self->types);
+    return Atoi(ptype);
+}
+
+- (unsigned)sizeOfRegisterArguments
+{
+    const char* type = strrchr(self->types, '+');
+    int size = 0;
+    if (type) size = objc_sizeof_type(type - 1) + atoi(type + 1);
+    return size;
+}
+
+- (unsigned)typeSpecifiersOfArgumentAt:(int)index
+{
+    if(index >= numberOfArguments) {
+        [[[IndexOutOfRangeException alloc]
+               initForSize:numberOfArguments index:index] raise];
+        return 0;
+    }
+
+    return objc_get_type_qualifiers(
+            get_nth_argument_type_with_qualifiers(self->types, index));
+}
+
+- (BOOL)isInArgumentAt:(int)index
+{
+    unsigned flags = [self typeSpecifiersOfArgumentAt:index];
+    return !flags || (flags & _F_IN);
+}
+
+- (BOOL)isOutArgumentAt:(int)index
+{
+    return [self typeSpecifiersOfArgumentAt:index] & _F_OUT;
+}
+
+- (BOOL)isBycopyArgumentAt:(int)index
+{
+    return [self typeSpecifiersOfArgumentAt:index] & _F_BYCOPY;
+}
+
+@end /* NSMethodSignature (Extensions) */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSNotification.h b/libFoundation/Foundation/NSNotification.h
new file mode 100644 (file)
index 0000000..988f175
--- /dev/null
@@ -0,0 +1,95 @@
+/* 
+   NSNotification.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSNotification_h__
+#define __NSNotification_h__
+
+#include <Foundation/NSObject.h>
+#include <Foundation/NSUtilities.h>
+#include <Foundation/NSMapTable.h>
+
+@class NSMutableDictionary;
+@class NSDictionary;
+@class NSMutableArray;
+@class NSArray;
+
+/*
+ * NSNotification      
+ */
+
+@interface NSNotification : NSObject <NSCoding>
+
++ (NSNotification*)notificationWithName:(NSString *)name object:object;
++ (NSNotification*)notificationWithName:(NSString *)aName
+  object:(id)anObject userInfo:(NSDictionary *)userInfo;
+
+- (id)initWithName:(NSString *)aName object:(id)anObject 
+  userInfo:(NSDictionary *)anUserInfo;
+
+- (NSString *)notificationName;    
+- (NSString *)name;    
+- (id)notificationObject;
+- (id)object;
+- (NSDictionary *)userInfo;
+
+@end
+
+/*
+ * NSNotificationCenter        
+ */
+
+struct _NSNotificationRegistrationList;
+
+@interface NSNotificationCenter : NSObject 
+{
+    NSMapTable *nameToObjects;
+    id         nullNameToObjects;
+}
+
++ (NSNotificationCenter *)defaultCenter;
+
+// Posting Notifications
+- (void)postNotification:(NSNotification *)notification;
+- (void)postNotificationName:(NSString *)notificationName object:(id)object;
+- (void)postNotificationName:(NSString *)notificationName object:(id)object
+  userInfo:(NSDictionary *)userInfo;
+
+// Adding and Removing Observers
+
+- (void)addObserver:(id)observer selector:(SEL)selector 
+  name:(NSString *)name object:object;
+- (void)removeObserver:(id)observer 
+  name:(NSString *)name object:(id)object;
+- (void)removeObserver:(id)observer;
+
+@end
+
+#endif /* __NSNotification_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSNotification.m b/libFoundation/Foundation/NSNotification.m
new file mode 100644 (file)
index 0000000..532934f
--- /dev/null
@@ -0,0 +1,222 @@
+/* 
+   NSNotification.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSNotification.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSCoder.h>
+
+/*
+ * Concrete notification
+ */
+
+@interface NSConcreteNotification : NSNotification
+{
+    NSString* name;
+    id object;
+    NSDictionary* userInfo;
+}
+- (id)initWithName:(NSString*)aName object:(id)anObject 
+  userInfo:(NSDictionary*)anUserInfo;
+- (NSString *)notificationName;    
+- notificationObject;
+- (NSDictionary *)userInfo;
+@end
+
+@implementation NSConcreteNotification
+
+- (id)initWithName:(NSString*)aName object:(id)anObject 
+  userInfo:(NSDictionary*)anUserInfo
+{
+    NSZone* zone = [self zone];
+    
+    name = [aName copyWithZone:zone];
+    userInfo = [anUserInfo copyWithZone:zone];
+    object = RETAIN(anObject);
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(name);
+    RELEASE(userInfo);
+    RELEASE(object);
+    [super dealloc];
+}
+
+- (NSString *)notificationName
+{
+    return name;
+}
+
+- (NSString *)name { return name; }
+
+- notificationObject
+{
+    return object;
+}
+
+- object { return object; }
+
+- (NSDictionary *)userInfo
+{
+    return userInfo;
+}
+
+// NSCopying
+
+- copyWithZone:(NSZone*)zone
+{
+    if (NSShouldRetainWithZone(self, zone))
+       return RETAIN(self);
+    else
+       return [[[self class] alloc]
+           initWithName:name object:object userInfo:userInfo];
+}
+
+@end
+
+/*
+ * NSNotification
+ */
+
+@implementation NSNotification
+
+/* Methods */
+
++ allocWithZone:(NSZone *)zone
+{
+    return NSAllocateObject( (self == [NSNotification class]) ? 
+           [NSConcreteNotification class] : self, 0, zone);
+}
+
++ (NSNotification *)notificationWithName:(NSString *)name object:object
+{
+    return AUTORELEASE([[self alloc] 
+                           initWithName:(NSString*)name 
+                           object:object 
+                           userInfo:nil]);
+}
+
++ (NSNotification *)notificationWithName:(NSString *)aName
+  object:(id)anObject userInfo:(NSDictionary *)anUserInfo
+{
+    return AUTORELEASE([[self alloc] 
+                           initWithName:(NSString*)aName 
+                           object:anObject 
+                           userInfo:anUserInfo]);
+}
+
+- (id)initWithName:(NSString*)_name object:(id)_object 
+  userInfo:(NSDictionary*)anUserInfo
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+- (NSString *)notificationName
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+- (NSString *)name
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+- notificationObject;
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+- object;
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+- (NSDictionary *)userInfo
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+/* NSCopying protocol */
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+/* NSCodinging protocol */
+
+- (Class)classForCoder
+{
+    return [NSNotification class];
+}
+
+- (void)encodeWithCoder:(NSCoder*)coder
+{
+    id name = [self notificationName];
+    id object = [self notificationObject];
+    id info = [self userInfo];
+
+    [coder encodeObject:name];
+    [coder encodeObject:object];
+    [coder encodeObject:info];
+}
+
+- initWithCoder:(NSCoder*)coder
+{
+    id name, object, info;
+
+    name = [coder decodeObject];
+    object = [coder decodeObject];
+    info = [coder decodeObject];
+    [self initWithName:name object:object userInfo:info];
+    return self;
+}
+
+- (NSString*)description
+{
+    return [NSString stringWithFormat:@"<NSNotification:\n  name = %@\n"
+                                     @"  object = %@\n  userInfo = %@\n>",
+                                     [self notificationName],
+                                     [self notificationObject],
+                                     [self userInfo]];
+}
+
+@end /* NSNotification */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSNotificationCenter.m b/libFoundation/Foundation/NSNotificationCenter.m
new file mode 100644 (file)
index 0000000..9f985bf
--- /dev/null
@@ -0,0 +1,615 @@
+/* 
+   NSNotificationCenter.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSNotification.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSUtilities.h>
+#include <Foundation/NSThread.h>
+
+#include <extensions/objc-runtime.h>
+#include <extensions/NSException.h>
+#include <extensions/NSException.h>
+#include <extensions/GarbageCollector.h>
+#include <extensions/exceptions/GeneralExceptions.h>
+
+#include "PrivateThreadData.h"
+
+#define DEFAULT_CAPACITY 32
+
+#define FREE_UNUSED_OBSERVED_OBJECTS 1
+/*
+ * Objects/selectors pair used in sets
+ */
+
+@interface NSNotificationListItem : NSObject
+{
+@public
+    /* weak */ id  observer;   // observer that will receive selector
+    SEL selector;              // is a postNotification:
+    NSNotificationListItem* next; // this is needed for keeping a
+                                  // linked list of items to be removed
+}
+- (id)initWithObject:(id)anObserver selector:(SEL)aSelector;
+- (BOOL)isEqual:(id)_other;
+- (unsigned)hash;
+- (void)postNotification:(NSNotification*)notification;
+@end
+
+@implementation NSNotificationListItem
+
+#if LIB_FOUNDATION_BOEHM_GC
+
++ (void)initialize
+{
+  class_ivar_set_gcinvisible (self, "observer", YES);
+}
+
++ (BOOL)requiresTypedMemory
+{
+    return YES;
+}
+
+#endif
+
+- (id)initWithObject:(id)anObserver selector:(SEL)aSelector
+{
+    self->observer = anObserver;
+    self->selector = aSelector;
+    return self;
+}
+
+- (BOOL)isEqual:(id)other
+{
+    if ([other isKindOfClass:[NSNotificationListItem class]]) {
+       NSNotificationListItem *obj;
+        obj = other;
+       return (observer == obj->observer) && SEL_EQ(selector, obj->selector);
+    }
+    
+    return NO;
+}
+
+- (unsigned)hash
+{
+    return ((long)observer >> 4) + 
+          __NSHashCString(NULL, sel_get_name(selector));
+}
+
+- (void)postNotification:(NSNotification*)notification
+{
+    [self->observer performSelector:self->selector withObject:notification];
+}
+
+- (NSString *)description
+{
+    return [NSString stringWithFormat:@"<%@ 0x%08X: observer=%@ sel=%@>",
+                       NSStringFromClass([self class]), self,
+                       self->observer, NSStringFromSelector(self->selector)
+                     ];
+}
+
+@end /* NSNotificationListItem */
+
+/*
+ * Register for objects to observer mapping
+ */
+
+@interface NSNotificationObserverRegister : NSObject
+{
+    NSHashTable *observerItems;
+@public
+    void (*addObserver)(id,SEL,id,SEL);
+    void (*remObserver)(id,SEL,id);
+}
+- (id)init;
+- (unsigned int)count;
+- (void)addObjectsToList:(NSMutableArray*)list;
+- (void)addObserver:(id)observer selector:(SEL)selector;
+- (void)removeObserver:(id)observer;
+@end
+
+@implementation NSNotificationObserverRegister
+
+- (id)init
+{
+    self->observerItems =
+        NSCreateHashTable(NSObjectHashCallBacks, DEFAULT_CAPACITY);
+    self->addObserver = (void *)
+        [self methodForSelector:@selector(addObserver:selector:)];
+    self->remObserver = (void *)
+        [self methodForSelector:@selector(removeObserver:)];
+    return self;
+}
+
+- (void)dealloc
+{
+    NSFreeHashTable(self->observerItems);
+    [super dealloc];
+}
+
+- (unsigned int)count
+{
+    return NSCountHashTable(self->observerItems);
+}
+
+- (void)addObjectsToList:(NSMutableArray *)list
+{
+    id reg;
+    void (*addObj)(id, SEL, id);
+    NSHashEnumerator itemsEnum = NSEnumerateHashTable(self->observerItems);
+
+    if (list == nil) return;
+    addObj = (void *)[list methodForSelector:@selector(addObject:)];
+    
+    while((reg = (id)NSNextHashEnumeratorItem(&itemsEnum)))
+        addObj(list, @selector(addObject:), reg);
+}
+
+- (void)addObserver:(id)observer selector:(SEL)selector
+{
+    NSNotificationListItem *reg;
+    
+    reg = [[NSNotificationListItem alloc]
+                                   initWithObject:observer selector:selector];
+    NSHashInsertIfAbsent(self->observerItems, reg);
+    RELEASE(reg);
+}
+
+- (void)removeObserver:(id)observer
+{
+    NSNotificationListItem *listItem = nil;
+    NSNotificationListItem *reg;
+    NSHashEnumerator       itemsEnum;
+    
+    itemsEnum = NSEnumerateHashTable(self->observerItems);
+    
+    while ((reg = (id)NSNextHashEnumeratorItem(&itemsEnum))) {
+      if (reg->observer == observer) {
+       /* Add 'reg' to the linked list of ListItems. We use this schema here
+          to avoid allocating anything, this can trigger finalization calls
+          in the case of Boehm's GC. */
+       reg->next = listItem;
+       listItem = reg;
+      }
+    }
+    while (listItem) {
+       NSHashRemove(self->observerItems, listItem);
+       listItem = listItem->next;
+    }
+}
+
+@end /* NSNotificationObserverRegister */
+
+/*
+ * Register for objects to observer mapping
+ */
+
+@interface NSNotificationObjectRegister : NSObject
+{
+    /* key is the object, value is an NSNotificationObserverRegister */
+    NSMapTable                     *objectObservers;
+    NSNotificationObserverRegister *nilObjectObservers;
+}
+
+- (id)init;
+- (NSArray *)listToNotifyForObject:(id)object;
+- (void)addObserver:(id)observer selector:(SEL)selector object:(id)object;
+- (void)removeObserver:(id)observer object:(id)object;
+- (void)removeObserver:(id)observer;
+
+#if LIB_FOUNDATION_BOEHM_GC
+- (void)removeObject:(id)object;
+#endif
+
+@end
+
+@implementation NSNotificationObjectRegister
+
+- (id)init
+{
+#if LIB_FOUNDATION_BOEHM_GC
+    self->objectObservers = NSCreateMapTableInvisibleKeysOrValues
+       (NSNonRetainedObjectMapKeyCallBacks,
+        NSNonRetainedObjectMapValueCallBacks,
+        DEFAULT_CAPACITY,
+        YES, NO);
+#else
+    self->objectObservers =
+        NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks,
+                         NSObjectMapValueCallBacks,
+                         DEFAULT_CAPACITY);
+#endif
+    self->nilObjectObservers =
+        [[NSNotificationObserverRegister allocWithZone:[self zone]] init];
+    return self;
+}
+
+- (void)dealloc
+{
+    NSFreeMapTable(self->objectObservers);
+    RELEASE(self->nilObjectObservers);
+    [super dealloc];
+}
+
+- (NSArray *)listToNotifyForObject:(id)object
+{
+    NSNotificationObserverRegister *reg = nil;
+    int count;
+    id  list;
+    
+    if (object)
+       reg = (id)NSMapGet(self->objectObservers, object);
+    
+    count = [reg count] + [nilObjectObservers count];
+    list  = [[NSMutableArray alloc] initWithCapacity:count];
+    
+    [reg addObjectsToList:list];
+    [nilObjectObservers addObjectsToList:list];
+    
+    return AUTORELEASE(list);
+}
+
+- (void)addObserver:(id)observer selector:(SEL)selector object:(id)object
+{
+    NSNotificationObserverRegister *reg;
+    
+    if (object) {
+       reg = (id)NSMapGet(self->objectObservers, object);
+       if (reg == nil) {
+           reg = [[NSNotificationObserverRegister alloc] init];
+           NSMapInsert(objectObservers, object, reg);
+            RELEASE(reg);
+       }
+    }
+    else
+       reg = nilObjectObservers;
+
+    reg->addObserver(reg, @selector(addObserver:selector:),
+                     observer, selector);
+}
+
+- (void)removeObserver:(id)observer object:(id)object
+{
+    NSNotificationObserverRegister *reg;
+    
+    reg = (object)
+        ? NSMapGet(self->objectObservers, object)
+        : nilObjectObservers;
+    
+    if (reg) reg->remObserver(reg, @selector(removeObserver:), observer);
+
+#if FREE_UNUSED_OBSERVED_OBJECTS    
+    if (![reg count]) {
+        NSMapRemove(self->objectObservers, object);
+    }
+#endif
+}
+
+- (void)removeObserver:(id)observer
+{
+    id obj;
+    NSNotificationObserverRegister *reg;
+    NSMapEnumerator regEnum;
+#if FREE_UNUSED_OBSERVED_OBJECTS    
+    id  *obj2Rm;
+    int obj2RmCnt;
+    id  z;
+
+    z         = [self zone];
+    obj2Rm    = NSZoneCalloc(z, NSCountMapTable(self->objectObservers) + 1,
+                          sizeof(id));
+    obj2RmCnt = 0;
+#endif
+    
+    regEnum   = NSEnumerateMapTable(self->objectObservers);
+
+    while (NSNextMapEnumeratorPair(&regEnum, (void*)&obj, (void*)&reg)) {
+       reg->remObserver(reg, @selector(removeObserver:),observer);
+#if FREE_UNUSED_OBSERVED_OBJECTS
+        if (![reg count]) {
+            obj2Rm[obj2RmCnt++] = obj;
+        }
+#endif        
+    }
+#if FREE_UNUSED_OBSERVED_OBJECTS
+    while (obj2RmCnt) {
+        NSMapRemove(self->objectObservers, obj2Rm[--obj2RmCnt]);
+    }
+    NSZoneFree(z, obj2Rm); obj2Rm = NULL;
+#endif
+    
+    nilObjectObservers->remObserver(nilObjectObservers,
+                                    @selector(removeObserver:), observer);
+}
+
+#if LIB_FOUNDATION_BOEHM_GC
+- (void)removeObject:(id)object
+{
+    NSMapRemove (self->objectObservers, object);
+}
+#endif
+
+@end /* NSNotificationObjectRegister */
+
+/*
+ * NSNotificationCenter        
+ */
+
+static NSNotificationCenter *defaultCenter = nil;
+static BOOL isMultiThreaded = NO;
+
+@implementation NSNotificationCenter 
+
+/* Class methods */
+
++ (void)initialize
+{
+    static BOOL initialized = NO;
+
+    if (!initialized) {
+       initialized = YES;
+       defaultCenter = [self alloc];
+       [defaultCenter init];
+    }
+}
+
++ (NSNotificationCenter*)defaultCenter
+{
+    if (isMultiThreaded)
+       return [[[NSThread currentThread] _privateThreadData]
+                   defaultNotificationCenter];
+    else
+       return defaultCenter;
+}
+
++ (void)taskNowMultiThreaded:notification
+{
+    PrivateThreadData* threadData = [[NSThread currentThread]
+                                               _privateThreadData];
+
+    [threadData setDefaultNotificationCenter:defaultCenter];
+    defaultCenter = nil;
+    isMultiThreaded = YES;
+}
+
+/* Init/dealloc */
+
+- (id)init
+{
+#if LIB_FOUNDATION_BOEHM_GC
+    nameToObjects = NSCreateMapTable  (NSNonRetainedObjectMapKeyCallBacks,
+                                       NSNonOwnedPointerMapValueCallBacks,
+                                       119);
+#else
+    nameToObjects = NSCreateMapTable (NSObjectMapKeyCallBacks,
+                                     NSObjectMapValueCallBacks,
+                                     119);
+#endif
+    nullNameToObjects = [NSNotificationObjectRegister new];
+    return self;
+}
+
+- (void)dealloc
+{
+    NSFreeMapTable (nameToObjects);
+    RELEASE(nullNameToObjects);
+    [super dealloc];
+}
+
+/* Register && post notifications */
+    
+- (void)postNotification:(NSNotification *)notification
+{
+    NSArray *fromName;
+    NSArray *fromNull;
+    NSNotificationObjectRegister* reg;
+    id name, object;
+
+#if LIB_FOUNDATION_BOEHM_GC
+    [GarbageCollector denyGarbageCollection];
+#endif
+    
+    name   = [notification notificationName];
+    object = [notification notificationObject];
+
+    if (name == nil) {
+       [[[InvalidArgumentException alloc]
+           initWithFormat:@"`nil' notification name in postNotification:"] 
+            raise];
+    }
+    
+    // get objects to notify with registered notification name
+    reg      = NSMapGet (nameToObjects, name);
+    fromName = [reg listToNotifyForObject:object];
+    
+    // get objects to notify with no notification name
+    fromNull = [nullNameToObjects listToNotifyForObject:object];
+
+    // send notifications
+    [fromName makeObjectsPerform:@selector(postNotification:)
+       withObject:notification];
+    [fromNull makeObjectsPerform:@selector(postNotification:)
+       withObject:notification];
+    
+#if LIB_FOUNDATION_BOEHM_GC
+    [GarbageCollector allowGarbageCollection];
+#endif
+}
+
+- (void)addObserver:(id)observer selector:(SEL)selector 
+  name:(NSString *)notificationName object:(id)object
+{
+    NSNotificationObjectRegister* reg;
+
+#if LIB_FOUNDATION_BOEHM_GC
+    [GarbageCollector denyGarbageCollection];
+#endif
+    
+    if (notificationName == nil)
+       reg = nullNameToObjects;
+    else {
+       notificationName
+            = AUTORELEASE([notificationName
+                              copyWithZone:[notificationName zone]]);
+       reg = NSMapGet (nameToObjects, notificationName);
+       if (!reg) {
+           reg = AUTORELEASE([[NSNotificationObjectRegister alloc] init]);
+           NSMapInsert (nameToObjects, notificationName, reg);
+       }
+    }
+    [reg addObserver:observer selector:selector object:object];
+
+#if LIB_FOUNDATION_BOEHM_GC
+    if (object) {
+        [GarbageCollector registerForFinalizationObserver:self
+                         selector:@selector(_objectWillFinalize:)
+                         object:object];
+    }
+
+    [GarbageCollector registerForFinalizationObserver:self
+                     selector:@selector(_observerWillFinalize:)
+                     object:observer];
+
+    [GarbageCollector allowGarbageCollection];
+#endif
+}
+
+- (void)removeObserver:(id)observer 
+  name:(NSString*)notificationName object:(id)object
+{
+    NSNotificationObjectRegister *reg;
+
+#if LIB_FOUNDATION_BOEHM_GC
+    [GarbageCollector denyGarbageCollection];
+#endif
+    
+    reg = (notificationName == nil)
+       ? nullNameToObjects
+       : NSMapGet (nameToObjects, notificationName);
+    
+    [reg removeObserver:observer object:object];
+
+#if LIB_FOUNDATION_BOEHM_GC
+    [GarbageCollector allowGarbageCollection];
+#endif
+}
+
+- (void)removeObserver:(id)observer
+{
+    id                           name;
+    NSMapEnumerator              enumerator;
+    NSNotificationObjectRegister *reg;
+
+#if LIB_FOUNDATION_BOEHM_GC
+    [GarbageCollector denyGarbageCollection];
+#endif
+    
+    enumerator = NSEnumerateMapTable(self->nameToObjects);
+
+    while (NSNextMapEnumeratorPair(&enumerator, (void*)&name, (void*)&reg))
+       [reg removeObserver:observer];
+
+    [nullNameToObjects removeObserver:observer];
+
+#if LIB_FOUNDATION_BOEHM_GC
+    [GarbageCollector allowGarbageCollection];
+#endif
+}
+
+#if LIB_FOUNDATION_BOEHM_GC
+- (void)removeObject:object
+{
+    id                           name;
+    NSMapEnumerator              enumerator;
+    NSNotificationObjectRegister *reg;
+
+#if LIB_FOUNDATION_BOEHM_GC
+    [GarbageCollector denyGarbageCollection];
+#endif
+    
+    enumerator = NSEnumerateMapTable (nameToObjects);
+
+    while (NSNextMapEnumeratorPair (&enumerator, (void*)&name, (void*)&reg))
+       [reg removeObject:object];
+
+    [nullNameToObjects removeObject:object];
+
+#if LIB_FOUNDATION_BOEHM_GC
+    [GarbageCollector allowGarbageCollection];
+#endif
+}
+
+- (void)_objectWillFinalize:(id)object
+{
+#if 0
+  printf ("NSNotificationCenter _objectWillFinalize %lu\n",
+          (unsigned long)object);
+#endif
+  [self removeObject:object];
+}
+
+- (void)_observerWillFinalize:(id)observer
+{
+#if 0
+  printf ("NSNotificationCenter _observerWillFinalize: %lu\n",
+          (unsigned long)observer);
+#endif
+  [self removeObserver:observer];
+}
+#endif
+
+- (void)postNotificationName:(NSString*)notificationName object:object
+{
+    id notification;
+
+    notification = [[NSNotification alloc] initWithName:notificationName
+                                          object:object
+                                          userInfo:nil];
+    [self postNotification:notification];
+    RELEASE(notification);
+}
+
+- (void)postNotificationName:(NSString*)notificationName object:object
+  userInfo:(NSDictionary*)userInfo;
+{
+    id notification;
+
+    notification = [[NSNotification alloc] initWithName:notificationName
+                                          object:object
+                                          userInfo:userInfo];
+    [self postNotification:notification];
+    RELEASE(notification);
+}
+
+@end /* NSNotificationCenter */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSNotificationQueue.h b/libFoundation/Foundation/NSNotificationQueue.h
new file mode 100644 (file)
index 0000000..2d8b051
--- /dev/null
@@ -0,0 +1,98 @@
+/* 
+   NSNotificationQueue.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSNotificationQueue_h__
+#define __NSNotificationQueue_h__
+
+#include <Foundation/NSNotification.h>
+
+@class NSMutableArray;
+
+/*
+ * Posting styles into notification queue
+ */
+
+typedef enum {
+    NSPostWhenIdle,    
+    NSPostASAP,                
+    NSPostNow          
+} NSPostingStyle;
+
+typedef enum {
+    NSNotificationNoCoalescing = 0,    
+    NSNotificationCoalescingOnName = 1,        
+    NSNotificationCoalescingOnSender = 2,      
+} NSNotificationCoalescing;
+
+/*
+ * NSNotificationQueue class
+ */
+
+@interface NSNotificationQueue : NSObject
+{
+    NSNotificationCenter            *center;
+    struct _NSNotificationQueueList *asapQueue;
+    struct _NSNotificationQueueList *idleQueue;
+    NSZone *zone;
+}
+
+/* Creating Notification Queues */
+
++ (NSNotificationQueue *)defaultQueue;
+- (id)init;
+- (id)initWithNotificationCenter:(NSNotificationCenter *)notificationCenter;
+
+/* Inserting and Removing Notifications From a Queue */
+- (void)dequeueNotificationsMatching:(NSNotification*)notification
+  coalesceMask:(unsigned int)coalesceMask;
+
+- (void)enqueueNotification:(NSNotification*)notification
+  postingStyle:(NSPostingStyle)postingStyle;
+
+- (void)enqueueNotification:(NSNotification*)notification
+  postingStyle:(NSPostingStyle)postingStyle
+  coalesceMask:(unsigned int)coalesceMask
+  forModes:(NSArray*)modes;
+
+/* Implementation used by the the NSRunLoop */
+
++ (void)runLoopIdle;
++ (void)runLoopASAP;
+- (void)notifyIdle;
+- (void)notifyASAP;
+
+/* Private methods */
++ (void)taskNowMultiThreaded:notification;
+
+@end
+
+#endif /* __NSNotificationQueue_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSNotificationQueue.m b/libFoundation/Foundation/NSNotificationQueue.m
new file mode 100644 (file)
index 0000000..b849b81
--- /dev/null
@@ -0,0 +1,439 @@
+/* 
+   NSNotificationQueue.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSRunLoop.h>
+#include <Foundation/NSNotificationQueue.h>
+#include <Foundation/NSNotification.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSThread.h>
+
+#include "PrivateThreadData.h"
+
+/*
+ * NSNotificationQueue queue
+ */
+
+typedef struct _NSNotificationQueueRegistration {
+    struct _NSNotificationQueueRegistration* next;
+    struct _NSNotificationQueueRegistration* prev;
+    NSNotification* notification;
+    id name;
+    id object;
+    NSArray* modes;
+} NSNotificationQueueRegistration;
+
+typedef struct _NSNotificationQueueList {
+    struct _NSNotificationQueueRegistration *head;
+    struct _NSNotificationQueueRegistration *tail;
+} NSNotificationQueueList;
+
+/*
+ * Queue functions
+ *
+ *  Queue             Elem              Elem              Elem
+ *    head ---------> prev -----------> prev -----------> prev --> nil
+ *            nil <-- next <----------- next <----------- next
+ *    tail --------------------------------------------->
+ */
+
+static void
+remove_from_queue(
+    NSNotificationQueueList* queue,
+    NSNotificationQueueRegistration* item,
+    NSZone* zone)
+{
+    if (item->prev)
+       item->prev->next = item->next;
+    else {
+       queue->tail = item->next;
+       if (item->next)
+           item->next->prev = NULL;
+    }
+    
+    if (item->next)
+       item->next->prev = item->prev;
+    else {
+       queue->head = item->prev;
+       if (item->prev)
+           item->prev->next = NULL;
+    }
+    RELEASE(item->notification);
+    RELEASE(item->modes);
+    NSZoneFree(zone, item);
+}
+
+static void
+add_to_queue(
+    NSNotificationQueueList *queue,
+    NSNotification *notification,
+    NSArray *modes,
+    NSZone  *zone)
+{
+    /* note: this is called in UnixSignalHandler (no malloc allowed) */
+    // TODO: possibly calls malloc in Unix signal handler
+    NSNotificationQueueRegistration *item = 
+        NSZoneCalloc(zone, 1, sizeof(NSNotificationQueueRegistration));
+    
+    item->notification = RETAIN(notification);
+    item->name   = [notification notificationName];
+    item->object = [notification notificationObject];
+    
+    /* modes isn't used with sigs */
+    item->modes  = [modes copyWithZone:[modes zone]];
+    
+    item->prev = NULL;
+    item->next = queue->tail;
+    queue->tail = item;
+    if (item->next)
+       item->next->prev = item;
+    if (!queue->head)
+       queue->head = item;
+}
+
+/*
+ * Notification Queue calss variables
+ */
+
+typedef struct _InstanceList {
+    struct _InstanceList *next;
+    struct _InstanceList *prev;
+    id queue;
+} InstanceList;
+
+static BOOL isMultiThreaded = NO;
+static InstanceList        *notificationQueues = NULL;
+static NSNotificationQueue *defaultQueue = nil;
+
+/*
+ * NSNotificationQueue class implementation
+ */
+
+@implementation NSNotificationQueue
+
++ (void)initialize
+{
+    static BOOL initialized = NO;
+
+    if (!initialized) {
+       initialized = YES;
+       defaultQueue = [[self alloc] init];
+    }
+}
+
++ (void)taskNowMultiThreaded:notification
+{
+    PrivateThreadData *threadData = [[NSThread currentThread]
+                                               _privateThreadData];
+    
+    [threadData setThreadNotificationQueues:notificationQueues];
+    [threadData setDefaultNotificationQueue:defaultQueue];
+    notificationQueues = NULL;
+    defaultQueue = nil;
+    isMultiThreaded = YES;
+}
+
++ (NSNotificationQueue *)defaultQueue
+{
+    if (isMultiThreaded) {
+       return [[[NSThread currentThread] _privateThreadData]
+                           defaultNotificationQueue];
+    }
+    else {
+        NSAssert(defaultQueue, @"default queue not setup ...");
+       return defaultQueue;
+    }
+}
+
+- (id)init
+{
+    NSNotificationCenter *defcenter;
+
+    defcenter = [NSNotificationCenter defaultCenter];
+    return [self initWithNotificationCenter:defcenter];
+}
+
+- (id)initWithNotificationCenter:(NSNotificationCenter*)notificationCenter
+{
+    InstanceList *regItem;
+    
+    self->zone = [self zone];
+
+    // init queue
+    self->center = RETAIN(notificationCenter);
+    self->asapQueue =
+        NSZoneCalloc(self->zone, 1, sizeof(NSNotificationQueueList));
+    self->idleQueue =
+        NSZoneCalloc(self->zone, 1, sizeof(NSNotificationQueueList));
+    
+    // insert in global queue list
+    regItem = Calloc(1, sizeof(InstanceList));
+    regItem->queue = self; /* hh: do not retain ? */
+    
+    if (isMultiThreaded) {
+       PrivateThreadData* threadData = [[NSThread currentThread]
+                                               _privateThreadData];
+
+       regItem->next = [threadData threadNotificationQueues];
+       [threadData setThreadNotificationQueues:regItem];
+    }
+    else {
+       regItem->next = notificationQueues;
+       notificationQueues = regItem;
+    }
+    
+    return self;
+}
+
+- (void)dealloc
+{
+    NSNotificationQueueRegistration *item;
+    InstanceList      *regItem, *theItem;
+    PrivateThreadData *threadData = nil;
+    InstanceList *queues;
+
+    /* remove from class instances list */
+    if (isMultiThreaded) {
+       threadData = [[NSThread currentThread] _privateThreadData];
+       queues = [threadData threadNotificationQueues];
+    }
+    else
+       queues = notificationQueues;
+
+    if (queues->queue == self) {
+       if (isMultiThreaded)
+           [threadData setThreadNotificationQueues:queues->next];
+       else
+           notificationQueues = notificationQueues->next;
+    }
+    else {
+       for (regItem=notificationQueues;
+             regItem->next;
+             regItem=regItem->next)
+       {
+           if (regItem->next->queue == self) {
+               theItem = regItem->next;
+               regItem->next = theItem->next;
+               lfFree(theItem);
+               break;
+           }
+       }
+    }
+    
+    /* release self */
+    for (item = self->asapQueue->head; item; item=item->prev)
+       remove_from_queue(self->asapQueue, item, self->zone);
+    NSZoneFree(self->zone, self->asapQueue);
+
+    for (item = self->idleQueue->head; item; item=item->prev)
+       remove_from_queue(self->idleQueue, item, self->zone);
+    NSZoneFree(self->zone, self->idleQueue);
+
+    RELEASE(self->center);
+    [super dealloc];
+}
+
+/* Inserting and Removing Notifications From a Queue */
+
+- (void)dequeueNotificationsMatching:(NSNotification*)notification
+  coalesceMask:(NSNotificationCoalescing)coalesceMask
+{
+    NSNotificationQueueRegistration* item;
+    NSNotificationQueueRegistration* next;
+    id name   = [notification notificationName];
+    id object = [notification notificationObject];
+    
+    /* find in ASAP notification in queue */
+    for (item = self->asapQueue->tail; item; item=next) {
+       next = item->next;
+       if ((coalesceMask & NSNotificationCoalescingOnName)
+           && [name isEqual:item->name]) 
+           {
+               remove_from_queue(self->asapQueue, item, self->zone);
+               continue;
+           }
+       if ((coalesceMask & NSNotificationCoalescingOnSender)
+           && (object == item->object))
+           {
+               remove_from_queue(self->asapQueue, item, self->zone);
+               continue;
+           }
+    }
+    
+    // find in idle notification in queue
+    for (item = self->idleQueue->tail; item; item=next) {
+       next = item->next;
+       if ((coalesceMask & NSNotificationCoalescingOnName)
+           && [name isEqual:item->name]) 
+           {
+               remove_from_queue(self->asapQueue, item, self->zone);
+               continue;
+           }
+       if ((coalesceMask & NSNotificationCoalescingOnSender)
+           && (object == item->object))
+           {
+               remove_from_queue(self->asapQueue, item, self->zone);
+               continue;
+           }
+    }
+}
+
+- (BOOL)postNotification:(NSNotification *)notification
+  forModes:(NSArray *)modes
+{
+    BOOL     ok = NO;
+    NSString *mode = [[NSRunLoop currentRunLoop] currentMode];
+    
+    /* check to see if run loop is in a valid mode */
+    if (mode == nil || modes == nil)
+       ok = YES;
+    else {
+       int i;
+       
+       for (i = [modes count]-1; i >= 0; i--)
+           if ([mode isEqual:[modes objectAtIndex:i]]) {
+               ok = YES;
+               break;
+           }
+    }
+    
+    // if mode is valid then post
+    if (ok)
+       [self->center postNotification:notification];
+
+    return ok;
+}
+
+- (void)enqueueNotification:(NSNotification *)notification
+  postingStyle:(NSPostingStyle)postingStyle    
+{
+    [self enqueueNotification:notification
+          postingStyle:postingStyle
+          coalesceMask:(NSNotificationCoalescingOnName + 
+                        NSNotificationCoalescingOnSender)
+          forModes:nil];
+}
+
+- (void)enqueueNotification:(NSNotification*)notification
+  postingStyle:(NSPostingStyle)postingStyle
+  coalesceMask:(NSNotificationCoalescing)coalesceMask
+  forModes:(NSArray*)modes
+{
+    /* note: this is called in UnixSignalHandler (no malloc allowed) */
+    if (coalesceMask != NSNotificationNoCoalescing) {
+       [self dequeueNotificationsMatching:notification
+              coalesceMask:coalesceMask];
+    }
+
+    NSAssert(notification, @"missing notification ...");
+    
+    switch (postingStyle) {
+       case NSPostNow:
+               [self postNotification:notification forModes:modes];
+               break;
+       case NSPostASAP:
+               add_to_queue(self->asapQueue, notification, modes, self->zone);
+               break;
+       case NSPostWhenIdle:
+               add_to_queue(self->idleQueue, notification, modes, self->zone);
+               break;
+    }
+}
+
+/*
+ * NotificationQueue internals
+ */
+
++ (void)runLoopIdle
+{
+    InstanceList *item, *queues;
+
+    if (isMultiThreaded)
+       queues = [[[NSThread currentThread] _privateThreadData]
+                       threadNotificationQueues];
+    else
+       queues = notificationQueues;
+
+    for (item = queues; item; item = item->next)
+       [item->queue notifyIdle];
+}
+
++ (void)runLoopASAP
+{
+    InstanceList *item, *queues;
+    
+    if (isMultiThreaded) {
+       queues = [[[NSThread currentThread] _privateThreadData]
+                             threadNotificationQueues];
+    }
+    else
+       queues = notificationQueues;
+
+    //printf("RUNNING LOOP ASAP ...\n");
+    for (item = queues; item; item = item->next) {
+        //printf("  RUNNING ITEM ...\n");
+       [item->queue notifyASAP];
+    }
+}
+
+- (void)notifyIdle
+{
+    /* post next IDLE notification in queue */
+    if (self->idleQueue->head) {
+       if ([self postNotification:self->idleQueue->head->notification 
+                  forModes:self->idleQueue->head->modes]) {
+           remove_from_queue(self->idleQueue, self->idleQueue->head,
+                              self->zone);
+        }
+    }
+}
+
+- (void)notifyASAP
+{
+    /* post all ASAP notifications in queue */
+    while (self->asapQueue->head) {
+        struct _NSNotificationQueueRegistration *asapHead;
+        BOOL ok;
+
+        asapHead = self->asapQueue->head;
+
+        ok = [self postNotification:asapHead->notification
+                   forModes:asapHead->modes];
+        
+       if (ok)
+           remove_from_queue(self->asapQueue, asapHead, self->zone);
+    }
+}
+
+@end /* NSNotificationQueue */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSNull.h b/libFoundation/Foundation/NSNull.h
new file mode 100644 (file)
index 0000000..0e89ca7
--- /dev/null
@@ -0,0 +1,36 @@
+/* 
+   NSNull.h
+
+   Copyright (C) 2000, MDlink online service center GmbH, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSNull_h__
+#define __NSNull_h__
+
+#include <Foundation/NSObject.h>
+
+@interface NSNull : NSObject < NSCopying, NSCoding >
+
++ (NSNull *)null;
+
+@end
+
+#endif /* __NSNull_h__ */
diff --git a/libFoundation/Foundation/NSNull.m b/libFoundation/Foundation/NSNull.m
new file mode 100644 (file)
index 0000000..ceb197f
--- /dev/null
@@ -0,0 +1,130 @@
+/* 
+   NSNull.m
+
+   Copyright (C) 2000, MDlink online service center GmbH, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSNull.h>
+#include <Foundation/NSUtilities.h>
+#include <common.h>
+
+@implementation NSNull
+
+// MT, THREAD
+static NSNull *sharedNSNull = nil;
+
++ (void)initialize
+{
+  if (sharedNSNull == nil)
+    sharedNSNull = (NSNull*)NSAllocateObject(self, 0, NSDefaultMallocZone());
+}
+
++ (id)null
+{
+  return sharedNSNull;
+}
+
++ (id)allocWithZone:(NSZone *)_zone
+{
+  return sharedNSNull;
+}
++ (id)alloc
+{
+  return sharedNSNull;
+}
+
+- (void)dealloc
+{
+  NSLog(@"WARNING: tried to deallocate NSNull !");
+}
+
+/* NSCoding */
+
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+  if (self == sharedNSNull)
+    return sharedNSNull;
+
+  RELEASE(self);
+  return sharedNSNull;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+}
+
+/* NSCopying */
+
+- (id)copy
+{
+  return RETAIN(self);
+}
+- (id)copyWithZone:(NSZone *)zone
+{
+  return RETAIN(self);
+}
+
+- (id)retain
+{
+  return self;
+}
+- (void)release
+{
+}
+- (id)autorelease
+{
+  return self;
+}
+
+/* comparison */
+
+- (NSComparisonResult)compare:(id)_otherObject
+{
+  return (_otherObject == self)
+    ? NSOrderedSame
+    : NSOrderedDescending;
+}
+
+- (BOOL)boolValue
+{
+  return NO;
+}
+
+- (NSString *)description
+{
+  return @"<null>";
+}
+- (NSString *)stringValue
+{
+  return @"";
+}
+
+- (NSString *)stringRepresentation
+{
+  /* encode as empty string in property lists ! */
+#if DEBUG
+  NSLog(@"WARNING(%s): encoded NSNull in property list !",
+        __PRETTY_FUNCTION__);
+#endif
+  return @"\"\"";
+}
+
+@end /* NSNull */
diff --git a/libFoundation/Foundation/NSNumber.m b/libFoundation/Foundation/NSNumber.m
new file mode 100644 (file)
index 0000000..478b605
--- /dev/null
@@ -0,0 +1,530 @@
+/* 
+   NSNumber.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSCoder.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSUtilities.h>
+
+#include <Foundation/exceptions/NSValueExceptions.h>
+
+#include <extensions/objc-runtime.h>
+
+#include "NSConcreteNumber.h"
+#include "NSConcreteValue.h"
+
+/*
+ * Temporary number used to allocate and initialize NSNumbers 
+ * through initWith... methods in constructs like [[NSNumber alloc] initWith...
+ */
+
+@interface NSTemporaryNumber : NSNumber
+@end
+
+// THREAD
+static NSNumber *boolYes  = nil;
+static NSNumber *boolNo   = nil;
+static NSNumber *intNums[64] = {
+    nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+    nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+    nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+    nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+    nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+    nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+    nil, nil, nil, nil
+};
+
+#define INT_LRU_CACHE_SIZE 16
+static short lastRecentlyUsed = 0;
+static struct { int value; NSNumber *object; }
+recentlyUsed[INT_LRU_CACHE_SIZE] = {
+    { 0, nil }, { 0, nil }, { 0, nil }, { 0, nil },
+    { 0, nil }, { 0, nil }, { 0, nil }, { 0, nil },
+    { 0, nil }, { 0, nil }, { 0, nil }, { 0, nil },
+    { 0, nil }, { 0, nil }, { 0, nil }, { 0, nil },
+};
+
+static inline void setupYesAndNo(void)
+{
+    if (boolYes == nil) {
+        BOOL v;
+        v = YES;
+        boolYes = [[NSBoolNumber alloc] initValue:&v withObjCType:NULL];
+    }
+    if (boolNo == nil) {
+        BOOL v;
+        v = NO;
+        boolNo = [[NSBoolNumber alloc] initValue:&v withObjCType:NULL];
+    }
+}
+static inline NSIntNumber *makeInt(int i)
+{
+    static Class IntNumber = Nil;
+
+    if (IntNumber == Nil) IntNumber = [NSIntNumber class];
+    
+    if ((i < 0) || (i > 63)) {
+        /* scan LRU cache */
+        register int p;
+
+        for (p = 0; p < INT_LRU_CACHE_SIZE; p++) {
+            if (recentlyUsed[p].value == i)
+                return RETAIN(recentlyUsed[p].object);
+        }
+        
+        lastRecentlyUsed++;
+        if (lastRecentlyUsed == INT_LRU_CACHE_SIZE) lastRecentlyUsed = 0;
+        
+        RELEASE(recentlyUsed[lastRecentlyUsed].object);
+        
+        recentlyUsed[lastRecentlyUsed].value = i;
+        recentlyUsed[lastRecentlyUsed].object =
+            [[IntNumber alloc] initValue:&i withObjCType:NULL];
+        
+        return RETAIN(recentlyUsed[lastRecentlyUsed].object);
+    }
+    
+    if (intNums[i] == nil)
+        intNums[i] = [[IntNumber alloc] initValue:&i withObjCType:NULL];
+    
+    return RETAIN(intNums[i]);
+}
+
+@implementation NSTemporaryNumber
+
+- (id)initWithBool:(BOOL)value
+{
+    (void)AUTORELEASE(self);
+    setupYesAndNo();
+    return value ? RETAIN(boolYes) : RETAIN(boolNo);
+}
+
+- (id)initWithChar:(char)value
+{
+    (void)AUTORELEASE(self);
+    return [[NSCharNumber alloc] initValue:&value withObjCType:NULL];
+}
+
+- (id)initWithUnsignedChar:(unsigned char)value
+{
+    (void)AUTORELEASE(self);
+    return [[NSUCharNumber alloc] initValue:&value withObjCType:NULL];
+}
+
+- (id)initWithShort:(short)value
+{
+    (void)AUTORELEASE(self);
+    return [[NSShortNumber alloc] initValue:&value withObjCType:NULL];
+}
+
+- (id)initWithUnsignedShort:(unsigned short)value
+{
+    (void)AUTORELEASE(self);
+    return [[NSUShortNumber alloc] initValue:&value withObjCType:NULL];
+}
+
+- (id)initWithInt:(int)value
+{
+    (void)AUTORELEASE(self);
+    return makeInt(value);
+}
+
+- (id)initWithUnsignedInt:(unsigned int)value
+{
+    (void)AUTORELEASE(self);
+    return [[NSUIntNumber alloc] initValue:&value withObjCType:NULL];
+}
+
+- (id)initWithLong:(long)value
+{
+    (void)AUTORELEASE(self);
+    return [[NSLongNumber alloc] initValue:&value withObjCType:NULL];
+}
+
+- (id)initWithUnsignedLong:(unsigned long)value
+{
+    (void)AUTORELEASE(self);
+    return [[NSULongNumber alloc] initValue:&value withObjCType:NULL];
+}
+
+- (id)initWithLongLong:(long long)value
+{
+    (void)AUTORELEASE(self);
+    return [[NSLongLongNumber alloc] initValue:&value withObjCType:NULL];
+}
+
+- (id)initWithUnsignedLongLong:(unsigned long long)value
+{
+    (void)AUTORELEASE(self);
+    return [[NSULongLongNumber alloc] initValue:&value withObjCType:NULL];
+}
+
+- (id)initWithFloat:(float)value
+{
+    (void)AUTORELEASE(self);
+    return [[NSFloatNumber alloc] initValue:&value withObjCType:NULL];
+}
+
+- (id)initWithDouble:(double)value
+{
+    (void)AUTORELEASE(self);
+    return [[NSDoubleNumber alloc] initValue:&value withObjCType:NULL];
+}
+
+@end
+
+/*
+ *  NSNumber class implementation
+ */
+
+@implementation NSNumber
+
++ (id)allocWithZone:(NSZone*)zone
+{
+    return NSAllocateObject((self == [NSNumber class])
+                            ? [NSTemporaryNumber class] : self,
+                            0, zone);
+}
+
+/*
+ * Determines the concrete value class
+ * Only numbers
+ */
+
++ (Class)concreteClassForObjCType:(const char*)type
+{
+    if (!type)
+[[[NSNumberException new] setReason:@"NULL type"] raise];
+
+    if (Strlen(type) == 1) {
+       switch(*type) {
+        case _C_CHR:   return [NSCharNumber      class];
+        case _C_UCHR:  return [NSUCharNumber     class];
+        case _C_SHT:   return [NSShortNumber     class];
+        case _C_USHT:  return [NSUShortNumber    class];
+        case _C_INT:   return [NSIntNumber       class];
+        case _C_UINT:  return [NSUIntNumber      class];
+        case _C_LNG:   return [NSLongNumber      class];
+        case _C_ULNG:  return [NSULongNumber     class];
+        case _C_FLT:   return [NSFloatNumber     class];
+        case _C_DBL:   return [NSDoubleNumber    class];
+        case 'q':      return [NSLongLongNumber  class];
+        case 'Q':      return [NSULongLongNumber class];
+       }
+    }
+
+    if (self == [NSNumber class]) {
+       [[[NSNumberException new]
+                  initWithFormat:@"Invalid number type '%s'", type] raise];
+
+       return nil;
+    }
+    else 
+       return [super concreteClassForObjCType:type];
+}
+
++ (NSNumber*)numberWithBool:(BOOL)value
+{
+    setupYesAndNo();
+    return value ? boolYes : boolNo;
+}
+
++ (NSNumber*)numberWithChar:(char)value
+{
+    return AUTORELEASE([[NSCharNumber alloc]
+                           initValue:&value withObjCType:NULL]);
+}
+
++ (NSNumber*)numberWithUnsignedChar:(unsigned char)value
+{
+    return AUTORELEASE([[NSUCharNumber alloc] 
+                           initValue:&value withObjCType:NULL]);
+}
+
++ (NSNumber*)numberWithShort:(short)value
+{
+    return AUTORELEASE([[NSShortNumber alloc]
+                           initValue:&value withObjCType:NULL]);
+}
+
++ (NSNumber*)numberWithUnsignedShort:(unsigned short)value
+{
+    return AUTORELEASE([[NSUShortNumber alloc] 
+                           initValue:&value withObjCType:NULL]);
+}
+
++ (NSNumber*)numberWithInt:(int)value
+{
+    return AUTORELEASE(makeInt(value));
+}
+
++ (NSNumber*)numberWithUnsignedInt:(unsigned int)value
+{
+    return AUTORELEASE([[NSUIntNumber alloc]
+                           initValue:&value withObjCType:NULL]);
+}
+
++ (NSNumber*)numberWithLong:(long)value
+{
+    return AUTORELEASE([[NSLongNumber alloc] 
+                           initValue:&value withObjCType:NULL]);
+}
+
++ (NSNumber*)numberWithUnsignedLong:(unsigned long)value
+{
+    return AUTORELEASE([[NSULongNumber alloc]
+                           initValue:&value withObjCType:NULL]);
+}
+
++ (NSNumber*)numberWithLongLong:(long long)value
+{
+    return AUTORELEASE([[NSLongLongNumber alloc]
+                           initValue:&value withObjCType:NULL]);
+}
+
++ (NSNumber*)numberWithUnsignedLongLong:(unsigned long long)value
+{
+    return AUTORELEASE([[NSULongLongNumber alloc]
+                           initValue:&value withObjCType:NULL]);
+}
+
++ (NSNumber*)numberWithFloat:(float)value
+{
+    return AUTORELEASE([[NSFloatNumber alloc]
+                           initValue:&value withObjCType:NULL]);
+}
+
++ (NSNumber*)numberWithDouble:(double)value
+{
+    return AUTORELEASE([[NSDoubleNumber alloc]
+                           initValue:&value withObjCType:NULL]);
+}
+
+- (id)initWithBool:(BOOL)value
+{
+    [self shouldNotImplement:_cmd];
+    return nil;
+}
+
+- (id)initWithChar:(char)value
+{
+    [self shouldNotImplement:_cmd];
+    return nil;
+}
+
+- (id)initWithUnsignedChar:(unsigned char)value
+{
+    [self shouldNotImplement:_cmd];
+    return nil;
+}
+
+- (id)initWithShort:(short)value
+{
+    [self shouldNotImplement:_cmd];
+    return nil;
+}
+
+- (id)initWithUnsignedShort:(unsigned short)value
+{
+    [self shouldNotImplement:_cmd];
+    return nil;
+}
+
+- (id)initWithInt:(int)value
+{
+    [self shouldNotImplement:_cmd];
+    return nil;
+}
+
+- (id)initWithUnsignedInt:(unsigned int)value
+{
+    [self shouldNotImplement:_cmd];
+    return nil;
+}
+
+- (id)initWithLong:(long)value
+{
+    [self shouldNotImplement:_cmd];
+    return nil;
+}
+
+- (id)initWithUnsignedLong:(unsigned long)value
+{
+    [self shouldNotImplement:_cmd];
+    return nil;
+}
+
+- (id)initWithLongLong:(long long)value
+{
+    [self shouldNotImplement:_cmd];
+    return nil;
+}
+
+- (id)initWithUnsignedLongLong:(unsigned long long)value
+{
+    [self shouldNotImplement:_cmd];
+    return nil;
+}
+
+- (id)initWithFloat:(float)value
+{
+    [self shouldNotImplement:_cmd];
+    return nil;
+}
+
+- (id)initWithDouble:(double)value
+{
+    [self shouldNotImplement:_cmd];
+    return nil;
+}
+
+/* These methods are not written in concrete subclassses */
+
+- (unsigned)hash
+{
+    return [self unsignedIntValue];
+}
+
+- (NSComparisonResult)compare:(NSNumber*)otherNumber
+{
+    [self subclassResponsibility:_cmd];
+    return 0;
+}
+
+- (BOOL)isEqualToNumber:(NSNumber*)aNumber
+{
+    return [self compare:aNumber] == NSOrderedSame;
+}
+
+- (BOOL)isEqual:aNumber
+{
+    return [aNumber isKindOfClass:[NSNumber class]] 
+        && [self isEqualToNumber:aNumber];
+}
+
+- (NSString*)description
+{
+    return [self descriptionWithLocale:nil];
+}
+
+- (NSString*)descriptionWithLocale:(NSDictionary*)locale
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+/* Access methods are implemented in concrete subclasses */
+
+- (BOOL)boolValue
+{
+    [self subclassResponsibility:_cmd];
+    return 0;
+}
+
+- (char)charValue
+{
+    [self subclassResponsibility:_cmd];
+    return 0;
+}
+
+- (unsigned char)unsignedCharValue
+{
+    [self subclassResponsibility:_cmd];
+    return 0;
+}
+
+- (short)shortValue
+{
+    [self subclassResponsibility:_cmd];
+    return 0;
+}
+
+- (unsigned short)unsignedShortValue
+{
+    [self subclassResponsibility:_cmd];
+    return 0;
+}
+
+- (int)intValue
+{
+    [self subclassResponsibility:_cmd];
+    return 0;
+}
+
+- (unsigned int)unsignedIntValue
+{
+    [self subclassResponsibility:_cmd];
+    return 0;
+}
+
+- (long)longValue
+{
+    [self subclassResponsibility:_cmd];
+    return 0;
+}
+
+- (unsigned long)unsignedLongValue
+{
+    [self subclassResponsibility:_cmd];
+    return 0;
+}
+
+- (long long)longLongValue
+{
+    [self subclassResponsibility:_cmd];
+    return 0;
+}
+
+- (unsigned long long)unsignedLongLongValue
+{
+    [self subclassResponsibility:_cmd];
+    return 0;
+}
+
+- (float)floatValue
+{
+    [self subclassResponsibility:_cmd];
+    return 0;
+}
+
+- (double)doubleValue
+{
+    [self subclassResponsibility:_cmd];
+    return 0;
+}
+
+- (NSString *)stringValue
+{
+    return [self descriptionWithLocale:nil];
+}
+
+@end /* NSNumber */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSNumberFormatter.h b/libFoundation/Foundation/NSNumberFormatter.h
new file mode 100644 (file)
index 0000000..87ab02b
--- /dev/null
@@ -0,0 +1,125 @@
+/* 
+   NSNumberFormatter.h
+
+   Copyright (C) 1998 MDlink online service center, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess (helge@mdlink.de), Martin Spindler (spindler@mdlink.de)
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+// $Id$
+
+#ifndef __NSNumberFormatter_h__
+#define __NSNumberFormatter_h__
+
+#include <Foundation/NSFormatter.h>
+#include <Foundation/NSString.h>
+
+@class NSNumber;
+
+@interface NSNumberFormatter : NSFormatter
+{
+@protected
+    NSString  *negativeFormat;
+    NSString  *positiveFormat;
+    NSNumber  *minimum;
+    NSNumber  *maximum;
+
+    unichar   decimalSeparator;
+    unichar   thousandSeparator;
+    BOOL      hasThousandSeparator;
+}
+
+// setting formats
+
+- (void)setPositiveFormat:(NSString *)_format;
+- (NSString *)positiveFormat;
+
+- (void)setNegativeFormat:(NSString *)_format;
+- (NSString *)negativeFormat;
+
+- (void)setFormat:(NSString *)_format;
+- (NSString *)format;
+
+// attributed string support
+
+#if HAVE_ATTRIBUTED_STRING
+
+- (void)setTextAttributesForPositiveValues:(NSDictionary *)_attrs;
+- (NSDictionary *)textAttributesForPositiveValues;
+
+- (void)setTextAttributesForNegativeValues:(NSDictionary *)_attrs;
+- (NSDictionary *)textAttributesForNegativeValues;
+
+- (void)setAttributedStringForZero:(NSAttributedString *)_string;
+- (NSAttributedString *)attributedStringForZero;
+
+- (void)setAttributedStringForNil:(NSAttributedString *)_string;
+- (NSAttributedString *)attributedStringForNil;
+
+- (void)setAttributedStringForNotANumber:(NSAttributedString *)_string;
+- (NSAttributedString *)attributedStringForNotANumber;
+
+#endif
+
+// separators
+
+- (void)setThousandSeparator:(NSString *)_string;
+- (NSString *)thousandSeparator;
+
+- (void)setDecimalSeparator:(NSString *)_string;
+- (NSString *)decimalSeparator;
+
+- (void)setHasThousandSeparators:(BOOL)_flag;
+- (BOOL)hasThousandSeparators;
+
+// ranges
+
+#if HAVE_DECIMAL_NUMBER
+
+- (void)setMinimum:(NSDecimalNumber *)_number;
+- (NSDecimalNumber *)minimum;
+
+- (void)setMaximum:(NSDecimalNumber *)_number;
+- (NSDecimalNumber *)maximum;
+
+- (void)setRoundingBehaviour:(NSDecimalNumberHandler *)_handler;
+- (NSDecimalNumberHandler *)roundingBehaviour;
+
+#else
+
+- (void)setMinimum:(NSNumber *)_number;
+- (NSNumber *)minimum;
+
+- (void)setMaximum:(NSNumber *)_number;
+- (NSNumber *)maximum;
+
+#endif
+
+- (void)setAllowsFloats:(BOOL)_flag;
+- (BOOL)allowsFloats;
+
+@end
+
+#endif
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSNumberFormatter.m b/libFoundation/Foundation/NSNumberFormatter.m
new file mode 100644 (file)
index 0000000..400c3a1
--- /dev/null
@@ -0,0 +1,755 @@
+ /* 
+   NSNumberFormatter.m
+
+   Copyright (C) 1998 MDlink online service center, Helge Hess
+   All rights reserved.
+
+   Author: Martin Spindler (ms@mdlink.de), Helge Hess (helge@mdlink.de)
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+// $Id$
+
+#include <ctype.h>
+#include <Foundation/common.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+#include <Foundation/NSNumberFormatter.h>
+#include <Foundation/NSValue.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSUtilities.h>
+
+/*
+  Missing:
+  zero format strings
+ */
+
+#define posDefaultFormat @"0.00"
+#define negDefaultFormat @"-0.00"
+
+static void     _checkFormat(NSNumberFormatter *self, NSString *_format);
+static unichar  separatorFromString(NSString *_string);
+
+static NSString *_prefix(NSNumberFormatter *self, NSString *_format);
+static NSString *_suffix(NSNumberFormatter *self, NSString *_format);
+static NSString *cleanFormat(NSNumberFormatter *self, NSString *_format);
+static NSString *digitsToDot(NSString *_string);
+static NSString *digitsFromDot(NSString *_string, NSString *_sep);
+
+static BOOL digitsForString(NSNumberFormatter *self,
+                            NSString **digitStr, NSString *_string);
+
+static BOOL checkMinMaxForNumber(NSNumberFormatter *self, NSNumber *_number);
+
+#if defined(__MINGW32__)
+static inline const char *index(const char *cstr, char c) {
+    if (cstr == NULL) return NULL;
+    while (*cstr) {
+        if (*cstr == c) return cstr;
+        cstr++;
+    }
+    return NULL;
+}
+#endif
+
+@implementation NSNumberFormatter
+
+- (id)init
+{
+    self->decimalSeparator  = '.';
+    self->thousandSeparator = ',';
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(self->negativeFormat);
+    RELEASE(self->positiveFormat);
+    RELEASE(self->maximum);
+    RELEASE(self->minimum);
+    [super dealloc];
+}
+
+// accessors
+
+- (void)setFormat:(NSString *)_format
+{
+    NSArray *stringArray;
+    
+    if ([_format length] == 0) {
+        [self setPositiveFormat:nil];
+        [self setNegativeFormat:nil];
+        return;
+    }
+
+    //TODO: insert zeroFormat
+    stringArray = [_format componentsSeparatedByString:@";"];
+    
+    switch ([stringArray count]) {
+        case 0:
+            [self setPositiveFormat:nil];
+            [self setNegativeFormat:nil];
+            break;
+        case 1:
+            [self setPositiveFormat:_format];
+            [self setNegativeFormat:[@"-" stringByAppendingString:_format]];
+            break;
+        case 2:
+            [self setPositiveFormat:[stringArray objectAtIndex:0]];
+            [self setNegativeFormat:[stringArray objectAtIndex:1]];
+            break;
+        case 3:
+            //TODO: insert zeroFormat (at index 1)
+            //NSLog(@"WARNING: zero format is not supported !");
+            [self setPositiveFormat:[stringArray objectAtIndex:0]];
+            [self setNegativeFormat:[stringArray objectAtIndex:2]];
+            break;
+        case 4:
+            //TODO: insert zeroFormat (at index 1)
+            //NSLog(@"WARNING: zero format is not supported !");
+            [self setPositiveFormat:[stringArray objectAtIndex:0]];
+            [self setNegativeFormat:[stringArray objectAtIndex:2]];
+            [self setDecimalSeparator:[stringArray objectAtIndex:3]];
+            break;
+        case 5:
+            //TODO: insert zeroFormat (at index 1)
+            //NSLog(@"WARNING: zero format is not supported !");
+            [self setPositiveFormat:[stringArray objectAtIndex:0]];
+            [self setNegativeFormat:[stringArray objectAtIndex:2]];
+            [self setDecimalSeparator:[stringArray objectAtIndex:3]];
+            [self setThousandSeparator:[stringArray objectAtIndex:4]];
+            break;
+        default:
+            [[[InvalidArgumentException alloc]
+                 initWithReason:@"invalid format passed to -setFormat:"] raise];
+            break;
+    }
+}
+
+- (NSString *)format
+{
+    NSMutableString *myString = nil;
+
+    myString = [NSMutableString stringWithString:[self positiveFormat]];
+    [myString appendString:@";"];
+    [myString appendString:[self negativeFormat]];
+    return myString;
+}
+
+- (void)setNegativeFormat:(NSString *)_format
+{
+    _checkFormat(self, _format);
+
+    if (self->negativeFormat != _format) {
+        RELEASE(self->negativeFormat);
+        self->negativeFormat = [_format copyWithZone:[self zone]];
+    }
+}
+- (NSString *)negativeFormat
+{
+    return self->negativeFormat ? self->negativeFormat : negDefaultFormat;
+}
+
+- (void)setPositiveFormat:(NSString *)_format
+{
+    _checkFormat(self, _format);
+
+    if (self->positiveFormat != _format) {
+        RELEASE(self->positiveFormat);
+        self->positiveFormat = [_format copyWithZone:[self zone]];
+    }
+}
+- (NSString *)positiveFormat
+{
+    return self->positiveFormat ? self->positiveFormat : posDefaultFormat;
+}
+- (NSString *)zeroFormat
+{
+    return [self positiveFormat];
+}
+
+- (void)setDecimalSeparator:(NSString *)_separator
+{
+    self->decimalSeparator = separatorFromString(_separator);
+}
+- (NSString *)decimalSeparator
+{
+    char c = self->decimalSeparator;
+    if (c == '.') return @".";
+    if (c == ',') return @",";
+    return [NSString stringWithCString:&c length:1];
+}
+
+- (void)setThousandSeparator:(NSString *)_separator
+{
+    self->thousandSeparator = separatorFromString(_separator);
+}
+- (NSString *)thousandSeparator
+{
+    char c = self->thousandSeparator;
+    if (c == '.') return @".";
+    if (c == ',') return @",";
+    return [NSString stringWithCString:&c length:1];
+}
+
+- (void)setMinimum:(NSNumber *)_number
+{
+    ASSIGN(self->minimum, _number);
+}
+- (NSNumber *)minimum
+{
+    return self->minimum;
+}
+
+- (void)setMaximum:(NSNumber *)_number
+{
+    ASSIGN(self->maximum, _number);
+}
+- (NSNumber *)maximum
+{
+    return self->maximum;
+}
+
+- (void)setHasThousandSeparators:(BOOL)_status
+{
+    self->hasThousandSeparator = _status;
+}
+- (BOOL)hasThousandSeparators
+{
+    return self->hasThousandSeparator;
+}
+
+- (void)setAllowsFloats:(BOOL)_flag
+{
+    [self notImplemented:_cmd];
+}
+- (BOOL)allowsFloats
+{
+    return YES;
+}
+
+// public methods
+
+- (NSString *)_stringForDecimalNumber:(id)anObject
+{
+    return [self stringForObjectValue:
+                   [NSNumber numberWithDouble:[anObject doubleValue]]];
+}
+
+- (NSString *)stringForObjectValue:(id)anObject
+{
+    static Class DecNumber = Nil;
+    BOOL             hasThousandSep, hasDecimalSep;
+    NSString         *format;
+    NSString         *numStr;
+    NSMutableString  *newString;
+    int              len;
+    unsigned         decSepIdx;
+    double           dblValue;
+    NSString         *cFmt;
+    NSString         *decSepFmt;
+
+    //NSLog(@"STRING FOR OBJECT: %@", anObject);
+    
+    if (DecNumber == Nil)
+        DecNumber = NSClassFromString(@"NSDecimalNumber");
+    
+    if ([anObject isKindOfClass:DecNumber])
+        return [self _stringForDecimalNumber:anObject];
+    
+    if (anObject == nil) anObject = [NSNumber numberWithDouble:0.0];
+    
+    if ([anObject isKindOfClass:[NSString class]])
+        return anObject;
+    
+    if (![anObject isKindOfClass:[NSNumber class]]) {
+        [[[InvalidArgumentException alloc]
+             initWithReason:@"number formatter formats only numbers !"] raise];
+        return nil;
+    }
+
+    dblValue = [anObject doubleValue];
+
+    if (dblValue < 0.0)
+        format = [self negativeFormat];
+    else if (dblValue == 0.0)
+        format = [self zeroFormat];
+    else
+        format = [self positiveFormat];
+    
+    if ([format length] == 0) {
+        /* no format given, return stringValue */
+        //NSLog(@"%s: missing format ..", __PRETTY_FUNCTION__);
+        return [anObject stringValue];
+    }
+    
+    /* generate proper C format */
+    
+    cFmt = @"%0.16g";
+    
+    decSepIdx     = [format indexOfString:[self decimalSeparator]];
+    hasDecimalSep = (decSepIdx != NSNotFound) ? YES : NO;
+    
+    if (hasDecimalSep) {
+        /* get format part behind the decimal separator .. */
+        decSepFmt = digitsFromDot(format, [self decimalSeparator]);
+        cFmt = [NSString stringWithFormat:@"%%0.%if", [decSepFmt length]];
+    }
+    else
+        decSepFmt = nil;
+    
+    numStr = [NSString stringWithFormat:cFmt, dblValue];
+    
+    //NSLog(@"USE NUM STRING: %@ (fmt='%@')", numStr, cFmt);
+    
+    /* removes minus sign in result if negative .. */
+    
+    if (dblValue < 0.0)
+        numStr = [numStr substringFromIndex:1];
+    
+    /* scan whether the format contains thousand separators */
+    {
+        register const unsigned char *cfmt;
+        hasThousandSep = NO;
+        if ((cfmt = [format cString])) {
+            for ( ; *cfmt != '\0' && !hasThousandSep; cfmt++) {
+                if (*cfmt == self->thousandSeparator)
+                    hasThousandSep = YES;
+            }
+        }
+    }
+    //hasThousandSep=index([format cString], self->thousandSeparator) ? YES : NO;
+    
+    // removes all '#' and the 1000separators
+    format = cleanFormat(self, format);
+    NSAssert(format, @"invalid state !");
+    
+    //Digits in front of Decimal Separator
+    newString = [digitsToDot(numStr) mutableCopy];
+    newString = AUTORELEASE(newString);
+
+    /* insert thousand separators .. */
+    
+    if (self->hasThousandSeparator || hasThousandSep) {
+        int length = [newString length];
+        int i = 1;
+        
+        while ((i * 3) < length) {
+            [newString insertString:[self thousandSeparator]
+                       atIndex:(length - i * 3)];
+            i++;
+        }
+    }
+    len = [digitsToDot(format) length] - [digitsToDot(numStr) length];
+    if (len > 0) {
+        [newString insertString:[digitsToDot(format) substringToIndex:len]
+                   atIndex:0];
+    }
+    
+    /* add format prefix in front ... */
+    
+    [newString insertString:_prefix(self, format) atIndex:0];
+    
+    /* Digits behind Decimal Separator */
+    
+    if (hasDecimalSep && [self allowsFloats]) {
+        NSString *nkNumStr;
+        unsigned padLen;
+            
+        /* add separator */
+        [newString appendString:[self decimalSeparator]];
+        
+        /* get digits after decimal point */
+        nkNumStr = digitsFromDot(numStr, @".");
+        
+        /* find out whether format is longer than value .. */
+        padLen = [decSepFmt length] - [nkNumStr length];
+            
+        if (padLen > 0) {
+            /* format is longer than value, pad the rest */
+            NSString *fmtValue;
+            unsigned idx;
+                
+            idx      = [decSepFmt length] - padLen;
+            fmtValue = [decSepFmt substringFromIndex:idx];
+                
+            [newString appendString:nkNumStr];
+            [newString appendString:fmtValue];
+        }
+        else if (padLen == 0) {
+            /* perfect match */
+            [newString appendString:nkNumStr];
+        }
+        else {
+            /* value string is longer than format .. */
+            NSString *value;
+                
+            value = [nkNumStr substringToIndex:[nkNumStr length]];
+            [newString appendString:value];
+        }
+    }
+    
+    /* add format suffix */
+    [newString appendString:_suffix(self, format)];
+    
+    return newString;
+}
+
+
+- (BOOL)getObjectValue:(id *)obj forString:(NSString *)string
+  errorDescription:(NSString **)error
+{
+    NSString *num = nil;
+    BOOL     status;
+    
+    NSAssert(self->thousandSeparator != self->decimalSeparator,
+             @"decimal and thousand separators are equal !");
+    
+    if (digitsForString(self, &num, string)) {
+        status = YES;
+        if (obj)   *obj   = [NSNumber numberWithDouble:[num doubleValue]];
+        if (error) *error = @"";
+    }
+    else {
+        status = NO;
+        if (obj)   *obj   = [NSNumber numberWithDouble:[num doubleValue]];
+        if (error) *error = @"wrong chars in number (only digits and sep's) !";
+    }
+
+    if (!checkMinMaxForNumber(self, *obj)) {
+        status = NO;
+        if (obj)   *obj   = nil;
+        if (error) *error = @"number isn't in range of min and max! ";
+    }
+    return status;
+} 
+
+- (BOOL)isPartialStringValid:(NSString *)partialString
+  newEditingString:(NSString **)newString
+  errorDescription:(NSString **)error
+{
+    NSString *str     = nil;
+    NSNumber *num     = nil;
+    BOOL     status;
+
+    *error = @"";
+
+    //TODO: modify *newString (maybe it's not necessary)
+    if (digitsForString(self, &str, partialString)) {
+        status = YES;
+    }
+    else {
+        status  = NO;
+        if (error) *error = @"wrong chars in number (only digits and sep's) !";
+        if (newString) *newString = str;
+    }
+    
+    num = [NSNumber numberWithDouble:[str doubleValue]];
+    if (!checkMinMaxForNumber(self, num)) {
+        status  = NO;
+        num     = nil;
+        if (error) *error = @"number isn't in range of min and max! ";
+    }
+    return YES;
+}
+
+
+// Private Methods
+
+static void _checkFormat(NSNumberFormatter *self, NSString *_format)
+{
+    char *format     = NULL;
+    BOOL digitStatus = NO;
+    int  decSepCount = 0; 
+    int  i           = 0;
+    
+    if ([_format length] == 0)
+        return;
+    
+    format = MallocAtomic([_format cStringLength] + 1);
+    [_format getCString:format];
+    
+    while (format[i] != '\0') {
+        if (format[i] == self->decimalSeparator) {
+            digitStatus = NO;
+            decSepCount++;         
+        }
+        if (index("0123456789_", format[i]) != NULL)
+            digitStatus = YES;                    
+        
+        i++;
+    }
+    lfFree(format); format = NULL;
+    
+    NSCAssert1(decSepCount <= 1,
+               @"Too many decimal separators in format '%@' !",
+               _format);
+    NSCAssert1(digitStatus,
+               @"format should be x or x.x (x is a digit or \'_\'): '%@' !",
+               _format);
+}
+
+static unichar separatorFromString(NSString *_string)
+{
+   unichar theChar;
+
+   if (_string == nil)        return 0;
+   if ([_string length] == 0) return 0;
+   
+   if ([_string length] > 1)
+       NSLog(@"WARNING: separator greater than 1 !");
+   theChar = [_string characterAtIndex:0];
+
+   NSCAssert(theChar < 256,
+             @"unicode larger than 255, not supported (only 8-bit !)");
+   NSCAssert(index("$0123456789#_", theChar) == NULL,
+             @"invalid decimal separator char !");
+
+   return theChar;
+}
+
+static NSString *cleanFormat(NSNumberFormatter *self, NSString *_format)
+{
+    const char *format = [_format cString];
+    char *buffer = NULL;
+    int  i,j;
+
+    buffer = MallocAtomic([_format cStringLength] + 1);
+    
+    for (i = 0, j = 0; format[i] != '\0'; i++) {
+        register char c = format[i];
+        
+        if ((c != self->thousandSeparator) && (c != '#')) {
+            buffer[j] = format[i];
+            j++;
+        }
+    }
+    buffer[j] = '\0';
+    format = NULL;
+    
+    return [NSString stringWithCStringNoCopy:buffer freeWhenDone:YES];
+}
+
+
+static NSString *_prefix(NSNumberFormatter *self, NSString *_format)
+{
+    const char *format = [_format cString];
+    char *buffer = NULL;
+    int  i = 0;
+
+    buffer = MallocAtomic([_format cStringLength] + 1);
+
+    while ((index("0123456789_", format[i]) == NULL) && (format[i] != '\0') &&
+           (format[i] != self->decimalSeparator)) {
+        buffer[i] = format[i];
+        i++;
+    }
+    buffer[i] = '\0';
+    format = NULL;
+    
+    return [NSString stringWithCStringNoCopy:buffer freeWhenDone:YES];
+}
+
+static NSString *_suffix(NSNumberFormatter *self, NSString *_format)
+{
+    char *buffer = NULL;
+    char *format = NULL;
+    int  i,j;
+
+    format = MallocAtomic([_format cStringLength] +1);
+    buffer = MallocAtomic([_format cStringLength] +1);
+    [_format getCString:format];
+
+    i = [_format cStringLength] - 1;
+    j = 0;
+    while ((index("0123456789_", format[i]) == NULL) && (i>=0) &&
+           (format[i] !=self->decimalSeparator)) {
+        buffer[j] = format[i];
+        i--;
+        j++;
+    }
+    buffer[j] = '\0';
+    format[0] = '\0';
+
+    i = strlen(buffer) - 1;
+    j = 0;
+    while (i >= 0) {
+        format[j] = buffer[i];
+        j++;
+        i--;
+    }
+    format[j] = '\0';
+    lfFree(buffer); buffer = NULL;
+    
+    return [NSString stringWithCStringNoCopy:format freeWhenDone:YES];
+}
+
+static NSString *digitsToDot(NSString *_string)
+{
+    const char *string = [_string cString];
+    char *buffer = NULL;
+    int  i = 0;
+    int  j = 0;
+
+    buffer = MallocAtomic([_string cStringLength] +1);
+
+    while ((index("0123456789_", string[i]) == NULL) && (string[i] !='\0'))
+        i++;
+
+    while ((index("0123456789_", string[i]) != NULL) && (string[i] != '\0')) {
+        buffer[j] = (string[i] == '_') ? ' ' : string[i];
+        i++;
+        j++;
+    }
+    buffer[j] = '\0';
+    string = NULL;
+    return [NSString stringWithCStringNoCopy:buffer freeWhenDone:YES];
+}
+
+static NSString *digitsFromDot(NSString *_string, NSString *_sep)
+{
+    char *buffer = NULL;
+    char *string = NULL;
+    char sep[2];
+    int  i;
+    int  j;
+
+    if ([_string rangeOfString:_sep].length == 0)
+        // if there is no decimal separator then return @""
+        return @"";
+
+    NSCAssert([_sep length] < 2, @"separator to long (max 1 char)");
+    [_sep getCString:sep];
+    
+    i      = [_string cStringLength];
+    buffer = MallocAtomic(i + 1);
+    string = MallocAtomic(i + 1);
+    [_string getCString:string]; string[i] = '\0';
+    
+    i = strlen(string) - 1;
+    while ((index("0123456789_", string[i]) == NULL) && (i >= 0))
+        i--;
+    
+    j = 0;
+    while ((index(sep, string[i]) == NULL) && (i >= 0)) {
+        if (index("0123456789_", string[i]))
+            buffer[j] = (string[i] == '_') ? ' ' : string[i];
+        i--;
+        j++;
+    }
+    if ((index(sep, string[i]) == NULL) && (i == 0))
+        buffer[0] = '\0';
+    buffer[j] = '\0';
+
+    string[0] = '\0';
+
+    i = strlen(buffer) - 1;
+    j = 0;
+    while (i>=0) {
+        string[j] = buffer[i];
+        j++;
+        i--;
+    }
+    string[j] = '\0';
+    lfFree(buffer); buffer = NULL;
+
+    return [NSString stringWithCStringNoCopy:string freeWhenDone:YES];
+}
+
+static BOOL digitsForString(NSNumberFormatter *self,
+                            NSString **digitStr, NSString *_string)
+{
+    /* returns a string suitable for passing to atof() .. */
+    const char *string;
+    BOOL decStat = NO;
+    BOOL status  = YES;
+    char *buffer = NULL;
+    int  i       = 0;
+    int  j       = 0;
+    int  k       = 0;
+    
+    string = [_string cString];
+    buffer = MallocAtomic([_string cStringLength] +1);
+    
+    while ((index("0123456789", string[i]) == NULL) && (string[i] != '\0')) {
+        if (string[i] == '-') {
+            if (j == 0) {
+                buffer[j] = string[i];
+                j++;
+            }
+        }
+        i++;
+    }
+    while (string[i] !='\0') {
+        if (index("0123456789", string[i])) {
+            buffer[j] = string[i];
+            j++;
+        }
+        else if (string[i] == self->decimalSeparator) {
+            if (!decStat) {
+                decStat = YES;
+                if (j == 0) {
+                    buffer[j] = '0';
+                    j++;
+                }
+                buffer[j] = '.'; //string[i];
+                j++;
+            }
+            else break;
+        }
+        else if (string[i] == self->thousandSeparator) {
+        }
+        else
+            break;
+        i++;
+    }
+    for (k = strlen(string) - 1;
+         (index("0123456789_", string[k]) == NULL) && (k >= 0);
+         k--)
+        ;
+
+    for(; i < k; i++) {
+        status    = NO;
+        buffer[j] = string[i];
+        j++;
+    }
+    buffer[j] = '\0';
+    string = NULL;
+
+    *digitStr = [NSString stringWithCStringNoCopy:buffer freeWhenDone:YES];
+    buffer = NULL;
+
+    return status; 
+}
+
+static BOOL checkMinMaxForNumber(NSNumberFormatter *self, NSNumber *_number)
+{
+    if ((self->minimum) && ([_number compare:self->minimum] < 0))
+        return NO;
+
+    if ((self->maximum) && ([_number compare:self->maximum] > 0))
+        return NO;
+
+    return YES;
+}
+
+@end
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSObjCRuntime.h b/libFoundation/Foundation/NSObjCRuntime.h
new file mode 100644 (file)
index 0000000..a33c802
--- /dev/null
@@ -0,0 +1,45 @@
+/* 
+   NSObjCRuntime.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSObjCRuntime_h__
+#define __NSObjCRuntime_h__
+
+#include <Foundation/NSObject.h>
+
+@class NSString;
+
+/* Convert to and from a String */
+LF_EXPORT Class    NSClassFromString(NSString *aClassName);
+LF_EXPORT SEL      NSSelectorFromString(NSString *aSelectorName);
+LF_EXPORT NSString *NSStringFromClass(Class aClass);
+LF_EXPORT NSString *NSStringFromSelector(SEL aSelector);
+
+#endif /* __NSObjCRuntime_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSObjCRuntime.m b/libFoundation/Foundation/NSObjCRuntime.m
new file mode 100644 (file)
index 0000000..7be289e
--- /dev/null
@@ -0,0 +1,88 @@
+/* 
+   NSObjCRuntime.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+          Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSObjCRuntime.h>
+#include <Foundation/NSUtilities.h>
+
+#include <extensions/objc-runtime.h>
+
+/*
+ * Objective-C runtime info
+ */
+
+LF_DECLARE Class NSClassFromString(NSString *aClassName)
+{
+    unsigned len = [aClassName cStringLength];
+    char  *buf;
+    Class clazz;
+    if (len == 0) return NULL;
+    buf = malloc(len + 1);
+    [aClassName getCString:buf]; buf[len] = '\0';
+    clazz = objc_lookup_class(buf);
+    free(buf);
+    return clazz;
+}
+
+LF_DECLARE SEL NSSelectorFromString(NSString *aSelectorName)
+{
+    unsigned len = [aSelectorName cStringLength];
+    char *buf;
+    SEL  sel;
+    if (len == 0) return NULL;
+    buf = malloc(len + 1);
+    [aSelectorName getCString:buf]; buf[len] = '\0';
+    sel = sel_get_any_uid(buf);
+    free(buf);
+    return sel;
+}
+
+LF_DECLARE NSString *NSStringFromClass(Class aClass)
+{
+    return aClass ?
+       [NSString stringWithCStringNoCopy:(char*)class_get_class_name(aClass)
+           freeWhenDone:NO] : nil;
+}
+
+LF_DECLARE NSString *NSStringFromSelector(SEL aSelector)
+{
+    if (aSelector) {
+        return [NSString stringWithCStringNoCopy:(char*)sel_get_name(aSelector)
+                         freeWhenDone:NO];
+    }
+    else {
+        NSLog(@"WARNING: called %s with NULL-selector !", __PRETTY_FUNCTION__);
+        return nil;
+    }
+}
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSObject+PropLists.h b/libFoundation/Foundation/NSObject+PropLists.h
new file mode 100644 (file)
index 0000000..ca9df92
--- /dev/null
@@ -0,0 +1,44 @@
+/* 
+   NSObject+PropLists.h
+
+   Copyright (C) 1999, MDlink online service center GmbH, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSObject_PropLists_H__
+#define __NSObject_PropLists_H__
+
+#include "NSObject.h"
+
+@interface NSObject(PropertyListProtocol)
+
+- (NSString *)descriptionWithLocale:(NSDictionary *)_locale
+  indent:(unsigned int)_indent;
+- (NSString *)descriptionWithLocale:(NSDictionary *)_locale;
+- (NSString *)stringRepresentation;
+
+/* this method is called in property-list generation methods */
+
+- (NSString *)propertyListStringWithLocale:(NSDictionary *)_locale
+  indent:(unsigned int)_indent;
+
+@end
+
+#endif /* __NSObject_PropLists_H__ */
diff --git a/libFoundation/Foundation/NSObject.h.in b/libFoundation/Foundation/NSObject.h.in
new file mode 100644 (file)
index 0000000..42c4f8b
--- /dev/null
@@ -0,0 +1,258 @@
+/* 
+   NSObject.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSObject_h__
+#define __NSObject_h__
+
+#include <objc/objc.h>
+
+#if BUILD_libFoundation_DLL
+#  define LF_EXPORT  __declspec(dllexport)
+#  define LF_DECLARE __declspec(dllexport)
+#elif libFoundation_ISDLL
+#  define LF_EXPORT  extern __declspec(dllimport)
+#  define LF_DECLARE extern __declspec(dllimport)
+#else
+#  define LF_EXPORT  extern
+#  define LF_DECLARE 
+#endif
+
+#define LIB_FOUNDATION_LIBRARY 1
+
+#define LIB_FOUNDATION_MAJOR_VERSION    @MAJOR_VERSION@
+#define LIB_FOUNDATION_MINOR_VERSION    @MINOR_VERSION@
+#define LIB_FOUNDATION_SUBMINOR_VERSION @SUBMINOR_VERSION@
+
+#ifndef NSTimeInterval__defined
+#define NSTimeInterval__defined
+typedef double NSTimeInterval;
+#endif
+
+@class Protocol;
+@class NSZone;
+@class NSString;
+@class NSCoder;
+@class NSArchiver;
+@class NSMethodSignature;
+@class NSInvocation;
+
+/*
+ * NSObject protocol
+ */
+
+@protocol NSObject
+
+/* Identifying Class and Superclass */
+- (Class)class;
+- (Class)superclass;
+
+/* Determining Allocation Zones */
+- (NSZone*)zone;
+
+/* Identifying Proxies */
+- (BOOL)isProxy;
+
+/* Testing Inheritance Relationships */
+- (BOOL)isKindOfClass:(Class)aClass;
+- (BOOL)isMemberOfClass:(Class)aClass;
+
+/* Testing for Protocol Conformance */
+- (BOOL)conformsToProtocol:(Protocol*)aProtocol;
+
+/* Testing Class Functionality */
+- (BOOL)respondsToSelector:(SEL)aSelector;
+
+/* Managing Reference Counts */
+- (id)autorelease;
+- (oneway void)release;
+- (id)retain;
+- (unsigned int)retainCount;
+
+/* Identifying and Comparing Instances */
+- (unsigned)hash;
+- (BOOL)isEqual:(id)anObject;
+- (id)self;
+
+/* Sending Messages Determined at Run Time */
+- (id)performSelector:(SEL)aSelector;
+- (id)performSelector:(SEL)aSelector withObject:(id)anObject;
+- (id)performSelector:(SEL)aSelector withObject:(id)anObject
+  withObject:(id)anotherObject;
+
+/* Describing the Object */
+- (NSString*)description;
+
+@end /* NSObject */
+
+/* 
+ * Copying Objects (deep immutable copy)
+ */
+
+@protocol NSCopying
+- (id)copyWithZone:(NSZone*)zone;
+@end /* NSCopying */
+
+/* 
+ * Copying Objects (shallow mutable copy)
+ */
+
+@protocol NSMutableCopying
+- (id)mutableCopyWithZone:(NSZone*)zone;
+@end /* NSCopying */
+
+/* 
+ * Coding/Decoding Objects through NSCoder
+ */
+
+@protocol NSCoding
+- (void)encodeWithCoder:(NSCoder*)aCoder;
+- (id)initWithCoder:(NSCoder*)aDecoder;
+@end /* NSCoding */
+
+/*
+ * NSObject Class - base class for OpenStep Hierarchy
+ */
+
+@interface NSObject <NSObject>
+{
+    Class isa;
+}
+
+/* Initializing the Class */
++ (void)initialize;
+
+/* Creating and Destroying Instances */
++ (id)alloc;
++ (id)allocWithZone:(NSZone*)zone;
++ (id)new;
+- (void)dealloc;
+- (id)init;
+
+/* Testing Class Functionality */
++ (BOOL)instancesRespondToSelector:(SEL)aSelector;
+
+/* Testing Protocol Conformance */
++ (BOOL)conformsToProtocol:(Protocol*)aProtocol;
+
+/* Obtaining Method Information */
++ (IMP)instanceMethodForSelector:(SEL)aSelector;
+- (IMP)methodForSelector:(SEL)aSelector;
++ (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector;
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;
+
+/* Posing */
++ (void)poseAsClass:(Class)aClass;
+
+/* Error Handling */
+- (void)doesNotRecognizeSelector:(SEL)aSelector;
+
+/* Sending Deferred Messages */
++ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget
+       selector:(SEL)aSelector
+       object:(id)anObject;
+- (void)performSelector:(SEL)aSelector
+       withObject:(id)anObject
+       afterDelay:(NSTimeInterval)delay;
+
+/* Forwarding Messages */
+- (void)forwardInvocation:(NSInvocation*)anInvocation;
+
+/* Archiving */
+- (id)awakeAfterUsingCoder:(NSCoder*)aDecoder;
+- (Class)classForArchiver;
+- (Class)classForCoder;
+- (id)replacementObjectForArchiver:(NSArchiver*)anArchiver;
+- (id)replacementObjectForCoder:(NSCoder*)anEncoder;
++ (void)setVersion:(int)version;
++ (int)version;
+
+/* NSCopying/NSMutableCopying shortcuts */
+- (id)copy;
+- (id)mutableCopy;
+
+/* Obtaining a string representation */
+- (NSString*)stringRepresentation;
+
+@end /* NSObject */
+
+@interface NSObject (GNU)
+- (Class)transmuteClassTo:(Class)aClassObject;
+- subclassResponsibility:(SEL)aSel;
+- shouldNotImplement:(SEL)aSel;
+- notImplemented:(SEL)aSel;
+@end
+
+typedef enum _NSComparisonResult {
+    NSOrderedAscending = -1,
+    NSOrderedSame = 0,
+    NSOrderedDescending = 1
+} NSComparisonResult;
+
+enum {NSNotFound = 0x7fffffff};
+
+
+/* The following makes sense only when libFoundation is compiled to work with
+   Boehm's garbage collector. */
+
+/* An object can clean up the resources it's using right before it ends the
+   life. You should implement -gcFinalize in all the classes whose instances
+   can hold limited resources like file descriptors. NSObject does not
+   implement this method so there is no default implementation of it.
+
+   Other objects can observe an object's end of life by registering as
+   observers of that object. See the GarbageCollector class for more
+   information about this. */
+
+@protocol GCFinalization
+- (void)gcFinalize;
+@end
+
+@interface NSObject(BoehmTypedMemory)
++ (BOOL)requiresTypedMemory;
+@end
+
+/* This variable identifies how the library was compiled and how the
+   program will run. You can compile the library with support for
+   Boehm's garbage collector or not. If the library is compiled with
+   Boehm's GC the program runs using the automatic garbage collection
+   mechanis, otherwise it uses the normal retain/release mechanism. */
+
+extern BOOL _usesBoehmGC;      /* YES if the program is running using the
+                                  Boehm's garbage collector */
+
+#include <lfmemory.h>
+
+#endif /* __NSObject_h__ */
+
+#include <Foundation/NSZone.h>
+#include <Foundation/NSObjCRuntime.h>
+#include <Foundation/NSUtilities.h>
+
+/*
+  Local Variables:
+  mode: ObjC
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSObject.m b/libFoundation/Foundation/NSObject.m
new file mode 100644 (file)
index 0000000..568bad4
--- /dev/null
@@ -0,0 +1,1060 @@
+/* 
+   NSObject.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <config.h>
+#include <stdio.h>
+
+#include <Foundation/common.h>
+#include <Foundation/NSObject.h>
+#include <Foundation/NSZone.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSMethodSignature.h>
+#include <Foundation/NSInvocation.h>
+#include <Foundation/NSRunLoop.h>
+#include <Foundation/NSTimer.h>
+#include <Foundation/NSLock.h>
+#include <Foundation/NSValue.h>
+#include <extensions/objc-runtime.h>
+#include <Foundation/exceptions/FoundationExceptions.h>
+
+#include "exceptions/FoundationExceptions.h"
+#include "NSFrameInvocation.h"
+#include "NSObject+PropLists.h"
+
+/* this one is quite experimental, it avoids calls to NSZoneFromObject */
+#define DO_NOT_USE_ZONE 1
+
+extern NSRecursiveLock* libFoundationLock;
+
+@interface _NSObjectDelayedExecutionHolder : NSObject
+{
+    id target;
+    id argument;
+    SEL selector;
+}
++ holderForTarget:(id)target argument:(id)argument selector:(SEL)action;
+- (BOOL)isEqual:anotherHolder;
+- (void)execute;
+@end
+
+
+@implementation _NSObjectDelayedExecutionHolder
+
++ (id)holderForTarget:(id)_target argument:(id)_argument selector:(SEL)action
+{
+    _NSObjectDelayedExecutionHolder* holder = AUTORELEASE([self alloc]);
+
+    holder->target   = RETAIN(_target);
+    holder->argument = RETAIN(_argument);
+    holder->selector = action;
+    return holder;
+}
+
+- (unsigned)hash
+{
+  return [(NSObject *)self->target hash];
+}
+
+- (BOOL)isEqual:(_NSObjectDelayedExecutionHolder*)anotherHolder
+{
+    return [(NSObject *)self->target isEqual:anotherHolder->target]
+           && [(NSObject *)self->argument isEqual:anotherHolder->argument]
+           && SEL_EQ(self->selector, anotherHolder->selector);
+}
+
+- (void)execute
+{
+    [self->target performSelector:selector withObject:argument];
+}
+
+@end /* _NSObjectDelayedExecutionHolder */
+
+Class lfNSZoneClass = Nil; /* cache NSZone class */
+
+@implementation NSObject
+
+static BOOL 
+objc_runtime_exception(id object, int code, const char* fmt, va_list ap)
+{
+    [[[ObjcRuntimeException alloc] initWithFormat:
+                   @"Objective-C runtime error: %@",
+                   Avsprintf([NSString stringWithCString:fmt], ap)] raise];
+    return NO;
+}
+
+/* Class variables */
+static NSMutableDictionary* delayedExecutions = nil;
+       /* dictionary of _NSObjectDelayedExecutionHolder -> timer */
+
+/* Initializing the Class */
+
++ (void)initialize
+{
+    static BOOL initialized = NO;
+    
+    if(!initialized) {
+       initialized = YES;
+       lfNSZoneClass = [NSZone class];
+#if GNU_RUNTIME
+        objc_msg_lookup([NSZone class], @selector(initialize))
+            ([NSZone class], @selector(initialize));
+#else
+       [NSZone performSelector:@selector(initialize)];
+#endif
+       objc_set_error_handler(objc_runtime_exception);
+       delayedExecutions = [NSMutableDictionary new];
+    }
+}
+
+/* Creating and Destroying Instances */
+
+#if LIB_FOUNDATION_BOEHM_GC
+
++ (BOOL)requiresTypedMemory
+{
+    return NO;
+}
+
+#endif
+
++ (id)alloc
+{
+    return [self allocWithZone:NULL];
+}
+
++ (id)allocWithZone:(NSZone*)zone
+{
+    return NSAllocateObject(self, 0, zone);
+}
+
++ (id)new
+{
+    return [[self alloc] init];
+}
+
+#if LIB_FOUNDATION_BOEHM_GC
+- (void)gcFinalize
+{
+#if 1
+    fprintf(stderr, "finalize 0x%08X<%s>\n",
+            self,
+            ((*(Class *)self != NULL) ? (*(Class *)self)->name : "NULL"));
+    fflush(stderr);
+#endif
+}
+#endif
+
+- (void)dealloc
+{
+#if !LIB_FOUNDATION_BOEHM_GC
+    NSDeallocateObject(self);
+#endif
+}
+
++ (void)dealloc
+{
+}
+
+- (id)init
+{
+    return self;
+}
+
+/* Testing Class Functionality */
+
++ (BOOL)instancesRespondToSelector:(SEL)aSelector
+{
+    return aSelector
+               ? class_get_instance_method(self, aSelector) != METHOD_NULL
+               : NO;
+}
+
+/* Testing Protocol Conformance */
+
++ (BOOL)conformsToProtocol:(Protocol*)aProtocol
+{
+    int i;
+    struct objc_protocol_list *protos;
+
+    for(protos = ((struct objc_class*)self)->protocols;
+           protos; protos = protos->next) {
+       for(i = 0; i < protos->count; i++)
+           if([protos->list[i] conformsTo:aProtocol])
+               return YES;
+    }
+
+    if([self superclass])
+       return [[self superclass] conformsToProtocol: aProtocol];
+    else return NO;
+}
+
+- (BOOL)conformsToProtocol:(Protocol*)aProtocol
+{
+    int i;
+    struct objc_protocol_list *protos;
+
+    for(protos = ((struct objc_class*)self)->class_pointer->protocols;
+           protos; protos = protos->next) {
+       for(i = 0; i < protos->count; i++)
+           if([protos->list[i] conformsTo:aProtocol])
+               return YES;
+    }
+
+    if([self superclass])
+       return [[self superclass] conformsToProtocol: aProtocol];
+    else return NO;
+}
+
+/* Identifying Class and Superclass */
+
+- (Class)class
+{
+    return object_get_class(self);
+}
+
+- (Class)superclass
+{
+    return object_get_super_class(self);
+}
+
+/* Testing Class Functionality */
+
+- (BOOL)respondsToSelector: (SEL)aSelector
+{
+    if (aSelector == NULL)
+       return NO;
+    
+    return (object_is_instance(self)
+            ? (class_get_instance_method(self->isa, aSelector) != METHOD_NULL)
+            : (class_get_class_method(self->isa, aSelector)    != METHOD_NULL));
+}
+
+/* Managing Reference Counts */
+
+- (id)autorelease
+{
+#if !LIB_FOUNDATION_BOEHM_GC
+    extern void NSAutoreleasePool_AutoreleaseObject(id aObject);
+    NSAutoreleasePool_AutoreleaseObject(self);
+#endif
+    return self;
+}
+
++ (id)autorelease
+{
+    return self;
+}
+
+- (oneway void)release
+{
+#if !LIB_FOUNDATION_BOEHM_GC
+    extern BOOL __autoreleaseEnableCheck;
+    // check if retainCount is Ok
+    if (__autoreleaseEnableCheck) {
+       unsigned int toCome = [NSAutoreleasePool autoreleaseCountForObject:self];
+       if (toCome+1 > [self retainCount]) {
+           NSLog(@"Release[%p<%@>] release check for object %@ "
+                  @"has %d references "
+                 @"and %d pending calls to release in autorelease pools\n", 
+                 self, NSStringFromClass([self class]),
+                  self,
+                  [self retainCount], toCome);
+           return;
+       }
+    }
+    if (NSExtraRefCount(self) == 1)
+       [self dealloc];
+    else
+       NSDecrementExtraRefCountWasZero(self);
+#endif
+}
+
++ (oneway void)release
+{
+}
+
+- (id)retain
+{
+#if !LIB_FOUNDATION_BOEHM_GC
+    NSIncrementExtraRefCount(self);
+#endif
+    return self;
+}
+
++ (id)retain
+{
+    return self;
+}
+
+- (unsigned int)retainCount
+{
+    return NSExtraRefCount(self);
+}
+
++ (unsigned int)retainCount
+{
+    return (unsigned)-1;
+}
+
+/* Obtaining Method Information */
+
++ (IMP)instanceMethodForSelector:(SEL)aSelector
+{
+    if (!aSelector)
+       return NULL;
+
+    return aSelector
+               ? method_get_imp(class_get_instance_method(self, aSelector))
+               : NULL;
+}
+
+- (IMP)methodForSelector:(SEL)aSelector
+{
+    if (aSelector == NULL)
+       return NULL;
+
+    return method_get_imp(object_is_instance(self)
+                          ? class_get_instance_method(self->isa, aSelector)
+                         : class_get_class_method(self->isa, aSelector));
+}
+
++ (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector
+{
+    struct objc_method* mth;
+
+    if (!aSelector)
+       return nil;
+
+    mth = class_get_instance_method(self, aSelector);
+    return mth ? [NSMethodSignature signatureWithObjCTypes:mth->method_types]
+               : nil;
+}
+
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
+{
+    register const char *types = NULL;
+
+    if (aSelector == NULL) // invalid selector
+       return nil;
+
+#if GNU_RUNTIME && 0
+    // GNU runtime selectors may be typed, a lookup may not be necessary
+    types = aSelector->sel_types;
+#endif
+    if (types == NULL) {
+        // lookup method for selector
+        struct objc_method *mth;
+        mth = (object_is_instance(self) ?
+               class_get_instance_method(self->isa, aSelector)
+               : class_get_class_method(self->isa, aSelector));
+        if (mth) types = mth->method_types;
+    }
+#if GNU_RUNTIME
+    // GNU runtime selectors may be typed, a lookup may not be necessary
+    if (types == NULL)
+        types = aSelector->sel_types;
+#endif
+    if (types == NULL) {
+        /* construct a id-signature */
+        register const char *sel;
+        if ((sel = sel_get_name(aSelector))) {
+            register int colCount = 0;
+            static char *idSigs[] = {
+                "@@:", "@@:@", "@@:@@", "@@:@@@", "@@:@@@@", "@@:@@@@@",
+                "@@:@@@@@@", "@@:@@@@@@", "@@:@@@@@@@", "@@:@@@@@@@@"
+            };
+            
+            while (*sel) {
+                if (*sel == ':')
+                    colCount++;
+                sel++;
+            }
+            types = idSigs[colCount];
+        }
+        else
+            return nil;
+    }
+
+    //    NSLog(@"types: %s", types);
+    return [NSMethodSignature signatureWithObjCTypes:types];
+}
+
+/* property lists */
+
+- (NSString *)propertyListStringWithLocale:(NSDictionary *)_locale
+  indent:(unsigned int)_indent
+{
+    if ([self respondsToSelector:@selector(descriptionWithLocale:indent:)])
+        return [self descriptionWithLocale:_locale indent:_indent];
+    if ([self respondsToSelector:@selector(descriptionWithLocale:)])
+        return [self descriptionWithLocale:_locale];
+    if ([self respondsToSelector:@selector(stringRepresentation)])
+        return [self stringRepresentation];
+    
+    return [self description];
+}
+
+/* Describing the Object */
+
+- (NSString*)description
+{
+    /* Don't use -[NSString stringWithFormat:] method because it can cause
+       infinite recursion. */
+    char buffer[512];
+
+    sprintf (buffer, "<%s %p>", (char*)object_get_class_name(self), self);
+    return [NSString stringWithCString:buffer];
+}
+
++ (NSString*)description
+{
+    /* Don't use -[NSString stringWithFormat:] method because it can cause
+       infinite recursion. */
+    char buffer[512];
+
+    sprintf (buffer, "<class %s>", (char*)object_get_class_name(self));
+    return [NSString stringWithCString:buffer];
+}
+
+/* Obtaining a string representation */
+
+- (NSString*)stringRepresentation
+{
+    return [self description];
+}
+
++ (void)poseAsClass:(Class)aClass
+{
+    class_pose_as(self, aClass);
+}
+
+/* Error Handling */
+
+- (void)doesNotRecognizeSelector:(SEL)aSelector
+{
+    /* Don't use initWithFormat: here because it can cause infinite
+       recursion. */
+    char buffer[512];
+
+    sprintf (buffer, "%s (%s) does not recognize %s",
+             object_get_class_name(self),
+             CLS_ISCLASS(isa) ? "instance" : "class",
+             aSelector ? sel_get_name(aSelector) : "\"null selector\"");
+    [[[ObjcRuntimeException alloc]
+             setReason:[NSString stringWithCString:buffer]] raise];
+}
+
+/* Sending Deferred Messages */
+
++ (void)cancelPreviousPerformRequestsWithTarget:(id)target
+  selector:(SEL)aSelector
+  object:(id)anObject
+{
+    id holder = [_NSObjectDelayedExecutionHolder holderForTarget:target
+                                                 argument:anObject
+                                                 selector:aSelector];
+
+    [libFoundationLock lock];
+    [delayedExecutions removeObjectForKey:holder];
+    [libFoundationLock unlock];
+}
+
+- (void)performSelector:(SEL)aSelector
+  withObject:(id)anObject
+  afterDelay:(NSTimeInterval)delay
+{
+    NSTimer* timer;
+    _NSObjectDelayedExecutionHolder* holder;
+    
+    if (delay == 0.0) {
+        /* hh: is this correct ??? (double as bool, immediate exec) */
+       [self performSelector:aSelector withObject:anObject];
+       return;
+    }
+
+    holder = [_NSObjectDelayedExecutionHolder holderForTarget:self
+                                             argument:anObject
+                                             selector:aSelector];
+    timer = [NSTimer timerWithTimeInterval:delay
+                     target:self
+                     selector:@selector(_performDelayedExecution:)
+                     userInfo:holder
+                     repeats:NO];
+
+    [libFoundationLock lock];
+    [delayedExecutions setObject:timer forKey:holder];
+    [libFoundationLock unlock];
+
+    [[NSRunLoop currentRunLoop]
+       addTimer:timer forMode:NSDefaultRunLoopMode];
+}
+
+- (void)_performDelayedExecution:(NSTimer*)timer
+{
+  id holder = [timer userInfo];
+
+  [holder execute];
+}
+
+/* Forwarding Messages */
+
+- (void)forwardInvocation:(NSInvocation*)anInvocation
+{
+    return [self doesNotRecognizeSelector:[anInvocation selector]];
+}
+
+/* Archiving */
+
+- (id)awakeAfterUsingCoder:(NSCoder*)aDecoder
+{
+    return self;
+}
+
+- (Class)classForArchiver
+{
+    return [self classForCoder];
+}
+
+- (Class)classForCoder
+{
+    return [self class];
+}
+
+- (id)replacementObjectForArchiver:(NSArchiver*)anArchiver
+{
+    return [self replacementObjectForCoder:(NSCoder*)anArchiver];
+}
+
+- (id)replacementObjectForCoder:(NSCoder*)anEncoder
+{
+    return self;
+}
+
++ (void)setVersion:(int)version
+{
+    class_set_version(self, version);
+}
+
++ (int)version
+{
+    return class_get_version(self);
+}
+
+- (unsigned)hash
+{
+    return (unsigned)(unsigned long)self;
+}
+
+/* Identifying and Comparing Instances */
+
+- (BOOL)isEqual:(id)anObject
+{
+    return self == anObject;
+}
+
+- (id)self
+{
+    return self;
+}
+
+/* Determining Allocation Zones */
+
+- (NSZone *)zone
+{
+#if DO_NOT_USE_ZONE
+    return NULL;
+#else
+    return NSZoneFromObject(self);
+#endif
+}
+
+/* Sending Messages Determined at Run Time */
+
+- (id)performSelector:(SEL)aSelector
+{
+    IMP msg = aSelector ? objc_msg_lookup(self, aSelector) : NULL;
+
+    if(msg == NULL) {
+       [[[ObjcRuntimeException alloc] initWithFormat:
+           @"invalid selector `%s' passed to %s",
+           sel_get_name(aSelector), sel_get_name(_cmd)] raise];
+    }
+    return (*msg)(self, aSelector);
+}
+
+- (id)performSelector:(SEL)aSelector withObject:(id)anObject
+{
+    struct objc_method  *mth;
+    const unsigned char *argType;
+
+    if (aSelector == NULL) {
+       [[[ObjcRuntimeException alloc]
+           initWithFormat:@"invalid selector `%s' passed to %s",
+           sel_get_name(aSelector), sel_get_name(_cmd)] raise];
+    }
+    
+    *(&mth) = object_is_instance(self)
+        ? class_get_instance_method([self class], aSelector)
+        : class_get_class_method([self class], aSelector);
+    
+    if (mth == NULL) {
+        NSMethodSignature *signature;
+        NSInvocation      *invocation;
+        const char        *retType, *argType;
+        int          i;
+        unsigned int ui;
+
+        NSAssert1(mth == NULL, @"where does the method come from (sel=%@) ???",
+                  NSStringFromSelector(aSelector));
+        
+        if ((signature = [self methodSignatureForSelector:aSelector]) == nil)
+            [self doesNotRecognizeSelector:aSelector];
+
+        argType    = [signature getArgumentTypeAtIndex:2];
+        retType    = [signature methodReturnType];
+        invocation = [NSInvocation invocationWithMethodSignature:signature];
+        [invocation setTarget:self]; 
+        [invocation setSelector:aSelector];
+        
+        switch (*argType) {
+            case _C_ID:
+            case _C_CLASS:
+                [invocation setArgument:&anObject atIndex:2];
+                break;
+                
+            case _C_INT: {
+                i = [anObject intValue];
+                [invocation setArgument:&i atIndex:2];
+                break;
+            }
+            case _C_UINT: {
+                ui = [anObject unsignedIntValue];
+                [invocation setArgument:&ui atIndex:2];
+                break;
+            }
+
+            case '\0':
+                /* no method argument specified ! */
+                break;
+            
+            default:
+                [NSException raise:@"UnsupportedType"
+                             format:@"unsupported argument type '%s' !",argType];
+        }
+
+        [invocation invoke];
+        
+        switch (*retType) {
+            case _C_VOID:
+                return self;
+                
+            case _C_CLASS:
+            case _C_ID: {
+                [invocation getReturnValue:&anObject];
+                return anObject;
+            }
+
+            case _C_CHR: {
+                char c;
+                [invocation getReturnValue:&c];
+                return [NSNumber numberWithChar:c];
+            }
+            case _C_UCHR: {
+                unsigned char c;
+                [invocation getReturnValue:&c];
+                return [NSNumber numberWithUnsignedChar:c];
+            }
+            case _C_INT: {
+                int i;
+                [invocation getReturnValue:&i];
+                return [NSNumber numberWithInt:i];
+            }
+            case _C_UINT: {
+                unsigned int i;
+                [invocation getReturnValue:&i];
+                return [NSNumber numberWithUnsignedInt:i];
+            }
+            
+            default:
+                [NSException raise:@"UnsupportedType"
+                             format:@"unsupported return type '%s' !",retType];
+        }
+    }
+    
+    argType = mth->method_types;
+    if (*argType == _C_VOID) {
+        const char *astype;
+        
+        argType = objc_skip_argspec(argType); /* skip return */
+        argType = objc_skip_argspec(argType); /* skip self   */
+        argType = objc_skip_argspec(argType); /* skip _cmd   */
+        astype  = objc_skip_type_qualifiers(argType);
+
+        switch (*astype) {
+            case _C_ID: {
+                void (*f)(id, SEL, id);
+                f = (void*)mth->method_imp;
+                
+                (*f)(self, aSelector, anObject);
+                return self;
+            }
+            case _C_CHR:
+                ((void (*)(id, SEL, char))mth->method_imp)
+                    (self, aSelector, [anObject charValue]);
+                return self;
+            case _C_UCHR:
+                ((void (*)(id, SEL, unsigned char))mth->method_imp)
+                    (self, aSelector, [anObject unsignedCharValue]);
+                return self;
+            case _C_SHT:
+                ((void (*)(id, SEL, short))mth->method_imp)
+                    (self, aSelector, [anObject shortValue]);
+                return self;
+            case _C_USHT:
+                ((void (*)(id, SEL, unsigned short))mth->method_imp)
+                    (self, aSelector, [anObject unsignedShortValue]);
+                return self;
+            case _C_INT:
+                ((void (*)(id, SEL, int))mth->method_imp)
+                    (self, aSelector, [anObject intValue]);
+                return self;
+            case _C_UINT:
+                ((void (*)(id, SEL, unsigned int))mth->method_imp)
+                    (self, aSelector, [anObject unsignedIntValue]);
+                return self;
+            case _C_LNG:
+                ((void (*)(id, SEL, long))mth->method_imp)
+                    (self, aSelector, [anObject longValue]);
+                return self;
+            case _C_ULNG:
+                ((void (*)(id, SEL, unsigned long))mth->method_imp)
+                    (self, aSelector, [anObject unsignedLongValue]);
+                return self;
+            case _C_FLT:
+                ((void (*)(id, SEL, float))mth->method_imp)
+                    (self, aSelector, [anObject floatValue]);
+                return self;
+            case _C_DBL:
+                ((void (*)(id, SEL, double))mth->method_imp)
+                    (self, aSelector, [anObject doubleValue]);
+        
+                return self;
+            case '\0':
+                /* no further argument */
+                ((void (*)(id, SEL))mth->method_imp)(self, aSelector);
+                return self;
+        
+            default:
+                [NSException raise:@"UnsupportedType"
+                             format:
+                               @"unsupported argument type '%s' !", argType];
+                return nil;
+        }
+    }
+    else {
+        const char *astype, *rettype;
+
+        rettype = argType;
+        argType = objc_skip_argspec(argType); /* skip return */
+        argType = objc_skip_argspec(argType); /* skip self   */
+        argType = objc_skip_argspec(argType); /* skip _cmd   */
+        astype  = objc_skip_type_qualifiers(argType);
+
+        switch (*astype) {
+            case _C_ID:
+                return mth->method_imp(self, aSelector, anObject);
+            case _C_CHR:
+                return ((id (*)(id, SEL, char))mth->method_imp)
+                    (self, aSelector, [anObject charValue]);
+            case _C_UCHR:
+                return ((id (*)(id, SEL, unsigned char))mth->method_imp)
+                    (self, aSelector, [anObject unsignedCharValue]);
+            case _C_SHT:
+                return ((id (*)(id, SEL, short))mth->method_imp)
+                    (self, aSelector, [anObject shortValue]);
+            case _C_USHT:
+                return ((id (*)(id, SEL, unsigned short))mth->method_imp)
+                    (self, aSelector, [anObject unsignedShortValue]);
+            case _C_INT:
+                return ((id (*)(id, SEL, int))mth->method_imp)
+                    (self, aSelector, [anObject intValue]);
+            case _C_UINT:
+                return ((id (*)(id, SEL, unsigned int))mth->method_imp)
+                    (self, aSelector, [anObject unsignedIntValue]);
+            case _C_LNG:
+                return ((id (*)(id, SEL, long))mth->method_imp)
+                    (self, aSelector, [anObject longValue]);
+            case _C_ULNG:
+                return ((id (*)(id, SEL, unsigned long))mth->method_imp)
+                    (self, aSelector, [anObject unsignedLongValue]);
+            case _C_FLT:
+                return ((id (*)(id, SEL, float))mth->method_imp)
+                    (self, aSelector, [anObject floatValue]);
+            case _C_DBL:
+                return ((id (*)(id, SEL, double))mth->method_imp)
+                    (self, aSelector, [anObject doubleValue]);
+        
+            case '\0':
+                /* no further argument */
+                return ((id (*)(id, SEL))mth->method_imp)(self, aSelector);
+        
+            default:
+                [NSException raise:@"UnsupportedType"
+                             format:
+                               @"unsupported argument type '%s' !", argType];
+                return nil;
+        }
+    }
+}
+
+- (id)performSelector:(SEL)aSelector
+  withObject:(id)anObject
+  withObject:(id)anotherObject
+{
+    IMP msg = aSelector ? objc_msg_lookup(self, aSelector) : NULL;
+
+    if(!msg) {
+       [[[ObjcRuntimeException alloc]
+           initWithFormat:@"invalid selector `%s' passed to %s",
+           sel_get_name(aSelector), sel_get_name(_cmd)] raise];
+    }
+    return (*msg)(self, aSelector, anObject, anotherObject);
+}
+
+- (id)perform:(SEL)aSelector
+{
+    IMP msg = aSelector ? objc_msg_lookup(self, aSelector) : NULL;
+
+    if(!msg) {
+       [[[ObjcRuntimeException alloc] initWithFormat:
+           @"invalid selector `%s' passed to %s",
+           sel_get_name(aSelector), sel_get_name(_cmd)] raise];
+    }
+    return (*msg)(self, aSelector);
+}
+
+- (id)perform:(SEL)aSelector withObject:(id)anObject
+{
+    IMP msg = aSelector ? objc_msg_lookup(self, aSelector) : NULL;
+
+    if(msg == NULL) {
+       [[[ObjcRuntimeException alloc]
+           initWithFormat:@"invalid selector `%s' passed to %s",
+           sel_get_name(aSelector), sel_get_name(_cmd)] raise];
+    }
+    return (*msg)(self, aSelector, anObject);
+}
+
+- (id)perform:(SEL)aSelector
+  withObject:(id)anObject
+  withObject:(id)anotherObject
+{
+    IMP msg = aSelector ? objc_msg_lookup(self, aSelector) : NULL;
+
+    if(msg == NULL) {
+       [[[ObjcRuntimeException alloc]
+           initWithFormat:@"invalid selector `%s' passed to %s",
+           sel_get_name(aSelector), sel_get_name(_cmd)] raise];
+    }
+    return (*msg)(self, aSelector, anObject, anotherObject);
+}
+
+/* Identifying Proxies */
+
+- (BOOL)isProxy
+{
+    return NO;
+}
+
+/* Testing Inheritance Relationships */
+
++ (BOOL)isKindOfClass:(Class)aClass
+{
+    Class class;
+    
+    for (class = self; class != Nil; class = class_get_super_class(class))
+       if(class == aClass)
+           return YES;
+    return NO;
+}
+- (BOOL)isKindOfClass:(Class)aClass
+{
+    Class class;
+
+    for(class = self->isa; class != Nil; class = class_get_super_class(class))
+       if(class == aClass)
+           return YES;
+    return NO;
+}
+
+- (BOOL)isMemberOfClass:(Class)aClass
+{
+    return self->isa == aClass;
+}
+
+/* NSCopying/NSMutableCopying shortcuts */
+
+- (id)copy
+{
+    return [(id<NSCopying>)self copyWithZone:NULL];
+}
+
+- (id)mutableCopy
+{
+    return [(id<NSMutableCopying>)self mutableCopyWithZone:NULL];
+}
+
+#if 0
+- (void)gcFinalize
+{
+    fprintf (stderr, "%u (%s) will finalize\n", self, self->isa->name);
+}
+#endif
+
+@end /* NSObject */
+
+
+@implementation NSObject (GNU)
+
+- (Class)transmuteClassTo:(Class)aClassObject
+{
+    if(object_is_instance(self) && class_is_class(aClassObject)
+               && (class_get_instance_size(aClassObject)
+                               == class_get_instance_size(isa))
+               && [self isKindOfClass:aClassObject]) {
+       Class old_isa = isa;
+       isa = aClassObject;
+       return old_isa;
+    }
+    return nil;
+}
+
+- (id)subclassResponsibility:(SEL)aSel
+{
+    id exception = [[ObjcRuntimeException alloc]
+                           initWithFormat:@"subclass %s should override %s",
+                            object_get_class_name(self),
+                           sel_get_name(aSel)];
+    [exception raise];
+    return self;
+}
+
+- (id)shouldNotImplement:(SEL)aSel
+{
+    id exception = [[ObjcRuntimeException alloc]
+                           initWithFormat:@"%s should not implement %s",
+                           object_get_class_name(self), sel_get_name(aSel)];
+    [exception raise];
+    return self;
+}
+
+- (id)notImplemented:(SEL)aSel
+{
+    id exception = [[ObjcRuntimeException alloc]
+                           initWithFormat:@"%s does not implement %s",
+                           object_get_class_name(self), sel_get_name(aSel)];
+    [exception raise];
+    return self;
+}
+
+- (retval_t)forward:(SEL)aSel :(arglist_t)argFrame
+{
+    void* result;
+    NSInvocation* invocation;
+#if defined(NeXT_RUNTIME) && !defined(BROKEN_BUILTIN_APPLY) && defined(i386)
+    const char* retType;
+#endif
+
+#if NeXT_RUNTIME
+    /*  On NeXT the argFrame represents the stack zone with all the arguments.
+       We create a frame like that required by __builtin_apply. This is done
+       by __builtin_apply_args. This builtin function also sets correctly the
+       structure value return address if any. */
+    arglist_t frame = __builtin_apply_args();
+
+    frame->arg_ptr = (void*)argFrame;
+    argFrame = frame;
+#endif
+
+    invocation = AUTORELEASE([NSFrameInvocation new]);
+    [invocation setArgumentFrame:argFrame];
+    [invocation setSelector:aSel];
+    [invocation setTarget:self];
+
+    [self forwardInvocation:invocation];
+
+    result = [invocation returnFrame];
+
+#if GNU_RUNTIME
+    return result;
+#else /* NeXT_RUNTIME */
+# if !defined(BROKEN_BUILTIN_APPLY) && defined(i386)
+    /* Special hack to avoid pushing the poped float value back to the fp
+       stack on i386 machines. This happens with NeXT runtime and 2.7.2
+       compiler. If the result value is floating point don't call
+       __builtin_return anymore. */
+    retType = [[invocation methodSignature] methodReturnType];
+    if(*retType == _C_FLT || *retType == _C_DBL) {
+       long double value = *(long double*)(((char*)result) + 8);
+       asm("fld %0" : : "f" (value));
+    }
+    else
+# endif
+    __builtin_return(result);
+#endif /* NeXT_RUNTIME */
+}
+
+@end /* NSObject (GNU) */
+
+
+@implementation NSObject (GNUDebugger)
+
+/* The following two methods are necessary to make GDB to work correctly with
+   Foundation objects */
+
+- (BOOL)respondsTo: (SEL)aSelector
+{
+    return (object_is_instance(self) ?
+         (class_get_instance_method(self->isa, aSelector) != METHOD_NULL)
+       : (class_get_class_method(self->isa, aSelector) != METHOD_NULL));
+}
+
+- (IMP)methodFor:(SEL)aSelector
+{
+    return method_get_imp(object_is_instance(self) ?
+                             class_get_instance_method(self->isa, aSelector)
+                           : class_get_class_method(self->isa, aSelector));
+}
+
+@end /* NSObject (GNUDebugger) */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSObjectAllocation.m b/libFoundation/Foundation/NSObjectAllocation.m
new file mode 100644 (file)
index 0000000..2d63a80
--- /dev/null
@@ -0,0 +1,631 @@
+/* 
+   NSObjectAllocation.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+          Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <config.h>
+
+#if HAVE_LIBC_H
+# include <libc.h>
+#else
+# include <unistd.h>
+#endif
+
+#if HAVE_STRING_H
+# include <string.h>
+#endif
+
+#if HAVE_MEMORY_H
+# include <memory.h>
+#endif
+
+#if !HAVE_MEMCPY
+# define memcpy(d, s, n)       bcopy((s), (d), (n))
+# define memmove(d, s, n)      bcopy((s), (d), (n))
+#endif
+
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#else
+extern void* malloc();
+extern void* calloc();
+extern void* realloc();
+extern void free();
+extern atoi();
+extern atol();
+#endif
+
+#include <assert.h>
+
+#include <Foundation/common.h>
+#include <Foundation/NSZone.h>
+#include <Foundation/NSUtilities.h>
+#include <Foundation/NSUserDefaults.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+#include <Foundation/NSAutoreleasePool.h>
+
+#include <extensions/objc-runtime.h>
+#include "lfmemory.h"
+
+#if LIB_FOUNDATION_BOEHM_GC || LIB_FOUNDATION_LEAK_GC
+#  include <Foundation/NSNotification.h>
+#  if LIB_FOUNDATION_LEAK_GC
+#    include <Foundation/NSConcreteString.h>
+#  endif
+#endif
+
+/*
+* Global variables
+*/
+
+static BOOL objectRefInit = NO;
+
+#if !LIB_FOUNDATION_BOEHM_GC
+static NSMapTable* objectRefsHash = NULL;
+static objc_mutex_t objectRefsMutex = NULL;
+#endif
+
+#if DEBUG
+static unsigned totalMem    = 0;
+FILE *logAlloc   = (void*)-1;
+#endif
+
+static BOOL objectRefIsHash = NO;
+Class __freedObjectClass = nil;
+
+/* This is a global mutex which is used to lock the global hash table that
+   keeps the objects. This mutex should be locked/unlocked whenever an
+   operation is performed on the global table. It should NOT be locked when
+   the reference count of the object is kept right before the object.
+
+   The thread-safe feature of libFoundation refers to the fact that it is
+   guaranteed that the library is thread-safe, no matter what operations are
+   performed in each thread, as long as one object does NOT receive messages
+   from multiple threads that can modify its internal state*. This is also the
+   case for release/retain messages that you send to an object: if you want to
+   send these messages to an object from multiple threads you should use an
+   external lock object to syncronize the access to it, to ensure that the ref
+   count is correct. We use a lock here because the internal hash is private
+   and cannot be accessed by other programs.
+
+   As you can see having the external ref counts outside of the objects it's
+   much faster than having a global hash in both single-threaded and
+   multi-threaded programs.
+
+  * Note: One notable exception are the NSLock objects which change their state
+  when you send messages to them from multiple threads.
+*/
+
+static void init_refcounting(void)
+{
+#if DEBUG
+    if (logAlloc == (void*)-1) {
+        char *d;
+
+        logAlloc = NULL;
+        if ((d = getenv("NSLogAlloc"))) {
+            if (strcmp(d, "YES") == 0) {
+                logAlloc = fopen(".alloc", "w");
+                fprintf(logAlloc, "---- pid %d ----\n", getpid());
+            }
+        }
+        else {
+            if (logAlloc)
+                fprintf(stderr, "WARNING: logging object deallocation !\n");
+        }
+    }
+#endif /* DEBUG */
+    
+#if LIB_FOUNDATION_BOEHM_GC || WITH_FAST_RC
+    objectRefIsHash = NO;
+#elif defined(OBJECT_REFCOUNT) && OBJECT_REFCOUNT == 1
+    objectRefIsHash = YES;
+#elif defined(OBJECT_REFCOUNT) && OBJECT_REFCOUNT == 0
+    objectRefIsHash = NO;
+#else 
+    /* Undefined at compile-time. Use OBJECT_REFCOUNT environment variable */
+    objectRefIsHash = getenv("OBJECT_REFCOUNT") ? YES : NO;
+#endif
+
+/*
+  fprintf(stderr, "NSObjectAllocation: using %s refcounting\n", 
+  objectRefIsHash ? "hashtable" : "extra-allocated");
+*/
+
+#if !LIB_FOUNDATION_BOEHM_GC
+    if (objectRefIsHash)
+       objectRefsHash
+            = NSCreateMapTableWithZone(NSNonOwnedPointerMapKeyCallBacks,
+                                       NSIntMapValueCallBacks, 
+                                       64, nil);
+    objectRefsMutex = objc_mutex_allocate();
+#endif
+
+    objectRefInit = YES;
+    __freedObjectClass = objc_get_class("FREED_OBJECT");
+}
+
+#if LIB_FOUNDATION_BOEHM_GC
+/* Private function used to do the finalization code on an object */
+static void _do_finalize (void* object, void* client_data)
+{
+  [(id)object gcFinalize];
+
+  /* Set the class of anObject to FREED_OBJECT. The further messages to this
+     object will cause an error to occur. */
+  ((id)object)->class_pointer = __freedObjectClass;
+}
+#endif
+
+#if LIB_FOUNDATION_LEAK_GC
+// track leaks
+
+void _check_object_for_leak(void *memory, void *cd)
+{
+    Class        class  = Nil;
+    id           object = nil;
+    unsigned int rc;
+
+    if (objectRefIsHash) {
+        object = memory;
+        rc     = NSExtraRefCount(object);
+        class  = (Class)cd;
+    }
+    else {
+        object = (id)&(((struct RefObjectLayout *)memory)->class_pointer);
+        rc     = NSExtraRefCount(object);
+        class  = (Class)cd;
+    }
+
+    if ((rc >= 1) && (rc <= 1000)) {
+        fprintf(stderr, "LEAK(rc=%d): 0x%08X<%s>",
+                rc, (unsigned)object, (class ? class->name : "Nil"));
+
+        if ([object isKindOfClass:[NSString class]]) {
+            unsigned slen = [object cStringLength];
+            char buf[slen + 1];
+            [object getCString:buf]; buf[slen] = '\0';
+            fprintf(stderr, " string=\"%s\"", buf);
+        }
+        
+#if 0
+          if ([object isKindOfClass:[NSString class]])
+            fprintf(stderr, " string=\"%s\"", [object cString]);
+          else
+            fprintf(stderr, " description=%s", [[object description] cString]);
+#endif
+         
+        fprintf(stderr, "\n");
+    }    
+    object = nil; rc = 0; class = Nil;
+}
+
+#endif
+
+/* 
+ * Allocate an Object 
+ */
+
+NSObject *NSAllocateObject(Class aClass, unsigned extraBytes, NSZone *zone)
+{
+    assert(CLS_ISCLASS(aClass));
+    
+    if (!objectRefInit)
+       init_refcounting();
+    
+#if LIB_FOUNDATION_BOEHM_GC
+    {
+        size_t size = aClass->instance_size + extraBytes;
+        struct objc_object *p;
+        
+        if (aClass->gc_object_type == NULL) {
+            fprintf(stderr, "WARNING: GC object type is NULL for class %s\n",
+                    aClass->name);
+            fflush(stderr);
+
+            p = GC_MALLOC(size);
+        }
+        else {
+            if ([aClass requiresTypedMemory]) {
+                p = GC_CALLOC_EXPLICTLY_TYPED(1, size,
+                                              (GC_descr)(aClass->gc_object_type));
+            }
+            else {
+                p = GC_MALLOC(size);
+            }
+            
+            if (!p)
+                objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
+
+        }
+        memset (p, 0, size);
+        p->class_pointer = aClass;
+        /* Register the object for finalization */
+        if ([(id)p respondsToSelector:@selector(gcFinalize)]) {
+            GC_REGISTER_FINALIZER (p, _do_finalize, NULL, NULL, NULL);
+        }
+        return p;
+    }
+#else
+    if (objectRefIsHash) {
+       struct HashObjectLayout* p;
+       
+       p = NSZoneCalloc(zone, 1, sizeof(struct HashObjectLayout) + 
+                         aClass->instance_size + extraBytes);
+
+       p->class_pointer = aClass;
+       objc_mutex_lock(objectRefsMutex);
+       NSMapInsert(objectRefsHash, PTR2HSH(p), (void*)1);
+       objc_mutex_unlock(objectRefsMutex);
+
+#if LIB_FOUNDATION_LEAK_GC
+        GC_REGISTER_FINALIZER_IGNORE_SELF(p, _check_object_for_leak,
+                                          aClass, NULL, NULL);
+#endif
+#if DEBUG
+        totalMem += sizeof(struct HashObjectLayout) + 
+            aClass->instance_size + extraBytes;
+        if (logAlloc) {
+            fprintf(logAlloc,
+                    "alloc-#: 0x%08X<%s> size=%d (%d + %d) zone=0x%08X\n",
+                    (unsigned)p, class_get_class_name(aClass),
+                    (unsigned)(sizeof(struct HashObjectLayout) + 
+                      aClass->instance_size + extraBytes),
+                    (unsigned)aClass->instance_size, (unsigned)extraBytes,
+                    (unsigned)zone);
+        }
+#endif
+       return (NSObject*)p;
+    }
+    else {
+        struct RefObjectLayout* p;
+       
+        p = NSZoneCalloc(zone, 1, sizeof(struct RefObjectLayout) + 
+                         aClass->instance_size + extraBytes);
+
+        p->class_pointer = aClass;
+        p->ref_count = 1;
+       
+#if LIB_FOUNDATION_LEAK_GC
+        GC_REGISTER_FINALIZER(p, _check_object_for_leak, aClass,
+                              NULL, NULL);
+#endif
+
+#if DEBUG
+        totalMem += sizeof(struct RefObjectLayout) +
+            aClass->instance_size + extraBytes;
+        if (logAlloc) {
+            unsigned size;
+
+            size = (unsigned)(sizeof(struct RefObjectLayout) +
+                              aClass->instance_size + extraBytes);
+            
+            fprintf(logAlloc,
+                    "alloc-rc: 0x%08X<%s> size=%d (%d + %d) zone=0x%08X\n",
+                    (unsigned)&(p->class_pointer),
+                    aClass ? class_get_class_name(aClass) : "Nil",
+                    size,
+                    (unsigned)aClass->instance_size,
+                    (unsigned)extraBytes,
+                    (unsigned)zone);
+        }
+#endif
+        return (NSObject*)(&(p->class_pointer));
+    }
+    
+    return nil;
+#endif
+}
+
+NSObject *NSCopyObject(NSObject *anObject, unsigned extraBytes, NSZone *zone)
+{
+    id copy = NSAllocateObject(((id)anObject)->class_pointer,
+                           extraBytes, zone);
+    unsigned size = ((id)anObject)->class_pointer->instance_size + 
+                               extraBytes;
+
+    memcpy(copy, anObject, size);
+
+    return copy;
+}
+
+NSZone *NSZoneFromObject(NSObject *anObject)
+{
+    return NSZoneFromPointer(objectRefIsHash
+                             ? (void *)anObject
+                             : (void *)OBJ2PTR(anObject));
+}
+
+void NSDeallocateObject(NSObject *anObject)
+{
+#if !LIB_FOUNDATION_BOEHM_GC
+    void  *p;
+    Class oldIsa;
+#endif
+#if DEBUG
+    static int  useZombies  = -1;
+    
+    if (useZombies == -1) {
+        char *d;
+
+        if ((d = getenv("NSUseZombies")))
+            useZombies = (strcmp(d, "YES") == 0) ? 1 : 0;
+        else
+            useZombies = 0;
+        
+        if (useZombies)
+            fprintf(stderr, "WARNING: using Zombie objects !\n");
+    }
+#endif
+    
+#if LIB_FOUNDATION_BOEHM_GC
+    fprintf(stderr, "WARNING: explicit free of GC object 0x%08X !\n", anObject);
+    abort();
+    GC_FREE(anObject); anObject = nil;
+    return;
+#else
+
+#if DEBUG
+    if (logAlloc) {
+        fprintf(logAlloc, "dealloc: 0x%08X<%s>\n",
+                (unsigned)anObject,
+                class_get_class_name(((id)anObject)->class_pointer));
+    }
+#endif
+    
+    /* Set the class of anObject to FREED_OBJECT. The further messages to this
+       object will cause an error to occur. */
+    oldIsa = ((id)anObject)->class_pointer;
+    ((id)anObject)->class_pointer = __freedObjectClass;
+    
+    if ((unsigned)oldIsa->instance_size >= ((sizeof(Class) * 2))) {
+        /* if there is enough room for the old class pointer .. */
+        ((FREED_OBJECT *)anObject)->oldIsa = oldIsa;
+    }
+    
+    if (objectRefIsHash) {
+       p = anObject;
+       objc_mutex_lock(objectRefsMutex);
+       NSMapRemove(objectRefsHash, PTR2HSH(anObject));
+       objc_mutex_unlock(objectRefsMutex);
+    }
+    else {
+       p = OBJ2PTR(anObject);
+        ((struct RefObjectLayout *)p)->ref_count = 0;
+    }
+
+#if FIND_LEAK
+    GC_REGISTER_FINALIZER_IGNORE_SELF(p, _check_object_for_leak,
+                                      NULL, NULL, NULL);
+#endif
+
+#if DEBUG
+    if (useZombies)
+        return;
+#endif
+    NSZoneFree(NSZoneFromPointer(p), p);
+
+#if 0
+    fprintf(stderr, "deallocated: 0x%08X\n", anObject);
+#endif
+    anObject = nil; p = nil;
+#endif
+}
+
+/* 
+ * Retain / Release NSObject 
+ */
+
+BOOL NSShouldRetainWithZone(NSObject* anObject, NSZone* requestedZone)
+{
+    return requestedZone == NULL
+          || requestedZone == NSDefaultMallocZone()
+          || requestedZone == [anObject zone];
+}
+
+#if LIB_FOUNDATION_BOEHM_GC
+
+BOOL NSDecrementExtraRefCountWasZero(id anObject)
+{
+    return NO;
+}
+void NSIncrementExtraRefCount(id anObject)
+{
+}
+unsigned NSGetExtraRefCount(id anObject)
+{
+    // deprecated function
+    return (unsigned)-1;
+}
+unsigned NSExtraRefCount(id anObject)
+{
+    return (unsigned)-1;
+}
+
+unsigned NSAutoreleaseCountForObject(id object)
+{
+    return (unsigned)-1;
+}
+
+id NSFastAutorelease(id object) {
+    return object;
+}
+
+#else /* !LIB_FOUNDATION_BOEHM_GC */
+
+/* 
+ * Modify the Number of References to an Object 
+ */
+
+BOOL NSDecrementExtraRefCountWasZero(id anObject)
+{
+    if (objectRefIsHash) {
+        void* p = PTR2HSH(anObject);
+        unsigned long r;
+       
+        objc_mutex_lock(objectRefsMutex);
+        r = (unsigned long)NSMapGet(objectRefsHash, p);
+
+        if (!r) {
+            objc_mutex_unlock(objectRefsMutex);
+            return YES;
+        }
+
+        NSMapInsert(objectRefsHash, p, (void*)(--r));
+        objc_mutex_unlock(objectRefsMutex);
+        return (r == 0);
+    }
+    else {
+        struct RefObjectLayout* p = OBJ2PTR(anObject);
+        unsigned int r = p->ref_count;
+        
+        if (!r)
+            return YES;
+
+        r = --(p->ref_count);
+        return (r == 0);
+    }
+}
+
+void NSIncrementExtraRefCount(id anObject)
+{
+    if (objectRefIsHash) {
+       void* p = PTR2HSH(anObject);
+       unsigned long r;
+
+       objc_mutex_lock(objectRefsMutex);
+       r = (unsigned long)NSMapGet(objectRefsHash, p);
+       NSMapInsert(objectRefsHash, p, (void*)(r+1));
+       objc_mutex_unlock(objectRefsMutex);
+    }
+    else {
+       struct RefObjectLayout* p = OBJ2PTR(anObject);
+
+       (p->ref_count)++;
+    }
+}
+
+/* Obtain the Number of References to an Object */
+unsigned NSGetExtraRefCount(id anObject)
+{
+    return NSExtraRefCount(anObject);
+}
+unsigned NSExtraRefCount(id anObject)
+{
+    unsigned int r;
+
+    if (objectRefIsHash) {
+       void* p = PTR2HSH(anObject);
+       
+       objc_mutex_lock(objectRefsMutex);
+       r = (unsigned long)NSMapGet(objectRefsHash, p);
+       objc_mutex_unlock(objectRefsMutex);
+    }
+    else {
+       struct RefObjectLayout* p = OBJ2PTR(anObject);
+       r = p->ref_count;
+    }
+    return r;
+}
+
+unsigned NSAutoreleaseCountForObject(id object)
+{
+    return [NSAutoreleasePool autoreleaseCountForObject:object];
+}
+
+id NSFastAutorelease(id self) {
+    static Class NSAutoreleasePoolClass = Nil;
+    static void (*addObject)(id,SEL,id);
+    
+    if (self == nil) return nil;
+    
+    if (NSAutoreleasePoolClass == Nil) {
+        NSAutoreleasePoolClass = [NSAutoreleasePool class];
+        addObject = (void*)
+          [(id)NSAutoreleasePoolClass methodForSelector:@selector(addObject:)];
+    }
+    addObject(NSAutoreleasePoolClass, @selector(addObject:), self);
+    return self;
+}
+
+#endif /* !LIB_FOUNDATION_BOEHM_GC */
+
+@implementation FREED_OBJECT
+
+static void _raiseSelException(FREED_OBJECT *self, SEL _selector)
+{
+    id exception;
+    BOOL outIsa = NO;
+
+    if (self->oldIsa) {
+        if (CLS_ISCLASS(self->oldIsa))
+            outIsa = YES;
+    }
+    
+    exception = [ObjcRuntimeException alloc];
+    if (outIsa) {
+        exception = [exception initWithFormat:
+                                 @"message '%s' sent to freed object %p (%s)", 
+                                 sel_get_name(_selector), (void*)self,
+                                 class_get_class_name(self->oldIsa)];
+    }
+    else {
+        exception = [exception initWithFormat:
+                                 @"message '%s' sent to freed object %p", 
+                                 sel_get_name(_selector), (void*)self];
+    }
+    [exception raise];
+}
+
+- (id)autorelease
+{
+    _raiseSelException(self, _cmd);
+    return nil;
+}
+- (oneway void)release
+{
+    _raiseSelException(self, _cmd);
+}
+- (id)retain
+{
+    _raiseSelException(self, _cmd);
+    return nil;
+}
+
+#if GNU_RUNTIME
+- (void)doesNotRecognize:(SEL)aSelector
+#else
+- (void)doesNotRecognizeSelector:(SEL)aSelector
+#endif
+{
+    _raiseSelException(self, aSelector);
+}
+
+@end /* FREED_OBJECT */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSObjectInvocation.h b/libFoundation/Foundation/NSObjectInvocation.h
new file mode 100644 (file)
index 0000000..dccf285
--- /dev/null
@@ -0,0 +1,53 @@
+/* 
+   NSObjectInvocation.h
+
+   Copyright (C) 1999 Helge Hess.
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __Foundation_NSObjectInvocation_H__
+#define __Foundation_NSObjectInvocation_H__
+
+#include <Foundation/NSInvocation.h>
+
+@interface NSObjectInvocation : NSInvocation
+{
+@private
+    BOOL isVoid;
+    char argumentCount;
+    id   returnValue;
+    id   arguments[1];
+}
+
++ (id)allocForArgumentCount:(int)_count zone:(NSZone *)_zone;
+
+- (void)invokeWithTarget:(id)_target lookupAtClass:(Class)_class;
+- (void)superInvokeWithTarget:(id)_target;
+
+@end
+
+#endif /* __Foundation_NSObjectInvocation_H__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSObjectInvocation.m b/libFoundation/Foundation/NSObjectInvocation.m
new file mode 100644 (file)
index 0000000..055e022
--- /dev/null
@@ -0,0 +1,452 @@
+/* 
+   NSObjectInvocation.m
+
+   Copyright (C) 1999 Helge Hess.
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSInvocation.h>
+#include <Foundation/NSUtilities.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+#include <Foundation/exceptions/NSInvocationExceptions.h>
+#include "NSObjectInvocation.h"
+
+// method prototypes
+typedef void (*mVoid_Id0) (id, SEL);
+typedef void (*mVoid_Id1) (id, SEL, id);
+typedef void (*mVoid_Id2) (id, SEL, id, id);
+typedef void (*mVoid_Id3) (id, SEL, id, id, id);
+typedef void (*mVoid_Id4) (id, SEL, id, id, id, id);
+typedef void (*mVoid_Id5) (id, SEL, id, id, id, id, id);
+typedef void (*mVoid_Id6) (id, SEL, id, id, id, id, id, id);
+typedef void (*mVoid_Id7) (id, SEL, id, id, id, id, id, id, id);
+typedef void (*mVoid_Id8) (id, SEL, id, id, id, id, id, id, id, id);
+typedef void (*mVoid_Id9) (id, SEL, id, id, id, id, id, id, id, id, id);
+typedef void (*mVoid_Id10)(id, SEL, id, id, id, id, id, id, id, id, id, id);
+typedef id   (*mId_Id0)   (id, SEL);
+typedef id   (*mId_Id1)   (id, SEL, id);
+typedef id   (*mId_Id2)   (id, SEL, id, id);
+typedef id   (*mId_Id3)   (id, SEL, id, id, id);
+typedef id   (*mId_Id4)   (id, SEL, id, id, id, id);
+typedef id   (*mId_Id5)   (id, SEL, id, id, id, id, id);
+typedef id   (*mId_Id6)   (id, SEL, id, id, id, id, id, id);
+typedef id   (*mId_Id7)   (id, SEL, id, id, id, id, id, id, id);
+typedef id   (*mId_Id8)   (id, SEL, id, id, id, id, id, id, id, id);
+typedef id   (*mId_Id9)   (id, SEL, id, id, id, id, id, id, id, id, id);
+typedef id   (*mId_Id10)  (id, SEL, id, id, id, id, id, id, id, id, id, id);
+
+@interface NSInvocation(PrivateMethods)
+- (id)initWithSignature:(NSMethodSignature *)_signature;
+@end
+
+@interface NSObjectInvocation(PrivateMethods)
+- (void)_releaseArguments;
+@end
+
+@implementation NSObjectInvocation
+
++ (id)allocForArgumentCount:(int)_count zone:(NSZone *)_zone
+{
+    NSObjectInvocation *i = NSAllocateObject(self, _count * sizeof(id), _zone);
+    i->argumentCount = _count;
+    return i;
+}
+
+- (id)initWithSignature:(NSMethodSignature *)_signature
+{
+    self = [super initWithSignature:_signature];
+    self->isVoid = (*[_signature methodReturnType] == _C_VOID);
+    return self;
+}
+
+- (void)dealloc
+{
+    if (self->isValid) [self _releaseArguments];
+    [super dealloc];
+}
+
+// arguments
+
+- (void)_releaseArguments
+{
+    if (self->argumentsRetained) {
+        int i;
+        
+        self->argumentsRetained = 0;
+        RELEASE(self->target);
+
+        for (i = 0; i < self->argumentCount; i++)
+            RELEASE(self->arguments[i]);
+        RELEASE(self->returnValue);
+    }
+}
+
+- (void)getArgument:(void*)argumentLocation atIndex:(int)index
+{
+    NSAssert(self->signature, @"You must previously set the signature object");
+    if (index >= (self->argumentCount + 2)) {
+       [[[IndexOutOfRangeException alloc]
+                     initForSize:(self->argumentCount + 2) index:index] raise];
+       return;
+    }
+
+    if (index == 0) // target
+        *((id *)argumentLocation) = [self target];
+    else if (index == 1) // selector
+        *((SEL *)argumentLocation) = [self selector];
+    else // argument
+        *((id *)argumentLocation) = self->arguments[(index - 2)];
+}
+- (void)setArgument:(void*)argumentLocation atIndex:(int)index
+{
+    NSAssert(self->signature, @"You must previously set the signature object");
+    if (index >= (self->argumentCount + 2)) {
+       [[[IndexOutOfRangeException alloc]
+                     initForSize:(self->argumentCount + 2) index:index] raise];
+       return;
+    }
+    if (index == 0) // target
+        [self setTarget:*((id *)argumentLocation)];
+    else if (index == 1) // selector
+        [self setSelector:*((SEL *)argumentLocation)];
+    else { // argument
+        if (self->argumentsRetained) {
+            id tmp = self->arguments[(index - 2)];
+            self->arguments[(index - 2)] = RETAIN(*((id *)argumentLocation));
+            RELEASE(tmp); tmp = nil;
+        }
+        else
+            self->arguments[(index - 2)] = *((id *)argumentLocation);
+    }
+}
+
+- (void)retainArguments
+{
+    int i;
+    
+    NSAssert(self->signature, @"You must previously set the signature object");
+    
+    if (self->argumentsRetained)
+       return;
+
+    self->argumentsRetained = 1;
+    
+    self->target      = RETAIN(self->target);
+    self->returnValue = RETAIN(self->returnValue);
+
+    for (i = 0; i < self->argumentCount; i++)
+        self->arguments[i] = RETAIN(self->arguments[i]);
+}
+
+// return value
+
+- (void)getReturnValue:(void *)retLoc
+{
+    NSAssert(self->signature, @"You must previously set the signature object");
+    
+    *(id *)retLoc = self->returnValue;
+}
+- (void)setReturnValue:(void *)retLoc
+{
+    NSAssert(self->signature, @"You must previously set the signature object");
+    
+    if (self->argumentsRetained) {
+        id tmp = self->returnValue;
+        self->returnValue = RETAIN(*(id *)retLoc);
+        RELEASE(tmp); tmp = nil;
+    }
+    else
+        self->returnValue = *(id *)retLoc;
+}
+
+// validation
+
+- (void)invalidate
+{
+    if (self->isValid) {
+       [self _releaseArguments];
+       self->isValid = 0;
+    }
+}
+
+// invocation
+
+static inline void _invoke(NSObjectInvocation *self, id _t, Class _lookup);
+
+- (void)invokeWithTarget:(id)_target
+{
+    _invoke(self, _target, Nil);
+}
+- (void)invokeWithTarget:(id)_target lookupAtClass:(Class)_class
+{
+    _invoke(self, _target, _class);
+}
+- (void)superInvokeWithTarget:(id)_target
+{
+    Class superClass = (*(Class *)_target)->super_class;
+    _invoke(self, _target, superClass);
+}
+
+static void _invoke(NSObjectInvocation *self, id _target, Class _lookupClass) {
+    IMP method = NULL;
+    SEL sel    = [self selector];
+    
+    NSCAssert(self->argumentCount < 11, @"Unsupported argument count !");
+
+    if (_target == nil)
+        _target = [self target];
+    if (_target == nil) {
+        if (!self->isVoid) [self setReturnValue:&_target];
+        return;
+    }
+    
+    if (sel == NULL) {
+        [_target doesNotRecognizeSelector:sel];
+        return;
+    }
+    
+    if (_lookupClass)
+        method = method_get_imp(class_get_instance_method(_lookupClass, sel));
+    else {
+        method = method_get_imp(object_is_instance(self)
+                   ? class_get_instance_method(*(Class *)_target, sel)
+                   : class_get_class_method(*(Class *)_target, sel));
+    }
+
+    if (method == NULL) {
+        /* no method for dispatch, so forward invocation .. */
+        [_target forwardInvocation:self];
+        /* [_target doesNotRecognizeSelector:sel]; */
+        return;
+    }
+    
+    if (self->isVoid) {
+        switch (self->argumentCount) {
+            case 0:
+                ((mVoid_Id0)method)(_target, sel);
+                break;
+            case 1:
+                ((mVoid_Id1)method)(_target, sel, self->arguments[0]);
+                break;
+            case 2:
+                ((mVoid_Id2)method)(_target, sel,
+                                    self->arguments[0],
+                                    self->arguments[1]);
+                break;
+            case 3:
+                ((mVoid_Id3)method)(_target, sel,
+                                    self->arguments[0],
+                                    self->arguments[1],
+                                    self->arguments[2]);
+                break;
+            case 4:
+                ((mVoid_Id4)method)(_target, sel,
+                                    self->arguments[0],
+                                    self->arguments[1],
+                                    self->arguments[2],
+                                    self->arguments[3]);
+                break;
+            case 5:
+                ((mVoid_Id5)method)(_target, sel,
+                                    self->arguments[0],
+                                    self->arguments[1],
+                                    self->arguments[2],
+                                    self->arguments[3],
+                                    self->arguments[4]);
+                break;
+            case 6:
+                ((mVoid_Id6)method)(_target, sel,
+                                    self->arguments[0],
+                                    self->arguments[1],
+                                    self->arguments[2],
+                                    self->arguments[3],
+                                    self->arguments[4],
+                                    self->arguments[5]);
+                break;
+            case 7:
+                ((mVoid_Id7)method)(_target, sel,
+                                    self->arguments[0],
+                                    self->arguments[1],
+                                    self->arguments[2],
+                                    self->arguments[3],
+                                    self->arguments[4],
+                                    self->arguments[5],
+                                    self->arguments[6]);
+                break;
+            case 8:
+                ((mVoid_Id8)method)(_target, sel,
+                                    self->arguments[0],
+                                    self->arguments[1],
+                                    self->arguments[2],
+                                    self->arguments[3],
+                                    self->arguments[4],
+                                    self->arguments[5],
+                                    self->arguments[6],
+                                    self->arguments[7]);
+                break;
+            case 9:
+                ((mVoid_Id9)method)(_target, sel,
+                                    self->arguments[0],
+                                    self->arguments[1],
+                                    self->arguments[2],
+                                    self->arguments[3],
+                                    self->arguments[4],
+                                    self->arguments[5],
+                                    self->arguments[6],
+                                    self->arguments[7],
+                                    self->arguments[8]);
+                break;
+            case 10:
+                ((mVoid_Id10)method)(_target, sel,
+                                    self->arguments[0],
+                                    self->arguments[1],
+                                    self->arguments[2],
+                                    self->arguments[3],
+                                    self->arguments[4],
+                                    self->arguments[5],
+                                    self->arguments[6],
+                                    self->arguments[7],
+                                    self->arguments[8],
+                                    self->arguments[9]);
+                break;
+        }
+    }
+    else {
+        id retVal;
+        
+        switch (self->argumentCount) {
+            case 0:
+                retVal = ((mId_Id0)method)(_target, sel);
+                break;
+            case 1:
+                retVal = ((mId_Id1)method)(_target, sel, self->arguments[0]);
+                break;
+            case 2:
+                retVal = ((mId_Id2)method)(_target, sel,
+                                           self->arguments[0],
+                                           self->arguments[1]);
+                break;
+            case 3:
+                retVal = ((mId_Id3)method)(_target, sel,
+                                           self->arguments[0],
+                                           self->arguments[1],
+                                           self->arguments[2]);
+                break;
+            case 4:
+                retVal = ((mId_Id4)method)(_target, sel,
+                                           self->arguments[0],
+                                           self->arguments[1],
+                                           self->arguments[2],
+                                           self->arguments[3]);
+                break;
+            case 5:
+                retVal = ((mId_Id5)method)(_target, sel,
+                                           self->arguments[0],
+                                           self->arguments[1],
+                                           self->arguments[2],
+                                           self->arguments[3],
+                                           self->arguments[4]);
+                break;
+            case 6:
+                retVal = ((mId_Id6)method)(_target, sel,
+                                           self->arguments[0],
+                                           self->arguments[1],
+                                           self->arguments[2],
+                                           self->arguments[3],
+                                           self->arguments[4],
+                                           self->arguments[5]);
+                break;
+            case 7:
+                retVal = ((mId_Id7)method)(_target, sel,
+                                           self->arguments[0],
+                                           self->arguments[1],
+                                           self->arguments[2],
+                                           self->arguments[3],
+                                           self->arguments[4],
+                                           self->arguments[5],
+                                           self->arguments[6]);
+                break;
+            case 8:
+                retVal = ((mId_Id8)method)(_target, sel,
+                                           self->arguments[0],
+                                           self->arguments[1],
+                                           self->arguments[2],
+                                           self->arguments[3],
+                                           self->arguments[4],
+                                           self->arguments[5],
+                                           self->arguments[6],
+                                           self->arguments[7]);
+                break;
+            case 9:
+                retVal = ((mId_Id9)method)(_target, sel,
+                                           self->arguments[0],
+                                           self->arguments[1],
+                                           self->arguments[2],
+                                           self->arguments[3],
+                                           self->arguments[4],
+                                           self->arguments[5],
+                                           self->arguments[6],
+                                           self->arguments[7],
+                                           self->arguments[8]);
+                break;
+            case 10:
+                retVal = ((mId_Id10)method)(_target, sel,
+                                            self->arguments[0],
+                                            self->arguments[1],
+                                            self->arguments[2],
+                                            self->arguments[3],
+                                            self->arguments[4],
+                                            self->arguments[5],
+                                            self->arguments[6],
+                                            self->arguments[7],
+                                            self->arguments[8],
+                                            self->arguments[9]);
+                break;
+        }
+        [self setReturnValue:&retVal];
+    }
+}
+
+- (NSString *)description
+{
+    /* Don't use -[NSString stringWithFormat:] method because it can cause
+       infinite recursion. */
+    char buffer[1024];
+
+    sprintf (buffer, "<%s %p selector: %s target: %s>", \
+                (char*)object_get_class_name(self), \
+                self, \
+                selector ? [NSStringFromSelector(selector) cString] : "nil", \
+                target ? [NSStringFromClass([target class]) cString] : "nil" \
+                );
+
+    return [NSString stringWithCString:buffer];
+}
+
+@end
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSOutputStream.m b/libFoundation/Foundation/NSOutputStream.m
new file mode 100644 (file)
index 0000000..e29c8a1
--- /dev/null
@@ -0,0 +1,81 @@
+/* 
+   NSOutputStream.m
+
+   Copyright (C) 2003 SKYRIX Software AG, Helge Hess.
+   All rights reserved.
+   
+   Author: Helge Hess <helge.hess@opengroupware.org>
+   
+   This file is part of libFoundation.
+   
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+   
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSStream.h>
+#include <common.h>
+
+@implementation NSOutputStream
+
+/* TODO: this is probably a class cluster? */
+
++ (id)outputStreamToMemory
+{
+    return [[[self alloc] initToMemory] autorelease];
+}
++ (id)outputStreamToBuffer:(void *)_buf capacity:(unsigned int)_capacity
+{
+    return [[[self alloc] initToBuffer:_buf capacity:_capacity] autorelease];
+}
++ (id)outputStreamToFileAtPath:(NSStream *)_path append:(BOOL)_append
+{
+    return [[[self alloc] initToFileAtPath:_path append:_append] autorelease];
+}
+
+- (id)initToMemory
+{
+    [self release];
+    return [self notImplemented:_cmd];
+}
+
+- (id)initToBuffer:(void *)_buf capacity:(unsigned int)_capacity
+{
+    [self release];
+    return [self notImplemented:_cmd];
+}
+
+- (id)initToFileAtPath:(NSStream *)_path append:(BOOL)_append
+{
+    [self release];
+    return [self notImplemented:_cmd];
+}
+
+/* operations */
+
+- (BOOL)hasSpaceAvailable 
+{
+    return YES;
+}
+- (int)write:(const void *)buffer maxLength:(unsigned int)len
+{
+    return -1; // -1 error, 0 EOF
+}
+
+@end /* NSOutputStream */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSPathUtilities.h b/libFoundation/Foundation/NSPathUtilities.h
new file mode 100644 (file)
index 0000000..f5df242
--- /dev/null
@@ -0,0 +1,121 @@
+/* 
+   NSPathUtilities.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSPathUtilities_h__
+#define __NSPathUtilities_h__
+
+#include <Foundation/NSString.h>
+
+/*
+ * User Informations
+ */
+
+LF_EXPORT NSString *NSUserName(void);
+LF_EXPORT NSString *NSHomeDirectory(void);
+LF_EXPORT NSString *NSHomeDirectoryForUser(NSString* userName);
+
+LF_EXPORT NSString *NSFullUserName();
+LF_EXPORT NSString *NSTemporaryDirectory();
+
+/*
+ * Standard System Paths, primarily useful in the GNUstep environment
+ */
+
+typedef enum {
+    NSUserDomainMask    = 1,
+    NSLocalDomainMask   = 2,
+    NSNetworkDomainMask = 4,
+    NSSystemDomainMask  = 8,
+    NSAllDomainsMask    = 255
+} NSSearchPathDomainMask;
+
+typedef enum {
+    NSApplicationDirectory = 1,
+    NSLibraryDirectory,
+    NSUserDirectory,
+    NSAllApplicationDirectory = 1000,
+    NSAllLibrariesDirectory
+} NSSearchPathDirectory;
+
+@class NSString, NSArray;
+
+LF_EXPORT NSString *NSOpenStepRootDirectory(void);
+LF_EXPORT NSArray  *NSStandardLibraryPaths(void);
+LF_EXPORT NSArray  *NSStandardApplicationPaths(void);
+
+LF_EXPORT NSArray *
+NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory _directory,
+                                    NSSearchPathDomainMask _mask,
+                                    BOOL _expandTilde);
+
+/*
+ * String file naming utilities
+ */
+
+@interface NSString(FilePathMethods)
+
++ (NSString *)pathWithComponents:(NSArray *)components;
+- (NSArray *)pathComponents;
+- (unsigned int)completePathIntoString:(NSString **)outputName
+  caseSensitive:(BOOL)flag matchesIntoArray:(NSArray **)outputArray
+  filterTypes:(NSArray*)filterTypes; 
+- (const char *)fileSystemRepresentation;
+- (BOOL)getFileSystemRepresentation:(char *)buffer
+  maxLength:(unsigned int)maxLength;
+- (BOOL)isAbsolutePath;
+- (NSString *)lastPathComponent;
+- (NSString *)pathExtension;
+- (NSString *)stringByAbbreviatingWithTildeInPath;
+- (NSString *)stringByAppendingPathComponent:(NSString *)aString;
+- (NSString *)stringByAppendingPathExtension:(NSString *)aString;
+- (NSString *)stringByDeletingLastPathComponent;
+- (NSString *)stringByDeletingPathExtension;
+- (NSString *)stringByExpandingTildeInPath;
+- (NSString *)stringByResolvingSymlinksInPath;
+- (NSString *)stringByStandardizingPath;
+- (NSArray *)stringsByAppendingPaths:(NSArray *)paths;
+
+@end
+
+#endif /* __NSPathUtilities_h__ */
+
+#ifndef __NSPathUtilitiesArray_h__
+#define __NSPathUtilitiesArray_h__
+
+#include <Foundation/NSArray.h>
+
+@interface NSArray(FilePathMethods)
+
+- (NSArray *)pathsMatchingExtensions:(NSArray *)_exts; /* new in MacOSX */
+
+@end
+
+#endif /* __NSPathUtilitiesArray_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSPathUtilities.m b/libFoundation/Foundation/NSPathUtilities.m
new file mode 100644 (file)
index 0000000..07682d4
--- /dev/null
@@ -0,0 +1,770 @@
+/* 
+   NSPathUtilities.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <config.h>
+#include <objc/objc.h>
+
+#ifdef _POSIX_VERSION
+#include <limits.h>                    /* for PATH_MAX */
+#else
+# if HAVE_SYS_PARAM_H
+#  include <sys/param.h>                       /* for MAXPATHLEN */
+# endif
+#endif
+
+#include <Foundation/common.h>
+
+#include <Foundation/NSArray.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSPathUtilities.h>
+#include <Foundation/NSUtilities.h>
+#include <Foundation/NSAccount.h>
+#include <Foundation/NSSet.h>
+#include <Foundation/NSProcessInfo.h>
+
+#ifndef PATH_MAX
+#  ifdef _POSIX_VERSION
+#    define PATH_MAX _POSIX_PATH_MAX
+#  else
+#    ifdef MAXPATHLEN
+#      define PATH_MAX MAXPATHLEN
+#    else
+#      define PATH_MAX 1024
+#    endif
+#  endif
+#endif
+
+#if defined(HAVE_WINDOWS_H)
+#  include <windows.h>
+#endif
+
+/*
+ * User Account Functions
+ */
+
+NSString *NSUserName(void)
+{
+    return [[NSUserAccount currentAccount] accountName];
+}
+
+NSString *NSHomeDirectory(void)
+{
+    return [[NSUserAccount currentAccount] homeDirectory];
+}
+
+NSString *NSOpenStepRootDirectory(void)
+{
+#if defined(__MINGW32__)
+    return @"C:\\";
+#else
+    return @"/";
+#endif
+}
+
+NSArray *NSStandardLibraryPaths(void)
+{
+#if WITH_GNUSTEP
+    NSMutableArray *result;
+    NSDictionary   *env;
+    NSString       *value;
+    id             pathPrefixes;
+
+    result = [NSMutableArray arrayWithCapacity:4];
+    env    = [[NSProcessInfo processInfo] environment];
+    
+    pathPrefixes = [env objectForKey:@"GNUSTEP_PATHPREFIX_LIST"];
+    if (pathPrefixes == nil)
+       pathPrefixes = [env objectForKey:@"GNUSTEP_PATHLIST"];
+    
+    if (pathPrefixes) {
+#  if defined(__MINGW32__)
+        pathPrefixes = [pathPrefixes componentsSeparatedByString:@";"];
+#  else
+        pathPrefixes = [pathPrefixes componentsSeparatedByString:@":"];
+#  endif
+
+        pathPrefixes = [pathPrefixes objectEnumerator];
+        while ((value = [pathPrefixes nextObject])) {
+            value = [value stringByAppendingPathComponent:@"Library"];
+            [result addObject:value];
+        }
+    }
+    else {
+        value = [env objectForKey:@"GNUSTEP_USER_ROOT"];
+        value = [value stringByAppendingPathComponent:@"Library"];
+        if (value) [result addObject:value];
+        value = [env objectForKey:@"GNUSTEP_LOCAL_ROOT"];
+        value = [value stringByAppendingPathComponent:@"Library"];
+        if (value) [result addObject:value];
+        value = [env objectForKey:@"GNUSTEP_SYSTEM_ROOT"];
+        value = [value stringByAppendingPathComponent:@"Library"];
+        if (value) [result addObject:value];
+    }
+    
+    [result addObject:@"/usr/local/share"];
+    [result addObject:@"/usr/share"];
+    
+    return AUTORELEASE([result copy]);
+#else
+    return [NSArray arrayWithObject:@RESOURCES_PATH];
+#endif
+}
+
+NSArray *NSStandardApplicationPaths(void)
+{
+#if WITH_GNUSTEP
+    NSMutableArray *result;
+    NSDictionary   *env;
+    NSString       *value;
+    id             pathPrefixes;
+
+    result = [NSMutableArray arrayWithCapacity:4];
+    env    = [[NSProcessInfo processInfo] environment];
+    
+    pathPrefixes = [env objectForKey:@"GNUSTEP_PATHPREFIX_LIST"];
+    if (pathPrefixes == nil)
+       pathPrefixes = [env objectForKey:@"GNUSTEP_PATHLIST"];
+    
+    if (pathPrefixes) {
+#  if defined(__MINGW32__)
+        pathPrefixes = [pathPrefixes componentsSeparatedByString:@";"];
+#  else
+        pathPrefixes = [pathPrefixes componentsSeparatedByString:@":"];
+#  endif
+
+        pathPrefixes = [pathPrefixes objectEnumerator];
+        while ((value = [pathPrefixes nextObject])) {
+            value = [value stringByAppendingPathComponent:@"Apps"];
+            [result addObject:value];
+        }
+    }
+    else {
+        value = [env objectForKey:@"GNUSTEP_USER_ROOT"];
+        value = [value stringByAppendingPathComponent:@"Apps"];
+        if (value) [result addObject:value];
+        value = [env objectForKey:@"GNUSTEP_LOCAL_ROOT"];
+        value = [value stringByAppendingPathComponent:@"Apps"];
+        if (value) [result addObject:value];
+        value = [env objectForKey:@"GNUSTEP_SYSTEM_ROOT"];
+        value = [value stringByAppendingPathComponent:@"Apps"];
+        if (value) [result addObject:value];
+    }
+    
+    [result addObject:@"/usr/local/bin"];
+    [result addObject:@"/usr/bin"];
+    
+    return AUTORELEASE([result copy]);
+#else
+#  if defined(__MINGW32__)
+    return [NSArray arrayWithObject:
+                    [NSOpenStepRootDirectory() stringByAppendingPathComponent:
+                                            @"Programs"]];
+#else
+    return [NSArray arrayWithObject:@"/usr/local/bin"];
+#endif
+#endif
+}
+
+extern NSArray *
+NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory _directory,
+                                    NSSearchPathDomainMask _mask,
+                                    BOOL _expandTilde)
+{
+#if WITH_GNUSTEP
+    NSMutableArray *domainRoots = nil;
+    NSMutableArray *results     = nil;
+    NSDictionary   *env;
+    NSString       *path = nil;
+    int            idx, count;
+
+    env  = [[NSProcessInfo processInfo] environment];
+    if (_directory == NSUserDirectory) {
+        /* The home-directories (eg /Local/Users, /Network/Users) */
+        return [NSArray arrayWithObject:
+                  [NSHomeDirectory() stringByDeletingLastPathComponent]];
+    }
+    
+    /* collect root directories of domains selected with mask */
+
+    domainRoots = [NSMutableArray arrayWithCapacity:8];
+
+    if (_mask == NSAllDomainsMask) {
+        id pathPrefixes = nil;
+
+       pathPrefixes = [env objectForKey:@"GNUSTEP_PATHPREFIX_LIST"];
+       if (pathPrefixes == nil)
+           pathPrefixes = [env objectForKey:@"GNUSTEP_PATHLIST"];
+       
+        if (pathPrefixes != nil) {
+#  if defined(__MINGW32__)
+            pathPrefixes = [pathPrefixes componentsSeparatedByString:@";"];
+#  else
+            pathPrefixes = [pathPrefixes componentsSeparatedByString:@":"];
+#  endif
+            [domainRoots addObjectsFromArray:pathPrefixes];
+        }
+    }
+    if (_mask & NSUserDomainMask) {
+        if ((path = [env objectForKey:@"GNUSTEP_USER_ROOT"])) {
+            if (![domainRoots containsObject:path])
+                [domainRoots addObject:path];
+        }
+    }
+    if (_mask & NSLocalDomainMask) {
+        if ((path = [env objectForKey:@"GNUSTEP_LOCAL_ROOT"])) {
+            if (![domainRoots containsObject:path])
+                [domainRoots addObject:path];
+        }
+       if (![domainRoots containsObject:@"/usr/local"])
+           [domainRoots addObject:@"/usr/local"];
+    }
+    if (_mask & NSNetworkDomainMask) {
+        if ((path = [env objectForKey:@"GNUSTEP_NETWORK_ROOT"])) {
+            if (![domainRoots containsObject:path])
+                [domainRoots addObject:path];
+        }
+    }
+    if (_mask & NSSystemDomainMask) {
+        if ((path = [env objectForKey:@"GNUSTEP_SYSTEM_ROOT"])) {
+            if (![domainRoots containsObject:path])
+                [domainRoots addObject:path];
+        }
+       if (![domainRoots containsObject:@"/usr"])
+           [domainRoots addObject:@"/usr"];
+    }
+
+    /* no join the specified directories with the domains */
+
+    results = [NSMutableArray arrayWithCapacity:64];
+
+    for (idx = 0, count = [domainRoots count]; idx < count; idx++) {
+        path = [domainRoots objectAtIndex:idx];
+        
+        switch (_directory) {
+            case NSApplicationDirectory:
+            case NSAllApplicationDirectory:
+                [results addObject:
+                           [path stringByAppendingPathComponent:@"Apps"]];
+                break;
+            
+            case NSLibraryDirectory:
+            case NSAllLibrariesDirectory:
+                [results addObject:
+                           [path stringByAppendingPathComponent:@"Library"]];
+                break;
+
+            default:
+                break;
+        }
+    }
+    return results;
+#else
+    switch (_directory) {
+        case NSApplicationDirectory:
+        case NSAllApplicationDirectory:
+            return NSStandardApplicationPaths();
+            
+        case NSLibraryDirectory:
+        case NSAllLibrariesDirectory:
+            return NSStandardLibraryPaths();
+
+        case NSUserDirectory:
+            /* The home-directories (eg /Local/Users, /Network/Users) */
+            return [NSArray arrayWithObject:
+                      [NSHomeDirectory() stringByDeletingLastPathComponent]];
+            
+        default:
+            return nil;
+    }
+#endif
+}
+
+NSString *NSHomeDirectoryForUser(NSString* userName)
+{
+    return [[NSUserAccount accountWithName:userName] homeDirectory];
+}
+
+NSString *NSFullUserName()
+{
+    return [[NSUserAccount currentAccount] fullName];
+}
+
+NSString *NSTemporaryDirectory()
+{
+#if defined(__MINGW32__)
+    // should use 'DWORD GetTempPath(DWORD len, LPTSTR path)'
+    return @"C:\\TEMP";
+#else
+    return @"/tmp";
+#endif
+}
+
+/*
+ * String file naming functions
+ */
+
+#if defined(__MINGW32__)
+static NSString *pathSeparator = @"\\";
+#else
+static NSString *pathSeparator = @"/";
+#endif
+static NSString *extensionSeparator = @".";
+static NSString *nullSeparator = @"";
+static NSString *homeSeparator = @"~";
+static NSString *parentDirName = @"..";
+static NSString *selfDirName = @".";
+
+// WIN32 - must be @"C:/" on WINDOWS
+#if defined(__MINGW32__)
+static NSString *rootPath = @"C:\\";
+#else
+static NSString *rootPath = @"/";
+#endif
+
+@implementation NSString(FilePathMethods)
+
++ (NSString *)pathWithComponents:(NSArray *)components
+{
+    id str, result;
+    int n = [components count];
+    int i = 0;
+    BOOL previousIsPathSeparator = NO;
+    
+    if (!n)
+       return nullSeparator;
+    
+    result = AUTORELEASE([[NSMutableString alloc] init]);
+    
+    str = [components objectAtIndex:0];
+    if ([str isEqualToString:nullSeparator] || 
+       [str isEqualToString:pathSeparator]) {
+           [result appendString:rootPath];
+           previousIsPathSeparator = YES;
+    }
+    else
+       [result appendString:str];
+    
+    for (i = 1; i < n; i++) {
+        str = [components objectAtIndex:i];
+        
+       if (([str isEqualToString:nullSeparator]
+            || [str isEqualToString:pathSeparator])
+           && !previousIsPathSeparator) {
+           [result appendString:pathSeparator];
+           previousIsPathSeparator = YES;
+       }
+       else {
+           if (!previousIsPathSeparator)
+               [result appendString:pathSeparator];
+
+           [result appendString:[components objectAtIndex:i]];
+           previousIsPathSeparator = NO;
+       }
+    }
+
+    return result;
+}
+
+- (NSArray *)pathComponents
+{
+    NSMutableArray* components
+       = [[self componentsSeparatedByString:pathSeparator] mutableCopy];
+    int i;
+    
+    for (i = [components count]-1; i >= 0; i--)
+       if ([[components objectAtIndex:i] isEqual:nullSeparator])
+           [components removeObjectAtIndex:i];
+    
+    if ([self hasPrefix:pathSeparator])
+       [components insertObject:pathSeparator atIndex:0];
+
+    if ([self hasSuffix:pathSeparator])
+       [components addObject:nullSeparator];
+
+    return components;
+}
+
+- (unsigned int)completePathIntoString:(NSString **)outputName
+  caseSensitive:(BOOL)flag matchesIntoArray:(NSArray **)outputArray
+  filterTypes:(NSArray *)filterTypes
+{
+    // TODO
+    [self notImplemented:_cmd];
+    return 0;
+}
+
+- (const char *)fileSystemRepresentation
+{
+    // WIN32
+    return [self cString];
+}
+
+- (BOOL)getFileSystemRepresentation:(char *)buffer
+  maxLength:(unsigned int)maxLength
+{
+    // WIN32
+    NSRange left;
+    
+    [self getCString:buffer maxLength:maxLength
+       range:NSMakeRange(0, [self length]) remainingRange:&left];
+    return (left.length == 0) ? YES : NO;
+}
+
+- (BOOL)isAbsolutePath
+{
+    if (![self length])
+       return NO;
+
+#if defined(__MINGW32__)
+    if ([self indexOfString:@":"] != NSNotFound)
+        return YES;
+#endif
+    if ([self hasPrefix:rootPath] || [self hasPrefix:@"~"])
+       return YES;
+
+    return NO;
+}
+
+- (NSString *)lastPathComponent
+{
+    NSRange sepRange;
+    NSRange lastRange = { 0, 0 };
+    
+    lastRange.length = [self length];
+    if ([self hasSuffix:pathSeparator]) {
+       if (lastRange.length == [pathSeparator length])
+           return nullSeparator;
+
+       lastRange.length--;
+    }
+
+    sepRange = [self rangeOfString:pathSeparator
+                    options:NSBackwardsSearch range:lastRange];
+    if (sepRange.length == 0)
+       return AUTORELEASE([self copyWithZone:[self zone]]);
+    
+    lastRange.location = sepRange.location + sepRange.length;
+    lastRange.length   = lastRange.length - lastRange.location;
+    
+    if (lastRange.location == 0)
+       return AUTORELEASE([self copyWithZone:[self zone]]);
+    else
+       return lastRange.length ? 
+           [self substringWithRange:lastRange] : nullSeparator;
+}
+
+- (NSString *)pathExtension
+{
+    NSRange  sepRange, lastRange;
+    NSString *lastComponent;
+    int      length;
+
+    lastComponent = [self lastPathComponent];
+    length        = [lastComponent length];
+    
+    sepRange = [lastComponent rangeOfString:extensionSeparator 
+                             options:NSBackwardsSearch];
+    if (sepRange.length == 0)
+       return @"";
+    
+    lastRange.location = sepRange.location + sepRange.length;
+    lastRange.length   = length - lastRange.location;
+    
+    return lastRange.length && sepRange.length ? 
+       [lastComponent substringWithRange:lastRange] : nullSeparator;
+}
+
+- (NSString *)stringByAppendingPathComponent:(NSString *)aString
+{
+    NSString *str;
+    
+    str = [self hasSuffix:pathSeparator] ? nullSeparator : pathSeparator;
+    
+    return [aString length]
+        ? [self stringByAppendingString:
+                    ([self length]
+                     ? [str stringByAppendingString:aString] 
+                     : aString)]
+       : AUTORELEASE([self copyWithZone:[self zone]]);
+}
+
+- (NSArray *)stringsByAppendingPaths:(NSArray *)paths
+{
+    NSMutableArray *array;
+    int i, n;
+    
+    array = [NSMutableArray array];
+    
+    for (i = 0, n = [paths count]; i < n; i++) {
+       [array addObject:[self stringByAppendingPathComponent:
+           [paths objectAtIndex:i]]];
+    }
+    return array;
+}
+
+- (NSString *)stringByAppendingPathExtension:(NSString *)aString
+{
+    return [aString length]
+        ? [self stringByAppendingString:
+                    [extensionSeparator stringByAppendingString:aString]] 
+       : AUTORELEASE([self copyWithZone:[self zone]]);
+}
+
+- (NSString *)stringByDeletingLastPathComponent
+{
+    NSRange range = {0, [self length]};
+    
+    if (range.length == 0)
+       return nullSeparator;
+    
+    if ([self isEqualToString:pathSeparator])
+       return pathSeparator;
+    
+    range.length--;
+    range = [self rangeOfString:pathSeparator
+                  options:NSBackwardsSearch range:range];
+
+    if (range.length == 0)
+       return nullSeparator;
+    if (range.location == 0)
+       return pathSeparator;
+
+    return [self substringWithRange:NSMakeRange(0, range.location)];
+}
+
+- (NSString *)stringByDeletingPathExtension
+{
+    NSRange range = {0, [self length]};
+    NSRange extSep, patSep;
+    
+    if (range.length == 0)
+       return nullSeparator;
+    
+    if ([self hasSuffix:pathSeparator]) {
+       if (range.length == 1)
+           return AUTORELEASE([self copyWithZone:[self zone]]);
+       else
+           range.length--;
+    }
+    
+    extSep = [self rangeOfString:extensionSeparator
+                  options:NSBackwardsSearch range:range];
+
+    if (extSep.length != 0) {
+       patSep = [self rangeOfString:pathSeparator
+                      options:NSBackwardsSearch range:range];
+       if (patSep.length != 0) {
+           if (extSep.location > patSep.location + 1) {
+               range.length = extSep.location;
+           }
+           /* else the filename begins with a dot so don't consider it as
+              being an extension; do nothing */
+       }
+       else {
+           range.length = extSep.location;
+       }
+    }
+    
+    return [self substringWithRange:range];
+}
+
+- (NSString *)stringByAbbreviatingWithTildeInPath
+{
+    NSString *home;
+    int      homeLength;
+    
+    home       = NSHomeDirectory();
+    homeLength = [home length];
+    
+    if (![self hasPrefix:home])
+       return self;
+       
+    home = [self substringWithRange:
+                    NSMakeRange(homeLength, [self length] - homeLength)];
+    
+    return [homeSeparator stringByAppendingString:
+                             ([home length] > 0 ? home : pathSeparator)];
+}
+
+- (NSString *)stringByExpandingTildeInPath
+{
+    NSString *rest;
+    NSString *home;
+    unsigned int index;
+    unsigned int hlen;
+    
+    if (![self hasPrefix:homeSeparator])
+       return self;
+    
+    index = [self indexOfString:pathSeparator];
+    hlen  = [homeSeparator length];
+    
+    if (index == hlen)
+       home = NSHomeDirectory();
+    else {
+       home = NSHomeDirectoryForUser([self substringWithRange:
+           NSMakeRange(hlen, (index == NSNotFound) ?  
+               [self length] - hlen : index - hlen)]);
+    }
+    
+    if (index == NSNotFound)
+       rest = nullSeparator;
+    else
+       rest = [self substringWithRange:
+           NSMakeRange(index + 1, [self length] - index - 1)];
+    
+    return [home stringByAppendingPathComponent:rest];
+}
+
+- (NSString *)stringByResolvingSymlinksInPath
+{
+    // WIN32 - no symlinks; just convert and stat the path using real names
+#if defined(__MINGW32__)
+    return (GetFileAttributes([self cString]) != -1) ? self : nil;
+#else
+    extern char *resolve_symlinks_in_path(const char *, char *);
+    unsigned char resolved[PATH_MAX];
+    const char *source;
+    
+    if ((source = [self cString]) == NULL) {
+       fprintf(stderr, "ERROR(%s): did not get cString of string?!\n",
+               __PRETTY_FUNCTION__);
+       return nil;
+    }
+    if (!resolve_symlinks_in_path(source, resolved)) {
+        /* 
+          previously returned 'nil', which is wrong according to MacOSXS
+          Spec 
+       */
+#if 0
+       return nil;
+#else
+        return self;
+#endif
+    }
+    return [NSString stringWithCString:resolved];
+#endif
+}
+
+- (NSString *)stringByStandardizingPath
+{
+    if ([self isAbsolutePath])
+       return [self stringByResolvingSymlinksInPath];
+    
+    {
+#if defined(__MINGW32__)
+        unsigned char *buf = objc_atomic_malloc(2048);
+        DWORD         len;
+        LPTSTR        lastComponent;
+
+        len = GetFullPathName([self cString], 2046, buf, &lastComponent);
+        if (len > 2046) buf = objc_realloc(buf, len + 1);
+        len = GetFullPathName([self cString], len, buf, &lastComponent);
+
+       self = (len == 0) ? self : [NSString stringWithCString:buf length:len];
+       objc_free(buf);
+       return self;
+#else
+       NSString       *path;
+       NSMutableArray *components;
+       int            i, n;
+       
+        components = [[self pathComponents] mutableCopy];
+       n = [components count];
+       /* remove "//" and "/./" components */
+       for (i = n - 1; i >= 0; i--) {
+           NSString *comp;
+            
+            comp = [components objectAtIndex:i];
+           
+           if ([comp length] == 0 || [comp isEqualToString:selfDirName]) {
+               [components removeObjectAtIndex:i];
+               continue;
+           }
+       }
+        
+       /* compact ".../dir1/../dir2/..." into ".../dir2/..." */
+        n = [components count];
+       for (i = 1; i < n; i++) {
+           if ([[components objectAtIndex:i] isEqualToString:parentDirName] 
+               && i > 0 &&
+            ![[components objectAtIndex:i-1] isEqualToString:parentDirName]) {
+               i -= 1;
+               [components removeObjectAtIndex:i];
+               [components removeObjectAtIndex:i];
+           }
+       }
+       
+       path = [NSString pathWithComponents:components];
+       RELEASE(components);
+       
+       return path ? path : self;
+#endif
+    }
+}
+
+@end /* NSString(FilePathMethods) */
+
+@implementation NSArray(FilePathMethods)
+
+- (NSArray *)pathsMatchingExtensions:(NSArray *)_exts
+{
+    /* new in MacOSX */
+    NSSet          *exts;
+    NSEnumerator   *e;
+    NSString       *path;
+    NSMutableArray *ma;
+    
+    exts = [[NSSet alloc] initWithArray:_exts];
+    ma   = [[NSMutableArray alloc] init];
+    
+    e = [self objectEnumerator];
+    while ((path = [e nextObject])) {
+        if ([exts containsObject:[path pathExtension]])
+            [ma addObject:path];
+    }
+    RELEASE(exts); exts = nil;
+    
+    self = [ma copy];
+    RELEASE(ma);
+    return AUTORELEASE(self);
+}
+
+@end /* NSArray(FilePathMethods) */
+
+/*
+ * Used for forcing linking of this category
+ */
+
+void __dummyNSStringFilePathfile ()
+{
+    __dummyNSStringFilePathfile();
+}
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSPipe.m b/libFoundation/Foundation/NSPipe.m
new file mode 100644 (file)
index 0000000..f2236fb
--- /dev/null
@@ -0,0 +1,125 @@
+/* 
+   NSPipe.m
+
+   Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@net-community.com>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <errno.h>
+
+#include <Foundation/common.h>
+#include <Foundation/NSFileHandle.h>
+#include <Foundation/NSConcreteFileHandle.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSUtilities.h>
+
+#if defined(__MINGW32__)
+#define pipe _pipe
+#endif
+
+@interface NSConcretePipe : NSPipe
+{
+    NSFileHandle *_readFd;
+    NSFileHandle *_writeFd;
+}
+@end
+
+
+@implementation NSConcretePipe
+
+- (NSFileHandle *)fileHandleForReading
+{
+    return _readFd;
+}
+- (NSFileHandle *)fileHandleForWriting
+{
+    return _writeFd;
+}
+
+- (id)init
+{
+#if !defined(__MINGW32__)
+    int fildes[2];
+
+    if (pipe(fildes) == -1) {
+       NSLog (@"pipe system call failed: %s", strerror (errno));
+       (void)AUTORELEASE(self);
+       return nil;
+    }
+    _readFd = [[NSConcretePipeFileHandle alloc] initWithFileDescriptor:fildes[0]
+                                                closeOnDealloc:YES];
+    _writeFd = [[NSConcretePipeFileHandle alloc] initWithFileDescriptor:fildes[1]
+                                                 closeOnDealloc:YES];
+#else
+    BOOL ok;
+    HANDLE reading, writing;
+    
+    ok = CreatePipe(&reading, &writing, NULL, 0);
+    NSAssert(ok, @"couldn't create pipe !");
+
+    _readFd  = [[NSFileHandle alloc] initWithFileHandle:reading];
+    _writeFd = [[NSFileHandle alloc] initWithFileHandle:writing];
+#endif
+    
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(_readFd);
+    RELEASE(_writeFd);
+    [super dealloc];
+}
+
+@end
+
+@implementation NSPipe
+
++ (id)pipe
+{
+    return AUTORELEASE([[NSConcretePipe alloc] init]);
+}
+
+- (NSFileHandle *)fileHandleForReading
+{
+    [self shouldNotImplement:_cmd];
+    return nil;
+}
+
+- (NSFileHandle *)fileHandleForWriting
+{
+    [self shouldNotImplement:_cmd];
+    return nil;
+}
+
+- (id)init
+{
+    [self shouldNotImplement:_cmd];
+    return nil;
+}
+
+@end
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSPort.h b/libFoundation/Foundation/NSPort.h
new file mode 100644 (file)
index 0000000..61c788b
--- /dev/null
@@ -0,0 +1,142 @@
+/* 
+   NSPort.h
+
+   Copyright (C) 1999 Helge Hess.
+   All rights reserved.
+
+   Author: Helge Hess <hh@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSPort_H__
+#define __NSPort_H__
+
+#include <Foundation/NSObject.h>
+#if defined(WIN32)
+#  include <windows.h>
+#  include <winsock.h>
+typedef SOCKET NSSocketNativeHandle;
+#else
+typedef int NSSocketNativeHandle;
+#endif
+
+@class NSDate, NSMutableArray, NSPortMessage, NSData;
+
+@interface NSPort : NSObject < NSCoding, NSCopying >
+
+/* port creation */
+
++ (NSPort *)port;
++ (NSPort *)portWithMachPort:(int)aMachPort;
+- (id)init;
+- (id)initWithMachPort:(int)aMachPort;
+
+/* mach port */
+
+- (int)machPort;
+
+/* delegate */
+
+- (void)setDelegate:(id)anObject;
+- (id)delegate;
+
+/* validation */
+
+- (void)invalidate;
+- (BOOL)isValid;
+
+/* sending messages */
+
+- (BOOL)sendBeforeDate:(NSDate *)limitDate
+  components:(NSMutableArray *)components
+  from:(NSPort *)receivePort
+  reserved:(unsigned)headerSpaceReserved;
+
+- (BOOL)sendBeforeDate:(NSDate *)limitDate
+  msgid:(unsigned)_msgid
+  components:(NSMutableArray *)components
+  from:(NSPort *)receivePort
+  reserved:(unsigned)headerSpaceReserved;
+
+- (unsigned)reservedSpaceLength;
+
+@end
+
+@interface NSObject(NSPortDelegate)
+
+- (void)handleMachMessage:(void *)aMachMessage;
+- (void)handlePortMessage:(NSPortMessage *)aPortMessage;
+
+@end
+
+LF_EXPORT NSString *NSPortDidBecomeInvalidNotification;
+
+/*
+  Concrete subclass of NSPort for local connections only.
+*/
+
+@interface NSMessagePort : NSPort
+@end
+
+/*
+  Concrete subclass of NSPort for socket connections.
+*/
+
+@interface NSSocketPort : NSPort
+{
+@private
+  NSSocketNativeHandle sd;
+  int protocol;
+  int type;
+  int family;
+}
+
+- (id)init;
+- (id)initWithTCPPort:(unsigned short)_port;
+- (id)initRemoteWithTCPPort:(unsigned short)_port;
+
+- (id)initWithProtocolFamily:(int)_family
+  socketType:(int)_type
+  protocol:(int)_protocol
+  address:(NSData *)_address;
+- (id)initRemoteWithProtocolFamily:(int)_family
+  socketType:(int)_type
+  protocol:(int)_protocol
+  address:(NSData *)_address;
+
+- (id)initWithProtocolFamily:(int)_family
+  socketType:(int)_type
+  protocol:(int)_protocol
+  socket:(NSSocketNativeHandle)_handle;
+
+/* accessors */
+
+- (int)protocol;
+- (int)protocolFamily;
+- (int)socketType;
+- (NSSocketNativeHandle)socket;
+
+@end
+
+#endif /* __NSPort_H__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSPort.m b/libFoundation/Foundation/NSPort.m
new file mode 100644 (file)
index 0000000..59d4655
--- /dev/null
@@ -0,0 +1,137 @@
+/* 
+   NSPort.m
+
+   Copyright (C) 1999 Helge Hess.
+   All rights reserved.
+
+   Author: Helge Hess <hh@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSPort.h>
+#include <Foundation/NSString.h>
+#include <common.h>
+
+@implementation NSPort
+
+/* port creation */
+
++ (NSPort *)port
+{
+    return [self notImplemented:_cmd];
+}
++ (NSPort *)portWithMachPort:(int)aMachPort
+{
+    return [self notImplemented:_cmd];
+}
+
+- (id)init
+{
+    return [self notImplemented:_cmd];
+}
+- (id)initWithMachPort:(int)aMachPort
+{
+    return [self notImplemented:_cmd];
+}
+
+/* mach port */
+
+- (int)machPort
+{
+    [self notImplemented:_cmd];
+    return -1;
+}
+
+/* delegate */
+
+- (void)setDelegate:(id)anObject
+{
+    [self notImplemented:_cmd];
+}
+- (id)delegate
+{
+    return [self notImplemented:_cmd];
+}
+
+/* validation */
+
+- (void)invalidate
+{
+    [self notImplemented:_cmd];
+}
+- (BOOL)isValid
+{
+    [self notImplemented:_cmd];
+    return NO;
+}
+
+/* sending messages */
+
+- (BOOL)sendBeforeDate:(NSDate *)limitDate
+  components:(NSMutableArray *)components
+  from:(NSPort *)receivePort
+  reserved:(unsigned)headerSpaceReserved
+{
+    [self notImplemented:_cmd];
+    return NO;
+}
+- (BOOL)sendBeforeDate:(NSDate *)limitDate
+  msgid:(unsigned)_msgid
+  components:(NSMutableArray *)components
+  from:(NSPort *)receivePort
+  reserved:(unsigned)headerSpaceReserved
+{
+    [self notImplemented:_cmd];
+    return NO;
+}
+
+- (unsigned)reservedSpaceLength
+{
+    [self notImplemented:_cmd];
+    return 0;
+}
+
+/* NSCoding */
+
+- (void)encodeWithCoder:(NSCoder *)_coder
+{
+    [self notImplemented:_cmd];
+}
+
+- (id)initWithCoder:(NSCoder *)_coder
+{
+    return [self notImplemented:_cmd];
+}
+
+/* NSCopying */
+
+- (id)copyWithZone:(NSZone *)_zone
+{
+    return RETAIN(self);
+}
+
+@end
+
+LF_DECLARE NSString *NSPortDidBecomeInvalidNotification =
+  @"NSPortDidBecomeInvalidNotificationName";
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSPortCoder.h b/libFoundation/Foundation/NSPortCoder.h
new file mode 100644 (file)
index 0000000..b852885
--- /dev/null
@@ -0,0 +1,40 @@
+/* 
+   NSPortCoder.h
+
+   Copyright (C) 2000 MDlink GmbH, Helge Hess.
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSPortCoder_H__
+#define __NSPortCoder_H__
+
+#include <Foundation/NSObject.h>
+
+@interface NSPortCoder : NSObject
+@end
+
+#endif /* __NSPortCoder_H__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSPortCoder.m b/libFoundation/Foundation/NSPortCoder.m
new file mode 100644 (file)
index 0000000..a131eb9
--- /dev/null
@@ -0,0 +1,35 @@
+/* 
+   NSPortCoder.m
+
+   Copyright (C) 2000 MDlink GmbH, Helge Hess.
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSPortCoder.h>
+
+@implementation NSPortCoder
+@end /* NSPortCoder */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSPortMessage.h b/libFoundation/Foundation/NSPortMessage.h
new file mode 100644 (file)
index 0000000..09e250b
--- /dev/null
@@ -0,0 +1,75 @@
+/* 
+   NSPortMessage.h
+
+   Copyright (C) 1999 Helge Hess.
+   All rights reserved.
+
+   Author: Helge Hess <hh@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSPortMessage_H__
+#define __NSPortMessage_H__
+
+#include <Foundation/NSObject.h>
+
+@class NSArray, NSDate, NSPort;
+
+@interface NSPortMessage : NSObject
+{
+    NSArray      *components;
+    NSPort       *sendPort;
+    NSPort       *receivePort;
+    unsigned int msgId;
+}
+
+/* message creation */
+
+- (id)initWithMachMessage:(void *)aMsg;
+
+- (id)initWithSendPort:(NSPort *)aSendPort
+  receivePort:(NSPort *)aReceivePort
+  components:(NSArray *)components;
+
+/* getting message components (NSData's or NSPort's) */
+
+- (NSArray *)components;
+
+/* identification */
+
+- (void)setMsgid:(unsigned int)aMsgId;
+- (unsigned int)msgid;
+
+/* ports */
+
+- (NSPort *)sendPort;
+- (NSPort *)receivePort;
+
+/* send message */
+
+- (BOOL)sendBeforeDate:(NSDate *)limitDate;
+
+@end
+
+#endif /* __NSPortMessage_H__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSPortMessage.m b/libFoundation/Foundation/NSPortMessage.m
new file mode 100644 (file)
index 0000000..df6f38b
--- /dev/null
@@ -0,0 +1,103 @@
+/* 
+   NSPortMessage.m
+
+   Copyright (C) 1999 Helge Hess.
+   All rights reserved.
+
+   Author: Helge Hess <hh@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSPortMessage.h>
+#include <Foundation/NSPort.h>
+#include <Foundation/NSArray.h>
+
+@implementation NSPortMessage
+
+/* message creation */
+
+- (id)initWithMachMessage:(void *)aMsg
+{
+    return [self notImplemented:_cmd];
+}
+
+- (id)initWithSendPort:(NSPort *)aSendPort
+  receivePort:(NSPort *)aReceivePort
+  components:(NSArray *)_components
+{
+    self->components  = RETAIN(_components);
+    self->sendPort    = RETAIN(aSendPort);
+    self->receivePort = RETAIN(aReceivePort);
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(self->components);
+    RELEASE(self->sendPort);
+    RELEASE(self->receivePort);
+    [super dealloc];
+}
+
+/* getting message components (NSData's or NSPort's) */
+
+- (NSArray *)components
+{
+    return self->components;
+}
+
+/* identification */
+
+- (void)setMsgid:(unsigned int)aMsgId
+{
+    self->msgId = aMsgId;
+}
+- (unsigned int)msgid
+{
+    return self->msgId;
+}
+
+/* ports */
+
+- (NSPort *)sendPort
+{
+    return self->sendPort;
+}
+- (NSPort *)receivePort
+{
+    return self->receivePort;
+}
+
+/* send message */
+
+- (BOOL)sendBeforeDate:(NSDate *)limitDate
+{
+    return [self->receivePort sendBeforeDate:limitDate
+                              components:
+                                AUTORELEASE([self->components mutableCopy])
+                              from:self->sendPort
+                              reserved:0];
+}
+
+@end
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSPortNameServer.h b/libFoundation/Foundation/NSPortNameServer.h
new file mode 100644 (file)
index 0000000..1d5c61f
--- /dev/null
@@ -0,0 +1,63 @@
+/* 
+   NSPortNameServer.h
+
+   Copyright (C) 1999 Helge Hess.
+   All rights reserved.
+
+   Author: Helge Hess <hh@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSPortNameServer_H__
+#define __NSPortNameServer_H__
+
+#include <Foundation/NSObject.h>
+
+@class NSPort, NSString;
+
+@interface NSPortNameServer : NSObject
+
++ (id)defaultPortNameServer;
+
+/* port registry */
+
+- (BOOL)registerPort:(NSPort *)aPort forName:(NSString *)aPortName;
+- (void)removePortForName:(NSString *)aPortName;
+
+/* port lookup */
+
+- (NSPort *)portForName:(NSString *)aPortName onHost:(NSString *)aHostName;
+- (NSPort *)portForName:(NSString *)aPortName;
+
+@end
+
+/* concrete name server for local ports (NSMessagePort instances) */
+
+@interface NSMessagePortNameServer : NSPortNameServer
+
++ (id)sharedInstance;
+
+@end
+
+#endif /* __NSPortNameServer_H__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSPortNameServer.m b/libFoundation/Foundation/NSPortNameServer.m
new file mode 100644 (file)
index 0000000..3f1e657
--- /dev/null
@@ -0,0 +1,93 @@
+/* 
+   NSPortNameServer.m
+
+   Copyright (C) 1999 Helge Hess.
+   All rights reserved.
+
+   Author: Helge Hess <hh@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include "NSPortNameServer.h"
+#include <Foundation/NSLock.h>
+#include <Foundation/NSException.h>
+
+extern NSRecursiveLock *libFoundationLock;
+
+@implementation NSPortNameServer
+
++ (id)defaultPortNameServer
+{
+    return [self notImplemented:_cmd];
+}
+
+/* port registry */
+
+- (BOOL)registerPort:(NSPort *)aPort forName:(NSString *)aPortName
+{
+    [self notImplemented:_cmd];
+    return NO;
+}
+- (void)removePortForName:(NSString *)aPortName
+{
+    [self notImplemented:_cmd];
+}
+
+/* port lookup */
+
+- (NSPort *)portForName:(NSString *)aPortName onHost:(NSString *)aHostName
+{
+    return [self notImplemented:_cmd];
+}
+
+- (NSPort *)portForName:(NSString *)aPortName
+{
+    return [self portForName:aPortName onHost:nil];
+}
+
+@end /* NSPortNameServer */
+
+@implementation NSMessagePortNameServer : NSPortNameServer
+
++ (id)sharedInstance
+{
+    static id si = nil;
+    
+    [libFoundationLock lock];
+    if (si == nil)
+        si = [[NSMessagePortNameServer alloc] init];
+    [libFoundationLock unlock];
+    
+    return si;
+}
+
+/* port lookup */
+
+- (NSPort *)portForName:(NSString *)aPortName onHost:(NSString *)aHostName
+{
+    NSAssert(aHostName == nil, @"local ports only, hostname must be nil !");
+    return [self notImplemented:_cmd];
+}
+
+@end
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSPosixFileDescriptor.h b/libFoundation/Foundation/NSPosixFileDescriptor.h
new file mode 100644 (file)
index 0000000..074414f
--- /dev/null
@@ -0,0 +1,129 @@
+/* 
+   NSPosixFileDescriptor.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSPosixFileDescriptor_h__
+#define __NSPosixFileDescriptor_h__
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <Foundation/NSObject.h>
+#include <Foundation/NSRange.h>
+
+@class NSData;
+@class NSString;
+
+typedef enum {
+    NSPosixNoActivity = 0,
+    NSPosixReadableActivity = 1,
+    NSPosixWritableActivity = 2,
+    NSPosixExceptionalActivity = 4
+} NSPosixFileActivities;
+
+@interface NSPosixFileDescriptor : NSObject
+{
+    int      fd;
+    id       delegate;
+    unsigned fileActivity;
+    BOOL     owned;
+}
+
+// Getting a standard NSPosixFileDescriptor
+
++ (id)descriptorWithStandardInput;
++ (id)descriptorWithStandardOutput;
++ (id)descriptorWithStandardError;
+
+// Initialize
+
+- (id)initWithFileDescriptor:(int)fileDescriptor;
+- (id)initWithPath:(NSString*)aPath;
+- (id)initWithPath:(NSString*)aPath flags:(int)flags;
+- (id)initWithPath:(NSString*)aPath flags:(int)flags createMode:(int)mode;
+
+// Get FD
+
+- (int)fileDescriptor;
+
+// Read
+
+- (NSData *)readEntireFile;
+- (NSData *)readFileRange:(NSRange)aRange;
+- (NSData *)readFileLength:(long)length;
+- (NSData *)readRestOfFile;
+- (void)readBytes:(void*)bytes range:(NSRange)range;
+
+// Write
+
+- (void)writeData:(NSData*)aData;
+- (void)writeData:(NSData*)aData range:(NSRange)aRange;
+- (void)writeString:(NSString*)string;
+- (void)writeString:(NSString*)string range:(NSRange)aRange;
+
+// Seek & Truncate
+
+- (int unsigned)fileLength;
+- (int unsigned)filePosition;
+- (void)seekToEnd;
+- (void)seekToPosition:(long)aPosition;
+- (void)truncateAtPosition:(long)aPosition;
+
+// Mapping files to memory
+
+- (NSData *)mapFileRange:(NSRange)range;
+- (void)synchronizeFile;
+
+// Monitoring file descriptors
+
+- (void)monitorFileActivity:(NSPosixFileActivities)activity;
+- (void)monitorActivity:(NSPosixFileActivities)activity delegate:(id)delegate;
+- (void)ceaseMonitoringFileActivity;
+- (NSPosixFileActivities)fileActivity;
+
+// File descriptor delegate
+
+- (id)delegate;
+- (void)setDelegate:(id)delegate;
+
+@end /* NSPosixFileDescriptor */
+
+
+@interface NSObject (NSPosixFileDescriptorDelegateMethod)
+
+- (void)activity:(NSPosixFileActivities)activity
+  posixFileDescriptor:(NSPosixFileDescriptor *)fileDescriptor;
+
+@end
+
+LF_EXPORT NSString *NSPosixFileOperationException;
+
+#endif /* __NSPosixFileDescriptor_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSPosixFileDescriptor.m b/libFoundation/Foundation/NSPosixFileDescriptor.m
new file mode 100644 (file)
index 0000000..e3849dc
--- /dev/null
@@ -0,0 +1,419 @@
+/* 
+   NSPosixFileDescriptor.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <errno.h>
+#include <stdio.h>
+
+#if defined(__MINGW32__)
+# include <windows.h>
+# include <winsock.h>
+#else
+# include <sys/ioctl.h>
+#endif
+
+#include <Foundation/common.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSData.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSPosixFileDescriptor.h>
+#include <Foundation/NSRunLoop.h>
+#include <Foundation/NSPathUtilities.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+
+#include "NSMappedData.h"
+
+@implementation NSPosixFileDescriptor
+
+// Getting a standard NSPosixFileDescriptor
+
+static NSPosixFileDescriptor* descriptorForStandardInput = nil;
+static NSPosixFileDescriptor* descriptorForStandardOutput = nil;
+static NSPosixFileDescriptor* descriptorForStandardError = nil;
+
++ (void)initialize
+{
+    if (!descriptorForStandardInput)
+       descriptorForStandardInput = [[self alloc] 
+           initWithFileDescriptor:fileno(stdin)];
+    if (!descriptorForStandardOutput)
+       descriptorForStandardOutput = [[self alloc] 
+           initWithFileDescriptor:fileno(stdout)];
+    if (!descriptorForStandardError)
+       descriptorForStandardError = [[self alloc] 
+           initWithFileDescriptor:fileno(stderr)];
+}
+
++ (id)descriptorWithStandardInput
+{
+    return descriptorForStandardInput;
+}
+
++ (id)descriptorWithStandardOutput
+{
+    return descriptorForStandardOutput;
+}
+
++ (id)descriptorWithStandardError
+{
+    return descriptorForStandardError;
+}
+
+// Initialize
+
+- (id)initWithFileDescriptor:(int)fileDescriptor
+{
+    fd = fileDescriptor;
+    owned = NO;
+    return self;
+}
+
+- (id)initWithCStringPath:(const char*)aPath flags:(int)someFlags 
+  createMode:(int)someMode
+{
+    fd = open(aPath, someFlags, someMode);
+    if (fd == -1) {
+#if DEBUG
+        NSLog(@"%s: couldn't open file '%s': %s", __PRETTY_FUNCTION__,
+              aPath, strerror(errno));
+#endif
+       (void)RELEASE(self);
+       return nil;
+    }
+    owned = YES;
+    return self;
+}
+
+- (id)initWithPath:(NSString*)aPath
+{
+    return [self initWithCStringPath:[aPath fileSystemRepresentation] 
+           flags:O_RDONLY createMode:0];
+}
+
+- (id)initWithPath:(NSString*)aPath flags:(int)someFlags
+{
+    return [self initWithCStringPath:[aPath fileSystemRepresentation] 
+           flags:someFlags createMode:0];
+}
+
+- (id)initWithPath:(NSString*)aPath flags:(int)someFlags 
+  createMode:(int)someMode
+{
+    return [self initWithCStringPath:[aPath fileSystemRepresentation] 
+           flags:someFlags createMode:someMode];
+}
+
+- (void)dealloc
+{
+  if (owned)
+    close (fd);
+  [super dealloc];
+}
+
+// Get FD
+
+- (int)fileDescriptor
+{
+    return self->fd;
+}
+
+// Read
+
+- (NSData *)readEntireFile
+{
+    NSRange range;
+    off_t   ret;
+    
+    if ((ret = lseek(fd, 0, SEEK_END)) == -1) {
+        /* lseek failed */
+       [[[PosixFileOperationException alloc]
+           initWithFormat:@"could not lseek to end"] raise];
+    }
+    range.location = 0;
+    range.length   = ret;
+    return [self readFileRange:range]; 
+}
+
+- (NSData *)readRestOfFile
+{
+    NSRange range;
+    off_t   ret;
+
+    if ((ret = lseek(fd, 0, SEEK_CUR)) == -1) {
+        /* lseek failed */
+       [[[PosixFileOperationException alloc]
+           initWithFormat:@"could not lseek to cur"] raise];
+    }
+    else
+        range.location = ret;
+
+    if ((ret = lseek(fd, 0, SEEK_END)) == -1) {
+        /* lseek failed */
+       [[[PosixFileOperationException alloc]
+           initWithFormat:@"could not lseek to end"] raise];
+    }
+    else
+        range.location = ret - range.location;
+    
+    return [self readFileRange:range];
+}
+
+- (NSData *)readFileRange:(NSRange)range
+{      
+    void  *bytes;
+    off_t ret;
+    
+    bytes = MallocAtomic(range.length);
+    
+    if ((ret = lseek(fd, range.location, SEEK_SET)) == -1) {
+        /* lseek failed */
+       [[[PosixFileOperationException alloc]
+           initWithFormat:@"could not lseek set"] raise];
+    }
+    
+    if (read(fd, bytes, range.length) != (int)range.length) {
+       lfFree(bytes);
+       [[[PosixFileOperationException alloc]
+           initWithFormat:@"could not read %d bytes", range.length] raise];
+    }
+    
+    return AUTORELEASE([[NSData alloc]
+                           initWithBytesNoCopy:bytes length:range.length]);
+}
+
+- (void)readBytes:(void *)bytes range:(NSRange)range
+{
+    off_t ret;
+    
+    if ((ret = lseek(fd, range.location, SEEK_SET)) == -1) {
+        /* lseek failed */
+       [[[PosixFileOperationException alloc]
+           initWithFormat:@"could not lseek set"] raise];
+    }
+    
+    if (read(fd, bytes, range.length) != (int)range.length)
+       [[[PosixFileOperationException alloc]
+           initWithFormat:@"could not read %d bytes", range.length] raise];
+}
+
+- (NSData *)readFileLength:(long)length
+{
+    NSRange range;
+    off_t   ret;
+#if DEBUG
+    NSAssert(length >= 0, @"invalid length %i", length);
+#endif
+
+    if ((ret = lseek(fd, 0, SEEK_CUR)) == -1) {
+        /* lseek failed */
+       [[[PosixFileOperationException alloc]
+           initWithFormat:@"could not lseek cur"] raise];
+    }
+    range.location = ret;
+    range.length   = length;
+    
+    return [self readFileRange:range];
+}
+
+// Write
+
+- (void)writeData:(NSData*)aData
+{
+    NSRange range = {0, [aData length]};    
+    [self writeData:aData range:range];
+}
+
+- (void)writeData:(NSData*)aData range:(NSRange)range
+{
+    char *bytes;
+    
+    if (range.location + range.length > [aData length]) {
+       [[[RangeException alloc]
+               initWithReason:@"invalid range in NSData" size:[aData length] 
+                   index:range.location+range.length] raise];
+    }
+    
+    bytes = (char*)[aData bytes] + range.location;
+    if (write(fd, bytes, range.length) != (int)range.length) {
+       [[[PosixFileOperationException alloc]
+           initWithFormat:@"could not write %d bytes", range.length] raise];
+    }
+}
+
+- (void)writeString:(NSString*)string
+{
+    NSRange range = {0, [string cStringLength]};    
+    [self writeString:string range:range];
+}
+
+- (void)writeString:(NSString*)string range:(NSRange)range
+{
+    unsigned len = range.length;
+    char* bytes;
+    
+    if (range.location + range.length > [string cStringLength])
+       [[[RangeException alloc]
+               initWithReason:@"invalid range in NSString"
+                   size:[string cStringLength] 
+                   index:range.location + range.length] raise];
+    
+    bytes = (char*)[string cString] + range.location;
+    while (len > 0) {
+        int res = write(fd, bytes, len);
+
+        if (res == -1) {
+            [[[PosixFileOperationException alloc]
+                      initWithFormat:@"could not write %d bytes", len] raise];
+        }
+        len -= res;
+        bytes += res;
+    }
+}
+
+// Seek
+
+- (int unsigned)fileLength
+{
+    off_t cur, len, ret;
+    
+    if ((cur = lseek(fd, 0, SEEK_CUR)) == -1) {
+        /* lseek failed */
+       [[[PosixFileOperationException alloc]
+           initWithFormat:@"could not lseek to cur"] raise];
+    }
+    if ((len = lseek(fd, 0, SEEK_END)) == -1) {
+        /* lseek failed */
+       [[[PosixFileOperationException alloc]
+           initWithFormat:@"could not lseek to end"] raise];
+    }
+    
+    if ((ret = lseek(fd, cur, SEEK_SET)) == -1) {
+        /* lseek failed */
+       [[[PosixFileOperationException alloc]
+           initWithFormat:@"could not lseek set"] raise];
+    }
+    return len;
+}
+
+- (int unsigned)filePosition
+{
+    off_t ret;
+
+    if ((ret = lseek(fd, 0, SEEK_CUR)) == -1) {
+        /* lseek failed */
+       [[[PosixFileOperationException alloc]
+           initWithFormat:@"could not lseek to cur"] raise];
+    }
+    
+    return ret;
+}
+
+- (void)seekToEnd
+{
+    lseek(fd, 0, SEEK_END);
+}
+
+- (void)seekToPosition:(long)aPosition
+{
+    lseek(fd, aPosition, SEEK_SET);
+}
+
+- (void)truncateAtPosition:(long)aPosition
+{
+    lseek(fd, aPosition, SEEK_SET);
+#if defined(__MINGW32__)
+    if (_chsize(fd, aPosition) != 0)
+#else
+    if (ftruncate(fd, aPosition) != 0)
+#endif
+       [[[PosixFileOperationException alloc]
+           initWithFormat:@"could not truncate file"] raise];
+}
+
+// Mapping files to memory
+
+- (NSData *)mapFileRange:(NSRange)range
+{
+    return AUTORELEASE([[NSMappedData alloc]
+                           initWithPosixFileDescriptor:self range:range]);
+}
+
+- (void)synchronizeFile
+{
+#if HAVE_FSYNC
+    if (fsync(fd) != 0)
+       [[[PosixFileOperationException alloc]
+           initWithFormat:@"could not sync file"] raise];
+#endif
+}
+
+// Monitoring file descriptors
+
+- (void)ceaseMonitoringFileActivity
+{
+    NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
+
+    fileActivity = 0;
+    [runLoop removePosixFileDescriptor:self forMode:[runLoop currentMode]];
+}
+
+- (NSPosixFileActivities)fileActivity
+{
+    return fileActivity;
+}
+
+- (void)monitorFileActivity:(NSPosixFileActivities)activity
+{
+    NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
+
+    fileActivity |= activity;
+    [runLoop addPosixFileDescriptor:self forMode:[runLoop currentMode]];
+}
+
+- (void)monitorActivity:(NSPosixFileActivities)activity delegate:(id)anObject
+{
+    [self setDelegate:anObject];
+    [self monitorFileActivity:activity];
+}
+
+// File descriptor delegate
+
+- (id)delegate
+{
+    return delegate;
+}
+
+- (void)setDelegate:(id)aDelegate
+{
+    delegate = aDelegate;
+}
+
+@end /* NSPosixFileDescriptor */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSPredicate.h b/libFoundation/Foundation/NSPredicate.h
new file mode 100644 (file)
index 0000000..cecfbb0
--- /dev/null
@@ -0,0 +1,63 @@
+/* 
+   NSPredicate.h
+
+   Copyright (C) 2005, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@opengroupware.org>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSPredicate_H__
+#define __NSPredicate_H__
+
+#include <Foundation/NSObject.h>
+
+@interface NSPredicate : NSObject < NSCoding, NSCopying >
+{
+}
+
+/* evaluation */
+
+- (BOOL)evaluateWithObject:(id)_object;
+
+@end
+
+@interface NSPredicate(Parsing)
++ (NSPredicate *)predicateWithFormat:(NSString *)_format,...;
++ (NSPredicate *)predicateWithFormat:(NSString *)_format 
+  argumentArray:(NSArray *)_arguments;
+@end
+
+#include <Foundation/NSArray.h>
+
+@interface NSArray(NSPredicate)
+- (NSArray *)filteredArrayUsingPredicate:(NSPredicate *)_predicate;
+@end
+
+@interface NSMutableArray(NSPredicate)
+- (void)filterArrayUsingPredicate:(NSPredicate *)_predicate;
+@end
+
+#endif /* __NSPredicate_H__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSPredicate.m b/libFoundation/Foundation/NSPredicate.m
new file mode 100644 (file)
index 0000000..1693a97
--- /dev/null
@@ -0,0 +1,155 @@
+/* 
+   NSPredicate.m
+
+   Copyright (C) 2005, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@opengroupware.org>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include "NSPredicate.h"
+
+@interface NSTruePredicate : NSPredicate
+@end
+
+@interface NSFalsePredicate : NSPredicate
+@end
+
+#include "NSAutoreleasePool.h"
+#include "common.h"
+
+@implementation NSPredicate
+
+/* evaluation */
+
+- (BOOL)evaluateWithObject:(id)_object
+{
+    [self subclassResponsibility:_cmd];
+    return NO;
+}
+
+/* NSCoding */
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+}
+- (id)initWithCoder:(NSCoder*)aDecoder
+{
+    return self;
+}
+
+/* NSCopying */
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    /* NSPredicate objects are immutable! */
+    return [self retain];
+}
+
+@end /* NSPredicate */
+
+
+@implementation NSTruePredicate
+
+/* evaluation */
+
+- (BOOL)evaluateWithObject:(id)_object
+{
+    return YES;
+}
+
+@end /* NSTruePredicate */
+
+@implementation NSFalsePredicate
+
+/* evaluation */
+
+- (BOOL)evaluateWithObject:(id)_object
+{
+    return NO;
+}
+
+@end /* NSFalsePredicate */
+
+
+@implementation NSArray(NSPredicate)
+
+- (NSArray *)filteredArrayUsingPredicate:(NSPredicate *)_predicate
+{
+    NSAutoreleasePool *pool;
+    NSMutableArray *array = nil;
+    NSArray  *result;
+    unsigned i, count;
+
+    pool = [[NSAutoreleasePool alloc] init];
+    result = nil;
+  
+    count = [self count];
+    array = [NSMutableArray arrayWithCapacity:count];
+    for (i = 0, count; i < count; i++) {
+       id o;
+    
+       o = [self objectAtIndex:i];
+    
+       if ([_predicate evaluateWithObject:o])
+           [array addObject:o];
+    }
+    result = [array copy];
+    [pool release];
+    return [result autorelease];
+}
+
+@end /* NSArray(NSPredicate) */
+
+@implementation NSMutableArray(NSPredicate)
+
+- (void)filterArrayUsingPredicate:(NSPredicate *)_predicate
+{
+    // TODO: improve performance, do inline edits
+    NSAutoreleasePool *pool;
+    NSMutableArray *array = nil;
+    NSArray  *result;
+    unsigned i, count;
+
+    pool = [[NSAutoreleasePool alloc] init];
+    result = nil;
+  
+    count = [self count];
+    array = [NSMutableArray arrayWithCapacity:count];
+    for (i = 0, count; i < count; i++) {
+       id o;
+    
+       o = [self objectAtIndex:i];
+    
+       if ([_predicate evaluateWithObject:o])
+           [array addObject:o];
+    }
+  
+    [self setArray:array];
+    [pool release];
+}
+
+@end /* NSMutableArray(NSPredicate) */
+
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSPredicateParser.m b/libFoundation/Foundation/NSPredicateParser.m
new file mode 100644 (file)
index 0000000..66e7636
--- /dev/null
@@ -0,0 +1,1215 @@
+/* 
+   NSPredicateParser.m
+
+   Copyright (C) 2000-2005 SKYRIX Software AG
+   All rights reserved.
+   
+   Author: Helge Hess <helge.hess@opengroupware.org>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <stdio.h>
+#include "NSPredicate.h"
+#include "NSComparisonPredicate.h"
+#include "NSCompoundPredicate.h"
+#include "NSExpression.h"
+#include "NSValue.h"
+#include "NSException.h"
+#include "NSDictionary.h"
+#include "NSNull.h"
+#include "NSCalendarDate.h"
+#include "common.h"
+
+//#define USE_DESCRIPTION_FOR_AT 1
+
+static int qDebug = 0;
+static NSMutableDictionary *NSPredicateParserTypeMappings = nil;
+
+/* 
+   The literals understood by the value parser.
+   
+   NOTE: Any literal used here can never be used as a key ! So add as little
+   as possible.
+*/
+typedef struct {
+  const unsigned char *token;
+  id  value;
+  int scase;
+} NSQPTokEntry;
+
+static NSQPTokEntry toks[] = {
+  { (const unsigned char *)"NULL",  nil, 0 },
+  { (const unsigned char *)"nil",   nil, 1 },
+  { (const unsigned char *)"YES",   nil, 0 },
+  { (const unsigned char *)"NO",    nil, 0 },
+  { (const unsigned char *)"TRUE",  nil, 0 },
+  { (const unsigned char *)"FALSE", nil, 0 },
+  { (const unsigned char *)NULL,    nil, 0 }
+};
+
+static inline void _setupLiterals(void) {
+  static BOOL didSetup = NO;
+  if (didSetup) return;
+  didSetup = YES;
+  toks[0].value = [[NSNull null] retain];
+  toks[1].value = toks[0].value;
+  toks[2].value = [[NSNumber numberWithBool:YES] retain];
+  toks[3].value = [[NSNumber numberWithBool:NO]  retain];
+  toks[4].value = toks[2].value;
+  toks[5].value = toks[3].value;
+}
+
+/* cache */
+static Class  StringClass = Nil;
+static Class  NumberClass = Nil;
+static NSNull *null       = nil;
+
+/* parsing functions */
+
+static NSPredicate *_parseCompoundPredicate(id _ctx, const char *_buf,
+                                            unsigned _bufLen, unsigned *_predLen);
+static NSPredicate *_testOperator(id _ctx, const char *_buf,
+                                  unsigned _bufLen, unsigned *_opLen,
+                                  BOOL *_testAnd);
+static NSPredicate *_parsePredicates(id _ctx, const char *_buf,
+                                     unsigned _bufLen, unsigned *_predLen);
+static NSPredicate *_parseParenthesisPredicate(id _ctx,
+                                               const char *_buf, unsigned _bufLen,
+                                               unsigned *_predLen);
+static NSPredicate *_parseNotPredicate(id _ctx, const char *_buf,
+                                       unsigned _bufLen, unsigned *_predLen);
+static NSPredicate *_parseKeyCompPredicate(id _ctx, const char *_buf,
+                                           unsigned _bufLen, unsigned *_predLen);
+static NSString *_parseKey(id _ctx, const char *_buf, unsigned _bufLen,
+                           unsigned *_keyLen);
+static id _parseValue(id _ctx, const char *_buf, unsigned _bufLen,
+                      unsigned *_keyLen);
+static inline unsigned _countWhiteSpaces(const char *_buf, unsigned _bufLen);
+static NSString *_parseOp(const char *_buf, unsigned _bufLen,
+                          unsigned *_opLen);
+
+@interface NSPredicateParserContext : NSObject
+{
+  NSMapTable *predicateCache;
+}
+
+- (NSDictionary *)resultForFunction:(NSString *)_fct atPos:(unsigned)_pos;
+- (void)setResult:(NSDictionary *)_dict forFunction:(NSString *)_fct
+  atPos:(unsigned)_pos;
+- (id)getObjectFromStackFor:(char)_c;
+
+@end
+
+@interface NSPredicateVAParserContext : NSPredicateParserContext
+{
+  va_list    *va;  
+}
++ (id)contextWithVaList:(va_list *)_va;
+- (id)initWithVaList:(va_list *)_va;
+@end
+
+@interface NSPredicateEnumeratorParserContext : NSPredicateParserContext
+{
+  NSEnumerator *enumerator;
+}
++ (id)contextWithEnumerator:(NSEnumerator *)_enumerator;
+- (id)initWithEnumerator:(NSEnumerator  *)_enumerator;
+@end
+
+@implementation NSPredicateVAParserContext
+
++ (id)contextWithVaList:(va_list *)_va {
+  return [[[NSPredicateVAParserContext alloc] initWithVaList:_va] autorelease];
+}
+
+- (id)initWithVaList:(va_list *)_va {
+  if ((self = [super init])) {
+    self->va = _va;
+  }
+  return self;
+}
+
+- (id)getObjectFromStackFor:(char)_c {
+  id obj = nil;
+
+  if (StringClass == Nil) StringClass = [NSString class];
+  if (NumberClass == Nil) NumberClass = [NSNumber class];
+  if (null == nil)        null        = [NSNull null];
+  
+  if (_c == 's') {
+    char *str = va_arg(*self->va, char*);
+    obj = [StringClass stringWithCString:str];
+  }
+  else if (_c == 'd') {
+    int i= va_arg(*self->va, int);
+    obj = [NumberClass numberWithInt:i];
+  }
+  else if (_c == 'f') {
+    double d = va_arg(*self->va, double);
+    obj = [NumberClass numberWithDouble:d];
+  }
+  else if (_c == '@') {
+    id o = va_arg(*self->va, id);
+#if USE_DESCRIPTION_FOR_AT
+    obj = (o == nil) ? (id)null : (id)[o description];
+#else
+    obj = (o == nil) ? (id)null : (id)o;
+#endif
+  }
+  else {
+    [NSException raise:@"NSInvalidArgumentException"
+                 format:@"unknown conversation char %c", _c];
+  }
+  return obj;
+}
+
+@end /* NSPredicateVAParserContext */
+
+@implementation NSPredicateEnumeratorParserContext
+
++ (id)contextWithEnumerator:(NSEnumerator *)_enumerator {
+  return [[[NSPredicateEnumeratorParserContext alloc]
+                                      initWithEnumerator:_enumerator] autorelease];
+}
+
+- (id)initWithEnumerator:(NSEnumerator *)_enumerator {
+  if ((self = [super init])) {
+    ASSIGN(self->enumerator, _enumerator);
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [self->enumerator release];
+  [super dealloc];;
+}
+
+- (id)getObjectFromStackFor:(char)_c {
+  static Class NumberClass = Nil;
+  id o;
+
+  if (NumberClass == Nil) NumberClass = [NSNumber class];
+
+  o = [self->enumerator nextObject];
+  switch (_c) {
+    case '@':
+#if USE_DESCRIPTION_FOR_AT
+      return [o description];
+#else
+      return o;
+#endif
+    
+    case 'f':
+      return [NumberClass numberWithDouble:[o doubleValue]];
+      
+    case 'd':
+      return [NumberClass numberWithInt:[o intValue]];
+      
+    case 's':
+      // return [NSString stringWithCString:[o cString]];
+      return [[o copy] autorelease];
+      
+    default:
+      [NSException raise:@"NSInvalidArgumentException"
+                   format:@"unknown or not allowed conversation char %c", _c];
+  }
+  return nil;
+}
+
+@end /* NSPredicateEnumeratorParserContext */
+
+@implementation NSPredicateParserContext
+
+- (id)init {
+  if (StringClass == Nil) StringClass = [NSString class];
+  
+  if ((self = [super init])) {
+    self->predicateCache = NSCreateMapTable(NSObjectMapKeyCallBacks,
+                                            NSObjectMapValueCallBacks,
+                                            200);
+  }
+  return self;
+}
+
+- (void)dealloc {
+  if (self->predicateCache) NSFreeMapTable(self->predicateCache);
+  [super dealloc];
+}
+
+- (NSDictionary *)resultForFunction:(NSString *)_fct atPos:(unsigned)_pos
+{
+  return NSMapGet(self->predicateCache,
+                  [StringClass stringWithFormat:@"%@_%d", _fct, _pos]);
+}
+
+- (void)setResult:(NSDictionary *)_dict forFunction:(NSString *)_fct
+  atPos:(unsigned)_pos
+{
+  NSMapInsert(self->predicateCache,
+              [StringClass stringWithFormat:@"%@_%d", _fct, _pos],
+              _dict);
+}
+
+- (id)getObjectFromStackFor:(char)_c {
+  [self doesNotRecognizeSelector:_cmd];
+  return nil;
+}
+
+@end /* NSPredicateParserContext */
+
+@implementation NSPredicate(Parsing)
+
++ (void)registerValueClass:(Class)_valueClass forTypeName:(NSString *)_type {
+  if (NSPredicateParserTypeMappings == nil)
+    NSPredicateParserTypeMappings = [[NSMutableDictionary alloc] init];
+  
+  if (_type == nil) {
+    NSLog(@"ERROR(%s): got passed no type name!", __PRETTY_FUNCTION__);
+    return;
+  }
+  if (_valueClass == nil) {
+    NSLog(@"ERROR(%s): got passed no value-class for type '%@'!",
+          __PRETTY_FUNCTION__, _type);
+    return;
+  }
+  
+  [NSPredicateParserTypeMappings setObject:_valueClass forKey:_type];
+}
+
++ (NSPredicate *)predicateWithFormat:(NSString *)_format,... {
+  va_list     va;
+  NSPredicate *qualifier;
+  unsigned    length = 0;
+  const char  *buf;
+  unsigned    bufLen;
+  char        *cbuf;
+
+  _setupLiterals();
+  if (StringClass == Nil) StringClass = [NSString class];
+  
+  bufLen = [_format cStringLength];
+  cbuf   = malloc(bufLen + 1);
+  [_format getCString:cbuf]; cbuf[bufLen] = '\0';
+  buf = cbuf;
+  
+  va_start(va, _format);
+  qualifier =
+    _parsePredicates([NSPredicateVAParserContext contextWithVaList:&va],
+                     buf, bufLen, &length);
+  va_end(va);
+  
+  if (qualifier != nil) { /* check whether the rest of the string is OK */
+    if (length < bufLen)
+      length += _countWhiteSpaces(buf + length, bufLen - length);
+    
+    if (length < bufLen) {
+      NSLog(@"WARNING(%s): unexpected chars at the end of the "
+            @"string(class=%@,len=%i) '%@'",
+            __PRETTY_FUNCTION__,
+            [_format class],
+            [_format length], _format);
+      NSLog(@"  buf-length: %i", bufLen);
+      NSLog(@"  length:     %i", length);
+      NSLog(@"  char[length]: '%c' (%i) '%s'", buf[length], buf[length],
+           (buf+length));
+      qualifier = nil;
+    }
+    else if (length > bufLen) {
+      NSLog(@"WARNING(%s): length should never be longer than bufLen ?, "
+           @"internal parsing error !",
+           __PRETTY_FUNCTION__);
+    }
+  }
+  free(cbuf);
+  return qualifier;
+}
+
++ (NSPredicate *)predicateWithFormat:(NSString *)_format 
+  argumentArray:(NSArray *)_arguments
+{
+  NSPredicate *qual  = nil;
+  unsigned    length = 0;
+  const char  *buf   = NULL;
+  unsigned    bufLen = 0;
+  NSPredicateEnumeratorParserContext *ctx;
+
+  _setupLiterals();
+  if (StringClass == Nil) StringClass = [NSString class];
+  
+  ctx = [NSPredicateEnumeratorParserContext contextWithEnumerator:
+                                             [_arguments objectEnumerator]];
+  
+  //NSLog(@"qclass: %@", [_format class]);
+  buf    = [_format cString];
+  bufLen = [_format cStringLength];
+  qual   = _parsePredicates(ctx, buf, bufLen, &length);
+  
+  if (qual != nil) { /* check whether the rest of the string is OK */
+    if (length < bufLen) {
+      length += _countWhiteSpaces(buf + length, bufLen - length);
+    }
+    if (length != bufLen) {
+      NSLog(@"WARNING(%s): unexpected chars at the end of the string '%@'",
+            __PRETTY_FUNCTION__, _format);
+      qual = nil;
+    }
+  }
+  return qual;
+}
+@end /* NSPredicate(Parsing) */
+
+static NSPredicate *_parseSinglePredicate(id _ctx, const char *_buf,
+                                            unsigned _bufLen,
+                                            unsigned *_predLen)
+{
+  NSPredicate *res = nil;
+
+  if ((res = _parseParenthesisPredicate(_ctx, _buf, _bufLen, _predLen))  != nil) {
+    if (qDebug)
+      NSLog(@"_parseSinglePredicate return <%@> for <%s> ", res, _buf);
+
+    return res;
+  }
+  if ((res = _parseNotPredicate(_ctx, _buf, _bufLen, _predLen)) != nil) {
+    if (qDebug)
+      NSLog(@"_parseSinglePredicate return <%@> for <%s> ", res, _buf);
+
+    return res;
+  }
+  if ((res = _parseKeyCompPredicate(_ctx, _buf, _bufLen, _predLen)) != nil) {
+    if (qDebug) {
+      NSLog(@"_parseSinglePredicate return <%@> for <%s> length %d", 
+           res, _buf, *_predLen);
+    }
+    return res;
+  }
+  return nil;
+}
+
+static NSPredicate *_parsePredicates(id _ctx, const char *_buf, unsigned _bufLen,
+                                     unsigned *_predLen)
+{
+  NSPredicate *res = nil;
+
+
+  if ((res = _parseCompoundPredicate(_ctx, _buf, _bufLen, _predLen))) {
+    if (qDebug)
+      NSLog(@"_parsePredicates return <%@> for <%s> ", res, _buf);
+    return res;
+  }
+
+  if ((res = _parseSinglePredicate(_ctx, _buf, _bufLen, _predLen))) {
+    if (qDebug)
+      NSLog(@"_parsePredicates return <%@> for <%s> ", res, _buf);
+    return res;
+  }
+  
+  if (qDebug)
+    NSLog(@"_parsePredicates return nil for <%s> ", _buf);
+
+  return nil;
+}
+
+static NSPredicate *_parseParenthesisPredicate(id _ctx, const char *_buf,
+                                               unsigned _bufLen,
+                                               unsigned *_predLen)
+{
+  unsigned    pos     = 0;
+  unsigned    qualLen = 0;
+  NSPredicate *qual   = nil;
+
+  pos = _countWhiteSpaces(_buf, _bufLen);
+
+  if (_bufLen <= pos + 2) /* at least open and close parenthesis */ {
+    if (qDebug)
+      NSLog(@"1_parseParenthesisPredicate return nil for <%s> ", _buf);
+    return nil;
+  }
+  if (_buf[pos] != '(') {
+    if (qDebug)
+      NSLog(@"2_parseParenthesisPredicate return nil for <%s> ", _buf);
+    
+    return nil;
+  }
+  pos++;
+  if (!(qual = _parsePredicates(_ctx, _buf + pos, _bufLen - pos,
+                                &qualLen))) {
+    if (qDebug)
+      NSLog(@"3_parseParenthesisPredicate return nil for <%s> ", _buf);
+    
+    return nil;
+  }
+  
+  pos += qualLen;
+  if (_bufLen <= pos) {
+    if (qDebug)
+      NSLog(@"4_parseParenthesisPredicate return nil for <%s> qual[%@] %@ bufLen %d "
+            @"pos %d", _buf, [qual class], qual, _bufLen, pos);
+
+    return nil;
+  }
+  pos += _countWhiteSpaces(_buf + pos, _bufLen - pos);
+  if (_buf[pos] != ')') {
+    if (qDebug)
+      NSLog(@"5_parseParenthesisPredicate return nil for <%s> [%s] ", _buf, _buf+pos);
+
+    return nil;
+  }
+  if (qDebug)
+    NSLog(@"6_parseParenthesisPredicate return <%@> for <%s> ", qual, _buf);
+  
+  *_predLen = pos + 1; /* one step after the parenthesis */
+  return qual;
+}
+
+static NSPredicate *_parseNotPredicate(id _ctx, const char *_buf,
+                                       unsigned _bufLen, unsigned *_predLen)
+{
+  unsigned    pos, len   = 0;
+  char        c0, c1, c2 = 0;
+  NSPredicate *qual      = nil;
+
+  pos = _countWhiteSpaces(_buf, _bufLen);
+
+  if (_bufLen - pos < 4) { /* at least 3 chars for 'NOT' */
+    if (qDebug)
+      NSLog(@"_parseNotPredicate return nil for <%s> ", _buf);
+    
+    return nil;
+  }
+  c0 = _buf[pos];
+  c1 = _buf[pos + 1];
+  c2 = _buf[pos + 2];
+  if (!(((c0 == 'n') || (c0 == 'N')) &&
+        ((c1 == 'o') || (c1 == 'O')) &&
+        ((c2 == 't') || (c2 == 'T')))) {
+    if (qDebug)
+      NSLog(@"_parseNotPredicate return nil for <%s> ", _buf);
+    return nil;
+  }
+  pos += 3;
+  qual = _parseSinglePredicate(_ctx, _buf + pos, _bufLen - pos, &len);
+  if (qual == nil) {
+    if (qDebug)
+      NSLog(@"_parseNotPredicate return nil for <%s> ", _buf);
+    
+    return nil;
+  }
+  *_predLen = pos +len;
+  if (qDebug)
+    NSLog(@"_parseNotPredicate return %@ for <%s> ", qual, _buf);
+  
+  return [NSCompoundPredicate notPredicateWithSubpredicates:
+                               [NSArray arrayWithObjects:&qual count:1]];
+}
+
+static SEL operatorSelectorForString(NSString *_str)
+{
+  // TODO: fix for NSPredicate
+  static NSMapTable *operatorToSelector = NULL; // THREAD
+  SEL s;
+
+  if (operatorToSelector == NULL) {
+    operatorToSelector = NSCreateMapTable(NSObjectMapKeyCallBacks,
+                                          NSIntMapValueCallBacks,
+                                          10);
+    NSMapInsert(operatorToSelector, @"=",  
+               (void *)NSEqualToPredicateOperatorType);
+    NSMapInsert(operatorToSelector, @"==", 
+               (void *)NSEqualToPredicateOperatorType);
+    NSMapInsert(operatorToSelector, @"!=", 
+               (void *)NSNotEqualToPredicateOperatorType);
+    NSMapInsert(operatorToSelector, @"<>", 
+               (void *)NSNotEqualToPredicateOperatorType);
+    NSMapInsert(operatorToSelector, @"<",  
+               (void *)NSLessThanPredicateOperatorType);
+    NSMapInsert(operatorToSelector, @">",  
+               (void *)NSGreaterThanPredicateOperatorType);
+    
+    NSMapInsert(operatorToSelector, @"<=",  
+               (void *)NSLessThanOrEqualToPredicateOperatorType);
+    NSMapInsert(operatorToSelector, @">=",
+                (void *)NSGreaterThanOrEqualToPredicateOperatorType);
+
+    NSMapInsert(operatorToSelector, @"like", 
+               (void *)NSLikePredicateOperatorType);
+    NSMapInsert(operatorToSelector, @"LIKE", 
+               (void *)NSLikePredicateOperatorType);
+    
+#if 0 // TODO
+    // TODO: need to have options here
+    NSMapInsert(operatorToSelector, @"caseInsensitiveLike",
+                NSLikePredicateOperatorType);
+#endif
+  }
+  
+  if ((s = NSMapGet(operatorToSelector, _str)))
+    return s;
+  
+  return NSSelectorFromString(_str);
+}
+
+static NSPredicate *_parseKeyCompPredicate(id _ctx, const char *_buf,
+                                           unsigned _bufLen, 
+                                          unsigned *_predLen)
+{
+  NSExpression *lhs, *rhs;
+  NSString     *key       = nil;
+  NSString     *op        = nil;
+  NSString     *value     = nil;
+  NSPredicate  *qual      = nil;
+  NSDictionary *dict      = nil;
+  SEL          sel        = NULL;
+  unsigned     length     = 0;
+  unsigned     pos        = 0;
+  BOOL         valueIsKey = NO;
+
+  dict = [_ctx resultForFunction:@"parseKeyCompPredicate" atPos:(unsigned)_buf];
+  if (dict != nil) {
+    if (qDebug)
+      NSLog(@"_parseKeyCompQual return <%@> [cached] for <%s> ", dict, _buf);
+    
+    *_predLen = [[dict objectForKey:@"length"] unsignedIntValue];
+    return [dict objectForKey:@"object"];
+  }
+  pos = _countWhiteSpaces(_buf, _bufLen);
+
+  if ((key = _parseKey(_ctx , _buf + pos, _bufLen - pos, &length)) == nil) {
+    if (qDebug)
+      NSLog(@"_parseKeyCompPredicate return nil for <%s> ", _buf);
+    
+    return nil;
+  }
+  pos += length;
+  pos += _countWhiteSpaces(_buf + pos, _bufLen - pos);
+
+  if (!(op = _parseOp(_buf + pos, _bufLen - pos, &length))) {
+    if (qDebug)
+      NSLog(@"_parseKeyCompPredicate return nil for <%s> ", _buf);
+    return nil;
+  }
+
+  sel = operatorSelectorForString(op);
+  if (sel == NULL) {
+    NSLog(@"WARNING(%s): possible unknown operator <%@>", __PRETTY_FUNCTION__,
+          op);
+    if (qDebug)
+      NSLog(@"_parseKeyCompPredicate return nil for <%s> ", _buf);
+    return nil;
+  }
+  pos       +=length;
+  pos       += _countWhiteSpaces(_buf + pos, _bufLen - pos);
+  valueIsKey = NO;  
+  
+  value = _parseValue(_ctx, _buf + pos, _bufLen - pos, &length);
+  if (value == nil) {
+    value = _parseKey(_ctx, _buf + pos, _bufLen - pos, &length);
+    if (value == nil) {
+      if (qDebug)
+       NSLog(@"_parseKeyCompPredicate return nil for <%s> ", _buf);
+      return nil;
+    }
+    else
+      valueIsKey = YES;
+  }
+  pos      +=length;  
+  *_predLen = pos;
+
+  lhs = [NSExpression expressionForKeyPath:key];
+  rhs = valueIsKey
+    ? [NSExpression expressionForKeyPath:value]
+    : [NSExpression expressionForConstantValue:value];
+  
+  qual = [NSComparisonPredicate predicateWithLeftExpression:lhs
+                               rightExpression:rhs
+                               customSelector:sel];
+  if (qDebug)
+    NSLog(@"_parseKeyCompPredicate return <%@> for <%s> ", qual, _buf);
+
+  if (qual != nil) {
+    id keys[2], values[2];
+    keys[0] = @"length"; values[0] = [NSNumber numberWithUnsignedInt:pos];
+    keys[1] = @"object"; values[1] = qual;
+    [_ctx setResult:
+            [NSDictionary dictionaryWithObjects:values forKeys:keys count:2]
+          forFunction:@"parseKeyCompPredicate"
+          atPos:(unsigned)_buf];
+    *_predLen = pos;
+  }
+  return qual;
+}
+
+static NSString *_parseOp(const char *_buf, unsigned _bufLen,
+                          unsigned *_opLen)
+{
+  unsigned pos = 0;
+  char     c0  = 0;
+  char     c1  = 0;  
+
+  if (_bufLen == 0) {
+    if (qDebug)
+      NSLog(@"_parseOp _bufLen == 0 --> return nil");
+    return nil;
+  }
+  pos = _countWhiteSpaces(_buf, _bufLen);
+  if (_bufLen - pos > 1) {/* at least an operation and a value */
+    c0 = _buf[pos];
+    c1 = _buf[pos+1];  
+
+    if (((c0 >= '<') && (c0 <= '>')) || (c0 == '!')) {
+      NSString *result;
+      
+      if ((c1 >= '<') && (c1 <= '>')) {
+        *_opLen = 2;
+        result = [StringClass stringWithCString:_buf + pos length:2];
+       if (qDebug)
+         NSLog(@"_parseOp return <%@> for <%s> ", result, _buf);
+      }
+      else {
+        *_opLen = 1;
+        result = [StringClass stringWithCString:&c0 length:1];
+       if (qDebug)
+         NSLog(@"_parseOp return <%@> for <%s> ", result, _buf);
+      }
+      return result;
+    }
+    else { /* string designator operator */
+      unsigned opStart = pos;
+      while (pos < _bufLen) {
+        if (_buf[pos] == ' ')
+          break;
+        pos++;
+      }
+      if (pos >= _bufLen) {
+        NSLog(@"WARNING(%s): found end of string during operator parsing",
+              __PRETTY_FUNCTION__);
+      }
+
+      if (qDebug) {
+       NSLog(@"%s: _parseOp return <%@> for <%s> ", __PRETTY_FUNCTION__,
+             [StringClass stringWithCString:_buf + opStart
+                          length:pos - opStart], _buf);
+      }
+      
+      *_opLen = pos;
+      return [StringClass stringWithCString:_buf + opStart length:pos - opStart];
+    }
+  }
+  if (qDebug)
+    NSLog(@"_parseOp return nil for <%s> ", _buf);
+  return nil;
+}
+
+static NSString *_parseKey(id _ctx, const char *_buf, unsigned _bufLen,
+                           unsigned *_keyLen)
+{ 
+  id           result   = nil;
+  NSDictionary *dict    = nil;
+  unsigned     pos      = 0;
+  unsigned     startKey = 0;
+  char         c        = 0;
+
+  if (_bufLen == 0) {
+    if (qDebug) NSLog(@"%s: _bufLen == 0 --> return nil", __PRETTY_FUNCTION__);
+    return nil;
+  }
+  dict = [_ctx resultForFunction:@"parseKey" atPos:(unsigned)_buf];
+  if (dict != nil) {
+    if (qDebug) {
+      NSLog(@"%s: return <%@> [cached] for <%s> ", __PRETTY_FUNCTION__,
+           dict, _buf);
+    }
+    *_keyLen = [[dict objectForKey:@"length"] unsignedIntValue];
+    return [dict objectForKey:@"object"];
+  }
+  pos      = _countWhiteSpaces(_buf, _bufLen);
+  startKey = pos;
+  c        = _buf[pos];
+
+  if (c == '%') {
+    if (_bufLen - pos < 2) {
+      if (qDebug) {
+       NSLog(@"%s: [c==%%,bufLen-pos<2]: _parseValue return nil for <%s> ", 
+             __PRETTY_FUNCTION__, _buf);
+      }
+      return nil;
+    }
+    pos++;
+    result = [_ctx getObjectFromStackFor:_buf[pos]];
+    pos++;
+  }
+  else {
+    /* '{' for namspaces */
+    register BOOL isQuotedKey = NO;
+
+    if (c == '"')
+      isQuotedKey = YES;
+    else if (!(((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) ||
+             c == '{')) {
+      if (qDebug) {
+       NSLog(@"%s: [c!=AZaz{]: _parseKey return nil for <%s> ", 
+             __PRETTY_FUNCTION__, _buf);
+      }
+      return nil;
+    }
+    
+    pos++;
+    while (pos < _bufLen) {
+      c = _buf[pos];
+      if (isQuotedKey && c == '"')
+       break;
+      else if
+       ((c == ' ') || (c == '<') || (c == '>') || (c == '=') || (c == '!') ||
+         c == ')' || c == '(')
+        break;
+      pos++;    
+    }
+    if (isQuotedKey) {
+      pos++; // skip quote
+      result = [StringClass stringWithCString:(_buf + startKey + 1) 
+                           length:(pos - startKey - 2)];
+    }
+    else {
+      result = [StringClass stringWithCString:(_buf + startKey) 
+                           length:(pos - startKey)];
+    }
+  }
+  *_keyLen = pos;  
+  if (qDebug)
+    NSLog(@"%s: return <%@> for <%s> ", __PRETTY_FUNCTION__, result, _buf);
+  
+  if (result != nil) {
+    id keys[2], values[2];
+    
+    keys[0] = @"length"; values[0] = [NSNumber numberWithUnsignedInt:pos];
+    keys[1] = @"object"; values[1] = result;
+    
+    [_ctx setResult:
+            [NSDictionary dictionaryWithObjects:values forKeys:keys count:2]
+          forFunction:@"parseKey"
+          atPos:(unsigned)_buf];
+    *_keyLen = pos;
+  }
+  return result;
+}
+
+static id _parseValue(id _ctx, const char *_buf, unsigned _bufLen,
+                      unsigned *_keyLen)
+{
+  NSString     *cast = nil;
+  NSDictionary *dict = nil;
+  id           obj   = nil;
+  unsigned     pos   = 0;
+  char         c     = 0;
+  
+  if (NumberClass == Nil) NumberClass = [NSNumber class];
+  if (null == nil) null = [[NSNull null] retain];
+  
+  if (_bufLen == 0) {
+    if (qDebug) NSLog(@"_parseValue _bufLen == 0 --> return nil");
+    return nil;
+  }
+  
+  dict = [_ctx resultForFunction:@"parseValue" atPos:(unsigned)_buf];
+  if (dict != nil) {
+    if (qDebug) {
+      NSLog(@"_parseKeyCompPredicate return <%@> [cached] for <%s> ",
+           dict, _buf);
+    }
+    *_keyLen = [[dict objectForKey:@"length"] unsignedIntValue];
+    return [dict objectForKey:@"object"];
+  }
+  
+  pos = _countWhiteSpaces(_buf, _bufLen);
+  c   = _buf[pos];
+  
+  if (c == '$') { /* found NSPredicateVariable */
+    unsigned startVar = 0;
+    NSString *varKey;
+    
+    pos++;
+    startVar = pos;
+    while (pos < _bufLen) {
+      if ((_buf[pos] == ' ') || (_buf[pos] == ')'))
+        break;
+      pos++;
+    }
+
+    varKey = [StringClass stringWithCString:(_buf + startVar)
+                          length:pos - startVar];
+    obj = [NSExpression expressionForVariable:varKey];
+  }
+  else {
+    /* first, check for CAST */
+    BOOL parseComplexCast = NO;
+    
+    if (c == 'c' && _bufLen > 14) {
+      if (strstr(_buf, "cast") == _buf && (isspace(_buf[4]) || _buf[4]=='(')) {
+       /* for example: cast("1970-01-01T00:00:00Z" as 'dateTime') [min 15 #]*/
+       pos += 4; /* skip 'cast' */
+        while (isspace(_buf[pos])) /* skip spaces */
+          pos++;
+        if (_buf[pos] != '(') {
+          NSLog(@"WARNING(%s): got unexpected cast string: '%s'",
+                __PRETTY_FUNCTION__, _buf);
+        }
+        else
+          pos++; /* skip opening bracket '(' */
+        
+       parseComplexCast = YES;
+       c = _buf[pos];
+      }
+    }
+    else if (c == '(') { /* starting with a cast */
+      /* for example: (NSCalendarDate)"1999-12-12" [min 5 chars] */
+      unsigned startCast = 0;
+      
+      pos++;
+      startCast = pos;
+      while (pos < _bufLen) {
+        if (_buf[pos] == ')')
+          break;
+        pos++;
+      }
+      pos++;
+      if (pos >= _bufLen) {
+        NSLog(@"WARNING(%s): found end of string while reading a cast",
+              __PRETTY_FUNCTION__);
+        return nil;
+      }
+      c    = _buf[pos];
+      cast = [StringClass stringWithCString:(_buf + startCast)
+                          length:(pos - 1 - startCast)];
+      if (qDebug)
+       NSLog(@"%s: got cast %@", __PRETTY_FUNCTION__, cast);
+    }
+    
+    /* next, check for FORMAT SPECIFIER */
+    if (c == '%') {
+      if (_bufLen - pos < 2) {
+       if (qDebug)
+         NSLog(@"_parseValue return nil for <%s> ", _buf);
+       
+        return nil;
+      }
+      pos++;
+      obj = [_ctx getObjectFromStackFor:_buf[pos]];
+      pos++;
+    }
+    
+    /* next, check for A NUMBER */
+    else if (((c >= '0') && (c <= '9')) || (c == '-')) { /* got a number */
+      unsigned startNumber;
+
+      startNumber = pos;
+      pos++;
+      while (pos < _bufLen) {
+        c = _buf[pos];
+        if (!((c >= '0') && (c <= '9')))
+          break;
+        pos++;
+      }
+      obj = [NumberClass numberWithInt:atoi(_buf + startNumber)];
+    }
+
+    /* check for some text literals */
+    if ((obj == nil) && ((_bufLen - pos) > 1)) {
+      unsigned char i;
+      
+      for (i = 0; i < 20 && (toks[i].token != NULL) && (obj == nil); i++) {
+       const unsigned char *tok;
+       unsigned char toklen;
+       int rc;
+       
+       tok = toks[i].token;
+       toklen = strlen((const char *)tok);
+       if ((_bufLen - pos) < toklen)
+         /* remaining string not long enough */
+         continue;
+       
+       rc = toks[i].scase 
+         ? strncmp(&(_buf[pos]),     (const char *)tok, toklen)
+         : strncasecmp(&(_buf[pos]), (const char *)tok, toklen);
+       if (rc != 0)
+         /* does not match */
+         continue;
+       if (!(_buf[pos + toklen] == '\0' || isspace(_buf[pos + toklen])))
+         /* not at the string end or folloed by a space */
+         continue;
+
+       /* wow, found the token */
+       pos += toklen; /* skip it */
+       obj = toks[i].value;
+      }
+    }
+    
+    /* next, check for STRING */
+    if (obj == nil) {
+      if ((c == '\'') || (c == '"')) {
+       NSString *res                  = nil;
+       char     string[_bufLen - pos];
+       unsigned cnt                   = 0;
+      
+       pos++;
+       while (pos < _bufLen) {
+         char ch = _buf[pos];
+         if (ch == c)
+           break;
+         if ((ch == '\\') && (_bufLen > (pos + 1))) {
+           if (_buf[pos + 1] == c) {
+             pos += 1;
+             ch = c;
+           }
+         }
+         string[cnt++] = ch;
+         pos++;
+       }
+       if (pos >= _bufLen) {
+         NSLog(@"WARNING(%s): found end of string before end of quoted text",
+               __PRETTY_FUNCTION__);
+         return nil;
+       }
+       res = [StringClass stringWithCString:string length:cnt];
+       pos++; /* don`t forget quotations */
+       if (qDebug) NSLog(@"_parseValue return <%@> for <%s> ", res, _buf);
+       obj = res;
+      }
+    }
+    
+    /* complete parsing of cast */
+    if (parseComplexCast && (pos + 6) < _bufLen) {
+      /* now we need " as 'dateTime'" [min 7 #] */
+      
+      /* skip spaces */
+      while (isspace(_buf[pos]) && pos < _bufLen) pos++;
+      
+      //printf("POS: '%s'\n", &(_buf[pos]));
+      /* parse 'as' */
+      if (_buf[pos] != 'a' && _buf[pos] != 'A')
+       NSLog(@"%s: expecting 'AS' of complex cast ...", __PRETTY_FUNCTION__);
+      else if (_buf[pos + 1] != 's' && _buf[pos + 1] != 'S')
+       NSLog(@"%s: expecting 'AS' of complex cast ...", __PRETTY_FUNCTION__);
+      else {
+       /* skip AS */
+       pos += 2;
+       
+       /* skip spaces */
+       while (isspace(_buf[pos]) && pos < _bufLen) pos++;
+       
+       /* read cast type */
+       if (_buf[pos] != '\'') {
+         NSLog(@"%s: expected type of complex cast ...", __PRETTY_FUNCTION__);
+       }
+       else {
+         const unsigned char *cs, *ce;
+         
+         //printf("POS: '%s'\n", &(_buf[pos]));
+         pos++;
+         cs = (const unsigned char *)&(_buf[pos]);
+         ce = (const unsigned char *)index((const char *)cs, '\'');
+         cast = [NSString stringWithCString:(const char*)cs length:(ce - cs)];
+         if (qDebug) {
+           NSLog(@"%s: parsed complex cast: '%@' to '%@'", 
+                 __PRETTY_FUNCTION__, obj, cast);
+         }
+         pos += (ce - cs);
+         pos++; // skip '
+         pos++; // skip )
+         //printf("POS: '%s'\n", &(_buf[pos]));
+       }
+      }
+    }
+  }
+  
+  if (cast != nil && obj != nil) {
+    Class class = Nil;
+    id orig = obj;
+    
+    if ((class = [NSPredicateParserTypeMappings objectForKey:cast]) == nil) {
+      /* no value explicitly mapped to class, try to construct class name... */
+      NSString *className;
+
+      className = cast;
+      if ((class = NSClassFromString(className)) == Nil) {
+        /* check some default cast types ... */
+        className = [cast lowercaseString];
+        
+        if ([className isEqualToString:@"datetime"])
+          class = [NSCalendarDate class];
+        else if ([className isEqualToString:@"datetime.tz"])
+          class = [NSCalendarDate class];
+      }
+    }
+    if (class) {
+      obj = [[[class alloc] initWithString:[orig description]] autorelease];
+      
+      if (obj == nil) {
+       NSLog(@"%s: could not init object '%@' of cast class %@(%@) !",
+             __PRETTY_FUNCTION__, orig, class, cast);
+       obj = null;
+      }
+    }
+    else {
+      NSLog(@"WARNING(%s): could not map cast '%@' to a class "
+           @"(returning null) !", 
+           __PRETTY_FUNCTION__, cast);
+      obj = null;
+    }
+  }
+  
+  if (qDebug) {
+    NSLog(@"%s: return <%@> for <%s> ", __PRETTY_FUNCTION__, 
+         obj?obj:@"<nil>", _buf);
+  }
+  
+  if (obj != nil) {
+    id keys[2], values[2];
+    
+    keys[0] = @"length"; values[0] = [NSNumber numberWithUnsignedInt:pos];
+    keys[1] = @"object"; values[1] = obj;
+    
+    [_ctx setResult:
+            [NSDictionary dictionaryWithObjects:values forKeys:keys count:2]
+          forFunction:@"parseValue" atPos:(unsigned)_buf];
+    *_keyLen = pos;
+  }
+  return obj;
+}
+
+static NSPredicate *_testOperator(id _ctx, const char *_buf,
+                                  unsigned _bufLen, unsigned *_opLen,
+                                  BOOL *isAnd)
+{
+  NSPredicate *qual       = nil;
+  char        c0, c1, c2  = 0;
+  unsigned    pos, len    = 0;
+
+  pos = _countWhiteSpaces(_buf, _bufLen);  
+  
+  if (_bufLen < 4) {/* at least OR or AND and somethink more */   
+    if (qDebug)
+      NSLog(@"_testOperator return nil for <%s> ", _buf);
+    return nil;
+  }
+  c0 = _buf[pos + 0];
+  c1 = _buf[pos + 1];
+  c2 = _buf[pos + 2];
+  
+  if (((c0 == 'a') || (c0  == 'A')) &&
+        ((c1 == 'n') || (c1  == 'N')) &&
+        ((c2 == 'd') || (c2  == 'D'))) {
+      pos    += 3;
+      *isAnd  = YES;
+  }
+  else if (((c0 == 'o') || (c0  == 'O')) && ((c1 == 'r') || (c1  == 'R'))) {
+      pos    += 2;
+      *isAnd  = NO;
+  }
+  pos += _countWhiteSpaces(_buf + pos, _bufLen - pos);
+  qual = _parseSinglePredicate(_ctx, _buf + pos, _bufLen - pos, &len);
+  *_opLen = pos + len;
+  if (qDebug)
+    NSLog(@"_testOperator return %@ for <%s> ", qual, _buf);
+  
+  return qual;
+}
+
+static NSPredicate *_parseCompoundPredicate(id _ctx, const char *_buf,
+                                            unsigned _bufLen, 
+                                           unsigned *_predLen)
+{
+  NSPredicate    *q0, *q1 = nil;
+  NSMutableArray *array   = nil;
+  unsigned       pos, len = 0;
+  NSPredicate    *result;
+  BOOL           isAnd;
+
+  isAnd = YES;
+
+  if ((q0 = _parseSinglePredicate(_ctx, _buf, _bufLen, &len)) == nil) {
+    if (qDebug)
+      NSLog(@"_parseAndOrPredicate return nil for <%s> ", _buf);
+    
+    return nil;
+  }
+  pos = len;
+
+  if (!(q1 = _testOperator(_ctx, _buf + pos, _bufLen - pos, &len, &isAnd))) {
+    if (qDebug)
+      NSLog(@"_parseAndOrPredicate return nil for <%s> ", _buf);
+    return nil;
+  }
+  pos  += len;
+  array = [NSMutableArray arrayWithObjects:q0, q1, nil];
+  
+  while (YES) {
+    BOOL newIsAnd;
+
+    newIsAnd = YES;
+    q0       = _testOperator(_ctx,  _buf + pos, _bufLen - pos, &len, &newIsAnd);
+
+    if (!q0)
+      break;
+    
+    if (newIsAnd != isAnd) {
+      NSArray *a;
+
+      a = [[array copy] autorelease];
+      
+      q1 = (isAnd)
+       ? [NSCompoundPredicate andPredicateWithSubpredicates:a]
+       : [NSCompoundPredicate orPredicateWithSubpredicates:a];
+      
+      [array removeAllObjects];
+      [array addObject:q1];
+      isAnd = newIsAnd;
+    }
+    [array addObject:q0];
+
+    pos += len;
+  }
+
+  *_predLen = pos;
+  result = (isAnd)
+    ? [NSCompoundPredicate andPredicateWithSubpredicates:array]
+    : [NSCompoundPredicate orPredicateWithSubpredicates:array];
+  
+  if (qDebug)
+    NSLog(@"_parseAndOrPredicate return <%@> for <%s> ", result, _buf);
+
+  return result;
+}
+
+static inline unsigned _countWhiteSpaces(const char *_buf, unsigned _bufLen) {
+  unsigned cnt = 0;
+  
+  if (_bufLen == 0) {
+    if (qDebug)
+      NSLog(@"_parseString _bufLen == 0 --> return nil");
+    return 0;
+  }
+  
+  while (_buf[cnt] == ' ' || _buf[cnt] == '\t' || 
+        _buf[cnt] == '\n' || _buf[cnt] == '\r') {
+    cnt++;
+    if (cnt == _bufLen)
+      break;
+  }
+  return cnt;
+}
diff --git a/libFoundation/Foundation/NSProcessInfo.h b/libFoundation/Foundation/NSProcessInfo.h
new file mode 100644 (file)
index 0000000..0e37a26
--- /dev/null
@@ -0,0 +1,68 @@
+/* 
+   NSProcessInfo.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSProcessInfo_h__
+#define __NSProcessInfo_h__
+
+#include <Foundation/NSObject.h>
+
+@class NSArray;
+@class NSMutableArray;
+@class NSDictionary;
+@class NSData;
+
+@interface NSProcessInfo : NSObject
+
++ (void)initializeWithArguments:(char**)argv
+    count:(int)argc
+    environment:(char**)env;
+
+/* Returning the name of the operating system */
++ (NSString*)operatingSystem;
+
+/* Getting an NSProcessInfo Object */
++ (NSProcessInfo*)processInfo;
+
+/* Returning Process Information */
+- (NSArray*)arguments;
+- (NSDictionary*)environment;
+- (NSString*)hostName;
+- (int)processIdentifier;
+- (NSString*)processName;
+- (NSString*)globallyUniqueString;
+
+/* Specifying a Process Name */
+
+- (void)setProcessName:(NSString*)newName;
+
+@end
+
+#endif /* __NSProcessInfo_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSProcessInfo.m b/libFoundation/Foundation/NSProcessInfo.m
new file mode 100644 (file)
index 0000000..e1d0191
--- /dev/null
@@ -0,0 +1,355 @@
+/* 
+   NSProcessInfo.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <config.h>
+
+#include <stdio.h>
+
+#if HAVE_LIBC_H
+# include <libc.h>
+#else
+# include <unistd.h>
+#endif
+
+#if HAVE_PROCESS_H
+# include <process.h>
+#endif
+
+#if HAVE_WINDOWS_H
+# include <windows.h>
+#endif
+
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#if defined(__CYGWIN32__) && 0
+# include <cygwin32/in.h>
+#endif
+
+#if defined(__MINGW32__)
+# include <winsock.h> // gethostbyname
+#endif
+
+#include <Foundation/common.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSPathUtilities.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSDate.h>
+#include <Foundation/NSProcessInfo.h>
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/StackZone.h>
+#include <Foundation/NSThread.h>
+#include <Foundation/NSLock.h>
+
+#include <extensions/objc-runtime.h>
+
+/*
+ * Static global vars
+ */
+
+static NSString* operatingSystem = @TARGET_PLATFORM;
+
+// The shared NSProcessInfo instance
+static NSProcessInfo* processInfo = nil;
+
+// Host name of machine executing the process
+static NSString* hostName = nil;   
+
+// Current process name
+static NSString* processName = nil;
+
+// Array of NSStrings (argv[0] .. argv[argc-1])
+static NSArray* arguments = nil;
+
+// Dictionary of environment vars and their values
+static NSDictionary* environment = nil;
+
+// Use a special zone to keep the environment variables to make possible
+// debugging when we use the DejaGnu tests. This zone is allocated big enough
+// to keep all the needed objects.
+static NSZone* environmentZone = nil;
+
+/*
+ * NSProcessInfo implementation
+ */
+
+char *_libFoundation_argv0 = NULL;
+
+@implementation NSProcessInfo
+
++ (void)initializeWithArguments:(char**)argv
+    count:(int)argc
+    environment:(char**)env
+{
+    if (processInfo)
+       return;
+
+    if (argv) {
+        int i, count;
+        char str[1024];
+        
+        /* Create an autorelease pool since there might be no one in effect
+           at this moment. */
+        CREATE_AUTORELEASE_POOL(pool);
+
+        _libFoundation_argv0 = argv[0];
+        
+        /*
+          Allocate in front to avoid recursion
+        */
+        processInfo = [[self allocWithZone:environmentZone] init];
+
+        /* Create a zone big enough to hold all the environment variables. This
+           should be done to make the program behaves exactly the same when it
+           is run from DejaGnu, gdb or command line. */
+#if 1
+        environmentZone = NSDefaultMallocZone();
+#else
+        environmentZone = [[StackZone alloc]
+                                      initForSize:128000
+                                      granularity:0 canFree:NO];
+#endif
+
+        /* Getting the process name */
+#if defined(__MINGW32__)
+        {
+            /*
+              Mingw32 sometimes has both '\' and '/' as path separators,
+              this is because some native Windows shells (eg tcsh or bash)
+              can handle both.
+            */
+            unsigned char *ppath, *tmp;
+            int           len, pos;
+           
+           ppath = argv[0];
+           len   = strlen(ppath);
+            tmp   = &(ppath[len - 1]);
+           
+            for (pos = 0; pos < len; pos++) {
+                if ((*tmp == '/') || (*tmp == '\\')) {
+                    tmp++;
+                    break;
+                }
+               tmp--;
+            }
+           if (pos == len) tmp++;
+           
+            processName = [[NSString allocWithZone:environmentZone]
+                                     initWithCString:tmp];
+        }
+#else        
+        processName = AUTORELEASE([[NSString allocWithZone:environmentZone]
+                                             initWithCString:argv[0]]);
+        processName = RETAIN([processName lastPathComponent]);
+#endif
+
+        /* Copy the argument list */
+        {
+            id *argstr;
+
+            argstr = Malloc (argc * sizeof(id));
+            for (i = 0; i < argc; i++) {
+                argstr[i]
+                    = AUTORELEASE([[NSString allocWithZone:environmentZone]
+                                      initWithCString:argv[i]]);
+            }
+            arguments = [[NSArray allocWithZone:environmentZone]
+                            initWithObjects:argstr count:argc];
+            lfFree(argstr);
+        }
+    
+        /* Count the the evironment variables. */
+        for (count = 0; env[count]; count++)
+            /* nothing */ ;
+
+#if 1
+        /* Copy the environment variables. */
+        {
+            id *keys, *vals;
+       
+            keys = Malloc (count * sizeof(id));
+            vals = Malloc (count * sizeof(id));
+            for (i = 0; i < count; i++) {
+                char     *cp, *p;
+                unsigned keyLen, valLen;
+
+#if defined(__MINGW32__)
+                {
+                    unsigned char *buf = objc_atomic_malloc(2048);
+                    DWORD         len;
+
+                    len = ExpandEnvironmentStrings(env[i], buf, 2046);
+                    if (len > 2046) {
+                        buf = objc_realloc(buf, len + 2);
+                        len = ExpandEnvironmentStrings(env[i], buf, len);
+                    }
+                    
+                    if (len == 0) {
+                        p = Strdup (env[i]);
+                        objc_free (buf); buf = NULL;
+                    }
+                    else {
+                        p = buf;
+                        buf = NULL;
+                    }
+                }
+#else                
+                p = Strdup (env[i]);
+#endif
+                for (cp = p; *cp != '=' && *cp; cp++);
+                *cp = '\0';
+                
+                keyLen = strlen(p);
+                cp++;
+                valLen = strlen(cp);
+                
+                vals[i] = [[NSString allocWithZone:environmentZone]
+                                     initWithCString:cp length:valLen];
+                keys[i] = [[NSString allocWithZone:environmentZone]
+                                     initWithCString:p length:keyLen];
+                lfFree(p);
+            }
+            environment = [[NSDictionary allocWithZone:environmentZone]
+                              initWithObjects:vals forKeys:keys count:count];
+            lfFree(keys);
+            lfFree(vals);
+        }
+#else
+        environment = [[NSDictionary alloc] init];
+#endif
+
+        gethostname(str, 1024);
+        hostName = [[NSString allocWithZone:environmentZone]
+                       initWithCString:str];
+
+        RELEASE(pool);
+    }
+}
+
++ (NSString*)operatingSystem
+{
+    return operatingSystem;
+}
+
++ (NSProcessInfo*)processInfo
+{
+    if (processInfo == nil) {
+       fprintf (stderr, "You must call +[NSProcessInfo "
+                        "initializeWithArguments:count:environment:] "
+                        "in main()\n");
+       exit (1);
+    }
+    return processInfo;
+}
+
+- (id)init
+{
+    return self;
+}
+
+- (NSArray*)arguments
+{
+    return arguments;
+}
+
+- (NSDictionary*)environment
+{
+    return environment;
+}
+
+- (NSString*)hostName
+{
+    return hostName;
+}
+
+- (int)processIdentifier
+{
+#if defined(__MINGW32__)
+    return (int)GetCurrentProcessId();
+#else                     
+    return (int)getpid();
+#endif
+}
+
+- (NSString*)processName
+{
+    return processName;
+}
+
+- (NSString*)globallyUniqueString
+{
+    static int counter = 0;
+    static NSRecursiveLock* lock = nil;
+
+    if (!lock)
+        lock = [NSRecursiveLock new];
+
+    [lock lock];
+    counter++;
+    [lock unlock];
+    
+    return [NSString stringWithFormat:@"%s:%d:%p:%f:%d",
+                     [hostName cString],
+                     [self processIdentifier],
+                     [NSThread currentThread],
+                     [[NSDate date] timeIntervalSince1970],
+                     counter];
+}
+
+- (void)setProcessName:(NSString*)aName
+{
+    if (aName && [aName length])
+        ASSIGN(processName, aName);
+}
+
+/*
+ * internal class that cannot be deleted
+ */
+
+- (id)autorelease
+{
+    return self;
+}
+
+- (void)release
+{
+    return;
+}
+
+- (id)retain
+{
+    return self;
+}
+
+@end
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSProxy.h b/libFoundation/Foundation/NSProxy.h
new file mode 100644 (file)
index 0000000..092fa28
--- /dev/null
@@ -0,0 +1,64 @@
+/* 
+   NSProxy.h
+
+   Copyright (C) 1998 MDlink online service center, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess (helge@mdlink.de)
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSProxy_h__
+#define __NSProxy_h__
+
+#include <Foundation/NSObject.h>
+#include <Foundation/NSZone.h>
+
+@class NSInvocation, NSMethodSignature, NSString;
+
+@interface NSProxy < NSObject >
+{
+    Class isa;
+}
+
++ (id)alloc;
++ (id)allocWithZone:(NSZone *)_zone;
+- (void)dealloc;
+
+// getting the class
+
++ (Class)class;
+
+// handling unimplemented methods
+
+- (void)forwardInvocation:(NSInvocation *)_invocation;
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)_selector;
+
+// description
+
+- (NSString *)description;
+
+@end
+
+#endif // __NSProxy_h__
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSProxy.m b/libFoundation/Foundation/NSProxy.m
new file mode 100644 (file)
index 0000000..44b1057
--- /dev/null
@@ -0,0 +1,497 @@
+/* 
+   NSProxy.m
+
+   Copyright (C) 1998 MDlink online service center, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess (helge@mdlink.de)
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <config.h>
+#include <Foundation/common.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSMethodSignature.h>
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/NSInvocation.h>
+#include <Foundation/NSUtilities.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+#include <extensions/objc-runtime.h>
+#include "NSProxy.h"
+
+@implementation NSProxy
+
++ (id)alloc
+{
+    return [self allocWithZone:NULL];
+}
++ (id)allocWithZone:(NSZone *)_zone
+{
+    return NSAllocateObject(self, 0, _zone);
+}
+
+- (void)dealloc
+{
+#if !LIB_FOUNDATION_BOEHM_GC
+    NSDeallocateObject((NSObject *)self);
+#endif
+}
+
+// getting the class
+
++ (Class)class {
+    return self;
+}
+
+// handling unimplemented methods
+
+- (void)forwardInvocation:(NSInvocation *)_invocation
+{
+    [[[InvalidArgumentException new]
+              setReason:@"NSProxy subclass should override forwardInvocation:"] raise];
+}
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)_selector
+{
+    [[[InvalidArgumentException new]
+      setReason:@"NSProxy subclass should override methodSignatureForSelector:"] raise];
+    return nil;
+}
+
+// description
+
+- (NSString *)description
+{
+    /* Don't use -[NSString stringWithFormat:] method because it can cause
+       infinite recursion. */
+    char buffer[512];
+
+    sprintf (buffer, "<%s %p>", (char*)object_get_class_name(self), self);
+    return [NSString stringWithCString:buffer];
+}
+
+// ******************** Class methods ************************
+
+/*
+  Usually instance methods of root classes are inherited to the class object
+  of the root class. This isn't the case for most proxy methods, since the
+  proxy implementations usually just forward to the real object using
+  forwardInvocation:.
+*/
+
+/* Identifying Class and Superclass */
+
++ (Class)superclass
+{
+    return class_get_super_class(self);
+}
+
+/* Determining Allocation Zones */
++ (NSZone*)zone
+{
+    return NSZoneFromObject(self);
+}
+
+/* Identifying Proxies */
++ (BOOL)isProxy
+{
+    // while instances of NSProxy are proxies, the class itself isn't
+    return NO;
+}
+
+/* Testing Inheritance Relationships */
++ (BOOL)isKindOfClass:(Class)aClass
+{
+    // this is the behaviour specified in the MacOSX docs
+    return (aClass == [NSObject class]) ? YES : NO;
+}
++ (BOOL)isMemberOfClass:(Class)aClass
+{
+    // behaviour as specified in the MacOSX docs
+    return NO;
+}
+
+/* Testing for Protocol Conformance */
++ (BOOL)conformsToProtocol:(Protocol*)aProtocol
+{
+    struct objc_protocol_list *protos;
+
+    for (protos = ((struct objc_class*)self)->protocols;
+         protos; protos = protos->next) {
+        int i;
+        
+       for(i = 0; i < protos->count; i++)
+           if([protos->list[i] conformsTo:aProtocol])
+               return YES;
+    }
+
+    return [self superclass]
+       ? [[self superclass] conformsToProtocol: aProtocol]
+        : NO;
+}
+
+/* Testing Class Functionality */
++ (BOOL)respondsToSelector:(SEL)aSelector
+{
+    return (!aSelector)
+       ? NO
+        : (class_get_class_method(self, aSelector) != METHOD_NULL);
+}
+
+/* Managing Reference Counts */
++ (id)autorelease
+{
+    return self;
+}
++ (oneway void)release
+{
+}
++ (id)retain
+{
+    return self;
+}
++ (unsigned int)retainCount
+{
+    return (unsigned)-1;
+}
+
+/* Identifying and Comparing Instances */
++ (unsigned)hash
+{
+    return (unsigned)(unsigned long)self;
+}
++ (BOOL)isEqual:(id)anObject
+{
+    return (self == anObject) ? YES : NO;
+}   
++ (id)self
+{
+    return self;
+}
+
+/* Sending Messages Determined at Run Time */
++ (id)performSelector:(SEL)aSelector
+{
+    IMP msg = aSelector ? objc_msg_lookup(self, aSelector) : NULL;
+
+    if(msg == NULL) {
+       [[[ObjcRuntimeException alloc] initWithFormat:
+           @"invalid selector `%s' passed to %s",
+           sel_get_name(aSelector), sel_get_name(_cmd)] raise];
+    }
+    return (*msg)(self, aSelector);
+}
++ (id)performSelector:(SEL)aSelector withObject:(id)anObject
+{
+    IMP msg = aSelector ? objc_msg_lookup(self, aSelector) : NULL;
+
+    if(msg == NULL) {
+       [[[ObjcRuntimeException alloc] initWithFormat:
+           @"invalid selector `%s' passed to %s",
+           sel_get_name(aSelector), sel_get_name(_cmd)] raise];
+    }
+    return (*msg)(self, aSelector, anObject);
+}
++ (id)performSelector:(SEL)aSelector withObject:(id)anObject
+  withObject:(id)anotherObject
+{
+    IMP msg = aSelector ? objc_msg_lookup(self, aSelector) : NULL;
+
+    if(msg == NULL) {
+       [[[ObjcRuntimeException alloc] initWithFormat:
+           @"invalid selector `%s' passed to %s",
+           sel_get_name(aSelector), sel_get_name(_cmd)] raise];
+    }
+    return (*msg)(self, aSelector, anObject, anotherObject);
+}
+
+/* Describing the Object */
++ (NSString *)description
+{
+    /* Don't use -[NSString stringWithFormat:] method because it can cause
+       infinite recursion. */
+    char buffer[512];
+
+    sprintf (buffer, "<class %s>", (char*)object_get_class_name(self));
+    return [NSString stringWithCString:buffer];
+}
+
+// ******************** NSObject protocol ********************
+
+static inline NSInvocation *
+_makeInvocation(NSProxy *self, SEL _cmd, const char *sig)
+{
+    NSMethodSignature *s;
+    NSInvocation      *i;
+
+    s = [NSMethodSignature signatureWithObjCTypes:sig];
+    if (s == nil) return nil;
+    i = [NSInvocation invocationWithMethodSignature:s];
+    if (i == nil) return nil;
+
+    [i setSelector:_cmd];
+    [i setTarget:self];
+
+    return i;
+}
+static inline NSInvocation *
+_makeInvocation1(NSProxy *self, SEL _cmd, const char *sig, id _object)
+{
+    NSInvocation *i = _makeInvocation(self, _cmd, sig);
+    [i setArgument:&_object atIndex:2];
+    return i;
+}
+
+- (id)autorelease
+{
+#if !LIB_FOUNDATION_BOEHM_GC
+    [NSAutoreleasePool addObject:self];
+#endif
+    return self;
+}
+- (id)retain
+{
+#if !LIB_FOUNDATION_BOEHM_GC
+    NSIncrementExtraRefCount(self);
+#endif
+    return self;
+}
+- (oneway void)release
+{
+    if (NSExtraRefCount(self) == 1)
+       [self dealloc];
+    else
+       NSDecrementExtraRefCountWasZero(self);
+}
+- (unsigned)retainCount
+{
+    return NSExtraRefCount(self);
+}
+
+- (Class)class
+{
+    // Note that this returns the proxy class, not the real one !
+    return self->isa;
+}
+- (Class)superclass
+{
+    // Note that this returns the proxy's class superclass, not the real one !
+    return class_get_super_class(self->isa);
+}
+
+- (BOOL)conformsToProtocol:(Protocol *)_protocol
+{
+    NSInvocation *i = _makeInvocation1(self, _cmd, "C@:@", _protocol);
+    BOOL         r;
+    [i invoke];
+    [i getReturnValue:&r];
+    return r;
+}
+- (BOOL)isKindOfClass:(Class)_class
+{
+    NSInvocation *i = _makeInvocation1(self, _cmd, "C@:@", _class);
+    BOOL result;
+    [i invoke];
+    [i getReturnValue:&result];
+    return result;
+}
+- (BOOL)isMemberOfClass:(Class)_class
+{
+    NSInvocation *i = _makeInvocation1(self, _cmd, "C@:@", _class);
+    BOOL result;
+    [i invoke];
+    [i getReturnValue:&result];
+    return result;
+}
+
+- (BOOL)isProxy
+{
+    return YES;
+}
+
+- (BOOL)respondsToSelector:(SEL)_selector
+{
+    NSInvocation *i;
+    BOOL         r;
+
+    if (_selector) {
+        if (objc_msg_lookup(self, _selector)) return YES;
+    }
+
+    i = _makeInvocation(self, _cmd, "C@::");
+    [i setArgument:&_selector atIndex:2];
+    [i invoke];
+    [i getReturnValue:&r];
+    return r;
+}
+
+- (id)performSelector:(SEL)_selector
+{
+    NSInvocation *i;
+    id           result;
+    IMP          msg;
+
+    if (_selector == NULL) {
+        [[[InvalidArgumentException new]
+             setReason:@"passed NULL selector to performSelector:"]
+             raise];
+    }
+
+    if ((msg = objc_msg_lookup(self, _selector)))
+        return msg(self, _selector);
+
+    i = [NSInvocation invocationWithMethodSignature:
+                        [NSMethodSignature signatureWithObjCTypes:"@@:"]];
+    [i setTarget:self];
+    [i setSelector:_selector];
+    [i invoke];
+    [i getReturnValue:&result];
+    return result;
+}
+- (id)performSelector:(SEL)_selector withObject:(id)_object
+{
+    NSInvocation *i;
+    id           result;
+    IMP          msg;
+
+    if (_selector == NULL) {
+        [[[InvalidArgumentException new]
+                  setReason:@"passed NULL selector to performSelector:"] raise];
+    }
+
+    if ((msg = objc_msg_lookup(self, _selector)))
+        return msg(self, _selector, _object);
+    
+    i = [NSInvocation invocationWithMethodSignature:
+                        [NSMethodSignature signatureWithObjCTypes:"@@:@"]];
+    [i setTarget:self];
+    [i setSelector:_selector];
+    [i setArgument:&_object atIndex:2];
+    [i invoke];
+    [i getReturnValue:&result];
+    return result;
+}
+- (id)performSelector:(SEL)_selector withObject:(id)_object withObject:(id)_object2
+{
+    NSInvocation *i;
+    id           result;
+    IMP          msg;
+
+    if (_selector == NULL) {
+        [[[InvalidArgumentException new]
+                  setReason:@"passed NULL selector to performSelector:"] raise];
+    }
+
+    if ((msg = objc_msg_lookup(self, _selector)))
+        return msg(self, _selector, _object, _object2);
+    
+    i = [NSInvocation invocationWithMethodSignature:
+                        [NSMethodSignature signatureWithObjCTypes:"@@:@@"]];
+    [i setTarget:self];
+    [i setSelector:_selector];
+    [i setArgument:&_object  atIndex:2];
+    [i setArgument:&_object2 atIndex:3];
+    [i invoke];
+    [i getReturnValue:&result];
+    return result;
+}
+
+- (id)self
+{
+    return self;
+}
+
+- (NSZone *)zone
+{
+    return NSZoneFromObject((NSObject *)self);
+}
+
+- (BOOL)isEqual:(id)_object
+{
+    NSInvocation *i = _makeInvocation1(self, _cmd, "C@:@", _object);
+    BOOL result;
+
+    [i invoke];
+    [i getReturnValue:&result];
+    return result;
+}
+- (unsigned)hash
+{
+    NSInvocation *i = _makeInvocation(self, _cmd, "I@:");
+    unsigned hc;
+    [i invoke];
+    [i getReturnValue:&hc];
+    return hc;
+}
+
+// ******************** forwarding ********************
+
+- (retval_t)forward:(SEL)_selector:(arglist_t)argFrame {
+  void         *result;
+  NSInvocation *invocation;
+#if defined(NeXT_RUNTIME) && !defined(BROKEN_BUILTIN_APPLY) && defined(i386)
+  const char   *retType;
+#endif
+
+#if NeXT_RUNTIME
+  /*  On NeXT the argFrame represents the stack zone with all the arguments.
+      We create a frame like that required by __builtin_apply. This is done
+      by __builtin_apply_args. This builtin function also sets correctly the
+      structure value return address if any. */
+  arglist_t frame = __builtin_apply_args();
+
+  frame->arg_ptr = (void*)argFrame;
+  argFrame = frame;
+#endif
+
+  invocation = [NSInvocation invocationWithMethodSignature:
+                               [self methodSignatureForSelector:_selector]];
+  [invocation setArgumentFrame:argFrame];
+  [invocation setTarget:self];
+  [invocation setSelector:_selector];
+
+  [self forwardInvocation:invocation];
+
+  result = [invocation returnFrame];
+  
+#if GNU_RUNTIME
+  return result;
+#else // NeXT_RUNTIME
+# if !defined(BROKEN_BUILTIN_APPLY) && defined(i386)
+  /* Special hack to avoid pushing the poped float value back to the fp
+     stack on i386 machines. This happens with NeXT runtime and 2.7.2
+     compiler. If the result value is floating point don't call
+     __builtin_return anymore. */
+  retType = [[invocation methodSignature] methodReturnType];
+  if(*retType == _C_FLT || *retType == _C_DBL) {
+    long double value = *(long double*)(((char*)result) + 8);
+    asm("fld %0" : : "f" (value));
+  }
+  else
+# endif
+    __builtin_return(result);
+#endif /* NeXT_RUNTIME */
+}
+
+@end
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSRange.h b/libFoundation/Foundation/NSRange.h
new file mode 100644 (file)
index 0000000..fe0b2d3
--- /dev/null
@@ -0,0 +1,85 @@
+/* 
+   NSRange.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSRange_h__
+#define __NSRange_h__
+
+#include <Foundation/NSObject.h>
+
+typedef struct _NSRange 
+{
+    unsigned int location;
+    unsigned int length;
+} NSRange;
+
+#if (__GNUC__ == 2) && (__GNUC_MINOR__ <= 6) && !defined(__attribute__)
+#  define __attribute__(x)
+#endif
+
+@class NSString;
+
+LF_EXPORT NSRange      NSUnionRange(NSRange range1, NSRange range2);
+LF_EXPORT NSRange      NSIntersectionRange(NSRange range1, NSRange range2);
+LF_EXPORT NSString* NSStringFromRange(NSRange range);
+LF_EXPORT NSRange  NSSRangeFromString(NSString* string);
+LF_EXPORT BOOL         NSEqualRanges(NSRange range1, NSRange range2);
+
+static inline unsigned NSMaxRange(NSRange) __attribute__((unused));
+static inline BOOL NSLocationInRange(unsigned, NSRange)
+    __attribute__((unused));
+
+static inline NSRange
+NSMakeRange(unsigned int location, unsigned int length)
+    __attribute__((unused));
+
+
+static inline NSRange
+NSMakeRange(unsigned int location, unsigned int length)
+{
+    NSRange range;
+    range.location = location;
+    range.length   = length;
+    return range;
+}
+
+static inline unsigned
+NSMaxRange(NSRange range) 
+{
+  return range.location + range.length;
+}
+
+static inline BOOL 
+NSLocationInRange(unsigned location, NSRange range) 
+{
+  return (location >= range.location) && (location < NSMaxRange(range));
+}
+
+#endif /* __NSRange_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSRange.m b/libFoundation/Foundation/NSRange.m
new file mode 100644 (file)
index 0000000..8e6e153
--- /dev/null
@@ -0,0 +1,82 @@
+/* 
+   NSRange.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+          Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSString.h>
+
+/* Query a Range */
+BOOL   
+NSEqualRanges(NSRange range1, NSRange range2)
+{
+    return ((range1.location == range2.location)
+               && (range1.length == range2.length));
+}
+
+/* Compute a Range from Two Other Ranges */
+NSRange 
+NSUnionRange(NSRange aRange, NSRange bRange)
+{
+    NSRange range;
+    
+    range.location = MIN(aRange.location, bRange.location);
+    range.length   = MAX(NSMaxRange(aRange), NSMaxRange(bRange)) 
+               - range.location;
+    return range;
+}
+
+NSRange 
+NSIntersectionRange (NSRange aRange, NSRange bRange)
+{
+    NSRange range;
+    
+    if (NSMaxRange(aRange) < bRange.location
+               || NSMaxRange(bRange) < aRange.location)
+       return NSMakeRange(0, 0);
+       
+    range.location = MAX(aRange.location, bRange.location);
+    range.length   = MIN(NSMaxRange(aRange), NSMaxRange(bRange)) 
+               - range.location;
+    return range;
+}
+
+NSString*
+NSStringFromRange(NSRange range)
+{
+    return [NSString stringWithFormat:@"{location = %d; length = %d}",
+               range.location, range.length];
+}
+
+NSRange
+NSSRangeFromString(NSString* string)
+{
+    return NSMakeRange(0,0);
+}
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSRunLoop.h b/libFoundation/Foundation/NSRunLoop.h
new file mode 100644 (file)
index 0000000..d7aed78
--- /dev/null
@@ -0,0 +1,111 @@
+/* 
+   NSRunLoop.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSRunLoop_h__
+#define __NSRunLoop_h__
+
+#include <Foundation/NSObject.h>
+
+@class NSString, NSDate, NSTimer, NSNotification;
+@class NSPosixFileDescriptor;
+@class NSMutableArray, NSMutableDictionary;
+@class NSPort;
+
+LF_EXPORT NSString *NSDefaultRunLoopMode;
+LF_EXPORT NSString *NSConnectionReplyMode;
+
+LF_EXPORT NSString *NSFileObjectBecameActiveNotificationName; // not OpenStep
+
+@interface NSRunLoop : NSObject
+{
+    NSMutableDictionary *inputsForMode;
+    NSString            *mode;
+}
+
+/* Accessing the Current Run Loop */
++ (NSRunLoop*)currentRunLoop;
+- (NSString*)currentMode;
+- (NSDate*)limitDateForMode:(NSString*)mode;
+
+/* Adding Timers */
+- (void)addTimer:(NSTimer*)aTimer
+       forMode:(NSString*)mode;
+
+/* Running a Run Loop */
+- (void)acceptInputForMode:(NSString*)mode
+       beforeDate:(NSDate*)limitDate;
+- (void)run;
+- (BOOL)runMode:(NSString*)mode
+       beforeDate:(NSDate*)limitDate;
+- (void)runUntilDate:(NSDate*)limitDate;
+
+/* Delayed perform of an action */
+- (void)performSelector:(SEL)aSelector
+  target:(id)target
+  argument:(id)anArgument
+  order:(unsigned)order
+  modes:(NSArray*)modes;
+- (void)cancelPerformSelector:(SEL)aSelector
+  target:(id)target
+  argument:(id)anArgument;
+
+/* Monitoring file descriptors */
+- (void)addPosixFileDescriptor:(NSPosixFileDescriptor*)fileDescriptor
+  forMode:(NSString*)mode;
+- (void)removePosixFileDescriptor:(NSPosixFileDescriptor*)fileDescriptor
+  forMode:(NSString*)mode;
+
+/* Monitoring file objects */
+- (void)addFileObject:(id)_fileObject
+  activities:(unsigned int)_activities
+  forMode:(NSString *)_mode;
+- (void)removeFileObject:(id)_fileObject
+  forMode:(NSString *)_mode;
+
+/* Ports */
+- (void)addPort:(NSPort *)_port forMode:(NSString *)_mode;
+- (void)removePort:(NSPort *)_port forMode:(NSString *)_mode;
+
+/* Server operation */
+- (void)configureAsServer;
+
+/* Private methods */
++ (void)taskNowMultiThreaded:(NSNotification *)notification;
+
+@end
+
+@interface NSObject(RunloopFileObject)
+
+- (int)fileDescriptor;
+
+@end
+
+#endif /* __NSRunLoop_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSRunLoop.m b/libFoundation/Foundation/NSRunLoop.m
new file mode 100644 (file)
index 0000000..51d506b
--- /dev/null
@@ -0,0 +1,889 @@
+/* 
+   NSRunLoop.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+           Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+
+#include <sys/types.h>
+#if HAVE_SYS_ERRNO_H
+#include <sys/errno.h>
+#endif
+#include <errno.h>
+
+#if HAVE_SYS_TIME_H
+# include <sys/time.h> /* for struct timeval */
+#endif
+
+#if HAVE_STRING_H
+# include <string.h>
+#endif
+
+#if HAVE_MEMORY_H
+# include <memory.h>
+#endif
+
+#if !HAVE_MEMCPY
+# define memcpy(d, s, n)       bcopy((s), (d), (n))
+# define memmove(d, s, n)      bcopy((s), (d), (n))
+#endif
+
+#if HAVE_LIBC_H
+# include <libc.h>
+#else
+# include <unistd.h>
+#endif
+
+#if HAVE_WINDOWS_H
+# include <windows.h>
+#endif
+
+#if HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif
+
+#include <Foundation/NSRunLoop.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSValue.h>
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/NSDate.h>
+#include <Foundation/NSTimer.h>
+#include <Foundation/NSUtilities.h>
+#include <Foundation/NSThread.h>
+#include <Foundation/NSLock.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSPosixFileDescriptor.h>
+#include <Foundation/NSNotification.h>
+#include <Foundation/NSNotificationQueue.h>
+#include <Foundation/UnixSignalHandler.h>
+
+#include <extensions/objc-runtime.h>
+
+NSString* NSDefaultRunLoopMode = @"NSDefaultRunLoopMode";
+NSString* NSConnectionReplyMode = @"NSConnectionReplyMode";
+NSString* NSFileObjectBecameActiveNotificationName =
+  @"NSFileObjectBecameActiveNotificationName";
+
+static char *activityDesc[8] = {
+    "---", // 0
+    "--R", // 1
+    "-W-", // 2
+    "-WR", // 3
+    "E--", // 4
+    "E-R", // 5
+    "EW-", // 6
+    "EWR"  // 7
+};
+
+@interface NSRunLoopFileObjectInfo : NSObject
+{
+    id                    fileObject;
+    NSPosixFileActivities watchedActivities;
+    BOOL                  canCheckAlive;
+}
+
+- (id)initWithFileObject:(id)_fileObject
+  activities:(NSPosixFileActivities)_activities;
+
+- (BOOL)isAlive;
+- (int)fileDescriptor;
+- (NSPosixFileActivities)watchedActivities;
+
+- (void)activity:(NSPosixFileActivities)_activity onDescriptor:(int)_fd;
+
+@end
+
+@implementation NSRunLoopFileObjectInfo
+
+- (id)initWithFileObject:(id)_fileObject
+  activities:(NSPosixFileActivities)_activities
+{
+  self->fileObject        = RETAIN(_fileObject);
+  self->watchedActivities = _activities;
+  self->canCheckAlive     = [_fileObject respondsToSelector:@selector(isAlive)];
+  return self;
+}
+- (id)init
+{
+      NSLog(@"ERROR: do not use init with NSRunLoopFileObjectInfo ..");
+      self = AUTORELEASE(self);
+      return nil;
+}
+
+- (void)dealloc
+{
+    RELEASE(self->fileObject); self->fileObject = nil;
+    [super dealloc];
+}
+
+- (BOOL)isEqual:(NSRunLoopFileObjectInfo*)otherInfo
+{
+    return [self->fileObject isEqual:otherInfo->fileObject];
+}
+
+- (BOOL)isAlive {
+    return (self->canCheckAlive) ? [self->fileObject isAlive] : YES;
+}
+- (int)fileDescriptor
+{
+    return [self->fileObject fileDescriptor];
+}
+
+- (NSPosixFileActivities)watchedActivities
+{
+    return self->watchedActivities;
+}
+
+- (void)activity:(NSPosixFileActivities)_activity onDescriptor:(int)_fd
+{
+#if 0
+    NSLog(@"%s:%i: FileObject %@ became active ..", __PRETTY_FUNCTION__,__LINE__,
+          self->fileObject);
+#endif
+    
+    if ([self->fileObject isKindOfClass:[NSPosixFileDescriptor class]]) {
+        if (_activity & NSPosixReadableActivity) {
+            [[self->fileObject delegate]
+                               activity:NSPosixReadableActivity
+                               posixFileDescriptor:self->fileObject];
+        }
+        if (_activity & NSPosixWritableActivity) {
+            [[self->fileObject delegate]
+                               activity:NSPosixWritableActivity
+                               posixFileDescriptor:self->fileObject];
+        }
+        if (_activity & NSPosixExceptionalActivity) {
+            [[self->fileObject delegate]
+                               activity:NSPosixExceptionalActivity
+                               posixFileDescriptor:self->fileObject];
+        }
+    }
+    else {
+        [[NSNotificationCenter defaultCenter]
+                               postNotificationName:
+                                 NSFileObjectBecameActiveNotificationName
+                               object:self->fileObject];
+    }
+}
+
+- (NSString *)description
+{
+    return [NSString stringWithFormat:
+                       @"<%@[0x%08X]: object=%@ actitivity=%s>",
+                       NSStringFromClass([self class]), self,
+                       self->fileObject,
+                       activityDesc[self->watchedActivities]
+                     ];
+}
+
+@end
+
+@interface NSRunLoopTimerInfo : NSObject
+{
+    NSTimer* timer;
+    NSDate* fireDate;
+}
+
++ (NSRunLoopTimerInfo*)infoWithTimer:(NSTimer*)timer;
+- (void)recomputeFireDate;
+- (NSComparisonResult)compare:(NSRunLoopTimerInfo*)anObject;
+- (NSTimer*)timer;
+- (NSDate*)fireDate;
+@end
+
+@implementation NSRunLoopTimerInfo
+
++ (NSRunLoopTimerInfo *)infoWithTimer:(NSTimer*)aTimer
+{
+    NSRunLoopTimerInfo *info = [self new];
+    
+    info->timer    = RETAIN(aTimer);
+    info->fireDate = RETAIN([aTimer fireDate]);
+    return AUTORELEASE(info);
+}
+
+- (void)dealloc
+{
+    RELEASE(self->timer);
+    RELEASE(self->fireDate);
+    [super dealloc];
+}
+
+- (void)recomputeFireDate
+{
+  if ([self->timer isValid]) {
+    id tmp = [self->timer fireDate];
+    ASSIGN(self->fireDate, tmp);
+  }
+}
+
+- (NSComparisonResult)compare:(NSRunLoopTimerInfo*)anObject
+{
+    return [self->fireDate compare:anObject->fireDate];
+}
+
+- (NSTimer *)timer   { return self->timer;    }
+- (NSDate *)fireDate { return self->fireDate; }
+
+@end
+
+@interface NSRunLoopActionHolder : NSObject
+{
+    id target;
+    id argument;
+    SEL action;
+    int order;
+}
++ objectWithTarget:(id)target
+  argument:(id)argument
+  selector:(SEL)action
+  order:(int)order;
+- (BOOL)isEqual:(id)anotherHolder;
+- (void)execute;
+@end
+
+@implementation NSRunLoopActionHolder
+
++ (id)objectWithTarget:(id)_target
+  argument:(id)_argument
+  selector:(SEL)_action
+  order:(int)_order
+{
+    NSRunLoopActionHolder* holder = AUTORELEASE([self alloc]);
+
+    holder->target   = RETAIN(_target);
+    holder->argument = RETAIN(_argument);
+    holder->action   = _action;
+    holder->order    = _order;
+
+    return holder;
+}
+
+- (unsigned)hash
+{
+  return [(NSObject *)self->target hash];
+}
+
+- (BOOL)isEqual:(NSRunLoopActionHolder*)anotherHolder
+{
+    return [self->target isEqual:anotherHolder->target]
+           && [argument isEqual:anotherHolder->argument]
+           && SEL_EQ(self->action, anotherHolder->action);
+}
+
+- (void)execute
+{
+    [self->target performSelector:self->action withObject:self->argument];
+}
+
+- (NSComparisonResult)compare:(NSRunLoopActionHolder*)anotherHolder
+{
+    return (order - anotherHolder->order);
+}
+
+@end /* NSRunLoopActionHolder */
+
+
+@interface NSRunLoopInputManager : NSObject
+{
+    NSMutableArray *fileObjects;
+    NSMutableArray *timers;
+    NSMutableArray *otherOperations;
+}
+
+- (void)addFileObject:(id)_fileObject
+  activities:(NSPosixFileActivities)_activities;
+- (void)removeFileObject:(id)_fileObject;
+
+- (void)addPosixFileDescriptor:(NSPosixFileDescriptor*)fileDescriptor;
+- (void)removePosixFileDescriptor:(NSPosixFileDescriptor*)fileDescriptor;
+
+- (void)addTimer:(NSTimer*)aTimer;
+
+- (NSMutableArray*)fileObjects;
+- (NSMutableArray*)timers;
+
+- (void)addOperation:(NSRunLoopActionHolder*)holder;
+- (void)removeOperation:(NSRunLoopActionHolder*)holder;
+- (void)performAdditionalOperations;
+@end
+
+
+@implementation NSRunLoopInputManager
+
+- (id)init
+{
+    NSZone *z = [self zone];
+    self->fileObjects     = [[NSMutableArray allocWithZone:z] init];
+    self->timers          = [[NSMutableArray allocWithZone:z] init];
+    self->otherOperations = [[NSMutableArray allocWithZone:z] init];
+    return [super init];
+}
+
+- (void)dealloc
+{
+    RELEASE(self->fileObjects);
+    RELEASE(self->timers);
+    RELEASE(self->otherOperations);
+    [super dealloc];
+}
+
+- (void)addFileObject:(id)_fileObject
+  activities:(NSPosixFileActivities)_activities
+{
+    NSRunLoopFileObjectInfo *info = nil;
+    //NSAssert(_activities, @"no activity to watch ?!");
+    info = [[NSRunLoopFileObjectInfo allocWithZone:[self zone]]
+                                     initWithFileObject:_fileObject
+                                     activities:_activities];
+    [self->fileObjects addObject:info];
+    //NSLog(@"file objects now: %@", self->fileObjects);
+    RELEASE(info); info = nil;
+}
+- (void)removeFileObject:(id)_fileObject
+{
+    NSRunLoopFileObjectInfo *info = nil;
+    info = [[NSRunLoopFileObjectInfo allocWithZone:[self zone]]
+                                     initWithFileObject:_fileObject
+                                     activities:0];
+    [self->fileObjects removeObject:info];
+    //NSLog(@"file objects now: %@", self->fileObjects);
+    RELEASE(info); info = nil;
+}
+
+- (void)addPosixFileDescriptor:(NSPosixFileDescriptor*)fileDescriptor
+{
+    [self addFileObject:fileDescriptor
+          activities:[fileDescriptor fileActivity]];
+}
+
+- (void)removePosixFileDescriptor:(NSPosixFileDescriptor*)fileDescriptor
+{
+    [self removeFileObject:fileDescriptor];
+}
+
+- (void)addTimer:(NSTimer*)aTimer
+{
+    [self->timers addObject:[NSRunLoopTimerInfo infoWithTimer:aTimer]];
+}
+
+- (void)addOperation:(NSRunLoopActionHolder*)holder
+{
+    [self->otherOperations addObject:holder];
+    [self->otherOperations sortUsingSelector:@selector(compare:)];
+}
+
+- (void)removeOperation:(NSRunLoopActionHolder*)holder
+{
+    [self->otherOperations removeObject:holder];
+}
+
+- (void)performAdditionalOperations
+{
+    [self->otherOperations makeObjectsPerform:@selector(execute)];
+}
+
+- (NSMutableArray *)fileObjects
+{
+    return self->fileObjects;
+}
+- (NSMutableArray *)timers
+{
+    return self->timers;
+}
+
+@end /* NSRunLoopInputManager */
+
+
+@implementation NSRunLoop
+
+extern NSRecursiveLock* libFoundationLock;
+
+/* Class variable */
+static NSMutableDictionary* runLoopsDictionary = nil;
+static NSRunLoop* currentRunLoop = nil;
+static BOOL taskIsMultithreaded = NO;
+
+/*
++ (void)initialize
+{
+    [[NSNotificationCenter defaultCenter]
+       addObserver:self
+       selector:@selector(taskNowMultiThreaded:)
+       name:NSWillBecomeMultiThreadedNotification
+       object:nil];
+}
+*/
+
++ (NSRunLoop *)currentRunLoop
+{
+    if (taskIsMultithreaded) {
+       NSRunLoop* currentLoop;
+       NSThread* currentThread;
+
+       [libFoundationLock lock];
+
+       currentThread = [NSThread currentThread];
+       currentLoop = [runLoopsDictionary objectForKey:currentThread];
+       if (!currentLoop) {
+           currentLoop = AUTORELEASE([self new]);
+           [runLoopsDictionary setObject:currentLoop forKey:currentThread];
+       }
+
+       [libFoundationLock unlock];
+
+       return currentLoop;
+    }
+    else {
+       if (!currentRunLoop)
+           currentRunLoop = [self new];
+       return currentRunLoop;
+    }
+}
+
++ (void)taskNowMultiThreaded:(NSNotification *)notification
+{
+    taskIsMultithreaded = YES;
+    runLoopsDictionary = [NSMutableDictionary new];
+
+    if (currentRunLoop) {
+       NSThread* currentThread = [NSThread currentThread];
+
+       [runLoopsDictionary setObject:currentRunLoop forKey:currentThread];
+       RELEASE(currentRunLoop);
+       currentRunLoop = nil;
+    }
+}
+
+- init
+{
+    self = [super init];
+    self->inputsForMode =
+        [[NSMutableDictionary allocWithZone:[self zone]] init];
+    self->mode = RETAIN(NSDefaultRunLoopMode);
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(self->inputsForMode);
+    RELEASE(self->mode);
+    [super dealloc];
+}
+
+- (NSString*)currentMode
+{
+    return mode;
+}
+
+static inline NSRunLoopInputManager*
+_getInputManager(NSRunLoop *self, NSString *_mode)
+{
+    NSRunLoopInputManager* inputManager;
+
+    inputManager = [self->inputsForMode objectForKey:_mode];
+    if (inputManager == nil) {
+        inputManager = [[NSRunLoopInputManager alloc] init];
+        [self->inputsForMode setObject:inputManager forKey:_mode];
+        RELEASE(inputManager);
+    }
+    return inputManager;
+}
+
+static int compare_fire_dates(id timer1, id timer2, void* userData)
+{
+    return [[timer1 fireDate] compare:[timer2 fireDate]];
+}
+
+- (NSDate*)limitDateForMode:(NSString*)aMode
+{
+    NSString       *format =
+        @"%s: During NSTimer:-fire, caught exception %@ with reason %@ ";
+    NSMutableArray *timers = [[inputsForMode objectForKey:aMode] timers];
+    volatile int   i, count;
+    NSMutableArray *copyOfTimers;
+
+    ASSIGN(mode, aMode);
+
+    /* Remove invalid timers */
+    for(count = [timers count], i = count - 1; i >= 0; i--) {
+        if(![[[timers objectAtIndex:i] timer] isValid]) {
+            [timers removeObjectAtIndex:i];
+           count--;
+        }
+    }
+    
+    /* Currently only timers have limit dates associated with them */
+    if(!count)
+        return nil;
+
+    copyOfTimers = [timers mutableCopy];
+
+    /* Sort the timers based on their fire date */
+    [copyOfTimers sortUsingFunction:compare_fire_dates context:NULL];
+
+    /* Fire all the timers with their fire date expired */
+    for(i = 0; i < count; i++) {
+        NSRunLoopTimerInfo* timerInfo = [copyOfTimers objectAtIndex:i];
+        NSDate* fireDate = [timerInfo fireDate];
+        NSDate* currentDate = [NSDate date];
+
+        if([fireDate earlierDate:currentDate] == fireDate
+          || [fireDate isEqualToDate:currentDate]) {
+            NSTimer* timer = [timerInfo timer];
+            NS_DURING {
+             [timer fire];
+            }
+            NS_HANDLER {
+              NSLog(format, "NSRunLoop(-limitDateForMode:)",
+                    [localException name], [localException reason]);
+            }
+            NS_ENDHANDLER;
+           
+            if(![timer repeats])
+                [timer invalidate];
+        }
+    }
+
+    RELEASE(copyOfTimers);
+
+    /* Recompute the fire dates for this cycle */
+    [timers makeObjectsPerform:@selector(recomputeFireDate)];
+
+    /* Sort the timers based on their fire date */
+    [timers sortUsingFunction:compare_fire_dates context:NULL];
+
+    return [timers count] ? [[timers objectAtIndex:0] fireDate] : nil;
+}
+
+- (void)addTimer:(NSTimer*)aTimer
+       forMode:(NSString*)aMode
+{
+    [_getInputManager(self, aMode) addTimer:aTimer];
+}
+
+- (BOOL)runMode:(NSString *)aMode beforeDate:(NSDate *)limitDate
+{
+    id      inputManager, fileObjects;
+    NSArray *timers;
+    NSDate  *date;
+
+    /* Retain the limitDate so it doesn't get released by limitDateForMode:
+       if it fires a timer that has as fireDate the limitDate.
+       (bug report from Benhur Stein <Benhur-de-Oliveira.Stein@imag.fr>)
+      */
+    (void)RETAIN(limitDate);
+
+    inputManager = [self->inputsForMode objectForKey:aMode];
+    timers       = [inputManager timers];
+    fileObjects  = [inputManager fileObjects];
+
+    if (([timers count] != 0) || ([fileObjects count] != 0)) {
+       CREATE_AUTORELEASE_POOL(pool);
+
+       date = [self limitDateForMode:aMode];
+       date = date ? [date earlierDate:limitDate] : limitDate;
+       [self acceptInputForMode:aMode beforeDate:date];
+       RELEASE(pool);
+       RELEASE(limitDate);
+       return YES;
+    }
+
+    RELEASE(limitDate);
+    return NO;
+}
+
+/*  Runs the loop until limitDate or until the earliest limit date for input
+    sources in the specified mode. */
+- (void)acceptInputForMode:(NSString *)aMode beforeDate:(NSDate *)limitDate
+{
+    id              inputManager, fileObjects;
+    struct timeval  tp = { 0, 0 };
+    struct timeval* timeout = NULL;
+    NSTimeInterval  delay = 0;
+    fd_set          readSet, writeSet, exceptionsSet;
+    volatile int    i, r, count;
+
+    ASSIGN(self->mode, aMode);
+
+    if(limitDate == nil) { // delay = 0
+       limitDate = [NSDate distantFuture];
+    }
+    else {
+       delay = [limitDate timeIntervalSinceNow];
+           /* delay > 0 means a future date */
+
+       /* If limitDate is in the past return */
+       if(delay < 0)
+           return;
+    }
+
+    inputManager = [inputsForMode objectForKey:aMode];
+    fileObjects  = [inputManager fileObjects];
+    
+    /* Compute the timeout for select */
+    if([limitDate isEqual:[NSDate distantFuture]])
+       timeout = NULL;
+    else {
+       tp.tv_sec = delay;
+       tp.tv_usec = (delay - (NSTimeInterval)tp.tv_sec) * 1000000.0;
+       timeout = &tp;
+    }
+    
+    [NSNotificationQueue runLoopASAP];
+    
+    ASSIGN(self->mode, aMode);
+    
+    FD_ZERO(&readSet);
+    FD_ZERO(&writeSet);
+    FD_ZERO(&exceptionsSet);
+
+    do {
+        count = [fileObjects count];
+        for (i = 0; i < count; i++) {
+            NSRunLoopFileObjectInfo *info = [fileObjects objectAtIndex:i];
+            NSPosixFileActivities   fileActivity;
+            int                     fd;
+
+            if (![info isAlive])
+                continue;
+
+            fileActivity = [info watchedActivities];
+            fd           = [info fileDescriptor];
+            
+            if (fd >= 0) {
+#if !defined(__MINGW32__) /* on Windows descriptors can be BIG */
+                if (fd >= FD_SETSIZE) {
+                    NSLog(@"%s: fd %i of %@ exceeds select size %i",
+                          "NSRunLoop(-acceptInputForMode:beforeDate:)",
+                          fd, info, FD_SETSIZE);
+                    continue;
+                }
+#endif
+
+                //NSLog(@"registering activity %s for fd %i ..",
+                //      activityDesc[fileActivity], fd);
+
+                if (fileActivity & NSPosixReadableActivity)
+                    FD_SET(fd, &readSet);
+                if (fileActivity & NSPosixWritableActivity)
+                    FD_SET(fd, &writeSet);
+                if (fileActivity & NSPosixExceptionalActivity)
+                    FD_SET(fd, &exceptionsSet);
+            }
+        }
+        
+        /* ???: errno = 0; What is this good for ? */
+       r = select(FD_SETSIZE, &readSet, &writeSet, &exceptionsSet, timeout);
+       if (r == -1) {
+           if (errno == EINTR) {
+               /* Interrupt occured; break the loop to give a chance to
+                  UnixSignalHandler to handle the signals. */
+                //printf("%s: GOT EINTR ...\n", __PRETTY_FUNCTION__);
+               errno = 0;
+               break;
+           }
+           else {
+               NSLog(@"%s: select() error: '%s'",
+                      "NSRunLoop(-acceptInputForMode:beforeDate:)",
+                      strerror (errno));
+                break;
+            }
+           errno = 0;
+       }
+    } while (r == -1);
+
+    if (r > 0) {
+        id fileObjectsCopy;
+
+        *(&fileObjectsCopy) = nil;
+
+       {
+            // made copy, so that modifications in the delegate don't
+            // alter the loop
+            fileObjectsCopy = [fileObjects copyWithZone:[self zone]];
+            count           = [fileObjectsCopy count];
+            
+            for (i = 0; (i < count) && (r > 0); i++) {
+                NSRunLoopFileObjectInfo *info;
+                NSPosixFileActivities   activity = 0;
+                int fd;
+
+                info = [fileObjectsCopy objectAtIndex:i];
+                fd   = [info fileDescriptor];
+
+                if (fd >= 0) {
+                    //NSLog(@"checking activity for %i info %@ ..", fd, info);
+                
+                    if (FD_ISSET(fd, &readSet)) {
+                        activity |= NSPosixReadableActivity;
+                        r--;
+                    }
+                    if (FD_ISSET(fd, &writeSet)) {
+                        activity |= NSPosixWritableActivity;
+                        r--;
+                    }
+                    if (FD_ISSET(fd, &exceptionsSet)) {
+                        activity |= NSPosixExceptionalActivity;
+                        r--;
+                    }
+
+                    if (activity != 0)
+                        [info activity:activity onDescriptor:fd];
+                }
+            }
+#if 0
+            if (r > 0) {
+                NSLog(@"WARNING: did not resolve all activities (%i) ..", r);
+            }
+#endif
+       }
+
+       RELEASE(fileObjectsCopy); fileObjectsCopy = nil;
+    }
+    
+    [inputManager performAdditionalOperations];
+    [NSNotificationQueue runLoopASAP];
+    [inputManager performAdditionalOperations];
+}
+
+- (void)runUntilDate:(NSDate *)limitDate
+{
+    BOOL shouldContinue = YES;
+    
+    if (limitDate == nil)
+       limitDate = [NSDate distantFuture];
+    else {
+       /* If limitDate is in the past return */
+       if ([limitDate timeIntervalSinceNow] < 0)
+           return;
+    }
+
+    while (shouldContinue) {
+        CREATE_AUTORELEASE_POOL(pool);
+        
+        if ([limitDate laterDate:[NSDate date]] == limitDate) {
+           if ([self runMode:NSDefaultRunLoopMode beforeDate:limitDate] == NO)
+               shouldContinue = NO;
+        }
+       else
+           shouldContinue = NO;
+        RELEASE(pool);
+    }
+}
+
+- (void)run
+{
+    [self runUntilDate:[NSDate distantFuture]];
+}
+
+- (void)performSelector:(SEL)aSelector
+  target:(id)target
+  argument:(id)anArgument
+  order:(unsigned)order
+  modes:(NSArray*)modes
+{
+    id holder = [NSRunLoopActionHolder objectWithTarget:target
+                                       argument:anArgument
+                                       selector:aSelector
+                                       order:order];
+    int i, count = [modes count];
+
+    for (i = 0; i < count; i++)
+       [[inputsForMode objectForKey:[modes objectAtIndex:i]]
+           addOperation:holder];
+}
+
+- (void)cancelPerformSelector:(SEL)aSelector
+  target:(id)target
+  argument:(id)anArgument
+{
+    id holder = [NSRunLoopActionHolder objectWithTarget:target
+                                       argument:anArgument
+                                       selector:aSelector
+                                       order:0];
+    id enumerator = [inputsForMode keyEnumerator];
+    id aMode;
+
+    while ((aMode = [enumerator nextObject]))
+       [[inputsForMode objectForKey:aMode] removeOperation:holder];
+}
+
+/* Monitoring file descriptors */
+
+- (void)addPosixFileDescriptor:(NSPosixFileDescriptor *)fileDescriptor
+  forMode:(NSString *)aMode
+{
+    [_getInputManager(self, aMode) addPosixFileDescriptor:fileDescriptor];
+}
+
+- (void)removePosixFileDescriptor:(NSPosixFileDescriptor *)fileDescriptor
+  forMode:(NSString *)aMode
+{
+    [_getInputManager(self, aMode) removePosixFileDescriptor:fileDescriptor];
+}
+
+/* Monitoring file objects */
+
+- (void)addFileObject:(id)_fileObject
+  activities:(NSPosixFileActivities)_activities
+  forMode:(NSString *)_mode
+{
+    [_getInputManager(self, _mode) addFileObject:_fileObject
+                                   activities:_activities];
+}
+
+- (void)removeFileObject:(id)_fileObject
+  forMode:(NSString *)_mode
+{
+    [_getInputManager(self, _mode) removeFileObject:_fileObject];
+}
+
+/* Ports */
+
+- (void)addPort:(NSPort *)_port forMode:(NSString *)_mode
+{
+    [self notImplemented:_cmd];
+}
+
+- (void)removePort:(NSPort *)_port forMode:(NSString *)_mode
+{
+    [self notImplemented:_cmd];
+}
+
+/* Server operation */
+
+- (void)configureAsServer
+{
+    /* What is special about a server ?, maybe register as service in Win32 */
+}
+
+@end /* NSRunLoop */
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSScanner.h b/libFoundation/Foundation/NSScanner.h
new file mode 100644 (file)
index 0000000..33f27a9
--- /dev/null
@@ -0,0 +1,89 @@
+/* 
+   NSScanner.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSScanner_h__
+#define __NSScanner_h__
+
+#include <limits.h>
+#include <float.h>
+
+#include <Foundation/NSObject.h>
+
+#ifndef LONG_LONG_MAX
+# define LONG_LONG_MAX (((unsigned long long)-1) >> 1)
+#endif
+
+#ifndef LONG_LONG_MIN
+# define LONG_LONG_MIN (-LONG_LONG_MAX - 1)
+#endif
+
+@class NSString;
+@class NSDictionary;
+@class NSCharacterSet;
+
+@interface NSScanner : NSObject
+
+/* Creation */
++ (id)scannerWithString:(NSString*)string;
++ (id)localizedScannerWithString:(NSString*)string;
+- (id)initWithString:(NSString*)string;
+
+/* Getting an NSScanner's string */
+- (NSString*)string;
+
+/* Configuring an NSScanner */
+- (void)setScanLocation:(unsigned int)index;
+- (unsigned int)scanLocation;
+- (void)setCaseSensitive:(BOOL)flag;
+- (BOOL)caseSensitive;
+- (void)setCharactersToBeSkipped:(NSCharacterSet*)skipSet;
+- (NSCharacterSet*)charactersToBeSkipped;
+
+/* Setting and getting a locale */
+- (void)setLocale:(NSDictionary*)locale;
+- (NSDictionary*)locale;
+
+/* Scanning a string */
+- (BOOL)scanCharactersFromSet:(NSCharacterSet*)scanSet
+  intoString:(NSString**)value;
+- (BOOL)scanUpToCharactersFromSet:(NSCharacterSet*)stopSet
+  intoString:(NSString **)value;
+- (BOOL)scanDouble:(double*)value;
+- (BOOL)scanFloat:(float*)value;
+- (BOOL)scanInt:(int*)value;
+- (BOOL)scanLongLong:(long long*)value;
+- (BOOL)scanString:(NSString*)string intoString:(NSString**)value;
+- (BOOL)scanUpToString:(NSString*)stopString intoString:(NSString**)value;
+- (BOOL)isAtEnd;
+
+@end
+
+#endif /* __NSScanner_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSScanner.m b/libFoundation/Foundation/NSScanner.m
new file mode 100644 (file)
index 0000000..415f0b2
--- /dev/null
@@ -0,0 +1,298 @@
+/* 
+   NSScanner.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSCharacterSet.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSUserDefaults.h>
+#include <Foundation/NSScanner.h>
+#include <Foundation/NSRange.h>
+#include "NSConcreteScanner.h"
+
+/* BUGS:
+
+   The current implementation assumes that the characters given in
+   the locale dictionary under the NSDecimalDigits key are consecutive.
+
+   No verify is performed to see if the thousand separator is positioned
+   strictly between groups of digits. Maybe the grouping of digits should be
+   also described in the locale dictionary.
+*/
+
+@implementation NSScanner
+
++ (id)allocWithZone:(NSZone*)zone
+{
+    return NSAllocateObject([NSConcreteScanner class], 0, zone);
+}
+
++ (id)scannerWithString:(NSString*)string
+{
+    NSScanner* scanner = AUTORELEASE([[NSConcreteScanner alloc]
+                                         initWithString:string]);
+    [scanner setCharactersToBeSkipped:
+                 [NSCharacterSet whitespaceAndNewlineCharacterSet]];
+    return scanner;
+}
+
++ (id)localizedScannerWithString:(NSString*)string
+{
+    NSScanner* scanner = [self scannerWithString:string];
+    NSMutableDictionary* dictionary = [NSMutableDictionary dictionary];
+    NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
+
+    [dictionary setObject:[userDefaults objectForKey:NSDecimalDigits]
+               forKey:NSDecimalDigits];
+    [dictionary setObject:[userDefaults objectForKey:NSDecimalSeparator]
+               forKey:NSDecimalSeparator];
+    [dictionary setObject:[userDefaults objectForKey:NSThousandsSeparator]
+               forKey:NSThousandsSeparator];
+
+    return scanner;
+}
+
+- (id)initWithString:(NSString*)string
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+- (NSString*)string
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+- (void)setScanLocation:(unsigned int)index
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (unsigned int)scanLocation
+{
+    [self subclassResponsibility:_cmd];
+    return 0;
+}
+
+- (void)setCaseSensitive:(BOOL)flag
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (BOOL)caseSensitive
+{
+    [self subclassResponsibility:_cmd];
+    return NO;
+}
+
+- (void)setCharactersToBeSkipped:(NSCharacterSet *)skipSet
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (NSCharacterSet *)charactersToBeSkipped
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+- (BOOL)scanCharactersFromSet:(NSCharacterSet *)scanSet
+  intoString:(NSString **)value
+{
+    NSString       *string;
+    unsigned int   orig;
+    unsigned int   length;
+    unsigned int   location;
+    NSCharacterSet *lSkipSet;
+
+    string   = [self string];
+    orig     = [self scanLocation];
+    length   = [string length];
+    location = orig;
+    
+    lSkipSet = [self charactersToBeSkipped];
+    
+    if (![lSkipSet isEqual:scanSet]) {
+        /* scan characters */
+        
+        for (; location < length; location++) {
+            if (![lSkipSet characterIsMember:[string characterAtIndex:location]])
+                break;
+        }
+        [self setScanLocation:location];
+        orig = location;
+    }
+    
+    for (; location < length; location++) {
+       if (![scanSet characterIsMember:[string characterAtIndex:location]])
+           break;
+    }
+
+    /* Check if we scanned anything */
+    if (location != orig) {
+       if (value) {
+           NSRange range = { orig, location - orig }; 
+           *value = [string substringWithRange:range];
+       }
+       [self setScanLocation:location];
+       return YES;
+    }
+
+    return NO;
+}
+
+- (BOOL)scanUpToCharactersFromSet:(NSCharacterSet*)stopSet
+  intoString:(NSString**)value
+{
+    return [self scanCharactersFromSet:[stopSet invertedSet] intoString:value];
+}
+
+- (BOOL)scanDouble:(double*)value
+{
+#define DOUBLE_TYPE
+# include "scanFloat.def"
+#undef DOUBLE_TYPE
+}
+
+- (BOOL)scanFloat:(float*)value
+{
+#define FLOAT_TYPE
+# include "scanFloat.def"
+#undef FLOAT_TYPE
+}
+
+- (BOOL)scanInt:(int*)value
+{
+#define INT_TYPE
+# include "scanInt.def"
+#undef INT_TYPE
+}
+
+- (BOOL)scanLongLong:(long long*)value
+{
+#define LONG_LONG_TYPE
+# include "scanInt.def"
+#undef LONG_LONG_TYPE
+}
+
+- (BOOL)scanString:(NSString*)searchString intoString:(NSString**)value
+{
+    id string = [self string];
+    unsigned int searchStringLength = [searchString length];
+    NSRange range;
+    unsigned int options;
+    unsigned int location;
+
+    /* First skip the blank characters */
+    [self scanCharactersFromSet:[self charactersToBeSkipped] intoString:NULL];
+
+    range.location = location = [self scanLocation];
+    range.length = searchStringLength;
+
+    /* Check if the searchString can be contained in the remained scanned
+       string. */
+    if ([string length] < range.location + range.length)
+       return NO;
+
+    options = NSAnchoredSearch;
+    if (![self caseSensitive])
+       options |= NSCaseInsensitiveSearch;
+
+    if ([string compare:searchString options:options range:range]
+           == NSOrderedSame) {
+       [self setScanLocation:(range.location + range.length)];
+       if (value)
+           *value = [searchString copy];
+       return YES;
+    }
+
+    return NO;
+}
+
+- (BOOL)scanUpToString:(NSString*)stopString intoString:(NSString**)value
+{
+    id string = [self string];
+    int length = [string length];
+    NSRange range, lastRange;
+    unsigned int options = 0;
+    unsigned int location;
+
+    /* First skip the blank characters */
+    [self scanCharactersFromSet:[self charactersToBeSkipped] intoString:NULL];
+
+    if (![self caseSensitive])
+       options = NSCaseInsensitiveSearch;
+
+    range.location = location = [self scanLocation];
+    range.length = length - location;
+    lastRange = range;
+    range = [string rangeOfString:stopString options:options range:range];
+
+    if (range.length) {
+       /* A match was found */
+       [self setScanLocation:range.location];
+       if (value) {
+           range.length = range.location - location;
+           range.location = location;
+           *value = [string substringWithRange:range];
+       }
+       return YES;
+    }
+    else {
+        /* Return the remaining of the string as the result of scanning */
+        [self setScanLocation:length];
+        if (value)
+            *value = [string substringWithRange:lastRange];
+        return lastRange.length > 0;
+    }
+
+    return NO;
+}
+
+- (BOOL)isAtEnd
+{
+    return [self scanLocation] == [[self string] length];
+}
+
+- (void)setLocale:(NSDictionary*)locale
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (NSDictionary*)locale
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+
+@end /* NSScanner */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSScriptKeyValueCoding.h b/libFoundation/Foundation/NSScriptKeyValueCoding.h
new file mode 100644 (file)
index 0000000..f406224
--- /dev/null
@@ -0,0 +1,55 @@
+/* 
+   NSScriptKeyValueCoding.h
+
+   Copyright (C) 2002, SKYRIX Software AG, Helge Hess
+   All rights reserved.
+   
+   Author: Helge Hess <helge.hess@skyrix.com>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSScriptKeyValueCoding_h__
+#define __NSKeyValueCoding_h__
+
+#include <Foundation/NSObject.h>
+
+@interface NSObject(NSScriptKeyValueCoding)
+
+/* type coercion */
+
+- (id)coerceValue:(id)_val forKey:(NSString *)_key;
+
+/* query array properties (toManyRelationshipKeys) */
+
+- (id)valueAtIndex:(unsigned)_idx     inPropertyWithKey:(NSString *)_key;
+- (id)valueWithName:(NSString *)_name inPropertyWithKey:(NSString *)_key;
+- (id)valueWithUniqueID:(id)_uid      inPropertyWithKey:(NSString *)_key;
+
+/* modifying array properties (toManyRelationshipKeys) */
+
+- (void)insertValue:(id)_val atIndex:(unsigned)_idx
+  inPropertyWithKey:(NSString *)_key;
+- (void)insertValue:(id)_val inPropertyWithKey:(NSString *)_key;
+
+- (void)removeValueAtIndex:(unsigned)_idx fromPropertyWithKey:(NSString *)_key;
+
+- (void)replaceValueAtIndex:(unsigned)_idx inPropertyWithKey:(NSString *)_key
+  withValue:(id)_val;
+
+@end
+
+#endif /* __NSScriptKeyValueCoding_h__ */
diff --git a/libFoundation/Foundation/NSSerialization.h b/libFoundation/Foundation/NSSerialization.h
new file mode 100644 (file)
index 0000000..56593db
--- /dev/null
@@ -0,0 +1,77 @@
+/* 
+   NSSerialization.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSSerialization_h__
+#define __NSSerialization_h__
+
+#include <objc/objc.h>
+#include <Foundation/NSObject.h>
+
+@class NSData;
+@class NSMutableData;
+
+@protocol NSObjCTypeSerializationCallBack
+
+- (void)deserializeObjectAt:(id *)object
+  ofObjCType:(const char *)type
+  fromData:(NSData *)data
+  atCursor:(unsigned int *)cursor;
+
+- (void)serializeObjectAt:(id *)object
+  ofObjCType:(const char *)type
+  intoData:(NSMutableData *)data;
+
+@end
+
+@interface NSSerializer : NSObject
+
++ (void)serializePropertyList:(id)_plist intoData:(NSMutableData *)_data;
++ (NSData *)serializePropertyList:(id)_plist;
+
+@end
+
+@interface NSDeserializer : NSObject
+
++ (id)deserializePropertyListFromData:(NSData *)_data
+  atCursor:(unsigned *)_cursor
+  mutableContainers:(BOOL)_flag;
+
++ (id)deserializePropertyListLazilyFromData:(NSData *)_data
+  atCursor:(unsigned *)_cursor
+  length:(unsigned)_len
+  mutableContainers:(BOOL)_flag;
+
++ (id)deserializePropertyListFromData:(NSData *)_data
+  mutableContainers:(BOOL)_flag;
+
+@end
+
+#endif /* __NSSerialization_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSSerialization.m b/libFoundation/Foundation/NSSerialization.m
new file mode 100644 (file)
index 0000000..9caf884
--- /dev/null
@@ -0,0 +1,85 @@
+/* 
+   NSSerialization.h
+
+   Copyright (C) 2000 MDlink online service center, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess (helge.hess@mdlink.de)
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSSerialization.h>
+#include <Foundation/NSData.h>
+
+@implementation NSSerializer
+
++ (void)serializePropertyList:(id)_plist intoData:(NSMutableData *)_data
+{
+    [self notImplemented:_cmd];
+}
+
++ (NSData *)serializePropertyList:(id)_plist
+{
+    NSMutableData *md;
+    NSData        *d;
+
+    md = [[NSMutableData alloc] initWithCapacity:4096];
+    [self serializePropertyList:_plist intoData:md];
+    d = [md copy];
+    RELEASE(md);
+    return AUTORELEASE(d);
+}
+
+@end /* NSSerializer */
+
+@implementation NSDeserializer
+
+
++ (id)deserializePropertyListFromData:(NSData *)_data
+  atCursor:(unsigned *)_cursor
+  mutableContainers:(BOOL)_flag
+{
+    return nil;
+}
+
++ (id)deserializePropertyListLazilyFromData:(NSData *)_data
+  atCursor:(unsigned *)_cursor
+  length:(unsigned)_len
+  mutableContainers:(BOOL)_flag
+{
+    return nil;
+}
+
++ (id)deserializePropertyListFromData:(NSData *)_data
+  mutableContainers:(BOOL)_flag
+{
+    unsigned cursor;
+
+    return [self deserializePropertyListFromData:_data
+                 atCursor:&cursor
+                 mutableContainers:_flag];
+}
+
+@end /* NSDeserializer */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSSet.h b/libFoundation/Foundation/NSSet.h
new file mode 100644 (file)
index 0000000..ae5d97e
--- /dev/null
@@ -0,0 +1,163 @@
+/* 
+   NSSet.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSSet_h__
+#define __NSSet_h__
+
+#include <stdarg.h>
+#include <Foundation/NSObject.h>
+#include <Foundation/NSMapTable.h>
+#include <Foundation/NSHashTable.h>
+#include <Foundation/NSUtilities.h>
+
+@class NSString;
+@class NSArray;
+@class NSDictionary;
+@class NSEnumerator;
+
+/*
+ * NSSet class
+ */
+
+@interface NSSet : NSObject <NSCoding, NSCopying, NSMutableCopying>
+
+/* Allocating and Initializing a Set */
+
++ (id)allocWithZone:(NSZone*)zone;
++ (id)set;
++ (id)setWithArray:(NSArray*)array;
++ (id)setWithObject:(id)anObject;
++ (id)setWithObjects:(id)firstObj,...;
++ (id)setWithObjects:(id*)objects count:(unsigned int)count;
++ (id)setWithSet:(NSSet*)aSet;
+- (id)initWithArray:(NSArray*)array;
+- (id)initWithObjects:(id)firstObj,...;
+- (id)initWithObject:(id)firstObj arglist:(va_list)arglist;
+- (id)initWithObjects:(id*)objects count:(unsigned int)count;
+- (id)initWithSet:(NSSet*)anotherSet;
+- (id)initWithSet:(NSSet*)set copyItems:(BOOL)flag;
+- (id)initWithSet:(NSSet*)aSet;
+
+/* Querying the Set */
+
+- (NSArray*)allObjects;
+- (id)anyObject;
+- (BOOL)containsObject:(id)anObject;
+- (unsigned int)count;
+- (id)member:(id)anObject;
+- (NSEnumerator*)objectEnumerator;
+
+/* Sending Messages to Elements of the Set */
+- (void)makeObjectsPerformSelector:(SEL)aSelector;
+- (void)makeObjectsPerformSelector:(SEL)aSelector withObject:(id)anObject;
+/* Obsolete methods */
+- (void)makeObjectsPerform:(SEL)aSelector;
+- (void)makeObjectsPerform:(SEL)aSelector withObject:(id)anObject;
+
+/* Comparing Sets */
+
+- (BOOL)intersectsSet:(NSSet*)otherSet;
+- (BOOL)isEqualToSet:(NSSet*)otherSet;
+- (BOOL)isSubsetOfSet:(NSSet*)otherSet;
+
+/* Creating a String Description of the Set */
+
+- (NSString*)description;
+- (NSString*)descriptionWithLocale:(NSDictionary*)locale;
+- (NSString*)descriptionWithLocale:(NSDictionary*)locale
+   indent:(unsigned int)level;
+
+@end
+
+/*
+ * NSMutableSet
+ */
+
+@interface NSMutableSet : NSSet
+
++ (id)allocWithZone:(NSZone*)zone;
++ (id)setWithCapacity:(unsigned)numItems;
+- (id)initWithCapacity:(unsigned)numItems;
+
+/* Adding Objects */
+
+- (void)addObject:(id)object;
+- (void)addObjectsFromArray:(NSArray *)array;
+- (void)unionSet:(NSSet *)other;
+- (void)setSet:(NSSet *)other;
+
+/* Removing Objects */
+
+- (void)intersectSet:(NSSet *)other;
+- (void)minusSet:(NSSet *)other;
+- (void)removeAllObjects;
+- (void)removeObject:(id)object;
+
+@end
+
+/*
+ * NSCountedSet Class
+ */
+
+@interface NSCountedSet : NSMutableSet
+{
+       NSMapTable*     table;
+}
+
+/* Allocating and Initializing */
+
+- (id)init;
+- (id)initWithObjects:(id*)objects count:(unsigned int)count;
+- (id)initWithSet:(NSSet*)set copyItems:(BOOL)flag;
+
+/* Accessing keys and values */
+
+- (unsigned int)count;
+- (id)member:(id)anObject;
+- (NSEnumerator*)objectEnumerator;
+
+/* Add and remove entries */
+
+- (void)addObject:(id)object;
+- (void)removeObject:(id)object;
+- (void)removeAllObjects;
+
+/* Querying the NSCountedSet */
+
+- (unsigned)countForObject:(id)anObject;
+
+/* Private */
+
+- (void)__setObjectEnumerator:(void*)en;
+
+@end
+
+#endif /* __NSSet_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSSet.m b/libFoundation/Foundation/NSSet.m
new file mode 100644 (file)
index 0000000..be3a949
--- /dev/null
@@ -0,0 +1,587 @@
+/* 
+   NSSet.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include <Foundation/common.h>
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSSet.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSCoder.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+
+#include "NSConcreteSet.h"
+
+/*
+ * NSSet 
+ */
+
+@implementation NSSet
+
+/* Allocating and Initializing a Set */
+
++ (id)allocWithZone:(NSZone*)zone
+{
+    return NSAllocateObject( (self == [NSSet class]) ? 
+           [NSConcreteSet class] : self, 0, zone);
+}
+
++ (id)set
+{
+    return AUTORELEASE([[self alloc] init]);
+}
+
++ (id)setWithArray:(NSArray*)array
+{
+    return AUTORELEASE([[self alloc] initWithArray:array]);
+}
+
++ (id)setWithObject:(id)anObject
+{
+    return AUTORELEASE(([[self alloc] initWithObjects:anObject, nil]));
+}
+
++ (id)setWithObjects:(id)firstObj,...
+{
+    id set;
+    va_list va;
+    va_start(va, firstObj);
+    set = AUTORELEASE([[self alloc] initWithObject:firstObj arglist:va]);
+    va_end(va);
+    return set;
+}
+
++ (id)setWithObjects:(id*)objects count:(unsigned int)count
+{
+    return AUTORELEASE([[self alloc] initWithObjects:objects count:count]);
+}
+
++ (id)setWithSet:(NSSet*)aSet
+{
+    return AUTORELEASE([[self alloc] initWithSet:aSet]);
+}
+
+- (id)init
+{
+    [self subclassResponsibility:_cmd];
+    return self;
+}
+
+- (id)initWithArray:(NSArray*)array
+{
+    int i, n = [array count];
+    id *objects;
+
+    if (n == 0)
+        return [self initWithObjects:NULL count:0];
+    
+    objects = Malloc(sizeof(id) * n);
+    
+    for (i = 0; i < n; i++)
+       objects[i] = [array objectAtIndex:i];
+           
+    self = [self initWithObjects:objects count:n];
+    
+    lfFree(objects);
+    return self;
+}
+
+- (id)initWithObjects:(id)firstObj,...
+{
+    va_list va;
+    va_start(va, firstObj);
+    self = [self initWithObject:firstObj arglist:va];
+    va_end(va);
+    return self;
+}
+
+- (id)initWithObject:(id)firstObject arglist:(va_list)argList
+{
+    id object;
+    id *objs;
+    va_list va;
+    int count = 0;
+
+#ifdef __va_copy
+    __va_copy(va, argList);
+#else
+    va = argList;
+#endif
+
+    for (object = firstObject; object; object = va_arg(va,id))
+       count++;
+
+    if (count == 0)
+        return [self initWithObjects:NULL count:0];
+    
+    objs = Malloc(sizeof(id)*count);
+    
+    for (count=0, object=firstObject; object; object=va_arg(argList,id)) {
+       objs[count] = object;
+       count++;
+    }
+
+    self = [self initWithObjects:objs count:count];
+
+    lfFree(objs);
+    return self;
+}
+
+- (id)initWithObjects:(id*)objects count:(unsigned int)count
+{
+    [self subclassResponsibility:_cmd];
+    return self;
+}
+
+- (id)initWithSet:(NSSet*)set copyItems:(BOOL)flag;
+{
+    NSEnumerator *keys = [set objectEnumerator];
+    id       key;
+    id       *objs;
+    unsigned i = 0;
+    
+    objs = Malloc(sizeof(id)*[set count]);
+
+    while((key = [keys nextObject])) {
+       objs[i++] = flag ? AUTORELEASE([key copyWithZone:NULL]) : key;
+    }
+    
+    self = [self initWithObjects:objs count:i];
+    
+    lfFree(objs);
+    return self;
+}
+
+- (id)initWithSet:(NSSet*)aSet
+{
+    return [self initWithSet:aSet copyItems:NO];
+}
+
+/* Querying the Set */
+
+- (NSArray *)allObjects
+{
+    id array;
+    id *objs;
+    id keys;
+    id key;
+    unsigned i = 0, count;
+    
+    if ((count = [self count]) == 0) return [NSArray array];
+    
+    objs = Malloc(sizeof(id)*[self count]);
+    keys = [self objectEnumerator];
+    
+    for (i = 0; (key = [keys nextObject]); i++)
+       objs[i] = key;
+    
+    array = [[NSArray alloc] initWithObjects:objs count:count];
+    lfFree(objs);
+#if DEBUG
+    NSAssert(array, @"missing array ..");
+#endif
+    return AUTORELEASE(array);
+}
+
+- (id)anyObject
+{
+    return [[self objectEnumerator] nextObject];
+}
+
+- (BOOL)containsObject:(id)anObject
+{
+    return [self member:anObject] ? YES : NO;
+}
+
+- (unsigned int)count
+{
+    [self subclassResponsibility:_cmd];
+    return 0;
+}
+
+- (id)member:(id)anObject
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+- (NSEnumerator*)objectEnumerator
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+/* Sending Messages to Elements of the Set */
+
+- (void)makeObjectsPerformSelector:(SEL)aSelector
+{
+    id keys = [self objectEnumerator];
+    id key;
+
+    while ((key = [keys nextObject]))
+       [key performSelector:aSelector];
+}
+
+- (void)makeObjectsPerformSelector:(SEL)aSelector withObject:(id)anObject
+{
+    id keys = [self objectEnumerator];
+    id key;
+
+    while ((key = [keys nextObject]))
+       [key performSelector:aSelector withObject:anObject];
+}
+
+/* Obsolete methods */
+- (void)makeObjectsPerform:(SEL)aSelector
+{
+    id keys = [self objectEnumerator];
+    id key;
+
+    while ((key = [keys nextObject]))
+       [key performSelector:aSelector];
+}
+
+- (void)makeObjectsPerform:(SEL)aSelector withObject:(id)anObject
+{
+    id keys = [self objectEnumerator];
+    id key;
+
+    while ((key = [keys nextObject]))
+       [key performSelector:aSelector withObject:anObject];
+}
+
+/* Comparing Sets */
+
+- (BOOL)intersectsSet:(NSSet*)otherSet
+{
+    id keys = [self objectEnumerator];
+    id key;
+
+    while ((key = [keys nextObject]))
+       if ([otherSet containsObject:key])
+           return YES;
+    return NO;
+}
+
+- (BOOL)isEqualToSet:(NSSet*)otherSet
+{
+    id keys = [self objectEnumerator];
+    id key;
+
+    if ([self count] != [otherSet count])
+       return NO;
+    
+    while ((key = [keys nextObject]))
+       if (![otherSet containsObject:key])
+           return NO;
+    
+    return YES;
+}
+
+- (BOOL)isSubsetOfSet:(NSSet *)otherSet
+{
+    NSEnumerator *keys;
+    id key;
+    
+    if (otherSet == nil)
+        return NO;
+
+    keys = [self objectEnumerator];
+    
+    while ((key = [keys nextObject]))
+       if (![otherSet containsObject:key])
+           return NO;
+    return YES;
+}
+
+/* Creating a String Description of the Set */
+
+- (NSString*)descriptionWithLocale:(NSDictionary*)locale
+{
+    return [self descriptionWithLocale:locale indent:0];
+}
+
+- (NSString*)description
+{
+    return [self descriptionWithLocale:nil indent:0];
+}
+
+- (NSString*)descriptionWithLocale:(NSDictionary*)locale
+   indent:(unsigned int)indent;
+{
+    NSMutableString* description = [NSMutableString stringWithCString:"(\n"];
+    unsigned int indent1 = indent + 4;
+    NSMutableString* indentation
+           = [NSString stringWithFormat:
+                       [NSString stringWithFormat:@"%%%dc", indent1], ' '];
+    unsigned int count = [self count];
+    SEL sel = @selector(appendString:);
+    IMP imp = [description methodForSelector:sel];
+
+    if(count) {
+       id object;
+       id stringRepresentation;
+       id enumerator;
+       CREATE_AUTORELEASE_POOL(pool);
+
+        enumerator = [self objectEnumerator];
+
+       object = [enumerator nextObject];
+       if ([object respondsToSelector:
+               @selector(descriptionWithLocale:indent:)])
+           stringRepresentation = [object descriptionWithLocale:locale
+               indent:indent1];
+       else if ([object respondsToSelector:
+               @selector(descriptionWithLocale:)])
+           stringRepresentation = [object descriptionWithLocale:locale];
+       else
+           stringRepresentation = [object stringRepresentation];
+
+       (*imp)(description, sel, indentation);
+       (*imp)(description, sel, stringRepresentation);
+
+       while((object = [enumerator nextObject])) {
+           if ([object respondsToSelector:
+                   @selector(descriptionWithLocale:indent:)])
+               stringRepresentation = [object descriptionWithLocale:locale
+                   indent:indent1];
+           else if ([object respondsToSelector:
+                   @selector(descriptionWithLocale:)])
+               stringRepresentation = [object descriptionWithLocale:locale];
+           else
+               stringRepresentation = [object stringRepresentation];
+
+           (*imp)(description, sel, @",\n");
+           (*imp)(description, sel, indentation);
+           (*imp)(description, sel, stringRepresentation);
+       }
+       RELEASE(pool);
+    }
+
+    (*imp)(description, sel, indent
+           ? [NSMutableString stringWithFormat:
+                       [NSString stringWithFormat:@"\n%%%dc)", indent], ' ']
+           : [NSMutableString stringWithCString:"\n)"]);
+    return description;
+}
+
+/* From adopted/inherited protocols */
+
+- (unsigned)hash
+{
+    return [self count];
+}
+
+- (BOOL)isEqual:(id)anObject
+{
+    if ([anObject isKindOfClass:isa] == NO)
+           return NO;
+    return [self isEqualToSet:anObject];
+}
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    if (NSShouldRetainWithZone(self, zone))
+       return RETAIN(self);
+    else
+       return [[NSSet allocWithZone:zone] initWithSet:self copyItems:NO];
+}
+
+- (id)mutableCopyWithZone:(NSZone*)zone
+{
+    return [[NSMutableSet allocWithZone:zone] initWithSet:self copyItems:NO];
+}
+
+- (Class)classForCoder
+{
+    return [NSSet class];
+}
+
+- (void)encodeWithCoder:(NSCoder*)aCoder
+{
+    NSEnumerator* enumerator = [self objectEnumerator];
+    int count = [self count];
+    id object;
+
+    [aCoder encodeValueOfObjCType:@encode(int) at:&count];
+    while((object = [enumerator nextObject]))
+       [aCoder encodeObject:object];
+}
+
+- (id)initWithCoder:(NSCoder*)aDecoder
+{
+    int i, count;
+    id* objects;
+
+    [aDecoder decodeValueOfObjCType:@encode(int) at:&count];
+    objects = Malloc(sizeof(id) * count);
+    for(i = 0; i < count; i++)
+       objects[i] = [aDecoder decodeObject];
+
+    [self initWithObjects:objects count:count];
+    
+    lfFree(objects);
+
+    return self;
+}
+
+@end /* NSSet */
+
+/*
+ * NSMutableSet 
+ */
+
+@implementation NSMutableSet
+
+/* Methods from NSSet */
+
++ (id)allocWithZone:(NSZone*)zone
+{
+    return NSAllocateObject( (self == [NSMutableSet class]) ? 
+           [NSConcreteMutableSet class] : self, 0, zone);
+}
+
++ (id)setWithCapacity:(unsigned)numItems
+{
+    return AUTORELEASE([[self alloc] initWithCapacity:numItems]);
+}
+
+- (id)initWithCapacity:(unsigned)numItems
+{
+    [self subclassResponsibility:_cmd];
+    return self;
+}
+
+/* Adding Objects */
+
+- (void)addObject:(id)object
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (void)addObjectsFromArray:(NSArray*)array
+{
+    int i, n = [array count];
+    IMP _addObject = [self methodForSelector:@selector(addObject:)];
+    
+    for (i = 0; i < n; i++)
+        _addObject(self, @selector(addObject:), [array objectAtIndex:i]);
+}
+
+- (void)unionSet:(NSSet *)other
+{
+    if (self != (id)other) {
+        id keys = [other objectEnumerator];
+        id key;
+
+        while ((key = [keys nextObject]))
+            [self addObject:key];
+    }
+}
+
+- (void)setSet:(NSSet *)other
+{
+    if (self != (id)other) {
+        [self removeAllObjects];
+        [self unionSet:other];
+    }
+}
+
+/* Removing Objects */
+
+- (void)intersectSet:(NSSet*)other
+{
+    if (self != (id)other) {
+        NSMutableArray *toBeRemoved = nil;
+        id keys, key;
+
+        if ((keys = [self objectEnumerator]) == nil)
+            return;
+        
+        while ((key = [keys nextObject])) {
+            if (![other containsObject:key]) {
+                if (toBeRemoved == nil)
+                    toBeRemoved = [NSMutableArray arrayWithCapacity:16];
+                [toBeRemoved addObject:key];
+            }
+        }
+        if (toBeRemoved) {
+            keys = [toBeRemoved objectEnumerator];
+            while ((key = [keys nextObject]))
+                [self removeObject:key];
+        }
+    }
+}
+
+- (void)minusSet:(NSSet*)other
+{
+    if (other == self)
+        [self removeAllObjects];
+    else {
+        id keys, key;
+
+        if ((keys = [other objectEnumerator]) == nil)
+            return;
+
+        while ((key = [keys nextObject]))
+            [self removeObject:key];
+    }
+}
+
+- (void)removeAllObjects
+{
+    id en = [self objectEnumerator];
+    id key;
+    while ((key=[en nextObject]))
+       [self removeObject:key];
+}
+
+- (void)removeObject:(id)object
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    return [[NSSet allocWithZone:zone] initWithSet:self copyItems:NO];
+}
+
+- (Class)classForCoder
+{
+    return [NSMutableSet class];
+}
+
+@end /* NSMutableSet */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSSocketPort.m b/libFoundation/Foundation/NSSocketPort.m
new file mode 100644 (file)
index 0000000..5c3a3e7
--- /dev/null
@@ -0,0 +1,94 @@
+/* 
+   NSSocketPort.m
+
+   Copyright (C) 2000 Helge Hess.
+   All rights reserved.
+
+   Author: Helge Hess <hh@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSPort.h>
+
+@implementation NSSocketPort
+
+- (id)init
+{
+  /* invalid call ? */
+  return [self notImplemented:_cmd];
+}
+  
+- (id)initWithTCPPort:(unsigned short)_port
+{
+  /* bind */
+  return [self notImplemented:_cmd];
+}
+- (id)initRemoteWithTCPPort:(unsigned short)_port
+{
+  /* connect */
+  return [self notImplemented:_cmd];
+}
+
+- (id)initWithProtocolFamily:(int)_family
+  socketType:(int)_type
+  protocol:(int)_protocol
+  address:(NSData *)_address
+{
+  /* bind */
+  return [self notImplemented:_cmd];
+}
+- (id)initRemoteWithProtocolFamily:(int)_family
+  socketType:(int)_type
+  protocol:(int)_protocol
+  address:(NSData *)_address
+{
+  /* connect */
+  return [self notImplemented:_cmd];
+}
+
+- (id)initWithProtocolFamily:(int)_family
+  socketType:(int)_type
+  protocol:(int)_protocol
+  socket:(NSSocketNativeHandle)_handle
+{
+  self->protocol = _protocol;
+  self->type     = _type;
+  self->family   = _family;
+  self->sd       = _handle;
+  return self;
+}
+
+/* accessors */
+
+- (int)protocol
+{
+  return self->protocol;
+}
+- (int)protocolFamily
+{
+  return self->family;
+}
+- (int)socketType
+{
+  return self->type;
+}
+- (NSSocketNativeHandle)socket
+{
+  return self->sd;
+}
+
+@end /* NSSocketPort */
diff --git a/libFoundation/Foundation/NSSortDescriptor.h b/libFoundation/Foundation/NSSortDescriptor.h
new file mode 100644 (file)
index 0000000..586fe96
--- /dev/null
@@ -0,0 +1,78 @@
+/* 
+   NSSortDescriptor.h
+
+   Copyright (C) 2003 SKYRIX Software AG, Helge Hess.
+   All rights reserved.
+   
+   Author: Helge Hess <helge.hess@opengroupware.org>
+   
+   This file is part of libFoundation.
+   
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+   
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSSortDescriptor_H__
+#define __NSSortDescriptor_H__
+
+#include <Foundation/NSObject.h>
+#include <Foundation/NSArray.h>
+
+@class NSString;
+
+@interface NSSortDescriptor : NSObject < NSCoding, NSCopying >
+{
+  NSString *key;
+  SEL      selector;
+  struct {
+      int isAscending:1;
+      int reserved:31;
+  } sdFlags;
+}
+
+- (id)initWithKey:(NSString *)_key ascending:(BOOL)_asc selector:(SEL)_sortsel;
+- (id)initWithKey:(NSString *)_key ascending:(BOOL)_asc;
+
+/* accessors */
+
+- (NSString *)key;
+- (SEL)selector;
+- (BOOL)ascending;
+
+/* operations */
+
+- (id)reversedSortDescriptor;
+- (NSComparisonResult)compareObject:(id)_obj1 toObject:(id)_obj2;
+
+@end
+
+@interface NSArray(NSSortDescriptorSort)
+
+- (NSArray *)sortedArrayUsingDescriptors:(NSArray *)_descs;
+
+@end
+
+@interface NSMutableArray(NSSortDescriptorSort)
+
+- (void)sortUsingDescriptors:(NSArray *)_descs;
+
+@end
+
+#endif /* __NSSortDescriptor_H__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSSortDescriptor.m b/libFoundation/Foundation/NSSortDescriptor.m
new file mode 100644 (file)
index 0000000..c0f6e73
--- /dev/null
@@ -0,0 +1,217 @@
+/* 
+   NSSortDescriptor.m
+
+   Copyright (C) 2003 SKYRIX Software AG, Helge Hess.
+   All rights reserved.
+   
+   Author: Helge Hess <helge.hess@opengroupware.org>
+   
+   This file is part of libFoundation.
+   
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+   
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSSortDescriptor.h>
+#include <Foundation/NSCoder.h>
+#include <Foundation/NSNull.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSKeyValueCoding.h>
+#include <common.h>
+
+@implementation NSSortDescriptor
+
+- (id)initWithKey:(NSString *)_key ascending:(BOOL)_asc selector:(SEL)_sortsel
+{
+    if ((self = [super init])) {
+        self->key                 = [_key copy];
+        self->selector            = _sortsel ? _sortsel : @selector(compare:);
+        self->sdFlags.isAscending = _asc ? 1 : 0;
+    }
+    return self;
+}
+- (id)initWithKey:(NSString *)_key ascending:(BOOL)_asc
+{
+    return [self initWithKey:_key ascending:_asc selector:@selector(compare:)];
+}
+- (id)init 
+{
+    return [self initWithKey:nil ascending:YES selector:NULL];
+}
+
+/* accessors */
+
+- (NSString *)key 
+{
+    return self->key;
+}
+- (SEL)selector
+{
+    return self->selector;
+}
+- (BOOL)ascending
+{
+    return self->sdFlags.isAscending ? YES : NO;
+}
+
+/* operations */
+
+- (id)reversedSortDescriptor 
+{
+    return [self initWithKey:[self key] 
+                 ascending:([self ascending] ? NO : YES)
+                 selector:[self selector]];
+}
+
+- (NSComparisonResult)compareObject:(id)_obj1 toObject:(id)_obj2 
+{
+    // TODO: check out edge cases (eg nil!)
+    NSComparisonResult (*sortfunc)(id, SEL, id);
+    BOOL               doReverse;
+    NSComparisonResult result;
+    id v1, v2;
+    
+    if (_obj1 == _obj2) return NSOrderedSame;
+    
+    v1 = [_obj1 valueForKey:self->key];
+    v2 = [_obj2 valueForKey:self->key];
+    if (v1 == v2) return NSOrderedSame;
+    
+    doReverse = ![self ascending];
+    if (v1 == nil) { /* if the left side is nil, swap for comparison */
+        v1 = v2;
+        v2 = nil;
+        doReverse = !doReverse;
+    }
+    
+    if ((sortfunc = (void*)[v1 methodForSelector:self->selector]) == NULL)
+        return NSOrderedAscending;
+    
+    result = sortfunc(v1, self->selector, v2);
+    if (!doReverse) return result;
+    
+    /* reverse */
+    if (result < 0)
+        return NSOrderedDescending;
+    if (result > 0)
+        return NSOrderedAscending;
+    return NSOrderedSame;
+}
+
+/* NSCoding */
+
+- (void)encodeWithCoder:(NSCoder *)_coder
+{
+    BOOL iasc = self->sdFlags.isAscending;
+    [_coder encodeObject:self->key];
+    [_coder encodeValueOfObjCType:@encode(SEL)  at:&(self->selector)];
+    [_coder encodeValueOfObjCType:@encode(BOOL) at:&iasc];
+}
+- (id)initWithCoder:(NSCoder *)_decoder
+{
+    NSString *ikey = nil;
+    SEL      isel  = NULL;
+    BOOL     iasc  = YES;
+    
+    ikey = [_decoder decodeObject];
+    [_decoder decodeValueOfObjCType:@encode(SEL)  at:&isel];
+    [_decoder decodeValueOfObjCType:@encode(BOOL) at:&iasc];
+    return [self initWithKey:ikey ascending:iasc selector:isel];
+}
+
+/* NSCopying */
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    if (NSShouldRetainWithZone(self, zone))
+       return [self retain];
+    
+    return [[NSSortDescriptor allocWithZone:zone]
+               initWithKey:[self key] 
+               ascending:[self ascending] 
+               selector:[self selector]];
+}
+
+@end /* NSSortDescriptor */
+
+@implementation NSArray(NSSortDescriptorSort)
+
+- (NSArray *)sortedArrayUsingDescriptors:(NSArray *)_descs
+{
+    NSMutableArray *m      = nil;
+    NSArray        *result = nil;
+  
+    if ([_descs count] == 0)
+        return [[self copy] autorelease];
+  
+    m = [self mutableCopy];
+    [m sortUsingDescriptors:_descs];
+    result = [m copy];
+    [m release]; m = nil;
+    return [result autorelease];
+}
+
+@end /* NSArray(NSSortDescriptorSort) */
+
+@implementation NSMutableArray(NSSortDescriptorSort)
+
+#define MAX_DESC_COUNT 10
+typedef struct {
+    NSSortDescriptor *sortdescs[MAX_DESC_COUNT]; /* max depth 10 */
+    short            count;
+} NSSortDescriptorContext;
+
+static NSNull *null = nil;
+
+static int sortDescComparator(id o1, id o2, NSSortDescriptorContext *context) 
+{
+    short i;
+
+    for (i = 0; i < context->count; i++) {
+        int result;
+        
+        result = [context->sortdescs[i] compareObject:o1 toObject:o2];
+        if (result != NSOrderedSame)
+            return result;
+    }
+    return NSOrderedSame;
+}
+
+- (void)sortUsingDescriptors:(NSArray *)_descs 
+{
+    NSEnumerator            *e    = nil;
+    NSSortDescriptor        *desc = nil;
+    NSSortDescriptorContext ctx;
+    int                     i;
+  
+    NSAssert1([_descs count] < MAX_DESC_COUNT, 
+              @"max sort descriptor count is %i!", MAX_DESC_COUNT);
+  
+    e = [_descs objectEnumerator];
+    for (i = 0; (desc = [e nextObject]) && (i < MAX_DESC_COUNT); i++)
+        ctx.sortdescs[i] = desc;
+  
+    ctx.count = i;
+  
+    if (null == nil) null = [NSNull null];
+    [self sortUsingFunction:(void *)sortDescComparator context:&ctx];
+}
+
+@end /* NSMutableArray(NSSortDescriptorSort) */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSStream.h b/libFoundation/Foundation/NSStream.h
new file mode 100644 (file)
index 0000000..475c130
--- /dev/null
@@ -0,0 +1,142 @@
+/* 
+   NSStream.h
+
+   Copyright (C) 2003 SKYRIX Software AG, Helge Hess.
+   All rights reserved.
+   
+   Author: Helge Hess <helge.hess@opengroupware.org>
+   
+   This file is part of libFoundation.
+   
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+   
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSStream_H__
+#define __NSStream_H__
+
+#include <Foundation/NSObject.h>
+#include <Foundation/NSArray.h>
+
+@class NSString, NSData, NSHost, NSError, NSRunLoop;
+@class NSStream, NSInputStream, NSOutputStream;
+
+typedef enum {
+    NSStreamStatusNotOpen = 0,
+    NSStreamStatusOpening = 1,
+    NSStreamStatusOpen    = 2,
+    NSStreamStatusReading = 3,
+    NSStreamStatusWriting = 4,
+    NSStreamStatusAtEnd   = 5,
+    NSStreamStatusClosed  = 6,
+    NSStreamStatusError   = 7
+} NSStreamStatus;
+
+typedef enum {
+   NSStreamEventEndEncountered    = 1 << 4,
+   NSStreamEventErrorOccurred     = 1 << 3,
+   NSStreamEventHasBytesAvailable = 1 << 1,
+   NSStreamEventHasSpaceAvailable = 1 << 2,
+   NSStreamEventNone              = 0,
+   NSStreamEventOpenCompleted     = 1 << 0,
+} NSStreamEvent;
+
+
+@interface NSStream : NSObject
+{
+}
+
++ (void)getStreamsToHost:(NSHost *)_host port:(int)_port 
+  inputStream:(NSInputStream **)_in
+  outputStream:(NSOutputStream **)_out;
+
+/* accessors */
+
+- (void)setDelegate:(id)_delegate;
+- (id)delegate;
+
+- (NSError *)streamError;
+- (NSStreamStatus)streamStatus;
+
+/* properties */
+
+- (BOOL)setProperty:(id)_value forKey:(NSString *)_key;
+- (id)propertyForKey:(NSString *)_key;
+
+/* operations */
+
+- (void)open;
+- (void)close;
+
+/* runloop */
+
+- (void)scheduleInRunLoop:(NSRunLoop *)_runloop forMode:(NSString *)_mode;
+- (void)removeFromRunLoop:(NSRunLoop *)_runloop forMode:(NSString *)_mode;
+
+@end
+
+
+@interface NSInputStream : NSStream
+{
+}
+
++ (id)inputStreamWithData:(NSData *)_data;
++ (id)inputStreamWithFileAtPath:(NSString *)_path;
+
+- (id)initWithData:(NSData *)_data;
+- (id)initWithFileAtPath:(NSString *)_path;
+
+/* operations */
+
+- (int)read:(void *)_buf maxLength:(unsigned int)_len;
+- (BOOL)getBuffer:(void **)_buf length:(unsigned int *)_len;
+- (BOOL)hasBytesAvailable;
+
+@end
+
+
+@interface NSOutputStream : NSStream
+{
+}
+
++ (id)outputStreamToMemory;
++ (id)outputStreamToBuffer:(void *)_buf capacity:(unsigned int)_capacity;
++ (id)outputStreamToFileAtPath:(NSStream *)_path append:(BOOL)_append;
+
+- (id)initToMemory;
+- (id)initToBuffer:(void *)_buf capacity:(unsigned int)_capacity;
+- (id)initToFileAtPath:(NSStream *)_path append:(BOOL)_append;
+
+/* operations */
+
+- (BOOL)hasSpaceAvailable;
+- (int)write:(const void *)buffer maxLength:(unsigned int)len;
+
+@end
+
+/* delegate */
+
+@interface NSObject(NSStreamDelegate)
+
+- (void)stream:(NSStream *)_stream handleEvent:(NSStreamEvent)_event;
+
+@end
+
+#endif /* __NSStream_H__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSStream.m b/libFoundation/Foundation/NSStream.m
new file mode 100644 (file)
index 0000000..95153f4
--- /dev/null
@@ -0,0 +1,98 @@
+/* 
+   NSStream.m
+
+   Copyright (C) 2003 SKYRIX Software AG, Helge Hess.
+   All rights reserved.
+   
+   Author: Helge Hess <helge.hess@opengroupware.org>
+   
+   This file is part of libFoundation.
+   
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+   
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSStream.h>
+#include <common.h>
+
+@implementation NSStream
+
++ (void)getStreamsToHost:(NSHost *)_host port:(int)_port 
+  inputStream:(NSInputStream **)_in
+  outputStream:(NSOutputStream **)_out
+{
+    // TODO
+    if (_in) *_in = nil;
+    if (_in) *_in = nil;
+    [self notImplemented:_cmd];
+}
+
+/* accessors */
+
+- (void)setDelegate:(id)_delegate
+{
+    [self subclassResponsibility:_cmd];
+}
+- (id)delegate
+{
+    return nil;
+}
+
+- (NSError *)streamError
+{
+    return nil;
+}
+- (NSStreamStatus)streamStatus
+{
+    return NSStreamStatusError;
+}
+
+/* properties */
+
+- (BOOL)setProperty:(id)_value forKey:(NSString *)_key
+{
+    return NO;
+}
+- (id)propertyForKey:(NSString *)_key
+{
+    return nil;
+}
+
+/* operations */
+
+- (void)open
+{
+}
+- (void)close
+{
+}
+
+/* runloop */
+
+- (void)scheduleInRunLoop:(NSRunLoop *)_runloop forMode:(NSString *)_mode 
+{
+    [self subclassResponsibility:_cmd];
+}
+- (void)removeFromRunLoop:(NSRunLoop *)_runloop forMode:(NSString *)_mode 
+{
+    [self subclassResponsibility:_cmd];
+}
+
+@end /* NSStream */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSString+StringEncoding.m b/libFoundation/Foundation/NSString+StringEncoding.m
new file mode 100644 (file)
index 0000000..a95e4ab
--- /dev/null
@@ -0,0 +1,1076 @@
+/* 
+   NSString.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include <Foundation/common.h>
+#include <Foundation/NSData.h>
+#include <Foundation/NSException.h>
+#include <Foundation/exceptions/StringExceptions.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+
+#include <Foundation/NSCharacterSet.h>
+#include <Foundation/NSString.h>
+
+#include <locale.h>
+
+#include <netinet/in.h>
+
+int NSConvertUTF16toUTF8(unichar             **sourceStart,
+                         const unichar       *sourceEnd, 
+                         unsigned char       **targetStart,
+                         const unsigned char *targetEnd);
+int NSConvertUTF8toUTF16(unsigned char **sourceStart, unsigned char *sourceEnd, 
+                         unichar **targetStart, const unichar *targetEnd);
+
+#define MaxStringEncodingBufStackSize 200
+
+NSData *dataUsingEncoding(NSString *self, NSStringEncoding encoding,
+                          BOOL flag)
+{
+  unsigned len   = [self length];
+  NSRange  range = { 0, len };
+
+  unichar  *buf16;
+  unichar  tmpBuf16[MaxStringEncodingBufStackSize];
+  unichar  *tmpMalloc16 = NULL;
+
+  NSData *data;
+
+  if (len < MaxStringEncodingBufStackSize) {
+    [self getCharacters:tmpBuf16 range:range];
+    buf16 = tmpBuf16;
+  }
+  else {
+    tmpMalloc16 = malloc((sizeof(unichar) * len) + 1);
+    [self getCharacters:tmpMalloc16 range:range];
+    buf16 = tmpMalloc16;
+  }
+  
+  // UNICODE
+  // ENCODINGS
+  data = nil;
+    
+  switch (encoding) {
+    case NSUnicodeStringEncoding:
+      data = [NSData dataWithBytes:buf16
+                     length:(len * sizeof(unichar))];
+      break;
+
+    case NSISOLatin1StringEncoding: {
+      register unsigned int euroCnt = 0;
+      register unsigned int i;
+            
+      for (i = 0; i < len; i++) {
+        if (buf16[i] == 8364)
+          euroCnt++;
+        else if (buf16[i] > 255 && !flag) {
+          NSLog(@"cannot convert without loosing information");
+          /* cannot convert without loosing information */
+          goto END_OF_SWITCH;
+        }
+      }
+      {
+        unsigned char     *buf;
+        unsigned char     tmpBuf[MaxStringEncodingBufStackSize];
+        unsigned char     *tmpMalloc = NULL;
+        register unsigned j;
+
+        j = len + (euroCnt*2);
+                
+        if (j < MaxStringEncodingBufStackSize) {
+          buf = tmpBuf;
+        }
+        else {
+          tmpMalloc = malloc((sizeof(unsigned char) * j) + 1);
+          buf = tmpMalloc;
+        }
+                
+        for (i = 0, j = 0; i < len; j++,i++) {
+          /* Euro encoding, ignory lossy conversions*/
+          if (buf16[i] == 8364 /* unicode euro charcode */) {
+            buf[j++] = 'E';
+            buf[j++] = 'U';
+            buf[j]   = 'R';
+          }
+          else
+            buf[j] = buf16[i];
+        }
+        data = (tmpMalloc)
+          ?[NSData dataWithBytesNoCopy:buf length:j]
+          :[NSData dataWithBytes:buf length:j];
+      }
+      break;
+    }
+      /* from http://lists.w3.org/Archives/Public/www-international/1998JulSep/0022.html */
+    case NSWindowsCP1252StringEncoding: { 
+      register unsigned int i;
+      unsigned char     *buf;
+      unsigned char     tmpBuf[MaxStringEncodingBufStackSize];
+      unsigned char     *tmpMalloc = NULL;
+
+      if (len < MaxStringEncodingBufStackSize) {
+        buf = tmpBuf;
+      }
+      else {
+        tmpMalloc = malloc((sizeof(char) * len) + 1);
+        buf       = tmpMalloc;
+      }
+            
+      for (i = 0; i < len;i++) {
+        buf[i] = 0;
+        switch (buf16[i]) {
+          case 0x20AC: /* EURO SIGN */
+            buf[i] = 0x80;
+            break;
+          case 0x201A: /* SINGLE LOW-9 QUOTATION MARK */
+            buf[i] = 0x82;
+            break;
+          case 0x0192: /* LATIN SMALL LETTER F WITH HOOK */
+            buf[i] = 0x83;
+            break;
+          case 0x201E: /* DOUBLE LOW-9 QUOTATION MARK */
+            buf[i] = 0x84;
+            break;
+          case 0x2026: /* HORIZONTAL ELLIPSIS */
+            buf[i] = 0x85;
+            break;
+          case 0x2020: /* DAGGER */
+            buf[i] = 0x86;
+            break;
+          case 0x2021: /* DOUBLE DAGGER */
+            buf[i] = 0x87;
+            break;
+          case 0x02C6: /* MODIFIER LETTER CIRCUMFLEX ACCENT */
+            buf[i] = 0x88;
+            break;
+          case 0x2030: /* PER MILLE SIGN */
+            buf[i] = 0x89;
+            break;
+          case 0x0160: /* LATIN CAPITAL LETTER S WITH CARON */
+            buf[i] = 0x8A;
+            break;
+          case 0x2039: /* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
+            buf[i] = 0x8B;
+            break;
+          case 0x0152: /* LATIN CAPITAL LIGATURE OE */
+            buf[i] = 0x8C;
+            break;
+          case 0x017D: /* LATIN CAPITAL LETTER Z WITH CARON */
+            buf[i] = 0x8E;
+            break;
+          case 0x2018: /* LEFT SINGLE QUOTATION MARK */
+            buf[i] = 0x91;
+            break;
+          case 0x2019: /* RIGHT SINGLE QUOTATION MARK */
+            buf[i] = 0x92;
+            break;
+          case 0x201C: /* LEFT DOUBLE QUOTATION MARK */
+            buf[i] = 0x93;
+            break;
+          case 0x201D: /* RIGHT DOUBLE QUOTATION MARK */
+            buf[i] = 0x94;
+            break;
+          case 0x2022: /* BULLET */
+            buf[i] = 0x95;
+            break;
+          case 0x2013: /* EN DASH */
+            buf[i] = 0x96;
+            break;
+          case 0x2014: /* EM DASH */
+            buf[i] = 0x97;
+            break;
+          case 0x02DC: /* SMALL TILDE */
+            buf[i] = 0x98;
+            break;
+          case 0x2122: /* TRADE MARK SIGN */
+            buf[i] = 0x99;
+            break;
+          case 0x0161: /* LATIN SMALL LETTER S WITH CARON */
+            buf[i] = 0x9A;
+            break;
+          case 0x203A: /* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
+            buf[i] = 0x9B;
+            break;
+          case 0x0153: /* LATIN SMALL LIGATURE OE */
+            buf[i] = 0x9C;
+            break;
+          case 0x017E: /* LATIN SMALL LETTER Z WITH CARON */
+            buf[i] = 0x9E;
+            break;
+          case 0x0178: /* LATIN CAPITAL LETTER Y WITH DIAERESIS */
+            buf[i] = 0x9F;
+            break;
+        }
+        if (buf[i] == 0) {
+          if ((buf16[i] > 255) && !flag) {
+            /* cannot convert without loosing information */
+            if (tmpMalloc) {
+              free(tmpMalloc); tmpMalloc = NULL;
+            }
+            goto END_OF_SWITCH;
+          }
+          else {
+            buf[i] = buf16[i]; /* invalid */
+          }
+        }
+      }
+      data = (tmpMalloc)
+        ? [NSData dataWithBytesNoCopy:buf length:i]
+        : [NSData dataWithBytes:buf length:i];
+      break;
+    }
+      /* from ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-2.TXT */
+    case NSISOLatin2StringEncoding: {
+      register unsigned int i;
+      unsigned char     *buf;
+      unsigned char     tmpBuf[MaxStringEncodingBufStackSize];
+      unsigned char     *tmpMalloc = NULL;
+
+      if (len < MaxStringEncodingBufStackSize) {
+        buf = tmpBuf;
+      }
+      else {
+        tmpMalloc = malloc((sizeof(char) * len) + 1);
+        buf       = tmpMalloc;
+      }
+            
+      for (i = 0; i < len;i++) {
+        buf[i] = 0;
+        switch (buf16[i]) {
+          case 0x0104:
+            buf[i] = 0xA1; /* LATIN CAPITAL LETTER A WITH OGONEK */
+            break;
+          case 0x02D8:
+            buf[i] = 0xA2; /* BREVE */
+            break;
+          case 0x0141:
+            buf[i] = 0xA3; /* LATIN CAPITAL LETTER L WITH STROKE */
+            break;
+          case 0x013D:
+            buf[i] = 0xA5; /* LATIN CAPITAL LETTER L WITH CARON */
+            break;
+          case 0x015A:
+            buf[i] = 0xA6; /* LATIN CAPITAL LETTER S WITH ACUTE */
+            break;
+          case 0x0160:
+            buf[i] = 0xA9; /* LATIN CAPITAL LETTER S WITH CARON */
+            break;
+          case 0x015E:
+            buf[i] = 0xAA; /* LATIN CAPITAL LETTER S WITH CEDILLA */
+            break;
+          case 0x0164:
+            buf[i] = 0xAB; /* LATIN CAPITAL LETTER T WITH CARON */
+            break;
+          case 0x0179:
+            buf[i] = 0xAC; /* LATIN CAPITAL LETTER Z WITH ACUTE */
+            break;
+          case 0x017D:
+            buf[i] = 0xAE; /* LATIN CAPITAL LETTER Z WITH CARON */
+            break;
+          case 0x017B:
+            buf[i] = 0xAF; /* LATIN CAPITAL LETTER Z WITH DOT ABOVE */
+            break;
+          case 0x0105:
+            buf[i] = 0xB1; /* LATIN SMALL LETTER A WITH OGONEK */
+            break;
+          case 0x02DB:
+            buf[i] = 0xB2; /* OGONEK */
+            break;
+          case 0x0142:
+            buf[i] = 0xB3; /* LATIN SMALL LETTER L WITH STROKE */
+            break;
+          case 0x013E:
+            buf[i] = 0xB5; /* LATIN SMALL LETTER L WITH CARON */
+            break;
+          case 0x015B:
+            buf[i] = 0xB6; /* LATIN SMALL LETTER S WITH ACUTE */
+            break;
+          case 0x02C7:
+            buf[i] = 0xB7; /* CARON */
+            break;
+          case 0x0161:
+            buf[i] = 0xB9; /* LATIN SMALL LETTER S WITH CARON */
+            break;
+          case 0x015F:
+            buf[i] = 0xBA; /* LATIN SMALL LETTER S WITH CEDILLA */
+            break;
+          case 0x0165:
+            buf[i] = 0xBB; /* LATIN SMALL LETTER T WITH CARON */
+            break;
+          case 0x017A:
+            buf[i] = 0xBC; /* LATIN SMALL LETTER Z WITH ACUTE */
+            break;
+          case 0x02DD:
+            buf[i] = 0xBD; /* DOUBLE ACUTE ACCENT */
+            break;
+          case 0x017E:
+            buf[i] = 0xBE; /* LATIN SMALL LETTER Z WITH CARON */
+            break;
+          case 0x017C:
+            buf[i] = 0xBF; /* LATIN SMALL LETTER Z WITH DOT ABOVE */
+            break;
+          case 0x0154:
+            buf[i] = 0xC0; /* LATIN CAPITAL LETTER R WITH ACUTE */
+            break;
+          case 0x0102:
+            buf[i] = 0xC3; /* LATIN CAPITAL LETTER A WITH BREVE */
+            break;
+          case 0x0139:
+            buf[i] = 0xC5; /* LATIN CAPITAL LETTER L WITH ACUTE */
+            break;
+          case 0x0106:
+            buf[i] = 0xC6; /* LATIN CAPITAL LETTER C WITH ACUTE */
+            break;
+          case 0x010C:
+            buf[i] = 0xC8; /* LATIN CAPITAL LETTER C WITH CARON */
+            break;
+          case 0x0118:
+            buf[i] = 0xCA; /* LATIN CAPITAL LETTER E WITH OGONEK */
+            break;
+          case 0x011A:
+            buf[i] = 0xCC; /* LATIN CAPITAL LETTER E WITH CARON */
+            break;
+          case 0x010E:
+            buf[i] = 0xCF; /* LATIN CAPITAL LETTER D WITH CARON */
+            break;
+          case 0x0110:
+            buf[i] = 0xD0; /* LATIN CAPITAL LETTER D WITH STROKE */
+            break;
+          case 0x0143:
+            buf[i] = 0xD1; /* LATIN CAPITAL LETTER N WITH ACUTE */
+            break;
+          case 0x0147:
+            buf[i] = 0xD2; /* LATIN CAPITAL LETTER N WITH CARON */
+            break;
+          case 0x0150:
+            buf[i] = 0xD5; /* LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */
+            break;
+          case 0x0158:
+            buf[i] = 0xD8; /* LATIN CAPITAL LETTER R WITH CARON */
+            break;
+          case 0x016E:
+            buf[i] = 0xD9; /* LATIN CAPITAL LETTER U WITH RING ABOVE */
+            break;
+          case 0x0170:
+            buf[i] = 0xDB; /* LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */
+            break;
+          case 0x0162:
+            buf[i] = 0xDE; /* LATIN CAPITAL LETTER T WITH CEDILLA */
+            break;
+          case 0x0155:
+            buf[i] = 0xE0; /* LATIN SMALL LETTER R WITH ACUTE */
+            break;
+          case 0x0103:
+            buf[i] = 0xE3; /* LATIN SMALL LETTER A WITH BREVE */
+            break;
+          case 0x013A:
+            buf[i] = 0xE5; /* LATIN SMALL LETTER L WITH ACUTE */
+            break;
+          case 0x0107:
+            buf[i] = 0xE6; /* LATIN SMALL LETTER C WITH ACUTE */
+            break;
+          case 0x010D:
+            buf[i] = 0xE8; /* LATIN SMALL LETTER C WITH CARON */
+            break;
+          case 0x0119:
+            buf[i] = 0xEA; /* LATIN SMALL LETTER E WITH OGONEK */
+            break;
+          case 0x011B:
+            buf[i] = 0xEC; /* LATIN SMALL LETTER E WITH CARON */
+            break;
+          case 0x010F:
+            buf[i] = 0xEF; /* LATIN SMALL LETTER D WITH CARON */
+            break;
+          case 0x0111:
+            buf[i] = 0xF0; /* LATIN SMALL LETTER D WITH STROKE */
+            break;
+          case 0x0144:
+            buf[i] = 0xF1; /* LATIN SMALL LETTER N WITH ACUTE */
+            break;
+          case 0x0148:
+            buf[i] = 0xF2; /* LATIN SMALL LETTER N WITH CARON */
+            break;
+          case 0x0151:
+            buf[i] = 0xF5; /* LATIN SMALL LETTER O WITH DOUBLE ACUTE */
+            break;
+          case 0x0159:
+            buf[i] = 0xF8; /* LATIN SMALL LETTER R WITH CARON */
+            break;
+          case 0x016F:
+            buf[i] = 0xF9; /* LATIN SMALL LETTER U WITH RING ABOVE */
+            break;
+          case 0x0171:
+            buf[i] = 0xFB; /* LATIN SMALL LETTER U WITH DOUBLE ACUTE */
+            break;
+          case 0x0163:
+            buf[i] = 0xFE; /* LATIN SMALL LETTER T WITH CEDILLA */
+            break;
+          case 0x02D9:
+            buf[i] = 0xFF; /* DOT ABOVE */
+            break;
+        }
+        if (buf[i] == 0) {
+          if ((buf16[i] > 255) && !flag) {
+            /* cannot convert without loosing information */
+            if (tmpMalloc) {
+              free(tmpMalloc); tmpMalloc = NULL;
+            }
+            goto END_OF_SWITCH;
+          }
+          else {
+            buf[i] = buf16[i]; /* invalid */
+          }
+        }
+      }
+      data = (tmpMalloc)
+        ? [NSData dataWithBytesNoCopy:buf length:i]
+        : [NSData dataWithBytes:buf length:i];
+      break;
+    }
+    case NSISOLatin9StringEncoding: {
+      register unsigned int i;
+      unsigned char     *buf;
+      unsigned char     tmpBuf[MaxStringEncodingBufStackSize];
+      unsigned char     *tmpMalloc = NULL;
+
+      if (len < MaxStringEncodingBufStackSize) {
+        buf = tmpBuf;
+      }
+      else {
+        tmpMalloc = malloc((sizeof(char) * len) + 1);
+        buf       = tmpMalloc;
+      }
+            
+      for (i = 0; i < len;i++) {
+        buf[i] = 0;
+        switch (buf16[i]) {
+                
+          case 0x20AC: /* EURO SIGN */
+            buf[i] = 0xA4;
+            break;
+          case 0x0160: /* LATIN CAPITAL LETTER S WITH CARON */
+            buf[i] = 0xA6;
+            break;
+          case 0x0161: /* LATIN SMALL LETTER S WITH CARON */
+            buf[i] = 0xA8;
+            break;
+          case 0x017D: /* LATIN CAPITAL LETTER Z WITH CARON */
+            buf[i] = 0xB4;
+            break;
+          case 0x017E: /* LATIN SMALL LETTER Z WITH CARON */
+            buf[i] = 0xB8;
+            break;
+          case 0x0152: /* LATIN CAPITAL LIGATURE OE */
+            buf[i] = 0xBC;
+            break;
+          case 0x0153: /* LATIN SMALL LIGATURE OE */
+            buf[i] = 0xBD;
+            break;
+          case 0x0178: /* LATIN CAPITAL LETTER Y WITH DIAERESIS */
+            buf[i] = 0xBE;
+            break;
+                
+        }
+        if (buf[i] == 0) {
+          if ((buf16[i] > 255) && !flag) {
+            /* cannot convert without loosing information */
+            if (tmpMalloc) {
+              free(tmpMalloc); tmpMalloc = NULL;
+            }
+            goto END_OF_SWITCH;
+          }
+          else {
+            buf[i] = buf16[i]; /* invalid */
+          }
+        }
+      }
+      data = (tmpMalloc)
+        ? [NSData dataWithBytesNoCopy:buf length:i]
+        : [NSData dataWithBytes:buf length:i];
+      break;
+    }
+    case NSASCIIStringEncoding: {
+      register unsigned i;
+      unsigned char     *buf;
+      unsigned char     tmpBuf[MaxStringEncodingBufStackSize];
+      unsigned char     *tmpMalloc = NULL;
+
+      if (len < MaxStringEncodingBufStackSize) {
+        buf = tmpBuf;
+      }
+      else {
+        tmpMalloc = malloc((sizeof(char) * len) + 1);
+        buf       = tmpMalloc;
+      }
+            
+      for (i = 0; i < len; i++) {
+        if (buf16[i] > 127) {
+            if (!flag) {
+              /* cannot convert without loosing information */
+              if (tmpMalloc) {
+                free(tmpMalloc); tmpMalloc = NULL;
+              }
+              goto END_OF_SWITCH;
+            }
+            else {
+              buf[i] = ' ';
+            }
+        }
+        else 
+          buf[i] = buf16[i];
+      }
+      data = (tmpMalloc)
+        ? [NSData dataWithBytesNoCopy:buf length:i]
+        : [NSData dataWithBytes:buf length:i];
+      break;
+    }
+    case NSUTF8StringEncoding: {
+      unsigned char *buf;
+      unsigned      bufLen;
+      int           result;
+            
+      /* empty UTF16 becomes empty UTF8 .. */
+      if (len == 0) {
+        data = [NSData data];
+        goto END_OF_SWITCH;
+      }
+            
+      bufLen = (len + (len / 2));
+      buf    = NSZoneMallocAtomic(NULL, bufLen + 1);
+            
+      do {
+        unichar       *start16, *end16;
+        unsigned char *start, *end;
+                
+        start16 = &(buf16[0]);
+        end16   = buf16 + len;
+        start   = &(buf[0]);
+        end     = start + bufLen;
+                
+        result = NSConvertUTF16toUTF8(&start16, end16, &start, end);
+                
+        NSCAssert(result != 1, @"not enough chars in source buffer !");
+                
+        if (result == 2) {
+          /* not enough memory in target buffer */
+          bufLen *= 2;
+          buf = NSZoneRealloc(NULL, buf, bufLen + 1);
+        }
+        else {
+          len = start - buf;
+          break;
+        }
+      }
+      while (1);
+            
+      data = [NSData dataWithBytesNoCopy:buf length:len];
+      break;
+    }
+    default:
+      if (flag) {
+        NSLog(@"%s: unsupported string encoding: %@ "
+              @"(returning string as ISO-Latin-1)",
+              __PRETTY_FUNCTION__,
+              [NSString localizedNameOfStringEncoding:encoding]);
+                
+        data = [self dataUsingEncoding:NSISOLatin9StringEncoding
+                     allowLossyConversion:YES];
+      }
+      else {
+        NSLog(@"%s: unsupported string encoding: %@ "
+              @"(returning nil)",
+              __PRETTY_FUNCTION__,
+              [NSString localizedNameOfStringEncoding:encoding]);
+        goto END_OF_SWITCH;
+      }
+  }
+ END_OF_SWITCH:
+  if (tmpMalloc16) {
+    free(tmpMalloc16); tmpMalloc16 = NULL;
+  }
+  return data;
+}
+
+id NSInitStringWithData(NSString *self, NSData *data,
+                        NSStringEncoding encoding)
+{
+  // UNICODE
+  // ENCODINGS
+  unsigned      len;
+  unsigned char *buf;
+    
+  len = [data length];
+  buf = MallocAtomic(len + 1);
+
+  if (len > 0) [data getBytes:buf];
+  buf[len] = '\0';
+
+  switch (encoding) {
+    case NSWindowsCP1252StringEncoding: { 
+      register unsigned int i;
+      unichar *newBuf;
+
+      newBuf = MallocAtomic((len + 1)* sizeof(unichar));
+            
+      for (i = 0; i < len;i++) {
+        newBuf[i] = 0;
+        switch (buf[i]) {
+          case 0x80: /* EURO SIGN */
+            newBuf[i] = 0x20AC;
+            break;
+          case 0x82: /* SINGLE LOW-9 QUOTATION MARK */
+            newBuf[i] = 0x201A;
+            break;
+          case 0x83: /* LATIN SMALL LETTER F WITH HOOK */
+            newBuf[i] = 0x0192;
+            break;
+          case 0x84: /* DOUBLE LOW-9 QUOTATION MARK */
+            newBuf[i] = 0x201E;
+            break;
+          case 0x85: /* HORIZONTAL ELLIPSIS */
+            newBuf[i] = 0x2026;
+            break;
+          case 0x86: /* DAGGER */
+            newBuf[i] = 0x2020;
+            break;
+          case 0x87: /* DOUBLE DAGGER */
+            newBuf[i] = 0x2021;
+            break;
+          case 0x88: /* MODIFIER LETTER CIRCUMFLEX ACCENT */
+            newBuf[i] = 0x02C6;
+            break;
+          case 0x89: /* PER MILLE SIGN */
+            newBuf[i] = 0x2030;
+            break;
+          case 0x8A: /* LATIN CAPITAL LETTER S WITH CARON */
+            newBuf[i] = 0x0160;
+            break;
+          case 0x8B: /* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
+            newBuf[i] = 0x2039;
+            break;
+          case 0x8C: /* LATIN CAPITAL LIGATURE OE */
+            newBuf[i] = 0x0152;
+            break;
+          case 0x8E: /* LATIN CAPITAL LETTER Z WITH CARON */
+            newBuf[i] = 0x017D;
+            break;
+          case 0x91: /* LEFT SINGLE QUOTATION MARK */
+            newBuf[i] = 0x2018;
+            break;
+          case 0x92: /* RIGHT SINGLE QUOTATION MARK */
+            newBuf[i] = 0x2019;
+            break;
+          case 0x93: /* LEFT DOUBLE QUOTATION MARK */
+            newBuf[i] = 0x201C;
+            break;
+          case 0x94: /* RIGHT DOUBLE QUOTATION MARK */
+            newBuf[i] = 0x201D;
+            break;
+          case 0x95: /* BULLET */
+            newBuf[i] = 0x2022;
+            break;
+          case 0x96: /* EN DASH */
+            newBuf[i] = 0x2013;
+            break;
+          case 0x97: /* EM DASH */
+            newBuf[i] = 0x2014;
+            break;
+          case 0x98: /* SMALL TILDE */
+            newBuf[i] = 0x02DC;
+            break;
+          case 0x99: /* TRADE MARK SIGN */
+            newBuf[i] = 0x2122;
+            break;
+          case 0x9A: /* LATIN SMALL LETTER S WITH CARON */
+            newBuf[i] = 0x0161;
+            break;
+          case 0x9B: /* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
+            newBuf[i] = 0x203A;
+            break;
+          case 0x9C: /* LATIN SMALL LIGATURE OE */
+            newBuf[i] = 0x0153;
+            break;
+          case 0x9E: /* LATIN SMALL LETTER Z WITH CARON */
+            newBuf[i] = 0x017E;
+            break;
+          case 0x9F: /* LATIN CAPITAL LETTER Y WITH DIAERESIS */
+            newBuf[i] = 0x0178;
+            break;
+        }
+        if (newBuf[i] == 0)
+          newBuf[i] = buf[i];
+      }
+      {
+        id tmp;
+                
+        tmp = self;
+                
+        // TODO: this breaks NSMutableString !!!
+        self = [NSInlineUTF16String allocForCapacity:len
+                                    zone:[self zone]];
+        self = [self initWithCharacters:newBuf length:len];
+        RELEASE(tmp);
+      }
+      lfFree(newBuf);
+      lfFree(buf);
+      return self;
+    }
+        
+    case NSISOLatin9StringEncoding: {
+      register unsigned int i;
+      unichar *newBuf;
+            
+      newBuf = MallocAtomic((len + 1)* sizeof(unichar));
+            
+      for (i = 0; i < len; i++) {
+        newBuf[i] = 0;
+                
+        switch (buf[i]) {
+          case 0xA4:   /* EURO SIGN */
+            newBuf[i] = 0x20AC;
+            break;
+          case 0xA6:   /* LATIN CAPITAL LETTER S WITH CARON */
+            newBuf[i] = 0x0160;
+            break;
+          case 0xA8:   /* LATIN SMALL LETTER S WITH CARON */
+            newBuf[i] = 0x0161;
+            break;
+          case 0xB4:   /* LATIN CAPITAL LETTER Z WITH CARON */
+            newBuf[i] = 0x017D;
+            break;
+          case 0xB8:   /* LATIN SMALL LETTER Z WITH CARON */
+            newBuf[i] = 0x017E;
+            break;
+          case 0xBC:   /* LATIN CAPITAL LIGATURE OE */
+            newBuf[i] = 0x0152;
+            break;
+          case 0xBD:   /* LATIN SMALL LIGATURE OE */
+            newBuf[i] = 0x0153;
+            break;
+          case 0xBE:   /* LATIN CAPITAL LETTER Y WITH DIAERESIS */
+            newBuf[i] = 0x0178;
+            break;
+        }
+        if (newBuf[i] == 0)
+          newBuf[i] = buf[i];
+      }
+      {
+        id tmp;
+                
+        tmp = self;
+                
+        // TODO: this breaks NSMutableString !!!
+        self = [NSInlineUTF16String allocForCapacity:len
+                                    zone:[self zone]];
+        self = [self initWithCharacters:newBuf length:len];
+        RELEASE(tmp);
+      }
+      lfFree(newBuf);
+      lfFree(buf);
+      return self;
+    }
+          
+    case NSISOLatin2StringEncoding: {
+      register unsigned int i;
+      unichar *newBuf;
+            
+      newBuf = MallocAtomic((len + 1)* sizeof(unichar));
+            
+      for (i = 0; i < len; i++) {
+        newBuf[i] = 0;
+                
+        switch (buf[i]) {
+          case 0xA1:
+            newBuf[i] = 0x0104; /* LATIN CAPITAL LETTER A WITH OGONEK */
+            break;
+          case 0xA2:
+            newBuf[i] = 0x02D8; /* BREVE */
+            break;
+          case 0xA3:
+            newBuf[i] = 0x0141; /* LATIN CAPITAL LETTER L WITH STROKE */
+            break;
+          case 0xA5:
+            newBuf[i] = 0x013D; /* LATIN CAPITAL LETTER L WITH CARON */
+            break;
+          case 0xA6:
+            newBuf[i] = 0x015A; /* LATIN CAPITAL LETTER S WITH ACUTE */
+            break;
+          case 0xA9:
+            newBuf[i] = 0x0160; /* LATIN CAPITAL LETTER S WITH CARON */
+            break;
+          case 0xAA:
+            newBuf[i] = 0x015E; /* LATIN CAPITAL LETTER S WITH CEDILLA */
+            break;
+          case 0xAB:
+            newBuf[i] = 0x0164; /* LATIN CAPITAL LETTER T WITH CARON */
+            break;
+          case 0xAC:
+            newBuf[i] = 0x0179; /* LATIN CAPITAL LETTER Z WITH ACUTE */
+            break;
+          case 0xAE:
+            newBuf[i] = 0x017D; /* LATIN CAPITAL LETTER Z WITH CARON */
+            break;
+          case 0xAF:
+            newBuf[i] = 0x017B; /* LATIN CAPITAL LETTER Z WITH DOT ABOVE */
+            break;
+          case 0xB1:
+            newBuf[i] = 0x0105; /* LATIN SMALL LETTER A WITH OGONEK */
+            break;
+          case 0xB2:
+            newBuf[i] = 0x02DB; /* OGONEK */
+            break;
+          case 0xB3:
+            newBuf[i] = 0x0142; /* LATIN SMALL LETTER L WITH STROKE */
+            break;
+          case 0xB5:
+            newBuf[i] = 0x013E; /* LATIN SMALL LETTER L WITH CARON */
+            break;
+          case 0xB6:
+            newBuf[i] = 0x015B; /* LATIN SMALL LETTER S WITH ACUTE */
+            break;
+          case 0xB7:
+            newBuf[i] = 0x02C7; /* CARON */
+            break;
+          case 0xB9:
+            newBuf[i] = 0x0161; /* LATIN SMALL LETTER S WITH CARON */
+            break;
+          case 0xBA:
+            newBuf[i] = 0x015F; /* LATIN SMALL LETTER S WITH CEDILLA */
+            break;
+          case 0xBB:
+            newBuf[i] = 0x0165; /* LATIN SMALL LETTER T WITH CARON */
+            break;
+          case 0xBC:
+            newBuf[i] = 0x017A; /* LATIN SMALL LETTER Z WITH ACUTE */
+            break;
+          case 0xBD:
+            newBuf[i] = 0x02DD; /* DOUBLE ACUTE ACCENT */
+            break;
+          case 0xBE:
+            newBuf[i] = 0x017E; /* LATIN SMALL LETTER Z WITH CARON */
+            break;
+          case 0xBF:
+            newBuf[i] = 0x017C; /* LATIN SMALL LETTER Z WITH DOT ABOVE */
+            break;
+          case 0xC0:
+            newBuf[i] = 0x0154; /* LATIN CAPITAL LETTER R WITH ACUTE */
+            break;
+          case 0xC3:
+            newBuf[i] = 0x0102; /* LATIN CAPITAL LETTER A WITH BREVE */
+            break;
+          case 0xC5:
+            newBuf[i] = 0x0139; /* LATIN CAPITAL LETTER L WITH ACUTE */
+            break;
+          case 0xC6:
+            newBuf[i] = 0x0106; /* LATIN CAPITAL LETTER C WITH ACUTE */
+            break;
+          case 0xC8:
+            newBuf[i] = 0x010C; /* LATIN CAPITAL LETTER C WITH CARON */
+            break;
+          case 0xCA:
+            newBuf[i] = 0x0118; /* LATIN CAPITAL LETTER E WITH OGONEK */
+            break;
+          case 0xCC:
+            newBuf[i] = 0x011A; /* LATIN CAPITAL LETTER E WITH CARON */
+            break;
+          case 0xCF:
+            newBuf[i] = 0x010E; /* LATIN CAPITAL LETTER D WITH CARON */
+            break;
+          case 0xD0:
+            newBuf[i] = 0x0110; /* LATIN CAPITAL LETTER D WITH STROKE */
+            break;
+          case 0xD1:
+            newBuf[i] = 0x0143; /* LATIN CAPITAL LETTER N WITH ACUTE */
+            break;
+          case 0xD2:
+            newBuf[i] = 0x0147; /* LATIN CAPITAL LETTER N WITH CARON */
+            break;
+          case 0xD5:
+            newBuf[i] = 0x0150; /* LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */
+            break;
+          case 0xD8:
+            newBuf[i] = 0x0158; /* LATIN CAPITAL LETTER R WITH CARON */
+            break;
+          case 0xD9:
+            newBuf[i] = 0x016E; /* LATIN CAPITAL LETTER U WITH RING ABOVE */
+            break;
+          case 0xDB:
+            newBuf[i] = 0x0170; /* LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */
+            break;
+          case 0xDE:
+            newBuf[i] = 0x0162; /* LATIN CAPITAL LETTER T WITH CEDILLA */
+            break;
+          case 0xE0:
+            newBuf[i] = 0x0155; /* LATIN SMALL LETTER R WITH ACUTE */
+            break;
+          case 0xE3:
+            newBuf[i] = 0x0103; /* LATIN SMALL LETTER A WITH BREVE */
+            break;
+          case 0xE5:
+            newBuf[i] = 0x013A; /* LATIN SMALL LETTER L WITH ACUTE */
+            break;
+          case 0xE6:
+            newBuf[i] = 0x0107; /* LATIN SMALL LETTER C WITH ACUTE */
+            break;
+          case 0xE8:
+            newBuf[i] = 0x010D; /* LATIN SMALL LETTER C WITH CARON */
+            break;
+          case 0xEA:
+            newBuf[i] = 0x0119; /* LATIN SMALL LETTER E WITH OGONEK */
+            break;
+          case 0xEC:
+            newBuf[i] = 0x011B; /* LATIN SMALL LETTER E WITH CARON */
+            break;
+          case 0xEF:
+            newBuf[i] = 0x010F; /* LATIN SMALL LETTER D WITH CARON */
+            break;
+          case 0xF0:
+            newBuf[i] = 0x0111; /* LATIN SMALL LETTER D WITH STROKE */
+            break;
+          case 0xF1:
+            newBuf[i] = 0x0144; /* LATIN SMALL LETTER N WITH ACUTE */
+            break;
+          case 0xF2:
+            newBuf[i] = 0x0148; /* LATIN SMALL LETTER N WITH CARON */
+            break;
+          case 0xF5:
+            newBuf[i] = 0x0151; /* LATIN SMALL LETTER O WITH DOUBLE ACUTE */
+            break;
+          case 0xF8:
+            newBuf[i] = 0x0159; /* LATIN SMALL LETTER R WITH CARON */
+            break;
+          case 0xF9:
+            newBuf[i] = 0x016F; /* LATIN SMALL LETTER U WITH RING ABOVE */
+            break;
+          case 0xFB:
+            newBuf[i] = 0x0171; /* LATIN SMALL LETTER U WITH DOUBLE ACUTE */
+            break;
+          case 0xFE:
+            newBuf[i] = 0x0163; /* LATIN SMALL LETTER T WITH CEDILLA */
+            break;
+          case 0xFF:
+            newBuf[i] = 0x02D9; /* DOT ABOVE */
+            break;
+        }
+        if (newBuf[i] == 0)
+          newBuf[i] = buf[i];
+      }
+      {
+        id tmp;
+                
+        tmp = self;
+                
+        // TODO: this breaks NSMutableString !!!
+        self = [NSInlineUTF16String allocForCapacity:len
+                                    zone:[self zone]];
+        self = [self initWithCharacters:newBuf length:len];
+        RELEASE(tmp);
+      }
+      lfFree(newBuf);
+      lfFree(buf);
+      return self;
+    }
+          
+    case NSUnicodeStringEncoding: {
+      self = [self initWithCharacters:(unichar *)buf
+                   length:(len / sizeof(unichar))];
+      lfFree(buf);
+      return self;
+    }
+    case NSASCIIStringEncoding: 
+    case NSISOLatin1StringEncoding: {
+      self = [self initWithCString:buf length:len];
+      lfFree(buf);
+      return self;
+    }
+        
+    case NSUTF8StringEncoding: {
+      unichar       *buf16;
+      unsigned char *start,   *end;
+      unichar       *start16, *end16;
+      int result;
+            
+      buf16 = MallocAtomic((len + 1) * sizeof(unichar));
+#if DEBUG
+      NSCAssert(buf16,
+                @"couldn't allocate proper buffer of len %i", len);
+#endif
+            
+      start   = &(buf[0]);
+      end     = start + len;
+      start16 = &(buf16[0]);
+      end16   = start16 + len;
+
+      result = NSConvertUTF8toUTF16(&start, end, &start16, end16);
+      if (buf) {
+        lfFree(buf);
+        start = end = buf = NULL;
+      }
+            
+      if (result == 2) { /* target exhausted */
+        if (buf16) { lfFree(buf16); buf16 = NULL; }
+        [NSException raise:@"UTFConversionException"
+                     format:
+                     @"couldn't convert UTF8 to UTF16, "
+                     @"target buffer is to small !"];
+      }
+      else if (result == 1) { /* source exhausted */
+        if (buf16) { lfFree(buf16); buf16 = NULL; }
+        [NSException raise:@"UTFConversionException"
+                     format:
+                     @"couldn't convert UTF8 to UTF16, "
+                     @"source buffer is to small "
+                     @"(probably invalid input) !"];
+      }
+      else {
+        /* length correct ? */
+        {
+          id tmp;
+                    
+          tmp = self;
+          // TODO: this breaks NSMutableString !!!
+          self = [[NSInlineUTF16String class] allocForCapacity:(start16 - buf16)
+                                              zone:[self zone]];
+          self = [self initWithCharacters:buf16
+                       length:(start16 - buf16)];
+          RELEASE(tmp);
+        }
+        if (buf16) { lfFree(buf16); buf16 = NULL; }
+        return self;
+      }
+    }
+        
+    default:
+      NSLog(@"%s: unsupported string encoding: %@ "
+            @"(returning string as ISO-Latin-1)",
+            __PRETTY_FUNCTION__,
+            [NSString localizedNameOfStringEncoding:encoding]);
+           
+      self = NSInitStringWithData(self, data, NSISOLatin1StringEncoding);
+      lfFree(buf);
+      return self;
+  }
+}
diff --git a/libFoundation/Foundation/NSString.h b/libFoundation/Foundation/NSString.h
new file mode 100644 (file)
index 0000000..4784d90
--- /dev/null
@@ -0,0 +1,339 @@
+/* 
+   NSString.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSString_h__
+#define __NSString_h__
+
+#include <limits.h>
+#include <stdarg.h>
+#include <Foundation/NSObject.h>
+#include <Foundation/NSRange.h>
+
+@class NSDictionary;
+@class NSMutableDictionary;
+@class NSArray;
+@class NSData;
+@class NSCharacterSet;
+@class NSURL;
+
+/* String limits */
+#define NSMaximumStringLength   (INT_MAX-1)
+#define NSHashStringLength      63
+
+/* Known encodings */
+typedef unsigned NSStringEncoding;
+
+enum { 
+    NSASCIIStringEncoding                 = 1,
+    NSNEXTSTEPStringEncoding              = 2,
+    NSJapaneseEUCStringEncoding           = 3,
+    NSUTF8StringEncoding                  = 4,
+    NSISOLatin1StringEncoding             = 5,
+    NSSymbolStringEncoding                = 6,
+    NSNonLossyASCIIStringEncoding         = 7,
+    NSShiftJISStringEncoding              = 8,
+    NSISOLatin2StringEncoding             = 9,
+    NSUnicodeStringEncoding               = 10,
+    NSWindowsCP1251StringEncoding         = 11,
+    NSWindowsCP1252StringEncoding         = 12,
+    NSWindowsCP1253StringEncoding         = 13,
+    NSWindowsCP1254StringEncoding         = 14,
+    NSWindowsCP1250StringEncoding         = 15,
+    NSISO2022JPStringEncoding             = 21,
+    
+    /* not in MacOSX: */
+    NSAdobeStandardCyrillicStringEncoding,
+    NSWinLatin1StringEncoding,
+    NSISOLatin9StringEncoding
+};
+
+/* 
+ * Flags passed to compare & rangeOf...: With a zero mask passed in, 
+ * the searches are case sensitive, from the beginning, are non-anchored, 
+ * and take Unicode floating diacritics and other non-visible characters into
+ * account.
+ */
+
+enum {
+    NSCaseInsensitiveSearch = 1,
+    NSLiteralSearch         = 2, /* Character-by-character search */
+    NSBackwardsSearch       = 4, /* Search backwards in the range */
+    NSAnchoredSearch        = 8  /* Search anchored within specified range */
+};
+
+/* Unicode character is 16bit wide (assumes short is 16bit wide in gcc) */
+typedef unsigned short unichar;
+
+/*
+ * NSString
+ *
+ * primitive methods:
+ *      - characterAtIndex:
+ *      - length:
+ *      - init* as appropriate
+ */
+
+@interface NSString : NSObject <NSCoding, NSCopying, NSMutableCopying>
+/* Getting a string's length */
+- (unsigned int)length;
+
+/* Accessing characters */
+- (unichar)characterAtIndex:(unsigned int)index;
+- (void)getCharacters:(unichar*)buffer;
+- (void)getCharacters:(unichar*)buffer range:(NSRange)aRange;
+
+/* Combining strings */ 
+- (NSString*)stringByAppendingString:(NSString*)aString;
+- (NSString*)stringByAppendingFormat:(NSString*)format,...;
+- (NSString*)stringByAppendingFormat:(NSString*)format 
+  arguments:(va_list)argList;
+- (NSString*)stringByPrependingString:(NSString*)aString;
+- (NSString*)stringByPrependingFormat:(NSString*)format,...;
+- (NSString*)stringByPrependingFormat:(NSString*)format 
+  arguments:(va_list)argList;
+
+/* Dividing strings */
+- (NSArray*)componentsSeparatedByString:(NSString*)separator;
+- (NSString*)substringFromIndex:(unsigned int)index;
+- (NSString*)substringWithRange:(NSRange)aRange;
+- (NSString*)substringFromRange:(NSRange)aRange;
+        // obsolete; use instead -substringWithRange:
+- (NSString*)substringToIndex:(unsigned int)index;
+
+- (NSString *)stringByTrimmingCharactersInSet:(NSCharacterSet *)set;
+
+/* Finding characters and substrings */
+- (NSRange)rangeOfCharacterFromSet:(NSCharacterSet*)aSet;
+- (NSRange)rangeOfCharacterFromSet:(NSCharacterSet*)aSet
+  options:(unsigned int)mask;
+- (NSRange)rangeOfCharacterFromSet:(NSCharacterSet*)aSet
+  options:(unsigned int)mask range:(NSRange)aRange;
+- (NSRange)rangeOfString:(NSString*)string;
+- (NSRange)rangeOfString:(NSString*)string options:(unsigned int)mask;
+- (NSRange)rangeOfString:(NSString*)aString
+  options:(unsigned int)mask range:(NSRange)aRange;
+- (unsigned int)indexOfString:(NSString*)substring;
+- (unsigned int)indexOfString:(NSString*)substring fromIndex:(unsigned)index;
+- (unsigned int)indexOfString:(NSString*)substring range:(NSRange)aRange;
+
+/* Determining composed character sequences */
+- (NSRange)rangeOfComposedCharacterSequenceAtIndex:(unsigned int)anIndex;
+
+/* Converting string contents into a property list */
+- (id)propertyList;
+- (NSMutableDictionary*)propertyListFromStringsFileFormat;
+
+/* Identifying and comparing strings */
+- (NSComparisonResult)caseInsensitiveCompare:(NSString*)aString;
+- (NSComparisonResult)compare:(id)aString;
+- (NSComparisonResult)compare:(NSString*)aString options:(unsigned int)mask;
+- (NSComparisonResult)compare:(NSString*)aString
+  options:(unsigned int)mask range:(NSRange)aRange;
+- (BOOL)hasPrefix:(NSString*)aString;
+- (BOOL)hasSuffix:(NSString*)aString;
+
+- (BOOL)isEqual:(id)anObject;
+- (BOOL)isEqualToString:(NSString*)aString;
+- (unsigned)hash;       
+
+/* Getting a shared prefix */
+- (NSString*)commonPrefixWithString:(NSString*)aString
+  options:(unsigned int)mask;
+
+/* Changing case */
+- (NSString*)capitalizedString;
+- (NSString*)lowercaseString;
+- (NSString*)uppercaseString;
+
+/* Getting C strings */
+- (const char *)cString;
+- (unsigned int)cStringLength;
+- (void)getCString:(char *)buffer;
+- (void)getCString:(char *)buffer maxLength:(unsigned int)maxLength;
+- (void)getCString:(char *)buffer maxLength:(unsigned int)maxLength
+  range:(NSRange)aRange remainingRange:(NSRange *)leftoverRange;
+- (const char *)UTF8String;
+
+/* Getting numeric values */
+- (double)doubleValue;
+- (float)floatValue;
+- (int)intValue;
+
+/* Working with encodings */
++ (NSStringEncoding *)availableStringEncodings;
++ (NSStringEncoding)defaultCStringEncoding;
++ (NSString *)localizedNameOfStringEncoding:(NSStringEncoding)encoding;
+- (BOOL)canBeConvertedToEncoding:(NSStringEncoding)encoding;
+- (NSData *)dataUsingEncoding:(NSStringEncoding)encoding;
+- (NSData *)dataUsingEncoding:(NSStringEncoding)encoding
+  allowLossyConversion:(BOOL)flag;
+- (NSStringEncoding)fastestEncoding;
+- (NSStringEncoding)smallestEncoding;
+- (BOOL)getBytes:(void *)bytes maxLength:(unsigned int)maxLength
+  inEncoding:(NSStringEncoding)encoding
+  allowLossesInConversion:(BOOL)allowLossesInConversion
+  fromRange:(NSRange)fromRange
+  usedRange:(NSRange *)usedRange
+  remainingRange:(NSRange *)remainingRange;
+
+/* Writing to a file */
+- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)flag;
+@end
+
+@interface NSString(NSStringCreation)
++ (id)localizedStringWithFormat:(NSString*)format,...;
++ (id)stringWithCharacters:(const unichar*)chars
+  length:(unsigned int)length;
++ (id)stringWithCharactersNoCopy:(unichar *)chars        
+  length:(unsigned int)length freeWhenDone:(BOOL)flag;
++ (id)stringWithString:(NSString *)aString;
++ (id)stringWithCString:(const char *)byteString;
++ (id)stringWithUTF8String:(const char *)byteString;
++ (NSString *)stringWithCString:(const char*)byteString
+  length:(unsigned int)length;
++ (id)stringWithCStringNoCopy:(char *)byteString
+  freeWhenDone:(BOOL)flag;
++ (NSString *)stringWithCStringNoCopy:(char *)byteString
+  length:(unsigned int)length freeWhenDone:(BOOL)flag;
++ (id)stringWithFormat:(NSString *)format,...;
++ (id)stringWithFormat:(NSString *)format arguments:(va_list)argList;
++ (id)stringWithContentsOfFile:(NSString *)path;
++ (id)stringWithContentsOfURL:(NSURL *)_url;
++ (id)string;
+@end
+
+@interface NSString(NSStringInitialization)
+- (id)init;
+- (id)initWithCharacters:(const unichar*)chars length:(unsigned int)length;
+- (id)initWithCharactersNoCopy:(unichar*)chars length:(unsigned int)length 
+  freeWhenDone:(BOOL)flag;
+- (id)initWithCString:(const char*)byteString;
+- (id)initWithUTF8String:(const char*)byteString;
+- (id)initWithBytes:(const void *)_bytes length:(unsigned)_length 
+  encoding:(NSStringEncoding)_enc;
+- (id)initWithBytesNoCopy:(void *)_bytes length:(unsigned)_length 
+  encoding:(NSStringEncoding)_enc freeWhenDone:(BOOL)_fwd;
+- (id)initWithCString:(const char*)byteString length:(unsigned int)length;
+- (id)initWithCStringNoCopy:(char*)byteString freeWhenDone:(BOOL)flag;
+- (id)initWithCStringNoCopy:(char*)byteString length:(unsigned int)length 
+  freeWhenDone:(BOOL)flag;
+- (id)initWithString:(NSString*)aString;
+- (id)initWithFormat:(NSString*)format, ...;
+- (id)initWithFormat:(NSString*)format arguments:(va_list)argList;
+- (id)initWithFormat:(NSString*)format
+  locale:(NSDictionary*)dictionary, ...;
+- (id)initWithFormat:(NSString*)format 
+  locale:(NSDictionary*)dictionary arguments:(va_list)argList;  
+- (id)initWithData:(NSData *)data encoding:(NSStringEncoding)encoding;
+- (id)initWithContentsOfFile:(NSString *)path;
+- (id)initWithContentsOfURL:(NSURL *)_url;
+@end
+
+
+/*
+ * NSMutableString
+ *
+ * primitive methods:
+ *      - characterAtIndex:
+ *      - length:
+ *      - replaceCharactersInRange:withString:
+ *      - init* as appropriate
+ */
+
+@interface NSMutableString : NSString
+/* Modifying a string */
+- (void)replaceCharactersInRange:(NSRange)aRange withString:(NSString*)aString;
+- (void)appendFormat:(NSString*)format,...;
+- (void)appendFormat:(NSString*)format arguments:(va_list)argList;
+- (void)appendString:(NSString*)aString;
+- (void)prependFormat:(NSString*)format,...;
+- (void)prependFormat:(NSString*)format arguments:(va_list)argList;
+- (void)prependString:(NSString*)aString;
+- (void)deleteCharactersInRange:(NSRange)range;
+- (void)insertString:(NSString*)aString atIndex:(unsigned)index;
+- (void)setString:(NSString*)aString;
+@end
+
+@interface NSMutableString(NSStringCreation)
++ (id)stringWithCapacity:(unsigned int)capacity;
++ (id)string;
+@end
+
+@interface NSMutableString(NSStringInitialization)
+- (id)initWithCapacity:(unsigned int)capacity;
+@end
+
+/*
+ * Additions made in GNUstep base
+ *
+ * Added to lF to support compilation of GNUstep stuff, do avoid to
+ * use such functions - they make you loose OpenStep compatibility !
+ *
+ * NOTE: apparently this was removed from gstep-base in the meantime, sigh
+ */
+
+@interface NSString(GSAdditions)
+
+- (NSString *)stringWithoutPrefix:(NSString *)_prefix;
+- (NSString *)stringWithoutSuffix:(NSString *)_suffix;
+
+- (NSString *)stringByReplacingString:(NSString *)_orignal
+  withString:(NSString *)_replacement;
+
+- (NSString *)stringByTrimmingLeadWhiteSpaces;
+- (NSString *)stringByTrimmingTailWhiteSpaces;
+- (NSString *)stringByTrimmingWhiteSpaces;
+
+- (NSString *)stringByTrimmingLeadSpaces;
+- (NSString *)stringByTrimmingTailSpaces;
+- (NSString *)stringByTrimmingSpaces;
+
+@end
+
+@interface NSMutableString(GNUstepCompatibility)
+
+- (void)trimLeadSpaces;
+- (void)trimTailSpaces;
+- (void)trimSpaces;
+
+@end
+
+/* Errors & exceptions for strings */
+
+LF_EXPORT NSString* NSStringBoundsError;
+
+/*
+ * Include header for concrete subclasses for debug info
+ */
+
+#include <Foundation/NSConcreteString.h>
+
+#endif /* __NSString_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSString.m b/libFoundation/Foundation/NSString.m
new file mode 100644 (file)
index 0000000..9420c88
--- /dev/null
@@ -0,0 +1,2790 @@
+/* 
+   NSString.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include <Foundation/common.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/NSData.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSCoder.h>
+#include <Foundation/NSURL.h>
+#include <Foundation/NSURLHandle.h>
+#include <Foundation/NSException.h>
+#include <Foundation/exceptions/StringExceptions.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+#include <Foundation/PropertyListParser.h>
+
+#include <Foundation/NSCharacterSet.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSThread.h>
+#include <Foundation/NSNotification.h>
+#include <Foundation/NSConcreteString.h>
+#include <Foundation/NSPathUtilities.h>
+#include <Foundation/NSByteOrder.h>
+
+#include "PrivateThreadData.h"
+#include "NSObject+PropLists.h"
+
+#include <locale.h>
+
+#include <netinet/in.h>
+
+int NSConvertUTF16toUTF8(unichar             **sourceStart,
+                         const unichar       *sourceEnd, 
+                         unsigned char       **targetStart,
+                         const unsigned char *targetEnd);
+int NSConvertUTF8toUTF16(unsigned char **sourceStart, unsigned char *sourceEnd, 
+                         unichar **targetStart, const unichar *targetEnd);
+
+id NSInitStringWithData(NSString *self, NSData *data,
+                        NSStringEncoding encoding);
+
+NSData *dataUsingEncoding(NSString *self,
+                          NSStringEncoding encoding, BOOL flag);
+/* 
+
+General ideas in NSString class cluster implementation
+
+The NSString class is an abstract class that uses only unicode representation
+and handles in an inefficient manner since it operates on abstract strings
+accessing characters one by one using characterAtIndex: method.
+
+Currently there is only one abstract subclass of classes designed to implement
+ANSI C strings in the default encoding provided by the operating system 
+(assumed ASCII or ASCII extension like NEXTSTEP). This type of strings are called NS8BitString since they uses characters (usually represented on 8 bits)
+for immutable classes and NSMutable8BitString for mutable ones respectively. 
+This tree of classes is implemented based on `__compact8BitBytes' method
+that returns a pointer to the internal representation of the string as char[],
+with all characters compact, with no gap.
+
+Unicode and encodings will be supported in the future when I will know
+how to handle the following (If you know about these please send me a message)
+       - convert between different encodings
+       - convert characters to upper/lower cases
+       - handle composed character sequences
+
+So for the time being only NS8BitString/NSMutable8BitString are used but their
+use in the future will be limited to ...WithCString... methods and the strings
+generated by the compiler with @"" construct (which should generate unicode 
+ones some day in the future).
+
+There is another problem: methods like initWithCharacters... and 
+initWithCString assume that the underlying support is 16Bit respectively 8Bit
+but it is sent to an instance allocated with [NSString alloc]. So we make 
+NSString alloc method to return a temporary string that will allocate and 
+initialize the concrete class that will hold the character in initWith... 
+methods. This class is NSTemporaryString. Thus one must use constructs like
+       var = [[NSString alloc] initWith...]
+       var = [NSString stringWith...]
+but not
+       var = [NSString alloc]
+       [var initWith...]
+since the second line will return an instance different from the one in var.
+
+*/
+
+#define USE_SINGLE8BITSTRING 1
+// #define HAS_UNICODE_STRING 1
+
+/***************************
+ * NSString abstract class
+ ***************************/
+
+#if USE_SINGLE8BITSTRING 
+static id Single8BitStringStore[256];
+static Class Single8BitStringClass = Nil;
+
+static inline id _getSingle8BitString(unsigned char _byte) {
+    register id str;
+    
+    if (Single8BitStringClass == Nil) {
+        Single8BitStringClass = [NSCharacter8BitString class];
+        memset(Single8BitStringStore, 0, sizeof(Single8BitStringStore));
+    }
+    
+    if ((str = Single8BitStringStore[(int)_byte]) == nil) {
+        str = [[Single8BitStringClass allocWithZone:nil]
+                                      initWithCString:(char *)&_byte length:1];
+        Single8BitStringStore[(unsigned int)_byte] = str;
+#if DEBUG && 0
+        printf("%s: add str[%p] for char %c\n", __PRETTY_FUNCTION__,
+               str, _byte);
+#endif
+    }
+    return str;
+}
+#endif
+
+@implementation NSString
+
+static Class NSStringClass = Nil;
+
++ (void)initialize
+{
+    const char *cstr;
+
+    if (NSStringClass == Nil)
+        NSStringClass = [NSString class];
+
+#ifndef __WIN32__
+    /* required for toupper/tolower to work with umlauts */
+    if ((cstr = getenv("LC_CTYPE")))
+        setlocale(LC_CTYPE, cstr);
+    if ((cstr = getenv("LC_COLLATE")))
+        setlocale(LC_COLLATE, cstr);
+#endif
+    
+    NSUserName();
+}
+
+/* Getting a string's length */
+
+- (unsigned int)length
+{
+    [self subclassResponsibility:_cmd];
+    return 0;
+}
+
+/* Accessing characters        */
+
+- (unichar)characterAtIndex:(unsigned int)index
+{
+    [self subclassResponsibility:_cmd];
+    return 0;
+}
+
+- (void)getCharacters:(unichar*)buffer
+{
+    NSRange range = {0, [self length]};
+    [self getCharacters:buffer range:range];
+}
+
+- (void)getCharacters:(unichar *)buffer range:(NSRange)aRange
+{
+    register unsigned int i = 0;
+    IMP imp = [self methodForSelector:@selector(characterAtIndex:)];
+
+    if (aRange.location + aRange.length > [self length]) {
+       [[[IndexOutOfRangeException alloc] 
+           initWithFormat:@"range (%d,%d) in string %x of length %d",
+               aRange.location, aRange.length, self, [self length]] raise];
+    }
+    
+    for (i = 0; i < aRange.length; i++) {
+       buffer[i] = (unichar)(long)(*imp)(self, @selector(characterAtIndex:), 
+           aRange.location + i);
+    }
+}
+
+/* Combining strings */        
+
+- (NSString *)stringByAppendingString:(NSString *)aString
+{
+    unichar  *buf;
+    unsigned len1, len2;
+    NSString *s;
+    
+    len1 = [self length];
+    len2 = [aString length];
+    
+    if (len2 == 0)
+       return [[self copy] autorelease];
+    
+    buf = calloc(len1 + len2 + 1, sizeof(unichar));
+    [self    getCharacters:buf];
+    [aString getCharacters:&(buf[len1])];
+    buf[len1 + len2] = 0;
+    s = [NSStringClass stringWithCharacters:buf length:(len1 + len2)];
+    free(buf);
+    return s;
+}
+
+- (NSString*)stringByAppendingFormat:(NSString*)format,...
+{
+    NSMutableString *string = [self mutableCopy];
+    va_list va;
+    
+    va_start(va, format);
+    [string appendFormat:format arguments:va];
+    va_end(va);
+    return AUTORELEASE(string);
+}
+
+- (NSString*)stringByAppendingFormat:(NSString*)format 
+  arguments:(va_list)argList
+{
+    NSMutableString *string = [self mutableCopy];
+
+    [string appendFormat:format arguments:argList];
+    return AUTORELEASE(string);
+}
+
+- (NSString*)stringByPrependingString:(NSString*)aString
+{
+    return [aString stringByAppendingString:self];
+}
+
+- (NSString*)stringByPrependingFormat:(NSString*)format,...
+{
+    NSString *string;
+    va_list va;
+
+    va_start(va, format);
+    string = Avsprintf(format, va);
+    va_end(va);
+
+    return [string stringByAppendingString:self];
+}
+
+- (NSString*)stringByPrependingFormat:(NSString*)format 
+  arguments:(va_list)argList
+{
+    NSString *string = Avsprintf(format, argList);
+
+    return [string stringByAppendingString:self];
+}
+
+/* Dividing strings */
+
+- (NSArray *)componentsSeparatedByString:(NSString *)separator
+{
+    unsigned int first = 0, last = 0;
+    unsigned int slen;
+    NSMutableArray *components;
+
+    if ((slen = [separator length]) == 0)
+        return [NSArray arrayWithObject:self];
+
+    if ([self length] == 0)
+        return [NSArray arrayWithObject:self];
+    
+    components = [NSMutableArray arrayWithCapacity:16];
+
+    while ((first = [self indexOfString:separator fromIndex:last]) !=NSNotFound) {
+       NSRange  range;
+        NSString *substring;
+
+        range.location = last;
+        range.length   = (first - last);
+        substring = [self substringWithRange:range];
+
+       [components addObject:substring];
+       last = first + slen;
+    }
+    
+    if ([self length] >= last) {
+       NSString *lastComponent;
+        
+        lastComponent = [self substringFromIndex:last];
+       [components addObject:lastComponent];
+    }
+    return components;
+}
+
+- (NSString *)substringWithRange:(NSRange)aRange
+{
+    unichar * buf;
+    id rc;
+
+    if (aRange.location + aRange.length > [self length] )
+       [[[IndexOutOfRangeException alloc]
+           initWithFormat:@"range (%d,%d) in string %x of length %d",
+               aRange.location, aRange.length, self, [self length]] raise];
+
+    if (aRange.length == 0)
+       return @"";
+
+    buf = MallocAtomic(sizeof(unichar) * (aRange.length + 1));
+    [self getCharacters:buf range:aRange];
+    rc = AUTORELEASE([[NSStringClass alloc]
+                           initWithCharactersNoCopy:buf
+                           length:aRange.length
+                           freeWhenDone:YES]);
+    return rc;
+}
+
+- (NSString *)substringFromRange:(NSRange)aRange
+{
+    return [self substringWithRange:aRange];
+}
+
+- (NSString *)substringFromIndex:(unsigned int)index
+{
+    NSRange range;
+    
+    range.location = index;
+    range.length   = [self length]; //- index
+    if (range.length < index) {
+       [[[IndexOutOfRangeException alloc] 
+           initWithFormat:@"index %d in string %x of length %d",
+               index, self, [self length]] raise];
+    }
+    range.length -= index;
+    
+    return [self substringWithRange:range];
+}
+
+- (NSString*)substringToIndex:(unsigned int)index
+{
+    NSRange range = {0, index};
+
+    return [self substringWithRange:range];
+}
+
+- (NSString *)stringByTrimmingCharactersInSet:(NSCharacterSet *)_set
+{
+    unsigned len;
+    unichar  *buf;
+    unsigned idx;
+    unsigned ridx;
+    BOOL (*isMem)(id,SEL,unichar);
+    
+    if ((len = [self length]) == 0)
+        return [[self copy] autorelease];
+       
+    buf = calloc(len + 1, sizeof(unichar));
+    [self getCharacters:buf];
+    
+    isMem = (void *)[_set methodForSelector:@selector(characterIsMember:)];
+    
+    for (idx = 0; 
+        (idx < len) && isMem(_set,@selector(characterIsMember:),buf[idx]); 
+        idx++)
+       ;
+    for (ridx = len-1; 
+        (ridx >= idx) && isMem(_set,@selector(characterIsMember:),buf[ridx]);
+        ridx--)
+       ;
+    
+    self = [NSStringClass stringWithCharacters:&(buf[idx]) 
+                         length:((ridx+1) - idx)];
+    free(buf);
+    return self;
+}
+
+/* Finding characters and substrings */
+
+- (NSRange)rangeOfCharacterFromSet:(NSCharacterSet*)aSet
+{
+    NSRange range = {0, [self length]};
+
+    return [self rangeOfCharacterFromSet:aSet options:0 range:range];
+}
+
+- (NSRange)rangeOfCharacterFromSet:(NSCharacterSet*)aSet
+  options:(unsigned int)mask
+{
+    NSRange range = {0, [self length]};
+
+    return [self rangeOfCharacterFromSet:aSet options:mask range:range];
+}
+
+- (NSRange)rangeOfCharacterFromSet:(NSCharacterSet*)aSet
+  options:(unsigned int)mask range:(NSRange)aRange
+{
+    // UNICODE 
+    // ENCODINGS - this code applies to the system's default encoding
+    SEL characterIsMemberSel = @selector(characterIsMember:);
+    IMP imp = [aSet methodForSelector:characterIsMemberSel];
+
+    if (NSMaxRange(aRange) > [self length])
+       [[[IndexOutOfRangeException alloc]
+           initWithFormat:@"range %@ not in string 0x%08x of length %d",
+           NSStringFromRange(aRange), self, [self length]] raise];
+
+    if (mask & NSBackwardsSearch) {
+        int i;
+        
+       for (i = aRange.length - 1; i >= aRange.location; i--) {
+           unichar c = [self characterAtIndex:i];
+
+           if ((*imp)(aSet, characterIsMemberSel, c) ||
+               ((mask & NSCaseInsensitiveSearch)
+                && ((islower(c)
+                     && (*imp)(aSet, characterIsMemberSel, toupper(c)))
+                    || (isupper(c)
+                        && (*imp)(aSet, characterIsMemberSel, tolower(c)))))) {
+               return NSMakeRange(i, 1);
+           }
+       }
+    }
+    else {
+        unsigned int i, max;
+        max = NSMaxRange(aRange);
+       for (i = aRange.location; i < max; i++) {
+           unichar c = [self characterAtIndex:i];
+
+           if ((*imp)(aSet, characterIsMemberSel, c) ||
+               ((mask & NSCaseInsensitiveSearch) &&
+                ((islower(c)
+                 && (*imp)(aSet, characterIsMemberSel, toupper(c)))
+                || (isupper(c)
+                    && (*imp)(aSet, characterIsMemberSel, tolower(c)))))) {
+               return NSMakeRange(i, 1);
+           }
+       }
+    }
+
+    return NSMakeRange(NSNotFound, 0);
+}
+
+- (NSRange)rangeOfString:(NSString*)string
+{
+    NSRange range = {0, [self length]};
+
+    return [self rangeOfString:string options:0 range:range];
+}
+
+- (NSRange)rangeOfString:(NSString*)string options:(unsigned int)mask
+{
+    NSRange range = {0, [self length]};
+
+    return [self rangeOfString:string options:mask range:range];
+}
+
+- (NSRange)rangeOfString:(NSString*)aString
+  options:(unsigned int)mask range:(NSRange)aRange
+{
+    // UNICODE 
+    // ENCODINGS - this code applies to the system's default encoding
+    // islower needs to be replaced with proper NSCharacterSet calls (speed?)
+    unsigned int i, a;
+    NSRange range;
+
+    if (aRange.location + aRange.length > [self length]) {
+       [[[IndexOutOfRangeException alloc]
+           initWithFormat:@"range (%d,%d) in string %x of length %d",
+               aRange.location, aRange.length, self, [self length]] raise];
+    }
+    
+    a = [aString length];
+    
+    if (a == 0 || aRange.length < a)
+       return NSMakeRange(0,0);
+
+    if (mask & NSAnchoredSearch)  {
+       range.location = aRange.location +
+           ((mask & NSBackwardsSearch) ? aRange.length - a : 0);
+       range.length = a;
+       
+       if ([self compare:aString options:mask range:range] == NSOrderedSame)
+           return range;
+       else
+           return NSMakeRange(NSNotFound, 0);
+    }
+
+    if (mask & NSBackwardsSearch) {    
+       if (mask & NSCaseInsensitiveSearch) {
+           // Backward case insensitive
+           unichar cf;
+            int n;
+            
+            cf = [aString characterAtIndex: 0 ];
+           cf = islower(cf) ? toupper(cf) : cf;
+           for (n = aRange.length - a; n >= 0; n--) {
+               unichar ca = cf;
+               unichar cm = [self characterAtIndex:n + aRange.location ];
+
+               cm = islower(cm) ? toupper(cm) : cm;
+
+               if (cm != ca)
+                   continue;
+               for (i = 1; i < a; i++) {
+                   cm = [self characterAtIndex:n + i + aRange.location ];
+                   ca = [aString characterAtIndex:i];
+                   cm = islower(cm) ? toupper(cm) : cm;
+                   ca = islower(ca) ? toupper(ca) : ca;
+                   if (cm != ca)
+                       break;
+               }
+               if (i == a) {
+                   range.location = aRange.location + n;
+                   range.length = a;
+                   return range;
+               }
+           }
+       }
+       else {
+           // Backward case sensitive
+            int n;
+            
+           for (n = aRange.length - a; n >= 0; n--) {
+               if ([self characterAtIndex:n + aRange.location]
+                       != [aString characterAtIndex:0])
+                   continue;
+               for (i = 1; i < a; i++)
+                   if ([self characterAtIndex:(n + i + aRange.location)]
+                           != [aString characterAtIndex: i] )
+                       break;
+               if (i == a) {
+                   range.location = aRange.location + n;
+                   range.length = a;
+                   return range;
+               }
+           }
+       }
+    }
+    else {
+       if (mask & NSCaseInsensitiveSearch) {
+           // Forward case insensitive
+            unsigned int n;
+           unichar      cf;
+            
+            cf = [aString characterAtIndex: n];
+           cf = islower(cf) ? toupper(cf) : cf;
+           for (n = 0; n + a <= aRange.length; n++) {
+               unichar ca = cf;
+               unichar cm = [self characterAtIndex: n + aRange.location ];
+
+               cm = islower(cm) ? toupper(cm) : cm;
+               
+               if (cm != ca)
+                   continue;
+               for (i = 1; i < a; i++) {
+                   cm = [self characterAtIndex:n + i + aRange.location];
+                   ca = [aString characterAtIndex:i];
+                   cm = islower(cm) ? toupper(cm) : cm;
+                   ca = islower(ca) ? toupper(ca) : ca;
+                   if (cm != ca)
+                       break;
+               }
+               if (i == a) {
+                   range.location = aRange.location + n;
+                   range.length = a;
+                   return range;
+               }
+           }
+       }
+       else {
+           // Forward case sensitive
+            unsigned int n;
+           for (n = 0; n + a <= aRange.length; n++) {
+               if ([self characterAtIndex:n + aRange.location]
+                       != [aString characterAtIndex: 0] )
+                   continue;
+               for (i = 1; i < a; i++)
+                   if ([self characterAtIndex:n + i + aRange.location]
+                           != [aString characterAtIndex:i])
+                       break;
+               if (i == a) {
+                   range.location = aRange.location + n;
+                   range.length = a;
+                   return range;
+               }
+           }
+       }
+    }
+    
+    range.location = NSNotFound;
+    range.length   = 0;
+    return range;
+}
+
+- (unsigned int)indexOfString:(NSString *)substring
+{
+    NSRange range = {0, [self length]};
+    
+    range = [self rangeOfString:substring options:0 range:range];
+    return range.length ? range.location : NSNotFound;
+}
+
+- (unsigned int)indexOfString:(NSString*)substring fromIndex:(unsigned)index
+{
+    NSRange range = {index, [self length]-index};
+    
+    range = [self rangeOfString:substring options:0 range:range];
+    return range.length ? range.location : NSNotFound;
+}
+
+- (unsigned int)indexOfString:(NSString*)substring range:(NSRange)range
+{
+    range = [self rangeOfString:substring options:0 range:range];
+    return range.length ? range.location : NSNotFound;
+}
+
+/* Determining composed character sequences */
+
+- (NSRange)rangeOfComposedCharacterSequenceAtIndex:(unsigned int)anIndex
+{
+    NSRange range;
+    unsigned int length = [self length];
+    
+    if (anIndex >= length) {
+       [[[IndexOutOfRangeException alloc] 
+           initWithFormat:@"index %d out of range in string %x of length %d",
+               anIndex, self, length] raise];
+    }
+    // UNICODE
+    range.location = anIndex;
+    range.length = 1;
+    return range;
+}
+
+/* Converting string contents into a property list */
+
+- (id)propertyList
+{
+    return NSParsePropertyListFromString(self);
+}
+
+- (NSMutableDictionary*)propertyListFromStringsFileFormat
+{
+    return NSParseStringsFromString(self);
+}
+
+/* Identifying and comparing strings */
+
+- (NSComparisonResult)caseInsensitiveCompare:(NSString*)aString
+{
+    NSRange range = {0, [self length]};
+    
+    return [self compare:aString options:NSCaseInsensitiveSearch range:range];
+}
+
+- (NSComparisonResult)compare:(id)aString
+{
+    NSRange range = {0, [self length]};
+    
+    return [self compare:aString options:0 range:range];
+}
+
+- (NSComparisonResult)compare:(NSString*)aString options:(unsigned int)mask
+{
+    NSRange range = {0, [self length]};
+    
+    return [self compare:aString options:mask range:range];
+}
+
+- (NSComparisonResult)compare:(NSString*)aString
+  options:(unsigned int)mask range:(NSRange)aRange
+{
+    // UNICODE
+    // ENCODINGS - this code applies to the system's default encoding
+    unsigned int i, n, a;
+
+    if (NSMaxRange(aRange) > [self length]) {
+      [[[IndexOutOfRangeException alloc] initWithFormat:@"range %@ in string %x of length %d",
+               NSStringFromRange(aRange), self, [self length]] raise];
+    }
+    
+    a = [aString length];
+    n = MIN(a, aRange.length);
+
+    if (mask & NSCaseInsensitiveSearch) {
+      for (i = 0; i < n; i++) {
+             unichar cm = [self characterAtIndex:i + aRange.location];
+             unichar ca = [aString characterAtIndex:i];
+
+             cm = islower(cm) ? toupper(cm) : cm;
+             ca = islower(ca) ? toupper(ca) : ca;
+
+             if (cm < ca)
+               return NSOrderedAscending;
+             if (cm > ca)
+               return NSOrderedDescending;
+      }
+    }
+    else {
+      for (i = 0; i < n; i++) {
+        if ([self characterAtIndex:i + aRange.location] <
+            [aString characterAtIndex:i])
+          return NSOrderedAscending;
+        if ([self characterAtIndex:i + aRange.location] >
+            [aString characterAtIndex:i])
+          return NSOrderedDescending;
+      }
+    }
+
+    if (aRange.length < a)
+      return NSOrderedAscending;
+    if (aRange.length > a)
+      return NSOrderedDescending;
+
+    return NSOrderedSame;
+}
+
+- (BOOL)hasPrefix:(NSString *)aString
+{
+    int mLen = [self length];
+    int aLen = [aString length];
+    NSRange range = {0, aLen};
+
+#if DEBUG
+    if (aString == nil) {
+       NSLog(@"NOTE: [%@ hasPrefix:nil] does not work on MacOSX !", aString);
+#if 0 && DEBUG
+#  warning ABORT CODE ENABLED - do not deploy!
+       abort();
+#endif
+    }
+#endif
+    
+    if (aLen == 0)
+        return NO;
+    
+    if (aLen > mLen)
+       return NO;
+    
+    return [self compare:aString options:0 range:range] == NSOrderedSame;
+}
+
+- (BOOL)hasSuffix:(NSString*)aString
+{
+    int mLen = [self length];
+    int aLen = [aString length];
+    NSRange range = {mLen-aLen, aLen};
+    
+    if (aLen == 0)
+        return NO;
+    
+    if (aLen > mLen)
+       return NO;
+    
+    return [self compare:aString options:0 range:range] == NSOrderedSame;
+}
+
+- (BOOL)isEqual:(id)aString
+{
+    register Class clazz;
+    register BOOL  i;
+    NSRange range;
+    
+    if (self == aString)
+       return YES;
+    else if (aString == nil)
+       return NO;
+    
+    if (NSStringClass == Nil)
+        NSStringClass = [NSString class];
+    
+    i = NO;
+    for (clazz = *(id *)aString; clazz; clazz = class_get_super_class(clazz)) {
+       if (clazz == NSStringClass) {
+           i = YES;
+           break;
+       }
+    }
+    if (i == NO)
+       return NO;
+    
+    range.location = 0;
+    range.length   = [self length];
+    return [self compare:aString options:0 range:range] == NSOrderedSame;
+}
+
+- (BOOL)isEqualToString:(NSString*)aString
+{
+    NSRange range;
+    
+    if (self == aString)
+       return YES;
+    else if (aString == nil)
+       return NO;
+    
+    range.location = 0;
+    range.length   = [self length];
+    return [self compare:aString options:0 range:range] == NSOrderedSame;
+}
+
+- (unsigned)hash
+{
+    unsigned hash = 0, hash2;
+    int i, n = [self length];
+
+    for(i = 0; i < n; i++) {
+        hash <<= 4;
+       // UNICODE - must use a for independent of composed characters
+        hash += [self characterAtIndex:i];
+        if((hash2 = hash & 0xf0000000))
+            hash ^= (hash2 >> 24) ^ hash2;
+    }
+
+    return hash;
+}
+
+/* Getting a shared prefix */
+
+- (NSString *)commonPrefixWithString:(NSString*)aString
+  options:(unsigned int)mask
+{
+    NSRange range = {0, 0};
+    int mLen;
+    int aLen;
+    int i;
+    
+    mLen = [self    length];
+    aLen = [aString length];
+    if ((mLen == 0) || (aLen == 0)) return @"";
+    
+    for (i = 0; (i < mLen) && (i < aLen); i++) {
+       unichar c1, c2;
+        
+        c1 = [self characterAtIndex:i];
+        c2 = [self characterAtIndex:i];
+        
+        if (mask & NSCaseInsensitiveSearch) {
+            // ENCODINGS - this code applies to the system's default encoding
+            c1 = tolower(c1);
+            c2 = tolower(c2);
+        }
+        
+        if (c1 != c2)
+            break;
+    }
+    
+    range.length = i;
+    return [self substringWithRange:range];
+}
+
+/* Changing case */
+
+- (NSString *)capitalizedString
+{
+    // UNICODE
+    // ENCODINGS - this code applies to the system's default encoding
+    int i;
+    BOOL f = YES;
+    int length = [self cStringLength];
+    unichar* buf = MallocAtomic(sizeof(unichar) * (length + 1));
+
+    for (i = 0; i < length; i++) {
+       unichar c = [self characterAtIndex:i];
+
+       if (isspace(c))
+           f = YES;
+
+       if (f) {
+           buf[i] = islower(c) ? toupper(c) : c;
+           f = NO;
+       }
+       else
+           buf[i] = isupper(c) ? tolower(c) : c;
+    }
+    buf[i] = 0;
+
+    return AUTORELEASE([[NSStringClass alloc]
+                             initWithCharactersNoCopy:buf
+                             length:length
+                             freeWhenDone:YES]);
+}
+
+- (NSString *)lowercaseString
+{
+    // UNICODE
+    // ENCODINGS - this code applies to the system's default encoding
+    int i;
+    int length = [self cStringLength];
+    unichar* buf = MallocAtomic(sizeof(unichar) * (length+1));
+
+    for (i = 0; i < length; i++) {
+       unichar c = [self characterAtIndex:i];
+        
+       buf[i] = isupper(c) ? tolower(c) : c;
+    }
+    buf[i] = 0;
+
+    return AUTORELEASE([[NSStringClass alloc]
+                             initWithCharactersNoCopy:buf
+                             length:length
+                             freeWhenDone:YES]);
+}
+
+- (NSString *)uppercaseString
+{
+    // UNICODE
+    // ENCODINGS - this code applies to the system's default encoding
+    int i;
+    int length = [self cStringLength];
+    unichar* buf = MallocAtomic(sizeof(unichar) * (length+1));
+
+    for (i = 0; i < length; i++) {
+       unichar c = [self characterAtIndex:i];
+       buf[i] = islower(c) ? toupper(c) : c;
+    }
+
+    buf[i] = 0;
+
+    return AUTORELEASE([[NSStringClass alloc]
+                             initWithCharactersNoCopy:buf
+                             length:length
+                             freeWhenDone:YES]);
+}
+
+/* Getting C strings */
+
+- (const char *)cString
+{
+    // UNICODE
+    // ENCODINGS
+    [self subclassResponsibility:_cmd];
+    return NULL;
+}
+
+- (unsigned int)cStringLength
+{
+    // UNICODE
+    // ENCODINGS
+    [self subclassResponsibility:_cmd];
+    return 0;
+}
+
+- (const char *)UTF8String
+{
+    NSData        *d;
+    unsigned      dlen;
+    unsigned char *cstr;
+    
+    if ((d = [self dataUsingEncoding:NSUTF8StringEncoding]) == nil)
+        return NULL;
+    
+    if ((dlen = [d length]) == 0) {
+        static unsigned char c = '\0';
+        return (const char *)&c;
+    }
+    
+    cstr = NSZoneMallocAtomic([self zone], sizeof(unsigned char) * (dlen + 1));
+    [d getBytes:cstr];
+    cstr[dlen] = '\0';
+#if !LIB_FOUNDATION_BOEHM_GC
+    [NSAutoreleasedPointer autoreleasePointer:cstr];
+#endif
+    return (const char *)cstr;
+}
+
+- (void)getCString:(char *)buffer
+{
+    NSRange range = {0, [self length]};
+    
+    [self getCString:buffer maxLength:NSMaximumStringLength
+          range:range remainingRange:NULL];
+    buffer[range.length] = '\0';
+}
+
+- (void)getCString:(char*)buffer maxLength:(unsigned int)maxLength
+{
+    NSRange range = {0, [self length]};
+    
+    [self getCString:buffer maxLength:maxLength
+          range:range remainingRange:NULL];
+    buffer[range.length] = '\0';
+}
+
+- (void)getCString:(char*)buffer maxLength:(unsigned int)maxLength
+  range:(NSRange)aRange remainingRange:(NSRange*)leftoverRange
+{
+    unsigned int toMove, i, cLength;
+    unichar (*charAtIndex)(id,SEL,int);
+
+    charAtIndex = (void*)[self methodForSelector:@selector(characterAtIndex:)];
+    
+    toMove  = MIN(maxLength, aRange.length);
+    cLength = [self cStringLength];
+    
+    if (aRange.location + aRange.length > cLength) {
+       [[[IndexOutOfRangeException alloc]
+           initWithFormat:@"range (%d,%d) in string %x of length %d",
+               aRange.location, aRange.length, self, cLength] raise];
+    }
+
+    if (leftoverRange) {
+       leftoverRange->location = aRange.location + toMove;
+       leftoverRange->length = cLength - leftoverRange->location;
+    }
+    for (i = 0; i < toMove; i++) {
+        buffer[i] = charAtIndex(self, @selector(characterAtIndex:),
+                                aRange.location + i);
+    }
+    if (toMove < maxLength)
+       buffer[toMove] = '\0';
+}
+
+/* Getting numeric values */
+
+- (double)doubleValue
+{
+    // UNICODE
+    // ENCODINGS
+    double   val = 0.0;
+    unsigned len;
+    char     *str;
+    
+    len = [self cStringLength];
+    if (len == 0)
+        return 0.0;
+    if ((str = malloc(len + 1)) == NULL)
+        return 0.0;
+    
+    [self getCString:str]; str[len] = '\0';
+    sscanf(str ? str : "", " %lf ", &val);
+    free(str);
+    return val;
+}
+
+- (float)floatValue
+{
+    // UNICODE
+    // ENCODINGS
+    float    val = 0;
+    unsigned len;
+    char     *str;
+    
+    if ((len = [self cStringLength]) == 0)
+        return 0.0;
+    if ((str = malloc(len + 1)) == NULL)
+        return 0.0;
+    
+    [self getCString:str]; str[len] = '\0';
+    sscanf(str ? str : "", " %f ", &val);
+    free(str);
+    return val;
+}
+
+- (int)intValue
+{
+    // UNICODE
+    // ENCODINGS
+    int      val = 0;
+    unsigned len;
+    char     *str;
+    
+    if ((len = [self cStringLength]) == 0)
+        return 0;
+    if ((str = malloc(len + 1)) == NULL)
+        return 0;
+    [self getCString:str]; str[len] = '\0';
+    sscanf(str ? str : "", " %d ", &val);
+    free(str);
+    return val;
+}
+
+/* Working with encodings */
+
++ (NSStringEncoding *)availableStringEncodings
+{
+    // UNICODE
+    // ENCODINGS
+    static NSStringEncoding availableEncodings[] = {
+       NSASCIIStringEncoding,
+        NSISOLatin1StringEncoding,
+        NSISOLatin9StringEncoding,
+        NSUTF8StringEncoding,
+        NSUnicodeStringEncoding,
+       0
+    };
+    
+    return availableEncodings;
+}
+
++ (NSStringEncoding)defaultCStringEncoding
+{
+    // UNICODE
+    // ENCODINGS
+#if USE_LATIN9
+    return NSISOLatin9StringEncoding;
+#else
+    return NSISOLatin1StringEncoding;
+#endif
+}
+
++ (NSString *)localizedNameOfStringEncoding:(NSStringEncoding)encoding
+{
+    switch(encoding) {
+       case NSASCIIStringEncoding:     return @"NSASCIIStringEncoding";
+       case NSNEXTSTEPStringEncoding:  return @"NSNEXTSTEPStringEncoding";
+       case NSUTF8StringEncoding:      return @"NSUTF8StringEncoding";
+       case NSISOLatin1StringEncoding: return @"NSISOLatin1StringEncoding";
+       case NSISOLatin9StringEncoding: return @"NSISOLatin9StringEncoding";
+       case NSSymbolStringEncoding:    return @"NSSymbolStringEncoding";
+       case NSShiftJISStringEncoding:  return @"NSShiftJISStringEncoding";
+       case NSISOLatin2StringEncoding: return @"NSISOLatin2StringEncoding";
+       case NSUnicodeStringEncoding:   return @"NSUnicodeStringEncoding";
+       case NSWinLatin1StringEncoding: return @"NSWinLatin1StringEncoding";
+        case NSISO2022JPStringEncoding: return @"NSISO2022JPStringEncoding";
+
+        case NSWindowsCP1251StringEncoding:
+           return @"NSWindowsCP1251StringEncoding";
+        case NSWindowsCP1252StringEncoding:
+           return @"NSWindowsCP1252StringEncoding";
+        case NSWindowsCP1253StringEncoding:
+           return @"NSWindowsCP1253StringEncoding";
+        case NSWindowsCP1254StringEncoding:
+           return @"NSWindowsCP1254StringEncoding";
+        case NSWindowsCP1250StringEncoding:
+           return @"NSWindowsCP1250StringEncoding";
+           
+       case NSNonLossyASCIIStringEncoding:
+           return @"NSNonLossyASCIIStringEncoding";
+       case NSJapaneseEUCStringEncoding:
+           return @"NSJapaneseEUCStringEncoding";
+       case NSAdobeStandardCyrillicStringEncoding:
+           return @"NSAdobeStandardCyrillicStringEncoding";
+       default: 
+           return @"Invalid encoding";
+    }
+}
+
+- (BOOL)canBeConvertedToEncoding:(NSStringEncoding)encoding
+{
+    id data;
+    data = [self dataUsingEncoding:encoding allowLossyConversion:NO];
+    return data ? YES : NO;
+}
+
+- (NSData *)dataUsingEncoding:(NSStringEncoding)encoding
+{
+    return [self dataUsingEncoding:encoding allowLossyConversion:NO];
+}
+
+- (NSData *)dataUsingEncoding:(NSStringEncoding)encoding
+  allowLossyConversion:(BOOL)flag
+{
+    return dataUsingEncoding(self, encoding, flag);
+}
+
+- (NSStringEncoding)fastestEncoding
+{
+    // UNICODE
+    // ENCODINGS
+    return NSISOLatin1StringEncoding;
+}
+
+- (NSStringEncoding)smallestEncoding
+{
+    // UNICODE
+    // ENCODINGS
+    return NSISOLatin1StringEncoding;
+}
+
+- (BOOL)getBytes:(void*)bytes maxLength:(unsigned int)maxLength
+  inEncoding:(NSStringEncoding)encoding
+  allowLossesInConversion:(BOOL)allowLossesInConversion
+  fromRange:(NSRange)fromRange
+  usedRange:(NSRange*)usedRange
+  remainingRange:(NSRange*)remainingRange
+{
+    // UNICODE
+    // ENCODINGS
+    [self notImplemented:_cmd];
+    return NO;
+}
+
+/* Writing to a file */
+
+- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)flag
+{
+    // UNICODE - remove this
+    NSData *data;
+    data = [self dataUsingEncoding:[NSStringClass defaultCStringEncoding]];
+    //data = [NSData dataWithBytes:[self cString] length:[self length]];
+    return writeToFile(path, data, flag);
+}
+
+/* Encoding methods */
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+    int     length;
+    unichar *buf;
+    
+    length = [self length];
+    buf    = MallocAtomic(sizeof(unichar) * length);
+    
+    [self getCharacters:buf];
+    [aCoder encodeValueOfObjCType:@encode(int)     at:&length];
+    [aCoder encodeArrayOfObjCType:@encode(unichar) count:length at:buf];
+    lfFree(buf);
+}
+
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+    unichar* buf;
+    int length;
+
+    [aDecoder decodeValueOfObjCType:@encode(int) at:&length];
+    buf = MallocAtomic (sizeof(unichar) * length);
+    [aDecoder decodeArrayOfObjCType:@encode(unichar) count:length at:buf];
+
+    self = AUTORELEASE(self);
+    return [self initWithCharactersNoCopy:buf
+                 length:length
+                 freeWhenDone:YES];
+}
+
+/* NSCopying methods */
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    if (NSStringClass == Nil)
+        NSStringClass = [NSString class];
+    
+    return RETAIN(self);
+    // return [[NSStringClass allocWithZone:zone] initWithString:self];
+}
+
+/* NSMutableCopying methods */
+
+- (id)mutableCopyWithZone:(NSZone*)zone
+{
+    return [[NSMutableString allocWithZone:zone] initWithString:self];
+}
+
+/* NSObject protocol */
+
+- (NSString *)stringRepresentation
+{
+    /*
+      an implementation of this method must quote the string for
+      use in property lists.
+    */
+    return [self subclassResponsibility:_cmd];
+}
+
+- (NSString *)description
+{
+    return self;
+}
+
+@end /* NSString */
+
+/*********************************
+ * NSMutableString abstract class
+ *********************************/
+
+@implementation NSMutableString
+
+/*
+ * Modifying a string 
+ */
+
+- (void)appendFormat:(NSString*)format,...
+{
+    va_list va;
+
+    va_start(va, format);
+    [self appendFormat:format arguments:va];
+    va_end(va);
+}
+
+- (void)appendFormat:(NSString*)format arguments:(va_list)argList;
+{
+    // FIX : Vsprinf(self, format, argList)
+    [self appendString:Avsprintf(format, argList)];
+}
+
+- (void)appendString:(NSString*)aString
+{
+    NSRange range = {[self length], 0};
+
+    [self replaceCharactersInRange:range withString:aString];
+}
+
+- (void)prependFormat:(NSString*)format,...
+{
+    NSRange range = {0, 0};
+    va_list va;
+
+    va_start(va, format);
+    [self replaceCharactersInRange:range
+       withString:Avsprintf(format, va)];
+    va_end(va);
+}
+
+- (void)prependFormat:(NSString*)format arguments:(va_list)argList
+{
+    NSRange range = {0, 0};
+
+    [self replaceCharactersInRange:range
+       withString:Avsprintf(format, argList)];
+}
+
+- (void)prependString:(NSString*)aString
+{
+    NSRange range = {0, 0};
+
+    [self replaceCharactersInRange:range withString:aString];
+}
+
+- (void)deleteCharactersInRange:(NSRange)range
+{
+    [self replaceCharactersInRange:range withString:nil];
+}
+
+- (void)insertString:(NSString*)aString atIndex:(unsigned)index
+{
+    NSRange range = {index, 0};
+
+    [self replaceCharactersInRange:range withString:aString];
+}
+
+- (void)setString:(NSString*)aString
+{
+    NSRange range = {0, [self length]};
+
+    [self replaceCharactersInRange:range withString:aString];
+}
+
+- (void)replaceCharactersInRange:(NSRange)aRange
+  withString:(NSString*)aString
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    if (NSStringClass == Nil)
+        NSStringClass = [NSString class];
+    return [[NSStringClass allocWithZone:zone] initWithString:self];
+}
+
+@end /* NSMutableString */
+
+/*********************************
+ * NSString creation methods
+ *********************************/
+
+@implementation NSString(NSStringCreation)
+
++ (id)allocWithZone:(NSZone *)zone
+{
+    static Class NSTemporaryStringClass = Nil;
+    if (NSStringClass == Nil)
+        NSStringClass = [NSString class];
+    if (NSTemporaryStringClass == Nil)
+        NSTemporaryStringClass = [NSTemporaryString class];
+    
+    return (self == NSStringClass) ? 
+       [NSTemporaryStringClass allocWithZone:zone] 
+       : NSAllocateObject(self, 0, zone);
+}
+
++ (id)localizedStringWithFormat:(NSString*)format,...
+{
+    va_list va;
+    NSString* string;
+    
+    va_start(va, format);
+    string = AUTORELEASE([[self alloc] initWithFormat:format arguments:va]);
+    va_end(va);
+    return string;
+}
+
++ (id)string
+{
+    return @"";
+}
+
++ (id)stringWithCharacters:(const unichar*)chars
+  length:(unsigned int)length
+{
+    return AUTORELEASE([[self alloc] initWithCharacters:chars length:length]);
+}
+
++ (id)stringWithCharactersNoCopy:(unichar*)chars       
+  length:(unsigned int)length freeWhenDone:(BOOL)flag
+{
+    return AUTORELEASE([[self alloc] initWithCharactersNoCopy:chars 
+                                     length:length freeWhenDone:flag]);
+}
+
++ (id)stringWithString:(NSString*)aString
+{
+    return [self stringWithCString:[aString cString]];
+}
+
++ (id)stringWithCString:(const char*)byteString
+{
+    return AUTORELEASE([[self alloc] initWithCString:byteString]);
+}
+
++ (id)stringWithUTF8String:(const char *)bytes
+{
+    register unsigned char *p;
+    for (p = (unsigned char *)bytes; *p; p++) {
+        if (*p > 127)
+            return AUTORELEASE([[self alloc] initWithUTF8String:bytes]);
+    }
+    return [self stringWithCString:bytes];
+}
+
++ (NSString *)stringWithCString:(const char*)byteString
+  length:(unsigned int)length
+{
+    return AUTORELEASE([[self alloc]
+                           initWithCString:byteString length:length]);
+}
+
++ (NSString *)stringWithCStringNoCopy:(char*)byteString
+  length:(unsigned int)length freeWhenDone:(BOOL)flag
+{
+    return AUTORELEASE([[self alloc] initWithCStringNoCopy:byteString
+                                     length:length freeWhenDone:flag]);
+}
+
++ (id)stringWithCStringNoCopy:(char*)byteString
+  freeWhenDone:(BOOL)flag
+{
+    return AUTORELEASE([[self alloc] initWithCStringNoCopy:byteString
+                                     freeWhenDone:flag]);
+}
+
++ (id)stringWithFormat:(NSString*)format,...
+{
+    va_list va;
+    NSString* string;
+    
+    va_start(va, format);
+    string = AUTORELEASE([[self alloc] initWithFormat:format arguments:va]);
+    va_end(va);
+    return string;
+}
+
++ (id)stringWithFormat:(NSString *)format arguments:(va_list)argList
+{
+    return AUTORELEASE([[self alloc] initWithFormat:format
+                                     arguments:argList]);
+}
+
++ (id)stringWithContentsOfFile:(NSString *)path
+{
+    return AUTORELEASE([[self alloc] initWithContentsOfFile:path]);
+}
++ (id)stringWithContentsOfURL:(NSURL *)_url
+{
+    return AUTORELEASE([[self alloc] initWithContentsOfURL:_url]);
+}
+
+@end /* NSString(NSStringCreation) */
+
+@implementation NSString(GSAdditions)
+
+- (NSString *)stringWithoutPrefix:(NSString *)_prefix
+{
+    return ([self hasPrefix:_prefix])
+        ? [self substringFromIndex:[_prefix length]]
+        : [[self copy] autorelease];
+}
+
+- (NSString *)stringWithoutSuffix:(NSString *)_suffix
+{
+    return ([self hasSuffix:_suffix])
+        ? [self substringToIndex:([self length] - [_suffix length])]
+        : [[self copy] autorelease];
+}
+
+- (NSString *)stringByReplacingString:(NSString *)_orignal
+  withString:(NSString *)_replacement
+{
+    /* very slow solution .. */
+    
+    if ([self indexOfString:_orignal] == NSNotFound)
+        return [[self copy] autorelease];
+    
+    return [[self componentsSeparatedByString:_orignal]
+                  componentsJoinedByString:_replacement];
+}
+
+static NSCharacterSet *whiteSpaceSet = nil;
+static BOOL (*isWhiteSpaceSetMem)(id, SEL, unichar);
+
+- (NSString *)stringByTrimmingLeadWhiteSpaces
+{
+    /* can't we share the implementation of lead and tail?! It is 98% similiar */
+    unsigned len;
+    unichar  *buf;
+    unsigned idx;
+    
+    if (whiteSpaceSet == nil) {
+       whiteSpaceSet = [[NSCharacterSet whitespaceAndNewlineCharacterSet] retain];
+       isWhiteSpaceSetMem = (void *)
+           [whiteSpaceSet methodForSelector:@selector(characterIsMember:)];
+    }
+    
+    if ((len = [self length]) == 0)
+        return @"";
+    
+    buf = calloc(len + 1, sizeof(unichar));
+    [self getCharacters:buf];
+        
+    for (idx = 0; 
+        (idx < len) && isWhiteSpaceSetMem(whiteSpaceSet,
+                                          @selector(characterIsMember:),
+                                          buf[idx]); 
+        idx++)
+       ;
+    
+    self = [NSStringClass stringWithCharacters:&(buf[idx]) length:(len - idx)];
+    free(buf);
+    return self;
+}
+- (NSString *)stringByTrimmingTailWhiteSpaces
+{
+    unichar      *buf;
+    unsigned int idx;
+    unsigned     len;
+
+    if (whiteSpaceSet == nil) {
+       whiteSpaceSet = [[NSCharacterSet whitespaceAndNewlineCharacterSet] retain];
+       isWhiteSpaceSetMem = (void *)
+           [whiteSpaceSet methodForSelector:@selector(characterIsMember:)];
+    }
+    
+    if ((len = [self length]) == 0)
+        return @"";
+    
+    buf = calloc(len + 2, sizeof(unichar));
+    [self getCharacters:buf];
+        
+    for (idx = (len - 1); 
+        (idx >= 0) && isWhiteSpaceSetMem(whiteSpaceSet, 
+                                         @selector(characterIsMember:), buf[idx]);
+        idx--)
+        ;
+    
+    self = [NSStringClass stringWithCharacters:buf length:(idx + 1)];
+    free(buf);
+    return self;
+}
+
+- (NSString *)stringByTrimmingLeadSpaces
+{
+    unsigned int len;
+    unsigned int idx;
+    unichar  *buf;
+    
+    if ((len = [self length]) == 0)
+        return @"";
+        
+    buf = calloc(len + 2, sizeof(unichar));
+    [self getCharacters:buf];
+        
+    for (idx = 0; (idx < len) && isspace(buf[idx]); idx++)
+        ;
+        
+    self = [NSStringClass stringWithCharacters:&(buf[idx]) length:(len - idx)];
+    if (buf) free(buf);
+    return self;
+}
+- (NSString *)stringByTrimmingTailSpaces
+{
+    unsigned len;
+    unichar *buf;
+    int     idx;
+    
+    if ((len = [self length]) == 0)
+        return @"";
+        
+    buf = calloc(len + 2, sizeof(unichar));
+    [self getCharacters:buf];
+        
+    for (idx = (len - 1); (idx >= 0) && isspace(buf[idx]); idx--)
+        ;
+        
+    self = [NSStringClass stringWithCharacters:buf length:(idx + 1)];
+    if (buf) free(buf);
+    return self;
+}
+
+- (NSString *)stringByTrimmingWhiteSpaces
+{
+    return [[self stringByTrimmingTailWhiteSpaces]
+                  stringByTrimmingLeadWhiteSpaces];
+}
+- (NSString *)stringByTrimmingSpaces
+{
+    return [[self stringByTrimmingTailSpaces]
+                  stringByTrimmingLeadSpaces];
+}
+
+@end /* NSString(GSAdditions) */
+
+@implementation NSMutableString(GNUstepCompatibility)
+
+- (void)trimLeadSpaces
+{
+    [self setString:[self stringByTrimmingLeadSpaces]];
+}
+- (void)trimTailSpaces
+{
+    [self setString:[self stringByTrimmingTailSpaces]];
+}
+- (void)trimSpaces
+{
+    [self setString:[self stringByTrimmingSpaces]];
+}
+
+@end /* NSMutableString(GNUstepCompatibility) */
+
+@implementation NSMutableString(NSStringCreation)
+
++ (id)allocWithZone:(NSZone *)zone
+{
+    return (self == [NSMutableString class]) ? 
+       [NSMutableTemporaryString allocWithZone:zone] 
+       : NSAllocateObject(self, 0, zone);
+}
+
++ (id)stringWithCapacity:(unsigned int)capacity
+{
+    return AUTORELEASE([[self alloc] initWithCapacity:capacity]);
+}
++ (id)string
+{
+    return [self stringWithCapacity:0];
+}
+
+@end /* NSMutableString(NSStringCreation) */
+
+/****************************
+ * Initializing strings
+ ****************************/
+
+@implementation NSMutableString(NSStringInitialization)
+
+- (id)initWithCapacity:(unsigned int)capacity
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+- (id)initWithCharacters:(const unichar *)chars length:(unsigned int)length
+{
+    unsigned char *buffer;
+    unsigned int  i, j;
+    BOOL isLower8BitEqual = NO;
+    BOOL isLower7BitEqual = NO;
+    unsigned int convertCount = 0;
+    
+    switch ([NSStringClass defaultCStringEncoding]) {
+        case NSISOLatin1StringEncoding:
+            isLower8BitEqual = YES;
+            break;
+        case NSASCIIStringEncoding:
+        case NSUTF8StringEncoding:
+            isLower7BitEqual = YES;
+            break;
+    }
+    
+    /* scan whether this is a non-8-bit- string ... */
+    for (i = 0; i < length; i++) {
+        //NSMutableString *s;
+        
+#if !HAS_UNICODE_STRING
+       /* allow Euro char code (8364) */
+       if (chars[i] == 8364) {
+           convertCount++;
+           continue;
+       }
+#endif
+        if (isLower8BitEqual && (chars[i] < 256))
+            /* valid 8-bit character in default encoding */
+            continue;
+        if (isLower7BitEqual && (chars[i] < 128))
+            /* valid 7-bit character in default encoding */
+            continue;
+        
+#if HAS_UNICODE_STRING
+        s = [[NSMutableUnicodeString alloc]
+                                     initWithCharacters:chars
+                                     length:length];
+        if (flag) {
+            lfFree(chars);
+            chars = NULL;
+        }
+#endif
+        return [self notImplemented:_cmd];
+    }
+    
+    buffer = MallocAtomic(length + (convertCount*3) + 1);
+    
+    for (i = 0, j = 0; i < length; i++, j++) {
+#if !HAS_UNICODE_STRING
+       if (chars[i] == 8364) {
+           buffer[j++] = 'E';
+           buffer[j++] = 'U';
+           buffer[j] = 'R';
+       }
+#endif
+        buffer[j] = chars[i];
+    }
+    
+    buffer[j] = '\0';
+    self = [self initWithCString:(char *)buffer length:j];
+    if (buffer) lfFree(buffer);
+    return self;
+}
+
+- (id)initWithCharactersNoCopy:(unichar*)chars length:(unsigned int)length 
+  freeWhenDone:(BOOL)flag
+{
+    unsigned char *buffer;
+    unsigned int  i, j;
+    BOOL isLower8BitEqual = NO;
+    BOOL isLower7BitEqual = NO;
+    unsigned int convertCount = 0;
+    
+    switch ([NSStringClass defaultCStringEncoding]) {
+        case NSISOLatin1StringEncoding:
+            isLower8BitEqual = YES;
+            break;
+        case NSASCIIStringEncoding:
+        case NSUTF8StringEncoding:
+        case NSISOLatin9StringEncoding:
+            isLower7BitEqual = YES;
+            break;
+    }
+    
+    /* scan whether this is a non-8-bit- string ... */
+    for (i = 0; i < length; i++) {
+        //NSMutableString *s;
+        
+#if !HAS_UNICODE_STRING
+       /* allow Euro char code (8364) */
+       if (chars[i] == 8364) {
+           convertCount++;
+           continue;
+       }
+#endif
+        if (isLower8BitEqual && (chars[i] < 256))
+            /* valid 8-bit character in default encoding */
+            continue;
+        if (isLower7BitEqual && (chars[i] < 128))
+            /* valid 7-bit character in default encoding */
+            continue;
+        
+#if HAS_UNICODE_STRING
+        s = [[NSMutableUTF16String alloc]
+                                   initWithCharacters:chars
+                                   length:length];
+        if (flag) {
+            lfFree(chars);
+            chars = NULL;
+        }
+#endif
+        return [self notImplemented:_cmd];
+    }
+    
+    buffer = MallocAtomic(length + (convertCount*3) + 1);
+    
+    for (i = 0, j = 0; i < length; i++, j++) {
+#if !HAS_UNICODE_STRING
+       if (chars[i] == 8364) {
+           buffer[j++] = 'E';
+           buffer[j++] = 'U';
+           buffer[j] = 'R';
+       }
+#endif
+        buffer[j] = chars[i];
+    }
+
+    
+    buffer[j] = '\0';
+    if (flag) {
+        lfFree(chars);
+        chars = NULL;
+    }
+    self = [self initWithCString:(char *)buffer length:j];
+    if (buffer) lfFree(buffer);
+    return self;
+}
+
+- (id)initWithCString:(const char*)byteString
+{
+    if (NSStringClass == Nil)
+        NSStringClass = [NSString class];
+    return [self initWithString:
+                     AUTORELEASE([[NSStringClass alloc] 
+                                     initWithCStringNoCopy:(char*)byteString
+                                     freeWhenDone:NO])];
+}
+
+- (id)initWithCString:(const char*)byteString length:(unsigned int)length
+{
+    if (NSStringClass == Nil)
+        NSStringClass = [NSString class];
+    return [self initWithString:
+                     AUTORELEASE([[NSStringClass alloc] 
+                                     initWithCStringNoCopy:(char*)byteString
+                                     length:length freeWhenDone:NO])];
+}
+
+- (id)initWithCStringNoCopy:(char*)byteString freeWhenDone:(BOOL)flag
+{
+    if (NSStringClass == Nil)
+        NSStringClass = [NSString class];
+    return [self initWithString:
+                     AUTORELEASE([[NSStringClass alloc]
+                                     initWithCStringNoCopy:byteString
+                                     freeWhenDone:flag])];
+}
+
+- (id)initWithCStringNoCopy:(char*)byteString length:(unsigned int)length 
+  freeWhenDone:(BOOL)flag
+{
+    if (NSStringClass == Nil)
+        NSStringClass = [NSString class];
+    return [self initWithString:
+                     AUTORELEASE([[NSStringClass alloc]
+                                     initWithCStringNoCopy:byteString
+                                     length:length freeWhenDone:flag])];
+}
+
+- (id)initWithString:(NSString*)aString
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+- (id)initWithFormat:(NSString*)format, ...
+{
+    id str;
+    va_list va;
+    
+    va_start(va, format);
+    str = [self initWithFormat:format arguments:va];
+    va_end(va);
+    return str;
+}
+
+- (id)initWithFormat:(NSString*)format arguments:(va_list)argList
+{
+    return [self initWithString:Avsprintf(format, argList)];
+}
+
+- (id)initWithFormat:(NSString*)format
+  locale:(NSDictionary*)dictionary, ...
+{
+    id str;
+    va_list va;
+    
+    va_start(va, dictionary);
+    str = [self initWithFormat:format arguments:va];
+    va_end(va);
+    return str;
+}
+
+- (id)initWithFormat:(NSString *)format 
+  locale:(NSDictionary*)dictionary arguments:(va_list)argList
+{
+    return [self initWithFormat:format arguments:argList];
+}
+
+- (id)initWithData:(NSData *)data encoding:(NSStringEncoding)encoding
+{
+    /* NSMutableString */
+    return NSInitStringWithData(self, data, encoding);
+}
+
+- (id)initWithContentsOfFile:(NSString *)path
+{
+    // UNICODE
+    // ENCODINGS
+    [self notImplemented:_cmd];
+    return nil;
+}
+
+@end /* NSMutableString(NSStringInitialization) */
+
+/****************************
+ * Allocate concrete strings
+ ****************************/
+/*
+ * Classes used for allocation of NSString concrete instances
+ */
+
+@implementation NSTemporaryString
+
+static BOOL              isMultithreaded              = NO;
+static NSTemporaryString *temporaryStringsPool        = nil;
+static Class             NSInline8BitStringClass      = Nil;
+static Class             NSShortInline8BitStringClass = Nil;
+
++ (void)initialize
+{
+    static BOOL initialized = NO;
+
+    if (!initialized) {
+       [[NSNotificationCenter defaultCenter]
+           addObserver:self
+           selector:@selector(taskNowMultiThreaded:)
+           name:NSWillBecomeMultiThreadedNotification
+           object:nil];
+       initialized = YES;
+    }
+}
+
++ (void)taskNowMultiThreaded:notification
+{
+    PrivateThreadData* threadData = [[NSThread currentThread]
+                                       _privateThreadData];
+
+    [threadData setTemporaryStringsPool:temporaryStringsPool];
+    temporaryStringsPool = nil;
+    isMultithreaded = YES;
+}
+
++ (id)allocWithZone:(NSZone*)zone
+{
+    NSTemporaryString* obj = nil;
+    PrivateThreadData* threadData = nil;
+
+    if (isMultithreaded) {
+       threadData = [[NSThread currentThread] _privateThreadData];
+       obj = [threadData temporaryString];
+    }
+    else {
+       if (temporaryStringsPool) {
+           obj = temporaryStringsPool;
+           temporaryStringsPool = temporaryStringsPool->next;
+           obj->next = nil;
+       }
+    }
+
+    if (!obj)
+       obj = (id)NSAllocateObject(self, 0, zone);
+
+    obj->_zone = zone;
+
+    return obj;
+}
+
+- (void)dealloc
+{
+    fprintf (stderr, "ERROR: NSTemporaryString %s to be deallocated!\n", 
+             isa->name);
+    abort ();
+}
+
+static inline void _collectTemporary(NSTemporaryString *self)
+{
+    if (isMultithreaded) {
+       [[[NSThread currentThread] _privateThreadData]
+                    addTemporaryString:self];
+    }
+    else {
+       if (self != temporaryStringsPool)
+           self->next = temporaryStringsPool;
+       temporaryStringsPool = self;
+    }
+}
+
+- (NSZone *)zone
+{
+    return _zone;
+}
+
+/*
+ * Methods that return strings
+ */
+
+- (id)init
+{
+    id str = @"";
+
+    _collectTemporary(self);
+    return str;
+}
+
+- (id)initWithCharacters:(const unichar *)chars length:(unsigned int)length
+{
+    unsigned char         *buffer;
+    register unsigned int i;
+    BOOL isLower8BitEqual = NO;
+    BOOL isLower7BitEqual = NO;
+
+    if (length == 0) {
+        _collectTemporary(self);
+        return @"";
+    }
+
+    switch ([NSStringClass defaultCStringEncoding]) {
+        case NSISOLatin1StringEncoding:
+            isLower8BitEqual = YES;
+            break;
+        case NSASCIIStringEncoding:
+        case NSUTF8StringEncoding:
+            isLower7BitEqual = YES;
+            break;
+    }
+    
+    /* scan whether this is a non-8-bit- string ... */
+    for (i = 0; i < length; i++) {
+        NSString *s;
+        
+        if (isLower8BitEqual && (chars[i] < 256))
+            /* valid 8-bit character in default encoding */
+            continue;
+        if (isLower7BitEqual && (chars[i] < 128))
+            /* valid 7-bit character in default encoding */
+            continue;
+        
+        s = [[NSInlineUTF16String allocForCapacity:(length + 1) zone:NULL]
+                                  initWithCharacters:chars
+                                  length:length];
+        _collectTemporary(self);
+        return s;
+    }
+    
+    buffer = MallocAtomic(length + 1);
+    
+    for (i = 0; i < length; i++)
+        buffer[i] = chars[i];
+    
+    buffer[length] = '\0';
+    
+    self = [self initWithCString:(char *)buffer length:length];
+    if (buffer) lfFree(buffer);
+    return self;
+}
+
+- (id)initWithCharactersNoCopy:(unichar *)chars
+  length:(unsigned int)length freeWhenDone:(BOOL)flag
+{
+    unsigned char         *buffer;
+    register unsigned int i;
+    BOOL isLower8BitEqual = NO;
+    BOOL isLower7BitEqual = NO;
+
+    if (length == 0) {
+        _collectTemporary(self);
+        if (flag && chars != NULL) {
+            lfFree(chars);
+            chars = NULL;
+        }
+        return @"";
+    }
+
+    switch ([NSStringClass defaultCStringEncoding]) {
+        case NSISOLatin1StringEncoding:
+            isLower8BitEqual = YES;
+            break;
+        case NSASCIIStringEncoding:
+        case NSUTF8StringEncoding:
+            isLower7BitEqual = YES;
+            break;
+    }
+    
+    /* scan whether this is a non-8-bit- string ... */
+    for (i = 0; i < length; i++) {
+        NSString *s;
+
+#if 0
+        printf("chars[%d] %c %d\n", i, chars[i], chars[i]);
+#endif
+        
+        if (isLower8BitEqual && (chars[i] < 256))
+            /* valid 8-bit character in default encoding */
+            continue;
+        if (isLower7BitEqual && (chars[i] < 128))
+            /* valid 7-bit character in default encoding */
+            continue;
+        
+        s = [[NSInlineUTF16String allocForCapacity:(length + 1) zone:NULL]
+                                  initWithCharacters:chars
+                                  length:length];
+        if (flag && (chars != NULL)) {
+            lfFree(chars);
+            chars = NULL;
+        }
+        _collectTemporary(self);
+#if 0
+        printf("%s: return s[%s]\n", __PRETTY_FUNCTION__, 
+               [[[s class] description] cString]);
+#endif
+        return s;
+    }
+    
+    buffer = MallocAtomic(length + 1);
+    
+    for (i = 0; i < length; i++)
+        buffer[i] = chars[i];
+    
+    buffer[length] = '\0';
+    if (flag && (chars != NULL)) {
+        lfFree(chars);
+        chars = NULL;
+    }
+    self = [self initWithCString:(char *)buffer length:length];
+    if (buffer != NULL) lfFree(buffer);
+    return self;
+}
+
+- (id)initWithCString:(const char *)byteString
+{
+    Class clazz;
+    int length;
+    id  str;
+    
+    if (NSInline8BitStringClass == Nil)
+        NSInline8BitStringClass = [NSInline8BitString class];
+    if (NSShortInline8BitStringClass == Nil)
+        NSShortInline8BitStringClass = [NSShortInline8BitString class];
+    
+    length = Strlen(byteString);
+    
+    if (length == 0)
+        return @"";
+    
+#if USE_SINGLE8BITSTRING    
+    if (length == 1) {
+        if ((str = _getSingle8BitString(*(unsigned char *)byteString))) {
+            _collectTemporary(self);
+            return RETAIN(str);
+        }
+    }
+#endif    
+    
+    clazz = length < 255
+        ? NSShortInline8BitStringClass
+        : NSInline8BitStringClass;
+    
+    str = [[clazz allocForCapacity:length zone:_zone]
+                  initWithCString:byteString length:length];
+    
+    _collectTemporary(self);
+    return str;
+}
+
+- (id)initWithUTF8String:(const char *)byteString
+{
+    NSData *d;
+    
+    d = byteString
+       ? [NSData dataWithBytes:byteString length:strlen(byteString)]
+       : nil;
+    return [self initWithData:d encoding:NSUTF8StringEncoding];
+}
+
+- (id)initWithBytes:(void *)_bytes length:(unsigned)_length 
+  encoding:(NSStringEncoding)_enc
+{
+    NSData *d;
+    
+    d = _bytes
+       ? [NSData dataWithBytes:_bytes length:_length]
+       : nil;
+    return [self initWithData:d encoding:_enc];
+}
+- (id)initWithBytesNoCopy:(void *)_bytes length:(unsigned)_length 
+  encoding:(NSStringEncoding)_enc freeWhenDone:(BOOL)_fwd
+{
+    NSData *d;
+    
+    d = (_bytes != nil)
+       ? [[NSData alloc] initWithBytesNoCopy:_bytes length:_length
+                          freeWhenDone:_fwd]
+       : nil;
+    self = [self initWithData:d encoding:_enc];
+    [d release];
+    return self;
+}
+
+- (id)initWithCString:(const char *)byteString length:(unsigned int)length
+{
+    Class clazz;
+    id    str;
+
+    if (length == 0) {
+        _collectTemporary(self);
+        return @"";
+    }
+#if USE_SINGLE8BITSTRING    
+    if (length == 1) {
+        if ((str = _getSingle8BitString(*(unsigned char *)byteString))) {
+            _collectTemporary(self);
+            return RETAIN(str);
+        }
+    }
+#endif
+    
+    if (NSInline8BitStringClass == Nil)
+        NSInline8BitStringClass = [NSInline8BitString class];
+    if (NSShortInline8BitStringClass == Nil)
+        NSShortInline8BitStringClass = [NSShortInline8BitString class];
+    
+    clazz = length < 255
+        ? NSShortInline8BitStringClass
+        : NSInline8BitStringClass;
+    
+    str = [[clazz allocForCapacity:length zone:_zone]
+                  initWithCString:byteString length:length];
+
+    _collectTemporary(self);
+    return str;
+}
+
+- (id)initWithCStringNoCopy:(char*)byteString freeWhenDone:(BOOL)flag
+{
+    id str = flag
+       ? [NSOwned8BitString allocWithZone:_zone]
+       : [NSNonOwned8BitString allocWithZone:_zone];
+
+    str = [str initWithCString:byteString length:Strlen(byteString) copy:NO];
+    _collectTemporary(self);
+    return str;
+}
+
+- (id)initWithCStringNoCopy:(char *)byteString
+  length:(unsigned int)length freeWhenDone:(BOOL)flag
+{
+    id str;
+
+    str = flag
+        ? [NSOwnedOpen8BitString    allocWithZone:_zone]
+       : [NSNonOwnedOpen8BitString allocWithZone:_zone];
+    
+    str = [str initWithCString:byteString length:length copy:NO];
+    _collectTemporary(self);
+    return str;
+}
+
+- (id)initWithString:(NSString *)aString
+{
+    id str = [aString copyWithZone:_zone];
+    _collectTemporary(self);
+    return str;
+}
+
+- (id)initWithFormat:(NSString *)format, ...
+{
+    id str;
+    va_list va;
+    
+    va_start(va, format);
+    str = [self initWithFormat:format arguments:va];
+    va_end(va);
+    return str;
+}
+
+- (id)initWithFormat:(NSString *)format arguments:(va_list)argList
+{
+    id str = Avsprintf(format, argList);
+    str = [str copyWithZone:_zone];
+    _collectTemporary(self);
+    return str;
+}
+
+- (id)initWithFormat:(NSString*)format
+  locale:(NSDictionary*)dictionary, ...
+{
+    id str;
+    va_list va;
+    
+    va_start(va, dictionary);
+    str = [self initWithFormat:format arguments:va];
+    va_end(va);
+    return str;
+}
+
+- (id)initWithFormat:(NSString*)format 
+  locale:(NSDictionary*)dictionary arguments:(va_list)argList
+{
+    return [self initWithFormat:format arguments:argList];
+}
+
+- (id)initWithData:(NSData *)data encoding:(NSStringEncoding)encoding
+{
+    /* NSTemporaryString */
+    // UNICODE
+    Class    clazz;
+    id       str;
+    unsigned len;
+    
+    len = [data length];
+        
+    clazz = Nil;
+
+    if (encoding == NSUnicodeStringEncoding) {
+        /* scan for characters > 255 ... (everything below is covered by L1) */
+        const unichar *s;
+        unsigned int  i, slen;
+        
+        s    = [data bytes];
+        slen = len / 2;
+        
+        for (i = 0; i < slen; i++) {
+            if (s[i] > 255) {
+                /* use wide string ... */
+                str = [NSInlineUTF16String allocForCapacity:slen zone:_zone];
+                str = [str initWithCharacters:s length:slen];
+                _collectTemporary(self);
+                return str;
+            }
+        }
+    }
+    else if (encoding == NSISOLatin9StringEncoding) {
+        const unsigned char *buf;
+        unichar  *newBuf;
+        unsigned int i;
+        NSString *str;
+
+        buf = [data bytes];
+        newBuf = MallocAtomic((len + 1)* sizeof(unichar));
+        
+        for (i = 0; i < len; i++) { /* convert Euro sign */
+            /* missing conversions for other latin9 signs */
+            if (buf[i] == 164) {
+                newBuf[i] = 8364;
+            }
+            else {
+                newBuf[i] = buf[i];
+            }
+        }
+        str = [NSInlineUTF16String allocForCapacity:len zone:[self zone]];
+        str = [str initWithCharacters:newBuf length:len];
+        
+        lfFree(newBuf);
+        _collectTemporary(self);
+        return str;
+    }
+    else if (encoding == NSUTF8StringEncoding) {
+        unichar       *buf16;
+        unsigned char *start,   *end;
+        unichar       *start16, *end16;
+        int           result;
+        
+        buf16 = MallocAtomic((len + 1) * sizeof(unichar));
+#if DEBUG
+        NSCAssert(buf16,
+                  @"couldn't allocate proper buffer of len %i", len);
+#endif
+        
+        start   = (void *)[data bytes]; /* should I allocate a buffer ?? */
+        end     = start + len;
+        start16 = &(buf16[0]);
+        end16   = start16 + len;
+        
+        result = NSConvertUTF8toUTF16(&start, end, &start16, end16);
+        
+        if (result == 2) { /* target exhausted */
+            if (buf16) { lfFree(buf16); buf16 = NULL; }
+            [NSException raise:@"UTFConversionException"
+                         format:
+                         @"couldn't convert UTF8 to UTF16, "
+                         @"target buffer is to small !"];
+        }
+        else if (result == 1) { /* source exhausted */
+            if (buf16) { lfFree(buf16); buf16 = NULL; }
+            [NSException raise:@"UTFConversionException"
+                         format:
+                         @"couldn't convert UTF8 to UTF16, "
+                         @"source buffer is to small "
+                         @"(probably invalid input) !, data: %@", data];
+        }
+        else {
+            /* length correct ? */
+            unsigned int  i, slen;
+            const unichar *s;
+
+            s    = buf16;
+            slen = (start16 - buf16);
+
+            for (i = 0; i < slen; i++) {
+                if (s[i] > 255) {
+                    /* use wide string ... */
+                    str = [NSInlineUTF16String allocForCapacity:slen
+                                               zone:_zone];
+                    str = [str initWithCharacters:s length:slen];
+                    if (buf16) { lfFree(buf16); buf16 = NULL; }
+                    _collectTemporary(self);
+
+                    return str;
+                }
+            }
+            
+            if (buf16) { lfFree(buf16); buf16 = NULL; }
+        }
+    }
+    
+    if (clazz == Nil) {
+        if (NSInline8BitStringClass == Nil)
+            NSInline8BitStringClass = [NSInline8BitString class];
+        if (NSShortInline8BitStringClass == Nil)
+            NSShortInline8BitStringClass = [NSShortInline8BitString class];
+        
+        clazz = len < 255
+            ? NSShortInline8BitStringClass
+            : NSInline8BitStringClass;
+    }
+    len = [data length];
+    str = [clazz allocForCapacity:len zone:_zone];
+    str = NSInitStringWithData(str, data, encoding);
+    _collectTemporary(self);
+    return str;
+}
+
+- (id)initWithContentsOfFile:(NSString *)_path
+{
+    unsigned char *bytes = NULL;
+    unsigned len;
+    
+    if ((bytes = NSReadContentsOfFile(_path, 1, &len))) {
+        NSString *str;
+        
+        bytes[len] = '\0';
+        
+        if (len >= 2) {
+            BOOL             isUnicode;
+            enum NSByteOrder fbo;
+            
+            if (bytes[0] == 0xFF && bytes[1] == 0xFE) {
+                isUnicode = YES;
+                fbo = NS_LittleEndian;
+            }
+            else if (bytes[0] == 0xFE && bytes[1] == 0xFF) {
+                isUnicode = YES;
+                fbo = NS_BigEndian;
+            }
+            else
+                isUnicode = NO;
+
+            if (isUnicode) {
+                unichar *chars;
+                
+                chars = (unichar *)&(bytes[2]);
+                len   = ((len - 2) / 2);
+                
+                if (fbo != NSHostByteOrder()) {
+                    unsigned i;
+                    
+                    /* IMPROVE THAT JUNK !!! */
+                    for (i = 0; i < len; i++) {
+                        unsigned char buf[2];
+                        unsigned char t;
+                        memcpy(buf, &(chars[i]), 2);
+                        t = buf[0];
+                        buf[0] = buf[1];
+                        buf[1] = t;
+                        memcpy(&(chars[i]), buf, 2);
+                    }
+                }
+                
+                str = [self initWithCharacters:chars length:len];
+                if (bytes) free(bytes);
+                return str;
+            }
+        }
+        
+        str = [[NSOwned8BitString allocWithZone:_zone] 
+                                 initWithCString:(char *)bytes
+                                  length:len copy:NO];
+        
+        _collectTemporary(self);
+        return str;
+    }    
+    else {
+        _collectTemporary(self);
+        return nil;
+    }
+}
+
+- (id)initWithContentsOfURL:(NSURL *)_url
+{
+    if ([_url isFileURL]) {
+        return [self initWithContentsOfFile:[_url path]];
+    }
+    else if (_url == nil) {
+        _collectTemporary(self);
+        return nil;
+    }
+    else {
+        NSURLHandle      *handle;
+        NSData           *data;
+        NSString         *mimeType;
+        NSStringEncoding enc;
+        
+        handle   = [_url URLHandleUsingCache:NO];
+        data     = [handle resourceData];
+        mimeType = [[handle propertyForKey:@"content-type"] description];
+        
+        if ([mimeType length] > 0) {
+            unsigned idx;
+
+            enc = [NSStringClass defaultCStringEncoding];
+            if ([mimeType hasPrefix:@"text/xml"])
+                enc = NSUTF8StringEncoding;
+            
+            if ((idx = [mimeType indexOfString:@"charset="]) != NSNotFound) {
+                NSString *cs;
+                
+                cs = [mimeType substringFromIndex:(idx + 8)];
+                cs = [cs lowercaseString];
+                if ([cs hasPrefix:@"utf-8"])
+                    enc = NSUTF8StringEncoding;
+                else if ([cs hasPrefix:@"iso-8859-1"])
+                    enc = NSISOLatin1StringEncoding;
+                else if ([cs hasPrefix:@"utf-16"])
+                    enc = NSUnicodeStringEncoding;
+                else if ([cs hasPrefix:@"ascii"])
+                    enc = NSASCIIStringEncoding;
+                else
+                    NSLog(@"WARNING: cannot process content charset "
+                          @"'%@' of URL '%@'", cs, [_url absoluteString]);
+            }
+        }
+        else
+            enc = [NSStringClass defaultCStringEncoding];
+        
+        return [self initWithData:data encoding:enc];
+    }
+}
+
+@end /* NSTemporaryString */
+
+
+@implementation NSMutableTemporaryString
+
+static NSMutableTemporaryString *temporaryMutableStringsPool = nil;
+
++ (void)initialize
+{
+    static BOOL initialized = NO;
+
+    if (!initialized) {
+       [[NSNotificationCenter defaultCenter]
+           addObserver:self
+           selector:@selector(taskNowMultiThreaded:)
+           name:NSWillBecomeMultiThreadedNotification
+           object:nil];
+       initialized = YES;
+    }
+}
+
++ (void)taskNowMultiThreaded:notification
+{
+    PrivateThreadData* threadData = [[NSThread currentThread]
+                                       _privateThreadData];
+
+    [threadData setTemporaryMutableStringsPool:temporaryMutableStringsPool];
+    temporaryMutableStringsPool = nil;
+    isMultithreaded = YES;
+}
+
++ (id)allocWithZone:(NSZone*)zone
+{
+    NSMutableTemporaryString *obj = nil;
+    PrivateThreadData        *threadData = nil;
+
+    if (isMultithreaded) {
+       threadData = [[NSThread currentThread] _privateThreadData];
+       obj = [threadData temporaryMutableString];
+    }
+    else {
+       if (temporaryMutableStringsPool) {
+           obj = temporaryMutableStringsPool;
+           temporaryMutableStringsPool = temporaryMutableStringsPool->next;
+           obj->next = nil;
+       }
+    }
+
+    if (!obj)
+       obj = (id)NSAllocateObject(self, 0, zone);
+
+    obj->_zone = zone;
+
+    return obj;
+}
+
+- (void)dealloc
+{
+    fprintf(stderr,"NSMutableTemporaryString %s to be deallocated!\n",isa->name);
+    abort();
+}
+
+static inline void _collectMutableTemporary(NSMutableTemporaryString *self)
+{
+    if (isMultithreaded) {
+       [[[NSThread currentThread] _privateThreadData]
+                    addTemporaryMutableString:self];
+    }
+    else {
+       if (self != temporaryMutableStringsPool)
+           self->next = temporaryMutableStringsPool;
+       temporaryMutableStringsPool = self;
+    }
+}
+
+/*
+ * Methods that return strings
+ */
+
+- (id)initWithCapacity:(unsigned int)capacity
+{
+    id str = [[NSMutableSimple8BitString allocWithZone:_zone] 
+       initWithCapacity:capacity];
+
+    _collectMutableTemporary(self);
+    return str;
+}
+
+- (id)init
+{
+    id str = [[NSMutableSimple8BitString allocWithZone:_zone] init];
+    _collectMutableTemporary(self);
+    return str;
+}
+
+- (id)initWithCString:(const char*)byteString
+{
+    int length = Strlen(byteString);
+    id str = [[NSMutableSimple8BitString allocWithZone:_zone]
+           initWithCString:(char*)byteString length:length copy:YES];
+    _collectMutableTemporary(self);
+    return str;
+}
+
+- (id)initWithCString:(const char*)byteString length:(unsigned int)length
+{
+    id str = [[NSMutableSimple8BitString allocWithZone:_zone]
+           initWithCString:(char*)byteString length:length copy:YES];
+    _collectMutableTemporary(self);
+    return str;
+}
+
+- (id)initWithCStringNoCopy:(char*)byteString freeWhenDone:(BOOL)flag
+{
+    id str = [NSMutableSimple8BitString allocWithZone:_zone];
+    
+    str = [str initWithCString:byteString
+       length:Strlen(byteString) copy:!flag];
+    
+    _collectMutableTemporary(self);
+    return str;
+}
+
+- (id)initWithCStringNoCopy:(char*)byteString
+  length:(unsigned int)length freeWhenDone:(BOOL)flag
+{
+    id str = [NSMutableSimple8BitString allocWithZone:_zone];
+    
+    str = [str initWithCString:byteString
+       length:Strlen(byteString) copy:!flag];
+
+    _collectMutableTemporary(self);
+    return str;
+}
+
+- (id)initWithString:(NSString*)aString
+{
+    id str = [[NSMutableSimple8BitString allocWithZone:_zone] 
+       initWithString:aString];
+    
+    _collectMutableTemporary(self);
+    return str;
+}
+
+- (id)initWithFormat:(NSString*)format, ...
+{
+    id str;
+    va_list va;
+    
+    va_start(va, format);
+    str = [self initWithFormat:format arguments:va];
+    va_end(va);
+    return str;
+}
+
+- (id)initWithFormat:(NSString*)format arguments:(va_list)argList
+{
+    id str = [[NSMutableSimple8BitString allocWithZone:_zone] init];
+
+    [str appendFormat:format arguments:argList];
+    _collectMutableTemporary(self);
+    return str;
+}
+
+- (id)initWithFormat:(NSString *)format
+  locale:(NSDictionary *)dictionary, ...
+{
+    id str;
+    va_list va;
+    
+    va_start(va, dictionary);
+    str = [self initWithFormat:format arguments:va];
+    va_end(va);
+    return str;
+}
+
+- (id)initWithFormat:(NSString *)format 
+  locale:(NSDictionary *)dictionary arguments:(va_list)argList
+{
+    return [self initWithFormat:format arguments:argList];
+}
+
+- (id)initWithData:(NSData *)data encoding:(NSStringEncoding)encoding
+{
+    /* NSMutableTemporaryString */
+    // UNICODE
+    id str;
+    str = [NSMutableSimple8BitString allocWithZone:_zone];
+    str = NSInitStringWithData(str, data, encoding);
+    _collectMutableTemporary(self);
+    return str;
+}
+
+- (id)initWithContentsOfFile:(NSString *)_path
+{
+    unsigned char *bytes = NULL;
+    unsigned len;
+
+    if ((bytes = NSReadContentsOfFile(_path, 1, &len))) {
+        NSMutableString *str;
+        
+        bytes[len] = '\0';
+        
+        str = [[NSMutableSimple8BitString allocWithZone:_zone] 
+                                         initWithCString:(char *)bytes
+                                          length:len copy:NO];
+        _collectMutableTemporary(self);
+        return str;
+    }    
+    else {
+        _collectMutableTemporary(self);
+        return nil;
+    }
+}
+
+@end /* NSMutableTemporaryString */
+
+#include <Foundation/NSAutoreleasePool.h>
+
+/*
+ * Used for forcing linking of this category
+ */
+
+static void __dummyNSStringfile ()
+{
+    extern void __dummyNSStringFilePathfile();
+    __dummyNSStringFilePathfile();
+    __dummyNSStringfile();
+}
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSStringScanner.m b/libFoundation/Foundation/NSStringScanner.m
new file mode 100644 (file)
index 0000000..fabaa99
--- /dev/null
@@ -0,0 +1,848 @@
+
+/* parser.dlg -- DLG Description of scanner
+ *
+ * Generated from: NSStringPropList.g
+ *
+ * Terence Parr, Will Cohen, and Hank Dietz: 1989-1994
+ * Purdue University Electrical Engineering
+ * With AHPCRC, University of Minnesota
+ * ANTLR Version 1.33
+ */
+
+#include <stdio.h>
+#define ANTLR_VERSION  133
+#define zzparser NSStringPropertyListParser
+#include "remap.h"
+
+#include <objc/objc.h>
+
+#ifndef __Attrib_def__
+#define __Attrib_def__
+typedef id Attrib;
+#endif
+
+#define USER_ZZSYN
+#define zzcr_attr NSStringPropertyListParser_zzcr_attr
+void zzcr_attr(Attrib* attr, int token, char* text);
+#include "antlr.h"
+#include "tokens.h"
+#include "dlgdef.h"
+LOOKAHEAD
+void zzerraction()
+{
+       (*zzerr)("invalid token");
+       zzadvance();
+       zzskip();
+}
+/*
+ * D L G tables
+ *
+ * Generated from: parser.dlg
+ *
+ * 1989-1998 by  Will Cohen, Terence Parr, and Hank Dietz
+ * Purdue University Electrical Engineering
+ * DLG Version 1.33MR14
+ */
+
+#include "mode.h"
+
+
+
+
+#include <Foundation/NSString.h>
+
+static int level = 0;
+extern NSMutableString* NSStringPropertyListParser_errors;
+
+#define ERROR(msg) \
+[NSStringPropertyListParser_errors \
+appendFormat:[NSString stringWithCString:"line %d: " msg "\n"], zzline]
+#define ERROR1(msg, arg) \
+[NSStringPropertyListParser_errors \
+appendFormat:[NSString stringWithCString:"line %d: " msg "\n"], zzline, arg]
+
+static void act1()
+{ 
+               NLA = Eof;
+       }
+
+
+static void act2()
+{ 
+               NLA = 22;
+               zzskip();  
+       }
+
+
+static void act3()
+{ 
+               NLA = 23;
+               zzline++; zzskip();  
+       }
+
+
+static void act4()
+{ 
+               NLA = 24;
+               zzmode(COMMENT); level++; zzskip();  
+       }
+
+
+static void act5()
+{ 
+               NLA = 25;
+               zzmode(LINE_COMMENT); zzskip();  
+       }
+
+
+static void act6()
+{ 
+               NLA = 26;
+               ERROR("unexpected comment terminator"); zzskip();  
+       }
+
+
+static void act7()
+{ 
+               NLA = 27;
+               zzmode(STRING_CLASS); zzskip();  
+       }
+
+
+static void act8()
+{ 
+               NLA = 28;
+               zzmode(DATA_CLASS); zzskip();  
+       }
+
+
+static void act9()
+{ 
+               NLA = STRING;
+       }
+
+
+static void act10()
+{ 
+               NLA = 29;
+       }
+
+
+static void act11()
+{ 
+               NLA = 30;
+       }
+
+
+static void act12()
+{ 
+               NLA = 31;
+       }
+
+
+static void act13()
+{ 
+               NLA = 32;
+       }
+
+
+static void act14()
+{ 
+               NLA = 33;
+       }
+
+
+static void act15()
+{ 
+               NLA = 34;
+       }
+
+
+static void act16()
+{ 
+               NLA = 35;
+       }
+
+static unsigned char shift0[257] = {
+  0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 
+  1, 2, 16, 16, 16, 16, 16, 16, 16, 16, 
+  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 
+  16, 16, 16, 1, 16, 5, 7, 8, 16, 16, 
+  16, 9, 11, 4, 16, 10, 16, 8, 3, 7, 
+  7, 7, 7, 7, 7, 7, 7, 7, 7, 16, 
+  14, 6, 13, 16, 16, 7, 7, 7, 7, 7, 
+  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 
+  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 
+  7, 7, 16, 16, 16, 16, 7, 16, 7, 7, 
+  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 
+  7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 
+  7, 7, 7, 7, 12, 16, 15, 16, 16, 16, 
+  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 
+  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 
+  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 
+  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 
+  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 
+  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 
+  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 
+  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 
+  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 
+  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 
+  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 
+  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 
+  16, 16, 16, 16, 16, 16, 16
+};
+
+
+static void act17()
+{ 
+               NLA = Eof;
+       }
+
+
+static void act18()
+{ 
+               NLA = 2;
+               level++; zzskip();  
+       }
+
+
+static void act19()
+{ 
+               NLA = 3;
+               if(!--level) zzmode(START); zzskip();  
+       }
+
+
+static void act20()
+{ 
+               NLA = 4;
+               zzline++; zzskip();  
+       }
+
+
+static void act21()
+{ 
+               NLA = 5;
+               zzskip();  
+       }
+
+static unsigned char shift1[257] = {
+  0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+  3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+  3, 3, 3, 2, 3, 3, 3, 3, 1, 3, 
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
+  3, 3, 3, 3, 3, 3, 3
+};
+
+
+static void act22()
+{ 
+               NLA = Eof;
+       }
+
+
+static void act23()
+{ 
+               NLA = 6;
+               zzmode(START); zzline++; zzskip();  
+       }
+
+
+static void act24()
+{ 
+               NLA = 7;
+               zzskip();  
+       }
+
+static unsigned char shift2[257] = {
+  0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
+  2, 2, 2, 2, 2, 2, 2
+};
+
+
+static void act25()
+{ 
+               NLA = Eof;
+       }
+
+
+static void act26()
+{ 
+               NLA = STRING;
+               zzmode(START); zzreplstr("");  
+       }
+
+
+static void act27()
+{ 
+               NLA = 9;
+               zzmore();  
+       }
+
+
+static void act28()
+{ 
+               NLA = 10;
+               {char a[2]={'\a',0}; zzreplstr(a);zzmore();}  
+       }
+
+
+static void act29()
+{ 
+               NLA = 11;
+               {char a[2]={'\b',0}; zzreplstr(a);zzmore();}  
+       }
+
+
+static void act30()
+{ 
+               NLA = 12;
+               {char a[2]={'\f',0}; zzreplstr(a);zzmore();}  
+       }
+
+
+static void act31()
+{ 
+               NLA = 13;
+               {char a[2]={'\n',0}; zzreplstr(a);zzmore();}  
+       }
+
+
+static void act32()
+{ 
+               NLA = 14;
+               {char a[2]={'\t',0}; zzreplstr(a);zzmore();}  
+       }
+
+
+static void act33()
+{ 
+               NLA = 15;
+               {char a[2]={'\v',0}; zzreplstr(a);zzmore();}  
+       }
+
+
+static void act34()
+{ 
+               NLA = 16;
+               {char a[2]={*zzendexpr,0}; zzreplstr(a);zzmore();}  
+       }
+
+
+static void act35()
+{ 
+               NLA = 17;
+               zzmore();  
+       }
+
+static unsigned char shift3[257] = {
+  0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 
+  9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 
+  9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 
+  9, 9, 9, 9, 9, 1, 9, 9, 9, 9, 
+  9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 
+  9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 
+  9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 
+  9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 
+  9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 
+  9, 9, 9, 2, 9, 9, 9, 9, 3, 4, 
+  9, 9, 9, 5, 9, 9, 9, 9, 9, 9, 
+  9, 6, 9, 9, 9, 9, 9, 7, 9, 8, 
+  9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 
+  9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 
+  9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 
+  9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 
+  9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 
+  9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 
+  9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 
+  9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 
+  9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 
+  9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 
+  9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 
+  9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 
+  9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 
+  9, 9, 9, 9, 9, 9, 9
+};
+
+
+static void act36()
+{ 
+               NLA = Eof;
+       }
+
+
+static void act37()
+{ 
+               NLA = DATA;
+               zzmode(START); zzreplstr("");  
+       }
+
+
+static void act38()
+{ 
+               NLA = 19;
+               zzreplstr(""); zzmore();  
+       }
+
+
+static void act39()
+{ 
+               NLA = 20;
+               zzmore();  
+       }
+
+
+static void act40()
+{ 
+               NLA = 21;
+               ERROR1("invalid character in description of NSData: '%c'", *zzendexpr); zzskip();  
+       }
+
+static unsigned char shift4[257] = {
+  0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+  2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+  4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 
+  4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 
+  4, 4, 4, 1, 4, 4, 3, 3, 3, 3, 
+  3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 
+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+  4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 
+  3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 
+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
+  4, 4, 4, 4, 4, 4, 4
+};
+
+#define DfaStates      52
+typedef unsigned char DfaState;
+
+static DfaState st0[17] = {
+  1, 2, 3, 4, 5, 6, 7, 8, 52, 9, 
+  10, 11, 12, 13, 14, 15, 52
+};
+
+static DfaState st1[17] = {
+  52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
+  52, 52, 52, 52, 52, 52, 52
+};
+
+static DfaState st2[17] = {
+  52, 2, 52, 52, 52, 52, 52, 52, 52, 52, 
+  52, 52, 52, 52, 52, 52, 52
+};
+
+static DfaState st3[17] = {
+  52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
+  52, 52, 52, 52, 52, 52, 52
+};
+
+static DfaState st4[17] = {
+  52, 52, 52, 16, 17, 52, 52, 18, 18, 52, 
+  52, 52, 52, 52, 52, 52, 52
+};
+
+static DfaState st5[17] = {
+  52, 52, 52, 19, 52, 52, 52, 52, 52, 52, 
+  52, 52, 52, 52, 52, 52, 52
+};
+
+static DfaState st6[17] = {
+  52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
+  52, 52, 52, 52, 52, 52, 52
+};
+
+static DfaState st7[17] = {
+  52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
+  52, 52, 52, 52, 52, 52, 52
+};
+
+static DfaState st8[17] = {
+  52, 52, 52, 18, 52, 52, 52, 18, 18, 52, 
+  52, 52, 52, 52, 52, 52, 52
+};
+
+static DfaState st9[17] = {
+  52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
+  52, 52, 52, 52, 52, 52, 52
+};
+
+static DfaState st10[17] = {
+  52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
+  52, 52, 52, 52, 52, 52, 52
+};
+
+static DfaState st11[17] = {
+  52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
+  52, 52, 52, 52, 52, 52, 52
+};
+
+static DfaState st12[17] = {
+  52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
+  52, 52, 52, 52, 52, 52, 52
+};
+
+static DfaState st13[17] = {
+  52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
+  52, 52, 52, 52, 52, 52, 52
+};
+
+static DfaState st14[17] = {
+  52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
+  52, 52, 52, 52, 52, 52, 52
+};
+
+static DfaState st15[17] = {
+  52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
+  52, 52, 52, 52, 52, 52, 52
+};
+
+static DfaState st16[17] = {
+  52, 52, 52, 18, 52, 52, 52, 18, 18, 52, 
+  52, 52, 52, 52, 52, 52, 52
+};
+
+static DfaState st17[17] = {
+  52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
+  52, 52, 52, 52, 52, 52, 52
+};
+
+static DfaState st18[17] = {
+  52, 52, 52, 18, 52, 52, 52, 18, 18, 52, 
+  52, 52, 52, 52, 52, 52, 52
+};
+
+static DfaState st19[17] = {
+  52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
+  52, 52, 52, 52, 52, 52, 52
+};
+
+static DfaState st20[6] = {
+  21, 22, 23, 24, 25, 52
+};
+
+static DfaState st21[6] = {
+  52, 52, 52, 52, 52, 52
+};
+
+static DfaState st22[6] = {
+  52, 24, 26, 24, 52, 52
+};
+
+static DfaState st23[6] = {
+  52, 27, 23, 24, 52, 52
+};
+
+static DfaState st24[6] = {
+  52, 24, 23, 24, 52, 52
+};
+
+static DfaState st25[6] = {
+  52, 52, 52, 52, 52, 52
+};
+
+static DfaState st26[6] = {
+  52, 27, 23, 24, 52, 52
+};
+
+static DfaState st27[6] = {
+  52, 24, 23, 24, 52, 52
+};
+
+static DfaState st28[4] = {
+  29, 30, 31, 52
+};
+
+static DfaState st29[4] = {
+  52, 52, 52, 52
+};
+
+static DfaState st30[4] = {
+  52, 52, 52, 52
+};
+
+static DfaState st31[4] = {
+  52, 52, 31, 52
+};
+
+static DfaState st32[11] = {
+  33, 34, 35, 36, 36, 36, 36, 36, 36, 36, 
+  52
+};
+
+static DfaState st33[11] = {
+  52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
+  52
+};
+
+static DfaState st34[11] = {
+  52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
+  52
+};
+
+static DfaState st35[11] = {
+  52, 37, 37, 38, 39, 40, 41, 42, 43, 37, 
+  52
+};
+
+static DfaState st36[11] = {
+  52, 52, 52, 36, 36, 36, 36, 36, 36, 36, 
+  52
+};
+
+static DfaState st37[11] = {
+  52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
+  52
+};
+
+static DfaState st38[11] = {
+  52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
+  52
+};
+
+static DfaState st39[11] = {
+  52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
+  52
+};
+
+static DfaState st40[11] = {
+  52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
+  52
+};
+
+static DfaState st41[11] = {
+  52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
+  52
+};
+
+static DfaState st42[11] = {
+  52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
+  52
+};
+
+static DfaState st43[11] = {
+  52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 
+  52
+};
+
+static DfaState st44[6] = {
+  45, 46, 47, 48, 49, 52
+};
+
+static DfaState st45[6] = {
+  52, 52, 52, 52, 52, 52
+};
+
+static DfaState st46[6] = {
+  52, 52, 52, 52, 52, 52
+};
+
+static DfaState st47[6] = {
+  52, 52, 50, 52, 52, 52
+};
+
+static DfaState st48[6] = {
+  52, 52, 52, 51, 52, 52
+};
+
+static DfaState st49[6] = {
+  52, 52, 52, 52, 52, 52
+};
+
+static DfaState st50[6] = {
+  52, 52, 50, 52, 52, 52
+};
+
+static DfaState st51[6] = {
+  52, 52, 52, 51, 52, 52
+};
+
+
+DfaState *dfa[52] = {
+       st0,
+       st1,
+       st2,
+       st3,
+       st4,
+       st5,
+       st6,
+       st7,
+       st8,
+       st9,
+       st10,
+       st11,
+       st12,
+       st13,
+       st14,
+       st15,
+       st16,
+       st17,
+       st18,
+       st19,
+       st20,
+       st21,
+       st22,
+       st23,
+       st24,
+       st25,
+       st26,
+       st27,
+       st28,
+       st29,
+       st30,
+       st31,
+       st32,
+       st33,
+       st34,
+       st35,
+       st36,
+       st37,
+       st38,
+       st39,
+       st40,
+       st41,
+       st42,
+       st43,
+       st44,
+       st45,
+       st46,
+       st47,
+       st48,
+       st49,
+       st50,
+       st51
+};
+
+
+DfaState accepts[53] = {
+  0, 1, 2, 3, 9, 0, 7, 8, 9, 10, 
+  11, 12, 13, 14, 15, 16, 5, 4, 9, 6, 
+  0, 17, 21, 21, 21, 20, 18, 19, 0, 22, 
+  23, 24, 0, 25, 26, 27, 35, 34, 28, 29, 
+  30, 31, 32, 33, 0, 36, 37, 38, 39, 40, 
+  38, 39, 0
+};
+
+void (*actions[41])() = {
+       zzerraction,
+       act1,
+       act2,
+       act3,
+       act4,
+       act5,
+       act6,
+       act7,
+       act8,
+       act9,
+       act10,
+       act11,
+       act12,
+       act13,
+       act14,
+       act15,
+       act16,
+       act17,
+       act18,
+       act19,
+       act20,
+       act21,
+       act22,
+       act23,
+       act24,
+       act25,
+       act26,
+       act27,
+       act28,
+       act29,
+       act30,
+       act31,
+       act32,
+       act33,
+       act34,
+       act35,
+       act36,
+       act37,
+       act38,
+       act39,
+       act40
+};
+
+static DfaState dfa_base[] = {
+       0,
+       20,
+       28,
+       32,
+       44
+};
+
+static unsigned char *b_class_no[] = {
+       shift0,
+       shift1,
+       shift2,
+       shift3,
+       shift4
+};
+
+
+
+#define ZZSHIFT(c) (b_class_no[zzauto][1+c])
+#define MAX_MODE 5
+#include "dlgauto.h"
diff --git a/libFoundation/Foundation/NSTask.h b/libFoundation/Foundation/NSTask.h
new file mode 100644 (file)
index 0000000..ecda9b3
--- /dev/null
@@ -0,0 +1,77 @@
+/* 
+   NSTask.h
+
+   Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@net-community.com>
+
+   Based on the code written by Aleksandr Savostyanov <sav@conextions.com>.
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSTask_h__
+#define __NSTask_h__
+
+#include <Foundation/NSObject.h>
+
+@class NSString, NSArray, NSDictionary, NSFileHandle;
+
+LF_EXPORT NSString *NSTaskDidTerminateNotification;
+
+@interface NSTask : NSObject
+
++ (NSTask *)launchedTaskWithLaunchPath:(NSString *)path
+  arguments:(NSArray *)arguments;
+
+- (void)setLaunchPath:(NSString *)path;
+- (void)setArguments:(NSArray *)arguments;
+- (void)setEnvironment:(NSDictionary *)dict;
+- (void)setCurrentDirectoryPath:(NSString *)path;
+
+- (void)setStandardInput:(id)input;
+- (void)setStandardOutput:(id)output;
+- (void)setStandardError:(id)error;
+
+- (NSString *)launchPath;
+- (NSArray *)arguments;
+- (NSDictionary *)environment;
+- (NSString *)currentDirectoryPath;
+
+- (id)standardInput;
+- (id)standardOutput;
+- (id)standardError;
+
+- (void)launch;
+- (void)terminate;
+- (void)interrupt;
+- (BOOL)isRunning;
+- (int)terminationStatus;
+- (void)waitUntilExit;
+
+- (unsigned int)processId;
+
+@end
+
+#endif /* __NSTask_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSTask.m b/libFoundation/Foundation/NSTask.m
new file mode 100644 (file)
index 0000000..3221443
--- /dev/null
@@ -0,0 +1,197 @@
+/* 
+   NSTask.m
+
+   Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@net-community.com>
+
+   Based on the code written by Aleksandr Savostyanov <sav@conextions.com>.
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <config.h>
+#include <extensions/objc-runtime.h>
+
+#include <Foundation/common.h>
+#include <Foundation/NSTask.h>
+#include <Foundation/NSProcessInfo.h>
+#include <Foundation/NSUtilities.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+
+#if defined(__WIN32__)
+#  ifdef __CYGWIN32__
+#    warning using win task on Cygwin32
+#  endif
+#  include "NSConcreteWindowsTask.h"
+#  define NSConcreteTask NSConcreteWindowsTask
+#else
+#  ifdef __CYGWIN32__
+#    warning using unix task on Cygwin32
+#  endif
+#  include "NSConcreteUnixTask.h"
+#  define NSConcreteTask NSConcreteUnixTask
+#endif
+
+NSString *NSTaskDidTerminateNotification = @"NSTaskDidTerminateNotification";
+
+@implementation NSTask
+
++ (id)allocWithZone:(NSZone*)zone
+{
+    NSTask *task = NSAllocateObject((self == [NSTask class]) ? 
+                                    [NSConcreteTask class] : self, 0, zone);
+    return task;
+}
+
++ (NSTask *)launchedTaskWithLaunchPath:(NSString*)path
+  arguments:(NSArray*)arguments
+{
+    id aTask;
+    
+    aTask = [[NSConcreteTask alloc] init];
+    [aTask setLaunchPath:path];
+    [aTask setArguments:arguments];
+    [aTask setEnvironment:[[NSProcessInfo processInfo] environment]];
+    [aTask launch];
+
+    return AUTORELEASE(aTask);
+}
+
+- (void)setLaunchPath:(NSString *)path
+{
+    [self shouldNotImplement:_cmd];
+}
+
+- (void)setArguments:(NSArray*)arguments
+{
+    [self shouldNotImplement:_cmd];
+}
+
+- (void)setEnvironment:(NSDictionary*)dict
+{
+    [self shouldNotImplement:_cmd];
+}
+
+- (void)setCurrentDirectoryPath:(NSString*)path
+{
+    [self shouldNotImplement:_cmd];
+}
+
+- (void)setStandardInput:(id)input
+{
+    [self shouldNotImplement:_cmd];
+}
+
+- (void)setStandardOutput:(id)output
+{
+    [self shouldNotImplement:_cmd];
+}
+
+- (void)setStandardError:(id)error
+{
+    [self shouldNotImplement:_cmd];
+}
+
+- (NSString*)launchPath
+{
+    [self shouldNotImplement:_cmd];
+    return nil;
+}
+
+- (NSArray*)arguments
+{
+    [self shouldNotImplement:_cmd];
+    return nil;
+}
+
+- (NSDictionary*)environment
+{
+    [self shouldNotImplement:_cmd];
+    return nil;
+}
+
+- (NSString*)currentDirectoryPath
+{
+    [self shouldNotImplement:_cmd];
+    return nil;
+}
+
+- (id)standardInput
+{
+    [self shouldNotImplement:_cmd];
+    return nil;
+}
+
+- (id)standardOutput
+{
+    [self shouldNotImplement:_cmd];
+    return nil;
+}
+
+- (id)standardError
+{
+    [self shouldNotImplement:_cmd];
+    return nil;
+}
+
+- (void)launch
+{
+    [self shouldNotImplement:_cmd];
+}
+
+- (void)terminate
+{
+    [self shouldNotImplement:_cmd];
+}
+
+- (void)interrupt
+{
+    [self shouldNotImplement:_cmd];
+}
+
+- (BOOL)isRunning
+{
+    [self shouldNotImplement:_cmd];
+    return NO;
+}
+
+- (int)terminationStatus
+{
+    [self shouldNotImplement:_cmd];
+    return 0;
+}
+
+- (void)waitUntilExit
+{
+    [self shouldNotImplement:_cmd];
+}
+
+- (unsigned int)processId
+{
+    [self shouldNotImplement:_cmd];
+    return 0;
+}
+
+@end /* NSTask */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSThread.h b/libFoundation/Foundation/NSThread.h
new file mode 100644 (file)
index 0000000..66fa523
--- /dev/null
@@ -0,0 +1,88 @@
+/* 
+   NSThread.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSThread_h__
+#define __NSThread_h__
+
+#include <Foundation/NSObject.h>
+
+@class NSDate;
+@class NSString;
+@class NSMutableDictionary;
+
+enum {
+    NSInteractiveThreadPriority,
+    NSBackgroundThreadPriority,
+    NSLowThreadPriority
+};
+
+@interface NSThread : NSObject
+{
+    /* global thread info */
+    id   threadDictionary;
+    BOOL isRunning;
+    id   target;
+    SEL  selector;
+    id   arg;
+    id   privateThreadData;
+}
+
++ (NSThread*)currentThread;
++ (void)exit;
++ (BOOL)isMultiThreaded;
++ (void)sleepUntilDate:(NSDate*)aDate;
++ (void)detachNewThreadSelector:(SEL)aSelector 
+  toTarget:(id)aTarget withObject:(id)anArgument;
+- (NSMutableDictionary*)threadDictionary;
+
+/* Private method */
+- (id)_privateThreadData;
+
+@end /* NSThread */
+
+/* Thead notifications */
+
+LF_EXPORT NSString *NSWillBecomeMultiThreadedNotification;
+LF_EXPORT NSString *NSThreadWillExitNotification;
+
+/* GNUstep compatibility */
+
+@interface NSThread(GNUstepCompatibility)
+
++ (BOOL)registerCurrentThread;
++ (void)unregisterCurrentThread;
+
+LF_EXPORT NSThread *GSCurrentThread(void);
+LF_EXPORT NSString *NSThreadDidStartNotification;
+
+@end
+
+#endif /* __NSThread_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSThread.m b/libFoundation/Foundation/NSThread.m
new file mode 100644 (file)
index 0000000..d3b5b54
--- /dev/null
@@ -0,0 +1,292 @@
+/* 
+   NSThread.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+
+#include <time.h>
+
+#if HAVE_SYS_TIME_H
+# include <sys/time.h> /* for struct timeval */
+#endif
+
+#if HAVE_LIBC_H
+# include <libc.h>
+#else
+# include <unistd.h>
+#endif
+
+#if HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif
+
+#if defined(__MINGW32__)
+# include <windows.h>
+#endif
+
+#include <Foundation/common.h>
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSNotification.h>
+#include <Foundation/NSUtilities.h>
+#include <Foundation/NSObjCRuntime.h>
+#include <Foundation/NSThread.h>
+#include <Foundation/NSLock.h>
+#include <Foundation/NSDate.h>
+#include <Foundation/NSRunLoop.h>
+#include <Foundation/NSNotificationQueue.h>
+
+#include <Foundation/NSException.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+
+#include <extensions/objc-runtime.h>
+#include "PrivateThreadData.h"
+
+/*
+    NSAutoreleasePool must be changed to return a default pool from 
+    the current thread autorelease stack and to operate on that stack
+    when pools are allocated and deallocated. The overhead is one more
+    method call in +[NSAutoreleasePool defaultPool] to 
+    +[NSThread currentThread].
+
+    NSExceptions && exception handlers must be changed to use current
+    thread top-level handler instead of internal static variable. The
+    overhead is not important since handler are not pushed/extracted
+    too often.
+ */
+
+/* NSThread notifications */
+
+LF_DECLARE NSString* NSWillBecomeMultiThreadedNotification = 
+       @"NSWillBecomeMultiThreadedNotification";
+LF_DECLARE NSString* NSThreadWillExitNotification =
+       @"NSThreadWillExitNotification";
+
+/* Global thread variables */
+
+static BOOL     isMultiThreaded = NO;
+static NSThread *mainThread = nil;
+
+@implementation NSThread
+
+/*
+ * Instance Methods
+ */
+
+- (id)initWithTarget:(id)aTarget selector:(SEL)aSelector argument:(id)anArgument
+{
+    // Not yet running
+    isRunning = NO;
+
+    // Set running parameters
+    target = RETAIN(aTarget);
+    selector = aSelector;
+    arg = RETAIN(anArgument);
+
+    // Thread dictionary
+    threadDictionary = [NSMutableDictionary new];
+    privateThreadData = [PrivateThreadData new];
+    
+    return self;
+}
+
+- (void)run
+{
+    // Set current thread data (must be done before the autorelease pool is
+    // created)
+    objc_thread_set_data(self);
+    {
+        CREATE_AUTORELEASE_POOL(pool);
+
+        [privateThreadData threadWillStart];
+
+        // Run
+        [target performSelector:selector withObject:arg];
+
+        // pool cleanup
+        RELEASE(pool);
+    }
+}
+
+- (void)exit
+{
+    [privateThreadData threadExit];
+    objc_thread_exit();
+}
+
+- (NSMutableDictionary*)threadDictionary
+{
+    return threadDictionary;
+}
+
+- (void)dealloc
+{
+    if (isRunning) {
+       [[[InvalidUseOfMethodException alloc] initWithFormat:
+           @"cannot deallocate NSThread for running thread"] raise];
+    }
+    RELEASE(target);
+    RELEASE(arg);
+    RELEASE(threadDictionary);
+    RELEASE(privateThreadData);
+    [super dealloc];
+}
+
+- (id)_privateThreadData
+{
+    return privateThreadData;
+}
+
+/*
+ * Class Methods
+ */
+
++ (void)initialize
+{
+    // We are still in non-multithread state
+    if (mainThread == nil) {
+       mainThread = [NSThread alloc];
+       mainThread->threadDictionary  = [NSMutableDictionary new];
+       mainThread->privateThreadData = [PrivateThreadData new];;
+       objc_thread_set_data(mainThread);
+    }
+}
+
+#if HAVE_OBJC_THREAD_CREATE
+static void nsThreadStartThread(id thread)
+{
+    [thread run];
+//    [thread exit];
+    RELEASE(thread); thread = nil;
+}
+#else
++ (void)_runThread:(NSThread*)thread
+{
+    [thread run];
+//    [thread exit];
+    RELEASE(thread); thread = nil;
+}
+#endif
+
++ (void)detachNewThreadSelector:(SEL)aSelector 
+  toTarget:(id)aTarget withObject:(id)anArgument
+{
+    id thread = [[self alloc] 
+       initWithTarget:aTarget selector:aSelector argument:anArgument];
+    
+    if (!isMultiThreaded) {
+       [NSAutoreleasePool     taskNowMultiThreaded:nil];
+       [NSException           taskNowMultiThreaded:nil];
+       [NSRunLoop             taskNowMultiThreaded:nil];
+       [NSNotificationQueue   taskNowMultiThreaded:nil];
+       [NSNotificationCenter  taskNowMultiThreaded:nil];
+       [[NSNotificationCenter defaultCenter]
+           postNotificationName:NSWillBecomeMultiThreadedNotification
+           object:nil userInfo:nil];
+       isMultiThreaded = YES;
+    }
+    
+#if HAVE_OBJC_THREAD_CREATE
+    objc_thread_create((void(*)(void*arg))nsThreadStartThread, thread);
+#else
+    if (objc_thread_detach(@selector(_runThread:), self, thread) == NULL) {
+        // thread creation failed
+        RELEASE(thread); thread = nil;
+        [NSException raise:@"NSThreadCreationFailedException"
+                     format:@"creation of Objective-C thread failed."];
+    }
+#endif
+}
+
++ (NSThread *)currentThread
+{
+    return isMultiThreaded ? (NSThread *)objc_thread_get_data() : mainThread;
+}
+
++ (void)exit
+{
+    [[NSNotificationCenter defaultCenter]
+       postNotificationName:NSThreadWillExitNotification
+       object:self userInfo:nil];
+    [[self currentThread] exit];
+}
+
++ (BOOL)isMultiThreaded
+{
+    return isMultiThreaded;
+}
+
++ (void)sleepUntilDate:(NSDate*)aDate
+{
+    NSTimeInterval delay = 0;
+    
+    if (!aDate) return;
+    if([aDate earlierDate:[NSDate date]] == aDate) return;
+    delay = [aDate timeIntervalSinceNow];
+
+#if defined(__MINGW32__)
+    Sleep((DWORD)(delay * 1000.0));
+#else
+    {
+        struct timeval tp = { 0, 0 };
+        struct timeval *timeout = NULL;
+        fd_set set;
+
+        tp.tv_sec = delay;
+        tp.tv_usec = (delay - (NSTimeInterval)tp.tv_sec) * 1000000.0;
+        timeout = &tp;
+
+        FD_ZERO(&set);
+        select(FD_SETSIZE, &set, NULL, NULL, timeout);
+    }
+#endif
+}
+
+/* registering external threads (GNUstep extension) */
+
++ (BOOL)registerCurrentThread
+{
+    return NO;
+}
++ (void)unregisterCurrentThread
+{
+}
+
+NSThread *GSCurrentThread(void)
+{
+    /* for GNUstep compatibility */
+    return [NSThread currentThread];
+}
+
+NSString *NSThreadDidStartNotification =
+       @"NSThreadDidStartNotification";
+
+@end /* NSThread */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSTimeZone.h b/libFoundation/Foundation/NSTimeZone.h
new file mode 100644 (file)
index 0000000..b92854a
--- /dev/null
@@ -0,0 +1,37 @@
+/* 
+   NSTimeZone.h
+
+   Copyright (C) 2004 Helge Hess.
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@opengroupware.org>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSTimeZone_H__
+#define __NSTimeZone_H__
+
+#include <Foundation/NSDate.h>
+
+#endif /* __NSTimeZone_H__
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSTimeZone.m b/libFoundation/Foundation/NSTimeZone.m
new file mode 100644 (file)
index 0000000..44abb02
--- /dev/null
@@ -0,0 +1,475 @@
+/* 
+   NSTimeZone.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+          Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSDate.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSUtilities.h>
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/NSProcessInfo.h>
+#include <Foundation/NSUserDefaults.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSCoder.h>
+#include <Foundation/NSBundle.h>
+#include <Foundation/NSFileManager.h>
+#include <Foundation/NSPathUtilities.h>
+
+#include "NSConcreteTimeZone.h"
+
+/*
+ * NSTimeZone cluster abstract class
+ */
+
+static NSString            *timeZoneInfoFilesPath  = nil;
+static NSMutableDictionary *abbreviationDictionary = nil;
+static NSArray             *timeZoneArray          = nil;
+static NSMutableDictionary *regionsByOffset        = nil;
+static NSMutableDictionary *timeZonesByName        = nil;
+static NSTimeZone          *defaultTimeZone        = nil;
+static NSTimeZone          *localTimeZone          = nil;
+
+@implementation NSTimeZone
+
++ (NSTimeZone *)_createTimeZoneWithName:(NSString *)name
+  checkDuplicates:(BOOL)checkDuplicates
+{
+    NSString   *filename;
+    NSTimeZone *concreteTimeZone;
+
+    if (checkDuplicates) {
+       if ([timeZonesByName objectForKey:name])
+           return nil;
+    }
+    
+    filename = [[[timeZoneInfoFilesPath
+                   stringByAppendingPathComponent:@"TimeZoneInfo"]
+                   stringByAppendingPathComponent:name]
+                   stringByResolvingSymlinksInPath];
+
+    if (filename) {
+        if (![[NSFileManager defaultManager] fileExistsAtPath:filename])
+            filename = nil;
+    }
+    
+    if ((filename == nil) || [filename length] == 0) {
+       fprintf(stderr,
+                "%s: Cannot find the time zone description file '%s' in "
+               "resource directory '%s'\n",
+                __PRETTY_FUNCTION__,
+               [name cString], [timeZoneInfoFilesPath cString]);
+       return nil;
+    }
+    
+    concreteTimeZone = AUTORELEASE([[NSConcreteTimeZoneFile alloc]
+                                       initFromFile:filename withName:name]);
+    [timeZonesByName setObject:concreteTimeZone forKey:name];
+
+    return concreteTimeZone;
+}
+
++ (void)initialize
+{
+    static BOOL didInit = NO;
+
+    if (didInit)
+       return;
+
+    didInit = YES;
+
+    {
+        id           regionsDictionary;
+        id           regionsFile = nil;
+        NSString     *offset;
+        NSEnumerator *enumerator;
+        NSString     *abbreviation;
+        CREATE_AUTORELEASE_POOL(pool);
+       
+        timeZonesByName = [[NSMutableDictionary alloc] init];
+        regionsFile = [NSBundle _fileResourceNamed:@"RegionsDictionary"
+                                extension:nil
+                                inDirectory:@"TimeZoneInfo"];
+        
+        if (regionsFile == nil || [regionsFile length] == 0) {
+            fprintf(stderr,
+                    "ERROR(%s): Cannot find the "
+                   "'TimeZoneInfo/RegionsDictionary' "
+                    "resource file for NSTimeZone\n",
+                   __PRETTY_FUNCTION__);
+            return;
+        }
+        timeZoneInfoFilesPath
+            = RETAIN([[regionsFile stringByDeletingLastPathComponent]
+                         stringByDeletingLastPathComponent]);
+        regionsDictionary = [[NSString stringWithContentsOfFile:regionsFile]
+                                propertyList];
+        
+        regionsByOffset = [[regionsDictionary objectForKey:@"RegionsByOffset"]
+                              mutableCopy];
+        if (regionsByOffset == nil) {
+            fprintf(stderr,
+                    "ERROR: No regions by offset in the '%s' resource file ("
+                    "under key 'RegionsByOffset')\n", [regionsFile cString]);
+            return;
+        }
+        
+        timeZoneArray = RETAIN([[regionsDictionary
+                                    objectForKey:@"RegionsByOffset"]
+                                   allValues]);
+        enumerator = [regionsByOffset keyEnumerator];
+        while ((offset = [enumerator nextObject])) {
+            NSMutableArray *longitudinalRegions
+                = AUTORELEASE([[regionsByOffset objectForKey:offset]
+                                  mutableCopy]);
+            int j, count2;
+
+            [regionsByOffset setObject:longitudinalRegions forKey:offset];
+            for (j = 0, count2 = [longitudinalRegions count]; j < count2; j++){
+                NSString* timeZoneName = [longitudinalRegions objectAtIndex:j];
+                NSTimeZone* timeZone;
+
+                timeZone = [timeZonesByName objectForKey:timeZoneName];
+                if (!timeZone)
+                    timeZone = [self _createTimeZoneWithName:timeZoneName
+                                     checkDuplicates:NO];
+
+                [longitudinalRegions replaceObjectAtIndex:j
+                                     withObject:timeZone];
+            }
+        }
+
+        abbreviationDictionary = [[regionsDictionary
+                                      objectForKey:@"Abbreviations"]
+                                     mutableCopy];
+        if (abbreviationDictionary == nil) {
+            fprintf(stderr,
+                    "ERROR: No abbreviation dictionary in the '%s' "
+                    "resource file (under key 'Abbreviations')\n", 
+                    [regionsFile cString]);
+            return;
+        }
+        enumerator = [abbreviationDictionary keyEnumerator];
+        while ((abbreviation = [enumerator nextObject])) {
+            NSString* timeZoneName
+               = [abbreviationDictionary objectForKey:abbreviation];
+            NSTimeZone* timeZone = [timeZonesByName objectForKey:timeZoneName];
+
+            if (timeZone == nil) {
+                fprintf(stderr,
+                        "warning: time zone '%s' is not declared in the "
+                        "'RegionsByOffset' dictionary in resource file '%s'\n",
+                        [timeZoneName cString], [regionsFile cString]);
+                timeZone = [self _createTimeZoneWithName:timeZoneName
+                                 checkDuplicates:NO];
+            }
+
+            if (timeZone)
+                [abbreviationDictionary setObject:timeZone
+                                        forKey:abbreviation];
+        }
+
+        RELEASE(pool);
+    }
+}
+
++ (void)setDefaultTimeZone:(NSTimeZone*)aTimeZone
+{
+#if SYNC_DEF_TZ
+    NSUserDefaults* userDef = [NSUserDefaults standardUserDefaults];
+#endif
+
+    ASSIGN(defaultTimeZone, aTimeZone);
+    ASSIGN(localTimeZone,   aTimeZone);
+
+#if SYNC_DEF_TZ
+    [userDef setObject:[defaultTimeZone timeZoneName] forKey:@"TimeZoneName"];
+    [userDef synchronize];
+#endif
+}
+
++ (NSTimeZone *)defaultTimeZone
+{
+    if (defaultTimeZone == nil) {
+       NSUserDefaults *userDef;
+       NSString       *zName;
+       static BOOL isSettingTZ = NO; /* protect against recursion */
+       
+       if (isSettingTZ) {
+           /* do not use NSLog, which uses NSTimeZone => recursion ... */
+           fprintf(stderr, 
+                   "ERROR(%s): recursive call! (libFoundation setup is "
+                   "probably mixed up)\n", 
+                   __PRETTY_FUNCTION__);
+           return nil;
+       }
+       
+       isSettingTZ = YES;
+       
+       userDef = [NSUserDefaults standardUserDefaults];
+       zName   = [userDef stringForKey:@"TimeZoneName"];
+       defaultTimeZone = RETAIN([self timeZoneWithName:zName]);
+       
+       if (defaultTimeZone == nil)
+           defaultTimeZone = RETAIN([self timeZoneWithAbbreviation:zName]);
+       
+       if (defaultTimeZone == nil)
+           defaultTimeZone = RETAIN([self timeZoneWithAbbreviation:@"GMT"]);
+       isSettingTZ = NO;
+    }
+
+    return defaultTimeZone;
+}
+
++ (NSTimeZone *)localTimeZone
+{
+    if (localTimeZone == nil) {
+       // TODO : subclass NS*TimeZone to have a special encoding class
+       localTimeZone = RETAIN([self defaultTimeZone]);
+    }
+    
+    return localTimeZone;
+}
+
++ (NSDictionary *)abbreviationDictionary
+{
+    return abbreviationDictionary;
+}
+
++ (NSArray *)timeZoneArray
+{
+    return timeZoneArray;
+}
+
++ (NSTimeZone *)timeZoneWithName:(NSString *)name
+{
+    NSTimeZone* timezone;
+
+    if (!name)
+       return nil;
+
+    if (!(timezone = [timeZonesByName objectForKey:name]))
+       timezone = [self _createTimeZoneWithName:name checkDuplicates:NO];
+
+    return timezone;
+}
+
++ (NSTimeZone *)timeZoneWithAbbreviation:(NSString *)abbreviation
+{
+    return [abbreviationDictionary objectForKey:abbreviation];
+}
+
++ (NSTimeZone *)timeZoneForSecondsFromGMT:(int)seconds
+{
+    BOOL              isNegative = (seconds < 0);
+    int               hours, minutes;
+    NSString*         offset;
+    NSArray*          timeZoneArray;
+    NSArray*          details;
+    NSTimeZoneDetail* detail;
+    NSTimeZone*       timeZone;
+    int               i, j, count1, count2;
+    unsigned          char buf[16];
+    
+    hours   = abs (seconds) / 3600;
+    minutes = (abs (seconds) - hours * 3600) / 60;
+    
+    sprintf(buf, "%c%02d%02d", (isNegative ? '-' : '+'), hours, minutes);
+    offset = [NSString stringWithCString:buf];
+    
+    timeZoneArray = [regionsByOffset objectForKey:offset];
+
+    /* If there is no matching zone create an instance of NSConcreteTimeZone
+       with a single detail whose offset is `seconds'. */
+    if (timeZoneArray == nil)
+       return [NSConcreteTimeZone timeZoneWithOffset:seconds];
+
+    /* Do a search to find a zone that has a detail with no daylight
+       saving which has the offset equal with `seconds'. */
+    for (i = 0, count1 = [timeZoneArray count]; i < count1; i++) {
+       timeZone = [timeZoneArray objectAtIndex:i];
+       details = [timeZone timeZoneDetailArray];
+
+       /* Find a time zone that has a detail which is not daylight saving
+          and has the offset equal with `seconds'. If no such detail is
+          found the search either continues or ends depending on the offset
+          of detail. */
+       for (j = 0, count2 = [details count]; j < count2; j++) {
+           detail = [details objectAtIndex:j];
+           if (![detail isDaylightSavingTimeZone]
+               && [detail timeZoneSecondsFromGMT] == seconds)
+                   return timeZone;
+       }
+    }
+
+    fprintf(stderr,
+            "warning: unexpected failure of +timeZoneForSecondsFromGMT: "
+           "method. All the timezones specified for offset %s do not "
+           "contain a detail whose non daylight saving offset is equal to "
+           "%s!\n", [offset cString], [offset cString]);
+
+    /* Return something useful even if there was an error! */
+    return [NSConcreteTimeZone timeZoneWithOffset:seconds];
+}
+
+- (NSString *)timeZoneName
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+- (NSArray *)timeZoneDetailArray
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+- (NSTimeZoneDetail *)timeZoneDetailForDate:(NSDate *)date
+{
+    /* deprecated in MacOSXS */
+    return (id)[self timeZoneForDate:date];
+}
+- (NSTimeZone *)timeZoneForDate:(NSDate *)date
+{
+    /* new in MacOSXS */
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+- (NSString *)description
+{
+    return [[self timeZoneName] description];
+}
+
+// New methods in MacOSX
+
+- (NSString *)abbreviation
+{
+    return [self abbreviationForDate:[NSCalendarDate date]];
+}
+- (NSString *)abbreviationForDate:(NSDate *)_date
+{
+    return [[self timeZoneForDate:_date] timeZoneAbbreviation];
+}
+
+- (BOOL)isDaylightSavingTime
+{
+    return [self isDaylightSavingTimeForDate:[NSCalendarDate date]];
+}
+- (BOOL)isDaylightSavingTimeForDate:(NSDate *)_date
+{
+    return [[self timeZoneForDate:_date] isDaylightSavingTimeZone];
+}
+
+- (int)secondsFromGMT
+{
+    return [self secondsFromGMTForDate:[NSCalendarDate date]];
+}
+- (int)secondsFromGMTForDate:(NSDate *)_date
+{
+    return [[self timeZoneForDate:_date] timeZoneSecondsFromGMT];
+}
+
+- (int)timeZoneSecondsFromGMT
+{      
+    [self subclassResponsibility:_cmd];
+    return 0;
+}
+
+- (NSString *)timeZoneAbbreviation
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+- (BOOL)isDaylightSavingTimeZone
+{
+    [self subclassResponsibility:_cmd];
+    return NO;
+}
+
+/* equality */
+
+- (BOOL)isEqual:(id)anObject
+{
+    if (anObject == self) return YES;
+
+    return ([super isEqual:anObject]
+       // this checks to ensure that they're the same class
+       && [[self timeZoneName] isEqual:[anObject timeZoneName]]
+       && [[self timeZoneAbbreviation] 
+               isEqual:[anObject timeZoneAbbreviation]]
+       && [self isDaylightSavingTimeZone] 
+               == [anObject isDaylightSavingTimeZone]
+       && [self timeZoneSecondsFromGMT] 
+               == [anObject timeZoneSecondsFromGMT]);
+}
+
+- (unsigned)hash
+{
+    // This should be sufficient for hashing
+    return [self timeZoneSecondsFromGMT];
+}
+
+/* NSCoding */
+
+- (Class)classForCoder
+{
+    return [NSTimeZone class];
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+    [aCoder encodeObject:[self timeZoneName]];
+}
+
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+    NSString *timeZoneName = [aDecoder decodeObject];
+    return [NSTimeZone timeZoneWithName:timeZoneName];
+}
+
+@end /* NSTimeZone */
+
+/*
+ * NSTimeZone detail (concrete non-mutable subclass of NSTimeZone)
+ */
+
+@implementation NSTimeZoneDetail /* deprecated in MacOSXS */
+
+@end /* NSTimeZoneDetail */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSTimer.h b/libFoundation/Foundation/NSTimer.h
new file mode 100644 (file)
index 0000000..f8e3790
--- /dev/null
@@ -0,0 +1,96 @@
+/* 
+   NSTimer.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSTimer_h__
+#define __NSTimer_h__
+
+#include <Foundation/NSObject.h>
+#include <Foundation/NSDate.h>
+
+@class NSDate;
+@class NSInvocation;
+
+/*
+ * NSTimer class
+ */
+
+@interface NSTimer : NSObject
+{
+    NSTimeInterval     timeInterval;
+    NSDate*            fireDate;
+    NSInvocation*      invocation;
+    id                 userInfo;
+    BOOL               repeats;
+    BOOL               isValid;
+}
+
++ (NSTimer*)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds
+  invocation:(NSInvocation*)anInvocation repeats:(BOOL)repeats;
+
++ (NSTimer*)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds
+  target:(id)anObject selector:(SEL)aSelector
+  userInfo:(id)anArgument repeats:(BOOL)repeats;
+
++ (NSTimer*)timerWithTimeInterval:(NSTimeInterval)seconds
+  invocation:(NSInvocation*)anInvocation repeats:(BOOL)repeats;
+
++ (NSTimer*)timerWithTimeInterval:(NSTimeInterval)seconds
+  target:(id)anObject selector:(SEL)aSelector
+  userInfo:(id)anArgument repeats:(BOOL)repeats; 
+
+/* Firing the Timer */
+- (void)fire;
+
+/* Stopping the Timer */
+- (void)invalidate;
+
+/* Getting Information About the NSTimer */
+- (NSDate*)fireDate;
+
+- (id)userInfo;
+
+- (BOOL)isValid;
+- (BOOL)repeats;
+
+- (NSTimeInterval)timeInterval;
+
+@end
+
+/*
+ * NSTimer implementation messages
+ */
+@interface NSTimer(NSTimerImplementation)
+- (id)initWith:(NSTimeInterval)seconds invocation:(NSInvocation*)anInvocation
+  userInfo:(id)anObject repeat:(BOOL)repeats;
+@end
+
+#endif /* __NSTimer_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSTimer.m b/libFoundation/Foundation/NSTimer.m
new file mode 100644 (file)
index 0000000..4a990a3
--- /dev/null
@@ -0,0 +1,210 @@
+/* 
+   NSTimer.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <stdio.h>
+#include <math.h>
+
+#include <Foundation/common.h>
+#include <Foundation/NSTimer.h>
+#include <Foundation/NSDate.h>
+#include <Foundation/NSInvocation.h>
+#include <Foundation/NSRunLoop.h>
+
+#include <extensions/objc-runtime.h>
+
+@implementation NSTimer
++ (NSTimer*)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds
+    invocation:(NSInvocation*)anInvocation
+    repeats:(BOOL)_repeats
+{
+    id timer = [self timerWithTimeInterval:seconds
+                       invocation:anInvocation
+                       repeats:_repeats];
+    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
+    return timer;
+}
+
++ (NSTimer*)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds
+    target:(id)anObject
+    selector:(SEL)aSelector
+    userInfo:(id)anArgument
+    repeats:(BOOL)_repeats
+{
+    id timer = [self timerWithTimeInterval:seconds
+                       target:anObject
+                       selector:aSelector
+                       userInfo:anArgument
+                       repeats:_repeats];
+    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
+    return timer;
+}
+
++ (NSTimer*)timerWithTimeInterval:(NSTimeInterval)seconds
+    invocation:(NSInvocation*)anInvocation
+    repeats:(BOOL)_repeats
+{
+    id timer = AUTORELEASE([[self alloc]
+                               initWith:seconds invocation:anInvocation
+                               userInfo:nil repeat:_repeats]);
+    return timer;
+}
+
++ (NSTimer*)timerWithTimeInterval:(NSTimeInterval)seconds
+    target:(id)anObject
+    selector:(SEL)aSelector
+    userInfo:(id)anArgument
+    repeats:(BOOL)_repeats
+{
+    id anInvocation = [NSInvocation invocationWithMethodSignature:
+                       [anObject methodSignatureForSelector:aSelector]];
+    id timer = AUTORELEASE([[self alloc]
+                               initWith:seconds invocation:anInvocation
+                               userInfo:anArgument repeat:_repeats]);
+    [anInvocation setTarget:anObject];
+    [anInvocation setSelector:aSelector];
+    if ([[anInvocation methodSignature] numberOfArguments] > 2)
+       [anInvocation setArgument:&timer atIndex:2];
+    [anInvocation retainArguments];
+
+    return timer;
+}
+
+- (void)dealloc
+{
+    RELEASE(fireDate);
+    RELEASE(invocation);
+    RELEASE(userInfo);
+    [super dealloc];
+}
+
+- (NSString *)description
+{
+    /* Don't use -[NSString stringWithFormat:] method because it can cause
+       infinite recursion. */
+    char buffer[1024];
+    NSDate *fd;
+
+    fd = [self fireDate];
+
+    sprintf (buffer,
+           "<%s %p fireDate: %s selector: %s repeats: %s isValid: %s>",
+           (char*)object_get_class_name(self),
+           self,
+           fd ? [[fd description] cString] : "nil",
+           [invocation selector]
+               ? [NSStringFromSelector([invocation selector]) cString]
+               : "nil",
+           repeats ? "YES" : "NO",
+           isValid ? "YES" : "NO");
+
+    return [NSString stringWithCString:buffer];
+}
+
+- (void)fire
+{
+    if(self->isValid)
+       [self->invocation invoke];
+    
+    if(self->repeats) {
+        NSTimeInterval ellapsedTimeSinceCreated;
+        NSTimeInterval nextTime;
+       NSDate         *newDate;
+
+        ellapsedTimeSinceCreated = -[fireDate timeIntervalSinceNow];
+        nextTime = ceil(ellapsedTimeSinceCreated / timeInterval) * timeInterval;
+       newDate  = [fireDate addTimeInterval:nextTime];
+        
+       ASSIGN(self->fireDate, newDate);
+    }
+}
+
+- (NSDate *)fireDate
+{
+    if(!self->repeats)
+       return [self->fireDate addTimeInterval:self->timeInterval];
+    else {
+       NSTimeInterval ellapsedTimeSinceCreated, nextTime;
+
+        ellapsedTimeSinceCreated = -[fireDate timeIntervalSinceNow];
+        nextTime = ceil(ellapsedTimeSinceCreated / timeInterval) * timeInterval;
+       return [self->fireDate addTimeInterval:nextTime];
+    }
+}
+
+- (void)invalidate
+{
+    if (self->isValid) {
+#if 0
+        /*hh: why was this ??? */
+       [self->invocation invalidate];
+#endif
+       self->isValid = NO;
+    }
+}
+
+- (id)userInfo
+{
+    return self->userInfo;
+}
+- (BOOL)isValid
+{
+    return self->isValid;
+}
+- (BOOL)repeats
+{
+    return self->repeats;
+}
+
+- (NSTimeInterval)timeInterval
+{
+    return self->timeInterval;
+}
+
+@end
+
+/*
+ * NSTimer implementation messages
+ */
+@implementation NSTimer(NSTimerImplementation)
+- initWith:(NSTimeInterval)seconds invocation:(NSInvocation*)anInvocation
+    userInfo:(id)anObject repeat:(BOOL)_repeats
+{
+    timeInterval = seconds;
+    fireDate = RETAIN([NSDate date]);
+    invocation = RETAIN(anInvocation);
+    userInfo = RETAIN(anObject);
+    repeats = _repeats;
+    isValid = YES;
+    return self;
+}
+
+@end
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSURL.h b/libFoundation/Foundation/NSURL.h
new file mode 100644 (file)
index 0000000..3fdac28
--- /dev/null
@@ -0,0 +1,99 @@
+/* 
+   NSURL.h
+
+   Copyright (C) 2000 MDlink GmbH, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSURL_h__
+#define __NSURL_h__
+
+#include <Foundation/NSObject.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSURLHandle.h>
+
+@class NSData, NSNumber;
+
+LF_EXPORT NSString *NSURLFileScheme;
+
+@interface NSURL : NSObject < NSCoding, NSCopying, NSURLHandleClient >
+{
+    id currentClient;
+}
+
++ (id)URLWithString:(NSString *)_str;
++ (id)URLWithString:(NSString *)_str relativeToURL:(NSURL *)_base;
++ (id)fileURLWithPath:(NSString *)_path;
+
+- (id)initFileURLWithPath:(NSString *)_path;
+- (id)initWithScheme:(NSString *)_scheme
+  host:(NSString *)_host
+  path:(NSString *)_path;
+- (id)initWithString:(NSString *)_string relativeToURL:(NSURL *)_baseURL;
+- (id)initWithString:(NSString *)_string;
+
+/* relative URLs */
+
+- (NSURL *)baseURL;
+- (NSString *)relativePath;
+- (NSString *)relativeString;
+- (NSString *)absoluteString;
+
+/* attributes */
+
+- (NSString *)fragment;
+- (NSString *)host;
+- (NSString *)path;
+- (NSString *)scheme;
+- (NSString *)user;
+- (NSString *)password;
+- (NSNumber *)port;
+- (NSString *)query;
+
+- (BOOL)isFileURL;
+
+/* fetching */
+
+- (NSURLHandle *)URLHandleUsingCache:(BOOL)_useCache;
+- (void)loadResourceDataNotifyingClient:(id)_client usingCache:(BOOL)_useCache;
+
+- (NSData *)resourceDataUsingCache:(BOOL)_useCache;
+- (BOOL)setResourceData:(NSData *)_data;
+
+@end
+
+@interface NSObject(NSURLClient)
+@end
+
+@interface NSString(NSURLUtilities)
+
+- (BOOL)isAbsoluteURL;
+- (NSString *)urlScheme;
+
+@end
+
+#endif /* __NSURL_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSURL.m b/libFoundation/Foundation/NSURL.m
new file mode 100644 (file)
index 0000000..ea341ec
--- /dev/null
@@ -0,0 +1,1599 @@
+/* 
+   NSURL.m
+
+   Copyright (C) 2000 MDlink GmbH, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSURL.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSData.h>
+#include <Foundation/NSCoder.h>
+#include <Foundation/NSValue.h>
+#include <Foundation/NSUtilities.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSPathUtilities.h>
+#include <Foundation/NSFileManager.h>
+#include "common.h"
+
+LF_DECLARE NSString *NSURLFileScheme = @"file";
+
+/*
+  I was just working with NSURL yesterday and I got it so that I can load
+  the HTML of a web page.  Here is a simple example:
+
+  - (void) getHTMLFromURL
+  {
+    NSURL *theURL;
+    NSURLHandle *theURLHandle;
+    NSData *theData;
+    NSString *tempString;
+    
+    theURL = [NSURL URLWithString:@"http://www.apple.com/"];
+    theURLHandle = [theURL URLHandleUsingCache:NO];
+    
+    theData = [theURLHandle resourceData];  // retrieves page HTML
+    tempString = [[NSString alloc] initWithData:theData
+                                   encoding:NSASCIIStringEncoding];
+  }
+*/
+
+@interface _NSAbsoluteURL : NSURL
+{
+}
+@end
+
+@interface _NSAbsoluteHTTPURL : _NSAbsoluteURL
+{
+    NSString *path;
+    NSString *host;
+    NSString *fragment;
+    NSString *query;
+    NSString *login;
+    NSString *password;
+    unsigned port;
+    BOOL     isSSL;
+}
+
+@end
+
+@interface _NSAbsoluteFileURL : _NSAbsoluteURL
+{
+    NSString *path;
+}
+@end
+
+@interface _NSAbsoluteMailToURL : _NSAbsoluteURL
+{
+    NSString *mailto;
+}
+@end
+
+@interface _NSAbsoluteGenericURL : _NSAbsoluteURL
+{
+    NSString *scheme;
+    NSString *path;
+    NSString *host;
+    NSString *fragment;
+    NSString *query;
+    NSString *login;
+    NSString *password;
+    unsigned port;
+}
+@end
+
+@interface _NSRelativeURL : NSURL
+{
+    NSURL    *baseURL;
+    NSString *relString;
+    NSString *relPath;
+    NSString *fragment;
+    NSString *query;
+}
+@end
+
+@interface NSURL(Privates)
+- (NSString *)_pathForRelativeURL:(NSURL *)_relurl;
+- (NSString *)_absoluteStringForRelativeURL:(NSURL *)_relurl;
+@end
+
+@implementation NSString(NSURLUtilities)
+
+- (BOOL)isAbsoluteURL
+{
+    unsigned idx;
+    unsigned i;
+    
+    if ([self hasPrefix:@"mailto:"])
+        return YES;
+    if ([self hasPrefix:@"javascript:"])
+        return YES;
+    
+    if ((idx = [self indexOfString:@"://"]) == NSNotFound) {
+        if ([self hasPrefix:@"file:"])
+            return YES;
+        return NO;
+    }
+    
+    if ([self hasPrefix:@"/"])
+        return NO;
+
+    for (i = 0; i < idx; i++) {
+        if (!isalpha([self characterAtIndex:i]))
+            return NO;
+    }
+    return YES;
+}
+
+- (NSString *)urlScheme
+{
+    register unsigned i, count;
+    register unichar c = 0;
+    
+    if ((count = [self length]) == 0)
+        return nil;
+    
+    for (i = 0; i < count; i++) {
+        c = [self characterAtIndex:i];
+        
+        if (!isalpha(c))
+            break;
+    }
+    if ((c != ':') || (i < 1))
+        return nil;
+    
+    return [self substringToIndex:i];
+}
+
+@end /* NSString(NSURLUtilities) */
+
+@implementation NSURL
+
+static NSMutableDictionary *schemeToURLClass = nil; // THREAD
+
+static Class _NSAbsoluteURLClass = Nil;
+static Class _NSRelativeURLClass = Nil;
+
++ (void)initialize
+{
+    if (_NSAbsoluteURLClass == Nil)
+        _NSAbsoluteURLClass = [_NSAbsoluteURL class];
+    if (_NSRelativeURLClass == Nil)
+        _NSRelativeURLClass = [_NSRelativeURL class];
+    
+    if (schemeToURLClass == nil) {
+        schemeToURLClass = [[NSMutableDictionary alloc] initWithCapacity:8];
+        
+        [schemeToURLClass setObject:[_NSAbsoluteFileURL class]
+                          forKey:NSURLFileScheme];
+        [schemeToURLClass setObject:[_NSAbsoluteHTTPURL class]
+                          forKey:@"http"];
+        [schemeToURLClass setObject:[_NSAbsoluteHTTPURL class]
+                          forKey:@"httpu"];
+        [schemeToURLClass setObject:[_NSAbsoluteMailToURL class]
+                          forKey:@"mailto"];
+    }
+}
+
+/* relative URLs */
+
+- (NSURL *)_makeRelativeURLWithString:(NSString *)_str
+{
+    return [_NSRelativeURL URLWithString:_str relativeToURL:self];
+}
+
++ (id)URLWithString:(NSString *)_str
+{
+    if ([_str length] == 0)
+        /* empty URL */
+        return nil;
+    
+    return [_NSAbsoluteURL URLWithString:_str];
+}
+
++ (id)URLWithString:(NSString *)_str relativeToURL:(NSURL *)_base
+{
+    if (_base == nil)
+        return [self URLWithString:_str];
+
+    if ([_str length] == 0)
+        return AUTORELEASE(RETAIN(_base));
+    
+    if ([_str isAbsoluteURL])
+        return [self URLWithString:_str];
+    
+    return [_base _makeRelativeURLWithString:_str];
+}
+
++ (id)fileURLWithPath:(NSString *)_path
+{
+    return [[[self alloc] initFileURLWithPath:_path] autorelease];
+}
+
+- (id)initFileURLWithPath:(NSString *)_path
+{
+    /* may need to transform path */
+    return [self initWithScheme:NSURLFileScheme
+                 host:nil
+                 path:_path];
+}
+
+- (id)initWithScheme:(NSString *)_scheme
+  host:(NSString *)_host
+  path:(NSString *)_path
+{
+    if ([self class] != _NSAbsoluteURLClass) {
+        Class clazz;
+        
+        RELEASE(self);
+        
+        if ((clazz = [schemeToURLClass objectForKey:_scheme]) == Nil)
+            clazz = [_NSAbsoluteGenericURL class];
+        
+        return [[clazz alloc] initWithScheme:_scheme
+                              host:_host
+                              path:_path];
+    }
+    return self;
+}
+
+- (id)initWithString:(NSString *)_string relativeToURL:(NSURL *)_baseURL
+{
+    if ([self class] != _NSAbsoluteURLClass) {
+        RELEASE(self);
+
+        return [[NSURL URLWithString:_string relativeToURL:_baseURL] retain];
+    }
+    return self;
+}
+- (id)initWithString:(NSString *)_string
+{
+    return [self initWithString:_string relativeToURL:nil];
+}
+
+/* relative URLs */
+
+- (NSURL *)baseURL
+{
+    return [self subclassResponsibility:_cmd];
+}
+
+- (NSString *)relativePath
+{
+    return [self path];
+}
+- (NSString *)relativeString
+{
+    return [self absoluteString];
+}
+- (NSString *)absoluteString
+{
+    return [self subclassResponsibility:_cmd];
+}
+
+- (NSString *)_pathForRelativeURL:(NSURL *)_relurl
+{
+    NSString *relPath;
+    NSString *s;
+    
+    relPath = [_relurl relativePath];
+    
+    if ([relPath hasPrefix:@"/"]) {
+       /* the relative URI has an absolute path */
+        s = relPath;
+    }
+    else if ([relPath length] > 0) {
+       /* the relative URI has some path */
+       
+        s = [self path];
+       
+       if ([self isFileURL]) {
+           /* auto-add trailing slash for directories ... */
+           NSFileManager *fm = [NSFileManager defaultManager];
+           BOOL isDir;
+           
+           if ([fm fileExistsAtPath:s isDirectory:&isDir]) {
+               if (isDir) {
+                   if (![s hasSuffix:@"/"]) 
+                       s = [s stringByAppendingString:@"/"];
+               }
+           }
+       }
+       
+       if ([s hasSuffix:@"/"]) {
+           /* base is a "folder" */
+           s = [s stringByAppendingString:relPath];
+       }
+       else {
+           NSRange r;
+           
+           r = [s rangeOfString:@"/" options:NSBackwardsSearch];
+           s = [s substringToIndex:(r.location + r.length)];
+           s = [s stringByAppendingString:relPath];
+       }
+    }
+    else
+       /* the relative URI has no path */
+        s = [self path];
+    
+    return s;
+}
+- (NSString *)_absoluteStringForRelativeURL:(NSURL *)_relurl
+{
+    NSMutableString *ms;
+    NSString *s;
+    
+    ms = [[NSMutableString alloc] initWithCapacity:100];
+    
+    [ms appendString:[_relurl scheme]];
+    [ms appendString:@"://"];
+    
+    if ((s = [_relurl user])) {
+        [ms appendString:s];
+        if ((s = [_relurl password])) {
+            [ms appendString:@":"];
+            [ms appendString:s];
+        }
+        [ms appendString:@"@"];
+    }
+    
+    if ((s = [_relurl host])) {
+        NSNumber *n;
+        
+        [ms appendString:s];
+        if ((n = [_relurl port])) {
+            [ms appendString:@":"];
+            [ms appendString:[n stringValue]];
+        }
+    }
+    else if ((s = [self host])) {
+        NSNumber *n;
+        
+        [ms appendString:s];
+        if ((n = [self port])) {
+            [ms appendString:@":"];
+            [ms appendString:[n stringValue]];
+        }
+    }
+    
+    [ms appendString:[_relurl path]];
+    
+    if ((s = [_relurl fragment])) {
+        [ms appendString:@"#"];
+        [ms appendString:s];
+    }
+    if ((s = [_relurl query])) {
+        [ms appendString:@"?"];
+        [ms appendString:s];
+    }
+    
+    s = [ms copy];
+    RELEASE(ms);
+    
+    return AUTORELEASE(s);
+}
+
+/* properties */
+
+- (NSString *)fragment
+{
+    return [self subclassResponsibility:_cmd];
+}
+- (NSString *)query
+{
+    return [self subclassResponsibility:_cmd];
+}
+
+- (NSString *)host
+{
+    return [self subclassResponsibility:_cmd];
+}
+- (NSString *)path
+{
+    return [self subclassResponsibility:_cmd];
+}
+- (NSString *)scheme
+{
+    return [self subclassResponsibility:_cmd];
+}
+
+- (NSNumber *)port
+{
+    return nil;
+}
+- (NSString *)user
+{
+    return nil;
+}
+- (NSString *)password
+{
+    return nil;
+}
+
+- (BOOL)isFileURL
+{
+    return [[self scheme] isEqualToString:NSURLFileScheme];
+}
+
+/* NSCopying */
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    /* NSURL's are immutable objects */
+    return RETAIN(self);
+}
+
+/* equality */
+
+- (unsigned)hash
+{
+    return [[self path] hash];
+}
+- (BOOL)isEqualToURL:(NSURL *)_other
+{
+    if (![[_other scheme] isEqualToString:[self scheme]])
+        return NO;
+
+    return [[_other absoluteString] isEqualToString:[self absoluteString]];
+}
+- (BOOL)isEqual:(id)_other
+{
+    if (_other == nil)
+        return NO;
+    if ([_other isKindOfClass:[NSURL class]])
+        return [_other isEqualToURL:self];
+    return NO;
+}
+
+/* NSCoding */
+
+- (void)encodeWithCoder:(NSCoder *)_coder
+{
+}
+- (id)initWithCoder:(NSCoder *)_decoder
+{
+    return [self subclassResponsibility:_cmd];
+}
+
+/* NSURLHandleClient */
+
+- (void)URLHandleResourceDidBeginLoading:(NSURLHandle *)_handler
+{
+}
+- (void)URLHandleResourceDidCancelLoading:(NSURLHandle *)_handler
+{
+}
+- (void)URLHandleResourceDidFinishLoading:(NSURLHandle *)_handler
+{
+}
+
+- (void)URLHandle:(NSURLHandle *)_handler
+  resourceDataDidBecomeAvailable:(NSData *)_data
+{
+}
+- (void)URLHandle:(NSURLHandle *)_handler
+  resourceDidFailLoadingWithReason:(NSString *)_reason
+{
+}
+
+/* fetching */
+
+- (NSURLHandle *)URLHandleUsingCache:(BOOL)_useCache
+{
+    Class       handleClass;
+    NSURLHandle *handle;
+    
+    if ((handleClass = [NSURLHandle URLHandleClassForURL:self]) == Nil) {
+        NSLog(@"%s: missing handler for URL '%@'", __PRETTY_FUNCTION__, self);
+        return nil;
+    }
+    
+    handle = [[handleClass alloc] initWithURL:self cached:_useCache];
+    if (handle == nil) {
+        NSLog(@"%s: couldn't create handle of class %@ for URL '%@'",
+              __PRETTY_FUNCTION__, handleClass, self);
+        return nil;
+    }
+    
+    return AUTORELEASE(handle);
+}
+- (void)loadResourceDataNotifyingClient:(id)_client usingCache:(BOOL)_useCache
+{
+    NSURLHandle *handle;
+    
+    NSAssert(self->currentClient == nil, @"already loading resource ..");
+    self->currentClient = _client;
+    
+    handle = [self URLHandleUsingCache:_useCache];
+    [handle addClient:self];
+    [handle loadInBackground];
+    [handle removeClient:self];
+    
+    self->currentClient = nil;
+}
+
+- (NSData *)resourceDataUsingCache:(BOOL)_useCache
+{
+    return [[self URLHandleUsingCache:_useCache] resourceData];
+}
+
+- (BOOL)setResourceData:(NSData *)_data
+{
+    NSURLHandle *handle;
+    
+    if ((handle = [self URLHandleUsingCache:YES]) == nil)
+        return NO;
+    
+    return [handle writeData:_data];
+}
+
+/* description */
+
+- (NSString *)stringValue
+{
+    return [self absoluteString];
+}
+
+- (NSString *)description
+{
+    return [NSString stringWithFormat:@"<%@ 0x%08x: '%@'>",
+                       NSStringFromClass([self class]), self,
+                       [self absoluteString]];
+}
+
+@end /* NSURL */
+
+@implementation _NSAbsoluteURL
+
++ (id)URLWithString:(NSString *)_str
+{
+    NSString *scheme;
+    Class clazz;
+    
+    if ([_str length] == 0) {
+        /* empty URL */
+#if 0
+        NSLog(@"%s: passed empty string", __PRETTY_FUNCTION__);
+#endif
+        return nil;
+    }
+
+    if ((scheme = [_str urlScheme]) == nil) {
+        /* missing URL scheme .. */
+        if ([_str hasPrefix:@"/"]) {
+            return [[[_NSAbsoluteFileURL alloc]
+                                         initWithScheme:@"file"
+                                         host:nil
+                                         path:_str]
+                                         autorelease];
+        }
+        
+#if 0
+        NSLog(@"%s: missing URL scheme in string '%@'",
+              __PRETTY_FUNCTION__, _str);
+#endif
+        return nil;
+    }
+    
+    if ((clazz = [schemeToURLClass objectForKey:scheme]) == Nil)
+        clazz = [_NSAbsoluteGenericURL class];
+    
+    return [clazz URLWithString:_str];
+}
+
+- (id)initWithScheme:(NSString *)_scheme
+  host:(NSString *)_host
+  path:(NSString *)_path
+{
+    return self;
+}
+
+- (void)dealloc
+{
+    [super dealloc];
+}
+
+/* stuff for relative URLs */
+
+- (NSURL *)baseURL
+{
+    return nil;
+}
+- (NSString *)relativePath
+{
+    return [self path];
+}
+- (NSString *)relativeString
+{
+    return [self absoluteString];
+}
+- (NSString *)absoluteString
+{
+    NSMutableString *ms;
+    NSString *s;
+    
+    ms = [[NSMutableString alloc] initWithCapacity:100];
+    
+    [ms appendString:[self scheme]];
+    [ms appendString:@"://"];
+
+    if ((s = [self user])) {
+        [ms appendString:s];
+        if ((s = [self password])) {
+            [ms appendString:@":"];
+            [ms appendString:s];
+        }
+        [ms appendString:@"@"];
+    }
+    
+    if ((s = [self host])) {
+        NSNumber *n;
+        
+        [ms appendString:s];
+        if ((n = [self port])) {
+            [ms appendString:@":"];
+            [ms appendString:[n stringValue]];
+        }
+    }
+    
+    [ms appendString:[self path]];
+    
+    if ((s = [self fragment])) {
+        [ms appendString:@"#"];
+        [ms appendString:s];
+    }
+    if ((s = [self query])) {
+        [ms appendString:@"?"];
+        [ms appendString:s];
+    }
+    
+    s = [ms copy];
+    RELEASE(ms);
+    return AUTORELEASE(s);
+}
+
+/* properties */
+
+- (NSString *)fragment
+{
+    return nil;
+}
+- (NSString *)query
+{
+    return nil;
+}
+- (NSString *)host
+{
+    return nil;
+}
+- (NSString *)path
+{
+    return nil;
+}
+- (NSString *)scheme
+{
+    return nil;
+}
+
+- (NSString *)user
+{
+    return nil;
+}
+- (NSString *)password
+{
+    return nil;
+}
+- (NSNumber *)port
+{
+    return nil;
+}
+
+/* NSCoding */
+
+- (void)encodeWithCoder:(NSCoder *)_coder
+{
+    [_coder encodeObject:[self absoluteString]];
+}
+- (id)initWithCoder:(NSCoder *)_decoder
+{
+    NSString *as;
+    
+    as = [_decoder decodeObject];
+    RELEASE(self);
+    return RETAIN([[self class] URLWithString:as]);
+}
+
+@end /* _NSAbsoluteURL */
+
+@implementation _NSAbsoluteHTTPURL
+
+/*
+  HTTP Urls:
+
+    httpaddress : 'http://' { loginpwd '@' } 
+                  hostport { '/' path } { '?' search }
+    loginpwd    : login { ':' pwd }
+    hostport    : hostname { ':' port }
+    login       : alpha ( xalpha )*
+    pwd         : alpha ( xalpha )*
+    hostname    : alpha ( xalpha )*
+    port        : ( digit )+
+    path        : void | (xpalpha)+ { '/' path }
+    search      : ( xalpha )+ { '+' search }
+    xalpha      : alpha | digit | safe | extra | escape
+    xpalpha     : xalpha | +
+
+  Description:
+  
+    Xpalpha are chars that can occure in a path. Notably this includes the
+    '+' char which has a different meaning the search part, where the plus
+    separated the search components.
+
+  Examples:
+
+    http://www.mdlink.de/search.cgi?hallo=23&
+*/
+
++ (id)URLWithString:(NSString *)_str
+{
+    unsigned char *urlbuf, *buf, *cur, *tmp;
+    unsigned len, idx;
+    NSString *uscheme = nil, *hostName = nil, *ulogin = nil, *pwd = nil;
+    unsigned uport = 0;
+    NSString *upath = nil, *ufrag = nil, *uquery = nil;
+    _NSAbsoluteHTTPURL *url;
+    
+    if (![_str hasPrefix:@"http://"] && 
+        ![_str hasPrefix:@"https://"] &&
+        ![_str hasPrefix:@"httpu://"])
+        return nil;
+    
+    // TODO: use UTF-8?
+    len    = [_str cStringLength];
+    urlbuf = calloc(len + 4 /* required for peek! */, sizeof(unsigned char));
+    [_str getCString:(char *)urlbuf]; urlbuf[len] = '\0';
+    cur = urlbuf;
+    
+    buf = malloc(len + 4);
+    
+    /* scan scheme */
+    
+    for (idx = 0, buf[idx] = '\0'; (idx<len) && (*cur != '\0'); idx++,cur++) {
+        if ((cur[0] == ':') && (cur[1] == '/') && (cur[2] == '/')) {
+           buf[idx] = '\0';
+            uscheme = [NSString stringWithCString:(char *)buf length:idx];
+            idx = 0;
+            cur += 3; // skip '://'
+            break; // leave loop
+        }
+        buf[idx] = *cur;
+    }
+    if (*cur == '\0') goto done;
+
+    //NSLog(@"after scheme %@, CUR: '%s'", uscheme, cur);
+    
+    /* scan login/password */
+    
+    if ((tmp = (unsigned char *)index((char *)cur, '@')) != NULL) {
+       /* avoid issues with this: '/localhost/user@blah/' */
+       if ((unsigned char *)tmp < (unsigned char *)index((char *)cur, '/')) {
+           /* donald:duck@localhost:13 */
+           unsigned char *s;
+           BOOL foundColon = NO;
+       
+           pwd = @"";
+           buf[idx] = '\0';
+           for (idx = 0, s = cur; s < tmp; s++) {
+               if (*s == ':') {
+                   /* next is pwd */
+                   buf[idx] = '\0';
+                   ulogin = [NSString stringWithCString:(char *)buf
+                                      length:idx];
+                   idx = 0;
+                   foundColon = YES;
+               }
+               else if (*s == '@') {
+                   /* found end marker */
+                   break;
+               }
+               else {
+                   buf[idx] = *s;
+                   idx++;
+               }
+           }
+           if (foundColon) {
+               buf[idx] = '\0';
+               pwd = [NSString stringWithCString:(char *)buf length:idx];
+           }
+           if (*s == '@') s++;
+           cur = s;
+       }
+    }
+    if (*cur == '\0') goto done;
+
+    //NSLog(@"after login %@/pwd %@, CUR: '%s'", ulogin, pwd, cur);
+    
+    /* scan hostname & port */
+    
+    for (idx = 0, buf[idx] = '\0'; YES; idx++, cur++) {
+        if (*cur == ':') {
+            /* found host/port breakup (eg myhost:80) */
+            buf[idx] = '\0';
+            hostName = [NSString stringWithCString:(char *)buf length:idx];
+            
+            idx = 0;
+            cur++; // skip ':'
+            
+            /* parse port number */
+            uport = 0;
+            while (isdigit(*cur) && (*cur != '\0')) {
+                uport *= 10;
+                uport += *cur - '0';
+                cur++;
+            }
+            
+            break;
+        }
+        else if ((*cur == '/') || (*cur == '\0')) {
+            /* reached end of host/port combo */
+            buf[idx] = '\0';
+            hostName = [NSString stringWithCString:(char *)buf length:idx];
+            uport    = 0;
+            
+            break;
+        }
+        else {
+            /* continue */
+            buf[idx] = *cur;
+        }
+    }
+    if (*cur == '\0') goto done;
+    
+    /* scan path */
+    
+    for (idx = 0, buf[idx] = '\0'; YES; idx++, cur++) {
+        if (*cur == '#') {
+            /* found fragment */
+            buf[idx] = '\0';
+            upath  = [NSString stringWithCString:(char *)buf length:idx];
+
+            /* parse fragment */
+            cur++; // skip '#'
+            for (idx = 0, buf[idx] = '\0'; (*cur != '?' && *cur != '\0');
+                 idx++, cur++) {
+                buf[idx] = *cur;
+            }
+            ufrag = [NSString stringWithCString:(char *)buf length:idx];
+
+            if (*cur == '?') {
+                /* parse query */
+                cur++; // skip '?'
+                uquery = [NSString stringWithCString:(char *)cur];
+            }
+            
+            break;
+        }
+        else if (*cur == '?') {
+            /* found query */
+            buf[idx] = '\0';
+            upath = [NSString stringWithCString:(char *)buf length:idx];
+            ufrag = nil;
+            
+            /* parse query */
+            cur++; // skip '?'
+            uquery = [NSString stringWithCString:(char *)cur];
+            break;
+        }
+        else if (*cur == '\0') {
+            /* found end */
+            buf[idx] = '\0';
+            upath  = [NSString stringWithCString:(char *)buf length:idx];
+            ufrag  = nil;
+            uquery = nil;
+            break;
+        }
+        buf[idx] = *cur;
+    }
+    if (*cur == '\0') goto done;
+    
+ done:
+    if (buf)    free(buf);
+    if (urlbuf) free(urlbuf);
+    
+    /* resolve '..' and '.' in path */
+    if ((upath != nil) && [upath indexOfString:@".."] != NSNotFound) {
+        NSArray *pc;
+        NSMutableArray *nc;
+        unsigned i, count;
+        
+        pc    = [upath pathComponents];
+        count = [pc count];
+        nc    = [NSMutableArray arrayWithCapacity:count];
+
+        for (i = 0; i < count; i++) {
+            NSString *pcc;
+            
+            pcc = [pc objectAtIndex:i];
+            if ([pcc isEqualToString:@".."]) {
+                unsigned ncount;
+                
+                if ((ncount = [nc count]) > 0)
+                    [nc removeObjectAtIndex:(ncount - 1)];
+                else
+                    /* invalid absolute path .. */
+                    [nc addObject:pcc];
+            }
+            else if ([pcc isEqualToString:@"."]) {
+                /* do not add '.' */
+            }
+            else
+                [nc addObject:pcc];
+        }
+    }
+    
+    if (upath == nil)
+        upath = @"/";
+    
+    url = [[_NSAbsoluteHTTPURL alloc] initWithScheme:uscheme
+                                      host:hostName
+                                      path:upath];
+    url->port     = uport > 0 ? uport : 80;
+    url->fragment = [ufrag  copy];
+    url->query    = [uquery copy];
+    url->login    = [ulogin copy];
+    url->password = [pwd    copy];
+    
+    return AUTORELEASE(url);
+}
+
+- (id)initWithScheme:(NSString *)_scheme
+  host:(NSString *)_host
+  path:(NSString *)_path
+{
+    if ([_scheme isEqualToString:@"https"]) {
+       self->isSSL = YES;
+    }
+    else if (![_scheme hasPrefix:@"http"]) {
+        RELEASE(self);
+        return nil;
+    }
+    
+    if ((self = [super initWithScheme:_scheme host:_host path:_path])) {
+        self->host = [_host copy];
+        self->path = [_path length] > 0 ? [_path copy] : @"/";
+    }
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(self->login);
+    RELEASE(self->password);
+    RELEASE(self->fragment);
+    RELEASE(self->query);
+    RELEASE(self->path);
+    RELEASE(self->host);
+    [super dealloc];
+}
+
+/* component accessors */
+
+- (NSNumber *)port
+{
+    return self->port > 0
+       ? [NSNumber numberWithUnsignedInt:self->port]
+       : nil;
+}
+
+- (NSString *)fragment
+{
+    return self->fragment;
+}
+- (NSString *)query
+{
+    return self->query;
+}
+- (NSString *)host
+{
+    return self->host;
+}
+- (NSString *)path
+{
+    return self->path;
+}
+- (NSString *)scheme
+{
+    return self->isSSL ? @"https" : @"http";
+}
+- (NSString *)user
+{
+    return self->login;
+}
+- (NSString *)password
+{
+    return self->password;
+}
+
+@end /* _NSAbsoluteHTTPURL */
+
+@implementation _NSAbsoluteGenericURL
+
++ (id)URLWithString:(NSString *)_str
+{
+    // TODO: UNICODE, based on cString
+    // TODO: does not properly parse login/pwd! (eg for IMAP4 URLs)
+    unsigned char *urlbuf, *buf, *cur;
+    unsigned len, idx;
+    NSString *uscheme, *hostName;
+    unsigned uport;
+    NSString *upath, *ufrag, *uquery, *ulogin, *upwd;
+    NSRange  r;
+    _NSAbsoluteGenericURL *url;
+    
+    uscheme  = nil;
+    hostName = nil;
+    uport    = 0;
+    upath    = nil;
+    ufrag    = nil;
+    uquery   = nil;
+    
+    len    = [_str cStringLength];
+    urlbuf = calloc(len + 4, sizeof(unsigned char));
+    [_str getCString:(char *)urlbuf]; urlbuf[len] = '\0';
+    cur = urlbuf;
+    
+    buf = malloc(len + 1);
+    
+    /* scan scheme */
+    
+    for (idx = 0, buf[idx] = '\0'; (idx<len) && (*cur != '\0'); idx++, cur++) {
+        if ((cur[0] == ':') && (cur[1] == '/') && (cur[2] == '/')) {
+           buf[idx] = '\0';
+            uscheme = [NSString stringWithCString:(char *)buf length:idx];
+            idx = 0;
+            cur += 3; // skip '://'
+            break; // leave loop
+        }
+        buf[idx] = *cur;
+    }
+    if (*cur == '\0') goto done;
+    
+    /* scan hostname & port */
+    
+    for (idx = 0, buf[idx] = '\0'; YES; idx++, cur++) {
+        if (*cur == ':') {
+            /* found host/port breakup (eg myhost:80) */
+            buf[idx] = '\0';
+            hostName = [NSString stringWithCString:(char *)buf length:idx];
+            
+            idx = 0;
+            cur++; // skip ':'
+            
+            /* parse port number */
+            uport = 0;
+            while (isdigit(*cur) && (*cur != '\0')) {
+                uport *= 10;
+                uport += *cur - '0';
+                cur++;
+            }
+            
+            break;
+        }
+        else if ((*cur == '/') || (*cur == '\0')) {
+            /* reached end of host/port combo */
+            buf[idx] = '\0';
+            hostName = [NSString stringWithCString:(char *)buf length:idx];
+            uport    = 0;
+            
+            break;
+        }
+        else {
+            /* continue */
+            buf[idx] = *cur;
+        }
+    }
+    if (*cur == '\0') goto done;
+    
+    /* scan path */
+    
+    for (idx = 0, buf[idx] = '\0'; YES; idx++, cur++) {
+        if (*cur == '#') {
+            /* found fragment */
+            buf[idx] = '\0';
+            upath  = [NSString stringWithCString:(char *)buf length:idx];
+
+            /* parse fragment */
+            cur++; // skip '#'
+            for (idx = 0, buf[idx] = '\0'; (*cur != '?' && *cur != '\0');
+                 idx++, cur++) {
+                buf[idx] = *cur;
+            }
+            ufrag = [NSString stringWithCString:(char *)buf length:idx];
+
+            if (*cur == '?') {
+                /* parse query */
+                cur++; // skip '?'
+                uquery = [NSString stringWithCString:(char *)cur];
+            }
+            
+            break;
+        }
+        else if (*cur == '?') {
+            /* found query */
+            buf[idx] = '\0';
+            upath = [NSString stringWithCString:(char *)buf length:idx];
+            ufrag = nil;
+            
+            /* parse query */
+            cur++; // skip '?'
+            uquery = [NSString stringWithCString:(char *)cur];
+            break;
+        }
+        else if (*cur == '\0') {
+            /* found end */
+            buf[idx] = '\0';
+            upath  = [NSString stringWithCString:(char *)buf length:idx];
+            ufrag  = nil;
+            uquery = nil;
+            break;
+        }
+        buf[idx] = *cur;
+    }
+    if (*cur == '\0') goto done;
+    
+ done:
+    if (buf)    free(buf);
+    if (urlbuf) free(urlbuf);
+    
+    /* resolve '..' and '.' in path */
+    if ((upath != nil) && [upath indexOfString:@".."] != NSNotFound) {
+        NSArray *pc;
+        NSMutableArray *nc;
+        unsigned i, count;
+        
+        pc    = [upath pathComponents];
+        count = [pc count];
+        nc    = [NSMutableArray arrayWithCapacity:count];
+
+        for (i = 0; i < count; i++) {
+            NSString *pcc;
+            
+            pcc = [pc objectAtIndex:i];
+            if ([pcc isEqualToString:@".."]) {
+                unsigned ncount;
+                
+                if ((ncount = [nc count]) > 0)
+                    [nc removeObjectAtIndex:(ncount - 1)];
+                else
+                    /* invalid absolute path .. */
+                    [nc addObject:pcc];
+            }
+            else if ([pcc isEqualToString:@"."]) {
+                /* do not add '.' */
+            }
+            else
+                [nc addObject:pcc];
+        }
+    }
+    
+    if (upath == nil)
+        upath = @"/";
+    
+    /* extract login/password */
+    
+    ulogin = nil;
+    upwd   = nil;
+    r = [hostName rangeOfString:@"@"];
+    if (r.length > 0) {
+       ulogin   = [hostName substringToIndex:r.location];
+       hostName = [hostName substringFromIndex:(r.location + r.length)];
+
+       r = [ulogin rangeOfString:@":"];
+       if (r.length > 0) {
+           upwd   = [ulogin substringToIndex:r.location];
+           ulogin = [ulogin substringFromIndex:(r.location + r.length)];
+       }
+    }
+    
+    /* create object */
+    
+    url = [[_NSAbsoluteGenericURL alloc] initWithScheme:uscheme
+                                         host:hostName
+                                         path:upath];
+    url->port     = uport > 0 ? uport : 0;
+    url->fragment = [ufrag  copy];
+    url->query    = [uquery copy];
+    url->login    = [ulogin copy];
+    url->password = [upwd   copy];
+    
+    return AUTORELEASE(url);
+}
+
+- (id)initWithScheme:(NSString *)_scheme
+  host:(NSString *)_host
+  path:(NSString *)_path
+{
+    if ((self = [super initWithScheme:_scheme host:_host path:_path])) {
+        self->scheme = [_scheme copy];
+        self->host   = [_host copy];
+        self->path   = [_path length] > 0 ? [_path copy] : @"/";
+    }
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(self->login);
+    RELEASE(self->password);
+    RELEASE(self->scheme);
+    RELEASE(self->fragment);
+    RELEASE(self->query);
+    RELEASE(self->path);
+    RELEASE(self->host);
+    [super dealloc];
+}
+
+/* component accessors */
+
+- (NSNumber *)port
+{
+    return self->port > 0
+       ? [NSNumber numberWithUnsignedInt:self->port]
+       : nil;
+}
+
+- (NSString *)fragment
+{
+    return self->fragment;
+}
+- (NSString *)query
+{
+    return self->query;
+}
+- (NSString *)host
+{
+    return self->host;
+}
+- (NSString *)path
+{
+    return self->path;
+}
+- (NSString *)scheme
+{
+    return self->scheme;
+}
+- (NSString *)user
+{
+    return self->login;
+}
+- (NSString *)password
+{
+    return self->password;
+}
+
+@end /* _NSAbsoluteGenericURL */
+
+@implementation _NSAbsoluteFileURL
+
++ (id)URLWithString:(NSString *)_str
+{
+    NSURL    *url;
+    NSString *ps;
+    
+    if (![_str hasPrefix:@"file:"]) {
+        NSLog(@"%s: string is not a file URL '%@'", __PRETTY_FUNCTION__, _str);
+        return nil;
+    }
+    
+    ps = [_str substringFromIndex:5];
+    if ([ps length] == 0) {
+        NSLog(@"ERROR: missing path in URL '%@' !", _str);
+        return nil;
+    }
+    
+    if ([ps hasPrefix:@"//"])
+        ps = [ps substringFromIndex:2];
+    if ([ps length] == 0)
+        ps = @"/";
+    
+    url = [[self alloc] initWithScheme:@"file"
+                        host:nil
+                        path:ps];
+    return AUTORELEASE(url);
+}
+
+- (id)initWithScheme:(NSString *)_scheme
+  host:(NSString *)_host
+  path:(NSString *)_path
+{
+    if (![_scheme isEqualToString:@"file"]) {
+        RELEASE(self);
+        return nil;
+    }
+    
+    if ((self = [super initWithScheme:_scheme host:_host path:_path])) {
+        if (![_path isAbsolutePath]) {
+            _path = [[[NSFileManager defaultManager] currentDirectoryPath]
+                                     stringByAppendingPathComponent:_path];
+        }
+        self->path = [[_path stringByStandardizingPath] copy];
+    }
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(self->path);
+    [super dealloc];
+}
+
+/* component accessors */
+
+- (NSString *)path
+{
+    return self->path;
+}
+- (NSString *)scheme
+{
+    return @"file";
+}
+
+- (NSString *)absoluteString
+{
+    NSMutableString *ms;
+    NSString *s;
+    
+    ms = [[NSMutableString alloc] initWithCapacity:100];
+    
+    [ms appendString:[self scheme]];
+    [ms appendString:@"://"];
+    [ms appendString:[self path]];
+
+    s = [ms copy];
+    RELEASE(ms);
+    return AUTORELEASE(s);
+}
+
+@end /* _NSAbsoluteFileURL */
+
+@implementation _NSAbsoluteMailToURL
+
++ (id)URLWithString:(NSString *)_str
+{
+    NSURL    *url;
+    NSString *ps;
+    
+    if (![_str hasPrefix:@"mailto:"]) {
+        NSLog(@"%s: string is not a file URL '%@'", __PRETTY_FUNCTION__, _str);
+        return nil;
+    }
+    
+    ps = [_str substringFromIndex:7];
+    if ([ps length] == 0) {
+        NSLog(@"ERROR: missing address in URL '%@' !", _str);
+        return nil;
+    }
+    
+    url = [[self alloc] initWithScheme:@"mailto"
+                        host:nil
+                        path:ps];
+    return AUTORELEASE(url);
+}
+- (id)initWithScheme:(NSString *)_scheme
+  host:(NSString *)_host
+  path:(NSString *)_path
+{
+    if (![_scheme isEqualToString:@"mailto"]) {
+        RELEASE(self);
+        return nil;
+    }
+
+    self->mailto = [_path copy];
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(self->mailto);
+    [super dealloc];
+}
+
+- (NSString *)path
+{
+    return self->mailto;
+}
+- (NSString *)scheme
+{
+    return @"mailto";
+}
+- (NSString *)absoluteString
+{
+    return [@"mailto:" stringByAppendingString:[self path]];
+}
+
+@end /* _NSAbsoluteMailToURL */
+
+@implementation _NSRelativeURL
+
++ (id)URLWithString:(NSString *)_str relativeToURL:(NSURL *)_base
+{
+    if ([_str length] == 0)
+        return AUTORELEASE(RETAIN(_base));
+    
+    return AUTORELEASE([[self alloc] initWithString:_str relativeToURL:_base]);
+}
+
+- (id)initWithString:(NSString *)_string relativeToURL:(NSURL *)_baseURL
+{
+    unsigned fidx, qidx;
+    
+    self->baseURL   = RETAIN(_baseURL);
+    self->relString = [_string  copy];
+    
+    fidx = [self->relString indexOfString:@"#"];
+    qidx = [self->relString indexOfString:@"?"];
+
+    if ((fidx == NSNotFound) && (qidx == NSNotFound)) {
+        /* no query and fragment components */
+        self->relPath = RETAIN(self->relString);
+    }
+    else if (fidx == NSNotFound) {
+        /* query component */
+        self->relPath = [[self->relString substringToIndex:qidx] copy];
+        self->query   = [[self->relString substringFromIndex:(qidx + 1)] copy];
+    }
+    else if (qidx == NSNotFound) {
+        /* fragment component */
+        self->relPath  = [[self->relString substringToIndex:fidx] copy];
+        self->fragment = [[self->relString substringFromIndex:(fidx + 1)] copy];
+    }
+    else {
+        /* both, query and fragment components */
+        self->relPath = [[self->relString substringToIndex:fidx] copy];
+        
+        if (fidx > qidx) {
+            /* hm, invalid URL ! (query must follow fragment !) */
+            self->fragment =
+                [[self->relString substringFromIndex:(fidx + 1)] copy];
+        }
+        else {
+            self->fragment = [[[self->relString substringToIndex:qidx]
+                                                substringFromIndex:fidx]
+                                                copy];
+            
+            self->query = [[self->relString substringFromIndex:(qidx + 1)] copy];
+        }
+    }
+    
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(self->fragment);
+    RELEASE(self->query);
+    RELEASE(self->relPath);
+    RELEASE(self->relString);
+    RELEASE(self->baseURL);
+    [super dealloc];
+}
+
+/* stuff for relative URLs */
+
+- (NSURL *)baseURL
+{
+    return self->baseURL;
+}
+
+- (NSString *)relativePath
+{
+    /* may need to strip fragments&queries */
+    return self->relPath;
+}
+- (NSString *)relativeString
+{
+    return self->relString;
+}
+
+- (NSString *)absoluteString
+{
+    return [[self baseURL] _absoluteStringForRelativeURL:self];
+}
+
+/* properties */
+
+- (NSString *)fragment
+{
+    return self->fragment;
+}
+- (NSString *)query
+{
+    return self->query;
+}
+- (NSString *)host
+{
+    return [[self baseURL] host];
+}
+- (NSString *)path
+{
+    return [[self baseURL] _pathForRelativeURL:self];
+}
+- (NSString *)scheme
+{
+    return [[self baseURL] scheme];
+}
+- (NSNumber *)port
+{
+    return [[self baseURL] port];
+}
+
+- (BOOL)isFileURL
+{
+    return [[self baseURL] isFileURL];
+}
+
+- (NSString *)user
+{
+    return [[self baseURL] user];
+}
+- (NSString *)password
+{
+    return [[self baseURL] password];
+}
+
+/* NSCoding */
+
+- (void)encodeWithCoder:(NSCoder *)_coder
+{
+    [_coder encodeObject:[self baseURL]];
+    [_coder encodeObject:[self relativeString]];
+    [self notImplemented:_cmd];
+}
+- (id)initWithCoder:(NSCoder *)_decoder
+{
+    NSURL    *ibase;
+    NSString *istring;
+
+    ibase   = [_decoder decodeObject];
+    istring = [_decoder decodeObject];
+    [self notImplemented:_cmd];
+
+    return [self initWithString:istring relativeToURL:ibase];
+}
+
+/* description */
+
+- (NSString *)description
+{
+    return [NSString stringWithFormat:
+                       @"<%@ 0x%08x: abs='%@',rel='%@' relative to %@>",
+                       NSStringFromClass([self class]), self,
+                       [self absoluteString], [self relativeString],
+                       [self baseURL]];
+}
+
+@end /* _NSRelativeURL */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSURLHandle.h b/libFoundation/Foundation/NSURLHandle.h
new file mode 100644 (file)
index 0000000..3528479
--- /dev/null
@@ -0,0 +1,102 @@
+/* 
+   NSURLHandle.h
+
+   Copyright (C) 2000 MDlink GmbH, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSURLHandle_h__
+#define __NSURLHandle_h__
+
+#include <Foundation/NSObject.h>
+
+@class NSURL, NSURLHandle, NSString, NSData, NSMutableArray;
+
+@protocol NSURLHandleClient
+
+- (void)URLHandleResourceDidBeginLoading:(NSURLHandle *)_handler;
+- (void)URLHandleResourceDidCancelLoading:(NSURLHandle *)_handler;
+- (void)URLHandleResourceDidFinishLoading:(NSURLHandle *)_handler;
+
+- (void)URLHandle:(NSURLHandle *)_handler
+  resourceDataDidBecomeAvailable:(NSData *)_data;
+- (void)URLHandle:(NSURLHandle *)_handler
+  resourceDidFailLoadingWithReason:(NSString *)_reason;
+
+@end
+
+typedef enum {
+    NSURLHandleNotLoaded,
+    NSURLHandleLoadSucceeded,
+    NSURLHandleLoadInProgress,
+    NSURLHandleLoadFailed
+} NSURLHandleStatus;
+
+@interface NSURLHandle : NSObject
+{
+    NSMutableArray *clients;
+}
+
++ (Class)URLHandleClassForURL:(NSURL *)_url;
++ (void)registerURLHandleClass:(Class)_clazz;
+
++ (NSURLHandle *)cachedHandleForURL:(NSURL *)_url;
++ (BOOL)canInitWithURL:(NSURL *)_url;
+
+- (id)initWithURL:(NSURL *)_url cached:(BOOL)_flag;
+
+/* loading */
+
+- (NSData *)loadInForeground;
+- (void)loadInBackground;
+- (void)beginLoadInBackground;
+- (void)endLoadInBackground;
+- (NSURLHandleStatus)status;
+
+/* clients */
+
+- (void)addClient:(id<NSURLHandleClient>)_client;
+- (void)removeClient:(id<NSURLHandleClient>)_client;
+
+/* reading data */
+
+- (NSData *)resourceData;
+- (void)flushCachedData;
+
+/* writing data */
+
+- (BOOL)writeData:(NSData *)_data;
+
+/* properties */
+
+- (id)propertyForKey:(NSString *)_propertyKey;
+- (id)propertyForKeyIfAvailable:(NSString *)_propertyKey;
+- (BOOL)writeProperty:(id)_propValue forKey:(NSString *)_propertyKey;
+
+@end
+
+#endif /* __NSURLHandle_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSURLHandle.m b/libFoundation/Foundation/NSURLHandle.m
new file mode 100644 (file)
index 0000000..ec877b2
--- /dev/null
@@ -0,0 +1,188 @@
+/* 
+   NSURLHandle.m
+
+   Copyright (C) 2000 MDlink GmbH, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSURLHandle.h>
+#include <Foundation/NSURL.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSEnumerator.h>
+#include <Foundation/NSException.h>
+#include <common.h>
+
+@implementation NSURLHandle
+
+// THREAD
+static NSMutableArray *classRegistry = nil;
+
++ (void)initialize
+{
+    if (classRegistry == nil) {
+        classRegistry = [[NSMutableArray alloc] init];
+        [classRegistry addObject:NSClassFromString(@"NSFileURLHandle")];
+    }
+}
+
++ (Class)URLHandleClassForURL:(NSURL *)_url
+{
+    NSEnumerator *e;
+    Class        clazz;
+    
+    if (_url == nil)
+        return Nil;
+
+    NSAssert(classRegistry, @"class registry is not setup ..");
+    
+    e = [classRegistry objectEnumerator];
+    while ((clazz = [e nextObject])) {
+        if ([clazz canInitWithURL:_url])
+            return clazz;
+    }
+    return Nil;
+}
+
++ (void)registerURLHandleClass:(Class)_clazz
+{
+    if (_clazz == Nil)
+        return;
+    
+    NSAssert(classRegistry, @"class registry is not setup ..");
+    [classRegistry addObject:_clazz];
+}
+
++ (NSURLHandle *)cachedHandleForURL:(NSURL *)_url
+{
+    Class hClass;
+    
+    if (self != [NSURLHandle class])
+        return nil;
+    
+    if ((hClass = [self URLHandleClassForURL:_url]) == self)
+        /* avoid recursion */
+        return nil;
+    
+    return [hClass cachedHandleForURL:_url];
+}
+
++ (BOOL)canInitWithURL:(NSURL *)_url
+{
+    return NO;
+}
+
+- (id)initWithURL:(NSURL *)_url cached:(BOOL)_flag
+{
+    return self;
+}
+- (id)init
+{
+    return [self initWithURL:nil cached:NO];
+}
+
+- (void)dealloc
+{
+    RELEASE(self->clients);
+    [super dealloc];
+}
+
+/* loading */
+
+- (NSData *)loadInForeground
+{
+    return [self subclassResponsibility:_cmd];
+}
+
+- (void)loadInBackground
+{
+    NSData *data;
+    [self beginLoadInBackground];
+    data = [self loadInForeground];
+    [self endLoadInBackground];
+}
+- (void)beginLoadInBackground
+{
+}
+- (void)endLoadInBackground
+{
+}
+
+- (NSURLHandleStatus)status
+{
+    return NSURLHandleNotLoaded;
+}
+
+/* clients */
+
+- (void)addClient:(id<NSURLHandleClient>)_client
+{
+    if (self->clients == nil)
+        self->clients = [[NSMutableArray alloc] initWithCapacity:2];
+    [self->clients addObject:_client];
+}
+- (void)removeClient:(id<NSURLHandleClient>)_client
+{
+    [self->clients removeObjectIdenticalTo:_client];
+}
+
+/* reading data */
+
+- (NSData *)resourceData
+{
+    return [self loadInForeground];
+}
+- (void)flushCachedData
+{
+}
+
+/* writing data */
+
+- (BOOL)writeData:(NSData *)_data
+{
+    [self flushCachedData];
+    [self subclassResponsibility:_cmd];
+    return NO;
+}
+
+/* properties */
+
+- (id)propertyForKey:(NSString *)_propertyKey
+{
+    return nil;
+}
+- (id)propertyForKeyIfAvailable:(NSString *)_propertyKey
+{
+    return nil;
+}
+
+- (BOOL)writeProperty:(id)_propValue forKey:(NSString *)_propertyKey
+{
+    return NO;
+}
+
+@end /* NSURLHandle */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSUndoManager.h b/libFoundation/Foundation/NSUndoManager.h
new file mode 100644 (file)
index 0000000..8bce150
--- /dev/null
@@ -0,0 +1,54 @@
+/* 
+   NSUndoManager.h
+
+   Copyright (C) 1999 MDlink GmbH, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSUndoManager_h__
+#define __NSUndoManager_h__
+
+#include <Foundation/NSObject.h>
+
+@interface NSUndoManager : NSObject
+
+- (BOOL)canUndo;
+- (BOOL)canRedo;
+
+- (void)undo;
+- (void)redo;
+
+- (void)registerUndoWithTarget:(id)_target
+  selector:(SEL)_selector
+  object:(id)_object;
+
+- (void)removeAllActions;
+- (void)removeAllActionsWithTarget:(id)_target;
+
+@end
+
+#endif /* __NSUndoManager_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSUndoManager.m b/libFoundation/Foundation/NSUndoManager.m
new file mode 100644 (file)
index 0000000..6006c82
--- /dev/null
@@ -0,0 +1,65 @@
+/* 
+   NSUndoManager.m
+
+   Copyright (C) 1999 MDlink GmbH, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSUndoManager.h>
+
+@implementation NSUndoManager
+
+- (BOOL)canUndo
+{
+    return NO;
+}
+- (BOOL)canRedo
+{
+    return NO;
+}
+
+- (void)undo
+{
+}
+- (void)redo
+{
+}
+
+- (void)registerUndoWithTarget:(id)_target
+  selector:(SEL)_selector
+  object:(id)_object
+{
+}
+
+- (void)removeAllActions
+{
+}
+- (void)removeAllActionsWithTarget:(id)_target
+{
+}
+
+@end /* NSUndoManager */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSUserDefaults.h b/libFoundation/Foundation/NSUserDefaults.h
new file mode 100644 (file)
index 0000000..d497301
--- /dev/null
@@ -0,0 +1,154 @@
+/* 
+   NSUserDefaults.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSUserDefaults_h__
+#define __NSUserDefaults_h__
+
+#include <Foundation/NSObject.h>
+
+@class NSString, NSData;
+@class NSArray, NSMutableArray;
+@class NSDictionary, NSMutableDictionary;
+@class NSMutableSet;
+
+@interface NSUserDefaults : NSObject
+{
+    NSString            *directoryForSaving;
+    NSString            *appDomain;
+    NSMutableDictionary *persistentDomains;
+    NSMutableDictionary *volatileDomains;
+    NSMutableArray      *searchList;
+    NSMutableSet        *domainsToRemove;
+    NSMutableSet        *dirtyDomains;
+}
+
+/* Creation of defaults */
+
++ (NSUserDefaults *)standardUserDefaults;
++ (void)synchronizeStandardUserDefaults:(id)sender;
+
+/* Getting and Setting a Default */
+
+- (NSArray *)arrayForKey:(NSString *)defaultName;
+- (NSDictionary *)dictionaryForKey:(NSString *)defaultName;
+- (NSData *)dataForKey:(NSString *)defaultName;
+- (NSArray *)stringArrayForKey:(NSString *)defaultName;
+- (NSString *)stringForKey:(NSString *)defaultName;
+- (BOOL)boolForKey:(NSString *)defaultName;
+- (float)floatForKey:(NSString *)defaultName;
+- (int)integerForKey:(NSString *)defaultName;
+
+- (id)objectForKey:(NSString *)defaultName;
+- (void)removeObjectForKey:(NSString *)defaultName;
+
+- (void)setBool:(BOOL)value forKey:(NSString *)defaultName;
+- (void)setFloat:(float)value forKey:(NSString *)defaultName;
+- (void)setInteger:(int)value forKey:(NSString *)defaultName;
+- (void)setObject:(id)value forKey:(NSString *)defaultName;
+
+/* Initializing the User Defaults */
+
+- (id)init;
+- (id)initWithUser:(NSString *)userName;
+- (id)initWithPath:(NSString *)pathName;
+- (void)makeStandardDomainSearchList;
+
+/* Returning the Search List */
+
+- (void)setSearchList:(NSArray *)_array;
+- (NSArray *)searchList;
+
+/* Maintaining Persistent Domains */
+
+- (NSDictionary *)persistentDomainForName:(NSString *)domainName;
+- (NSArray *)persistentDomainNames;
+- (void)removePersistentDomainForName:(NSString *)domainName;
+- (void)setPersistentDomain:(NSDictionary *)domain
+  forName:(NSString *)domainName;
+- (BOOL)synchronize;
+- (void)persistentDomainHasChanged:(NSString *)domainName;
+
+/* Maintaining Volatile Domains */
+
+- (void)removeVolatileDomainForName:(NSString *)domainName;
+- (void)setVolatileDomain:(NSDictionary *)domain  
+  forName:(NSString *)domainName;
+- (NSDictionary *)volatileDomainForName:(NSString *)domainName;
+- (NSArray *)volatileDomainNames;
+
+/* Making Advanced Use of Defaults */
+
+- (NSDictionary *)dictionaryRepresentation;
+- (void)registerDefaults:(NSDictionary *)dictionary;
+
+@end
+
+/* Defaults domains */
+LF_EXPORT NSString *NSArgumentDomain;
+LF_EXPORT NSString *NSGlobalDomain;
+LF_EXPORT NSString *NSRegistrationDomain;
+
+/* Defaults Domains */
+LF_EXPORT  NSString *NSArgumentDomain;
+LF_EXPORT  NSString *NSGlobalDomain;
+LF_EXPORT  NSString *NSRegistrationDomain;
+/* Notification name */
+LF_EXPORT  NSString *NSUserDefaultsDidChangeNotification;
+/* Defaults names */
+LF_EXPORT  NSString *NSWeekDayNameArray;       
+LF_EXPORT  NSString *NSShortWeekDayNameArray;
+LF_EXPORT  NSString *NSMonthNameArray;
+LF_EXPORT  NSString *NSShortMonthNameArray;
+LF_EXPORT  NSString *NSTimeFormatString;
+LF_EXPORT  NSString *NSDateFormatString;
+LF_EXPORT  NSString *NSTimeDateFormatString;
+LF_EXPORT  NSString *NSShortTimeDateFormatString;
+LF_EXPORT  NSString *NSCurrencySymbol;
+LF_EXPORT  NSString *NSDecimalSeparator;
+LF_EXPORT  NSString *NSThousandsSeparator;
+LF_EXPORT  NSString *NSInternationalCurrencyString;
+LF_EXPORT  NSString *NSCurrencyString;
+LF_EXPORT  NSString *NSDecimalDigits;
+LF_EXPORT  NSString *NSAMPMDesignation;
+LF_EXPORT  NSString *NSHourNameDesignations;
+LF_EXPORT  NSString *NSYearMonthWeekDesignations;
+LF_EXPORT  NSString *NSEarlierTimeDesignations;
+LF_EXPORT  NSString *NSLaterTimeDesignations;
+LF_EXPORT  NSString *NSThisDayDesignations;
+LF_EXPORT  NSString *NSNextDayDesignations;
+LF_EXPORT  NSString *NSNextNextDayDesignations;
+LF_EXPORT  NSString *NSPriorDayDesignations;
+LF_EXPORT  NSString *NSDateTimeOrdering;
+LF_EXPORT  NSString *NSShortDateFormatString;
+LF_EXPORT  NSString *NSPositiveCurrencyFormatString;
+LF_EXPORT  NSString *NSNegativeCurrencyFormatString;
+
+#endif /* __NSUserDefaults_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSUserDefaults.m b/libFoundation/Foundation/NSUserDefaults.m
new file mode 100644 (file)
index 0000000..2f69b69
--- /dev/null
@@ -0,0 +1,900 @@
+/* 
+   NSUserDefaults.m
+
+   Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+          Ovidiu Predescu <ovidiu@net-community.com>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSData.h>
+#include <Foundation/NSValue.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSDate.h>
+#include <Foundation/NSNotification.h>
+#include <Foundation/NSProcessInfo.h>
+#include <Foundation/NSDistributedLock.h>
+#include <Foundation/NSBundle.h>
+#include <Foundation/NSUserDefaults.h>
+#include <Foundation/NSFileManager.h>
+#include <Foundation/NSSet.h>
+#include <Foundation/NSPathUtilities.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+
+#if HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+
+/*
+ * User defaults strings
+ */
+
+/* Defaults Domains */
+NSString *NSArgumentDomain     = @"NSArgumentDomain";
+NSString *NSGlobalDomain       = @"NSGlobalDomain";
+NSString *NSRegistrationDomain = @"NSRegistrationDomain";
+
+/* Notification name */
+NSString*  NSUserDefaultsDidChangeNotification =
+@"NSUserDefaultsDidChangeNotification";
+
+/* Defaults names */
+LF_DECLARE NSString *NSWeekDayNameArray            = @"NSWeekDayNameArray";
+LF_DECLARE NSString *NSShortWeekDayNameArray       = @"NSShortWeekDayNameArray";
+LF_DECLARE NSString *NSMonthNameArray              = @"NSMonthNameArray";
+LF_DECLARE NSString *NSShortMonthNameArray         = @"NSShortMonthNameArray";
+LF_DECLARE NSString *NSTimeFormatString            = @"NSTimeFormatString";
+LF_DECLARE NSString *NSDateFormatString            = @"NSDateFormatString";
+LF_DECLARE NSString *NSTimeDateFormatString        = @"NSTimeDateFormatString";
+LF_DECLARE NSString *NSShortTimeDateFormatString   = @"NSShortTimeDateFormatString";
+LF_DECLARE NSString *NSCurrencySymbol              = @"NSCurrencySymbol";
+LF_DECLARE NSString *NSDecimalSeparator            = @"NSDecimalSeparator";
+LF_DECLARE NSString *NSThousandsSeparator          = @"NSThousandsSeparator";
+LF_DECLARE NSString *NSInternationalCurrencyString = @"NSInternationalCurrencyString";
+LF_DECLARE NSString *NSCurrencyString              = @"NSCurrencyString";
+LF_DECLARE NSString *NSDecimalDigits               = @"NSDecimalDigits";
+LF_DECLARE NSString *NSAMPMDesignation             = @"NSAMPMDesignation";
+LF_DECLARE NSString *NSHourNameDesignations        = @"NSHourNameDesignations";
+LF_DECLARE NSString *NSYearMonthWeekDesignations   = @"NSYearMonthWeekDesignations";
+LF_DECLARE NSString *NSEarlierTimeDesignations     = @"NSEarlierTimeDesignations";
+LF_DECLARE NSString *NSLaterTimeDesignations       = @"NSLaterTimeDesignations";
+LF_DECLARE NSString *NSThisDayDesignations         = @"NSThisDayDesignations";
+LF_DECLARE NSString *NSNextDayDesignations         = @"NSNextDayDesignations";
+LF_DECLARE NSString *NSNextNextDayDesignations     = @"NSNextNextDayDesignations";
+LF_DECLARE NSString *NSPriorDayDesignations        = @"NSPriorDayDesignations";
+LF_DECLARE NSString *NSDateTimeOrdering            = @"NSDateTimeOrdering";
+LF_DECLARE NSString *NSShortDateFormatString       = @"NSShortDateFormatString";
+LF_DECLARE NSString *NSPositiveCurrencyFormatString = @"NSPositiveCurrencyFormatString";
+LF_DECLARE NSString *NSNegativeCurrencyFormatString = @"NSNegativeCurrencyFormatString";
+
+/* 
+ * User defaults shared class 
+ */
+
+
+#define CREATE_DEFAULT_PATH_ON_DEMAND 1
+
+@interface NSUserDefaults(Internals)
+- (BOOL)_checkPathNameCreate:(BOOL)_create;
+@end /*NSUserDefaults(Internals) */
+
+@interface NSSharedUserDefaults : NSUserDefaults
+{
+}
+@end
+
+@implementation NSSharedUserDefaults
+- (id)retain      {return self;}
+- (id)autorelease {return self;}
+- (void)release   {}
+- (unsigned int)retainCount {return 1;}
+@end
+
+/* 
+ * User defaults class 
+ */
+
+@implementation NSUserDefaults
+
+/* Getting and Setting a Default */
+
+- (NSArray*)arrayForKey:(NSString*)defaultName
+{
+    id obj = [self objectForKey:defaultName];
+    if ([obj isKindOfClass:[NSArray class]])
+       return obj;
+    return nil;
+}
+
+- (NSDictionary*)dictionaryForKey:(NSString*)defaultName
+{
+    id obj = [self objectForKey:defaultName];
+    if ([obj isKindOfClass:[NSDictionary class]])
+       return obj;
+    return nil;
+}
+
+- (NSData*)dataForKey:(NSString*)defaultName;
+{
+    id obj = [self objectForKey:defaultName];
+    if ([obj isKindOfClass:[NSData class]])
+       return obj;
+    return nil;
+}
+
+- (NSArray*)stringArrayForKey:(NSString*)defaultName
+{
+    id obj = [self objectForKey:defaultName];
+    if ([obj isKindOfClass:[NSArray class]]) {
+       int n;
+       Class strClass = [NSString class];
+       
+       for (n = [obj count]-1; n >= 0; n--)
+           if (![[obj objectAtIndex:n] isKindOfClass:strClass])
+               return nil;
+
+       return obj;
+    }
+    return nil;
+}
+
+- (NSString*)stringForKey:(NSString*)defaultName
+{
+    id obj = [self objectForKey:defaultName];
+    if ([obj isKindOfClass:[NSString class]])
+       return obj;
+    return nil;
+}
+
+- (BOOL)boolForKey:(NSString*)defaultName
+{
+    id obj;
+
+    if ((obj = [self objectForKey:defaultName])) {
+      if ([obj isKindOfClass:[NSString class]]) {
+       if ([obj compare:@"YES" options:NSCaseInsensitiveSearch] == 
+            NSOrderedSame) {
+          return YES;
+        }
+      }
+      if ([obj respondsToSelector:@selector(intValue)])
+          return [obj intValue] ? YES : NO;
+    }
+    return NO;
+}
+
+- (float)floatForKey:(NSString*)defaultName
+{
+    id obj = [self stringForKey:defaultName];
+    if (obj) 
+       return [obj floatValue];
+    return 0;
+}
+
+- (int)integerForKey:(NSString*)defaultName
+{
+    id obj = [self stringForKey:defaultName];
+    if (obj) 
+       return [obj intValue];
+    return 0;
+}
+
+- (void)setBool:(BOOL)value forKey:(NSString*)defaultName
+{
+    [self setObject:(value ? @"YES" : @"NO") 
+           forKey:defaultName];
+}
+
+- (void)setFloat:(float)value forKey:(NSString*)defaultName
+{
+    [self setObject:[NSString stringWithFormat:@"%f", value]
+           forKey:defaultName];
+}
+
+- (void)setInteger:(int)value forKey:(NSString*)defaultName
+{
+    [self setObject:[NSString stringWithFormat:@"%d", value] 
+           forKey:defaultName];
+}
+
+/* Accessing app domain defaults */
+
+- (id)objectForKey:(NSString*)defaultName
+{
+    int i, n = [self->searchList count];
+    
+    for (i = 0; i < n; i++) {
+       NSString     *name   = [self->searchList objectAtIndex:i];
+       NSDictionary *domain = nil;
+       id           obj;
+        
+       if ((domain = [self->volatileDomains objectForKey:name])) {
+           if (domain && (obj = [domain objectForKey:defaultName]))
+               return obj;
+        }
+       if ((domain = [self->persistentDomains objectForKey:name])) {
+           if (domain && (obj = [domain objectForKey:defaultName]))
+               return obj;
+        }
+    }
+    return nil;
+}
+
+- (void)setObject:(id)value forKey:(NSString*)defaultName
+{
+    NSMutableDictionary *domain;
+    
+    domain = (NSMutableDictionary *)[self persistentDomainForName:appDomain];
+    if (value == nil) {
+        fprintf(stderr,
+                "WARNING: attempt to set nil value for "
+                "default %s in domain %s\n",
+                [defaultName cString], [appDomain cString]);
+    }
+    [domain setObject:value forKey:defaultName];
+    [self persistentDomainHasChanged:appDomain];
+}
+
+- (void)removeObjectForKey:(NSString*)defaultName
+{
+    NSMutableDictionary *domain = [self persistentDomainForName:appDomain];
+    [domain removeObjectForKey:defaultName];
+    [self persistentDomainHasChanged:appDomain];
+}
+
+/* Returning the Search List */
+
+- (void)setSearchList:(NSArray *)_searchList
+{
+#if !LIB_FOUNDATION_BOEHM_GC
+    id old = self->searchList;
+#endif
+    self->searchList = [_searchList mutableCopyWithZone:[self zone]];
+    RELEASE(old);
+}
+- (NSArray *)searchList
+{
+    return self->searchList;
+}
+
+/* Making Advanced Use of Defaults */
+
+- (NSDictionary*)dictionaryRepresentation
+{
+    NSMutableDictionary *dict;
+    int i, n;
+    
+    dict = AUTORELEASE([[NSMutableDictionary alloc] init]);
+    n = [searchList count];
+    
+    for (i = n - 1; i >= 0; i--) {
+       NSString     *name;
+        NSDictionary *domain;
+        
+        name = [searchList objectAtIndex:i];
+       
+       if ((domain = [volatileDomains objectForKey:name]))
+           [dict addEntriesFromDictionary:domain];
+       if ((domain = [persistentDomains objectForKey:name]))
+           [dict addEntriesFromDictionary:domain];
+    }
+
+    return dict;
+}
+
+- (void)registerDefaults:(NSDictionary *)dictionary
+{
+    NSMutableDictionary *regDomain;
+    
+    regDomain = (NSMutableDictionary *)
+        [self volatileDomainForName:NSRegistrationDomain];
+    
+    if ([self->searchList indexOfObjectIdenticalTo:regDomain] == NSNotFound)
+       [self->searchList addObject:NSRegistrationDomain];
+    
+    [regDomain addEntriesFromDictionary:dictionary];
+}
+
+/* Maintaining Volatile Domains */
+
+- (void)removeVolatileDomainForName:(NSString*)domainName
+{
+    /* apparently in MacOSX-S the name isn't removed from the search list */
+    [self->searchList removeObject:domainName];
+    [self->volatileDomains removeObjectForKey:domainName];
+}
+
+- (void)setVolatileDomain:(NSDictionary *)domain  
+  forName:(NSString *)domainName
+{
+    if ([volatileDomains objectForKey:domainName]) {
+       [[[InvalidArgumentException alloc]
+                   initWithFormat:@"volatile domain %@ already exists",
+                                   domainName] raise];
+    }
+    
+    [volatileDomains setObject:
+                       [[NSMutableDictionary alloc] initWithDictionary:domain] 
+                     forKey:domainName];
+}
+
+- (NSDictionary *)volatileDomainForName:(NSString *)domainName
+{
+    return [volatileDomains objectForKey:domainName];
+}
+
+- (NSArray *)volatileDomainNames
+{
+    return [volatileDomains allKeys];
+}
+
+/* Maintaining Persistent Domains */
+
+- (NSDictionary *)loadPersistentDomainNamed:(NSString*)domainName
+{
+#if USE_LOCKING
+    int n;
+    NSDistributedLock *lock = nil;
+#endif
+    NSDictionary *dict = nil;
+    NSString     *domainPath;
+    NSString     *path;
+
+#if CREATE_DEFAULT_PATH_ON_DEMAND
+    domainPath = nil;
+    path       = nil;
+    if ([self _checkPathNameCreate:NO]) {
+#endif
+    domainPath = [[self->directoryForSaving 
+                       stringByAppendingPathComponent:domainName] 
+                      stringByAppendingPathExtension:@"plist"];
+#if CREATE_DEFAULT_PATH_ON_DEMAND    
+    }
+#endif
+    
+    /* Take the address of `path' to force the compiler to not allocate it
+       in a register. */
+    *(&path) = [domainPath stringByResolvingSymlinksInPath];
+    if (path) {
+        if (![[NSFileManager defaultManager] fileExistsAtPath:path])
+            path = nil;
+    }
+    if (path) {
+#if USE_LOCKING
+       lock = [NSDistributedLock lockWithPath:
+           [[path stringByDeletingPathExtension]
+               stringByAppendingPathExtension:@"lock"]];
+       for (n = 0;  n < 3; n++)
+           if ([lock tryLock])
+               break;
+           else
+               sleep(1);
+
+       if (n >= 3) {
+           NSLog(@"could not lock user defaults domain %@", domainName);
+           return nil;
+       }
+#endif
+
+        NS_DURING
+            dict = [NSDictionary dictionaryWithContentsOfFile:path];
+        NS_HANDLER {
+           fprintf (stderr,
+                     "caught exception '%s' with reason '%s' "
+                     "while loading user defaults domain '%s'\n",
+                     [[localException name] cString],
+                     [[localException reason] cString],
+                     [domainName cString]);
+           dict = nil;
+        }
+        NS_ENDHANDLER;
+
+#if 0
+        if (dict == nil) {
+          fprintf(stderr,
+                   "could not load user defaults domain %s from path %s.\n",
+                   [domainName cString], [path cString]);
+        }
+#endif
+      
+#if USE_LOCKING
+       [lock unlock];
+#endif
+    }
+    
+    if ((path == nil) || (dict == nil)) {
+       path = [NSBundle _fileResourceNamed:domainName
+                         extension:@"plist"
+                         inDirectory:@"Defaults"];
+
+       if (path) {
+            NS_DURING
+                dict = [NSDictionary dictionaryWithContentsOfFile:path];
+            NS_HANDLER
+               fprintf (stderr,
+                         "caught exception '%s' with reason '%s' "
+                         "while loading user defaults domain '%s'\n",
+                         [[localException name] cString],
+                         [[localException reason] cString],
+                         [domainName cString]);
+               dict = nil;
+            NS_ENDHANDLER
+       }
+#if 0
+       else {
+          fprintf(stderr,
+                   "could not load user defaults domain %s from path %s.\n",
+                   [domainName cString], [path cString]);
+        }
+#endif
+    }
+    
+    if (dict == nil)
+       return nil;
+    
+    dict = [[NSMutableDictionary alloc] initWithDictionary:dict];
+    return AUTORELEASE(dict);
+}
+
+- (BOOL)savePersistentDomainNamed:(NSString*)domainName
+{
+    BOOL ok = YES;
+#if USE_LOCKING
+    int n;
+    NSDistributedLock* lock = nil;
+#endif
+    NSDictionary *dict = nil;
+    NSString     *path = nil;
+
+#if CREATE_DEFAULT_PATH_ON_DEMAND
+    [self _checkPathNameCreate:YES];
+#endif
+    
+    dict = [self->persistentDomains objectForKey:domainName];
+    path = [[self->directoryForSaving stringByAppendingPathComponent:domainName]
+                                      stringByAppendingPathExtension:@"plist"];
+
+    if ([path length] < 1) {
+        NSLog(@"Could not save persistent domain %@: invalid path '%@', "
+              @"directory for saving is '%@'.",
+              domainName, path, self->directoryForSaving);
+        return NO;
+    }
+
+#if USE_LOCKING
+    lock = [NSDistributedLock lockWithPath:
+                                [path stringByAppendingPathExtension:@"lock"]];
+    for (n = 0;  n < 3; n++)
+       if (![lock tryLock])
+           sleep(1);
+       else
+           break;
+    if (n >= 3) {
+       NSLog(@"could not lock user defaults domain %@", domainName);
+       return NO;
+    }
+#endif
+
+    NS_DURING
+       ok = [dict writeToFile:path atomically:YES];
+    NS_HANDLER
+       fprintf (stderr,
+                 "caught exception '%s' with reason '%s' "
+                 "while saving user defaults domain '%s'\n",
+                [[localException name]   cString],
+                [[localException reason] cString],
+                [domainName cString]);
+       ok = NO;
+    NS_ENDHANDLER
+    
+#if USE_LOCKING
+    [lock unlock];
+#endif
+
+    if (!ok) {
+        NSLog(@"Could not save persistent domain %@ (in path '%@').",
+              domainName, path);
+    }
+    return ok;
+}
+
+- (void)removePersistentDomainForName:(NSString*)domainName
+{
+    [domainsToRemove addObject:domainName];
+    [persistentDomains removeObjectForKey:domainName];
+    [self persistentDomainHasChanged:domainName];
+}
+
+- (NSDictionary *)persistentDomainForName:(NSString*)domainName
+{
+    NSDictionary *domain;
+    
+    domain = [persistentDomains objectForKey:domainName];
+    
+    if (domain == nil) {
+       domain = [[self loadPersistentDomainNamed:domainName] mutableCopy];
+       if (domain)
+           [persistentDomains setObject:domain forKey:domainName];
+        RELEASE(domain);
+    }
+    return domain;
+}
+
+- (void)setPersistentDomain:(NSDictionary*)domain
+  forName:(NSString*)domainName
+{
+    if ([self->persistentDomains objectForKey:domainName]) {
+       [[[InvalidArgumentException alloc]
+                   initWithFormat:@"persistent domain %@ already exists",
+                                   domainName] raise];
+    }
+    if (domain == nil) {
+        fprintf(stderr,
+                "WARNING: attempt to set nil for persistent domain %s.\n",
+                [domainName cString]);
+    }
+    [self->persistentDomains setObject:domain forKey:domainName];
+    [self->domainsToRemove removeObject:domainName];
+    [self persistentDomainHasChanged:domainName];
+}
+
+- (NSArray*)persistentDomainNames
+{
+    NSArray *knownDomains;
+    int     i, count;
+
+#if CREATE_DEFAULT_PATH_ON_DEMAND
+    if (![self _checkPathNameCreate:NO])
+        return nil;
+#endif
+
+    knownDomains =
+        [[NSFileManager defaultManager]
+                        directoryContentsAtPath:self->directoryForSaving];
+    count = [knownDomains count];
+    
+    if (count > 0) {
+       NSString *domainNames[count];
+
+       for (i = 0; i < count; i++) {
+           domainNames[i] = [[knownDomains objectAtIndex:i]
+                                            stringByDeletingPathExtension];
+        }
+       return [NSArray arrayWithObjects:domainNames count:count];
+    }
+    return nil;
+}
+
+/* Creation of defaults */
+
+static NSUserDefaults* sharedDefaults    = nil;
+static NSString*       sharedDefaultsDir = nil;
+
++ (void)setStandardDefaultsDirectory:(NSString*)dir
+{
+    ASSIGN(sharedDefaultsDir, dir);
+}
+
++ (NSUserDefaults *)standardUserDefaults
+{
+    if (sharedDefaults == nil) {
+       if (sharedDefaultsDir) {
+            sharedDefaults = (id)
+                [[NSSharedUserDefaults alloc]
+                                       initWithPath:sharedDefaultsDir];
+       }
+       else {
+           NSString *defdir;
+
+#if WITH_GNUSTEP
+            NSDictionary *env;
+            
+            env = [[NSProcessInfo processInfo] environment];
+            defdir = [env objectForKey:@"GNUSTEP_DEFAULTS_ROOT"];
+            if ([defdir length] == 0)
+                defdir = [env objectForKey:@"GNUSTEP_USER_ROOT"];
+#else
+            defdir = nil;
+#endif
+
+            if ([defdir length] == 0) {
+                if ((defdir = NSHomeDirectory()) == nil) {
+                    NSString *user = NSUserName();
+                
+                    fprintf(stderr,
+                            "WARNING: could not get home "
+                            "directory of user %s !\n",
+                            user ? [user cString] : "<null>");
+                }
+            }
+            
+            defdir =
+                [defdir stringByAppendingPathComponent:@".libFoundation"];
+            defdir =
+                [defdir stringByAppendingPathComponent:@"Defaults"];
+            
+#if !CREATE_DEFAULT_PATH_ON_DEMAND
+           if (([defdir stringByResolvingSymlinksInPath] == nil) ||
+                (![[NSFileManager defaultManager] fileExistsAtPath:defdir])) {
+               if (![[NSFileManager defaultManager]
+                                     createDirectoryAtPath:defdir
+                                     attributes:nil]) {
+                    fprintf(stderr,
+                            "WARNING: could not create user defaults directory"
+                            " at path %s !\n",
+                            defdir ? [defdir cString] : "<null>");
+                }
+            }
+#endif            
+
+           sharedDefaults = (id)
+                [[NSSharedUserDefaults alloc] initWithPath:defdir];
+       }
+       [sharedDefaults makeStandardDomainSearchList];
+    }
+    return sharedDefaults;
+}
+
++ (void)synchronizeStandardUserDefaults:(id)sender
+{
+    [sharedDefaults synchronize];
+}
+
+/* Initializing the User Defaults */
+
+- (id)init
+{
+    return [self initWithUser:NSUserName()];
+}
+
+- (id)initWithUser:(NSString*)aUserName
+{
+    return [self initWithPath:[[NSHomeDirectoryForUser(aUserName)
+                   stringByAppendingPathComponent:@".libFoundation"]
+                   stringByAppendingPathComponent:@"Defaults"]];
+}
+
+- (NSDictionary *)_collectArgumentDomain {
+    NSMutableDictionary *defArgs = nil;
+    NSArray             *args;
+    int           i, n;
+
+    args    = [[NSProcessInfo processInfo] arguments];
+    *(&n)   = [args count];
+    defArgs = [NSMutableDictionary dictionaryWithCapacity:(n / 2)];
+
+    for (*(&i) = 0; i < n; i++) {
+            NSString *argument;
+
+            *(&argument) = [args objectAtIndex:i];
+
+            if ([argument hasPrefix:@"-"] && [argument length] > 1) {
+                // found option
+                if ((i + 1) == n) { // is last option ?
+                    fprintf(stderr,
+                            "Missing value for command line default '%s'.\n",
+                            [[argument substringFromIndex:1] cString]);
+                }
+                else { // is not the last option
+                    id value = [args objectAtIndex:(i + 1)];
+
+                    argument = [argument substringFromIndex:1];
+
+                    // parse property list value
+                    NS_DURING {
+                        *(&value) = [value propertyList];
+                    }
+                    NS_HANDLER {}
+                    NS_ENDHANDLER;
+
+                    if (value == nil) {
+                        fprintf(stderr,
+                                "Could not process value %s "
+                                "of command line default '%s'.\n",
+                                [argument cString],
+                                [[args objectAtIndex:(i + 1)] cString]);
+                    }
+                    else {
+                        [defArgs setObject:value forKey:argument];
+                    }
+                    i++; // skip value
+                }
+            }
+    }
+    return defArgs;
+}
+
+- (id)initWithPath:(NSString*)pathName
+{
+    NSDictionary* dict;
+    NSArray*      languages;
+    int           i, n;
+    NSZone        *z = [self zone];
+    
+    self->directoryForSaving = [pathName copyWithZone:z];
+
+    self->persistentDomains = 
+        [[NSMutableDictionary allocWithZone:z] initWithCapacity:8];
+    self->volatileDomains = 
+        [[NSMutableDictionary allocWithZone:z] initWithCapacity:4];
+
+    self->domainsToRemove= [[NSMutableSet allocWithZone:z] initWithCapacity:2];
+    self->dirtyDomains   = [[NSMutableSet allocWithZone:z] initWithCapacity:2];
+    
+    self->searchList = [[NSMutableArray allocWithZone:z] initWithCapacity:8];
+    self->appDomain  = RETAIN([[NSProcessInfo processInfo] processName]);
+    
+    [self setVolatileDomain:[self _collectArgumentDomain]
+          forName:NSArgumentDomain];
+    
+    [self setVolatileDomain:[NSMutableDictionary dictionaryWithCapacity:128] 
+          forName:NSRegistrationDomain];
+    
+    if ((dict = [self persistentDomainForName:appDomain]) == nil) {
+       [self setPersistentDomain:
+                  [NSMutableDictionary dictionaryWithCapacity:16] 
+              forName:appDomain];
+    }
+    if ((dict = [self persistentDomainForName:NSGlobalDomain]) == nil) {
+       [self setPersistentDomain:
+                  [NSMutableDictionary dictionaryWithCapacity:64] 
+              forName:NSGlobalDomain];
+    }
+    
+    languages = [[self persistentDomainForName:NSGlobalDomain] 
+                       objectForKey:@"Languages"];
+    if ((languages != nil) && ![languages isKindOfClass:[NSArray class]])
+        languages = [NSArray arrayWithObjects:&languages count:1];
+    for (i = 0, n = [languages count]; i < n; i++) {
+       dict = [self persistentDomainForName:[languages objectAtIndex:i]];
+       if (dict != nil)
+           break;
+    }
+    
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(self->directoryForSaving);
+    RELEASE(self->appDomain);
+    RELEASE(self->persistentDomains);
+    RELEASE(self->volatileDomains);
+    RELEASE(self->searchList);
+    RELEASE(self->domainsToRemove);
+    RELEASE(self->dirtyDomains);
+    [super dealloc];
+}
+
+- (void)makeStandardDomainSearchList
+{
+    int i,n;
+    NSArray* languages;
+    
+    /* make clear list */
+    [searchList removeAllObjects];
+    
+    /* make argument domain */
+    [searchList addObject:NSArgumentDomain];
+    
+    /* make app domain */
+    [searchList addObject:appDomain];
+    
+    /* make global domain */
+    [searchList addObject:NSGlobalDomain];
+    
+    /* add languages domains */
+    languages = [[self persistentDomainForName:NSGlobalDomain] 
+                       objectForKey:@"Languages"];
+    if (languages != nil && ![languages isKindOfClass:[NSArray class]]) 
+        languages = [NSArray arrayWithObject:languages];
+    else if (languages == nil)
+       languages = [NSArray arrayWithObject:@"English"];
+    
+    for (i = 0, n = [languages count]; i < n; i++) {
+       NSString* lang = [languages objectAtIndex:i];
+       /* check that the domain exists */
+       if ([self persistentDomainForName:lang]) {
+           [searchList addObject:lang];
+       }
+    }
+
+    /* add catch-all registration domain */
+    [searchList addObject:NSRegistrationDomain];
+}
+
+- (BOOL)synchronize
+{
+    NSEnumerator *enumerator;
+    NSString     *domainName;
+    BOOL         allOk = YES;
+    
+    enumerator = [self->dirtyDomains objectEnumerator];
+    while ((domainName = [enumerator nextObject]))
+       allOk = allOk && [self savePersistentDomainNamed:domainName];
+    
+    enumerator = [self->domainsToRemove objectEnumerator];
+
+#if CREATE_DEFAULT_PATH_ON_DEMAND
+    [self _checkPathNameCreate:YES];
+#endif
+
+    while ((domainName = [enumerator nextObject])) {
+       NSString* path = [[self->directoryForSaving
+                           stringByAppendingPathComponent:domainName]
+                           stringByAppendingPathExtension:@"plist"];
+
+       [[NSFileManager defaultManager] removeFileAtPath:path handler:nil];
+    }
+    return allOk;
+}
+
+- (void)persistentDomainHasChanged:(NSString*)domainName
+{
+    if (![self->dirtyDomains containsObject:domainName]) {
+       [self->dirtyDomains addObject:domainName];
+       [[NSNotificationCenter defaultCenter]
+           postNotificationName:NSUserDefaultsDidChangeNotification
+           object:self
+           userInfo:nil];
+    }
+}
+
+@end
+
+@implementation NSUserDefaults(Internals)
+
+- (BOOL)_checkPathNameCreate:(BOOL)_create
+{
+    NSString *defDir;
+
+    defDir = self->directoryForSaving;
+    
+    if (([defDir stringByResolvingSymlinksInPath] == nil) ||
+        (![[NSFileManager defaultManager] fileExistsAtPath:defDir])) {
+
+        if (_create) {
+            if (![[NSFileManager defaultManager]
+                                 createDirectoryAtPath:defDir
+                                 attributes:nil]) {
+                fprintf(stderr,
+                        "WARNING: could not create user defaults directory"
+                        " at path %s !\n",
+                        defDir
+                        ? [defDir cString] : "<null>");
+            }
+        }
+        else
+            return NO;
+    }
+    return YES;
+}
+
+@end /* NSUserDefaults(Internals) */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSUtilities.h b/libFoundation/Foundation/NSUtilities.h
new file mode 100644 (file)
index 0000000..8469fa0
--- /dev/null
@@ -0,0 +1,124 @@
+/* 
+   NSUtilities.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+          Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+          Florin Mihaila <phil@pathcom.com>
+          Bogdan Baliuc <stark@protv.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSUtilities_h__
+#define __NSUtilities_h__
+
+#include <Foundation/NSObject.h>
+#include <Foundation/NSObjCRuntime.h>
+#include <Foundation/NSHashTable.h>
+#include <Foundation/NSMapTable.h>
+#include <Foundation/NSEnumerator.h>
+
+#include <objc/objc.h>
+#include <stdarg.h>
+
+@class NSObject;
+@class NSString;
+@class NSZone;
+@class NSArray;
+
+/*
+ * Virtual Memory Management 
+ */
+
+/* Get the Virtual Memory Page Size */
+LF_EXPORT unsigned NSPageSize(void);
+LF_EXPORT unsigned NSLogPageSize(void);
+LF_EXPORT unsigned NSRoundDownToMultipleOfPageSize(unsigned byteCount);
+LF_EXPORT unsigned NSRoundUpToMultipleOfPageSize(unsigned byteCount);
+
+/* Allocate or Free Virtual Memory */
+LF_EXPORT void* NSAllocateMemoryPages(unsigned byteCount);
+LF_EXPORT void NSDeallocateMemoryPages(void* pointer, unsigned byteCount);
+LF_EXPORT void NSCopyMemoryPages(const void* source, void* destination, unsigned byteCount);
+
+/*
+ * Allocate or Free an Object
+ */
+
+LF_EXPORT NSObject* NSAllocateObject(Class aClass, unsigned extraBytes, NSZone* zone);
+LF_EXPORT NSObject* NSCopyObject(NSObject* anObject, unsigned extraBytes, NSZone* zone);
+LF_EXPORT void NSDeallocateObject(NSObject* anObject);
+LF_EXPORT NSZone* NSZoneFromObject(NSObject* anObject);
+LF_EXPORT BOOL NSShouldRetainWithZone(NSObject* anObject, NSZone* requestedZone);
+
+/*
+ * Message log on console/stderr
+ */
+
+LF_EXPORT void NSLog(NSString* format, ...);
+LF_EXPORT void NSLogv(NSString* format, va_list args);
+
+/*
+ * Manipulate the Number of References to an Object
+ */
+
+LF_EXPORT BOOL NSDecrementExtraRefCountWasZero(id anObject);
+LF_EXPORT void NSIncrementExtraRefCount(id anObject);
+LF_EXPORT unsigned NSExtraRefCount(id anObject);
+
+/*
+ * Convenience functions to deal with Hash and Map Table
+ */
+
+LF_EXPORT unsigned __NSHashObject(void* table, const void* anObject);
+LF_EXPORT unsigned __NSHashPointer(void* table, const void* anObject);
+LF_EXPORT unsigned __NSHashInteger(void* table, const void* anObject);
+LF_EXPORT unsigned __NSHashCString(void* table, const void* anObject);
+LF_EXPORT BOOL __NSCompareObjects(void* table, 
+       const void* anObject1, const void* anObject2);
+LF_EXPORT BOOL __NSComparePointers(void* table, 
+       const void* anObject1, const void* anObject2);
+LF_EXPORT BOOL __NSCompareInts(void* table, 
+       const void* anObject1, const void* anObject2);
+LF_EXPORT BOOL __NSCompareCString(void* table, 
+       const void* anObject1, const void* anObject2);
+LF_EXPORT void __NSRetainNothing(void* table, const void* anObject);
+LF_EXPORT void __NSRetainObjects(void* table, const void* anObject);
+LF_EXPORT void __NSReleaseNothing(void* table, void* anObject);
+LF_EXPORT void __NSReleaseObjects(void* table, void* anObject);
+LF_EXPORT void __NSReleasePointers(void* table, void* anObject);
+LF_EXPORT NSString* __NSDescribeObjects(void* table, const void* anObject);
+LF_EXPORT NSString* __NSDescribePointers(void* table, const void* anObject);
+LF_EXPORT NSString* __NSDescribeInts(void* table, const void* anObject);
+
+/* Some allocation macros */
+#define OBJC_MALLOC(pointer, type, elements) \
+       (pointer = calloc (sizeof(type), elements))
+
+#define OBJC_FREE(pointer) \
+       if (pointer) free(pointer)
+
+#endif /* __NSUtilities_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSUtilities.m b/libFoundation/Foundation/NSUtilities.m
new file mode 100644 (file)
index 0000000..0615fd8
--- /dev/null
@@ -0,0 +1,116 @@
+/* 
+   NSUtilities.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+          Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSUtilities.h>
+#include <Foundation/NSDate.h>
+#include <Foundation/NSProcessInfo.h>
+#include <Foundation/NSPosixFileDescriptor.h>
+#include <Foundation/NSLock.h>
+#include <Foundation/NSByteOrder.h>
+#include <config.h>
+
+#if defined(HAVE_WINDOWS_H)
+#  include <windows.h>
+#endif
+
+extern NSRecursiveLock *libFoundationLock;
+
+/* 
+ * Log a Message 
+ */
+
+static Class NSStringClass              = Nil;
+static Class NSCalendarDateClass        = Nil;
+static Class NSProcessInfoClass         = Nil;
+
+void NSLog(NSString *format, ...)
+{
+    va_list ap;
+    
+    va_start(ap, format);
+    NSLogv(format, ap);
+    va_end(ap);
+}
+
+void NSLogv(NSString *format, va_list args)
+{
+    NSString       *message;
+    NSCalendarDate *date;
+    
+    if (NSStringClass == Nil)
+        NSStringClass = [NSString class];
+    if (NSCalendarDateClass == Nil)
+        NSCalendarDateClass = [NSCalendarDate class];
+    if (NSProcessInfoClass == Nil)
+        NSProcessInfoClass = [NSProcessInfo class];
+    
+    message = [[NSStringClass alloc] initWithFormat:format arguments:args];
+    date    = [[NSCalendarDateClass alloc] init];
+    
+    [libFoundationLock lock];
+    
+    fprintf(stderr,
+            "%s %s [%d]: %s\n",
+            [[date descriptionWithCalendarFormat:@"%b %d %H:%M:%S"] cString],
+            [[[NSProcessInfoClass processInfo] processName] cString],
+#if defined(__MINGW32__)
+            (int)GetCurrentProcessId(),
+#else
+            getpid(),
+#endif
+            [message cString]);
+    
+    [libFoundationLock unlock];
+    
+    RELEASE(date);
+    RELEASE(message);
+}
+
+/* Support function for debugger */
+NSString *_NSNewStringFromCString (const char* cString)
+{
+    if (NSStringClass == Nil)
+        NSStringClass = [NSString class];
+    return [NSStringClass stringWithCString:cString];
+}
+
+/* NSByteOrder.h */
+
+unsigned int NSHostByteOrder(void) {
+#if WORDS_BIGENDIAN
+    return NS_BigEndian;
+#else
+    return NS_LittleEndian;
+#endif
+}
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSVMPage.m b/libFoundation/Foundation/NSVMPage.m
new file mode 100644 (file)
index 0000000..6d46062
--- /dev/null
@@ -0,0 +1,158 @@
+/* 
+   NSVMPage.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+          Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <config.h>
+#include <objc/objc-api.h>
+
+#ifdef NeXT
+# include <mach/mach.h>
+# include <mach/mach_error.h>
+#endif
+
+#if defined(__MINGW32__)
+#  include <windows.h>
+static DWORD getpagesize(void)
+{
+    SYSTEM_INFO info;
+    GetSystemInfo(&info);
+    return info.dwPageSize;
+}
+#elif !defined(HAVE_GETPAGESIZE)
+#  if HAVE_SYSCONF
+#    include <unistd.h>
+#    ifdef _SC_PAGE_SIZE
+#      define _SC_PAGESIZE _SC_PAGE_SIZE
+#    endif
+#    define getpagesize()      sysconf(_SC_PAGESIZE)
+#  elif HAVE_GETSYSTEMINFO
+#    include <windows.h>
+static DWORD getpagesize(void)
+{
+    SYSTEM_INFO info;
+    GetSystemInfo(&info);
+    return info.dwPageSize;
+}
+#  endif
+#endif
+
+#include <Foundation/common.h>
+#include <Foundation/NSZone.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSUtilities.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+
+/* 
+ * Get the Virtual Memory Page Size 
+ */
+
+unsigned NSPageSize(void)
+{
+    return getpagesize();
+}
+
+unsigned NSLogPageSize(void)
+{
+    register unsigned pagesize = NSPageSize();
+    register unsigned log = 0;
+
+    if(pagesize >= 65536) { log += 16; pagesize >>= 16; }
+    if(pagesize >=   256) { log +=  8; pagesize >>=  8; }
+    if(pagesize >=    16) { log +=  4; pagesize >>=  4; }
+    if(pagesize >=     4) { log +=  2; pagesize >>=  2; }
+    if(pagesize >=     2) { log +=  1; pagesize >>=  1; }
+    return log;
+}
+
+unsigned NSRoundDownToMultipleOfPageSize(unsigned byteCount)
+{
+    unsigned pageSize = NSPageSize();
+    return (byteCount / pageSize) * pageSize;
+}
+
+unsigned NSRoundUpToMultipleOfPageSize(unsigned byteCount)
+{
+    unsigned pageSize = NSPageSize();
+    unsigned anotherOne = (byteCount % pageSize != 0);
+
+    return (byteCount / pageSize + anotherOne) * pageSize;
+}
+
+/* Allocate or Free Virtual Memory */
+void *NSAllocateMemoryPages(unsigned byteCount)
+{
+#ifdef NeXT
+    kern_return_t ret;
+    vm_address_t p;
+    unsigned size = NSRoundUpToMultipleOfPageSize(byteCount);
+
+    if((ret = vm_allocate(task_self(), &p, size, TRUE)) != KERN_SUCCESS) {
+       THROW([memoryExhaustedException
+                   setPointer:(void**)&p memorySize:size]);
+       return NULL;
+    }
+    else return (void*)p;
+#else
+    return objc_calloc(byteCount, 1);
+#endif 
+}
+
+void NSDeallocateMemoryPages(void *pointer, unsigned byteCount)
+{
+#ifdef NeXT
+    unsigned size = NSRoundUpToMultipleOfPageSize(byteCount);
+    kern_return_t ret;
+
+    if ((ret = vm_deallocate(task_self(), (vm_address_t)pointer, size))
+           != KERN_SUCCESS)
+       THROW([[[MemoryDeallocationException alloc]
+           setReason:[NSString stringWithCString:mach_error_string(ret)]]
+           setPointer:&pointer memorySize:size]);
+#else
+    objc_free(pointer);
+#endif
+}
+
+void NSCopyMemoryPages(const void *source, void *dest, unsigned byteCount)
+{
+#ifdef NeXT
+    unsigned size = NSRoundUpToMultipleOfPageSize(byteCount);
+    kern_return_t ret;
+
+    if((ret = vm_copy(task_self(), (vm_address_t)source, size,
+                     (vm_address_t)dest)) != KERN_SUCCESS)
+       THROW([[MemoryCopyException alloc]
+           setReason:[NSString stringWithCString:mach_error_string(ret)]]);
+#else
+    memcpy(dest, source, byteCount);
+#endif
+}
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSValue.h b/libFoundation/Foundation/NSValue.h
new file mode 100644 (file)
index 0000000..b402113
--- /dev/null
@@ -0,0 +1,152 @@
+/* 
+   NSValue.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSValue_h__
+#define __NSValue_h__
+
+#include <Foundation/NSObject.h>
+#include <Foundation/NSGeometry.h>
+
+@class NSString;
+@class NSDictionary;
+
+@interface NSValue : NSObject
+
+// Internal method to determine concrete value class
+
++ (Class)concreteClassForObjCType:(const char*)type;
+
+// Allocating and Initializing Value Objects
+
++ (NSValue*)valueWithBytes:(const void*)value objCType:(const char*)type;
++ (NSValue*)value:(const void*)value withObjCType:(const char*)type;
++ (NSValue*)valueWithNonretainedObject:(id)anObject;
++ (NSValue*)valueWithPointer:(const void*)pointer;
+
+// Allocating and Initializing Geometry Value Objects
+
++ (NSValue*)valueWithPoint:(NSPoint)point;
++ (NSValue*)valueWithRect:(NSRect)rect;
++ (NSValue*)valueWithSize:(NSSize)size;
+
+// Initializing
+- (id)initWithBytes:(const void*)value objCType:(const char*)type;
+
+// Accessing Data in Value Objects
+
+- (void)getValue:(void*)value;
+- (const char*)objCType;
+
+- (id)nonretainedObjectValue;
+- (void*)pointerValue;
+- (void*)valueBytes;
+- (BOOL)isEqualToValue:(NSValue*)aValue;
+
+// Accessing Data in Geometry Value Objects
+
+- (NSRect)rectValue;
+- (NSSize)sizeValue;
+- (NSPoint)pointValue;
+
+@end
+
+@interface NSNumber : NSValue
+
+// Internal method to determine concrete value class
+
++ (Class)concreteClassForObjCType:(const char*)type;
+
+// Allocating and Initializing
+
+- (id)initWithBool:(BOOL)value;
+- (id)initWithChar:(char)value;
+- (id)initWithUnsignedChar:(unsigned char)value;
+- (id)initWithShort:(short)value;
+- (id)initWithUnsignedShort:(unsigned short)value;
+- (id)initWithInt:(int)value;
+- (id)initWithUnsignedInt:(unsigned int)value;
+- (id)initWithLong:(long)value;
+- (id)initWithUnsignedLong:(unsigned long)value;
+- (id)initWithLongLong:(long long)value;
+- (id)initWithUnsignedLongLong:(unsigned long long)value;
+- (id)initWithFloat:(float)value;
+- (id)initWithDouble:(double)value;
+
++ (NSNumber*)numberWithBool:(BOOL)value; 
++ (NSNumber*)numberWithChar:(char)value;
++ (NSNumber*)numberWithUnsignedChar:(unsigned char)value;
++ (NSNumber*)numberWithShort:(short)value;
++ (NSNumber*)numberWithUnsignedShort:(unsigned short)value;
++ (NSNumber*)numberWithInt:(int)value;
++ (NSNumber*)numberWithUnsignedInt:(unsigned int)value;
++ (NSNumber*)numberWithLong:(long)value;
++ (NSNumber*)numberWithUnsignedLong:(unsigned long)value;
++ (NSNumber*)numberWithLongLong:(long long)value;
++ (NSNumber*)numberWithUnsignedLongLong:(unsigned long long)value;
++ (NSNumber*)numberWithFloat:(float)value;
++ (NSNumber*)numberWithDouble:(double)value;
+
+// Accessing Data 
+
+- (BOOL)boolValue;
+- (char)charValue;
+- (unsigned char)unsignedCharValue;
+- (short)shortValue;
+- (unsigned short)unsignedShortValue;
+- (int)intValue;
+- (unsigned int)unsignedIntValue;
+- (long)longValue;
+- (unsigned long)unsignedLongValue;
+- (long long)longLongValue;
+- (unsigned long long)unsignedLongLongValue;
+- (float)floatValue;
+- (double)doubleValue;
+
+// Converting to string
+
+- (NSString*)stringValue;
+- (NSString*)descriptionWithLocale:(NSDictionary*)locale;
+- (NSString*)description;
+
+// Comparing Data 
+
+- (NSComparisonResult)compare:(NSNumber*)otherNumber;
+- (BOOL)isEqualToNumber:(NSNumber*)aNumber;
+
+@end
+
+// Method to determine the conversion sense for comparing NSNumber values 
+
+@interface NSNumber(Generality)
+- (int)generality;
+@end
+
+#endif /* __NSValue_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSValue.m b/libFoundation/Foundation/NSValue.m
new file mode 100644 (file)
index 0000000..8efdf4b
--- /dev/null
@@ -0,0 +1,269 @@
+/* 
+   NSValue.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSCoder.h>
+#include <Foundation/NSException.h>
+#include <Foundation/exceptions/NSValueExceptions.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSUtilities.h>
+
+#include <extensions/objc-runtime.h>
+
+#include "NSConcreteValue.h"
+#include "NSConcreteNumber.h"
+
+@implementation NSValue
+
+/* 
+ * Returns concrete class for a given encoding 
+ * Should we return NSNumbers ?
+ */
+
++ (Class)concreteClassForObjCType:(const char*)type
+{
+    /* Let someone else deal with this error */
+    if (!type)
+       [[[NSValueException new] setReason:@"NULL type"] raise];
+
+    if (Strlen(type) == 1) {
+       switch(*type) {
+           case _C_CHR:        return [NSCharNumber class];
+           case _C_UCHR:       return [NSUCharNumber class];
+           case _C_SHT:        return [NSShortNumber class];
+           case _C_USHT:       return [NSUShortNumber class];
+           case _C_INT:        return [NSIntNumber class];
+           case _C_UINT:       return [NSUIntNumber class];
+           case _C_LNG:        return [NSLongNumber class];
+           case _C_ULNG:       return [NSULongNumber class];
+           case _C_FLT:        return [NSFloatNumber class];
+           case _C_DBL:        return [NSDoubleNumber class];
+           case _C_ID:         return [NSNonretainedObjectValue class];
+           case 'q':           return [NSLongLongNumber class];
+           case 'Q':           return [NSULongLongNumber class];
+       }
+    }
+    else {
+       if(!Strcmp(@encode(NSPoint), type))
+           return [NSPointValue class];
+       else if(!Strcmp(@encode(NSRect), type))
+           return [NSRectValue class];
+       else if(!Strcmp(@encode(NSSize), type))
+           return [NSSizeValue class];
+       else if(!Strcmp(@encode(void*), type))
+           return [NSPointerValue class];
+    }                                                  
+
+    return nil;
+}
+
+// Allocating and Initializing 
+
++ (NSValue *)valueWithBytes:(const void*)value objCType:(const char*)type
+{
+    return [self value:value withObjCType:type];
+}
+
++ (NSValue *)value:(const void*)value withObjCType:(const char*)type
+{
+    Class theClass = [self concreteClassForObjCType:type];
+
+    if (theClass)
+        return AUTORELEASE([[theClass alloc]
+                               initValue:value withObjCType:type]);
+    else
+       return AUTORELEASE([[NSConcreteValue allocForType:type zone:nil]
+                               initValue:value withObjCType:type]);
+}
+               
++ (NSValue *)valueWithNonretainedObject:(id)anObject
+{
+    return AUTORELEASE([[NSNonretainedObjectValue alloc] 
+                           initValue:&anObject withObjCType:@encode(id)]);
+}
+       
++ (NSValue *)valueWithPointer:(const void*)pointer
+{
+    return AUTORELEASE([[NSPointerValue alloc] 
+                           initValue:&pointer withObjCType:@encode(void*)]);
+}
+
++ (NSValue *)valueWithPoint:(NSPoint)point
+{
+    return AUTORELEASE([[NSPointValue alloc] 
+                           initValue:&point withObjCType:@encode(NSPoint)]);
+}
+
++ (NSValue *)valueWithRect:(NSRect)rect
+{
+    return AUTORELEASE([[NSRectValue alloc] 
+                           initValue:&rect withObjCType:@encode(NSRect)]);
+}
++ (NSValue *)valueWithSize:(NSSize)size
+{
+    return AUTORELEASE([[NSSizeValue alloc] 
+                           initValue:&size withObjCType:@encode(NSSize)]);
+}
+
+- (id)initWithBytes:(const void *)value objCType:(const char *)type
+{
+    (void)AUTORELEASE(self);
+    return [[[self class] alloc] valueWithBytes:value objCType:type];
+}
+
+- (BOOL)isEqual:(id)aValue
+{
+    if ([aValue isKindOfClass:[NSValue class]])
+       return [self isEqualToValue:aValue];
+    else
+       return NO;
+}
+
+- (BOOL)isEqualToValue:(NSValue *)aValue
+{
+    if (Strcmp([self objCType], [aValue objCType]) != 0)
+        /* not the same type */
+        return NO;
+
+    if (memcmp([self valueBytes], [aValue valueBytes],
+               objc_sizeof_type([self objCType])) != 0)
+        /* not the same value */
+        return NO;
+    
+    return YES;
+}
+
+- (NSString *)description
+{
+    return [NSString stringWithFormat:@"<Value with objc type '%s'>", 
+                       [self objCType]];
+}
+
+// NSCopying
+
+- (id)copyWithZone:(NSZone*)zone
+{
+    if (NSShouldRetainWithZone(self, zone))
+       return RETAIN(self);
+    else {
+       Class theClass = [isa concreteClassForObjCType:[self objCType]];
+       return [[theClass allocWithZone:zone]
+                          initValue:[self valueBytes]
+                          withObjCType:[self objCType]];
+    }
+}
+
+// Accessing Data - implemented in concrete subclasses
+
+- (void *)valueBytes
+{
+    [self subclassResponsibility:_cmd];
+    return NULL;
+}
+
+- (void)getValue:(void*)value
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (const char*)objCType
+{
+    [self subclassResponsibility:_cmd];
+    return NULL;
+}
+
+- (id)nonretainedObjectValue
+{
+    [self subclassResponsibility:_cmd];
+    return nil;
+}
+
+- (void*)pointerValue
+{
+    [self subclassResponsibility:_cmd];
+    return NULL;
+} 
+
+- (NSRect)rectValue
+{
+    [self subclassResponsibility:_cmd];
+    return NSMakeRect(0,0,0,0);
+}
+
+- (NSSize)sizeValue
+{
+    [self subclassResponsibility:_cmd];
+    return NSMakeSize(0,0);
+}
+
+- (NSPoint)pointValue
+{
+    [self subclassResponsibility:_cmd];
+    return NSMakePoint(0,0);
+}
+
+// NSCoding
+
+- (id)replacementObjectForCoder:(NSCoder *)anEncoder
+{
+    return self;
+}
+
+- (Class)classForCoder
+{
+    return [NSValue class];
+}
+
+- (void)encodeWithCoder:(NSCoder*)coder
+{
+    const char* objctype = [self objCType];
+    void* data = [self valueBytes];
+
+    [coder encodeValueOfObjCType:@encode(char*) at:&objctype];
+    [coder encodeValueOfObjCType:objctype at:data];
+}
+
+- (id)initWithCoder:(NSCoder*)coder
+{
+    char* type;
+    void* data;
+    id value;
+
+    [coder decodeValueOfObjCType:@encode(char*) at:&type];
+    data = Malloc (objc_sizeof_type(type));
+    [coder decodeValueOfObjCType:type at:(void*)data];
+    value = [NSValue valueWithBytes:data objCType:type];
+    lfFree(data);
+    return value;
+}
+
+@end
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/NSZone.h b/libFoundation/Foundation/NSZone.h
new file mode 100644 (file)
index 0000000..6ae1856
--- /dev/null
@@ -0,0 +1,299 @@
+/* 
+   NSZone.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSZone_h__
+#define __NSZone_h__
+
+#include <Foundation/NSObject.h>
+
+@class NSString;
+
+#if (__GNUC__ == 2) && (__GNUC_MINOR__ <= 6) && !defined(__attribute__)
+#  define __attribute__(x)
+#endif
+
+@interface NSZone : NSObject
+{
+    unsigned   refCount;
+    NSString   *name;
+}
+
++ (void)setDefaultZone:(NSZone*)zone;
++ (NSZone*)defaultZone;
+
++ (NSZone*)zoneFromPointer:(void*)pointer;
++ (BOOL)checkZone;
++ (id)allocZoneInstance;
+
+- initForSize:(unsigned)startSize granularity:(unsigned)granularity
+       canFree:(BOOL)canFree;
+- (void*)malloc:(unsigned)size;
+- (void*)mallocAtomic:(unsigned)size;
+- (void*)calloc:(unsigned)numElems byteSize:(unsigned)byteSize;
+- (void*)callocAtomic:(unsigned)numElems byteSize:(unsigned)byteSize;
+- (void*)realloc:(void*)pointer size:(unsigned)size;
+- (void)recycle;
+- (BOOL)pointerInZone:(void*)pointer;
+- (void)freePointer:(void*)pointer;
+- (void)setName:(NSString*)name;
+- (NSString*)name;
+- (BOOL)checkZone;
+@end
+
+/* OpenStep functions. The NSAtomic* functions are useful only when
+   libFoundation is compiled with support for Boehm's garbage collector;
+   otherwise they are equivalent with the normal functions. */
+
+static inline NSZone *NSCreateZone(unsigned, unsigned, BOOL)
+    __attribute__((unused));
+
+static inline NSZone *NSDefaultMallocZone(void) __attribute__((unused));
+
+static inline NSZone *NSZoneFromPointer(void *) __attribute__((unused));
+
+static inline void *NSZoneMalloc(NSZone*, unsigned) __attribute__((unused));
+static inline void *NSZoneMallocAtomic(NSZone*, unsigned)
+       __attribute__((unused));
+
+static inline void *NSZoneCalloc(NSZone*, unsigned, unsigned)
+    __attribute__((unused));
+static inline void *NSZoneCallocAtomic(NSZone*, unsigned, unsigned)
+    __attribute__((unused));
+
+static inline void *NSZoneRealloc(NSZone*, void*, unsigned)
+    __attribute__((unused));
+
+static inline void NSRecycleZone(NSZone*) __attribute__((unused));
+static inline void NSZoneFree(NSZone*, void*) __attribute__((unused));
+static inline void NSSetZoneName(NSZone*, NSString*) __attribute__((unused));
+static inline NSString *NSZoneName(NSZone*) __attribute__((unused));
+
+extern Class lfNSZoneClass; /* cache NSZone class (in NSObject) */
+
+#if !(LIB_FOUNDATION_BOEHM_GC)
+
+LF_EXPORT NSZone *_lfDefaultZone(void);
+
+static inline
+NSZone *NSCreateZone(unsigned startSize, unsigned granularity, BOOL canFree)
+{
+    return [[lfNSZoneClass alloc] initForSize:startSize
+                           granularity:granularity canFree:canFree];
+}
+
+static inline
+NSZone *NSDefaultMallocZone(void)
+{
+    return [lfNSZoneClass defaultZone];
+}
+
+static inline
+NSZone *NSZoneFromPointer(void *pointer)
+{
+    return [lfNSZoneClass zoneFromPointer:pointer];
+}
+
+static inline
+void *NSZoneMalloc(NSZone *zone, unsigned size)
+{
+    return zone
+        ? [zone malloc:size] 
+        : [_lfDefaultZone() malloc:size];
+}
+
+static inline
+void *NSZoneMallocAtomic(NSZone *zone, unsigned size)
+{
+    return zone
+        ? [zone mallocAtomic:size] 
+        : [_lfDefaultZone() mallocAtomic:size];
+}
+
+static inline
+void *NSZoneCalloc(NSZone *zone, unsigned numElems, unsigned byteSize)
+{
+    return zone
+        ? [zone calloc:numElems byteSize:byteSize]
+        : [_lfDefaultZone() calloc:numElems byteSize:byteSize];
+
+}
+
+static inline
+void *NSZoneCallocAtomic(NSZone *zone, unsigned numElems, unsigned byteSize)
+{
+    return zone
+        ? [zone callocAtomic:numElems byteSize:byteSize]
+        : [_lfDefaultZone() callocAtomic:numElems byteSize:byteSize];
+
+}
+
+static inline
+void *NSZoneRealloc(NSZone *zone, void *pointer, unsigned size)
+{
+    return zone
+        ? [zone realloc:pointer size:size]
+        : [_lfDefaultZone() realloc:pointer size:size];
+}
+
+static inline
+void NSRecycleZone(NSZone *zone)
+{
+    zone ? [zone recycle] : [_lfDefaultZone() recycle];
+}
+
+static inline
+void NSZoneFree(NSZone *zone, void *pointer)
+{
+    zone ? [zone freePointer:pointer]
+        : [_lfDefaultZone() freePointer:pointer];
+}
+
+static inline
+void NSSetZoneName(NSZone *zone, NSString *name)
+{
+    zone ? [zone setName:name]  : [_lfDefaultZone() setName:name];
+}
+
+static inline
+NSString *NSZoneName(NSZone *zone)
+{
+    return zone ? [zone name] : [_lfDefaultZone() name];
+}
+
+#else /* LIB_FOUNDATION_BOEHM_GC */
+
+/* When working with Boehm's garbage collector there are no zones
+   involved. */
+
+void __raiseMemoryException (void* pointer, int size);
+
+static inline
+NSZone *NSCreateZone(unsigned startSize, unsigned granularity, BOOL canFree)
+{
+    return nil;
+}
+
+static inline
+NSZone *NSDefaultMallocZone(void)
+{
+    return nil;
+}
+
+static inline
+NSZone *NSZoneFromPointer(void *pointer)
+{
+    return nil;
+}
+
+static inline
+void *NSZoneMalloc(NSZone *zone, unsigned size)
+{
+    void* p = (void *)GC_MALLOC (size);
+    if (!p)
+        __raiseMemoryException (&p, size);
+    return p;
+}
+
+static inline
+void *NSZoneMallocAtomic(NSZone *zone, unsigned size)
+{
+    void* p = (void*)GC_MALLOC_ATOMIC (size);
+    if(!p)
+        __raiseMemoryException (&p, size);
+    return p;
+}
+
+static inline
+void *NSZoneCalloc(NSZone *zone, unsigned numElems, unsigned byteSize)
+{
+    int howMuch = numElems * byteSize;
+    void* p = (void*)GC_MALLOC (howMuch);
+
+    if(!p)
+        __raiseMemoryException (&p, howMuch);
+    memset (p, 0, howMuch);
+    return p;
+}
+
+static inline
+void *NSZoneCallocAtomic(NSZone *zone, unsigned numElems, unsigned byteSize)
+{
+    int howMuch = numElems * byteSize;
+    void* p = (void*)GC_MALLOC_ATOMIC (howMuch);
+
+    if(!p)
+        __raiseMemoryException (&p, howMuch);
+    memset (p, 0, howMuch);
+    return p;
+}
+
+static inline
+void *NSZoneRealloc(NSZone *zone, void *pointer, unsigned size)
+{
+    void* new_p = GC_REALLOC (pointer, size);
+
+    if(!new_p)
+        __raiseMemoryException (&new_p, size);
+    return new_p;
+}
+
+static inline
+void NSRecycleZone(NSZone *zone)
+{}
+
+static inline
+void NSZoneFree(NSZone *zone, void *pointer)
+{
+#if 0
+    if (pointer) {
+        fprintf(stderr, "%s: EXPLICIT FREE !!\n", __PRETTY_FUNCTION__);
+        GC_FREE(pointer);
+    }
+#endif
+    pointer = NULL;
+}
+
+static inline
+void NSSetZoneName(NSZone *zone, NSString *name)
+{}
+
+static inline
+NSString *NSZoneName(NSZone *zone)
+{
+    LF_EXPORT NSString* _gcDefaultZoneName;
+
+    return _gcDefaultZoneName;
+}
+
+#endif /* LIB_FOUNDATION_BOEHM_GC */
+
+
+#endif /* __NSZone_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/NSZone.m b/libFoundation/Foundation/NSZone.m
new file mode 100644 (file)
index 0000000..fa1864f
--- /dev/null
@@ -0,0 +1,341 @@
+/* 
+   NSZone.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#if HAVE_LIBC_H
+# include <libc.h>
+#else
+# include <unistd.h>
+#endif
+
+#include "lfmemory.h"
+
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSZone.h>
+#include <Foundation/NSUtilities.h>
+
+#include <extensions/NSException.h>
+#include <extensions/objc-runtime.h>
+
+#include <Foundation/NSDefaultZone.h>
+#include <Foundation/NSAllocDebugZone.h>
+
+static id defaultZone = nil;
+
+NSZone *_lfDefaultZone(void)
+{
+    return defaultZone;
+}
+
+#if LIB_FOUNDATION_BOEHM_GC
+LF_DECLARE NSString *_gcDefaultZoneName = @"Default garbage collector zone";
+#endif
+
+/* The NSZone class keeps a linked list of zones. The default zone should be
+   the last zone in this list because the implementation of NSDefaultZone
+   implements the -pointerInZone: method to return YES no matter what is the
+   value of its argument. This because we cannot assume anything about how the
+   system malloc library, especially if it has a function that tells us if
+   a pointer was allocated using malloc(). */
+
+typedef struct ZoneListNode {
+    struct ZoneListNode* next;
+    NSZone* zone;
+} ZoneListNode;
+
+static ZoneListNode* zones = NULL;
+
+/* Remove the zone node from the zones list and return the node. */
+static ZoneListNode* removeZoneFromList (NSZone* aZone)
+{
+    if (!zones)
+       return NULL;
+
+    /* Try to see if the zone is the first one in list. */
+    if (zones->zone == aZone) {
+       ZoneListNode* node = zones;
+       zones = zones->next;
+       node->next = NULL;
+       return node;
+    }
+    else {
+       ZoneListNode* prev = zones;
+       ZoneListNode* curr = zones->next;
+
+       /* Iterate on the zones list until we find the zone */
+       while (curr && curr->zone != aZone) {
+           prev = curr;
+           curr = curr->next;
+       }
+
+       /* curr should not be NULL, but who knows... */
+       NSCAssert1(curr, @"curr zone node ptr is NULL (prev=0x%08X)", prev);
+
+       prev->next = curr->next;
+       curr->next = NULL;
+       return curr;
+    }
+}
+
+@implementation NSZone
+
+#if !LIB_FOUNDATION_BOEHM_GC
++ (void)initialize
+{
+    static BOOL initialized = NO;
+
+    if(!initialized) {
+       initialized = YES;
+       // alloc is redefined in NSDefaultZone to return memory for this
+       // class from malloc; this is because alloc in NSObject calls
+       // NSAllocateObject(class, 0, defaultZone) and defaultZone is 
+       // uninitialized yet
+       // So for zones we have special allocation method allocZoneInstance
+       // and we redefine all refcounting methods and keep an ivar refCount
+
+        {
+            char* str = getenv("ALLOCDEBUG");
+
+            if (str && *str)
+                defaultZone = [[NSAllocDebugZone alloc] init];
+            else
+                defaultZone = [[NSDefaultZone alloc] init];
+        }
+    }
+}
+#endif
+
++ (id)alloc
+{
+    return defaultZone;
+}
+
++ (id)allocWithZone:(NSZone*)zone
+{
+    return defaultZone;
+}
+
++ (void)setDefaultZone:(NSZone*)zone
+{
+    ZoneListNode *node, *zoneNode;
+
+    defaultZone = zone;
+
+    /* Remove the zone from the list of zones */
+    zoneNode = removeZoneFromList (zone);
+
+    /* Setup the new zone to be the last zone in the list of zones */
+    if (!zones)
+       zones = zoneNode;
+    else {
+       for (node = zones; node->next; node = node->next)
+           /* nothing */;
+       node->next = zoneNode;
+    }
+}
+
++ (NSZone *)defaultZone
+{
+    return defaultZone;
+}
+
++ (NSZone*)zoneFromPointer:(void*)pointer
+{
+    ZoneListNode* node = zones;
+
+    while(node && ![node->zone pointerInZone:pointer])
+       node = node->next;
+
+    if (node)
+       return node->zone;
+
+    return defaultZone;
+}
+
++ (BOOL)checkZone
+{
+    return [defaultZone checkZone];
+}
+
+- (id)initForSize:(unsigned)startSize granularity:(unsigned)granularity
+    canFree:(BOOL)canFree
+{
+    [self subclassResponsibility:_cmd];
+    return self;
+}
+
+- (void*)malloc:(unsigned)size
+{
+    [self subclassResponsibility:_cmd];
+    return NULL;
+}
+
+- (void*)mallocAtomic:(unsigned)size
+{
+  return [self malloc:size];
+}
+
+- (void*)calloc:(unsigned)numElems byteSize:(unsigned)byteSize
+{
+    [self subclassResponsibility:_cmd];
+    return NULL;
+}
+
+- (void*)callocAtomic:(unsigned)numElems byteSize:(unsigned)byteSize
+{
+  return [self calloc:numElems byteSize:byteSize];
+}
+
+- (void*)realloc:(void*)pointer size:(unsigned)size
+{
+    [self subclassResponsibility:_cmd];
+    return NULL;
+}
+
+- (void)recycle
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (BOOL)pointerInZone:(void*)pointer
+{
+    [self subclassResponsibility:_cmd];
+    return NO;
+}
+
+- (void)freePointer:(void*)pointer
+{
+    [self subclassResponsibility:_cmd];
+}
+
+- (void)setName:(NSString*)newName
+{
+    ASSIGN(name, newName);
+}
+
+- (NSString*)name
+{
+    return name;
+}
+
+- (BOOL)checkZone
+{
+    return YES;
+}
+
+/* Refcounting is special to NSZone */
+
++ (id)allocZoneInstance
+{
+    struct myzone {
+       @defs(NSZone);
+    }* theZone;
+    Class class = (Class)self;
+    ZoneListNode* node;
+
+    theZone = objc_calloc(1, class->instance_size);
+    
+    theZone->isa = self;
+    theZone->refCount = 1;
+
+    /* Enter this zone into the zones list */
+    node = objc_malloc(sizeof(ZoneListNode));
+    node->next = zones;
+    node->zone = (NSZone*)theZone;
+    zones = node;
+
+    return (id)theZone;
+}
+
+- autorelease
+{
+#if !LIB_FOUNDATION_BOEHM_GC
+    [NSAutoreleasePool addObject:self];
+#endif
+    return self;
+}
+
+- (void)dealloc
+{
+    /* Remove the zone node from the zones list. */
+    ZoneListNode* node = removeZoneFromList (self);
+
+    /* If the zone is the default zone setup a new default zone */
+    if (defaultZone == self) {
+       ZoneListNode* listNode = zones;
+
+       NSAssert (zones, @"at least one zone should be available");
+
+       /* Find out the last zone */
+       while (listNode->next)
+           listNode = listNode->next;
+       defaultZone = listNode->zone;
+    }
+
+    objc_free(node);
+    objc_free(self);
+}
+
+- (oneway void)release
+{
+#if !LIB_FOUNDATION_BOEHM_GC
+    if (!refCount || !--refCount)
+       [self dealloc];
+#endif
+}
+
+#if LIB_FOUNDATION_BOEHM_GC
+- (void)gcFinalize
+{
+    [self dealloc];
+}
+#endif
+
+- (id)retain
+{
+#if !LIB_FOUNDATION_BOEHM_GC
+    refCount++;
+#endif
+    return self;
+}
+
+- (unsigned int)retainCount
+{
+    return refCount;
+}
+
+@end /* NSZone */
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/PrintfFormatScanner.m b/libFoundation/Foundation/PrintfFormatScanner.m
new file mode 100644 (file)
index 0000000..00a5186
--- /dev/null
@@ -0,0 +1,66 @@
+/* 
+   PrintfFormatScanner.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSString.h>
+#include <extensions/PrintfFormatScanner.h>
+#include <extensions/DefaultScannerHandler.h>
+
+@implementation PrintfFormatScanner
+
+- (NSString *)stringWithFormat:(NSString *)format arguments:(va_list)args
+{
+    va_list va;
+
+#ifdef __va_copy
+    __va_copy(va, args);
+#else
+    va = args;
+#endif
+
+    self->result = [NSMutableString stringWithCapacity:[format cStringLength]];
+    [self parseFormatString:format context:&va];
+    return [[self->result copy] autorelease];
+}
+
+- (BOOL)handleOrdinaryString:(NSString *)string
+{
+    [self->result appendString:string];
+    return YES;
+}
+
+- (BOOL)handleFormatSpecifierWithContext:(void *)context
+{
+    [self->result appendString:[handler stringForArgument:context scanner:self]];
+    return YES;
+}
+
+@end /* PrintfFormatScanner */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/PrintfScannerHandler.m b/libFoundation/Foundation/PrintfScannerHandler.m
new file mode 100644 (file)
index 0000000..ed3f315
--- /dev/null
@@ -0,0 +1,220 @@
+/* 
+   PrintfScannerHandler.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+           Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSValue.h>
+
+#include <extensions/FormatScanner.h>
+#include <extensions/PrintfScannerHandler.h>
+
+@implementation PrintfScannerHandler
+
+- (id)init
+{
+    [super init];
+
+    specHandler['d'] = [self methodForSelector:@selector(convertInt:scanner:)];
+    specHandler['i'] = [self methodForSelector:@selector(convertInt:scanner:)];
+    specHandler['o'] = [self methodForSelector:@selector(convertInt:scanner:)];
+    specHandler['x'] = [self methodForSelector:@selector(convertInt:scanner:)];
+    specHandler['X'] = [self methodForSelector:@selector(convertInt:scanner:)];
+    specHandler['u'] = [self methodForSelector:@selector(convertInt:scanner:)];
+    specHandler['c']
+           = [self methodForSelector:@selector(convertChar:scanner:)];
+    specHandler['s']
+           = [self methodForSelector:@selector(convertString:scanner:)];
+    specHandler['f']
+           = [self methodForSelector:@selector(convertFloat:scanner:)];
+    specHandler['e']
+           = [self methodForSelector:@selector(convertFloat:scanner:)];
+    specHandler['E']
+           = [self methodForSelector:@selector(convertFloat:scanner:)];
+    specHandler['g']
+           = [self methodForSelector:@selector(convertFloat:scanner:)];
+    specHandler['G']
+           = [self methodForSelector:@selector(convertFloat:scanner:)];
+    specHandler['p']
+           = [self methodForSelector:@selector(convertPointer:scanner:)];
+    return self;
+}
+
+- (NSString*)convertInt:(va_list*)pInt scanner:(FormatScanner*)scanner
+{
+    char buffer[256];
+    sprintf(buffer, [scanner currentSpecifier], va_arg(*pInt, int));
+    return [NSString stringWithCString:buffer];
+}
+
+- (NSString*)convertChar:(va_list*)pChar scanner:(FormatScanner*)scanner
+{
+#if 0
+    char buffer[2] = { (char)va_arg(*pChar, char), 0 };
+    return [NSString stringWithCString:buffer];
+#else
+    char buffer[256];
+    sprintf(buffer, [scanner currentSpecifier], (char)va_arg(*pChar, int));
+    return [NSString stringWithCString:buffer];
+#endif
+}
+
+- (NSString*)convertString:(va_list*)pString scanner:(FormatScanner*)scanner
+{
+    char* string = va_arg(*pString, char*);
+    return string ? [NSString stringWithCString:string] : @"";
+}
+
+- (NSString*)convertFloat:(va_list*)pFloat scanner:(FormatScanner*)scanner
+{
+    char buffer[256];
+    sprintf(buffer, [scanner currentSpecifier], va_arg(*pFloat, double));
+    return [NSString stringWithCString:buffer];
+}
+
+- (NSString*)convertPointer:(va_list*)pPointer scanner:(FormatScanner*)scanner
+{
+    char buffer[256];
+    sprintf(buffer, [scanner currentSpecifier], va_arg(*pPointer, void*));
+    return [NSString stringWithCString:buffer];
+}
+
+@end /* PrintfScannerHandler */
+
+@implementation PrintfEnumScannerHandler
+
+- (id)init
+{
+    [super init];
+
+    specHandler['d'] = [self methodForSelector:@selector(convertInt:scanner:)];
+    specHandler['i'] = [self methodForSelector:@selector(convertInt:scanner:)];
+    specHandler['o'] = [self methodForSelector:@selector(convertInt:scanner:)];
+    specHandler['x'] = [self methodForSelector:@selector(convertInt:scanner:)];
+    specHandler['X'] = [self methodForSelector:@selector(convertInt:scanner:)];
+    specHandler['u'] = [self methodForSelector:@selector(convertInt:scanner:)];
+    specHandler['c']
+           = [self methodForSelector:@selector(convertChar:scanner:)];
+    specHandler['s']
+           = [self methodForSelector:@selector(convertString:scanner:)];
+    specHandler['f']
+           = [self methodForSelector:@selector(convertFloat:scanner:)];
+    specHandler['e']
+           = [self methodForSelector:@selector(convertFloat:scanner:)];
+    specHandler['E']
+           = [self methodForSelector:@selector(convertFloat:scanner:)];
+    specHandler['g']
+           = [self methodForSelector:@selector(convertFloat:scanner:)];
+    specHandler['G']
+           = [self methodForSelector:@selector(convertFloat:scanner:)];
+    specHandler['p']
+           = [self methodForSelector:@selector(convertPointer:scanner:)];
+    return self;
+}
+
+- (NSString *)convertInt:(NSEnumerator **)pInt scanner:(FormatScanner*)scanner
+{
+    char buffer[256];
+    sprintf(buffer, [scanner currentSpecifier], [[*pInt nextObject] intValue]);
+    return [NSString stringWithCString:buffer];
+}
+
+- (NSString*)convertChar:(NSEnumerator **)pChar scanner:(FormatScanner*)scanner
+{
+#if 0
+    char buffer[2] = { (char)va_arg(*pChar, char), 0 };
+    return [NSString stringWithCString:buffer];
+#else
+    char buffer[256];
+    sprintf(buffer, [scanner currentSpecifier],
+            [[*pChar nextObject] charValue]);
+    return [NSString stringWithCString:buffer];
+#endif
+}
+
+- (NSString *)convertString:(NSEnumerator **)pString
+  scanner:(FormatScanner *)scanner
+{
+    id str;
+
+    if ((str = [*pString nextObject]) == nil)
+        str = @"";
+    else if ([str isKindOfClass:[NSString class]])
+        ;
+    else if ([str respondsToSelector:@selector(stringValue)])
+        str = [str stringValue];
+    else
+        str = [str description];
+
+    if (str == nil)
+        str = @"";
+    return str;
+}
+
+- (NSString *)convertFloat:(NSEnumerator **)pFloat
+  scanner:(FormatScanner *)scanner
+{
+    char buffer[256];
+    sprintf(buffer, [scanner currentSpecifier],
+            [[*pFloat nextObject] doubleValue]);
+    return [NSString stringWithCString:buffer];
+}
+
+- (NSString *)convertPointer:(NSEnumerator **)pPointer
+  scanner:(FormatScanner *)scanner
+{
+    char buffer[256];
+    sprintf(buffer, [scanner currentSpecifier],
+            [[*pPointer nextObject] pointerValue]);
+    return [NSString stringWithCString:buffer];
+}
+
+@end /* PrintfEnumScannerHandler */
+
+@implementation FSObjectFormat
+
+- (id)init
+{
+    [super init];
+    specHandler['@']
+           = [self methodForSelector:@selector(convertObject:scanner:)];
+    return self;
+}
+
+- (NSString *)convertObject:(va_list*)pId scanner:(id)scanner
+{
+    id object;
+    object = va_arg(*pId, id);
+    return [object description];
+}
+
+@end /* FSObjectFormat */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/PrivateThreadData.h b/libFoundation/Foundation/PrivateThreadData.h
new file mode 100644 (file)
index 0000000..a38bc78
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+   PrivateThreadData.h
+
+   Copyright (C) 1995, 1996, 1997, 1998 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@net-community.com>
+   Date: February 1998
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+#ifndef __PrivateThreadData_h__
+#define __PrivateThreadData_h__
+
+#include <Foundation/common.h>
+#include <Foundation/NSException.h>
+
+/* Fast access to per-thread-global variables */
+
+@class NSAutoreleasePool;
+@class NSNotificationCenter;
+@class NSNotificationQueue;
+@class NSRunLoop;
+
+@interface PrivateThreadData : NSObject
+{
+    id autoreleaseStack;
+    void* exceptionStack;
+#ifdef BROKEN_COMPILER
+    NSUncaughtExceptionHandler* uncaughtExceptionHandler;
+#endif
+    NSRunLoop* runLoop;
+    struct _InstanceList* notificationQueues;
+    NSNotificationQueue* defaultQueue;
+    NSNotificationCenter* defaultCenter;
+    id temporaryStringsPool;
+    id temporaryMutableStringsPool;
+}
+
+- (void)threadWillStart;
+- (void)threadExit;
+
+/* NSAutoreleasePool */
+- (NSAutoreleasePool*)threadDefaultAutoreleasePool;
+- (void)setThreadDefaultAutoreleasePool:(NSAutoreleasePool*)pool;
+
+/* NSException */
+- (void*)threadDefaultExceptionHandler;
+- (void)setThreadDefaultExceptionHandler:(void*)handler;
+- (void)setUncaughtExceptionHandler:(NSUncaughtExceptionHandler*)handler;
+- (NSUncaughtExceptionHandler*)uncaughtExceptionHandler;
+#ifdef BROKEN_COMPILER
+- (void)invokeUncaughtExceptionHandlerWithException:(NSException*)exception;
+#endif
+
+/* NSRunLoop */
+- (NSRunLoop*)threadRunLoop;
+- (void)setThreadRunLoop:(NSRunLoop*)aLoop;
+
+/* NSNotificationQueue */
+- (struct _InstanceList*)threadNotificationQueues;
+- (void)setThreadNotificationQueues:(struct _InstanceList*)theQueues;
+- (NSNotificationQueue*)defaultNotificationQueue;
+- (void)setDefaultNotificationQueue:(NSNotificationQueue*)aQueue;
+
+/* NSNotificationCenter */
+- (NSNotificationCenter*)defaultNotificationCenter;
+- (void)setDefaultNotificationCenter:(NSNotificationCenter*)center;
+
+/* NSString */
+- (id)temporaryString;
+- (void)addTemporaryString:(id)anObject;
+- (void)setTemporaryStringsPool:(id)anObject;
+
+/* NSMutableString */
+- (id)temporaryMutableString;
+- (void)addTemporaryMutableString:(id)anObject;
+- (void)setTemporaryMutableStringsPool:(id)anObject;
+
+@end
+
+#endif /* __PrivateThreadData_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/PrivateThreadData.m b/libFoundation/Foundation/PrivateThreadData.m
new file mode 100644 (file)
index 0000000..1f8736e
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+   PrivateThreadData.m
+
+   Copyright (C) 1995, 1996, 1997, 1998 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@net-community.com>
+   Date: February 1998
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include "PrivateThreadData.h"
+#include "NSConcreteString.h"
+#include <Foundation/NSNotification.h>
+#include <Foundation/NSNotificationQueue.h>
+#include <Foundation/NSRunLoop.h>
+
+#include <extensions/PrintfFormatScanner.h>
+#include <extensions/PrintfScannerHandler.h>
+
+@implementation PrivateThreadData
+
+- init
+{
+    extern void _default_exception_handler(NSException* exception);
+    extern void _init_first_exception_handler(NSHandler* handler);
+
+    // Autorelease pool is nil
+    autoreleaseStack = nil;
+    // No exception handler
+    exceptionStack = Malloc (sizeof (NSHandler));
+    _init_first_exception_handler (exceptionStack);
+#ifdef BROKEN_COMPILER
+    uncaughtExceptionHandler = _default_exception_handler;
+#endif
+    return self;
+}
+
+- (void)dealloc
+{
+    RELEASE(defaultQueue);
+    RELEASE(runLoop);
+    lfFree(exceptionStack);
+    [super dealloc];
+}
+
+- (void)threadWillStart
+{
+    // Make thread's top-level autorelease pool
+    runLoop = [NSRunLoop new];
+}
+
+- (void)threadExit
+{
+#if !LIB_FOUNDATION_BOEHM_GC
+    // Clear autorelease for current thread
+    while (autoreleaseStack)
+       RELEASE(autoreleaseStack);
+#endif
+}
+
+- (NSAutoreleasePool*)threadDefaultAutoreleasePool
+{
+    return autoreleaseStack;
+}
+
+- (void)setThreadDefaultAutoreleasePool:(NSAutoreleasePool*)pool
+{
+    autoreleaseStack = pool;
+}
+
+- (void*)threadDefaultExceptionHandler
+{
+    return exceptionStack;
+}
+
+- (void)setThreadDefaultExceptionHandler:(void*)handler
+{
+    exceptionStack = handler;
+}
+
+- (NSUncaughtExceptionHandler*)uncaughtExceptionHandler
+{
+#ifdef BROKEN_COMPILER
+    return uncaughtExceptionHandler;
+#else
+    NSHandler* ex = exceptionStack;
+
+    while (ex->previousHandler)
+        ex = ex->previousHandler;
+    return ex->handler;
+#endif
+}
+
+- (void)setUncaughtExceptionHandler:(NSUncaughtExceptionHandler*)handler
+{
+#ifdef BROKEN_COMPILER
+    uncaughtExceptionHandler = handler;
+#else
+    NSHandler* ex = exceptionStack;
+
+    while (ex->previousHandler)
+        ex = ex->previousHandler;
+    ex->handler = handler;
+#endif
+}
+
+#ifdef BROKEN_COMPILER
+- (void)invokeUncaughtExceptionHandlerWithException:(NSException*)exception
+{
+    uncaughtExceptionHandler (exception);
+}
+#endif
+
+- (NSRunLoop*)threadRunLoop
+{
+    return runLoop;
+}
+
+- (void)setThreadRunLoop:(NSRunLoop*)aLoop
+{
+    runLoop = RETAIN(aLoop);
+}
+
+- (struct _InstanceList*)threadNotificationQueues
+{
+    return notificationQueues;
+}
+
+- (void)setThreadNotificationQueues:(struct _InstanceList*)theQueues
+{
+    notificationQueues = theQueues;
+}
+
+- (NSNotificationQueue*)defaultNotificationQueue
+{
+    if (!defaultQueue)
+        defaultQueue = [[NSNotificationQueue alloc] init];
+    return defaultQueue;
+}
+
+- (void)setDefaultNotificationQueue:(NSNotificationQueue*)aQueue
+{
+    defaultQueue = RETAIN(aQueue);
+}
+
+- (NSNotificationCenter*)defaultNotificationCenter
+{
+    if (!defaultCenter)
+        defaultCenter = [[NSNotificationCenter alloc] init];
+    return defaultCenter;
+}
+
+- (void)setDefaultNotificationCenter:(NSNotificationCenter*)center
+{
+    defaultCenter = RETAIN(center);
+}
+
+- (id)temporaryString
+{
+    struct String {
+       @defs (NSTemporaryString);
+    } *string = (void*)temporaryStringsPool;
+
+    if (string) {
+       temporaryStringsPool = string->next;
+       string->next = nil;
+    }
+    return (id)string;
+}
+
+- (void)addTemporaryString:(id)anObject
+{
+    struct String {
+       @defs (NSTemporaryString);
+    } *string = (void*)anObject;
+
+    if ((void*)string != temporaryStringsPool)
+       string->next = temporaryStringsPool;
+    temporaryStringsPool = anObject;
+}
+
+- (void)setTemporaryStringsPool:(id)anObject
+{
+    temporaryStringsPool = anObject;
+}
+
+- (id)temporaryMutableString
+{
+    struct String {
+       @defs (NSMutableTemporaryString);
+    } *string = (void*)temporaryMutableStringsPool;
+
+    if (string) {
+       temporaryMutableStringsPool = string->next;
+       string->next = nil;
+    }
+    return (id)string;
+}
+
+- (void)addTemporaryMutableString:(id)anObject
+{
+    struct String {
+       @defs (NSMutableTemporaryString);
+    } *string = (void*)anObject;
+
+    if ((void*)string != temporaryMutableStringsPool)
+       string->next = temporaryMutableStringsPool;
+    temporaryMutableStringsPool = anObject;
+}
+
+- (void)setTemporaryMutableStringsPool:(id)anObject
+{
+    temporaryMutableStringsPool = anObject;
+}
+
+@end /* PrivateThreadData */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/PropertyListParser.h b/libFoundation/Foundation/PropertyListParser.h
new file mode 100644 (file)
index 0000000..451d080
--- /dev/null
@@ -0,0 +1,80 @@
+/* 
+   PropertyListParser.h
+
+   Copyright (C) 1998 MDlink online service center, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess (helge@mdlink.de)
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+// $Id$
+
+#ifndef __PropertyListParser_h__
+#define __PropertyListParser_h__
+
+#include <Foundation/NSObject.h>
+
+@class NSString, NSArray, NSDictionary, NSData;
+
+/*
+  The property list format is:
+
+    Strings: char's without specials:  'hello', but not 'hel  lo'
+             or quoted string:         '"hello world !"
+
+    Arrays:  '(' ')'
+             or '(' element ( ',' element )* ')'
+
+    Dicts:   '{' ( dictEntry )* '}'
+             dictEntry = property '=' property ';' ;
+
+    Data:    '<' data '>', eg: '< AABB 88CC 77a7 11 >'
+ */
+
+// Note: you should prefer the NSString methods
+NSString     *NSParseStringFromBuffer(const unsigned char *_buffer, 
+                                     unsigned _len);
+NSArray      *NSParseArrayFromBuffer(const unsigned char *_buffer, 
+                                    unsigned _len);
+NSDictionary *NSParseDictionaryFromBuffer(const unsigned char *_buffer, 
+                                         unsigned _len);
+
+NSString     *NSParseStringFromData(NSData *_data);
+NSArray      *NSParseArrayFromData(NSData *_data);
+NSDictionary *NSParseDictionaryFromData(NSData *_data);
+NSString     *NSParseStringFromString(NSString *_str);
+NSArray      *NSParseArrayFromString(NSString *_str);
+NSDictionary *NSParseDictionaryFromString(NSString *_str);
+
+id NSParsePropertyListFromBuffer(const unsigned char *_buffer, unsigned _len);
+id NSParsePropertyListFromData(NSData *_data);
+id NSParsePropertyListFromString(NSString *_string);
+id NSParsePropertyListFromFile(NSString *_path);
+
+id NSParseStringsFromBuffer(const unsigned char *_buffer, unsigned _len);
+id NSParseStringsFromData(NSData *_data);
+id NSParseStringsFromString(NSString *_string);
+id NSParseStringsFromFile(NSString *_path);
+
+#endif /* __PropertyListParser_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/PropertyListParser.m b/libFoundation/Foundation/PropertyListParser.m
new file mode 100644 (file)
index 0000000..0452f33
--- /dev/null
@@ -0,0 +1,1369 @@
+/* 
+   PropertyListParser.m
+
+   Copyright (C) 1998 MDlink online service center, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess (helge@mdlink.de)
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <ctype.h>
+#include <Foundation/common.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSData.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSValue.h>
+#include <Foundation/NSNull.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+
+#ifdef NeXT /* NeXT Mach map_fd() */
+#  include <mach/mach.h>
+#  include <libc.h>
+#elif defined(HAVE_MMAP) /* Posix mmap() */
+#  include <sys/types.h>
+#  include <sys/mman.h>
+#  include <unistd.h>
+#else  /* No file mapping available */
+#endif
+
+#include "PropertyListParser.h"
+
+static NSString     *_parseString (NSZone *_zone, const unsigned char *_buffer,
+                                   unsigned *_idx, unsigned _len,
+                                   NSException **_exception);
+static NSDictionary *_parseDict   (NSZone *_zone, const unsigned char *_buffer,
+                                   unsigned *_idx, unsigned _len,
+                                   NSException **_exception);
+static NSArray      *_parseArray  (NSZone *_zone, const unsigned char *_buffer,
+                                   unsigned *_idx, unsigned _len,
+                                   NSException **_exception);
+static NSData       *_parseData   (NSZone *_zone, const unsigned char *_buffer,
+                                   unsigned *_idx, unsigned _len,
+                                   NSException **_exception);
+static id           _parseProperty(NSZone *_zone, const unsigned char *_buffer,
+                                   unsigned *_idx, unsigned _len,
+                                   NSException **_exception);
+static NSDictionary *_parseStrings(NSZone *_zone, const unsigned char *_buffer,
+                                   unsigned *_idx, unsigned _len,
+                                   NSException **_exception,
+                                   NSString *fname);
+
+// public functions
+
+NSString *NSParseStringFromBuffer(const unsigned char *_buffer, unsigned _len)
+{
+    NSString    *result    = nil;
+    NSException *exception = nil;
+    unsigned    idx        = 0;
+
+    if (_len >= 2) {
+        if (_buffer[0] == 0xFE && _buffer[1] == 0xFF) {
+            NSLog(@"WARNING(%s): tried to parse Unicode string (FE/FF) ...",
+                  __PRETTY_FUNCTION__);
+            return nil;
+        }
+        else if (_buffer[0] == 0xFF && _buffer[1] == 0xFE) {
+            NSLog(@"WARNING(%s): tried to parse Unicode string (FF/FE) ...",
+                  __PRETTY_FUNCTION__);
+            return nil;
+        }
+    }
+    
+    result = _parseString(nil, _buffer, &idx, _len, &exception);
+    result = AUTORELEASE(result);
+    if (exception)
+        [exception raise];
+    return result;
+}
+
+NSArray *NSParseArrayFromBuffer(const unsigned char *_buffer, unsigned _len)
+{
+    NSArray     *result    = nil;
+    NSException *exception = nil;
+    unsigned    idx        = 0;
+
+    if (_len >= 2) {
+        if (_buffer[0] == 0xFE && _buffer[1] == 0xFF) {
+            NSLog(@"WARNING(%s): tried to parse Unicode array (FE/FF) ...",
+                  __PRETTY_FUNCTION__);
+            return nil;
+        }
+        else if (_buffer[0] == 0xFF && _buffer[1] == 0xFE) {
+            NSLog(@"WARNING(%s): tried to parse Unicode array (FF/FE) ...",
+                  __PRETTY_FUNCTION__);
+            return nil;
+        }
+    }
+    
+    result = _parseArray(nil, _buffer, &idx, _len, &exception);
+    result = AUTORELEASE(result);
+    if (exception)
+        [exception raise];
+    return result;
+}
+
+NSDictionary *NSParseDictionaryFromBuffer(const unsigned char *_buffer, unsigned _len)
+{
+    NSDictionary *result    = nil;
+    NSException  *exception = nil;
+    unsigned     idx        = 0;
+
+    if (_len >= 2) {
+        if (_buffer[0] == 0xFE && _buffer[1] == 0xFF) {
+            NSLog(@"WARNING(%s): tried to parse Unicode dict (FE/FF) ...",
+                  __PRETTY_FUNCTION__);
+            return nil;
+        }
+        else if (_buffer[0] == 0xFF && _buffer[1] == 0xFE) {
+            NSLog(@"WARNING(%s): tried to parse Unicode dict (FF/FE) ...",
+                  __PRETTY_FUNCTION__);
+            return nil;
+        }
+    }
+    
+    result = _parseDict(nil, _buffer, &idx, _len, &exception);
+    result = AUTORELEASE(result);
+    if (exception)
+        [exception raise];
+    return result;
+}
+
+NSString *NSParseStringFromData(NSData *_data)
+{
+    return NSParseStringFromBuffer([_data bytes], [_data length]);
+}
+
+NSArray *NSParseArrayFromData(NSData *_data)
+{
+    return NSParseArrayFromBuffer([_data bytes], [_data length]);
+}
+
+NSDictionary *NSParseDictionaryFromData(NSData *_data)
+{
+    return NSParseDictionaryFromBuffer([_data bytes], [_data length]);
+}
+
+NSString *NSParseStringFromString(NSString *_str)
+{
+    NSString *s;
+    char     *buf;
+    unsigned len;
+    
+    len = [_str cStringLength];
+    buf = malloc(len + 1);
+    [_str getCString:buf]; buf[len] = '\0';
+    s = NSParseStringFromBuffer(buf, len);
+    free(buf);
+    return s;
+}
+
+NSArray *NSParseArrayFromString(NSString *_str)
+{
+    NSArray  *a;
+    char     *buf;
+    unsigned len;
+    
+    len = [_str cStringLength];
+    buf = malloc(len + 1);
+    [_str getCString:buf]; buf[len] = '\0';
+    a = NSParseArrayFromBuffer(buf, len);
+    free(buf);
+    return a;
+}
+
+NSDictionary *NSParseDictionaryFromString(NSString *_str)
+{
+    NSDictionary *d;
+    char         *buf;
+    unsigned     len;
+    
+    len = [_str cStringLength];
+    buf = malloc(len + 1);
+    [_str getCString:buf]; buf[len] = '\0';
+    d = NSParseDictionaryFromBuffer(buf, len);
+    free(buf);
+    return d;
+}
+
+id NSParsePropertyListFromBuffer(const unsigned char *_buffer, unsigned _len)
+{
+    id          result = nil;
+    NSException *exception = nil;
+    unsigned    idx = 0;
+
+    if (_len >= 2) {
+        if (_buffer[0] == 0xFE && _buffer[1] == 0xFF) {
+            NSLog(@"WARNING(%s): tried to parse Unicode plist (FE/FF) ...",
+                  __PRETTY_FUNCTION__);
+            return nil;
+        }
+        else if (_buffer[0] == 0xFF && _buffer[1] == 0xFE) {
+            NSLog(@"WARNING(%s): tried to parse Unicode plist (FF/FE) ...",
+                  __PRETTY_FUNCTION__);
+            return nil;
+        }
+    }
+    
+    result = _parseProperty(nil, _buffer, &idx, _len, &exception);
+    result = AUTORELEASE(result);
+    if (exception)
+        [exception raise];
+    return result;
+}
+
+id NSParsePropertyListFromData(NSData *_data)
+{
+    return NSParsePropertyListFromBuffer([_data bytes], [_data length]);
+}
+
+id NSParsePropertyListFromString(NSString *_string)
+{
+    unsigned len;
+    char     *buf;
+    id       p;
+
+    len = [_string cStringLength];
+    buf = malloc(len + 1);
+    [_string getCString:buf]; buf[len] = '\0';
+    
+    p = NSParsePropertyListFromBuffer(buf, len);
+    free(buf);
+    return p;
+}
+
+id NSParsePropertyListFromFile(NSString *_path)
+{
+    if (_path == nil) {
+        return nil;
+    }
+    else {
+#if HAVE_MMAP
+        NSException *exception = nil;
+        int         fd         = 0;
+        id          result     = nil;
+        unsigned    plen       = [_path cStringLength];
+        char        *path;
+        
+        path = malloc(plen + 1);
+        [_path getCString:path]; path[plen] = '\0';
+        
+        if ((fd = open(path, O_RDONLY, 0)) != -1) {
+            struct stat statInfo;
+            
+            if (fstat(fd, &statInfo) == 0) {
+                void *mem = NULL;
+
+                mem = mmap(0, statInfo.st_size, PROT_READ, MAP_SHARED, fd, 0);
+                if ((mem != MAP_FAILED) || (mem == NULL)) {
+                    NS_DURING {
+                        unsigned idx = 0;
+                        result = _parseProperty(nil, mem, &idx, statInfo.st_size,
+                                                &exception);
+                    }
+                    NS_HANDLER {
+                        result = nil;
+                        exception = [localException retain];
+                    }
+                    NS_ENDHANDLER;
+                    
+                    munmap(mem, statInfo.st_size);
+                    mem = NULL;
+                }
+                else {
+                    NSLog(@"%s: Couldn't map file '%@' into virtual memory !",
+                          __PRETTY_FUNCTION__, _path);
+                }
+            }
+            else {
+                NSLog(@"%s: File '%@' couldn't be mapped !",
+                      __PRETTY_FUNCTION__,_path);
+            }
+            close(fd);
+        }
+#if 0
+        else {
+            NSLog(@"%s: File %@ does not exist !", __PRETTY_FUNCTION__, _path);
+        }
+#endif
+
+        if (path) {
+            free(path);
+            path = NULL;
+        }
+        
+        result = AUTORELEASE(result);
+        if (exception) {
+            NSMutableDictionary *ui;
+            ui = [[exception userInfo] mutableCopy];
+            [ui setObject:_path forKey:@"path"];
+            [exception setUserInfo:ui];
+            RELEASE(ui); ui = nil;
+            [exception raise];
+        }
+        return result;
+#else
+        NSData *data;
+        
+        if ((data = [NSData dataWithContentsOfFile:_path])) {
+            id          result = nil;
+            NSException *exception = nil;
+            unsigned    idx = 0;
+            void        *_buffer;
+            unsigned    _len;
+
+            _buffer = (void *)[data bytes];
+            _len    = [data length];
+            
+            result = _parseProperty(nil, _buffer, &idx, _len, &exception);
+            result = AUTORELEASE(result);
+            
+            if (exception) {
+                NSMutableDictionary *ui;
+                ui = [[exception userInfo] mutableCopy];
+                [ui setObject:_path forKey:@"path"];
+                [exception setUserInfo:ui];
+                RELEASE(ui); ui = nil;
+                
+                [exception raise];
+            }
+            return result;
+        }
+        else {
+            NSLog(@"%s: couldn't read file %@ !", __PRETTY_FUNCTION__, _path);
+            return nil;
+        }
+#endif
+    }
+}
+
+id NSParseStringsFromBuffer(const unsigned char *_buffer, unsigned _len)
+{
+    NSDictionary *result    = nil;
+    NSException  *exception = nil;
+    unsigned     idx        = 0;
+
+    result = _parseStrings(nil, _buffer, &idx, _len, &exception, @"<buffer>");
+    result = AUTORELEASE(result);
+    if (exception)
+        [exception raise];
+    return result;
+}
+
+id NSParseStringsFromData(NSData *_data)
+{
+    NSDictionary *result    = nil;
+    NSException  *exception = nil;
+    unsigned     idx        = 0;
+
+    result = _parseStrings(nil, [_data bytes], &idx, [_data length],
+                           &exception, @"<data>");
+    result = AUTORELEASE(result);
+    if (exception)
+        [exception raise];
+    return result;
+}
+
+id NSParseStringsFromString(NSString *_string)
+{
+    NSDictionary *o;
+    unsigned     len;
+    char         *buf;
+    NSException  *exception = nil;
+    unsigned     idx        = 0;
+    
+    len = [_string cStringLength];
+    buf = malloc(len + 1);
+    [_string getCString:buf]; buf[len] = '\0';
+    
+    o = _parseStrings(nil, buf, &idx, len, &exception, @"<string>");
+    o = AUTORELEASE(o);
+    
+    free(buf);
+
+    if (exception)
+        [exception raise];
+    
+    return o;
+}
+
+id NSParseStringsFromFile(NSString *_path)
+{
+#ifdef HAVE_MMAP
+    struct stat statInfo;
+    NSException *exception = nil;
+    int         fd = 0;
+    id          result = nil;
+    unsigned    plen = [_path cStringLength];
+    char        *path;
+    
+    path = malloc(plen + 1);
+    [_path getCString:path]; path[plen] = '\0';
+    
+    fd = open(path, O_RDONLY, 0);
+    free(path); path = NULL;
+    
+    if (fd != -1) {
+        if (fstat(fd, &statInfo) == 0) {
+            void *mem = NULL;
+
+            mem = mmap(0, statInfo.st_size, PROT_READ, MAP_SHARED, fd, 0);
+            if (mem != MAP_FAILED) {
+                NS_DURING {
+                    unsigned idx = 0;
+                    result = _parseStrings(nil, mem, &idx, statInfo.st_size,
+                                           &exception,
+                                           _path);
+                }
+                NS_HANDLER {
+                    exception = [localException retain];
+                    result = nil;
+                }
+                NS_ENDHANDLER;
+                
+                munmap(mem, statInfo.st_size);
+                mem = NULL;
+            }
+            else
+                NSLog(@"Couldn't map file %@ into virtual memory !", _path);
+        }
+        else {
+            NSLog(@"File %@ couldn't be mapped !", _path);
+        }
+        close(fd);
+    }
+#if 0
+    else {
+        NSLog(@"File %@ does not exist !", _path);
+    }
+#endif
+
+    result = AUTORELEASE(result);
+    if (exception) {
+        NSMutableDictionary *ui;
+        ui = [[exception userInfo] mutableCopy];
+        [ui setObject:_path forKey:@"path"];
+        [exception setUserInfo:ui];
+        RELEASE(ui); ui = nil;
+        
+        [exception raise];
+    }
+    return result;
+#else
+    NSData *data;
+
+    if ((data = [NSData dataWithContentsOfFile:_path])) {
+        NSDictionary *result    = nil;
+        NSException  *exception = nil;
+        unsigned     idx        = 0;
+        void         *_buffer;
+        unsigned     _len;
+
+        _buffer = (void *)[data bytes];
+        _len    = [data length];
+        result  = _parseStrings(nil, _buffer, &idx, _len, &exception, _path);
+        result  = AUTORELEASE(result);
+        
+        if (exception) {
+            NSMutableDictionary *ui;
+            ui = [[exception userInfo] mutableCopy];
+            [ui setObject:_path forKey:@"path"];
+            [exception setUserInfo:ui];
+            RELEASE(ui); ui = nil;
+                
+            [exception raise];
+        }
+        return result;
+    }
+    else {
+        NSLog(@"%s: couldn't read file %@ !", __PRETTY_FUNCTION__, _path);
+        return nil;
+    }
+#endif
+}
+
+/* ******************* implementation ******************** */
+
+static inline BOOL _isBreakChar(unsigned char _c)
+{
+    switch (_c) {
+        case ' ': case '\t': case '\n': case '\r':
+        case '/': case '=':  case ';':  case ',':
+        case '{': case '(':  case '"':  case '<':
+        case ')': case '}':  case '>':
+            return YES;
+
+        default:
+            return NO;
+    }
+}
+static inline BOOL _isUnquotedStringEndChar(unsigned char _c) {
+    switch (_c) {
+        case ' ': case '\t': case '\n': case '\r':
+        case '=':  case ';':  case ',': case '"':
+        case ')': case '}':  case '>':
+            return YES;
+        
+        default:
+            return NO;
+    }
+}
+
+static inline int _valueOfHexChar(char _c)
+{
+    switch (_c) {
+        case '0': case '1': case '2': case '3': case '4':
+        case '5': case '6': case '7': case '8': case '9':
+            return (_c - '0'); // 0-9 (ascii-char)'0' - 48 => (int)0
+      
+        case 'A': case 'B': case 'C':
+        case 'D': case 'E': case 'F':
+            return (_c - 'A' + 10); // A-F, A=10..F=15, 'A'=65..'F'=70
+      
+        case 'a': case 'b': case 'c':
+        case 'd': case 'e': case 'f':
+            return (_c - 'a' + 10); // a-f, a=10..F=15, 'a'=97..'f'=102
+
+        default:
+            return -1;
+    }
+}
+static inline BOOL _isHexDigit(char _c)
+{
+    switch (_c) {
+        case '0': case '1': case '2': case '3': case '4':
+        case '5': case '6': case '7': case '8': case '9':
+        case 'A': case 'B': case 'C':
+        case 'D': case 'E': case 'F':
+        case 'a': case 'b': case 'c':
+        case 'd': case 'e': case 'f':
+            return YES;
+
+        default:
+            return NO;
+    }
+}
+
+static inline int _numberOfLines(const unsigned char *_buffer, unsigned _lastIdx)
+{
+    register unsigned int pos, lineCount = 1;
+
+    for (pos = 0; (pos < _lastIdx) && (_buffer[pos] != '\0'); pos++) {
+        if (_buffer[pos] == '\n')
+            lineCount++;
+    }
+    return lineCount;
+}
+
+static NSException *_makeException(NSException *_exception,
+                                   const unsigned char *_buffer, unsigned _idx,
+                                   unsigned _len, NSString *_text)
+{
+    NSMutableDictionary *ui = nil;
+    NSException *exception = nil;
+    int         numLines;
+    BOOL        atEof;
+    
+    numLines   = _numberOfLines(_buffer, _idx);
+    atEof      = (_idx >= _len) ? YES : NO;
+    
+    /* error resulted from a previous error (exception already set) */
+    if (_exception) 
+        return _exception;
+    
+    exception = [[SyntaxErrorException alloc] init];
+    
+    _text = atEof
+        ? [NSString stringWithFormat:@"Unexpected end: %@", _text]
+        : [NSString stringWithFormat:@"Syntax error in line %i: %@",
+                      numLines,_text];
+  
+    [exception setReason:_text];
+
+    // user info
+    {
+        ui = [[exception userInfo] mutableCopy];
+        if (ui == nil)
+            ui = [[NSMutableDictionary alloc] initWithCapacity:8];
+
+        [ui setObject:[NSNumber numberWithInt:numLines] forKey:@"line"];
+        [ui setObject:[NSNumber numberWithInt:_len]     forKey:@"size"];
+        [ui setObject:[NSNumber numberWithInt:_idx]     forKey:@"position"];
+
+        /*
+          if (_len > 0)
+          [ui setObject:[NSString stringWithCString:_buffer length:_len]
+              forKey:@"text"];
+    
+          if (!atEof && (_idx > 0)) {
+          [ui setObject:[NSString stringWithCString:_buffer length:_idx]
+          forKey:@"consumedText"];
+          }
+        */
+        if (!atEof && (_idx > 0)) {
+            register unsigned pos;
+            const unsigned char *startPos, *endPos;
+
+            for (pos = _idx; (pos >= 0) && (_buffer[pos] != '\n'); pos--)
+                ;
+            startPos = &(_buffer[pos + 1]);
+
+            for (pos = _idx; ((pos < _len) && (_buffer[pos] != '\n')); pos++)
+                ;
+            endPos = &(_buffer[pos - 1]);
+            
+            if (startPos < endPos) {
+                [ui setObject:[NSString stringWithCString:startPos
+                                        length:(endPos - startPos)]
+                    forKey:@"lastLine"];
+            }
+            else {
+                NSLog(@"%s: startPos=0x%08X endPos=0x%08X",
+                      __PRETTY_FUNCTION__, startPos, endPos);
+            }
+        }
+    
+        [exception setUserInfo:ui];
+    
+        RELEASE(ui); ui = nil;
+    }
+
+    return exception;
+}
+
+static BOOL _skipComments(const unsigned char *_buffer,
+                          unsigned *_idx, unsigned _len,
+                          BOOL _skipSpaces, NSException **_exception)
+{
+    register unsigned pos = *_idx;
+    BOOL lookAgain;
+
+    if (pos >= _len)
+        return NO;
+    
+    do { // until all comments are filtered ..
+        lookAgain = NO;
+        
+        if ((_buffer[pos] == '/') && ((pos + 1) < _len)) {
+            if (_buffer[pos + 1] == '/') { // single line comments
+                pos += 2; // skip '//'
+                
+                // search for '\n' ..
+                while ((pos < _len) && (_buffer[pos] != '\n'))
+                    pos++;
+
+                if ((pos < _len) && (_buffer[pos] == '\n')) {
+                    pos++; // skip newline, otherwise EOF was reached
+                    lookAgain = YES;
+                }
+            }
+            else if (_buffer[pos + 1] == '*') { /* multiline comments */
+                BOOL commentIsClosed = NO;
+                
+                pos += 2; // skip '/*'
+                
+                do { // search for '*/'
+                    while ((pos < _len) && (_buffer[pos] != '*'))
+                        pos++;
+
+                    if (pos < _len) { // found '*'
+                        pos++; // skip '*'
+                        
+                        if (pos < _len) {
+                            if (_buffer[pos] == '/') { // found '*/'
+                                commentIsClosed = YES;
+                                pos ++; // skip '/'
+                                lookAgain = YES;
+                                break; // leave loop
+                            }
+#if DEBUG_PLIST
+                            else
+                                printf("'*' inside multiline comment !\n");
+#endif
+                        }
+                    }
+                }
+                while (pos < _len);
+                
+                if (!commentIsClosed) {
+                    // EOF found, comment wasn't closed
+                    *_exception =
+                        _makeException(*_exception, _buffer, *_idx, _len,
+                                       @"comment was not closed "
+                                       @"(expected '*/')");
+                    return NO;
+                }
+            }
+        }
+        else if (_skipSpaces && isspace((int)_buffer[pos])) {
+            pos++;
+            lookAgain = YES;
+        }
+    }
+    while (lookAgain && (pos < _len));
+    
+    // store position ..
+    *_idx = pos;
+    //NSLog(@"skipped comments, now at '%s'", &(_buffer[*_idx]));
+
+    return (pos < _len);
+}
+
+static NSString *_parseString(NSZone *_zone, const unsigned char *_buffer,
+                              unsigned *_idx,
+                              unsigned _len, NSException **_exception)
+{
+
+    // skip comments and spaces
+    if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+        // EOF reached during comment-skipping
+        *_exception =
+            _makeException(*_exception, _buffer, *_idx, _len,
+                           @"did not find a string !");
+        return nil;
+    }
+
+    if (_buffer[*_idx] == '"') { // a quoted string
+        register unsigned pos = *_idx;
+        register unsigned len = 0;
+        unsigned startPos = pos + 1;
+        BOOL     containsEscaped = NO;
+    
+        pos++; // skip starting quote
+
+        // loop until closing quote
+        while ((_buffer[pos] != '"') && (pos < _len)) {
+            if (_buffer[pos] == '\\') {
+                containsEscaped = YES;
+                pos++; // skip following char
+                if (pos == _len) {
+                    *_exception =
+                        _makeException(*_exception, _buffer, *_idx, _len,
+                                       @"escape in quoted string not finished !");
+                    return nil;
+                }
+            }
+            pos++;
+            len++;
+        }
+
+        if (pos == _len) { // syntax error, quote not closed
+            *_idx = pos;
+            *_exception =
+                _makeException(*_exception, _buffer, *_idx, _len,
+                               @"quoted string not closed (expected '\"')");
+            return nil;
+        }
+
+        pos++;       // skip closing quote
+        *_idx = pos; // store pointer
+        pos = 0;
+    
+        if (len == 0) { // empty string
+            return @"";
+        }
+        else if (containsEscaped) {
+            register unsigned pos2;
+            char *str = MallocAtomic(len + 1);
+            id   ostr = nil;
+
+            NSCAssert(len > 0, @"invalid length ..");
+
+            for (pos = startPos, pos2 = 0; _buffer[pos] != '"'; pos++, pos2++) {
+                //NSLog(@"char=%c pos=%i pos2=%i", _buffer[pos], pos2);
+                if (_buffer[pos] == '\\') { /* a quoted char */
+                    pos++;
+                    switch (_buffer[pos]) {
+                    case 'a':  str[pos2] = '\a'; break;
+                    case 'b':  str[pos2] = '\b'; break;
+                    case 'f':  str[pos2] = '\f'; break;
+                    case 'n':  str[pos2] = '\n'; break;
+                    case 'r':  str[pos2] = '\r'; break;
+                    case 't':  str[pos2] = '\t'; break;
+                    case 'v':  str[pos2] = '\v'; break;
+                    case '\\': str[pos2] = '\\'; break;
+            
+                    default:
+                        str[pos2] = _buffer[pos];
+                        break;
+                    }
+                }
+                else {
+                    str[pos2] = _buffer[pos];
+                }
+            }
+            str[pos2] = '\0';
+            NSCAssert(pos2 == len, @"invalid unescape ..");
+
+            ostr = [[NSString allocWithZone:_zone]
+                              initWithCString:str length:len];
+            lfFree(str); str = NULL;
+
+            return ostr;
+        }
+        else {
+            NSCAssert(len > 0, @"invalid length ..");
+      
+            return [[NSString allocWithZone:_zone]
+                              initWithCString:&(_buffer[startPos]) length:len];
+        }
+    }
+    else { /* an unquoted string, may not be zero chars long ! */
+        register unsigned pos = *_idx;
+        register unsigned len = 0;
+        unsigned startPos = pos;
+        
+        // loop until break char
+        while (!_isUnquotedStringEndChar(_buffer[pos]) && (pos < _len)) {
+            pos++;
+            len++;
+        }
+        
+        if (len == 0) { // wasn't a string ..
+            *_exception = _makeException(*_exception, _buffer, *_idx, _len,
+                                         @"did not find a string !");
+            return nil;
+        }
+        else {
+            *_idx = pos;
+            return [[NSString allocWithZone:_zone]
+                              initWithCString:&(_buffer[startPos]) length:len];
+        }
+    }
+}
+
+static NSData *_parseData(NSZone *_zone, const unsigned char *_buffer,
+                          unsigned *_idx, unsigned _len, NSException **_exception)
+{
+    if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+        // EOF reached during comment-skipping
+        *_exception = _makeException(*_exception, _buffer, *_idx, _len,
+                                     @"did not find a data (expected '<') !");
+        return nil;
+    }
+
+    if (_buffer[*_idx] != '<') { // it's not a data that's follows
+        *_exception = _makeException(*_exception, _buffer, *_idx, _len,
+                                     @"did not find a data (expected '<') !");
+        return nil;
+    }
+    else {
+        register      unsigned pos = *_idx + 1;
+        register      unsigned len = 0;
+        unsigned      endPos = 0;
+        NSMutableData *data  = nil;
+    
+        *_idx += 1; // skip '<'
+
+        if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+            *_exception = _makeException(*_exception, _buffer, *_idx, _len,
+                                         @"data was not closed (expected '>') ..");
+            return nil; // EOF
+        }
+
+        if (_buffer[*_idx] == '>') { // empty data
+            *_idx += 1; // skip '>'
+            return [[NSData allocWithZone:_zone] init];
+        }
+
+        // count significant chars
+        while ((_buffer[pos] != '>') && (pos < _len)) {
+            if ((_buffer[pos] == ' ') || (_buffer[pos] == '\t'))
+                ;
+            else if (_isHexDigit(_buffer[pos]))
+                len++;
+            else {
+                *_idx = pos;
+                *_exception = _makeException(*_exception, _buffer, *_idx, _len,
+                                             @"invalid char in data property");
+                return nil; // abort
+            }
+            pos++;
+        }
+        if (pos == _len) {
+            *_idx = pos;
+            *_exception = _makeException(*_exception, _buffer, *_idx, _len,
+                                         @"data was not closed (expected '>')");
+            return nil; // EOF
+        }
+        endPos = pos; // store position of closing '>'
+
+        // if odd, then add one byte for trailing nibble
+        len = (len % 2 == 1) ? len / 2 + 1 : len / 2;
+        data = [[NSMutableData allocWithZone:_zone] initWithLength:len];
+
+        // now copy bytes ..
+        {
+            register unsigned i;
+            register int pending = -1;
+            char *buf = [data mutableBytes];
+      
+            for (pos = *_idx, i = 0; (pos < endPos) && (i < len); pos++) {
+                int value = _valueOfHexChar(_buffer[pos]);
+
+                if (value != -1) {
+                    if (pending == -1)
+                        pending = value;
+                    else {
+                        value = pending * 16 + value;
+                        pending = -1;
+
+                        buf[i] = value;
+                        i++;
+                    }
+                }
+            }
+            if (pending != -1) { // was odd, now add the trailer ..
+                NSCAssert(i < len, @"invalid length ..");
+                buf[i] = pending * 16;
+            }
+        }
+    
+        // update global position
+        *_idx = endPos + 1; // endPos + 1 (*endPos == '>', 1 => skips '>')
+
+        return data;
+    }
+}
+
+static NSDictionary *_parseDict
+(NSZone *_zone, const unsigned char *_buffer, unsigned *_idx,
+ unsigned _len, NSException **_exception)
+{
+    if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+        // EOF reached during comment-skipping
+        *_exception =
+            _makeException(*_exception, _buffer, *_idx, _len,
+                           @"did not find dictionary (expected '{')");
+        return nil;
+    }
+    
+    if (_buffer[*_idx] != '{') { // it's not a dict that's follows
+        *_exception =
+            _makeException(*_exception, _buffer, *_idx, _len,
+                           @"did not find dictionary (expected '{')");
+        return nil;
+    }
+    else {
+        NSMutableDictionary *result = nil;
+        id   key     = nil;
+        id   value   = nil;
+        BOOL didFail = NO;
+    
+        *_idx += 1; // skip '{'
+
+        if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+            *_exception =
+                _makeException(*_exception, _buffer, *_idx, _len,
+                               @"dictionary was not closed (expected '}')");
+            return nil; // EOF
+        }
+
+        if (_buffer[*_idx] == '}') { // an empty dictionary
+            *_idx += 1; // skip the '}'
+            return [[NSDictionary allocWithZone:_zone] init];
+        }
+       
+        result = [[NSMutableDictionary allocWithZone:_zone] init];
+        do {
+            key   = nil;
+            value = nil;
+      
+            if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+                *_exception =
+                    _makeException(*_exception, _buffer, *_idx, _len,
+                                   @"dictionary was not closed (expected '}')");
+                didFail = YES;
+                break; // unexpected EOF
+            }
+
+            if (_buffer[*_idx] == '}') { // dictionary closed
+                *_idx += 1; // skip the '}'
+                break;
+            }
+      
+            // read key property
+            key = _parseProperty(_zone, _buffer, _idx, _len, _exception);
+            if (key == nil) { // syntax error
+                if (*_exception == nil) {
+                    *_exception =
+                        _makeException(*_exception,
+                                       _buffer, *_idx, _len,
+                                       @"got nil-key in dictionary ..");
+                }
+                didFail = YES;
+                break;
+            }
+
+            /* The following parses:  (comment|space)* '=' (comment|space)* */
+            if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+                *_exception =
+                    _makeException(*_exception, _buffer, *_idx, _len,
+                                   @"expected '=' after key in dictionary");
+                didFail = YES;
+                break; // unexpected EOF
+            }
+            // no we need a '=' assignment
+            if (_buffer[*_idx] != '=') {
+                *_exception =
+                    _makeException(*_exception, _buffer, *_idx, _len,
+                                   @"expected '=' after key in dictionary");
+                didFail = YES;
+                break;
+            }
+            *_idx += 1; // skip '='
+            if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+                *_exception =
+                    _makeException(*_exception, _buffer, *_idx, _len,
+                                   @"expected value after key '=' in dictionary");
+                didFail = YES;
+                break; // unexpected EOF
+            }
+
+            // read value property
+            value = _parseProperty(_zone, _buffer, _idx, _len, _exception);
+            if (value == nil) { // syntax error
+                value = [NSNull null];
+                if (*_exception == nil) {
+                    *_exception = _makeException(*_exception, _buffer, *_idx, _len,
+                                                 @"got nil-value in dictionary");
+                }
+                didFail = YES;
+                break;
+            }
+            
+            NSCAssert(key,   @"invalid key ..");
+            NSCAssert(value, @"invalid value ..");
+
+            if ([result objectForKey:key]) {
+#if !RAISE_ON_DUPLICATE_KEYS
+                NSLog(@"WARNING: duplicate key '%@' found in dictionary !", key);
+#else
+                NSString *r;
+                r = [NSString stringWithFormat:
+                                @"duplicate key '%@' found in dictionary !",
+                                key];
+                *_exception =
+                    _makeException(*_exception, _buffer, *_idx, _len, r);
+                didFail = YES;
+                break; // unexpected EOF
+#endif
+            }
+            
+            [result setObject:value forKey:key];
+
+            // release key and value
+            RELEASE(key);   key   = nil;
+            RELEASE(value); value = nil;
+
+            // read trailing ';' if available
+            if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+                *_exception =
+                    _makeException(*_exception, _buffer, *_idx, _len,
+                                   @"dictionary was not closed (expected '}')");
+                didFail = YES;
+                break; // unexpected EOF
+            }
+            if (_buffer[*_idx] == ';') {
+                *_idx += 1; // skip ';'
+            }
+            else { // no ';' at end of pair, only allowed at end of dictionary
+                if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+                    *_exception =
+                        _makeException(*_exception, _buffer, *_idx, _len,
+                                       @"dictionary was not closed (expected '}')");
+                    didFail = YES;
+                    break; // unexpected EOF
+                }
+
+                if (_buffer[*_idx] != '}') { // dictionary wasn't closed
+                    *_exception =
+                        _makeException(*_exception, _buffer, *_idx, _len,
+                                       @"key-value pair without ';' at the end");
+                    didFail = YES;
+                    break;
+                }
+            }
+        }
+        while ((*_idx < _len) && (result != nil) && !didFail);
+
+        if (didFail) {
+            RELEASE(key);    key    = nil;
+            RELEASE(value);  value  = nil;
+            RELEASE(result); result = nil;
+            return nil;
+        }
+        else {
+#if 1
+            return result;
+#else
+           NSDictionary *d;
+           d = [result copyWithZone:_zone];
+           RELEASE(result);
+            return d;
+#endif
+       }
+    }
+}
+
+static NSArray *_parseArray(NSZone *_zone, const unsigned char *_buffer, unsigned *_idx,
+                            unsigned _len, NSException **_exception)
+{
+    if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+        // EOF reached during comment-skipping
+        *_exception = _makeException(*_exception, _buffer, *_idx, _len,
+                                     @"did not find array (expected '(')");
+        return nil;
+    }
+
+    if (_buffer[*_idx] != '(') { // it's not an array that's follows
+        *_exception = _makeException(*_exception, _buffer, *_idx, _len,
+                                     @"did not find array (expected '(')");
+        return nil;
+    }
+    else {
+        NSMutableArray *result = nil;
+        id element = nil;
+
+        *_idx += 1; // skip '('
+
+        if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+            *_exception = _makeException(*_exception, _buffer, *_idx, _len,
+                                         @"array was not closed (expected ')')");
+            return nil; // EOF
+        }
+
+        if (_buffer[*_idx] == ')') { // an empty array
+            *_idx += 1; // skip the ')'
+            return [[NSArray allocWithZone:_zone] init];
+        }
+
+        result = [[NSMutableArray allocWithZone:_zone] init];
+        do {
+            element = _parseProperty(_zone, _buffer, _idx, _len, _exception);
+            if (element == nil) {
+                *_exception = _makeException(*_exception, _buffer, *_idx, _len,
+                                             @"expected element in array");
+                RELEASE(result); result = nil;
+                break;
+            }
+            [result addObject:element];
+            RELEASE(element); element = nil;
+
+            if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+                *_exception =
+                    _makeException(*_exception, _buffer, *_idx, _len,
+                                   @"array was not closed (expected ')' or ',')");
+                RELEASE(result); result = nil;
+                break;
+            }
+
+            if (_buffer[*_idx] == ')') { // closed array
+                *_idx += 1; // skip ')'
+                break;
+            }
+            else if (_buffer[*_idx] == ',') { // next element
+                *_idx += 1; // skip ','
+
+                if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+                    *_exception =
+                        _makeException(*_exception, _buffer, *_idx, _len,
+                                       @"array was not closed (expected ')')");
+                    RELEASE(result); result = nil;
+                    break;
+                }
+                if (_buffer[*_idx] == ')') { // closed array, like this '(1,2,)'
+                    *_idx += 1; // skip ')'
+                    break;
+                }
+            }
+            else { // syntax error
+                *_exception =
+                    _makeException(*_exception, _buffer, *_idx, _len,
+                                   @"expected ')' or ',' after array element");
+                RELEASE(result); result = nil;
+                break;
+            }
+        }
+        while ((*_idx < _len) && (result != nil));
+
+        return result;
+    }
+}
+
+static id _parseProperty(NSZone *_zone, const unsigned char *_buffer, unsigned *_idx,
+                         unsigned _len, NSException **_exception)
+{
+    id result = nil;
+    
+    if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+        // no property found
+        return nil; // EOF
+    }
+
+    switch (_buffer[*_idx]) {
+    case '"': // quoted string
+        result = _parseString(_zone, _buffer, _idx, _len, _exception);
+        break;
+    case '{': // dictionary
+        result = _parseDict(_zone, _buffer, _idx, _len, _exception);
+        break;
+    case '(': // array
+        result = _parseArray(_zone, _buffer, _idx, _len, _exception);
+        break;
+    case '<': // data
+        result = _parseData(_zone, _buffer, _idx, _len, _exception);
+        break;
+    default: // an unquoted string
+        result = _parseString(_zone, _buffer, _idx, _len, _exception);
+        break;
+    }
+    
+    return result;
+}
+
+static NSDictionary *_parseStrings(NSZone *_zone, const unsigned char *_buffer,
+                                   unsigned *_idx, unsigned _len,
+                                   NSException **_exception,
+                                   NSString *fname)
+{
+    NSMutableDictionary *result = nil;
+    id   key     = nil;
+    id   value   = nil;
+    BOOL didFail = NO;
+  
+    result = [[NSMutableDictionary allocWithZone:_zone] init];
+    while ((*_idx < _len) && (result != nil) && !didFail) {
+        key   = nil;
+        value = nil;
+      
+        if (!_skipComments(_buffer, _idx, _len, YES, _exception))
+            break; // expected EOF
+
+        // read key string
+        key = _parseString(_zone, _buffer, _idx, _len, _exception);
+        if (key == nil) { // syntax error
+            if (*_exception == nil) {
+                NSString *txt = @"got nil-key in string table";
+                if (fname)
+                    txt = [txt stringByAppendingFormat:@" (path=%@)", fname];
+                *_exception =
+                    _makeException(*_exception, _buffer, *_idx, _len, txt);
+            }
+            didFail = YES;
+            break;
+        }
+
+        /* The following parses:  (comment|space)* '=' (comment|space)* */
+        if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+            NSString *txt = @"expected '=' after key in string table";
+            if (fname)
+                txt = [txt stringByAppendingFormat:@" (path=%@)", fname];
+            *_exception =
+                _makeException(*_exception, _buffer, *_idx, _len, txt);
+            didFail = YES;
+            break; // unexpected EOF
+        }
+        // now we need a '=' assignment
+        if (_buffer[*_idx] != '=') {
+            NSString *txt = @"expected '=' after key in string table";
+            if (fname)
+                txt = [txt stringByAppendingFormat:@" (path=%@)", fname];
+            *_exception = _makeException(*_exception, _buffer, *_idx, _len,
+                                         txt);
+            didFail = YES;
+            break;
+        }
+        *_idx += 1; // skip '='
+        if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+            NSString *txt = @"expected value after key in string table";
+            if (fname)
+                txt = [txt stringByAppendingFormat:@" (path=%@)", fname];
+            *_exception =
+                _makeException(*_exception, _buffer, *_idx, _len, txt);
+            didFail = YES;
+            break; // unexpected EOF
+        }
+
+        // read value string
+        value = _parseString(_zone, _buffer, _idx, _len, _exception);
+        if (value == nil) { // syntax error
+            if (*_exception == nil) {
+                *_exception =
+                    _makeException(*_exception, _buffer, *_idx, _len,
+                                   @"got nil-value after key in string table");
+            }
+            didFail = YES;
+            break;
+        }
+
+        NSCAssert(key,   @"invalid key ..");
+        NSCAssert(value, @"invalid value ..");
+
+        if ([result objectForKey:key]) {
+            NSString *txt;
+
+            txt = fname
+                ? [NSString stringWithFormat:
+                            @"duplicate key '%@' found in strings file '%@'",
+                              key, fname]
+                : [NSString stringWithFormat:
+                            @"duplicate key '%@' found in strings file", key];
+            
+#if !RAISE_ON_DUPLICATE_KEYS
+            NSLog(@"WARNING: %@ !", txt);
+#else
+            *_exception =
+                _makeException(*_exception, _buffer, *_idx, _len, txt);
+            didFail = YES;
+            break; // unexpected EOF
+#endif
+        }
+        else
+            [result setObject:value forKey:key];
+        
+        // release key and value
+        RELEASE(key);   key   = nil;
+        RELEASE(value); value = nil;
+
+        // read trailing ';' if available
+        if (!_skipComments(_buffer, _idx, _len, YES, _exception))
+            break; // expected EOF
+
+        if (_buffer[*_idx] == ';') {
+            *_idx += 1; // skip ';'
+        }
+    }
+
+    if (didFail) {
+        RELEASE(key);    key    = nil;
+        RELEASE(value);  value  = nil;
+        RELEASE(result); result = nil;
+        return nil;
+    }
+    else
+        return result;
+}
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/PropertyListParserUnichar.m b/libFoundation/Foundation/PropertyListParserUnichar.m
new file mode 100644 (file)
index 0000000..57a6dc6
--- /dev/null
@@ -0,0 +1,1326 @@
+/* 
+   PropertyListParser.m
+
+   Copyright (C) 1998 MDlink online service center, Helge Hess
+   All rights reserved.
+
+   Author: Helge Hess (helge@mdlink.de)
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <ctype.h>
+#include <Foundation/common.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSArray.h>
+#include <Foundation/NSData.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSValue.h>
+#include <Foundation/NSNull.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+
+#ifdef NeXT /* NeXT Mach map_fd() */
+#  include <mach/mach.h>
+#  include <libc.h>
+#elif defined(HAVE_MMAP) /* Posix mmap() */
+#  include <sys/types.h>
+#  include <sys/mman.h>
+#  include <unistd.h>
+#else  /* No file mapping available */
+#endif
+
+#include "PropertyListParser.h"
+
+// TODO: track filename
+// TODO: the code below has quite some duplicate code which should be replaced
+//       by macros
+// TODO: the 8bit parser used mmap() before, we can't do that with Unicode
+
+static NSString     *_parseString (NSZone *_zone, const unichar *_buffer,
+                                   unsigned *_idx, unsigned _len,
+                                   NSException **_exception);
+static NSDictionary *_parseDict   (NSZone *_zone, const unichar *_buffer,
+                                   unsigned *_idx, unsigned _len,
+                                   NSException **_exception);
+static NSArray      *_parseArray  (NSZone *_zone, const unichar *_buffer,
+                                   unsigned *_idx, unsigned _len,
+                                   NSException **_exception);
+static NSData       *_parseData   (NSZone *_zone, const unichar *_buffer,
+                                   unsigned *_idx, unsigned _len,
+                                   NSException **_exception);
+static id           _parseProperty(NSZone *_zone, const unichar *_buffer,
+                                   unsigned *_idx, unsigned _len,
+                                   NSException **_exception);
+static NSDictionary *_parseStrings(NSZone *_zone, const unichar *_buffer,
+                                   unsigned *_idx, unsigned _len,
+                                   NSException **_exception,
+                                   NSString *fname);
+
+static __inline__ BOOL NSPL_IS_UCS2_BUF(const unsigned char *_buffer, 
+                                       unsigned _len)
+{
+    if (_len >= 2) {
+        if (_buffer[0] == 0xFE && _buffer[1] == 0xFF)
+            return YES;
+       
+       if (_buffer[0] == 0xFF && _buffer[1] == 0xFE)
+            return YES;
+    }
+    return NO;
+}
+
+// public unichar functions
+
+NSString *NSParseStringFromUnichars(const unichar *_buffer, unsigned _len)
+{
+    NSString    *result    = nil;
+    NSException *exception = nil;
+    unsigned    idx        = 0;
+    
+    result = _parseString(nil, _buffer, &idx, _len, &exception);
+    result = AUTORELEASE(result);
+    if (exception)
+        [exception raise];
+    return result;
+}
+
+NSArray *NSParseArrayFromUnichars(const unichar *_buffer, unsigned _len)
+{
+    NSArray     *result    = nil;
+    NSException *exception = nil;
+    unsigned    idx        = 0;
+    
+    result = _parseArray(nil, _buffer, &idx, _len, &exception);
+    result = AUTORELEASE(result);
+    if (exception)
+        [exception raise];
+    return result;
+}
+
+NSDictionary *NSParseDictionaryFromUnichars(const unichar *_buffer, 
+                                           unsigned _len)
+{
+    NSDictionary *result    = nil;
+    NSException  *exception = nil;
+    unsigned     idx        = 0;
+    
+    result = _parseDict(nil, _buffer, &idx, _len, &exception);
+    result = AUTORELEASE(result);
+    if (exception)
+        [exception raise];
+    return result;
+}
+
+// public functions
+
+NSString *NSParseStringFromBuffer(const unsigned char *_buffer, unsigned _len)
+{
+    // DEPRECATED (based on char stream)
+    NSString *result;
+    NSString *s;
+    
+    if (NSPL_IS_UCS2_BUF(_buffer, _len)) {
+       NSLog(@"WARNING(%s): tried to parse Unicode string (FE/FF or rev) ...",
+             __PRETTY_FUNCTION__);
+       return nil;
+    }
+    
+    s = [[NSString alloc] initWithCString:_buffer length:_len];
+    result = NSParseStringFromString(s);
+    [s release];
+    return result;
+}
+
+NSArray *NSParseArrayFromBuffer(const unsigned char *_buffer, unsigned _len)
+{
+    // DEPRECATED (based on char stream)
+    NSArray  *result;
+    NSString *s;
+
+    if (NSPL_IS_UCS2_BUF(_buffer, _len)) {
+       NSLog(@"WARNING(%s): tried to parse Unicode string (FE/FF or rev) ...",
+             __PRETTY_FUNCTION__);
+       return nil;
+    }
+    
+    s = [[NSString alloc] initWithCString:_buffer length:_len];
+    result = NSParseArrayFromString(s);
+    [s release];
+    return result;
+}
+
+NSDictionary *NSParseDictionaryFromBuffer(const unsigned char *_buffer, 
+                                         unsigned _len)
+{
+    // DEPRECATED (based on char stream)
+    NSDictionary *result;
+    NSString     *s;
+
+    if (NSPL_IS_UCS2_BUF(_buffer, _len)) {
+       NSLog(@"WARNING(%s): tried to parse Unicode string (FE/FF or rev) ...",
+             __PRETTY_FUNCTION__);
+       return nil;
+    }
+    
+    s = [[NSString alloc] initWithCString:_buffer length:_len];
+    result = NSParseDictionaryFromString(s);
+    [s release];
+    return result;
+}
+
+NSString *NSParseStringFromData(NSData *_data)
+{
+    NSString *s, *r;
+    
+    if (_data == nil)
+       return nil;
+    
+    // TODO: could we directly recode to unichar buffer?
+    s = [[NSString alloc] initWithData:_data 
+                         encoding:[NSString defaultCStringEncoding]];
+    r = NSParseStringFromString(s);
+    [s release];
+    return r;
+}
+
+NSArray *NSParseArrayFromData(NSData *_data)
+{
+    NSArray  *r;
+    NSString *s;
+    
+    if (_data == nil)
+       return nil;
+    
+    // TODO: could we directly recode to unichar buffer?
+    s = [[NSString alloc] initWithData:_data 
+                         encoding:[NSString defaultCStringEncoding]];
+    r = NSParseArrayFromString(s);
+    [s release];
+    return r;
+}
+
+NSDictionary *NSParseDictionaryFromData(NSData *_data)
+{
+    NSDictionary *r;
+    NSString     *s;
+    
+    if (_data == nil)
+       return nil;
+    
+    // TODO: could we directly recode to unichar buffer?
+    s = [[NSString alloc] initWithData:_data 
+                         encoding:[NSString defaultCStringEncoding]];
+    r = NSParseDictionaryFromString(s);
+    [s release];
+    return r;
+}
+
+NSString *NSParseStringFromString(NSString *_str)
+{
+    NSString *s;
+    unichar  *buf;
+    unsigned len;
+    
+    len = [_str length];
+    buf = calloc(len + 4, sizeof(unichar));
+    [_str getCharacters:buf]; buf[len] = '\0';
+    s = NSParseStringFromUnichars(buf, len);
+    if (buf != NULL) free(buf);
+    return s;
+}
+
+NSArray *NSParseArrayFromString(NSString *_str)
+{
+    NSArray  *a;
+    unichar  *buf;
+    unsigned len;
+    
+    len = [_str length];
+    buf = calloc(len + 4, sizeof(unichar));
+    [_str getCharacters:buf]; buf[len] = '\0';
+    a = NSParseArrayFromUnichars(buf, len);
+    if (buf) free(buf);
+    return a;
+}
+
+NSDictionary *NSParseDictionaryFromString(NSString *_str)
+{
+    NSDictionary *d;
+    unichar      *buf;
+    unsigned     len;
+    
+    len = [_str length];
+    buf = calloc(len + 4, sizeof(unichar));
+    [_str getCharacters:buf]; buf[len] = '\0';
+    d = NSParseDictionaryFromUnichars(buf, len);
+    if (buf) free(buf);
+    return d;
+}
+
+id NSParsePropertyListFromBuffer(const unsigned char *_buffer, unsigned _len)
+{
+    // DEPRECATED (based on char stream)
+    id       result;
+    NSString *s;
+
+    if (NSPL_IS_UCS2_BUF(_buffer, _len)) {
+       NSLog(@"WARNING(%s): tried to parse Unicode plist (FE/FF or rev) ...",
+             __PRETTY_FUNCTION__);
+       return nil;
+    }
+    
+    s = [[NSString alloc] initWithCString:_buffer length:_len];
+    result = NSParsePropertyListFromString(s);
+    [s release];
+    return result;
+}
+
+id NSParsePropertyListFromData(NSData *_data)
+{
+    return NSParsePropertyListFromBuffer([_data bytes], [_data length]);
+}
+
+id NSParsePropertyListFromUnichars(const unichar *_buffer, unsigned _len)
+{
+    id          result = nil;
+    NSException *exception = nil;
+    unsigned    idx = 0;
+    
+    result = _parseProperty(nil, _buffer, &idx, _len, &exception);
+    result = AUTORELEASE(result);
+    if (exception)
+        [exception raise];
+    return result;
+}
+
+id NSParsePropertyListFromString(NSString *_string)
+{
+    unsigned len;
+    unichar  *buf;
+    id       p;
+
+    len = [_string length];
+    buf = calloc(len + 4, sizeof(unichar));
+    [_string getCharacters:buf]; buf[len] = '\0';
+    
+    p = NSParsePropertyListFromUnichars(buf, len);
+    
+    if (buf != NULL) free(buf);
+    return p;
+}
+
+id NSParsePropertyListFromFile(NSString *_path)
+{
+    NSString *content;
+    id plist;
+    
+    if (_path == nil)
+        return nil;
+    
+    content = [[NSString alloc] initWithContentsOfFile:_path];
+    plist = NSParsePropertyListFromString(content);
+    [content release];
+    
+    return plist;
+}
+
+id NSParseStringsFromBuffer(const unsigned char *_buffer, unsigned _len)
+{
+    // DEPRECATED (based on char stream)
+    NSDictionary *result;
+    NSString     *s;
+    
+    s = [[NSString alloc] initWithCString:_buffer length:_len];
+    result = NSParseStringsFromString(s);
+    [s release];
+    return result;
+}
+
+id NSParseStringsFromData(NSData *_data)
+{
+    NSDictionary *result;
+    NSString     *s;
+    
+    if (_data == nil)
+       return nil;
+    
+    s = [[NSString alloc] initWithData:_data 
+                         encoding:[NSString defaultCStringEncoding]];
+    result = NSParseStringsFromString(s);
+    [s release];
+    return result;
+}
+
+id NSParseStringsFromStringWithFilename(NSString *_string, NSString *_fn) {
+    NSDictionary *o;
+    unsigned     len;
+    unichar      *buf;
+    NSException  *exception = nil;
+    unsigned     idx        = 0;
+    
+    len = [_string length];
+    buf = calloc(len + 3, sizeof(unichar));
+    [_string getCharacters:buf]; buf[len] = '\0';
+    
+#if HEAVY_DEBUG
+#warning REMOVE DEBUG LOG
+    printf("PARSE STR: %s len=%d, %s ",
+          [_fn cString],
+          len, 
+          (*(Class *)_string)->name);
+    fflush(stdout);
+#endif
+    
+    o = _parseStrings(nil, buf, &idx, len, &exception, _fn);
+    o = AUTORELEASE(o);
+
+#if HEAVY_DEBUG
+    printf("=> %d entries\n", [o count]);
+#endif
+    
+    if (buf != NULL) free(buf);
+    
+    if (exception != nil)
+        [exception raise];
+    
+    return o;
+}
+id NSParseStringsFromString(NSString *_string)
+{
+    return NSParseStringsFromStringWithFilename(_string, @"<string>");
+}
+
+id NSParseStringsFromFile(NSString *_path)
+{
+    NSString *content;
+    id plist;
+    
+    if (_path == nil)
+        return nil;
+    
+    content = [[NSString alloc] initWithContentsOfFile:_path];
+    plist = NSParseStringsFromStringWithFilename(content, _path);
+    [content release];
+    
+    return plist;
+}
+
+/* ******************* implementation ******************** */
+
+static inline BOOL _isBreakChar(unsigned char _c)
+{
+    switch (_c) {
+        case ' ': case '\t': case '\n': case '\r':
+        case '/': case '=':  case ';':  case ',':
+        case '{': case '(':  case '"':  case '<':
+        case ')': case '}':  case '>':
+            return YES;
+
+        default:
+            return NO;
+    }
+}
+static inline BOOL _isUnquotedStringEndChar(unsigned char _c) {
+    switch (_c) {
+        case ' ': case '\t': case '\n': case '\r':
+        case '=':  case ';':  case ',': case '"':
+        case ')': case '}':  case '>':
+            return YES;
+        
+        default:
+            return NO;
+    }
+}
+
+static inline int _valueOfHexChar(char _c)
+{
+    switch (_c) {
+        case '0': case '1': case '2': case '3': case '4':
+        case '5': case '6': case '7': case '8': case '9':
+            return (_c - '0'); // 0-9 (ascii-char)'0' - 48 => (int)0
+      
+        case 'A': case 'B': case 'C':
+        case 'D': case 'E': case 'F':
+            return (_c - 'A' + 10); // A-F, A=10..F=15, 'A'=65..'F'=70
+      
+        case 'a': case 'b': case 'c':
+        case 'd': case 'e': case 'f':
+            return (_c - 'a' + 10); // a-f, a=10..F=15, 'a'=97..'f'=102
+
+        default:
+            return -1;
+    }
+}
+static inline BOOL _isHexDigit(char _c)
+{
+    switch (_c) {
+        case '0': case '1': case '2': case '3': case '4':
+        case '5': case '6': case '7': case '8': case '9':
+        case 'A': case 'B': case 'C':
+        case 'D': case 'E': case 'F':
+        case 'a': case 'b': case 'c':
+        case 'd': case 'e': case 'f':
+            return YES;
+
+        default:
+            return NO;
+    }
+}
+
+static inline int _numberOfLines(const unichar *_buffer, unsigned _lastIdx)
+{
+    register unsigned int pos, lineCount = 1;
+
+    for (pos = 0; (pos < _lastIdx) && (_buffer[pos] != '\0'); pos++) {
+        if (_buffer[pos] == '\n')
+            lineCount++;
+    }
+    return lineCount;
+}
+
+static NSException *_makeException(NSException *_exception,
+                                   const unichar *_buffer, unsigned _idx,
+                                   unsigned _len, NSString *_text)
+{
+    NSMutableDictionary *ui = nil;
+    NSException *exception = nil;
+    int         numLines;
+    BOOL        atEof;
+    
+    numLines   = _numberOfLines(_buffer, _idx);
+    atEof      = (_idx >= _len) ? YES : NO;
+    
+    /* error resulted from a previous error (exception already set) */
+    if (_exception) 
+        return _exception;
+    
+    exception = [[SyntaxErrorException alloc] init];
+    
+    _text = atEof
+        ? [NSString stringWithFormat:@"Unexpected end: %@", _text]
+        : [NSString stringWithFormat:@"Syntax error in line %i: %@",
+                      numLines,_text];
+  
+    [exception setReason:_text];
+
+    // user info
+    {
+        ui = [[exception userInfo] mutableCopy];
+        if (ui == nil)
+            ui = [[NSMutableDictionary alloc] initWithCapacity:8];
+
+        [ui setObject:[NSNumber numberWithInt:numLines] forKey:@"line"];
+        [ui setObject:[NSNumber numberWithInt:_len]     forKey:@"size"];
+        [ui setObject:[NSNumber numberWithInt:_idx]     forKey:@"position"];
+
+        /*
+          if (_len > 0)
+          [ui setObject:[NSString stringWithCString:_buffer length:_len]
+              forKey:@"text"];
+    
+          if (!atEof && (_idx > 0)) {
+          [ui setObject:[NSString stringWithCString:_buffer length:_idx]
+          forKey:@"consumedText"];
+          }
+        */
+        if (!atEof && (_idx > 0)) {
+            register unsigned pos;
+            const unichar *startPos, *endPos;
+
+            for (pos = _idx; (pos >= 0) && (_buffer[pos] != '\n'); pos--)
+                ;
+            startPos = &(_buffer[pos + 1]);
+
+            for (pos = _idx; ((pos < _len) && (_buffer[pos] != '\n')); pos++)
+                ;
+            endPos = &(_buffer[pos - 1]);
+            
+            if (startPos < endPos) {
+               NSString *s;
+               
+               s = [[NSString alloc] initWithCharacters:startPos
+                                     length:(endPos - startPos)];
+                [ui setObject:s forKey:@"lastLine"];
+               [s release];
+            }
+            else {
+                NSLog(@"%s: startPos=0x%08X endPos=0x%08X",
+                      __PRETTY_FUNCTION__, startPos, endPos);
+            }
+        }
+    
+        [exception setUserInfo:ui];
+    
+        RELEASE(ui); ui = nil;
+    }
+
+    return exception;
+}
+
+static BOOL _skipComments(const unichar *_buffer,
+                          unsigned *_idx, unsigned _len,
+                          BOOL _skipSpaces, NSException **_exception)
+{
+    register unsigned pos = *_idx;
+    BOOL lookAgain;
+
+    if (pos >= _len)
+        return NO;
+    
+    do { // until all comments are filtered ..
+        lookAgain = NO;
+        
+        if ((_buffer[pos] == '/') && ((pos + 1) < _len)) {
+            if (_buffer[pos + 1] == '/') { // single line comments
+                pos += 2; // skip '//'
+                
+                // search for '\n' ..
+                while ((pos < _len) && (_buffer[pos] != '\n'))
+                    pos++;
+
+                if ((pos < _len) && (_buffer[pos] == '\n')) {
+                    pos++; // skip newline, otherwise EOF was reached
+                    lookAgain = YES;
+                }
+            }
+            else if (_buffer[pos + 1] == '*') { /* multiline comments */
+                BOOL commentIsClosed = NO;
+                
+                pos += 2; // skip '/*'
+                
+                do { // search for '*/'
+                    while ((pos < _len) && (_buffer[pos] != '*'))
+                        pos++;
+
+                    if (pos < _len) { // found '*'
+                        pos++; // skip '*'
+                        
+                        if (pos < _len) {
+                            if (_buffer[pos] == '/') { // found '*/'
+                                commentIsClosed = YES;
+                                pos ++; // skip '/'
+                                lookAgain = YES;
+                                break; // leave loop
+                            }
+#if DEBUG_PLIST
+                            else
+                                printf("'*' inside multiline comment !\n");
+#endif
+                        }
+                    }
+                }
+                while (pos < _len);
+                
+                if (!commentIsClosed) {
+                    // EOF found, comment wasn't closed
+                    *_exception =
+                        _makeException(*_exception, _buffer, *_idx, _len,
+                                       @"comment was not closed "
+                                       @"(expected '*/')");
+                    return NO;
+                }
+            }
+        }
+        else if (_skipSpaces && isspace((int)_buffer[pos])) {
+            pos++;
+            lookAgain = YES;
+        }
+    }
+    while (lookAgain && (pos < _len));
+    
+    // store position ..
+    *_idx = pos;
+    //NSLog(@"skipped comments, now at '%s'", &(_buffer[*_idx]));
+
+    return (pos < _len);
+}
+
+static NSString *_parseString(NSZone *_zone, const unichar *_buffer,
+                              unsigned *_idx,
+                              unsigned _len, NSException **_exception)
+{
+
+    // skip comments and spaces
+    if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+        // EOF reached during comment-skipping
+        *_exception =
+            _makeException(*_exception, _buffer, *_idx, _len,
+                           @"did not find a string !");
+        return nil;
+    }
+    
+    if (_buffer[*_idx] == '"') { // a quoted string
+        register unsigned pos = *_idx;
+        register unsigned len = 0;
+        unsigned startPos = pos + 1;
+        BOOL     containsEscaped = NO;
+    
+        pos++; // skip starting quote
+
+        // loop until closing quote
+        while ((_buffer[pos] != '"') && (pos < _len)) {
+            if (_buffer[pos] == '\\') {
+                containsEscaped = YES;
+                pos++; // skip following char
+                if (pos == _len) {
+                    *_exception =
+                        _makeException(*_exception, _buffer, *_idx, _len,
+                                       @"escape in quoted string not finished !");
+                    return nil;
+                }
+            }
+            pos++;
+            len++;
+        }
+
+        if (pos == _len) { // syntax error, quote not closed
+            *_idx = pos;
+            *_exception =
+                _makeException(*_exception, _buffer, *_idx, _len,
+                               @"quoted string not closed (expected '\"')");
+            return nil;
+        }
+
+        pos++;       // skip closing quote
+        *_idx = pos; // store pointer
+        pos = 0;
+       
+        if (len == 0) // empty string
+            return @"";
+       
+       if (containsEscaped) {
+            register unsigned pos2;
+            unichar *str;
+            id   ostr = nil;
+
+           str = calloc(len + 3, sizeof(unichar));
+
+            NSCAssert(len > 0, @"invalid length ..");
+           
+            for (pos = startPos, pos2 = 0; _buffer[pos] != '"'; pos++,pos2++) {
+                //NSLog(@"char=%c pos=%i pos2=%i", _buffer[pos], pos2);
+                if (_buffer[pos] == '\\') { /* a quoted char */
+                    pos++;
+                    switch (_buffer[pos]) {
+                    case 'a':  str[pos2] = '\a'; break;
+                    case 'b':  str[pos2] = '\b'; break;
+                    case 'f':  str[pos2] = '\f'; break;
+                    case 'n':  str[pos2] = '\n'; break;
+                    case 'r':  str[pos2] = '\r'; break;
+                    case 't':  str[pos2] = '\t'; break;
+                    case 'v':  str[pos2] = '\v'; break;
+                    case '\\': str[pos2] = '\\'; break;
+            
+                    default:
+                        str[pos2] = _buffer[pos];
+                        break;
+                    }
+                }
+                else {
+                    str[pos2] = _buffer[pos];
+                }
+            }
+            str[pos2] = '\0';
+            NSCAssert(pos2 == len, @"invalid unescape ..");
+           
+            ostr = [[NSString allocWithZone:_zone]
+                              initWithCharacters:str length:len];
+            if (str != NULL) free(str); str = NULL;
+           
+            return ostr;
+        }
+        else {
+            NSCAssert(len > 0, @"invalid length ..");
+
+#if HEAVY_DEBUG
+#warning REMOVE DEBUG LOG
+           if (len>10 && _buffer[startPos] == 'B' && 
+               _buffer[startPos+1] == 'u') {
+               printf("%s: make string len %d (%c,%c,%c,%c)\n",
+                      __PRETTY_FUNCTION__, len,
+                      _buffer[startPos],
+                      _buffer[startPos+1],
+                      _buffer[startPos+2],
+                      _buffer[startPos+3]);
+           }
+#endif
+           
+            return [[NSString allocWithZone:_zone]
+                              initWithCharacters:&(_buffer[startPos]) 
+                             length:len];
+        }
+    }
+    else { /* an unquoted string, may not be zero chars long ! */
+        register unsigned pos = *_idx;
+        register unsigned len = 0;
+        unsigned startPos = pos;
+        
+        // loop until break char
+        while (!_isUnquotedStringEndChar(_buffer[pos]) && (pos < _len)) {
+            pos++;
+            len++;
+        }
+        
+        if (len == 0) { // wasn't a string ..
+            *_exception = _makeException(*_exception, _buffer, *_idx, _len,
+                                         @"did not find a string !");
+            return nil;
+        }
+       
+       *_idx = pos;
+       
+       return [[NSString allocWithZone:_zone]
+                         initWithCharacters:&(_buffer[startPos]) length:len];
+    }
+}
+
+static NSData *_parseData(NSZone *_zone, const unichar *_buffer,
+                          unsigned *_idx, unsigned _len, 
+                         NSException **_exception)
+{
+    if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+        // EOF reached during comment-skipping
+        *_exception = _makeException(*_exception, _buffer, *_idx, _len,
+                                     @"did not find a data (expected '<') !");
+        return nil;
+    }
+
+    if (_buffer[*_idx] != '<') { // it's not a data that's follows
+        *_exception = _makeException(*_exception, _buffer, *_idx, _len,
+                                     @"did not find a data (expected '<') !");
+        return nil;
+    }
+    else {
+        register      unsigned pos = *_idx + 1;
+        register      unsigned len = 0;
+        unsigned      endPos = 0;
+        NSMutableData *data  = nil;
+    
+        *_idx += 1; // skip '<'
+       
+        if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+            *_exception = 
+               _makeException(*_exception, _buffer, *_idx, _len,
+                              @"data was not closed (expected '>')");
+            return nil; // EOF
+        }
+
+        if (_buffer[*_idx] == '>') { // empty data
+            *_idx += 1; // skip '>'
+            return [[NSData allocWithZone:_zone] init];
+        }
+
+        // count significant chars
+        while ((_buffer[pos] != '>') && (pos < _len)) {
+            if ((_buffer[pos] == ' ') || (_buffer[pos] == '\t'))
+                ;
+            else if (_isHexDigit(_buffer[pos]))
+                len++;
+            else {
+                *_idx = pos;
+                *_exception = _makeException(*_exception, _buffer, *_idx, _len,
+                                             @"invalid char in data property");
+                return nil; // abort
+            }
+            pos++;
+        }
+        if (pos == _len) {
+            *_idx = pos;
+            *_exception = _makeException(*_exception, _buffer, *_idx, _len,
+                                         @"data was not closed (expected '>')");
+            return nil; // EOF
+        }
+        endPos = pos; // store position of closing '>'
+
+        // if odd, then add one byte for trailing nibble
+        len = (len % 2 == 1) ? len / 2 + 1 : len / 2;
+        data = [[NSMutableData allocWithZone:_zone] initWithLength:len];
+
+        // now copy bytes ..
+        {
+            register unsigned i;
+            register int pending = -1;
+            char *buf = [data mutableBytes];
+      
+            for (pos = *_idx, i = 0; (pos < endPos) && (i < len); pos++) {
+                int value = _valueOfHexChar(_buffer[pos]);
+
+                if (value != -1) {
+                    if (pending == -1)
+                        pending = value;
+                    else {
+                        value = pending * 16 + value;
+                        pending = -1;
+
+                        buf[i] = value;
+                        i++;
+                    }
+                }
+            }
+            if (pending != -1) { // was odd, now add the trailer ..
+                NSCAssert(i < len, @"invalid length ..");
+                buf[i] = pending * 16;
+            }
+        }
+    
+        // update global position
+        *_idx = endPos + 1; // endPos + 1 (*endPos == '>', 1 => skips '>')
+
+        return data;
+    }
+}
+
+static NSDictionary *_parseDict
+(NSZone *_zone, const unichar *_buffer, unsigned *_idx,
+ unsigned _len, NSException **_exception)
+{
+    if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+        // EOF reached during comment-skipping
+        *_exception =
+            _makeException(*_exception, _buffer, *_idx, _len,
+                           @"did not find dictionary (expected '{')");
+        return nil;
+    }
+    
+    if (_buffer[*_idx] != '{') { // it's not a dict that's follows
+        *_exception =
+            _makeException(*_exception, _buffer, *_idx, _len,
+                           @"did not find dictionary (expected '{')");
+        return nil;
+    }
+    else {
+        NSMutableDictionary *result = nil;
+        id   key     = nil;
+        id   value   = nil;
+        BOOL didFail = NO;
+    
+        *_idx += 1; // skip '{'
+
+        if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+            *_exception =
+                _makeException(*_exception, _buffer, *_idx, _len,
+                               @"dictionary was not closed (expected '}')");
+            return nil; // EOF
+        }
+
+        if (_buffer[*_idx] == '}') { // an empty dictionary
+            *_idx += 1; // skip the '}'
+            return [[NSDictionary allocWithZone:_zone] init];
+        }
+       
+        result = [[NSMutableDictionary allocWithZone:_zone] init];
+        do {
+            key   = nil;
+            value = nil;
+      
+            if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+                *_exception =
+                    _makeException(*_exception, _buffer, *_idx, _len,
+                                   @"dictionary was not closed (expected '}')");
+                didFail = YES;
+                break; // unexpected EOF
+            }
+
+            if (_buffer[*_idx] == '}') { // dictionary closed
+                *_idx += 1; // skip the '}'
+                break;
+            }
+      
+            // read key property
+            key = _parseProperty(_zone, _buffer, _idx, _len, _exception);
+            if (key == nil) { // syntax error
+                if (*_exception == nil) {
+                    *_exception =
+                        _makeException(*_exception,
+                                       _buffer, *_idx, _len,
+                                       @"got nil-key in dictionary ..");
+                }
+                didFail = YES;
+                break;
+            }
+
+            /* The following parses:  (comment|space)* '=' (comment|space)* */
+            if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+                *_exception =
+                    _makeException(*_exception, _buffer, *_idx, _len,
+                                   @"expected '=' after key in dictionary");
+                didFail = YES;
+                break; // unexpected EOF
+            }
+            // no we need a '=' assignment
+            if (_buffer[*_idx] != '=') {
+                *_exception =
+                    _makeException(*_exception, _buffer, *_idx, _len,
+                                   @"expected '=' after key in dictionary");
+                didFail = YES;
+                break;
+            }
+            *_idx += 1; // skip '='
+            if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+                *_exception =
+                    _makeException(*_exception, _buffer, *_idx, _len,
+                                   @"expected value after key '=' in dictionary");
+                didFail = YES;
+                break; // unexpected EOF
+            }
+
+            // read value property
+            value = _parseProperty(_zone, _buffer, _idx, _len, _exception);
+            if (value == nil) { // syntax error
+                value = [NSNull null];
+                if (*_exception == nil) {
+                    *_exception = _makeException(*_exception, _buffer, *_idx, _len,
+                                                 @"got nil-value in dictionary");
+                }
+                didFail = YES;
+                break;
+            }
+            
+            NSCAssert(key,   @"invalid key ..");
+            NSCAssert(value, @"invalid value ..");
+
+            if ([result objectForKey:key]) {
+#if !RAISE_ON_DUPLICATE_KEYS
+                NSLog(@"WARNING: duplicate key '%@' found in dictionary !", key);
+#else
+                NSString *r;
+                r = [NSString stringWithFormat:
+                                @"duplicate key '%@' found in dictionary !",
+                                key];
+                *_exception =
+                    _makeException(*_exception, _buffer, *_idx, _len, r);
+                didFail = YES;
+                break; // unexpected EOF
+#endif
+            }
+            
+            [result setObject:value forKey:key];
+
+            // release key and value
+            RELEASE(key);   key   = nil;
+            RELEASE(value); value = nil;
+
+            // read trailing ';' if available
+            if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+                *_exception =
+                    _makeException(*_exception, _buffer, *_idx, _len,
+                                   @"dictionary was not closed (expected '}')");
+                didFail = YES;
+                break; // unexpected EOF
+            }
+            if (_buffer[*_idx] == ';') {
+                *_idx += 1; // skip ';'
+            }
+            else { // no ';' at end of pair, only allowed at end of dictionary
+                if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+                    *_exception =
+                        _makeException(*_exception, _buffer, *_idx, _len,
+                                       @"dictionary was not closed (expected '}')");
+                    didFail = YES;
+                    break; // unexpected EOF
+                }
+
+                if (_buffer[*_idx] != '}') { // dictionary wasn't closed
+                    *_exception =
+                        _makeException(*_exception, _buffer, *_idx, _len,
+                                       @"key-value pair without ';' at the end");
+                    didFail = YES;
+                    break;
+                }
+            }
+        }
+        while ((*_idx < _len) && (result != nil) && !didFail);
+
+        if (didFail) {
+            RELEASE(key);    key    = nil;
+            RELEASE(value);  value  = nil;
+            RELEASE(result); result = nil;
+            return nil;
+        }
+        else {
+#if 1 // TODO: explain
+            return result;
+#else
+           NSDictionary *d;
+           d = [result copyWithZone:_zone];
+           RELEASE(result);
+            return d;
+#endif
+       }
+    }
+}
+
+static NSArray *_parseArray(NSZone *_zone, const unichar *_buffer, 
+                           unsigned *_idx,
+                            unsigned _len, NSException **_exception)
+{
+    if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+        // EOF reached during comment-skipping
+        *_exception = _makeException(*_exception, _buffer, *_idx, _len,
+                                     @"did not find array (expected '(')");
+        return nil;
+    }
+
+    if (_buffer[*_idx] != '(') { // it's not an array that's follows
+        *_exception = _makeException(*_exception, _buffer, *_idx, _len,
+                                     @"did not find array (expected '(')");
+        return nil;
+    }
+    
+    {
+        NSMutableArray *result = nil;
+        id element = nil;
+
+        *_idx += 1; // skip '('
+
+        if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+            *_exception = _makeException(*_exception, _buffer, *_idx, _len,
+                                         @"array was not closed (expected ')')");
+            return nil; // EOF
+        }
+
+        if (_buffer[*_idx] == ')') { // an empty array
+            *_idx += 1; // skip the ')'
+            return [[NSArray allocWithZone:_zone] init];
+        }
+
+        result = [[NSMutableArray allocWithZone:_zone] init];
+        do {
+            element = _parseProperty(_zone, _buffer, _idx, _len, _exception);
+            if (element == nil) {
+                *_exception = _makeException(*_exception, _buffer, *_idx, _len,
+                                             @"expected element in array");
+                RELEASE(result); result = nil;
+                break;
+            }
+            [result addObject:element];
+            RELEASE(element); element = nil;
+
+            if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+                *_exception =
+                    _makeException(*_exception, _buffer, *_idx, _len,
+                                   @"array was not closed (expected ')' or ',')");
+                RELEASE(result); result = nil;
+                break;
+            }
+
+            if (_buffer[*_idx] == ')') { // closed array
+                *_idx += 1; // skip ')'
+                break;
+            }
+            else if (_buffer[*_idx] == ',') { // next element
+                *_idx += 1; // skip ','
+
+                if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+                    *_exception =
+                        _makeException(*_exception, _buffer, *_idx, _len,
+                                       @"array was not closed (expected ')')");
+                    RELEASE(result); result = nil;
+                    break;
+                }
+                if (_buffer[*_idx] == ')') { // closed array, like this '(1,2,)'
+                    *_idx += 1; // skip ')'
+                    break;
+                }
+            }
+            else { // syntax error
+                *_exception =
+                    _makeException(*_exception, _buffer, *_idx, _len,
+                                   @"expected ')' or ',' after array element");
+                RELEASE(result); result = nil;
+                break;
+            }
+        }
+        while ((*_idx < _len) && (result != nil));
+
+        return result;
+    }
+}
+
+static id _parseProperty(NSZone *_zone, const unichar *_buffer, unsigned *_idx,
+                         unsigned _len, NSException **_exception)
+{
+    id result = nil;
+    
+    if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+        // no property found
+        return nil; // EOF
+    }
+
+    switch (_buffer[*_idx]) {
+    case '"': // quoted string
+        result = _parseString(_zone, _buffer, _idx, _len, _exception);
+        break;
+    case '{': // dictionary
+        result = _parseDict(_zone, _buffer, _idx, _len, _exception);
+        break;
+    case '(': // array
+        result = _parseArray(_zone, _buffer, _idx, _len, _exception);
+        break;
+    case '<': // data
+        result = _parseData(_zone, _buffer, _idx, _len, _exception);
+        break;
+    default: // an unquoted string
+        result = _parseString(_zone, _buffer, _idx, _len, _exception);
+        break;
+    }
+    
+    return result;
+}
+
+static NSDictionary *_parseStrings(NSZone *_zone, const unichar *_buffer,
+                                   unsigned *_idx, unsigned _len,
+                                   NSException **_exception,
+                                   NSString *fname)
+{
+    NSMutableDictionary *result = nil;
+    id   key     = nil;
+    id   value   = nil;
+    BOOL didFail = NO;
+    
+    result = [[NSMutableDictionary allocWithZone:_zone] init];
+    while ((*_idx < _len) && (result != nil) && !didFail) {
+        key   = nil;
+        value = nil;
+      
+        if (!_skipComments(_buffer, _idx, _len, YES, _exception))
+            break; // expected EOF
+
+        // read key string
+        key = _parseString(_zone, _buffer, _idx, _len, _exception);
+        if (key == nil) { // syntax error
+            if (*_exception == nil) {
+                NSString *txt = @"got nil-key in string table";
+                if (fname)
+                    txt = [txt stringByAppendingFormat:@" (path=%@)", fname];
+                *_exception =
+                    _makeException(*_exception, _buffer, *_idx, _len, txt);
+            }
+            didFail = YES;
+            break;
+        }
+
+        /* The following parses:  (comment|space)* '=' (comment|space)* */
+        if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+            NSString *txt = @"expected '=' after key in string table";
+            if (fname)
+                txt = [txt stringByAppendingFormat:@" (path=%@)", fname];
+            *_exception =
+                _makeException(*_exception, _buffer, *_idx, _len, txt);
+            didFail = YES;
+            break; // unexpected EOF
+        }
+        // now we need a '=' assignment
+        if (_buffer[*_idx] != '=') {
+            NSString *txt = @"expected '=' after key in string table";
+            if (fname != nil)
+                txt = [txt stringByAppendingFormat:@" (path=%@)", fname];
+            *_exception = _makeException(*_exception, _buffer, *_idx, _len,
+                                         txt);
+            didFail = YES;
+            break;
+        }
+        *_idx += 1; // skip '='
+        if (!_skipComments(_buffer, _idx, _len, YES, _exception)) {
+            NSString *txt = @"expected value after key in string table";
+            if (fname)
+                txt = [txt stringByAppendingFormat:@" (path=%@)", fname];
+            *_exception =
+                _makeException(*_exception, _buffer, *_idx, _len, txt);
+            didFail = YES;
+            break; // unexpected EOF
+        }
+       
+        // read value string
+        value = _parseString(_zone, _buffer, _idx, _len, _exception);
+        if (value == nil) { // syntax error
+            if (*_exception == nil) {
+                *_exception =
+                    _makeException(*_exception, _buffer, *_idx, _len,
+                                   @"got nil-value after key in string table");
+            }
+            didFail = YES;
+            break;
+        }
+
+        NSCAssert(key,   @"invalid key ..");
+        NSCAssert(value, @"invalid value ..");
+
+#if HEAVY_DEBUG        
+#warning REMOVE DEBUG LOG
+       if ([key indexOfString:@"PrayerAndRepe"] != NSNotFound) {
+           NSLog(@"%s: parsed string (%@,len=%d): %@", __PRETTY_FUNCTION__, 
+                 NSStringFromClass([value class]),
+                 [value length], value);
+       }
+#endif
+       
+        if ([result objectForKey:key]) {
+            NSString *txt;
+
+            txt = fname
+                ? [NSString stringWithFormat:
+                            @"duplicate key '%@' found in strings file '%@'",
+                              key, fname]
+                : [NSString stringWithFormat:
+                            @"duplicate key '%@' found in strings file", key];
+            
+#if !RAISE_ON_DUPLICATE_KEYS
+            NSLog(@"WARNING: %@ !", txt);
+#else
+            *_exception =
+                _makeException(*_exception, _buffer, *_idx, _len, txt);
+            didFail = YES;
+            break; // unexpected EOF
+#endif
+        }
+        else
+            [result setObject:value forKey:key];
+        
+        // release key and value
+        RELEASE(key);   key   = nil;
+        RELEASE(value); value = nil;
+
+        // read trailing ';' if available
+        if (!_skipComments(_buffer, _idx, _len, YES, _exception))
+            break; // expected EOF
+       
+        if (_buffer[*_idx] == ';') {
+            *_idx += 1; // skip ';'
+        }
+       else {
+           NSLog(@"Warning: strings file misses semicolon "
+                 @"(required by Cocoa).");
+       }
+    }
+
+    if (didFail) {
+        RELEASE(key);    key    = nil;
+        RELEASE(value);  value  = nil;
+        RELEASE(result); result = nil;
+        return nil;
+    }
+    
+    return result;
+}
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/StackZone.h b/libFoundation/Foundation/StackZone.h
new file mode 100644 (file)
index 0000000..0447407
--- /dev/null
@@ -0,0 +1,51 @@
+/* 
+   StackZone.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __StackZone_h__
+#define __StackZone_h__
+
+#include <Foundation/NSZone.h>
+
+typedef struct AllocationNode {
+    struct AllocationNode* previous;
+    BOOL freed;
+    char allocatedMemory[0];
+} AllocationNode;
+
+@interface StackZone : NSZone
+{
+    char* memory;
+    AllocationNode* nextNode;
+    unsigned memorySize;
+}
+@end
+
+#endif /* __StackZone_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/StackZone.m b/libFoundation/Foundation/StackZone.m
new file mode 100644 (file)
index 0000000..24333b2
--- /dev/null
@@ -0,0 +1,171 @@
+/* 
+   StackZone.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/StackZone.h>
+#include <Foundation/NSUtilities.h>
+#include <extensions/NSException.h>
+#include <objc/objc-api.h>
+
+@implementation StackZone
+
+/* nextNode indicates to the next allocation node available. The `previous'
+   component of this node points to the node allocated before it.
+   When a new allocation is requested it is satisfied from the node pointed to
+   by nextNode and then nextNode is updated to point to the zone where the
+   next node will be allocated. The algorithm tries first to allocate memory
+   in the nodes below the current node if they are freed. */
+
++ alloc
+{
+    return [self allocZoneInstance];
+}
+
+- init
+{
+    return [self initForSize:64536 granularity:0 canFree:YES];
+}
+
+- initForSize:(unsigned)startSize granularity:(unsigned)granularity
+    canFree:(BOOL)canFree
+{
+    [self setName:@"Default zone"];
+    memory = objc_malloc(startSize);
+    nextNode = (AllocationNode*)memory;
+    nextNode->previous = NULL;
+    memorySize = startSize;
+    return self;
+}
+
+- (void*)malloc:(unsigned)size
+{
+    AllocationNode* previous = nextNode->previous;
+
+    /* Try to use the nodes below the top of stack if they are freed */
+    while (previous && previous->freed == YES) {
+       nextNode = previous;
+       previous = previous->previous;
+    }
+
+    NSCAssert(nextNode, @"nextNode is NULL (previous=0x%08X)", previous);
+
+    /* Check if the requested size can be handled */
+    if (((char*)nextNode) + size - memory
+           + sizeof(AllocationNode) >= memorySize)
+       return NULL;
+
+    /* Prepare nextNode to be allocated */
+    nextNode->freed = NO;
+
+    /* Make nextNode to point to the next allocation node */
+    previous = nextNode;
+    nextNode = (void*)(((char*)nextNode) + sizeof(AllocationNode) + size);
+    nextNode->previous = previous;
+
+    /* Return the memory from the previous node */
+    return &(previous->allocatedMemory);
+}
+
+- (void*)calloc:(unsigned)numElems byteSize:(unsigned)byteSize
+{
+    unsigned size = numElems * byteSize;
+    void* pointer = [self malloc:size];
+
+    memset (pointer, 0, size);
+    return pointer;
+}
+
+- (void*)realloc:(void*)pointer size:(unsigned)newSize
+{
+    AllocationNode* currentNode = nextNode->previous;
+    unsigned size = ((char*)nextNode) - ((char*)currentNode)
+                       - sizeof(AllocationNode);
+    void* newPointer;
+
+    /* If the pointer is NULL behave like a normal allocation */
+    if (!pointer)
+       return [self malloc:newSize];
+
+    while (currentNode && &(currentNode->allocatedMemory) != pointer) {
+       size = ((char*)currentNode) - ((char*)(currentNode->previous))
+               - sizeof(AllocationNode);
+       currentNode = currentNode->previous;
+    }
+
+    /* If the requested size is lower than the allocated pointer size, return
+       the old value. Otherwise allocate a new memory zone, copy the content of
+       the old one and return the address of the new pointer. The old zone is
+       marked as freed. */
+    if (currentNode && size >= newSize)
+       return pointer;
+    else {
+       newPointer = [self malloc:newSize];
+       if (newPointer)
+           memcpy(newPointer, pointer, size);
+       currentNode->freed = YES;
+       return newPointer;
+    }
+}
+
+- (void)recycle
+{
+}
+
+- (BOOL)pointerInZone:(void*)pointer
+{
+    return (char*)pointer > memory && (char*)pointer < memory + memorySize;
+}
+
+- (void)freePointer:(void*)pointer
+{
+    AllocationNode* currentNode = nextNode->previous;
+
+    /* Identify the allocation node of pointer and mark it as freed. */
+    while (currentNode && &(currentNode->allocatedMemory) != pointer)
+       currentNode = currentNode->previous;
+
+    if (currentNode) {
+       if (currentNode->freed == YES)
+           NSLog(@"attempt to free an already freed pointer: %p\n", pointer);
+       else
+           currentNode->freed = YES;
+    }
+    else
+       NSLog(@"attempt to free an unexisting pointer in zone: pointer %p, "
+             @"zone %p (%@)", pointer, self, [self name]);
+}
+
+- (BOOL)checkZone
+{
+    return YES;
+}
+
+@end /* StackZone */
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/UnixSignalHandler.h b/libFoundation/Foundation/UnixSignalHandler.h
new file mode 100644 (file)
index 0000000..88867d3
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+   UnixSignalHandler.h
+
+   Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@net-community.com>
+   Date: November 1997
+
+   Based on a similar class written by Mircea Oancea in July 1995.
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+#ifndef __UnixSignalHandler_h__
+#define __UnixSignalHandler_h__
+
+#if defined(__MINGW32__)
+#  include <signal.h>
+#else
+#  include <sys/signal.h>
+#endif
+#include <Foundation/NSObject.h>
+
+@class UnixSignalHandlerList;
+
+@interface UnixSignalHandler : NSObject
+{
+  UnixSignalHandlerList *signalHandlers[NSIG];
+  unsigned int          currentSigmask;
+  BOOL                  signalsPending;
+}
+
++ sharedHandler;
+
+- (void)addObserver:(id)observer
+  selector:(SEL)selector
+  forSignal:(int)signalNumber
+  immediatelyNotifyOnSignal:(BOOL)flag;
+- (void)removeObserver:(id)observer;
+- (void)removeObserver:(id)observer
+  forSignal:(int)signalNumber;
+
+/* Blocking or enabling signals */
+- (void)blockAllSignals;
+- (void)enableAllSignals;
+- (void)blockSignal:(int)signum;
+- (void)enableSignal:(int)signum;
+
+- (void)waitForSignal:(int)signum;
+
+- (BOOL)signalsPending;
+
+@end
+
+#endif /* __UnixSignalHandler_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/UnixSignalHandler.m b/libFoundation/Foundation/UnixSignalHandler.m
new file mode 100644 (file)
index 0000000..9755370
--- /dev/null
@@ -0,0 +1,474 @@
+/*
+   UnixSignalHandler.m
+
+   Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@net-community.com>
+   Date: November 1997
+
+   Based on a similar class written by Mircea Oancea in July 1995.
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <config.h>
+
+#include <signal.h>
+#include <errno.h>
+
+#include <Foundation/common.h>
+#include <Foundation/NSValue.h>
+#include <Foundation/NSNotification.h>
+#include <Foundation/NSUserDefaults.h>
+#include <Foundation/NSNotificationQueue.h>
+#include <Foundation/UnixSignalHandler.h>
+
+static NSString* UnixSignalPendingNotification
+    = @"UnixSignalPendingNotification";
+
+#if HAVE_SIGSETMASK
+#  define BSD_SIGNALS 1
+#elif HAVE_SIGHOLD
+#  define SYSV_SIGNALS 1
+#else
+#  if defined(__MINGW32__)
+#    warning "Don't know how to handle signals on Mingw32 !"
+#  elif defined(__CYGWIN32__)
+#    warning "Don't know how to handle signals on Cygwin32 !"
+#  else
+#    error "Don't know how to handle signals!"
+#  endif
+#endif
+
+#if !defined(sigmask)
+# define sigmask(m)    (1 << ((m)-1))
+#endif
+
+static RETSIGTYPE signalHandlerFunction (int signum);
+
+typedef RETSIGTYPE (*PTSignalFunction)(int);
+
+@interface UnixSignalHandlerListItem : NSObject
+{
+@public
+  id   observer;
+  SEL  selector;
+  BOOL immediatelyNotifyOnSignal;
+  UnixSignalHandlerListItem *nextItem;
+}
+- (id)initWithObserver:observer
+  selector:(SEL)selector
+  immediatelyNotifyOnSignal:(BOOL)flag;
+- (id)removeObserver:observer;
+- (void)invokeForSignal:(int)signum;
+@end
+
+
+@implementation UnixSignalHandlerListItem
+
+- (id)initWithObserver:anObserver
+  selector:(SEL)aSelector
+  immediatelyNotifyOnSignal:(BOOL)flag
+{
+  self->observer = anObserver;
+  self->selector = aSelector;
+  self->immediatelyNotifyOnSignal = flag;
+  return self;
+}
+
+- (id)removeObserver:(id)anObserver
+{
+  if (self->observer == anObserver) {
+    (void)AUTORELEASE(self);
+    return self->nextItem;
+  }
+  else {
+    self->nextItem = [self->nextItem removeObserver:anObserver];
+    return self;
+  }
+}
+
+- (void)invokeForSignal:(int)signum
+{
+  [self->observer
+       performSelector:self->selector
+       withObject:[NSNumber numberWithInt:signum]];
+}
+
+@end /* UnixSignalHandlerListItem */
+
+
+@interface UnixSignalHandlerList : NSObject
+{
+@public
+  UnixSignalHandlerListItem *firstItem;
+  PTSignalFunction          oldSignalHandler;
+  BOOL                      signalsPending;
+}
+
+- (void)addObserver:(id)observer
+  selector:(SEL)selector
+  immediatelyNotifyOnSignal:(BOOL)flag;
+- (void)removeObserver:observer;
+- (void)invokeIfCalledImmediatelyIs:(BOOL)flag signal:(int)signum;
+
+@end
+
+@implementation UnixSignalHandlerList
+
+- (void)addObserver:anObserver
+  selector:(SEL)aSelector
+  immediatelyNotifyOnSignal:(BOOL)flag
+{
+    UnixSignalHandlerListItem *newItem = [UnixSignalHandlerListItem new];
+  
+    newItem->nextItem = self->firstItem;
+    [newItem initWithObserver:anObserver
+             selector:aSelector
+             immediatelyNotifyOnSignal:flag];
+    self->firstItem = newItem;
+}
+
+- (void)removeObserver:(id)observer
+{
+    self->firstItem = [self->firstItem removeObserver:observer];
+}
+
+- (void)invokeIfCalledImmediatelyIs:(BOOL)flag signal:(int)signum
+{
+    UnixSignalHandlerListItem *item = self->firstItem;
+    BOOL missed = NO;
+    
+    flag = flag ? YES : NO;
+    
+    if (self->signalsPending) {
+        while (item) {
+            if (item->immediatelyNotifyOnSignal == flag)
+                [item invokeForSignal:signum];
+            else
+                missed = YES;
+            item = item->nextItem;
+        }
+        
+        if (!missed) /* all signals were processed */
+            self->signalsPending = NO;
+    }
+}
+
+@end /* UnixSignalHandlerList */
+
+
+@interface UnixSignalHandler (private)
+- (void)_pendingSignal:(int)signum;
+@end
+
+@implementation UnixSignalHandler
+
+static NSNotification    *notification = nil;
+static UnixSignalHandler *sharedHandler = nil;
+
+static int DebugSigHandler = -1;
+BOOL UnixSignalHandlerIsProcessing = NO;
+
+static RETSIGTYPE signalHandlerFunction (int signum)
+{
+    /* note: no malloc is allowed in signal handlers !!! */
+    int savedErrno; 
+    
+    /* Temporary disable the signals */
+    [sharedHandler blockAllSignals];
+    if (UnixSignalHandlerIsProcessing) {
+        /* nested processing ??? (we are not really allowed to call print) */
+        fprintf(stderr, "%s: detected nested call ...\n",
+                __PRETTY_FUNCTION__);
+        fflush(stderr);
+    }
+    
+    UnixSignalHandlerIsProcessing = YES;
+    savedErrno = errno; /* save errno, see Stevens */
+    {
+        NSNotificationQueue   *queue =
+            [NSNotificationQueue defaultQueue];
+        UnixSignalHandlerList *handlers =
+            sharedHandler->signalHandlers[signum];
+      
+        handlers->signalsPending = YES;
+        sharedHandler->signalsPending = YES;
+        
+        [queue enqueueNotification:notification
+               postingStyle:NSPostASAP
+               /* no coalescing (prev coalesce, but this broke in free()) */
+               coalesceMask:NSNotificationNoCoalescing
+               forModes:nil];
+        [sharedHandler _pendingSignal:signum];
+    }
+    errno = savedErrno; /* restore errno */
+    UnixSignalHandlerIsProcessing = NO;
+    [sharedHandler enableAllSignals];
+}
+
++ (void)initialize
+{
+  static BOOL initialized = NO;
+  
+  if (!initialized) {
+    initialized = YES;
+    
+    if (DebugSigHandler == -1) {
+        DebugSigHandler =
+            [[NSUserDefaults standardUserDefaults]
+                             boolForKey:@"DebugUnixSignalHandler"] ? 1 : 0;
+    }
+    
+    sharedHandler = [[self alloc] init];
+    
+    notification =
+        [[NSNotification notificationWithName:UnixSignalPendingNotification
+                         object:sharedHandler]
+                         retain];
+    [[NSNotificationCenter defaultCenter]
+                           addObserver:self
+                           selector:@selector(_dispatch:)
+                           name:UnixSignalPendingNotification
+                           object:nil];
+  }
+}
+
++ (id)sharedHandler
+{
+    return sharedHandler;
+}
+
+- (id)init
+{
+  int i;
+  
+  for (i = 0; i < NSIG; i++) {
+      self->signalHandlers[i] = [[UnixSignalHandlerList alloc] init];
+      //NSLog(@"handler 0x%08X %i: %@", self, i, self->signalHandlers[i]);
+  }
+  
+#if BSD_SIGNALS
+  self->currentSigmask = sigblock(0);
+#endif
+
+  return self;
+}
+
+- (void)_pendingSignal:(int)signum
+{
+  /* Notify all the handlers that listen for the signal signum immediately.
+     Only those handlers that have requested an immediate notification on
+     signal are invoked here. Those that want to be called after the signal
+     occured are invoked at a later time, when the current NSRunLoop finishes
+     the current cycle. */
+  /* note: no malloc is allowed in signal handlers !!! */
+  [self->signalHandlers[signum] invokeIfCalledImmediatelyIs:YES signal:signum];
+}
+
++ (void)_dispatch:(NSNotification *)notification
+{
+    /* Notify all the handlers that have requested to be called after the
+       current NSRunLoop cycle has finished. The others were already called
+       when the signal occurred. */
+    
+    if (sharedHandler->signalsPending) {
+        int i;
+      
+        for (i = 0; i < NSIG; i++) {
+            UnixSignalHandlerList *handler = sharedHandler->signalHandlers[i];
+
+            if (handler->signalsPending) {
+                //NSLog(@"pending sigs for %i on handler: %@", i, handler);
+                [handler invokeIfCalledImmediatelyIs:NO
+                         signal:i];
+            }
+        }
+        sharedHandler->signalsPending = NO;
+    }
+}
+
+- (BOOL)signalsPending
+{
+    return self->signalsPending;
+}
+
+- (void)addObserver:(id)observer
+  selector:(SEL)selector
+  forSignal:(int)signum
+  immediatelyNotifyOnSignal:(BOOL)flag
+{
+    UnixSignalHandlerList *handler = self->signalHandlers[signum];
+    BOOL shouldInstall = (handler->firstItem == NULL);
+    
+    [self blockSignal:signum];
+    {
+        [handler addObserver:observer
+                 selector:selector
+                 immediatelyNotifyOnSignal:flag];
+        
+        if (shouldInstall)
+#if HAVE_SIGACTION && !defined(__alpha__)
+            {
+                /* this is used on Linux */
+                struct sigaction act, oldact;
+        
+                act.sa_handler = (PTSignalFunction)signalHandlerFunction;
+                sigemptyset (&act.sa_mask);
+                act.sa_flags = 0;
+                sigaction (signum, &act, &oldact);
+                handler->oldSignalHandler = oldact.sa_handler;
+            }
+#elif HAVE_SIGSET
+        handler->oldSignalHandler =
+            (PTSignalFunction)sigset(signum, signalHandlerFunction);
+#else
+        handler->oldSignalHandler =
+            (PTSignalFunction)signal(signum, signalHandlerFunction);
+#endif
+    }
+    [self enableSignal:signum];
+}
+
+- (void)removeObserver:(id)observer forSignal:(int)signum
+{
+    [self blockSignal:signum];
+    {
+        UnixSignalHandlerList *handler = self->signalHandlers[signum];
+      
+        [handler removeObserver:observer];
+        
+        if (handler->firstItem == NULL) {
+#if HAVE_SIGSET && !HAVE_SIGACTION
+            sigset(signum, handler->oldSignalHandler);
+#else
+            signal(signum, handler->oldSignalHandler);
+#endif
+        }
+    }
+    [self enableSignal:signum];
+}
+
+- (void)removeObserver:(id)observer
+{
+  int i;
+  
+  for (i = 0; i < NSIG; i++)
+    [self removeObserver:observer forSignal:i];
+}
+
+
+#if BSD_SIGNALS
+#  if __linux__
+//#    warning using BSD signal functions on Linux ??? (should be SYSV ?)
+#    if SYSV_SIGNALS
+#      warning SYSV signals are also enabled ...
+#    endif
+#  endif
+
+- (void)blockAllSignals
+{
+    if (DebugSigHandler) printf("block all signals\n");
+    sigsetmask((unsigned)-1);
+}
+- (void)enableAllSignals
+{
+    if (DebugSigHandler) printf("enable all signals\n");
+    sigsetmask(self->currentSigmask);
+}
+
+- (void)blockSignal:(int)signum
+{
+    if (DebugSigHandler) printf("block signal %i\n", signum);
+    self->currentSigmask |= sigmask(signum);
+    sigsetmask(self->currentSigmask);
+}
+- (void)enableSignal:(int)signum
+{
+    if (DebugSigHandler) printf("enable signal %i\n", signum);
+    self->currentSigmask &= ~(sigmask(signum));
+    sigsetmask(self->currentSigmask);
+}
+
+- (void)waitForSignal:(int)signum
+{
+    if (DebugSigHandler) printf("wait for signal %i\n", signum);
+    sigpause(sigmask (signum));
+}
+
+#elif SYSV_SIGNALS
+
+- (void)blockAllSignals
+{
+  int i;
+  
+  for (i = 0; i < NSIG; i++)
+    sighold(i);
+}
+
+- (void)enableAllSignals
+{
+  int i;
+
+  for (i = 0; i < NSIG; i++) {
+      if ((self->currentSigmask & sigmask(i)))
+         sigrelse(i);
+  }
+}
+
+- (void)blockSignal:(int)signum
+{
+  self->currentSigmask |= sigmask(signum);
+  sighold(signum);
+}
+- (void)enableSignal:(int)signum
+{
+  self->currentSigmask &= ~(sigmask(signum));
+  sigrelse(signum);
+}
+
+- (void)waitForSignal:(int)signum
+{
+  sigpause(signum);
+}
+
+#else
+#warning cannot handle signals on this platform ...
+
+- (void)blockSignal:(int)signum
+{
+    [self notImplemented:_cmd];
+}
+- (void)enableSignal:(int)signum
+{
+    [self notImplemented:_cmd];
+}
+- (void)waitForSignal:(int)signum
+{
+    [self notImplemented:_cmd];
+}
+
+#endif
+
+@end /* UnixSignalHandler */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/behavior.m b/libFoundation/Foundation/behavior.m
new file mode 100644 (file)
index 0000000..99f5856
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * This file implements behaviors, "protocols with implementations",
+ * an original idea of Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>.
+ *
+ * I wrote another implementation that works with both GNU and NeXT runtimes.
+ * I kept some of Andrew's original comments and some of his functions.
+ *
+ */
+
+/* A Behavior can be seen as a "Protocol with an implementation" or a
+   "Class without any instance variables".  A key feature of behaviors
+   is that they give a degree of multiple inheritance.
+   
+   xxx not necessarily on the "no instance vars".  The behavior just has 
+   to have the same layout as the class.
+   
+   The following function is a sneaky hack way that provides Behaviors
+   without adding any new syntax to the Objective C language.  Simply
+   define a class with the methods you want in the behavior, then call
+   this function with that class as the BEHAVIOR argument.
+   
+   This function should be called in CLASS's +initialize method.
+  
+   If you add several behaviors to a class, be aware that the order of 
+   the additions is significant.
+  
+   */
+
+#include <Foundation/common.h>
+#include <extensions/objc-runtime.h>
+#include <extensions/NSException.h>
+#include <extensions/exceptions/GeneralExceptions.h>
+#include "common.h"
+
+static void class_add_methods_if_not_there (Class, Class);
+static struct objc_method *search_for_method_in_list (struct objc_method_list*, SEL);
+static BOOL class_is_kind_of (Class, Class);
+
+void class_add_behavior (Class class, Class behavior)
+{
+  Class behavior_super_class;
+
+  if (!CLS_ISCLASS (class) || !CLS_ISCLASS (behavior))
+    [[[ObjcRuntimeException alloc] initWithFormat:
+           @"Only classes must be passed to class_add_behavior"] raise];
+
+  class_add_methods_if_not_there (class, behavior);
+  class_add_methods_if_not_there (class->class_pointer,
+                                 behavior->class_pointer);
+
+  behavior_super_class = class_get_super_class (behavior);
+  if (!class_is_kind_of (class, behavior_super_class))
+    class_add_behavior (class, behavior_super_class);
+}
+
+static void class_add_methods_if_not_there (Class class, Class behavior)
+{
+  static SEL initialize_sel = 0;
+  struct objc_method_list *mlist;
+
+  if (!initialize_sel)
+    initialize_sel = sel_register_name ("initialize");
+
+  for (mlist = behavior->methods; mlist; mlist = mlist->method_next)
+    {
+      int i;
+      int size = mlist->method_count ? mlist->method_count - 1 : 1;
+      struct objc_method_list *new_list
+        = objc_malloc (sizeof (struct objc_method_list) + sizeof (struct objc_method) * size);
+
+      new_list->method_next = NULL;
+      new_list->method_count = 0;
+      for (i = 0; i < mlist->method_count; i++)
+       {
+         struct objc_method *behavior_method = &(mlist->method_list[i]);
+         struct objc_method *class_method =
+            search_for_method_in_list (class->methods,
+                                       behavior_method->method_name);
+
+         if (!class_method
+             && !SEL_EQ (behavior_method->method_name, initialize_sel))
+           {
+             /* As long as the method isn't defined in the CLASS, put the
+                 BEHAVIOR method in there.  Thus, behavior methods override
+                 the superclasses' methods. */
+             new_list->method_list[new_list->method_count++] =
+               *behavior_method;
+           }
+       }
+      if (i)
+       {
+          int new_size
+            = new_list->method_count ? new_list->method_count - 1 : 1;
+         new_list = objc_realloc (new_list,
+                                   sizeof (struct objc_method_list) + sizeof (struct objc_method) * new_size);
+         class_addMethods (class, new_list);
+       }
+      else
+       objc_free (new_list);
+    }
+}
+
+/* Given a linked list of method and a method's name.  Search for the named
+   method's method structure.  Return a pointer to the method's method
+   structure if found.  NULL otherwise. */
+static struct objc_method *
+search_for_method_in_list (struct objc_method_list *mlist, SEL op)
+{
+  if (!sel_is_mapped (op))
+    return NULL;
+
+  /* If not found then we'll search the list.  */
+  for (; mlist; mlist = mlist->method_next)
+    {
+      int i;
+
+      /* Search the method list.  */
+      for (i = 0; i < mlist->method_count; ++i)
+       {
+         struct objc_method *method = &mlist->method_list[i];
+
+         if (method->method_name)
+           if (SEL_EQ (method->method_name, op))
+             return method;
+       }
+    }
+
+  return NULL;
+}
+
+static BOOL class_is_kind_of (Class a, Class b)
+{
+  for (; a; a = class_get_super_class (a))
+    if (a == b)
+      return YES;
+  return NO;
+}
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/byte_order.h b/libFoundation/Foundation/byte_order.h
new file mode 100644 (file)
index 0000000..a33d393
--- /dev/null
@@ -0,0 +1,247 @@
+/* 
+   byte_order.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+/*
+   Conversion routines for doubles and floats in and from the network floating
+   format. Assumes the target machine has the IEEE floating point format.
+
+   This file was inspired from architecture/byte_order.h by David E. Bohman
+   from NeXT.
+ */
+
+#ifndef __byte_order_h__
+#define __byte_order_h__
+
+#include <sys/types.h>
+
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#if HAVE_WINDOWS_H
+# include <windows.h>
+#endif
+
+#ifdef __CYGWIN32__
+//# include <cygwin32/in.h>
+#endif
+#ifdef __MINGW32__
+# include <winsock.h> // include for ntohs,..
+#endif
+
+#include <config.h>
+
+/* BUGS: Assumes the endianism of target machine is either big or little
+   endian, format of floating point is IEEE and
+       sizeof (long) == 4
+       sizeof (long long) == 8
+       sizeof (long) == sizeof (float)
+       sizeof (long long) == sizeof (double)
+ */
+
+#if (__GNUC__ == 2) && (__GNUC_MINOR__ <= 6) && !defined(__attribute__)
+#  define __attribute__(x)
+#endif
+
+typedef unsigned long network_float;
+typedef unsigned long long network_double;
+
+
+/* Prototypes */
+
+static inline unsigned short
+network_short_to_host (unsigned short x) __attribute__((unused));
+static inline unsigned short
+host_short_to_network (unsigned short x) __attribute__((unused));
+static inline unsigned int
+network_int_to_host (unsigned int x) __attribute__((unused));
+static inline unsigned int
+host_int_to_network (unsigned int x) __attribute__((unused));
+static inline unsigned long
+network_long_to_host (unsigned long x) __attribute__((unused));
+static inline unsigned long
+host_long_to_network (unsigned long x) __attribute__((unused));
+static inline unsigned long long
+network_long_long_to_host (unsigned long long x) __attribute__((unused));
+static inline unsigned long long
+host_long_long_to_network (unsigned long long x) __attribute__((unused));
+static inline float
+network_float_to_host (network_float x) __attribute__((unused));
+static inline network_float
+host_float_to_network (float x) __attribute__((unused));
+static inline double
+network_double_to_host (network_double x) __attribute__((unused));
+static inline network_double
+host_double_to_network (double x) __attribute__((unused));
+
+
+/* Public entries */
+
+static inline unsigned short
+network_short_to_host (unsigned short x)
+{
+    return ntohs (x);
+}
+
+static inline unsigned short
+host_short_to_network (unsigned short x)
+{
+    return htons (x);
+}
+
+static inline unsigned int
+network_int_to_host (unsigned int x)
+{
+    return ntohl (x);
+}
+
+static inline unsigned int
+host_int_to_network (unsigned int x)
+{
+    return htonl (x);
+}
+
+static inline unsigned long
+network_long_to_host (unsigned long x)
+{
+    return ntohl (x);
+}
+
+static inline unsigned long
+host_long_to_network (unsigned long x)
+{
+    return htonl (x);
+}
+
+#if WORDS_BIGENDIAN
+static inline unsigned long long
+network_long_long_to_host (unsigned long long x)
+{
+    return x;
+}
+
+static inline unsigned long long
+host_long_long_to_network (unsigned long long x)
+{
+    return x;
+}
+
+#else /* !WORDS_BIGENDIAN */
+
+static inline unsigned long
+swap_long (unsigned long x)
+{
+    union lconv {
+       unsigned long ul;
+       unsigned char uc[4];
+    } *inp, outx;
+
+    inp = (union lconv*)&x;
+    outx.uc[0] = inp->uc[3];
+    outx.uc[1] = inp->uc[2];
+    outx.uc[2] = inp->uc[1];
+    outx.uc[3] = inp->uc[0];
+    return outx.ul;
+}
+
+static inline unsigned long long
+swap_long_long (unsigned long long x)
+{
+    union dconv {
+       unsigned long  ul[2];
+       network_double ull;
+    } *inp, outx;
+
+    inp = (union dconv*)&x;
+    outx.ul[0] = swap_long (inp->ul[1]);
+    outx.ul[1] = swap_long (inp->ul[0]);
+    return outx.ull;
+}
+
+static inline unsigned long long
+network_long_long_to_host (unsigned long long x)
+{
+    return swap_long_long (x);
+}
+
+static inline unsigned long long
+host_long_long_to_network (unsigned long long x)
+{
+    return swap_long_long (x);
+}
+
+#endif /* !WORDS_BIGENDIAN */
+
+static inline float
+network_float_to_host (network_float x)
+{
+    union fconv {
+       float number;
+       unsigned long ul;
+    };
+    unsigned long fx = network_long_to_host (x);
+
+    return ((union fconv*)&fx)->number;
+}
+
+static inline network_float
+host_float_to_network (float x)
+{
+    union fconv {
+       float number;
+       unsigned long ul;
+    };
+    return host_long_to_network (((union fconv*)&x)->ul);
+}
+
+static inline double
+network_double_to_host (network_double x)
+{
+    union dconv {
+       double number;
+       unsigned long long ull;
+    };
+    unsigned long long dx = network_long_long_to_host (x);
+
+    return ((union dconv*)&dx)->number;
+}
+
+static inline network_double
+host_double_to_network (double x)
+{
+    union dconv {
+       double number;
+       unsigned long long ull;
+    };
+    return host_long_long_to_network (((union dconv*)&x)->ull);
+}
+
+#endif /* __byte_order_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/common.h b/libFoundation/Foundation/common.h
new file mode 100644 (file)
index 0000000..ce3d509
--- /dev/null
@@ -0,0 +1,445 @@
+/* 
+   common.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+          Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+          Florin Mihaila <phil@pathcom.com>
+          Bogdan Baliuc <stark@protv.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __common_h__
+#define __common_h__
+
+#include <config.h>
+#include <Foundation/NSString.h>
+
+#if HAVE_STRING_H
+# include <string.h>
+#endif
+
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+
+#if HAVE_MEMORY_H
+# include <memory.h>
+#endif
+
+#if !HAVE_MEMCPY
+# define memcpy(d, s, n)       bcopy((s), (d), (n))
+# define memmove(d, s, n)      bcopy((s), (d), (n))
+#endif
+
+#include <ctype.h>
+
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#else
+extern void* malloc();
+extern void* calloc();
+extern void* realloc();
+extern void free();
+extern atoi();
+extern atol();
+#endif
+
+#if HAVE_LIBC_H
+# define NSObject AppleNSObject
+# include <libc.h>
+# undef NSObject
+#else
+# include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <fcntl.h>                     
+
+#if HAVE_PWD_H
+# include <pwd.h>
+#endif
+#include <stdarg.h>
+
+#if HAVE_PROCESS_H
+#include <process.h>
+#endif
+
+#ifdef __WIN32__
+#define sleep(x) Sleep(x*1000)
+#endif
+
+#include "lfmemory.h"
+
+#if (__GNUC__ == 2) && (__GNUC_MINOR__ <= 6) && !defined(__attribute__)
+#  define __attribute__(x)
+#endif
+
+
+@class NSString;
+@class NSData;
+
+#define MAYBE_UNUSED __attribute__((unused))
+
+static inline void *Malloc(int) __attribute__((unused));
+static inline void *MallocAtomic(int) __attribute__((unused));
+static inline void lfFree(void*) __attribute__((unused));
+static inline void *Calloc(int, int) __attribute__((unused));
+static inline void *CallocAtomic(int, int) __attribute__((unused));
+static inline void *Realloc(void*, int) __attribute__((unused));
+static inline int Strlen(const char*) __attribute__((unused));
+static inline char* Strdup(const char*) __attribute__((unused));
+static inline char* Strcpy (char*, const char*) __attribute__((unused));
+static inline char* Strncpy (char*, const char*, unsigned)
+     MAYBE_UNUSED;
+static inline char* Strcat (char*, const char*) __attribute__((unused));
+static inline char* Strncat (char*, const char*, unsigned)
+     MAYBE_UNUSED;
+static inline int Strcmp(const char*, const char*) __attribute__((unused));
+static inline int Strncmp(const char*, const char*, unsigned)
+     MAYBE_UNUSED;
+static inline int Atoi(const char*) __attribute__((unused));
+static inline long Atol(const char*) __attribute__((unused));
+
+static inline BOOL lf_isPlistBreakChar(unsigned char c) MAYBE_UNUSED;
+static inline NSString *lf_quoteString (const char *cString, int length)
+     MAYBE_UNUSED;
+
+
+#include <Foundation/NSObject.h>
+
+/* Windows Support */
+
+#if defined(__MINGW32__)
+#  include <windows.h>
+LF_EXPORT NSString *NSWindowsWideStringToString(LPWSTR _wstr);
+LF_EXPORT LPWSTR    NSStringToWindowsWideString(NSString *_str);
+#endif
+
+/* File reading */
+
+LF_EXPORT void *NSReadContentsOfFile(NSString *_path,
+                                  unsigned _extraCapacity,
+                                  unsigned *len);
+
+/* Non OpenStep useful things */
+
+#if LIB_FOUNDATION_BOEHM_GC || LIB_FOUNDATION_LEAK_GC
+
+LF_EXPORT void __raiseMemoryException (void* pointer, int size);
+
+
+static inline void *Malloc(int size)
+{
+    void* p = (void*)GC_MALLOC (size);
+    if(!p)
+        __raiseMemoryException (&p, size);
+    return p;
+}
+
+static inline void *MallocAtomic(int size)
+{
+    void* p = (void*)GC_MALLOC_ATOMIC (size);
+    if(!p)
+        __raiseMemoryException (&p, size);
+    return p;
+}
+
+static inline void lfFree(void* p)
+{
+    //if (p) GC_FREE(p);
+}
+
+static inline void *Calloc(int elem, int size)
+{
+    int howMuch = elem * size;
+    void* p = (void*)GC_MALLOC (howMuch);
+
+    if(!p)
+        __raiseMemoryException (&p, howMuch);
+    memset (p, 0, howMuch);
+    return p;
+}
+
+static inline void *CallocAtomic(int elem, int size)
+{
+    int howMuch = elem * size;
+    void* p = (void*)GC_MALLOC_ATOMIC (howMuch);
+
+    if(!p)
+        __raiseMemoryException (&p, howMuch);
+    memset (p, 0, howMuch);
+    return p;
+}
+
+static inline void *Realloc(void* p, int size)
+{
+    void* new_p = GC_REALLOC (p, size);
+
+    if(!new_p)
+        __raiseMemoryException (&new_p, size);
+    return new_p;
+}
+
+#else /* !LIB_FOUNDATION_BOEHM_GC || LIB_FOUNDATION_LEAK_GC */
+
+#if !WITHOUT_ZONES
+
+#include <Foundation/NSZone.h>
+
+// TODO: can't we cache the defaultZone somewhere? (or at least the class?)
+
+static inline void *Malloc(int size)
+{
+    return [[NSZone defaultZone] malloc:size];
+}
+
+static inline void *MallocAtomic(int size)
+{
+    return [[NSZone defaultZone] mallocAtomic:size];
+}
+
+static inline void lfFree(void* p)
+{
+    return [[NSZone zoneFromPointer:p] freePointer:p];
+}
+
+static inline void *Calloc(int elem, int size)
+{
+    return [[NSZone defaultZone] calloc:elem byteSize:size];
+}
+
+static inline void *CallocAtomic(int elem, int size)
+{
+    return [[NSZone defaultZone] callocAtomic:elem byteSize:size];
+}
+
+static inline void *Realloc(void* p, int size)
+{
+    return [[NSZone zoneFromPointer:p] realloc:p size:size];
+}
+
+#else
+
+static inline void *Malloc(int size)
+{
+    return objc_malloc(size);
+}
+static inline void *MallocAtomic(int size)
+{
+    return objc_malloc(size);
+}
+
+static inline void lfFree(void* p)
+{
+    if (p) objc_free(p);
+}
+
+static inline void *Calloc(int elem, int size)
+{
+    return objc_calloc(elem, size);
+}
+static inline void *CallocAtomic(int elem, int size)
+{
+    return objc_calloc(elem, size);
+}
+
+static inline void *Realloc(void* p, int size)
+{
+    return p ? objc_realloc(p, size) : objc_malloc (size);
+}
+
+#endif
+
+#endif /* !LIB_FOUNDATION_BOEHM_GC || LIB_FOUNDATION_LEAK_GC*/
+
+static inline BOOL lf_isPlistBreakChar(unsigned char c)
+{
+    if (!isalnum(c)) return YES;
+    
+    switch (c) {
+        case '_': case '@': case '#': case '$':
+        case '.': case '=': case ';': case ',':
+        case '{': case '}': case '(': case ')':
+        case '<': case '>': case '/': case '\\':
+        case '"':
+            return YES;
+            
+        default:
+            return NO;
+    }
+}
+
+static NSString *lf_quoteString (const char *cString, int length)
+{
+    unsigned char buf[length * 2 + 4];
+    register int i, j;
+
+    buf[0] = '"';
+    for (i = 0, j = 1; i < length; i++, j++) {
+#if 0
+        if ((cString[i] < 33) || (cString[i] == '"') || (cString[i] == '\\')) {
+            buf[j] = '\\'; j++;
+            buf[j] = cString[i];
+        }
+#endif
+        switch (cString[i]) {
+            case '"':
+                buf[j] = '\\'; j++;
+                buf[j] = cString[i];
+                break;
+            case '\n':
+                buf[j] = '\\'; j++;
+                buf[j] = 'n';
+                break;
+            case '\\':
+                buf[j] = '\\'; j++;
+                buf[j] = '\\';
+                break;
+            default:
+                buf[j] = cString[i];
+                break;
+        }
+    }
+    buf[j] = '"'; j++;
+    buf[j] = '\0';
+    
+    return [NSString stringWithCString:(char *)buf length:j];
+}
+
+static inline int Strlen(const char* s)
+{
+    return s ? strlen(s) : 0;
+}
+
+static inline char* Strdup(const char* s)
+{
+    return s ? strcpy(MallocAtomic(strlen(s) + 1), s) : NULL;
+}
+
+static inline char* Strcpy (char* d, const char* s)
+{
+    return s && d ? strcpy(d, s) : d;
+}
+
+static inline char* Strncpy (char* d, const char* s, unsigned size)
+{
+    return s && d ? strncpy(d, s, size) : d;
+}
+
+static inline char* Strcat (char* d, const char* s)
+{
+    return s && d ? strcat(d, s) : d;
+}
+
+static inline char* Strncat (char* d, const char* s , unsigned size)
+{
+    return s && d ? strncat(d, s , size) : d;
+}
+
+static inline int Strcmp(const char* p, const char* q)
+{
+    if(!p) {
+        if(!q)
+            return 0;
+        else return -1;
+    }
+    else {
+        if(!q)
+            return 1;
+        else return strcmp(p, q);
+    }
+}
+
+static inline int Strncmp(const char* p, const char* q, unsigned size)
+{
+    if(!p) {
+        if(!q)
+            return 0;
+        else return -1;
+    }
+    else {
+        if(!q)
+            return 1;
+        else return strncmp(p, q, size);
+    }
+}
+
+static inline int Atoi(const char* str)
+{
+    return str ? atoi(str) : 0;
+}
+
+static inline long Atol(const char *str)
+{
+    return str ? atol(str) : 0;
+}
+
+LF_EXPORT char*        Ltoa(long nr, char *str, int base);
+LF_EXPORT void vaRelease(id obj, ...);
+
+/* Hash function used by NSString */
+LF_EXPORT unsigned hashjb(const char* name, int len);
+
+LF_EXPORT NSString* Asprintf(NSString* format, ...);
+LF_EXPORT NSString* Avsprintf(NSString* format, va_list args);
+
+LF_EXPORT BOOL writeToFile(NSString* path, NSData* data, BOOL atomically);
+
+LF_EXPORT char* Tmpnam(char* s);
+
+#ifndef MAX
+#define MAX(a, b) \
+    ({typeof(a) _a = (a); typeof(b) _b = (b);     \
+       _a > _b ? _a : _b; })
+#endif
+
+#ifndef MIN
+#define MIN(a, b) \
+    ({typeof(a) _a = (a); typeof(b) _b = (b);  \
+       _a < _b ? _a : _b; })
+#endif
+
+/* varargs macros, required to be able to handle powerpc64 (eg iSeries) */
+
+/* va_list needs not be a scalar type on all archs, so to be portable
+ * one cannot use simple assignment, but must copy it. */
+
+#ifndef lfCopyVA
+#  if defined(__va_copy) || defined(__linux__)
+#    define lfCopyVA(__lvar__, __avar__) __va_copy(__lvar__, __avar__);
+#  elif VA_LIST_IS_ARRAY
+#    define lfCopyVA(__lvar__, __avar__) \
+              memcpy(__lvar__,__avar__,sizeof(va_list));
+#  else
+#    define lfCopyVA(__lvar__, __avar__) __lvar__ = __avar__;
+#  endif
+#endif
+
+#endif /* __common_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/common.m b/libFoundation/Foundation/common.m
new file mode 100644 (file)
index 0000000..0081741
--- /dev/null
@@ -0,0 +1,391 @@
+/* 
+   common.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+          Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+          Florin Mihaila <phil@pathcom.com>
+          Bogdan Baliuc <stark@protv.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/common.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSData.h>
+#include <Foundation/NSPosixFileDescriptor.h>
+#include <Foundation/NSFileManager.h>
+#include <Foundation/NSException.h>
+#include <Foundation/NSThread.h>
+#include <Foundation/NSAutoreleasePool.h>
+#include <Foundation/NSPathUtilities.h>
+
+#include "PrivateThreadData.h"
+#include "NSCalendarDateScanf.h"
+
+#include <Foundation/exceptions/GeneralExceptions.h>
+#include <extensions/PrintfFormatScanner.h>
+#include <extensions/PrintfScannerHandler.h>
+
+#include "config.h"
+
+#if HAVE_WINDOWS_H
+#  include <windows.h>
+#endif
+
+#ifndef O_BINARY
+#  if HAVE_WINDOWS_H
+#    warning defined O_BINARY
+#  endif
+#  define O_BINARY 0
+#endif
+
+#include <errno.h>
+
+/* Windows Support */
+
+#if defined(__MINGW32__)
+
+NSString *NSWindowsWideStringToString(LPWSTR _wstr)
+{
+  unsigned char cstr[256];
+  int           result;
+
+  result = WideCharToMultiByte(CP_ACP,
+                               0,
+                               _wstr,        /* the wide string */
+                               -1,           /* determine length of _wstr */
+                               cstr,         /* destination */
+                               sizeof(cstr), /* buffer size */
+                               NULL, /* insert char if char could not be conv */
+                               NULL  /* pointer to flag: couldNotBeConverted */);
+  return [NSString stringWithCString:cstr];
+}
+
+LPWSTR NSStringToWindowsWideString(NSString *_str)
+{
+  LPWSTR wstr    = NULL;
+  int    wstrlen = 0;
+  int    result  = 0;
+  LPCSTR cstr;
+  int    cstrlen = [_str cStringLength];
+
+  cstr = malloc(cstrlen + 1);
+  [_str getCString:cstr]; cstr[cstrlen] = '\0';
+  
+  // first determine required buffer size
+  wstrlen = MultiByteToWideChar(CP_ACP,      /* ANSI Code Conversion */
+                                0,           /* conversion flags     */
+                                cstr,        /* ANSI string          */
+                                cstrlen + 1, /* ANSI string length + zero byte */
+                                wstr,        /* destination          */
+                                0);          /* Shall determine required size */
+
+  // allocate buffer
+  wstr = NSZoneMalloc(NULL, sizeof(WCHAR) * (wstrlen + 1));
+  
+  result = MultiByteToWideChar(CP_ACP,      /* ANSI Code Conversion */
+                               0,           /* conversion flags     */
+                               cstr,        /* ANSI string          */
+                               cstrlen + 1, /* ANSI string length + zero byte */
+                               wstr,        /* destination          */
+                               wstrlen);    /* destination buffer size */
+  free(cstr);
+#if !LIB_FOUNDATION_BOEHM_GC
+  [NSAutoreleasedPointer autoreleasePointer:wstr];
+#endif
+  return wstr;
+}
+
+#endif
+
+/* File reading */
+
+void *NSReadContentsOfFile(NSString *_path, unsigned _extraCapacity,
+                           unsigned *len)
+{
+    unsigned char *bytes = NULL;
+#if defined(__MINGW32__)
+    HANDLE fh;
+    DWORD  sizeLow, sizeHigh;
+    DWORD  got;
+
+    if (len) *len = 0;
+    
+    fh = CreateFile([_path fileSystemRepresentation],
+                    GENERIC_READ,          /* assume read access  */
+                    FILE_SHARE_READ,       /* multiple read lock  */
+                    NULL,                  /* security attributes */
+                    OPEN_EXISTING,         /* fail if file does not exist */
+                    FILE_ATTRIBUTE_NORMAL, /* access normal file  */
+                    NULL);                 /* template file (not used)    */
+    if (fh == INVALID_HANDLE_VALUE)
+        // could not open file
+        return NULL;
+
+    sizeLow = GetFileSize(fh, &sizeHigh);
+    if ((sizeLow == 0xFFFFFFFF) && (GetLastError() != NO_ERROR)) {
+        // could not stat file
+        CloseHandle(fh);
+        return NULL;
+    }
+    NSCAssert(sizeHigh == 0, @"cannot handle 64bit filesizes yet");
+
+    bytes = NSZoneMallocAtomic(NULL, sizeLow + _extraCapacity);
+    if (!ReadFile(fh, bytes, sizeLow, &got, NULL)) {
+        if (bytes) {
+            lfFree(bytes);
+            bytes = NULL;
+        }
+    }
+    CloseHandle(fh);
+
+    if (len) *len = bytes ? sizeLow : 0;
+#else /* !mingw32 */
+    int         fd;
+    struct stat fstat_buf;
+    int         got;
+    unsigned    plen;
+    char        *path;
+    
+    if (len) *len = 0;
+    plen = [_path cStringLength];
+    path = malloc(plen + 1);
+    [_path getCString:path]; path[plen] = '\0';
+    
+    if ((fd = open(path, O_RDONLY|O_BINARY, 0)) == -1) {
+       //fprintf(stderr, "couldn't open file '%s'\n", path ? path : "<NULL>");
+        if (path) free(path);
+        return NULL;
+    }
+    
+    if (path) free(path);
+    
+    if (fstat(fd, &fstat_buf) == -1) {
+       // NSLog(@"couldn't stat fd %i file '%@'", fd, _path ? _path : nil);
+        close(fd);
+       return NULL;
+    }
+
+    bytes = NSZoneMallocAtomic(NULL, fstat_buf.st_size + _extraCapacity);
+    if (bytes) {
+       if ((got = read(fd, bytes, fstat_buf.st_size)) != fstat_buf.st_size) {
+           if (bytes) {
+               lfFree(bytes);
+               bytes = NULL;
+           }
+       }
+    }
+    close(fd);
+    
+    if (len) *len = bytes ? fstat_buf.st_size : 0;
+#endif
+    return bytes;
+}
+
+/* Non OpenStep useful things */
+
+void vaRelease(id obj, ...)
+{
+    va_list args;
+    id next_obj;
+       
+    va_start(args, obj);
+    next_obj = obj;
+    while (next_obj) {
+       RELEASE(next_obj);
+       next_obj = va_arg(args, id);
+    }
+    va_end(args);
+}
+
+BOOL writeToFile(NSString *path, NSData *data, BOOL atomically)
+{
+    const void    *bytes    = [data bytes];
+    int           len       = [data length];
+    volatile BOOL result    = YES;
+    NSString      *filename = nil;
+    
+#if defined(__MINGW32__)
+    HANDLE fh;
+    DWORD  wroteBytes;
+
+    filename = atomically ? [path stringByAppendingString:@".tmp"] : path;
+    
+    fh = CreateFile([filename fileSystemRepresentation],
+                    GENERIC_WRITE,         /* assume write access  */
+                    0,                     /* exclusive lock       */
+                    NULL,                  /* security attributes  */
+                    CREATE_ALWAYS,         /* create a new file    */
+                    FILE_ATTRIBUTE_NORMAL, /* access normal file   */
+                    NULL);                 /* template file (not used) */
+    if (fh == INVALID_HANDLE_VALUE) {
+        fprintf(stderr, "Could not create file for writing %s: %s\n",
+                [filename fileSystemRepresentation], strerror(errno));
+        return NO;
+    }
+
+    if (!WriteFile(fh, bytes, len, &wroteBytes, NULL)) {
+        fprintf(stderr,
+               "Failed to write %i bytes to %s, only wrote %li bytes\n",
+                len, [filename fileSystemRepresentation], wroteBytes);
+        CloseHandle(fh);
+        return NO;
+    }
+    CloseHandle(fh);
+#else
+    int fd;
+    
+    filename = atomically ? [path stringByAppendingString:@"~"] : path;
+    
+    fd = open([filename fileSystemRepresentation],
+              O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
+    if (fd == -1) {
+        fprintf(stderr, "Could not open file for writing %s: %s\n",
+                [filename fileSystemRepresentation], strerror(errno));
+        return NO;
+    }
+
+    if (write(fd, bytes, len) != len) {
+        fprintf(stderr, "Failed to write %i bytes to %s: %s\n",
+                len, [filename fileSystemRepresentation], strerror(errno));
+        close(fd);
+        return NO;
+    }
+    close(fd);
+#endif
+        
+    if (atomically) {
+        NSFileManager *fileManager = nil;
+        
+       fileManager = [NSFileManager defaultManager];
+
+        NS_DURING {
+            [fileManager removeFileAtPath:path handler:nil];
+            result = [fileManager movePath:filename toPath:path handler:nil];
+        }
+        NS_HANDLER {
+            fprintf(stderr, "Could not move file %s to file %s\n",
+                    [filename fileSystemRepresentation],
+                    [path fileSystemRepresentation]);
+            result = NO;
+        }
+        NS_ENDHANDLER;
+    }
+    return result;
+}
+
+char *Ltoa(long nr, char *str, int base)
+{
+    char buff[34], rest, is_negative;
+    int ptr;
+
+    ptr = 32;
+    buff[33] = '\0';
+    if(nr < 0) {
+       is_negative = 1;
+       nr = -nr;
+    }
+    else
+       is_negative = 0;
+
+    while(nr != 0) {
+       rest = nr % base;
+       if(rest > 9)
+           rest += 'A' - 10;
+       else
+           rest += '0';
+       buff[ptr--] = rest;
+       nr /= base;
+    }
+    if(ptr == 32)
+       buff[ptr--] = '0';
+    if(is_negative)
+       buff[ptr--] = '-';
+
+    Strcpy(str, &buff[ptr+1]);
+
+    return(str);
+}
+
+unsigned hashjb(const char* name, int len)
+{
+  register unsigned long hash = 0, i = 0;
+  register unsigned char ch;
+
+  for (; (ch = *name++); i ^= 1) {
+    if (i)
+      hash *= ch;
+    else
+      hash += ch;
+  }
+  hash += ((hash & 0xffff0000) >> 16);
+  hash += ((hash & 0x0000ff00) >> 8);
+  return hash & (len - 1);
+}
+
+NSString* Asprintf(NSString* format, ...)
+{
+    id string;
+    va_list ap;
+
+    va_start(ap, format);
+    string = Avsprintf(format, ap);
+    va_end(ap);
+    return string;
+}
+
+NSString* Avsprintf(NSString* format, va_list args)
+{
+    // THREADING
+    static id ofmt = nil;
+    id objectFormat, formatScanner, string;
+
+    if (ofmt) {
+        objectFormat = ofmt;
+        ofmt = nil;
+    }
+    else
+        objectFormat = [[FSObjectFormat alloc] init];
+    
+    formatScanner = [[PrintfFormatScanner alloc] init];
+
+    [formatScanner setFormatScannerHandler:objectFormat];
+    string = [formatScanner stringWithFormat:format arguments:args];
+
+    if (ofmt == nil) ofmt = objectFormat;
+    else RELEASE(objectFormat);
+    RELEASE(formatScanner);
+
+    return string;
+}
+
+/* Moved the THROW here from common.h to avoid recursion in the definition of
+   memoryExhaustedException. */
+void __raiseMemoryException (void* pointer, int size)
+{
+    [[memoryExhaustedException setPointer:&pointer memorySize:size] raise];
+}
+
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/cvtutf.c b/libFoundation/Foundation/cvtutf.c
new file mode 100644 (file)
index 0000000..c0f2b20
--- /dev/null
@@ -0,0 +1,339 @@
+/* ================================================================ */
+/*
+File:   ConvertUTF.C
+Author: Mark E. Davis
+Copyright (C) 1994 Taligent, Inc. All rights reserved.
+
+This code is copyrighted. Under the copyright laws, this code may not
+be copied, in whole or part, without prior written consent of Taligent. 
+
+Taligent grants the right to use or reprint this code as long as this
+ENTIRE copyright notice is reproduced in the code or reproduction.
+The code is provided AS-IS, AND TALIGENT DISCLAIMS ALL WARRANTIES,
+EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IN
+NO EVENT WILL TALIGENT BE LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING,
+WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS
+INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY
+LOSS) ARISING OUT OF THE USE OR INABILITY TO USE THIS CODE, EVEN
+IF TALIGENT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+BECAUSE SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF
+LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE
+LIMITATION MAY NOT APPLY TO YOU.
+
+RESTRICTED RIGHTS LEGEND: Use, duplication, or disclosure by the
+government is subject to restrictions as set forth in subparagraph
+(c)(l)(ii) of the Rights in Technical Data and Computer Software
+clause at DFARS 252.227-7013 and FAR 52.227-19.
+
+This code may be protected by one or more U.S. and International
+Patents.
+
+TRADEMARKS: Taligent and the Taligent Design Mark are registered
+trademarks of Taligent, Inc.
+*/
+/* ================================================================ */
+
+#include "cvtutf.h"
+
+/* ================================================================ */
+
+static const int halfShift             = 10;
+static const UCS4 halfBase             = 0x0010000UL;
+static const UCS4 halfMask             = 0x3FFUL;
+static const UCS4 kSurrogateHighStart  = 0xD800UL;
+static const UCS4 kSurrogateHighEnd    = 0xDBFFUL;
+static const UCS4 kSurrogateLowStart   = 0xDC00UL;
+static const UCS4 kSurrogateLowEnd     = 0xDFFFUL;
+
+/* ================================================================ */
+
+ConversionResult
+ConvertUCS4toUTF16(UCS4** sourceStart, const UCS4* sourceEnd, 
+                   UTF16** targetStart, const UTF16* targetEnd)
+{
+  ConversionResult result = ok;
+  register UCS4* source = *sourceStart;
+  register UTF16* target = *targetStart;
+  while (source < sourceEnd) {
+    register UCS4 ch;
+    if (target >= targetEnd) {
+      result = targetExhausted; break;
+    };
+    ch = *source++;
+    if (ch <= kMaximumUCS2) {
+      *target++ = ch;
+    } else if (ch > kMaximumUTF16) {
+      *target++ = kReplacementCharacter;
+    } else {
+      if (target + 1 >= targetEnd) {
+        result = targetExhausted; break;
+      };
+      ch -= halfBase;
+      *target++ = (ch >> halfShift) + kSurrogateHighStart;
+      *target++ = (ch & halfMask) + kSurrogateLowStart;
+    };
+  };
+  *sourceStart = source;
+  *targetStart = target;
+  return result;
+};
+
+/* ================================================================ */
+
+ConversionResult ConvertUTF16toUCS4(UTF16** sourceStart, UTF16* sourceEnd, 
+                                    UCS4** targetStart, const UCS4* targetEnd)
+{
+  ConversionResult result = ok;
+  register UTF16* source = *sourceStart;
+  register UCS4* target = *targetStart;
+  while (source < sourceEnd) {
+    register UCS4 ch;
+    ch = *source++;
+    if (ch >= kSurrogateHighStart &&
+        ch <= kSurrogateHighEnd &&
+        source < sourceEnd) {
+      register UCS4 ch2 = *source;
+      if (ch2 >= kSurrogateLowStart && ch2 <= kSurrogateLowEnd) {
+        ch = ((ch - kSurrogateHighStart) << halfShift)
+          + (ch2 - kSurrogateLowStart) + halfBase;
+        ++source;
+      };
+    };
+    if (target >= targetEnd) {
+      result = targetExhausted; break;
+    };
+    *target++ = ch;
+  };
+  *sourceStart = source;
+  *targetStart = target;
+  return result;
+};
+
+/* ================================================================ */
+
+static UCS4 offsetsFromUTF8[6] = {
+  0x00000000UL, 0x00003080UL, 0x000E2080UL, 
+  0x03C82080UL, 0xFA082080UL, 0x82082080UL
+};
+static char bytesFromUTF8[256] = {
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
+};
+
+static UTF8 firstByteMark[7] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC};
+
+/* ================================================================ */
+/*      This code is similar in effect to making successive calls on the
+mbtowc and wctomb routines in FSS-UTF. However, it is considerably
+different in code:
+* it is adapted to be consistent with UTF16,
+* the interface converts a whole buffer to avoid function-call overhead
+* constants have been gathered.
+* loops & conditionals have been removed as much as possible for
+efficiency, in favor of drop-through switch statements.
+*/
+
+/* ================================================================ */
+int NSConvertUTF16toUTF8(unichar             **sourceStart,
+                         const unichar       *sourceEnd, 
+                         unsigned char       **targetStart,
+                         const unsigned char *targetEnd)
+{
+  ConversionResult result = ok;
+  register UTF16* source = *sourceStart;
+  register UTF8* target = *targetStart;
+  while (source < sourceEnd) {
+    register UCS4 ch;
+    register unsigned short bytesToWrite = 0;
+    register const UCS4 byteMask = 0xBF;
+    register const UCS4 byteMark = 0x80; 
+    ch = *source++;
+    if (ch >= kSurrogateHighStart && ch <= kSurrogateHighEnd
+        && source < sourceEnd) {
+      register UCS4 ch2 = *source;
+      if (ch2 >= kSurrogateLowStart && ch2 <= kSurrogateLowEnd) {
+        ch = ((ch - kSurrogateHighStart) << halfShift)
+          + (ch2 - kSurrogateLowStart) + halfBase;
+        ++source;
+      };
+    };
+    if (ch < 0x80) {                    bytesToWrite = 1;
+    } else if (ch < 0x800) {            bytesToWrite = 2;
+    } else if (ch < 0x10000) {          bytesToWrite = 3;
+    } else if (ch < 0x200000) {         bytesToWrite = 4;
+    } else if (ch < 0x4000000) {        bytesToWrite = 5;
+    } else if (ch <= kMaximumUCS4){     bytesToWrite = 6;
+    } else {                                            bytesToWrite = 2;
+    ch = kReplacementCharacter;
+    }; /* I wish there were a smart way to avoid this conditional */
+                
+    target += bytesToWrite;
+    if (target > targetEnd) {
+      target -= bytesToWrite; result = targetExhausted; break;
+    };
+    switch (bytesToWrite) {     /* note: code falls through cases! */
+      case 6:   *--target = (ch | byteMark) & byteMask; ch >>= 6;
+      case 5:   *--target = (ch | byteMark) & byteMask; ch >>= 6;
+      case 4:   *--target = (ch | byteMark) & byteMask; ch >>= 6;
+      case 3:   *--target = (ch | byteMark) & byteMask; ch >>= 6;
+      case 2:   *--target = (ch | byteMark) & byteMask; ch >>= 6;
+      case 1:   *--target =  ch | firstByteMark[bytesToWrite];
+    };
+    target += bytesToWrite;
+  };
+  *sourceStart = source;
+  *targetStart = target;
+
+  return result;
+};
+
+/* ================================================================ */
+
+int NSConvertUTF8toUTF16(unsigned char **sourceStart, unsigned char *sourceEnd, 
+                         unichar **targetStart, const unichar *targetEnd)
+{
+  ConversionResult result = ok;
+  register UTF8  *source = *sourceStart;
+  register UTF16 *target = *targetStart;
+  
+  while (source < sourceEnd) {
+    register UCS4 ch = 0;
+    register unsigned short extraBytesToWrite = bytesFromUTF8[*source];
+
+    if (source + extraBytesToWrite > sourceEnd) {
+      result = sourceExhausted; break;
+    };
+    switch(extraBytesToWrite) { /* note: code falls through cases! */
+      case 5:   ch += *source++; ch <<= 6;
+      case 4:   ch += *source++; ch <<= 6;
+      case 3:   ch += *source++; ch <<= 6;
+      case 2:   ch += *source++; ch <<= 6;
+      case 1:   ch += *source++; ch <<= 6;
+      case 0:   ch += *source++;
+    };
+    ch -= offsetsFromUTF8[extraBytesToWrite];
+    
+    if (target >= targetEnd) {
+      result = targetExhausted; break;
+    };
+    if (ch <= kMaximumUCS2) {
+      *target++ = ch;
+    } else if (ch > kMaximumUTF16) {
+      *target++ = kReplacementCharacter;
+    } else {
+      if (target + 1 >= targetEnd) {
+        result = targetExhausted; break;
+      };
+      ch -= halfBase;
+      *target++ = (ch >> halfShift) + kSurrogateHighStart;
+      *target++ = (ch & halfMask) + kSurrogateLowStart;
+    };
+  };
+  *sourceStart = source;
+  *targetStart = target;
+  
+  return result;
+};
+
+/* ================================================================ */
+ConversionResult ConvertUCS4toUTF8 ( UCS4** sourceStart, const UCS4* sourceEnd, 
+                                     UTF8** targetStart, const UTF8* targetEnd)
+{
+  ConversionResult result = ok;
+  register UCS4* source = *sourceStart;
+  register UTF8* target = *targetStart;
+  while (source < sourceEnd) {
+    register UCS4 ch;
+    register unsigned short bytesToWrite = 0;
+    register const UCS4 byteMask = 0xBF;
+    register const UCS4 byteMark = 0x80; 
+    ch = *source++;
+    if (ch >= kSurrogateHighStart && ch <= kSurrogateHighEnd
+        && source < sourceEnd) {
+      register UCS4 ch2 = *source;
+      if (ch2 >= kSurrogateLowStart && ch2 <= kSurrogateLowEnd) {
+        ch = ((ch - kSurrogateHighStart) << halfShift)
+          + (ch2 - kSurrogateLowStart) + halfBase;
+        ++source;
+      };
+    };
+    if (ch < 0x80) {                            bytesToWrite = 1;
+    } else if (ch < 0x800) {            bytesToWrite = 2;
+    } else if (ch < 0x10000) {          bytesToWrite = 3;
+    } else if (ch < 0x200000) {         bytesToWrite = 4;
+    } else if (ch < 0x4000000) {        bytesToWrite = 5;
+    } else if (ch <= kMaximumUCS4){     bytesToWrite = 6;
+    } else {                                            bytesToWrite = 2;
+    ch = kReplacementCharacter;
+    }; /* I wish there were a smart way to avoid this conditional */
+                
+    target += bytesToWrite;
+    if (target > targetEnd) {
+      target -= bytesToWrite; result = targetExhausted; break;
+    };
+    switch (bytesToWrite) {     /* note: code falls through cases! */
+      case 6:   *--target = (ch | byteMark) & byteMask; ch >>= 6;
+      case 5:   *--target = (ch | byteMark) & byteMask; ch >>= 6;
+      case 4:   *--target = (ch | byteMark) & byteMask; ch >>= 6;
+      case 3:   *--target = (ch | byteMark) & byteMask; ch >>= 6;
+      case 2:   *--target = (ch | byteMark) & byteMask; ch >>= 6;
+      case 1:   *--target =  ch | firstByteMark[bytesToWrite];
+    };
+    target += bytesToWrite;
+  };
+  *sourceStart = source;
+  *targetStart = target;
+  return result;
+};
+
+/* ================================================================ */
+
+ConversionResult ConvertUTF8toUCS4 (UTF8** sourceStart, UTF8* sourceEnd, 
+                                    UCS4** targetStart, const UCS4* targetEnd)
+{
+  ConversionResult result = ok;
+  register UTF8* source = *sourceStart;
+  register UCS4* target = *targetStart;
+  while (source < sourceEnd) {
+    register UCS4 ch = 0;
+    register unsigned short extraBytesToWrite = bytesFromUTF8[*source];
+    if (source + extraBytesToWrite > sourceEnd) {
+      result = sourceExhausted; break;
+    };
+    switch(extraBytesToWrite) { /* note: code falls through cases! */
+      case 5:   ch += *source++; ch <<= 6;
+      case 4:   ch += *source++; ch <<= 6;
+      case 3:   ch += *source++; ch <<= 6;
+      case 2:   ch += *source++; ch <<= 6;
+      case 1:   ch += *source++; ch <<= 6;
+      case 0:   ch += *source++;
+    };
+    ch -= offsetsFromUTF8[extraBytesToWrite];
+
+    if (target >= targetEnd) {
+      result = targetExhausted; break;
+    };
+    if (ch <= kMaximumUCS2) {
+      *target++ = ch;
+    } else if (ch > kMaximumUCS4) {
+      *target++ = kReplacementCharacter;
+    } else {
+      if (target + 1 >= targetEnd) {
+        result = targetExhausted; break;
+      };
+      ch -= halfBase;
+      *target++ = (ch >> halfShift) + kSurrogateHighStart;
+      *target++ = (ch & halfMask) + kSurrogateLowStart;
+    };
+  };
+  *sourceStart = source;
+  *targetStart = target;
+  return result;
+};
diff --git a/libFoundation/Foundation/cvtutf.h b/libFoundation/Foundation/cvtutf.h
new file mode 100644 (file)
index 0000000..7325117
--- /dev/null
@@ -0,0 +1,110 @@
+/* ================================================================ */
+/*
+File:  ConvertUTF.h
+Author: Mark E. Davis
+Copyright (C) 1994 Taligent, Inc. All rights reserved.
+
+This code is copyrighted. Under the copyright laws, this code may not
+be copied, in whole or part, without prior written consent of Taligent. 
+
+Taligent grants the right to use or reprint this code as long as this
+ENTIRE copyright notice is reproduced in the code or reproduction.
+The code is provided AS-IS, AND TALIGENT DISCLAIMS ALL WARRANTIES,
+EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IN
+NO EVENT WILL TALIGENT BE LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING,
+WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS
+INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY
+LOSS) ARISING OUT OF THE USE OR INABILITY TO USE THIS CODE, EVEN
+IF TALIGENT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+BECAUSE SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF
+LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE
+LIMITATION MAY NOT APPLY TO YOU.
+
+RESTRICTED RIGHTS LEGEND: Use, duplication, or disclosure by the
+government is subject to restrictions as set forth in subparagraph
+(c)(l)(ii) of the Rights in Technical Data and Computer Software
+clause at DFARS 252.227-7013 and FAR 52.227-19.
+
+This code may be protected by one or more U.S. and International
+Patents.
+
+TRADEMARKS: Taligent and the Taligent Design Mark are registered
+trademarks of Taligent, Inc.
+*/
+/* ================================================================ */
+
+#ifndef __cvtutf_H__
+#define __cvtutf_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+// #include <types.h>
+#include <string.h>
+
+/* ================================================================ */
+/*     The following 4 definitions are compiler-specific.
+       I would use wchar_t for UCS2/UTF16, except that the C standard
+       does not guarantee that it has at least 16 bits, so wchar_t is
+       no less portable than unsigned short!
+*/
+
+typedef unsigned long  UCS4;
+typedef unsigned short UCS2;
+typedef unsigned short UTF16;
+typedef unsigned char  UTF8;
+#define unichar UTF16
+
+typedef enum {false, true} Boolean;
+
+const UCS4 kReplacementCharacter = 0x0000FFFDUL;
+const UCS4 kMaximumUCS2          = 0x0000FFFFUL;
+const UCS4 kMaximumUTF16         = 0x0010FFFFUL;
+const UCS4 kMaximumUCS4          = 0x7FFFFFFFUL;
+
+/* ================================================================ */
+/*     Each of these routines converts the text between *sourceStart and 
+sourceEnd, putting the result into the buffer between *targetStart and
+targetEnd. Note: the end pointers are *after* the last item: e.g. 
+*(sourceEnd - 1) is the last item.
+
+       The return result indicates whether the conversion was successful,
+and if not, whether the problem was in the source or target buffers.
+
+       After the conversion, *sourceStart and *targetStart are both
+updated to point to the end of last text successfully converted in
+the respective buffers.
+*/
+
+typedef enum {
+       ok,                             /* conversion successful */
+       sourceExhausted,        /* partial character in source, but hit end */
+       targetExhausted         /* insuff. room in target for conversion */
+} ConversionResult;
+
+ConversionResult ConvertUCS4toUTF16 (
+               UCS4** sourceStart, const UCS4* sourceEnd, 
+               UTF16** targetStart, const UTF16* targetEnd);
+
+ConversionResult ConvertUTF16toUCS4 (
+               UTF16** sourceStart, UTF16* sourceEnd, 
+               UCS4** targetStart, const UCS4* targetEnd);
+
+int NSConvertUTF16toUTF8(unichar             **sourceStart,
+                         const unichar       *sourceEnd, 
+                         unsigned char       **targetStart,
+                         const unsigned char *targetEnd);
+int NSConvertUTF8toUTF16(unsigned char **sourceStart, unsigned char *sourceEnd, 
+                         unichar **targetStart, const unichar *targetEnd);
+
+ConversionResult ConvertUCS4toUTF8 (
+               UCS4** sourceStart, const UCS4* sourceEnd, 
+               UTF8** targetStart, const UTF8* targetEnd);
+               
+ConversionResult ConvertUTF8toUCS4 (
+               UTF8** sourceStart, UTF8* sourceEnd, 
+               UCS4** targetStart, const UCS4* targetEnd);
+
+/* ================================================================ */
+
+#endif /* __cvtutf_H__ */
diff --git a/libFoundation/Foundation/encoding.m b/libFoundation/Foundation/encoding.m
new file mode 100644 (file)
index 0000000..255ee42
--- /dev/null
@@ -0,0 +1,565 @@
+/* Encoding of types for Objective C.
+   Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
+   Contributed by Kresten Krab Thorup
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with files
+   compiled with GCC to produce an executable, this does not cause
+   the resulting executable to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#if ((__GNUC__ == 2) && (__GNUC_MINOR__ <= 5) && !defined(__attribute__)) || NeXT_RUNTIME
+# define ROUND(V, A) \
+    A * ((V + A - 1) / A)
+#else
+# define ROUND(V, A) \
+    ({ typeof(V) __v=(V); typeof(A) __a=(A); \
+       __a*((__v+__a-1)/__a); })
+#endif
+
+#include "common.h"
+#include <extensions/objc-runtime.h>
+
+#if !defined(OBJC_FORWARDING_STACK_OFFSET) && defined(NeXT) \
+       && (defined(i386) || defined(m68k))
+# define OBJC_FORWARDING_STACK_OFFSET 8
+#endif
+
+/*
+  return the size of an object specified by type 
+*/
+
+int
+objc_sizeof_type(const char* type)
+{
+  switch(*type) {
+  case _C_ID:
+    return sizeof(id);
+    break;
+
+  case _C_CLASS:
+    return sizeof(Class);
+    break;
+
+  case _C_SEL:
+    return sizeof(SEL);
+    break;
+
+  case _C_CHR:
+    return sizeof(char);
+    break;
+    
+  case _C_UCHR:
+    return sizeof(unsigned char);
+    break;
+
+  case _C_SHT:
+    return sizeof(short);
+    break;
+
+  case _C_USHT:
+    return sizeof(unsigned short);
+    break;
+
+  case _C_INT:
+    return sizeof(int);
+    break;
+
+  case _C_UINT:
+    return sizeof(unsigned int);
+    break;
+
+  case _C_LNG:
+    return sizeof(long);
+    break;
+
+  case _C_ULNG:
+    return sizeof(unsigned long);
+    break;
+
+  case 'q':
+    return sizeof(long long);
+    break;
+
+  case 'Q':
+    return sizeof(unsigned long long);
+    break;
+
+  case _C_FLT:
+    return sizeof(float);
+    break;
+
+  case _C_DBL:
+    return sizeof(double);
+    break;
+
+  case _C_PTR:
+  case _C_ATOM:
+  case _C_CHARPTR:
+    return sizeof(char*);
+    break;
+
+  case _C_ARY_B:
+    {
+      int len = atoi(type+1);
+      while (isdigit(*++type));
+      return len*objc_aligned_size (type);
+    }
+    break; 
+
+  case _C_STRUCT_B:
+    {
+      int acc_size = 0;
+      int align;
+      while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
+      while (*type != _C_STRUCT_E)
+       {
+         align = objc_alignof_type (type);       /* padd to alignment */
+         acc_size = ROUND (acc_size, align);
+         acc_size += objc_sizeof_type (type);   /* add component size */
+         type = objc_skip_typespec (type);              /* skip component */
+       }
+      return acc_size;
+    }
+
+  case _C_UNION_B:
+    {
+      int max_size = 0;
+      while (*type != _C_UNION_E && *type++ != '=') /* do nothing */;
+      while (*type != _C_UNION_E)
+       {
+         max_size = MAX (max_size, objc_sizeof_type (type));
+         type = objc_skip_typespec (type);
+       }
+      return max_size;
+    }
+    
+  default:
+    objc_error(nil, OBJC_ERR_BAD_TYPE, "%s: unknown type %s\n",
+               __PRETTY_FUNCTION__, type);
+  }
+  return -1;
+}
+
+
+/*
+  Return the alignment of an object specified by type 
+*/
+
+int
+objc_alignof_type(const char* type)
+{
+  switch(*type) {
+  case _C_ID:
+    return __alignof__(id);
+    break;
+
+  case _C_CLASS:
+    return __alignof__(Class);
+    break;
+    
+  case _C_SEL:
+    return __alignof__(SEL);
+    break;
+
+  case _C_CHR:
+    return __alignof__(char);
+    break;
+    
+  case _C_UCHR:
+    return __alignof__(unsigned char);
+    break;
+
+  case _C_SHT:
+    return __alignof__(short);
+    break;
+
+  case _C_USHT:
+    return __alignof__(unsigned short);
+    break;
+
+  case _C_INT:
+    return __alignof__(int);
+    break;
+
+  case _C_UINT:
+    return __alignof__(unsigned int);
+    break;
+
+  case _C_LNG:
+    return __alignof__(long);
+    break;
+
+  case _C_ULNG:
+    return __alignof__(unsigned long);
+    break;
+
+  case 'q':
+    return __alignof__(long long);
+    break;
+
+  case 'Q':
+    return __alignof__(unsigned long long);
+    break;
+
+  case _C_FLT:
+    return __alignof__(float);
+    break;
+
+  case _C_DBL:
+    return __alignof__(double);
+    break;
+
+  case _C_PTR:
+  case _C_ATOM:
+  case _C_CHARPTR:
+    return __alignof__(char*);
+    break;
+
+  case _C_ARY_B:
+    while (isdigit(*++type)) /* do nothing */;
+    return objc_alignof_type (type);
+      
+  case _C_STRUCT_B:
+    {
+      struct { int x; double y; } fooalign;
+      while(*type != _C_STRUCT_E && *type++ != '=') /* do nothing */;
+      if (*type != _C_STRUCT_E)
+       return MAX (objc_alignof_type (type), __alignof__ (fooalign));
+      else
+       return __alignof__ (fooalign);
+    }
+
+  case _C_UNION_B:
+    {
+      int maxalign = 0;
+      while (*type != _C_UNION_E && *type++ != '=') /* do nothing */;
+      while (*type != _C_UNION_E)
+       {
+         maxalign = MAX (maxalign, objc_alignof_type (type));
+         type = objc_skip_typespec (type);
+       }
+      return maxalign;
+    }
+    
+  default:
+    objc_error(nil, OBJC_ERR_BAD_TYPE, "%s: unknown type %s\n",
+               __PRETTY_FUNCTION__, type);
+  }
+  return -1;
+}
+
+/*
+  The aligned size if the size rounded up to the nearest alignment.
+*/
+
+int
+objc_aligned_size (const char* type)
+{
+  int size = objc_sizeof_type (type);
+  int align = objc_alignof_type (type);
+  return ROUND (size, align);
+}
+
+/*
+  The size rounded up to the nearest integral of the wordsize, taken
+  to be the size of a void*.
+*/
+
+int 
+objc_promoted_size (const char* type)
+{
+  int size = objc_sizeof_type (type);
+  int wordsize = sizeof (void*);
+
+  return ROUND (size, wordsize);
+}
+
+/*
+  Skip type qualifiers.  These may eventually precede typespecs
+  occurring in method prototype encodings.
+*/
+
+inline const char*
+objc_skip_type_qualifiers (const char* type)
+{
+  while (*type == _C_CONST
+        || *type == _C_IN 
+        || *type == _C_INOUT
+        || *type == _C_OUT 
+        || *type == _C_BYCOPY
+        || *type == _C_ONEWAY)
+    {
+      type += 1;
+    }
+  return type;
+}
+
+  
+/*
+  Skip one typespec element.  If the typespec is prepended by type
+  qualifiers, these are skipped as well.
+*/
+
+const char* 
+objc_skip_typespec (const char* type)
+{
+  type = objc_skip_type_qualifiers (type);
+  
+  switch (*type) {
+
+  case _C_ID:
+    /* An id may be annotated by the actual type if it is known
+       with the @"ClassName" syntax */
+
+    if (*++type != '"')
+      return type;
+    else
+      {
+       while (*++type != '"') /* do nothing */;
+       return type + 1;
+      }
+
+    /* The following are one character type codes */
+  case _C_CLASS:
+  case _C_SEL:
+  case _C_CHR:
+  case _C_UCHR:
+  case _C_CHARPTR:
+  case _C_ATOM:
+  case _C_SHT:
+  case _C_USHT:
+  case _C_INT:
+  case _C_UINT:
+  case _C_LNG:
+  case _C_ULNG:
+  case 'q':
+  case 'Q':
+  case _C_FLT:
+  case _C_DBL:
+  case _C_VOID:
+  case _C_UNDEF:
+    return ++type;
+    break;
+
+  case _C_ARY_B:
+    /* skip digits, typespec and closing ']' */
+    
+    while(isdigit(*++type));
+    type = objc_skip_typespec(type);
+    if (*type == _C_ARY_E)
+      return ++type;
+    else
+      objc_error(nil, OBJC_ERR_BAD_TYPE, "bad array type %s\n", type);
+
+  case _C_STRUCT_B:
+    /* skip name, and elements until closing '}'  */
+    
+    while (*type != _C_STRUCT_E && *type++ != '=');
+    while (*type != _C_STRUCT_E) { type = objc_skip_typespec (type); }
+    return ++type;
+
+  case _C_UNION_B:
+    /* skip name, and elements until closing ')'  */
+    
+    while (*type != _C_UNION_E && *type++ != '=');
+    while (*type != _C_UNION_E) { type = objc_skip_typespec (type); }
+    return ++type;
+
+  case _C_PTR:
+    /* Just skip the following typespec */
+    
+    return objc_skip_typespec (++type);
+    
+  default:
+    objc_error(nil, OBJC_ERR_BAD_TYPE, "%s: unknown type %s\n",
+               __PRETTY_FUNCTION__, type);
+  }
+  return NULL;
+}
+
+/*
+  Skip an offset as part of a method encoding.  This is prepended by a
+  '+' if the argument is passed in registers.
+*/
+inline const char* 
+objc_skip_offset (const char* type)
+{
+  if (*type == '+') type++;
+  while(isdigit(*++type));
+  return type;
+}
+
+/*
+  Skip an argument specification of a method encoding.
+*/
+const char*
+objc_skip_argspec (const char* type)
+{
+  type = objc_skip_typespec (type);
+  type = objc_skip_offset (type);
+  return type;
+}
+
+/*
+  Return the number of arguments that the method MTH expects.
+  Note that all methods need two implicit arguments `self' and
+  `_cmd'. 
+*/
+int
+method_get_number_of_arguments (struct objc_method* mth)
+{
+  int i = 0;
+  const char* type = mth->method_types;
+  while (*type)
+    {
+      type = objc_skip_argspec (type);
+      i += 1;
+    }
+  return i - 1;
+}
+
+/*
+  Return the size of the argument block needed on the stack to invoke
+  the method MTH.  This may be zero, if all arguments are passed in
+  registers.
+*/
+
+int
+method_get_sizeof_arguments (struct objc_method* mth)
+{
+  const char* type = objc_skip_typespec (mth->method_types);
+  return atoi (type);
+}
+
+/*
+  Return a pointer to the next argument of ARGFRAME.  type points to
+  the last argument.  Typical use of this look like:
+
+  {
+    char *datum, *type; 
+    for (datum = method_get_first_argument (method, argframe, &type);
+         datum; datum = method_get_next_argument (argframe, &type))
+      {
+        unsigned flags = objc_get_type_qualifiers (type);
+        type = objc_skip_type_qualifiers (type);
+       if (*type != _C_PTR)
+          [portal encodeData: datum ofType: type];
+       else
+         {
+           if ((flags & _F_IN) == _F_IN)
+              [portal encodeData: *(char**)datum ofType: ++type];
+         }
+      }
+  }
+*/  
+
+char*
+method_get_next_argument (arglist_t argframe,
+                         const char **type)
+{
+  const char *t = objc_skip_argspec (*type);
+
+  if (*t == '\0')
+    return 0;
+
+  *type = t;
+  t = objc_skip_typespec (t);
+
+  if (*t == '+')
+    return argframe->arg_regs + atoi (++t) - OBJC_FORWARDING_STACK_OFFSET;
+  else
+    return argframe->arg_ptr + atoi (t) - OBJC_FORWARDING_STACK_OFFSET;
+}
+
+/*
+  Return a pointer to the value of the first argument of the method 
+  described in M with the given argumentframe ARGFRAME.  The type
+  is returned in TYPE.  type must be passed to successive calls of 
+  method_get_next_argument.
+*/
+char*
+method_get_first_argument (struct objc_method* m,
+                          arglist_t argframe, 
+                          const char** type)
+{
+  *type = m->method_types;
+  return method_get_next_argument (argframe, type);
+}
+
+/*
+   Return a pointer to the ARGth argument of the method
+   M from the frame ARGFRAME.  The type of the argument
+   is returned in the value-result argument TYPE 
+*/
+
+char*
+method_get_nth_argument (struct objc_method* m,
+                        arglist_t argframe, int arg, 
+                        const char **type)
+{
+  const char* t = objc_skip_argspec (m->method_types);
+
+  if (arg > method_get_number_of_arguments (m))
+    return 0;
+
+  while (arg--)
+    t = objc_skip_argspec (t);
+  
+  *type = t;
+  t = objc_skip_typespec (t);
+
+  if (*t == '+')
+    return argframe->arg_regs + atoi (++t) - OBJC_FORWARDING_STACK_OFFSET;
+  else
+    return argframe->arg_ptr + atoi (t) - OBJC_FORWARDING_STACK_OFFSET;
+}
+
+unsigned
+objc_get_type_qualifiers (const char* type)
+{
+  unsigned res = 0;
+  BOOL flag = YES;
+
+  while (flag)
+    switch (*type++)
+      {
+      case _C_CONST:  res |= _F_CONST; break;
+      case _C_IN:     res |= _F_IN; break;
+      case _C_INOUT:  res |= _F_INOUT; break;
+      case _C_OUT:    res |= _F_OUT; break;
+      case _C_BYCOPY: res |= _F_BYCOPY; break;
+      case _C_ONEWAY: res |= _F_ONEWAY; break;
+      default: flag = NO;
+    }
+
+  return res;
+}
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/err.m b/libFoundation/Foundation/err.m
new file mode 100644 (file)
index 0000000..59da9b4
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * A n t l r  S e t s / E r r o r  F i l e  H e a d e r
+ *
+ * Generated from: NSStringPropList.g
+ *
+ * Terence Parr, Russell Quong, Will Cohen, and Hank Dietz: 1989-1995
+ * Parr Research Corporation
+ * with Purdue University Electrical Engineering
+ * With AHPCRC, University of Minnesota
+ * ANTLR Version 1.33
+ */
+
+#include <stdio.h>
+#define ANTLR_VERSION  133
+#define zzparser NSStringPropertyListParser
+#include "remap.h"
+
+#include <objc/objc.h>
+
+#ifndef __Attrib_def__
+#define __Attrib_def__
+typedef id Attrib;
+#endif
+
+#define USER_ZZSYN
+#define zzcr_attr NSStringPropertyListParser_zzcr_attr
+void zzcr_attr(Attrib* attr, int token, char* text);
+#define zzSET_SIZE 8
+#include "antlr.h"
+#include "tokens.h"
+#include "dlgdef.h"
+#include "err.h"
+
+ANTLRChar *NSStringPropertyListParser_zztokens[36]={
+       /* 00 */        "Invalid",
+       /* 01 */        "Eof",
+       /* 02 */        "/\\*",
+       /* 03 */        "~[\\n]*\\*/",
+       /* 04 */        "\\n",
+       /* 05 */        "~[\\n]+",
+       /* 06 */        "\\n",
+       /* 07 */        "~[\\n]+",
+       /* 08 */        "STRING",
+       /* 09 */        "\\",
+       /* 10 */        "\\a",
+       /* 11 */        "\\b",
+       /* 12 */        "\\f",
+       /* 13 */        "\\n",
+       /* 14 */        "\\t",
+       /* 15 */        "\\v",
+       /* 16 */        "\\~[]",
+       /* 17 */        "~[\"\\]+",
+       /* 18 */        "DATA",
+       /* 19 */        "[\\ \\t]+",
+       /* 20 */        "([0-9a-fA-F])+",
+       /* 21 */        "~[]",
+       /* 22 */        "[\\t\\ ]+",
+       /* 23 */        "\\n",
+       /* 24 */        "/\\*",
+       /* 25 */        "//",
+       /* 26 */        "\\*/",
+       /* 27 */        "\"",
+       /* 28 */        "\\<",
+       /* 29 */        "\\(",
+       /* 30 */        ",",
+       /* 31 */        "\\)",
+       /* 32 */        "\\{",
+       /* 33 */        "=",
+       /* 34 */        ";",
+       /* 35 */        "\\}"
+};
+SetWordType zzerr1[8] = {0x0,0x1,0x4,0x20, 0x1,0x0,0x0,0x0};
+SetWordType setwd1[36] = {0x0,0xd3,0x0,0x0,0x0,0x0,0x0,
+       0x0,0x7e,0x0,0x0,0x0,0x0,0x0,0x0,
+       0x0,0x0,0x0,0x7e,0x0,0x0,0x0,0x0,
+       0x0,0x0,0x0,0x0,0x0,0x0,0x7e,0x5a,
+       0x52,0x7e,0x52,0x52,0x52};
diff --git a/libFoundation/Foundation/exceptions/EncodingFormatExceptions.h b/libFoundation/Foundation/exceptions/EncodingFormatExceptions.h
new file mode 100644 (file)
index 0000000..ff604c1
--- /dev/null
@@ -0,0 +1,41 @@
+/* 
+   EncodingFormatExceptions.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __EncodingFormatExceptions_h__
+#define __EncodingFormatExceptions_h__
+
+#include <Foundation/exceptions/FoundationException.h>
+
+@interface DifferentKindOfEncodingFormatsException : NSException
+- initForClass:(Class)expected andClass:(Class)got;
+@end
+
+#endif /* __EncodingFormatExceptions_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/exceptions/EncodingFormatExceptions.m b/libFoundation/Foundation/exceptions/EncodingFormatExceptions.m
new file mode 100644 (file)
index 0000000..c7aab01
--- /dev/null
@@ -0,0 +1,47 @@
+/* 
+   EncodingFormatExceptions.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSString.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/exceptions/EncodingFormatExceptions.h>
+
+@implementation DifferentKindOfEncodingFormatsException
+- initForClass:(Class)expected andClass:(Class)got
+{
+    [self initWithName:NSInvalidArgumentException
+           reason:@"Invalid encoding format class"
+           userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
+                                   [expected description], @"expected",
+                                   [got description], @"got",
+                                   nil]];
+    return self;
+}
+@end /* DifferentKindOfEncodingFormatsException */
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/exceptions/FoundationException.h b/libFoundation/Foundation/exceptions/FoundationException.h
new file mode 100644 (file)
index 0000000..c1cd891
--- /dev/null
@@ -0,0 +1,45 @@
+/* 
+   FoundationException.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __FoundationException_h__
+#define __FoundationException_h__
+
+#include <Foundation/NSException.h>
+
+#ifndef __FoundationException_definition__
+#define __FoundationException_definition__
+
+@interface FoundationException : NSException
+@end
+
+#endif /* __FoundationException_definition__ */
+
+#endif /* __FoundationException_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/exceptions/FoundationException.m b/libFoundation/Foundation/exceptions/FoundationException.m
new file mode 100644 (file)
index 0000000..363aa27
--- /dev/null
@@ -0,0 +1,35 @@
+/* 
+   FoundationException.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <extensions/exceptions/FoundationException.h>
+
+@implementation FoundationException
+@end
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/exceptions/FoundationExceptions.h b/libFoundation/Foundation/exceptions/FoundationExceptions.h
new file mode 100644 (file)
index 0000000..7ea2813
--- /dev/null
@@ -0,0 +1,41 @@
+/* 
+   FoundationExceptions.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __FoundationExceptions_h__
+#define __FoundationExceptions_h__
+
+#include <Foundation/exceptions/FoundationException.h>
+#include <Foundation/exceptions/GeneralExceptions.h>
+#include <Foundation/exceptions/NSValueExceptions.h>
+#include <Foundation/exceptions/StringExceptions.h>
+#include <Foundation/exceptions/NSCoderExceptions.h>
+
+#endif /* __FoundationExceptions_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/exceptions/GeneralExceptions.h b/libFoundation/Foundation/exceptions/GeneralExceptions.h
new file mode 100644 (file)
index 0000000..3c1c81b
--- /dev/null
@@ -0,0 +1,119 @@
+/* 
+   GeneralExceptions.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __GeneralExceptions_h__
+#define __GeneralExceptions_h__
+
+#include <extensions/support.h>
+#include <extensions/exceptions/FoundationException.h>
+
+@class NSString;
+
+#if LIB_FOUNDATION_LIBRARY
+
+@class MemoryExhaustedException;
+
+extern MemoryExhaustedException* memoryExhaustedException;
+
+@interface MemoryExhaustedException : FoundationException
+{
+    void** pointer;
+    unsigned size;
+}
+- setPointer:(void**)pointer memorySize:(unsigned)size;
+@end
+
+
+@interface MemoryDeallocationException : FoundationException
+{
+    void** pointer;
+    unsigned size;
+}
+- setPointer:(void**)pointer memorySize:(unsigned)size;
+@end
+
+
+@interface MemoryCopyException : FoundationException
+@end
+
+#endif /* LIB_FOUNDATION_LIBRARY */
+
+@interface FileNotFoundException : FoundationException
+- initWithFilename:(NSString*)f;
+- (NSString*)filename;
+@end
+
+
+@interface SyntaxErrorException : FoundationException
+@end
+
+
+@interface UnknownTypeException : NSException
+- initForType:(const char*)type;
+@end
+
+
+@interface UnknownClassException : NSException
+- setClassName:(NSString*)className;
+@end
+
+
+@interface ObjcRuntimeException : FoundationException
+@end
+
+
+@interface InternalInconsistencyException : NSException
+@end
+
+
+@interface InvalidArgumentException : NSException
+- initWithReason:(NSString*)aReason;
+@end
+
+
+@interface IndexOutOfRangeException : FoundationException
+- initForSize:(int)size index:(int)pos;
+@end
+
+
+@interface RangeException : IndexOutOfRangeException
+- initWithReason:(NSString*)aReason size:(int)size index:(int)index;
+@end
+
+
+@interface InvalidUseOfMethodException : NSException
+@end
+
+@interface PosixFileOperationException : NSException
+@end
+
+
+#endif /* __GeneralExceptions_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/exceptions/GeneralExceptions.m b/libFoundation/Foundation/exceptions/GeneralExceptions.m
new file mode 100644 (file)
index 0000000..188ba25
--- /dev/null
@@ -0,0 +1,267 @@
+/* 
+   GeneralExceptions.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <Foundation/NSString.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSValue.h>
+
+#include <extensions/NSException.h>
+#include <extensions/exceptions/GeneralExceptions.h>
+
+#if GNUSTEP_BASE_LIBRARY || LIBOBJECTS_LIBRARY
+# define name_ivar     e_name
+# define reason_ivar   e_reason
+# define userInfo_ivar e_info
+#else
+# define name_ivar     name
+# define reason_ivar   reason
+# define userInfo_ivar userInfo
+#endif
+
+#if LIB_FOUNDATION_LIBRARY
+@implementation MemoryExhaustedException
+
+MemoryExhaustedException* memoryExhaustedException = nil;
+
+- __init
+{
+    name = [NSMallocException retain];
+    reason = @"Memory exhausted";
+    return self;
+}
+
++ (void)initialize
+{
+    memoryExhaustedException = [NSAllocateObject(self, 0, NULL) init];
+}
+
++ (id)alloc
+{
+    return memoryExhaustedException;
+}
+
++ (id)allocWithZone:(NSZone*)zone
+{
+    return memoryExhaustedException;
+}
+
+- (void)release
+{
+    pointer = NULL;
+    size = 0;
+}
+
+- (id)init
+{
+    return self;
+}
+
+- setPointer:(void**)_pointer memorySize:(unsigned)_size
+{
+    pointer = _pointer;
+    size = _size;
+    return self;
+}
+
+@end /* MemoryExhaustedException */
+
+
+@implementation MemoryDeallocationException
+
+- setPointer:(void**)_pointer memorySize:(unsigned)_size
+{
+    pointer = _pointer;
+    size = _size;
+    name = NSMallocException;
+    reason = @"Deallocation error";
+    return self;
+}
+
+@end  /* MemoryDeallocationException */
+
+
+@implementation MemoryCopyException
+@end
+
+#endif /* LIB_FOUNDATION_LIBRARY */
+
+
+@implementation FileNotFoundException
+- initWithFilename:(NSString*)f
+{
+    id aux =  @"filename";
+    id message = [@"File not found: " stringByAppendingString:f];
+
+    self = [self initWithName:@"FileNotFoundException"
+       reason:message
+       userInfo:[NSDictionary dictionaryWithObjectsAndKeys:f, aux, nil]];
+    return self;
+}
+
+- (NSString*)filename
+{
+    return [[self userInfo] objectForKey:@"filename"];
+}
+@end /* FileNotFoundException */
+
+
+@implementation AssertException
+- init
+{
+    self = [self initWithName:NSInternalInconsistencyException
+                   reason:nil userInfo:nil];
+    return self;
+}
+@end /* AssertException */
+
+
+@implementation SyntaxErrorException
+- init
+{
+    self = [self initWithName:@"Syntax error" reason:nil userInfo:nil];
+    return self;
+}
+- initWithReason:(NSString*)aReason
+{
+    self = [self initWithName:@"Syntax error" reason:aReason userInfo:nil];
+    return self;
+}
+@end /* SyntaxErrorException */
+
+
+@implementation UnknownTypeException
+- initForType:(const char*)type
+{
+    self = [self initWithName:NSInvalidArgumentException
+                   reason:@"Unknown Objective-C type encoding"
+                   userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
+                           [NSString stringWithCString:type], @"type",
+                           nil]];
+    return self;
+}
+@end /* UnknownTypeException */
+
+
+@implementation UnknownClassException
+- setClassName:(NSString*)className
+{
+    self = [[self setName:NSInvalidArgumentException]
+               initWithFormat:@"Unknown Objective-C class '%@'", className];
+    return self;
+}
+@end /* UnknownClassException */
+
+
+@implementation ObjcRuntimeException
+@end /* ObjcRuntimeException */
+
+
+@implementation InternalInconsistencyException
+- init
+{
+    self = [self initWithName:@"Internal inconsistency exception" reason:nil userInfo:nil];
+    return self;
+}
+@end /* InternalInconsistencyException */
+
+
+@implementation InvalidArgumentException
+- init
+{
+    self = [self initWithName:NSInvalidArgumentException reason:nil userInfo:nil];
+    return self;
+}
+- initWithReason:(NSString*)aReason
+{
+    self = [self initWithName:NSInvalidArgumentException 
+           reason:aReason userInfo:nil];
+    return self;
+}
+@end /* InvalidArgumentException */
+
+
+@implementation IndexOutOfRangeException
+- init
+{
+    self = [self initWithName:@"Index out of range"
+                   reason:nil userInfo:nil];
+    return self;
+}
+
+- initForSize:(int)size index:(int)index
+{
+    id keys[] = { @"size", @"index" };
+    id values[] = { [NSNumber numberWithInt:size],
+                   [NSNumber numberWithInt:index] };
+    self = [self initWithName:@"Index out of range"
+           reason:nil
+           userInfo:[NSDictionary dictionaryWithObjects:values
+                                   forKeys:keys
+                                   count:2]];
+    return self;
+}
+
+@end /* IndexOutOfRangeException */
+
+
+@implementation RangeException
+- init
+{
+    self = [self initWithName:NSRangeException reason:nil userInfo:nil];
+    return self;
+}
+
+- initWithReason:(NSString*)aReason size:(int)size index:(int)index
+{
+    id keys[] = { @"size", @"index" };
+    id values[] = { [NSNumber numberWithInt:size],
+                   [NSNumber numberWithInt:index] };
+    self = [self initWithName:@"Index out of range"
+           reason:aReason
+           userInfo:[NSDictionary dictionaryWithObjects:values
+                                   forKeys:keys
+                                   count:2]];
+    return self;
+}
+@end /* RangeException */
+
+
+@implementation InvalidUseOfMethodException
+@end
+
+@implementation PosixFileOperationException : NSException
+- (NSString*)name
+{
+    return @"NSPosixFileOperationException";
+}
+@end
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/exceptions/NSCoderExceptions.h b/libFoundation/Foundation/exceptions/NSCoderExceptions.h
new file mode 100644 (file)
index 0000000..1dbb85f
--- /dev/null
@@ -0,0 +1,71 @@
+/* 
+   NSCoderExceptions.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSCoderExceptions_h__
+#define __NSCoderExceptions_h__
+
+#include <extensions/exceptions/FoundationException.h>
+
+@class NSString;
+
+@interface NSCoderException : FoundationException
+@end
+
+@interface InvalidSignatureForCoderException : NSCoderException
+@end
+
+@interface DifferentKindOfCodersException : NSCoderException
+- initForClassName:(NSString*)class1 andClassName:(NSString*)class2;
+@end
+
+@interface CoderHasAlreadyWrittenRootObjectException : NSCoderException
+@end
+
+@interface RootObjectHasNotBeenWrittenException : NSCoderException
+@end
+
+@interface UnexpectedTypeException : NSCoderException
+{
+    NSString* expected;
+    NSString* got;
+}
++ allocForExpected:(NSString*)expected andGot:(NSString*)got;
++ allocForExpectedSize:(int)expected andGotSize:(int)got;
+@end
+
+@interface ReadUnknownTagException : NSCoderException
+{
+    char tag;
+}
+- initForTag:(char)tag;
+@end
+
+#endif /* __NSCoderExceptions_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/exceptions/NSCoderExceptions.m b/libFoundation/Foundation/exceptions/NSCoderExceptions.m
new file mode 100644 (file)
index 0000000..60da5e8
--- /dev/null
@@ -0,0 +1,133 @@
+/* 
+   NSCoderExceptions.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSString.h>
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSValue.h>
+#include <extensions/exceptions/NSCoderExceptions.h>
+
+
+@implementation NSCoderException
+@end /* NSCoderExceptions */
+
+
+@implementation InvalidSignatureForCoderException
+- init
+{
+    self = [self initWithName:NSInvalidArgumentException
+           reason:@"Invalid signature for unarchiver's data: "
+                   @"data written by an unknown archiver type"
+           userInfo:nil];
+    return self;
+}
+@end /* InvalidSignatureForCoder */
+
+
+@implementation DifferentKindOfCodersException
+- initForClassName:(NSString*)class1 andClassName:(NSString*)class2
+{
+    self = [self initWithName:NSInvalidArgumentException
+           reason:@"Invalid coder signature"
+           userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
+                                       class1, @"first class",
+                                       class2, @"second class", nil]];
+    return self;
+}
+@end /* DifferentKindOfCodersException */
+
+
+@implementation CoderHasAlreadyWrittenRootObjectException
+- init
+{
+    self = [self initWithName:NSInvalidArgumentException
+           reason:@"Coder has already written root object"
+           userInfo:nil];
+    return self;
+}
+@end /* CoderHasAlreadyWrittenRootObjectException */
+
+
+@implementation RootObjectHasNotBeenWrittenException
+- init
+{
+    self = [self initWithName:NSInvalidArgumentException
+           reason:@"Root object has not been written before"
+           userInfo:nil];
+    return self;
+}
+@end /* RootObjectHasNotBeenWrittenException */
+
+@implementation UnexpectedTypeException
++ allocForExpected:(NSString*)_expected andGot:(NSString*)_got
+{
+    UnexpectedTypeException* exception = [self alloc];
+    exception->expected = _expected;
+    exception->got = _got;
+
+    exception = [exception initWithName:NSInvalidArgumentException
+           reason:@"Different type was written in archive"
+           userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
+                                   exception->expected, @"expected to read",
+                                   exception->got, @"got from archive", nil]];
+
+    return exception;
+}
+
++ allocForExpectedSize:(int)_expected andGotSize:(int)_got
+{
+    UnexpectedTypeException* exception = [self alloc];
+    exception->expected = [[NSNumber numberWithInt:_expected] stringValue];
+    exception->got = [[NSNumber numberWithInt:_got] stringValue];
+
+    exception = [exception initWithName:NSInvalidArgumentException
+           reason:@"Different number of elements was written in archive"
+           userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
+                               exception->expected, @"expected to read",
+                               exception->got, @"got from archive", nil]];
+
+    return exception;
+}
+@end /* UnexpectedTypeException */
+
+
+@implementation ReadUnknownTagException
+- initForTag:(char)_tag
+{
+    tag = _tag;
+    self = [self initWithName:NSInvalidArgumentException
+           reason:@"Invalid tag read from archive"
+           userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
+                       [[NSNumber numberWithChar:tag] stringValue], @"tag",
+                       nil]];
+    return self;
+}
+@end /* ReadUnknownTagException */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/exceptions/NSFileHandleExceptions.h b/libFoundation/Foundation/exceptions/NSFileHandleExceptions.h
new file mode 100644 (file)
index 0000000..40b23dc
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+   NSFileHandleExceptions.h
+
+   Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@net-community.com>
+   Date: June 1997
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+#ifndef __NSFileHandleExceptions_h__
+#define __NSFileHandleExceptions_h__
+
+#include <extensions/exceptions/FoundationException.h>
+
+@class NSString;
+
+@interface NSFileHandleException : FoundationException
+- initWithFileHandle:(id)fileHandle operation:(NSString*)operation;
+@end
+
+@interface NSFileHandleOperationException : NSFileHandleException
+- initWithFileHandle:(id)fileHandle operation:(NSString*)operation;
+@end
+
+@interface NSFileHandleUnknownTypeException : NSFileHandleException
+- initWithFileHandle:(id)fileHandle;
+@end
+
+#endif /* __NSFileHandleExceptions_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/exceptions/NSFileHandleExceptions.m b/libFoundation/Foundation/exceptions/NSFileHandleExceptions.m
new file mode 100644 (file)
index 0000000..1b221fc
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+   NSFileHandleExceptions.m
+
+   Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@net-community.com>
+   Date: June 1997
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSDictionary.h>
+#include "NSFileHandleExceptions.h"
+
+@implementation NSFileHandleException
+- initWithFileHandle:(id)fileHandle operation:(NSString*)operation
+{
+    NSString* _reason = [NSString stringWithFormat:@"An error occured on "
+                         @"NSFileHandle object %@. %@",
+                         fileHandle, operation];
+
+    self = [self initWithName:@"NSFileHandleException"
+                 reason:_reason
+                 userInfo:nil];
+    return self;
+}
+@end /* NSFileHandleException */
+
+
+@implementation NSFileHandleOperationException
+- initWithFileHandle:(id)fileHandle operation:(NSString*)operation
+{
+    NSString* _reason = [NSString stringWithFormat:@"An operation error "
+                           @"occured on NSFileHandle object %@. %@",
+                           fileHandle, operation];
+
+    self = [self initWithName:@"NSFileHandleOperationException"
+                 reason:_reason
+                 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
+                               fileHandle, @"NSFileHandle",
+                               nil]];
+    return self;
+}
+@end /* NSFileHandleOperationException */
+
+
+@implementation NSFileHandleUnknownTypeException
+- initWithFileHandle:(id)fileHandle
+{
+    NSString* _reason = [NSString stringWithFormat:@"NSFileHandle object "
+                           @"has no associated type %@", fileHandle];
+
+    self = [self initWithName:@"NSFileHandleOperationException"
+                 reason:_reason
+                 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
+                               fileHandle, @"NSFileHandle",
+                               nil]];
+    return self;
+}
+@end /* NSFileHandleUnknownTypeException */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/exceptions/NSInvocationExceptions.h b/libFoundation/Foundation/exceptions/NSInvocationExceptions.h
new file mode 100644 (file)
index 0000000..f585588
--- /dev/null
@@ -0,0 +1,60 @@
+/* 
+   NSInvocationExceptions.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSInvocationExceptions_h__
+#define __NSInvocationExceptions_h__
+
+#include <Foundation/exceptions/FoundationException.h>
+
+@interface NSInvocationException : FoundationException
+@end
+
+@interface NullTargetException : NSInvocationException
+@end
+
+@interface NullSelectorException : NSInvocationException
+@end
+
+@interface InvalidMethodSignatureException : NSInvocationException
+@end
+
+@interface FrameIsNotSetupException : NSInvocationException
+@end
+
+@interface CouldntGetTypeForSelector : NSInvocationException
+- initForSelector:(SEL)selector;
+@end
+
+@interface TypesDontMatchException : NSInvocationException
+- initWithTypes:(const char*)t1 :(const char*)t2;
+@end
+
+#endif /* __NSInvocationExceptions_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/exceptions/NSInvocationExceptions.m b/libFoundation/Foundation/exceptions/NSInvocationExceptions.m
new file mode 100644 (file)
index 0000000..56bb5c3
--- /dev/null
@@ -0,0 +1,104 @@
+/* 
+   NSInvocationExceptions.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSString.h>
+#include <Foundation/exceptions/NSInvocationExceptions.h>
+
+@implementation NSInvocationException
+@end /* NSInvocationException */
+
+
+@implementation NullTargetException
+- init
+{
+    [self initWithName:NSInvalidArgumentException
+           reason:@"Target for NSInvocation must not be the nil object"
+           userInfo:nil];
+    return self;
+}
+@end /* NullTargetException */
+
+
+@implementation NullSelectorException
+- init
+{
+    [self initWithName:NSInvalidArgumentException
+           reason:@"Selector for NSInvocation must not be the NULL selector"
+           userInfo:nil];
+    return self;
+}
+@end /* NullSelectorException */
+
+
+@implementation InvalidMethodSignatureException
+- init
+{
+    [self initWithName:NSInvalidArgumentException
+       reason:@"NSMethodSignature must not be nil to perform the operation"
+       userInfo:nil];
+    return self;
+}
+@end /* InvalidMethodSignatureException */
+
+
+@implementation FrameIsNotSetupException
+- init
+{
+    [self initWithName:NSInvalidArgumentException
+       reason:@"Frame must be previously set up before invoking the method"
+       userInfo:nil];
+    return self;
+}
+@end /* FrameIsNotSetupException */
+
+
+@implementation CouldntGetTypeForSelector
+- initForSelector:(SEL)selector
+{
+    reason = [NSString stringWithFormat:@"Couldn't get type for selector %s",
+                                   [NSStringFromSelector(selector) cString]];
+    [self initWithName:NSInvalidArgumentException
+                   reason:reason userInfo:nil];
+    return self;
+}
+@end /* CouldntGetTypeForSelector */
+
+
+@implementation TypesDontMatchException
+- initWithTypes:(const char*)t1 :(const char*)t2
+{
+       reason = [NSString stringWithFormat:@"Types of selector and method "
+                           @"signature don't match: '%s' and '%s'", t1, t2];
+       [self initWithName:NSInvalidArgumentException
+                       reason:reason userInfo:nil];
+       return self;
+}
+@end
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/exceptions/NSValueExceptions.h b/libFoundation/Foundation/exceptions/NSValueExceptions.h
new file mode 100644 (file)
index 0000000..7b1de5e
--- /dev/null
@@ -0,0 +1,48 @@
+/* 
+   NSValueExceptions.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __NSValueExceptions_h__
+#define __NSValueExceptions_h__
+
+#include <Foundation/exceptions/FoundationException.h>
+
+@class NSString;
+
+@interface NSValueException : FoundationException
+@end
+
+@interface NSNumberException : NSValueException
+@end
+
+@interface NSValueDoesNotContainAnObject : NSValueException
+@end
+
+#endif /* __NSValueExceptions_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/exceptions/NSValueExceptions.m b/libFoundation/Foundation/exceptions/NSValueExceptions.m
new file mode 100644 (file)
index 0000000..365b192
--- /dev/null
@@ -0,0 +1,53 @@
+/* 
+   NSValueExceptions.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSString.h>
+#include <Foundation/exceptions/NSValueExceptions.h>
+
+@implementation NSValueException
+- init
+{
+    return [self initWithName:@"NSValue exception" reason:nil userInfo:nil];
+}
+@end /* NSValueException */
+
+
+@implementation NSNumberException
+@end
+
+@implementation NSValueDoesNotContainAnObject
+- init
+{
+    [self initWithName:@"NSValue does not contain an object"
+                   reason:nil userInfo:nil];
+    return self;
+}
+@end /* NSValueDoesNotContainAnObject */
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/exceptions/StringExceptions.h b/libFoundation/Foundation/exceptions/StringExceptions.h
new file mode 100644 (file)
index 0000000..65e3e3f
--- /dev/null
@@ -0,0 +1,43 @@
+/* 
+   StringExceptions.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __StringExceptions_h__
+#define __StringExceptions_h__
+
+#include <Foundation/exceptions/GeneralExceptions.h>
+
+@interface StringException : FoundationException
+@end
+
+@interface StringBoundsErrorException : IndexOutOfRangeException
+@end
+
+#endif /* __StringExceptions_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/exceptions/StringExceptions.m b/libFoundation/Foundation/exceptions/StringExceptions.m
new file mode 100644 (file)
index 0000000..4eeffb9
--- /dev/null
@@ -0,0 +1,45 @@
+/* 
+   StringExceptions.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSString.h>
+#include <Foundation/exceptions/StringExceptions.h>
+
+@implementation StringException
+@end
+
+NSString* NSStringBoundsError = @"Index out of range in string";
+
+@implementation StringBoundsErrorException
+- init
+{
+    return [self initWithName:NSStringBoundsError reason:nil userInfo:nil];
+}
+@end
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/fhs.make b/libFoundation/Foundation/fhs.make
new file mode 100644 (file)
index 0000000..688d2f4
--- /dev/null
@@ -0,0 +1,57 @@
+#  fhs.make
+#
+#  Copyright (C) 2004 Helge Hess.
+#  All rights reserved.
+#
+#  Author: Helge Hess <helge.hess@opengroupware.org>
+#  Date: Ausgust 2004
+#
+#  This file is part of libFoundation.
+#
+#  Permission to use, copy, modify, and distribute this software and its
+#  documentation for any purpose and without fee is hereby granted, provided
+#  that the above copyright notice appear in all copies and that both that
+#  copyright notice and this permission notice appear in supporting
+#  documentation.
+#
+#  We disclaim all warranties with regard to this software, including all
+#  implied warranties of merchantability and fitness, in no event shall
+#  we be liable for any special, indirect or consequential damages or any
+#  damages whatsoever resulting from loss of use, data or profits, whether in
+#  an action of contract, negligence or other tortious action, arising out of
+#  or in connection with the use or performance of this software.
+#
+
+# FHS support (this is a hack and is going to be done by gstep-make!)
+
+ifneq ($(FHS_INSTALL_ROOT),)
+
+FHS_INCLUDE_DIR=$(FHS_INSTALL_ROOT)/include/
+FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib/
+
+fhs-header-dirs ::
+       $(MKDIRS) $(FHS_INCLUDE_DIR)
+       $(MKDIRS) $(FHS_INCLUDE_DIR)/Foundation
+       $(MKDIRS) $(FHS_INCLUDE_DIR)/Foundation/exceptions
+       $(MKDIRS) $(FHS_INCLUDE_DIR)/extensions
+
+move-headers-to-fhs :: fhs-header-dirs
+       @echo "moving headers to $(FHS_INCLUDE_DIR) .."
+       mv $(DIR_FD)/Foundation/*.h $(FHS_INCLUDE_DIR)/Foundation/
+       mv $(DIR_FD)/Foundation/exceptions/*.h \
+          $(FHS_INCLUDE_DIR)/Foundation/exceptions/
+       mv $(DIR_FD)/extensions/*.h $(FHS_INCLUDE_DIR)/extensions/
+       mv $(DIR_FD)/$(CTO)/*.h $(FHS_INCLUDE_DIR)
+
+NONFHS_LIBDIR="$(GNUSTEP_LIBRARIES)/$(GNUSTEP_TARGET_LDIR)/"
+NONFHS_LIBNAME="$(LIBRARY_NAME)$(LIBRARY_NAME_SUFFIX)$(SHARED_LIBEXT)"
+
+move-libs-to-fhs :: 
+       @echo "moving libs to $(FHS_LIB_DIR) .."
+       mv $(NONFHS_LIBDIR)/$(NONFHS_LIBNAME)* $(FHS_LIB_DIR)/
+
+move-to-fhs :: move-headers-to-fhs move-libs-to-fhs
+
+after-install :: move-to-fhs
+
+endif
diff --git a/libFoundation/Foundation/lfmemory.h.in b/libFoundation/Foundation/lfmemory.h.in
new file mode 100644 (file)
index 0000000..ebd8588
--- /dev/null
@@ -0,0 +1,171 @@
+/* 
+   lfmemory.h
+
+   Copyright (C) 1999 Helge Hess and MDlink online service center GmbH.
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+/*
+   This file defines various wrapper macros around the reference counting
+   methods of NSObject.
+   It also includes the appropriate garbage collector header files if the
+   GC support is enabled
+*/
+
+#ifndef __libFoundation_lfmemory_H__
+#define __libFoundation_lfmemory_H__
+
+#include <stdio.h>
+#include <objc/objc.h>
+#include <objc/objc-api.h>
+#include <Foundation/NSObject.h>
+
+@class NSAutoreleasePool;
+
+/* Define it if we use the Boehm's garbage collector */
+#undef WITH_GC
+
+extern void NSIncrementExtraRefCount(id anObject);
+extern BOOL NSDecrementExtraRefCountWasZero(id anObject);
+extern unsigned NSExtraRefCount(id anObject);
+extern unsigned NSAutoreleaseCountForObject(id object);
+
+/*
+ * When an object is deallocated, its class pointer points to the FREED_OBJECT
+ * class.
+ */
+
+@interface FREED_OBJECT
+{
+@public
+  Class isa;
+  Class oldIsa;
+}
+@end
+
+/*
+ * Reference counting can be done in two ways:
+ *  (1) increasing the size of NSObject by allocating a "hidden" int
+ *      before the pointer. This has the disadvantage that the pointers
+ *      returned by malloc differ from those kept by the program, making
+ *      the use of NeXT's MallocDebug program unusable :-)
+ *  (2) keeping a global hash with object pointers as keys and reference
+ *      counts as values.
+ *
+ * This mecanisms are controlled by one compile time defines and one 
+ * environment variable as follows:
+ *  OBJECT_REFCOUNT    (define)
+ *     1                       => mecanism is controlled by hash
+ *     0                       => mechanism is controlled by extra ref-count
+ *     *                       => mecanism controlled by environment variable
+ *  OBJECT_REFCOUNT (environment variable)
+ *     defined         => mecanism is controlled by hash
+ *     undefined       => mechanism is controlled by extra ref-count
+ *
+ */
+
+/*
+ * OBJ2PTR(p) : id object --> real allocated pointer used by Malloc/Free
+ * PTR2HSH(p) : id object --> pointer kept as key in hashtable
+ */
+
+#define OBJ2PTR(p) ((struct RefObjectLayout*)((char*)p - @STRUCT_ALIGNMENT@))
+#define PTR2HSH(p) ((void*)((char*)p - @STRUCT_ALIGNMENT@))
+
+struct RefObjectLayout {
+    unsigned   ref_count;      /*  <---- Malloc/Free pointer */
+    Class      class_pointer __attribute__ ((aligned (@STRUCT_ALIGNMENT@)));
+                               /*  <---- id pointer  */
+    char       extra[0];
+};
+
+struct HashObjectLayout {
+    Class      class_pointer;  /*  <---- id pointer == Malloc/Free pointer */
+    char       extra[0];
+};
+
+#if LIB_FOUNDATION_BOEHM_GC
+#  include <@GC_INCLUDE_DIR@gc.h>
+#  include <@GC_INCLUDE_DIR@gc_typed.h>
+
+#  ifndef ASSIGN
+#    define ASSIGN(object, value) (object = value)
+#  endif
+#  ifndef ASSIGNCOPY
+#    define ASSIGNCOPY(object, value) (object = [value copy])
+#  endif
+#  ifndef RETAIN
+#    define RETAIN(object) ((id)object)
+#  endif
+#  ifndef RELEASE
+#    define RELEASE(object)
+#  endif
+#  ifndef AUTORELEASE
+#    define AUTORELEASE(object) ((id)object)
+#  endif
+#  ifndef DESTROY
+#    define DESTROY(object) (object = nil)
+#  endif
+
+#  if !defined(CREATE_AUTORELEASE_POOL)
+#    define CREATE_AUTORELEASE_POOL(pool)
+#  endif
+
+#else /* !LIB_FOUNDATION_BOEHM_GC */
+
+#  ifndef ASSIGN
+#    define ASSIGN(object, value) \
+       ({id __object = (id)object;    \
+         id __value = (id)value;      \
+         if (__value != __object) { if (__value) [__value retain]; \
+          if (__object) [__object release]; \
+          object = __value;}})
+#  endif
+#  ifndef ASSIGNCOPY
+#    define ASSIGNCOPY(object, value) \
+       ({id __object = (id)object;    \
+         id __value = (id)value;      \
+         if (__value != __object) { if (__value) __value = [__value copy];   \
+          if (__object) [__object release]; \
+          object = __value;}})
+#  endif
+
+#  ifndef RETAIN
+#    define RETAIN(object)      [object retain]
+#  endif
+#  ifndef RELEASE
+#    define RELEASE(object)     [object release]
+#  endif
+#  ifndef AUTORELEASE
+#    define AUTORELEASE(object) [object autorelease]
+#  endif
+#  ifndef DESTROY
+#    define DESTROY(_object_) \
+        ({if (_object_) { id _tmp_=_object_; _object_=nil; [_tmp_ release]; }})
+#  endif
+
+#  ifndef CREATE_AUTORELEASE_POOL
+#    define CREATE_AUTORELEASE_POOL(pool) \
+              id pool = [[NSAutoreleasePool alloc] init]
+#  endif
+
+#endif /* !LIB_FOUNDATION_BOEHM_GC */
+
+#endif /* __libFoundation_lfmemory_H__ */
diff --git a/libFoundation/Foundation/libFoundation.def b/libFoundation/Foundation/libFoundation.def
new file mode 100644 (file)
index 0000000..d02fc40
--- /dev/null
@@ -0,0 +1,243 @@
+
+EXPORTS
+       __objc_class_name_DefaultEnumScannerHandler;
+       __objc_class_name_DefaultScannerHandler;
+       __objc_class_name_FREED_OBJECT;
+       __objc_class_name_FSObjectFormat;
+       __objc_class_name_FormatScanner;
+       __objc_class_name_GCArray;
+       __objc_class_name_GCDictionary;
+       __objc_class_name_GCDoubleLinkedList;
+       __objc_class_name_GCMutableArray;
+       __objc_class_name_GCMutableDictionary;
+       __objc_class_name_GCObject;
+       __objc_class_name_GarbageCollector;
+       __objc_class_name_NS8BitString;
+       __objc_class_name_NSAccount;
+       __objc_class_name_NSAllocDebugZone;
+       __objc_class_name_NSArchiver;
+       __objc_class_name_NSArray;
+       __objc_class_name_NSAssertionHandler;
+       __objc_class_name_NSAutoreleasePool;
+       __objc_class_name_NSAutoreleasedPointer;
+       __objc_class_name_NSBitmapCharacterSet;
+       __objc_class_name_NSBoolNumber;
+       __objc_class_name_NSBundle;
+       __objc_class_name_NSCalendarDate;
+       __objc_class_name_NSCalendarDateScanf;
+       __objc_class_name_NSCalendarDateScannerHandler;
+       __objc_class_name_NSCharNumber;
+       __objc_class_name_NSCharacterSet;
+       __objc_class_name_NSCoder;
+       __objc_class_name_NSConcreteArray;
+       __objc_class_name_NSConcreteData;
+       __objc_class_name_NSConcreteDataRange;
+       __objc_class_name_NSConcreteDate;
+       __objc_class_name_NSConcreteEmptyArray;
+       __objc_class_name_NSConcreteEmptyDictionary;
+       __objc_class_name_NSConcreteFileHandle;
+       __objc_class_name_NSConcreteMutableArray;
+       __objc_class_name_NSConcreteMutableData;
+       __objc_class_name_NSConcreteMutableDictionary;
+       __objc_class_name_NSConcreteMutableSet;
+       __objc_class_name_NSConcreteNotification;
+       __objc_class_name_NSConcreteObjCValue;
+       __objc_class_name_NSConcretePipe;
+       __objc_class_name_NSConcreteScanner;
+       __objc_class_name_NSConcreteSet;
+       __objc_class_name_NSConcreteSingleObjectArray;
+       __objc_class_name_NSConcreteSingleObjectDictionary;
+       __objc_class_name_NSConcreteSmallDictionary;
+       __objc_class_name_NSConcreteTimeZone;
+       __objc_class_name_NSConcreteTimeZoneDetail;
+       __objc_class_name_NSConcreteTimeZoneFile;
+       __objc_class_name_NSConcreteValue;
+#      __objc_class_name_NSConcreteWindowsTask;
+       __objc_class_name_NSConditionLock;
+       __objc_class_name_NSCountedSet;
+       __objc_class_name_NSData;
+       __objc_class_name_NSDate;
+       __objc_class_name_NSDateFormatter;
+       __objc_class_name_NSDefaultZone;
+       __objc_class_name_NSDictionary;
+       __objc_class_name_NSDirectoryEnumerator;
+       __objc_class_name_NSDistributedLock;
+       __objc_class_name_NSDoubleNumber;
+       __objc_class_name_NSEnumerator;
+       __objc_class_name_NSException;
+       __objc_class_name_NSFileHandle;
+       __objc_class_name_NSFileManager;
+       __objc_class_name_NSFloatNumber;
+       __objc_class_name_NSFormatter;
+       __objc_class_name_NSFrameInvocation;
+       __objc_class_name_NSGroupAccount;
+       __objc_class_name_NSHost;
+       __objc_class_name_NSInline8BitString;
+       __objc_class_name_NSIntNumber;
+       __objc_class_name_NSInvocation;
+       __objc_class_name_NSLock;
+       __objc_class_name_NSLongLongNumber;
+       __objc_class_name_NSLongNumber;
+       __objc_class_name_NSMappedData;
+       __objc_class_name_NSMethodSignature;
+       __objc_class_name_NSMutable8BitString;
+       __objc_class_name_NSMutableArray;
+       __objc_class_name_NSMutableBitmapCharacterSet;
+       __objc_class_name_NSMutableCharacterSet;
+       __objc_class_name_NSMutableData;
+       __objc_class_name_NSMutableDictionary;
+       __objc_class_name_NSMutableSet;
+       __objc_class_name_NSMutableSimple8BitString;
+       __objc_class_name_NSMutableString;
+       __objc_class_name_NSMutableTemporaryString;
+       __objc_class_name_NSNonOwned8BitString;
+       __objc_class_name_NSNonOwnedOpen8BitString;
+       __objc_class_name_NSNonretainedObjectValue;
+       __objc_class_name_NSNotification;
+       __objc_class_name_NSNotificationCenter ;
+       __objc_class_name_NSNotificationListItem;
+       __objc_class_name_NSNotificationObjectRegister;
+       __objc_class_name_NSNotificationObserverRegister;
+       __objc_class_name_NSNotificationQueue;
+        __objc_class_name_NSNull;
+       __objc_class_name_NSNullDeviceFileHandle;
+       __objc_class_name_NSNumber;
+       __objc_class_name_NSNumberFormatter;
+       __objc_class_name_NSObject;
+       __objc_class_name_NSObject;
+       __objc_class_name_NSObjectInvocation;
+       __objc_class_name_NSOwned8BitString;
+       __objc_class_name_NSOwnedOpen8BitString;
+       __objc_class_name_NSPipe;
+       __objc_class_name_NSPointValue;
+       __objc_class_name_NSPointerValue;
+       __objc_class_name_NSPort;
+       __objc_class_name_NSPortMessage;
+       __objc_class_name_NSPortNameServer;
+       __objc_class_name_NSPosixFileDescriptor;
+       __objc_class_name_NSProcessInfo;
+       __objc_class_name_NSProxy;
+       __objc_class_name_NSRange8BitString;
+       __objc_class_name_NSRangeCharacterSet;
+       __objc_class_name_NSRectValue;
+       __objc_class_name_NSRecursiveLock;
+       __objc_class_name_NSRunLoop;
+       __objc_class_name_NSRunLoopActionHolder;
+       __objc_class_name_NSRunLoopFileObjectInfo;
+       __objc_class_name_NSRunLoopInputManager;
+       __objc_class_name_NSRunLoopTimerInfo;
+       __objc_class_name_NSScanner;
+       __objc_class_name_NSSet;
+       __objc_class_name_NSSharedUserDefaults;
+       __objc_class_name_NSShortNumber;
+       __objc_class_name_NSSizeValue;
+       __objc_class_name_NSString;
+       __objc_class_name_NSStringCharacterSet;
+       __objc_class_name_NSTask;
+       __objc_class_name_NSTemporaryNumber;
+       __objc_class_name_NSTemporaryString;
+       __objc_class_name_NSThread;
+       __objc_class_name_NSTimeZone;
+       __objc_class_name_NSTimeZoneDetail;
+       __objc_class_name_NSTimeZoneRule;
+       __objc_class_name_NSTimeZoneTransitionDate;
+       __objc_class_name_NSTimeZoneTransitionRule;
+       __objc_class_name_NSTimer;
+       __objc_class_name_NSUCharNumber;
+       __objc_class_name_NSUIntNumber;
+       __objc_class_name_NSULongLongNumber;
+       __objc_class_name_NSULongNumber;
+       __objc_class_name_NSUShortNumber;
+       __objc_class_name_NSUnarchiver;
+       __objc_class_name_NSUndoManager;
+       __objc_class_name_NSUserAccount;
+       __objc_class_name_NSUserDefaults;
+       __objc_class_name_NSValue;
+       __objc_class_name_NSZone;
+       __objc_class_name_NXConstantString;
+       __objc_class_name_PrintfEnumScannerHandler;
+       __objc_class_name_PrintfFormatScanner;
+       __objc_class_name_PrintfScannerHandler;
+       __objc_class_name_PrivateThreadData;
+       __objc_class_name_StackZone;
+       __objc_class_name_UnixSignalHandler;
+       __objc_class_name_UnixSignalHandlerList;
+       __objc_class_name_UnixSignalHandlerListItem;
+       __objc_class_name__GCDictionaryKeyEnumerator;
+       __objc_class_name__NSArrayEnumerator ;
+       __objc_class_name__NSConcreteSetEnumerator;
+       __objc_class_name__NSConcreteSingleObjectDictionaryKeyEnumerator;
+       __objc_class_name__NSConcreteSmallDictionaryKeyEnumerator;
+       __objc_class_name__NSDictionaryObjectEnumerator;
+       __objc_class_name__NSObjectDelayedExecutionHolder;
+       __objc_class_name___DummyGCObject;
+       __objc_class_name___KeyValueDescription;
+       __objc_class_name_InvalidArgumentException;
+       __objc_class_name_IndexOutOfRangeException;
+       __objc_class_name_RangeException;
+       __objc_class_name_SyntaxErrorException;
+       __objc_class_name_InternalInconsistencyException;
+       NSLog;
+       _NSAddHandler;
+       _NSRemoveHandler;
+       NSAllMapTableKeys;
+       NSAllocateObject;
+       NSClassFromString;
+       NSCountHashTable;
+       NSCountMapTable;
+       NSCreateHashTable;
+       NSCreateMapTable;
+       NSCreateMapTableWithZone;
+       NSDecrementExtraRefCountWasZero;
+       NSEnumerateHashTable;
+       NSEnumerateMapTable;
+       NSExtraRefCount;
+       NSFileModificationDate;
+       NSFileSize;
+       NSFreeHashTable;
+       NSFreeMapTable;
+       NSHashGet;
+       NSHashInsert;
+       NSHashRemove;
+       NSInconsistentArchiveException;
+       NSIncrementExtraRefCount;
+       NSIntMapKeyCallBacks;
+       NSIntMapValueCallBacks;
+       NSInternalInconsistencyException;
+       NSInvalidArgumentException;
+       NSMapGet;
+       NSMapInsert;
+       NSMapRemove;
+       NSNextHashEnumeratorItem;
+       NSNextMapEnumeratorPair;
+       NSNonOwnedPointerHashCallBacks;
+       NSNonOwnedPointerMapKeyCallBacks;
+       NSNonOwnedPointerMapValueCallBacks;
+       NSNonRetainedObjectMapKeyCallBacks;
+       NSNonRetainedObjectMapValueCallBacks;
+       NSObjectHashCallBacks;
+       NSObjectMapKeyCallBacks;
+       NSObjectMapValueCallBacks;
+       NSResetHashTable;
+       NSResetMapTable;
+       NSSelectorFromString;
+       NSStringFromClass;
+       NSStringFromRange;
+       NSStringFromSelector;
+       NSWillBecomeMultiThreadedNotification;
+       NSThreadWillExitNotification;
+       NSDefaultRunLoopMode
+       NSConnectionReplyMode
+       NSFileObjectBecameActiveNotificationName
+       NSTaskDidTerminateNotification
+       __NSComparePointers;
+       __NSDescribePointers;
+       __NSHashPointer;
+       __NSReleaseObjects;
+       __NSRetainObjects;
+       __autoreleaseEnableCheck;
+       class_add_behavior;
+;
+;      __objc_class_name_DummyNXConstantString;
+;      __objc_class_name_NSDistributedNotificationCenter;
+;      __objc_class_name_NSConcreteUnixTask;
diff --git a/libFoundation/Foundation/libFoundation.make.in b/libFoundation/Foundation/libFoundation.make.in
new file mode 100644 (file)
index 0000000..d38369a
--- /dev/null
@@ -0,0 +1,92 @@
+#  libFoundation.make.in
+#
+#  Copyright (C) 1995, 1996, 1997, 1998 Ovidiu Predescu and Mircea Oancea.
+#  All rights reserved.
+#
+#  Author: Ovidiu Predescu <ovidiu@net-community.com>
+#  Date: February 1998
+#
+#  This file is part of libFoundation.
+#
+#  Permission to use, copy, modify, and distribute this software and its
+#  documentation for any purpose and without fee is hereby granted, provided
+#  that the above copyright notice appear in all copies and that both that
+#  copyright notice and this permission notice appear in supporting
+#  documentation.
+#
+#  We disclaim all warranties with regard to this software, including all
+#  implied warranties of merchantability and fitness, in no event shall
+#  we be liable for any special, indirect or consequential damages or any
+#  damages whatsoever resulting from loss of use, data or profits, whether in
+#  an action of contract, negligence or other tortious action, arising out of
+#  or in connection with the use or performance of this software.
+#
+
+ifeq ($(FOUNDATION_LIB),fd)
+
+FND_DEFINE  = -DLIB_FOUNDATION_LIBRARY=1 -DFD_WITH_GSMAKE=1 -DGNUSTEP=1
+FND_LDFLAGS =
+FND_LIBS    = -lFoundation
+
+GNUSTEP_DEFINE = -DGNUSTEP=1 -DWITH_GSTEP_MAKE=1
+
+SUMMARY_VERSION = $(GNUSTEP_MAKE_MAJOR_VERSION).$(GNUSTEP_MAKE_MINOR_VERSION)
+
+# All versions but the ones listed look for headers in xxx/Library/Headers
+ifneq ($(SUMMARY_VERSION),1.3)
+  ifneq ($(SUMMARY_VERSION),1.4)
+    ifneq ($(SUMMARY_VERSION),1.5)
+      ifneq ($(SUMMARY_VERSION),1.6)
+LIBFOUNDATION_HEADER_TARGET_FLAG = \
+  -I$(GNUSTEP_SYSTEM_ROOT)/Library/Headers/libFoundation/$(GNUSTEP_TARGET_CPU)/$(GNUSTEP_TARGET_OS)/$(OBJC_RUNTIME)
+      endif
+    endif
+  endif
+endif
+
+# Old versions (the ones listead above) look for headers in xxx/Library/Headers
+ifeq ($(LIBFOUNDATION_HEADER_TARGET_FLAG),)
+LIBFOUNDATION_HEADER_TARGET_FLAG = \
+  -I$(GNUSTEP_SYSTEM_ROOT)/Headers/libFoundation/$(GNUSTEP_TARGET_CPU)/$(GNUSTEP_TARGET_OS)/$(OBJC_RUNTIME)
+endif
+
+AUXILIARY_CPPFLAGS += $(LIBFOUNDATION_HEADER_TARGET_FLAG)
+
+# If gc=yes was passed and libFoundation was compiled with Boehm's
+# GC support, use the appropriate libraries
+
+ifeq ($(gc), yes)
+  ifeq ($(LIBFOUNDATION_WITH_GC), yes)
+    OBJC_LIBS = -lobjc $(LIBFOUNDATION_GC_LIBRARY)
+    ifeq ($(leak), yes)
+      AUXILIARY_CPPFLAGS += -DLIB_FOUNDATION_LEAK_GC=1
+    else
+      AUXILIARY_CPPFLAGS += -DLIB_FOUNDATION_BOEHM_GC=1
+    endif
+  endif
+endif
+
+ifeq ($(LIBFOUNDATION_MAKE),)
+  LIBFOUNDATION_MAKE = yes
+
+  # If libFoundation is built with support for Boehm's garbage collector we
+  # should pass in addition to GC library to linker.
+
+  ifeq ($(gc), yes)
+    LIBFOUNDATION_WITH_GC = yes
+  else
+    LIBFOUNDATION_WITH_GC = no
+  endif
+  # LIBFOUNDATION_WITH_GC = @WITH_GC@
+
+  GC_LIB = @GC_LIB@
+
+  ifeq ($(LIBFOUNDATION_WITH_GC), yes)
+    ifneq ($(GC_LIB),)
+      LIBFOUNDATION_GC_LIBRARY          = -l$(GC_LIB)
+      LIBRARIES_FOUNDATION_DEPENDS_UPON = -l$(GC_LIB)
+    endif # GC_LIB != ""
+  endif # LIBFOUNDATION_WITH_GC
+endif # LIBFOUNDATION_MAKE!=yes
+
+endif # ($(FOUNDATION_LIB),fd)
diff --git a/libFoundation/Foundation/load.m b/libFoundation/Foundation/load.m
new file mode 100644 (file)
index 0000000..985d963
--- /dev/null
@@ -0,0 +1,175 @@
+/* 
+   load.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <config.h>
+#include <stdio.h>
+#include <objc/objc-api.h>
+#include "lfmemory.h" /* necessary when used with GC */
+
+#if defined(NeXT) && defined(NeXT_RUNTIME)
+#  include <streams/streams.h>
+#elif defined(__ELF__) || defined (__svr4__)
+#  include <dlfcn.h>
+#elif defined(LOADHP)
+#  include <dl.h>
+#elif defined(__WIN32__)
+#  include <windows.h>
+#endif
+
+int objc_load_module(char* name, void (*callback)(Class, Category*))
+{
+
+#if defined(NeXT) && defined(NeXT_RUNTIME)
+
+    /*
+     * NeXT NeXTStep 3.3 with next objc-runtime
+     */
+    
+    int ok;
+    NXStream* stream;
+    char* files[] = {name, NULL};
+    int objc_loadModules(
+       char**, NXStream*, void (*callback)(Class, Category*), void*, void*);
+    
+    stream = NXOpenFile(fileno(stderr), NX_WRITEONLY);
+
+    ok = objc_loadModules(files, stream, callback, NULL, NULL);
+
+    NXClose(stream);
+    
+    return !ok;
+
+#elif defined(__ELF__) || defined (__svr4__)
+
+    /*
+     * ELF system
+     */
+
+    void* handle;
+    void (*old_objc_load_callback)(Class, Category*);
+    
+    
+    old_objc_load_callback = _objc_load_callback;
+    _objc_load_callback = callback;
+
+#if defined(__OpenBSD__)
+    handle = dlopen(name, DL_LAZY);
+#else
+    handle = dlopen(name, RTLD_NOW | RTLD_GLOBAL);
+#endif
+
+    _objc_load_callback = old_objc_load_callback;
+
+    if (!handle) {
+       fprintf(stderr, "dynamic load (dlopen) error:\n%s\n", dlerror());
+       return 0;
+    }
+
+    return 1;
+
+#elif defined(LOADHP)
+
+    /*
+     * HP SHL LOAD system
+     */
+
+    shl_t handle;
+    int* ctorlist;
+
+    void (*old_objc_load_callback)(Class, Category*);
+    
+    
+    old_objc_load_callback = _objc_load_callback;
+    _objc_load_callback = callback;
+
+    handle = shl_load(name, BIND_IMMEDIATE | BIND_VERBOSE, 0);
+
+    if (!handle) {
+       fprintf(stderr, "dynamic load (shl_load) error:\n");
+       return 0;
+    }
+
+    if (!shl_findsym(&handle, "__CTOR_LIST__", TYPE_UNDEFINED, &ctorlist)) {
+       void (**ctor)(void) = (void*)ctorlist;
+       int ccount;
+
+       ccount = (int)(**ctor);
+       ctor++;
+       while (ccount--) {
+           (**ctor)();
+           ctor++;
+       }
+    }
+    else {
+       fprintf(stderr, "cannot find modules' ctor list\n");
+       return 0;
+    }
+
+    _objc_load_callback = old_objc_load_callback;
+    return 1;
+
+#elif defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN32__)
+
+    /*
+     * WIN32 system
+     */
+
+    HINSTANCE handle;
+    void (*old_objc_load_callback)(Class, Category*);
+    
+    
+    old_objc_load_callback = _objc_load_callback;
+    _objc_load_callback = callback;
+
+    handle = LoadLibraryEx(name, 0, 0);
+
+    _objc_load_callback = old_objc_load_callback;
+
+    if (!handle) {
+       fprintf(stderr, "dynamic load (LoadLibraryEx) error on '%s':\n%ld\n",
+               name, GetLastError());
+       return 0;
+    }
+
+    return 1;
+
+#else
+
+    /*
+     * Non NeXT, Non ELF system
+     */
+
+#warning Dynamic loading not supported!
+
+    fprintf(stderr, "dynamic code loading is not supported\n");
+    return 0;
+
+#endif
+}
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/Foundation/misc.m b/libFoundation/Foundation/misc.m
new file mode 100644 (file)
index 0000000..311d629
--- /dev/null
@@ -0,0 +1,161 @@
+/* GNU Objective C Runtime Miscellaneous 
+   Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+Author: Kresten Krab Thorup
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+GNU CC is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with files compiled with
+   GCC to produce an executable, this does not cause the resulting executable
+   to be covered by the GNU General Public License. This exception does not
+   however invalidate any other reasons why the executable file might be
+   covered by the GNU General Public License.  */
+
+#include <stdlib.h>
+#include <Foundation/common.h>
+#include <extensions/objc-runtime.h>
+
+/*
+** Hook functions for memory allocation and disposal.
+** This makes it easy to substitute garbage collection systems
+** such as Boehm's GC by assigning these function pointers
+** to the GC's allocation routines.  By default these point
+** to the ANSI standard malloc, realloc, free, etc.
+**
+** Users should call the normal objc routines above for
+** memory allocation and disposal within their programs.
+*/
+void *(*_objc_malloc)(size_t) = malloc;
+void *(*_objc_atomic_malloc)(size_t) = malloc;
+void *(*_objc_valloc)(size_t) = malloc;
+void *(*_objc_realloc)(void *, size_t) = realloc;
+void *(*_objc_calloc)(size_t, size_t) = calloc;
+void (*_objc_free)(void *) = free;
+
+/*
+** Error handler function
+** NULL so that default is to just print to stderr
+*/
+static objc_error_handler _objc_error_handler = NULL;
+
+/* Trigger an objc error */
+void
+objc_error(id object, int code, const char* fmt, ...)
+{
+  va_list ap;
+
+  va_start(ap, fmt);
+  objc_verror(object, code, fmt, ap);
+  va_end(ap);
+}
+
+/* Trigger an objc error */
+void
+objc_verror(id object, int code, const char* fmt, va_list ap)
+{
+  BOOL result = NO;
+
+  /* Call the error handler if its there
+     Otherwise print to stderr */
+  if (_objc_error_handler)
+    result = (*_objc_error_handler)(object, code, fmt, ap);
+  else
+    vfprintf (stderr, fmt, ap);
+
+  /* Continue if the error handler says its ok
+     Otherwise abort the program */
+  if (result)
+    return;
+  else
+    abort();
+}
+
+/* Set the error handler */
+objc_error_handler
+objc_set_error_handler(objc_error_handler func)
+{
+  objc_error_handler temp = _objc_error_handler;
+  _objc_error_handler = func;
+  return temp;
+}
+
+/*
+** Standard functions for memory allocation and disposal.
+** Users should use these functions in their ObjC programs so
+** that they work properly with garbage collectors as well as
+** can take advantage of the exception/error handling available.
+*/
+
+void *
+objc_malloc(size_t size)
+{
+  void* res = (void*) (*_objc_malloc)(size);
+  if(!res)
+    objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
+  return res;
+}
+
+void *
+objc_atomic_malloc(size_t size)
+{
+  void* res = (void*) (*_objc_atomic_malloc)(size);
+  if(!res)
+    objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
+  return res;
+}
+
+void *
+objc_valloc(size_t size)
+{
+  void* res = (void*) (*_objc_valloc)(size);
+  if(!res)
+    objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
+  return res;
+}
+
+void *
+objc_realloc(void *mem, size_t size)
+{
+  void* res = (void*) (*_objc_realloc)(mem, size);
+  if(!res)
+    objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
+  return res;
+}
+
+void *
+objc_calloc(size_t nelem, size_t size)
+{
+  void* res = (void*) (*_objc_calloc)(nelem, size);
+  if(!res)
+    objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
+  return res;
+}
+
+void
+objc_free(void *mem)
+{
+  (*_objc_free)(mem);
+}
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/objc-runtime.m b/libFoundation/Foundation/objc-runtime.m
new file mode 100644 (file)
index 0000000..8ed733a
--- /dev/null
@@ -0,0 +1,132 @@
+/* 
+   objc-runtime.m
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSString.h>
+
+#include "common.h"
+#include <extensions/NSException.h>
+#include <extensions/objc-runtime.h>
+
+#if GNU_RUNTIME
+#include <objc/sarray.h>
+
+
+LF_EXPORT void class_add_methods(Class class, struct objc_method_list* mlist)
+{
+#if libobjc_ISDLL
+    extern __declspec(dllimport) void *__objc_uninstalled_dtable;
+#else
+    extern void *__objc_uninstalled_dtable;
+#endif
+    int i;
+    
+    NSCAssert(mlist->method_next == NULL, @"mlist must not be linked");
+    /* Insert the new method list in the methods linked list. */
+    mlist->method_next = class->methods;
+    class->methods = mlist;
+
+    if(class->dtable != __objc_uninstalled_dtable) {
+       /* Insert each method imp in the class dtable. */
+       for(i = 0; i < mlist->method_count; i++) {
+           struct objc_method* method = &(mlist->method_list[i]);
+           sarray_at_put_safe (class->dtable,
+                               (sidx)method->method_name->sel_id,
+                               method->method_imp);
+       }
+    }
+}
+
+#endif /* GNU_RUNTIME */
+
+
+#if NeXT_RUNTIME
+
+id nil_method(id receiver, SEL op, ...)
+{
+    return receiver;
+}
+
+id next_objc_msg_sendv(id object, SEL op, void* frame)
+{
+  arglist_t  argFrame = __builtin_apply_args();
+  Method     *m       = class_get_instance_method(object->class_pointer, op);
+  const char *type;
+  void       *result;
+
+  argFrame->arg_ptr = frame;
+  *((id*)method_get_first_argument (m, argFrame, &type)) = object;
+  *((SEL*)method_get_next_argument (argFrame, &type)) = op;
+  result = __builtin_apply((apply_t)m->method_imp, 
+                          argFrame,
+                          method_get_sizeof_arguments (m));
+
+#if !defined(BROKEN_BUILTIN_APPLY) && defined(i386)
+    /* Special hack to avoid pushing the poped float value back to the fp
+       stack on i386 machines. This happens with NeXT runtime and 2.7.2
+       compiler. If the result value is floating point don't call
+       __builtin_return anymore. */
+    if(*m->method_types == _C_FLT || *m->method_types == _C_DBL) {
+       long double value = *(long double*)(((char*)result) + 8);
+       asm("fld %0" : : "f" (value));
+    }
+    else
+#endif
+  __builtin_return(result);
+}
+
+/* Returns YES iff t1 and t2 have same method types, but we ignore
+   the argframe layout */
+BOOL
+sel_types_match (const char* t1, const char* t2)
+{
+  if (!t1 || !t2)
+    return NO;
+  while (*t1 && *t2)
+    {
+      if (*t1 == '+') t1++;
+      if (*t2 == '+') t2++;
+      while (isdigit(*t1)) t1++;
+      while (isdigit(*t2)) t2++;
+      /* xxx Remove these next two lines when qualifiers are put in
+        all selectors, not just Protocol selectors. */
+      t1 = objc_skip_type_qualifiers(t1);
+      t2 = objc_skip_type_qualifiers(t2);
+      if (!*t1 && !*t2)
+       return YES;
+      if (*t1 != *t2)
+       return NO;
+      t1++;
+      t2++;
+    }
+  return NO;
+}
+
+#endif /* NeXT_RUNTIME */
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/realpath.m b/libFoundation/Foundation/realpath.m
new file mode 100644 (file)
index 0000000..cad6571
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * realpath.c -- canonicalize pathname by removing symlinks
+ * Copyright (C) 1993 Rick Sladkey <jrs@world.std.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library Public License for more details.
+ */
+
+/* Modified function name & some ifdefs to compile under this hierarchy */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <errno.h>
+
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>                 /* for S_IFLNK */
+#endif
+
+#ifdef HAVE_LIBC_H
+# include <libc.h>
+#else
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+
+#ifdef _POSIX_VERSION
+#include <limits.h>                    /* for PATH_MAX */
+#else
+# if HAVE_SYS_PARAM_H
+# include <sys/param.h>                        /* for MAXPATHLEN */
+# endif
+#endif
+
+#ifndef PATH_MAX
+#if defined(_POSIX_VERSION) && defined(_POSIX_PATH_MAX)
+#define PATH_MAX _POSIX_PATH_MAX
+#else
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 1024
+#endif
+#endif
+#endif
+
+#define MAX_READLINKS 32
+
+/* this is the same as realpath() but renamed to avoid linkink problems */
+
+char *resolve_symlinks_in_path(const char *path, char *resolved_path)
+{
+       char copy_path[PATH_MAX];
+       char *new_path = resolved_path;
+       char *max_path;
+#ifdef S_IFLNK
+       int readlinks = 0;
+       int n;
+       char link_path[PATH_MAX];
+#endif
+
+       /* Make a copy of the source path since we may need to modify it. */
+       strcpy(copy_path, path);
+       path = copy_path;
+       max_path = copy_path + PATH_MAX - 2;
+       /* If it's a relative pathname use getwd for starters. */
+       if (*path != '/') {
+#ifdef HAVE_GETCWD
+               getcwd(new_path, PATH_MAX - 1);
+#else
+               getwd(new_path);
+#endif
+               new_path += strlen(new_path);
+               if (new_path[-1] != '/')
+                       *new_path++ = '/';
+       }
+       else {
+               *new_path++ = '/';
+               path++;
+       }
+       /* Expand each slash-separated pathname component. */
+       while (*path != '\0') {
+               /* Ignore stray "/". */
+               if (*path == '/') {
+                       path++;
+                       continue;
+               }
+               if (*path == '.') {
+                       /* Ignore ".". */
+                       if (path[1] == '\0' || path[1] == '/') {
+                               path++;
+                               continue;
+                       }
+                       if (path[1] == '.') {
+                               if (path[2] == '\0' || path[2] == '/') {
+                                       path += 2;
+                                       /* Ignore ".." at root. */
+                                       if (new_path == resolved_path + 1)
+                                               continue;
+                                       /* Handle ".." by backing up. */
+                                       while ((--new_path)[-1] != '/')
+                                               ;
+                                       continue;
+                               }
+                       }
+               }
+               /* Safely copy the next pathname component. */
+               while (*path != '\0' && *path != '/') {
+                       if (path > max_path) {
+                               errno = ENAMETOOLONG;
+                               return NULL;
+                       }
+                       *new_path++ = *path++;
+               }
+#ifdef S_IFLNK
+               /* Protect against infinite loops. */
+               if (readlinks++ > MAX_READLINKS) {
+                       errno = ELOOP;
+                       return NULL;
+               }
+               /* See if latest pathname component is a symlink. */
+               *new_path = '\0';
+               n = readlink(resolved_path, link_path, PATH_MAX - 1);
+               if (n < 0) {
+                       /* EINVAL means the file exists but isn't a symlink. */
+                       if (errno != EINVAL)
+                               return NULL;
+               }
+               else {
+                       /* Note: readlink doesn't add the null byte. */
+                       link_path[n] = '\0';
+                       if (*link_path == '/')
+                               /* Start over for an absolute symlink. */
+                               new_path = resolved_path;
+                       else
+                               /* Otherwise back up over this component. */
+                               while (*(--new_path) != '/')
+                                       ;
+                       /* Safe sex check. */
+                       if (strlen(path) + n >= PATH_MAX) {
+                               errno = ENAMETOOLONG;
+                               return NULL;
+                       }
+                       /* Insert symlink contents into path. */
+                       strcat(link_path, path);
+                       strcpy(copy_path, link_path);
+                       path = copy_path;
+               }
+#endif /* S_IFLNK */
+               *new_path++ = '/';
+       }
+       /* Delete trailing slash but don't whomp a lone slash. */
+       if (new_path != resolved_path + 1 && new_path[-1] == '/')
+               new_path--;
+       /* Make sure it's null terminated. */
+       *new_path = '\0';
+       return resolved_path;
+}
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/Foundation/scanFloat.def b/libFoundation/Foundation/scanFloat.def
new file mode 100644 (file)
index 0000000..4adb9f7
--- /dev/null
@@ -0,0 +1,232 @@
+/* 
+   scanFloat.def
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+/* This file is included by NSScanner.m to produce the definitions of
+   -scanFloat: and -scanDouble: methods. In order to work, either FLOAT_TYPE or
+   DOUBLE_TYPE should be defined. */
+
+#if defined(FLOAT_TYPE)
+# define TYPE double
+# define MIN_VALUE FLT_MIN
+# define MAX_VALUE FLT_MAX
+# define MAX_DIG FLT_DIG
+# define MAX_EXP FLT_MAX_10_EXP
+# define MIN_EXP FLT_MIN_10_EXP
+#elif defined(DOUBLE_TYPE)
+# define TYPE double
+# define MIN_VALUE DBL_MIN
+# define MAX_VALUE DBL_MAX
+# define MAX_DIG DBL_DIG
+# define MAX_EXP DBL_MAX_10_EXP
+# define MIN_EXP DBL_MIN_10_EXP
+#else
+# error You should define FLOAT_TYPE or DOUBLE_TYPE
+#endif
+
+    NSCharacterSet* decimals = nil;
+    id string = [self string];
+    unsigned int orig;
+    unsigned int location;
+    unsigned int length = [string length];
+    TYPE maxvalue = MAX_VALUE / 10;
+    TYPE mantissa = 0;
+    TYPE decValue = 0;
+    TYPE exponent1 = 0;
+    TYPE result;
+    int exponent2 = 0;
+    BOOL isNegative = NO;
+    NSDictionary* locale = [self locale];
+    unichar zeroChar = '0';
+    unichar thousandSep = ',';
+    unichar decimalSep = '.';
+    unichar c;
+
+    if ([self isAtEnd])
+       return NO;
+
+    /* First skip the blank characters */
+    [self scanCharactersFromSet:[self charactersToBeSkipped] intoString:NULL];
+
+    /* Create the decimals set */
+    if (locale) {
+       NSString* thousandString = [locale objectForKey:NSThousandsSeparator];
+       NSString* decimalsString = [locale objectForKey:NSDecimalDigits];
+       NSString* decimalSepString = [locale objectForKey:NSDecimalSeparator];
+
+       if (decimalsString) {
+           zeroChar = [decimalsString characterAtIndex:0];
+           decimals = [NSCharacterSet characterSetWithCharactersInString:
+                                   decimalsString];
+       }
+
+       if (thousandString)
+           thousandSep = [thousandString characterAtIndex:0];
+
+       if (decimalSepString)
+           decimalSep = [decimalSepString characterAtIndex:0];
+    }
+
+    if (!decimals)
+       decimals = [NSCharacterSet decimalDigitCharacterSet];
+
+    orig = [self scanLocation];
+    c = [string characterAtIndex:orig];
+    if (c == '-' || c == '+') {
+       isNegative = (c == '-');
+       orig++;
+    }
+
+    /* Scan the mantisa */
+    for (location = orig; location < length; location++) {
+       c = [string characterAtIndex:location];
+       if ([decimals characterIsMember:c]) {
+           /* Even if result is greater than the maximum value that can be 
+              represented, continue the scanning to skip the hole number. */
+           if (mantissa <= maxvalue)
+               mantissa = mantissa * 10 + (c - zeroChar);
+           continue;
+       }
+       if (c == thousandSep)
+           continue;
+
+       /* If `c' is neither a decimal nor a thousand separator, break. */
+       break;
+    }
+    result = mantissa;
+
+    if (c == decimalSep) {
+       /* The number has a decimal part. Store it in the decValue but no more
+          than MAX_DIG digits; then skip all the digits. */
+       int digits_no = 0;
+
+       location++;
+
+       /* Iterate through the exponent's digits */
+       for (exponent1 = 0.1; location < length; location++, exponent1 /= 10) {
+           c = [string characterAtIndex:location];
+
+           /* Break if the character is not a digit */
+           if (![decimals characterIsMember:c])
+               break;
+
+           /* If result is too big to be represented just skip to the
+              next character. */
+           if (result > maxvalue)
+               continue;
+
+           digits_no++;
+
+           /* Only store the digit if the number of digits read so far is less
+              than MAX_DIG to avoid a possible overflow. */
+           if (digits_no <= MAX_DIG)
+               decValue += (c - zeroChar) * exponent1;
+       }
+    }
+    if (result <= maxvalue)
+       result += decValue;
+
+    if (c == 'e' || c == 'E') {
+       /* The number has an exponent. Store it in exponent2. */
+       BOOL expIsNegative = NO;
+
+       location++;
+       if (location < length) {
+           c = [string characterAtIndex:location];
+           if (c == '-') {
+               expIsNegative = YES;
+               location++;
+           }
+           else if (c == '+')
+               location++;
+       }
+
+       /* Read the digits of the exponent. First skip the leading zeroes. */
+       for (; location < length; location++) {
+           c = [string characterAtIndex:location];
+           if (c == '0')
+               continue;
+           else
+               break;
+       }
+
+       /* Read the exponent digits but check if it's greater than MAX_EXP or
+          less than MIN_EXP. */
+       for (; location < length; location++) {
+           TYPE power10[10] = {
+               1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9
+           };
+
+           c = [string characterAtIndex:location];
+
+           /* Break if the character is not a digit */
+           if (![decimals characterIsMember:c])
+               break;
+
+           /* If result is too big to be represented just skip to the
+              next character. */
+           if (result > maxvalue)
+               continue;
+
+           if (expIsNegative) {
+               if (exponent2 < abs(MIN_EXP)) {
+                   exponent2 = exponent2 * 10 + (c - zeroChar);
+                   /* Adjust the result */
+                   if (exponent2 < abs(MIN_EXP))
+                       result /= power10[c - zeroChar];
+               }
+           }
+           else {
+               if (exponent2 < MAX_EXP) {
+                   exponent2 = exponent2 * 10 + (c - zeroChar);
+                   /* Adjust the result */
+                   if (exponent2 < MAX_EXP)
+                       result *= power10[c - zeroChar];
+               }
+           }
+       }
+    }
+
+    if (location != orig) {
+       [self setScanLocation:location];
+
+       if (result > maxvalue) {
+           if (value)
+               *value = (isNegative ? MIN_VALUE : MAX_VALUE);
+           return NO;
+       }
+       else {
+           if (value)
+               *value = (isNegative ? -result : result);
+           return YES;
+       }
+    }
+
+    return NO;
+
+#undef TYPE
+#undef MIN_VALUE
+#undef MAX_VALUE
+#undef MAX_DIG
+#undef MAX_EXP
+#undef MIN_EXP
diff --git a/libFoundation/Foundation/scanInt.def b/libFoundation/Foundation/scanInt.def
new file mode 100644 (file)
index 0000000..630fd9c
--- /dev/null
@@ -0,0 +1,129 @@
+/* 
+   scanInt.def
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+/* This file is included by NSScanner.m to produce the definitions of
+   -scanInt: and -scanLongLong: methods. In order to work, either INT_TYPE or
+   LONG_LONG_TYPE should be defined. */
+
+#if defined(INT_TYPE)
+# define TYPE int
+# define MIN_VALUE INT_MIN
+# define MAX_VALUE INT_MAX
+#elif defined(LONG_LONG_TYPE)
+# define TYPE long long
+# define MIN_VALUE LONG_LONG_MIN
+# define MAX_VALUE LONG_LONG_MAX
+#else
+# error You should define INT_TYPE or LONG_LONG_TYPE
+#endif
+
+    NSCharacterSet* decimals = nil;
+    id string = [self string];
+    unsigned int orig;
+    unsigned int location;
+    unsigned int length = [string length];
+    unsigned TYPE maxTruncValue = MAX_VALUE / 10;
+    unsigned TYPE maxvalue = MAX_VALUE;
+    unsigned TYPE result = 0;
+    BOOL isNegative = NO;
+    BOOL exceedsMaximumValue = NO;
+    NSDictionary* locale = [self locale];
+    unichar zeroChar = '0';
+    unichar thousandSep = ',';
+    unichar c;
+
+    if ([self isAtEnd])
+       return NO;
+
+    /* First skip the blank characters */
+    [self scanCharactersFromSet:[self charactersToBeSkipped] intoString:NULL];
+
+    /* Create the decimals set */
+    if (locale) {
+       NSString* thousandString = [locale objectForKey:NSThousandsSeparator];
+       NSString* decimalsString = [locale objectForKey:NSDecimalDigits];
+
+       thousandString = [locale objectForKey:NSThousandsSeparator];
+
+       if (decimalsString) {
+           zeroChar = [decimalsString characterAtIndex:0];
+           decimals = [NSCharacterSet characterSetWithCharactersInString:
+                                   decimalsString];
+       }
+
+       if (thousandString)
+           thousandSep = [thousandString characterAtIndex:0];
+    }
+
+    if (!decimals)
+       decimals = [NSCharacterSet decimalDigitCharacterSet];
+
+    orig = [self scanLocation];
+    c = [string characterAtIndex:orig];
+    if (c == '-' || c == '+') {
+       isNegative = (c == '-');
+       orig++;
+    }
+
+    for (location = orig; location < length; location++) {
+       c = [string characterAtIndex:location];
+       if ([decimals characterIsMember:c]) {
+           /* Even if result is greater than the maximum value that can be 
+              represented, continue the scanning to skip the hole number. */
+           if (result <= maxTruncValue && !exceedsMaximumValue) {
+               result = result * 10 + (c - zeroChar);
+               if (result > maxvalue)
+                   exceedsMaximumValue = YES;
+           }
+           else
+               exceedsMaximumValue = YES;
+           continue;
+       }
+       if (c == thousandSep)
+           continue;
+
+       /* If `c' is neither a decimal nor a thousand separator, break. */
+       break;
+    }
+
+    if (location != orig) {
+       [self setScanLocation:location];
+
+       if (exceedsMaximumValue) {
+           if (value)
+               *value = (isNegative ? MIN_VALUE : MAX_VALUE);
+           return NO;
+       }
+       else {
+           if (value)
+               *value = (isNegative ? -result : result);
+           return YES;
+       }
+    }
+
+    return NO;
+
+#undef TYPE
+#undef MIN_VALUE
+#undef MAX_VALUE
diff --git a/libFoundation/Foundation/thr-mach.m b/libFoundation/Foundation/thr-mach.m
new file mode 100644 (file)
index 0000000..6d62afc
--- /dev/null
@@ -0,0 +1,484 @@
+/* GNU Objective C Runtime Thread Implementation
+   Copyright (C) 1996 Free Software Foundation, Inc.
+
+Author: Galen C. Hunt (gchunt@@cs.rochester.edu)
+Modified for Mach threads by: Bill Bumgarner <bbum@@friday.com>
+Condition functions added by: Mircea Oancea <mircea@@first.elcom.pub.ro>
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2, or (at your option) any later version.
+
+GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with files compiled with
+   GCC to produce an executable, this does not cause the resulting executable
+   to be covered by the GNU General Public License. This exception does not
+   however invalidate any other reasons why the executable file might be
+   covered by the GNU General Public License.  */
+
+#include <mach/mach.h>
+#include <mach/cthreads.h>
+#include <objc/objc-api.h>
+
+#if NeXT_RUNTIME
+typedef void * objc_thread_t;
+#endif
+
+/********
+ *  This structure represents a single mutual exclusion lock.  Lock semantics
+ *  are detailed with the subsequent functions.  We use whatever lock is
+ *  provided by the system.  We augment it with depth and current owner id
+ *  fields to implement and re-entrant lock.
+ */
+struct objc_mutex 
+{
+    volatile objc_thread_t     owner;           /* Id of thread that owns.  */
+    volatile int                depth;          /* # of acquires.           */
+    struct mutex                lock;           /* cthread mutex            */
+};
+typedef struct objc_mutex *objc_mutex_t;
+
+struct objc_condition 
+{
+    struct condition            condition;      /* cthread condition        */
+};
+typedef struct objc_condition *objc_condition_t;
+
+/********
+ *  Universal static variables:
+ */
+int __objc_thread_exit_status = 0;             /* Global exit status.      */
+int __objc_runtime_threads_alive = 0;          /* Number of threads alive  */
+struct objc_mutex* __objc_runtime_mutex = NULL;        /* Thread create/exit mutex */
+
+/********
+ * obtain the maximum thread priority that can set for t.  Under the
+ * mach threading model, it is possible for the developer to adjust the
+ * maximum priority downward only-- cannot be raised without superuser
+ * priviledges.  Once lowered, it cannot be raised.
+ */
+static int __mach_get_max_thread_priority(cthread_t t, int *base) {
+    thread_t                         threadP;
+    kern_return_t             error;
+    struct thread_sched_info  info;
+    unsigned int              info_count=THREAD_SCHED_INFO_COUNT;
+    
+    if (t == NULL)
+       return -1;
+
+    threadP  = cthread_thread(t);      /* get thread underlying */
+
+    error=thread_info(threadP, THREAD_SCHED_INFO, 
+                     (thread_info_t)&info, &info_count);
+
+    if (error != KERN_SUCCESS)
+       return -1;
+
+    if (base != NULL)
+       *base = info.base_priority;
+
+    return info.max_priority;
+}
+       
+/********
+ *  Initialize the threads subsystem.  Returns 0 if successful, or -1 if no
+ *  thread support is available.
+ */
+int
+__objc_init_thread_system(void)
+{
+    return 0;                                    /* Succeeded.       */
+}
+
+
+int
+__objc_fini_thread_system(void)
+{
+  return 0;
+}
+
+/********
+ *  Create a new thread of execution and return its id.  Return NULL if fails.
+ *  The new thread starts in "func" with the given argument.
+ */
+objc_thread_t
+objc_thread_create(void (*func)(void *arg), void *arg)
+{
+    objc_thread_t       thread_id = NULL;       /* Detached thread id.      */
+    cthread_t           new_thread_handle;      /* cthread handle.          */
+
+    if (!__objc_runtime_mutex)
+       __objc_runtime_mutex = objc_mutex_allocate();
+    
+    objc_mutex_lock(__objc_runtime_mutex);
+    
+    /* create thread */
+    new_thread_handle = cthread_fork((cthread_fn_t)func, arg);
+
+    if(new_thread_handle) {
+      /* this is not terribly portable */
+        thread_id = *(objc_thread_t *)&new_thread_handle; 
+        cthread_detach(new_thread_handle);      /* fully detach thread */
+        __objc_runtime_threads_alive++;         /* increment thread count */
+    }
+    
+    objc_mutex_unlock(__objc_runtime_mutex);
+    return thread_id;
+}
+
+/********
+ *  Set the current thread's priority.
+ */
+int
+objc_thread_set_priority(int priority)
+{
+    objc_thread_t   *t      = objc_thread_id();
+    cthread_t        cT             = (cthread_t) t; 
+    int             maxPriority  = __mach_get_max_thread_priority(cT, NULL);
+    int              sys_priority = 0;
+
+    if (maxPriority == -1)
+       return -1;
+
+    switch (priority) {
+    case OBJC_THREAD_INTERACTIVE_PRIORITY:
+        sys_priority = maxPriority;
+        break;
+    case OBJC_THREAD_BACKGROUND_PRIORITY:
+        sys_priority = (maxPriority * 2) / 3;
+        break;
+    case OBJC_THREAD_LOW_PRIORITY:
+        sys_priority = maxPriority / 3;
+        break;
+    default:
+       return -1;
+    }
+
+    if (sys_priority == 0)
+       return -1;
+    
+    if (cthread_priority(cT, sys_priority, 0) == KERN_SUCCESS)
+        return 0;                               /* Changed priority. End.   */
+    
+    return -1;                                  /* Failed.                  */
+}
+
+/********
+ *  Return the current thread's priority [well, whatever it is closest to].
+ */
+int
+objc_thread_get_priority(void)
+{
+    objc_thread_t *t           = objc_thread_id();
+    cthread_t      cT          = (cthread_t) t; /* see objc_thread_id() */
+    int           basePriority;
+    int           maxPriority;
+
+    maxPriority = __mach_get_max_thread_priority(cT, &basePriority);
+
+    if(maxPriority == -1)
+       return -1;
+
+    if (basePriority > ( (maxPriority * 2) / 3))
+       return OBJC_THREAD_INTERACTIVE_PRIORITY; /* interactive priority
+                                                */
+    if (basePriority > ( maxPriority / 3))
+       return OBJC_THREAD_BACKGROUND_PRIORITY; /* background priority
+                                                */
+    return OBJC_THREAD_LOW_PRIORITY; /* everything else is low */
+}
+
+/********
+ *  Yield our process time to another thread.  Any BUSY waiting that is done
+ *  by a thread should use this function to make sure that other threads can
+ *  make progress even on a lazy uniprocessor system.
+ */
+void
+objc_thread_yield(void)
+{
+    cthread_yield();                            /* Yield to equal thread.   */
+}
+
+/********
+ *  Terminate the current tread.  Doesn't return anything.  Doesn't return.
+ *  Actually, if it failed returns -1.
+ */
+int
+objc_thread_exit(void)
+{
+  objc_mutex_lock(__objc_runtime_mutex);
+  __objc_runtime_threads_alive--;
+  objc_mutex_unlock(__objc_runtime_mutex);
+      
+  cthread_exit(&__objc_thread_exit_status);     /* Terminate thread.        */
+  return -1;
+}
+
+/********
+ *  Returns an integer value which uniquely describes a thread.  Must not be
+ *  NULL which is reserved as a marker for "no thread".
+ */
+objc_thread_t
+objc_thread_id(void)
+{
+  cthread_t self = cthread_self();
+  return (objc_thread_t)self;
+}
+
+/********
+ *  Sets the thread's local storage pointer.  Returns 0 if successful or -1
+ *  if failed.
+ */
+
+int
+objc_thread_set_data(void *value)
+{
+  cthread_set_data(cthread_self(), (any_t) value);
+  return 0;
+}
+
+/********
+ *  Returns the thread's local storage pointer.  Returns NULL on failure.
+ */
+void *
+objc_thread_get_data(void)
+{
+  return (void *) cthread_data(cthread_self());
+}
+
+/********
+ *  Allocate a mutex.  Return the mutex pointer if successful or NULL if the
+ *  allocation failed for any reason.
+ */
+objc_mutex_t
+objc_mutex_allocate(void)
+{
+    objc_mutex_t mutex;
+    int         err = 0;
+    
+    if (!(mutex = (objc_mutex_t)objc_malloc(sizeof(struct objc_mutex))))
+        return NULL;                            /* Abort if malloc failed.  */
+
+    err = mutex_init(&(mutex->lock));
+    
+    if (err != 0) {                             /* System init failed?      */
+        objc_free(mutex);                       /* Yes, free local memory.  */
+        return NULL;                            /* Abort.                   */
+    }
+    mutex->owner = (objc_thread_t) -1;         /* No owner.                */
+    mutex->depth = 0;                           /* No locks.                */
+    return mutex;                               /* Return mutex handle.     */
+}
+
+/********
+ *  Deallocate a mutex.  Note that this includes an implicit mutex_lock to
+ *  insure that no one else is using the lock.  It is legal to deallocate
+ *  a lock if we have a lock on it, but illegal to deallocate a lock held
+ *  by anyone else.
+ *  Returns the number of locks on the thread.  (1 for deallocate).
+ */
+int
+objc_mutex_deallocate(objc_mutex_t mutex)
+{
+    int         depth;                          /* # of locks on mutex.     */
+
+    if (!mutex)                                 /* Is argument bad?         */
+        return -1;                              /* Yes, abort.              */
+    depth = objc_mutex_lock(mutex);             /* Must have lock.          */
+    
+    mutex_unlock(&(mutex->lock));               /* Must unlock system mutex.*/
+    mutex_clear(&(mutex->lock));                /* Free system mutex.       */
+    
+    objc_free(mutex);                           /* Free memory.             */
+    return depth;                               /* Return last depth.       */
+}
+
+/********
+ *  Grab a lock on a mutex.  If this thread already has a lock on this mutex
+ *  then we increment the lock count.  If another thread has a lock on the 
+ *  mutex we block and wait for the thread to release the lock.
+ *  Returns the lock count on the mutex held by this thread.
+ */
+int
+objc_mutex_lock(objc_mutex_t mutex)
+{
+    objc_thread_t thread_id;                  /* Cache our thread id.     */
+
+    if (!mutex)                                 /* Is argument bad?         */
+        return -1;                              /* Yes, abort.              */
+    thread_id = objc_thread_id();               /* Get this thread's id.    */
+    if (mutex->owner == thread_id)              /* Already own lock?        */
+        return ++mutex->depth;                  /* Yes, increment depth.    */
+
+    mutex_lock(&(mutex->lock));                 /* Lock cthread mutex.      */
+    
+    mutex->owner = thread_id;                   /* Mark thread as owner.    */
+    return mutex->depth = 1;                    /* Increment depth to end.  */
+}
+
+/********
+ *  Try to grab a lock on a mutex.  If this thread already has a lock on
+ *  this mutex then we increment the lock count and return it.  If another
+ *  thread has a lock on the mutex returns -1.
+ */
+int
+objc_mutex_trylock(objc_mutex_t mutex)
+{
+    objc_thread_t         thread_id;           /* Cache our thread id.     */
+
+    if (!mutex)                                 /* Is argument bad?         */
+        return -1;                              /* Yes, abort.              */
+    thread_id = objc_thread_id();               /* Get this thread's id.    */
+    if (mutex->owner == thread_id)              /* Already own lock?        */
+        return ++mutex->depth;                  /* Yes, increment depth.    */
+    
+    if (mutex_try_lock(&(mutex->lock)) == 0)    /* Lock cthread mutex.      */
+        return -1;                              /* Failed, abort.           */
+    
+    mutex->owner = thread_id;                   /* Mark thread as owner.    */
+    return mutex->depth = 1;                    /* Increment depth to end.  */
+}
+
+/********
+ *  Decrements the lock count on this mutex by one.  If the lock count reaches
+ *  zero, release the lock on the mutex.  Returns the lock count on the mutex.
+ *  It is an error to attempt to unlock a mutex which this thread doesn't hold
+ *  in which case return -1 and the mutex is unaffected.
+ *  Will also return -1 if the mutex free fails.
+ */
+int
+objc_mutex_unlock(objc_mutex_t mutex)
+{
+    objc_thread_t    thread_id;                /* Cache our thread id.     */
+    
+    if (!mutex)                                 /* Is argument bad?         */
+        return -1;                              /* Yes, abort.              */
+    thread_id = objc_thread_id();               /* Get this thread's id.    */
+    if (mutex->owner != thread_id)              /* Does some else own lock? */
+        return -1;                              /* Yes, abort.              */
+    if (mutex->depth > 1)                       /* Released last lock?      */
+        return --mutex->depth;                  /* No, Decrement depth, end.*/
+    mutex->depth = 0;                           /* Yes, reset depth to 0.   */
+    mutex->owner = (objc_thread_t) -1;         /* Set owner to "no thread".*/
+    
+    mutex_unlock(&(mutex->lock));               /* unlock cthread mutex.    */
+    
+    return 0;                                   /* No, return success.      */
+}
+
+/********
+ *  Allocate a condition.  Return the condition pointer if successful or NULL
+ * if the allocation failed for any reason.
+ */
+objc_condition_t 
+objc_condition_allocate(void)
+{
+    objc_condition_t condition;
+    
+    if (!(condition = (objc_condition_t)objc_malloc(
+                        sizeof(struct objc_condition))))
+        return NULL;                            /* Abort if malloc failed.  */
+
+    condition_init(&(condition->condition));
+    
+    return condition;                           /* Return mutex handle.     */
+}
+
+/********
+ *  Deallocate a condition. Note that this includes an implicit 
+ *  condition_broadcast to insure that waiting threads have the opportunity
+ *  to wake.  It is legal to dealloc a condition only if no other
+ *  thread is/will be using it. Here we do NOT check for other threads
+ *  waiting but just wake them up.
+ */
+int
+objc_condition_deallocate(objc_condition_t condition)
+{
+       condition_broadcast(&(condition->condition));
+       condition_clear(&(condition->condition));
+       objc_free(condition);
+       return 0;
+}
+
+/********
+ *  Wait on the condition unlocking the mutex until objc_condition_signal()
+ *  or objc_condition_broadcast() are called for the same condition. The
+ *  given mutex *must* have the depth set to 1 so that it can be unlocked
+ *  here, so that someone else can lock it and signal/broadcast the condition.
+ *  The mutex is used to lock access to the shared data that make up the
+ *  "condition" predicate.
+ */
+int
+objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
+{
+    objc_thread_t    thread_id;                /* Cache our thread id.     */
+    
+    if (!mutex || !condition)                   /* Is argument bad?         */
+        return -1;                              /* Yes, abort.              */
+
+    thread_id = objc_thread_id();               /* Get this thread's id.    */
+    if (mutex->owner != thread_id)              /* Does some else own lock? */
+        return -1;                              /* Yes, abort.              */
+    if (mutex->depth > 1)                       /* Locked more than once ?  */
+        return -1;                              /* YES, return error        */
+                                                /* mutex will be unlocked   */
+    mutex->depth = 0;                           /* Yes, reset depth to 0.   */
+    mutex->owner = (objc_thread_t) -1;         /* Set owner to "no thread".*/
+    
+    condition_wait(&(condition->condition),
+               &(mutex->lock));                        /* unlock, wait ..., lock   */
+    
+    mutex->owner = thread_id;                   /* Mark thread as owner.    */
+    mutex->depth = 1;                           /* Increment depth to end.  */
+    return 0;                                   /* Return success.          */
+}
+
+/********
+ *  Wake up all threads waiting on this condition. It is recommended that 
+ *  the called would lock the same mutex as the threads in objc_condition_wait
+ *  before changing the "condition predicate" and make this call and unlock it
+ *  right away after this call.
+ */
+int
+objc_condition_broadcast(objc_condition_t condition)
+{
+    if (!condition)
+               return -1;
+       condition_broadcast(&(condition->condition));
+       return 0;
+}
+
+/********
+ *  Wake up one thread waiting on this condition. It is recommended that 
+ *  the called would lock the same mutex as the threads in objc_condition_wait
+ *  before changing the "condition predicate" and make this call and unlock it
+ *  right away after this call.
+ */
+int
+objc_condition_signal(objc_condition_t condition)
+{
+    if (!condition)
+               return -1;
+       condition_signal(&(condition->condition));
+       return 0;
+}
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
+
diff --git a/libFoundation/GNUmakefile b/libFoundation/GNUmakefile
new file mode 100644 (file)
index 0000000..967b278
--- /dev/null
@@ -0,0 +1,51 @@
+# $Id$
+# 
+#  GNUmakefile.gnustep
+#
+#  Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+#  All rights reserved.
+#
+#  Author: Ovidiu Predescu <ovidiu@net-community.com>
+#  Date: October 1997
+#
+#  This file is part of libFoundation.
+#
+#  Permission to use, copy, modify, and distribute this software and its
+#  documentation for any purpose and without fee is hereby granted, provided
+#  that the above copyright notice appear in all copies and that both that
+#  copyright notice and this permission notice appear in supporting
+#  documentation.
+#
+#  We disclaim all warranties with regard to this software, including all
+#  implied warranties of merchantability and fitness, in no event shall
+#  we be liable for any special, indirect or consequential damages or any
+#  damages whatsoever resulting from loss of use, data or profits, whether in
+#  an action of contract, negligence or other tortious action, arising out of
+#  or in connection with the use or performance of this software.
+#
+
+-include gsfix.make
+
+ifeq ($(GNUSTEP_SYSTEM_ROOT),)
+
+$(warning ERROR: Your $(GNUSTEP_SYSTEM_ROOT) environment variable is empty !)
+$(error Please try again after running ". $(GNUSTEP_MAKEFILES)/GNUstep.sh")
+
+else
+
+GNUSTEP_INSTALLATION_DIR = $(GNUSTEP_SYSTEM_ROOT)
+
+include $(GNUSTEP_MAKEFILES)/common.make
+include ./Version
+
+SUBPROJECTS = Foundation Resources examples
+
+include $(GNUSTEP_MAKEFILES)/aggregate.make
+
+after-distclean::
+       rm -f config.cache config.log config.status config.h config.mak
+
+after-install ::
+       $(INSTALL_DATA) Foundation/libFoundation.make $(INSTALL_ROOT_DIR)$(GNUSTEP_MAKEFILES)/Additional/
+
+endif
diff --git a/libFoundation/GNUmakefile.alone b/libFoundation/GNUmakefile.alone
new file mode 100644 (file)
index 0000000..e474402
--- /dev/null
@@ -0,0 +1,52 @@
+# GNUmakefile
+#
+# Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+# All rights reserved.
+#
+# Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+#
+# This file is part of libFoundation.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose and without fee is hereby granted, provided
+# that the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation.
+#
+# We disclaim all warranties with regard to this software, including all
+# implied warranties of merchantability and fitness, in no event shall
+# we be liable for any special, indirect or consequential damages or any
+# damages whatsoever resulting from loss of use, data or profits, whether in
+# an action of contract, negligence or other tortious action, arising out of
+# or in connection with the use or performance of this software.
+
+TOP    = .
+OBJDIR = obj
+
+include $(TOP)/config.mak
+
+DIRS_TO_MAKE = Foundation Resources examples
+
+all clean distclean realclean install uninstall check check-all::
+       @(dir=`(cd $(TOP); pwd)`; newdir=`(pwd | sed "s%$$dir/%%")`;\
+       if test "$$newdir" = "$$dir"; then dir=; else dir=$$newdir/; fi; \
+       for f in $(DIRS_TO_MAKE); do \
+           echo Making $@ in $${dir}$$f...;\
+           (cd $$f; $(MAKE) $@ OBJDIR=$(OBJDIR)); \
+       done)
+
+clean::
+       rm -f lib/libFoundation.*
+
+distclean::
+       rm -f config.cache config.log config.status config.h config.mak \
+           GNUmakefile lib/libFoundation.*
+
+realclean:: distclean
+
+shared static:
+       @(echo Making $@ in Foundation...; \
+       (cd Foundation; $(MAKE) $@ OBJDIR=$(OBJDIR)))
+
+$(TOP)/config.mak:
+       touch $@
diff --git a/libFoundation/INSTALL.txt b/libFoundation/INSTALL.txt
new file mode 100644 (file)
index 0000000..8a6cc9e
--- /dev/null
@@ -0,0 +1,243 @@
+# $Id: INSTALL.txt,v 1.2 2004/07/15 17:32:19 helge Exp $
+
+UPDATE: the OGo fork of libFoundation can only be build with gstep-make!
+
+libFoundation can be built in two different ways:
+
+1. as a standalone library.
+2. as the Foundation library in the GNUstep environment, instead of
+gnustep-base.
+
+In both cases you can build the library with support for the Boehm's
+garbage collector.
+
+To be able to build libFoundation you need either GCC 2.8.x or EGCS
+1.1. Older versions of GCC with the Objective-C patches are
+obsolete. You'll also need the GNUmake to compile libFoundation.
+
+
+
+Which way to build libFoundation?
+=================================
+
+People that don't want to use the library in the GNUstep environment
+should build it in the standalone mode. In this mode you're not
+required to specify any environment variables in order to make the
+library work. In the GNUstep environment you will have to specify the
+GNUSTEP_SYSTEM_ROOT in order for the library to find the resource
+files it needs.
+
+For example applications like CGI programs that use libFoundation may
+want to use the standalone library as they don't have to setup a
+special environment.
+
+People that want to use libFoundation as the Foundation library for
+GNUstep should build it for the GNUstep environment.
+
+If you need libFoundation in both types of applications you can
+configure, compile and install it in both ways. The two versions of
+the library install their header files and libraries in different
+places and they do not interfere with each other.
+
+IMPORTANT: If you compile libFoundation in the standalone mode be sure
+you don't have the gnustep-base headers in the include path or you'll
+encounter problems because the compiler will get them instead.
+
+
+
+Boehm's garbage collector support
+=================================
+
+Starting with 0.9.0, libFoundation supports the Boehm's garbage
+collector. You must have the Boehm's garbage collector support
+installed before building libFoundation.
+
+Here are the steps you need to do to install the Boehm's garbage
+collector:
+
+1. Download the package. The library was tested using the 4.12
+version, previous versions may work but they were not tested. The
+official site is:
+
+    http://reality.sgi.com/employees/boehm_mti/
+
+Read carefully the Makefile and add the flags specific to your
+system. Don't add the -DNO_SIGNALS to the list of flags, as
+libFoundation uses signals internally. After you're sure everything is
+fine with the makefile, type 'make' followed by 'make test' which
+briefly tests the collector.
+
+The next step is to install the collector. The makefile doesn't have
+an install target, so copy the gc.h and gc_typed.h files to
+/usr/local/include or to whatever location you prefer. Then copy the
+gc.a library into /usr/local/lib and rename it to libgc.a. This step
+is important, otherwise the configure script in libFoundation and the
+test programs you'll write will not work.
+
+2. You need to compile a special version of the compiler which adds
+support for the Boehm's collector to the GNU runtime. 
+
+The currently supported compilers are GCC 2.8.1 and EGCS 1.1. The
+patches are contained in the libFoundation's distribution. Apply the
+appropriate patch for your compiler. Then configure the compiler using
+
+       ./configure --enable-objc-gc
+
+Add whatever arguments you might need to the configure. Then compile
+the compiler following the instructions in the INSTALL file included
+with the compiler.
+
+3. Configure libFoundation to be compiled with Boehm's GC support. To
+do this add --with-gc to the specific flags for your system. At this
+point you also have to decide in which environment you want to build
+libFoundation.
+
+For an impatient user, just type the following if you want to build
+the library in the GNUstep environment.
+
+       ./configure --with-gnustep --with-gc
+
+Or run the following if you want to build the library as a standalone
+library.
+
+       ./configure --with-gc
+
+Configuring the library with support for Boehm's garbage collector
+does not imply that the built library will be automatically using the
+collector. Actually you can build two versions of the library, one
+that is garbage collected and another one that uses the normal
+reference counting mechanism.
+
+To build the garbage collected library type:
+
+       make gc=yes
+
+To build the normal library type in the OpenStep compatibility mode:
+
+       make
+
+If you're building in the GNUstep environment you may want to add
+additional options like debug=yes.
+
+
+
+Building libFoundation
+======================
+
+If you want to build the library with support for Boehm's garbage
+collector, please read the above part first.
+
+1. If you want to build the library in the GNUstep environment, run
+the configure script with the --with-gnustep argument, otherwise just
+omit it:
+
+   ./configure --with-gnustep
+
+If you need support for Boehm's garbage collector, just add the
+--with-gc flag:
+
+   ./configure --with-gnustep --with-gc
+
+If you're building on a NeXTSTEP/OPENSTEP system read the note at the
+end of this file.
+
+2. Run `make' to compile the package. If you're building in the
+GNUstep environment add any additional options you might need. For
+example if you want debugging and/or profile information to be
+included in the library:
+
+   make debug=yes [profile=yes]
+
+where [profile=yes] means that profile=yes is an optional
+argument. Read the GNUstep's makefile package documentation to find
+out more about compiling in the GNUstep environment.
+
+NOTE: In the standalone environment, debug=yes and profile=yes
+arguments have no meaning.
+
+To build the garbage collected library add the gc=yes argument to the
+list of arguments you pass to make:
+
+   make gc=yes
+
+This works with both the standalone and GNUstep environments.
+
+3. Before you install the library you may want to set up the locales
+for your site. To do this go to the Resources/Defaults directory and
+modify the NSGlobalDomain.plist file as you wish. This file specifies
+the language and the time zone name of your site.
+
+If your language is not included in the supported languages, you can
+create a new one using as model one of the existing language files.
+
+The timezones are specified in the Resources/TimeZoneInfo
+directory. You should choose as time zone the one that coresponds to
+your geo-political region.
+
+4. Type `make install' to install the library, the headers and the
+public binaries. Add the debug and profile arguments to the make
+process if you want that specific version to be installed:
+
+   make [debug=yes] [profile=yes] [gc=yes] install
+
+5. To try out if the package works fine on your machine, you can run
+the tests from the FoundationTestsuite directory. All the tests are
+written using the DejaGnu testing framework. So if you don't have
+installed the package on your machine you have to install it before
+trying out these tests. Before compiling the FoundationTestsuite you
+will have to install the ObjCTest package that comes with the
+libFoundation's distribution.
+
+The classes that intimately depend on the specific machine are
+NSMethodSignature and NSInvocation. If you get crashes when you run
+the NSInvocation and NSMethodSignature tests you have to look to the
+sources for these classes in the Foundation directory and to the files
+dependent on the target machine in config directory.
+
+6. You can remove the object files and binaries using the `make clean'
+command. You can also remove all the generated files (the files
+generated by configure etc) with `make distclean'.
+
+
+
+Notes for NeXTSTEP/OPENSTEP users
+=================================
+
+If you're compiling the package on a NeXT system you can compile it to
+use with either the GNU or the NeXT Objective-C runtime. You can
+specify this by setting the OBJC_RUNTIME variable. For example:
+
+   OBJC_RUNTIME=gnu ./configure
+
+will compile the package using the GNU runtime. Similarly, you can do:
+
+   OBJC_RUNTIME=next ./configure
+
+In the last case you will be able to link the package with code
+compiled with the native compiler.
+
+If you don't specify the OBJC_RUNTIME flag the code will be compiled
+with the default option for runtime. It is either -fnext-runtime on
+NeXT systems or -fgnu-runtime on the other machines.
+
+You can also specify the compiler using the CC variable. The package
+has been compiled using the 2.6.3, 2.7.0 and 2.7.2.1 gcc versions,
+depending on machine. If you compile the package with other versions
+than 2.7.2.1 you will need to adapt yourself the Objective-C patch to
+the compiler sources. GCC 2.8.x and EGCS 1.0.x have not been tested.
+
+Compiling the package on NeXT release 3.3 with the native compiler
+won't work. The native compiler doesn't support nested functions and
+variable arguments macros.
+
+Starting with the 0.9.0 version the NeXTSTEP systems are no longer
+supported due to compiler and debugger problems on these systems. If
+somebody is willing to send us patches for NeXTSTEP, we'll incorporate
+them in the distribution.
+
+
+
+
+! Local variables:
+! mode: indented-text
+! End:
diff --git a/libFoundation/NEWS b/libFoundation/NEWS
new file mode 100644 (file)
index 0000000..a8f3d80
--- /dev/null
@@ -0,0 +1,128 @@
+Changes in version 1.0.0 since version 0.9.0:
+
+* The focus of this version is a bug-free and stable code base, only
+  few new features were added, but a *lot* of bugs were fixed and some
+  important performance improvements were added. 1.0 can be considered
+  production quality.
+
+* Support for some new Cocoa classes, like NSURL
+
+* Improved compatibility with gstep-base
+
+* more and fixed timezone files
+
+* support for read-only strings in UTF-8 and UTF-16
+
+* some fixes for warnings thrown in new gcc (gcc3+) compilers
+
+
+
+Changes in version 0.9.0 since version 0.8.0:
+
+* The most important change is the support for Boehm's conservative
+  garbage collector, that makes the memory management much more easier
+  than the reference counting mechanism. Many thanks to Helge Hess
+  <helge@mdlink.de> for persuading me to implement this facility and
+  also for his support.
+
+* Some portions of the code have been optimized to gain speed: objects
+  that were previously allocated in some functions or methods at each
+  invocation have been allocated once per-thread.
+
+* The library has been ported to PowerPC running AIX 4.1.5. The port is
+  complete, it also includes the NSInvocation and NSMethodSignature
+  classes. Many thanks to Steven Besler <sbesler@exchange.ml.com> and
+  Leon Salvail <lsalvail@global-village.net> for supporting this work.
+
+* Added support for dynamically loading bundles when running in the
+  GNUstep environment.
+
+* The documentation is now written in Texinfo and we documented almost
+  all of the additional features libFoundation comes with in addition
+  to the OPENSTEP implementation.
+
+* Bug fixes in several classes, including NSArray, NSString and
+  UnixSignalHandler.
+
+
+
+Changes in version 0.8.0 since version 0.7.1:
+
+* The library has been made thread-safe; much of the work has been done by 
+  Aleksandr Savostyanov <sav@conextions.com>.
+
+* New classes NSFileHandle, NSHost, NSPipe and NSTask have been added. These
+  classes are new in the OPENSTEP 4.x and Rhapsody implementation from
+  NeXT/Apple.
+
+* A new class UnixSignalHandler which provides an object oriented approach
+  for dealing with the Unix signals. The class works with both BSD and System V
+  ways of handling signals and allows messages to be sent both immediately
+  after the signal has been received or after the run loop finishes the current
+  loop.
+
+* The library was partially ported over to Alpha machines running Linux. The
+  code is 64-bit clean but I still need to finish the NSInvocation and
+  NSMethodSignature Alpha dependent macros. The library was also ported to
+  Intel/Solaris 2.5.1.
+
+* A new program for managing the defaults database system was added. It works
+  much like the defaults program under OPENSTEP 4.x. You can also compile it
+  for other implementations of the Foundation library since it does not use
+  any features specific to libFoundation.
+
+* NSNotificationQueue has been integrated with the NSRunLoop class. You can now
+  use the various ways of posting notifications as described by the
+  documentation of this class.
+
+* The testsuite was ported to work with the Foundation on OPENSTEP 4.x using
+  the native compiler. Thus we have an easy way to ensure the compatibility of
+  various OpenStep Foundation library implementations. We have split the
+  test suite in two parts: a general library and some scripts that are
+  general enough so they can be also used by other libraries to write DejaGnu
+  test for Objective-C programs and the test suite itself, specific for the
+  Foundation library. In order to compile and run the tests you should have to
+  install the GNUstep makefile package first and then the objc-test library.
+  If you're using it for other libraries than libFoundation you should also
+  get and compile the FoundationExtensions library.
+
+* The library has been ported over to the GNUstep makefile package so one can
+  use libFoundation as a Foundation library in GNUstep applications (support
+  for libFoundation is already included in the makefile package).
+
+* Bug fixes and improvements in a lot of classes.
+
+
+
+Changes in version 0.7.1 since version 0.7:
+
+* The port to Solaris has been completed thanks to Aleksandr Savostyanov
+  <sav@conextions.com>.
+
+* libFoundation was ported to Windows NT; thanks to Jeremy R. Bettis
+  <jeremy@hksys.com>.
+
+* Shared library support has been added. New makefile targets exist on systems
+  that support shared libraries (`shared' and `install_shared'). The currently
+  supported systems are Linux ELF, Solaris and OPENSTEP 4.x.
+
+* NSRunLoop and NSPosixFileDescriptor classes has been finished. The NSRunLoop
+  API has been changed to work with NSPosixFileDescriptor objects instead of
+  Unix file descriptors.
+
+* Delayed execution of methods in NSObject is now working.
+
+* The library now works with both 960906 and 960318 Objective-C runtime
+  patches. (You must have either one of these patches applied to the compiler
+  before compiling libFoundation; see the INSTALL file for more info.)
+
+* Many bug fixes and improvements in NSInvocation, NSTimer, exception handling
+  without nested functions support, NSString, geometry functions,
+  NSDistributedLock, NSFileManager and NSRunLoop. See the ChangeLog file for a
+  complete list of the changes.
+
+
+
+! Local variables:
+! mode: indented-text
+! End:
diff --git a/libFoundation/README b/libFoundation/README
new file mode 100644 (file)
index 0000000..37cf3e5
--- /dev/null
@@ -0,0 +1,240 @@
+libFoundation Library README
+============================
+
+
+History
+=======
+
+    This library is derived from an old library we designed, wrote and
+    used for developing a commercial application during 1995.
+
+    That time we needed a small library that had some general
+    containers and strong support for distributed objects. We needed
+    to write code that runs on different machines, not only on NeXT.
+
+    Also we needed to write programs that communicate via general Unix
+    IPC channels. So we designed a library that had support for
+    distributed objects on different channels of communication like
+    Internet or Unix domain stream sockets or socketpairs.
+
+    We also experimented some ideas, such as calling the exception
+    handlers as functions and returning from them, choosing the best
+    communication channel when a connection is established and some
+    other interesting ideas.
+
+
+The design of the library
+=========================
+
+    We have followed two important points in designing this
+    library. The first is runtime independence. The second is to write
+    the code without using extensions to the OpenStep spec, or if we
+    are using such extensions, we provide a separate library
+    containing them that allows porting of the code written for
+    libFoundation to another implementation of Foundation.
+
+    We wanted to give people a library that compiles and runs in the
+    both worlds of Objective-C: NeXT and GNU. This will allow one to
+    write programs that mix together the code that exists for NeXT and
+    the code that runs only on the GNU runtime. libFoundation compiles
+    with both runtimes using different compilers. If all the other
+    GNUstep work would be done to allow easy porting of programs, then
+    one can move easily from NeXT's OpenStep to GNUstep.
+
+    The library includes a header file that allows you to write the
+    programs portable across runtimes. If you write the programs using
+    only the GNU API without some GNU runtime dependent facilities
+    your programs will also run without modifications on both GNU and
+    NeXT runtime.
+
+    The actual extensions are the exception handling mechanism and the
+    garbage collector based on reference counting. The exception
+    handling mechanism offers a better approach to exception handling
+    than that found in the OpenStep specification by using a more
+    intuitive syntax. In addition the exception handler is invoked as
+    a function so you can see in debugger where the exception was
+    generated from.
+
+    The garbage collector works in conjunction with the reference
+    counting mechanism and releases you from thinking on how to solve
+    the cycles in your program, thus saving time and code to write and
+    maintain.
+
+    For all these extensions we provide a separate library that
+    compiles with other implementations of Foundation.
+
+    Starting with version 0.9.0 support for Boehm's garbage collector
+    has been added; see
+
+       http://reality.sgi.com/employees/boehm_mti/
+
+    for more information on this collector. The support in
+    libFoundation includes the possibility of registering an object
+    for the finalization of another object, which is very important
+    for the implementation of classes like NSNotificationCenter in
+    libFoundation and EOObjectUniquer in GDL. See the documentation
+    for more details about this facitity.
+
+
+The current status
+==================
+
+    Almost all of the classes from the original OpenStep specification
+    are implemented. We also implemented several classes found in the
+    NeXT's OPENSTEP implementation like NSFileManager, NSFileHandle,
+    NSTask and NSPipe. We estimate the library is completed in
+    proportion of 80% from the original OpenStep specification;
+    extensions are not counted.
+
+    Almost all of the classes are thoroughly tested using a special
+    testing framework we designed.
+
+
+Future work
+===========
+
+    Starting with 0.8.0 libFoundation was made thread-safe. More
+    testing should be done: we need to come up with some automated
+    tests for checking the thread-safety of the library.
+
+    At this time libFoundation does not provide an implementation of
+    Distributed Objects (DO) and Unicode strings.
+
+    A small implementation for DO was written by Helge Hess and it
+    will eventually become part of libFoundation. This implementation
+    will be further worked on to be based upon the Corba's IIOP, which
+    will allow libFoundation's Distributed Objects clients to
+    communicate directly with Corba clients written in other
+    languages, that run using a variety of Corba implementations.
+
+    Mircea wrote most of the Unicode implementation but we still need
+    to come up with some good algorithms for searching Unicode
+    strings.
+
+Resources
+=========
+
+    Snapshots/releases of libFoundation will usually become available in
+    the contrib directory of the GNUstep site (ftp.gnustep.org).
+    There is also a web page on
+
+    http://www.geocities.com/SiliconValley/Monitor/7464/libFoundation/index.html
+
+Remote access to the sources through CVS
+========================================
+
+    You can have read-only access to the most recent developments on 
+    libFoundation using anonymous CVS. To be able to do this setup the 
+    CVSROOT environment variable like this (a Bourne shell is assumed): 
+
+      CVSROOT=:pserver:anoncvs@cvs.net-community.com:/libFoundation
+      export CVSROOT
+
+    Then do a 'cvs login'. You will be prompted to introduce a password, 
+    enter anoncvs.
+
+    Then issue this command to get the sources: 
+
+      cvs -z 3 checkout libFoundation
+
+    Once you have the sources checked out you can update them to the 
+    recent changes by running inside of libFoundation source tree: 
+
+      cvs -z 3 update
+
+GNUstep makefile package (gstep-make)
+=====================================
+
+    GNUstep includes a makefile package, called gstep-make, which is
+    supported by the libFoundation. The package is available at the
+    GNUstep site (ftp.gnustep.org).
+    Take a look at the libFoundation INSTALL file on how to compile
+    lF using gstep-make.
+
+Ports
+=====
+
+    This package was compiled and tested on these machines:
+
+    m68k-next-nextstep3
+
+       The package was compiled and tested successfully using the
+       2.6.3 and 2.7.2 versions of compiler and with both NeXT and
+       GNU runtimes.  Returning of aggregates of all sizes works well
+       with both runtimes.
+
+    i386-next-nextstep3
+
+       The package was compiled and tested successfully using the
+       2.6.3 and 2.7.2 versions of compiler and with both NeXT and
+       GNU runtimes.  Returning of aggregates of all sizes works well
+       with both runtimes.
+
+    i386-next-nextstep4
+
+       The package was compiled and tested successfully using the
+       2.7.2.1 version of compiler with GNU runtime. The port of GNU
+       compiler on this machine does not work with nested functions
+       so parts of exception handling facility don't work.
+
+    i386-pc-linux-gnu
+
+       The package was compiled on linux with ELF using the 2.7.2.1,
+       with GCC 2.8.1 and with EGCS 1.0.3. All the tests ran
+       successfully, except some NSInvocation tests that crash when
+       returning some structures.
+
+    i386-pc-cygwin32
+
+       The package was compiled using the Cygnus Win32 beta 17.1
+       binaries, with the libobjc.a built from the newer gcc sources
+       with the 960906 runtime patch applied.
+
+    i386-pc-mingw32
+
+        The port to mingw32 is currently in progress. See README.mingw32 
+        for information. The package is cross-compiled using egcs 1.1.1.
+
+    i386-sun-solaris2.5.1
+
+       The package was compiled with the 2.7.2.1 compiler with the
+       970317 runtime patch applied.
+
+    sparc-sun-solaris2.5
+
+       The package was compiled with the 2.7.2.1 compiler with the
+       960906 runtime patch applied.
+        See README.sparc for more information.
+
+    sparc-sun-solaris2.6
+
+       The package was compiled with a modified egcs 1.1.1 compiler.
+        See README.sparc for more information.
+
+    alpha-unknown-linux-gnu
+
+       The package was compiled using a pre-release of GCC version
+       2.8. Still needs some work to finish the NSInvocation and
+       NSMethodSignature machine dependent macros.
+
+    powerpc-ibm-aix4.1.5.0
+
+       The package was compiled using the EGCS 1.0.3a compiler with a
+       patch applied to it; the patch can be found in the
+       libFoundation's distribution. NSInvocation and
+       NSMethodSignature have been ported.
+    
+    Some preliminary work has been done on HPUX 9. This platform is
+    obsolete and we'll try to port the library to 10.20 and 11.0.
+
+
+    Happy hacking,
+
+    Ovidiu Predescu <ovidiup@altavista.net>
+    Mircea Oancea   <mircea@pathcom.com>
+    Helge Hess      <helge.hess@skyrix.com>
+
+
+! Local variables:
+! mode: indented-text
+! End:
diff --git a/libFoundation/README.first b/libFoundation/README.first
new file mode 100644 (file)
index 0000000..b9ff672
--- /dev/null
@@ -0,0 +1,6 @@
+
+Please read the INSTALL file for IMPORTANT information on building
+libFoundation; this file is not the standard installation instructions
+file.
+
+
diff --git a/libFoundation/README.gc b/libFoundation/README.gc
new file mode 100644 (file)
index 0000000..954f0b9
--- /dev/null
@@ -0,0 +1,67 @@
+
+Starting with the release 0.9.0, libFoundation supports the Boehm's
+garbage collector as an alternative to the standard memory allocation
+from OpenStep. We consider the new mechanism as a better alternative
+to the standard way because of its benefits:
+
+* the programmer is no longer required to use the
+  -retain/release/autorelease messages, so a source of bugs introduced
+  by the missuse of these methods is removed
+
+* the reference counting memory management is unable to properly
+  handle graphs of objects that contain cycles. This is not the case
+  with the Boehm's conservative collector, it automatically eliminates
+  the cycles.
+
+
+To work with the Boehm's collector several changes were made to the
+Objective-C runtime. Here is a small description of the changes to the
+GNU runtime to support the Boehm's collector:
+
+* a new member was added to the objc_class, it keeps the type
+  description of each class. This type description is needed because
+  we use the typed memory allocation available in Boehm's collector to
+  maximize the performance and to be able to use the so-called
+  'invisible' pointers (see below).
+  [Be careful to use typed memory with variable sized instances !!!]
+
+* defines two new runtime functions, class_get_gc_object_type and
+  class_ivar_set_gcinvisible. The first function provides access to
+  the type descriptor of a class. The second function marks a named
+  instance variable name as invisible to the collector, aka a pointer
+  which is not considered by the collector a reference to a particular
+  zone of memory.
+
+* the allocation functions are set up to the the Boehm's collector.
+
+Currently only the GNU runtime is supported and I don't think I'll be
+able to add support for NeXT runtime anytime soon because this support
+requires access to the runtime sources :-(.
+
+The garbage collected library is chosen automatically by the makefile
+package when you specify the gc=yes flag to the top-level make
+process, in addition to the rest of the options:
+
+   $ make debug=yes gc=yes
+
+This happens automatically only when you're working with libFoundation
+in the GNUstep environment. If you're working in the standalone
+environment, you should add -DLIB_FOUNDATION_BOEHM_GC=1 to the
+compiler's command line and link against libFoundation_gc.a or
+libFoundation_gc.so.
+
+The library is installed in a different directory than the normal one,
+the library combo is extended with one more part that specifies the
+Boehm's GC. To take advantage of the Boehm's collector, you will need
+to rebuild all your libraries so that they'll exist in this
+directory. Other than that you normaly don't have to modify your
+programs except for optimizing them for the presence of Boehm's
+collector. libFoundation for example removes out all of the
+retain/release/autorelease messages sent to objects so that the
+overhead of sending these messages is completely eliminated.
+
+
+
+! Local variables:
+! mode: indented-text
+! End:
diff --git a/libFoundation/README.mingw32 b/libFoundation/README.mingw32
new file mode 100644 (file)
index 0000000..fdb18af
--- /dev/null
@@ -0,0 +1,208 @@
+libFoundation on Windows mingw32 README
+=======================================
+
+Intro
+=====
+
+    I have started to port the libFoundation library to Windows 95/NT by
+    using the so called mingw32 environment. Mingw32 is a GNU compilation
+    environment containing gcc, ld and other tools.
+    The port is done in a cross-compilation environment. This is significant
+    mostly because configure and the Makefiles might not work on Win32 because
+    of file naming problems (slash vs backslash).
+    First attempts are made to compile lF using mingw32 only, that is, without
+    cross-compilation and without cygwin, see below for issues.
+
+Mingw32
+=======
+
+    The libFoundation compiles with a sparc-solaris-X-i386-mingw32 compiler in
+    the GNUstep make environment. Quite a lot information regarding Unix
+    to Windows porting using GNU tools is contained on this site:
+        
+        http://www.xraylith.wisc.edu/~khan/software/gnu-win32/
+    
+    The site includes a HOWTO file for creating a cross-compiler with a
+    i386-mingw32 target which I found *very* useful.
+
+    I recently modified libFoundation to use the Win32 API libraries at
+
+        http://www.acc.umu.se/~anorland/gnu-win32/w32api.html
+
+    These includes/libraries are much more extensive than the ones delivered
+    with mingw32. Probably they will make it into the mingw32 distribution.
+
+    There are some other Unix-to-Windows porting packages, especially Cygwin
+    from http://www.cygnus.com. Cygwin emulates large parts of Unix
+    in it's environment and also provides a Unix shell environment that
+    might be used to host native mingw32 compiles.
+    The major advantages of mingw32 is that the resulting executables are
+    not covered by GPL and that it doesn't require any additional libraries but
+    the ones provided by Windows itself. The disadvantage is that more porting
+    is required ..
+
+GNUstep-make
+============
+
+    If compiling lF with gstep-make (--with-gnustep configure switch) you
+    have to configure gstep-make for cross-compilation. This is usually 
+    done with a sequence like this:
+
+      cd make
+      setenv CC      i386-mingw32-gcc
+      setenv RANLIB  i386-mingw32-ranlib
+      setenv AR      i386-mingw32-ar
+      setenv DLLTOOL i386-mingw32-dlltool
+      rm -f config.cache
+      ./configure --prefix=/usr/local/GNUstep \
+        --target="i386-mingw32" \
+        --program-suffix=exe
+      unsetenv CC RANLIB AR DLLTOOL
+      make install
+
+    Never forget to remove config.cache before calling configure on a different
+    target !!!
+    If you have done this you can use just
+
+      make target="i386-mingw32"
+
+    to cross compile a gstep-make package.
+
+Building lF
+===========
+
+    If you have correctly installed your mingw32 x-tools and gstep-make package,
+    compilation of libFoundation for Windows is quite easy:
+
+      cd libFoundation
+      setenv CC i386-mingw32-gcc
+      rm -f config.cache
+      ./configure --with-gnustep --target="i386-mingw32"
+      unsetenv CC
+      make target="i386-mingw32" install
+
+    That's it ! The resulting binaries will be placed in the appropriate 
+    platform subdirectories of the GNUstep hierachy, this way you can keep 
+    libraries for multiple targets in one hierachy.
+
+Native Build of lF with cygwin tools
+====================================
+
+    I managed to compile lF on NT using the cygwin environment (this is 
+    actually a x-compilation as well, from cygwin->mingw32). Note that the
+    cygwin environment is only used as the compilation environment, the 
+    resulting binary is still mingw32-only.
+    
+    To get this running I got the b20 version of cygwin:
+    
+       http://sourceware.cygnus.com
+    
+    The gcc 2.95.2 compilers from Mumit Khan:
+    
+       ftp://www.xraylith.wisc.edu/pub/khan/gnu-win32/mingw32/
+    
+    The GNUstep-make package:
+    
+       ftp://ftp.gnustep.org/pub/gnustep
+    
+    First you need to configure gstep-make:
+    
+       cd make
+       ./configure --target=i386-mingw32       \
+                  --prefix=/cygwin/GNUstep     \
+                  --program-suffix=.exe        \
+                  --with-library-combo=gnu-fd-gnu-nil
+       make target=i386-mingw32 install
+    
+    Note the --target switch. If you miss that, gstep-make will be configured
+    for producing cygwin binaries, which is a different story - so don't
+    forget it ! (See below for a hack avoiding this x-setup).
+    If you get a message from native make like 'unmatched "', you probably
+    are using a wrong shell. Check whether the SHELL variable and /bin/sh
+    matches your standard shell (eg cygwin bash or zsh)
+    If you get makefiles errors, you may want to make sure that you are
+    running cygwin in unix-make-mode (eg echo $MAKE_MODE)
+    
+    If you like you can patch config.guess to output 'i386-pc-mingw32', this
+    makes running tools a bit nicer (this way you avoid making config.guess
+    guess the environment as being cygwin). To do that, replace config.guess
+    with these contents:
+
+      #!/bin/sh
+      echo "i386-pc-mingw32"
+    
+    After you have installed GNUstep makefiles, source them (you might also
+    want to source them on every startup in the .profile file).
+
+Native Build of lF with mingw32 tools
+=====================================
+    
+    It will also be possible to compile libFoundation without the help of a
+    Unix system or a Unix emulation like cygwin. The native build process needs
+    some more stuff than just the mingw32 binaries provided by Mumit Khan.
+    
+    You need at least:
+    
+      egcs and make binaries as provided by Mumit Khan:
+
+        ftp://www.xraylith.wisc.edu/pub/khan/gnu-win32/mingw32/
+      
+      an appropriate sh.exe, eg the zsh:
+      
+        ftp://ftp.blarg.net/users/amol/
+      
+      (note that the native bash I retrieved didn't work with make)
+      
+      a sed:
+      
+        ftp://agnes.dida.physik.uni-essen.de/home/janjaap/mingw32/newnew/
+      
+      some other tools are useful but not required if one does some handwork:
+      
+        mkdir  (the DOS mkdir is an internal command and not available in zsh)
+        rm
+      
+      I figured out that you need at least these to run configure:
+      
+        a sh shell:
+        
+          see above
+        
+        grep:
+        
+          http://agnes.dida.physik.uni-essen.de/~janjaap/mingw32/download.html
+        
+        cat
+      
+      The Unix95 kit provides some Unix utilities described (it's also called
+      'Virtually Unix'):
+      
+        http://www.itribe.net/virtunix/files/unix95.7.zip
+    
+    Note that the library doesn't yet build cleanly, I work on this.
+
+Other useful native Windows software
+====================================
+
+    Native Xemacs:
+    
+      ftp://ftp.ese-metz.fr/pub/xemacs/win32/
+    
+    Native tcsh:
+    
+      ftp://ftp.blarg.net/users/amol/tcsh/
+
+    Further Mingw32 software:
+    
+      ftp://agnes.dida.physik.uni-essen.de/home/janjaap/mingw32
+      ftp://www.xraylith.wisc.edu/pub/khan
+      ftp://ftp.franken.de/pub/win32/develop/gnuwin32/mingw32
+
+---
+Helge Hess (hh@mdlink.de)
+MDlink online service center
+2000-02-09
+
+! Local variables:
+! mode: indented-text
+! End:
diff --git a/libFoundation/README.osx b/libFoundation/README.osx
new file mode 100644 (file)
index 0000000..c2615d6
--- /dev/null
@@ -0,0 +1,65 @@
+GNU Objective-C/libFoundation on MacOSX README
+==============================================
+
+Intro
+=====
+
+    It doesn't work out of the box to compile libFoundation on
+    Darwin or MacOSX, primarily because the default compiler
+    produces binaries for the Apple ObjC runtime which libFoundation
+    doesn't seem to support anymore.
+
+GNU Runtime
+===========
+
+    To get a working GNU runtime, you should first fetch & compile 
+    GCC 3.2, this worked out-of-the-box in OSX 10.1.5.
+
+GNUstep Makefiles
+=================
+
+    I only tried with GNUstep Makefiles (libFoundation theoretically
+    can compile without them ...)
+
+Configuration
+=============
+
+    Before invoking configure you need to set the following environment
+    variables:
+
+      export CFLAGS="-traditional-cpp -fgnu-runtime"
+      export OBJC_RUNTIME_FLAG="-fgnu-runtime"
+      export LDFLAGS="-L/usr/local/gcc32/lib/"
+      export CC="/usr/local/gcc32/bin/gcc"
+      export OBJC_LIBS="/usr/local/gcc32/lib/libobjc.a"
+      export LIBS="/usr/local/gcc32/lib/libobjc.a"
+    
+    at least this worked for me ;-)
+
+    Then you can call configure:
+    
+      ./configure --with-gnustep
+
+    Ensure that configure recognized the GNU runtime:
+
+      checking for the Objective-C runtime... GNU
+
+    REALLY! ;-) Also ensure that these ObjC things are found:
+    
+      checking for objc_mutex_allocate... yes
+      checking for objc_malloc... yes
+
+    Otherwise something is still wrong ...
+
+TO BE COMPLETED
+  - currently I get a lot of weird gcc 3.2 debugging output
+    during compilation ..., so didn't get it working yet
+
+---
+2002-08-16
+Helge Hess (hh@skyrix.com)
+SKYRIX Software AG
+
+! Local variables:
+! mode: indented-text
+! End:
diff --git a/libFoundation/README.sparc b/libFoundation/README.sparc
new file mode 100644 (file)
index 0000000..6b0d94b
--- /dev/null
@@ -0,0 +1,137 @@
+GNU Objective-C/libFoundation on SPARC README
+=============================================
+
+Intro
+=====
+
+    Some people may have problems with libFoundation together with
+    SPARC machines and/or with GNU Objective-C on SPARC in
+    general. Here are collected some known issues.
+
+Dates
+=====
+
+    There may be a problem with incorrect dates, but I couldn't
+    reproduce it on our SPARC/Solaris 2.6. If you want to ensure that
+    it works on your system, try this:
+
+      if (time(NULL) != (time_t)([[NSDate date] timeIntervalSince1970]))
+        NSLog(@"timezone correction error");
+
+    If this shows the error, something is probably wrong.
+
+ObjC-Runtime
+============
+
+    Sometimes the Objective-C runtime of gcc/egcs is configured incorrectly.
+    In this case configure won't be able to run some libFoundation tests,
+    eg the check for the Objective-C runtime and the check whether nested
+    functions work in cc1obj.
+    
+    The output of configure looks like this:
+
+        checking for the Objective-C runtime... 
+        Cannot determine the Objective-C runtime! Probably you have to specify 
+        some additional libraries needed to link an ObjC program, so please take
+        a look in the config.log file to see the reason and try again.
+        
+        ... and ...
+        
+        checking if the Objective-C compiler crashes with nested functions... yes
+
+    Usually this happens if the runtime was configured to be threaded, in this
+    case a combination of -lthread, -lposix or -lposix4 may be necessary or if
+    no threading is required, egcs should be recompiled with the configure option
+    --with-threads=single.
+
+Multithreading
+==============
+
+    If you want to use the NSThread class in libFoundation you have to
+    do several things, it applies to Solaris in general:
+
+       - Compile the GNU Objective-C runtime with either
+         --enable-threads=solaris or --enable-threads=posix (I would
+         recommend 'solaris', Posix is just a layer on top of it).
+         Watch out that the runtime files are compiled with
+         -D_REENTRANT, otherwise something is wrong.
+
+       - Compile _all_ your files (including libraries) with the
+         -D_REENTRANT preprocessor flag. This makes the Solaris system
+         libraries thread-safe (like stdio.h or stdlib.h). In the future
+         the gstep-make package should do this automatically, but watch
+         out that the compilation is actually done this way !  - Do
+         never forget to link against 'thread' and if you selected
+         'posix' for the runtime against 'posix' (use the LDFLAGS
+         -lthread). There won't be any linking error if you don't, the
+         program just won't be able to fork new threads. Thread creation
+         errors are not catched by some versions of the runtime and/or
+         library.
+
+    If you watch out for these things Solaris will be one of the best
+    MT environments because of it's M-M threading approach.  For more
+    Solaris threading info take a look on:
+
+        http://www.sun.com/workshop/threads/index.html
+
+    It contains some of the information mentioned above and much more.
+
+Dynamic Invocations (forward::, forwardInvocation:)
+===================================================
+
+    There are problems related to SPARC with the Objective-C runtime
+    and there may be problems with NSMethodSignature and/or
+    NSInvocation.
+
+    First the runtime probably won't work correctly (to be exact, the
+    objc_msg_sendv function). According to Richard Henderson from
+    Cygnus this is because:
+
+        "__builtin_apply will not work on any machine that doesn't simply push 
+         arguments on the stack."
+
+    Since objc_msg_sendv relies on __builtin_apply it won't work too. There is
+    a patch for gcc-2.8.0 on
+
+        ftp://alpha.gnu.org/pub/gnu/gnustep/contrib/gcc-2.8.0-sparc.diff
+
+    which apparently fixed the problem for me. The patch works with
+    egcs-1.0.3 as well and for egcs>1.1 with small modifications. It
+    works on the machine description file (gcc/config/sparc/sparc.md)
+    for SPARC.  Regarding this patch Richard Henderson said:
+
+        "The extention is an abomination and should be removed."
+
+    and
+      ---snip---
+        I should have mentioned that the proper way to do something
+        like what objc is trying to do with __builtin_apply is to use
+        a library like libffi.
+
+           ftp://ftp.cygnus.com/pub/home/green/libffi-1.20.tar.gz
+      ---snap---
+    
+    So apparently there is a much bigger problem with it in general. I
+    found the homepage of libffi on this URL:
+
+        http://www.cygnus.com/~green/libffi.html
+
+    Maybe one should take a look whether this library can be
+    integrated with the runtime.
+
+    Addition: After some discussion with Ovidiu it seems that
+    __builtin_apply is really broken. Libffi is a library which is
+    somewhat like NSMethodSignature and NSInvocation, it's nice, but
+    not 'what objc is trying to do'. Forwarding just saves/restores
+    all args and doesn't attempt to process them, as libffi
+    does. Libffi might be used to implement NSInvocation on system for
+    which no port exists.
+
+---
+1999-05-25
+Helge Hess (hh@mdlink.de)
+MDlink online service center
+
+! Local variables:
+! mode: indented-text
+! End:
diff --git a/libFoundation/Resources/CharacterSets/alphanumericCharacterSet.bitmap b/libFoundation/Resources/CharacterSets/alphanumericCharacterSet.bitmap
new file mode 100644 (file)
index 0000000..6cc2d7e
Binary files /dev/null and b/libFoundation/Resources/CharacterSets/alphanumericCharacterSet.bitmap differ
diff --git a/libFoundation/Resources/CharacterSets/controlCharacterSet.bitmap b/libFoundation/Resources/CharacterSets/controlCharacterSet.bitmap
new file mode 100644 (file)
index 0000000..6817001
Binary files /dev/null and b/libFoundation/Resources/CharacterSets/controlCharacterSet.bitmap differ
diff --git a/libFoundation/Resources/CharacterSets/decimalDigitCharacterSet.bitmap b/libFoundation/Resources/CharacterSets/decimalDigitCharacterSet.bitmap
new file mode 100644 (file)
index 0000000..d0bc0f0
Binary files /dev/null and b/libFoundation/Resources/CharacterSets/decimalDigitCharacterSet.bitmap differ
diff --git a/libFoundation/Resources/CharacterSets/decomposableCharacterSet.bitmap b/libFoundation/Resources/CharacterSets/decomposableCharacterSet.bitmap
new file mode 100644 (file)
index 0000000..342cb4f
Binary files /dev/null and b/libFoundation/Resources/CharacterSets/decomposableCharacterSet.bitmap differ
diff --git a/libFoundation/Resources/CharacterSets/emptyCharacterSet.bitmap b/libFoundation/Resources/CharacterSets/emptyCharacterSet.bitmap
new file mode 100644 (file)
index 0000000..6d17cf9
Binary files /dev/null and b/libFoundation/Resources/CharacterSets/emptyCharacterSet.bitmap differ
diff --git a/libFoundation/Resources/CharacterSets/illegalCharacterSet.bitmap b/libFoundation/Resources/CharacterSets/illegalCharacterSet.bitmap
new file mode 100644 (file)
index 0000000..f86e548
Binary files /dev/null and b/libFoundation/Resources/CharacterSets/illegalCharacterSet.bitmap differ
diff --git a/libFoundation/Resources/CharacterSets/letterCharacterSet.bitmap b/libFoundation/Resources/CharacterSets/letterCharacterSet.bitmap
new file mode 100644 (file)
index 0000000..dfdc184
Binary files /dev/null and b/libFoundation/Resources/CharacterSets/letterCharacterSet.bitmap differ
diff --git a/libFoundation/Resources/CharacterSets/lowercaseLetterCharacterSet.bitmap b/libFoundation/Resources/CharacterSets/lowercaseLetterCharacterSet.bitmap
new file mode 100644 (file)
index 0000000..bae9d52
Binary files /dev/null and b/libFoundation/Resources/CharacterSets/lowercaseLetterCharacterSet.bitmap differ
diff --git a/libFoundation/Resources/CharacterSets/nonBaseCharacterSet.bitmap b/libFoundation/Resources/CharacterSets/nonBaseCharacterSet.bitmap
new file mode 100644 (file)
index 0000000..208c14b
Binary files /dev/null and b/libFoundation/Resources/CharacterSets/nonBaseCharacterSet.bitmap differ
diff --git a/libFoundation/Resources/CharacterSets/punctuationCharacterSet.bitmap b/libFoundation/Resources/CharacterSets/punctuationCharacterSet.bitmap
new file mode 100644 (file)
index 0000000..1a39f8c
Binary files /dev/null and b/libFoundation/Resources/CharacterSets/punctuationCharacterSet.bitmap differ
diff --git a/libFoundation/Resources/CharacterSets/uppercaseLetterCharacterSet.bitmap b/libFoundation/Resources/CharacterSets/uppercaseLetterCharacterSet.bitmap
new file mode 100644 (file)
index 0000000..b9a8a1c
Binary files /dev/null and b/libFoundation/Resources/CharacterSets/uppercaseLetterCharacterSet.bitmap differ
diff --git a/libFoundation/Resources/CharacterSets/whitespaceAndNewlineCharacterSet.bitmap b/libFoundation/Resources/CharacterSets/whitespaceAndNewlineCharacterSet.bitmap
new file mode 100644 (file)
index 0000000..0ae4d0a
Binary files /dev/null and b/libFoundation/Resources/CharacterSets/whitespaceAndNewlineCharacterSet.bitmap differ
diff --git a/libFoundation/Resources/CharacterSets/whitespaceCharacterSet.bitmap b/libFoundation/Resources/CharacterSets/whitespaceCharacterSet.bitmap
new file mode 100644 (file)
index 0000000..ea3fbe2
Binary files /dev/null and b/libFoundation/Resources/CharacterSets/whitespaceCharacterSet.bitmap differ
diff --git a/libFoundation/Resources/Defaults/English.plist b/libFoundation/Resources/Defaults/English.plist
new file mode 100644 (file)
index 0000000..a89f241
--- /dev/null
@@ -0,0 +1,41 @@
+{
+    NSWeekDayNameArray = (
+       Monday, Tuesday, Wednesday, Thusday, Friday, Saturday, Sunday
+    );
+    NSShortWeekDayNameArray = (
+       Mon, Tue, Wed, Thu, Fri, Sat, Sun
+    );
+    NSMonthNameArray = (
+       January, February, March, April,
+       May, June, July, August,
+       September, October, November, December
+    );
+    NSShortMonthNameArray = (
+       Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
+    );
+    NSTimeFormatString            = "%H:%M:%S";
+    NSDateFormatString            = "%a, %b %d, %Y";
+    NSDateTimeOrdering            = MDYH;
+    NSTimeDateFormatString        = "%a %b %d %Y %H:%M:%S %z";
+    NSShortTimeDateFormatString   = "%m.%d.%y %H:%M:%S";
+    NSCurrencySymbol              = "$";
+    NSDecimalSeparator            = ".";
+    NSThousandsSeparator          = ",";
+    NSInternationalCurrencyString = USD;
+    NSCurrencyString              = "$";
+    NSDecimalDigits               = (0, 1, 2 , 3, 4, 5, 6, 7, 8, 9);
+    NSAMPMDesignation             = (AM, PM);
+    NSEarlierTimeDesignations     = ( prior, last, past, ago );
+    NSLaterTimeDesignations       = ( next );
+    NSNextDayDesignations         = ( tomorrow );
+    NSNextNextDayDesignations     = ( next );
+    NSPriorDayDesignations        = ( yesterday );
+    NSThisDayDesignations         = ( today, now );
+    NSHourNameDesignations        = ( 
+        (0,  midnight),  (10, morning), (12, noon, lunch), 
+        (14, afternoon), (19, dinner) 
+    );
+    NSPositiveCurrencyFormatString= "$9,999.00";
+    NSNegativeCurrencyFormatString= "-$9,999.00";
+    NSShortDateFormatString       = "%d %b %Y";
+}
diff --git a/libFoundation/Resources/Defaults/French.plist b/libFoundation/Resources/Defaults/French.plist
new file mode 100644 (file)
index 0000000..4cc3f02
--- /dev/null
@@ -0,0 +1,26 @@
+{
+    NSWeekDayNameArray = (
+       Lundi, Mardi, Mercredi, Jeudi, Vendredi, Samedi, Dimanche
+    );
+    NSShortWeekDayNameArray = (
+       Lun, Mar, Mer, Jeu, Ven, Sam, Dim
+    );
+    NSMonthNameArray = (
+       Janvier, Fevrier, Mars, Avril, Mai, Juin, Juillet, Aout, Septembre,
+       Octobre, Novembre, Decembre
+    );
+    NSShortMonthNameArray = (
+       Jan, Fev, Mar, Avr, Mai, Jun, Jul, Aou, Sep, Oct, Nov, Dec
+    );
+    NSTimeFormatString = "%H:%M:%S";
+    NSDateFormatString = "%a, %b %d, %Y";
+    NSTimeDateFormatString = "%a %b %d %Y %H:%M:%S %z";
+    NSShortTimeDateFormatString = "%m.%d.%y %H:%M:%S";
+    NSDecimalSeparator = ",";
+    NSThousandsSeparator = " ";
+    NSInternationalCurrencyString = FRF;
+    NSCurrencySymbol = F;
+    NSCurrencyString = F;
+    NSDecimalDigits = (0, 1, 2 , 3, 4, 5, 6, 7, 8, 9);
+    NSAMPMDesignation = (AM, PM);
+}
diff --git a/libFoundation/Resources/Defaults/German.plist b/libFoundation/Resources/Defaults/German.plist
new file mode 100644 (file)
index 0000000..75cbfd5
--- /dev/null
@@ -0,0 +1,39 @@
+{
+    NSWeekDayNameArray = (
+       Montag, Dienstag, Mittwoch, Donnerstag, Freitag, Samstag, Sonntag
+    );
+    NSShortWeekDayNameArray = (
+       Mo, Di, Mi, Do, Fr, Sa, So
+    );
+    NSMonthNameArray = (
+       Januar, Februar, Marz, April, Mai, Juni, Juli, August, September,
+       Oktober, November, Dezember
+    );
+    NSShortMonthNameArray = (
+       Jan, Feb, Mrz, Apr, Mai, Jun, Jul, Aug, Sep, Okt, Nov, Dez
+    );
+    NSTimeFormatString = "%H:%M:%S";
+    NSDateFormatString = "%a, %b %d, %Y";
+    NSTimeDateFormatString = "%a %b %d %Y %H:%M:%S %z";
+    NSShortTimeDateFormatString = "%m.%d.%y %H:%M:%S";
+    NSDecimalSeparator = ",";
+    NSThousandsSeparator = ".";
+    NSInternationalCurrencyString = DEM;
+    NSCurrencySymbol = DM;
+    NSCurrencyString = DM;
+    NSDecimalDigits = (0, 1, 2 , 3, 4, 5, 6, 7, 8, 9);
+    NSAMPMDesignation = (AM, PM);
+    NSEarlierTimeDesignations     = ( vorher );
+    NSLaterTimeDesignations       = ( nachher );
+    NSNextDayDesignations         = ( morgen );
+    NSNextNextDayDesignations     = ( uebermorgen );
+    NSPriorDayDesignations        = ( gestern );
+    NSThisDayDesignations         = ( heute, jetzt );
+    NSHourNameDesignations        = ( 
+        (0,  Mitternacht),  (10, Vormittag), (12, Mittag, lunch), 
+        (14, Nachmittag), (19, Abend) 
+    );
+    NSPositiveCurrencyFormatString= "$9.999,00";
+    NSNegativeCurrencyFormatString= "-$9.999,00";
+    NSShortDateFormatString       = "%b %d %Y";
+}
diff --git a/libFoundation/Resources/Defaults/NSGlobalDomain.plist b/libFoundation/Resources/Defaults/NSGlobalDomain.plist
new file mode 100644 (file)
index 0000000..e5023f3
--- /dev/null
@@ -0,0 +1,4 @@
+{
+    Languages    = (English);
+    TimeZoneName = GMT;
+}
diff --git a/libFoundation/Resources/Defaults/Romanian.plist b/libFoundation/Resources/Defaults/Romanian.plist
new file mode 100644 (file)
index 0000000..3f036b5
--- /dev/null
@@ -0,0 +1,26 @@
+{
+    NSWeekDayNameArray = (
+       Luni, Marti, Miercuri, Joi, Vineri, Simbata
+    );
+    NSShortWeekDayNameArray = (
+       Lu, Ma, Mi, Jo, Vi, Si, Du
+    );
+    NSMonthNameArray = (
+       Ianuarie, Februarie, Martie, Aprilie, Mai, Iunie, Iulie, August,
+       Septembrie, Octombrie, Noiembrie, Decembrie
+    );
+    NSShortMonthNameArray = (
+       Ian, Feb, Mar, Apr, Mai, Iun, Iul, Aug, Sep, Oct, Noi, Dec
+    );
+    NSTimeFormatString = "%H:%M:%S";
+    NSDateFormatString = "%a, %b %d, %Y";
+    NSTimeDateFormatString = "%a %b %d %Y %H:%M:%S %z";
+    NSShortTimeDateFormatString = "%m.%d.%y %H:%M:%S";
+    NSDecimalSeparator = ",";
+    NSThousandsSeparator = " ";
+    NSInternationalCurrencyString = LEI;
+    NSCurrencySymbol = Lei;
+    NSCurrencyString = Lei;
+    NSDecimalDigits = (0, 1, 2 , 3, 4, 5, 6, 7, 8, 9);
+    NSAMPMDesignation = (AM, PM);
+}
diff --git a/libFoundation/Resources/GNUmakefile b/libFoundation/Resources/GNUmakefile
new file mode 100644 (file)
index 0000000..85c34ee
--- /dev/null
@@ -0,0 +1,124 @@
+# GNUmakefile
+#
+# Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+# All rights reserved.
+#
+# Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+#
+# This file is part of libFoundation.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose and without fee is hereby granted, provided
+# that the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation.
+#
+# We disclaim all warranties with regard to this software, including all
+# implied warranties of merchantability and fitness, in no event shall
+# we be liable for any special, indirect or consequential damages or any
+# damages whatsoever resulting from loss of use, data or profits, whether in
+# an action of contract, negligence or other tortious action, arising out of
+# or in connection with the use or performance of this software.
+
+TOP    = ..
+
+GNUSTEP_INSTALLATION_DIR = $(GNUSTEP_SYSTEM_ROOT)
+
+-include $(GNUSTEP_SYSTEM_ROOT)/Makefiles/common.make
+-include $(TOP)/Foundation/$(GNUSTEP_TARGET_CPU)/$(GNUSTEP_TARGET_OS)/$(OBJC_RUNTIME)/config.mak
+-include $(TOP)/config.mak
+
+CHARSETS = alphanumericCharacterSet.bitmap controlCharacterSet.bitmap \
+       decimalDigitCharacterSet.bitmap decomposableCharacterSet.bitmap \
+       emptyCharacterSet.bitmap illegalCharacterSet.bitmap \
+       letterCharacterSet.bitmap lowercaseLetterCharacterSet.bitmap \
+       nonBaseCharacterSet.bitmap uppercaseLetterCharacterSet.bitmap \
+       whitespaceAndNewlineCharacterSet.bitmap whitespaceCharacterSet.bitmap \
+       punctuationCharacterSet.bitmap
+
+TIMEZONES = CET CST6CDT EET EST EST5EDT GB-Eire GMT GMT+1 GMT+10 \
+       GMT+11 GMT+12 GMT+13 GMT+2 GMT+3 GMT+4 GMT+5 GMT+6 GMT+7 GMT+8 GMT+9 \
+       GMT-1 GMT-10 GMT-11 GMT-12 GMT-2 GMT-3 GMT-4 GMT-5 GMT-6 GMT-7 GMT-8 \
+       GMT-9 Greenwich Singapore Iceland Japan MET SGT MST MST7MDT NZ Poland \
+       PST8PDT UCT UTC Universal HST W-SU WET Turkey RegionsDictionary \
+       GMT+0_30 GMT+10_30 GMT+11_30 GMT+1_30 GMT+2_30 GMT+3_30 GMT+4_30 \
+       GMT+5_30 GMT+6_30 GMT+7_30 GMT+8_30 GMT+9_30 GMT-0_30 GMT-10_30 \
+       GMT-11_30 GMT-1_30 GMT-2_30 GMT-3_30 GMT-4_30 GMT-5_30 GMT-6_30 \
+       GMT-7_30 GMT-8_30 GMT-9_30 GMT+14 CLST SAST
+
+TIMEZONE_DIRS = Australia Canada SystemV US Europe Asia
+
+Australia_ZONES = North NSW Queensland South Victoria West Tasmania
+Canada_ZONES = Atlantic Central East-Saskatchewan Eastern Mountain \
+       Newfoundland Pacific Yukon
+SystemV_ZONES = AST4 AST4ADT CST6 CST6CDT EST5 EST5EDT HST10 MST7 MST7MDT \
+       PST8 PST8PDT YST9 YST9YDT
+US_ZONES = Arizona Central Eastern Hawaii Mountain Pacific Yukon Pacific-New \
+       East-Indiana
+EUROPE_ZONES = Berlin Paris Brussels
+
+DEFAULTS = $(wildcard Defaults/*.plist)
+
+all clean distclean realclean check check-all:
+
+ifeq ($(FHS_INSTALL_ROOT),)
+INSTALL_DIR = $(GNUSTEP_INSTALLATION_DIR)/Libraries/Resources/libFoundation
+else
+INSTALL_DIR = $(FHS_INSTALL_ROOT)/share/libFoundation
+endif
+
+install:
+       (PATH=..:$$PATH; export PATH; \
+       $(TOP)/mkinstalldirs $(INSTALL_DIR)/CharacterSets; \
+       $(TOP)/mkinstalldirs $(INSTALL_DIR)/TimeZoneInfo; \
+       $(TOP)/mkinstalldirs $(INSTALL_DIR)/Defaults; \
+       for f in $(TIMEZONES); do \
+           $(INSTALL_DATA) $(addprefix TimeZoneInfo/, $$f) \
+               $(INSTALL_DIR)/TimeZoneInfo; \
+       done; \
+       $(TOP)/mkinstalldirs $(INSTALL_DIR)/TimeZoneInfo/Australia; \
+       $(TOP)/mkinstalldirs $(INSTALL_DIR)/TimeZoneInfo/Canada; \
+       $(TOP)/mkinstalldirs $(INSTALL_DIR)/TimeZoneInfo/SystemV; \
+       $(TOP)/mkinstalldirs $(INSTALL_DIR)/TimeZoneInfo/US; \
+       $(TOP)/mkinstalldirs $(INSTALL_DIR)/TimeZoneInfo/Europe; \
+       $(TOP)/mkinstalldirs $(INSTALL_DIR)/TimeZoneInfo/Africa; \
+       $(TOP)/mkinstalldirs $(INSTALL_DIR)/TimeZoneInfo/Asia; \
+       for f in $(Australia_ZONES); do \
+           $(INSTALL_DATA) \
+             $(addprefix TimeZoneInfo/Australia/, $$f) \
+             $(INSTALL_DIR)/TimeZoneInfo/Australia; \
+       done; \
+       for f in $(Canada_ZONES); do \
+           $(INSTALL_DATA) \
+               $(addprefix TimeZoneInfo/Canada/, $$f) \
+           $(INSTALL_DIR)/TimeZoneInfo/Canada; \
+       done; \
+       for f in $(SystemV_ZONES); do \
+       $(INSTALL_DATA) \
+           $(addprefix TimeZoneInfo/SystemV/, $$f) \
+           $(INSTALL_DIR)/TimeZoneInfo/SystemV; \
+       done; \
+       for f in $(US_ZONES); do \
+           $(INSTALL_DATA) \
+               $(addprefix TimeZoneInfo/US/, $$f) \
+           $(INSTALL_DIR)/TimeZoneInfo/US; \
+       done; \
+       for f in $(EUROPE_ZONES); do \
+           $(INSTALL_DATA) \
+               $(addprefix TimeZoneInfo/Europe/, $$f) \
+           $(INSTALL_DIR)/TimeZoneInfo/Europe; \
+       done; \
+       for f in $(CHARSETS); do \
+           $(INSTALL_DATA) $(addprefix CharacterSets/, $$f) \
+               $(INSTALL_DIR)/CharacterSets; \
+       done; \
+       for f in $(DEFAULTS); do \
+           if [ ! -f $(INSTALL_DIR)/$$f ]; then \
+             $(INSTALL_DATA) $$f $(INSTALL_DIR)/$$f; \
+            fi;\
+       done)
+
+uninstall:
+       rm -rf $(addprefix $(INSTALL_DIR)/, \
+                   CharacterSets TimeZoneInfo  Defaults)
+
diff --git a/libFoundation/Resources/GNUmakefile.alone b/libFoundation/Resources/GNUmakefile.alone
new file mode 100644 (file)
index 0000000..834efa5
--- /dev/null
@@ -0,0 +1,105 @@
+# GNUmakefile
+#
+# Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+# All rights reserved.
+#
+# Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+#
+# This file is part of libFoundation.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose and without fee is hereby granted, provided
+# that the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation.
+#
+# We disclaim all warranties with regard to this software, including all
+# implied warranties of merchantability and fitness, in no event shall
+# we be liable for any special, indirect or consequential damages or any
+# damages whatsoever resulting from loss of use, data or profits, whether in
+# an action of contract, negligence or other tortious action, arising out of
+# or in connection with the use or performance of this software.
+
+TOP    = ..
+
+-include $(TOP)/config.mak
+
+CHARSETS = alphanumericCharacterSet.bitmap controlCharacterSet.bitmap \
+       decimalDigitCharacterSet.bitmap decomposableCharacterSet.bitmap \
+       emptyCharacterSet.bitmap illegalCharacterSet.bitmap \
+       letterCharacterSet.bitmap lowercaseLetterCharacterSet.bitmap \
+       nonBaseCharacterSet.bitmap uppercaseLetterCharacterSet.bitmap \
+       whitespaceAndNewlineCharacterSet.bitmap whitespaceCharacterSet.bitmap \
+       punctuationCharacterSet.bitmap
+
+TIMEZONES = CET CST6CDT EET EST EST5EDT GB-Eire GMT GMT+1 GMT+10 \
+       GMT+11 GMT+12 GMT+13 GMT+2 GMT+3 GMT+4 GMT+5 GMT+6 GMT+7 GMT+8 GMT+9 \
+       GMT-1 GMT-10 GMT-11 GMT-12 GMT-2 GMT-3 GMT-4 GMT-5 GMT-6 GMT-7 GMT-8 \
+       GMT-9 Greenwich Singapore Iceland Japan MET SGT MST MST7MDT NZ Poland \
+       PST8PDT UCT UTC Universal HST W-SU WET Turkey RegionsDictionary \
+       GMT+0_30 GMT+10_30 GMT+11_30 GMT+1_30 GMT+2_30 GMT+3_30 GMT+4_30 \
+       GMT+5_30 GMT+6_30 GMT+7_30 GMT+8_30 GMT+9_30 GMT-0_30 GMT-10_30 \
+       GMT-11_30 GMT-1_30 GMT-2_30 GMT-3_30 GMT-4_30 GMT-5_30 GMT-6_30 \
+       GMT-7_30 GMT-8_30 GMT-9_30 GMT+14
+
+TIMEZONE_DIRS = Australia Canada SystemV US
+
+Australia_ZONES = North NSW Queensland South Victoria West Tasmania
+Canada_ZONES = Atlantic Central East-Saskatchewan Eastern Mountain \
+       Newfoundland Pacific Yukon
+SystemV_ZONES = AST4 AST4ADT CST6 CST6CDT EST5 EST5EDT HST10 MST7 MST7MDT \
+       PST8 PST8PDT YST9 YST9YDT
+US_ZONES = Arizona Central Eastern Hawaii Mountain Pacific Yukon Pacific-New \
+       East-Indiana
+
+DEFAULTS = $(wildcard Defaults/*.plist)
+
+all clean distclean realclean check check-all:
+
+INSTALL_DIR = $(sharedstatedir)
+
+install:
+       (PATH=..:$$PATH; export PATH; \
+       $(TOP)/mkinstalldirs $(INSTALL_DIR)/CharacterSets; \
+       $(TOP)/mkinstalldirs $(INSTALL_DIR)/TimeZoneInfo; \
+       $(TOP)/mkinstalldirs $(INSTALL_DIR)/Defaults; \
+       for f in $(TIMEZONES); do \
+           $(INSTALL_DATA) $(addprefix TimeZoneInfo/, $$f) \
+               $(INSTALL_DIR)/TimeZoneInfo; \
+       done; \
+       $(TOP)/mkinstalldirs $(INSTALL_DIR)/TimeZoneInfo/Australia; \
+       for f in $(Australia_ZONES); do \
+           $(INSTALL_DATA) \
+             $(addprefix TimeZoneInfo/Australia/, $$f) \
+             $(INSTALL_DIR)/TimeZoneInfo/Australia; \
+       done; \
+       $(TOP)/mkinstalldirs $(INSTALL_DIR)/TimeZoneInfo/Canada; \
+       for f in $(Canada_ZONES); do \
+           $(INSTALL_DATA) \
+               $(addprefix TimeZoneInfo/Canada/, $$f) \
+           $(INSTALL_DIR)/TimeZoneInfo/Canada; \
+       done; \
+       $(TOP)/mkinstalldirs $(INSTALL_DIR)/TimeZoneInfo/SystemV; \
+       for f in $(SystemV_ZONES); do \
+       $(INSTALL_DATA) \
+           $(addprefix TimeZoneInfo/SystemV/, $$f) \
+           $(INSTALL_DIR)/TimeZoneInfo/SystemV; \
+       done; \
+       $(TOP)/mkinstalldirs $(INSTALL_DIR)/TimeZoneInfo/US; \
+       for f in $(US_ZONES); do \
+           $(INSTALL_DATA) \
+               $(addprefix TimeZoneInfo/US/, $$f) \
+           $(INSTALL_DIR)/TimeZoneInfo/US; \
+       done; \
+       for f in $(CHARSETS); do \
+           $(INSTALL_DATA) $(addprefix CharacterSets/, $$f) \
+               $(INSTALL_DIR)/CharacterSets; \
+       done; \
+       for f in $(DEFAULTS); do \
+           $(INSTALL_DATA) $$f $(INSTALL_DIR)/Defaults; \
+       done)
+
+uninstall:
+       rm -rf $(addprefix $(INSTALL_DIR)/, \
+                   CharacterSets TimeZoneInfo  Defaults)
+
diff --git a/libFoundation/Resources/TimeZoneInfo/Asia/Calcutta b/libFoundation/Resources/TimeZoneInfo/Asia/Calcutta
new file mode 100644 (file)
index 0000000..275936c
--- /dev/null
@@ -0,0 +1,3 @@
+{
+   details = {GMT+0530 = {abbrev = GMT+0530; isDST = 0; offset = +5:30:00; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/Australia/NSW b/libFoundation/Resources/TimeZoneInfo/Australia/NSW
new file mode 100644 (file)
index 0000000..96326f2
--- /dev/null
@@ -0,0 +1,177 @@
+{
+    details = {
+       EDT = {abbrev = EDT; isDST = 1; offset = "+11:00:00"; };
+       EST = {abbrev = EST; isDST = 0; offset = "+10:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sat Mar 03 18:00:00 1973 GMT";
+           endDate = "Sat Oct 25 18:00:00 1980 GMT";
+           transitions = (
+               { date = "March/first Saturday/18:00:00"; detail = EST; },
+               { date = "October/last Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 06 18:00:00 1982 GMT";
+           endDate = "Sat Oct 26 18:00:00 1985 GMT";
+           transitions = (
+               { date = "March/first Saturday/18:00:00"; detail = EST; },
+               { date = "October/last Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 17 18:00:00 1990 GMT";
+           endDate = "Sat Oct 19 18:00:00 1991 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 20 18:00:00 1993 GMT";
+           endDate = "Sat Oct 22 18:00:00 1994 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/fourth Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 18 18:00:00 1995 GMT";
+           endDate = "Sat Oct 18 18:00:00 1997 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 17 18:00:00 2001 GMT";
+           endDate = "Sat Oct 18 18:00:00 2003 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 20 18:00:00 2004 GMT";
+           endDate = "Sat Oct 22 18:00:00 2005 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/fourth Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 18 18:00:00 2006 GMT";
+           endDate = "Sat Oct 18 18:00:00 2008 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 20 18:00:00 2010 GMT";
+           endDate = "Sat Oct 22 18:00:00 2011 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/fourth Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 17 18:00:00 2012 GMT";
+           endDate = "Sat Oct 18 18:00:00 2014 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 17 18:00:00 2018 GMT";
+           endDate = "Sat Oct 19 18:00:00 2019 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 20 18:00:00 2021 GMT";
+           endDate = "Sat Oct 22 18:00:00 2022 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/fourth Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 18 18:00:00 2023 GMT";
+           endDate = "Sat Oct 18 18:00:00 2025 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 17 18:00:00 2029 GMT";
+           endDate = "Sat Oct 18 18:00:00 2031 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 20 18:00:00 2032 GMT";
+           endDate = "Sat Oct 22 18:00:00 2033 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/fourth Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 18 18:00:00 2034 GMT";
+           endDate = "Sat Oct 18 18:00:00 2036 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Sat Oct 30 18:00:00 1971 GMT"; detail = EDT; },
+       { date = "Sat Feb 26 18:00:00 1972 GMT"; detail = EST; },
+       { date = "Sat Oct 28 18:00:00 1972 GMT"; detail = EDT; },
+       { date = "Sat Feb 28 18:00:00 1981 GMT"; detail = EST; },
+       { date = "Sat Oct 24 18:00:00 1981 GMT"; detail = EDT; },
+       { date = "Sat Mar 15 18:00:00 1986 GMT"; detail = EST; },
+       { date = "Sat Oct 18 18:00:00 1986 GMT"; detail = EDT; },
+       { date = "Sat Mar 14 18:00:00 1987 GMT"; detail = EST; },
+       { date = "Sat Oct 17 18:00:00 1987 GMT"; detail = EDT; },
+       { date = "Sat Mar 19 18:00:00 1988 GMT"; detail = EST; },
+       { date = "Sat Oct 22 18:00:00 1988 GMT"; detail = EDT; },
+       { date = "Sat Mar 18 18:00:00 1989 GMT"; detail = EST; },
+       { date = "Sat Oct 21 18:00:00 1989 GMT"; detail = EDT; },
+       { date = "Sat Mar 14 18:00:00 1992 GMT"; detail = EST; },
+       { date = "Sat Oct 17 18:00:00 1992 GMT"; detail = EDT; },
+       { date = "Sat Mar 14 18:00:00 1998 GMT"; detail = EST; },
+       { date = "Sat Oct 17 18:00:00 1998 GMT"; detail = EDT; },
+       { date = "Sat Mar 20 18:00:00 1999 GMT"; detail = EST; },
+       { date = "Sat Oct 23 18:00:00 1999 GMT"; detail = EDT; },
+       { date = "Sat Mar 18 18:00:00 2000 GMT"; detail = EST; },
+       { date = "Sat Oct 21 18:00:00 2000 GMT"; detail = EDT; },
+       { date = "Sat Mar 14 18:00:00 2009 GMT"; detail = EST; },
+       { date = "Sat Oct 17 18:00:00 2009 GMT"; detail = EDT; },
+       { date = "Sat Mar 14 18:00:00 2015 GMT"; detail = EST; },
+       { date = "Sat Oct 17 18:00:00 2015 GMT"; detail = EDT; },
+       { date = "Sat Mar 19 18:00:00 2016 GMT"; detail = EST; },
+       { date = "Sat Oct 22 18:00:00 2016 GMT"; detail = EDT; },
+       { date = "Sat Mar 18 18:00:00 2017 GMT"; detail = EST; },
+       { date = "Sat Oct 21 18:00:00 2017 GMT"; detail = EDT; },
+       { date = "Sat Mar 14 18:00:00 2020 GMT"; detail = EST; },
+       { date = "Sat Oct 17 18:00:00 2020 GMT"; detail = EDT; },
+       { date = "Sat Mar 14 18:00:00 2026 GMT"; detail = EST; },
+       { date = "Sat Oct 17 18:00:00 2026 GMT"; detail = EDT; },
+       { date = "Sat Mar 20 18:00:00 2027 GMT"; detail = EST; },
+       { date = "Sat Oct 23 18:00:00 2027 GMT"; detail = EDT; },
+       { date = "Sat Mar 18 18:00:00 2028 GMT"; detail = EST; },
+       { date = "Sat Oct 21 18:00:00 2028 GMT"; detail = EDT; },
+       { date = "Sat Mar 14 18:00:00 2037 GMT"; detail = EST; },
+       { date = "Sat Oct 17 18:00:00 2037 GMT"; detail = EDT; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/Australia/North b/libFoundation/Resources/TimeZoneInfo/Australia/North
new file mode 100644 (file)
index 0000000..65c037e
--- /dev/null
@@ -0,0 +1 @@
+{details = {CST = {abbrev = CST; isDST = 0; offset = "+9:30:00"; }; }; }
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/Australia/Queensland b/libFoundation/Resources/TimeZoneInfo/Australia/Queensland
new file mode 100644 (file)
index 0000000..ca48e9b
--- /dev/null
@@ -0,0 +1 @@
+{details = {EST = {abbrev = EST; isDST = 0; offset = "+10:00:00"; }; }; }
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/Australia/South b/libFoundation/Resources/TimeZoneInfo/Australia/South
new file mode 100644 (file)
index 0000000..118147f
--- /dev/null
@@ -0,0 +1,177 @@
+{
+    details = {
+       CDT = {abbrev = CDT; isDST = 1; offset = "+10:30:00"; };
+       CST = {abbrev = CST; isDST = 0; offset = "+9:30:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sat Mar 03 18:30:00 1973 GMT";
+           endDate = "Sat Oct 25 18:30:00 1980 GMT";
+           transitions = (
+               { date = "March/first Saturday/18:30:00"; detail = CST; },
+               { date = "October/last Saturday/18:30:00"; detail = CDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 06 18:30:00 1982 GMT";
+           endDate = "Sat Oct 26 18:30:00 1985 GMT";
+           transitions = (
+               { date = "March/first Saturday/18:30:00"; detail = CST; },
+               { date = "October/last Saturday/18:30:00"; detail = CDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 17 18:30:00 1990 GMT";
+           endDate = "Sat Oct 19 18:30:00 1991 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:30:00"; detail = CST; },
+               { date = "October/third Saturday/18:30:00"; detail = CDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 20 18:30:00 1993 GMT";
+           endDate = "Sat Oct 22 18:30:00 1994 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:30:00"; detail = CST; },
+               { date = "October/fourth Saturday/18:30:00"; detail = CDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 18 18:30:00 1995 GMT";
+           endDate = "Sat Oct 18 18:30:00 1997 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:30:00"; detail = CST; },
+               { date = "October/third Saturday/18:30:00"; detail = CDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 17 18:30:00 2001 GMT";
+           endDate = "Sat Oct 18 18:30:00 2003 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:30:00"; detail = CST; },
+               { date = "October/third Saturday/18:30:00"; detail = CDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 20 18:30:00 2004 GMT";
+           endDate = "Sat Oct 22 18:30:00 2005 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:30:00"; detail = CST; },
+               { date = "October/fourth Saturday/18:30:00"; detail = CDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 18 18:30:00 2006 GMT";
+           endDate = "Sat Oct 18 18:30:00 2008 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:30:00"; detail = CST; },
+               { date = "October/third Saturday/18:30:00"; detail = CDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 20 18:30:00 2010 GMT";
+           endDate = "Sat Oct 22 18:30:00 2011 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:30:00"; detail = CST; },
+               { date = "October/fourth Saturday/18:30:00"; detail = CDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 17 18:30:00 2012 GMT";
+           endDate = "Sat Oct 18 18:30:00 2014 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:30:00"; detail = CST; },
+               { date = "October/third Saturday/18:30:00"; detail = CDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 17 18:30:00 2018 GMT";
+           endDate = "Sat Oct 19 18:30:00 2019 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:30:00"; detail = CST; },
+               { date = "October/third Saturday/18:30:00"; detail = CDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 20 18:30:00 2021 GMT";
+           endDate = "Sat Oct 22 18:30:00 2022 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:30:00"; detail = CST; },
+               { date = "October/fourth Saturday/18:30:00"; detail = CDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 18 18:30:00 2023 GMT";
+           endDate = "Sat Oct 18 18:30:00 2025 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:30:00"; detail = CST; },
+               { date = "October/third Saturday/18:30:00"; detail = CDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 17 18:30:00 2029 GMT";
+           endDate = "Sat Oct 18 18:30:00 2031 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:30:00"; detail = CST; },
+               { date = "October/third Saturday/18:30:00"; detail = CDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 20 18:30:00 2032 GMT";
+           endDate = "Sat Oct 22 18:30:00 2033 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:30:00"; detail = CST; },
+               { date = "October/fourth Saturday/18:30:00"; detail = CDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 18 18:30:00 2034 GMT";
+           endDate = "Sat Oct 18 18:30:00 2036 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:30:00"; detail = CST; },
+               { date = "October/third Saturday/18:30:00"; detail = CDT; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Sat Oct 30 18:30:00 1971 GMT"; detail = CDT; },
+       { date = "Sat Feb 26 18:30:00 1972 GMT"; detail = CST; },
+       { date = "Sat Oct 28 18:30:00 1972 GMT"; detail = CDT; },
+       { date = "Sat Feb 28 18:30:00 1981 GMT"; detail = CST; },
+       { date = "Sat Oct 24 18:30:00 1981 GMT"; detail = CDT; },
+       { date = "Sat Mar 01 18:30:00 1986 GMT"; detail = CST; },
+       { date = "Sat Oct 18 18:30:00 1986 GMT"; detail = CDT; },
+       { date = "Sat Mar 14 18:30:00 1987 GMT"; detail = CST; },
+       { date = "Sat Oct 17 18:30:00 1987 GMT"; detail = CDT; },
+       { date = "Sat Mar 19 18:30:00 1988 GMT"; detail = CST; },
+       { date = "Sat Oct 22 18:30:00 1988 GMT"; detail = CDT; },
+       { date = "Sat Mar 18 18:30:00 1989 GMT"; detail = CST; },
+       { date = "Sat Oct 21 18:30:00 1989 GMT"; detail = CDT; },
+       { date = "Sat Mar 14 18:30:00 1992 GMT"; detail = CST; },
+       { date = "Sat Oct 17 18:30:00 1992 GMT"; detail = CDT; },
+       { date = "Sat Mar 14 18:30:00 1998 GMT"; detail = CST; },
+       { date = "Sat Oct 17 18:30:00 1998 GMT"; detail = CDT; },
+       { date = "Sat Mar 20 18:30:00 1999 GMT"; detail = CST; },
+       { date = "Sat Oct 23 18:30:00 1999 GMT"; detail = CDT; },
+       { date = "Sat Mar 18 18:30:00 2000 GMT"; detail = CST; },
+       { date = "Sat Oct 21 18:30:00 2000 GMT"; detail = CDT; },
+       { date = "Sat Mar 14 18:30:00 2009 GMT"; detail = CST; },
+       { date = "Sat Oct 17 18:30:00 2009 GMT"; detail = CDT; },
+       { date = "Sat Mar 14 18:30:00 2015 GMT"; detail = CST; },
+       { date = "Sat Oct 17 18:30:00 2015 GMT"; detail = CDT; },
+       { date = "Sat Mar 19 18:30:00 2016 GMT"; detail = CST; },
+       { date = "Sat Oct 22 18:30:00 2016 GMT"; detail = CDT; },
+       { date = "Sat Mar 18 18:30:00 2017 GMT"; detail = CST; },
+       { date = "Sat Oct 21 18:30:00 2017 GMT"; detail = CDT; },
+       { date = "Sat Mar 14 18:30:00 2020 GMT"; detail = CST; },
+       { date = "Sat Oct 17 18:30:00 2020 GMT"; detail = CDT; },
+       { date = "Sat Mar 14 18:30:00 2026 GMT"; detail = CST; },
+       { date = "Sat Oct 17 18:30:00 2026 GMT"; detail = CDT; },
+       { date = "Sat Mar 20 18:30:00 2027 GMT"; detail = CST; },
+       { date = "Sat Oct 23 18:30:00 2027 GMT"; detail = CDT; },
+       { date = "Sat Mar 18 18:30:00 2028 GMT"; detail = CST; },
+       { date = "Sat Oct 21 18:30:00 2028 GMT"; detail = CDT; },
+       { date = "Sat Mar 14 18:30:00 2037 GMT"; detail = CST; },
+       { date = "Sat Oct 17 18:30:00 2037 GMT"; detail = CDT; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/Australia/Tasmania b/libFoundation/Resources/TimeZoneInfo/Australia/Tasmania
new file mode 100644 (file)
index 0000000..e735bbf
--- /dev/null
@@ -0,0 +1,177 @@
+{
+    details = {
+       EDT = {abbrev = EDT; isDST = 1; offset = "+11:00:00"; };
+       EST = {abbrev = EST; isDST = 0; offset = "+10:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sat Mar 03 18:00:00 1973 GMT";
+           endDate = "Sat Oct 25 18:00:00 1980 GMT";
+           transitions = (
+               { date = "March/first Saturday/18:00:00"; detail = EST; },
+               { date = "October/last Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 06 18:00:00 1982 GMT";
+           endDate = "Sat Oct 26 18:00:00 1985 GMT";
+           transitions = (
+               { date = "March/first Saturday/18:00:00"; detail = EST; },
+               { date = "October/last Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 17 18:00:00 1990 GMT";
+           endDate = "Sat Oct 19 18:00:00 1991 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 20 18:00:00 1993 GMT";
+           endDate = "Sat Oct 22 18:00:00 1994 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/fourth Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 18 18:00:00 1995 GMT";
+           endDate = "Sat Oct 18 18:00:00 1997 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 17 18:00:00 2001 GMT";
+           endDate = "Sat Oct 18 18:00:00 2003 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 20 18:00:00 2004 GMT";
+           endDate = "Sat Oct 22 18:00:00 2005 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/fourth Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 18 18:00:00 2006 GMT";
+           endDate = "Sat Oct 18 18:00:00 2008 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 20 18:00:00 2010 GMT";
+           endDate = "Sat Oct 22 18:00:00 2011 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/fourth Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 17 18:00:00 2012 GMT";
+           endDate = "Sat Oct 18 18:00:00 2014 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 17 18:00:00 2018 GMT";
+           endDate = "Sat Oct 19 18:00:00 2019 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 20 18:00:00 2021 GMT";
+           endDate = "Sat Oct 22 18:00:00 2022 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/fourth Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 18 18:00:00 2023 GMT";
+           endDate = "Sat Oct 18 18:00:00 2025 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 17 18:00:00 2029 GMT";
+           endDate = "Sat Oct 18 18:00:00 2031 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 20 18:00:00 2032 GMT";
+           endDate = "Sat Oct 22 18:00:00 2033 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/fourth Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 18 18:00:00 2034 GMT";
+           endDate = "Sat Oct 18 18:00:00 2036 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Sat Oct 30 18:00:00 1971 GMT"; detail = EDT; },
+       { date = "Sat Feb 26 18:00:00 1972 GMT"; detail = EST; },
+       { date = "Sat Oct 28 18:00:00 1972 GMT"; detail = EDT; },
+       { date = "Sat Feb 28 18:00:00 1981 GMT"; detail = EST; },
+       { date = "Sat Oct 24 18:00:00 1981 GMT"; detail = EDT; },
+       { date = "Sat Mar 01 18:00:00 1986 GMT"; detail = EST; },
+       { date = "Sat Oct 18 18:00:00 1986 GMT"; detail = EDT; },
+       { date = "Sat Mar 14 18:00:00 1987 GMT"; detail = EST; },
+       { date = "Sat Oct 17 18:00:00 1987 GMT"; detail = EDT; },
+       { date = "Sat Mar 19 18:00:00 1988 GMT"; detail = EST; },
+       { date = "Sat Oct 22 18:00:00 1988 GMT"; detail = EDT; },
+       { date = "Sat Mar 18 18:00:00 1989 GMT"; detail = EST; },
+       { date = "Sat Oct 21 18:00:00 1989 GMT"; detail = EDT; },
+       { date = "Sat Mar 14 18:00:00 1992 GMT"; detail = EST; },
+       { date = "Sat Oct 17 18:00:00 1992 GMT"; detail = EDT; },
+       { date = "Sat Mar 14 18:00:00 1998 GMT"; detail = EST; },
+       { date = "Sat Oct 17 18:00:00 1998 GMT"; detail = EDT; },
+       { date = "Sat Mar 20 18:00:00 1999 GMT"; detail = EST; },
+       { date = "Sat Oct 23 18:00:00 1999 GMT"; detail = EDT; },
+       { date = "Sat Mar 18 18:00:00 2000 GMT"; detail = EST; },
+       { date = "Sat Oct 21 18:00:00 2000 GMT"; detail = EDT; },
+       { date = "Sat Mar 14 18:00:00 2009 GMT"; detail = EST; },
+       { date = "Sat Oct 17 18:00:00 2009 GMT"; detail = EDT; },
+       { date = "Sat Mar 14 18:00:00 2015 GMT"; detail = EST; },
+       { date = "Sat Oct 17 18:00:00 2015 GMT"; detail = EDT; },
+       { date = "Sat Mar 19 18:00:00 2016 GMT"; detail = EST; },
+       { date = "Sat Oct 22 18:00:00 2016 GMT"; detail = EDT; },
+       { date = "Sat Mar 18 18:00:00 2017 GMT"; detail = EST; },
+       { date = "Sat Oct 21 18:00:00 2017 GMT"; detail = EDT; },
+       { date = "Sat Mar 14 18:00:00 2020 GMT"; detail = EST; },
+       { date = "Sat Oct 17 18:00:00 2020 GMT"; detail = EDT; },
+       { date = "Sat Mar 14 18:00:00 2026 GMT"; detail = EST; },
+       { date = "Sat Oct 17 18:00:00 2026 GMT"; detail = EDT; },
+       { date = "Sat Mar 20 18:00:00 2027 GMT"; detail = EST; },
+       { date = "Sat Oct 23 18:00:00 2027 GMT"; detail = EDT; },
+       { date = "Sat Mar 18 18:00:00 2028 GMT"; detail = EST; },
+       { date = "Sat Oct 21 18:00:00 2028 GMT"; detail = EDT; },
+       { date = "Sat Mar 14 18:00:00 2037 GMT"; detail = EST; },
+       { date = "Sat Oct 17 18:00:00 2037 GMT"; detail = EDT; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/Australia/Victoria b/libFoundation/Resources/TimeZoneInfo/Australia/Victoria
new file mode 100644 (file)
index 0000000..96326f2
--- /dev/null
@@ -0,0 +1,177 @@
+{
+    details = {
+       EDT = {abbrev = EDT; isDST = 1; offset = "+11:00:00"; };
+       EST = {abbrev = EST; isDST = 0; offset = "+10:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sat Mar 03 18:00:00 1973 GMT";
+           endDate = "Sat Oct 25 18:00:00 1980 GMT";
+           transitions = (
+               { date = "March/first Saturday/18:00:00"; detail = EST; },
+               { date = "October/last Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 06 18:00:00 1982 GMT";
+           endDate = "Sat Oct 26 18:00:00 1985 GMT";
+           transitions = (
+               { date = "March/first Saturday/18:00:00"; detail = EST; },
+               { date = "October/last Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 17 18:00:00 1990 GMT";
+           endDate = "Sat Oct 19 18:00:00 1991 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 20 18:00:00 1993 GMT";
+           endDate = "Sat Oct 22 18:00:00 1994 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/fourth Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 18 18:00:00 1995 GMT";
+           endDate = "Sat Oct 18 18:00:00 1997 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 17 18:00:00 2001 GMT";
+           endDate = "Sat Oct 18 18:00:00 2003 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 20 18:00:00 2004 GMT";
+           endDate = "Sat Oct 22 18:00:00 2005 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/fourth Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 18 18:00:00 2006 GMT";
+           endDate = "Sat Oct 18 18:00:00 2008 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 20 18:00:00 2010 GMT";
+           endDate = "Sat Oct 22 18:00:00 2011 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/fourth Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 17 18:00:00 2012 GMT";
+           endDate = "Sat Oct 18 18:00:00 2014 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 17 18:00:00 2018 GMT";
+           endDate = "Sat Oct 19 18:00:00 2019 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 20 18:00:00 2021 GMT";
+           endDate = "Sat Oct 22 18:00:00 2022 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/fourth Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 18 18:00:00 2023 GMT";
+           endDate = "Sat Oct 18 18:00:00 2025 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 17 18:00:00 2029 GMT";
+           endDate = "Sat Oct 18 18:00:00 2031 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 20 18:00:00 2032 GMT";
+           endDate = "Sat Oct 22 18:00:00 2033 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/fourth Saturday/18:00:00"; detail = EDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 18 18:00:00 2034 GMT";
+           endDate = "Sat Oct 18 18:00:00 2036 GMT";
+           transitions = (
+               { date = "March/third Saturday/18:00:00"; detail = EST; },
+               { date = "October/third Saturday/18:00:00"; detail = EDT; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Sat Oct 30 18:00:00 1971 GMT"; detail = EDT; },
+       { date = "Sat Feb 26 18:00:00 1972 GMT"; detail = EST; },
+       { date = "Sat Oct 28 18:00:00 1972 GMT"; detail = EDT; },
+       { date = "Sat Feb 28 18:00:00 1981 GMT"; detail = EST; },
+       { date = "Sat Oct 24 18:00:00 1981 GMT"; detail = EDT; },
+       { date = "Sat Mar 15 18:00:00 1986 GMT"; detail = EST; },
+       { date = "Sat Oct 18 18:00:00 1986 GMT"; detail = EDT; },
+       { date = "Sat Mar 14 18:00:00 1987 GMT"; detail = EST; },
+       { date = "Sat Oct 17 18:00:00 1987 GMT"; detail = EDT; },
+       { date = "Sat Mar 19 18:00:00 1988 GMT"; detail = EST; },
+       { date = "Sat Oct 22 18:00:00 1988 GMT"; detail = EDT; },
+       { date = "Sat Mar 18 18:00:00 1989 GMT"; detail = EST; },
+       { date = "Sat Oct 21 18:00:00 1989 GMT"; detail = EDT; },
+       { date = "Sat Mar 14 18:00:00 1992 GMT"; detail = EST; },
+       { date = "Sat Oct 17 18:00:00 1992 GMT"; detail = EDT; },
+       { date = "Sat Mar 14 18:00:00 1998 GMT"; detail = EST; },
+       { date = "Sat Oct 17 18:00:00 1998 GMT"; detail = EDT; },
+       { date = "Sat Mar 20 18:00:00 1999 GMT"; detail = EST; },
+       { date = "Sat Oct 23 18:00:00 1999 GMT"; detail = EDT; },
+       { date = "Sat Mar 18 18:00:00 2000 GMT"; detail = EST; },
+       { date = "Sat Oct 21 18:00:00 2000 GMT"; detail = EDT; },
+       { date = "Sat Mar 14 18:00:00 2009 GMT"; detail = EST; },
+       { date = "Sat Oct 17 18:00:00 2009 GMT"; detail = EDT; },
+       { date = "Sat Mar 14 18:00:00 2015 GMT"; detail = EST; },
+       { date = "Sat Oct 17 18:00:00 2015 GMT"; detail = EDT; },
+       { date = "Sat Mar 19 18:00:00 2016 GMT"; detail = EST; },
+       { date = "Sat Oct 22 18:00:00 2016 GMT"; detail = EDT; },
+       { date = "Sat Mar 18 18:00:00 2017 GMT"; detail = EST; },
+       { date = "Sat Oct 21 18:00:00 2017 GMT"; detail = EDT; },
+       { date = "Sat Mar 14 18:00:00 2020 GMT"; detail = EST; },
+       { date = "Sat Oct 17 18:00:00 2020 GMT"; detail = EDT; },
+       { date = "Sat Mar 14 18:00:00 2026 GMT"; detail = EST; },
+       { date = "Sat Oct 17 18:00:00 2026 GMT"; detail = EDT; },
+       { date = "Sat Mar 20 18:00:00 2027 GMT"; detail = EST; },
+       { date = "Sat Oct 23 18:00:00 2027 GMT"; detail = EDT; },
+       { date = "Sat Mar 18 18:00:00 2028 GMT"; detail = EST; },
+       { date = "Sat Oct 21 18:00:00 2028 GMT"; detail = EDT; },
+       { date = "Sat Mar 14 18:00:00 2037 GMT"; detail = EST; },
+       { date = "Sat Oct 17 18:00:00 2037 GMT"; detail = EDT; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/Australia/West b/libFoundation/Resources/TimeZoneInfo/Australia/West
new file mode 100644 (file)
index 0000000..d7232d0
--- /dev/null
@@ -0,0 +1 @@
+{details = {WST = {abbrev = WST; isDST = 0; offset = "+8:00:00"; }; }; }
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/CET b/libFoundation/Resources/TimeZoneInfo/CET
new file mode 100644 (file)
index 0000000..fced764
--- /dev/null
@@ -0,0 +1,24 @@
+{
+    details = {
+       CET = {abbrev = CET; isDST = 0; offset = "+1:00:00"; };
+       "CEST" = {abbrev = "CEST"; isDST = 1; offset = "+2:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 30 03:00:00 1986 GMT";
+           endDate = "Sun Sep 24 03:00:00 1995 GMT";
+           transitions = (
+               { date = "March/last Sunday/3:00:00"; detail = "CEST"; },
+               { date = "September/last Sunday/3:00:00"; detail = CET; }
+           );
+       },
+       {
+           startDate = "Sun Mar 31 03:00:00 1996 GMT";
+           endDate = "Sun Oct 25 03:00:00 2037 GMT";
+           transitions = (
+               { date = "March/last Sunday/3:00:00"; detail = "CEST"; },
+               { date = "October/last Sunday/3:00:00"; detail = CET; }
+           );
+       }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/CLST b/libFoundation/Resources/TimeZoneInfo/CLST
new file mode 100644 (file)
index 0000000..e405bd4
--- /dev/null
@@ -0,0 +1,16 @@
+{
+    details = {
+       CLST = {abbrev = CLST; isDST = 0; offset = "-4:00:00"; };
+       CLDT = {abbrev = CLDT; isDST = 1; offset = "-3:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 31 03:00:00 1977 GMT";
+           endDate = "Sun Oct 25 03:00:00 2037 GMT";
+           transitions = (
+               { date = "March/third Sunday/0:00:00";   detail = CLDT; },
+               { date = "October/third Sunday/0:00:00"; detail = CLST; }
+           );
+       }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/CST6CDT b/libFoundation/Resources/TimeZoneInfo/CST6CDT
new file mode 100644 (file)
index 0000000..9eaf31a
--- /dev/null
@@ -0,0 +1,49 @@
+{
+    details = {
+       CDT = {abbrev = CDT; isDST = 1; offset = "-5:00:00"; };
+       CST = {abbrev = CST; isDST = 0; offset = "-6:00:00"; };
+       CWT = {abbrev = CWT; isDST = 1; offset = "-5:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 31 10:00:00 1918 GMT";
+           endDate = "Sun Oct 26 09:00:00 1919 GMT";
+           transitions = (
+               { date = "March/last Sunday/10:00:00"; detail = CDT; },
+               { date = "October/last Sunday/9:00:00"; detail = CST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 30 10:00:00 1967 GMT";
+           endDate = "Sun Oct 28 09:00:00 1973 GMT";
+           transitions = (
+               { date = "April/last Sunday/10:00:00"; detail = CDT; },
+               { date = "October/last Sunday/9:00:00"; detail = CST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 25 10:00:00 1976 GMT";
+           endDate = "Sun Oct 26 09:00:00 1986 GMT";
+           transitions = (
+               { date = "April/last Sunday/10:00:00"; detail = CDT; },
+               { date = "October/last Sunday/9:00:00"; detail = CST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 05 10:00:00 1987 GMT";
+           endDate = "Sun Oct 25 09:00:00 2037 GMT";
+           transitions = (
+               { date = "April/first Sunday/10:00:00"; detail = CDT; },
+               { date = "October/last Sunday/9:00:00"; detail = CST; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Mon Feb 09 10:00:00 1942 GMT"; detail = CWT; },
+       { date = "Sun Sep 30 09:00:00 1945 GMT"; detail = CST; },
+       { date = "Sun Jan 06 10:00:00 1974 GMT"; detail = CDT; },
+       { date = "Sun Oct 27 09:00:00 1974 GMT"; detail = CST; },
+       { date = "Sun Feb 23 10:00:00 1975 GMT"; detail = CDT; },
+       { date = "Sun Oct 26 09:00:00 1975 GMT"; detail = CST; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/Canada/Atlantic b/libFoundation/Resources/TimeZoneInfo/Canada/Atlantic
new file mode 100644 (file)
index 0000000..8dc262e
--- /dev/null
@@ -0,0 +1,24 @@
+{
+    details = {
+       ADT = {abbrev = ADT; isDST = 1; offset = "-3:00:00"; };
+       AST = {abbrev = AST; isDST = 0; offset = "-4:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Apr 27 08:00:00 1969 GMT";
+           endDate = "Sun Oct 26 07:00:00 1986 GMT";
+           transitions = (
+               { date = "April/last Sunday/8:00:00"; detail = ADT; },
+               { date = "October/last Sunday/7:00:00"; detail = AST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 05 08:00:00 1987 GMT";
+           endDate = "Sun Oct 25 07:00:00 2037 GMT";
+           transitions = (
+               { date = "April/first Sunday/8:00:00"; detail = ADT; },
+               { date = "October/last Sunday/7:00:00"; detail = AST; }
+           );
+       }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/Canada/Central b/libFoundation/Resources/TimeZoneInfo/Canada/Central
new file mode 100644 (file)
index 0000000..ebb20c6
--- /dev/null
@@ -0,0 +1,24 @@
+{
+    details = {
+       CDT = {abbrev = CDT; isDST = 1; offset = "-5:00:00"; };
+       CST = {abbrev = CST; isDST = 0; offset = "-6:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Apr 27 10:00:00 1969 GMT";
+           endDate = "Sun Oct 26 09:00:00 1986 GMT";
+           transitions = (
+               { date = "April/last Sunday/10:00:00"; detail = CDT; },
+               { date = "October/last Sunday/9:00:00"; detail = CST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 05 10:00:00 1987 GMT";
+           endDate = "Sun Oct 25 09:00:00 2037 GMT";
+           transitions = (
+               { date = "April/first Sunday/10:00:00"; detail = CDT; },
+               { date = "October/last Sunday/9:00:00"; detail = CST; }
+           );
+       }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/Canada/East-Saskatchewan b/libFoundation/Resources/TimeZoneInfo/Canada/East-Saskatchewan
new file mode 100644 (file)
index 0000000..6eea625
--- /dev/null
@@ -0,0 +1 @@
+{details = {CST = {abbrev = CST; isDST = 0; offset = "-6:00:00"; }; }; }
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/Canada/Eastern b/libFoundation/Resources/TimeZoneInfo/Canada/Eastern
new file mode 100644 (file)
index 0000000..b2f0f64
--- /dev/null
@@ -0,0 +1,24 @@
+{
+    details = {
+       EDT = {abbrev = EDT; isDST = 1; offset = "-4:00:00"; };
+       EST = {abbrev = EST; isDST = 0; offset = "-5:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Apr 27 09:00:00 1969 GMT";
+           endDate = "Sun Oct 26 08:00:00 1986 GMT";
+           transitions = (
+               { date = "April/last Sunday/9:00:00"; detail = EDT; },
+               { date = "October/last Sunday/8:00:00"; detail = EST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 05 09:00:00 1987 GMT";
+           endDate = "Sun Oct 25 08:00:00 2037 GMT";
+           transitions = (
+               { date = "April/first Sunday/9:00:00"; detail = EDT; },
+               { date = "October/last Sunday/8:00:00"; detail = EST; }
+           );
+       }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/Canada/Mountain b/libFoundation/Resources/TimeZoneInfo/Canada/Mountain
new file mode 100644 (file)
index 0000000..ac7b459
--- /dev/null
@@ -0,0 +1,24 @@
+{
+    details = {
+       MDT = {abbrev = MDT; isDST = 1; offset = "-6:00:00"; };
+       MST = {abbrev = MST; isDST = 0; offset = "-7:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Apr 27 11:00:00 1969 GMT";
+           endDate = "Sun Oct 26 10:00:00 1986 GMT";
+           transitions = (
+               { date = "April/last Sunday/11:00:00"; detail = MDT; },
+               { date = "October/last Sunday/10:00:00"; detail = MST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 05 11:00:00 1987 GMT";
+           endDate = "Sun Oct 25 10:00:00 2037 GMT";
+           transitions = (
+               { date = "April/first Sunday/11:00:00"; detail = MDT; },
+               { date = "October/last Sunday/10:00:00"; detail = MST; }
+           );
+       }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/Canada/Newfoundland b/libFoundation/Resources/TimeZoneInfo/Canada/Newfoundland
new file mode 100644 (file)
index 0000000..18b65f8
--- /dev/null
@@ -0,0 +1,24 @@
+{
+    details = {
+       NDT = {abbrev = NDT; isDST = 1; offset = "-2:30:00"; };
+       NST = {abbrev = NST; isDST = 0; offset = "-3:30:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Apr 27 07:30:00 1969 GMT";
+           endDate = "Sun Oct 26 06:30:00 1986 GMT";
+           transitions = (
+               { date = "April/last Sunday/7:30:00"; detail = NDT; },
+               { date = "October/last Sunday/6:30:00"; detail = NST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 05 07:30:00 1987 GMT";
+           endDate = "Sun Oct 25 06:30:00 2037 GMT";
+           transitions = (
+               { date = "April/first Sunday/7:30:00"; detail = NDT; },
+               { date = "October/last Sunday/6:30:00"; detail = NST; }
+           );
+       }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/Canada/Pacific b/libFoundation/Resources/TimeZoneInfo/Canada/Pacific
new file mode 100644 (file)
index 0000000..25888a0
--- /dev/null
@@ -0,0 +1,24 @@
+{
+    details = {
+       PDT = {abbrev = PDT; isDST = 1; offset = "-7:00:00"; };
+       PST = {abbrev = PST; isDST = 0; offset = "-8:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Apr 27 12:00:00 1969 GMT";
+           endDate = "Sun Oct 26 11:00:00 1986 GMT";
+           transitions = (
+               { date = "April/last Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 05 12:00:00 1987 GMT";
+           endDate = "Sun Oct 25 11:00:00 2037 GMT";
+           transitions = (
+               { date = "April/first Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/Canada/Yukon b/libFoundation/Resources/TimeZoneInfo/Canada/Yukon
new file mode 100644 (file)
index 0000000..4bb22c3
--- /dev/null
@@ -0,0 +1,24 @@
+{
+    details = {
+       YDT = {abbrev = YDT; isDST = 1; offset = "-8:00:00"; };
+       YST = {abbrev = YST; isDST = 0; offset = "-9:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Apr 27 13:00:00 1969 GMT";
+           endDate = "Sun Oct 26 12:00:00 1986 GMT";
+           transitions = (
+               { date = "April/last Sunday/13:00:00"; detail = YDT; },
+               { date = "October/last Sunday/12:00:00"; detail = YST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 05 13:00:00 1987 GMT";
+           endDate = "Sun Oct 25 12:00:00 2037 GMT";
+           transitions = (
+               { date = "April/first Sunday/13:00:00"; detail = YDT; },
+               { date = "October/last Sunday/12:00:00"; detail = YST; }
+           );
+       }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/EET b/libFoundation/Resources/TimeZoneInfo/EET
new file mode 100644 (file)
index 0000000..00171ce
--- /dev/null
@@ -0,0 +1,24 @@
+{
+    details = {
+       EET = {abbrev = EET; isDST = 0; offset = "+2:00:00"; };
+       "EET DST" = {abbrev = "EET DST"; isDST = 1; offset = "+3:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 30 03:00:00 1986 GMT";
+           endDate = "Sun Sep 24 03:00:00 1995 GMT";
+           transitions = (
+               { date = "March/last Sunday/3:00:00"; detail = "EET DST"; },
+               { date = "September/last Sunday/3:00:00"; detail = EET; }
+           );
+       },
+       {
+           startDate = "Sun Mar 31 03:00:00 1996 GMT";
+           endDate = "Sun Oct 25 03:00:00 2037 GMT";
+           transitions = (
+               { date = "March/last Sunday/3:00:00"; detail = "EET DST"; },
+               { date = "October/last Sunday/3:00:00"; detail = EET; }
+           );
+       }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/EST b/libFoundation/Resources/TimeZoneInfo/EST
new file mode 100644 (file)
index 0000000..cc8663a
--- /dev/null
@@ -0,0 +1,21 @@
+{
+    details = {
+       EDT = {abbrev = EDT; isDST = 1; offset = "-4:00:00"; };
+       EST = {abbrev = EST; isDST = 0; offset = "-5:00:00"; };
+       EWT = {abbrev = EWT; isDST = 1; offset = "-4:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 31 09:00:00 1918 GMT";
+           endDate = "Sun Oct 26 08:00:00 1919 GMT";
+           transitions = (
+               { date = "March/last Sunday/9:00:00"; detail = EDT; },
+               { date = "October/last Sunday/8:00:00"; detail = EST; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Mon Feb 09 09:00:00 1942 GMT"; detail = EWT; },
+       { date = "Sun Sep 30 08:00:00 1945 GMT"; detail = EST; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/EST5EDT b/libFoundation/Resources/TimeZoneInfo/EST5EDT
new file mode 100644 (file)
index 0000000..62c7b77
--- /dev/null
@@ -0,0 +1,49 @@
+{
+    details = {
+       EDT = {abbrev = EDT; isDST = 1; offset = "-4:00:00"; };
+       EST = {abbrev = EST; isDST = 0; offset = "-5:00:00"; };
+       EWT = {abbrev = EWT; isDST = 1; offset = "-4:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 31 09:00:00 1918 GMT";
+           endDate = "Sun Oct 26 08:00:00 1919 GMT";
+           transitions = (
+               { date = "March/last Sunday/9:00:00"; detail = EDT; },
+               { date = "October/last Sunday/8:00:00"; detail = EST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 30 09:00:00 1967 GMT";
+           endDate = "Sun Oct 28 08:00:00 1973 GMT";
+           transitions = (
+               { date = "April/last Sunday/9:00:00"; detail = EDT; },
+               { date = "October/last Sunday/8:00:00"; detail = EST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 25 09:00:00 1976 GMT";
+           endDate = "Sun Oct 26 08:00:00 1986 GMT";
+           transitions = (
+               { date = "April/last Sunday/9:00:00"; detail = EDT; },
+               { date = "October/last Sunday/8:00:00"; detail = EST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 05 09:00:00 1987 GMT";
+           endDate = "Sun Oct 25 08:00:00 2037 GMT";
+           transitions = (
+               { date = "April/first Sunday/9:00:00"; detail = EDT; },
+               { date = "October/last Sunday/8:00:00"; detail = EST; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Mon Feb 09 09:00:00 1942 GMT"; detail = EWT; },
+       { date = "Sun Sep 30 08:00:00 1945 GMT"; detail = EST; },
+       { date = "Sun Jan 06 09:00:00 1974 GMT"; detail = EDT; },
+       { date = "Sun Oct 27 08:00:00 1974 GMT"; detail = EST; },
+       { date = "Sun Feb 23 09:00:00 1975 GMT"; detail = EDT; },
+       { date = "Sun Oct 26 08:00:00 1975 GMT"; detail = EST; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/Europe/Berlin b/libFoundation/Resources/TimeZoneInfo/Europe/Berlin
new file mode 100644 (file)
index 0000000..378a5e3
--- /dev/null
@@ -0,0 +1,24 @@
+{
+    details = {
+       MET = {abbrev = MET; isDST = 0; offset = "+1:00:00"; };
+       "MET DST" = {abbrev = "MET DST"; isDST = 1; offset = "+2:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 30 03:00:00 1986 GMT";
+           endDate = "Sun Sep 24 03:00:00 1995 GMT";
+           transitions = (
+               { date = "March/last Sunday/3:00:00"; detail = "MET DST"; },
+               { date = "September/last Sunday/3:00:00"; detail = MET; }
+           );
+       },
+       {
+           startDate = "Sun Mar 31 03:00:00 1996 GMT";
+           endDate = "Sun Oct 25 03:00:00 2037 GMT";
+           transitions = (
+               { date = "March/last Sunday/3:00:00"; detail = "MET DST"; },
+               { date = "October/last Sunday/3:00:00"; detail = MET; }
+           );
+       }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/Europe/Brussels b/libFoundation/Resources/TimeZoneInfo/Europe/Brussels
new file mode 100644 (file)
index 0000000..378a5e3
--- /dev/null
@@ -0,0 +1,24 @@
+{
+    details = {
+       MET = {abbrev = MET; isDST = 0; offset = "+1:00:00"; };
+       "MET DST" = {abbrev = "MET DST"; isDST = 1; offset = "+2:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 30 03:00:00 1986 GMT";
+           endDate = "Sun Sep 24 03:00:00 1995 GMT";
+           transitions = (
+               { date = "March/last Sunday/3:00:00"; detail = "MET DST"; },
+               { date = "September/last Sunday/3:00:00"; detail = MET; }
+           );
+       },
+       {
+           startDate = "Sun Mar 31 03:00:00 1996 GMT";
+           endDate = "Sun Oct 25 03:00:00 2037 GMT";
+           transitions = (
+               { date = "March/last Sunday/3:00:00"; detail = "MET DST"; },
+               { date = "October/last Sunday/3:00:00"; detail = MET; }
+           );
+       }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/Europe/Paris b/libFoundation/Resources/TimeZoneInfo/Europe/Paris
new file mode 100644 (file)
index 0000000..378a5e3
--- /dev/null
@@ -0,0 +1,24 @@
+{
+    details = {
+       MET = {abbrev = MET; isDST = 0; offset = "+1:00:00"; };
+       "MET DST" = {abbrev = "MET DST"; isDST = 1; offset = "+2:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 30 03:00:00 1986 GMT";
+           endDate = "Sun Sep 24 03:00:00 1995 GMT";
+           transitions = (
+               { date = "March/last Sunday/3:00:00"; detail = "MET DST"; },
+               { date = "September/last Sunday/3:00:00"; detail = MET; }
+           );
+       },
+       {
+           startDate = "Sun Mar 31 03:00:00 1996 GMT";
+           endDate = "Sun Oct 25 03:00:00 2037 GMT";
+           transitions = (
+               { date = "March/last Sunday/3:00:00"; detail = "MET DST"; },
+               { date = "October/last Sunday/3:00:00"; detail = MET; }
+           );
+       }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GB-Eire b/libFoundation/Resources/TimeZoneInfo/GB-Eire
new file mode 100644 (file)
index 0000000..d27bbd5
--- /dev/null
@@ -0,0 +1,46 @@
+{
+    details = {
+       BST = {abbrev = BST; isDST = 1; offset = "+1:00:00"; };
+       GMT = {abbrev = GMT; isDST = 0; offset = "+0:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 30 03:00:00 1986 GMT";
+           endDate = "Sun Oct 25 03:00:00 1987 GMT";
+           transitions = (
+               { date = "March/last Sunday/3:00:00"; detail = BST; },
+               { date = "October/last Sunday/3:00:00"; detail = GMT; }
+           );
+       },
+       {
+           startDate = "Sun Mar 25 03:00:00 1990 GMT";
+           endDate = "Sun Oct 24 03:00:00 1993 GMT";
+           transitions = (
+               { date = "March/last Sunday/3:00:00"; detail = BST; },
+               { date = "October/last Sunday/3:00:00"; detail = GMT; }
+           );
+       },
+       {
+           startDate = "Sun Mar 27 03:00:00 1994 GMT";
+           endDate = "Sun Oct 22 03:00:00 1995 GMT";
+           transitions = (
+               { date = "March/last Sunday/3:00:00"; detail = BST; },
+               { date = "October/fourth Sunday/3:00:00"; detail = GMT; }
+           );
+       },
+       {
+           startDate = "Sun Mar 31 03:00:00 1996 GMT";
+           endDate = "Sun Oct 25 03:00:00 2037 GMT";
+           transitions = (
+               { date = "March/last Sunday/3:00:00"; detail = BST; },
+               { date = "October/last Sunday/3:00:00"; detail = GMT; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Sun Mar 27 03:00:00 1988 GMT"; detail = BST; },
+       { date = "Sun Oct 23 03:00:00 1988 GMT"; detail = GMT; },
+       { date = "Sun Mar 26 03:00:00 1989 GMT"; detail = BST; },
+       { date = "Sun Oct 29 03:00:00 1989 GMT"; detail = GMT; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT b/libFoundation/Resources/TimeZoneInfo/GMT
new file mode 100644 (file)
index 0000000..d897b30
--- /dev/null
@@ -0,0 +1 @@
+{details = {GMT = {abbrev = GMT; isDST = 0; offset = "+0:00:00"; }; }; }
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+0_30 b/libFoundation/Resources/TimeZoneInfo/GMT+0_30
new file mode 100644 (file)
index 0000000..bdc4386
--- /dev/null
@@ -0,0 +1,3 @@
+{
+   details = {GMT+0030 = {abbrev = GMT+0030; isDST = 0; offset = +0:30:00; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+1 b/libFoundation/Resources/TimeZoneInfo/GMT+1
new file mode 100644 (file)
index 0000000..7362b74
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT+0100" = {abbrev = "GMT+0100"; isDST = 0; offset = "+1:00:00"; }; };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+10 b/libFoundation/Resources/TimeZoneInfo/GMT+10
new file mode 100644 (file)
index 0000000..27a3fac
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT+1000" = {abbrev = "GMT+1000"; isDST = 0; offset = "+10:00:00"; }; };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+10_30 b/libFoundation/Resources/TimeZoneInfo/GMT+10_30
new file mode 100644 (file)
index 0000000..ea7bfa4
--- /dev/null
@@ -0,0 +1,3 @@
+{
+   details = {GMT+1030 = {abbrev = GMT+1030; isDST = 0; offset = +10:30:00; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+11 b/libFoundation/Resources/TimeZoneInfo/GMT+11
new file mode 100644 (file)
index 0000000..872b340
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT+1100" = {abbrev = "GMT+1100"; isDST = 0; offset = "+11:00:00"; }; };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+11_30 b/libFoundation/Resources/TimeZoneInfo/GMT+11_30
new file mode 100644 (file)
index 0000000..d47321a
--- /dev/null
@@ -0,0 +1,3 @@
+{
+   details = {GMT+1130 = {abbrev = GMT+1130; isDST = 0; offset = +11:30:00; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+12 b/libFoundation/Resources/TimeZoneInfo/GMT+12
new file mode 100644 (file)
index 0000000..8855f01
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT+1200" = {abbrev = "GMT+1200"; isDST = 0; offset = "+12:00:00"; }; };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+13 b/libFoundation/Resources/TimeZoneInfo/GMT+13
new file mode 100644 (file)
index 0000000..d47c231
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT+1300" = {abbrev = "GMT+1300"; isDST = 0; offset = "+13:00:00"; }; };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+14 b/libFoundation/Resources/TimeZoneInfo/GMT+14
new file mode 100644 (file)
index 0000000..7e8b9b1
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT+1400" = {abbrev = "GMT+1400"; isDST = 0; offset = "+14:00:00"; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+1_30 b/libFoundation/Resources/TimeZoneInfo/GMT+1_30
new file mode 100644 (file)
index 0000000..2a13759
--- /dev/null
@@ -0,0 +1,3 @@
+{
+   details = {GMT+0130 = {abbrev = GMT+0130; isDST = 0; offset = +1:30:00; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+2 b/libFoundation/Resources/TimeZoneInfo/GMT+2
new file mode 100644 (file)
index 0000000..941115e
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT+0200" = {abbrev = "GMT+0200"; isDST = 0; offset = "+2:00:00"; }; };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+2_30 b/libFoundation/Resources/TimeZoneInfo/GMT+2_30
new file mode 100644 (file)
index 0000000..ee3365e
--- /dev/null
@@ -0,0 +1,3 @@
+{
+   details = {GMT+0230 = {abbrev = GMT+0230; isDST = 0; offset = +2:30:00; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+3 b/libFoundation/Resources/TimeZoneInfo/GMT+3
new file mode 100644 (file)
index 0000000..ba654ad
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT+0300" = {abbrev = "GMT+0300"; isDST = 0; offset = "+3:00:00"; }; };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+3_30 b/libFoundation/Resources/TimeZoneInfo/GMT+3_30
new file mode 100644 (file)
index 0000000..02876f4
--- /dev/null
@@ -0,0 +1,3 @@
+{
+   details = {GMT+0330 = {abbrev = GMT+0330; isDST = 0; offset = +3:30:00; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+4 b/libFoundation/Resources/TimeZoneInfo/GMT+4
new file mode 100644 (file)
index 0000000..97b626c
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT+0400" = {abbrev = "GMT+0400"; isDST = 0; offset = "+4:00:00"; }; };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+4_30 b/libFoundation/Resources/TimeZoneInfo/GMT+4_30
new file mode 100644 (file)
index 0000000..fccde00
--- /dev/null
@@ -0,0 +1,3 @@
+{
+   details = {GMT+0430 = {abbrev = GMT+0430; isDST = 0; offset = +4:30:00; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+5 b/libFoundation/Resources/TimeZoneInfo/GMT+5
new file mode 100644 (file)
index 0000000..e955c12
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT+0500" = {abbrev = "GMT+0500"; isDST = 0; offset = "+5:00:00"; }; };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+5_30 b/libFoundation/Resources/TimeZoneInfo/GMT+5_30
new file mode 100644 (file)
index 0000000..275936c
--- /dev/null
@@ -0,0 +1,3 @@
+{
+   details = {GMT+0530 = {abbrev = GMT+0530; isDST = 0; offset = +5:30:00; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+6 b/libFoundation/Resources/TimeZoneInfo/GMT+6
new file mode 100644 (file)
index 0000000..7293727
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT+0600" = {abbrev = "GMT+0600"; isDST = 0; offset = "+6:00:00"; }; };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+6_30 b/libFoundation/Resources/TimeZoneInfo/GMT+6_30
new file mode 100644 (file)
index 0000000..cdcc0d1
--- /dev/null
@@ -0,0 +1,3 @@
+{
+   details = {GMT+0630 = {abbrev = GMT+0630; isDST = 0; offset = +6:30:00; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+7 b/libFoundation/Resources/TimeZoneInfo/GMT+7
new file mode 100644 (file)
index 0000000..3a26ec9
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT+0700" = {abbrev = "GMT+0700"; isDST = 0; offset = "+7:00:00"; }; };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+7_30 b/libFoundation/Resources/TimeZoneInfo/GMT+7_30
new file mode 100644 (file)
index 0000000..c42797f
--- /dev/null
@@ -0,0 +1,3 @@
+{
+   details = {GMT+0730 = {abbrev = GMT+0730; isDST = 0; offset = +7:30:00; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+8 b/libFoundation/Resources/TimeZoneInfo/GMT+8
new file mode 100644 (file)
index 0000000..9669747
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT+0800" = {abbrev = "GMT+0800"; isDST = 0; offset = "+8:00:00"; }; };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+8_30 b/libFoundation/Resources/TimeZoneInfo/GMT+8_30
new file mode 100644 (file)
index 0000000..2d5f298
--- /dev/null
@@ -0,0 +1,3 @@
+{
+   details = {GMT+0830 = {abbrev = GMT+0830; isDST = 0; offset = +8:30:00; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+9 b/libFoundation/Resources/TimeZoneInfo/GMT+9
new file mode 100644 (file)
index 0000000..8a2a275
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT+0900" = {abbrev = "GMT+0900"; isDST = 0; offset = "+9:00:00"; }; };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT+9_30 b/libFoundation/Resources/TimeZoneInfo/GMT+9_30
new file mode 100644 (file)
index 0000000..cb228f9
--- /dev/null
@@ -0,0 +1,3 @@
+{
+   details = {GMT+0930 = {abbrev = GMT+0930; isDST = 0; offset = +9:30:00; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT-0_30 b/libFoundation/Resources/TimeZoneInfo/GMT-0_30
new file mode 100644 (file)
index 0000000..39a1366
--- /dev/null
@@ -0,0 +1,3 @@
+{
+   details = {GMT-0030 = {abbrev = GMT-0030; isDST = 0; offset = -0:30:00; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT-1 b/libFoundation/Resources/TimeZoneInfo/GMT-1
new file mode 100644 (file)
index 0000000..6bdc3cf
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT-0100" = {abbrev = "GMT-0100"; isDST = 0; offset = "-1:00:00"; }; };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT-10 b/libFoundation/Resources/TimeZoneInfo/GMT-10
new file mode 100644 (file)
index 0000000..6ceca4f
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT-1000" = {abbrev = "GMT-1000"; isDST = 0; offset = "-10:00:00"; }; };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT-10_30 b/libFoundation/Resources/TimeZoneInfo/GMT-10_30
new file mode 100644 (file)
index 0000000..86b0d20
--- /dev/null
@@ -0,0 +1,3 @@
+{
+   details = {GMT-1030 = {abbrev = GMT-1030; isDST = 0; offset = -10:30:00; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT-11 b/libFoundation/Resources/TimeZoneInfo/GMT-11
new file mode 100644 (file)
index 0000000..4c53f53
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT-1100" = {abbrev = "GMT-1100"; isDST = 0; offset = "-11:00:00"; }; };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT-11_30 b/libFoundation/Resources/TimeZoneInfo/GMT-11_30
new file mode 100644 (file)
index 0000000..8bfd726
--- /dev/null
@@ -0,0 +1,3 @@
+{
+   details = {GMT-1130 = {abbrev = GMT-1130; isDST = 0; offset = -11:30:00; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT-12 b/libFoundation/Resources/TimeZoneInfo/GMT-12
new file mode 100644 (file)
index 0000000..67b8b78
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT-1200" = {abbrev = "GMT-1200"; isDST = 0; offset = "-12:00:00"; }; };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT-1_30 b/libFoundation/Resources/TimeZoneInfo/GMT-1_30
new file mode 100644 (file)
index 0000000..48aa320
--- /dev/null
@@ -0,0 +1,3 @@
+{
+   details = {GMT-0130 = {abbrev = GMT-0130; isDST = 0; offset = -1:30:00; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT-2 b/libFoundation/Resources/TimeZoneInfo/GMT-2
new file mode 100644 (file)
index 0000000..3684c41
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT-0200" = {abbrev = "GMT-0200"; isDST = 0; offset = "-2:00:00"; }; };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT-2_30 b/libFoundation/Resources/TimeZoneInfo/GMT-2_30
new file mode 100644 (file)
index 0000000..ed81722
--- /dev/null
@@ -0,0 +1,3 @@
+{
+   details = {GMT-0230 = {abbrev = GMT-0230; isDST = 0; offset = -2:30:00; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT-3 b/libFoundation/Resources/TimeZoneInfo/GMT-3
new file mode 100644 (file)
index 0000000..46ab7cb
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT-0300" = {abbrev = "GMT-0300"; isDST = 0; offset = "-3:00:00"; }; };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT-3_30 b/libFoundation/Resources/TimeZoneInfo/GMT-3_30
new file mode 100644 (file)
index 0000000..9262fac
--- /dev/null
@@ -0,0 +1,3 @@
+{
+   details = {GMT-0330 = {abbrev = GMT-0330; isDST = 0; offset = -3:30:00; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT-4 b/libFoundation/Resources/TimeZoneInfo/GMT-4
new file mode 100644 (file)
index 0000000..1997145
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT-0400" = {abbrev = "GMT-0400"; isDST = 0; offset = "-4:00:00"; }; };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT-4_30 b/libFoundation/Resources/TimeZoneInfo/GMT-4_30
new file mode 100644 (file)
index 0000000..185219d
--- /dev/null
@@ -0,0 +1,3 @@
+{
+   details = {GMT-0430 = {abbrev = GMT-0430; isDST = 0; offset = -4:30:00; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT-5 b/libFoundation/Resources/TimeZoneInfo/GMT-5
new file mode 100644 (file)
index 0000000..926c8f8
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT-0500" = {abbrev = "GMT-0500"; isDST = 0; offset = "-5:00:00"; }; };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT-5_30 b/libFoundation/Resources/TimeZoneInfo/GMT-5_30
new file mode 100644 (file)
index 0000000..156d011
--- /dev/null
@@ -0,0 +1,3 @@
+{
+   details = {GMT-0530 = {abbrev = GMT-0530; isDST = 0; offset = -5:30:00; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT-6 b/libFoundation/Resources/TimeZoneInfo/GMT-6
new file mode 100644 (file)
index 0000000..aaf6c15
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT-0600" = {abbrev = "GMT-0600"; isDST = 0; offset = "-6:00:00"; }; };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT-6_30 b/libFoundation/Resources/TimeZoneInfo/GMT-6_30
new file mode 100644 (file)
index 0000000..aecef96
--- /dev/null
@@ -0,0 +1,3 @@
+{
+   details = {GMT-0630 = {abbrev = GMT-0630; isDST = 0; offset = -6:30:00; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT-7 b/libFoundation/Resources/TimeZoneInfo/GMT-7
new file mode 100644 (file)
index 0000000..fe167ba
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT-0700" = {abbrev = "GMT-0700"; isDST = 0; offset = "-7:00:00"; }; };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT-7_30 b/libFoundation/Resources/TimeZoneInfo/GMT-7_30
new file mode 100644 (file)
index 0000000..f38d122
--- /dev/null
@@ -0,0 +1,3 @@
+{
+   details = {GMT-0730 = {abbrev = GMT-0730; isDST = 0; offset = -7:30:00; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT-8 b/libFoundation/Resources/TimeZoneInfo/GMT-8
new file mode 100644 (file)
index 0000000..c376b62
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT-0800" = {abbrev = "GMT-0800"; isDST = 0; offset = "-8:00:00"; }; };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT-8_30 b/libFoundation/Resources/TimeZoneInfo/GMT-8_30
new file mode 100644 (file)
index 0000000..b25dbef
--- /dev/null
@@ -0,0 +1,3 @@
+{
+   details = {GMT-0830 = {abbrev = GMT-0830; isDST = 0; offset = -8:30:00; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT-9 b/libFoundation/Resources/TimeZoneInfo/GMT-9
new file mode 100644 (file)
index 0000000..279f486
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"GMT-0900" = {abbrev = "GMT-0900"; isDST = 0; offset = "-9:00:00"; }; };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/GMT-9_30 b/libFoundation/Resources/TimeZoneInfo/GMT-9_30
new file mode 100644 (file)
index 0000000..9d3f7c7
--- /dev/null
@@ -0,0 +1,3 @@
+{
+   details = {GMT-0930 = {abbrev = GMT-0930; isDST = 0; offset = -9:30:00; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/Greenwich b/libFoundation/Resources/TimeZoneInfo/Greenwich
new file mode 100644 (file)
index 0000000..d897b30
--- /dev/null
@@ -0,0 +1 @@
+{details = {GMT = {abbrev = GMT; isDST = 0; offset = "+0:00:00"; }; }; }
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/HST b/libFoundation/Resources/TimeZoneInfo/HST
new file mode 100644 (file)
index 0000000..1556d88
--- /dev/null
@@ -0,0 +1,25 @@
+{
+    details = {
+       HDT = {abbrev = HDT; isDST = 1; offset = "-9:30:00"; };
+       HST = {abbrev = HST; isDST = 0; offset = "-10:30:00"; };
+       HST2 = {abbrev = HST; isDST = 0; offset = "-10:00:00"; };
+       HWT = {abbrev = HWT; isDST = 1; offset = "-9:30:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 31 14:30:00 1918 GMT";
+           endDate = "Sun Oct 26 13:30:00 1919 GMT";
+           transitions = (
+               { date = "March/last Sunday/14:30:00"; detail = HDT; },
+               { date = "October/last Sunday/13:30:00"; detail = HST; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Sun Apr 30 14:30:00 1933 GMT"; detail = HDT; },
+       { date = "Mon May 01 13:30:00 1933 GMT"; detail = HST; },
+       { date = "Mon Feb 09 14:30:00 1942 GMT"; detail = HWT; },
+       { date = "Sun Sep 30 13:30:00 1945 GMT"; detail = HST; },
+       { date = "Sun Jun 08 14:30:00 1947 GMT"; detail = HST2; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/Iceland b/libFoundation/Resources/TimeZoneInfo/Iceland
new file mode 100644 (file)
index 0000000..4b00a01
--- /dev/null
@@ -0,0 +1 @@
+{details = {WET = {abbrev = WET; isDST = 0; offset = "+0:00:00"; }; }; }
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/Japan b/libFoundation/Resources/TimeZoneInfo/Japan
new file mode 100644 (file)
index 0000000..f03ce0e
--- /dev/null
@@ -0,0 +1 @@
+{details = {JST = {abbrev = JST; isDST = 0; offset = "+9:00:00"; }; }; }
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/MET b/libFoundation/Resources/TimeZoneInfo/MET
new file mode 100644 (file)
index 0000000..378a5e3
--- /dev/null
@@ -0,0 +1,24 @@
+{
+    details = {
+       MET = {abbrev = MET; isDST = 0; offset = "+1:00:00"; };
+       "MET DST" = {abbrev = "MET DST"; isDST = 1; offset = "+2:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 30 03:00:00 1986 GMT";
+           endDate = "Sun Sep 24 03:00:00 1995 GMT";
+           transitions = (
+               { date = "March/last Sunday/3:00:00"; detail = "MET DST"; },
+               { date = "September/last Sunday/3:00:00"; detail = MET; }
+           );
+       },
+       {
+           startDate = "Sun Mar 31 03:00:00 1996 GMT";
+           endDate = "Sun Oct 25 03:00:00 2037 GMT";
+           transitions = (
+               { date = "March/last Sunday/3:00:00"; detail = "MET DST"; },
+               { date = "October/last Sunday/3:00:00"; detail = MET; }
+           );
+       }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/MST b/libFoundation/Resources/TimeZoneInfo/MST
new file mode 100644 (file)
index 0000000..8d0b295
--- /dev/null
@@ -0,0 +1,21 @@
+{
+    details = {
+       MDT = {abbrev = MDT; isDST = 1; offset = "-6:00:00"; };
+       MST = {abbrev = MST; isDST = 0; offset = "-7:00:00"; };
+       MWT = {abbrev = MWT; isDST = 1; offset = "-6:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 31 11:00:00 1918 GMT";
+           endDate = "Sun Oct 26 10:00:00 1919 GMT";
+           transitions = (
+               { date = "March/last Sunday/11:00:00"; detail = MDT; },
+               { date = "October/last Sunday/10:00:00"; detail = MST; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Mon Feb 09 11:00:00 1942 GMT"; detail = MWT; },
+       { date = "Sun Sep 30 10:00:00 1945 GMT"; detail = MST; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/MST7MDT b/libFoundation/Resources/TimeZoneInfo/MST7MDT
new file mode 100644 (file)
index 0000000..91ab107
--- /dev/null
@@ -0,0 +1,49 @@
+{
+    details = {
+       MDT = {abbrev = MDT; isDST = 1; offset = "-6:00:00"; };
+       MST = {abbrev = MST; isDST = 0; offset = "-7:00:00"; };
+       MWT = {abbrev = MWT; isDST = 1; offset = "-6:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 31 11:00:00 1918 GMT";
+           endDate = "Sun Oct 26 10:00:00 1919 GMT";
+           transitions = (
+               { date = "March/last Sunday/11:00:00"; detail = MDT; },
+               { date = "October/last Sunday/10:00:00"; detail = MST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 30 11:00:00 1967 GMT";
+           endDate = "Sun Oct 28 10:00:00 1973 GMT";
+           transitions = (
+               { date = "April/last Sunday/11:00:00"; detail = MDT; },
+               { date = "October/last Sunday/10:00:00"; detail = MST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 25 11:00:00 1976 GMT";
+           endDate = "Sun Oct 26 10:00:00 1986 GMT";
+           transitions = (
+               { date = "April/last Sunday/11:00:00"; detail = MDT; },
+               { date = "October/last Sunday/10:00:00"; detail = MST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 05 11:00:00 1987 GMT";
+           endDate = "Sun Oct 25 10:00:00 2037 GMT";
+           transitions = (
+               { date = "April/first Sunday/11:00:00"; detail = MDT; },
+               { date = "October/last Sunday/10:00:00"; detail = MST; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Mon Feb 09 11:00:00 1942 GMT"; detail = MWT; },
+       { date = "Sun Sep 30 10:00:00 1945 GMT"; detail = MST; },
+       { date = "Sun Jan 06 11:00:00 1974 GMT"; detail = MDT; },
+       { date = "Sun Oct 27 10:00:00 1974 GMT"; detail = MST; },
+       { date = "Sun Feb 23 11:00:00 1975 GMT"; detail = MDT; },
+       { date = "Sun Oct 26 10:00:00 1975 GMT"; detail = MST; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/NZ b/libFoundation/Resources/TimeZoneInfo/NZ
new file mode 100644 (file)
index 0000000..248c28e
--- /dev/null
@@ -0,0 +1,101 @@
+{
+    details = {
+       NZDT = {abbrev = NZDT; isDST = 1; offset = "+13:00:00"; };
+       NZST = {abbrev = NZST; isDST = 0; offset = "+12:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sat Mar 01 16:00:00 1975 GMT";
+           endDate = "Sat Oct 25 16:00:00 1980 GMT";
+           transitions = (
+               { date = "March/first Saturday/16:00:00"; detail = NZST; },
+               { date = "October/last Saturday/16:00:00"; detail = NZDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 06 16:00:00 1982 GMT";
+           endDate = "Sat Oct 25 16:00:00 1986 GMT";
+           transitions = (
+               { date = "March/first Saturday/16:00:00"; detail = NZST; },
+               { date = "October/last Saturday/16:00:00"; detail = NZDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 05 16:00:00 1988 GMT";
+           endDate = "Sat Oct 26 16:00:00 1991 GMT";
+           transitions = (
+               { date = "March/first Saturday/16:00:00"; detail = NZST; },
+               { date = "October/last Saturday/16:00:00"; detail = NZDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 06 16:00:00 1993 GMT";
+           endDate = "Sat Oct 25 16:00:00 1997 GMT";
+           transitions = (
+               { date = "March/first Saturday/16:00:00"; detail = NZST; },
+               { date = "October/last Saturday/16:00:00"; detail = NZDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 06 16:00:00 1999 GMT";
+           endDate = "Sat Oct 25 16:00:00 2008 GMT";
+           transitions = (
+               { date = "March/first Saturday/16:00:00"; detail = NZST; },
+               { date = "October/last Saturday/16:00:00"; detail = NZDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 06 16:00:00 2010 GMT";
+           endDate = "Sat Oct 25 16:00:00 2014 GMT";
+           transitions = (
+               { date = "March/first Saturday/16:00:00"; detail = NZST; },
+               { date = "October/last Saturday/16:00:00"; detail = NZDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 05 16:00:00 2016 GMT";
+           endDate = "Sat Oct 26 16:00:00 2019 GMT";
+           transitions = (
+               { date = "March/first Saturday/16:00:00"; detail = NZST; },
+               { date = "October/last Saturday/16:00:00"; detail = NZDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 06 16:00:00 2021 GMT";
+           endDate = "Sat Oct 25 16:00:00 2025 GMT";
+           transitions = (
+               { date = "March/first Saturday/16:00:00"; detail = NZST; },
+               { date = "October/last Saturday/16:00:00"; detail = NZDT; }
+           );
+       },
+       {
+           startDate = "Sat Mar 06 16:00:00 2027 GMT";
+           endDate = "Sat Oct 25 16:00:00 2036 GMT";
+           transitions = (
+               { date = "March/first Saturday/16:00:00"; detail = NZST; },
+               { date = "October/last Saturday/16:00:00"; detail = NZDT; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Sat Oct 26 16:00:00 1974 GMT"; detail = NZDT; },
+       { date = "Sat Feb 28 16:00:00 1981 GMT"; detail = NZST; },
+       { date = "Sat Oct 24 16:00:00 1981 GMT"; detail = NZDT; },
+       { date = "Sat Feb 28 16:00:00 1987 GMT"; detail = NZST; },
+       { date = "Sat Oct 24 16:00:00 1987 GMT"; detail = NZDT; },
+       { date = "Sat Feb 29 16:00:00 1992 GMT"; detail = NZST; },
+       { date = "Sat Oct 24 16:00:00 1992 GMT"; detail = NZDT; },
+       { date = "Sat Feb 28 16:00:00 1998 GMT"; detail = NZST; },
+       { date = "Sat Oct 24 16:00:00 1998 GMT"; detail = NZDT; },
+       { date = "Sat Feb 28 16:00:00 2009 GMT"; detail = NZST; },
+       { date = "Sat Oct 24 16:00:00 2009 GMT"; detail = NZDT; },
+       { date = "Sat Feb 28 16:00:00 2015 GMT"; detail = NZST; },
+       { date = "Sat Oct 24 16:00:00 2015 GMT"; detail = NZDT; },
+       { date = "Sat Feb 29 16:00:00 2020 GMT"; detail = NZST; },
+       { date = "Sat Oct 24 16:00:00 2020 GMT"; detail = NZDT; },
+       { date = "Sat Feb 28 16:00:00 2026 GMT"; detail = NZST; },
+       { date = "Sat Oct 24 16:00:00 2026 GMT"; detail = NZDT; },
+       { date = "Sat Feb 28 16:00:00 2037 GMT"; detail = NZST; },
+       { date = "Sat Oct 24 16:00:00 2037 GMT"; detail = NZDT; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/PST8PDT b/libFoundation/Resources/TimeZoneInfo/PST8PDT
new file mode 100644 (file)
index 0000000..23f6fb0
--- /dev/null
@@ -0,0 +1,49 @@
+{
+    details = {
+       PDT = {abbrev = PDT; isDST = 1; offset = "-7:00:00"; };
+       PST = {abbrev = PST; isDST = 0; offset = "-8:00:00"; };
+       PWT = {abbrev = PWT; isDST = 1; offset = "-7:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 31 12:00:00 1918 GMT";
+           endDate = "Sun Oct 26 11:00:00 1919 GMT";
+           transitions = (
+               { date = "March/last Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 30 12:00:00 1967 GMT";
+           endDate = "Sun Oct 28 11:00:00 1973 GMT";
+           transitions = (
+               { date = "April/last Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 25 12:00:00 1976 GMT";
+           endDate = "Sun Oct 26 11:00:00 1986 GMT";
+           transitions = (
+               { date = "April/last Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 05 12:00:00 1987 GMT";
+           endDate = "Sun Oct 25 11:00:00 2037 GMT";
+           transitions = (
+               { date = "April/first Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Mon Feb 09 12:00:00 1942 GMT"; detail = PWT; },
+       { date = "Sun Sep 30 11:00:00 1945 GMT"; detail = PST; },
+       { date = "Sun Jan 06 12:00:00 1974 GMT"; detail = PDT; },
+       { date = "Sun Oct 27 11:00:00 1974 GMT"; detail = PST; },
+       { date = "Sun Feb 23 12:00:00 1975 GMT"; detail = PDT; },
+       { date = "Sun Oct 26 11:00:00 1975 GMT"; detail = PST; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/Poland b/libFoundation/Resources/TimeZoneInfo/Poland
new file mode 100644 (file)
index 0000000..a637dee
--- /dev/null
@@ -0,0 +1,24 @@
+{
+    details = {
+       MET = {abbrev = MET; isDST = 0; offset = "+1:00:00"; };
+       "MET DST" = {abbrev = "MET DST"; isDST = 1; offset = "+2:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 30 02:00:00 1986 GMT";
+           endDate = "Sun Sep 24 02:00:00 1995 GMT";
+           transitions = (
+               { date = "March/last Sunday/2:00:00"; detail = "MET DST"; },
+               { date = "September/last Sunday/2:00:00"; detail = MET; }
+           );
+       },
+       {
+           startDate = "Sun Mar 31 02:00:00 1996 GMT";
+           endDate = "Sun Oct 25 02:00:00 2037 GMT";
+           transitions = (
+               { date = "March/last Sunday/2:00:00"; detail = "MET DST"; },
+               { date = "October/last Sunday/2:00:00"; detail = MET; }
+           );
+       }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/RegionsDictionary b/libFoundation/Resources/TimeZoneInfo/RegionsDictionary
new file mode 100644 (file)
index 0000000..09d7fe3
--- /dev/null
@@ -0,0 +1,114 @@
+{
+Abbreviations = {
+    CDT = "US/Central";
+    CST = "US/Central";
+    CWT = "US/Central";
+    EDT = "US/Eastern";
+    EET = Turkey;
+    "EET DST" = Turkey;
+    EST = "US/Eastern";
+    EWT = "US/Eastern";
+    GMT = GMT;
+    "GMT+0100" = "GMT+1";
+    "GMT+0200" = "GMT+2";
+    "GMT+0300" = "GMT+3";
+    "GMT+0400" = "GMT+4";
+    "GMT+0500" = "GMT+5";
+    "GMT+0600" = "GMT+6";
+    "GMT+0700" = "GMT+7";
+    "GMT+0800" = "GMT+8";
+    "GMT+0900" = "GMT+9";
+    "GMT+1000" = "GMT+10";
+    "GMT+1100" = "GMT+11";
+    "GMT+1200" = "GMT+12";
+    "GMT+1300" = "GMT+13";
+    "GMT-0100" = "GMT-1";
+    "GMT-0200" = "GMT-2";
+    "GMT-0300" = "GMT-3";
+    "GMT-0400" = "GMT-4";
+    "GMT-0500" = "GMT-5";
+    "GMT-0600" = "GMT-6";
+    "GMT-0700" = "GMT-7";
+    "GMT-0800" = "GMT-8";
+    "GMT-0900" = "GMT-9";
+    "GMT-1000" = "GMT-10";
+    "GMT-1100" = "GMT-11";
+    "GMT-1200" = "GMT-12";
+    HDT = "US/Hawaii";
+    HST = "US/Hawaii";
+    HWT = "US/Hawaii";
+    JST = Japan;
+    MDT = "US/Mountain";
+    MET = Poland;
+    "MET DST" = Poland;
+    MST = "US/Mountain";
+    MWT = "US/Mountain";
+    NZDT = NZ;
+    NZST = NZ;
+    PDT = "US/Pacific";
+    PST = "US/Pacific";
+    PWT = "US/Pacific";
+    SST = Singapore;
+    YDT = "US/Yukon";
+    YST = "US/Yukon";
+    YWT = "US/Yukon";
+  };
+
+/*
+    The following dictionary contains dictionaries whose keys represents
+    offsets from GMT and the values are time zone names whose offsets are equal
+    with the key offset.
+
+    The offset keys are represented in the [+|-]HHMM format. It's important to
+    keep all the insignificant zeroes even if the number is the same.
+
+    A time zone should be put in a value array corresponding to a given key
+    offset if it has a detail which is not daylight saving whose offset is
+    equal with the key offset. If the time zone contains details that have
+    different offsets, the time zone should appear in all the entries for
+    the given offsets.
+ */
+RegionsByOffset = {
+    "-1200" = ("GMT-12");
+    "-1100" = ("GMT-11");
+    "-1030" = ("HST", "US/Hawaii");
+    "-1000" = ("GMT-10", "HST", "US/Hawaii");
+    "-0900" = ("GMT-9", "US/Yukon", "Canada/Yukon");
+    "-0800" = ("GMT-8", "US/Pacific", "US/Pacific-New", "Canada/Pacific", PST8PDT);
+    "-0700" = ("GMT-7", "US/Mountain", "US/Arizona", "Canada/Mountain", MST, "MST7MDT");
+    "-0600" = (
+       "GMT-6",
+       "US/Central",
+       "Canada/Central",
+       "Canada/East-Saskatchewan",
+       "CST6CDT"
+    );
+    "-0500" = ("GMT-5", "US/Eastern", "US/East-Indiana", "Canada/Eastern");
+    "-0400" = ("GMT-4", "Canada/Atlantic", EST, "EST5EDT");
+    "-0330" = ("Canada/Newfoundland");
+    "-0300" = ("GMT-3");
+    "-0200" = ("GMT-2");
+    "-0100" = ("GMT-1");
+    "+0000" = (GMT, "Greenwich", "GB-Eire", "Iceland", "WET", "Universal", "UTC");
+    "+0100" = ("GMT+1", "Poland", "MET", "CET");
+    "+0200" = ("GMT+2", "EET");
+    "+0300" = ("GMT+3", "Turkey", "W-SU");
+    "+0400" = ("GMT+4");
+    "+0500" = ("GMT+5");
+    "+0600" = ("GMT+6");
+    "+0700" = ("GMT+7");
+    "+0800" = ("GMT+8", "Singapore", "Australia/West");
+    "+0900" = ("GMT+9", "Japan");
+    "+0930" = ("Australia/North", "Australia/South");
+    "+1000" = (
+      "GMT+10",
+      "Australia/Tasmania",
+      "Australia/Queensland",
+      "Australia/Victoria",
+      "Australia/NSW"
+    );
+    "+1100" = ("GMT+11");
+    "+1200" = ("GMT+12", "NZ");
+    "+1300" = ("GMT+13");
+  };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/SAST b/libFoundation/Resources/TimeZoneInfo/SAST
new file mode 100644 (file)
index 0000000..3a5938d
--- /dev/null
@@ -0,0 +1,5 @@
+{
+    details = { /* south africa standard time */
+       SAST = {abbrev = SAST; isDST = 0; offset = "+2:00:00"; };
+    };
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/SGT b/libFoundation/Resources/TimeZoneInfo/SGT
new file mode 100644 (file)
index 0000000..91608cb
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    details = {"SGT" = {abbrev = "SGT"; isDST = 0; offset = "+8:00:00"; }; };
+}
diff --git a/libFoundation/Resources/TimeZoneInfo/Singapore b/libFoundation/Resources/TimeZoneInfo/Singapore
new file mode 100644 (file)
index 0000000..03caa51
--- /dev/null
@@ -0,0 +1 @@
+{details = {SST = {abbrev = SST; isDST = 0; offset = "+8:00:00"; }; }; }
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/SystemV/AST4 b/libFoundation/Resources/TimeZoneInfo/SystemV/AST4
new file mode 100644 (file)
index 0000000..d8cf456
--- /dev/null
@@ -0,0 +1 @@
+{details = {AST = {abbrev = AST; isDST = 0; offset = "-4:00:00"; }; }; }
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/SystemV/AST4ADT b/libFoundation/Resources/TimeZoneInfo/SystemV/AST4ADT
new file mode 100644 (file)
index 0000000..5e15ceb
--- /dev/null
@@ -0,0 +1,30 @@
+{
+    details = {
+       ADT = {abbrev = ADT; isDST = 1; offset = "-3:00:00"; };
+       AST = {abbrev = AST; isDST = 0; offset = "-4:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Apr 27 08:00:00 1902 GMT";
+           endDate = "Sun Oct 28 07:00:00 1973 GMT";
+           transitions = (
+               { date = "April/last Sunday/8:00:00"; detail = ADT; },
+               { date = "October/last Sunday/7:00:00"; detail = AST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 25 08:00:00 1976 GMT";
+           endDate = "Sun Oct 25 07:00:00 2037 GMT";
+           transitions = (
+               { date = "April/last Sunday/8:00:00"; detail = ADT; },
+               { date = "October/last Sunday/7:00:00"; detail = AST; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Sun Jan 06 08:00:00 1974 GMT"; detail = ADT; },
+       { date = "Sun Nov 24 07:00:00 1974 GMT"; detail = AST; },
+       { date = "Sun Feb 23 08:00:00 1975 GMT"; detail = ADT; },
+       { date = "Sun Oct 26 07:00:00 1975 GMT"; detail = AST; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/SystemV/CST6 b/libFoundation/Resources/TimeZoneInfo/SystemV/CST6
new file mode 100644 (file)
index 0000000..6eea625
--- /dev/null
@@ -0,0 +1 @@
+{details = {CST = {abbrev = CST; isDST = 0; offset = "-6:00:00"; }; }; }
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/SystemV/CST6CDT b/libFoundation/Resources/TimeZoneInfo/SystemV/CST6CDT
new file mode 100644 (file)
index 0000000..b92deb5
--- /dev/null
@@ -0,0 +1,30 @@
+{
+    details = {
+       CDT = {abbrev = CDT; isDST = 1; offset = "-5:00:00"; };
+       CST = {abbrev = CST; isDST = 0; offset = "-6:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Apr 27 10:00:00 1902 GMT";
+           endDate = "Sun Oct 28 09:00:00 1973 GMT";
+           transitions = (
+               { date = "April/last Sunday/10:00:00"; detail = CDT; },
+               { date = "October/last Sunday/9:00:00"; detail = CST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 25 10:00:00 1976 GMT";
+           endDate = "Sun Oct 25 09:00:00 2037 GMT";
+           transitions = (
+               { date = "April/last Sunday/10:00:00"; detail = CDT; },
+               { date = "October/last Sunday/9:00:00"; detail = CST; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Sun Jan 06 10:00:00 1974 GMT"; detail = CDT; },
+       { date = "Sun Nov 24 09:00:00 1974 GMT"; detail = CST; },
+       { date = "Sun Feb 23 10:00:00 1975 GMT"; detail = CDT; },
+       { date = "Sun Oct 26 09:00:00 1975 GMT"; detail = CST; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/SystemV/EST5 b/libFoundation/Resources/TimeZoneInfo/SystemV/EST5
new file mode 100644 (file)
index 0000000..aa4ecf9
--- /dev/null
@@ -0,0 +1 @@
+{details = {EST = {abbrev = EST; isDST = 0; offset = "-5:00:00"; }; }; }
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/SystemV/EST5EDT b/libFoundation/Resources/TimeZoneInfo/SystemV/EST5EDT
new file mode 100644 (file)
index 0000000..3367f60
--- /dev/null
@@ -0,0 +1,30 @@
+{
+    details = {
+       EDT = {abbrev = EDT; isDST = 1; offset = "-4:00:00"; };
+       EST = {abbrev = EST; isDST = 0; offset = "-5:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Apr 27 09:00:00 1902 GMT";
+           endDate = "Sun Oct 28 08:00:00 1973 GMT";
+           transitions = (
+               { date = "April/last Sunday/9:00:00"; detail = EDT; },
+               { date = "October/last Sunday/8:00:00"; detail = EST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 25 09:00:00 1976 GMT";
+           endDate = "Sun Oct 25 08:00:00 2037 GMT";
+           transitions = (
+               { date = "April/last Sunday/9:00:00"; detail = EDT; },
+               { date = "October/last Sunday/8:00:00"; detail = EST; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Sun Jan 06 09:00:00 1974 GMT"; detail = EDT; },
+       { date = "Sun Nov 24 08:00:00 1974 GMT"; detail = EST; },
+       { date = "Sun Feb 23 09:00:00 1975 GMT"; detail = EDT; },
+       { date = "Sun Oct 26 08:00:00 1975 GMT"; detail = EST; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/SystemV/HST10 b/libFoundation/Resources/TimeZoneInfo/SystemV/HST10
new file mode 100644 (file)
index 0000000..517ddb3
--- /dev/null
@@ -0,0 +1 @@
+{details = {HST = {abbrev = HST; isDST = 0; offset = "-10:00:00"; }; }; }
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/SystemV/MST7 b/libFoundation/Resources/TimeZoneInfo/SystemV/MST7
new file mode 100644 (file)
index 0000000..a5deb24
--- /dev/null
@@ -0,0 +1 @@
+{details = {MST = {abbrev = MST; isDST = 0; offset = "-7:00:00"; }; }; }
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/SystemV/MST7MDT b/libFoundation/Resources/TimeZoneInfo/SystemV/MST7MDT
new file mode 100644 (file)
index 0000000..a949997
--- /dev/null
@@ -0,0 +1,30 @@
+{
+    details = {
+       MDT = {abbrev = MDT; isDST = 1; offset = "-6:00:00"; };
+       MST = {abbrev = MST; isDST = 0; offset = "-7:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Apr 27 11:00:00 1902 GMT";
+           endDate = "Sun Oct 28 10:00:00 1973 GMT";
+           transitions = (
+               { date = "April/last Sunday/11:00:00"; detail = MDT; },
+               { date = "October/last Sunday/10:00:00"; detail = MST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 25 11:00:00 1976 GMT";
+           endDate = "Sun Oct 25 10:00:00 2037 GMT";
+           transitions = (
+               { date = "April/last Sunday/11:00:00"; detail = MDT; },
+               { date = "October/last Sunday/10:00:00"; detail = MST; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Sun Jan 06 11:00:00 1974 GMT"; detail = MDT; },
+       { date = "Sun Nov 24 10:00:00 1974 GMT"; detail = MST; },
+       { date = "Sun Feb 23 11:00:00 1975 GMT"; detail = MDT; },
+       { date = "Sun Oct 26 10:00:00 1975 GMT"; detail = MST; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/SystemV/PST8 b/libFoundation/Resources/TimeZoneInfo/SystemV/PST8
new file mode 100644 (file)
index 0000000..55092c4
--- /dev/null
@@ -0,0 +1 @@
+{details = {PST = {abbrev = PST; isDST = 0; offset = "-8:00:00"; }; }; }
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/SystemV/PST8PDT b/libFoundation/Resources/TimeZoneInfo/SystemV/PST8PDT
new file mode 100644 (file)
index 0000000..90be838
--- /dev/null
@@ -0,0 +1,30 @@
+{
+    details = {
+       PDT = {abbrev = PDT; isDST = 1; offset = "-7:00:00"; };
+       PST = {abbrev = PST; isDST = 0; offset = "-8:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Apr 27 12:00:00 1902 GMT";
+           endDate = "Sun Oct 28 11:00:00 1973 GMT";
+           transitions = (
+               { date = "April/last Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 25 12:00:00 1976 GMT";
+           endDate = "Sun Oct 25 11:00:00 2037 GMT";
+           transitions = (
+               { date = "April/last Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Sun Jan 06 12:00:00 1974 GMT"; detail = PDT; },
+       { date = "Sun Nov 24 11:00:00 1974 GMT"; detail = PST; },
+       { date = "Sun Feb 23 12:00:00 1975 GMT"; detail = PDT; },
+       { date = "Sun Oct 26 11:00:00 1975 GMT"; detail = PST; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/SystemV/YST9 b/libFoundation/Resources/TimeZoneInfo/SystemV/YST9
new file mode 100644 (file)
index 0000000..e5c461b
--- /dev/null
@@ -0,0 +1 @@
+{details = {YST = {abbrev = YST; isDST = 0; offset = "-9:00:00"; }; }; }
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/SystemV/YST9YDT b/libFoundation/Resources/TimeZoneInfo/SystemV/YST9YDT
new file mode 100644 (file)
index 0000000..1ded713
--- /dev/null
@@ -0,0 +1,30 @@
+{
+    details = {
+       YDT = {abbrev = YDT; isDST = 1; offset = "-8:00:00"; };
+       YST = {abbrev = YST; isDST = 0; offset = "-9:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Apr 27 13:00:00 1902 GMT";
+           endDate = "Sun Oct 28 12:00:00 1973 GMT";
+           transitions = (
+               { date = "April/last Sunday/13:00:00"; detail = YDT; },
+               { date = "October/last Sunday/12:00:00"; detail = YST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 25 13:00:00 1976 GMT";
+           endDate = "Sun Oct 25 12:00:00 2037 GMT";
+           transitions = (
+               { date = "April/last Sunday/13:00:00"; detail = YDT; },
+               { date = "October/last Sunday/12:00:00"; detail = YST; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Sun Jan 06 13:00:00 1974 GMT"; detail = YDT; },
+       { date = "Sun Nov 24 12:00:00 1974 GMT"; detail = YST; },
+       { date = "Sun Feb 23 13:00:00 1975 GMT"; detail = YDT; },
+       { date = "Sun Oct 26 12:00:00 1975 GMT"; detail = YST; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/Turkey b/libFoundation/Resources/TimeZoneInfo/Turkey
new file mode 100644 (file)
index 0000000..36d92ae
--- /dev/null
@@ -0,0 +1,24 @@
+{
+    details = {
+       EET = {abbrev = EET; isDST = 0; offset = "+3:00:00"; };
+       "EET DST" = {abbrev = "EET DST"; isDST = 1; offset = "+4:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 30 01:00:00 1986 GMT";
+           endDate = "Sun Sep 24 01:00:00 1995 GMT";
+           transitions = (
+               { date = "March/last Sunday/1:00:00"; detail = "EET DST"; },
+               { date = "September/last Sunday/1:00:00"; detail = EET; }
+           );
+       },
+       {
+           startDate = "Sun Mar 31 01:00:00 1996 GMT";
+           endDate = "Sun Oct 25 01:00:00 2037 GMT";
+           transitions = (
+               { date = "March/last Sunday/1:00:00"; detail = "EET DST"; },
+               { date = "October/last Sunday/1:00:00"; detail = EET; }
+           );
+       }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/UCT b/libFoundation/Resources/TimeZoneInfo/UCT
new file mode 100644 (file)
index 0000000..d897b30
--- /dev/null
@@ -0,0 +1 @@
+{details = {GMT = {abbrev = GMT; isDST = 0; offset = "+0:00:00"; }; }; }
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/US/Arizona b/libFoundation/Resources/TimeZoneInfo/US/Arizona
new file mode 100644 (file)
index 0000000..8d0b295
--- /dev/null
@@ -0,0 +1,21 @@
+{
+    details = {
+       MDT = {abbrev = MDT; isDST = 1; offset = "-6:00:00"; };
+       MST = {abbrev = MST; isDST = 0; offset = "-7:00:00"; };
+       MWT = {abbrev = MWT; isDST = 1; offset = "-6:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 31 11:00:00 1918 GMT";
+           endDate = "Sun Oct 26 10:00:00 1919 GMT";
+           transitions = (
+               { date = "March/last Sunday/11:00:00"; detail = MDT; },
+               { date = "October/last Sunday/10:00:00"; detail = MST; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Mon Feb 09 11:00:00 1942 GMT"; detail = MWT; },
+       { date = "Sun Sep 30 10:00:00 1945 GMT"; detail = MST; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/US/Central b/libFoundation/Resources/TimeZoneInfo/US/Central
new file mode 100644 (file)
index 0000000..9eaf31a
--- /dev/null
@@ -0,0 +1,49 @@
+{
+    details = {
+       CDT = {abbrev = CDT; isDST = 1; offset = "-5:00:00"; };
+       CST = {abbrev = CST; isDST = 0; offset = "-6:00:00"; };
+       CWT = {abbrev = CWT; isDST = 1; offset = "-5:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 31 10:00:00 1918 GMT";
+           endDate = "Sun Oct 26 09:00:00 1919 GMT";
+           transitions = (
+               { date = "March/last Sunday/10:00:00"; detail = CDT; },
+               { date = "October/last Sunday/9:00:00"; detail = CST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 30 10:00:00 1967 GMT";
+           endDate = "Sun Oct 28 09:00:00 1973 GMT";
+           transitions = (
+               { date = "April/last Sunday/10:00:00"; detail = CDT; },
+               { date = "October/last Sunday/9:00:00"; detail = CST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 25 10:00:00 1976 GMT";
+           endDate = "Sun Oct 26 09:00:00 1986 GMT";
+           transitions = (
+               { date = "April/last Sunday/10:00:00"; detail = CDT; },
+               { date = "October/last Sunday/9:00:00"; detail = CST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 05 10:00:00 1987 GMT";
+           endDate = "Sun Oct 25 09:00:00 2037 GMT";
+           transitions = (
+               { date = "April/first Sunday/10:00:00"; detail = CDT; },
+               { date = "October/last Sunday/9:00:00"; detail = CST; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Mon Feb 09 10:00:00 1942 GMT"; detail = CWT; },
+       { date = "Sun Sep 30 09:00:00 1945 GMT"; detail = CST; },
+       { date = "Sun Jan 06 10:00:00 1974 GMT"; detail = CDT; },
+       { date = "Sun Oct 27 09:00:00 1974 GMT"; detail = CST; },
+       { date = "Sun Feb 23 10:00:00 1975 GMT"; detail = CDT; },
+       { date = "Sun Oct 26 09:00:00 1975 GMT"; detail = CST; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/US/East-Indiana b/libFoundation/Resources/TimeZoneInfo/US/East-Indiana
new file mode 100644 (file)
index 0000000..cc8663a
--- /dev/null
@@ -0,0 +1,21 @@
+{
+    details = {
+       EDT = {abbrev = EDT; isDST = 1; offset = "-4:00:00"; };
+       EST = {abbrev = EST; isDST = 0; offset = "-5:00:00"; };
+       EWT = {abbrev = EWT; isDST = 1; offset = "-4:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 31 09:00:00 1918 GMT";
+           endDate = "Sun Oct 26 08:00:00 1919 GMT";
+           transitions = (
+               { date = "March/last Sunday/9:00:00"; detail = EDT; },
+               { date = "October/last Sunday/8:00:00"; detail = EST; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Mon Feb 09 09:00:00 1942 GMT"; detail = EWT; },
+       { date = "Sun Sep 30 08:00:00 1945 GMT"; detail = EST; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/US/Eastern b/libFoundation/Resources/TimeZoneInfo/US/Eastern
new file mode 100644 (file)
index 0000000..62c7b77
--- /dev/null
@@ -0,0 +1,49 @@
+{
+    details = {
+       EDT = {abbrev = EDT; isDST = 1; offset = "-4:00:00"; };
+       EST = {abbrev = EST; isDST = 0; offset = "-5:00:00"; };
+       EWT = {abbrev = EWT; isDST = 1; offset = "-4:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 31 09:00:00 1918 GMT";
+           endDate = "Sun Oct 26 08:00:00 1919 GMT";
+           transitions = (
+               { date = "March/last Sunday/9:00:00"; detail = EDT; },
+               { date = "October/last Sunday/8:00:00"; detail = EST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 30 09:00:00 1967 GMT";
+           endDate = "Sun Oct 28 08:00:00 1973 GMT";
+           transitions = (
+               { date = "April/last Sunday/9:00:00"; detail = EDT; },
+               { date = "October/last Sunday/8:00:00"; detail = EST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 25 09:00:00 1976 GMT";
+           endDate = "Sun Oct 26 08:00:00 1986 GMT";
+           transitions = (
+               { date = "April/last Sunday/9:00:00"; detail = EDT; },
+               { date = "October/last Sunday/8:00:00"; detail = EST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 05 09:00:00 1987 GMT";
+           endDate = "Sun Oct 25 08:00:00 2037 GMT";
+           transitions = (
+               { date = "April/first Sunday/9:00:00"; detail = EDT; },
+               { date = "October/last Sunday/8:00:00"; detail = EST; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Mon Feb 09 09:00:00 1942 GMT"; detail = EWT; },
+       { date = "Sun Sep 30 08:00:00 1945 GMT"; detail = EST; },
+       { date = "Sun Jan 06 09:00:00 1974 GMT"; detail = EDT; },
+       { date = "Sun Oct 27 08:00:00 1974 GMT"; detail = EST; },
+       { date = "Sun Feb 23 09:00:00 1975 GMT"; detail = EDT; },
+       { date = "Sun Oct 26 08:00:00 1975 GMT"; detail = EST; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/US/Hawaii b/libFoundation/Resources/TimeZoneInfo/US/Hawaii
new file mode 100644 (file)
index 0000000..1556d88
--- /dev/null
@@ -0,0 +1,25 @@
+{
+    details = {
+       HDT = {abbrev = HDT; isDST = 1; offset = "-9:30:00"; };
+       HST = {abbrev = HST; isDST = 0; offset = "-10:30:00"; };
+       HST2 = {abbrev = HST; isDST = 0; offset = "-10:00:00"; };
+       HWT = {abbrev = HWT; isDST = 1; offset = "-9:30:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 31 14:30:00 1918 GMT";
+           endDate = "Sun Oct 26 13:30:00 1919 GMT";
+           transitions = (
+               { date = "March/last Sunday/14:30:00"; detail = HDT; },
+               { date = "October/last Sunday/13:30:00"; detail = HST; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Sun Apr 30 14:30:00 1933 GMT"; detail = HDT; },
+       { date = "Mon May 01 13:30:00 1933 GMT"; detail = HST; },
+       { date = "Mon Feb 09 14:30:00 1942 GMT"; detail = HWT; },
+       { date = "Sun Sep 30 13:30:00 1945 GMT"; detail = HST; },
+       { date = "Sun Jun 08 14:30:00 1947 GMT"; detail = HST2; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/US/Mountain b/libFoundation/Resources/TimeZoneInfo/US/Mountain
new file mode 100644 (file)
index 0000000..91ab107
--- /dev/null
@@ -0,0 +1,49 @@
+{
+    details = {
+       MDT = {abbrev = MDT; isDST = 1; offset = "-6:00:00"; };
+       MST = {abbrev = MST; isDST = 0; offset = "-7:00:00"; };
+       MWT = {abbrev = MWT; isDST = 1; offset = "-6:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 31 11:00:00 1918 GMT";
+           endDate = "Sun Oct 26 10:00:00 1919 GMT";
+           transitions = (
+               { date = "March/last Sunday/11:00:00"; detail = MDT; },
+               { date = "October/last Sunday/10:00:00"; detail = MST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 30 11:00:00 1967 GMT";
+           endDate = "Sun Oct 28 10:00:00 1973 GMT";
+           transitions = (
+               { date = "April/last Sunday/11:00:00"; detail = MDT; },
+               { date = "October/last Sunday/10:00:00"; detail = MST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 25 11:00:00 1976 GMT";
+           endDate = "Sun Oct 26 10:00:00 1986 GMT";
+           transitions = (
+               { date = "April/last Sunday/11:00:00"; detail = MDT; },
+               { date = "October/last Sunday/10:00:00"; detail = MST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 05 11:00:00 1987 GMT";
+           endDate = "Sun Oct 25 10:00:00 2037 GMT";
+           transitions = (
+               { date = "April/first Sunday/11:00:00"; detail = MDT; },
+               { date = "October/last Sunday/10:00:00"; detail = MST; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Mon Feb 09 11:00:00 1942 GMT"; detail = MWT; },
+       { date = "Sun Sep 30 10:00:00 1945 GMT"; detail = MST; },
+       { date = "Sun Jan 06 11:00:00 1974 GMT"; detail = MDT; },
+       { date = "Sun Oct 27 10:00:00 1974 GMT"; detail = MST; },
+       { date = "Sun Feb 23 11:00:00 1975 GMT"; detail = MDT; },
+       { date = "Sun Oct 26 10:00:00 1975 GMT"; detail = MST; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/US/Pacific b/libFoundation/Resources/TimeZoneInfo/US/Pacific
new file mode 100644 (file)
index 0000000..23f6fb0
--- /dev/null
@@ -0,0 +1,49 @@
+{
+    details = {
+       PDT = {abbrev = PDT; isDST = 1; offset = "-7:00:00"; };
+       PST = {abbrev = PST; isDST = 0; offset = "-8:00:00"; };
+       PWT = {abbrev = PWT; isDST = 1; offset = "-7:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 31 12:00:00 1918 GMT";
+           endDate = "Sun Oct 26 11:00:00 1919 GMT";
+           transitions = (
+               { date = "March/last Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 30 12:00:00 1967 GMT";
+           endDate = "Sun Oct 28 11:00:00 1973 GMT";
+           transitions = (
+               { date = "April/last Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 25 12:00:00 1976 GMT";
+           endDate = "Sun Oct 26 11:00:00 1986 GMT";
+           transitions = (
+               { date = "April/last Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 05 12:00:00 1987 GMT";
+           endDate = "Sun Oct 25 11:00:00 2037 GMT";
+           transitions = (
+               { date = "April/first Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Mon Feb 09 12:00:00 1942 GMT"; detail = PWT; },
+       { date = "Sun Sep 30 11:00:00 1945 GMT"; detail = PST; },
+       { date = "Sun Jan 06 12:00:00 1974 GMT"; detail = PDT; },
+       { date = "Sun Oct 27 11:00:00 1974 GMT"; detail = PST; },
+       { date = "Sun Feb 23 12:00:00 1975 GMT"; detail = PDT; },
+       { date = "Sun Oct 26 11:00:00 1975 GMT"; detail = PST; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/US/Pacific-New b/libFoundation/Resources/TimeZoneInfo/US/Pacific-New
new file mode 100644 (file)
index 0000000..ac1d25f
--- /dev/null
@@ -0,0 +1,181 @@
+{
+    details = {
+       PDT = {abbrev = PDT; isDST = 1; offset = "-7:00:00"; };
+       PPET = {abbrev = PPET; isDST = 1; offset = "-7:00:00"; };
+       PST = {abbrev = PST; isDST = 0; offset = "-8:00:00"; };
+       PWT = {abbrev = PWT; isDST = 1; offset = "-7:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 31 12:00:00 1918 GMT";
+           endDate = "Sun Oct 26 11:00:00 1919 GMT";
+           transitions = (
+               { date = "March/last Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 30 12:00:00 1967 GMT";
+           endDate = "Sun Oct 28 11:00:00 1973 GMT";
+           transitions = (
+               { date = "April/last Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 25 12:00:00 1976 GMT";
+           endDate = "Sun Oct 26 11:00:00 1986 GMT";
+           transitions = (
+               { date = "April/last Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 02 12:00:00 1989 GMT";
+           endDate = "Sun Oct 27 11:00:00 1991 GMT";
+           transitions = (
+               { date = "April/first Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 04 12:00:00 1993 GMT";
+           endDate = "Sun Oct 29 11:00:00 1995 GMT";
+           transitions = (
+               { date = "April/first Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 06 12:00:00 1997 GMT";
+           endDate = "Sun Oct 31 11:00:00 1999 GMT";
+           transitions = (
+               { date = "April/first Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 01 12:00:00 2001 GMT";
+           endDate = "Sun Oct 26 11:00:00 2003 GMT";
+           transitions = (
+               { date = "April/first Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 03 12:00:00 2005 GMT";
+           endDate = "Sun Oct 28 11:00:00 2007 GMT";
+           transitions = (
+               { date = "April/first Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 05 12:00:00 2009 GMT";
+           endDate = "Sun Oct 30 11:00:00 2011 GMT";
+           transitions = (
+               { date = "April/first Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 07 12:00:00 2013 GMT";
+           endDate = "Sun Oct 25 11:00:00 2015 GMT";
+           transitions = (
+               { date = "April/first Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 02 12:00:00 2017 GMT";
+           endDate = "Sun Oct 27 11:00:00 2019 GMT";
+           transitions = (
+               { date = "April/first Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 04 12:00:00 2021 GMT";
+           endDate = "Sun Oct 29 11:00:00 2023 GMT";
+           transitions = (
+               { date = "April/first Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 06 12:00:00 2025 GMT";
+           endDate = "Sun Oct 31 11:00:00 2027 GMT";
+           transitions = (
+               { date = "April/first Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 01 12:00:00 2029 GMT";
+           endDate = "Sun Oct 26 11:00:00 2031 GMT";
+           transitions = (
+               { date = "April/first Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 03 12:00:00 2033 GMT";
+           endDate = "Sun Oct 28 11:00:00 2035 GMT";
+           transitions = (
+               { date = "April/first Sunday/12:00:00"; detail = PDT; },
+               { date = "October/last Sunday/11:00:00"; detail = PST; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Mon Feb 09 12:00:00 1942 GMT"; detail = PWT; },
+       { date = "Sun Sep 30 11:00:00 1945 GMT"; detail = PST; },
+       { date = "Sun Jan 06 12:00:00 1974 GMT"; detail = PDT; },
+       { date = "Sun Oct 27 11:00:00 1974 GMT"; detail = PST; },
+       { date = "Sun Feb 23 12:00:00 1975 GMT"; detail = PDT; },
+       { date = "Sun Oct 26 11:00:00 1975 GMT"; detail = PST; },
+       { date = "Sun Apr 05 12:00:00 1987 GMT"; detail = PDT; },
+       { date = "Sun Oct 25 11:00:00 1987 GMT"; detail = PST; },
+       { date = "Sun Apr 03 12:00:00 1988 GMT"; detail = PDT; },
+       { date = "Sun Oct 30 11:00:00 1988 GMT"; detail = PPET; },
+       { date = "Sun Nov 13 11:00:00 1988 GMT"; detail = PST; },
+       { date = "Sun Apr 05 12:00:00 1992 GMT"; detail = PDT; },
+       { date = "Sun Oct 25 11:00:00 1992 GMT"; detail = PPET; },
+       { date = "Sun Nov 08 11:00:00 1992 GMT"; detail = PST; },
+       { date = "Sun Apr 07 12:00:00 1996 GMT"; detail = PDT; },
+       { date = "Sun Oct 27 11:00:00 1996 GMT"; detail = PPET; },
+       { date = "Sun Nov 10 11:00:00 1996 GMT"; detail = PST; },
+       { date = "Sun Apr 02 12:00:00 2000 GMT"; detail = PDT; },
+       { date = "Sun Oct 29 11:00:00 2000 GMT"; detail = PPET; },
+       { date = "Sun Nov 12 11:00:00 2000 GMT"; detail = PST; },
+       { date = "Sun Apr 04 12:00:00 2004 GMT"; detail = PDT; },
+       { date = "Sun Oct 31 11:00:00 2004 GMT"; detail = PPET; },
+       { date = "Sun Nov 07 11:00:00 2004 GMT"; detail = PST; },
+       { date = "Sun Apr 06 12:00:00 2008 GMT"; detail = PDT; },
+       { date = "Sun Oct 26 11:00:00 2008 GMT"; detail = PPET; },
+       { date = "Sun Nov 09 11:00:00 2008 GMT"; detail = PST; },
+       { date = "Sun Apr 01 12:00:00 2012 GMT"; detail = PDT; },
+       { date = "Sun Oct 28 11:00:00 2012 GMT"; detail = PPET; },
+       { date = "Sun Nov 11 11:00:00 2012 GMT"; detail = PST; },
+       { date = "Sun Apr 03 12:00:00 2016 GMT"; detail = PDT; },
+       { date = "Sun Oct 30 11:00:00 2016 GMT"; detail = PPET; },
+       { date = "Sun Nov 13 11:00:00 2016 GMT"; detail = PST; },
+       { date = "Sun Apr 05 12:00:00 2020 GMT"; detail = PDT; },
+       { date = "Sun Oct 25 11:00:00 2020 GMT"; detail = PPET; },
+       { date = "Sun Nov 08 11:00:00 2020 GMT"; detail = PST; },
+       { date = "Sun Apr 07 12:00:00 2024 GMT"; detail = PDT; },
+       { date = "Sun Oct 27 11:00:00 2024 GMT"; detail = PPET; },
+       { date = "Sun Nov 10 11:00:00 2024 GMT"; detail = PST; },
+       { date = "Sun Apr 02 12:00:00 2028 GMT"; detail = PDT; },
+       { date = "Sun Oct 29 11:00:00 2028 GMT"; detail = PPET; },
+       { date = "Sun Nov 12 11:00:00 2028 GMT"; detail = PST; },
+       { date = "Sun Apr 04 12:00:00 2032 GMT"; detail = PDT; },
+       { date = "Sun Oct 31 11:00:00 2032 GMT"; detail = PPET; },
+       { date = "Sun Nov 07 11:00:00 2032 GMT"; detail = PST; },
+       { date = "Sun Apr 06 12:00:00 2036 GMT"; detail = PDT; },
+       { date = "Sun Oct 26 11:00:00 2036 GMT"; detail = PPET; },
+       { date = "Sun Nov 09 11:00:00 2036 GMT"; detail = PST; },
+       { date = "Sun Apr 05 12:00:00 2037 GMT"; detail = PDT; },
+       { date = "Sun Oct 25 11:00:00 2037 GMT"; detail = PST; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/US/Yukon b/libFoundation/Resources/TimeZoneInfo/US/Yukon
new file mode 100644 (file)
index 0000000..95144a2
--- /dev/null
@@ -0,0 +1,49 @@
+{
+    details = {
+       YDT = {abbrev = YDT; isDST = 1; offset = "-8:00:00"; };
+       YST = {abbrev = YST; isDST = 0; offset = "-9:00:00"; };
+       YWT = {abbrev = YWT; isDST = 1; offset = "-8:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 31 13:00:00 1918 GMT";
+           endDate = "Sun Oct 26 12:00:00 1919 GMT";
+           transitions = (
+               { date = "March/last Sunday/13:00:00"; detail = YDT; },
+               { date = "October/last Sunday/12:00:00"; detail = YST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 30 13:00:00 1967 GMT";
+           endDate = "Sun Oct 28 12:00:00 1973 GMT";
+           transitions = (
+               { date = "April/last Sunday/13:00:00"; detail = YDT; },
+               { date = "October/last Sunday/12:00:00"; detail = YST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 25 13:00:00 1976 GMT";
+           endDate = "Sun Oct 26 12:00:00 1986 GMT";
+           transitions = (
+               { date = "April/last Sunday/13:00:00"; detail = YDT; },
+               { date = "October/last Sunday/12:00:00"; detail = YST; }
+           );
+       },
+       {
+           startDate = "Sun Apr 05 13:00:00 1987 GMT";
+           endDate = "Sun Oct 25 12:00:00 2037 GMT";
+           transitions = (
+               { date = "April/first Sunday/13:00:00"; detail = YDT; },
+               { date = "October/last Sunday/12:00:00"; detail = YST; }
+           );
+       }
+    );
+    transitions = (
+       { date = "Mon Feb 09 13:00:00 1942 GMT"; detail = YWT; },
+       { date = "Sun Sep 30 12:00:00 1945 GMT"; detail = YST; },
+       { date = "Sun Jan 06 13:00:00 1974 GMT"; detail = YDT; },
+       { date = "Sun Oct 27 12:00:00 1974 GMT"; detail = YST; },
+       { date = "Sun Feb 23 13:00:00 1975 GMT"; detail = YDT; },
+       { date = "Sun Oct 26 12:00:00 1975 GMT"; detail = YST; }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/UTC b/libFoundation/Resources/TimeZoneInfo/UTC
new file mode 100644 (file)
index 0000000..d897b30
--- /dev/null
@@ -0,0 +1 @@
+{details = {GMT = {abbrev = GMT; isDST = 0; offset = "+0:00:00"; }; }; }
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/Universal b/libFoundation/Resources/TimeZoneInfo/Universal
new file mode 100644 (file)
index 0000000..d897b30
--- /dev/null
@@ -0,0 +1 @@
+{details = {GMT = {abbrev = GMT; isDST = 0; offset = "+0:00:00"; }; }; }
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/W-SU b/libFoundation/Resources/TimeZoneInfo/W-SU
new file mode 100644 (file)
index 0000000..9305917
--- /dev/null
@@ -0,0 +1,24 @@
+{
+    details = {
+       "????" = {abbrev = "????"; isDST = 1; offset = "+4:00:00"; };
+       "????2" = {abbrev = "????"; isDST = 0; offset = "+3:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 30 01:00:00 1986 GMT";
+           endDate = "Sun Sep 24 01:00:00 1995 GMT";
+           transitions = (
+               { date = "March/last Sunday/1:00:00"; detail = "????"; },
+               { date = "September/last Sunday/1:00:00"; detail = "????2"; }
+           );
+       },
+       {
+           startDate = "Sun Mar 31 01:00:00 1996 GMT";
+           endDate = "Sun Oct 25 01:00:00 2037 GMT";
+           transitions = (
+               { date = "March/last Sunday/1:00:00"; detail = "????"; },
+               { date = "October/last Sunday/1:00:00"; detail = "????2"; }
+           );
+       }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/WET b/libFoundation/Resources/TimeZoneInfo/WET
new file mode 100644 (file)
index 0000000..d9c67ad
--- /dev/null
@@ -0,0 +1,24 @@
+{
+    details = {
+       WET = {abbrev = WET; isDST = 0; offset = "+0:00:00"; };
+       "WET DST" = {abbrev = "WET DST"; isDST = 1; offset = "+1:00:00"; };
+    };
+    rules = (
+       {
+           startDate = "Sun Mar 30 03:00:00 1986 GMT";
+           endDate = "Sun Sep 24 03:00:00 1995 GMT";
+           transitions = (
+               { date = "March/last Sunday/3:00:00"; detail = "WET DST"; },
+               { date = "September/last Sunday/3:00:00"; detail = WET; }
+           );
+       },
+       {
+           startDate = "Sun Mar 31 03:00:00 1996 GMT";
+           endDate = "Sun Oct 25 03:00:00 2037 GMT";
+           transitions = (
+               { date = "March/last Sunday/3:00:00"; detail = "WET DST"; },
+               { date = "October/last Sunday/3:00:00"; detail = WET; }
+           );
+       }
+    );
+}
\ No newline at end of file
diff --git a/libFoundation/Resources/TimeZoneInfo/create b/libFoundation/Resources/TimeZoneInfo/create
new file mode 100644 (file)
index 0000000..84fefed
--- /dev/null
@@ -0,0 +1,12 @@
+for ((i=0; i < 12; i=i+1)); do 
+  if test $i -lt 10; then export is=0$i; else export is=$i; fi;
+  echo "{
+   details = {"GMT+${is}30" = {abbrev = "GMT+${is}30"; isDST = 0; offset = "+${i}:30:00"; }; };
+}" > GMT+${i}_30; done;
+
+for ((i=0; i < 12; i=i+1)); do 
+  if test $i -lt 10; then export is=0$i; else export is=$i; fi;
+  echo "{
+   details = {"GMT-${is}30" = {abbrev = "GMT-${is}30"; isDST = 0; offset = "-${i}:30:00"; }; };
+}" > GMT-${i}_30; done;
+
diff --git a/libFoundation/TODO b/libFoundation/TODO
new file mode 100644 (file)
index 0000000..13f9f86
--- /dev/null
@@ -0,0 +1,211 @@
+=========================== BIG THINGS TO DO ==================================
+
+- Distributed Objects
+- Unicode support in NSString
+- change the NSInvocation and NSMethodSignature machine dependent macros to
+  use the macros defined into the GNU compiler. This should eventually become
+  part of the GNU Objective-C runtime library.
+- locale support?
+
+========================== SMALL THINGS TO DO =================================
+
+- Bug: descriptionWithCalendarFormat:timeZone:locale: does not honor timezone
+  argument, at least with NSCalendarDate (SKYRIX Bug 1106)
+
+- finish NSFileManager
+- port to HP-UX (NSInvocation and NSMethodSignature)
+  (what about OSF/1 and Ultrix?)
+- serializer/deserializer
+- change NSZone from class to struct
+- finish NSByteOrder.h
+- HH: avoid creating/releasing the formatter objects in common.m:Avsprintf
+- HH: check return value of 'objc_thread_detach' in NSThread.m
+- HH: description methods of NSCalendarFormat must be made timezone-aware
+- HH: support GetTempPath() with mingw32
+- HH: finish NSSearchPathForDirectoriesInDomains() function
+- HH: merge implementation of -stringByTrimmingTailWhiteSpaces and 
+      -stringByTrimmingTailWhiteSpaces? Or remove them altogether (not part
+      of gstep-base anymore either?)
+
+- HH: add -replaceOccurrencesOfString:withString:options:range: 
+
+- NSCalendarDate parser can't parse '20041212' with %Y%m%d, because it uses
+  scanInt: which parses that as a complete int (needs a char-count limit)
+
+============================ general checks ===================================
+
+(The following does not necessary mean they are missing ;-). These should
+remind implementors what do they have to check for. )
+
+- implement `copyWithZone:' and `mutableCopyWithZone:' for all classes
+
+- implement `encodeWithCoder:' and `initWithCoder:' for all classes
+
+- implement meaningful `description', `descriptionWithIndent:' or
+`stringRepresentation'
+
+- revise `hash' `isEqual:' and `compare:' methods for all containers so that
+  isEqual/compare/hash shoud be consistent
+
+- check that all `dealloc' calls [super dealloc] to release memory
+
+- check that calls to [super init] are done before *any* ivar is set
+
+- check imutable `copyWithZone:' for containers so that it performs a deep
+  copy, making all its content imutable
+
+- check mutable `mutableCopyWithZone:' for containers so that it performs a
+  shallow copy, making all its content imutable
+
+- thread-safe notes (comment with `// THREAD') where we access global variables
+
+================================== CLASSES ====================================
+
+NSArchiver, NSUnarchiver
+       - more tests
+
+NSArray, NSMutableArray
+       - extended tests
+       - init* methods for immutable should throw if called twice
+
+NSAutoreleasePool
+       - OK
+
+NSBundle
+       - implement unloading of code (need some patches to objc-runtime)
+
+NSCharacterSet, NSMutableCharacterSet
+       - init* methods for immutable should throw if called twice
+       - extended tests
+
+NSCoder
+       - more tests with it and the NSArchiver for all methods
+
+NSConnection, NSDistantObject, NSProxy
+       - TODO
+
+NSData, NSMutableData
+       - extended tests
+       - init* methods for immutable should throw if called twice
+       - check subclasses for mmap and range
+
+NSDate, NSCalendarDate
+       - init* methods for immutable should throw if called twice
+       - extended tests
+
+NSDictionary, NSMutableDictionary
+       - init* methods for immutable should throw if called twice
+       - tests
+
+NSDistributedLock
+       - test that checks concurrence
+
+NSEnumerator
+       - OK
+
+NSException
+       - OK
+
+NSFileHandle
+       - tests
+
+NSFileManager
+       - tests
+       - finish implementation (2-3 methods left)
+
+NSInvocation
+       - port and test on HPPA HPUX
+       - test on Solaris
+
+NSMethodSignature
+       - port and test on HPPA HPUX
+       - test on Solaris (code was written)
+
+NSLock, NSRecursiveLock,  NSConditionLock
+       - OK
+
+NSNotification, NSNotificationCenter, NSNotificationQueue
+       - OK
+
+NSObject
+       - OK
+
+NSPipe
+       - tests
+
+NSPosixFileDescriptor
+       - tests
+
+NSProcessInfo
+       - OK
+
+NSRunLoop
+       - write code that determines when the process is idle
+
+NSScanner
+       - OK
+
+NSSerializer, NSDeserializer
+       - TODO
+
+NSSet, NSMutableSet,  NSCountedSet
+       - tests for all methods
+       - write init* in concrete classes
+       - init* methods for immutable should throw if called twice
+
+NSString, NSMutableString
+       - add support for Unicode
+
+NSTask
+       - OK
+
+NSThread
+       - tests
+
+NSTimeZone, NSTimeZoneDetail
+       - tests
+
+NSTimer
+       - tests
+
+NSUserDefaults
+       - put command-line args in NSArgument domain
+
+NSValue, NSNumber
+       - tests
+
+NSZone (NSDefaultZone)
+       - make an allocator with zones using page-allocation functions
+       - make a non-free zone and support recycle
+
+UnixSignalHandler
+       - OK
+
+NSStream, NSInputStream, NSOutputStream
+        - implement
+
+NSError, NSURLError
+        - implement
+
+================================ DOCUMENTATION ===============================
+
+- comment the headers about classes, functions, ivars
+- comment sources about class structure and general ideas
+- README.debugging
+
+================================ NEW CLASSES =================================
+
+Ascii Coder
+       - TODO: human readable and easy modifiable format. Such a class was
+       already designed and implemented and it is used for archiving
+       and unarchiving GNUstep GUI objects.
+
+Regexp support 
+       - new class and support methods in a category to NSString
+
+========================== Configure, Makefile, Porting ======================
+
+We discussed long time ago about a makefile package to help developers
+easily build libraries and applications using the current free
+libraries written in Objective-C. This was finally implemented by
+Scott Christley and Ovidiu Predescu in the GNUstep makefile package.
diff --git a/libFoundation/Version b/libFoundation/Version
new file mode 100644 (file)
index 0000000..c4e177c
--- /dev/null
@@ -0,0 +1,5 @@
+# version file
+
+MAJOR_VERSION:=1
+MINOR_VERSION:=0
+SUBMINOR_VERSION:=75
diff --git a/libFoundation/aclocal.m4 b/libFoundation/aclocal.m4
new file mode 100644 (file)
index 0000000..5faef8c
--- /dev/null
@@ -0,0 +1,269 @@
+AC_SUBST(MAKE)
+AC_SUBST(OBJC_RUNTIME)
+AC_SUBST(OBJC_RUNTIME_FLAG)
+AC_SUBST(BROKEN_COMPILER)
+AC_SUBST(BROKEN_BUILTIN_APPLY)
+AC_SUBST(NO_NESTED_FUNCTIONS)
+AC_SUBST(PCCTS_CFLAGS)
+AC_SUBST(HOST)dnl
+AC_SUBST(HOST_CPU)dnl
+AC_SUBST(HOST_VENDOR)dnl
+AC_SUBST(HOST_OS)dnl
+AC_SUBST(TARGET)dnl
+AC_SUBST(TARGET_CPU)dnl
+AC_SUBST(TARGET_VENDOR)dnl
+AC_SUBST(TARGET_OS)dnl
+AC_SUBST(STRUCT_ALIGNMENT)dnl
+dnl
+dnl
+AC_DEFUN(AC_LANG_OBJECTIVE_C,
+[AC_REQUIRE([AC_PROG_CC])dnl
+define([AC_LANG], [AC_LANG_OBJECTIVE_C])dnl
+OLD_IFS=$IFS
+IFS=:
+for i in $LD_LIBRARY_PATH
+do
+  LDFLAGS="-L$i $LDFLAGS"
+done
+IFS=$OLD_IFS
+LIBS="-lobjc $LIBS"
+ac_ext=m
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $OBJC_RUNTIME_FLAG'
+ac_compile='${CC-cc} -c $OBJC_RUNTIME_FLAG $CFLAGS conftest.$ac_ext 1>&AC_FD_CC 2>&AC_FD_CC'
+ac_link='${CC-cc} -o conftest $OBJC_RUNTIME_FLAG $CFLAGS $LDFLAGS conftest.$ac_ext $LIBS $OBJC_LIBS 1>&AC_FD_CC 2>&AC_FD_CC'
+])dnl
+dnl
+dnl
+AC_DEFUN(AC_CHECK_NESTED_FUNCTIONS,
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_MSG_CHECKING(whether nested functions work)
+AC_CACHE_VAL(ac_cv_nested_functions,
+[AC_LANG_SAVE[]dnl
+AC_LANG_OBJECTIVE_C[]
+AC_TRY_RUN([
+f(void (*nested)())
+{
+    (*nested)();
+}
+
+main()
+{
+    int a = 0;
+    void nested()
+    {
+       a = 1;
+    }
+    f(nested);
+    if(a != 1)
+       exit(1);
+    exit(0);
+}
+], ac_cv_nested_functions=yes, ac_cv_nested_functions=no,
+ac_cv_nested_functions=yes)
+AC_LANG_RESTORE[]
+])dnl
+AC_MSG_RESULT(${ac_cv_nested_functions})
+NO_NESTED_FUNCTIONS=no
+if test $ac_cv_nested_functions = no; then
+    AC_DEFINE(NO_NESTED_FUNCTIONS)
+    NO_NESTED_FUNCTIONS=yes
+fi
+])dnl
+dnl
+dnl
+AC_DEFUN(AC_BROKEN_COMPILER,
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_MSG_CHECKING(if the Objective-C compiler crashes with nested functions)
+AC_CACHE_VAL(ac_cv_broken_compiler,
+[AC_LANG_SAVE[]dnl
+AC_LANG_OBJECTIVE_C[]
+AC_TRY_RUN([
+#include <objc/objc.h>
+#include <objc/Object.h>
+
+void f()
+{
+    auto void h(id);
+
+    void h(id exception)
+    {
+       [Object alloc];
+       {
+           void clean(void)
+           {
+           }
+       }
+    }
+}
+
+void g()
+{
+    auto void h(id);
+
+    void h(id exception)
+    {
+       [Object alloc];
+    }
+}
+
+main()
+{
+    exit(0);
+}
+], ac_cv_broken_compiler=no,
+ac_cv_broken_compiler=yes,
+ac_cv_broken_compiler=no)
+AC_LANG_RESTORE[]
+])dnl
+BROKEN_COMPILER=${ac_cv_broken_compiler}
+if test ${ac_cv_nested_functions} = no -o ${ac_cv_broken_compiler} = yes; then
+  ac_cv_broken_compiler=yes;
+  BROKEN_COMPILER=yes;
+  AC_DEFINE(BROKEN_COMPILER)
+fi
+AC_MSG_RESULT(${ac_cv_broken_compiler})
+])dnl
+dnl
+dnl
+AC_DEFUN(AC_BROKEN_BUILTIN_APPLY,
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_MSG_CHECKING(whether __builtin_apply and __builtin_return are broken)
+AC_CACHE_VAL(ac_cv_broken_builtin_apply,
+[AC_LANG_SAVE[]dnl
+AC_LANG_OBJECTIVE_C[]
+AC_TRY_RUN([
+#include <objc/Object.h>
+
+float value = 123.456;
+
+@interface MyObject : Object
+@end
+
+@implementation MyObject
+- (float)floatValue
+{
+    return value;
+}
+@end
+
+@interface Forwarder : Object
+{
+    id object;
+}
+@end
+
+@implementation Forwarder
+- setObject:anObject
+{
+    object = anObject;
+    return self;
+}
+
+- (void*)forward:(SEL)selector:(void*)argframe
+{
+    IMP imp = [object methodFor:@selector(floatValue)];
+    void* retframe;
+    void* frame = malloc(116);
+    *(void**)frame = NULL;
+    retframe = __builtin_apply((void(*)(void))imp, frame, 0);
+    if(*(long double*)(((char*)retframe) + 8) == (long double)value)
+       exit(0);
+    exit(1);
+}
+@end
+
+int main()
+{
+    id fwd = [[[Forwarder alloc] init] setObject:[MyObject alloc]];
+    [fwd floatValue];
+    exit(0);
+    return 0; // keep compiler happy
+}
+], ac_cv_broken_builtin_apply=no,
+ac_cv_broken_builtin_apply=yes,
+ac_cv_broken_builtin_apply=no)
+AC_LANG_RESTORE[]
+])dnl
+AC_MSG_RESULT(${ac_cv_broken_builtin_apply})
+BROKEN_BUILTIN_APPLY=${ac_cv_broken_builtin_apply}
+if test $BROKEN_BUILTIN_APPLY = yes; then
+    AC_DEFINE(BROKEN_BUILTIN_APPLY)
+fi
+])dnl
+dnl
+dnl
+AC_DEFUN(AC_CHECK_MATH_LIB,
+[AC_REQUIRE([AC_PROG_CC])dnl
+dnl temporary rename AC_MSG_RESULT to do nothing
+define(old_AC_MSG_RESULT, defn([AC_MSG_RESULT]))dnl
+define([AC_MSG_RESULT],)dnl
+AC_CHECK_FUNC(sqrt, ,
+[dnl On linux, to link a program that use math functions we must link with libm.a
+LIBS="$LIBS -lm -lc"
+ac_cv_func_sqrt=no
+AC_TRY_LINK(, [
+double sqrt(double);
+sqrt(2.0);
+], ac_cv_func_sqrt="-lm -lc")
+])
+define([AC_MSG_RESULT], defn([old_AC_MSG_RESULT]))dnl
+undefine([old_AC_MSG_RESULT])dnl
+AC_MSG_RESULT($ac_cv_func_sqrt)
+])dnl
+dnl
+dnl
+AC_DEFUN(AC_STRUCT_ALIGNMENT,
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_MSG_CHECKING(for the C structures alignment)
+AC_CACHE_VAL(ac_cv_struct_alignment,
+[AC_TRY_RUN([#include <stdio.h>
+
+struct simple {
+    double x;
+    char y;
+} simple1;
+
+int struct_alignment = __alignof__ (simple1);
+
+main()
+{
+  FILE *f=fopen("conftestval", "w");
+  if (!f) exit(1);
+  fprintf(f, "%u\n", struct_alignment);
+  exit(0);
+}
+], ac_cv_struct_alignment=`cat conftestval`,
+ac_cv_struct_alignment=0,
+ifelse([$2], , , ac_cv_struct_alignment=$2))])dnl
+AC_MSG_RESULT($ac_cv_struct_alignment)
+STRUCT_ALIGNMENT=$ac_cv_struct_alignment
+])dnl
+dnl
+dnl
+AC_DEFUN(AC_COMPILE_CHECK_SIZEOF,
+[changequote(<<, >>)dnl 
+dnl The name to #define. 
+define(<<AC_TYPE_NAME>>, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl 
+dnl The cache variable name. 
+define(<<AC_CV_NAME>>, translit(ac_cv_sizeof_$1, [ *], [_p]))dnl 
+changequote([, ])dnl 
+AC_MSG_CHECKING(size of $1) 
+AC_CACHE_VAL(AC_CV_NAME, 
+[for ac_size in 4 8 1 2 16 $2 ; do # List sizes in rough order of prevalence. 
+  AC_TRY_COMPILE([#include "confdefs.h" 
+#include <sys/types.h> 
+$2 
+], [switch (0) case 0: case (sizeof ($1) == $ac_size):;], AC_CV_NAME=$ac_size) 
+  if test x$AC_CV_NAME != x ; then break; fi 
+done 
+]) 
+if test x$AC_CV_NAME = x ; then 
+  echo "cannot determine a size for $1";
+  AC_CV_NAME=0; 
+fi 
+AC_MSG_RESULT($AC_CV_NAME) 
+AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME, [The number of bytes in type $1]) 
+undefine([AC_TYPE_NAME])dnl 
+undefine([AC_CV_NAME])dnl 
+]) 
diff --git a/libFoundation/config.guess b/libFoundation/config.guess
new file mode 100755 (executable)
index 0000000..b11ea89
--- /dev/null
@@ -0,0 +1,743 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Written by Per Bothner <bothner@cygnus.com>.
+# The master version of this file is at the FSF in /home/gd/gnu/lib.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit system type (host/target name).
+#
+# Only a few systems have been added to this list; please add others
+# (but try to keep the structure clean).
+#
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 8/24/94.)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+       PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    alpha:OSF1:*:*)
+       # A Vn.n version is a released version.
+       # A Tn.n version is a released field test version.
+       # A Xn.n version is an unreleased experimental baselevel.
+       # 1.2 uses "1.2" for uname -r.
+       echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//'`
+       exit 0 ;;
+    21064:Windows_NT:50:3)
+       echo alpha-dec-winnt3.5
+       exit 0 ;;
+    Amiga*:UNIX_System_V:4.0:*)
+       echo m68k-cbm-sysv4
+       exit 0;;
+    amiga:NetBSD:*:*)
+      echo m68k-cbm-netbsd${UNAME_RELEASE}
+      exit 0 ;;
+    amiga:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    arc64:OpenBSD:*:*)
+       echo mips64el-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    arc:OpenBSD:*:*)
+       echo mipsel-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    hkmips:OpenBSD:*:*)
+       echo mips-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    pmax:OpenBSD:*:*)
+       echo mipsel-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    sgi:OpenBSD:*:*)
+       echo mips-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    wgrisc:OpenBSD:*:*)
+       echo mipsel-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+       echo arm-acorn-riscix${UNAME_RELEASE}
+       exit 0;;
+    SR2?01:HI-UX/MPP:*:*)
+       echo hppa1.1-hitachi-hiuxmpp
+       exit 0;;
+    Pyramid*:OSx*:*:*|MIS*:OSx*:*:*)
+       # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+       if test "`(/bin/universe) 2>/dev/null`" = att ; then
+               echo pyramid-pyramid-sysv3
+       else
+               echo pyramid-pyramid-bsd
+       fi
+       exit 0 ;;
+    NILE:*:*:dcosx)
+       echo pyramid-pyramid-svr4
+       exit 0 ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+       echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    i86pc:SunOS:5.*:*)
+       echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    sun4*:SunOS:6*:*)
+       # According to config.sub, this is the proper way to canonicalize
+       # SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+       # it's likely to be more like Solaris than SunOS4.
+       echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    sun4*:SunOS:*:*)
+       case "`/usr/bin/arch -k`" in
+           Series*|S4*)
+               UNAME_RELEASE=`uname -v`
+               ;;
+       esac
+       # Japanese Language versions have a version number like `4.1.3-JL'.
+       echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+       exit 0 ;;
+    sun3*:SunOS:*:*)
+       echo m68k-sun-sunos${UNAME_RELEASE}
+       exit 0 ;;
+    aushp:SunOS:*:*)
+       echo sparc-auspex-sunos${UNAME_RELEASE}
+       exit 0 ;;
+    atari*:NetBSD:*:*)
+       echo m68k-atari-netbsd${UNAME_RELEASE}
+       exit 0 ;;
+    atari*:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    sun3*:NetBSD:*:*)
+       echo m68k-sun-netbsd${UNAME_RELEASE}
+       exit 0 ;;
+    sun3*:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mac68k:NetBSD:*:*)
+       echo m68k-apple-netbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mac68k:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mvme68k:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mvme88k:OpenBSD:*:*)
+       echo m88k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    powerpc:machten:*:*)
+       echo powerpc-apple-machten${UNAME_RELEASE}
+       exit 0 ;;
+    RISC*:Mach:*:*)
+       echo mips-dec-mach_bsd4.3
+       exit 0 ;;
+    RISC*:ULTRIX:*:*)
+       echo mips-dec-ultrix${UNAME_RELEASE}
+       exit 0 ;;
+    VAX*:ULTRIX*:*:*)
+       echo vax-dec-ultrix${UNAME_RELEASE}
+       exit 0 ;;
+    2020:CLIX:*:*)
+       echo clipper-intergraph-clix${UNAME_RELEASE}
+       exit 0 ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+       sed 's/^        //' << EOF >dummy.c
+       int main (argc, argv) int argc; char **argv; {
+       #if defined (host_mips) && defined (MIPSEB)
+       #if defined (SYSTYPE_SYSV)
+         printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_SVR4)
+         printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+         printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+       #endif
+       #endif
+         exit (-1);
+       }
+EOF
+       ${CC-cc} dummy.c -o dummy \
+         && ./dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+         && rm dummy.c dummy && exit 0
+       rm -f dummy.c dummy
+       echo mips-mips-riscos${UNAME_RELEASE}
+       exit 0 ;;
+    Night_Hawk:Power_UNIX:*:*)
+       echo powerpc-harris-powerunix
+       exit 0 ;;
+    m88k:CX/UX:7*:*)
+       echo m88k-harris-cxux7
+       exit 0 ;;
+    m88k:*:4*:R4*)
+       echo m88k-motorola-sysv4
+       exit 0 ;;
+    m88k:*:3*:R3*)
+       echo m88k-motorola-sysv3
+       exit 0 ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+        if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then
+       if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
+            -o ${TARGET_BINARY_INTERFACE}x = x ] ; then
+               echo m88k-dg-dgux${UNAME_RELEASE}
+       else
+               echo m88k-dg-dguxbcs${UNAME_RELEASE}
+       fi
+        else echo i586-dg-dgux${UNAME_RELEASE}
+        fi
+       exit 0 ;;
+    M88*:DolphinOS:*:*)        # DolphinOS (SVR3)
+       echo m88k-dolphin-sysv3
+       exit 0 ;;
+    M88*:*:R3*:*)
+       # Delta 88k system running SVR3
+       echo m88k-motorola-sysv3
+       exit 0 ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+       echo m88k-tektronix-sysv3
+       exit 0 ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+       echo m68k-tektronix-bsd
+       exit 0 ;;
+    *:IRIX*:*:*)
+       echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+       exit 0 ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+       echo romp-ibm-aix      # uname -m gives an 8 hex-code CPU id
+       exit 0 ;;              # Note that: echo "'`uname -s`'" gives 'AIX '
+    i?86:AIX:*:*)
+       echo i386-ibm-aix
+       exit 0 ;;
+    *:AIX:2:3)
+       if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+               sed 's/^                //' << EOF >dummy.c
+               #include <sys/systemcfg.h>
+
+               main()
+                       {
+                       if (!__power_pc())
+                               exit(1);
+                       puts("powerpc-ibm-aix3.2.5");
+                       exit(0);
+                       }
+EOF
+               ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+               rm -f dummy.c dummy
+               echo rs6000-ibm-aix3.2.5
+       elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+               echo rs6000-ibm-aix3.2.4
+       else
+               echo rs6000-ibm-aix3.2
+       fi
+       exit 0 ;;
+    *:AIX:*:4)
+       if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then
+               IBM_ARCH=rs6000
+       else
+               IBM_ARCH=powerpc
+       fi
+       if [ -x /usr/bin/oslevel ] ; then
+               IBM_REV=`/usr/bin/oslevel`
+       else
+               IBM_REV=4.${UNAME_RELEASE}
+       fi
+       echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+       exit 0 ;;
+    *:AIX:*:*)
+       echo rs6000-ibm-aix
+       exit 0 ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+       echo romp-ibm-bsd4.4
+       exit 0 ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC NetBSD and
+       echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+       exit 0 ;;                           # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+       echo rs6000-bull-bosx
+       exit 0 ;;
+    DPX/2?00:B.O.S.:*:*)
+       echo m68k-bull-sysv3
+       exit 0 ;;
+    9000/[34]??:4.3bsd:1.*:*)
+       echo m68k-hp-bsd
+       exit 0 ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+       echo m68k-hp-bsd4.4
+       exit 0 ;;
+    9000/[3478]??:HP-UX:*:*)
+       case "${UNAME_MACHINE}" in
+           9000/31? )            HP_ARCH=m68000 ;;
+           9000/[34]?? )         HP_ARCH=m68k ;;
+           9000/7?? | 9000/8?[1679] ) HP_ARCH=hppa1.1 ;;
+           9000/8?? )            HP_ARCH=hppa1.0 ;;
+       esac
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+       exit 0 ;;
+    3050*:HI-UX:*:*)
+       sed 's/^        //' << EOF >dummy.c
+       #include <unistd.h>
+       int
+       main ()
+       {
+         long cpu = sysconf (_SC_CPU_VERSION);
+         /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+            true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+            results, however.  */
+         if (CPU_IS_PA_RISC (cpu))
+           {
+             switch (cpu)
+               {
+                 case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+                 default: puts ("hppa-hitachi-hiuxwe2"); break;
+               }
+           }
+         else if (CPU_IS_HP_MC68K (cpu))
+           puts ("m68k-hitachi-hiuxwe2");
+         else puts ("unknown-hitachi-hiuxwe2");
+         exit (0);
+       }
+EOF
+       ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+       rm -f dummy.c dummy
+       echo unknown-hitachi-hiuxwe2
+       exit 0 ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+       echo hppa1.1-hp-bsd
+       exit 0 ;;
+    9000/8??:4.3bsd:*:*)
+       echo hppa1.0-hp-bsd
+       exit 0 ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+       echo hppa1.1-hp-osf
+       exit 0 ;;
+    hp8??:OSF1:*:*)
+       echo hppa1.0-hp-osf
+       exit 0 ;;
+    i?86:OSF1:*:*)
+       if [ -x /usr/sbin/sysversion ] ; then
+           echo ${UNAME_MACHINE}-unknown-osf1mk
+       else
+           echo ${UNAME_MACHINE}-unknown-osf1
+       fi
+       exit 0 ;;
+    parisc*:Lites*:*:*)
+       echo hppa1.1-hp-lites
+       exit 0 ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+       echo c1-convex-bsd
+        exit 0 ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+        exit 0 ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+       echo c34-convex-bsd
+        exit 0 ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+       echo c38-convex-bsd
+        exit 0 ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+       echo c4-convex-bsd
+        exit 0 ;;
+    CRAY*X-MP:*:*:*)
+       echo xmp-cray-unicos
+        exit 0 ;;
+    CRAY*Y-MP:*:*:*)
+       echo ymp-cray-unicos${UNAME_RELEASE}
+       exit 0 ;;
+    CRAY*[A-Z]90:*:*:*)
+       echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+       | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+             -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
+       exit 0 ;;
+    CRAY*TS:*:*:*)
+       echo t90-cray-unicos${UNAME_RELEASE}
+       exit 0 ;;
+    CRAY-2:*:*:*)
+       echo cray2-cray-unicos
+        exit 0 ;;
+    F300:UNIX_System_V:*:*)
+        FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit 0 ;;
+    F301:UNIX_System_V:*:*)
+       echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'`
+       exit 0 ;;
+    hp3[0-9][05]:NetBSD:*:*)
+       echo m68k-hp-netbsd${UNAME_RELEASE}
+       exit 0 ;;
+    hp300:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    i?86:BSD/386:*:* | *:BSD/OS:*:*)
+       echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+       exit 0 ;;
+    *:FreeBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+       exit 0 ;;
+    *:NetBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+       exit 0 ;;
+    *:OpenBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+       exit 0 ;;
+    i*:CYGWIN*:*)
+       echo i386-pc-cygwin32
+       exit 0 ;;
+    i*:MINGW*:*)
+       echo i386-pc-mingw32
+       exit 0 ;;
+    p*:CYGWIN*:*)
+       echo powerpcle-unknown-cygwin32
+       exit 0 ;;
+    prep*:SunOS:5.*:*)
+       echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    *:GNU:*:*)
+       echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+       exit 0 ;;
+    *:Linux:*:*)
+       # The BFD linker knows what the default object file format is, so
+       # first see if it will tell us.
+       ld_help_string=`ld --help 2>&1`
+       if echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: elf_i.86"; then
+         echo "${UNAME_MACHINE}-pc-linux-gnu" ; exit 0
+       elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i.86linux"; then
+         echo "${UNAME_MACHINE}-pc-linux-gnuaout" ; exit 0
+       elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i.86coff"; then
+         echo "${UNAME_MACHINE}-pc-linux-gnucoff" ; exit 0
+       elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68kelf"; then
+         echo "${UNAME_MACHINE}-unknown-linux-gnu" ; exit 0
+       elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68klinux"; then
+         echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0
+       elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: elf32ppc"; then
+         echo "powerpc-unknown-linux-gnu" ; exit 0
+       elif test "${UNAME_MACHINE}" = "alpha" ; then
+         echo alpha-unknown-linux-gnu ; exit 0
+       elif test "${UNAME_MACHINE}" = "sparc" ; then
+         echo sparc-unknown-linux-gnu ; exit 0
+       elif test "${UNAME_MACHINE}" = "mips" ; then
+         cat >dummy.c <<EOF
+main(argc, argv)
+int argc;
+char *argv[];
+{
+#ifdef __MIPSEB__
+  printf ("%s-unknown-linux-gnu\n", argv[1]);
+#endif
+#ifdef __MIPSEL__
+  printf ("%sel-unknown-linux-gnu\n", argv[1]);
+#endif
+  return 0;
+}
+EOF
+         ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
+         rm -f dummy.c dummy
+       else
+         # Either a pre-BFD a.out linker (linux-gnuoldld) or one that does not give us
+         # useful --help.  Gcc wants to distinguish between linux-gnuoldld and linux-gnuaout.
+         test ! -d /usr/lib/ldscripts/. \
+           && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0
+         # Determine whether the default compiler is a.out or elf
+         cat >dummy.c <<EOF
+main(argc, argv)
+int argc;
+char *argv[];
+{
+#ifdef __ELF__
+  printf ("%s-pc-linux-gnu\n", argv[1]);
+#else
+  printf ("%s-pc-linux-gnuaout\n", argv[1]);
+#endif
+  return 0;
+}
+EOF
+         ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
+         rm -f dummy.c dummy
+       fi ;;
+# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.  earlier versions
+# are messed up and put the nodename in both sysname and nodename.
+    i?86:DYNIX/ptx:4*:*)
+       echo i386-sequent-sysv4
+       exit 0 ;;
+    i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*)
+       if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+               echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
+       else
+               echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
+       fi
+       exit 0 ;;
+    i?86:*:3.2:*)
+       if test -f /usr/options/cb.name; then
+               UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+               echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+       elif /bin/uname -X 2>/dev/null >/dev/null ; then
+               UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+               (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+               (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+                       && UNAME_MACHINE=i586
+               echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+       else
+               echo ${UNAME_MACHINE}-pc-sysv32
+       fi
+       exit 0 ;;
+    Intel:Mach:3*:*)
+       echo i386-pc-mach3
+       exit 0 ;;
+    paragon:*:*:*)
+       echo i860-intel-osf1
+       exit 0 ;;
+    i860:*:4.*:*) # i860-SVR4
+       if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+         echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+       else # Add other i860-SVR4 vendors below as they are discovered.
+         echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+       fi
+       exit 0 ;;
+    mini*:CTIX:SYS*5:*)
+       # "miniframe"
+       echo m68010-convergent-sysv
+       exit 0 ;;
+    M68*:*:R3V[567]*:*)
+       test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+    3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
+       OS_REL=''
+       test -r /etc/.relid \
+       && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+       /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+         && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+       /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+         && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && echo i486-ncr-sysv4 && exit 0 ;;
+    m68*:LynxOS:2.*:*)
+       echo m68k-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    mc68030:UNIX_System_V:4.*:*)
+       echo m68k-atari-sysv4
+       exit 0 ;;
+    i?86:LynxOS:2.*:*)
+       echo i386-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    TSUNAMI:LynxOS:2.*:*)
+       echo sparc-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*)
+       echo rs6000-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    SM[BE]S:UNIX_SV:*:*)
+       echo mips-dde-sysv${UNAME_RELEASE}
+       exit 0 ;;
+    RM*:SINIX-*:*:*)
+       echo mips-sni-sysv4
+       exit 0 ;;
+    *:SINIX-*:*:*)
+       if uname -p 2>/dev/null >/dev/null ; then
+               UNAME_MACHINE=`(uname -p) 2>/dev/null`
+               echo ${UNAME_MACHINE}-sni-sysv4
+       else
+               echo ns32k-sni-sysv
+       fi
+       exit 0 ;;
+    PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                           # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit 0 ;;
+    *:UNIX_System_V:4*:FTX*)
+       # From Gerald Hewes <hewes@openmarket.com>.
+       # How about differentiating between stratus architectures? -djm
+       echo hppa1.1-stratus-sysv4
+       exit 0 ;;
+    *:*:*:FTX*)
+       # From seanf@swdc.stratus.com.
+       echo i860-stratus-sysv4
+       exit 0 ;;
+    mc68*:A/UX:*:*)
+       echo m68k-apple-aux${UNAME_RELEASE}
+       exit 0 ;;
+    R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:*)
+       if [ -d /usr/nec ]; then
+               echo mips-nec-sysv${UNAME_RELEASE}
+       else
+               echo mips-unknown-sysv${UNAME_RELEASE}
+       fi
+        exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+cat >dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+         ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+       printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+       printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+#if !defined (ultrix)
+  printf ("vax-dec-bsd\n"); exit (0);
+#else
+  printf ("vax-dec-ultrix\n"); exit (0);
+#endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0
+rm -f dummy.c dummy
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+       echo c1-convex-bsd
+       exit 0 ;;
+    c2*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+       exit 0 ;;
+    c34*)
+       echo c34-convex-bsd
+       exit 0 ;;
+    c38*)
+       echo c38-convex-bsd
+       exit 0 ;;
+    c4*)
+       echo c4-convex-bsd
+       exit 0 ;;
+    esac
+fi
+
+#echo '(Unable to guess system type)' 1>&2
+
+exit 1
diff --git a/libFoundation/config.h.in b/libFoundation/config.h.in
new file mode 100644 (file)
index 0000000..2cccef1
--- /dev/null
@@ -0,0 +1,245 @@
+#ifndef __config_h__
+#define __config_h__
+
+/* Define it if we want to use libFoundation with GNUstep */
+#undef WITH_GNUSTEP
+
+/* Define it if we want to use libFoundation with ffcall */
+#undef WITH_FFCALL
+
+/* Define it if we use the Boehm's garbage collector */
+#undef WITH_GC
+
+/* Macros that determine the Objective-C runtime and compiler */
+#undef NeXT_RUNTIME
+#undef GNU_RUNTIME
+
+/* Define if the compiler does not support nested functions */
+#undef NO_NESTED_FUNCTIONS
+
+/* Define if the compiler is broken when nested functions are used with
+   Objective-C messages. */
+#undef BROKEN_COMPILER
+
+/* Define if the __builtin_apply pseudo-function doesn't set the floating
+   point return value at retframe + 8 on Intel machines. */
+#undef BROKEN_BUILTIN_APPLY
+
+/* Define if system calls automatically restart after interruption
+   by a signal.  */
+#undef HAVE_RESTARTABLE_SYSCALLS
+
+/* Define if you have the vprintf function.  */
+#undef HAVE_VPRINTF
+
+/* Define if you need to in order for stat and other things to work.  */
+#undef _POSIX_SOURCE
+
+/* Define as the return type of signal handlers (int or void).  */
+#undef RETSIGTYPE
+
+/* Define this if you have the sigsetmask function, eg the BSD signal
+   handling. */
+#undef HAVE_SIGSETMASK
+
+/* Define this if you have the sighold function, eg the System V signal
+   handling. */
+#undef HAVE_SIGHOLD
+
+/* Define if you have the sigset function. */
+#undef HAVE_SIGSET
+
+/* Define if you have the sigaction function. */
+#undef HAVE_SIGACTION
+
+/* Define if you have the gethostbyname_r function. */
+#undef HAVE_GETHOSTBYNAME_R
+
+/* Define if you have the gethostbyaddr_r function. */
+#undef HAVE_GETHOSTBYADDR_R
+
+/* Define if you have the gethostent_r function. */
+#undef HAVE_GETHOSTENT_R
+
+/* Define if the Objective-C runtime contains the objc_thread_create function;
+   this function was defined in the multi-thread support in the 960906
+   version of runtime patch. */
+#undef HAVE_OBJC_THREAD_CREATE
+
+/* Define if the Objective-C runtime contains the objc_mutex_allocate func;
+   this function is not available in gcc 2.7.2. */
+#undef HAVE_OBJC_MUTEX_ALLOCATE
+
+/* Define if the Objective-C runtime contains the objc_malloc function;
+   this function is not available in gcc 2.7.2. */
+#undef HAVE_OBJC_MALLOC
+
+/* Define if you have the memcpy function.  */
+#undef HAVE_MEMCPY
+
+/* Define if you have the ualarm function.  */
+#undef HAVE_UALARM
+
+/* Define if you have posix mmap function.  */
+#undef HAVE_MMAP
+
+/* Define if you have the getcwd function */
+#undef HAVE_GETCWD
+
+/* Define if you have the getuid function */
+#undef HAVE_GETUID
+
+/* Define if you have the getpwnam function */
+#undef HAVE_GETPWNAM
+
+/* Define if you have the getpwuid function */
+#undef HAVE_GETPWUID
+
+/* Define if you have the kill function */
+#undef HAVE_KILL
+
+/* Define if you have the getpagesize function */
+#undef HAVE_GETPAGESIZE
+
+/* Define if you have the statvfs function */
+#undef HAVE_STATVFS
+
+/* Define if you have the raise function */
+#undef HAVE_RAISE
+
+/* Define if you have the gettimeofday function */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define if you have the GetLocalTime function */
+#undef HAVE_GETLOCALTIME
+
+/* Define if you have the chown function */
+#undef HAVE_CHOWN
+
+/* Define if you have the symlink function */
+#undef HAVE_SYMLINK
+
+/* Define if you have the readlink function */
+#undef HAVE_READLINK
+
+/* Define if you have the fsync function */
+#undef HAVE_FSYNC
+
+/* Define if you have the opendir family of functions */
+#undef HAVE_OPENDIR
+
+/* Define if you have the sysconf function */
+#undef HAVE_SYSCONF
+
+/* Define if you have the GetSystemInfo function */
+#undef HAVE_GETSYSTEMINFO
+
+/* Define if you have the <string.h> header file.  */
+#undef HAVE_STRING_H
+
+/* Define if you have the <strings.h> header file.  */
+#undef HAVE_STRINGS_H
+
+/* Define if you have the <memory.h> header file */
+#undef HAVE_MEMORY_H
+
+/* Define if you have the <stdlib.h> header file.  */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <libc.h> header file.  */
+#undef HAVE_LIBC_H
+
+/* Define if you have the <sys/time.h> header file.  */
+#undef HAVE_SYS_TIME_H
+
+/* Define if you have the <sys/stat.h> header file */
+#undef HAVE_SYS_STAT_H
+
+/* Define if you have the <sys/vfs.h> header file */
+#undef HAVE_SYS_VFS_H
+
+/* Define if you have the <sys/statfs.h> header file */
+#undef HAVE_SYS_STATFS_H
+
+/* Define if you have the <sys/statvfs.h> header file */
+#undef HAVE_SYS_STATVFS_H
+
+/* Define if you have the <netinet/in.h> header file */
+#undef HAVE_NETINET_IN_H
+
+/* Define if you have the <windows.h> header file */
+#undef HAVE_WINDOWS_H
+
+/* Define if you have the <Windows32/Sockets.h> header file */
+#undef HAVE_WINDOWS32_SOCKETS_H
+
+/* Define if you have the <pwd.h> header file */
+#undef HAVE_PWD_H
+
+/* Define if you have the <sys/param.h> header file */
+#undef HAVE_SYS_PARAM_H
+
+/* Define if you have the <process.h> header file */
+#undef HAVE_PROCESS_H
+
+/* Define if you have the <grp.h> header file */
+#undef HAVE_GRP_H
+
+/* Define if you have the <sys/file.h> header file */
+#undef HAVE_SYS_FILE_H
+
+/* Define if you have the <sys/select.h> header file */
+#undef HAVE_SYS_SELECT_H
+
+/* Define if you have the <utime.h> header file */
+#undef HAVE_UTIME_H
+
+/* Define if you have the <sys/errno.h> header file */
+#undef HAVE_SYS_ERRNO_H
+
+/* Define if sys/wait.h is POSIX compatible */
+#undef HAVE_SYS_WAIT_H
+
+/* Define this if you have the <vfork.h> header file */
+#undef HAVE_VFORK_H
+
+/* Define for vfork in case it's not defined */
+#undef vfork
+
+/* Define for pid_t in case it's not defined */
+#undef pid_t
+
+/* Define if your processor stores words with the most significant
+   byte first (like Motorola and SPARC, unlike Intel and VAX).  */
+#undef WORDS_BIGENDIAN
+
+/* The following macros deal with directory entries. */
+#undef HAVE_DIRENT_H
+#undef HAVE_SYS_NDIR_H
+#undef HAVE_SYS_DIR_H
+#undef HAVE_NDIR_H
+#undef HAVE_DIR_H
+
+/* The structure alignment as determined by configure */
+#define STRUCT_ALIGNMENT @STRUCT_ALIGNMENT@
+
+/* The name of the target platform, obtained by configure */
+#define TARGET_PLATFORM                "@target@"
+
+/*  Include this file here to give the above information to the configuration
+       file if needs them. */
+#include "config/@target_cpu@/@target_os@.h"
+
+/* This is a hack but I haven't found a way to check for it */
+#ifndef __WIN32__
+/* Define if your mkdir has two arguments.  */
+# define MKDIR_HAS_TWO_ARGS 1
+#endif
+
+
+#if LIB_FOUNDATION_BOEHM_GC
+#  include <@GC_INCLUDE_DIR@gc.h>
+#  include <@GC_INCLUDE_DIR@gc_typed.h>
+#endif
+
+#endif /* __config_h__ */
diff --git a/libFoundation/config.h.win32 b/libFoundation/config.h.win32
new file mode 100644 (file)
index 0000000..a22e08b
--- /dev/null
@@ -0,0 +1,178 @@
+#ifndef __config_h__
+#define __config_h__
+
+/* Macros that determine the Objective-C runtime and compiler */
+#undef NeXT_RUNTIME
+#define GNU_RUNTIME 1
+
+/* Define if the compiler does not support nested functions */
+#undef NO_NESTED_FUNCTIONS
+
+/* Define if the compiler is broken when nested functions are used with
+   Objective-C messages. */
+#undef BROKEN_COMPILER
+
+/* Define if the __builtin_apply pseudo-function doesn't set the floating
+   point return value at retframe + 8 on Intel machines. */
+#undef BROKEN_BUILTIN_APPLY
+
+/* Define if system calls automatically restart after interruption
+   by a signal.  */
+#undef HAVE_RESTARTABLE_SYSCALLS
+
+/* Define if you have the vprintf function.  */
+#define HAVE_VPRINTF 1
+
+/* Define if you need to in order for stat and other things to work.  */
+#undef _POSIX_SOURCE
+
+/* Define as the return type of signal handlers (int or void).  */
+#define RETSIGTYPE void
+
+/* Define if the Objective-C runtime contains the objc_thread_create function;
+   this function was defined in the multi-thread support in the 960906
+   version of runtime patch. */
+#define HAVE_OBJC_THREAD_CREATE 1
+
+/* Define if you have the memcpy function.  */
+#define HAVE_MEMCPY 1
+
+/* Define if you have the ualarm function.  */
+#undef HAVE_UALARM
+
+/* Define if you have posix mmap function.  */
+#undef HAVE_MMAP
+
+/* Define if you have the getcwd function */
+#define HAVE_GETCWD 1
+
+/* Define if you have the getuid function */
+#undef HAVE_GETUID
+
+/* Define if you have the getpwnam function */
+#undef HAVE_GETPWNAM
+
+/* Define if you have the getpwuid function */
+#undef HAVE_GETPWUID
+
+/* Define if you have the kill function */
+#undef HAVE_KILL
+
+/* Define if you have the getpagesize function */
+#undef HAVE_GETPAGESIZE
+
+/* Define if you have the statvfs function */
+#undef HAVE_STATVFS
+
+/* Define if you have the raise function */
+#define HAVE_RAISE 1
+
+/* Define if you have the gettimeofday function */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define if you have the GetLocalTime function */
+#define HAVE_GETLOCALTIME 1
+
+/* Define if you have the chown function */
+#undef HAVE_CHOWN
+
+/* Define if you have the symlink function */
+#undef HAVE_SYMLINK
+
+/* Define if you have the readlink function */
+#undef HAVE_READLINK
+
+/* Define if you have the fsync function */
+#undef HAVE_FSYNC
+
+/* Define if you have the opendir family of functions */
+#undef HAVE_OPENDIR
+
+/* Define if you have the sysconf function */
+#undef HAVE_SYSCONF
+
+/* Define if you have the GetSystemInfo function */
+#define HAVE_GETSYSTEMINFO 1
+
+/* Define if you have the <string.h> header file.  */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <memory.h> header file */
+#define HAVE_MEMORY_H 1
+
+/* Define if you have the <stdlib.h> header file.  */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the <libc.h> header file.  */
+#undef HAVE_LIBC_H
+
+/* Define if you have the <sys/time.h> header file.  */
+#undef HAVE_SYS_TIME_H
+
+/* Define if you have the <sys/stat.h> header file */
+#define HAVE_SYS_STAT_H 1
+
+/* Define if you have the <sys/vfs.h> header file */
+#undef HAVE_SYS_VFS_H
+
+/* Define if you have the <sys/statfs.h> header file */
+#undef HAVE_SYS_STATFS_H
+
+/* Define if you have the <netinet/in.h> header file */
+#undef HAVE_NETINET_IN_H
+
+/* Define if you have the <windows.h> header file */
+#define HAVE_WINDOWS_H 1
+
+/* Define if you have the <Windows32/Sockets.h> header file */
+#define HAVE_WINDOWS32_SOCKETS_H 1
+
+/* Define if you have the <pwd.h> header file */
+#define HAVE_PWD_H 1
+
+/* Define if you have the <sys/param.h> header file */
+#undef HAVE_SYS_PARAM_H
+
+/* Define if you have the <process.h> header file */
+#define HAVE_PROCESS_H 1
+
+/* Define if you have the <grp.h> header file */
+#define HAVE_GRP_H 1
+
+/* Define if you have the <sys/file.h> header file */
+#undef HAVE_SYS_FILE_H
+
+/* Define if you have the <utime.h> header file */
+#define HAVE_UTIME_H 1
+
+/* Define if you have the <sys/errno.h> header file */
+#undef HAVE_SYS_ERRNO_H
+
+/* Define if your processor stores words with the most significant
+   byte first (like Motorola and SPARC, unlike Intel and VAX).  */
+#undef WORDS_BIGENDIAN
+
+/* The following macros deal with directory entries. */
+#undef HAVE_DIRENT_H
+#undef HAVE_SYS_NDIR_H
+#undef HAVE_SYS_DIR_H
+#undef HAVE_NDIR_H
+#define HAVE_DIR_H 1
+
+/* The structure alignment as determined by configure */
+#define STRUCT_ALIGNMENT 4
+
+/* The name of the target platform, obtained by configure */
+#define TARGET_PLATFORM                "i386-pc-cygwin32"
+
+/*  Include this file here to give the above information to the configuration
+       file if needs them. */
+#include "config/i386/cygwin32.h"
+
+/* This is a hack but I haven't found a way to check for it */
+#ifndef __WIN32__
+/* Define if your mkdir has two arguments.  */
+# define MKDIR_HAS_TWO_ARGS 1
+#endif
+
+#endif /* __config_h__ */
diff --git a/libFoundation/config.mak.in b/libFoundation/config.mak.in
new file mode 100644 (file)
index 0000000..b61bba0
--- /dev/null
@@ -0,0 +1,78 @@
+# @configure_input@
+
+# preparations for GNUstep.sh-less compilation
+#GNUSTEP_FLATTENED    = @GNUSTEP_FLATTENED@
+#GNUSTEP_HOST         = @GNUSTEP_HOST@
+#GNUSTEP_HOST_CPU     = @GNUSTEP_HOST_CPU@
+#GNUSTEP_HOST_OS      = @GNUSTEP_HOST_OS@
+#GNUSTEP_HOST_VENDOR  = @GNUSTEP_HOST_VENDOR@
+#GNUSTEP_LOCAL_ROOT   = @GNUSTEP_LOCAL_ROOT@
+#GNUSTEP_MAKEFILES    = @GNUSTEP_MAKEFILES@
+#GNUSTEP_NETWORK_ROOT = @GNUSTEP_NETWORK_ROOT@
+#GNUSTEP_PATHLIST     = @GNUSTEP_PATHLIST@
+#GNUSTEP_ROOT         = @GNUSTEP_ROOT@
+#GNUSTEP_SYSTEM_ROOT  = @GNUSTEP_SYSTEM_ROOT@
+#GNUSTEP_USER_ROOT    = @GNUSTEP_USER_ROOT@
+#LIBRARY_COMBO        = @LIBRARY_COMBO@
+
+# avoid a gstep-make warning in some setups
+#PATH:=$(GNUSTEP_SYSTEM_ROOT)/Tools:$(PATH)
+
+# libFoundation options
+WITH_GNUSTEP    = @WITH_GNUSTEP@
+WITH_FFCALL     = @WITH_FFCALL@
+WITH_GC         = @WITH_GC@
+GC_INCLUDE_DIR  = @GC_INCLUDE_DIR@
+GC_LIB          = @GC_LIB@
+
+prefix         = @prefix@
+exec_prefix    = @exec_prefix@
+libdir         = @libdir@
+bindir         = @bindir@
+includedir     = @includedir@
+sharedstatedir = @datadir@/libFoundation
+srcdir         = @srcdir@
+
+HOST           = @HOST@
+HOST_CPU       = @HOST_CPU@
+HOST_VENDOR    = @HOST_VENDOR@
+HOST_OS                = @HOST_OS@
+TARGET         = @TARGET@
+TARGET_CPU     = @TARGET_CPU@
+TARGET_VENDOR  = @TARGET_VENDOR@
+TARGET_OS      = @TARGET_OS@
+
+LIB_FOUNDATION_NAME = libFoundation$(libext)
+
+PERL   = @PERL@
+
+ANTLR          = antlr
+DLG            = dlg
+ANTLR_FLAGS     =
+DLG_FLAGS       = -C2
+PCCTS_CFLAGS    = -I$(TOP)/pccts
+
+OBJC_RUNTIME        = GNU
+BROKEN_COMPILER             = @BROKEN_COMPILER@
+BROKEN_BUILTIN_APPLY = @BROKEN_BUILTIN_APPLY@
+NO_NESTED_FUNCTIONS  = @NO_NESTED_FUNCTIONS@
+
+CFLAGS = @OBJC_RUNTIME_FLAG@ -I$(TOP) @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS   = @LIBS@
+
+ifeq ($(findstring mingw32, $(TARGET_OS)), mingw32)
+LIBS    += \
+       -lwsock32 -ladvapi32 -lcomctl32 -luser32 -lcomdlg32 \
+       -lmpr -lnetapi32 \
+       -lm
+endif
+
+ifeq ($(findstring solaris, $(TARGET_OS)), solaris)
+CFLAGS += -D_REENTRANT -D_TS_ERRNO
+endif
+
+MAJOR_VERSION   = @MAJOR_VERSION@
+MINOR_VERSION   = @MINOR_VERSION@
+SUBMINOR_VERSION = @SUBMINOR_VERSION@
+VERSION                 = $(MAJOR_VERSION).$(MINOR_VERSION).$(SUBMINOR_VERSION)
diff --git a/libFoundation/config.mak.win32 b/libFoundation/config.mak.win32
new file mode 100644 (file)
index 0000000..eff3b6b
--- /dev/null
@@ -0,0 +1,55 @@
+# @configure_input@
+
+prefix         = /cygnus/ObjC
+exec_prefix    = $(prefix)/bin
+libdir         = $(prefix)/lib
+includedir     = $(prefix)/include
+sharedstatedir = $(prefix)/share/libFoundation
+srcdir         = .
+
+libext = .a
+objext = .o
+exeext = .exe
+
+INSTALL                = install
+INSTALL_PROGRAM        = install
+INSTALL_DATA   = install
+
+HOST           = i386-pc-cygwin32
+HOST_CPU       = i386
+HOST_VENDOR    = pc
+HOST_OS                = cygwin32
+TARGET         = i386-pc-cygwin32
+TARGET_CPU     = i386
+TARGET_VENDOR  = pc
+TARGET_OS      = cygwin32
+
+LIB_FOUNDATION_NAME = libFoundation$(libext)
+
+CC     = gcc
+DEBUGFLAGS     = -Wall -DDEBUG
+
+MAKE   = make
+LIBTOOL        =
+RANLIB = ranlib
+PERL   = perl
+
+ANTLR  = antlr
+DLG    = dlg
+ANTLR_FLAGS =
+DLG_FLAGS = -C2
+PCCTS_CFLAGS = -I$(TOP)/pccts
+
+OBJC_RUNTIME   = GNU
+BROKEN_COMPILER        = no
+BROKEN_BUILTIN_APPLY = no
+NO_NESTED_FUNCTIONS = no
+
+CFLAGS = -I$(TOP) 
+LDFLAGS = 
+LIBS   = -lobjc -lwsock32 -ladvapi32
+
+MAJOR_VERSION  = 0
+MINOR_VERSION  = 7
+SUBMINOR_VERSION = 1
+VERSION                = $(MAJOR_VERSION).$(MINOR_VERSION).$(SUBMINOR_VERSION)
diff --git a/libFoundation/config.sub b/libFoundation/config.sub
new file mode 100755 (executable)
index 0000000..ea9ed1b
--- /dev/null
@@ -0,0 +1,1242 @@
+#! /bin/sh
+# Configuration validation subroutine script, version 1.1.
+#   Copyright (C) 1991, 92-97, 1998, 1999 Free Software Foundation, Inc.
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#      CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#      CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+if [ x$1 = x ]
+then
+       echo Configuration name missing. 1>&2
+       echo "Usage: $0 CPU-MFR-OPSYS" 1>&2
+       echo "or     $0 ALIAS" 1>&2
+       echo where ALIAS is a recognized configuration type. 1>&2
+       exit 1
+fi
+
+# First pass through any local machine types.
+case $1 in
+       *local*)
+               echo $1
+               exit 0
+               ;;
+       *)
+       ;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  linux-gnu*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+       -sun*os*)
+               # Prevent following clause from handling this invalid input.
+               ;;
+       -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+       -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+       -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+       -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+       -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+       -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+       -apple)
+               os=
+               basic_machine=$1
+               ;;
+       -sim | -cisco | -oki | -wec | -winbond )        # EGCS LOCAL
+               os=
+               basic_machine=$1
+               ;;
+       -scout)                                         # EGCS LOCAL
+               ;;
+       -wrs)                                           # EGCS LOCAL
+               os=-vxworks
+               basic_machine=$1
+               ;;
+       -hiux*)
+               os=-hiuxwe2
+               ;;
+       -sco5)
+               os=-sco3.2v5
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco4)
+               os=-sco3.2v4
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco3.2.[4-9]*)
+               os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco3.2v[4-9]*)
+               # Don't forget version if it is 3.2v4 or newer.
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco*)
+               os=-sco3.2v2
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -udk*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -isc)
+               os=-isc2.2
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -clix*)
+               basic_machine=clipper-intergraph
+               ;;
+       -isc*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -lynx*)
+               os=-lynxos
+               ;;
+       -ptx*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+               ;;
+       -windowsnt*)
+               os=`echo $os | sed -e 's/windowsnt/winnt/'`
+               ;;
+       -psos*)
+               os=-psos
+               ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+       # Recognize the basic CPU types without company name.
+       # Some are omitted here because they have special meanings below.
+       tahoe | i860 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \
+               | arme[lb] | pyramid | mn10200 | mn10300 \
+               | tron | a29k | 580 | i960 | h8300 \
+               | hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \
+               | alpha | alphaev5 | alphaev56 | alphapca56 | alphaev6 \
+               | we32k | ns16k | clipper | i370 | sh | powerpc | powerpcle \
+               | 1750a | dsp16xx | pdp11 | s390 \
+               | mips64 | mipsel | mips64el | mips64orion | mips64orionel \
+               | mipstx39 | mipstx39el \
+               | sparc | sparclet | sparclite | sparc64 | sparcv9 | v850 | c4x)
+               basic_machine=$basic_machine-unknown
+               ;;
+       m88110 | m680[012346]0 | m683?2 | m68360 | m5200 | z8k | v70 \
+               | h8500 | w65) # EGCS LOCAL
+               ;;
+       thumb)
+               basic_machine=$basic_machine-unknown
+               ;;
+       mips64vr4300 | mips64vr4300el) # EGCS LOCAL jsmith/vr4300
+               basic_machine=$basic_machine-unknown
+               ;;
+       mips64vr4100 | mips64vr4100el) # EGCS LOCAL jsmith/vr4100
+               basic_machine=$basic_machine-unknown
+               ;;
+       mips64vr5000 | mips64vr5000el) # EGCS LOCAL ian/vr5000
+               basic_machine=$basic_machine-unknown
+               ;;
+       mips16)
+               basic_machine=$basic_machine-unknown
+               ;;
+       d10v)
+               basic_machine=$basic_machine-unknown
+               ;;
+       # We use `pc' rather than `unknown'
+       # because (1) that's what they normally are, and
+       # (2) the word "unknown" tends to confuse beginning users.
+       i[34567]86)
+         basic_machine=$basic_machine-pc
+         ;;
+       # Object if more than one company name word.
+       *-*-*)
+               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+               exit 1
+               ;;
+       # Recognize the basic CPU types with company name.
+       vax-* | tahoe-* | i[34567]86-* | i860-* | m32r-* | m68k-* | m68000-* \
+             | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \
+             | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
+             | power-* | none-* | 580-* | cray2-* | h8300-* | i960-* \
+             | xmp-* | ymp-* \
+             | hppa-* | hppa1.0-* | hppa1.1-* \
+             | hppa2.0-* | hppa2.0w-* | hppa2.0n-* \
+             | alpha-* | alphaev5-* | alphaev56-* | alphapca56-* \
+             | alphaev6-* | we32k-* | cydra-* | ns16k-* | pn-* | np1-* \
+             | xps100-* | clipper-* | orion-* \
+             | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \
+             | sparc64-* | sparcv9-* | sparc86x-* | mips64-* | mipsel-* \
+             | mips64el-* | mips64orion-* | mips64orionel-*  \
+             | mipstx39-* | mipstx39el-* \
+             | f301-* | arm*-*)
+               ;;
+       m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | h8500-* | d10v-*) # EGCS LOCAL
+               ;;
+       thumb-*) # EGCS LOCAL angela/thumb
+               ;;
+       v850-*) # EGCS LOCAL
+               ;;
+       d30v-*) # EGCS LOCAL
+               ;;
+       mips64vr4300-* | mips64vr4300el-*) # EGCS LOCAL jsmith/vr4300
+               ;;
+       mips64vr4100-* | mips64vr4100el-*) # EGCS LOCAL jsmith/vr4100
+               ;;
+       mips16-*) # EGCS LOCAL krk/mips16
+               ;;
+       tic30-*) # EGCS LOCAL ian/tic30
+               ;;
+       c30-*) # EGCS LOCAL ian/tic30
+               basic_machine=tic30-unknown
+               ;;
+       # Recognize the various machine names and aliases which stand
+       # for a CPU type and a company and sometimes even an OS.
+       386bsd)                                         # EGCS LOCAL
+               basic_machine=i386-unknown
+               os=-bsd
+               ;;
+       3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+               basic_machine=m68000-att
+               ;;
+       3b*)
+               basic_machine=we32k-att
+               ;;
+       a29khif)                                        # EGCS LOCAL
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       adobe68k)                                       # EGCS LOCAL
+               basic_machine=m68010-adobe
+               os=-scout
+               ;;
+       alliant | fx80)
+               basic_machine=fx80-alliant
+               ;;
+       altos | altos3068)
+               basic_machine=m68k-altos
+               ;;
+       am29k)
+               basic_machine=a29k-none
+               os=-bsd
+               ;;
+       amdahl)
+               basic_machine=580-amdahl
+               os=-sysv
+               ;;
+       amiga | amiga-*)
+               basic_machine=m68k-cbm
+               ;;
+       amigaos | amigados)
+               basic_machine=m68k-cbm
+               os=-amigaos
+               ;;
+       amigaunix | amix)
+               basic_machine=m68k-cbm
+               os=-sysv4
+               ;;
+       apollo68)
+               basic_machine=m68k-apollo
+               os=-sysv
+               ;;
+       apollo68bsd)                                    # EGCS LOCAL
+               basic_machine=m68k-apollo
+               os=-bsd
+               ;;
+       aux)
+               basic_machine=m68k-apple
+               os=-aux
+               ;;
+       balance)
+               basic_machine=ns32k-sequent
+               os=-dynix
+               ;;
+       convex-c1)
+               basic_machine=c1-convex
+               os=-bsd
+               ;;
+       convex-c2)
+               basic_machine=c2-convex
+               os=-bsd
+               ;;
+       convex-c32)
+               basic_machine=c32-convex
+               os=-bsd
+               ;;
+       convex-c34)
+               basic_machine=c34-convex
+               os=-bsd
+               ;;
+       convex-c38)
+               basic_machine=c38-convex
+               os=-bsd
+               ;;
+       cray | ymp)
+               basic_machine=ymp-cray
+               os=-unicos
+               ;;
+       cray2)
+               basic_machine=cray2-cray
+               os=-unicos
+               ;;
+       [ctj]90-cray)
+               basic_machine=c90-cray
+               os=-unicos
+               ;;
+       crds | unos)
+               basic_machine=m68k-crds
+               ;;
+       da30 | da30-*)
+               basic_machine=m68k-da30
+               ;;
+       decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+               basic_machine=mips-dec
+               ;;
+       delta | 3300 | motorola-3300 | motorola-delta \
+             | 3300-motorola | delta-motorola)
+               basic_machine=m68k-motorola
+               ;;
+       delta88)
+               basic_machine=m88k-motorola
+               os=-sysv3
+               ;;
+       dpx20 | dpx20-*)
+               basic_machine=rs6000-bull
+               os=-bosx
+               ;;
+       dpx2* | dpx2*-bull)
+               basic_machine=m68k-bull
+               os=-sysv3
+               ;;
+       ebmon29k)
+               basic_machine=a29k-amd
+               os=-ebmon
+               ;;
+       elxsi)
+               basic_machine=elxsi-elxsi
+               os=-bsd
+               ;;
+       encore | umax | mmax)
+               basic_machine=ns32k-encore
+               ;;
+       es1800 | OSE68k | ose68k | ose | OSE)           # EGCS LOCAL
+               basic_machine=m68k-ericsson
+               os=-ose
+               ;;
+       fx2800)
+               basic_machine=i860-alliant
+               ;;
+       genix)
+               basic_machine=ns32k-ns
+               ;;
+       gmicro)
+               basic_machine=tron-gmicro
+               os=-sysv
+               ;;
+       h3050r* | hiux*)
+               basic_machine=hppa1.1-hitachi
+               os=-hiuxwe2
+               ;;
+       h8300hms)
+               basic_machine=h8300-hitachi
+               os=-hms
+               ;;
+       h8300xray)                                      # EGCS LOCAL
+               basic_machine=h8300-hitachi
+               os=-xray
+               ;;
+       h8500hms)                                       # EGCS LOCAL
+               basic_machine=h8500-hitachi
+               os=-hms
+               ;;
+       harris)
+               basic_machine=m88k-harris
+               os=-sysv3
+               ;;
+       hp300-*)
+               basic_machine=m68k-hp
+               ;;
+       hp300bsd)
+               basic_machine=m68k-hp
+               os=-bsd
+               ;;
+       hp300hpux)
+               basic_machine=m68k-hp
+               os=-hpux
+               ;;
+        w89k-*)                                                # EGCS LOCAL
+                basic_machine=hppa1.1-winbond
+                os=-proelf
+                ;;
+        op50n-*)                                       # EGCS LOCAL
+                basic_machine=hppa1.1-oki
+                os=-proelf
+                ;;
+        op60c-*)                                       # EGCS LOCAL
+                basic_machine=hppa1.1-oki
+                os=-proelf
+                ;;
+        hppro)                                         # EGCS LOCAL
+                basic_machine=hppa1.1-hp
+                os=-proelf
+                ;;
+       hp3k9[0-9][0-9] | hp9[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hp9k2[0-9][0-9] | hp9k31[0-9])
+               basic_machine=m68000-hp
+               ;;
+       hp9k3[2-9][0-9])
+               basic_machine=m68k-hp
+               ;;
+       hp9k6[0-9][0-9] | hp6[0-9][0-9] )
+               basic_machine=hppa1.0-hp
+               ;;
+       hp9k7[0-79][0-9] | hp7[0-79][0-9] )
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k78[0-9] | hp78[0-9] )
+               # FIXME: really hppa2.0-hp
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | \
+       hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893 )
+               # FIXME: really hppa2.0-hp
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[0-9][13679] | hp8[0-9][13679] )
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[0-9][0-9] | hp8[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hppa-next)
+               os=-nextstep3
+               ;;
+       hppaosf)                                        # EGCS LOCAL
+               basic_machine=hppa1.1-hp
+               os=-osf
+               ;;
+       i370-ibm* | ibm*)
+               basic_machine=i370-ibm
+               os=-mvs
+               ;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+       i[34567]86v32)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv32
+               ;;
+       i[34567]86v4*)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv4
+               ;;
+       i[34567]86v)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv
+               ;;
+       i[34567]86sol2)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-solaris2
+               ;;
+       i386mach)                                       # EGCS LOCAL
+               basic_machine=i386-mach
+               os=-mach
+               ;;
+       i386-vsta | vsta)                               # EGCS LOCAL
+               basic_machine=i386-unknown
+               os=-vsta
+               ;;
+       i386-go32 | go32)                               # EGCS LOCAL
+               basic_machine=i386-unknown
+               os=-go32
+               ;;
+       i386-mingw32 | mingw32)
+               basic_machine=i386-unknown
+               os=-mingw32
+               ;;
+       iris | iris4d)
+               basic_machine=mips-sgi
+               case $os in
+                   -irix*)
+                       ;;
+                   *)
+                       os=-irix4
+                       ;;
+               esac
+               ;;
+       isi68 | isi)
+               basic_machine=m68k-isi
+               os=-sysv
+               ;;
+       m88k-omron*)
+               basic_machine=m88k-omron
+               ;;
+       magnum | m3230)
+               basic_machine=mips-mips
+               os=-sysv
+               ;;
+       merlin)
+               basic_machine=ns32k-utek
+               os=-sysv
+               ;;
+       miniframe)
+               basic_machine=m68000-convergent
+               ;;
+       mipsel*-linux*)
+               basic_machine=mipsel-unknown
+               os=-linux-gnu
+               ;;
+       mips*-linux*)
+               basic_machine=mips-unknown
+               os=-linux-gnu
+               ;;
+       mips3*-*)
+               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+               ;;
+       mips3*)
+               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+               ;;
+       monitor)                                        # EGCS LOCAL
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
+       msdos)                                          # EGCS LOCAL
+               basic_machine=i386-unknown      
+               os=-msdos
+               ;;
+       ncr3000)
+               basic_machine=i486-ncr
+               os=-sysv4
+               ;;
+       netbsd386)
+               basic_machine=i386-unknown              # EGCS LOCAL
+               os=-netbsd
+               ;;
+       netwinder)
+               basic_machine=armv4l-corel
+               os=-linux
+               ;;
+       news | news700 | news800 | news900)
+               basic_machine=m68k-sony
+               os=-newsos
+               ;;
+       news1000)
+               basic_machine=m68030-sony
+               os=-newsos
+               ;;
+       news-3600 | risc-news)
+               basic_machine=mips-sony
+               os=-newsos
+               ;;
+       necv70)                                         # EGCS LOCAL
+               basic_machine=v70-nec
+               os=-sysv
+               ;;
+       next | m*-next )
+               basic_machine=m68k-next
+               case $os in
+                   -nextstep* )
+                       ;;
+                   -ns2*)
+                     os=-nextstep2
+                       ;;
+                   *)
+                     os=-nextstep3
+                       ;;
+               esac
+               ;;
+       nh3000)
+               basic_machine=m68k-harris
+               os=-cxux
+               ;;
+       nh[45]000)
+               basic_machine=m88k-harris
+               os=-cxux
+               ;;
+       nindy960)
+               basic_machine=i960-intel
+               os=-nindy
+               ;;
+       mon960)                                         # EGCS LOCAL
+               basic_machine=i960-intel
+               os=-mon960
+               ;;
+       np1)
+               basic_machine=np1-gould
+               ;;
+       OSE68000 | ose68000)                            # EGCS LOCAL
+               basic_machine=m68000-ericsson
+               os=-ose
+               ;;
+       os68k)                                          # EGCS LOCAL
+               basic_machine=m68k-none
+               os=-os68k
+               ;;
+       pa-hitachi)
+               basic_machine=hppa1.1-hitachi
+               os=-hiuxwe2
+               ;;
+       paragon)
+               basic_machine=i860-intel
+               os=-osf
+               ;;
+       pbd)
+               basic_machine=sparc-tti
+               ;;
+       pbb)
+               basic_machine=m68k-tti
+               ;;
+        pc532 | pc532-*)
+               basic_machine=ns32k-pc532
+               ;;
+       pentium | p5 | k5 | k6 | nexen)
+               basic_machine=i586-pc
+               ;;
+       pentiumpro | p6 | 6x86)
+               basic_machine=i686-pc
+               ;;
+       pentiumii | pentium2)
+               basic_machine=i786-pc
+               ;;
+       pentium-* | p5-* | k5-* | k6-* | nexen-*)
+               basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentiumpro-* | p6-* | 6x86-*)
+               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentiumii-* | pentium2-*)
+               basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pn)
+               basic_machine=pn-gould
+               ;;
+       power)  basic_machine=rs6000-ibm
+               ;;
+       ppc)    basic_machine=powerpc-unknown
+               ;;
+       ppc-*)  basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppcle | powerpclittle | ppc-le | powerpc-little)
+               basic_machine=powerpcle-unknown
+               ;;
+       ppcle-* | powerpclittle-*)
+               basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ps2)
+               basic_machine=i386-ibm
+               ;;
+       rom68k)                                         # EGCS LOCAL
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
+       rm[46]00)
+               basic_machine=mips-siemens
+               ;;
+       rtpc | rtpc-*)
+               basic_machine=romp-ibm
+               ;;
+       s390-ibm*|s390-*)
+               basic_machine=s390-ibm
+               os=-linux
+               ;;
+       sa29200)                                        # EGCS LOCAL
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       sequent)
+               basic_machine=i386-sequent
+               ;;
+       sh)
+               basic_machine=sh-hitachi
+               os=-hms
+               ;;
+       sparclite-wrs)                                  # EGCS LOCAL
+               basic_machine=sparclite-wrs
+               os=-vxworks
+               ;;
+       sps7)
+               basic_machine=m68k-bull
+               os=-sysv2
+               ;;
+       spur)
+               basic_machine=spur-unknown
+               ;;
+       st2000)                                         # EGCS LOCAL
+               basic_machine=m68k-tandem
+               ;;
+       stratus)                                        # EGCS LOCAL
+               basic_machine=i860-stratus
+               os=-sysv4
+               ;;
+       sun2)
+               basic_machine=m68000-sun
+               ;;
+       sun2os3)
+               basic_machine=m68000-sun
+               os=-sunos3
+               ;;
+       sun2os4)
+               basic_machine=m68000-sun
+               os=-sunos4
+               ;;
+       sun3os3)
+               basic_machine=m68k-sun
+               os=-sunos3
+               ;;
+       sun3os4)
+               basic_machine=m68k-sun
+               os=-sunos4
+               ;;
+       sun4os3)
+               basic_machine=sparc-sun
+               os=-sunos3
+               ;;
+       sun4os4)
+               basic_machine=sparc-sun
+               os=-sunos4
+               ;;
+       sun4sol2)
+               basic_machine=sparc-sun
+               os=-solaris2
+               ;;
+       sun3 | sun3-*)
+               basic_machine=m68k-sun
+               ;;
+       sun4)
+               basic_machine=sparc-sun
+               ;;
+       sun386 | sun386i | roadrunner)
+               basic_machine=i386-sun
+               ;;
+       symmetry)
+               basic_machine=i386-sequent
+               os=-dynix
+               ;;
+       tx39)
+               basic_machine=mipstx39-unknown
+               ;;
+       tx39el)
+               basic_machine=mipstx39el-unknown
+               ;;
+       tower | tower-32)
+               basic_machine=m68k-ncr
+               ;;
+       udi29k)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       ultra3)
+               basic_machine=a29k-nyu
+               os=-sym1
+               ;;
+       v810 | necv810)                                 # EGCS LOCAL
+               basic_machine=v810-nec
+               os=-none
+               ;;
+       vaxv)
+               basic_machine=vax-dec
+               os=-sysv
+               ;;
+       vms)
+               basic_machine=vax-dec
+               os=-vms
+               ;;
+       vpp*|vx|vx-*)
+               basic_machine=f301-fujitsu
+               ;;
+       vxworks960)
+               basic_machine=i960-wrs
+               os=-vxworks
+               ;;
+       vxworks68)
+               basic_machine=m68k-wrs
+               os=-vxworks
+               ;;
+       vxworks29k)
+               basic_machine=a29k-wrs
+               os=-vxworks
+               ;;
+       w65*)                                           # EGCS LOCAL
+               basic_machine=w65-wdc
+               os=-none
+               ;;
+       xmp)
+               basic_machine=xmp-cray
+               os=-unicos
+               ;;
+        xps | xps100)
+               basic_machine=xps100-honeywell
+               ;;
+       z8k-*-coff)                                     # EGCS LOCAL
+               basic_machine=z8k-unknown
+               os=-sim
+               ;;
+       none)
+               basic_machine=none-none
+               os=-none
+               ;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+       w89k)                                           # EGCS LOCAL
+               basic_machine=hppa1.1-winbond
+               ;;
+       op50n)                                          # EGCS LOCAL
+               basic_machine=hppa1.1-oki
+               ;;
+       op60c)                                          # EGCS LOCAL
+               basic_machine=hppa1.1-oki
+               ;;
+       mips)
+               if [ x$os = x-linux-gnu ]; then
+                       basic_machine=mips-unknown
+               else
+                       basic_machine=mips-mips
+               fi
+               ;;
+       romp)
+               basic_machine=romp-ibm
+               ;;
+       rs6000)
+               basic_machine=rs6000-ibm
+               ;;
+       vax)
+               basic_machine=vax-dec
+               ;;
+       pdp11)
+               basic_machine=pdp11-dec
+               ;;
+       we32k)
+               basic_machine=we32k-att
+               ;;
+       sparc | sparcv9)
+               basic_machine=sparc-sun
+               ;;
+        cydra)
+               basic_machine=cydra-cydrome
+               ;;
+       orion)
+               basic_machine=orion-highlevel
+               ;;
+       orion105)
+               basic_machine=clipper-highlevel
+               ;;
+       mac | mpw | mac-mpw)                            # EGCS LOCAL
+               basic_machine=m68k-apple
+               ;;
+       pmac | pmac-mpw)                                # EGCS LOCAL
+               basic_machine=powerpc-apple
+               ;;
+       c4x*)
+               basic_machine=c4x-none
+               os=-coff
+               ;;
+       *)
+               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+               exit 1
+               ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+       *-digital*)
+               basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+               ;;
+       *-commodore*)
+               basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+               ;;
+       *)
+               ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+       # -solaris* is a basic system type, with this one exception.
+       -solaris1 | -solaris1.*)
+               os=`echo $os | sed -e 's|solaris1|sunos4|'`
+               ;;
+       -solaris)
+               os=-solaris2
+               ;;
+       -svr4*)
+               os=-sysv4
+               ;;
+       -unixware*)
+               os=-sysv4.2uw
+               ;;
+       -gnu/linux*)
+               os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+               ;;
+       # First accept the basic system types.
+       # The portable systems comes first.
+       # Each alternative MUST END IN A *, to match a version number.
+       # -sysv* is not here because it comes later, after sysvr4.
+       -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+             | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+             | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+             | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+             | -aos* \
+             | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+             | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+             | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+             | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+             | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+             | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+             | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+             | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
+             | -interix* | -uwin* )
+       # Remember, each alternative MUST END IN *, to match a version number.
+               ;;
+       # EGCS LOCAL
+       -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+             | -windows* | -osx | -abug |  -netware* | -os9* | -beos* \
+             | -macos* | -mpw* | -magic* | -mon960* | -lnews* )
+               ;;
+       -mac*)
+               os=`echo $os | sed -e 's|mac|macos|'`
+               ;;
+       # END EGCS LOCAL
+       -linux*)
+               os=`echo $os | sed -e 's|linux|linux-gnu|'`
+               ;;
+       -sunos5*)
+               os=`echo $os | sed -e 's|sunos5|solaris2|'`
+               ;;
+       -sunos6*)
+               os=`echo $os | sed -e 's|sunos6|solaris3|'`
+               ;;
+       -osfrose*)
+               os=-osfrose
+               ;;
+       -osf*)
+               os=-osf
+               ;;
+       -utek*)
+               os=-bsd
+               ;;
+       -dynix*)
+               os=-bsd
+               ;;
+       -acis*)
+               os=-aos
+               ;;
+       -386bsd)                                        # EGCS LOCAL
+               os=-bsd
+               ;;
+       -ctix* | -uts*)
+               os=-sysv
+               ;;
+       -ns2 )
+               os=-nextstep2
+               ;;
+       # Preserve the version number of sinix5.
+       -sinix5.*)
+               os=`echo $os | sed -e 's|sinix|sysv|'`
+               ;;
+       -sinix*)
+               os=-sysv4
+               ;;
+       -triton*)
+               os=-sysv3
+               ;;
+       -oss*)
+               os=-sysv3
+               ;;
+       -svr4)
+               os=-sysv4
+               ;;
+       -svr3)
+               os=-sysv3
+               ;;
+       -sysvr4)
+               os=-sysv4
+               ;;
+       # This must come after -sysvr4.
+       -sysv*)
+               ;;
+       -ose*)                                          # EGCS LOCAL
+               os=-ose
+               ;;
+       -es1800*)                                       # EGCS LOCAL
+               os=-ose
+               ;;
+       -xenix)
+               os=-xenix
+               ;;
+       -none)
+               ;;
+       *)
+               # Get rid of the `-' at the beginning of $os.
+               os=`echo $os | sed 's/[^-]*-//'`
+               echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+               exit 1
+               ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+       *-acorn)
+               os=-riscix1.2
+               ;;
+       arm*-corel)
+               os=-linux
+               ;;
+       arm*-semi)
+               os=-aout
+               ;;
+        pdp11-*)
+               os=-none
+               ;;
+       *-dec | vax-*)
+               os=-ultrix4.2
+               ;;
+       m68*-apollo)
+               os=-domain
+               ;;
+       i386-sun)
+               os=-sunos4.0.2
+               ;;
+       m68000-sun)
+               os=-sunos3
+               # This also exists in the configure program, but was not the
+               # default.
+               # os=-sunos4
+               ;;
+       m68*-cisco)                                     # EGCS LOCAL
+               os=-aout
+               ;;
+       mips*-cisco)                                    # EGCS LOCAL
+               os=-elf
+               ;;
+        mips*-*)                                        # EGCS LOCAL
+                os=-elf
+                ;;
+       *-tti)  # must be before sparc entry or we get the wrong os.
+               os=-sysv3
+               ;;
+       sparc-* | *-sun)
+               os=-sunos4.1.1
+               ;;
+       *-be)
+               os=-beos
+               ;;
+       *-ibm)
+               os=-aix
+               ;;
+       *-wec)                                          # EGCS LOCAL
+               os=-proelf
+               ;;
+       *-winbond)                                      # EGCS LOCAL
+               os=-proelf
+               ;;
+       *-oki)                                          # EGCS LOCAL
+               os=-proelf
+               ;;
+       *-hp)
+               os=-hpux
+               ;;
+       *-hitachi)
+               os=-hiux
+               ;;
+       i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+               os=-sysv
+               ;;
+       *-cbm)
+               os=-amigaos
+               ;;
+       *-dg)
+               os=-dgux
+               ;;
+       *-dolphin)
+               os=-sysv3
+               ;;
+       m68k-ccur)
+               os=-rtu
+               ;;
+       m88k-omron*)
+               os=-luna
+               ;;
+       *-next )
+               os=-nextstep
+               ;;
+       *-sequent)
+               os=-ptx
+               ;;
+       *-crds)
+               os=-unos
+               ;;
+       *-ns)
+               os=-genix
+               ;;
+       i370-*)
+               os=-mvs
+               ;;
+       *-next)
+               os=-nextstep3
+               ;;
+        *-gould)
+               os=-sysv
+               ;;
+        *-highlevel)
+               os=-bsd
+               ;;
+       *-encore)
+               os=-bsd
+               ;;
+        *-sgi)
+               os=-irix
+               ;;
+        *-siemens)
+               os=-sysv4
+               ;;
+       *-masscomp)
+               os=-rtu
+               ;;
+       f301-fujitsu)
+               os=-uxpv
+               ;;
+       *-rom68k)                                       # EGCS LOCAL
+               os=-coff
+               ;;
+       *-*bug)                                         # EGCS LOCAL
+               os=-coff
+               ;;
+       *-apple)                                        # EGCS LOCAL
+               os=-macos
+               ;;
+       *)
+               os=-none
+               ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+       *-unknown)
+               case $os in
+                       -riscix*)
+                               vendor=acorn
+                               ;;
+                       -sunos*)
+                               vendor=sun
+                               ;;
+                       -aix*)
+                               vendor=ibm
+                               ;;
+                       -beos*)
+                               vendor=be
+                               ;;
+                       -hpux*)
+                               vendor=hp
+                               ;;
+                       -mpeix*)
+                               vendor=hp
+                               ;;
+                       -hiux*)
+                               vendor=hitachi
+                               ;;
+                       -unos*)
+                               vendor=crds
+                               ;;
+                       -dgux*)
+                               vendor=dg
+                               ;;
+                       -luna*)
+                               vendor=omron
+                               ;;
+                       -genix*)
+                               vendor=ns
+                               ;;
+                       -mvs*)
+                               vendor=ibm
+                               ;;
+                       -ptx*)
+                               vendor=sequent
+                               ;;
+                       -vxsim* | -vxworks*)
+                               vendor=wrs
+                               ;;
+                       -aux*)
+                               vendor=apple
+                               ;;
+                       -hms*)                          # EGCS LOCAL
+                               vendor=hitachi
+                               ;;
+                       -mpw* | -macos*)                # EGCS LOCAL
+                               vendor=apple
+                               ;;
+               esac
+               basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+               ;;
+esac
+
+echo $basic_machine$os
diff --git a/libFoundation/config/alpha/linux-gnu.h b/libFoundation/config/alpha/linux-gnu.h
new file mode 100644 (file)
index 0000000..4266379
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+   linux-gnu.h
+
+   Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@net-community.com>
+   Date: November 1997
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+#ifndef __linux_gnu_h__
+#define __linux_gnu_h__
+
+#ifndef OBJC_FORWARDING_STACK_OFFSET
+#define OBJC_FORWARDING_STACK_OFFSET   0
+#endif
+
+#ifndef OBJC_FORWARDING_MIN_OFFSET
+#define OBJC_FORWARDING_MIN_OFFSET 0
+#endif
+
+/* Define the size of the block returned by __builtin_apply_args. This value is
+   computed by the function in expr.c. The block contains in order: a pointer
+   to the stack arguments frame, the structure value address unless this is
+   passed as an "invisible" first argument and all registers that may be used
+   in calling a function. */
+
+#define APPLY_ARGS_SIZE                104
+
+/* Define the size of the result block returned by the __builtin_apply. This
+   block contains all registers that could be used to return the function
+   value. This value is computed by apply_result_size function in expr.c. There
+   are also machines where this value is predefined in the machine description
+   file, so that machine specific information can be stored. */
+
+#define APPLY_RESULT_SIZE      16
+
+/* Define how to find the value returned by a function. TYPE is an Objective-C
+   encoding string describing the type of the returned value. ARGS is the
+   arguments frame passed to __builtin_apply. RESULT_FRAME is the address of
+   the block returned by __builtin_apply. RETURN_VALUE is an address where
+   this macro should put the returned value. */
+
+#define FUNCTION_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({ int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT || *(TYPE) == _C_DBL) \
+           *(double*)(RETURN_VALUE) = \
+               *(double*)(((char*)(RESULT_FRAME)) + 24); \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy((RETURN_VALUE), *(void**)(RESULT_FRAME), type_size); \
+       else memcpy((RETURN_VALUE), (RESULT_FRAME), type_size); })
+
+
+/* Set the value in RETURN_VALUE to be the value returned by a function.
+   Assume that the function was previously called and RESULT_FRAME is the
+   address of the block returned by __builtin_apply. TYPE is the actual
+   type of this value. ARGS is the address of block that was passed
+   to __builtin_apply. */
+
+#define FUNCTION_SET_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({  int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT || *(TYPE) == _C_DBL) \
+           *(double*)(((char*)(RESULT_FRAME)) + 24) = \
+                 *(double*)(RETURN_VALUE); \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy(*(void**)(RESULT_FRAME), (RETURN_VALUE), type_size); \
+       else memcpy((RESULT_FRAME), (RETURN_VALUE), type_size); })
+
+/* If the RETTYPE is a structure and the address of the structure value is
+   passed to the called function, then obtain from ARGS its address. In general
+   this address is the second pointer into the arguments frame. This macro
+   should produce 0 if the RETTYPE doesn't match the conditions above. */
+
+#define GET_STRUCT_VALUE_ADDRESS(ARGS, RETTYPE) \
+    ((*(RETTYPE) == _C_STRUCT_B || *(RETTYPE) == _C_UNION_B \
+           || *(RETTYPE) == _C_ARY_B) \
+       ? *(void**)(ARGS) : 0)
+
+/* Prepare ARGS for calling the function. If the function returns a struct by
+   value, it's the caller responsability to pass to the called function the
+   address of where to store the structure value. */
+
+#define SET_STRUCT_VALUE_ADDRESS(ARGS, ADDR, RETTYPE) \
+    *(void**)(ARGS) = (ADDR)
+
+
+/* The following macros are used to determine the encoding of a selector given
+   the types of arguments. This macros follows the similar ones defined in the
+   target machine description from the compiler sources. */
+
+/* Define a data type for recording info about the arguments list of a method.
+   A variable of this type is further used by FUNCTION_ARG_ENCODING to
+   determine the encoding of an argument. This type should record all info
+   about arguments processed so far. */
+
+#define CUMULATIVE_ARGS int
+
+/* Initialize a variable of type CUMULATIVE_ARGS. This macro is called before
+   processing the first argument of a method. */
+
+#define INIT_CUMULATIVE_ARGS(CUM)      ((CUM) = 0)
+
+/* This macro determines the encoding of the next argument of a method. It is
+   called repetitively, starting with the first argument and continuing to the
+   last one. CUM is a variable of type CUMULATIVE_ARGS. TYPE is a NSString
+   which represents the type of the argument processed. This macro must
+   produce a NSString whose value represents the encoding and position of the
+   current argument. STACKSIZE is a variable that counts the number of bytes
+   occupied by the arguments on the stack. */
+
+#ifndef ROUND
+#define ROUND(V, A) \
+  ({ typeof(V) __v=(V); typeof(A) __a=(A); \
+     __a*((__v+__a-1)/__a); })
+#endif
+
+#define FUNCTION_ARG_ENCODING(CUM, TYPE, STACK_ARGSIZE) \
+    ({  id encoding; \
+       const char* type = [(TYPE) cString]; \
+       int align = objc_alignof_type(type); \
+       int type_size = objc_sizeof_type(type); \
+\
+       (CUM) = ROUND((CUM), align); \
+       encoding = [NSString stringWithFormat:@"%@%d", \
+                                   (TYPE), \
+                                   (CUM) + OBJC_FORWARDING_STACK_OFFSET]; \
+       (STACK_ARGSIZE) = (CUM) + type_size; \
+       (CUM) += ROUND(type_size, sizeof(void*)); \
+       encoding; })
+
+
+#endif /* __linux_gnu_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/config/generic/generic.h b/libFoundation/config/generic/generic.h
new file mode 100644 (file)
index 0000000..60630e4
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+   generic.h
+
+   Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@net-community.com>
+   Date: May 1997
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __generic_h__
+#define __generic_h__
+
+#ifndef OBJC_FORWARDING_STACK_OFFSET
+#define OBJC_FORWARDING_STACK_OFFSET   0
+#endif
+
+#ifndef OBJC_FORWARDING_MIN_OFFSET
+#define OBJC_FORWARDING_MIN_OFFSET 0
+#endif
+
+/* Define the size of the block returned by __builtin_apply_args. This value is
+   computed by the function in expr.c. The block contains in order: a pointer
+   to the stack arguments frame, the structure value address unless this is
+   passed as an "invisible" first argument and all registers that may be used
+   in calling a function. */
+
+#define APPLY_ARGS_SIZE        8
+
+/* Define the size of the result block returned by the __builtin_apply. This
+   block contains all registers that could be used to return the function
+   value. This value is computed by apply_result_size function in expr.c. There
+   are also machines where this value is predefined in the machine description
+   file, so that machine specific information can be stored. */
+
+#define APPLY_RESULT_SIZE      8
+
+/* Define how to find the value returned by a function. TYPE is a Objective-C
+   encoding string describing the type of the returned value. ARGS is the
+   arguments frame passed to __builtin_apply. RESULT_FRAME is the address of
+   the block returned by __builtin_apply. RETURN_VALUE is an address where
+   this macro should put the returned value. */
+
+#define FUNCTION_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({ int type_size = objc_sizeof_type(TYPE); \
+       memcpy((RETURN_VALUE), (RESULT_FRAME), type_size); })
+
+/* Set the value in RETURN_VALUE to be the value returned by a function.
+   Assume that the fucntion was previously called and RESULT_FRAME is the
+   address of the block returned by __builtin_apply. TYPE is the actual
+   type of this value. ARGS is the address of block that was passed
+   to __builtin_apply. */
+
+#define FUNCTION_SET_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({  int type_size = objc_sizeof_type(TYPE); \
+       memcpy((RESULT_FRAME), (RETURN_VALUE), type_size); })
+
+/* If the RETTYPE is a structure and the address of the structure value is
+   passed to the called function, then obtain from ARGS its address. In general
+   this address is the second pointer into the arguments frame. This macro
+   should produce 0 if the RETTYPE doesn't match the conditions above. */
+
+#define GET_STRUCT_VALUE_ADDRESS(ARGS, RETTYPE) \
+    ((*(RETTYPE) == _C_STRUCT_B || *(RETTYPE) == _C_UNION_B \
+           || *(RETTYPE) == _C_ARY_B) ? \
+         *(void**)(((char*)(ARGS)) + sizeof(void*)) \
+       : 0)
+
+/* Prepare ARGS for calling the function. If the function returns a struct by
+   value, it's the caller responsability to pass to the called function the
+   address of where to store the structure value. */
+
+#define SET_STRUCT_VALUE_ADDRESS(ARGS, ADDR, RETTYPE) \
+    *(void**)(((char*)(ARGS)) + sizeof(void*)) = (ADDR)
+
+
+/* The following macros are used to determine the encoding of a selector given
+   the types of arguments. This macros follows the similar ones defined in the
+   target machine description from the compiler sources. */
+
+/* Define a data type for recording info about the arguments list of a method.
+   A variable of this type is further used by FUNCTION_ARG_ENCODING to
+   determine the encoding of an argument. This type should record all info
+   about arguments processed so far. */
+
+#define CUMULATIVE_ARGS int
+
+/* Initialize a variable of type CUMULATIVE_ARGS. This macro is called before
+   processing the first argument of a method. */
+
+#define INIT_CUMULATIVE_ARGS(CUM)      ((CUM) = 0)
+
+/* This macro determines the encoding of the next argument of a method. It is
+   called repetitively, starting with the first argument and continuing to the
+   last one. CUM is a variable of type CUMULATIVE_ARGS. TYPE is a NSString
+   which represents the type of the argument processed. This macro must
+   produce a NSString whose value represents the encoding and position of the
+   current argument. STACKSIZE is a variable that counts the number of bytes
+   occupied by the arguments on the stack. */
+
+#ifndef ROUND
+#define ROUND(V, A) \
+  ({ typeof(V) __v=(V); typeof(A) __a=(A); \
+     __a*((__v+__a-1)/__a); })
+#endif
+
+#define FUNCTION_ARG_ENCODING(CUM, TYPE, STACK_ARGSIZE) \
+    ({  id encoding; \
+       const char* type = [(TYPE) cString]; \
+       int align = objc_alignof_type(type); \
+       int type_size = objc_sizeof_type(type); \
+\
+       (CUM) = ROUND((CUM), align); \
+       encoding = [NSString stringWithFormat:@"%@%d", \
+                                   (TYPE), \
+                                   (CUM) + OBJC_FORWARDING_STACK_OFFSET]; \
+       (STACK_ARGSIZE) = (CUM) + type_size; \
+       (CUM) += ROUND(type_size, sizeof(void*)); \
+       encoding; })
+
+#endif /* __generic_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/config/hppa/hppa.h b/libFoundation/config/hppa/hppa.h
new file mode 100644 (file)
index 0000000..a87ba9c
--- /dev/null
@@ -0,0 +1,163 @@
+/* 
+   hppa.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __hppa_h__
+#define __hppa_h__
+
+/* This file contains only the definitions of the needed macros with some
+   dummy values. If want to port the library on machines having this processor
+   you have to write the real macros. */
+
+#ifndef OBJC_FORWARDING_STACK_OFFSET
+#define OBJC_FORWARDING_STACK_OFFSET   0
+#endif
+
+#ifndef OBJC_FORWARDING_MIN_OFFSET
+#define OBJC_FORWARDING_MIN_OFFSET 0
+#endif
+
+/* Define the size of the block returned by __builtin_apply_args. This value is
+   computed by the function in expr.c. The block contains in order: a pointer
+   to the stack arguments frame, the structure value address unless this is
+   passed as an "invisible" first argument and all registers that may be used
+   in calling a function. */
+
+#define APPLY_ARGS_SIZE        56
+
+/* Define the size of the result block returned by the __builtin_apply. This
+   block contains all registers that could be used to return the function
+   value. This value is computed by apply_result_size function in expr.c. There
+   are also machines where this value is predefined in the machine description
+   file, so that machine specific information can be stored. */
+
+#define APPLY_RESULT_SIZE      16
+
+/* Define how to find the value returned by a function. TYPE is a Objective-C
+   encoding string describing the type of the returned value. ARGS is the
+   arguments frame passed to __builtin_apply. RESULT is the address of the
+   block returned by __builtin_apply. RETURN_VALUE is an address where this
+   macro should put the returned value. */
+
+#define FUNCTION_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({ int type_size = objc_sizeof_type(TYPE); \
+       if((*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) && type_size > 8) \
+           memcpy((RETURN_VALUE), *(void**)(RESULT_FRAME), type_size); \
+       else memcpy((RETURN_VALUE), (RESULT_FRAME), type_size); })
+
+/* Set the value in RETURN_VALUE to be the value returned by a function.
+   Assume that the fucntion was previously called and RESULT_FRAME is the
+   address of the block returned by __builtin_apply. TYPE is the actual
+   type of this value. ARGS is the address of block that was passed
+   to __builtin_apply. */
+
+#define FUNCTION_SET_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({  int type_size = objc_sizeof_type(TYPE); \
+       if((*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) && type_size > 8) \
+           memcpy(*(void**)(ARGS), (RETURN_VALUE), type_size); \
+       else memcpy((RESULT_FRAME), (RETURN_VALUE), type_size); })
+
+/* If the RETTYPE is a structure and the address of the structure value is
+   passed to the called function, then obtain from ARGS its address. In general
+   this address is the second pointer into the arguments frame. This macro
+   should produce 0 if the RETTYPE doesn't match the conditions above. */
+
+#define GET_STRUCT_VALUE_ADDRESS(ARGS, RETTYPE) \
+    (((*(RETTYPE) == _C_STRUCT_B || *(RETTYPE) == _C_UNION_B \
+           || *(RETTYPE) == _C_ARY_B) && objc_sizeof_type(RETTYPE) > 8) \
+       ? **(void***)(ARGS) \
+       : 0)
+
+/* Prepare ARGS for calling the function. If the function returns a struct by
+   value, it's the caller responsability to pass to the called function the
+   address of where to store the structure value. */
+
+#define SET_STRUCT_VALUE_ADDRESS(ARGS, ADDR, RETTYPE) \
+    (((*(RETTYPE) == _C_STRUCT_B || *(RETTYPE) == _C_UNION_B \
+           || *(RETTYPE) == _C_ARY_B) && objc_sizeof_type(RETTYPE) > 8) ? \
+       **(void***)(ARGS) = (ADDR) : 0)
+
+
+/* The following macros are used to determine the encoding of a selector given
+   the types of arguments. This macros follows the similar ones defined in the
+   target machine description from the compiler sources. */
+
+/* Define a data type for recording info about the arguments list of a method.
+   A variable of this type is further used by FUNCTION_ARG_ENCODING to
+   determine the encoding of an argument. This type should record all info
+   about arguments processed so far. */
+
+#define CUMULATIVE_ARGS int
+
+/* Initialize a variable of type CUMULATIVE_ARGS. This macro is called before
+   processing the first argument of a method. */
+
+#define INIT_CUMULATIVE_ARGS(CUM)  ((CUM) = 0)
+
+
+/* This macro determines the encoding of the next argument of a method. It is
+   called repetitively, starting with the first argument and continuing to the
+   last one. CUM is a variable of type CUMULATIVE_ARGS. TYPE is a NSString
+   which represents the type of the argument processed. This macro must
+   produce a NSString whose value represents the encoding and position of the
+   current argument. STACKSIZE is a variable that counts the number of bytes
+   occupied by the arguments on the stack. */
+
+#ifndef ROUND
+#define ROUND(V, A) \
+  ({ typeof(V) __v=(V); typeof(A) __a=(A); \
+     __a*((__v+__a-1)/__a); })
+#endif
+
+#define FUNCTION_ARG_SIZE(TYPESIZE)    \
+    ((TYPESIZE + 3) / 4)
+
+#define FUNCTION_ARG_ENCODING(CUM, TYPE, STACK_ARGSIZE) \
+    ({  id encoding; \
+       int align = objc_alignof_type([(TYPE) cString]); \
+       int type_size = objc_sizeof_type([(TYPE) cString]); \
+       const char* type = [(TYPE) cString]; \
+\
+       (CUM) = ROUND((CUM), align); \
+       encoding = [NSString stringWithFormat:@"%@%d", \
+                                   (TYPE), \
+                                   (CUM) + OBJC_FORWARDING_STACK_OFFSET]; \
+       if((*type == _C_STRUCT_B || *type == _C_UNION_B || *type == _C_ARY_B)) \
+           (STACK_ARGSIZE) = (CUM) + ROUND(type_size, align); \
+       else (STACK_ARGSIZE) = (CUM) + type_size; \
+\
+       /* Compute the new value of cumulative args */ \
+       ((((CUM) & 01) && FUNCTION_ARG_SIZE(type_size) > 1) && (CUM)++); \
+       (CUM) += FUNCTION_ARG_SIZE(type_size); \
+       encoding; })
+
+#endif /* __hppa_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/config/i386/cygwin32.h b/libFoundation/config/i386/cygwin32.h
new file mode 100644 (file)
index 0000000..2a006d3
--- /dev/null
@@ -0,0 +1,150 @@
+/* 
+   cygwin32.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __cygwin32_h__
+#define __cygwin32_h__
+
+#include "i386.h"
+
+#undef FUNCTION_VALUE
+#undef FUNCTION_SET_VALUE
+#undef GET_STRUCT_VALUE_ADDRESS
+#undef SET_STRUCT_VALUE_ADDRESS
+
+/* Define how to find the value returned by a function. TYPE is a Objective-C
+   encoding string describing the type of the returned value. ARGS is the
+   arguments frame passed to __builtin_apply. RESULT_FRAME is the address of
+   the block returned by __builtin_apply. RETURN_VALUE is an address where
+   this macro should put the returned value. */
+
+#if 0 && defined(BROKEN_BUILTIN_APPLY)
+
+#define FUNCTION_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({ int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) { \
+           float aFloat; \
+           asm("fsts %0" : "=f2" (aFloat) :); \
+           *(float*)(RETURN_VALUE) = aFloat; \
+       } \
+       else if(*(TYPE) == _C_DBL) { \
+           double aDouble; \
+           asm("fstl %0" : "=f2" (aDouble)); \
+           *(double*)(RETURN_VALUE) = aDouble; \
+       } \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy((RETURN_VALUE), *(void**)(RESULT_FRAME), type_size); \
+       else memcpy((RETURN_VALUE), (RESULT_FRAME), type_size); })
+
+#else /* !BROKEN_BUILTIN_APPLY */
+
+#define FUNCTION_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({ int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) { \
+           *(float*)(RETURN_VALUE) = \
+               (float)*(long double*)(((char*)(RESULT_FRAME)) + 8); \
+           printf("float value result = %f\n", *(float*)(RETURN_VALUE)); \
+       } \
+       else if(*(TYPE) == _C_DBL) { \
+           *(double*)(RETURN_VALUE) = \
+               (double)*(long double*)(((char*)(RESULT_FRAME)) + 8); \
+           printf("double value result = %f\n", *(double*)(RETURN_VALUE)); \
+       } \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy((RETURN_VALUE), *(void**)(RESULT_FRAME), type_size); \
+       else memcpy((RETURN_VALUE), (RESULT_FRAME), type_size); })
+
+#endif /* !BROKEN_BUILTIN_APPLY */
+
+/* Set the value in RETURN_VALUE to be the value returned by a function.
+   Assume that the fucntion was previously called and RESULT_FRAME is the
+   address of the block returned by __builtin_apply. TYPE is the actual
+   type of this value. ARGS is the address of block that was passed
+   to __builtin_apply. */
+
+#if 0 && defined(BROKEN_BUILTIN_APPLY)
+
+#define FUNCTION_SET_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({  int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) { \
+           float aFloat = *(float*)(RETURN_VALUE); \
+           asm("fld %0" : : "f" (aFloat)); \
+       } \
+       else if(*(TYPE) == _C_DBL) { \
+           double aDouble = *(double*)(RETURN_VALUE); \
+           asm("fldl %0" : : "f" (aDouble)); \
+       } \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy(*(void**)(ARGS), (RETURN_VALUE), type_size); \
+       else memcpy((RESULT_FRAME), (RETURN_VALUE), type_size); })
+
+#else /* !BROKEN_BUILTIN_APPLY */
+
+#define FUNCTION_SET_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({  int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) \
+           *(long double*)(((char*)(RESULT_FRAME)) + 8) = \
+               (long double)*(float*)(RETURN_VALUE); \
+       else if(*(TYPE) == _C_DBL) \
+           *(long double*)(((char*)(RESULT_FRAME)) + 8) = \
+               (long double)*(double*)(RETURN_VALUE); \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy(*(void**)(ARGS), (RETURN_VALUE), type_size); \
+       else memcpy((RESULT_FRAME), (RETURN_VALUE), type_size); })
+
+#endif /* !BROKEN_BUILTIN_APPLY */
+
+/* If the RETTYPE is a structure and the address of the structure value is
+   passed to the called function, then obtain from ARGS its address. In general
+   this address is the second pointer into the arguments frame. However on
+   cygwin32 this address is passed as the first argument to the called function.
+   This macro should produce 0 if the RETTYPE doesn't match the conditions
+   above. */
+
+#define GET_STRUCT_VALUE_ADDRESS(ARGS, RETTYPE) \
+    ((*(RETTYPE) == _C_STRUCT_B || *(RETTYPE) == _C_UNION_B \
+           || *(RETTYPE) == _C_ARY_B) ? \
+         **(void***)(ARGS) \
+       : 0)
+
+/* Prepare ARGS for calling the function. If the function returns a struct by
+   value, it's the caller responsability to pass to the called function the
+   address of where to store the structure value. */
+
+#define SET_STRUCT_VALUE_ADDRESS(ARGS, ADDR, RETTYPE) \
+    if(*(RETTYPE) == _C_STRUCT_B || *(RETTYPE) == _C_UNION_B \
+           || *(RETTYPE) == _C_ARY_B) \
+       **(void***)(ARGS) = (ADDR);
+
+#endif /* __cygwin32_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/config/i386/freebsd.h b/libFoundation/config/i386/freebsd.h
new file mode 100644 (file)
index 0000000..95ab143
--- /dev/null
@@ -0,0 +1,37 @@
+/* 
+   freebsd.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __freebsd_h__
+#define __freebsd_h__
+
+#include "linux.h"
+
+#endif /* __freebsd_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/config/i386/gnu.h b/libFoundation/config/i386/gnu.h
new file mode 100644 (file)
index 0000000..b07983a
--- /dev/null
@@ -0,0 +1,37 @@
+/* 
+   linux_gnu.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __gnu_h__
+#define __gnu_h__
+
+#include "linux.h"
+
+#endif /* __gnu_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/config/i386/i386.h b/libFoundation/config/i386/i386.h
new file mode 100644 (file)
index 0000000..2729904
--- /dev/null
@@ -0,0 +1,213 @@
+/* 
+   i386.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __i386_h__
+#define __i386_h__
+
+#ifndef OBJC_FORWARDING_STACK_OFFSET
+#define OBJC_FORWARDING_STACK_OFFSET   0
+#endif
+
+#ifndef OBJC_FORWARDING_MIN_OFFSET
+#define OBJC_FORWARDING_MIN_OFFSET 0
+#endif
+
+/* Define the size of the block returned by __builtin_apply_args. This value is
+   computed by the function in expr.c. The block contains in order: a pointer
+   to the stack arguments frame, the structure value address unless this is
+   passed as an "invisible" first argument and all registers that may be used
+   in calling a function. */
+
+#define APPLY_ARGS_SIZE        8
+
+/* Define the size of the result block returned by the __builtin_apply. This
+   block contains all registers that could be used to return the function
+   value. This value is computed by apply_result_size function in expr.c. There
+   are also machines where this value is predefined in the machine description
+   file, so that machine specific information can be stored. */
+
+#define APPLY_RESULT_SIZE      116
+
+/* Define how to find the value returned by a function. TYPE is a Objective-C
+   encoding string describing the type of the returned value. ARGS is the
+   arguments frame passed to __builtin_apply. RESULT_FRAME is the address of
+   the block returned by __builtin_apply. RETURN_VALUE is an address where
+   this macro should put the returned value. */
+
+#ifdef BROKEN_BUILTIN_APPLY
+
+#define FUNCTION_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({ int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) { \
+           float aFloat; \
+           asm("fsts %0" : "=f2" (aFloat) :); \
+           *(float*)(RETURN_VALUE) = aFloat; \
+       } \
+       else if(*(TYPE) == _C_DBL) { \
+           double aDouble; \
+           asm("fstl %0" : "=f2" (aDouble)); \
+           *(double*)(RETURN_VALUE) = aDouble; \
+       } \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy((RETURN_VALUE), \
+                  *(void**)(((char*)(ARGS)) + sizeof(void*)), type_size); \
+       else memcpy((RETURN_VALUE), (RESULT_FRAME), type_size); })
+
+#else /* !BROKEN_BUILTIN_APPLY */
+
+#define FUNCTION_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({ int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) { \
+           *(float*)(RETURN_VALUE) = \
+               (float)*(long double*)(((char*)(RESULT_FRAME)) + 8); \
+       } \
+       else if(*(TYPE) == _C_DBL) { \
+           *(double*)(RETURN_VALUE) = \
+               (double)*(long double*)(((char*)(RESULT_FRAME)) + 8); \
+       } \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy((RETURN_VALUE), \
+                  *(void**)(((char*)(ARGS)) + sizeof(void*)), type_size); \
+       else memcpy((RETURN_VALUE), (RESULT_FRAME), type_size); })
+
+#endif /* !BROKEN_BUILTIN_APPLY */
+
+/* Set the value in RETURN_VALUE to be the value returned by a function.
+   Assume that the fucntion was previously called and RESULT_FRAME is the
+   address of the block returned by __builtin_apply. TYPE is the actual
+   type of this value. ARGS is the address of block that was passed
+   to __builtin_apply. */
+
+#ifdef BROKEN_BUILTIN_APPLY
+
+#define FUNCTION_SET_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({  int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) { \
+           float aFloat = *(float*)(RETURN_VALUE); \
+           asm("fld %0" : : "f" (aFloat)); \
+       } \
+       else if(*(TYPE) == _C_DBL) { \
+           double aDouble = *(double*)(RETURN_VALUE); \
+           asm("fldl %0" : : "f" (aDouble)); \
+       } \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy(*(void**)(((char*)(ARGS)) + sizeof(void*)), \
+                  (RETURN_VALUE), type_size); \
+       else memcpy((RESULT_FRAME), (RETURN_VALUE), type_size); })
+
+#else /* !BROKEN_BUILTIN_APPLY */
+
+#define FUNCTION_SET_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({  int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) \
+           *(long double*)(((char*)(RESULT_FRAME)) + 8) = \
+               (long double)*(float*)(RETURN_VALUE); \
+       else if(*(TYPE) == _C_DBL) \
+           *(long double*)(((char*)(RESULT_FRAME)) + 8) = \
+               (long double)*(double*)(RETURN_VALUE); \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy(*(void**)(((char*)(ARGS)) + sizeof(void*)), \
+                  (RETURN_VALUE), type_size); \
+       else memcpy((RESULT_FRAME), (RETURN_VALUE), type_size); })
+
+#endif /* !BROKEN_BUILTIN_APPLY */
+
+/* If the RETTYPE is a structure and the address of the structure value is
+   passed to the called function, then obtain from ARGS its address. In general
+   this address is the second pointer into the arguments frame. This macro
+   should produce 0 if the RETTYPE doesn't match the conditions above. */
+
+#define GET_STRUCT_VALUE_ADDRESS(ARGS, RETTYPE) \
+    ((*(RETTYPE) == _C_STRUCT_B || *(RETTYPE) == _C_UNION_B \
+           || *(RETTYPE) == _C_ARY_B) ? \
+         *(void**)(((char*)(ARGS)) + sizeof(void*)) \
+       : 0)
+
+/* Prepare ARGS for calling the function. If the function returns a struct by
+   value, it's the caller responsability to pass to the called function the
+   address of where to store the structure value. */
+
+#define SET_STRUCT_VALUE_ADDRESS(ARGS, ADDR, RETTYPE) \
+    *(void**)(((char*)(ARGS)) + sizeof(void*)) = (ADDR)
+
+
+/* The following macros are used to determine the encoding of a selector given
+   the types of arguments. This macros follows the similar ones defined in the
+   target machine description from the compiler sources. */
+
+/* Define a data type for recording info about the arguments list of a method.
+   A variable of this type is further used by FUNCTION_ARG_ENCODING to
+   determine the encoding of an argument. This type should record all info
+   about arguments processed so far. */
+
+#define CUMULATIVE_ARGS int
+
+/* Initialize a variable of type CUMULATIVE_ARGS. This macro is called before
+   processing the first argument of a method. */
+
+#define INIT_CUMULATIVE_ARGS(CUM)      ((CUM) = 0)
+
+/* This macro determines the encoding of the next argument of a method. It is
+   called repetitively, starting with the first argument and continuing to the
+   last one. CUM is a variable of type CUMULATIVE_ARGS. TYPE is a NSString
+   which represents the type of the argument processed. This macro must
+   produce a NSString whose value represents the encoding and position of the
+   current argument. STACKSIZE is a variable that counts the number of bytes
+   occupied by the arguments on the stack. */
+
+#ifndef ROUND
+#define ROUND(V, A) \
+  ({ typeof(V) __v=(V); typeof(A) __a=(A); \
+     __a*((__v+__a-1)/__a); })
+#endif
+
+#define FUNCTION_ARG_ENCODING(CUM, TYPE, STACK_ARGSIZE) \
+    ({  id encoding; \
+       const char* type = [(TYPE) cString]; \
+       int align = objc_alignof_type(type); \
+       int type_size = objc_sizeof_type(type); \
+\
+       (CUM) = ROUND((CUM), align); \
+       encoding = [NSString stringWithFormat:@"%@%d", \
+                                   (TYPE), \
+                                   (CUM) + OBJC_FORWARDING_STACK_OFFSET]; \
+       if((*type == _C_STRUCT_B || *type == _C_UNION_B || *type == _C_ARY_B) \
+               && type_size > 2) \
+           (STACK_ARGSIZE) = (CUM) + ROUND(type_size, align); \
+       else (STACK_ARGSIZE) = (CUM) + type_size; \
+       (CUM) += ROUND(type_size, sizeof(void*)); \
+       encoding; })
+
+#endif /* __i386_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/config/i386/linux-gnu.h b/libFoundation/config/i386/linux-gnu.h
new file mode 100644 (file)
index 0000000..ec5a214
--- /dev/null
@@ -0,0 +1,37 @@
+/* 
+   linux_gnu.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __linux_gnu_h__
+#define __linux_gnu_h__
+
+#include "linux.h"
+
+#endif /* __linux_gnu_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/config/i386/linux.h b/libFoundation/config/i386/linux.h
new file mode 100644 (file)
index 0000000..de4e0a5
--- /dev/null
@@ -0,0 +1,147 @@
+/* 
+   linux.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __linux_h__
+#define __linux_h__
+
+#include "i386.h"
+
+#undef FUNCTION_VALUE
+#undef FUNCTION_SET_VALUE
+#undef GET_STRUCT_VALUE_ADDRESS
+#undef SET_STRUCT_VALUE_ADDRESS
+
+/* Define how to find the value returned by a function. TYPE is a Objective-C
+   encoding string describing the type of the returned value. ARGS is the
+   arguments frame passed to __builtin_apply. RESULT_FRAME is the address of
+   the block returned by __builtin_apply. RETURN_VALUE is an address where
+   this macro should put the returned value. */
+
+#if 0 && defined(BROKEN_BUILTIN_APPLY)
+
+#define FUNCTION_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({ int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) { \
+           float aFloat; \
+           asm("fsts %0" : "=f2" (aFloat) :); \
+           *(float*)(RETURN_VALUE) = aFloat; \
+       } \
+       else if(*(TYPE) == _C_DBL) { \
+           double aDouble; \
+           asm("fstl %0" : "=f2" (aDouble)); \
+           *(double*)(RETURN_VALUE) = aDouble; \
+       } \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy((RETURN_VALUE), *(void**)(RESULT_FRAME), type_size); \
+       else memcpy((RETURN_VALUE), (RESULT_FRAME), type_size); })
+
+#else /* !BROKEN_BUILTIN_APPLY */
+
+#define FUNCTION_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({ int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) { \
+           *(float*)(RETURN_VALUE) = \
+               (float)*(long double*)(((char*)(RESULT_FRAME)) + 8); \
+       } \
+       else if(*(TYPE) == _C_DBL) { \
+           *(double*)(RETURN_VALUE) = \
+               (double)*(long double*)(((char*)(RESULT_FRAME)) + 8); \
+       } \
+       else if(*(TYPE) != _C_STRUCT_B && *(TYPE) != _C_UNION_B \
+               && *(TYPE) != _C_ARY_B) \
+           memcpy((RETURN_VALUE), (RESULT_FRAME), type_size); })
+
+#endif /* !BROKEN_BUILTIN_APPLY */
+
+/* Set the value in RETURN_VALUE to be the value returned by a function.
+   Assume that the fucntion was previously called and RESULT_FRAME is the
+   address of the block returned by __builtin_apply. TYPE is the actual
+   type of this value. ARGS is the address of block that was passed
+   to __builtin_apply. */
+
+#if 0 && defined(BROKEN_BUILTIN_APPLY)
+
+#define FUNCTION_SET_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({  int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) { \
+           float aFloat = *(float*)(RETURN_VALUE); \
+           asm("fld %0" : : "f" (aFloat)); \
+       } \
+       else if(*(TYPE) == _C_DBL) { \
+           double aDouble = *(double*)(RETURN_VALUE); \
+           asm("fldl %0" : : "f" (aDouble)); \
+       } \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy(*(void**)(ARGS), (RETURN_VALUE), type_size); \
+       else memcpy((RESULT_FRAME), (RETURN_VALUE), type_size); })
+
+#else /* !BROKEN_BUILTIN_APPLY */
+
+#define FUNCTION_SET_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({  int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) \
+           *(long double*)(((char*)(RESULT_FRAME)) + 8) = \
+               (long double)*(float*)(RETURN_VALUE); \
+       else if(*(TYPE) == _C_DBL) \
+           *(long double*)(((char*)(RESULT_FRAME)) + 8) = \
+               (long double)*(double*)(RETURN_VALUE); \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy(*(void**)(ARGS), (RETURN_VALUE), type_size); \
+       else memcpy((RESULT_FRAME), (RETURN_VALUE), type_size); })
+
+#endif /* !BROKEN_BUILTIN_APPLY */
+
+/* If the RETTYPE is a structure and the address of the structure value is
+   passed to the called function, then obtain from ARGS its address. In general
+   this address is the second pointer into the arguments frame. However on
+   linux this address is passed as the first argument to the called function.
+   This macro should produce 0 if the RETTYPE doesn't match the conditions
+   above. */
+
+#define GET_STRUCT_VALUE_ADDRESS(ARGS, RETTYPE) \
+    ((*(RETTYPE) == _C_STRUCT_B || *(RETTYPE) == _C_UNION_B \
+           || *(RETTYPE) == _C_ARY_B) ? \
+         **(void***)(ARGS) \
+       : 0)
+
+/* Prepare ARGS for calling the function. If the function returns a struct by
+   value, it's the caller responsability to pass to the called function the
+   address of where to store the structure value. */
+
+#define SET_STRUCT_VALUE_ADDRESS(ARGS, ADDR, RETTYPE) \
+    if(*(RETTYPE) == _C_STRUCT_B || *(RETTYPE) == _C_UNION_B \
+           || *(RETTYPE) == _C_ARY_B) \
+       **(void***)(ARGS) = (ADDR);
+
+#endif /* __linux_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/config/i386/mingw32.h b/libFoundation/config/i386/mingw32.h
new file mode 100644 (file)
index 0000000..d54ec4d
--- /dev/null
@@ -0,0 +1,150 @@
+/* 
+   mingw32.h (this is a copy of cygwin32.h, Helge)
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __mingw32_h__
+#define __mingw32_h__
+
+#include "i386.h"
+
+#undef FUNCTION_VALUE
+#undef FUNCTION_SET_VALUE
+#undef GET_STRUCT_VALUE_ADDRESS
+#undef SET_STRUCT_VALUE_ADDRESS
+
+/* Define how to find the value returned by a function. TYPE is a Objective-C
+   encoding string describing the type of the returned value. ARGS is the
+   arguments frame passed to __builtin_apply. RESULT_FRAME is the address of
+   the block returned by __builtin_apply. RETURN_VALUE is an address where
+   this macro should put the returned value. */
+
+#if 0 && defined(BROKEN_BUILTIN_APPLY)
+
+#define FUNCTION_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({ int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) { \
+           float aFloat; \
+           asm("fsts %0" : "=f2" (aFloat) :); \
+           *(float*)(RETURN_VALUE) = aFloat; \
+       } \
+       else if(*(TYPE) == _C_DBL) { \
+           double aDouble; \
+           asm("fstl %0" : "=f2" (aDouble)); \
+           *(double*)(RETURN_VALUE) = aDouble; \
+       } \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy((RETURN_VALUE), *(void**)(RESULT_FRAME), type_size); \
+       else memcpy((RETURN_VALUE), (RESULT_FRAME), type_size); })
+
+#else /* !BROKEN_BUILTIN_APPLY */
+
+#define FUNCTION_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({ int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) { \
+           *(float*)(RETURN_VALUE) = \
+               (float)*(long double*)(((char*)(RESULT_FRAME)) + 8); \
+           printf("float value result = %f\n", *(float*)(RETURN_VALUE)); \
+       } \
+       else if(*(TYPE) == _C_DBL) { \
+           *(double*)(RETURN_VALUE) = \
+               (double)*(long double*)(((char*)(RESULT_FRAME)) + 8); \
+           printf("double value result = %f\n", *(double*)(RETURN_VALUE)); \
+       } \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy((RETURN_VALUE), *(void**)(RESULT_FRAME), type_size); \
+       else memcpy((RETURN_VALUE), (RESULT_FRAME), type_size); })
+
+#endif /* !BROKEN_BUILTIN_APPLY */
+
+/* Set the value in RETURN_VALUE to be the value returned by a function.
+   Assume that the fucntion was previously called and RESULT_FRAME is the
+   address of the block returned by __builtin_apply. TYPE is the actual
+   type of this value. ARGS is the address of block that was passed
+   to __builtin_apply. */
+
+#if 0 && defined(BROKEN_BUILTIN_APPLY)
+
+#define FUNCTION_SET_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({  int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) { \
+           float aFloat = *(float*)(RETURN_VALUE); \
+           asm("fld %0" : : "f" (aFloat)); \
+       } \
+       else if(*(TYPE) == _C_DBL) { \
+           double aDouble = *(double*)(RETURN_VALUE); \
+           asm("fldl %0" : : "f" (aDouble)); \
+       } \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy(*(void**)(ARGS), (RETURN_VALUE), type_size); \
+       else memcpy((RESULT_FRAME), (RETURN_VALUE), type_size); })
+
+#else /* !BROKEN_BUILTIN_APPLY */
+
+#define FUNCTION_SET_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({  int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) \
+           *(long double*)(((char*)(RESULT_FRAME)) + 8) = \
+               (long double)*(float*)(RETURN_VALUE); \
+       else if(*(TYPE) == _C_DBL) \
+           *(long double*)(((char*)(RESULT_FRAME)) + 8) = \
+               (long double)*(double*)(RETURN_VALUE); \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy(*(void**)(ARGS), (RETURN_VALUE), type_size); \
+       else memcpy((RESULT_FRAME), (RETURN_VALUE), type_size); })
+
+#endif /* !BROKEN_BUILTIN_APPLY */
+
+/* If the RETTYPE is a structure and the address of the structure value is
+   passed to the called function, then obtain from ARGS its address. In general
+   this address is the second pointer into the arguments frame. However on
+   cygwin32 this address is passed as the first argument to the called function.
+   This macro should produce 0 if the RETTYPE doesn't match the conditions
+   above. */
+
+#define GET_STRUCT_VALUE_ADDRESS(ARGS, RETTYPE) \
+    ((*(RETTYPE) == _C_STRUCT_B || *(RETTYPE) == _C_UNION_B \
+           || *(RETTYPE) == _C_ARY_B) ? \
+         **(void***)(ARGS) \
+       : 0)
+
+/* Prepare ARGS for calling the function. If the function returns a struct by
+   value, it's the caller responsability to pass to the called function the
+   address of where to store the structure value. */
+
+#define SET_STRUCT_VALUE_ADDRESS(ARGS, ADDR, RETTYPE) \
+    if(*(RETTYPE) == _C_STRUCT_B || *(RETTYPE) == _C_UNION_B \
+           || *(RETTYPE) == _C_ARY_B) \
+       **(void***)(ARGS) = (ADDR);
+
+#endif /* __mingw32_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/config/i386/nextstep3.h b/libFoundation/config/i386/nextstep3.h
new file mode 100644 (file)
index 0000000..df35fa6
--- /dev/null
@@ -0,0 +1,157 @@
+/* 
+   nextstep3.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __nextstep3_h__
+#define __nextstep3_h__
+
+/* From gcc/config/i386/next.h:
+  `This accounts for the return pc and saved fp on the i386.' */
+#define OBJC_FORWARDING_STACK_OFFSET   8
+#define OBJC_FORWARDING_MIN_OFFSET 8
+
+#include "i386.h"
+
+#undef FUNCTION_VALUE
+#undef FUNCTION_SET_VALUE
+#undef GET_STRUCT_VALUE_ADDRESS
+#undef SET_STRUCT_VALUE_ADDRESS
+
+
+/* Define how to find the value returned by a function. TYPE is a Objective-C
+   encoding string describing the type of the returned value. ARGS is the
+   arguments frame passed to __builtin_apply. RESULT_FRAME is the address of
+   the block returned by __builtin_apply. RETURN_VALUE is an address where
+   this macro should put the returned value. */
+
+#ifdef BROKEN_BUILTIN_APPLY
+
+#define FUNCTION_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({ int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) { \
+           float aFloat; \
+           asm("fsts %0" : "=f2" (aFloat) :); \
+           *(float*)(RETURN_VALUE) = aFloat; \
+       } \
+       else if(*(TYPE) == _C_DBL) { \
+           double aDouble; \
+           asm("fstl %0" : "=f2" (aDouble)); \
+           *(double*)(RETURN_VALUE) = aDouble; \
+       } \
+       else if((*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) && type_size > 8)\
+           memcpy((RETURN_VALUE), \
+                  *(void**)(((char*)(ARGS)) + sizeof(void*)), type_size); \
+       else memcpy((RETURN_VALUE), (RESULT_FRAME), type_size); })
+
+#else /* !BROKEN_BUILTIN_APPLY */
+
+#define FUNCTION_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({ int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) { \
+           *(float*)(RETURN_VALUE) = \
+               (float)*(long double*)(((char*)(RESULT_FRAME)) + 8); \
+           printf("float value result = %f\n", *(float*)(RETURN_VALUE)); \
+       } \
+       else if(*(TYPE) == _C_DBL) { \
+           *(double*)(RETURN_VALUE) = \
+               (double)*(long double*)(((char*)(RESULT_FRAME)) + 8); \
+           printf("double value result = %f\n", *(double*)(RETURN_VALUE)); \
+       } \
+       else if((*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) && type_size > 8) \
+           memcpy((RETURN_VALUE), \
+                  *(void**)(((char*)(ARGS)) + sizeof(void*)), type_size); \
+       else memcpy((RETURN_VALUE), (RESULT_FRAME), type_size); })
+
+#endif /* !BROKEN_BUILTIN_APPLY */
+
+/* Set the value in RETURN_VALUE to be the value returned by a function.
+   Assume that the fucntion was previously called and RESULT_FRAME is the
+   address of the block returned by __builtin_apply. TYPE is the actual
+   type of this value. ARGS is the address of block that was passed
+   to __builtin_apply. */
+
+#ifdef BROKEN_BUILTIN_APPLY
+
+#define FUNCTION_SET_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({  int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) { \
+           float aFloat = *(float*)(RETURN_VALUE); \
+           asm("fld %0" : : "f" (aFloat)); \
+       } \
+       else if(*(TYPE) == _C_DBL) { \
+           double aDouble = *(double*)(RETURN_VALUE); \
+           asm("fldl %0" : : "f" (aDouble)); \
+       } \
+       else if((*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) && type_size > 8)\
+           memcpy(*(void**)(((char*)(ARGS)) + sizeof(void*)), \
+                  (RETURN_VALUE), type_size); \
+       else memcpy((RESULT_FRAME), (RETURN_VALUE), type_size); })
+
+#else /* !BROKEN_BUILTIN_APPLY */
+
+#define FUNCTION_SET_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({  int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) \
+           *(long double*)(((char*)(RESULT_FRAME)) + 8) = \
+               (long double)*(float*)(RETURN_VALUE); \
+       else if(*(TYPE) == _C_DBL) \
+           *(long double*)(((char*)(RESULT_FRAME)) + 8) = \
+               (long double)*(double*)(RETURN_VALUE); \
+       else if((*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) && type_size > 8)\
+           memcpy(*(void**)(((char*)(ARGS)) + sizeof(void*)), \
+                  (RETURN_VALUE), type_size); \
+       else memcpy((RESULT_FRAME), (RETURN_VALUE), type_size); })
+
+#endif /* !BROKEN_BUILTIN_APPLY */
+
+/* If the RETTYPE is a structure and the address of the structure value is
+   passed to the called function, then obtain from ARGS its address. In general
+   this address is the second pointer into the arguments frame. This macro
+   should produce 0 if the RETTYPE doesn't match the conditions above. */
+
+#define GET_STRUCT_VALUE_ADDRESS(ARGS, RETTYPE) \
+    (((*(RETTYPE) == _C_STRUCT_B || *(RETTYPE) == _C_UNION_B \
+           || *(RETTYPE) == _C_ARY_B) && objc_sizeof_type(RETTYPE) > 8) ? \
+         *(void**)(((char*)(ARGS)) + sizeof(void*)) \
+       : 0)
+
+/* Prepare ARGS for calling the function. If the function returns a struct by
+   value, it's the caller responsability to pass to the called function the
+   address of where to store the structure value. */
+
+#define SET_STRUCT_VALUE_ADDRESS(ARGS, ADDR, RETTYPE) \
+    *(void**)(((char*)(ARGS)) + sizeof(void*)) = (ADDR)
+
+
+#endif /* __nextstep3_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/config/i386/nextstep4.h b/libFoundation/config/i386/nextstep4.h
new file mode 100644 (file)
index 0000000..7f6804c
--- /dev/null
@@ -0,0 +1,8 @@
+#include "nextstep3.h"
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/config/i386/openbsd3.7.h b/libFoundation/config/i386/openbsd3.7.h
new file mode 100644 (file)
index 0000000..3c542be
--- /dev/null
@@ -0,0 +1,37 @@
+/* 
+   openbsd3.7.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __openbsd3_7_h__
+#define __openbsd3_7_h__
+
+#include "linux.h"
+
+#endif /* __openbsd3_7_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/config/i386/solaris2.5.1.h b/libFoundation/config/i386/solaris2.5.1.h
new file mode 100644 (file)
index 0000000..eb5c5dc
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+   solaris2.5.1.h
+
+   Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@net-community.com>
+   Date: August 1997
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __solaris2_5_1_h__
+#define __solaris2_5_1_h__
+
+#include "i386.h"
+
+#undef FUNCTION_VALUE
+#undef FUNCTION_SET_VALUE
+#undef GET_STRUCT_VALUE_ADDRESS
+#undef SET_STRUCT_VALUE_ADDRESS
+
+/* Define how to find the value returned by a function. TYPE is a Objective-C
+   encoding string describing the type of the returned value. ARGS is the
+   arguments frame passed to __builtin_apply. RESULT_FRAME is the address of
+   the block returned by __builtin_apply. RETURN_VALUE is an address where
+   this macro should put the returned value. */
+
+#define FUNCTION_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({ int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) { \
+           *(float*)(RETURN_VALUE) = \
+               (float)*(long double*)(((char*)(RESULT_FRAME)) + 8); \
+           printf("float value result = %f\n", *(float*)(RETURN_VALUE)); \
+       } \
+       else if(*(TYPE) == _C_DBL) { \
+           *(double*)(RETURN_VALUE) = \
+               (double)*(long double*)(((char*)(RESULT_FRAME)) + 8); \
+           printf("double value result = %f\n", *(double*)(RETURN_VALUE)); \
+       } \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy((RETURN_VALUE), *(void**)(RESULT_FRAME), type_size); \
+       else memcpy((RETURN_VALUE), (RESULT_FRAME), type_size); })
+
+/* Set the value in RETURN_VALUE to be the value returned by a function.
+   Assume that the fucntion was previously called and RESULT_FRAME is the
+   address of the block returned by __builtin_apply. TYPE is the actual
+   type of this value. ARGS is the address of block that was passed
+   to __builtin_apply. */
+
+#define FUNCTION_SET_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({  int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) \
+           *(long double*)(((char*)(RESULT_FRAME)) + 8) = \
+               (long double)*(float*)(RETURN_VALUE); \
+       else if(*(TYPE) == _C_DBL) \
+           *(long double*)(((char*)(RESULT_FRAME)) + 8) = \
+               (long double)*(double*)(RETURN_VALUE); \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy(*(void**)(ARGS), (RETURN_VALUE), type_size); \
+       else memcpy((RESULT_FRAME), (RETURN_VALUE), type_size); })
+
+/* If the RETTYPE is a structure and the address of the structure value is
+   passed to the called function, then obtain from ARGS its address. In general
+   this address is the second pointer into the arguments frame. However on
+   linux this address is passed as the first argument to the called function.
+   This macro should produce 0 if the RETTYPE doesn't match the conditions
+   above. */
+
+#define GET_STRUCT_VALUE_ADDRESS(ARGS, RETTYPE) \
+    ((*(RETTYPE) == _C_STRUCT_B || *(RETTYPE) == _C_UNION_B \
+           || *(RETTYPE) == _C_ARY_B) ? \
+         **(void***)(ARGS) \
+       : 0)
+
+/* Prepare ARGS for calling the function. If the function returns a struct by
+   value, it's the caller responsability to pass to the called function the
+   address of where to store the structure value. */
+
+#define SET_STRUCT_VALUE_ADDRESS(ARGS, ADDR, RETTYPE) \
+    if(*(RETTYPE) == _C_STRUCT_B || *(RETTYPE) == _C_UNION_B \
+           || *(RETTYPE) == _C_ARY_B) \
+       **(void***)(ARGS) = (ADDR);
+
+#endif /* __solaris2_5_1_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/config/i386/solaris2.9.h b/libFoundation/config/i386/solaris2.9.h
new file mode 100644 (file)
index 0000000..fbd338b
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+   solaris2.9.h
+
+   Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@net-community.com>
+   Date: August 1997
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __solaris2_9_h__
+#define __solaris2_9_h__
+
+#include "i386.h"
+
+#undef FUNCTION_VALUE
+#undef FUNCTION_SET_VALUE
+#undef GET_STRUCT_VALUE_ADDRESS
+#undef SET_STRUCT_VALUE_ADDRESS
+
+/* Define how to find the value returned by a function. TYPE is a Objective-C
+   encoding string describing the type of the returned value. ARGS is the
+   arguments frame passed to __builtin_apply. RESULT_FRAME is the address of
+   the block returned by __builtin_apply. RETURN_VALUE is an address where
+   this macro should put the returned value. */
+
+#define FUNCTION_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({ int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) { \
+           *(float*)(RETURN_VALUE) = \
+               (float)*(long double*)(((char*)(RESULT_FRAME)) + 8); \
+           printf("float value result = %f\n", *(float*)(RETURN_VALUE)); \
+       } \
+       else if(*(TYPE) == _C_DBL) { \
+           *(double*)(RETURN_VALUE) = \
+               (double)*(long double*)(((char*)(RESULT_FRAME)) + 8); \
+           printf("double value result = %f\n", *(double*)(RETURN_VALUE)); \
+       } \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy((RETURN_VALUE), *(void**)(RESULT_FRAME), type_size); \
+       else memcpy((RETURN_VALUE), (RESULT_FRAME), type_size); })
+
+/* Set the value in RETURN_VALUE to be the value returned by a function.
+   Assume that the fucntion was previously called and RESULT_FRAME is the
+   address of the block returned by __builtin_apply. TYPE is the actual
+   type of this value. ARGS is the address of block that was passed
+   to __builtin_apply. */
+
+#define FUNCTION_SET_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({  int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) \
+           *(long double*)(((char*)(RESULT_FRAME)) + 8) = \
+               (long double)*(float*)(RETURN_VALUE); \
+       else if(*(TYPE) == _C_DBL) \
+           *(long double*)(((char*)(RESULT_FRAME)) + 8) = \
+               (long double)*(double*)(RETURN_VALUE); \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy(*(void**)(ARGS), (RETURN_VALUE), type_size); \
+       else memcpy((RESULT_FRAME), (RETURN_VALUE), type_size); })
+
+/* If the RETTYPE is a structure and the address of the structure value is
+   passed to the called function, then obtain from ARGS its address. In general
+   this address is the second pointer into the arguments frame. However on
+   linux this address is passed as the first argument to the called function.
+   This macro should produce 0 if the RETTYPE doesn't match the conditions
+   above. */
+
+#define GET_STRUCT_VALUE_ADDRESS(ARGS, RETTYPE) \
+    ((*(RETTYPE) == _C_STRUCT_B || *(RETTYPE) == _C_UNION_B \
+           || *(RETTYPE) == _C_ARY_B) ? \
+         **(void***)(ARGS) \
+       : 0)
+
+/* Prepare ARGS for calling the function. If the function returns a struct by
+   value, it's the caller responsability to pass to the called function the
+   address of where to store the structure value. */
+
+#define SET_STRUCT_VALUE_ADDRESS(ARGS, ADDR, RETTYPE) \
+    if(*(RETTYPE) == _C_STRUCT_B || *(RETTYPE) == _C_UNION_B \
+           || *(RETTYPE) == _C_ARY_B) \
+       **(void***)(ARGS) = (ADDR);
+
+#endif /* __solaris2_9_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/config/m68k/m68k.h b/libFoundation/config/m68k/m68k.h
new file mode 100644 (file)
index 0000000..6d08588
--- /dev/null
@@ -0,0 +1,191 @@
+/* 
+   m68k.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __m68k_h__
+#define __m68k_h__
+
+#ifndef OBJC_FORWARDING_STACK_OFFSET
+#define OBJC_FORWARDING_STACK_OFFSET   0
+#endif
+
+#ifndef OBJC_FORWARDING_MIN_OFFSET
+#define OBJC_FORWARDING_MIN_OFFSET 0
+#endif
+
+/* Define the size of the block returned by __builtin_apply_args. This value is
+   computed by the function in expr.c. The block contains in order: a pointer
+   to the stack arguments frame, the structure value address unless this is
+   passed as an "invisible" first argument and all registers that may be used
+   in calling a function. */
+
+#define APPLY_ARGS_SIZE        8
+
+/* Define the size of the result block returned by the __builtin_apply. This
+   block contains all registers that could be used to return the function
+   value. This value is computed by apply_result_size function in expr.c. There
+   are also machines where this value is predefined in the machine description
+   file, so that machine specific information can be stored. */
+
+#define APPLY_RESULT_SIZE      8
+
+/* Define how to find the value returned by a function. TYPE is a Objective-C
+   encoding string describing the type of the returned value. ARGS is the
+   arguments frame passed to __builtin_apply. RESULT is the address of the
+   block returned by __builtin_apply. RETURN_VALUE is an address where this
+   macro should put the returned value. */
+
+#define FUNCTION_VALUE(TYPE, ARGS, RESULT, RETURN_VALUE) \
+    ({ int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B || *(TYPE) == _C_ARY_B) {\
+           if(type_size > 4 && type_size != 7 && type_size != 8) { \
+               /*void** p = *(void**)(((char*)(ARGS)) + sizeof(void*));*/ \
+               memcpy((RETURN_VALUE), \
+                       *(void**)(((char*)(ARGS)) + sizeof(void*)), type_size); \
+               /*printf("result1 = %p %p\n", *p, *(p + 1)); */\
+           } \
+           else if(type_size <= sizeof(void*)) {\
+               memcpy((RETURN_VALUE), \
+                       ((char*)(RESULT)) + sizeof(void*) - type_size - (type_size % 2), type_size); \
+               /*printf("result2 = %p\n", *(char**)(RESULT));*/ \
+           } \
+           else { \
+               memcpy((RETURN_VALUE), (RESULT), type_size); \
+               /*printf("result3 = %p %p\n", *(char**)(RESULT), *((char**)(RESULT) + 1));*/ \
+           } \
+       } \
+       else if(type_size <= sizeof(void*)) {\
+           memcpy((RETURN_VALUE), \
+                   ((char*)(RESULT)) + sizeof(void*) - type_size, type_size); \
+           /*printf("result2 = %p\n", *(char**)(RESULT));*/ \
+       } \
+       else { \
+           memcpy((RETURN_VALUE), (RESULT), type_size); \
+           /*printf("result3 = %p %p\n", *(char**)(RESULT), *((char**)(RESULT) + 1));*/ \
+       } \
+       })
+
+/* Set the value in RETURN_VALUE to be the value returned by a function.
+   Assume that the fucntion was previously called and RESULT_FRAME is the
+   address of the block returned by __builtin_apply. TYPE is the actual
+   type of this value. ARGS is the address of block that was passed
+   to __builtin_apply. */
+
+#define FUNCTION_SET_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({ int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B || *(TYPE) == _C_ARY_B) {\
+           if(type_size > 4 && type_size != 7 && type_size != 8) \
+               memcpy(*(void**)(((char*)(ARGS)) + sizeof(void*)), \
+                       (RETURN_VALUE), type_size); \
+           else if(type_size <= sizeof(void*)) {\
+               memcpy(((char*)(RESULT_FRAME)) + sizeof(void*) - type_size - (type_size % 2), \
+                       (RETURN_VALUE), type_size); \
+           } \
+           else { \
+               memcpy((RESULT_FRAME), (RETURN_VALUE), type_size); \
+           } \
+       } \
+       else if(type_size <= sizeof(void*)) \
+           memcpy(((char*)(RESULT_FRAME)) + sizeof(void*) - type_size, \
+                  (RETURN_VALUE), type_size); \
+       else memcpy((RESULT_FRAME), (RETURN_VALUE), type_size); })
+
+/* If the RETTYPE is a structure and the address of the structure value is
+   passed to the called function, then obtain from ARGS its address. In general
+   this address is the second pointer into the arguments frame. This macro
+   should produce 0 if the RETTYPE doesn't match the conditions above. */
+
+#define GET_STRUCT_VALUE_ADDRESS(ARGS, RETTYPE) \
+    ({ int type_size = objc_sizeof_type(RETTYPE); \
+       ((*(RETTYPE) == _C_STRUCT_B || *(RETTYPE) == _C_UNION_B || *(RETTYPE) == _C_ARY_B) \
+               && type_size > 4 && type_size != 7 && type_size != 8) ? \
+           *(void**)(((char*)(ARGS)) + sizeof(void*)) \
+       : 0; })
+
+/* Prepare ARGS for calling the function. If the function returns a struct by
+   value, it's the caller responsability to pass to the called function the
+   address of where to store the structure value. */
+
+#define SET_STRUCT_VALUE_ADDRESS(ARGS, ADDR, RETTYPE) \
+    *(void**)(((char*)(ARGS)) + sizeof(void*)) = (ADDR)
+
+
+/* The following macros are used to determine the encoding of a selector given
+   the types of arguments. This macros follows the similar ones defined in the
+   target machine description from the compiler sources. */
+
+/* Define a data type for recording info about the arguments list of a method.
+   A variable of this type is further used by FUNCTION_ARG_ENCODING to
+   determine the encoding of an argument. This type should record all info
+   about arguments processed so far. */
+
+#define CUMULATIVE_ARGS int
+
+/* Initialize a variable of type CUMULATIVE_ARGS. This macro is called before
+   processing the first argument of a method. */
+
+#define INIT_CUMULATIVE_ARGS(CUM)      ((CUM) = 0)
+
+/* This macro determines the encoding of the next argument of a method. It is
+   called repetitively, starting with the first argument and continuing to the
+   last one. CUM is a variable of type CUMULATIVE_ARGS. TYPE is a NSString
+   which represents the type of the argument processed. This macro must
+   produce a NSString whose value represents the encoding and position of the
+   current argument. STACKSIZE is a variable that counts the number of bytes
+   occupied by the arguments on the stack. */
+
+#ifndef ROUND
+#define ROUND(V, A) \
+  ({ typeof(V) __v=(V); typeof(A) __a=(A); \
+     __a*((__v+__a-1)/__a); })
+#endif
+
+#define FUNCTION_ARG_ENCODING(CUM, TYPE, STACK_ARGSIZE) \
+    ({  id encoding; \
+       const char* type = [(TYPE) cString]; \
+       int align = objc_alignof_type(type); \
+       int type_size = objc_sizeof_type(type); \
+\
+       (CUM) = ROUND((CUM), align); \
+       if(type_size < sizeof(int)) \
+           (CUM) += sizeof(int) - ROUND(type_size, align); \
+       encoding = [NSString stringWithFormat:@"%@%d", \
+                                   (TYPE), \
+                                   (CUM) + OBJC_FORWARDING_STACK_OFFSET]; \
+       if((*type == _C_STRUCT_B || *type == _C_UNION_B || *type == _C_ARY_B) \
+               && type_size > 2) \
+           (STACK_ARGSIZE) = (CUM) + ROUND(type_size, align); \
+       else (STACK_ARGSIZE) = (CUM) + ROUND(type_size, align); \
+       (CUM) += type_size < sizeof(int) \
+               ? ROUND(type_size, align) \
+               : ROUND(type_size, sizeof(void*)); \
+       encoding; })
+
+#endif /* __m68k_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/config/m68k/nextstep3.h b/libFoundation/config/m68k/nextstep3.h
new file mode 100644 (file)
index 0000000..9586aa8
--- /dev/null
@@ -0,0 +1,42 @@
+/* 
+   nextstep3.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __nextstep3_h__
+#define __nextstep3_h__
+
+/* From gcc/config/m68k/next.h:
+  `This accounts for the return pc and saved fp on the m68k.' */
+#define OBJC_FORWARDING_STACK_OFFSET   8
+#define OBJC_FORWARDING_MIN_OFFSET 8
+
+#include "m68k.h"
+
+#endif /* __nextstep3_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/config/powerpc/powerpc.h b/libFoundation/config/powerpc/powerpc.h
new file mode 100644 (file)
index 0000000..d6257c6
--- /dev/null
@@ -0,0 +1,265 @@
+/* 
+   powerpc.h
+
+   Copyright (C) 1998 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@aracnet.com>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __powerpc_h__
+#define __powerpc_h__
+
+#ifndef OBJC_FORWARDING_STACK_OFFSET
+#define OBJC_FORWARDING_STACK_OFFSET   0
+#endif
+
+#ifndef OBJC_FORWARDING_MIN_OFFSET
+#define OBJC_FORWARDING_MIN_OFFSET 0
+#endif
+
+/* Define the size of the block returned by __builtin_apply_args. This value is
+   computed by the function in expr.c. The block contains in order: a pointer
+   to the stack arguments frame, the structure value address unless this is
+   passed as an "invisible" first argument and all registers that may be used
+   in calling a function. */
+
+#define APPLY_ARGS_SIZE        144
+
+/* Define the size of the result block returned by the __builtin_apply. This
+   block contains all registers that could be used to return the function
+   value. This value is computed by apply_result_size function in expr.c. There
+   are also machines where this value is predefined in the machine description
+   file, so that machine specific information can be stored. */
+
+#define APPLY_RESULT_SIZE      16
+
+/* Define how to access the arguments' frame in order to set an argument.
+   FRAME_DATA is the address in the frame where the argument has to be set.
+   ARGUMENT_LOCATION is the address of the argument that has to be set.
+   ARG_INFO is an NSArgumentInfo that describes the argument. */
+
+#define FRAME_SET_ARGUMENT(FRAME_DATA, ARGUMENT_LOCATION, ARG_INFO) \
+    ({ if ((ARG_INFO).size < sizeof(void*)) \
+           memcpy(((char*)(FRAME_DATA)) + sizeof(void*) - (ARG_INFO).size, \
+                  (ARGUMENT_LOCATION), \
+                  (ARG_INFO).size); \
+       else if (*(ARG_INFO).type == _C_FLT) \
+           *(double*)(FRAME_DATA) = (double)*(float*)(ARGUMENT_LOCATION); \
+       else memcpy((FRAME_DATA), (ARGUMENT_LOCATION), (ARG_INFO).size); \
+    })
+
+/* Define how to access the arguments' frame in order to get an argument.
+   FRAME_DATA is the address in the frame where the argument has to be get
+   from.
+   ARGUMENT_LOCATION is the address of the argument where the value has to
+   be set.
+   ARG_INFO is an NSArgumentInfo that describes the argument. */
+
+#define FRAME_GET_ARGUMENT(FRAME_DATA, ARGUMENT_LOCATION, ARG_INFO) \
+     ({ if ((ARG_INFO).size < sizeof(void*)) \
+           memcpy((ARGUMENT_LOCATION), \
+                  ((char*)(FRAME_DATA)) + sizeof(void*) - (ARG_INFO).size, \
+                  (ARG_INFO).size); \
+       else if (*(ARG_INFO).type == _C_FLT) \
+           *(float*)(ARGUMENT_LOCATION) = (float)*(double*)(FRAME_DATA); \
+       else memcpy((ARGUMENT_LOCATION), (FRAME_DATA), (ARG_INFO).size); \
+    })
+
+
+/* Define how to find the value returned by a function. TYPE is a Objective-C
+   encoding string describing the type of the returned value. ARGS is the
+   arguments frame passed to __builtin_apply. RESULT_FRAME is the address of
+   the block returned by __builtin_apply. RETURN_VALUE is an address where
+   this macro should put the returned value. */
+
+#define FUNCTION_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({ int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) { \
+           *(float*)(RETURN_VALUE) \
+                = (float)*(double*)(((char*)(RESULT_FRAME)) + 8); \
+       } \
+       else if(*(TYPE) == _C_DBL) { \
+           *(double*)(RETURN_VALUE) \
+                = *(double*)(((char*)(RESULT_FRAME)) + 8); \
+       } \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy((RETURN_VALUE), \
+                  *(void**)(((char*)(ARGS)) + sizeof(void*)), type_size); \
+       else if(type_size <= sizeof(void*)) \
+           memcpy((RETURN_VALUE), \
+                  ((char*)(RESULT_FRAME)) + sizeof(void*) - type_size, \
+                   type_size); \
+         else memcpy((RETURN_VALUE), (RESULT_FRAME), type_size); })
+
+
+/* Set the value in RETURN_VALUE to be the value returned by a function.
+   Assume that the fucntion was previously called and RESULT_FRAME is the
+   address of the block returned by __builtin_apply. TYPE is the actual
+   type of this value. ARGS is the address of block that was passed
+   to __builtin_apply. */
+
+#define FUNCTION_SET_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({  int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) \
+           *(double*)(((char*)(RESULT_FRAME)) + 8) = \
+               (double)*(float*)(RETURN_VALUE); \
+       else if(*(TYPE) == _C_DBL) \
+           *(double*)(((char*)(RESULT_FRAME)) + 8) = \
+               *(double*)(RETURN_VALUE); \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy(*(void**)(((char*)(ARGS)) + sizeof(void*)), \
+                  (RETURN_VALUE), type_size); \
+       else if(type_size <= sizeof(void*)) \
+           memcpy(((char*)(RESULT_FRAME)) + sizeof(void*) - type_size, \
+                   (RETURN_VALUE), \
+                   type_size); \
+       else memcpy((RESULT_FRAME), (RETURN_VALUE), type_size); })
+
+
+/* If the RETTYPE is a structure and the address of the structure value is
+   passed to the called function, then obtain from ARGS its address. In general
+   this address is the second pointer into the arguments frame. This macro
+   should produce 0 if the RETTYPE doesn't match the conditions above. */
+
+#define GET_STRUCT_VALUE_ADDRESS(ARGS, RETTYPE) \
+    ((*(RETTYPE) == _C_STRUCT_B || *(RETTYPE) == _C_UNION_B \
+           || *(RETTYPE) == _C_ARY_B) ? \
+         *(void**)(((char*)(ARGS)) + sizeof(void*)) \
+       : 0)
+
+/* Prepare ARGS for calling the function. If the function returns a struct by
+   value, it's the caller responsability to pass to the called function the
+   address of where to store the structure value. */
+
+#define SET_STRUCT_VALUE_ADDRESS(ARGS, ADDR, RETTYPE) \
+    *(void**)(((char*)(ARGS)) + sizeof(void*)) = (ADDR)
+
+
+/* The following macros are used to determine the encoding of a selector given
+   the types of arguments. This macros follows the similar ones defined in the
+   target machine description from the compiler sources. */
+
+/* Define a data type for recording info about the arguments list of a method.
+   A variable of this type is further used by FUNCTION_ARG_ENCODING to
+   determine the encoding of an argument. This type should record all info
+   about arguments processed so far. */
+
+/* On RS/6000 the first eight words of non-FP are normally in
+   registers and the rest are pushed.  The first 13 FP args are in
+   registers. */
+
+typedef struct rs6000_args 
+{
+    int int_args;       /* Number of integer arguments so far */
+    int float_args;     /* Number of float arguments so far */
+    int int_regs_position;  /* The current position for integers in
+                               the register's frame */
+    int stack_position; /* The current position in the stack frame */
+} CUMULATIVE_ARGS;
+
+
+/* Initialize a variable of type CUMULATIVE_ARGS. This macro is called before
+   processing the first argument of a method. */
+
+#define INIT_CUMULATIVE_ARGS(CUM) \
+    ({ (CUM).int_args = 0; \
+       (CUM).float_args = 0; \
+       (CUM).int_regs_position = 4; \
+       (CUM).stack_position = 0; \
+    })
+
+/* This macro determines the encoding of the next argument of a method. It is
+   called repetitively, starting with the first argument and continuing to the
+   last one. CUM is a variable of type CUMULATIVE_ARGS. TYPE is a NSString
+   which represents the type of the argument processed. This macro must
+   produce a NSString whose value represents the encoding and position of the
+   current argument. STACKSIZE is a variable that counts the number of bytes
+   occupied by the arguments on the stack. */
+
+#ifndef ROUND
+#define ROUND(V, A) \
+  ({ typeof(V) __v=(V); typeof(A) __a=(A); \
+     __a*((__v+__a-1)/__a); })
+#endif
+
+
+#define FUNCTION_ARG_ENCODING(CUM, TYPE, STACK_ARGSIZE) \
+({  id encoding; \
+    const char* type = [(TYPE) cString]; \
+\
+    if (*type == _C_FLT || *type == _C_DBL) { \
+        if (++(CUM).float_args > 13) { \
+            /* Place the argument on stack. Floats are pushed as doubles. */ \
+            (CUM).stack_position += ROUND ((CUM).stack_position, \
+                                           __alignof__(double)); \
+            encoding = [NSString stringWithFormat:@"%s%d", type, \
+                         (CUM).stack_position + OBJC_FORWARDING_MIN_OFFSET]; \
+            (STACK_ARGSIZE) = ROUND ((CUM).stack_position, sizeof(double)); \
+        } \
+        else { \
+            /* Place the argument on register's frame. Floats are \
+               pushed as doubles. The register's frame for floats and \
+               doubles starts at index 40. */ \
+            int offset = 40 + sizeof (double) * ((CUM).float_args - 1); \
+            encoding = [NSString stringWithFormat:@"%s+%d", type, offset]; \
+            (CUM).int_regs_position += ROUND (objc_sizeof_type(type), \
+                                              objc_alignof_type(type)); \
+        } \
+    } \
+    else { \
+        int align, size; \
+\
+        if (*type == _C_STRUCT_B || *type == _C_UNION_B \
+            || *type == _C_ARY_B) { \
+            align = __alignof__(type); \
+            size = objc_sizeof_type (type); \
+        } \
+        else { \
+            align = __alignof__(int); \
+            size = objc_sizeof_type (type); \
+        } \
+\
+        if (++(CUM).int_args > 8) { \
+            /* We have a type to place on the stack */ \
+            (CUM).stack_position += ROUND ((CUM).stack_position, align); \
+            encoding = [NSString stringWithFormat:@"%s%d", type, \
+                        (CUM).stack_position + OBJC_FORWARDING_MIN_OFFSET]; \
+            (STACK_ARGSIZE) = ROUND ((CUM).stack_position, size); \
+        } \
+        else { \
+            /* We have to place a value on the register's frame. The \
+               register's frame for references and integers starts at 4. */ \
+            (CUM).int_regs_position = ROUND((CUM).int_regs_position, align); \
+            encoding = [NSString stringWithFormat:@"%s+%d", type, \
+                                 (CUM).int_regs_position]; \
+            (CUM).int_regs_position += ROUND (size, align); \
+        } \
+    } \
+    encoding; })
+
+#endif /* __powerpc_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/config/powerpc64/gnu.h b/libFoundation/config/powerpc64/gnu.h
new file mode 100644 (file)
index 0000000..b07983a
--- /dev/null
@@ -0,0 +1,37 @@
+/* 
+   linux_gnu.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __gnu_h__
+#define __gnu_h__
+
+#include "linux.h"
+
+#endif /* __gnu_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/config/powerpc64/linux-gnu.h b/libFoundation/config/powerpc64/linux-gnu.h
new file mode 100644 (file)
index 0000000..ec5a214
--- /dev/null
@@ -0,0 +1,37 @@
+/* 
+   linux_gnu.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __linux_gnu_h__
+#define __linux_gnu_h__
+
+#include "linux.h"
+
+#endif /* __linux_gnu_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/config/powerpc64/linux.h b/libFoundation/config/powerpc64/linux.h
new file mode 100644 (file)
index 0000000..de4e0a5
--- /dev/null
@@ -0,0 +1,147 @@
+/* 
+   linux.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __linux_h__
+#define __linux_h__
+
+#include "i386.h"
+
+#undef FUNCTION_VALUE
+#undef FUNCTION_SET_VALUE
+#undef GET_STRUCT_VALUE_ADDRESS
+#undef SET_STRUCT_VALUE_ADDRESS
+
+/* Define how to find the value returned by a function. TYPE is a Objective-C
+   encoding string describing the type of the returned value. ARGS is the
+   arguments frame passed to __builtin_apply. RESULT_FRAME is the address of
+   the block returned by __builtin_apply. RETURN_VALUE is an address where
+   this macro should put the returned value. */
+
+#if 0 && defined(BROKEN_BUILTIN_APPLY)
+
+#define FUNCTION_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({ int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) { \
+           float aFloat; \
+           asm("fsts %0" : "=f2" (aFloat) :); \
+           *(float*)(RETURN_VALUE) = aFloat; \
+       } \
+       else if(*(TYPE) == _C_DBL) { \
+           double aDouble; \
+           asm("fstl %0" : "=f2" (aDouble)); \
+           *(double*)(RETURN_VALUE) = aDouble; \
+       } \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy((RETURN_VALUE), *(void**)(RESULT_FRAME), type_size); \
+       else memcpy((RETURN_VALUE), (RESULT_FRAME), type_size); })
+
+#else /* !BROKEN_BUILTIN_APPLY */
+
+#define FUNCTION_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({ int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) { \
+           *(float*)(RETURN_VALUE) = \
+               (float)*(long double*)(((char*)(RESULT_FRAME)) + 8); \
+       } \
+       else if(*(TYPE) == _C_DBL) { \
+           *(double*)(RETURN_VALUE) = \
+               (double)*(long double*)(((char*)(RESULT_FRAME)) + 8); \
+       } \
+       else if(*(TYPE) != _C_STRUCT_B && *(TYPE) != _C_UNION_B \
+               && *(TYPE) != _C_ARY_B) \
+           memcpy((RETURN_VALUE), (RESULT_FRAME), type_size); })
+
+#endif /* !BROKEN_BUILTIN_APPLY */
+
+/* Set the value in RETURN_VALUE to be the value returned by a function.
+   Assume that the fucntion was previously called and RESULT_FRAME is the
+   address of the block returned by __builtin_apply. TYPE is the actual
+   type of this value. ARGS is the address of block that was passed
+   to __builtin_apply. */
+
+#if 0 && defined(BROKEN_BUILTIN_APPLY)
+
+#define FUNCTION_SET_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({  int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) { \
+           float aFloat = *(float*)(RETURN_VALUE); \
+           asm("fld %0" : : "f" (aFloat)); \
+       } \
+       else if(*(TYPE) == _C_DBL) { \
+           double aDouble = *(double*)(RETURN_VALUE); \
+           asm("fldl %0" : : "f" (aDouble)); \
+       } \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy(*(void**)(ARGS), (RETURN_VALUE), type_size); \
+       else memcpy((RESULT_FRAME), (RETURN_VALUE), type_size); })
+
+#else /* !BROKEN_BUILTIN_APPLY */
+
+#define FUNCTION_SET_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({  int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) \
+           *(long double*)(((char*)(RESULT_FRAME)) + 8) = \
+               (long double)*(float*)(RETURN_VALUE); \
+       else if(*(TYPE) == _C_DBL) \
+           *(long double*)(((char*)(RESULT_FRAME)) + 8) = \
+               (long double)*(double*)(RETURN_VALUE); \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy(*(void**)(ARGS), (RETURN_VALUE), type_size); \
+       else memcpy((RESULT_FRAME), (RETURN_VALUE), type_size); })
+
+#endif /* !BROKEN_BUILTIN_APPLY */
+
+/* If the RETTYPE is a structure and the address of the structure value is
+   passed to the called function, then obtain from ARGS its address. In general
+   this address is the second pointer into the arguments frame. However on
+   linux this address is passed as the first argument to the called function.
+   This macro should produce 0 if the RETTYPE doesn't match the conditions
+   above. */
+
+#define GET_STRUCT_VALUE_ADDRESS(ARGS, RETTYPE) \
+    ((*(RETTYPE) == _C_STRUCT_B || *(RETTYPE) == _C_UNION_B \
+           || *(RETTYPE) == _C_ARY_B) ? \
+         **(void***)(ARGS) \
+       : 0)
+
+/* Prepare ARGS for calling the function. If the function returns a struct by
+   value, it's the caller responsability to pass to the called function the
+   address of where to store the structure value. */
+
+#define SET_STRUCT_VALUE_ADDRESS(ARGS, ADDR, RETTYPE) \
+    if(*(RETTYPE) == _C_STRUCT_B || *(RETTYPE) == _C_UNION_B \
+           || *(RETTYPE) == _C_ARY_B) \
+       **(void***)(ARGS) = (ADDR);
+
+#endif /* __linux_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/config/powerpc64/powerpc64.h b/libFoundation/config/powerpc64/powerpc64.h
new file mode 100644 (file)
index 0000000..d6257c6
--- /dev/null
@@ -0,0 +1,265 @@
+/* 
+   powerpc.h
+
+   Copyright (C) 1998 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@aracnet.com>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __powerpc_h__
+#define __powerpc_h__
+
+#ifndef OBJC_FORWARDING_STACK_OFFSET
+#define OBJC_FORWARDING_STACK_OFFSET   0
+#endif
+
+#ifndef OBJC_FORWARDING_MIN_OFFSET
+#define OBJC_FORWARDING_MIN_OFFSET 0
+#endif
+
+/* Define the size of the block returned by __builtin_apply_args. This value is
+   computed by the function in expr.c. The block contains in order: a pointer
+   to the stack arguments frame, the structure value address unless this is
+   passed as an "invisible" first argument and all registers that may be used
+   in calling a function. */
+
+#define APPLY_ARGS_SIZE        144
+
+/* Define the size of the result block returned by the __builtin_apply. This
+   block contains all registers that could be used to return the function
+   value. This value is computed by apply_result_size function in expr.c. There
+   are also machines where this value is predefined in the machine description
+   file, so that machine specific information can be stored. */
+
+#define APPLY_RESULT_SIZE      16
+
+/* Define how to access the arguments' frame in order to set an argument.
+   FRAME_DATA is the address in the frame where the argument has to be set.
+   ARGUMENT_LOCATION is the address of the argument that has to be set.
+   ARG_INFO is an NSArgumentInfo that describes the argument. */
+
+#define FRAME_SET_ARGUMENT(FRAME_DATA, ARGUMENT_LOCATION, ARG_INFO) \
+    ({ if ((ARG_INFO).size < sizeof(void*)) \
+           memcpy(((char*)(FRAME_DATA)) + sizeof(void*) - (ARG_INFO).size, \
+                  (ARGUMENT_LOCATION), \
+                  (ARG_INFO).size); \
+       else if (*(ARG_INFO).type == _C_FLT) \
+           *(double*)(FRAME_DATA) = (double)*(float*)(ARGUMENT_LOCATION); \
+       else memcpy((FRAME_DATA), (ARGUMENT_LOCATION), (ARG_INFO).size); \
+    })
+
+/* Define how to access the arguments' frame in order to get an argument.
+   FRAME_DATA is the address in the frame where the argument has to be get
+   from.
+   ARGUMENT_LOCATION is the address of the argument where the value has to
+   be set.
+   ARG_INFO is an NSArgumentInfo that describes the argument. */
+
+#define FRAME_GET_ARGUMENT(FRAME_DATA, ARGUMENT_LOCATION, ARG_INFO) \
+     ({ if ((ARG_INFO).size < sizeof(void*)) \
+           memcpy((ARGUMENT_LOCATION), \
+                  ((char*)(FRAME_DATA)) + sizeof(void*) - (ARG_INFO).size, \
+                  (ARG_INFO).size); \
+       else if (*(ARG_INFO).type == _C_FLT) \
+           *(float*)(ARGUMENT_LOCATION) = (float)*(double*)(FRAME_DATA); \
+       else memcpy((ARGUMENT_LOCATION), (FRAME_DATA), (ARG_INFO).size); \
+    })
+
+
+/* Define how to find the value returned by a function. TYPE is a Objective-C
+   encoding string describing the type of the returned value. ARGS is the
+   arguments frame passed to __builtin_apply. RESULT_FRAME is the address of
+   the block returned by __builtin_apply. RETURN_VALUE is an address where
+   this macro should put the returned value. */
+
+#define FUNCTION_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({ int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) { \
+           *(float*)(RETURN_VALUE) \
+                = (float)*(double*)(((char*)(RESULT_FRAME)) + 8); \
+       } \
+       else if(*(TYPE) == _C_DBL) { \
+           *(double*)(RETURN_VALUE) \
+                = *(double*)(((char*)(RESULT_FRAME)) + 8); \
+       } \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy((RETURN_VALUE), \
+                  *(void**)(((char*)(ARGS)) + sizeof(void*)), type_size); \
+       else if(type_size <= sizeof(void*)) \
+           memcpy((RETURN_VALUE), \
+                  ((char*)(RESULT_FRAME)) + sizeof(void*) - type_size, \
+                   type_size); \
+         else memcpy((RETURN_VALUE), (RESULT_FRAME), type_size); })
+
+
+/* Set the value in RETURN_VALUE to be the value returned by a function.
+   Assume that the fucntion was previously called and RESULT_FRAME is the
+   address of the block returned by __builtin_apply. TYPE is the actual
+   type of this value. ARGS is the address of block that was passed
+   to __builtin_apply. */
+
+#define FUNCTION_SET_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({  int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_FLT) \
+           *(double*)(((char*)(RESULT_FRAME)) + 8) = \
+               (double)*(float*)(RETURN_VALUE); \
+       else if(*(TYPE) == _C_DBL) \
+           *(double*)(((char*)(RESULT_FRAME)) + 8) = \
+               *(double*)(RETURN_VALUE); \
+       else if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy(*(void**)(((char*)(ARGS)) + sizeof(void*)), \
+                  (RETURN_VALUE), type_size); \
+       else if(type_size <= sizeof(void*)) \
+           memcpy(((char*)(RESULT_FRAME)) + sizeof(void*) - type_size, \
+                   (RETURN_VALUE), \
+                   type_size); \
+       else memcpy((RESULT_FRAME), (RETURN_VALUE), type_size); })
+
+
+/* If the RETTYPE is a structure and the address of the structure value is
+   passed to the called function, then obtain from ARGS its address. In general
+   this address is the second pointer into the arguments frame. This macro
+   should produce 0 if the RETTYPE doesn't match the conditions above. */
+
+#define GET_STRUCT_VALUE_ADDRESS(ARGS, RETTYPE) \
+    ((*(RETTYPE) == _C_STRUCT_B || *(RETTYPE) == _C_UNION_B \
+           || *(RETTYPE) == _C_ARY_B) ? \
+         *(void**)(((char*)(ARGS)) + sizeof(void*)) \
+       : 0)
+
+/* Prepare ARGS for calling the function. If the function returns a struct by
+   value, it's the caller responsability to pass to the called function the
+   address of where to store the structure value. */
+
+#define SET_STRUCT_VALUE_ADDRESS(ARGS, ADDR, RETTYPE) \
+    *(void**)(((char*)(ARGS)) + sizeof(void*)) = (ADDR)
+
+
+/* The following macros are used to determine the encoding of a selector given
+   the types of arguments. This macros follows the similar ones defined in the
+   target machine description from the compiler sources. */
+
+/* Define a data type for recording info about the arguments list of a method.
+   A variable of this type is further used by FUNCTION_ARG_ENCODING to
+   determine the encoding of an argument. This type should record all info
+   about arguments processed so far. */
+
+/* On RS/6000 the first eight words of non-FP are normally in
+   registers and the rest are pushed.  The first 13 FP args are in
+   registers. */
+
+typedef struct rs6000_args 
+{
+    int int_args;       /* Number of integer arguments so far */
+    int float_args;     /* Number of float arguments so far */
+    int int_regs_position;  /* The current position for integers in
+                               the register's frame */
+    int stack_position; /* The current position in the stack frame */
+} CUMULATIVE_ARGS;
+
+
+/* Initialize a variable of type CUMULATIVE_ARGS. This macro is called before
+   processing the first argument of a method. */
+
+#define INIT_CUMULATIVE_ARGS(CUM) \
+    ({ (CUM).int_args = 0; \
+       (CUM).float_args = 0; \
+       (CUM).int_regs_position = 4; \
+       (CUM).stack_position = 0; \
+    })
+
+/* This macro determines the encoding of the next argument of a method. It is
+   called repetitively, starting with the first argument and continuing to the
+   last one. CUM is a variable of type CUMULATIVE_ARGS. TYPE is a NSString
+   which represents the type of the argument processed. This macro must
+   produce a NSString whose value represents the encoding and position of the
+   current argument. STACKSIZE is a variable that counts the number of bytes
+   occupied by the arguments on the stack. */
+
+#ifndef ROUND
+#define ROUND(V, A) \
+  ({ typeof(V) __v=(V); typeof(A) __a=(A); \
+     __a*((__v+__a-1)/__a); })
+#endif
+
+
+#define FUNCTION_ARG_ENCODING(CUM, TYPE, STACK_ARGSIZE) \
+({  id encoding; \
+    const char* type = [(TYPE) cString]; \
+\
+    if (*type == _C_FLT || *type == _C_DBL) { \
+        if (++(CUM).float_args > 13) { \
+            /* Place the argument on stack. Floats are pushed as doubles. */ \
+            (CUM).stack_position += ROUND ((CUM).stack_position, \
+                                           __alignof__(double)); \
+            encoding = [NSString stringWithFormat:@"%s%d", type, \
+                         (CUM).stack_position + OBJC_FORWARDING_MIN_OFFSET]; \
+            (STACK_ARGSIZE) = ROUND ((CUM).stack_position, sizeof(double)); \
+        } \
+        else { \
+            /* Place the argument on register's frame. Floats are \
+               pushed as doubles. The register's frame for floats and \
+               doubles starts at index 40. */ \
+            int offset = 40 + sizeof (double) * ((CUM).float_args - 1); \
+            encoding = [NSString stringWithFormat:@"%s+%d", type, offset]; \
+            (CUM).int_regs_position += ROUND (objc_sizeof_type(type), \
+                                              objc_alignof_type(type)); \
+        } \
+    } \
+    else { \
+        int align, size; \
+\
+        if (*type == _C_STRUCT_B || *type == _C_UNION_B \
+            || *type == _C_ARY_B) { \
+            align = __alignof__(type); \
+            size = objc_sizeof_type (type); \
+        } \
+        else { \
+            align = __alignof__(int); \
+            size = objc_sizeof_type (type); \
+        } \
+\
+        if (++(CUM).int_args > 8) { \
+            /* We have a type to place on the stack */ \
+            (CUM).stack_position += ROUND ((CUM).stack_position, align); \
+            encoding = [NSString stringWithFormat:@"%s%d", type, \
+                        (CUM).stack_position + OBJC_FORWARDING_MIN_OFFSET]; \
+            (STACK_ARGSIZE) = ROUND ((CUM).stack_position, size); \
+        } \
+        else { \
+            /* We have to place a value on the register's frame. The \
+               register's frame for references and integers starts at 4. */ \
+            (CUM).int_regs_position = ROUND((CUM).int_regs_position, align); \
+            encoding = [NSString stringWithFormat:@"%s+%d", type, \
+                                 (CUM).int_regs_position]; \
+            (CUM).int_regs_position += ROUND (size, align); \
+        } \
+    } \
+    encoding; })
+
+#endif /* __powerpc_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/config/sparc/solaris2.4.h b/libFoundation/config/sparc/solaris2.4.h
new file mode 100644 (file)
index 0000000..ca6b5f0
--- /dev/null
@@ -0,0 +1,209 @@
+/* 
+   sparc.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __sparc_h__
+#define __sparc_h__
+
+#ifndef OBJC_FORWARDING_STACK_OFFSET
+#define OBJC_FORWARDING_STACK_OFFSET   0
+#endif
+
+#ifndef OBJC_FORWARDING_MIN_OFFSET
+#define OBJC_FORWARDING_MIN_OFFSET 0
+#endif
+
+/* Define the size of the block returned by __builtin_apply_args. This value is
+   computed by the function in expr.c. The block contains in order: a pointer
+   to the stack arguments frame, the structure value address unless this is
+   passed as an "invisible" first argument and all registers that may be used
+   in calling a function. */
+
+#define APPLY_ARGS_SIZE        32
+
+/* Define the size of the result block returned by the __builtin_apply. This
+   block contains all registers that could be used to return the function
+   value. This value is computed by apply_result_size function in expr.c. There
+   are also machines where this value is predefined in the machine description
+   file, so that machine specific information can be stored. */
+
+#define APPLY_RESULT_SIZE      16
+
+/* Define how to find the value returned by a function. TYPE is a Objective-C
+   encoding string describing the type of the returned value. ARGS is the
+   arguments frame passed to __builtin_apply. RESULT is the address of the
+   block returned by __builtin_apply. RETURN_VALUE is an address where this
+   macro should put the returned value. */
+
+#define FUNCTION_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({ int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy((RETURN_VALUE), *(void**)(RESULT_FRAME), type_size); \
+       else if (*(TYPE) == _C_FLT || *(TYPE) == _C_DBL) \
+           memcpy((RETURN_VALUE), (RESULT_FRAME) + 8, type_size); \
+       else if (type_size <= sizeof(void*)) \
+           memcpy((RETURN_VALUE), (RESULT_FRAME) + sizeof(void*) - type_size, type_size);  })
+
+
+/* Set the value in RETURN_VALUE to be the value returned by a function.
+   Assume that the fucntion was previously called and RESULT_FRAME is the
+   address of the block returned by __builtin_apply. TYPE is the actual
+   type of this value. ARGS is the address of block that was passed
+   to __builtin_apply. */
+
+#define FUNCTION_SET_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({  int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy(*(void**)(ARGS), (RETURN_VALUE), type_size); \
+       else if (*(TYPE) == _C_FLT || *(TYPE) == _C_DBL) \
+           memcpy((RESULT_FRAME) + 8, (RETURN_VALUE), type_size); \
+       else if (type_size <= sizeof(void*)) \
+           memcpy((RESULT_FRAME) + sizeof(void*) - type_size, (RETURN_VALUE), type_size); })
+
+/* If the RETTYPE is a structure and the address of the structure value is
+   passed to the called function, then obtain from ARGS its address. In general
+   this address is the second pointer into the arguments frame. This macro
+   should produce 0 if the RETTYPE doesn't match the conditions above. */
+
+#define GET_STRUCT_VALUE_ADDRESS(ARGS, RETTYPE) \
+    ((*(RETTYPE) == _C_STRUCT_B || *(RETTYPE) == _C_UNION_B \
+           || *(RETTYPE) == _C_ARY_B) ? \
+         **(void***)(ARGS) \
+       : 0)
+
+/* Prepare ARGS for calling the function. If the function returns a struct by
+   value, it's the caller responsability to pass to the called function the
+   address of where to store the structure value. */
+
+#define SET_STRUCT_VALUE_ADDRESS(ARGS, ADDR, RETTYPE) \
+    if(*(RETTYPE) == _C_STRUCT_B || *(RETTYPE) == _C_UNION_B \
+           || *(RETTYPE) == _C_ARY_B) \
+       **(void***)(ARGS) = (ADDR);
+
+
+/* The following macros are used to determine the encoding of a selector given
+   the types of arguments. This macros follows the similar ones defined in the
+   target machine description from the compiler sources. */
+
+/* Define a data type for recording info about the arguments list of a method.
+   A variable of this type is further used by FUNCTION_ARG_ENCODING to
+   determine the encoding of an argument. This type should record all info
+   about arguments processed so far. */
+
+/* From config/sparc/sparc.h in the GCC sources:
+
+   On SPARC the first six args are normally in registers
+   and the rest are pushed.  Any arg that starts within the first 6 words
+   is at least partially passed in a register unless its data type forbids.
+   For v9, the first 6 int args are passed in regs and the first N
+   float args are passed in regs (where N is such that %f0-15 are filled).
+   The rest are pushed.  Any arg that starts within the first 6 words
+   is at least partially passed in a register unless its data type forbids.
+
+   ...
+
+   The SPARC ABI stipulates passing struct arguments (of any size) and
+   (!v9) quad-precision floats by invisible reference.
+*/
+
+enum sparc_arg_location { IN_REGS = 0, ON_STACK = 1 };
+
+struct sparc_args {
+    int offsets[2];   /* 0 for args in regs, 1 for the rest of args on stack */
+    int onStack;
+};
+
+#define CUMULATIVE_ARGS struct sparc_args
+
+/* Initialize a variable of type CUMULATIVE_ARGS. This macro is called before
+   processing the first argument of a method. */
+
+#define INIT_CUMULATIVE_ARGS(CUM) \
+    ({  (CUM).offsets[0] = 8; /* encoding in regs starts from 8 */ \
+       (CUM).offsets[1] = 20; /* encoding in regs starts from 20 or 24 */ \
+       (CUM).onStack = NO; })
+
+
+/* This macro determines the encoding of the next argument of a method. It is
+   called repetitively, starting with the first argument and continuing to the
+   last one. CUM is a variable of type CUMULATIVE_ARGS. TYPE is a NSString
+   which represents the type of the argument processed. This macro must
+   produce a NSString whose value represents the encoding and position of the
+   current argument. STACKSIZE is a variable that counts the number of bytes
+   occupied by the arguments on the stack. */
+
+#ifndef ROUND
+#define ROUND(V, A) \
+  ({ typeof(V) __v=(V); typeof(A) __a=(A); \
+     __a*((__v+__a-1)/__a); })
+#endif
+
+#define GET_SPARC_ARG_LOCATION(CUM, CSTRING_TYPE, TYPESIZE) \
+    ((CUM).onStack \
+       ? ON_STACK \
+       : ((CUM).offsets[IN_REGS] + TYPESIZE <= 6 * sizeof(int) + 8 \
+           ? (((CUM).offsets[IN_REGS] + TYPESIZE <= 6 * sizeof(int) + 4 \
+               ? 0 : ((CUM).offsets[ON_STACK] += 4)),\
+             IN_REGS) \
+           : ((CUM).onStack = YES, ON_STACK)))
+
+#define FUNCTION_ARG_ENCODING(CUM, TYPE, STACK_ARGSIZE) \
+    ({  id encoding; \
+       const char* type = [(TYPE) cString]; \
+       int align = objc_alignof_type(type); \
+       int type_size = objc_sizeof_type(type); \
+       int arg_location = GET_SPARC_ARG_LOCATION(CUM, type, type_size); \
+\
+       (CUM).offsets[arg_location] \
+               = ROUND((CUM).offsets[arg_location], align); \
+       if(type_size < sizeof(int)) \
+           (CUM).offsets[arg_location] += sizeof(int) - ROUND(type_size, align); \
+       encoding = [NSString stringWithFormat: \
+                               (arg_location == IN_REGS ? @"%@+%d" : @"%@%d"), \
+                               (TYPE), \
+                               (arg_location == IN_REGS \
+                                   ? ((CUM).offsets[arg_location] \
+                                           + OBJC_FORWARDING_STACK_OFFSET) \
+                                   : (CUM).offsets[arg_location])]; \
+       if(arg_location == ON_STACK) { \
+           if((*type == _C_STRUCT_B || *type == _C_UNION_B \
+                   || *type == _C_ARY_B)) \
+               (STACK_ARGSIZE) = (CUM).offsets[ON_STACK] + ROUND(type_size, align); \
+           else (STACK_ARGSIZE) = (CUM).offsets[ON_STACK] + type_size; \
+       } \
+       (CUM).offsets[arg_location] += \
+           type_size < sizeof(int) \
+               ? ROUND(type_size, align) \
+               : ROUND(type_size, sizeof(void*)); \
+       encoding; })
+
+#endif /* __sparc_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/config/sparc/sparc.h b/libFoundation/config/sparc/sparc.h
new file mode 100644 (file)
index 0000000..fc3d587
--- /dev/null
@@ -0,0 +1,209 @@
+/* 
+   sparc.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __sparc_h__
+#define __sparc_h__
+
+#ifndef OBJC_FORWARDING_STACK_OFFSET
+#define OBJC_FORWARDING_STACK_OFFSET   0
+#endif
+
+#ifndef OBJC_FORWARDING_MIN_OFFSET
+#define OBJC_FORWARDING_MIN_OFFSET 0
+#endif
+
+/* Define the size of the block returned by __builtin_apply_args. This value is
+   computed by the function in expr.c. The block contains in order: a pointer
+   to the stack arguments frame, the structure value address unless this is
+   passed as an "invisible" first argument and all registers that may be used
+   in calling a function. */
+
+#define APPLY_ARGS_SIZE        32
+
+/* Define the size of the result block returned by the __builtin_apply. This
+   block contains all registers that could be used to return the function
+   value. This value is computed by apply_result_size function in expr.c. There
+   are also machines where this value is predefined in the machine description
+   file, so that machine specific information can be stored. */
+
+#define APPLY_RESULT_SIZE      16
+
+/* Define how to find the value returned by a function. TYPE is a Objective-C
+   encoding string describing the type of the returned value. ARGS is the
+   arguments frame passed to __builtin_apply. RESULT is the address of the
+   block returned by __builtin_apply. RETURN_VALUE is an address where this
+   macro should put the returned value. */
+
+#define FUNCTION_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({ int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy((RETURN_VALUE), *(void**)(RESULT_FRAME), type_size); \
+       else if (*(TYPE) == _C_FLT || *(TYPE) == _C_DBL) \
+           memcpy((RETURN_VALUE), (RESULT_FRAME) + 8, type_size); \
+       else if (type_size <= sizeof(void*)) \
+           memcpy((RETURN_VALUE), (RESULT_FRAME) + sizeof(void*) - type_size, type_size); })
+
+
+/* Set the value in RETURN_VALUE to be the value returned by a function.
+   Assume that the fucntion was previously called and RESULT_FRAME is the
+   address of the block returned by __builtin_apply. TYPE is the actual
+   type of this value. ARGS is the address of block that was passed
+   to __builtin_apply. */
+
+#define FUNCTION_SET_VALUE(TYPE, ARGS, RESULT_FRAME, RETURN_VALUE) \
+    ({  int type_size = objc_sizeof_type(TYPE); \
+       if(*(TYPE) == _C_STRUCT_B || *(TYPE) == _C_UNION_B \
+               || *(TYPE) == _C_ARY_B) \
+           memcpy(*(void**)(ARGS), (RETURN_VALUE), type_size); \
+       else if (*(TYPE) == _C_FLT || *(TYPE) == _C_DBL) \
+           memcpy((RESULT_FRAME) + 8, (RETURN_VALUE), type_size); \
+       else if (type_size <= sizeof(void*)) \
+           memcpy((RESULT_FRAME) + sizeof(void*) - type_size, (RETURN_VALUE), type_size); })
+
+/* If the RETTYPE is a structure and the address of the structure value is
+   passed to the called function, then obtain from ARGS its address. In general
+   this address is the second pointer into the arguments frame. This macro
+   should produce 0 if the RETTYPE doesn't match the conditions above. */
+
+#define GET_STRUCT_VALUE_ADDRESS(ARGS, RETTYPE) \
+    ((*(RETTYPE) == _C_STRUCT_B || *(RETTYPE) == _C_UNION_B \
+           || *(RETTYPE) == _C_ARY_B) ? \
+         **(void***)(ARGS) \
+       : 0)
+
+/* Prepare ARGS for calling the function. If the function returns a struct by
+   value, it's the caller responsability to pass to the called function the
+   address of where to store the structure value. */
+
+#define SET_STRUCT_VALUE_ADDRESS(ARGS, ADDR, RETTYPE) \
+    if(*(RETTYPE) == _C_STRUCT_B || *(RETTYPE) == _C_UNION_B \
+           || *(RETTYPE) == _C_ARY_B) \
+       **(void***)(ARGS) = (ADDR);
+
+
+/* The following macros are used to determine the encoding of a selector given
+   the types of arguments. This macros follows the similar ones defined in the
+   target machine description from the compiler sources. */
+
+/* Define a data type for recording info about the arguments list of a method.
+   A variable of this type is further used by FUNCTION_ARG_ENCODING to
+   determine the encoding of an argument. This type should record all info
+   about arguments processed so far. */
+
+/* From config/sparc/sparc.h in the GCC sources:
+
+   On SPARC the first six args are normally in registers
+   and the rest are pushed.  Any arg that starts within the first 6 words
+   is at least partially passed in a register unless its data type forbids.
+   For v9, the first 6 int args are passed in regs and the first N
+   float args are passed in regs (where N is such that %f0-15 are filled).
+   The rest are pushed.  Any arg that starts within the first 6 words
+   is at least partially passed in a register unless its data type forbids.
+
+   ...
+
+   The SPARC ABI stipulates passing struct arguments (of any size) and
+   (!v9) quad-precision floats by invisible reference.
+*/
+
+enum sparc_arg_location { IN_REGS = 0, ON_STACK = 1 };
+
+struct sparc_args {
+    int offsets[2];   /* 0 for args in regs, 1 for the rest of args on stack */
+    int onStack;
+};
+
+#define CUMULATIVE_ARGS struct sparc_args
+
+/* Initialize a variable of type CUMULATIVE_ARGS. This macro is called before
+   processing the first argument of a method. */
+
+#define INIT_CUMULATIVE_ARGS(CUM) \
+    ({  (CUM).offsets[0] = 8; /* encoding in regs starts from 8 */ \
+       (CUM).offsets[1] = 20; /* encoding in regs starts from 20 or 24 */ \
+       (CUM).onStack = NO; })
+
+
+/* This macro determines the encoding of the next argument of a method. It is
+   called repetitively, starting with the first argument and continuing to the
+   last one. CUM is a variable of type CUMULATIVE_ARGS. TYPE is a NSString
+   which represents the type of the argument processed. This macro must
+   produce a NSString whose value represents the encoding and position of the
+   current argument. STACKSIZE is a variable that counts the number of bytes
+   occupied by the arguments on the stack. */
+
+#ifndef ROUND
+#define ROUND(V, A) \
+  ({ typeof(V) __v=(V); typeof(A) __a=(A); \
+     __a*((__v+__a-1)/__a); })
+#endif
+
+#define GET_SPARC_ARG_LOCATION(CUM, CSTRING_TYPE, TYPESIZE) \
+    ((CUM).onStack \
+       ? ON_STACK \
+       : ((CUM).offsets[IN_REGS] + TYPESIZE <= 6 * sizeof(int) + 8 \
+           ? (((CUM).offsets[IN_REGS] + TYPESIZE <= 6 * sizeof(int) + 4 \
+               ? 0 : ((CUM).offsets[ON_STACK] += 4)),\
+             IN_REGS) \
+           : ((CUM).onStack = YES, ON_STACK)))
+
+#define FUNCTION_ARG_ENCODING(CUM, TYPE, STACK_ARGSIZE) \
+    ({  id encoding; \
+       const char* type = [(TYPE) cString]; \
+       int align = objc_alignof_type(type); \
+       int type_size = objc_sizeof_type(type); \
+       int arg_location = GET_SPARC_ARG_LOCATION(CUM, type, type_size); \
+\
+       (CUM).offsets[arg_location] \
+               = ROUND((CUM).offsets[arg_location], align); \
+       if(type_size < sizeof(int)) \
+           (CUM).offsets[arg_location] += sizeof(int) - ROUND(type_size, align); \
+       encoding = [NSString stringWithFormat: \
+                               (arg_location == IN_REGS ? @"%@+%d" : @"%@%d"), \
+                               (TYPE), \
+                               (arg_location == IN_REGS \
+                                   ? ((CUM).offsets[arg_location] \
+                                           + OBJC_FORWARDING_STACK_OFFSET) \
+                                   : (CUM).offsets[arg_location])]; \
+       if(arg_location == ON_STACK) { \
+           if((*type == _C_STRUCT_B || *type == _C_UNION_B \
+                   || *type == _C_ARY_B)) \
+               (STACK_ARGSIZE) = (CUM).offsets[ON_STACK] + ROUND(type_size, align); \
+           else (STACK_ARGSIZE) = (CUM).offsets[ON_STACK] + type_size; \
+       } \
+       (CUM).offsets[arg_location] += \
+           type_size < sizeof(int) \
+               ? ROUND(type_size, align) \
+               : ROUND(type_size, sizeof(void*)); \
+       encoding; })
+
+#endif /* __sparc_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/configure b/libFoundation/configure
new file mode 100755 (executable)
index 0000000..06d1d41
--- /dev/null
@@ -0,0 +1,3916 @@
+#! /bin/sh
+
+
+
+
+
+
+
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13 
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+
+--with-ffcall
+    Use the ffcall library to implement dynamic invocation of methods. Note
+    the licensing restrictions of ffcall before enabling that switch !"
+ac_help="$ac_help
+
+--with-gc
+--with-gc=DIR
+    Use the Boehm's garbage collector for automatic memory management instead
+    of the normal OpenStep memory management policy.
+    Search in DIR for GC include files (eg DIR=objc leads to <objc/gc.h>)"
+ac_help="$ac_help
+
+--with-gc-lib
+--with-gc-lib=LIB
+    Link against GC library LIB. The default is 'gc'. Do not specify
+    --with-gc-lib if you have the GC contained in some of your system
+    libraries (eg libobjc.a)"
+ac_default_prefix=/usr/local
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  case "$ac_option" in
+  -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) ac_optarg= ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case "$ac_option" in
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir="$ac_optarg" ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build="$ac_optarg" ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file="$ac_optarg" ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir="$ac_optarg" ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    eval "enable_${ac_feature}=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix="$ac_optarg" ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he)
+    # Omit some internal or obsolete options to make the list less imposing.
+    # This message is too long to be a string in the A/UX 3.1 sh.
+    cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+  --cache-file=FILE       cache test results in FILE
+  --help                  print this message
+  --no-create             do not create output files
+  --quiet, --silent       do not print \`checking...' messages
+  --version               print the version of autoconf that created configure
+Directory and file names:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [same as prefix]
+  --bindir=DIR            user executables in DIR [EPREFIX/bin]
+  --sbindir=DIR           system admin executables in DIR [EPREFIX/sbin]
+  --libexecdir=DIR        program executables in DIR [EPREFIX/libexec]
+  --datadir=DIR           read-only architecture-independent data in DIR
+                          [PREFIX/share]
+  --sysconfdir=DIR        read-only single-machine data in DIR [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data in DIR
+                          [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data in DIR [PREFIX/var]
+  --libdir=DIR            object code libraries in DIR [EPREFIX/lib]
+  --includedir=DIR        C header files in DIR [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc in DIR [/usr/include]
+  --infodir=DIR           info documentation in DIR [PREFIX/info]
+  --mandir=DIR            man documentation in DIR [PREFIX/man]
+  --srcdir=DIR            find the sources in DIR [configure dir or ..]
+  --program-prefix=PREFIX prepend PREFIX to installed program names
+  --program-suffix=SUFFIX append SUFFIX to installed program names
+  --program-transform-name=PROGRAM
+                          run sed PROGRAM on installed program names
+EOF
+    cat << EOF
+Host type:
+  --build=BUILD           configure for building on BUILD [BUILD=HOST]
+  --host=HOST             configure for HOST [guessed]
+  --target=TARGET         configure for TARGET [TARGET=HOST]
+Features and packages:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --x-includes=DIR        X include files are in DIR
+  --x-libraries=DIR       X library files are in DIR
+EOF
+    if test -n "$ac_help"; then
+      echo "--enable and --with options recognized:$ac_help"
+    fi
+    exit 0 ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host="$ac_optarg" ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir="$ac_optarg" ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir="$ac_optarg" ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir="$ac_optarg" ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir="$ac_optarg" ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    localstatedir="$ac_optarg" ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir="$ac_optarg" ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir="$ac_optarg" ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix="$ac_optarg" ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix="$ac_optarg" ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix="$ac_optarg" ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name="$ac_optarg" ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir="$ac_optarg" ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir="$ac_optarg" ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site="$ac_optarg" ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir="$ac_optarg" ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir="$ac_optarg" ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target="$ac_optarg" ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers)
+    echo "configure generated by autoconf version 2.13"
+    exit 0 ;;
+
+  -with-* | --with-*)
+    ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_${ac_package}='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    eval "with_${ac_package}=no" ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes="$ac_optarg" ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries="$ac_optarg" ;;
+
+  -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+    ;;
+
+  *)
+    if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+      echo "configure: warning: $ac_option: invalid host type" 1>&2
+    fi
+    if test "x$nonopt" != xNONE; then
+      { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+    fi
+    nonopt="$ac_option"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+  exec 6>/dev/null
+else
+  exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+  case "$ac_arg" in
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c) ;;
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+  *" "*|*"     "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+  ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+  *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+  esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set.  These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}"    = set; then LC_CTYPE=C;    export LC_CTYPE;    fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=${srcdir}/Foundation/NSObject.h.in
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then its parent.
+  ac_prog=$0
+  ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+  test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+  srcdir=$ac_confdir
+  if test ! -r $srcdir/$ac_unique_file; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+  else
+    { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+  fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    echo "loading site script $ac_site_file"
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  echo "loading cache $cache_file"
+  . $cache_file
+else
+  echo "creating cache $cache_file"
+  > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+  # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+    ac_n= ac_c='
+' ac_t='       '
+  else
+    ac_n=-n ac_c= ac_t=
+  fi
+else
+  ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+# ******************** GNUstep env ************************************
+
+if test "x$GNUSTEP_SYSTEM_ROOT" = "x"; then
+  { echo "configure: error: Your GNUstep.sh is not sourced" 1>&2; exit 1; }
+fi
+
+# ******************** version ****************************************
+
+# todo: read from Version file?
+MAJOR_VERSION=1
+MINOR_VERSION=0
+SUBMINOR_VERSION=73
+
+
+
+
+
+
+# ******************** options ****************************************
+
+# Check whether --with-ffcall or --without-ffcall was given.
+if test "${with_ffcall+set}" = set; then
+  withval="$with_ffcall"
+  ac_cv_use_ffcall=yes
+else
+  ac_cv_use_ffcall=no
+
+fi
+
+
+# Check whether --with-gc or --without-gc was given.
+if test "${with_gc+set}" = set; then
+  withval="$with_gc"
+  ac_cv_use_gc=yes; ac_cv_link_gc=yes;
+if  test x${withval} != xyes ; then
+    GC_INCLUDE_DIR="${withval}/"
+else
+    GC_INCLUDE_DIR=""
+fi
+
+else
+  ac_cv_use_gc=no; ac_cv_link_gc=no; GC_INCLUDE_DIR=""
+
+fi
+
+
+# Check whether --with-gc-lib or --without-gc-lib was given.
+if test "${with_gc_lib+set}" = set; then
+  withval="$with_gc_lib"
+  ac_cv_link_gc=yes;
+if  test x${withval} != xyes ; then
+    GC_LIB="${withval}"
+else
+    GC_LIB="gc"
+fi
+
+else
+  ac_cv_link_gc=no; GC_LIB=""
+
+fi
+
+
+
+
+
+
+# ******************** system type ************************************
+
+# Determine the host, build, and target systems
+CC_TARGET=$target # use --target value for CC, not the canonical form
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+  if test -f $ac_dir/install-sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f $ac_dir/install.sh; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+#    configure --host=HOST --target=TARGET --build=BUILD NONOPT
+#
+# The rules are:
+# 1. You are not allowed to specify --host, --target, and nonopt at the
+#    same time.
+# 2. Host defaults to nonopt.
+# 3. If nonopt is not specified, then host defaults to the current host,
+#    as determined by config.guess.
+# 4. Target and build default to nonopt.
+# 5. If nonopt is not specified, then target and build default to host.
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+case $host---$target---$nonopt in
+NONE---*---* | *---NONE---* | *---*---NONE) ;;
+*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+esac
+
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:671: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+  case $nonopt in
+  NONE)
+    if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+    else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+    fi ;;
+  *) host_alias=$nonopt ;;
+  esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking target system type""... $ac_c" 1>&6
+echo "configure:692: checking target system type" >&5
+
+target_alias=$target
+case "$target_alias" in
+NONE)
+  case $nonopt in
+  NONE) target_alias=$host_alias ;;
+  *) target_alias=$nonopt ;;
+  esac ;;
+esac
+
+target=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $target_alias`
+target_cpu=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$target" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+echo "configure:710: checking build system type" >&5
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+  case $nonopt in
+  NONE) build_alias=$host_alias ;;
+  *) build_alias=$nonopt ;;
+  esac ;;
+esac
+
+build=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+test "$host_alias" != "$target_alias" &&
+  test "$program_prefix$program_suffix$program_transform_name" = \
+    NONENONEs,x,x, &&
+  program_prefix=${target_alias}-
+
+
+
+
+
+# check for cross compilation
+
+if [ x$target = xNONE ]; then
+  set target $host
+fi
+
+if test "x$host" != "x$target"; then
+       cross_defines="CROSS=-DCROSS_COMPILE"
+        cross_compiling="yes"
+        echo "cross compiling from $host to $target .."
+        CC=${CC_TARGET}-gcc
+        LD=${CC_TARGET}-ld
+        AR=${CC_TARGET}-ar
+        RANLIB=${CC_TARGET}-ranlib
+fi
+
+case "x${host_cpu}" in
+    xi[456]86*)        host_cpu=i386;;
+    xhppa1.1)  host_cpu=hppa;;
+esac
+
+if test "x$cross_compiling" = xyes; then
+  case "x${target_cpu}" in
+    xi[456]86*)        target_cpu=i386;;
+    xhppa1.1)  target_cpu=hppa;;
+  esac
+else
+  target_cpu=${host_cpu}
+  target_os=${host_os}
+  target_vendor=${host_vendor}
+fi
+
+case "x${target_os}" in
+  xfreebsd*) target_os=freebsd;;
+esac
+
+
+# Assign the HOST/TARGET variables for sharedlib.mak
+HOST=$host
+HOST_CPU=$host_cpu
+HOST_VENDOR=$host_vendor
+HOST_OS=$host_os
+TARGET=$target
+TARGET_CPU=$target_cpu
+TARGET_VENDOR=$target_vendor
+TARGET_OS=$target_os
+
+if test ! -f ${srcdir}/config/${target_cpu}/${target_os}.h; then
+    if test -d ${srcdir}/config/${target_cpu}; then
+       echo
+       echo '*************** Warning ****************'
+       echo This package was not ported to $target_cpu running $target_os operating system.
+       echo We\'ll use the default configuration file ${srcdir}/config/$target_cpu/$target_cpu.h.
+       echo '****************************************'
+       echo
+       target_os=$target_cpu
+    else
+       echo
+       echo '*************** Warning ****************'
+       echo This package was not ported to $target_cpu running $target_os operating system.
+       echo We\'ll use a generic configuration file, thus you will be able to compile the library, but most probably the NSInvocation, NSMethodSignature and all classes that use them will not work correctly or will not work at all.
+       echo '****************************************'
+       target_cpu=generic
+       target_os=generic
+    fi
+fi
+
+
+# ******************** autoconf vars **********************************
+
+
+WITH_GNUSTEP=yes
+cat >> confdefs.h <<\EOF
+#define WITH_GNUSTEP 1
+EOF
+
+
+
+WITH_FFCALL=$ac_cv_use_ffcall
+if test "x$ac_cv_use_ffcall" = xyes; then
+  cat >> confdefs.h <<\EOF
+#define WITH_FFCALL 1
+EOF
+
+fi
+
+
+WITH_GC=$ac_cv_use_gc
+if test "$WITH_GC" = yes; then
+  cat >> confdefs.h <<\EOF
+#define LIB_FOUNDATION_BOEHM_GC 1
+EOF
+
+fi
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:834: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CC="gcc"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:864: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_prog_rejected=no
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+        ac_prog_rejected=yes
+       continue
+      fi
+      ac_cv_prog_CC="cc"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# -gt 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    set dummy "$ac_dir/$ac_word" "$@"
+    shift
+    ac_cv_prog_CC="$@"
+  fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+  if test -z "$CC"; then
+    case "`uname -s`" in
+    *win32* | *WIN32*)
+      # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:915: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CC="cl"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+ ;;
+    esac
+  fi
+  test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:947: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 958 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:963: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  ac_cv_prog_cc_works=yes
+  # If we can't run a trivial program, we are probably using a cross compiler.
+  if (./conftest; exit) 2>/dev/null; then
+    ac_cv_prog_cc_cross=no
+  else
+    ac_cv_prog_cc_cross=yes
+  fi
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+  { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:989: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:994: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.c <<EOF
+#ifdef __GNUC__
+  yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1003: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+  ac_cv_prog_gcc=yes
+else
+  ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:1022: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+  ac_cv_prog_cc_g=yes
+else
+  ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+
+if test "x$cross_compiling" = xyes; then
+        echo "cross compiling to $target"
+fi
+
+
+# ******************** system tools ***********************************
+
+echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6
+echo "configure:1061: checking for POSIXized ISC" >&5
+if test -d /etc/conf/kconfig.d &&
+  grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1
+then
+  echo "$ac_t""yes" 1>&6
+  ISC=yes # If later tests want to check for ISC.
+  cat >> confdefs.h <<\EOF
+#define _POSIX_SOURCE 1
+EOF
+
+  if test "$GCC" = yes; then
+    CC="$CC -posix"
+  else
+    CC="$CC -Xp"
+  fi
+else
+  echo "$ac_t""no" 1>&6
+  ISC=
+fi
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:1082: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    # This must be in double quotes, not single quotes, because CPP may get
+  # substituted into the Makefile and "${CC-cc}" will confuse make.
+  CPP="${CC-cc} -E"
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp.
+  cat > conftest.$ac_ext <<EOF
+#line 1097 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1103: \"$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
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP="${CC-cc} -E -traditional-cpp"
+  cat > conftest.$ac_ext <<EOF
+#line 1114 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1120: \"$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
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP="${CC-cc} -nologo -E"
+  cat > conftest.$ac_ext <<EOF
+#line 1131 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1137: \"$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
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+  ac_cv_prog_CPP="$CPP"
+fi
+  CPP="$ac_cv_prog_CPP"
+else
+  ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+for ac_prog in gmake gnumake make
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1166: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_MAKE'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$MAKE"; then
+  ac_cv_prog_MAKE="$MAKE" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_MAKE="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+MAKE="$ac_cv_prog_MAKE"
+if test -n "$MAKE"; then
+  echo "$ac_t""$MAKE" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$MAKE" && break
+done
+
+for ac_prog in ar
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1200: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$AR"; then
+  ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_AR="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+AR="$ac_cv_prog_AR"
+if test -n "$AR"; then
+  echo "$ac_t""$AR" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$AR" && break
+done
+
+for ac_prog in ld
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1234: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LD'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$LD"; then
+  ac_cv_prog_LD="$LD" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_LD="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+LD="$ac_cv_prog_LD"
+if test -n "$LD"; then
+  echo "$ac_t""$LD" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$LD" && break
+done
+
+for ac_prog in perl
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1268: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_PERL'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$PERL"; then
+  ac_cv_prog_PERL="$PERL" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_PERL="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+PERL="$ac_cv_prog_PERL"
+if test -n "$PERL"; then
+  echo "$ac_t""$PERL" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$PERL" && break
+done
+
+
+# uses AC_TRY_RUN
+
+if test "x$cross_compiling" = xyes; then
+  if [ "x${target_cpu}" = xi386 ]; then
+    echo "WARNING: using predefined structure alignment of 4 for i386 !"
+    ac_cv_struct_alignment=4
+    STRUCT_ALIGNMENT=4
+  elif [ "x${target_cpu}" = xsparc ]; then
+    echo "WARNING: using predefined structure alignment of 8 for ${target_cpu} !"
+    ac_cv_struct_alignment=8
+    STRUCT_ALIGNMENT=8
+  elif [ "x${target_cpu}" = xmipsel ]; then
+    echo "WARNING: using predefined structure alignment of 8 for ${target_cpu} !"
+    ac_cv_struct_alignment=8
+    STRUCT_ALIGNMENT=8
+  else
+    echo "ERROR: unknown structure alignment for CPU ${target_cpu}, using 4 !"
+    ac_cv_struct_alignment=4
+    STRUCT_ALIGNMENT=4
+  fi
+else
+  echo $ac_n "checking for the C structures alignment""... $ac_c" 1>&6
+echo "configure:1320: checking for the C structures alignment" >&5
+if eval "test \"`echo '$''{'ac_cv_struct_alignment'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+    { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1328 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+
+struct simple {
+    double x;
+    char y;
+} simple1;
+
+int struct_alignment = __alignof__ (simple1);
+
+main()
+{
+  FILE *f=fopen("conftestval", "w");
+  if (!f) exit(1);
+  fprintf(f, "%u\n", struct_alignment);
+  exit(0);
+}
+
+EOF
+if { (eval echo configure:1348: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_struct_alignment=`cat conftestval`
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_struct_alignment=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_struct_alignment" 1>&6
+STRUCT_ALIGNMENT=$ac_cv_struct_alignment
+
+fi
+
+echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
+echo "configure:1367: checking for dlopen in -ldl" >&5
+ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-ldl  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1375 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char dlopen();
+
+int main() {
+dlopen()
+; return 0; }
+EOF
+if { (eval echo configure:1386: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo dl | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-ldl $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for pthread_create in -lpcthread""... $ac_c" 1>&6
+echo "configure:1414: checking for pthread_create in -lpcthread" >&5
+ac_lib_var=`echo pcthread'_'pthread_create | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lpcthread  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1422 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char pthread_create();
+
+int main() {
+pthread_create()
+; return 0; }
+EOF
+if { (eval echo configure:1433: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo pcthread | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-lpcthread $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+echo $ac_n "checking for pthread_create in -lpthread""... $ac_c" 1>&6
+echo "configure:1459: checking for pthread_create in -lpthread" >&5
+ac_lib_var=`echo pthread'_'pthread_create | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lpthread  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1467 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char pthread_create();
+
+int main() {
+pthread_create()
+; return 0; }
+EOF
+if { (eval echo configure:1478: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo pthread | sed -e 's/^a-zA-Z0-9_/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-lpthread $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+echo $ac_n "checking for sqrt in -lm""... $ac_c" 1>&6
+echo "configure:1508: checking for sqrt in -lm" >&5
+ac_lib_var=`echo m'_'sqrt | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lm  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1516 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char sqrt();
+
+int main() {
+sqrt()
+; return 0; }
+EOF
+if { (eval echo configure:1527: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo m | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-lm $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for chown in -lnsl""... $ac_c" 1>&6
+echo "configure:1555: checking for chown in -lnsl" >&5
+ac_lib_var=`echo nsl'_'chown | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lnsl  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1563 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char chown();
+
+int main() {
+chown()
+; return 0; }
+EOF
+if { (eval echo configure:1574: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo nsl | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-lnsl $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for accept in -lsocket""... $ac_c" 1>&6
+echo "configure:1602: checking for accept in -lsocket" >&5
+ac_lib_var=`echo socket'_'accept | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lsocket  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1610 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char accept();
+
+int main() {
+accept()
+; return 0; }
+EOF
+if { (eval echo configure:1621: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo socket | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-lsocket $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+
+RUNTIME=GNU
+transformed_target_cpu=`${GNUSTEP_SYSTEM_ROOT}/Makefiles/clean_cpu.sh ${TARGET_CPU}`
+ac_cv_file_output_prefix=Foundation/$transformed_target_cpu/${TARGET_OS}/$RUNTIME
+
+
+echo $ac_n "checking whether nested functions work""... $ac_c" 1>&6
+echo "configure:1655: checking whether nested functions work" >&5
+if eval "test \"`echo '$''{'ac_cv_nested_functions'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  OLD_IFS=$IFS
+IFS=:
+for i in $LD_LIBRARY_PATH
+do
+  LDFLAGS="-L$i $LDFLAGS"
+done
+IFS=$OLD_IFS
+LIBS="-lobjc $LIBS"
+ac_ext=m
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $OBJC_RUNTIME_FLAG'
+ac_compile='${CC-cc} -c $OBJC_RUNTIME_FLAG $CFLAGS conftest.$ac_ext 1>&5 2>&5'
+ac_link='${CC-cc} -o conftest $OBJC_RUNTIME_FLAG $CFLAGS $LDFLAGS conftest.$ac_ext $LIBS $OBJC_LIBS 1>&5 2>&5'
+
+if test "$cross_compiling" = yes; then
+  ac_cv_nested_functions=yes
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1677 "configure"
+#include "confdefs.h"
+
+f(void (*nested)())
+{
+    (*nested)();
+}
+
+main()
+{
+    int a = 0;
+    void nested()
+    {
+       a = 1;
+    }
+    f(nested);
+    if(a != 1)
+       exit(1);
+    exit(0);
+}
+
+EOF
+if { (eval echo configure:1699: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_nested_functions=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_nested_functions=no
+fi
+rm -fr conftest*
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+
+fi
+echo "$ac_t""${ac_cv_nested_functions}" 1>&6
+NO_NESTED_FUNCTIONS=no
+if test $ac_cv_nested_functions = no; then
+    cat >> confdefs.h <<\EOF
+#define NO_NESTED_FUNCTIONS 1
+EOF
+
+    NO_NESTED_FUNCTIONS=yes
+fi
+
+echo $ac_n "checking if the Objective-C compiler crashes with nested functions""... $ac_c" 1>&6
+echo "configure:1731: checking if the Objective-C compiler crashes with nested functions" >&5
+if eval "test \"`echo '$''{'ac_cv_broken_compiler'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  OLD_IFS=$IFS
+IFS=:
+for i in $LD_LIBRARY_PATH
+do
+  LDFLAGS="-L$i $LDFLAGS"
+done
+IFS=$OLD_IFS
+LIBS="-lobjc $LIBS"
+ac_ext=m
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $OBJC_RUNTIME_FLAG'
+ac_compile='${CC-cc} -c $OBJC_RUNTIME_FLAG $CFLAGS conftest.$ac_ext 1>&5 2>&5'
+ac_link='${CC-cc} -o conftest $OBJC_RUNTIME_FLAG $CFLAGS $LDFLAGS conftest.$ac_ext $LIBS $OBJC_LIBS 1>&5 2>&5'
+
+if test "$cross_compiling" = yes; then
+  ac_cv_broken_compiler=no
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1753 "configure"
+#include "confdefs.h"
+
+#include <objc/objc.h>
+#include <objc/Object.h>
+
+void f()
+{
+    auto void h(id);
+
+    void h(id exception)
+    {
+       [Object alloc];
+       {
+           void clean(void)
+           {
+           }
+       }
+    }
+}
+
+void g()
+{
+    auto void h(id);
+
+    void h(id exception)
+    {
+       [Object alloc];
+    }
+}
+
+main()
+{
+    exit(0);
+}
+
+EOF
+if { (eval echo configure:1790: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_broken_compiler=no
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_broken_compiler=yes
+fi
+rm -fr conftest*
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+
+fi
+BROKEN_COMPILER=${ac_cv_broken_compiler}
+if test ${ac_cv_nested_functions} = no -o ${ac_cv_broken_compiler} = yes; then
+  ac_cv_broken_compiler=yes;
+  BROKEN_COMPILER=yes;
+  cat >> confdefs.h <<\EOF
+#define BROKEN_COMPILER 1
+EOF
+
+fi
+echo "$ac_t""${ac_cv_broken_compiler}" 1>&6
+
+
+if test $target_cpu = i386; then
+    echo $ac_n "checking whether __builtin_apply and __builtin_return are broken""... $ac_c" 1>&6
+echo "configure:1825: checking whether __builtin_apply and __builtin_return are broken" >&5
+if eval "test \"`echo '$''{'ac_cv_broken_builtin_apply'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  OLD_IFS=$IFS
+IFS=:
+for i in $LD_LIBRARY_PATH
+do
+  LDFLAGS="-L$i $LDFLAGS"
+done
+IFS=$OLD_IFS
+LIBS="-lobjc $LIBS"
+ac_ext=m
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $OBJC_RUNTIME_FLAG'
+ac_compile='${CC-cc} -c $OBJC_RUNTIME_FLAG $CFLAGS conftest.$ac_ext 1>&5 2>&5'
+ac_link='${CC-cc} -o conftest $OBJC_RUNTIME_FLAG $CFLAGS $LDFLAGS conftest.$ac_ext $LIBS $OBJC_LIBS 1>&5 2>&5'
+
+if test "$cross_compiling" = yes; then
+  ac_cv_broken_builtin_apply=no
+else
+  cat > conftest.$ac_ext <<EOF
+#line 1847 "configure"
+#include "confdefs.h"
+
+#include <objc/Object.h>
+
+float value = 123.456;
+
+@interface MyObject : Object
+@end
+
+@implementation MyObject
+- (float)floatValue
+{
+    return value;
+}
+@end
+
+@interface Forwarder : Object
+{
+    id object;
+}
+@end
+
+@implementation Forwarder
+- setObject:anObject
+{
+    object = anObject;
+    return self;
+}
+
+- (void*)forward:(SEL)selector:(void*)argframe
+{
+    IMP imp = [object methodFor:@selector(floatValue)];
+    void* retframe;
+    void* frame = malloc(116);
+    *(void**)frame = NULL;
+    retframe = __builtin_apply((void(*)(void))imp, frame, 0);
+    if(*(long double*)(((char*)retframe) + 8) == (long double)value)
+       exit(0);
+    exit(1);
+}
+@end
+
+int main()
+{
+    id fwd = [[[Forwarder alloc] init] setObject:[MyObject alloc]];
+    [fwd floatValue];
+    exit(0);
+    return 0; // keep compiler happy
+}
+
+EOF
+if { (eval echo configure:1899: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_broken_builtin_apply=no
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_broken_builtin_apply=yes
+fi
+rm -fr conftest*
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+
+fi
+echo "$ac_t""${ac_cv_broken_builtin_apply}" 1>&6
+BROKEN_BUILTIN_APPLY=${ac_cv_broken_builtin_apply}
+if test $BROKEN_BUILTIN_APPLY = yes; then
+    cat >> confdefs.h <<\EOF
+#define BROKEN_BUILTIN_APPLY 1
+EOF
+
+fi
+
+fi
+
+# If we're using the Boehm's GC check to see if we have the gc.h file and
+# libgc.a installed.
+cat >> confdefs.h <<\EOF
+#define WITH_GC 1
+EOF
+
+for ac_hdr in ${GC_INCLUDE_DIR}gc.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1941: 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
+#line 1946 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1951: \"$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*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+
+if test "x$ac_cv_link_gc" = xyes; then
+    echo $ac_n "checking for GC_malloc in -l${GC_LIB}""... $ac_c" 1>&6
+echo "configure:1980: checking for GC_malloc in -l${GC_LIB}" >&5
+ac_lib_var=`echo ${GC_LIB}'_'GC_malloc | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-l${GC_LIB}  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1988 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char GC_malloc();
+
+int main() {
+GC_malloc()
+; return 0; }
+EOF
+if { (eval echo configure:1999: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_lib=HAVE_LIB`echo ${GC_LIB} | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+  LIBS="-l${GC_LIB} $LIBS"
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+    if test "x$ac_cv_header_gc_h" != xyes -o "x$ac_cv_lib_gc_GC_malloc" != xyes; then
+       
+       { echo "configure: error: It appears your system doesn't have the Boehm's garbage collector installed! Please install it first or check your paths in case it's already installed. Note that we expect the Boehm's GC library to be named so that linking using -lgc works; please be careful as the normal 'make' in Boehm's GC neither creates the library nor installs it. You should copy the files gc.h and gc.a in the appropriate directories and rename gc.a to libgc.a." 1>&2; exit 1; }
+       
+    fi
+fi
+
+# uses AC_TRY_RUN
+if test x"$cross_compiling" = xyes; then
+    echo "WARNING: cannot check for byte-order during cross compilation."
+else
+    echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
+echo "configure:2038: checking whether byte ordering is bigendian" >&5
+if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_cv_c_bigendian=unknown
+# See if sys/param.h defines the BYTE_ORDER macro.
+cat > conftest.$ac_ext <<EOF
+#line 2045 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/param.h>
+int main() {
+
+#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
+ bogus endian macros
+#endif
+; return 0; }
+EOF
+if { (eval echo configure:2056: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  # It does; now see whether it defined to BIG_ENDIAN or not.
+cat > conftest.$ac_ext <<EOF
+#line 2060 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/param.h>
+int main() {
+
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif
+; return 0; }
+EOF
+if { (eval echo configure:2071: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_c_bigendian=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_c_bigendian=no
+fi
+rm -f conftest*
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+if test $ac_cv_c_bigendian = unknown; then
+if test "$cross_compiling" = yes; then
+    { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2091 "configure"
+#include "confdefs.h"
+main () {
+  /* Are we little or big endian?  From Harbison&Steele.  */
+  union
+  {
+    long l;
+    char c[sizeof (long)];
+  } u;
+  u.l = 1;
+  exit (u.c[sizeof (long) - 1] == 1);
+}
+EOF
+if { (eval echo configure:2104: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_c_bigendian=no
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_c_bigendian=yes
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_c_bigendian" 1>&6
+if test $ac_cv_c_bigendian = yes; then
+  cat >> confdefs.h <<\EOF
+#define WORDS_BIGENDIAN 1
+EOF
+
+fi
+
+fi
+
+echo $ac_n "checking size of short""... $ac_c" 1>&6
+echo "configure:2130: checking size of short" >&5 
+if eval "test \"`echo '$''{'ac_cv_sizeof_short'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  for ac_size in 4 8 1 2 16  ; do # List sizes in rough order of prevalence. 
+  cat > conftest.$ac_ext <<EOF
+#line 2136 "configure"
+#include "confdefs.h"
+#include "confdefs.h" 
+#include <sys/types.h> 
+
+int main() {
+switch (0) case 0: case (sizeof (short) == $ac_size):;
+; return 0; }
+EOF
+if { (eval echo configure:2146: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_sizeof_short=$ac_size
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+fi
+rm -f conftest* 
+  if test x$ac_cv_sizeof_short != x ; then break; fi 
+done 
+
+fi
+if test x$ac_cv_sizeof_short = x ; then 
+  echo "cannot determine a size for short";
+  ac_cv_sizeof_short=0; 
+fi 
+echo "$ac_t""$ac_cv_sizeof_short" 1>&6 
+cat >> confdefs.h <<EOF
+#define SIZEOF_SHORT $ac_cv_sizeof_short
+EOF
+
+echo $ac_n "checking size of int""... $ac_c" 1>&6
+echo "configure:2170: checking size of int" >&5 
+if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  for ac_size in 4 8 1 2 16  ; do # List sizes in rough order of prevalence. 
+  cat > conftest.$ac_ext <<EOF
+#line 2176 "configure"
+#include "confdefs.h"
+#include "confdefs.h" 
+#include <sys/types.h> 
+
+int main() {
+switch (0) case 0: case (sizeof (int) == $ac_size):;
+; return 0; }
+EOF
+if { (eval echo configure:2186: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_sizeof_int=$ac_size
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+fi
+rm -f conftest* 
+  if test x$ac_cv_sizeof_int != x ; then break; fi 
+done 
+
+fi
+if test x$ac_cv_sizeof_int = x ; then 
+  echo "cannot determine a size for int";
+  ac_cv_sizeof_int=0; 
+fi 
+echo "$ac_t""$ac_cv_sizeof_int" 1>&6 
+cat >> confdefs.h <<EOF
+#define SIZEOF_INT $ac_cv_sizeof_int
+EOF
+
+echo $ac_n "checking size of long""... $ac_c" 1>&6
+echo "configure:2210: checking size of long" >&5 
+if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  for ac_size in 4 8 1 2 16  ; do # List sizes in rough order of prevalence. 
+  cat > conftest.$ac_ext <<EOF
+#line 2216 "configure"
+#include "confdefs.h"
+#include "confdefs.h" 
+#include <sys/types.h> 
+
+int main() {
+switch (0) case 0: case (sizeof (long) == $ac_size):;
+; return 0; }
+EOF
+if { (eval echo configure:2226: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_sizeof_long=$ac_size
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+fi
+rm -f conftest* 
+  if test x$ac_cv_sizeof_long != x ; then break; fi 
+done 
+
+fi
+if test x$ac_cv_sizeof_long = x ; then 
+  echo "cannot determine a size for long";
+  ac_cv_sizeof_long=0; 
+fi 
+echo "$ac_t""$ac_cv_sizeof_long" 1>&6 
+cat >> confdefs.h <<EOF
+#define SIZEOF_LONG $ac_cv_sizeof_long
+EOF
+
+echo $ac_n "checking size of long long""... $ac_c" 1>&6
+echo "configure:2250: checking size of long long" >&5 
+if eval "test \"`echo '$''{'ac_cv_sizeof_long_long'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  for ac_size in 4 8 1 2 16  ; do # List sizes in rough order of prevalence. 
+  cat > conftest.$ac_ext <<EOF
+#line 2256 "configure"
+#include "confdefs.h"
+#include "confdefs.h" 
+#include <sys/types.h> 
+
+int main() {
+switch (0) case 0: case (sizeof (long long) == $ac_size):;
+; return 0; }
+EOF
+if { (eval echo configure:2266: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_sizeof_long_long=$ac_size
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+fi
+rm -f conftest* 
+  if test x$ac_cv_sizeof_long_long != x ; then break; fi 
+done 
+
+fi
+if test x$ac_cv_sizeof_long_long = x ; then 
+  echo "cannot determine a size for long long";
+  ac_cv_sizeof_long_long=0; 
+fi 
+echo "$ac_t""$ac_cv_sizeof_long_long" 1>&6 
+cat >> confdefs.h <<EOF
+#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long
+EOF
+
+echo $ac_n "checking size of float""... $ac_c" 1>&6
+echo "configure:2290: checking size of float" >&5 
+if eval "test \"`echo '$''{'ac_cv_sizeof_float'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  for ac_size in 4 8 1 2 16  ; do # List sizes in rough order of prevalence. 
+  cat > conftest.$ac_ext <<EOF
+#line 2296 "configure"
+#include "confdefs.h"
+#include "confdefs.h" 
+#include <sys/types.h> 
+
+int main() {
+switch (0) case 0: case (sizeof (float) == $ac_size):;
+; return 0; }
+EOF
+if { (eval echo configure:2306: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_sizeof_float=$ac_size
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+fi
+rm -f conftest* 
+  if test x$ac_cv_sizeof_float != x ; then break; fi 
+done 
+
+fi
+if test x$ac_cv_sizeof_float = x ; then 
+  echo "cannot determine a size for float";
+  ac_cv_sizeof_float=0; 
+fi 
+echo "$ac_t""$ac_cv_sizeof_float" 1>&6 
+cat >> confdefs.h <<EOF
+#define SIZEOF_FLOAT $ac_cv_sizeof_float
+EOF
+
+echo $ac_n "checking size of double""... $ac_c" 1>&6
+echo "configure:2330: checking size of double" >&5 
+if eval "test \"`echo '$''{'ac_cv_sizeof_double'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  for ac_size in 4 8 1 2 16  ; do # List sizes in rough order of prevalence. 
+  cat > conftest.$ac_ext <<EOF
+#line 2336 "configure"
+#include "confdefs.h"
+#include "confdefs.h" 
+#include <sys/types.h> 
+
+int main() {
+switch (0) case 0: case (sizeof (double) == $ac_size):;
+; return 0; }
+EOF
+if { (eval echo configure:2346: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_sizeof_double=$ac_size
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+fi
+rm -f conftest* 
+  if test x$ac_cv_sizeof_double != x ; then break; fi 
+done 
+
+fi
+if test x$ac_cv_sizeof_double = x ; then 
+  echo "cannot determine a size for double";
+  ac_cv_sizeof_double=0; 
+fi 
+echo "$ac_t""$ac_cv_sizeof_double" 1>&6 
+cat >> confdefs.h <<EOF
+#define SIZEOF_DOUBLE $ac_cv_sizeof_double
+EOF
+
+echo $ac_n "checking size of long double""... $ac_c" 1>&6
+echo "configure:2370: checking size of long double" >&5 
+if eval "test \"`echo '$''{'ac_cv_sizeof_long_double'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  for ac_size in 4 8 1 2 16  ; do # List sizes in rough order of prevalence. 
+  cat > conftest.$ac_ext <<EOF
+#line 2376 "configure"
+#include "confdefs.h"
+#include "confdefs.h" 
+#include <sys/types.h> 
+
+int main() {
+switch (0) case 0: case (sizeof (long double) == $ac_size):;
+; return 0; }
+EOF
+if { (eval echo configure:2386: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_sizeof_long_double=$ac_size
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+fi
+rm -f conftest* 
+  if test x$ac_cv_sizeof_long_double != x ; then break; fi 
+done 
+
+fi
+if test x$ac_cv_sizeof_long_double = x ; then 
+  echo "cannot determine a size for long double";
+  ac_cv_sizeof_long_double=0; 
+fi 
+echo "$ac_t""$ac_cv_sizeof_long_double" 1>&6 
+cat >> confdefs.h <<EOF
+#define SIZEOF_LONG_DOUBLE $ac_cv_sizeof_long_double
+EOF
+
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6
+echo "configure:2415: checking for $ac_hdr that defines DIR" >&5
+if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2420 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <$ac_hdr>
+int main() {
+DIR *dirp = 0;
+; return 0; }
+EOF
+if { (eval echo configure:2428: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  eval "ac_cv_header_dirent_$ac_safe=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_dirent_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+ ac_header_dirent=$ac_hdr; break
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6
+echo "configure:2453: checking for opendir in -ldir" >&5
+ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-ldir  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2461 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char opendir();
+
+int main() {
+opendir()
+; return 0; }
+EOF
+if { (eval echo configure:2472: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  LIBS="$LIBS -ldir"
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+else
+echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6
+echo "configure:2494: checking for opendir in -lx" >&5
+ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lx  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2502 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char opendir();
+
+int main() {
+opendir()
+; return 0; }
+EOF
+if { (eval echo configure:2513: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  LIBS="$LIBS -lx"
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+for ac_hdr in dir.h libc.h sys/time.h stdlib.h memory.h string.h               strings.h sys/stat.h sys/vfs.h sys/statfs.h sys/statvfs.h               netinet/in.h windows.h          Windows32/Sockets.h pwd.h process.h grp.h sys/param.h           sys/file.h sys/errno.h sys/select.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:2539: 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
+#line 2544 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2549: \"$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*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6
+echo "configure:2576: checking for sys/wait.h that is POSIX.1 compatible" >&5
+if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2581 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/wait.h>
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
+int main() {
+int s;
+wait (&s);
+s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
+; return 0; }
+EOF
+if { (eval echo configure:2597: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_header_sys_wait_h=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_header_sys_wait_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_sys_wait_h" 1>&6
+if test $ac_cv_header_sys_wait_h = yes; then
+  cat >> confdefs.h <<\EOF
+#define HAVE_SYS_WAIT_H 1
+EOF
+
+fi
+
+
+for ac_func in memcpy ualarm getcwd getuid getpwnam getpwuid kill raise               getpagesize statvfs chown symlink readlink opendir fsync                sysconf GetSystemInfo gettimeofday GetLocalTime sigsetmask              sigset sigaction sighold                gethostbyname_r gethostbyaddr_r gethostent_r
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2621: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2626 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2649: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_hdr in unistd.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:2677: 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
+#line 2682 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2687: \"$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*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_func in getpagesize
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2716: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2721 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2744: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+echo $ac_n "checking for working mmap""... $ac_c" 1>&6
+echo "configure:2769: checking for working mmap" >&5
+if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_mmap_fixed_mapped=no
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2777 "configure"
+#include "confdefs.h"
+
+/* Thanks to Mike Haertel and Jim Avera for this test.
+   Here is a matrix of mmap possibilities:
+       mmap private not fixed
+       mmap private fixed at somewhere currently unmapped
+       mmap private fixed at somewhere already mapped
+       mmap shared not fixed
+       mmap shared fixed at somewhere currently unmapped
+       mmap shared fixed at somewhere already mapped
+   For private mappings, we should verify that changes cannot be read()
+   back from the file, nor mmap's back from the file at a different
+   address.  (There have been systems where private was not correctly
+   implemented like the infamous i386 svr4.0, and systems where the
+   VM page cache was not coherent with the filesystem buffer cache
+   like early versions of FreeBSD and possibly contemporary NetBSD.)
+   For shared mappings, we should conversely verify that changes get
+   propogated back to all the places they're supposed to be.
+
+   Grep wants private fixed already mapped.
+   The main things grep needs to know about mmap are:
+   * does it exist and is it safe to write into the mmap'd area
+   * how to use it (BSD variants)  */
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+/* This mess was copied from the GNU getpagesize.h.  */
+#ifndef HAVE_GETPAGESIZE
+# ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+# endif
+
+/* Assume that all systems that can run configure have sys/param.h.  */
+# ifndef HAVE_SYS_PARAM_H
+#  define HAVE_SYS_PARAM_H 1
+# endif
+
+# ifdef _SC_PAGESIZE
+#  define getpagesize() sysconf(_SC_PAGESIZE)
+# else /* no _SC_PAGESIZE */
+#  ifdef HAVE_SYS_PARAM_H
+#   include <sys/param.h>
+#   ifdef EXEC_PAGESIZE
+#    define getpagesize() EXEC_PAGESIZE
+#   else /* no EXEC_PAGESIZE */
+#    ifdef NBPG
+#     define getpagesize() NBPG * CLSIZE
+#     ifndef CLSIZE
+#      define CLSIZE 1
+#     endif /* no CLSIZE */
+#    else /* no NBPG */
+#     ifdef NBPC
+#      define getpagesize() NBPC
+#     else /* no NBPC */
+#      ifdef PAGESIZE
+#       define getpagesize() PAGESIZE
+#      endif /* PAGESIZE */
+#     endif /* no NBPC */
+#    endif /* no NBPG */
+#   endif /* no EXEC_PAGESIZE */
+#  else /* no HAVE_SYS_PARAM_H */
+#   define getpagesize() 8192  /* punt totally */
+#  endif /* no HAVE_SYS_PARAM_H */
+# endif /* no _SC_PAGESIZE */
+
+#endif /* no HAVE_GETPAGESIZE */
+
+#ifdef __cplusplus
+extern "C" { void *malloc(unsigned); }
+#else
+char *malloc();
+#endif
+
+int
+main()
+{
+       char *data, *data2, *data3;
+       int i, pagesize;
+       int fd;
+
+       pagesize = getpagesize();
+
+       /*
+        * First, make a file with some known garbage in it.
+        */
+       data = malloc(pagesize);
+       if (!data)
+               exit(1);
+       for (i = 0; i < pagesize; ++i)
+               *(data + i) = rand();
+       umask(0);
+       fd = creat("conftestmmap", 0600);
+       if (fd < 0)
+               exit(1);
+       if (write(fd, data, pagesize) != pagesize)
+               exit(1);
+       close(fd);
+
+       /*
+        * Next, try to mmap the file at a fixed address which
+        * already has something else allocated at it.  If we can,
+        * also make sure that we see the same garbage.
+        */
+       fd = open("conftestmmap", O_RDWR);
+       if (fd < 0)
+               exit(1);
+       data2 = malloc(2 * pagesize);
+       if (!data2)
+               exit(1);
+       data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1);
+       if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE,
+           MAP_PRIVATE | MAP_FIXED, fd, 0L))
+               exit(1);
+       for (i = 0; i < pagesize; ++i)
+               if (*(data + i) != *(data2 + i))
+                       exit(1);
+
+       /*
+        * Finally, make sure that changes to the mapped area
+        * do not percolate back to the file as seen by read().
+        * (This is a bug on some variants of i386 svr4.0.)
+        */
+       for (i = 0; i < pagesize; ++i)
+               *(data2 + i) = *(data2 + i) + 1;
+       data3 = malloc(pagesize);
+       if (!data3)
+               exit(1);
+       if (read(fd, data3, pagesize) != pagesize)
+               exit(1);
+       for (i = 0; i < pagesize; ++i)
+               if (*(data + i) != *(data3 + i))
+                       exit(1);
+       close(fd);
+       unlink("conftestmmap");
+       exit(0);
+}
+
+EOF
+if { (eval echo configure:2917: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_func_mmap_fixed_mapped=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_func_mmap_fixed_mapped=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_func_mmap_fixed_mapped" 1>&6
+if test $ac_cv_func_mmap_fixed_mapped = yes; then
+  cat >> confdefs.h <<\EOF
+#define HAVE_MMAP 1
+EOF
+
+fi
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:2940: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2945 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2953: \"$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*
+  ac_cv_header_stdc=yes
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 2970 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "memchr" >/dev/null 2>&1; then
+  :
+else
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 2988 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "free" >/dev/null 2>&1; then
+  :
+else
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+  :
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3009 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:3020: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  :
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+  cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+echo $ac_n "checking for pid_t""... $ac_c" 1>&6
+echo "configure:3044: checking for pid_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3049 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "(^|[^a-zA-Z_0-9])pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_type_pid_t=yes
+else
+  rm -rf conftest*
+  ac_cv_type_pid_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_pid_t" 1>&6
+if test $ac_cv_type_pid_t = no; then
+  cat >> confdefs.h <<\EOF
+#define pid_t int
+EOF
+
+fi
+
+ac_safe=`echo "vfork.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for vfork.h""... $ac_c" 1>&6
+echo "configure:3078: checking for vfork.h" >&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
+#line 3083 "configure"
+#include "confdefs.h"
+#include <vfork.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:3088: \"$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*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  cat >> confdefs.h <<\EOF
+#define HAVE_VFORK_H 1
+EOF
+
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for working vfork""... $ac_c" 1>&6
+echo "configure:3113: checking for working vfork" >&5
+if eval "test \"`echo '$''{'ac_cv_func_vfork_works'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+  echo $ac_n "checking for vfork""... $ac_c" 1>&6
+echo "configure:3119: checking for vfork" >&5
+if eval "test \"`echo '$''{'ac_cv_func_vfork'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3124 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char vfork(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char vfork();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_vfork) || defined (__stub___vfork)
+choke me
+#else
+vfork();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3147: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_vfork=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_vfork=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'vfork`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  :
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+ac_cv_func_vfork_works=$ac_cv_func_vfork
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3169 "configure"
+#include "confdefs.h"
+/* Thanks to Paul Eggert for this test.  */
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_VFORK_H
+#include <vfork.h>
+#endif
+/* On some sparc systems, changes by the child to local and incoming
+   argument registers are propagated back to the parent.
+   The compiler is told about this with #include <vfork.h>,
+   but some compilers (e.g. gcc -O) don't grok <vfork.h>.
+   Test for this by using a static variable whose address
+   is put into a register that is clobbered by the vfork.  */
+static
+#ifdef __cplusplus
+sparc_address_test (int arg)
+#else
+sparc_address_test (arg) int arg;
+#endif
+{
+  static pid_t child;
+  if (!child) {
+    child = vfork ();
+    if (child < 0) {
+      perror ("vfork");
+      _exit(2);
+    }
+    if (!child) {
+      arg = getpid();
+      write(-1, "", 0);
+      _exit (arg);
+    }
+  }
+}
+main() {
+  pid_t parent = getpid ();
+  pid_t child;
+
+  sparc_address_test ();
+
+  child = vfork ();
+
+  if (child == 0) {
+    /* Here is another test for sparc vfork register problems.
+       This test uses lots of local variables, at least
+       as many local variables as main has allocated so far
+       including compiler temporaries.  4 locals are enough for
+       gcc 1.40.3 on a Solaris 4.1.3 sparc, but we use 8 to be safe.
+       A buggy compiler should reuse the register of parent
+       for one of the local variables, since it will think that
+       parent can't possibly be used any more in this routine.
+       Assigning to the local variable will thus munge parent
+       in the parent process.  */
+    pid_t
+      p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(),
+      p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid();
+    /* Convince the compiler that p..p7 are live; otherwise, it might
+       use the same hardware register for all 8 local variables.  */
+    if (p != p1 || p != p2 || p != p3 || p != p4
+       || p != p5 || p != p6 || p != p7)
+      _exit(1);
+
+    /* On some systems (e.g. IRIX 3.3),
+       vfork doesn't separate parent from child file descriptors.
+       If the child closes a descriptor before it execs or exits,
+       this munges the parent's descriptor as well.
+       Test for this by closing stdout in the child.  */
+    _exit(close(fileno(stdout)) != 0);
+  } else {
+    int status;
+    struct stat st;
+
+    while (wait(&status) != child)
+      ;
+    exit(
+        /* Was there some problem with vforking?  */
+        child < 0
+
+        /* Did the child fail?  (This shouldn't happen.)  */
+        || status
+
+        /* Did the vfork/compiler bug occur?  */
+        || parent != getpid()
+
+        /* Did the file descriptor bug occur?  */
+        || fstat(fileno(stdout), &st) != 0
+        );
+  }
+}
+EOF
+if { (eval echo configure:3264: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_func_vfork_works=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_func_vfork_works=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_func_vfork_works" 1>&6
+if test $ac_cv_func_vfork_works = no; then
+  cat >> confdefs.h <<\EOF
+#define vfork fork
+EOF
+
+fi
+
+echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
+echo "configure:3287: checking return type of signal handlers" >&5
+if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3292 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+#undef signal
+#endif
+#ifdef __cplusplus
+extern "C" void (*signal (int, void (*)(int)))(int);
+#else
+void (*signal ()) ();
+#endif
+
+int main() {
+int i;
+; return 0; }
+EOF
+if { (eval echo configure:3309: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_type_signal=void
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_type_signal=int
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_type_signal" 1>&6
+cat >> confdefs.h <<EOF
+#define RETSIGTYPE $ac_cv_type_signal
+EOF
+
+
+
+echo $ac_n "checking for sqrt""... $ac_c" 1>&6
+echo "configure:3329: checking for sqrt" >&5
+if eval "test \"`echo '$''{'ac_cv_func_sqrt'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3334 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char sqrt(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char sqrt();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_sqrt) || defined (__stub___sqrt)
+choke me
+#else
+sqrt();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3357: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_sqrt=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_sqrt=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'sqrt`\" = yes"; then
+  
+  :
+else
+  
+LIBS="$LIBS -lm -lc"
+ac_cv_func_sqrt=no
+cat > conftest.$ac_ext <<EOF
+#line 3377 "configure"
+#include "confdefs.h"
+
+int main() {
+
+double sqrt(double);
+sqrt(2.0);
+
+; return 0; }
+EOF
+if { (eval echo configure:3387: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  ac_cv_func_sqrt="-lm -lc"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_func_sqrt" 1>&6
+
+
+# uses AC_TRY_RUN
+if test "$cross_compiling" = yes; then
+    echo "WARNING: cannot check for restartable system calls during cross compilation."
+else
+    echo $ac_n "checking for restartable system calls""... $ac_c" 1>&6
+echo "configure:3406: checking for restartable system calls" >&5
+if eval "test \"`echo '$''{'ac_cv_sys_restartable_syscalls'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+    { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3414 "configure"
+#include "confdefs.h"
+/* Exit 0 (true) if wait returns something other than -1,
+   i.e. the pid of the child, which means that wait was restarted
+   after getting the signal.  */
+#include <sys/types.h>
+#include <signal.h>
+ucatch (isig) { }
+main () {
+  int i = fork (), status;
+  if (i == 0) { sleep (3); kill (getppid (), SIGINT); sleep (3); exit (0); }
+  signal (SIGINT, ucatch);
+  status = wait(&i);
+  if (status == -1) wait(&i);
+  exit (status == -1);
+}
+
+EOF
+if { (eval echo configure:3432: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_sys_restartable_syscalls=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_sys_restartable_syscalls=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_sys_restartable_syscalls" 1>&6
+if test $ac_cv_sys_restartable_syscalls = yes; then
+  cat >> confdefs.h <<\EOF
+#define HAVE_RESTARTABLE_SYSCALLS 1
+EOF
+
+fi
+
+fi
+
+
+# ******************** GNUstep.sh-less compilation ********************
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# ******************** output *****************************************
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs.  It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already.  You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+  case `(ac_space=' '; set | grep ac_space) 2>&1` in
+  *ac_space=\ *)
+    # `set' does not quote correctly, so add quotes (double-quote substitution
+    # turns \\\\ into \\, and sed turns \\ into \).
+    sed -n \
+      -e "s/'/'\\\\''/g" \
+      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+    ;;
+  *)
+    # `set' quotes correctly as required by POSIX, so do not add quotes.
+    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+    ;;
+  esac >> confcache
+if cmp -s $cache_file confcache; then
+  :
+else
+  if test -w $cache_file; then
+    echo "updating cache $cache_file"
+    cat confcache > $cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[        ]*VPATH[        ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+  case "\$ac_option" in
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+    exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+  -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+    echo "$CONFIG_STATUS generated by autoconf version 2.13"
+    exit 0 ;;
+  -help | --help | --hel | --he | --h)
+    echo "\$ac_cs_usage"; exit 0 ;;
+  *) echo "\$ac_cs_usage"; exit 1 ;;
+  esac
+done
+
+ac_given_srcdir=$srcdir
+
+trap 'rm -fr `echo "config.h.in.sed:config.h.in config.mak gsfix.make    Foundation/libFoundation.make           Foundation/NSObject.h.in.sed:Foundation/NSObject.h.in           Foundation/lfmemory.h.in.sed:Foundation/lfmemory.h.in config.h:config.h.in.sed                 Foundation/NSObject.h:Foundation/NSObject.h.in.sed                  Foundation/lfmemory.h:Foundation/lfmemory.h.in.sed" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@MAKE@%$MAKE%g
+s%@OBJC_RUNTIME@%$OBJC_RUNTIME%g
+s%@OBJC_RUNTIME_FLAG@%$OBJC_RUNTIME_FLAG%g
+s%@BROKEN_COMPILER@%$BROKEN_COMPILER%g
+s%@BROKEN_BUILTIN_APPLY@%$BROKEN_BUILTIN_APPLY%g
+s%@NO_NESTED_FUNCTIONS@%$NO_NESTED_FUNCTIONS%g
+s%@PCCTS_CFLAGS@%$PCCTS_CFLAGS%g
+s%@HOST@%$HOST%g
+s%@HOST_CPU@%$HOST_CPU%g
+s%@HOST_VENDOR@%$HOST_VENDOR%g
+s%@HOST_OS@%$HOST_OS%g
+s%@TARGET@%$TARGET%g
+s%@TARGET_CPU@%$TARGET_CPU%g
+s%@TARGET_VENDOR@%$TARGET_VENDOR%g
+s%@TARGET_OS@%$TARGET_OS%g
+s%@STRUCT_ALIGNMENT@%$STRUCT_ALIGNMENT%g
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@MAJOR_VERSION@%$MAJOR_VERSION%g
+s%@MINOR_VERSION@%$MINOR_VERSION%g
+s%@SUBMINOR_VERSION@%$SUBMINOR_VERSION%g
+s%@GC_INCLUDE_DIR@%$GC_INCLUDE_DIR%g
+s%@GC_LIB@%$GC_LIB%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@target@%$target%g
+s%@target_alias@%$target_alias%g
+s%@target_cpu@%$target_cpu%g
+s%@target_vendor@%$target_vendor%g
+s%@target_os@%$target_os%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+s%@WITH_GNUSTEP@%$WITH_GNUSTEP%g
+s%@WITH_FFCALL@%$WITH_FFCALL%g
+s%@WITH_GC@%$WITH_GC%g
+s%@CC@%$CC%g
+s%@CPP@%$CPP%g
+s%@AR@%$AR%g
+s%@LD@%$LD%g
+s%@PERL@%$PERL%g
+s%@GNUSTEP_FLATTENED@%$GNUSTEP_FLATTENED%g
+s%@GNUSTEP_HOST@%$GNUSTEP_HOST%g
+s%@GNUSTEP_HOST_CPU@%$GNUSTEP_HOST_CPU%g
+s%@GNUSTEP_HOST_OS@%$GNUSTEP_HOST_OS%g
+s%@GNUSTEP_HOST_VENDOR@%$GNUSTEP_HOST_VENDOR%g
+s%@GNUSTEP_LOCAL_ROOT@%$GNUSTEP_LOCAL_ROOT%g
+s%@GNUSTEP_MAKEFILES@%$GNUSTEP_MAKEFILES%g
+s%@GNUSTEP_NETWORK_ROOT@%$GNUSTEP_NETWORK_ROOT%g
+s%@GNUSTEP_PATHLIST@%$GNUSTEP_PATHLIST%g
+s%@GNUSTEP_ROOT@%$GNUSTEP_ROOT%g
+s%@GNUSTEP_SYSTEM_ROOT@%$GNUSTEP_SYSTEM_ROOT%g
+s%@GNUSTEP_USER_ROOT@%$GNUSTEP_USER_ROOT%g
+s%@LIBRARY_COMBO@%$LIBRARY_COMBO%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+  if test $ac_beg -gt 1; then
+    sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+  else
+    sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+  fi
+  if test ! -s conftest.s$ac_file; then
+    ac_more_lines=false
+    rm -f conftest.s$ac_file
+  else
+    if test -z "$ac_sed_cmds"; then
+      ac_sed_cmds="sed -f conftest.s$ac_file"
+    else
+      ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+    fi
+    ac_file=`expr $ac_file + 1`
+    ac_beg=$ac_end
+    ac_end=`expr $ac_end + $ac_max_sed_cmds`
+  fi
+done
+if test -z "$ac_sed_cmds"; then
+  ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"config.h.in.sed:config.h.in config.mak gsfix.make          Foundation/libFoundation.make           Foundation/NSObject.h.in.sed:Foundation/NSObject.h.in           Foundation/lfmemory.h.in.sed:Foundation/lfmemory.h.in"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+  # Remove last slash and all that follows it.  Not all systems have dirname.
+  ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+  if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+    # The file is in a subdirectory.
+    test ! -d "$ac_dir" && mkdir "$ac_dir"
+    ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+    # A "../" for each directory in $ac_dir_suffix.
+    ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+  else
+    ac_dir_suffix= ac_dots=
+  fi
+
+  case "$ac_given_srcdir" in
+  .)  srcdir=.
+      if test -z "$ac_dots"; then top_srcdir=.
+      else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+  /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+  *) # Relative path.
+    srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+    top_srcdir="$ac_dots$ac_given_srcdir" ;;
+  esac
+
+
+  echo creating "$ac_file"
+  rm -f "$ac_file"
+  configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+  case "$ac_file" in
+  *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+  *) ac_comsub= ;;
+  esac
+
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([  ]*\)#\([        ]*define[       ][      ]*\)'
+ac_dB='\([     ][      ]*\)[^  ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([  ]*\)#\([        ]*\)undef\([    ][      ]*\)'
+ac_uB='\([     ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([  ]*\)#\([        ]*\)undef\([    ][      ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+  CONFIG_HEADERS="config.h:config.h.in.sed              Foundation/NSObject.h:Foundation/NSObject.h.in.sed                  Foundation/lfmemory.h:Foundation/lfmemory.h.in.sed"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  echo creating $ac_file
+
+  rm -f conftest.frag conftest.in conftest.out
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  cat $ac_file_inputs > conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h.  And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[   ]*#[    ]*undef[        ][      ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+  ac_lines=`grep -c . conftest.vals`
+  # grep -c gives empty output for an empty file on some AIX systems.
+  if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+  # Write a limited-size here document to conftest.frag.
+  echo '  cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+  echo 'CEOF
+  sed -f conftest.frag conftest.in > conftest.out
+  rm -f conftest.in
+  mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+  rm -f conftest.vals
+  mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+  rm -f conftest.frag conftest.h
+  echo "/* $ac_file.  Generated automatically by configure.  */" > conftest.h
+  cat conftest.in >> conftest.h
+  rm -f conftest.in
+  if cmp -s $ac_file conftest.h 2>/dev/null; then
+    echo "$ac_file is unchanged"
+    rm -f conftest.h
+  else
+    # Remove last slash and all that follows it.  Not all systems have dirname.
+      ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+      if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+      # The file is in a subdirectory.
+      test ! -d "$ac_dir" && mkdir "$ac_dir"
+    fi
+    rm -f $ac_file
+    mv conftest.h $ac_file
+  fi
+fi; done
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+rm -f config.h.in.sed Foundation/NSObject.h.in.sed Foundation/lfmemory.h.in.sed
+# Read the variables from config.cache
+. ./config.cache
+
+# Create the output directory
+if test ! -d $ac_cv_file_output_prefix; then
+  ${srcdir}/mkinstalldirs $ac_cv_file_output_prefix
+fi
+
+# Move the config.h and config.mak over to the $ac_cv_file_output_prefix
+mv config.h   $ac_cv_file_output_prefix
+mv config.mak $ac_cv_file_output_prefix
+
+#
+# create the appropriate memory management file
+#
+mv -f Foundation/lfmemory.h $ac_cv_file_output_prefix
+
+# Create the NSException.h file to include a file in
+#      $ac_cv_file_output_prefix
+# which is the actual exceptions definition file.
+(cd Foundation;
+  rm -f NSException.h;
+  echo "#include <real_exception_file.h>" >NSException.h)
+
+#
+# Now create the real_exception_file.h based upon the compiler support
+#
+rm -f Foundation/$ac_cv_file_output_prefix/real_exception_file.h
+if test ${ac_cv_nested_functions} = no; then
+  echo "creating $ac_cv_file_output_prefix/real_exception_file.h from ${srcdir}/Foundation/NSExceptionWithoutNested.h"
+  cp ${srcdir}/Foundation/NSExceptionWithoutNested.h $ac_cv_file_output_prefix/real_exception_file.h
+elif test ${ac_cv_broken_compiler} = yes; then
+  echo "creating $ac_cv_file_output_prefix/real_exception_file.h from ${srcdir}/Foundation/NSClassicException.h"
+  cp ${srcdir}/Foundation/NSClassicException.h $ac_cv_file_output_prefix/real_exception_file.h
+else
+  echo "creating $ac_cv_file_output_prefix/real_exception_file.h from ${srcdir}/Foundation/NSFuncallException.h"
+  cp ${srcdir}/Foundation/NSFuncallException.h $ac_cv_file_output_prefix/real_exception_file.h
+fi
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/libFoundation/configure.bat b/libFoundation/configure.bat
new file mode 100644 (file)
index 0000000..801ecc2
--- /dev/null
@@ -0,0 +1,5 @@
+@echo off
+echo Creating configuration files
+cp config.mak.win32 config.mak
+cp config.h.win32 config.h
+cp Foundation\NSFuncallException.h Foundation\NSException.h
diff --git a/libFoundation/configure.in b/libFoundation/configure.in
new file mode 100644 (file)
index 0000000..7a4a4fb
--- /dev/null
@@ -0,0 +1,345 @@
+AC_PREREQ(2.4)
+
+AC_INIT(${srcdir}/Foundation/NSObject.h.in)
+
+# ******************** GNUstep env ************************************
+
+if test "x$GNUSTEP_SYSTEM_ROOT" = "x"; then
+  AC_MSG_ERROR(Your GNUstep.sh is not sourced, please load GNUstep.sh prior running configure!)
+fi
+
+# ******************** version ****************************************
+
+# todo: read from Version file?
+MAJOR_VERSION=1
+MINOR_VERSION=0
+SUBMINOR_VERSION=73
+
+AC_SUBST(MAJOR_VERSION)
+AC_SUBST(MINOR_VERSION)
+AC_SUBST(SUBMINOR_VERSION)
+
+
+# ******************** options ****************************************
+
+AC_ARG_WITH(ffcall,[
+--with-ffcall
+    Use the ffcall library to implement dynamic invocation of methods. Note
+    the licensing restrictions of ffcall before enabling that switch !],
+ac_cv_use_ffcall=yes,
+ac_cv_use_ffcall=no
+)
+
+AC_ARG_WITH(gc,[
+--with-gc
+--with-gc=DIR
+    Use the Boehm's garbage collector for automatic memory management instead
+    of the normal OpenStep memory management policy.
+    Search in DIR for GC include files (eg DIR=objc leads to <objc/gc.h>)],
+[ac_cv_use_gc=yes; ac_cv_link_gc=yes;
+if [ test x${withval} != xyes ]; then
+    GC_INCLUDE_DIR="${withval}/"
+else
+    GC_INCLUDE_DIR=""
+fi
+],
+[ac_cv_use_gc=no; ac_cv_link_gc=no; GC_INCLUDE_DIR=""]
+)
+
+AC_ARG_WITH(gc-lib,[
+--with-gc-lib
+--with-gc-lib=LIB
+    Link against GC library LIB. The default is 'gc'. Do not specify
+    --with-gc-lib if you have the GC contained in some of your system
+    libraries (eg libobjc.a)],
+[ac_cv_link_gc=yes;
+if [ test x${withval} != xyes ]; then
+    GC_LIB="${withval}"
+else
+    GC_LIB="gc"
+fi
+],
+[ac_cv_link_gc=no; GC_LIB=""]
+)
+
+AC_SUBST(GC_INCLUDE_DIR)
+AC_SUBST(GC_LIB)
+
+
+# ******************** system type ************************************
+
+# Determine the host, build, and target systems
+CC_TARGET=$target # use --target value for CC, not the canonical form
+AC_CANONICAL_SYSTEM
+AC_PREFIX_DEFAULT(/usr/local)
+
+AC_CONFIG_HEADER(config.h:config.h.in.sed dnl
+                Foundation/NSObject.h:Foundation/NSObject.h.in.sed dnl
+                 Foundation/lfmemory.h:Foundation/lfmemory.h.in.sed)
+
+# check for cross compilation
+
+if [[ x$target = xNONE ]]; then
+  set target $host
+fi
+
+if test "x$host" != "x$target"; then
+       cross_defines="CROSS=-DCROSS_COMPILE"
+        cross_compiling="yes"
+        echo "cross compiling from $host to $target .."
+        CC=${CC_TARGET}-gcc
+        LD=${CC_TARGET}-ld
+        AR=${CC_TARGET}-ar
+        RANLIB=${CC_TARGET}-ranlib
+fi
+
+changequote(,)dnl
+case "x${host_cpu}" in
+    xi[456]86*)        host_cpu=i386;;
+    xhppa1.1)  host_cpu=hppa;;
+esac
+
+if test "x$cross_compiling" = xyes; then
+  case "x${target_cpu}" in
+    xi[456]86*)        target_cpu=i386;;
+    xhppa1.1)  target_cpu=hppa;;
+  esac
+else
+  target_cpu=${host_cpu}
+  target_os=${host_os}
+  target_vendor=${host_vendor}
+fi
+
+case "x${target_os}" in
+  xfreebsd*) target_os=freebsd;;
+esac
+
+changequote([,])dnl
+
+# Assign the HOST/TARGET variables for sharedlib.mak
+HOST=$host
+HOST_CPU=$host_cpu
+HOST_VENDOR=$host_vendor
+HOST_OS=$host_os
+TARGET=$target
+TARGET_CPU=$target_cpu
+TARGET_VENDOR=$target_vendor
+TARGET_OS=$target_os
+
+if test ! -f ${srcdir}/config/${target_cpu}/${target_os}.h; then
+    if test -d ${srcdir}/config/${target_cpu}; then
+       echo
+       echo '*************** Warning ****************'
+       echo This package was not ported to $target_cpu running $target_os operating system.
+       echo We\'ll use the default configuration file ${srcdir}/config/$target_cpu/$target_cpu.h.
+       echo '****************************************'
+       echo
+       target_os=$target_cpu
+    else
+       echo
+       echo '*************** Warning ****************'
+       echo This package was not ported to $target_cpu running $target_os operating system.
+       echo We\'ll use a generic configuration file, thus you will be able to compile the library, but most probably the NSInvocation, NSMethodSignature and all classes that use them will not work correctly or will not work at all.
+       echo '****************************************'
+       target_cpu=generic
+       target_os=generic
+    fi
+fi
+
+
+# ******************** autoconf vars **********************************
+
+AC_SUBST(WITH_GNUSTEP)
+WITH_GNUSTEP=yes
+AC_DEFINE(WITH_GNUSTEP)
+
+AC_SUBST(WITH_FFCALL)
+WITH_FFCALL=$ac_cv_use_ffcall
+if test "x$ac_cv_use_ffcall" = xyes; then
+  AC_DEFINE(WITH_FFCALL)
+fi
+
+AC_SUBST(WITH_GC)
+WITH_GC=$ac_cv_use_gc
+if test "$WITH_GC" = yes; then
+  AC_DEFINE(LIB_FOUNDATION_BOEHM_GC)
+fi
+
+AC_PROG_CC
+if test "x$cross_compiling" = xyes; then
+        echo "cross compiling to $target"
+fi
+
+
+# ******************** system tools ***********************************
+
+AC_ISC_POSIX
+AC_PROG_CPP
+AC_CHECK_PROGS(MAKE, gmake gnumake make)
+AC_CHECK_PROGS(AR, ar)
+AC_CHECK_PROGS(LD, ld)
+AC_CHECK_PROGS(PERL, perl)
+
+# uses AC_TRY_RUN
+
+if test "x$cross_compiling" = xyes; then
+  if [[ "x${target_cpu}" = xi386 ]]; then
+    echo "WARNING: using predefined structure alignment of 4 for i386 !"
+    ac_cv_struct_alignment=4
+    STRUCT_ALIGNMENT=4
+  elif [[ "x${target_cpu}" = xsparc ]]; then
+    echo "WARNING: using predefined structure alignment of 8 for ${target_cpu} !"
+    ac_cv_struct_alignment=8
+    STRUCT_ALIGNMENT=8
+  elif [[ "x${target_cpu}" = xmipsel ]]; then
+    echo "WARNING: using predefined structure alignment of 8 for ${target_cpu} !"
+    ac_cv_struct_alignment=8
+    STRUCT_ALIGNMENT=8
+  else
+    echo "ERROR: unknown structure alignment for CPU ${target_cpu}, using 4 !"
+    ac_cv_struct_alignment=4
+    STRUCT_ALIGNMENT=4
+  fi
+else
+  AC_STRUCT_ALIGNMENT
+fi
+
+AC_CHECK_LIB(dl, dlopen)
+AC_CHECK_LIB(pcthread, pthread_create,
+           ,
+           AC_CHECK_LIB(pthread, pthread_create))
+AC_CHECK_LIB(m,      sqrt)
+AC_CHECK_LIB(nsl,    chown)
+AC_CHECK_LIB(socket, accept)
+
+RUNTIME=GNU
+transformed_target_cpu=`${GNUSTEP_SYSTEM_ROOT}/Makefiles/clean_cpu.sh ${TARGET_CPU}`
+ac_cv_file_output_prefix=Foundation/$transformed_target_cpu/${TARGET_OS}/$RUNTIME
+
+
+AC_CHECK_NESTED_FUNCTIONS
+AC_BROKEN_COMPILER
+
+if test $target_cpu = i386; then
+    AC_BROKEN_BUILTIN_APPLY
+fi
+
+# If we're using the Boehm's GC check to see if we have the gc.h file and
+# libgc.a installed.
+AC_DEFINE(WITH_GC)
+AC_HAVE_HEADERS(${GC_INCLUDE_DIR}gc.h)
+
+if test "x$ac_cv_link_gc" = xyes; then
+    AC_CHECK_LIB(${GC_LIB}, GC_malloc)
+    if test "x$ac_cv_header_gc_h" != xyes -o "x$ac_cv_lib_gc_GC_malloc" != xyes; then
+       changequote(,)
+       AC_MSG_ERROR(It appears your system doesn't have the Boehm's garbage collector installed! Please install it first or check your paths in case it's already installed. Note that we expect the Boehm's GC library to be named so that linking using -lgc works; please be careful as the normal 'make' in Boehm's GC neither creates the library nor installs it. You should copy the files gc.h and gc.a in the appropriate directories and rename gc.a to libgc.a.)
+       changequote([,])
+    fi
+fi
+
+# uses AC_TRY_RUN
+if test x"$cross_compiling" = xyes; then
+    echo "WARNING: cannot check for byte-order during cross compilation."
+else
+    AC_C_BIGENDIAN
+fi
+
+AC_COMPILE_CHECK_SIZEOF(short)
+AC_COMPILE_CHECK_SIZEOF(int)
+AC_COMPILE_CHECK_SIZEOF(long)
+AC_COMPILE_CHECK_SIZEOF(long long)
+AC_COMPILE_CHECK_SIZEOF(float)
+AC_COMPILE_CHECK_SIZEOF(double)
+AC_COMPILE_CHECK_SIZEOF(long double)
+
+AC_HEADER_DIRENT
+AC_HAVE_HEADERS(dir.h libc.h sys/time.h stdlib.h memory.h string.h dnl
+               strings.h sys/stat.h sys/vfs.h sys/statfs.h sys/statvfs.h dnl
+               netinet/in.h windows.h dnl
+               Windows32/Sockets.h pwd.h process.h grp.h sys/param.h dnl
+               sys/file.h sys/errno.h sys/select.h)
+AC_HEADER_SYS_WAIT
+
+AC_CHECK_FUNCS(memcpy ualarm getcwd getuid getpwnam getpwuid kill raise dnl
+              getpagesize statvfs chown symlink readlink opendir fsync dnl
+              sysconf GetSystemInfo gettimeofday GetLocalTime sigsetmask dnl
+              sigset sigaction sighold dnl
+               gethostbyname_r gethostbyaddr_r gethostent_r)
+AC_FUNC_MMAP
+AC_FUNC_VFORK
+AC_TYPE_SIGNAL
+
+AC_CHECK_MATH_LIB
+
+# uses AC_TRY_RUN
+if test "$cross_compiling" = yes; then
+    echo "WARNING: cannot check for restartable system calls during cross compilation."
+else
+    AC_SYS_RESTARTABLE_SYSCALLS
+fi
+
+
+# ******************** GNUstep.sh-less compilation ********************
+
+AC_SUBST(GNUSTEP_FLATTENED)
+AC_SUBST(GNUSTEP_HOST)
+AC_SUBST(GNUSTEP_HOST_CPU)
+AC_SUBST(GNUSTEP_HOST_OS)
+AC_SUBST(GNUSTEP_HOST_VENDOR)
+AC_SUBST(GNUSTEP_LOCAL_ROOT)
+AC_SUBST(GNUSTEP_MAKEFILES)
+AC_SUBST(GNUSTEP_NETWORK_ROOT)
+AC_SUBST(GNUSTEP_PATHLIST)
+AC_SUBST(GNUSTEP_ROOT)
+AC_SUBST(GNUSTEP_SYSTEM_ROOT)
+AC_SUBST(GNUSTEP_USER_ROOT)
+AC_SUBST(LIBRARY_COMBO)
+
+
+# ******************** output *****************************************
+
+AC_OUTPUT(config.h.in.sed:config.h.in config.mak gsfix.make dnl
+         Foundation/libFoundation.make dnl
+         Foundation/NSObject.h.in.sed:Foundation/NSObject.h.in dnl
+          Foundation/lfmemory.h.in.sed:Foundation/lfmemory.h.in,
+[rm -f config.h.in.sed Foundation/NSObject.h.in.sed Foundation/lfmemory.h.in.sed
+# Read the variables from config.cache
+. ./config.cache
+
+# Create the output directory
+if test ! -d $ac_cv_file_output_prefix; then
+  ${srcdir}/mkinstalldirs $ac_cv_file_output_prefix
+fi
+
+# Move the config.h and config.mak over to the $ac_cv_file_output_prefix
+mv config.h   $ac_cv_file_output_prefix
+mv config.mak $ac_cv_file_output_prefix
+
+#
+# create the appropriate memory management file
+#
+mv -f Foundation/lfmemory.h $ac_cv_file_output_prefix
+
+# Create the NSException.h file to include a file in
+#      $ac_cv_file_output_prefix
+# which is the actual exceptions definition file.
+(cd Foundation;
+  rm -f NSException.h;
+  echo "#include <real_exception_file.h>" >NSException.h)
+
+#
+# Now create the real_exception_file.h based upon the compiler support
+#
+rm -f Foundation/$ac_cv_file_output_prefix/real_exception_file.h
+if test ${ac_cv_nested_functions} = no; then
+  echo "creating $ac_cv_file_output_prefix/real_exception_file.h from ${srcdir}/Foundation/NSExceptionWithoutNested.h"
+  cp ${srcdir}/Foundation/NSExceptionWithoutNested.h $ac_cv_file_output_prefix/real_exception_file.h
+elif test ${ac_cv_broken_compiler} = yes; then
+  echo "creating $ac_cv_file_output_prefix/real_exception_file.h from ${srcdir}/Foundation/NSClassicException.h"
+  cp ${srcdir}/Foundation/NSClassicException.h $ac_cv_file_output_prefix/real_exception_file.h
+else
+  echo "creating $ac_cv_file_output_prefix/real_exception_file.h from ${srcdir}/Foundation/NSFuncallException.h"
+  cp ${srcdir}/Foundation/NSFuncallException.h $ac_cv_file_output_prefix/real_exception_file.h
+fi
+])
diff --git a/libFoundation/debian/changelog b/libFoundation/debian/changelog
new file mode 100644 (file)
index 0000000..04edda4
--- /dev/null
@@ -0,0 +1,6 @@
+libfoundation1.0 (1.0r24-1) experimental; urgency=low
+
+  * Initial Release.
+
+ -- Sebastian Ley <ley@debian.org>  Tue, 28 Sep 2004 15:55:26 +0200
+
diff --git a/libFoundation/debian/compat b/libFoundation/debian/compat
new file mode 100644 (file)
index 0000000..b8626c4
--- /dev/null
@@ -0,0 +1 @@
+4
diff --git a/libFoundation/debian/control b/libFoundation/debian/control
new file mode 100644 (file)
index 0000000..2964f19
--- /dev/null
@@ -0,0 +1,53 @@
+Source: libfoundation1.0
+Priority: extra
+Maintainer: Sebastian Ley <ley@debian.org>
+Build-Depends: debhelper (>= 4.0.0), dpatch, gnustep-make-ogo, gobjc | objc-compiler, libobjc-lf-dev
+Standards-Version: 3.6.1
+
+Package: libfoundation1.0-dev
+Section: libdevel
+Architecture: any
+Provides: libfoundation-dev
+Conflicts: libfoundation-dev
+Depends: libfoundation1.0 (= ${Source-Version})
+Description: Development files for libfoundation
+ LibFoundation is a library that provides an almost complete
+ implementation of the OpenStep specification plus many other extensions
+ that can be found in the Apple's MacOS X Foundation library.
+ .
+ This package contains the development files of libFoundation.
+
+Package: libfoundation1.0
+Section: libs
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, libfoundation-data
+Description: Implementation of the OpenStep specification
+ LibFoundation is a library that provides an almost complete
+ implementation of the OpenStep specification plus many other extensions
+ that can be found in the Apple's MacOS X Foundation library.
+ .
+ This package contains the shared library.
+
+Package: libfoundation-data
+Section: misc
+Architecture: all
+Description: Static data files used by libFoundation
+ LibFoundation is a library that provides an almost complete
+ implementation of the OpenStep specification plus many other extensions
+ that can be found in the Apple's MacOS X Foundation library.
+ .
+ This package contains some data needed by libFoundation, for
+ instance timezone information.
+
+Package: libfoundation-tools
+Section: misc
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Description: Configuration tools for libFoundation
+ LibFoundation is a library that provides an almost complete
+ implementation of the OpenStep specification plus many other extensions
+ that can be found in the Apple's MacOS X Foundation library.
+ .
+ This package contains tools shipped with libFoundation. Presently the
+ only tool is the "Defaults" program, used to read and store values
+ in libFoundation's configuration databases.
diff --git a/libFoundation/debian/copyright b/libFoundation/debian/copyright
new file mode 100644 (file)
index 0000000..30517df
--- /dev/null
@@ -0,0 +1,29 @@
+This package was debianized by Sebastian Ley <ley@debian.org> on
+Mon, 24 Nov 2003 17:37:16 +0100.
+
+It was downloaded from http://www.opengroupware.org/sources
+
+The original authors of libFoundation are Mircea Oanceai
+<mircea@pathcom.com> and Ovidiu Predescu. Important contributions were 
+done by Helge Hess <helge.hess@opengroupware.org>.
+
+Copyright:
+
+Copyright (C) 1995, 1996, 1997, 1998 Ovidiu Predescu and Mircea Oancea.
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for ANY purpose and without fee is hereby granted, provided
+that the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation. This software may be included in any commercial product
+provided that its distribution contain the libFoundation copyright notice
+and this permission notice.
+
+We disclaim all warranties with regard to this software, including all
+implied warranties of merchantability and fitness, in no event shall
+we be liable for any special, indirect or consequential damages or any
+damages whatsoever resulting from loss of use, data or profits, whether in
+an action of contract, negligence or other tortious action, arising out of
+or in connection with the use or performance of this software.
+
diff --git a/libFoundation/debian/docs b/libFoundation/debian/docs
new file mode 100644 (file)
index 0000000..92a0fde
--- /dev/null
@@ -0,0 +1,5 @@
+NEWS
+README
+README.gc
+README.sparc
+TODO
diff --git a/libFoundation/debian/libfoundation-data.install b/libFoundation/debian/libfoundation-data.install
new file mode 100644 (file)
index 0000000..dd222db
--- /dev/null
@@ -0,0 +1 @@
+usr/share
diff --git a/libFoundation/debian/libfoundation-tools.install b/libFoundation/debian/libfoundation-tools.install
new file mode 100644 (file)
index 0000000..e772481
--- /dev/null
@@ -0,0 +1 @@
+usr/bin
diff --git a/libFoundation/debian/libfoundation-tools.links b/libFoundation/debian/libfoundation-tools.links
new file mode 100644 (file)
index 0000000..fdd2123
--- /dev/null
@@ -0,0 +1 @@
+usr/share/man/man7/undocumented.7.gz usr/share/man/man1/Defaults.1.gz
diff --git a/libFoundation/debian/libfoundation1.0-dev.install b/libFoundation/debian/libfoundation1.0-dev.install
new file mode 100644 (file)
index 0000000..bc830ce
--- /dev/null
@@ -0,0 +1,3 @@
+usr/lib/*.so
+usr/include
+usr/lib/opengroupware.org/System/Library/Makefiles
diff --git a/libFoundation/debian/libfoundation1.0.install b/libFoundation/debian/libfoundation1.0.install
new file mode 100644 (file)
index 0000000..093956b
--- /dev/null
@@ -0,0 +1 @@
+usr/lib/*.so.*
diff --git a/libFoundation/debian/rules b/libFoundation/debian/rules
new file mode 100755 (executable)
index 0000000..4283b0a
--- /dev/null
@@ -0,0 +1,115 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# GNU copyright 1997 to 1999 by Joey Hess.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+# Include dpatch stuff.
+include /usr/share/dpatch/dpatch.make
+
+# These are used for cross-compiling and for saving the configure script
+# from having to guess our platform (since we know it already)
+DEB_HOST_GNU_TYPE   ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
+DEB_BUILD_GNU_TYPE  ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
+
+GNUSTEP_SETUP=/usr/lib/opengroupware.org/System/Library/Makefiles/GNUstep.sh
+
+CFLAGS = -Wall -g
+MAKE_FLAGS = messages=yes OPTFLAG=-O0
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+       CFLAGS += -O0
+else
+       CFLAGS += -O2
+endif
+ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
+       INSTALL_PROGRAM += -s
+endif
+
+config.status: configure
+       dh_testdir
+       CFLAGS="$(CFLAGS)" . $(GNUSTEP_SETUP); \
+               ./configure     --host=$(DEB_HOST_GNU_TYPE) \
+                               --build=$(DEB_BUILD_GNU_TYPE) \
+                               --with-gnustep
+
+build: build-stamp
+build-stamp:  config.status patch-stamp
+       dh_testdir
+
+       . $(GNUSTEP_SETUP); \
+               $(MAKE) $(MAKE_FLAGS) GNUSTEP_INSTALLATION_DIR=$(CURDIR)/debian/tmp/$$GNUSTEP_SYSTEM_ROOT
+
+       touch build-stamp
+
+clean: unpatch
+       dh_testdir
+       dh_testroot
+       rm -f build-stamp 
+
+       -. $(GNUSTEP_SETUP); $(MAKE) clean
+       -. $(GNUSTEP_SETUP); $(MAKE) distclean
+
+ifneq "$(wildcard /usr/share/misc/config.sub)" ""
+       cp -f /usr/share/misc/config.sub config.sub
+endif
+ifneq "$(wildcard /usr/share/misc/config.guess)" ""
+       cp -f /usr/share/misc/config.guess config.guess
+endif
+
+       dh_clean 
+
+install: build
+       dh_testdir
+       dh_testroot
+       dh_clean -k 
+       dh_installdirs
+
+       . $(GNUSTEP_SETUP); \
+               mkdir -p $(CURDIR)/debian/tmp/$$GNUSTEP_MAKEFILES/Additional
+
+       . $(GNUSTEP_SETUP); \
+               $(MAKE) $(MAKE_FLAGS) GNUSTEP_INSTALLATION_DIR=$(CURDIR)/debian/tmp/$$GNUSTEP_SYSTEM_ROOT \
+               INSTALL_ROOT_DIR=$(CURDIR)/debian/tmp install \
+               FHS_INSTALL_ROOT=$(CURDIR)/debian/tmp/usr
+               
+                       
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+       dh_testdir
+       dh_testroot
+       dh_installchangelogs ChangeLog
+       dh_installdocs
+       dh_installexamples
+       dh_install --sourcedir=debian/tmp
+#      dh_installmenu
+#      dh_installdebconf       
+#      dh_installlogrotate
+#      dh_installemacsen
+#      dh_installpam
+#      dh_installmime
+#      dh_installinit
+#      dh_installcron
+#      dh_installinfo
+       dh_installman
+       dh_link
+       dh_strip
+       dh_compress
+       dh_fixperms
+#      dh_perl
+#      dh_python
+       dh_makeshlibs -V
+       dh_installdeb
+       dh_shlibdeps  -L libfoundation1.0 -l debian/libfoundation1.0/usr/lib
+       dh_gencontrol
+       dh_md5sums
+       dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install 
diff --git a/libFoundation/doc/GNUmakefile b/libFoundation/doc/GNUmakefile
new file mode 100644 (file)
index 0000000..4e34f1b
--- /dev/null
@@ -0,0 +1,25 @@
+
+TEXI_FILES = libFoundation.texi
+
+DVI_FILES = $(TEXI_FILES:.texi=.dvi)
+HTML_FILES = $(foreach file, $(TEXI_FILES:.texi=), $(file)_toc.html)
+INFO_FILES = $(TEXI_FILES:.texi=.info)
+
+all: dvi html info
+
+dvi: $(DVI_FILES)
+html: $(HTML_FILES)
+info: $(INFO_FILES)
+
+%.dvi: %.texi
+       -texi2dvi $<
+
+$(HTML_FILES): $(TEXI_FILES)
+       -texi2html -split_node $<
+
+%.info: %.texi
+       -makeinfo $<
+
+clean distclean:
+       rm -f $(DVI_FILES) libFoundation_*.html $(INFO_FILES) \
+               *.aux *.cp *.fn *.ky *.log *.pg *.toc *.tp *.vr
diff --git a/libFoundation/doc/README b/libFoundation/doc/README
new file mode 100644 (file)
index 0000000..9dd8b28
--- /dev/null
@@ -0,0 +1,5 @@
+
+This directory contains documentation for libFoundation and also some
+Diagram2 files describing the hierachy of classes. The Postscript
+files are the printed versions of these file. The Diagram2 file were
+made available by Helge Hess <helge@mdlink.de>.
diff --git a/libFoundation/doc/libFoundation.texi b/libFoundation/doc/libFoundation.texi
new file mode 100644 (file)
index 0000000..3801f22
--- /dev/null
@@ -0,0 +1,1881 @@
+\input texinfo
+
+@c %**start of header
+@settitle libFoundation Library Manual
+@setfilename libFoundation.info
+@c %**end of header
+
+
+@set version 0.9.0
+@set update-month October 1998
+
+@ifinfo
+@format
+START-INFO-DIR-ENTRY
+* libFoundation::                      An OpenStep Foundation library.
+END-INFO-DIR-ENTRY
+@end format
+@end ifinfo
+
+@ifinfo
+This file documents the features of the libFoundation library.
+
+Copyright (C) 1995, 1996, 1997, 1998 Ovidiu Predescu and Mircea Oancea.
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for ANY purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation. This softare may be included in any commercial
+product provided that its distribution contain the libFoundation
+copyright notice and this permission notice.
+
+@sp 2
+
+The libFoundation Library Manual may be reproduced and distributed in
+whole or in part, in any medium, physical or electronic, so long as this
+copyright notice remains intact and unchanged on all copies.
+
+@end ifinfo
+
+
+@iftex
+@finalout
+@c @smallbook
+@end iftex
+
+@titlepage
+@title libFoundation Library Manual
+@subtitle for libFoundation version @value{version}
+@subtitle @value{update-month}
+@author by Ovidiu Predescu and Mircea Oancea 
+@page
+
+@vskip 0pt plus 1filll
+
+Copyright @copyright{} 1995, 1996, 1997, 1998 Ovidiu Predescu and Mircea
+Oancea.  All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for ANY purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation. This softare may be included in any commercial
+product provided that its distribution contain the libFoundation
+copyright notice and this permission notice.
+
+@sp 2
+
+The libFoundation Library Manual may be reproduced and distributed in
+whole or in part, in any medium, physical or electronic, so long as this
+copyright notice remains intact and unchanged on all copies.
+
+@end titlepage
+
+@tex
+\global\parindent 0pt
+\global\parskip 8pt plus 2pt
+@end tex
+
+
+
+@ifinfo
+@node   Top, Introduction, (dir), (dir)
+@comment node-name,    next,           previous,       up
+@top Top
+@end ifinfo
+
+@menu
+* Introduction::               About libFoundation and this documentation.
+* Coding with libFoundation::   How to write code for libFoundation.
+* Exception handling::          The extended exception handling mechanism.
+* Garbage collecting::          Two garbage collecting techniques.
+* NSZone::                      Implementation details.
+* NSInvocation::                Features of the NSInvocation class.
+* NSMethodSignature::           Features of the NSMethodSignature class.
+@end menu
+
+
+@c =========================================================================
+@node   Introduction, Coding with libFoundation, Top, Top
+@comment node-name, next, previous, up
+
+@chapter Introduction
+
+This document describes some of the features and particularities
+implemented in @emph{libFoundation}; they are also available in the
+FoundationExtensions library so that users of @emph{libFoundation} can
+use their code with other OpenStep Foundation implementations.
+
+This documentation does not provide yet a full description of all the
+classes throughout the library. However any documentation that describes
+the OpenStep's Foundation library should be good enough for the classes
+implemented by @emph{libFoundation}.
+
+Below are some resources that provide additional information about the
+OpenStep Foundation classes:
+
+@itemize @bullet
+
+@item
+The original OpenStep specification can be found at:
+
+@uref{http://www.gnustep.org/GNUOpenStep/OpenStepSpec/OpenStepSpec.html}.
+
+@item
+OPENSTEP/Rhapsody related documentation, you can find here a very good
+documentation for Foundation:
+
+@uref{http://developer.apple.com/techpubs/rhapsody/rhapsody.html}.
+
+@item
+The GNUstep site, @uref{http://www.gnustep.org} or the European
+mirror-site,
+
+@uref{http://www.nmr.embl-heidelberg.de/GNUstep}.
+
+@end itemize
+
+
+@c =========================================================================
+@node   Coding with libFoundation, Preprocessor defines, Introduction, Top
+@comment node-name, next, previous, up
+@chapter Coding with libFoundation
+
+There are some things one has to know when porting an OpenStep program
+to work with @emph{libFoundation}. These things do not change the
+general behavior of the program, they only make the program work
+properly with the library.
+
+@menu
+* Preprocessor defines::
+* Initializing your program::
+* Specifying the resources directory::
+* Objective-C runtime support::
+@end menu
+
+
+@c =========================================================================
+@node   Preprocessor defines, Initializing your program, Coding with libFoundation, Coding with libFoundation
+@comment node-name, next, previous, up
+
+@section Preprocessor defines
+
+@emph{libFoundation} defines some preprocessor values so you can check
+for them if you want to conditionally pass some code to the
+compiler. The following macros are defined in
+@code{Foundation/NSObject.h}:
+
+@example
+#define LIB_FOUNDATION_LIBRARY 1
+    
+#define LIB_FOUNDATION_MAJOR_VERSION 0
+#define LIB_FOUNDATION_MINOR_VERSION 9
+#define LIB_FOUNDATION_SUBMINOR_VERSION 0
+@end example
+
+If you want to include a portion of code that is specific to
+@emph{libFoundation} you should put it inside an @code{#ifdef}
+preprocessor command:
+
+@example
+#ifdef LIB_FOUNDATION_LIBRARY
+...
+#endif
+@end example
+
+This way you the code inside @code{#ifdef} is compiled only in the
+presence of @emph{libFoundation} and will not affect other libraries.
+
+Another macro which is defined only when the Boehm's garbage collector
+is used (@xref{Boehm garbage collector}) is
+@code{LIB_FOUNDATION_BOEHM_GC}. You can use it to check in your code
+whether the code is compiled with support for Boehm's garbage collector
+or not.
+
+@c =========================================================================
+@node   Initializing your program, Specifying the resources directory, Preprocessor defines, Coding with libFoundation
+@comment node-name, next, previous, up
+
+@section Initializing your program
+
+It is very important to properly initialize some @emph{libFoundation}
+internal data structures when the program starts. These information
+are mainly related to the @code{NSProcessInfo} class. Because not on all
+platforms is possible to find out the arguments and the environment
+variables passed to the program, we have chosen to explicitly delegate
+this task to user. The first lines in a @emph{libFoundation} program,
+before creating any other objects, should be the following:
+
+@example
+int main (int argc, char** argv, char** env)
+@{
+    /* Declarations here */
+...
+
+#ifdef LIB_FOUNDATION_LIBRARY
+    [NSProcessInfo initializeWithArguments:argv
+                   count:argc
+                   environment:env];
+#endif
+
+    /* Objects initialization and other instructions here */
+    ...
+@}
+@end example 
+
+@c =========================================================================
+@node   Specifying the resources directory, Objective-C runtime support, Initializing your program, Coding with libFoundation
+@comment node-name, next, previous, up
+
+@section Specifying the resources directory
+
+It is common to want to try the tests before you have installed the
+library in its default place. @emph{libFoundation} however requires to
+have access to the resource files to function correctly. You can install
+only the resources in the installation directory, but there is a more
+convenient way to let the library where are its resources. You can
+specify an environment variable that indicates where is the resource
+directory; the name of this variable is
+@code{LIB_FOUNDATION_RESOURCES_PATH} and it should indicate the
+@code{Resources} directory. In a @code{sh}-like shell for example, you can do:
+
+@example
+LIB_FOUNDATION_RESOURCES_PATH=/home/ovidiu\
+        /libFoundation-@value{version}/libFoundation/Resources
+export LIB_FOUNDATION_RESOURCES_PATH
+@end example
+
+This environment variable is similar with the @code{PATH} variable: you
+can specify more directories by separating them using @code{:}
+character. Specifying resource directories this way takes precedence
+over the default installation directory. You can use this to change the
+resources if you want.
+
+
+@c =========================================================================
+@node   Objective-C runtime support, Exception handling, Specifying the resources directory, Coding with libFoundation
+@comment node-name, next, previous, up
+
+@section Objective-C runtime support
+
+Currently there are two different Objective-C runtimes supported by
+@emph{libFoundation}: the original NeXT runtime and the GNU runtime
+which is modelled after it.
+
+The differences between the two runtimes resides mainly in the naming of
+functions. However there are differences that make the two runtimes
+incompatible. The most important one is how the selectors are kept.
+
+On NeXT runtime a selector is simply a unique string that represents its
+name. On GNU runtime, a selector is a structure consisting from a
+selector id (that is not its name) and a string describing its
+types. The both approaches have advantages and disadvantages. In the
+NeXT approach no matter how many times you request a selector (either
+using the @code{@@selector} directive or by @code{sel_getUid()}, you get
+the same selector. This is possible because the selector is simply
+represented as a unique string. On the GNU runtime each time you request
+a selector using the @code{@@selector} directive you get a different
+selector. Moreover the obtained selector has the @code{types} member set
+to @code{NULL}.
+
+In the NeXT approach the encoding of the selector's types are bound to
+each class that has a corresponding method. In the GNU approach the
+selector's types are bound to the selector.
+
+This differences have deep implication on how the @code{NSProxy} class
+handle a method call in the @code{forwardInvocation:} method. On the
+NeXT runtime, the proxy should make a request to the remote side to
+obtain the types of the method. The types are used locally by a
+@code{NSMethodSignature} object to determine an encoding. This encoding
+is used to access correctly the arguments on the stack. However you have
+the possibility to set a protocol to the @code{NSProxy} object at which
+the remote object answer. This should be done to avoid asking the true
+object about its selector types and so to increase performance.
+
+On the GNU runtime this is not necessarily because in the
+@code{forwardInvocation:} method the selector usually comes with types
+in it. However there are cases when this is not true and the same
+mechanism like in the NeXT case should be applied.
+
+Because the remote machine could be different than the local one, the
+@code{NSMethodSignature} class should be able to create the correct
+encoding from the types received from remote. Thus the
+@code{NSMethodSignature} class is dependent on the target machine.
+
+This implementation of Foundation works with both runtimes. The
+@code{extensions/objc-runtime.h} file defines the runtime functions to
+be those from the GNU runtime. All the NeXT runtime functions are
+defined in terms of GNU runtime functions.
+
+In order to write portable programs for both runtimes you should never
+use functions in the GNU runtime that work with the types associated
+with the selector. So the @code{sel_get_type}, @code{sel_get_any_uid}
+and @code{sel_get_typed_uid} cannot be used in programs. Also you should
+never use functions like @code{objc_msgSend} or
+@code{objc_msgSendv}. Use the @code{objc_msg_sendv} function or the
+@code{NSInvocation} class instead.
+
+Never use types like @code{Method} in the NeXT runtime or
+@code{Method_t} in the GNU runtime. Use instead the type @code{struct
+objc_method*}. This exists in both runtimes.
+
+
+@c =========================================================================
+@node   Exception handling, Garbage collecting, Objective-C runtime support, Top
+@comment node-name, next, previous, up
+
+@chapter Exception handling
+
+The exception handling mechanism provides several powerful features
+found in languages like C++ or Java. It extends the normal OpenStep
+exception handling, while still maintaining the backward compatibility
+with this. A program using the extended exception handling mechanism is
+still able to work with the normal OpenStep exception handling and
+viceversa.
+
+The first powerful feature is that you have exceptions grouped by
+classes. This means you can group exceptions in a hierarchy; not only
+a tree like but even as a general graph. This feature is present in
+C++ and with some restrictions in Java.
+
+Another feature is that the exception handler is called as a
+function. So if you are in debugger you can see the whole stack frame
+from the point that generated the exception up to the exception
+handler. So you are able to see what were the conditions that made the
+exception to be raised.
+
+The actual mechanism is based on nested functions, an extension to the
+C language. This extension is currently supported by the GNU C
+Compiler. The actual mechanism is written using macros, so there is no
+need for special support from the compiler.
+
+A code written using these macros looks like this:
+
+@example
+
+TRY @{
+    some code that can generate an exception
+@} END_TRY
+CATCH(ExceptionClass1) @{
+    code to handle an exception of class ExceptionClass1
+@}
+CATCH(ExceptionClass2) @{
+    code to handle an exception of class ExceptionClass2
+@}
+...
+OTHERWISE @{
+    catch all exceptions not handled above
+@}
+END_CATCH
+
+@end example
+
+In the @code{TRY} block the code that is supposed to generate an
+exception is executed. You can nest @code{TRY} blocks by entering other
+blocks of code in @code{TRY} blocks. All @code{TRY} blocks form a stack
+with the most recent @code{TRY} block which is executing on the top of
+the stack.
+
+If nothing happens during the execution of code inside a @code{TRY}
+block, the program continues with the first statement after the
+@code{END_CATCH} label. When this thing happens the topmost @code{TRY}
+block is popped off the exception handlers stack.
+
+To generate an exception you should allocate an exception object and
+pass it to the @code{THROW} function. This is called raising an
+exception. When an exception is raised the exception handler blocks are
+searched for the one that can @emph{catch} the exception. This means to
+find the first @code{CATCH} block that match the exception object
+class. This matching is done by sending the exception object the
+@code{exceptionIsKindOf:} message having as argument the class specified
+as parameter to @code{CATCH} block. If the result of this message is
+true then the @code{CATCH} block matches the exception.
+
+The @code{exceptionIsKindOf:} method is implemented at the
+@code{NSException} class to return the result of @code{isKindOf:}. So
+implicitly the exceptions are grouped after their inheritance
+hierarchy. Some specific exception classes could implement the
+@code{exceptionIsKindOf:} method and simulate a graph inheritance, which
+is like the multiple inheritance in C++.
+
+Inside the @code{CATCH} and @code{OTHERWISE} blocks you have one hidden
+parameter, the exception object, which has the name
+@code{localException}. You can do the following actions inside an
+exception handler:
+
+
+@itemize @bullet
+
+@item
+you can go immediately after the @code{END_CATCH} statement if it does
+not issue any of @code{RETURN} or @code{RETRY} statements
+
+@item
+you can reraise the exception by issuing the @code{RERAISE} if you want
+to generate an exception with the same object, or you can use
+@code{THROW} to generate an exception with a different object
+
+@end itemize
+
+
+You cannot execute a jump with the @code{goto} statement from the
+@code{TRY}, @code{CATCH} or @code{OTHERWISE} blocks outside them. These
+jumps are permitted only locally in the block. Also, do not return from
+@code{TRY} or @code{CATCH} blocks with ordinary return statements.
+
+You can jump outside the @code{TRY} block with the @code{BREAK}
+statement that will go to the first statement following the
+@code{END_CATCH} statement.
+
+Another construction allows you to specify a block of code that will be
+executed when an exception is caught by an upper exception handler. This
+allows you to do some cleanup, for example to release all the resources
+acquired from the system (such as memory allocation or file
+descriptors). This block is introduced by the @code{CLEANUP} label.
+
+Another construction is the @code{FINALLY} block. It is equivalent with
+the @code{finally} block in Java. The code inside this block is called
+whenever either an exception is raised and caught by an upper handler or
+when the code inside a @code{TRY} block runs successfully.
+
+The @code{FINALLY} construct is equivalent with the following @code{CLEANUP}
+construct:
+
+@example
+TRY @{
+    some code that can generate an exception
+@} END_TRY
+...
+CLEANUP @{
+    sequence of code
+@}
+END_CATCH
+the same sequence of code from inside the CLEANUP block
+@end example
+
+If several exception handlers are nested the order in which the cleanup
+and finally blocks are called is the same with the order in which the
+functions containing them will normally return.
+
+There are situations when you acquire some resources and you want to be
+sure that they are released in case of an exception that is caught above
+you in the stack frame. So you don' t need the @code{CATCH} or
+@code{OTHERWISE} blocks. You could simply write:
+
+@example
+TRY @{
+    some code that can generate an exception
+@} END_TRY
+CLEANUP @{
+    code to release acquired resources
+@}
+END_CATCH
+@end example
+
+You could use the @code{FINALLY} construct when the resource is acquired
+and also released in the same function. For example:
+
+@example
+acquire the resource
+TRY @{
+    some code that can generate an exception
+@}
+FINALLY @{
+    code to release the resource
+@}
+END_CATCH
+@end example
+
+With these constructions the exception handling macros has the
+following syntax:
+
+@example
+TRY @{
+    some code that can generate an exception
+@} END_TRY
+CATCH(ExceptionClass1) @{
+    code to handle an exception of class ExceptionClass1
+@}
+CATCH(ExceptionClass2) @{
+    code to handle an exception of class ExceptionClass2
+@}
+...
+OTHERWISE @{
+    catch all exceptions not handled above
+@}
+CLEANUP @{
+    ...
+@}
+FINALLY @{
+    ...
+@}
+END_CATCH
+@end example
+
+@section OpenStep exceptions
+
+The OpenStep exceptions are defined in the terms of the above macros.
+
+@example
+#define NS_DURING      TRY
+
+#define NS_HANDLER \
+    END_TRY \
+    OTHERWISE
+
+#define NS_ENDHANDLER   END_CATCH
+@end example
+
+In the actual implementation you can also use the @code{NS_VALRETURN}
+and @code{NS_VOIDRETURN} macros inside the @code{TRY} block,
+respectively inside @code{NS_DURING} block.
+
+When you use @code{NS_VALRETURN} or @code{NS_VOIDRETURN} macros inside a
+@code{TRY} block, be aware that before the function returns, the code
+inside all @code{FINALLY} blocks associated with the @code{TRY} block
+are executed first. However, because of a bug in the GNU compiler that
+causes the compiler to crash when it compiles Objective-C programs with
+nested functions for the NeXT runtime, this behavior is not implemented
+for the programs compiled with the NeXT runtime.
+
+
+@c =========================================================================
+@node   Garbage collecting, Garbage collector based on reference counting, Exception handling, Top
+@comment node-name, next, previous, up
+
+@chapter Garbage collecting
+
+Starting with version 0.9.0, @emph{libFoundation} comes with two garbage
+collecting mechanisms that provide you with the ability to solve the
+memory management problem.
+
+The first garbage collector works with the default memory management
+policy in OpenStep, the reference counting model. Reference counting is
+a simple model for keeping track of objects and works good enough unless
+you have cyclic data structures in your program, aka graphs of
+objects. These cyclic graphs of objects cannot be collected by the
+normal reference counting mechanism provided by OpenStep
+Foundation. @emph{libFoundation} comes with a garbage collector based on
+reference counting, that's fully integrated with the reference counting
+model in OpenStep Foundation.
+
+While reference counting is a simple and good technique for small to
+medium programs, it's usually hard to write programs using it because,
+as every human activity, is error-prone. The programmer can easily
+forget to retain or release an object, thus leading to memory leaks. A
+true garbage collector would solve the problem and would release the
+programmer from manually keeping track of the allocated
+memory. @emph{libFoundation} comes with support for Boehm's garbage
+collector, a conservative collector available from
+@uref{http://reality.sgi.com/boehm_mti/gc.html}.
+
+There is only one source tree for the both versions of the library, the
+normal OpenStep compatibility library and the support for the Boehm's
+garbage collector library. To build the last type of library you just
+have to type:
+
+@example
+  $ make gc=yes
+@end example
+
+This will build and install the library in a separate directory in the
+GNUstep system tree. For all the GNUstep package that you want to run in
+a garbage collected environment you will have to add @samp{gc=yes} as an
+additional argument to make.
+
+The next chapter present the garbage collector based on reference
+counting. The classes and protocols presented here are only useful when
+the garbage collector based on reference counting is used.
+
+@menu
+* Garbage collector based on reference counting::
+* Boehm garbage collector::
+@end menu
+
+@c =========================================================================
+@node   Garbage collector based on reference counting, The GarbageCollector class, Garbage collecting, Garbage collecting
+@comment node-name, next, previous, up
+
+@section Garbage collector based on reference counting
+
+@emph{libFoundation} contains some classes that allow you to write code
+without explicitly managing cyclic references between objects. Usually
+you have to manage explicitly the reference counts when you have objects
+that form cyclic graphs.
+
+The garbage collector neither maintains explicitly all the pointers in
+your program nor it collects all the memory allocated by you in the
+program. Instead it collects and maintains only some special kind of
+objects, that are garbage collectable.
+
+The algorithm was inspired from a similar one found in the OATH C++
+library written by Brian M. Kennedy's @w{@email{bmk@@csc.ti.com}}. It
+works in three passes. Suppose that all the objects that are garbage
+collectable are known. Also each object has an additional flag, used for
+determining if the object was already visited.
+
+During the first pass, all objects that are garbage collectable clears
+the associated flag and receive the message
+@code{-gcDecrementRefCountOfContainedObjects}. In this method the object
+decrements the reference count of every garbage collectable object it
+contains. After this pass all the objects that have the reference count
+0 are part of cyclic graphs. Such objects have their reference count due
+only to another objects from graph.
+
+In the second pass we have to restore the original reference counts and
+to isolate the nodes from cyclic graphs. In this pass all the objects
+that have the reference count greater than 0 receive the message
+@code{-gcIncrementRefCountOfContainedObjects}. In this method the object
+check the flag if it's set. This flag tells if the object was visited
+previously. If the flag is set, the method returns, else the flag is
+set. Then the reference count of every garbage collectable object
+contained is incremented and the message
+@code{-gcIncrementRefCountOfContainedObjects} is sent to those objects.
+
+After this pass all the objects that are reachable from `outside' have
+their reference count greater than 0. All the objects that still have
+their reference count equal with 0 are part of cyclic graphs and there is no
+reference from `outside' to an object from these graphs.
+
+In the third pass all the objects that have their reference count equal
+with 0 receive the @code{-dealloc} message. In this method the objects
+should send the @code{-release} message to all contained objects that
+are not garbage collectable. This because the order of deallocation is
+not known and you can send @code{-release} to an already deallocated
+object. So if a class contains both normal objects and garbage
+collectable objects, it should maintain their collectable status when
+the objects are retained.
+
+@menu
+* The GarbageCollector class::
+* The GarbageCollector protocol::
+* Support classes::
+@end menu
+
+@c =========================================================================
+@node   The GarbageCollector class, The GarbageCollector protocol, Garbage collector based on reference counting, Garbage collector based on reference counting
+@comment node-name, next, previous, up
+
+@subsection The @code{GarbageCollector} class
+
+The class @code{GarbageCollector} implements the garbage collector. It
+has the following interface:
+
+@example
+@@interface GarbageCollector : NSObject
+
++ (void)addObject:(id)anObject;
++ (void)objectWillBeDeallocated:(id)anObject;
+
++ (void)collectGarbages;
+
+@@end
+@end example
+
+A new garbage collectable object has to be made know to the
+@code{GarbageCollector} collector by sending it the @code{+addObject:}
+message with self as argument. When the object is deallocated it should
+inform the @code{GarbageCollector} class about this by sending it the
+@code{+objectWillBeDeallocated:} message with self as argument.
+
+The @code{+collectGarbages} should be send to the
+@code{GarbageCollector} class to collect the garbages. You can send it
+whenever you want. If you are using a run loop in your program you can
+set a timer to be called periodically. Or you can call the garbage
+collector when the program is idle.
+
+In the current implementation the garbage collector is not
+thread-safe, so please don't use it in multi-threaded programs, unless
+you use garbage collectable objects only in one thread.
+
+
+@c =========================================================================
+@node   The GarbageCollector protocol, Support classes, The GarbageCollector class, Garbage collector based on reference counting
+@comment node-name, next, previous, up
+
+@subsection The @code{GarbageCollecting} protocol
+
+To allow instances of a class to be garbage collectable, the class
+should implement the following protocol:
+
+@example
+@@protocol GarbageCollecting
+
+- gcSetNextObject:(id)anObject;
+- gcSetPreviousObject:(id)anObject;
+- (id)gcNextObject;
+- (id)gcPreviousObject;
+
+- (void)gcIncrementRefCount;
+- (void)gcDecrementRefCount;
+
+- (void)gcDecrementRefCountOfContainedObjects;
+- (BOOL)gcIncrementRefCountOfContainedObjects;
+
+- (BOOL)isGarbageCollectable;
+
+@@end
+@end example
+
+The @code{GarbageCollector} class uses a double linked list to maintain
+the objects. The @code{gcSetNextObject:}, @code{gcSetPreviousObject:},
+@code{gcNextObject} and @code{gcPreviousObject} are used by the
+collector to add or remove objects in its list. This could change in the
+future.
+
+The @code{gcIncrementRefCount} and @code{gcDecrementRefCount} methods
+should increment, respectively decrement the reference count of
+receiver.
+
+The @code{gcDecrementRefCountOfContainedObjects} method should decrement
+the reference count of all garbage collectable objects contained, by
+sending them the message @w{@code{-gcDecrementRefCount}} to them.
+
+The @code{gcIncrementRefCountOfContainedObjects} method should check the
+flag. If this is true, the method should return @code{NO}; it this is
+false the method should set it. Then it should increment the reference
+count of garbage collectable objects contained by sending them the
+@code{-gcIncrementRefCount} message. After this it should send the
+@code{-gcIncrementRefCountOfContainedObjects} message to the same
+objects. Then it should return @code{YES}.
+
+The object should respond @code{YES} at the @code{-isGarbageCollectable}
+message if it is garbage collectable. The NSObject class responds
+@code{NO} to this message.
+
+You should note the asymmetry between the
+@code{gcDecrementRefCountOfContainedObjects} and
+@code{gcIncrementRefCountOfContainedObjects} methods. This makes the
+algorithm to work. So be careful if you're using copy/paste operations
+to write them in your editor :-)!
+
+
+@c =========================================================================
+@node   Support classes, Boehm garbage collector, The GarbageCollector protocol, Garbage collector based on reference counting
+@comment node-name, next, previous, up
+
+@subsection Support classes
+
+There is a class @code{GCObject} from which you could inherit your own
+classes. This class implements the @code{GarbageCollecting} protocol.
+
+Using this class, you could write a class whose instances hold other
+objects. This class is safe to cyclic references. Here is its
+implementation:
+
+@example
+@@interface MyGCObject : GCObject
+@{
+    id object;
+    BOOL isGarbageCollectable;
+@}
+
+- (void)setObject:(id)anObject;
+- (id)object;
+
+@@end
+
+
+@@implementation MyGCObject
+
+- (void)setObject:(id)anObject
+@{
+    [anObject retain];
+    [object release];
+    object = anObject;
+    isGarbageCollectable = [object isGarbageCollectable];
+@}
+
+- (id)object
+@{
+    return object;
+@}
+
+- (void)decrementRefCountOfContainedObjects
+@{
+    [object gcDecrementRefCount];
+@}
+
+- (BOOL)incrementRefCountOfContainedObjects
+@{
+    if(![super incrementRefCountOfContainedObjects])
+        return NO;
+    [object gcIncrementRefCount];
+    [object incrementRefCountOfContainedObjects];
+    return YES;
+@}
+
+- (void)dealloc
+@{
+    if(!isGarbageCollectable)
+        [object release];
+    [super dealloc];
+@}
+
+@@end
+@end example
+
+There are also concrete subclasses of @code{NSArray} and
+@code{NSDictionary} named @code{GCArray} and @code{GCDictionary}
+respectively, together with their mutable classes @code{GCMutableArray}
+and @code{GCMutableDictionary}. Their instances could hold both normal
+and garbage collectable objects.
+
+
+
+@c =========================================================================
+@node   Boehm garbage collector, Atomic memory allocation, Support classes, Garbage collecting
+@comment node-name, next, previous, up
+
+@section Boehm's garbage collector
+
+Starting with version 0.9.0 @emph{libFoundation} comes with support for the
+Boehm's garbage collector. It is available from
+
+@uref{http://reality.sgi.com/boehm_mti/gc.html}
+
+It is a conservative garbage collector that works by replacing the
+system memory allocation routines
+(@code{malloc}/@code{calloc}/@code{realloc}) with the ones that come
+with the collector. The memory allocation works as before, you allocate
+memory using the @code{GC_malloc()} function instead of @code{malloc()},
+@code{GC_calloc()} instead of @code{calloc()} and @code{GC_realloc()}
+instead of @code{realloc()}. The difference comes from the fact that
+you're no longer required to call a @code{free} function. The collector
+takes care of no longer reachable portions of the allocated memory by
+monitoring the memory allocation of your program and trying to collect
+the garbages when certain conditions are met. You can also explicitly
+invoke the collection the garbages by calling the @code{GC_collect()}
+function.
+
+The collection can also occur in another thread on systems that support
+multi-threading. You can disable the collection in the main thread by
+setting the value of a variable (@code{GC_dont_gc}) and invoke the
+collection in a separate thread when you wish, perhaps on a time basis
+or when some other conditions are met.
+
+Another feature is that the collection can be done incrementally, ie not
+all the memory is collected at once. This can be done by calling the
+@code{GC_collect_a_little()} function. One can use this feature in the
+program's run loop of an interactive program to make sure the collection
+will not make the program stop while the collection is in progress.
+
+Memory allocation functions are described in @file{gc.h}.
+
+@menu
+* Atomic memory allocation::
+* Typed memory allocation::
+* Finalization::
+* GC support in GNU Objective-C::
+* GC support in libFoundation::
+* Useful macros::
+@end menu
+
+@c =========================================================================
+@node   Atomic memory allocation, Typed memory allocation, Boehm garbage collector, Boehm garbage collector
+@comment node-name, next, previous, up
+
+@subsection Atomic memory allocation
+
+The Boehm's garbage collector normally assumes that all the memory
+allocated potentially contains pointers. However this is not always
+true. For memory zones that one knows they don't contain pointers to
+other allocated memory, the @code{GC_malloc_atomic()} can be used. This
+function marks the returned memory zone as not containing any
+pointer. Use this function for allocating strings and memory zones that
+does not contain pointers.
+
+@c =========================================================================
+@node   Typed memory allocation, Finalization, Atomic memory allocation, Boehm garbage collector
+@comment node-name, next, previous, up
+
+@subsection Typed memory allocation
+
+There are many cases when the allocated memory may contain both data and
+pointers. In this case the memory can be allocated using the normal
+@code{GC_malloc()} function and let the collector assume that all the
+contained data are pointers. This is both inefficient and error-prone
+because it is possible, even with a small probability, that integers
+have the same value as an existing pointer, thus keeping a reference to
+a memory zone and preventing it to be deallocated.
+
+Fortunately there's a better approach for this. At the time of the
+allocation, it is possible to inform the collector where the pointers
+are located inside it. This mechanism is called @emph{typed memory}.
+
+To describe a memory zone a descriptor of it has to be constructed
+first. The @code{GC_make_descriptor()} function is used for this; it
+takes as arguments a bitmap describing the memory zone and the number of
+meaningful bits in the bitmap. The less signifiant bit in the bitmap
+corresponds to the first word in the memory zone.
+
+The descriptor returned by the @code{GC_make_descriptor()} function is
+then passed to the @code{GC_malloc_explicitly_typed()} or
+@code{GC_calloc_explicitly_typed()}functions to allocate a memory
+zone. One caveat though, the memory returned by these functions cannot
+be reallocated at a later point in time.
+
+The typed memory functions have their prototypes in the
+@file{gc_typed.h} file.
+
+@c =========================================================================
+@node   Finalization, GC support in GNU Objective-C, Typed memory allocation, Boehm garbage collector
+@comment node-name, next, previous, up
+
+@subsection Finalization
+
+The Boehm's collector provides a facility that allows a function to be
+called just before a memory zone is collected. The
+@code{GC_register_finalizer()} takes as arguments the function to be
+called when the memory zone is being collected, the address of the
+memory zone, a client data that's passed to the function when it is
+called together with the address of the memory zone. There two more
+arguments to this function, that are used as out arguments: the old
+finalizer function and the old client data. Pass @code{NULL} to these
+arguments if you're not interested in their values.
+
+Be careful with what you do in the finalizer function. In general don't
+assume that the finalizers are invoked in any particular order. More
+important @strong{don't do any memory allocation inside the finalizer
+function}. This would case the finalizer to be invoked again which is
+not probably what you want (this may be a bug in the collector).
+
+More explanation for the public functions can be found in both
+@file{gc.h} and @file{gc_typed.h}.
+
+@c =========================================================================
+@node   GC support in GNU Objective-C, GC support in libFoundation, Finalization, Boehm garbage collector
+@comment node-name, next, previous, up
+
+@subsection Boehm's garbage collector support in the GNU Objective-C compiler and runtime
+
+The GNU Objective-C runtime and compiler have been enhanced to support
+the Boehm's garbage collector. To gain speed and to be able to implement
+some special facilities like @strong{weak pointers} (pointers that are
+invisible to the garbage collector), the GNU Objective-C runtime uses
+typed memory to allocate all the instances of the classes.
+
+The typed memory descriptor for each class is computed once per class,
+immediately after the object has been initialized. The descriptor is
+computed from the information about instance variables available in the
+class. To correctly handle all the type information, the Objective-C
+encoding for bitfields has been changed to include description of the
+type holding the bitfield and the position of the bitfield inside the
+corresponding value.
+
+To mark a pointer inside an instance as a weak pointer, the function
+@code{class_ivar_set_gcinvisible()} from the GNU runtime should be
+used. This function takes as argument the class whose instances contain
+the weak pointer, the name of the instance variable and a boolean flag
+that marks or unmarks the instance variable as a weak pointer.
+
+See the documentation in the GNU Objective-C compiler for a description
+of the new encoding of bitfields and for an example of the
+@code{class_ivar_set_gcinvisible()} function.
+
+@c =========================================================================
+@node   GC support in libFoundation, Useful macros, GC support in GNU Objective-C, Boehm garbage collector
+@comment node-name, next, previous, up
+
+@subsection Boehm's garbage collector support in @emph{libFoundation}
+
+@emph{libFoundation} hides a lot of the interface with the Boehm's
+garbage collector by providing the same API for the memory management
+functions no matter what is the model used, the reference counting
+mechanism or the Boehm's garbage collector.
+
+The objects are allocated by the library using the normal
+@code{NSAllocateObject()} function. In the case of Boehm's garbage
+collector a typed memory object is properly allocated.
+
+Internally the memory allocation for things other than objects is
+performed using the @code{Malloc}, @code{Calloc}, @code{Realloc} and
+@code{Free} inline functions. There are also versions that are used to
+allocate atomic memory, @code{MallocAtomic} and
+@code{CallocAtomic}. These pseudo-functions are not exported but one can
+create similar functions for other libraries or applications.
+
+If you need to know when a given object will be finalized, you just have
+to make the class adopt the @code{GCFinalization} protocol. This
+protocol defines a single method, @code{-gcFinalize}, that is invoked by
+the garbage collector when an object is about to finalize.
+
+In addition to finalization, the @code{GarbageCollector} class provides
+a powerful mechanism that allows objects to be registered as observers
+of other objects finalization. Here are the specific methods:
+
+@example
+
+@@interface GarbageCollector (BoehmGCSupport)
+
++ (void)registerForFinalizationObserver:(id)observer
+  selector:(SEL)selector
+  object:(id)object;
++ (void)unregisterObserver:(id)observer
+  forObjectFinalization:(id)object;
+
+@@end
+
+@end example
+
+When the @code{observer} object is registered for observing the
+finalization of @code{object}, the @code{observer}'s method whose
+selector is represented by @code{selector} is automatically called when
+@code{object} is about to finalize.
+
+You can manually unregister an object as the observer of an object
+finalization by using the
+@code{+unregisterObserver:forObjectFinalization:} method. If you provide
+@code{nil} for the object then @code{observer} will be unregistered for
+all the objects it has been previously registered as observer.
+
+If an object registered as observer of another objects finalizes, the
+@code{GarbageCollector} class automatically unregisters the observer for
+all the objects it was observer. You don't have to take any special
+actions to remove the observer except if it's kept in the internal
+structures of your program. In this case you should register another
+object as an observer of the original's observer finalization and remove
+it from your structures. As you can see an object can be simultaneously
+both an observed and an observer object, there's no restriction in doing
+this.
+
+@c =========================================================================
+@node   Useful macros, NSZone, GC support in libFoundation, Boehm garbage collector
+@comment node-name, next, previous, up
+
+@subsection Useful macros
+
+When working with the Boehm's garbage collector, the messages used by
+the reference counting mechanism are obsolete and they simply introduce
+an unnecessary overhead. That's why instead of sending the
+@code{retain}, @code{release} and @code{autorelease} messages you'd
+better use the macros with the similar names, @code{RETAIN},
+@code{RELEASE} and @code{AUTORELEASE}. When the code is compiled with
+support for Boehm's garbage collector the correspondent messages are not
+sent at all.
+
+In addition to the above macros, another macro should be used to make
+the code cleaner. The @code{ASSIGN} macro can be used whenever an object
+value is assigned to an object variable and the old value of the
+variable needs to be release and the new value retained. The definition
+of this macro is:
+
+@example
+#define ASSIGN(object, value) \
+  (@{if (value) [value retain]; \
+    if (object) [object release]; \
+    object = value;@})
+@end example
+
+When Boehm's garbage collector is used the definition of the macro is
+simply:
+
+@example
+#define ASSIGN(object, value) \
+  object = value
+@end example
+
+Another macro can be used whenever the code requires the creation of an
+autorelease pool. This pool is not needed when the code works in the
+presence of Boehm's garbage collector. The macro is
+@code{CREATE_AUTORELEASE_POOL} and should be used as a variable
+definition and must placed the last in the variables definition
+list. Use the @code{RELEASE} macro to release the pool.
+
+The preprocessor define @code{LIB_FOUNDATION_BOEHM_GC} can be used to
+find out if the program is compiled with support for Boehm's garbage
+collector (@xref{Preprocessor defines} for other preprocessor
+defines). If you need to find out at runtime if the program was compiled
+with support for Boehm's collector you can access the read-only variable
+@code{_usesBoehmGC}.
+
+@c =========================================================================
+@node   NSZone, The NSZone class, Useful macros, Top
+@comment node-name, next, previous, up
+
+@chapter The @code{NSZone} class and memory allocation
+
+Object allocation is performed from @emph{zones} that group related
+objects in a zone of memory. A zone is represented in
+@emph{libFoundation} by an instance of a subclass of @code{NSZone}. A
+zone is an object that not only keeps the memory zone from which the
+objects are allocated, but also encapsulates the algorithms that manage
+the memory allocation from that zone.
+
+Traditionally, @code{NSZone} is implemented as a structure. In
+@emph{libFoundation}, @code{NSZone} is a class instead of a struct, and
+the related zone functions are static inline functions that invoke the
+corresponding methods of the zone instance. The idea behind the
+definition of the @code{NSZone} as a class and not as a struct is to
+offer the user of the library the possibility to build his own allocator
+and to let current and future allocators coexist.
+
+Currently three zones are available: @code{NSDefaultZone},
+@code{NSAllocDebugZone} and @code{StackZone}. The first two they can be
+used only through the @code{NSZone} class and not directly. When
+@emph{libFoundation} is compiled with support for the Boehm's garbage
+collector the allocation is done using only the collector's allocation
+functions and the entire mechanism described below for the @code{NSZone}
+classes is completely unused.
+
+When the program first starts a default zone is created
+automatically. This zone is either an instance of the
+@code{NSDefaultZone} or of the @code{NSAllocDebugZone} class, depending
+on the mode in which the program is run. If the program runs using the
+reference counting mechanism, the environment variable @code{ALLOCDEBUG}
+is checked. If the variable exists in your environment then the default
+zone will be an instance of @code{NSAllocDebugZone}. If this environment
+variable is not defined then an instance of @code{NSDefaultZone} becomes
+the default zone. If the program runs using the Boehm's garbage
+collector, no zones are used; for more information see @ref{Zones and
+garbage collection}.
+
+You can change the default zone from which the future objects will be
+allocated using the @code{setDefaultZone:} method. To do this you have
+to create an instance of the zone you want to allocate objects from and
+call the @code{+setDefaultZone:} method of @code{NSZone} with the new
+instance. The zones are kept into a stack, the most recent zone being
+passed to @code{setDefaultZone:} being the top of the stack. When you
+release a zone and it has to be deallocated, the zone is removed from
+the stack of zones. If the zone object happens to be the top of the
+stack, the zone under it becomes the new default zone.
+
+@menu
+* The NSZone class::
+* The NSZone functions::
+* The NSAllocDebugZone class::
+* Zones and garbage collection::
+@end menu
+
+
+@c =========================================================================
+@node   The NSZone class, The NSZone functions, NSZone, NSZone
+@comment node-name, next, previous, up
+
+@section The @code{NSZone} class
+
+@code{NSZone} is an abstract class that defines the basic behavior for
+all the memory allocators.
+
+@itemize @bullet
+
+@item
+@code{+(void)@strong{setDefaultZone}:(NSZone*)@emph{zone};}
+
+@quotation
+Sets the default zone from which the subsequent memory allocation takes
+place.
+@end quotation
+
+@item
+@code{+(NSZone*)@strong{defaultZone};}
+
+@quotation
+Returns the default zone.
+@end quotation
+
+@item
+@code{+(NSZone*)@strong{zoneFromPointer}:(void*)@emph{pointer};}
+
+@quotation
+Returns the zone from which @emph{pointer} was allocated. Care should be
+taken as the zones are asked (using @code{-pointerInZone:}) in order if
+the pointer was allocated by them. See the @code{-pointerInZone:} method
+description for more information.
+@end quotation
+
+@item
+@code{+(BOOL)@strong{checkZone};}
+
+@quotation
+Check the memory allocated by all the zones. See the @code{-checkZone}
+method description for more information.
+@end quotation
+
+@item
+@code{+(id)@strong{allocZoneInstance};}
+
+@quotation
+This is the low level method used to allocate a zone instance. This is
+used because allocation of zone instances is done in a special way to
+avoid the chicken and egg problem (from which zone a zone instance is
+allocated?)
+@end quotation
+
+@item
+@code{-(id)@strong{initForSize}:(unsigned)@emph{startSize} @strong{granularity}:(unsigned)@emph{granularity} @* @strong{canFree}:(BOOL)@emph{canFree};}
+
+@quotation
+This is the designated initialization method. Creates a zone that can
+allocate as much as @emph{startSize} memory initially. The memory can
+grow or shrink in increments of @emph{granularity}. If @emph{canFree} is
+set to @code{YES} the memory is freed when when @code{-free:} is sent,
+otherwise the memory is never freed.
+@end quotation
+
+@item
+@code{-(void*)@strong{malloc}:(unsigned)@emph{size};}
+
+@quotation
+Allocate a memory zone of @emph{size} bytes and return it. Returns
+@code{NULL} if this is not possible.
+@end quotation
+
+@item
+@code{-(void*)@strong{mallocAtomic}:(unsigned)@emph{size};}
+
+@quotation
+Similar with @code{-malloc:} but allocate a memory zone that's not
+searched by the garbage collector for pointers.
+@end quotation
+
+@item
+@code{-(void*)@strong{calloc}:(unsigned)@emph{numElems} @strong{byteSize}:(unsigned)@emph{byteSize};}
+
+@quotation
+Allocate a memory zone that holds @emph{numElems} elements, each of
+@emph{byteSize}, set all the bytes in it to @code{0} and return
+it. Returns @code{NULL} if the allocation fails.
+@end quotation
+
+@item
+@code{-(void*)@strong{callocAtomic}:(unsigned)@emph{numElems} @strong{byteSize}:(unsigned)@emph{byteSize};}
+
+@quotation
+Similar with @code{-calloc:byteSize:} but return a memory zone that's
+not searched by the garbage collector for pointers.
+@end quotation
+
+
+@item
+@code{-(void*)@strong{realloc}:(void*)@emph{pointer} @strong{size}:(unsigned)@emph{size};}
+
+@quotation
+Grow or shrink the size of the memory zone pointed to by @emph{pointer}
+to have the new size @emph{size}.
+@end quotation
+
+@item
+@code{-(void)@strong{recycle};}
+
+@quotation
+Frees the receiving zone after adding the still alive allocated zones to
+the default zone. Currently there are no zones in @emph{libFoundation}
+that implement this algorithm.
+@end quotation
+
+@item
+@code{-(BOOL)@strong{pointerInZone}:(void*)@emph{pointer};}
+
+@quotation
+Returns @code{YES} if @emph{pointer} points to a memory zone allocated
+by the receiving zone. Some zones are not able to reliably determine if
+the pointer is theirs or not. For example @code{NSDefaultZone} always
+returns true since few libc malloc implementation provide the capability
+to identify if a pointer is valid or not.
+@end quotation
+
+@item
+@code{-(void)@strong{freePointer}:(void*)@emph{pointer};}
+
+@quotation
+If the zone was initialized to free pointers, free the memory zone
+pointed to by @emph{pointer}. Otherwise do nothing.
+@end quotation
+
+@item
+@code{-(void)@strong{setName}:(NSString*)@emph{name};}
+
+@quotation
+Set the name of the receiving zone.
+@end quotation
+
+@item
+@code{-(NSString*)@strong{name};}
+
+@quotation
+Return the name of the receiving zone.
+@end quotation
+
+@item
+@code{-(BOOL)@strong{checkZone};}
+
+@quotation
+Checks the consistency of the memory allocated by the zone. Some
+classes, notably @code{NSAllocDebugZone}, when you request memory from
+them, they allocate more memory that is marked in a special way. In
+@code{-checkZone} they check if the marked zones are altered in which
+case they output an error message.
+@end quotation
+
+@end itemize
+
+
+@c =========================================================================
+@node   The NSZone functions, The NSAllocDebugZone class, The NSZone class, NSZone
+@comment node-name, next, previous, up
+
+@section The @code{NSZone} functions
+
+The OpenStep specification defines several functions that deal with
+zones. In @emph{libFoundation} these functions are implemented as inline
+functions that send the corresponding message to the zone instance or
+directly to the @code{NSZone} class. The correspondency between them is
+straightforward so check the method description for more information.
+
+Here are the functions used to manipulate a zone:
+
+@itemize @bullet
+
+@item
+@code{NSZone* @strong{NSCreateZone}(unsigned @emph{startSize}, unsigned @emph{granularity}, BOOL @emph{canFree});}
+
+@item
+@code{NSZone* @strong{NSDefaultMallocZone}(void);}
+
+@item
+@code{NSZone* @strong{NSZoneFromPointer}(void* @emph{pointer});}
+
+@item
+@code{void* @strong{NSZoneMalloc}(NSZone* @emph{zone}, unsigned @emph{size});}
+
+@item
+@code{void* @strong{NSZoneMallocAtomic}(NSZone* @emph{zone}, unsigned @emph{size});}
+
+@item
+@code{void* @strong{NSZoneCalloc}(NSZone* @emph{zone}, unsigned @emph{numElems}, unsigned @emph{byteSize});}
+
+@item
+@code{void* @strong{NSZoneCallocAtomic}(NSZone* @emph{zone}, unsigned @emph{numElems}, @* unsigned @emph{byteSize});}
+
+@item
+@code{void* @strong{NSZoneRealloc}(NSZone* @emph{zone}, void* @emph{pointer}, unsigned @emph{size});}
+
+@item
+@code{void @strong{NSZoneFree}(NSZone* @emph{zone}, void* @emph{pointer});}
+
+@item
+@code{void @strong{NSRecycleZone}(NSZone* @emph{zone});}
+
+@item
+@code{void @strong{NSSetZoneName}(NSZone* @emph{zone}, NSString* @emph{name});}
+
+@item
+@code{NSString* @strong{NSZoneName}(NSZone* @emph{zone});}
+
+@end itemize
+
+
+@c =========================================================================
+@node   The NSAllocDebugZone class, Zones and garbage collection, The NSZone functions, NSZone
+@comment node-name, next, previous, up
+
+
+@section The @code{NSAllocDebugZone} class
+
+The @code{NSDefaultZone} uses system @code{malloc}, @code{calloc},
+@code{realloc} and @code{free} directly, without any checks.
+
+The @code{NSAllocDebugZone} is used to help in tracking down memory
+allocation bugs. It provides the following features:
+
+
+@itemize @bullet
+
+@item
+check double deallocation for pointers
+
+@item
+check deallocation of non-existing pointers
+
+@item
+use a block of memory past its margins
+
+@item
+list blocks allocated since a moment (marked by a special call)
+
+@item
+each allocated pointer has a serial number
+
+@item
+stop when alloc-ing a pointer with a certain serial number
+
+@item
+do @code{SYSTEM_MALLOC_CHECK} and internal checks every count operation
+
+@item
+be able to control things from gdb
+
+@item
+be able to control things from environment variables
+
+@end itemize
+
+The @code{NSAllocDebugZone} is controlled by the following environment
+variables:
+
+@itemize @bullet
+
+@item
+@code{ALLOCDEBUG}: must be set to something to use the alloc debug zone
+
+@item
+@code{ALLOCDEBUG_STOP}: stop in debugger @code{SIGINT} when alloc-ing
+pointer with given serial number (this serial number is reported when
+and error with that pointer occurs). Undefined or 0 means no stop.
+
+@item
+@code{ALLOCDEBUG_COUNT}: number of passes inside allocation/deallocation
+functions to @code{SYSTEM_MALLOC_CHECK} and internal check. Undefined or
+0 means no checks.
+
+@item
+@code{ALLOCDEBUG_UPPER} and @code{ALLOCDEBUG_LOWER}: number of bytes to alloc at top/bottom of
+object block. These bytes are set to a given value (0x88) and checked at
+free and internal check to guard against using memory past the
+limit. Undefined or zero means no margin. Note that this size must be
+multiples of the machine address alignment (4, 8, 16 are recommended
+values).
+
+@end itemize
+
+The @code{NSAllocDebugZone} provides these functions to be used from the
+GNU debugger.
+
+@itemize @bullet
+
+@item
+@code{debuggerStopMark(unsigned mark)}: overrides @code{ALLOCDEBUG_STOP}
+
+@item
+@code{debuggerCheckTime(unsigned count)}: overrides @code{ALLOCDEBUG_COUNT}
+
+@item
+@code{debuggerDescription(id obj)}: performs @code{printf("%s\n", [obj description])}
+
+@item
+@code{debuggerPerform(id obj, char* sel)}: performs @code{[obj sel]}
+
+@item
+@code{debuggerPerformWith(id obj, char* sel, id arg)}: performs @* 
+@w{@code{[obj sel:(id)atoi(arg)]}}
+
+@end itemize
+
+The program instantiates two zones: one @code{NSDefaultZone} and one
+@code{NSAllocDebugZone}, and uses one or the other depending on the
+@code{ALLOCDEBUG} environment variable. If this variable exists in your
+environment then the @code{NSAllocDebugZone} instance will be
+used.
+
+Below are some setting you might find useful when working with the
+@code{NSAllocDebugZone} class.
+
+@example
+# must be set to something to use alloc debug zone
+ALLOCDEBUG=YES
+export ALLOCDEBUG=YES
+
+# stop in debugger (SIGINT) when alloc-ing pointer number *
+# nil or 0 means no stop
+ALLOCDEBUG_STOP=0
+export ALLOCDEBUG_STOP
+
+# stop in debugger (SIGINT) when alloc-ing pointer number *
+# nil or 0 means no stop
+ALLOCDEBUG_MARK=0
+export ALLOCDEBUG_MARK
+
+# number of passes inside allocation/deallocation functions
+# to SYSTEM_MALLOC_CHECK and internal check
+# nil or 0 means no checks
+ALLOCDEBUG_COUNT=16
+export ALLOCDEBUG_COUNT
+
+# number of bytes to alloc at top/bottom of object block
+# these bytes are set to a given value (0x88) and checked
+# at free and internal check to guard against using memory
+# past the limit.
+ALLOCDEBUG_UPPER=8
+ALLOCDEBUG_LOWER=8
+export ALLOCDEBUG_UPPER ALLOCDEBUG_LOWER
+@end example
+
+
+@c =========================================================================
+@node   Zones and garbage collection, NSInvocation, The NSAllocDebugZone class, NSZone
+@comment node-name, next, previous, up
+
+@section Zones and garbage collection
+
+The zone mechanism provides a way to group related pointers in a
+program.  For example different portions of an application which do not
+have much in common, can use different zones. This improves the memory
+localization in the virtual memory system of the operating system and
+lowers the mapping in and out of the memory pages.
+
+In the current implementation, both garbage collectors, the Boehm's
+collector and the one based on reference counting, do not take advantage
+of this behavior. When a collection starts searching for the unused
+pointers can spread over all the existing zones.
+
+Because of this, when @emph{libFoundation} is compiled with support for
+the Boehm's collector, the zones are completely disabled. The
+@code{NSZone} functions that perform memory allocation simply invoke the
+collector's functions.
+
+
+@c =========================================================================
+@node   NSInvocation, Porting NSInvocation, Zones and garbage collection, Top
+@comment node-name, next, previous, up
+
+@chapter Features of the @code{NSInvocation} class
+
+The ability to dynamically construct method invocations is an important
+feature in Objective-C libraries. This ability is used by various
+applications like distributed objects and various language interpreters
+to provide interface with the native methods or functions. In
+@emph{libFoundation} the @code{NSInvocation} class is designed to
+provide this important facility.
+
+In the OpenStep specification and some OpenStep Foundation
+implementations, the @code{NSInvocation} class is only used to
+encapsulate the arguments and return value of a forwarded message and to
+allow sending a different message in the context of the forwarding. The
+normal usage of the @code{NSInvocation} is in the
+@code{-forwardInvocation:} method:
+
+@example
+- (void)forwardInvocation:(NSInvocation*)anInvocation
+@{
+    [anInvocation setTarget:anotherObject];
+    [anInvocation setSelector:anotherSelector];
+    [anInvocation invoke];
+@}
+@end example
+
+In this example the @code{NSInvocation} object is created automatically
+by the Foundation library, with the help of the Objective-C runtime
+library, when a message is sent to an object that does not implement
+it. The actual implementation assumes the stack frame for the arguments
+of the method already exists @footnote{On many systems this is only a
+partial picture, because the native convention calls can also use
+registers to pass arguments to a function.}. All the further changes to
+the method's arguments using the @code{NSInvocation}'s methods are
+performed on that stack frame. After the method invocation returns you
+can access the return value and possibly change it, using the
+@code{getReturnValue:} and @code{setReturnValue:} methods.
+
+The situation is different when you build a dynamic method invocation.
+
+@example
+    BOOL flag = YES;
+    int anInt = 1234;
+    float aFloat = 12345.0;
+    double aDouble = 98765.0;
+    id invocation = [[NSInvocation new] autorelease];
+
+    [invocation setSelector:
+                @@selector(setFlag:intValue:floatValue:doubleValue:)];
+    [invocation setTarget:object];
+    [invocation setArgument:&flag atIndex:2];
+    [invocation setArgument:&anInt atIndex:3];
+    [invocation setArgument:&aFloat atIndex:4];
+    [invocation setArgument:&aDouble atIndex:5];
+    [invocation invoke];
+@end example
+
+In this example the dynamic method invocation is constructed from
+scratch, by providing the object, the message selector and the arguments
+of the message. Then you can invoke the message and, after the message
+returns, you can access the return value.
+
+It is very important to set the target and selector @emph{before}
+setting the arguments. The @code{NSInvocation} is not otherwise able to
+construct the stack and registers frame and set the arguments of the
+method invocation.
+
+@menu
+* Porting NSInvocation::
+@end menu
+
+
+@c =========================================================================
+@node   Porting NSInvocation, NSMethodSignature, NSInvocation, NSInvocation
+@comment node-name, next, previous, up
+
+
+@section Porting @code{NSInvocation}
+
+The @code{NSInvocation} is highly dependent on the target machine. The
+code that depends on the target machine is carefully separated from the
+independent part of the class. This code is written as macros in the
+@file{config/@emph{processor}/@emph{operating-system}}.
+
+
+@code{NSInvocation} is implemented using the @code{__builtin_apply} and
+@code{__builtin_return} built-in pseudo-functions that are available in
+the GNU C compiler. See the GNU C compiler documentation of these
+functions.
+
+The following macros have to be defined for a given target
+machine. Defining them is a though process, they closely follow the
+native convention calls defined for the target in the GCC target
+dependent files. We intend to take advantage of the knowledge that's
+already in the compiler and move the @code{NSInvocation}'s code into the
+Objective-C runtime library.
+
+@itemize @bullet
+
+@item
+@code{FUNCTION_VALUE}
+
+@item
+@code{FUNCTION_SET_VALUE}
+
+@item
+@code{GET_STRUCT_VALUE_ADDRESS}
+
+@item
+@code{SET_STRUCT_VALUE_ADDRESS}
+
+@end itemize
+
+In addition, if the target system does not work as expected copying the
+arguments onto and from the @code{__builtin_apply}'s frame, you can
+define in addition the @code{FRAME_SET_ARGUMENT} and
+@code{FRAME_GET_ARGUMENT} macros.
+
+@code{FUNCTION_VALUE} should copy the return value from the result frame
+returned by the @code{__builtin_apply} pseudo-function into a memory
+zone received as argument. This macro has the following arguments:
+
+@itemize @bullet
+
+@item
+@code{TYPE} (@code{char*}): the Objective-C encoding of the return value
+type
+
+@item
+@code{ARGS} (@code{void*}): the arguments frame passed to
+@code{__builtin_apply}
+
+@item
+@code{RESULT_FRAME} (@code{void*}): the result frame returned by
+@code{__builtin_apply}
+
+@item
+@code{RETURN_VALUE} (@code{void*}): the memory zone where the value
+should be set. This zone is already allocated.
+
+@end itemize
+
+
+@code{FUNCTION_SET_VALUE} should set the return value into the result
+frame returned by the @code{__builtin_apply}. It has the following
+arguments:
+
+@itemize @bullet
+
+@item
+@code{TYPE} (@code{char*}): the Objective-C encoding of the return value
+type
+
+@item
+@code{ARGS} (@code{void*}): the arguments frame passed to
+@code{__builtin_apply}
+
+@item
+@code{RESULT_FRAME} (@code{void*}): the result frame returned by
+@code{__builtin_apply}
+
+@item
+@code{RETURN_VALUE} (@code{void*}): the memory zone where the returned
+value should be copied from.
+
+@end itemize
+
+
+@code{GET_STRUCT_VALUE_ADDRESS} is an expression that should produce the
+return value address in the case this is returned by reference or
+@code{NULL} if the return value is not returned by reference. Usually
+only the aggregates (structures and unions) are returned by
+reference. This macro has the following arguments:
+
+@itemize @bullet
+
+@item
+@code{ARGS} (@code{void*}): the arguments frame passed to
+@code{__builtin_apply}. Usually the address of return value is set here
+by the @code{__builtin_apply_args} pseudo-function
+
+@item
+@code{RETTYPE} (@code{char*}): the Objective-C encoding of the return
+value type.
+
+@end itemize
+
+
+@code{SET_STRUCT_VALUE_ADDRESS} should set in the arguments frame that
+will be passed to @code{__builtin_apply} the address of the return value
+if this is returned by reference. The arguments are:
+
+@itemize @bullet
+
+@item
+@code{ARGS} (@code{void*}): the arguments frame that will be passed to
+@code{__builtin_apply}
+
+@item
+@code{ADDR} (@code{void*}): the address of the zone where the called
+function should set the return value. This zone is already allocated.
+
+@item
+@code{RETTYPE} (@code{char*}): the Objective-C encoding of the return
+value type
+
+@end itemize
+
+
+@code{FRAME_SET_ARGUMENT} should be used whenever the default mechanism
+of copying the argument onto the @code{__builtin_apply}'s frame is not
+working. The default mechanism is implemented in the
+@code{NSInvocation}'s @code{-setArgument:atIndex:} method. If you do not
+define this macro the default mechanism is used.
+
+The arguments of this macro are:
+
+@itemize @bullet
+
+@item
+@code{FRAME_DATA} (@code{void*}): The address in the
+@code{__builtin_apply}'s frame where the argument's value has to be copied.
+
+@code{ARGUMENT_LOCATION} (@code{void*}): The address where the argument
+to be copied is located.
+
+@code{ARG_INFO} (@code{NSArgumentInfo}): Describes the type of the
+argument.
+
+@end itemize
+
+The @code{FRAME_GET_ARGUMENT} macros is similar with
+@code{FRAME_SET_ARGUMENT} but does the opposite job.
+
+For an example of how the above macros are implemented you can take a
+look in the @file{config} directory in the @emph{libFoundation}'s
+distribution.
+
+
+@c =========================================================================
+@node   NSMethodSignature, Porting NSMethodSignature, Porting NSInvocation, Top
+@comment node-name, next, previous, up
+
+@chapter Features of the @code{NSMethodSignature} class
+
+@code{NSMethodSignature} provides information about the type signature
+of a method. The Objective-C type encoding of a method is a C string
+that contains an encoding of the return value type and type of the
+arguments including information about how to access them on the stack
+and registers frames. See the Objective-C documentation in the GCC
+runtime for more information about method type encoding.
+
+Below is an example of how to create a @code{NSMethodSignature} instance
+for a given method of an object:
+
+@example
+    id anObject;
+    struct objc_method* mth
+         = class_get_instance_method(self->isa, aSelector);
+    const char* types = mth->method_types;
+    id signature = [NSMethodSignature signatureWithObjCTypes:types];
+@end example
+
+The above code is implemented by the @code{NSObject}'s
+@code{methodSignatureForSelector:} method. If you send this method to a
+class, the method searches for a class method whose selector is the same
+as the argument. If the message is sent to an instance, the method
+searches for an instance method. If you don't want to create an instance
+of a class just to find out what is the signature of an instance method,
+you can use the @code{instanceMethodForSelector:} method, that searches
+in the class for an instance method with the same selector as the
+argument.
+
+In addition to providing information about already existing method
+encodings that are available for compiled methods, the
+@code{NSMethodSignature} class from @emph{libFoundation} allows you to
+construct method signatures for new methods, that could be created for
+example by an interpreter. Suppose one wants to create a method encoding
+that has arguments an integer and its return type is @code{void}; you
+can do like this:
+
+@example
+    id signature = [NSMethodSignature signatureWithObjCTypes:"v@:i"];
+@end example
+
+The @code{NSMethodSignature} class computes the full signature that
+contains the offsets of the arguments on the stack and registers
+frames. This code is dependent on the target machine so the result may
+be different between various processors and even on the same processor
+but different OSes.
+
+@menu
+* Porting NSMethodSignature::
+@end menu
+
+@c =========================================================================
+@node   Porting NSMethodSignature, , NSMethodSignature, NSMethodSignature
+@comment node-name, next, previous, up
+
+@section Porting NSMethodSignature
+
+Porting @code{NSMethodSignature} implies defining the below macros,
+similar with the way @code{NSInvocation} is ported to a new platform. As
+with the @code{NSInvocation}'s macros, this code will probably also move
+in the Objective-C runtime library, to take advantage of the compiler's
+knowledge on the target system.
+
+@itemize @bullet
+
+@item
+@code{CUMULATIVE_ARGS}
+
+@item
+@code{INIT_CUMULATIVE_ARGS}
+
+@item
+@code{FUNCTION_ARG_ENCODING}
+
+@end itemize
+
+The name of this macros are the same with the similar ones from the GNU
+CC compiler. However they don't correspond neither in semantics nor in
+the argument types.
+
+@code{CUMULATIVE_ARGS} is the data type of a variable used to hold about
+arguments processed so far. On a machine where all the arguments are
+passed on stack, this type is usually @code{int}.
+
+@code{INIT_CUMULATIVE_ARGS} should initialize the variable of type
+@code{CUMULATIVE_ARGS} described above.
+
+@code{FUNCTION_ARG_ENCODING} determines the encoding of the next
+argument of a method. It must produce a @code{NSString} describing the
+Objective-C encoding and position of the argument in the arguments frame
+of the method.
+
+If you want to determine how to write the encoding for a new machine you
+could use the program generated by signature-test.pl perl script in
+@emph{FoundationTestsuite}. This generates a class with a lot of
+methods. You can look at the output of the program to see how the
+compiler encodes the methods. Also take a look in the @file{objc-act.c}
+file in the compiler to see how the methods are encoded.
+
+
+@c =========================================================================
+
+@contents
+
+@bye
diff --git a/libFoundation/doc/signature-test.pl b/libFoundation/doc/signature-test.pl
new file mode 100644 (file)
index 0000000..03f8032
--- /dev/null
@@ -0,0 +1,220 @@
+#! /usr/local/bin/perl
+
+@types = (
+    'char', 
+    'short',
+    'int',
+    'long',
+    'float',
+    'double',
+    'void*',
+    'Struct1',
+    'Struct2',
+    'Struct3',
+    'Struct4',
+    'Struct5',
+    'Struct6',
+    'Struct7',
+    'Struct8'
+);
+
+%type_encoding = (
+    'char' => 'c',
+    'short' => 's',
+    'int' => 'i',
+    'long' => 'l',
+    'float' => 'f',
+    'double' => 'd',
+    'void*' => '^v',
+    'Struct1' => '{?=c}',
+    'Struct2' => '{?=s}',
+    'Struct3' => '{?=sc}',
+    'Struct4' => '{?=i}',
+    'Struct5' => '{?=ic}',
+    'Struct6' => '{?=is}',
+    'Struct7' => '{?=isc}',
+    'Struct8' => '{?=ii}'
+);
+
+%type_method_name = (
+    'char' => 'c',
+    'short' => 's',
+    'int' => 'i',
+    'long' => 'l',
+    'float' => 'f',
+    'double' => 'd',
+    'void*' => 'p',
+    'Struct1' => 's1',
+    'Struct2' => 's2',
+    'Struct3' => 's3',
+    'Struct4' => 's4',
+    'Struct5' => 's5',
+    'Struct6' => 's6',
+    'Struct7' => 's7',
+    'Struct8' => 's8'
+);
+
+# The maximum number of arguments a method should have
+$no_of_args = 2;
+
+sub generate_methods_file {
+    local ($file,
+           $file_prologue, $file_epilogue,
+           $method_prefix, $method_code,
+           $initial_acc_args
+    ) = @_;
+
+    $FILE = "> $file";
+    #$FILE = ">-";
+    open(FILE) or die "cannot open file: $!\n";
+    print FILE $file_prologue;
+
+    # The number of methods generated
+    $methods_generated = 0;
+
+    gen_method($no_of_args, $method_prefix, $method_code, $initial_acc_args);
+    print FILE $file_epilogue;
+
+    print "$methods_generated methods generated in file $file.\n";
+}
+
+sub gen_method {
+    local ($mth_no_of_args,
+           $method_prefix, $method_code,
+           $initial_acc_args
+    ) = @_;
+
+    gen_method1(0, $mth_no_of_args, "", $initial_acc_args,
+                           $method_prefix, $method_code);
+}
+
+sub gen_method1 {
+    local (
+           $curr_type_no, $curr_arg_no,
+           $acc_mth_name, $acc_args,
+           $method_prefix, $method_code
+    ) = @_;
+
+    if ($curr_arg_no == 0) {
+       print FILE "$method_prefix";
+       if ($acc_mth_name ne "") {
+               print FILE "${acc_mth_name}${acc_args}";
+       }
+       print FILE $method_code;
+       $methods_generated++;
+       print "$methods_generated\r";
+       return;
+    }
+
+    # Determine the preceding types. We not generate the methods that have more
+    # than 2 identical types in consecutive positions.
+    local $prev_type = "";
+    if ($acc_mth_name =~ /.*_(.*)$/) {
+           $prev_type = $acc_mth_name;
+           $prev_type =~ s/.*_(.*)$/$1/;
+    }
+
+    for (local $curr_type_no = 0; $curr_type_no <= $#types; $curr_type_no++) {
+       local $label = $type_method_name{$types[$curr_type_no]};
+
+       if(!($label eq $prev_type)) {
+           gen_method1($curr_type_no, $curr_arg_no - 1,
+                   "${acc_mth_name}_$label",
+                   &$show_acc_args($acc_args, $curr_type_no, $curr_arg_no),
+                   $method_prefix, $method_code);
+       }
+    }
+}
+
+$source_file = __FILE__;
+
+$show_acc_args = sub {
+    local ($acc_args, $curr_type_no, $curr_arg_no) = @_;
+    local $number = $no_of_args - $curr_arg_no;
+    local $label = $type_method_name{$types[$curr_type_no]};
+
+    return "$acc_args:($types[$curr_type_no])${label}${number} ";
+};
+
+generate_methods_file("SignatureTest.m",
+"/* Do not modify! Generated automatically from $source_file. */
+
+#include <objc/Object.h>
+
+typedef struct {
+char c;
+} Struct1;
+
+typedef struct {
+short s;
+} Struct2;
+
+typedef struct {
+short s;
+char c;
+} Struct3;
+
+typedef struct {
+int i;
+} Struct4;
+
+typedef struct {
+int i;
+char c;
+} Struct5;
+
+typedef struct {
+int i;
+short s;
+} Struct6;
+
+typedef struct {
+int i;
+short s;
+char c;
+} Struct7;
+
+typedef struct {
+int i;
+int j;
+} Struct8;
+
+\@interface SignatureTest : Object
+\@end
+
+\@implementation SignatureTest
+
+", "
+\@end /* SignatureTest */
+", "- (void)method",
+"{}
+",
+"");
+
+
+$show_acc_args = sub {
+    local ($acc_args, $curr_type_no, $curr_arg_no) = @_;
+
+    return ":${acc_args}";
+};
+
+generate_methods_file("test.m",
+"/* Do not modify! Generated automatically from $source_file. */
+#include <stdio.h>
+#include <objc/objc.h>
+#include <objc/objc-api.h>
+#include \"SignatureTest.m\"
+
+void main()
+{
+    id signtest = [[SignatureTest alloc] init];
+    struct objc_method* mth;
+
+", "
+}
+",
+"    mth = class_get_instance_method([signtest class], \@selector(method",
+"));
+    printf(\"'%s' is '%s'\\n\", sel_get_name(mth->method_name), mth->method_types);
+",
+"");
diff --git a/libFoundation/examples/Defaults.m b/libFoundation/examples/Defaults.m
new file mode 100644 (file)
index 0000000..8a7b02c
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+   Defaults.m
+
+   Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@net-community.com>
+   Date: October 1997
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/Foundation.h>
+
+volatile void usage (void)
+{
+    puts ("Tool to manipulate the defaults database of a generic implementation of");
+    puts ("OpenStep Foundation.\n");
+
+    puts ("Show the defaults for all the domains:");
+    puts ("\tDefaults read");
+
+    puts ("Show the defaults for a given domain:");
+    puts ("\tDefaults read \"domain's name\"");
+
+    puts ("Show the defaults for a given key of a given domain:");
+    puts ("\tDefaults read \"domain's name\" \"key\"");
+
+    puts ("Update the defaults for a given domain:");
+    puts ("\tDefaults write \"domain's name\" \"domain's plist representation\"");
+
+    puts ("Update the defaults for a given key in a given domain:");
+    puts ("\tDefaults write \"domain's name\" \"key\" \"value\"");
+
+    puts ("Delete the defaults for a given domain:");
+    puts ("\tDefaults delete \"domain's name\"");
+
+    puts ("Delete the defaults for a given key in a given domain:");
+    puts ("\tDefaults delete \"domain's name\" \"key\"");
+
+    puts ("Show all the existing domains:");
+    puts ("\tDefaults domains");
+
+    puts ("\nCopyright 1995-1997, Ovidiu Predescu and Mircea Oancea. See the libFoundation's");
+    puts ("license for more information.");
+    exit (0);
+}
+
+void read_command (NSArray* arguments)
+{
+    NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
+    id result = [NSMutableDictionary dictionary];
+    int argumentsCount = [arguments count];
+
+    if (argumentsCount == 2) { /* Defaults read */
+       /* Show the defaults for all the persistent domains */
+       NSArray* persistentDomainNames = [defaults persistentDomainNames];
+       int i, count = [persistentDomainNames count];
+       NSString* key;
+
+       for (i = 0; i < count; i++) {
+           key = [persistentDomainNames objectAtIndex:i];
+           [result setObject:[defaults persistentDomainForName:key]
+                   forKey:key];
+       }
+    }
+    else if (argumentsCount == 3
+            || argumentsCount == 4) {  /* Defaults read "domain name" [key] */
+       /* Show the defaults for a given domain */
+       NSString* domainName = [arguments objectAtIndex:2];
+
+       result = [defaults persistentDomainForName:domainName];
+       if (!result) {
+           NSLog(@"Domain '%@' does not exist!", domainName);
+           exit (1);
+       }
+
+       if (argumentsCount == 4) {
+           NSString* key = [arguments objectAtIndex:3];
+           id value = [result objectForKey:key];
+
+           if (!value) {
+               NSLog(@"There is no key '%@' under the '%@' domain!",
+                      key, domainName);
+               exit (1);
+           }
+           else
+               result = value;
+       }
+    }
+    else if (argumentsCount == 4) {    /* Defaults read "domain name" key */
+       /* Show the defaults for a given key in a domain */
+       NSString* domainName = [arguments objectAtIndex:2];
+
+       result = [defaults persistentDomainForName:domainName];
+       if (!result) {
+           NSLog (@"Domain '%@' does not exist!", domainName);
+           exit (1);
+       }
+    }
+    else
+        usage ();
+    printf ("%s\n", [[result description] cString]);
+}
+
+void write_command (NSArray* arguments)
+{
+    NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
+    int argumentsCount = [arguments count];
+
+    if (argumentsCount == 4) { /* Defaults write "domain name" "plist" */
+       /* Define here the format to avoid a bug in gcc. */
+       id format = @"Cannot parse the representation of the domain name: '%@'";
+       NSString* domainName = [arguments objectAtIndex:2];
+       id value;
+
+       NS_DURING
+           *(&value) = [[arguments objectAtIndex:3] propertyList];
+            if (![value isKindOfClass:[NSDictionary class]]) {
+                NSLog (@"The domain's value should be a dictionary object! "
+                       @"(got '%@')", value);
+                exit (1);
+            }
+       NS_HANDLER
+           NSLog (format, [arguments objectAtIndex:3]);
+           exit (1);
+       NS_ENDHANDLER
+
+       [defaults removePersistentDomainForName:domainName];
+       [defaults setPersistentDomain:value forName:domainName];
+    }
+    else if (argumentsCount == 5) {/* Defaults write "domain name" key value */
+       /* Define here the format to avoid a bug in gcc. */
+       id format =
+            @"Cannot parse the value of key '%@' for the domain name '%@': %@";
+       NSString* domainName = [arguments objectAtIndex:2];
+       id key = [arguments objectAtIndex:3];
+       NSMutableDictionary* domainValue;
+       id value;
+
+       NS_DURING {
+           *(&value) = [[arguments objectAtIndex:4] propertyList];
+        }
+       NS_HANDLER {
+           NSLog (format, key, [arguments objectAtIndex:4], localException);
+           exit (1);
+        }
+       NS_ENDHANDLER
+
+       domainValue = [[[defaults persistentDomainForName:domainName]
+                         mutableCopy]
+                         autorelease];
+       if (domainValue == nil)
+           domainValue = [NSMutableDictionary dictionary];
+       else
+           [defaults removePersistentDomainForName:domainName];
+
+       [domainValue setObject:value forKey:key];
+       [defaults setPersistentDomain:domainValue forName:domainName];
+    }
+    else
+       usage ();
+
+    if (![defaults synchronize])
+        NSLog(@"errors during synchronization of defaults !");
+}
+
+void delete_command(NSArray *arguments) {
+    /* Defaults delete "domain name" [key] */
+    NSUserDefaults      *defaults;
+    NSMutableDictionary *domainValue;
+    NSString            *domainName;
+    int                 argumentsCount;
+    
+    defaults       = [NSUserDefaults standardUserDefaults];
+    argumentsCount = [arguments count];
+    
+    if (argumentsCount < 3 || argumentsCount > 4) {
+        usage();
+        return;
+    }
+    
+    domainName = [arguments objectAtIndex:2];
+    
+    domainValue = [[[defaults persistentDomainForName:domainName]
+                         mutableCopy]
+                         autorelease];
+    if (domainValue == nil) {
+        NSLog(@"Domain '%@' does not exist!", domainName);
+        exit(1);
+    }
+    
+    if (argumentsCount == 3) {
+        [defaults removePersistentDomainForName:domainName];
+
+        // TODO: this prints a warning, but it is required
+        [defaults synchronize];
+    }
+    else if (argumentsCount == 4) {
+        id key = [arguments objectAtIndex:3];
+        
+        if ([domainValue objectForKey:key] == nil) {
+            NSLog(@"Cannot find the key '%@' under domain name '%@'!",
+                  key, domainName);
+            exit(1);
+        }
+
+        [defaults removePersistentDomainForName:domainName];
+        [domainValue removeObjectForKey:key];
+        [defaults setPersistentDomain:domainValue forName:domainName];
+        
+        if (![defaults synchronize])
+            NSLog(@"errors during synchronization of defaults !");
+    }
+}
+
+void show_domains(void) {
+    NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
+    NSArray* persistentDomainNames = [defaults persistentDomainNames];
+    int i, count = [persistentDomainNames count];
+
+    for (i = 0; i < count; i++)
+       printf ("%s\n", [[persistentDomainNames objectAtIndex:i] cString]);
+}
+
+#include <extensions/GarbageCollector.h>
+
+int main(int argc, char **argv, char **env) {
+    NSAutoreleasePool* pool;
+    NSArray* arguments;
+    NSString* command;
+    int count;
+
+#if LIB_FOUNDATION_LIBRARY
+    [NSProcessInfo initializeWithArguments:argv count:argc environment:env];
+#endif
+
+    pool = [NSAutoreleasePool new];
+
+    arguments = [[NSProcessInfo processInfo] arguments];
+    count = [arguments count];
+
+    if (count == 1)
+      usage ();
+
+    command = [arguments objectAtIndex:1];
+
+    if ([command isEqual:@"read"])
+       read_command (arguments);
+    else if ([command isEqual:@"write"])
+       write_command (arguments);
+    else if ([command isEqual:@"delete"])
+       delete_command (arguments);
+    else if ([command isEqual:@"domains"])
+       show_domains ();
+    else
+       usage ();
+
+    RELEASE(pool);
+    exit (0);
+    return 0;
+}
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/examples/GNUmakefile b/libFoundation/examples/GNUmakefile
new file mode 100644 (file)
index 0000000..2702aa3
--- /dev/null
@@ -0,0 +1,82 @@
+#  GNUmakefile.gnustep
+#
+#  Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+#  All rights reserved.
+#
+#  Author: Ovidiu Predescu <ovidiu@net-community.com>
+#  Date: October 1997
+#
+#  This file is part of libFoundation.
+#
+#  Permission to use, copy, modify, and distribute this software and its
+#  documentation for any purpose and without fee is hereby granted, provided
+#  that the above copyright notice appear in all copies and that both that
+#  copyright notice and this permission notice appear in supporting
+#  documentation.
+#
+#  We disclaim all warranties with regard to this software, including all
+#  implied warranties of merchantability and fitness, in no event shall
+#  we be liable for any special, indirect or consequential damages or any
+#  damages whatsoever resulting from loss of use, data or profits, whether in
+#  an action of contract, negligence or other tortious action, arising out of
+#  or in connection with the use or performance of this software.
+#
+
+-include ../gsfix.make
+
+ifeq ($(GNUSTEP_SYSTEM_ROOT),)
+
+$(warning ERROR: Your $(GNUSTEP_SYSTEM_ROOT) environment variable is empty !)
+$(error Please try again after running ". $(GNUSTEP_MAKEFILES)/GNUstep.sh")
+
+else
+
+# ZNeK: hardcoded this due to removal of support for other runtimes
+OBJC_RUNTIME=GNU
+
+GNUSTEP_INSTALLATION_DIR = $(GNUSTEP_SYSTEM_ROOT)
+
+include $(GNUSTEP_MAKEFILES)/common.make
+
+ifeq ($(gc), yes)
+ifeq ($(LIBFOUNDATION_WITH_GC), yes)
+GNUSTEP_OBJ_DIR = $(GNUSTEP_OBJ_PREFIX)/$(GNUSTEP_TARGET_DIR)/$(OBJC_RUNTIME)-gc
+GNUSTEP_OBJ_DIR_NAME = $(GNUSTEP_OBJ_PREFIX)/$(GNUSTEP_TARGET_DIR)/$(OBJC_RUNTIME)-gc
+else # $(LIBFOUNDATION_WITH_GC) == no
+GNUSTEP_OBJ_DIR = $(GNUSTEP_OBJ_PREFIX)/$(GNUSTEP_TARGET_DIR)/$(OBJC_RUNTIME)
+GNUSTEP_OBJ_DIR_NAME = $(GNUSTEP_OBJ_PREFIX)/$(GNUSTEP_TARGET_DIR)/$(OBJC_RUNTIME)
+endif
+else # $(gc) == no
+GNUSTEP_OBJ_DIR = $(GNUSTEP_OBJ_PREFIX)/$(GNUSTEP_TARGET_DIR)/$(OBJC_RUNTIME)
+GNUSTEP_OBJ_DIR_NAME = $(GNUSTEP_OBJ_PREFIX)/$(GNUSTEP_TARGET_DIR)/$(OBJC_RUNTIME)
+endif
+
+ADDITIONAL_LIB_DIRS = \
+       -L../Foundation/$(GNUSTEP_OBJ_DIR) \
+
+SYSTEM_LIB_DIR += \
+       -L/usr/local/lib -L/usr/lib
+
+ADDITIONAL_INCLUDE_DIRS = \
+       -I..    \
+       -I../Foundation/$(GNUSTEP_TARGET_CPU)/$(GNUSTEP_TARGET_OS)/$(OBJC_RUNTIME)
+
+TOOL_NAME = Defaults
+
+ifeq ($(examples),yes)
+TOOL_NAME += fmls fmrm printenv chkdict
+endif
+
+Defaults_OBJC_FILES = Defaults.m
+fmls_OBJC_FILES     = fmls.m
+fmrm_OBJC_FILES     = fmrm.m
+printenv_OBJC_FILES = printenv.m
+chkdict_OBJC_FILES  = chkdict.m
+
+ADDITIONAL_TOOL_LIBS += -lFoundation
+
+include $(GNUSTEP_MAKEFILES)/tool.make
+
+include fhs.make
+
+endif
diff --git a/libFoundation/examples/GNUmakefile.alone b/libFoundation/examples/GNUmakefile.alone
new file mode 100644 (file)
index 0000000..de56fbe
--- /dev/null
@@ -0,0 +1,76 @@
+# GNUmakefile
+#
+# Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+# All rights reserved.
+#
+# Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
+#
+# This file is part of libFoundation.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose and without fee is hereby granted, provided
+# that the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation.
+#
+# We disclaim all warranties with regard to this software, including all
+# implied warranties of merchantability and fitness, in no event shall
+# we be liable for any special, indirect or consequential damages or any
+# damages whatsoever resulting from loss of use, data or profits, whether in
+# an action of contract, negligence or other tortious action, arising out of
+# or in connection with the use or performance of this software.
+
+TOP    = ..
+OBJDIR = obj
+
+include $(TOP)/config.mak
+
+LIB    = $(TOP)/lib
+LIBS   := -lFoundation $(LIBS)
+
+.SUFFIXES: .m .h $(objext)
+
+DEFAULTS       = $(OBJDIR)/Defaults$(exeext)
+
+all: $(OBJDIR) $(DEFAULTS) .gdbinit
+
+DEFAULTSM = Defaults.m
+
+DEFAULTSO = $(addprefix $(OBJDIR)/, $(DEFAULTSM:.m=$(objext)))
+
+CFLAGS += -I../Foundation
+
+$(DEFAULTS): $(DEFAULTSO)
+       $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(DEFAULTSO) -L$(LIB) -L$(libdir) $(LIBS)
+
+#
+# Other rules
+#
+
+$(addprefix $(OBJDIR)/, %$(objext)) : %.m
+       $(CC) $(CFLAGS) $(DEBUGFLAGS) -c $< -o $(OBJDIR)/$(@F)
+
+$(OBJDIR):
+       mkdir $@
+
+clean:
+       rm -rf $(OBJDIR) .gdbinit t
+
+distclean: clean
+       rm -f GNUmakefile
+
+install:
+       if test ! -d $(bindir); then mkdir $(bindir); fi
+       $(INSTALL_PROGRAM) $(DEFAULTS) $(bindir)/Defaults$(exeext)
+
+uninstall:
+       rm $(exec_prefix)/$(DEFAULTS)
+
+.gdbinit:
+       @echo Making $@...
+       @echo define make >$@
+       @echo shell $(MAKE) >>$@
+       @echo end >>$@
+       @echo dir . $(TOP)/Foundation >>$@
+       @echo view >>$@
+
diff --git a/libFoundation/examples/chkdict.m b/libFoundation/examples/chkdict.m
new file mode 100644 (file)
index 0000000..6e20fe6
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+   chkdict.m
+
+   Copyright (C) 2000 Helge Hess.
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+   Date:   April 2000
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+/*
+  This is an example for loading a dictionary property list.
+*/
+
+#include <Foundation/Foundation.h>
+
+int main(int argc, char **argv, char **env) {
+  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+  NSArray *args;
+  int     i;
+  
+#if LIB_FOUNDATION_LIBRARY
+  [NSProcessInfo initializeWithArguments:argv count:argc environment:env];
+#endif
+  
+  args = [[NSProcessInfo processInfo] arguments];
+  if ([args count] < 2) {
+    NSLog(@"usage: %@ <files>", [args objectAtIndex:0]);
+    exit(1);
+  }
+
+  for (i = 1; i < [args count]; i++) {
+    NSString     *path;
+    NSDictionary *plist;
+    
+    path  = [args objectAtIndex:i];
+    plist = [[NSDictionary alloc] initWithContentsOfFile:path];
+    if (plist)
+      printf("%s: valid (%i entries)\n", [path cString], [plist count]);
+    else
+      printf("%s: invalid\n", [path cString]);
+    
+    RELEASE(plist);
+  }
+  [pool release];
+  exit(0);
+  return 0;
+}
diff --git a/libFoundation/examples/fhs.make b/libFoundation/examples/fhs.make
new file mode 100644 (file)
index 0000000..d063b1a
--- /dev/null
@@ -0,0 +1,46 @@
+#  fhs.make
+#
+#  Copyright (C) 2004 Helge Hess.
+#  All rights reserved.
+#
+#  Author: Helge Hess <helge.hess@opengroupware.org>
+#  Date: Ausgust 2004
+#
+#  This file is part of libFoundation.
+#
+#  Permission to use, copy, modify, and distribute this software and its
+#  documentation for any purpose and without fee is hereby granted, provided
+#  that the above copyright notice appear in all copies and that both that
+#  copyright notice and this permission notice appear in supporting
+#  documentation.
+#
+#  We disclaim all warranties with regard to this software, including all
+#  implied warranties of merchantability and fitness, in no event shall
+#  we be liable for any special, indirect or consequential damages or any
+#  damages whatsoever resulting from loss of use, data or profits, whether in
+#  an action of contract, negligence or other tortious action, arising out of
+#  or in connection with the use or performance of this software.
+#
+
+# FHS support (this is a hack and is going to be done by gstep-make!)
+
+ifneq ($(FHS_INSTALL_ROOT),)
+
+FHS_BIN_DIR=$(FHS_INSTALL_ROOT)/bin/
+
+fhs-bin-dirs ::
+       $(MKDIRS) $(FHS_BIN_DIR)
+
+NONFHS_BINDIR="$(GNUSTEP_TOOLS)/$(GNUSTEP_TARGET_LDIR)"
+
+move-tools-to-fhs :: fhs-bin-dirs
+       @echo "moving tools from $(NONFHS_BINDIR) to $(FHS_BIN_DIR) .."
+       for i in $(TOOL_NAME); do \
+         mv "$(NONFHS_BINDIR)/$${i}" $(FHS_BIN_DIR); \
+       done
+
+move-to-fhs :: move-tools-to-fhs
+
+after-install :: move-to-fhs
+
+endif
diff --git a/libFoundation/examples/fmls.m b/libFoundation/examples/fmls.m
new file mode 100644 (file)
index 0000000..ce2d578
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+   fmls.m
+
+   Copyright (C) 2000 Helge Hess.
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+   Date:   April 2000
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+/*
+  This is an example for using the NSFileManager class to remove
+  files in the filesystem.
+*/
+
+#include <Foundation/Foundation.h>
+
+int main(int argc, char **argv, char **env) {
+  NSArray       *args;
+  NSFileManager *fm;
+  BOOL          ok;
+  int           i;
+  
+#if LIB_FOUNDATION_LIBRARY
+  [NSProcessInfo initializeWithArguments:argv count:argc environment:env];
+#endif
+  
+  args = [[NSProcessInfo processInfo] arguments];
+  if ([args count] < 1) {
+    NSLog(@"usage: %@ <files>", [args objectAtIndex:0]);
+    exit(1);
+  }
+  else if ([args count] == 1)
+    args = [args arrayByAddingObject:@"."];
+
+  fm = [NSFileManager defaultManager];
+  
+  for (i = 1; i < [args count]; i++) {
+    NSString *path = [args objectAtIndex:i];
+    BOOL     isDir;
+
+    path = [args objectAtIndex:i];
+    
+    if (![fm fileExistsAtPath:path isDirectory:&isDir]) {
+      NSLog(@"file/directory does not exist: %@", path);
+      continue;
+    }
+    
+    if (isDir) {
+      NSEnumerator *contents;
+      NSString *p;
+      
+      contents = [[[fm directoryContentsAtPath:path]
+                       sortedArrayUsingSelector:@selector(compare:)]
+                       objectEnumerator];
+      
+      while ((p = [contents nextObject])) {
+        NSDictionary *info;
+        NSString *fp;
+
+        fp = [path stringByAppendingPathComponent:p];
+        info = [fm fileAttributesAtPath:fp traverseLink:YES];
+
+        if (info == nil) {
+          NSLog(@"couldn't get info of entry: %@", fp);
+          continue;
+        }
+
+        /* id uid gid date name */
+        printf("%8s  %8s  %8s  %8i  %8s  %s\n",
+               [[[info objectForKey:NSFileIdentifier] description] cString],
+               [[info objectForKey:NSFileOwnerAccountName]      cString],
+               [[info objectForKey:NSFileGroupOwnerAccountName] cString],
+               [[info objectForKey:NSFileSize] intValue],
+               [[[info objectForKey:NSFileModificationDate] description] cString],
+               [p cString]);
+      }
+    }
+    else {
+    }
+  }
+  
+  exit(0);
+  return 0;
+}
diff --git a/libFoundation/examples/fmrm.m b/libFoundation/examples/fmrm.m
new file mode 100644 (file)
index 0000000..8d13e83
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+   fmrm.m
+
+   Copyright (C) 2000 Helge Hess.
+   All rights reserved.
+
+   Author: Helge Hess <helge.hess@mdlink.de>
+   Date:   April 2000
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+/*
+  This is an example for using the NSFileManager class to remove
+  files in the filesystem.
+*/
+
+#include <Foundation/Foundation.h>
+
+int main(int argc, char **argv, char **env) {
+  NSArray       *args;
+  NSFileManager *fm;
+  BOOL          ok;
+  int           i;
+  
+#if LIB_FOUNDATION_LIBRARY
+  [NSProcessInfo initializeWithArguments:argv count:argc environment:env];
+#endif
+  
+  args = [[NSProcessInfo processInfo] arguments];
+  if ([args count] < 2) {
+    NSLog(@"usage: %@ <files>", [args objectAtIndex:0]);
+    exit(1);
+  }
+
+  fm = [NSFileManager defaultManager];
+
+  for (i = 1; i < [args count]; i++) {
+    NSString *path = [args objectAtIndex:i];
+    
+    ok = [fm removeFileAtPath:path handler:nil];
+    if (!ok)
+      NSLog(@"could not remove: %@", [args objectAtIndex:1]);
+  }
+  
+  exit(0);
+  return 0;
+}
diff --git a/libFoundation/examples/printenv.m b/libFoundation/examples/printenv.m
new file mode 100644 (file)
index 0000000..12a1ec8
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+   printenv.m
+
+   Copyright (C) 1999 Helge Hess.
+   All rights reserved.
+
+   Author: Helge Hess <hh@mdlink.de>
+   Date: March 1999
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/Foundation.h>
+
+/*
+  This tool prints to stdout the environment variables as decoded by
+  NSProcessInfo.
+*/
+
+int main (int argc, char** argv, char** env)
+{
+#if LIB_FOUNDATION_LIBRARY
+    [NSProcessInfo initializeWithArguments:argv count:argc environment:env];
+#endif
+
+    {
+      NSAutoreleasePool *pool = [NSAutoreleasePool new];
+      NSDictionary      *env  = [[NSProcessInfo processInfo] environment];
+      NSEnumerator      *names;
+      NSString          *name;
+
+      names = [[[env allKeys]
+                     sortedArrayUsingSelector:@selector(compare:)]
+                     objectEnumerator];
+      while ((name = [names nextObject])) {
+        NSString *value = [env objectForKey:name];
+
+        printf("%s=%s\n", [name cString], [value cString]);
+      }
+      RELEASE(pool);
+    }
+    exit (0);
+    return 0;
+}
diff --git a/libFoundation/extensions/DefaultScannerHandler.h b/libFoundation/extensions/DefaultScannerHandler.h
new file mode 100644 (file)
index 0000000..a634668
--- /dev/null
@@ -0,0 +1,62 @@
+/* 
+   DefaultScannerHandler.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __DefaultScannerHandler_h__
+#define __DefaultScannerHandler_h__
+
+#include <Foundation/NSObject.h>
+
+@class NSString;
+@class FormatScanner;
+
+@interface DefaultScannerHandler : NSObject
+{
+    IMP specHandler[256];
+}
+
+- (NSString *)stringForArgument:(void *)arg scanner:(id)aFormatScanner;
+- (NSString *)unknownSpecifier:(void *)arg scanner:(id)scanner;
+
+@end
+
+@class NSEnumerator;
+
+@interface DefaultEnumScannerHandler : NSObject
+{
+    IMP specHandler[256];
+}
+
+- (NSString *)stringForArgument:(void *)arg scanner:(id)aFormatScanner;
+- (NSString *)unknownSpecifier:(void *)arg scanner:(id)scanner;
+
+@end
+
+#endif /* __DefaultScannerHandler_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/extensions/FormatScanner.h b/libFoundation/extensions/FormatScanner.h
new file mode 100644 (file)
index 0000000..efa75ed
--- /dev/null
@@ -0,0 +1,127 @@
+/* 
+   FormatScanner.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __FormatScanner_h__
+#define __FormatScanner_h__
+
+#include <stdarg.h>
+#include <Foundation/NSObject.h>
+
+@class NSString;
+
+/*
+ * A FormatScanner scans a NSString format. When it reaches a specifier
+ * similar to printf(3S), it calls a handler object previously registered to
+ * it. The handler object is usually inherited from the DefaultScannerHandler
+ * class. The handler object maintains a mapping between format characters and
+ * selectors that have to be called when a specifier is found in the format
+ * string. The selector must have exactly two arguments: the first one is a
+ * pointer to a va_list and the second one is the format scanner. It is the
+ * responsability of handler to increase the pointer to the va_list with the
+ * size of the object it handles. During the execution of the method the
+ * scanner calls, the handler can ask the scanner about the flags, width,
+ * precision, modifiers and the specifier character. The method should return a
+ * NSString object that represents the converted object.
+ *
+ * FormatScanner is an abstract class. Use the PrintfFormatScanner class that
+ * is used to write printf-like functions. Additional classes can be inherited
+ * to write scanf-like functions.
+ */
+
+typedef enum {
+    FS_ALTERNATE_FORM  = 1,
+    FS_ZERO            = 2,
+    FS_MINUS_SIGN      = 4,
+    FS_PLUS_SIGN       = 8,
+    FS_BLANK           = 16
+} FormatScannerFlags;
+
+@interface FormatScanner : NSObject
+{
+    int                specifierLen, specifierSize;
+    char        *currentSpecifier;
+    id         handler;
+    unsigned   flags;
+    int                width;
+    int                precision;
+    char       modifier;
+    char       characterSpecifier;
+    BOOL       allowFlags:1;
+    BOOL       allowWidth:1;
+    BOOL       allowPeriod:1;
+    BOOL       allowPrecision:1;
+    BOOL       allowModifier:1;
+}
+
+/* This method start the searching of specifiers in `format'. `context' is
+   passed in handleFormatSpecifierWithContext: unmodified. */
+- (BOOL)parseFormatString:(NSString*)format context:(void*)context;
+
+/* This method is called whenever a string between two specifiers is found.
+   Rewrite it in subclasses to perform whatever action you want (for example
+   to collect them in a result string if you're doing printf). The method 
+   should return NO if the scanning of format should stop. */
+- (BOOL)handleOrdinaryString:(NSString*)string;
+
+/* This method is called whenever a format specifier is found in `format'.
+   Again, rewrite this method in subclasses to perform whatever action you
+   want. The method should return NO if the scanning of the format should stop.
+*/
+- (BOOL)handleFormatSpecifierWithContext:(void*)context;
+
+- (void)setFormatScannerHandler:(id)anObject;
+- (id)formatScannerHandler;
+
+- (unsigned int)flags;
+- (int)width;
+- (int)precision;
+- (char)modifier;
+- (char)characterSpecifier;
+- (const char*)currentSpecifier;
+
+- (id)setAllowFlags:(BOOL)flag;
+- (id)setAllowWidth:(BOOL)flag;
+- (id)setAllowPeriod:(BOOL)flag;
+- (id)setAllowPrecision:(BOOL)flag;
+- (id)setAllowModifier:(BOOL)flag;
+
+/* A shorthand for sending all -setAllow* messages with !flag as argument */
+- (id)setAllowOnlySpecifier:(BOOL)flag;
+
+- (BOOL)allowFlags;
+- (BOOL)allowWidth;
+- (BOOL)allowPeriod;
+- (BOOL)allowPrecision;
+- (BOOL)allowModifier;
+
+@end
+
+#endif /* __FormatScanner_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/extensions/GCArray.h b/libFoundation/extensions/GCArray.h
new file mode 100644 (file)
index 0000000..e3a1760
--- /dev/null
@@ -0,0 +1,67 @@
+/* 
+   GCArray.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __GCArray_h__
+#define __GCArray_h__
+
+#include <Foundation/NSArray.h>
+
+@interface GCArray : NSArray
+{
+    id gcNextObject;
+    id gcPreviousObject;
+    struct {
+       unsigned gcVisited:1;
+       unsigned refCount:31;
+    } gcFlags;
+    id         *items;         // data of the array object
+    BOOL*      isGarbageCollectable; // YES if items[i] is gc-able
+    unsigned int itemsCount;   // Actual number of elements
+}
+@end
+
+
+@interface GCMutableArray : NSMutableArray
+{\r
+    id gcNextObject;
+    id gcPreviousObject;
+    struct {
+       unsigned gcVisited:1;
+       unsigned refCount:31;
+    } gcFlags;
+    id         *items;         // data of the array object\r
+    BOOL*      isGarbageCollectable; // YES if items[i] is gc-able
+    unsigned   itemsCount;     // Actual number of elements\r
+    unsigned   maxItems;       // Maximum number of elements\r
+}\r
+@end
+
+#endif /* __GCArray_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/extensions/GCDictionary.h b/libFoundation/extensions/GCDictionary.h
new file mode 100644 (file)
index 0000000..9270f60
--- /dev/null
@@ -0,0 +1,69 @@
+/* 
+   GCDictionary.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __GCDictionary_h__
+#define __GCDictionary_h__
+
+#include <Foundation/NSDictionary.h>
+#include <Foundation/NSMapTable.h>
+
+typedef struct GCObjectCollectable {
+    id object;
+    BOOL isGarbageCollectable;
+} GCObjectCollectable;
+
+@interface GCDictionary : NSDictionary
+{
+    id gcNextObject;
+    id gcPreviousObject;
+    struct {
+       unsigned gcVisited:1;
+       unsigned refCount:31;
+    } gcFlags;
+    NSMapTable*        table;
+}
+/* Private */\r
+- (NSMapEnumerator)__keyEnumerator;
+@end
+
+@interface GCMutableDictionary : NSMutableDictionary
+{
+    id gcNextObject;
+    id gcPreviousObject;
+    struct {
+       unsigned gcVisited:1;
+       unsigned refCount:31;
+    } gcFlags;
+    NSMapTable *table;
+}
+@end
+
+#endif /* __GCDictionary_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/extensions/GCObject.h b/libFoundation/extensions/GCObject.h
new file mode 100644 (file)
index 0000000..c2a47f8
--- /dev/null
@@ -0,0 +1,91 @@
+/* 
+   GCObject.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __GCObject_h__
+#define __GCObject_h__
+
+#include <Foundation/NSObject.h>
+
+@protocol GarbageCollecting
+
+- gcSetNextObject:(id)anObject;
+- gcSetPreviousObject:(id)anObject;
+- (id)gcNextObject;
+- (id)gcPreviousObject;
+
+- (void)gcSetVisited:(BOOL)flag;
+- (BOOL)gcAlreadyVisited;
+
+- (void)gcIncrementRefCount;
+- (void)gcDecrementRefCount;
+
+- (void)gcDecrementRefCountOfContainedObjects;
+- (BOOL)gcIncrementRefCountOfContainedObjects;
+
+- (BOOL)isGarbageCollectable;
+
+@end
+
+
+@interface GCObject : NSObject <GarbageCollecting>
+{
+    id gcNextObject;
+    id gcPreviousObject;
+    struct {
+       unsigned gcVisited:1;
+       unsigned refCount:31;
+    } gcFlags;
+}
+
+- gcSetNextObject:(id)anObject;
+- gcSetPreviousObject:(id)anObject;
+- (id)gcNextObject;
+- (id)gcPreviousObject;
+
+- (void)gcSetVisited:(BOOL)flag;
+- (BOOL)gcAlreadyVisited;
+
+- (void)gcIncrementRefCount;
+- (void)gcDecrementRefCount;
+
+- (void)gcDecrementRefCountOfContainedObjects;
+- (BOOL)gcIncrementRefCountOfContainedObjects;
+
+- (BOOL)isGarbageCollectable;
+
+@end
+
+
+@interface NSObject (GarbageCollecting)
+- (BOOL)isGarbageCollectable;
+@end
+
+#endif /* __GCObject_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/extensions/GarbageCollector.h b/libFoundation/extensions/GarbageCollector.h
new file mode 100644 (file)
index 0000000..486d2d6
--- /dev/null
@@ -0,0 +1,75 @@
+/* 
+   GarbageCollector.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __GarbageCollector_h__
+#define __GarbageCollector_h__
+
+#include <Foundation/NSObject.h>
+
+@interface GarbageCollector : NSObject
+
+/* Determining the garbage collector environment */
+
++ (BOOL)usesBoehmGC;
++ (void)collectGarbages;
+
+@end
+
+
+@interface GarbageCollector (ReferenceCountingGC)
+
++ (void)addObject:(id)anObject;
++ (void)objectWillBeDeallocated:(id)anObject;
+
++ (BOOL)isGarbageCollecting;
+
+@end
+
+
+#if LIB_FOUNDATION_BOEHM_GC
+
+@interface GarbageCollector (BoehmGCSupport)
+
++ (void)registerForFinalizationObserver:(id)observer
+  selector:(SEL)selector
+  object:(id)object;
++ (void)unregisterObserver:(id)observer
+  forObjectFinalization:(id)object;
+
++ (void)allowGarbageCollection;
++ (void)denyGarbageCollection;
+
+@end
+
+#endif /* LIB_FOUNDATION_BOEHM_GC */
+
+
+#endif /* __GarbageCollector_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/extensions/NSException.h b/libFoundation/extensions/NSException.h
new file mode 100644 (file)
index 0000000..c857370
--- /dev/null
@@ -0,0 +1,32 @@
+/* 
+   NSException.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/NSException.h>
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/extensions/PrintfFormatScanner.h b/libFoundation/extensions/PrintfFormatScanner.h
new file mode 100644 (file)
index 0000000..3e0f7c2
--- /dev/null
@@ -0,0 +1,48 @@
+/* 
+   PrintfFormatScanner.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __PrintfFormatScanner_h__
+#define __PrintfFormatScanner_h__
+
+#include <extensions/FormatScanner.h>
+
+@class NSMutableString;
+
+@interface PrintfFormatScanner : FormatScanner
+{
+    NSMutableString *result;
+}
+
+- (NSString *)stringWithFormat:(NSString *)format arguments:(va_list)args;
+
+@end
+
+#endif /* __PrintfFormatScanner_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/extensions/PrintfScannerHandler.h b/libFoundation/extensions/PrintfScannerHandler.h
new file mode 100644 (file)
index 0000000..e27ef89
--- /dev/null
@@ -0,0 +1,61 @@
+/* 
+   PrintfScannerHandler.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __PrintfScannerHandler_h__
+#define __PrintfScannerHandler_h__
+
+#include <stdarg.h>
+#include <extensions/DefaultScannerHandler.h>
+
+@class NSString;
+@class FormatScanner;
+
+@interface PrintfScannerHandler : DefaultScannerHandler
+- (NSString *)convertInt:(va_list*)pInt scanner:(FormatScanner*)scanner;
+- (NSString *)convertChar:(va_list*)pChar scanner:(FormatScanner*)scanner;
+- (NSString *)convertString:(va_list*)pString scanner:(FormatScanner*)scanner;
+- (NSString *)convertFloat:(va_list*)pFloat scanner:(FormatScanner*)scanner;
+- (NSString *)convertPointer:(va_list*)pPointer scanner:(FormatScanner*)scanner;
+@end
+
+@interface PrintfEnumScannerHandler : DefaultEnumScannerHandler
+- (NSString *)convertInt:(NSEnumerator **)pInt scanner:(FormatScanner*)scanner;
+- (NSString *)convertChar:(NSEnumerator **)pChar scanner:(FormatScanner*)scanner;
+- (NSString *)convertString:(NSEnumerator **)pString scanner:(FormatScanner*)scanner;
+- (NSString *)convertFloat:(NSEnumerator **)pFloat scanner:(FormatScanner*)scanner;
+- (NSString *)convertPointer:(NSEnumerator **)pPointer scanner:(FormatScanner*)scanner;
+@end
+
+@interface FSObjectFormat : PrintfScannerHandler
+- (NSString *)convertObject:(va_list *)pId scanner:scanner;
+@end
+
+#endif /* __PrintfScannerHandler_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/extensions/encoding.h b/libFoundation/extensions/encoding.h
new file mode 100644 (file)
index 0000000..d7fefde
--- /dev/null
@@ -0,0 +1,82 @@
+/* Encoding of types for Objective C.
+   Copyright (C) 1993 Free Software Foundation, Inc.
+
+Author: Kresten Krab Thorup
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with files
+   compiled with GCC to produce an executable, this does not cause
+   the resulting executable to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+#ifndef __encoding_INCLUDE_GNU
+#define __encoding_INCLUDE_GNU
+
+#include <ctype.h>
+#include "objc/objc-api.h"
+
+#define _C_CONST    'r'
+#define _C_IN       'n'
+#define _C_INOUT    'N'
+#define _C_OUT      'o'
+#define _C_BYCOPY   'O'
+#define _C_ONEWAY   'V'
+
+#define _F_CONST    0x01
+#define _F_IN       0x01
+#define _F_OUT      0x02
+#define _F_INOUT    0x03
+#define _F_BYCOPY   0x04
+#define _F_ONEWAY   0x08
+
+
+int objc_aligned_size (const char* type);
+int objc_sizeof_type (const char* type);
+int objc_alignof_type (const char* type);
+int objc_aligned_size (const char* type);
+int objc_promoted_size (const char* type);
+const char* objc_skip_type_qualifiers (const char* type);
+const char* objc_skip_typespec (const char* type);
+const char* objc_skip_offset (const char* type);
+const char* objc_skip_argspec (const char* type);
+int method_get_number_of_arguments (struct objc_method*);
+int method_get_sizeof_arguments (struct objc_method*);
+
+char* method_get_first_argument (struct objc_method*,
+                                arglist_t argframe, 
+                                const char** type);
+char* method_get_next_argument (arglist_t argframe, 
+                               const char **type);
+char* method_get_nth_argument (struct objc_method* m, 
+                              arglist_t argframe,
+                              int arg, 
+                              const char **type);
+
+unsigned objc_get_type_qualifiers (const char* type);
+
+
+#endif /* __encoding_INCLUDE_GNU */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/extensions/exceptions/FoundationException.h b/libFoundation/extensions/exceptions/FoundationException.h
new file mode 100644 (file)
index 0000000..c0ff994
--- /dev/null
@@ -0,0 +1,32 @@
+/* 
+   FoundationException.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/exceptions/FoundationException.h>
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/extensions/exceptions/GeneralExceptions.h b/libFoundation/extensions/exceptions/GeneralExceptions.h
new file mode 100644 (file)
index 0000000..bbc49d1
--- /dev/null
@@ -0,0 +1,32 @@
+/* 
+   GeneralExceptions.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/exceptions/GeneralExceptions.h>
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/extensions/exceptions/NSCoderExceptions.h b/libFoundation/extensions/exceptions/NSCoderExceptions.h
new file mode 100644 (file)
index 0000000..bcc3821
--- /dev/null
@@ -0,0 +1,32 @@
+/* 
+   NSCoderExceptions.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#include <Foundation/exceptions/NSCoderExceptions.h>
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/extensions/objc-runtime.h b/libFoundation/extensions/objc-runtime.h
new file mode 100644 (file)
index 0000000..728302e
--- /dev/null
@@ -0,0 +1,217 @@
+/* 
+   objc-runtime.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __objc_runtime_h__
+#define __objc_runtime_h__
+
+#include <objc/objc.h>
+#include <objc/objc-api.h>
+#include <objc/Protocol.h>
+
+
+/* If neither GNU nor NeXT runtimes are defined,
+   make GNU the default runtime
+ */
+#if !(GNU_RUNTIME || NeXT_RUNTIME)
+# define GNU_RUNTIME 1
+#endif
+
+
+#if defined(NX_CURRENT_COMPILER_RELEASE) || defined(__APPLE_CC__)
+
+/* From objc/objc.h */
+typedef void* retval_t;                /* return value */
+typedef void(*apply_t)(void);  /* function pointer */
+typedef union {
+  char *arg_ptr;
+  char arg_regs[sizeof (char*)];
+} *arglist_t;                  /* argument frame */
+
+# define class_pointer isa
+
+#  if defined(__APPLE_CC__)
+#    define _C_ATOM '%'
+#  else
+#    define _C_ATOM _C_STR
+#  endif
+
+#  if defined(__APPLE_CC__)
+extern void objc_error(id object, int code, const char* fmt, ...);
+extern void objc_verror(id object, int code, const char* fmt, va_list ap);
+typedef BOOL (*objc_error_handler)(id, int code, const char *fmt, va_list ap);
+
+/*
+** Error codes
+** These are used by the runtime library, and your
+** error handling may use them to determine if the error is
+** hard or soft thus whether execution can continue or abort.
+*/
+#define OBJC_ERR_UNKNOWN 0             /* Generic error */
+
+#define OBJC_ERR_OBJC_VERSION 1        /* Incorrect runtime version */
+#define OBJC_ERR_GCC_VERSION 2         /* Incorrect compiler version */
+#define OBJC_ERR_MODULE_SIZE 3         /* Bad module size */
+#define OBJC_ERR_PROTOCOL_VERSION 4    /* Incorrect protocol version */
+
+#define OBJC_ERR_MEMORY 10             /* Out of memory */
+
+#define OBJC_ERR_RECURSE_ROOT 20       /* Attempt to archive the root
+                                         object more than once. */
+#define OBJC_ERR_BAD_DATA 21           /* Didn't read expected data */
+#define OBJC_ERR_BAD_KEY 22            /* Bad key for object */
+#define OBJC_ERR_BAD_CLASS 23          /* Unknown class */
+#define OBJC_ERR_BAD_TYPE 24           /* Bad type specification */
+#define OBJC_ERR_NO_READ 25            /* Cannot read stream */
+#define OBJC_ERR_NO_WRITE 26           /* Cannot write stream */
+#define OBJC_ERR_STREAM_VERSION 27     /* Incorrect stream version */
+#define OBJC_ERR_BAD_OPCODE 28         /* Bad opcode */
+
+#define OBJC_ERR_UNIMPLEMENTED 30      /* Method is not implemented */
+
+#define OBJC_ERR_BAD_STATE 40          /* Bad thread state */
+#  endif
+
+# include <extensions/encoding.h>
+#else
+# include <objc/encoding.h>
+#endif /* !NX_CURRENT_COMPILER_RELEASE */
+
+#if (__GNUC__ == 2) && (__GNUC_MINOR__ <= 6) && !defined(__attribute__)
+#  define __attribute__(x)
+#endif
+
+extern BOOL sel_types_match(const char*, const char*);
+
+#if GNU_RUNTIME
+
+#define class_addMethods       class_add_methods
+#define SEL_EQ(sel1, sel2)     sel_eq(sel1, sel2)
+
+#define class_getClassMethod           class_get_class_method
+#define class_getInstanceMethod                class_get_instance_method
+#define class_poseAs                   class_pose_as
+#define objc_getClass                  objc_get_class
+#define objc_lookUpClass               objc_lookup_class
+#define sel_getName                    sel_get_name
+#define sel_getUid                     sel_get_uid
+#define sel_registerName               sel_register_name
+#define sel_isMapped                   sel_is_mapped
+
+#define class_setVersion               class_set_version
+#define class_getVersion               class_get_version
+#define object_getClassName            object_get_class_name
+#define objc_msgLookup                 objc_msg_lookup
+#define next_objc_msg_sendv            objc_msg_sendv
+
+#endif
+
+
+#if NeXT_RUNTIME
+
+#define SEL_EQ(sel1, sel2)     (sel1 == sel2)
+
+extern BOOL sel_isMapped(SEL sel);
+extern const char *sel_getName(SEL sel);
+extern SEL sel_getUid(const char *str);
+extern SEL sel_registerName(const char *str);
+extern const char *object_getClassName(id obj);
+
+extern id class_createInstance(Class, unsigned idxIvars);
+
+extern void class_setVersion(Class, int);
+extern int class_getVersion(Class);
+
+extern struct objc_method* class_getInstanceMethod(Class, SEL);
+extern struct objc_method* class_getClassMethod(Class, SEL);
+
+extern Class class_poseAs(Class imposter, Class original);
+extern id objc_lookUpClass(const char *name);
+
+#define class_get_class_method         class_getClassMethod
+#define class_get_instance_method      class_getInstanceMethod
+#define class_pose_as                  class_poseAs
+#define objc_get_class                 objc_getClass
+#define objc_lookup_class              objc_lookUpClass
+#define sel_get_name                   sel_getName
+#define sel_get_uid                    sel_getUid
+#define sel_get_any_uid                        sel_getUid
+#define sel_register_name              sel_registerName
+#define sel_is_mapped                  sel_isMapped
+#define class_create_instance(CLASS) \
+       class_createInstance(CLASS, 0)
+#define class_set_version              class_setVersion
+#define class_get_version              class_getVersion
+#define object_get_class_name          object_getClassName
+
+#define objc_msg_lookup                        objc_msgLookup
+#define objc_msg_sendv                 next_objc_msg_sendv
+
+extern id objc_msgSend(id self, SEL op, ...);
+extern id objc_msgSendSuper(struct objc_super *super, SEL op, ...);
+
+/* forwarding operations */
+#if !defined(__APPLE_CC__)
+typedef void* marg_list;
+#endif
+
+#if defined(__APPLE_CC__)
+#define __CLS_INFO(cls)         ((cls)->info)
+#define __CLS_ISINFO(cls, mask) ((__CLS_INFO(cls) & mask) == mask)
+#define CLS_ISCLASS(cls) ((cls) && __CLS_ISINFO(cls, CLS_CLASS))
+#endif
+
+extern id next_objc_msg_sendv(id self, SEL op, void* arg_frame);
+
+static inline IMP
+objc_msgLookup(id object, SEL sel) __attribute__((unused));
+
+
+static inline IMP
+objc_msgLookup(id object, SEL sel)
+{
+    if(!object || !sel) return NULL;
+    else {
+       Class class = object->class_pointer;
+       struct objc_method* mth =
+           (CLS_ISCLASS(class) ?
+                 class_get_instance_method(class, sel)
+               : class_get_class_method(class, sel));
+       return mth ? mth->method_imp : (IMP)0;
+    }
+}
+
+#endif /* NeXT_RUNTIME */
+
+
+extern void class_addMethods(Class, struct objc_method_list*);
+void class_add_behavior(Class class, Class behavior);
+
+#endif /* __objc_runtime_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/extensions/support.h b/libFoundation/extensions/support.h
new file mode 100644 (file)
index 0000000..eabcc0b
--- /dev/null
@@ -0,0 +1,37 @@
+/* 
+   support.h
+
+   Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
+   All rights reserved.
+
+   Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+
+   This file is part of libFoundation.
+
+   Permission to use, copy, modify, and distribute this software and its
+   documentation for any purpose and without fee is hereby granted, provided
+   that the above copyright notice appear in all copies and that both that
+   copyright notice and this permission notice appear in supporting
+   documentation.
+
+   We disclaim all warranties with regard to this software, including all
+   implied warranties of merchantability and fitness, in no event shall
+   we be liable for any special, indirect or consequential damages or any
+   damages whatsoever resulting from loss of use, data or profits, whether in
+   an action of contract, negligence or other tortious action, arising out of
+   or in connection with the use or performance of this software.
+*/
+
+#ifndef __support_h__
+#define __support_h__
+
+#define LIB_FOUNDATION_LIBRARY 1
+
+#endif /* __support_h__ */
+
+/*
+  Local Variables:
+  c-basic-offset: 4
+  tab-width: 8
+  End:
+*/
diff --git a/libFoundation/gsfix.make.in b/libFoundation/gsfix.make.in
new file mode 100644 (file)
index 0000000..d90a62e
--- /dev/null
@@ -0,0 +1,19 @@
+# @configure_input@
+
+# preparations for GNUstep.sh-less compilation
+GNUSTEP_FLATTENED    = @GNUSTEP_FLATTENED@
+GNUSTEP_HOST         = @GNUSTEP_HOST@
+GNUSTEP_HOST_CPU     = @GNUSTEP_HOST_CPU@
+GNUSTEP_HOST_OS      = @GNUSTEP_HOST_OS@
+GNUSTEP_HOST_VENDOR  = @GNUSTEP_HOST_VENDOR@
+GNUSTEP_LOCAL_ROOT   = @GNUSTEP_LOCAL_ROOT@
+GNUSTEP_MAKEFILES    = @GNUSTEP_MAKEFILES@
+GNUSTEP_NETWORK_ROOT = @GNUSTEP_NETWORK_ROOT@
+GNUSTEP_PATHLIST     = @GNUSTEP_PATHLIST@
+GNUSTEP_ROOT         = @GNUSTEP_ROOT@
+GNUSTEP_SYSTEM_ROOT  = @GNUSTEP_SYSTEM_ROOT@
+GNUSTEP_USER_ROOT    = @GNUSTEP_USER_ROOT@
+LIBRARY_COMBO        = @LIBRARY_COMBO@
+
+# avoid a gstep-make warning in some setups
+PATH:=$(GNUSTEP_SYSTEM_ROOT)/Tools:$(PATH)
diff --git a/libFoundation/install-sh b/libFoundation/install-sh
new file mode 100755 (executable)
index 0000000..5871924
--- /dev/null
@@ -0,0 +1,238 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+       -c) instcmd="$cpprog"
+           shift
+           continue;;
+
+       -d) dir_arg=true
+           shift
+           continue;;
+
+       -m) chmodcmd="$chmodprog $2"
+           shift
+           shift
+           continue;;
+
+       -o) chowncmd="$chownprog $2"
+           shift
+           shift
+           continue;;
+
+       -g) chgrpcmd="$chgrpprog $2"
+           shift
+           shift
+           continue;;
+
+       -s) stripcmd="$stripprog"
+           shift
+           continue;;
+
+       -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+           shift
+           continue;;
+
+       -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+           shift
+           continue;;
+
+       *)  if [ x"$src" = x ]
+           then
+               src=$1
+           else
+               # this colon is to work around a 386BSD /bin/sh bug
+               :
+               dst=$1
+           fi
+           shift
+           continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+       echo "install:  no input file specified"
+       exit 1
+else
+       true
+fi
+
+if [ x"$dir_arg" != x ]; then
+       dst=$src
+       src=""
+       
+       if [ -d $dst ]; then
+               instcmd=:
+       else
+               instcmd=mkdir
+       fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+       if [ -f $src -o -d $src ]
+       then
+               true
+       else
+               echo "install:  $src does not exist"
+               exit 1
+       fi
+       
+       if [ x"$dst" = x ]
+       then
+               echo "install:  no destination specified"
+               exit 1
+       else
+               true
+       fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+       if [ -d $dst ]
+       then
+               dst="$dst"/`basename $src`
+       else
+               true
+       fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='   
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+       pathcomp="${pathcomp}${1}"
+       shift
+
+       if [ ! -d "${pathcomp}" ] ;
+        then
+               $mkdirprog "${pathcomp}"
+       else
+               true
+       fi
+
+       pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+       $doit $instcmd $dst &&
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+       if [ x"$transformarg" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               dstfile=`basename $dst $transformbasename | 
+                       sed $transformarg`$transformbasename
+       fi
+
+# don't allow the sed command to completely eliminate the filename
+
+       if [ x"$dstfile" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               true
+       fi
+
+# Make a temp file name in the proper directory.
+
+       dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+       $doit $instcmd $src $dsttmp &&
+
+       trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+       $doit $rmcmd -f $dstdir/$dstfile &&
+       $doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
diff --git a/libFoundation/libfoundation.spec b/libFoundation/libfoundation.spec
new file mode 100755 (executable)
index 0000000..7f224ad
--- /dev/null
@@ -0,0 +1,113 @@
+Summary:      Implementation of the OpenStep specification.
+Name:         libfoundation%{libf_major_version}%{libf_minor_version}
+Version:      %{libf_version}
+Release:      %{libf_release}.%{libf_buildcount}%{dist_suffix}
+Vendor:       OpenGroupware.org
+Packager:     Frank Reppin <frank@opengroupware.org>  
+License:      libFoundation license
+URL:          http://www.opengroupware.org
+Group:        Development/Libraries
+AutoReqProv:  off
+Source:       %{libf_source}
+Prefix:       %{libf_prefix}
+Requires:     libobjc-lf2
+Conflicts:    libfoundation
+BuildRoot:    %{_tmppath}/%{name}-%{version}-%{release}-root
+
+%description
+libFoundation is a library that provides an almost complete
+implementation of the OpenStep specification plus many other extensions
+that can be found in the Apple's MacOS X Foundation library.
+
+%package devel
+Summary:      Development files for libFoundation.
+Group:        Development/Libraries
+Requires:     ogo-gnustep_make libfoundation%{libf_major_version}%{libf_minor_version}
+AutoReqProv:  off
+Conflicts:    libfoundation-devel
+
+%description devel
+This package contains the development files of libFoundation.
+
+libFoundation is a library that provides an almost complete
+implementation of the OpenStep specification plus many other extensions
+that can be found in the Apple's MacOS X Foundation library.
+
+%prep
+rm -fr ${RPM_BUILD_ROOT}
+%setup -q -n libfoundation
+
+# ****************************** build ********************************
+%build
+source %{prefix}/OGo-GNUstep/Library/Makefiles/GNUstep.sh
+export CFLAGS=-Wno-import
+./configure
+make %{libf_makeflags} all
+
+# ****************************** install ******************************
+%install
+source %{prefix}/OGo-GNUstep/Library/Makefiles/GNUstep.sh
+mkdir -p ${RPM_BUILD_ROOT}%{prefix}/lib
+mkdir -p ${RPM_BUILD_ROOT}%{prefix}/OGo-GNUstep/Library/Makefiles/Additional
+
+make %{libf_makeflags} INSTALL_ROOT_DIR=${RPM_BUILD_ROOT} \
+                       GNUSTEP_INSTALLATION_DIR=${RPM_BUILD_ROOT}%{prefix} \
+                       FHS_INSTALL_ROOT=${RPM_BUILD_ROOT}%{prefix} \
+                       install
+
+rm -f ${RPM_BUILD_ROOT}%{prefix}/Library/Headers/libFoundation/extensions/exceptions/FoundationException.h
+rm -f ${RPM_BUILD_ROOT}%{prefix}/Library/Headers/libFoundation/extensions/exceptions/GeneralExceptions.h
+rm -f ${RPM_BUILD_ROOT}%{prefix}/Library/Headers/libFoundation/extensions/exceptions/NSCoderExceptions.h
+
+
+# ****************************** post *********************************
+%post
+if [ $1 = 1 ]; then
+  if [ -d %{_sysconfdir}/ld.so.conf.d ]; then
+    echo "%{prefix}/lib" > %{_sysconfdir}/ld.so.conf.d/libfoundation.conf
+  elif [ ! "`grep '%{prefix}/lib' %{_sysconfdir}/ld.so.conf`" ]; then
+    echo "%{prefix}/lib" >> %{_sysconfdir}/ld.so.conf
+  fi
+  /sbin/ldconfig
+fi
+
+# ****************************** postun *********************************
+%postun
+if [ $1 = 0 ]; then
+  if [ -e %{_sysconfdir}/ld.so.conf.d/libfoundation.conf ]; then
+    rm -f %{_sysconfdir}/ld.so.conf.d/libfoundation.conf
+  fi
+  /sbin/ldconfig
+fi
+
+# ****************************** clean ********************************
+%clean
+rm -fr ${RPM_BUILD_ROOT}
+
+# ****************************** files ********************************
+%files
+%defattr(-,root,root,-)
+%{prefix}/bin/Defaults
+%{prefix}/lib/libFoundation*.so.%{libf_version}
+%{prefix}/lib/libFoundation*.so.%{libf_major_version}.%{libf_minor_version}
+%{prefix}/share/libFoundation/CharacterSets
+%{prefix}/share/libFoundation/Defaults
+%{prefix}/share/libFoundation/TimeZoneInfo
+
+%files devel
+%defattr(-,root,root,-)
+%{prefix}/OGo-GNUstep/Library/Makefiles/Additional/libFoundation.make
+%{prefix}/include/lfmemory.h
+%{prefix}/include/real_exception_file.h
+%{prefix}/include/Foundation
+%{prefix}/include/extensions
+%{prefix}/lib/libFoundation*.so
+
+# ********************************* changelog *************************
+%changelog
+* Wed Mar 16 2005 Frank Reppin <frank@opengroupware.org>
+- conflicts: libfoundation (the former name of the package)
+* Tue Jan 18 2005 Frank Reppin <frank@opengroupware.org>
+- dealt with http://bugzilla.opengroupware.org/bugzilla/show_bug.cgi?id=1182
+* Wed Sep 09 2004 Frank Reppin <frank@opengroupware.org>
+- initial build
diff --git a/libFoundation/misc/GNUmakefile b/libFoundation/misc/GNUmakefile
new file mode 100644 (file)
index 0000000..db05fd3
--- /dev/null
@@ -0,0 +1,25 @@
+# GNU makefile
+
+include $(GNUSTEP_MAKEFILES)/common.make
+
+TOOL_NAME = testurl
+
+testurl_OBJC_FILES = testurl.m
+
+include $(GNUSTEP_MAKEFILES)/tool.make
+
+SYSTEM_LIB_DIR += -L/usr/local/lib -L/usr/lib
+
+# raw tools
+
+all :: testnested
+
+clean ::
+       rm -f testnested
+
+LIBDIR="-L/home/helge/OGoRoot/Library/Libraries"
+LIBS=-lobjc -lnsl -lm -lpthread -ldl
+OPT="-O2"
+
+testnested : testnested.c
+       gcc -o $@ -g $(OPT) $(LIBDIR) $< $(LIBS)
diff --git a/libFoundation/misc/testnested.c b/libFoundation/misc/testnested.c
new file mode 100644 (file)
index 0000000..f5122b2
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+  Checks whether nested functions work with the compiler.
+*/
+
+f(void (*nested)())
+{
+    (*nested)();
+}
+
+main()
+{
+    int a = 0;
+    void nested()
+    {
+       a = 1;
+    }
+    f(nested);
+    if(a != 1)
+       exit(1);
+    exit(0);
+}
diff --git a/libFoundation/misc/testurl.m b/libFoundation/misc/testurl.m
new file mode 100644 (file)
index 0000000..6e1b1e3
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+  Checks some URL parsing methods.
+*/
+
+#include <Foundation/Foundation.h>
+
+static void test(void) {
+  NSString *s;
+  NSURL    *u;
+  
+  s = @"http://localhost:80/imap/user@imaphost/blah/blub";
+  u = [NSURL URLWithString:s];
+  NSLog(@"compare:\n  str: %@\n  url: %@", s, u);
+  
+  s = @"http://localhost/imap/user@imaphost/blah/blub";
+  u = [NSURL URLWithString:s];
+  NSLog(@"compare:\n  str: %@\n  url: %@", s, u);
+}
+
+int main(int argc, char **argv, char **env) {
+  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+#if LIB_FOUNDATION_LIBRARY
+  [NSProcessInfo initializeWithArguments:argv count:argc environment:env];
+#endif
+
+  test();
+
+  [pool release];
+  exit(0);
+  return 0;
+}
diff --git a/libFoundation/mkinstalldirs b/libFoundation/mkinstalldirs
new file mode 100755 (executable)
index 0000000..f945dbf
--- /dev/null
@@ -0,0 +1,38 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+errstatus=0
+
+for file
+do
+   set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+   shift
+
+   pathcomp=
+   for d
+   do
+     pathcomp="$pathcomp$d"
+     case "$pathcomp" in
+       -* ) pathcomp=./$pathcomp ;;
+     esac
+
+     if test ! -d "$pathcomp"; then
+        echo "mkdir $pathcomp" 1>&2
+
+        mkdir "$pathcomp" || lasterr=$?
+
+        if test ! -d "$pathcomp"; then
+         errstatus=$lasterr
+        fi
+     fi
+
+     pathcomp="$pathcomp/"
+   done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/libFoundation/sharedlib.mak b/libFoundation/sharedlib.mak
new file mode 100644 (file)
index 0000000..5b3934e
--- /dev/null
@@ -0,0 +1,94 @@
+#  sharedlib.mak
+#
+#  Copyright (C) 1995, 1996, 1997 Ovidiu Predescu and Mircea Oancea.
+#  All rights reserved.
+#
+#  Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
+#  Date: March 1997
+#
+#  This file is part of libFoundation.
+#
+#  Permission to use, copy, modify, and distribute this software and its
+#  documentation for any purpose and without fee is hereby granted, provided
+#  that the above copyright notice appear in all copies and that both that
+#  copyright notice and this permission notice appear in supporting
+#  documentation.
+#
+#  We disclaim all warranties with regard to this software, including all
+#  implied warranties of merchantability and fitness, in no event shall
+#  we be liable for any special, indirect or consequential damages or any
+#  damages whatsoever resulting from loss of use, data or profits, whether in
+#  an action of contract, negligence or other tortious action, arising out of
+#  or in connection with the use or performance of this software.
+#
+
+
+HAVE_SHARED_LIBS       = no
+SHARED_LIB_DIR         = $(libdir)
+SHARED_OBJDIR          = $(OBJDIR)
+
+#
+# OpenStep 4.x
+#
+ifeq ($(TARGET_OS), nextstep4)
+HAVE_SHARED_LIBS       = yes
+SHARED_LIB_DIR         = $(libdir)
+SHARED_OBJDIR          = shared_obj
+
+ifeq ($(WITH_GC), yes)
+GC_LIB = -lgc
+endif
+
+SHARED_LIB_LINK_CMD    = \
+       libtool -dynamic -read_only_relocs suppress -o $@ \
+               -framework System -L$(SHARED_LIB_DIR) -lobjc -lgcc $(GC_LIB) $^
+
+INSTALL_SHARED_LIB_CMD = \
+       cp $(LIB_FOUNDATION_NAME) \
+               $(SHARED_LIB_DIR)/$(LIB_FOUNDATION_NAME)
+
+ADDITIONAL_CC_FLAGS    += -dynamic
+shared_libext  = .a
+endif
+
+
+#
+# Linux ELF
+#
+ifeq ($(findstring linux, $(TARGET_OS)), linux)
+HAVE_SHARED_LIBS       = yes
+SHARED_LIB_DIR         = $(libdir)
+SHARED_OBJDIR          = shared_obj
+SHARED_LIB_LINK_CMD    = \
+       $(CC) -shared -o $@ -Wl,-soname=$(LIB_FOUNDATION_NAME).$(VERSION) $^
+
+INSTALL_SHARED_LIB_CMD = \
+       cp $(LIB_FOUNDATION_NAME) $(SHARED_LIB_DIR)/$(LIB_FOUNDATION_NAME).$(VERSION); \
+       (cd $(SHARED_LIB_DIR); \
+        rm $(LIB_FOUNDATION_NAME); \
+        ln -sf $(LIB_FOUNDATION_NAME).$(VERSION) $(LIB_FOUNDATION_NAME))
+
+ADDITIONAL_CC_FLAGS    += -fPIC
+shared_libext  = .so
+endif
+
+
+#
+# Solaris
+#
+ifeq ($(findstring solaris, $(TARGET_OS)), solaris)
+HAVE_SHARED_LIBS       = yes
+SHARED_LIB_DIR         = $(libdir)
+SHARED_OBJDIR          = shared_obj
+SHARED_LIB_LINK_CMD    = \
+       $(CC) -G -o $@ $^
+
+INSTALL_SHARED_LIB_CMD = \
+       cp $(LIB_FOUNDATION_NAME) $(SHARED_LIB_DIR)/$(LIB_FOUNDATION_NAME).$(VERSION); \
+       (cd $(SHARED_LIB_DIR); \
+        rm $(LIB_FOUNDATION_NAME); \
+        ln -sf $(LIB_FOUNDATION_NAME).$(VERSION) $(LIB_FOUNDATION_NAME))
+
+ADDITIONAL_CC_FLAGS    += -fpic -fPIC
+shared_libext  = .so
+endif