diff --git a/ChangeLog b/ChangeLog index 4a05916a8..84d3060dd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2002-12-02 Adam Fedor + + * Port baseadd to MacOSX. + * Makefile.postamble (header-links): Don't link gnustep/gui to + Foundation for FOUNDATION_LIB=nx + * Headers/gnustep/base/NSObjCRuntime.h (FOUNDATION_EXPORT): Define + only if not defined already. + * Headers/gnustep/base/objc-gnu2next.h: Define _CLS_META, _CLS_CLASS + * Source/Makefile.preamble (libgnustep-baseadd_LIBRARIES_DEPEND_UPON): + Depend on framework Foudation if FOUNDATION_LIB=nx + * Source/objc-gnu2next.m: Move most functions... + * Source/Additions/GSNextRuntime.m: ...to here. + * Source/Additions/GSCompatibility.[hm]: New files. + * Source/Additions/GCDictionary.m: Include it. + * Source/Additions/GSMime.m: Idem. + * Source/Additions/GSXML.m: Idem. + * Source/Additions/GCObject.m: Idem. Null out mutex code + on NeXT_RUNTIME (Need a better fix). + * Source/Additions/GNUmakefile: Don't compile Unicode.m + on FOUNDATION_LIB=nx (not ported yet). + * Source/Additions/GSObjCRuntime.m (GSObjCAddClasses): Version + for NeXT_RUNTIME. + (GSObjCAddClassBehavior): Fixes for NeXT_RUNTIME. + * Source/Additions/behavior.m (behavior_class_add_class): Idem. + 2002-12-02 Jonathan Gapen * Headers/gnustep/base/NSPort.h: Add NSSocketPort interface. diff --git a/Headers/gnustep/base/GSObjCRuntime.h b/Headers/gnustep/base/GSObjCRuntime.h index 8612cbdc3..c1e11ea17 100644 --- a/Headers/gnustep/base/GSObjCRuntime.h +++ b/Headers/gnustep/base/GSObjCRuntime.h @@ -66,9 +66,6 @@ #define nil 0 #endif -#define FOUNDATION_EXPORT -#define FOUNDATION_STATIC_INLINE static inline - #ifndef NO_GNUSTEP /* * Functions for accessing instance variables directly - @@ -115,6 +112,11 @@ GS_EXPORT void GSSetValue(NSObject *self, NSString *key, id val, SEL sel, #include +#ifndef FOUNDATION_EXPORT +#define FOUNDATION_EXPORT +#define FOUNDATION_STATIC_INLINE static inline +#endif + /* * GSObjCClass() return the class of an instance. * The argument to this function must NOT be nil. diff --git a/Headers/gnustep/base/objc-gnu2next.h b/Headers/gnustep/base/objc-gnu2next.h index b1f1da910..e2dde81a2 100644 --- a/Headers/gnustep/base/objc-gnu2next.h +++ b/Headers/gnustep/base/objc-gnu2next.h @@ -53,6 +53,9 @@ typedef void(*apply_t)(void); /* function pointer */ #define METHOD_NULL (struct objc_method *)0 +#define _CLS_META CLS_META +#define _CLS_CLASS CLS_CLASS + #define class_pointer isa typedef struct objc_super Super; diff --git a/Makefile.postamble b/Makefile.postamble index f9f52e8d0..ace852083 100644 --- a/Makefile.postamble +++ b/Makefile.postamble @@ -91,6 +91,7 @@ remove-header-links: -rm -rf Headers/Foundation else +ifneq ($(FOUNDATION_LIB),nx) header-links: $(HEADER_LINK_DEPENDS) -rm -f Headers/Foundation -rm -f Source/Foundation @@ -98,6 +99,7 @@ header-links: $(HEADER_LINK_DEPENDS) remove-header-links: -rm -f Headers/Foundation endif +endif # Automatically run ./configure if needed to generate the makefiles # which we need in order to do our job. If you need any special diff --git a/Source/Additions/GCDictionary.m b/Source/Additions/GCDictionary.m index 8ec78fe28..ae45a9d04 100644 --- a/Source/Additions/GCDictionary.m +++ b/Source/Additions/GCDictionary.m @@ -28,6 +28,7 @@ #include #include +#include "GSCompatibility.h" typedef struct { id object; diff --git a/Source/Additions/GCObject.m b/Source/Additions/GCObject.m index ec66d49f7..e10a36f6c 100644 --- a/Source/Additions/GCObject.m +++ b/Source/Additions/GCObject.m @@ -33,6 +33,7 @@ #include #include +#include "GSCompatibility.h" /* * The head of a linked list of all garbage collecting objects is a @@ -60,7 +61,14 @@ static GCObject *allObjects = nil; static BOOL isCollecting = NO; +#ifdef NeXT_RUNTIME +static void *allocationLock = NULL; +#define objc_mutex_allocate() NULL +#define objc_mutex_lock(lock) +#define objc_mutex_unlock(lock) +#else static objc_mutex_t allocationLock = NULL; +#endif + (void) _becomeMultiThreaded: (NSNotification *)aNotification { diff --git a/Source/Additions/GNUmakefile b/Source/Additions/GNUmakefile index 73fbd36fa..86ff6388b 100644 --- a/Source/Additions/GNUmakefile +++ b/Source/Additions/GNUmakefile @@ -38,9 +38,16 @@ Additions_OBJC_FILES =\ GCDictionary.m \ GSMime.m \ GSXML.m \ - Unicode.m \ behavior.m +ifeq ($(OBJC_RUNTIME), NeXT) +Additions_OBJC_FILES += GSNextRuntime.m +endif +ifeq ($(FOUNDATION_LIB),nx) +Additions_OBJC_FILES += GSCompatibility.m +else +Additions_OBJC_FILES += Unicode.m +endif -include Makefile.preamble diff --git a/Source/Additions/GSCompatibility.h b/Source/Additions/GSCompatibility.h new file mode 100644 index 000000000..daa7699b6 --- /dev/null +++ b/Source/Additions/GSCompatibility.h @@ -0,0 +1,83 @@ +/* GSCompatibility - Extra definitions for compiling on MacOSX + + Copyright (C) 2002 Free Software Foundation, Inc. + + Written by: Adam Fedor + + This file is part of the GNUstep Base Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +*/ + +#ifndef GSCompatibility_H_INCLUDE +#define GSCompatibility_H_INCLUDE + +#ifdef NeXT_Foundation_LIBRARY +#include +#include +#include +#include "gnustep/base/preface.h" +#include "gnustep/base/GSObjCRuntime.h" +#include "gnustep/base/GNUstep.h" + +#define NSDebugMLLog(a, args...) + +typedef enum _NSGNUstepStringEncoding +{ +/* NB. Must not have an encoding with value zero - so we can use zero to + tell that a variable that should contain an encoding has not yet been + initialised */ + GSUndefinedEncoding = 0, + +// GNUstep additions + NSKOI8RStringEncoding = 50, // Russian/Cyrillic + NSISOLatin3StringEncoding = 51, // ISO-8859-3; South European + NSISOLatin4StringEncoding = 52, // ISO-8859-4; North European + NSISOCyrillicStringEncoding = 22, // ISO-8859-5 + NSISOArabicStringEncoding = 53, // ISO-8859-6 + NSISOGreekStringEncoding = 54, // ISO-8859-7 + NSISOHebrewStringEncoding = 55, // ISO-8859-8 + NSISOLatin5StringEncoding = 57, // ISO-8859-9; Turkish + NSISOLatin6StringEncoding = 58, // ISO-8859-10; Nordic + NSISOThaiStringEncoding = 59, // ISO-8859-11 +/* Possible future ISO-8859 additions + // ISO-8859-12 +*/ + NSISOLatin7StringEncoding = 61, // ISO-8859-13 + NSISOLatin8StringEncoding = 62, // ISO-8859-14 + NSISOLatin9StringEncoding = 63, // ISO-8859-15; Replaces ISOLatin1 + NSGB2312StringEncoding = 56, + NSUTF7StringEncoding = 64, // RFC 2152 + NSGSM0338StringEncoding, // GSM (mobile phone) default alphabet + NSBIG5StringEncoding // Traditional chinese +} NSGNUstepStringEncoding; + +#define GS_RANGE_CHECK(RANGE, SIZE) \ + if (RANGE.location > SIZE || RANGE.length > (SIZE - RANGE.location)) \ + [NSException raise: NSRangeException \ + format: @"in %s, range { %u, %u } extends beyond size (%u)", \ + sel_get_name(_cmd), RANGE.location, RANGE.length, SIZE] + +GS_EXPORT NSRecursiveLock *gnustep_global_lock; + +@interface NSArray (GSCompatibility) +- (id) initWithArray: (NSArray*)array copyItems: (BOOL)shouldCopy; +@end + +#endif /* NexT_FOUNDATION_LIB */ + +#endif + diff --git a/Source/Additions/GSCompatibility.m b/Source/Additions/GSCompatibility.m new file mode 100644 index 000000000..db2022eb7 --- /dev/null +++ b/Source/Additions/GSCompatibility.m @@ -0,0 +1,68 @@ +/* GSCompatibility - Extra definitions for compiling on MacOSX + + Copyright (C) 2002 Free Software Foundation, Inc. + + Written by: Adam Fedor + + This file is part of the GNUstep Base Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +*/ +#include "config.h" +#include "GSCompatibility.h" + +/* FIXME: Need to initialize this */ +NSRecursiveLock *gnustep_global_lock = NULL; + +@implementation NSArray (GSCompatibility) + +/** + * Initialize the receiver with the contents of array. + * The order of array is preserved.
+ * If shouldCopy is YES then the objects are copied + * rather than simply retained.
+ * Invokes -initWithObjects:count: + */ +- (id) initWithArray: (NSArray*)array copyItems: (BOOL)shouldCopy +{ + unsigned c = [array count]; + id objects[c]; + + [array getObjects: objects]; + if (shouldCopy == YES) + { + unsigned i; + + for (i = 0; i < c; i++) + { + objects[i] = [objects[i] copy]; + } + self = [self initWithObjects: objects count: c]; +#if GS_WITH_GC == 0 + while (i > 0) + { + [objects[--i] release]; + } +#endif + } + else + { + self = [self initWithObjects: objects count: c]; + } + return self; +} + +@end diff --git a/Source/Additions/GSMime.m b/Source/Additions/GSMime.m index 6bc385f97..ffa01d9b1 100644 --- a/Source/Additions/GSMime.m +++ b/Source/Additions/GSMime.m @@ -54,6 +54,7 @@ #include #include #include +#include "GSCompatibility.h" static NSCharacterSet *whitespace = nil; static NSCharacterSet *rfc822Specials = nil; @@ -2563,7 +2564,7 @@ static NSCharacterSet *tokenSet = nil; if (r.location > pos) { [m appendString: - [v substringFromRange: NSMakeRange(pos, r.location - pos)]]; + [v substringWithRange: NSMakeRange(pos, r.location - pos)]]; } pos = r.location + 1; c = [v characterAtIndex: r.location]; @@ -2589,7 +2590,7 @@ static NSCharacterSet *tokenSet = nil; if (l > pos) { [m appendString: - [v substringFromRange: NSMakeRange(pos, l - pos)]]; + [v substringWithRange: NSMakeRange(pos, l - pos)]]; } [m appendString: @"\""]; v = AUTORELEASE(m); diff --git a/Source/Additions/GSNextRuntime.m b/Source/Additions/GSNextRuntime.m new file mode 100644 index 000000000..fe863b160 --- /dev/null +++ b/Source/Additions/GSNextRuntime.m @@ -0,0 +1,569 @@ +/* Implementation to allow compilation of GNU objc code with NeXT runtime + Copyright (C) 1993,1994 Free Software Foundation, Inc. + + Author: Kresten Krab Thorup + Modified by: Andrew Kachites McCallum + Date: Sep 1994 + + This file is part of the GNUstep Base Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA. +*/ + +#include "config.h" +#include +#include +#ifndef ROUND +#define ROUND(V, A) \ + ({ typeof(V) __v=(V); typeof(A) __a=(A); \ + __a*((__v+__a-1)/__a); }) +#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 _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 "=" */ + 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: + abort(); + } +} + + +/* + 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 _C_FLT: + return __alignof__(float); + break; + + case _C_DBL: + return __alignof__(double); + break; + + 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: + abort(); + } +} + +/* + 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 + occuring in method prototype encodings. +*/ + +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 +#ifdef _C_BYREF + || *type == _C_BYREF +#endif +#ifdef _C_GCINVISIBLE + || *type == _C_GCINVISIBLE +#endif + || *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 _C_FLT: + case _C_DBL: + case _C_VOID: + 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 + abort(); + + 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: + abort(); + } +} + +/* + 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++; + 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; +} + +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; +#ifdef _C_BYREF + case _C_BYREF: res |= _F_BYREF; break; +#endif + case _C_ONEWAY: res |= _F_ONEWAY; break; +#ifdef _C_GCINVISIBLE + case _C_GCINVISIBLE: res |= _F_GCINVISIBLE; break; +#endif + default: flag = NO; + } + + return res; +} + +/* 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 (*t1 == '-') t1++; + if (*t2 == '+') t2++; + 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; +} + +/* +** 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; + +/* +** 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); +} + +/* +** 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; +} + diff --git a/Source/Additions/GSObjCRuntime.m b/Source/Additions/GSObjCRuntime.m index 7dc3c0daf..5c3091d0f 100644 --- a/Source/Additions/GSObjCRuntime.m +++ b/Source/Additions/GSObjCRuntime.m @@ -30,12 +30,15 @@ #include #include +#include +#include +#include #include +#include #include #include #include #include -#include #include /** Deprecated ... use GSObjCFindVariable() */ @@ -273,6 +276,18 @@ GSObjCMakeClass(NSString *name, NSString *superName, NSDictionary *iVars) * The classes argument is an array of NSValue objects containing pointers * to classes previously created by the GSObjCMakeClass() function. */ +#ifdef NeXT_RUNTIME +void +GSObjCAddClasses(NSArray *classes) +{ + unsigned int numClasses = [classes count]; + unsigned int i; + for (i = 0; i < numClasses; i++) + { + objc_addClass((Class)[[classes objectAtIndex: i] pointerValue]); + } +} +#else void GSObjCAddClasses(NSArray *classes) { @@ -313,7 +328,7 @@ GSObjCAddClasses(NSArray *classes) __objc_exec_class (module); __objc_resolve_class_links(); } - +#endif static int behavior_debug = 0; @@ -540,24 +555,14 @@ GSObjCAddClassBehavior(Class receiver, Class behavior) NSCAssert(CLS_ISCLASS(receiver), NSInvalidArgumentException); NSCAssert(CLS_ISCLASS(behavior), NSInvalidArgumentException); -#if NeXT_RUNTIME - if (receiver->instance_size < behavior->instance_size) - { - /* We can allow this since we're pretty sure NXConstantString is - not subclassed. */ - if (receiver == [NXConstantString class]) - { - receiver->instance_size = behavior->instance_size; - } - else - NSCAssert2(receiver->instance_size >= behavior->instance_size, - @"Trying to add behavior (%s) with instance size larger than class (%s)", - class_get_class_name(behavior), class_get_class_name(receiver)); - } -#else /* If necessary, increase instance_size of CLASS. */ if (receiver->instance_size < behavior->instance_size) { +#if NeXT_RUNTIME + NSCAssert2(receiver->instance_size >= behavior->instance_size, + @"Trying to add behavior (%s) with instance size larger than class (%s)", + class_get_class_name(behavior), class_get_class_name(receiver)); +#else NSCAssert(!receiver->subclass_list, @"The behavior-addition code wants to increase the\n" @"instance size of a class, but it cannot because you\n" @@ -565,9 +570,9 @@ GSObjCAddClassBehavior(Class receiver, Class behavior) @"(1) Don't subclass it; (2) Add placeholder instance\n" @"variables to the class, so the behavior-addition code\n" @"will not have to increase the instance size\n"); +#endif receiver->instance_size = behavior->instance_size; } -#endif if (behavior_debug) { @@ -609,7 +614,7 @@ GSObjCAddClassBehavior(Class receiver, Class behavior) method_list = class_nextMethodList(behavior->class_pointer, &iterator); while (method_list != 0) { - GSObjCAddMethods (class->class_pointer, method_list); + GSObjCAddMethods (receiver->class_pointer, method_list); method_list = class_nextMethodList(behavior->class_pointer, &iterator); } } diff --git a/Source/Additions/GSXML.m b/Source/Additions/GSXML.m index da462ff2a..a714ad061 100644 --- a/Source/Additions/GSXML.m +++ b/Source/Additions/GSXML.m @@ -40,6 +40,7 @@ */ #include +#include "GSCompatibility.h" #ifdef HAVE_LIBXML @@ -3215,6 +3216,8 @@ static BOOL warned = NO; if (warned == NO) { warned = YES; NSLog(@"WARNING, use #include #include +#include +#include /* * Build dummy implementations of the classes if libxml is not available diff --git a/Source/Additions/Makefile.preamble b/Source/Additions/Makefile.preamble index 42407ff4e..62d64cac6 100644 --- a/Source/Additions/Makefile.preamble +++ b/Source/Additions/Makefile.preamble @@ -57,4 +57,3 @@ ADDITIONAL_INCLUDE_DIRS = -I../../Headers/gnustep -I../../Headers \ # Additional LDFLAGS to pass to the linker ADDITIONAL_LDFLAGS = - diff --git a/Source/Additions/Unicode.m b/Source/Additions/Unicode.m index 7693e9a98..152582c51 100644 --- a/Source/Additions/Unicode.m +++ b/Source/Additions/Unicode.m @@ -34,6 +34,7 @@ #include #include #include +#include "GSCompatibility.h" #include #include #include diff --git a/Source/Additions/behavior.m b/Source/Additions/behavior.m index b55834546..e48f7bcea 100644 --- a/Source/Additions/behavior.m +++ b/Source/Additions/behavior.m @@ -53,6 +53,7 @@ #include #include #include +#include static BOOL class_is_kind_of(Class self, Class class); @@ -73,19 +74,9 @@ behavior_class_add_class (Class class, Class behavior) NSCAssert(CLS_ISCLASS(behavior), NSInvalidArgumentException); #if NeXT_RUNTIME - if (class->instance_size < behavior->instance_size) - { - /* We can allow this since we're pretty sure NXConstantString is - not subclassed. */ - if (class == [NXConstantString class]) - { - class->instance_size = behavior->instance_size; - } - else - NSCAssert2(class->instance_size >= behavior->instance_size, + NSCAssert2(class->instance_size >= behavior->instance_size, @"Trying to add behavior (%s) with instance size larger than class (%s)", class_get_class_name(behavior), class_get_class_name(class)); - } #else /* If necessary, increase instance_size of CLASS. */ if (class->instance_size < behavior->instance_size) diff --git a/Source/Makefile.preamble b/Source/Makefile.preamble index 319b13cc4..8aa29c37c 100644 --- a/Source/Makefile.preamble +++ b/Source/Makefile.preamble @@ -83,6 +83,9 @@ endif ifeq ($(shared),yes) libgnustep-base_LIBRARIES_DEPEND_UPON += $(CONFIG_SYSTEM_LIBS) endif +ifeq ($(FOUNDATION_LIB),nx) +libgnustep-baseadd_LIBRARIES_DEPEND_UPON += -framework Foundation +endif # Flags dealing with installing and uninstalling # diff --git a/Source/objc-gnu2next.m b/Source/objc-gnu2next.m index 3a9c89206..8280e9267 100644 --- a/Source/objc-gnu2next.m +++ b/Source/objc-gnu2next.m @@ -27,425 +27,6 @@ #include #include "mframe.h" -#ifndef ROUND -#define ROUND(V, A) \ - ({ typeof(V) __v=(V); typeof(A) __a=(A); \ - __a*((__v+__a-1)/__a); }) -#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 _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 "=" */ - 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: - abort(); - } -} - - -/* - 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 _C_FLT: - return __alignof__(float); - break; - - case _C_DBL: - return __alignof__(double); - break; - - 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: - abort(); - } -} - -/* - 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 - occuring in method prototype encodings. -*/ - -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 -#ifdef _C_BYREF - || *type == _C_BYREF -#endif -#ifdef _C_GCINVISIBLE - || *type == _C_GCINVISIBLE -#endif - || *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 _C_FLT: - case _C_DBL: - case _C_VOID: - 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 - abort(); - - 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: - abort(); - } -} - -/* - 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++; - 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; -} - -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; -#ifdef _C_BYREF - case _C_BYREF: res |= _F_BYREF; break; -#endif - case _C_ONEWAY: res |= _F_ONEWAY; break; -#ifdef _C_GCINVISIBLE - case _C_GCINVISIBLE: res |= _F_GCINVISIBLE; break; -#endif - default: flag = NO; - } - - return res; -} - -/* 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 (*t1 == '-') t1++; - if (*t2 == '+') t2++; - 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; -} - id next_objc_msg_sendv(id object, SEL op, void* frame) { arglist_t argFrame = __builtin_apply_args(); @@ -473,127 +54,3 @@ id next_objc_msg_sendv(id object, SEL op, void* frame) #endif __builtin_return(result); } - -/* -** 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; - -/* -** 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); -} - -/* -** 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; -} -