diff --git a/.mulle/share/sde/version/mulle-objc/vscode-clang b/.mulle/share/sde/version/mulle-objc/vscode-clang new file mode 100644 index 00000000..04a373ef --- /dev/null +++ b/.mulle/share/sde/version/mulle-objc/vscode-clang @@ -0,0 +1 @@ +0.16.0 diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..a3d1c538 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,29 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "_comment": "All? It's often convenient in library projects too", + "name": "Debug MulleObjC", + "type": "cppdbg", + "MIMode": "lldb", + "request": "launch", + "stopAtEntry": true, + "program": "${workspaceFolder}/kitchen/Debug/MulleObjC", + "args": [], + "environment": [], + "cwd": "${workspaceFolder}", + "additionalSOLibSearchPath": "${workspaceFolder}/dependency/Debug/lib:${workspaceFolder}/dependency/lib", + "windows": { + "miDebuggerPath": "C:\\mingw64\\bin\\mulle-lldb-mi.exe", + "program": "${workspaceFolder}/kitchen/Debug/MulleObjC.exe" + }, + "osx": { + "miDebuggerPath": "/usr/local/bin/mulle-lldb-mi" + }, + "linux": { + "miDebuggerPath": "/usr/bin/mulle-lldb-mi" + }, + "preLaunchTask": "Debug" + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..7dc67aca --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,16 @@ +{ + "files.exclude": { + "__error": "Not found", + "**/stash": true, + "**/build": true, + "**/var": true, + "**/dependency": true + }, + "files.watcherExclude": { + "__error": "Not found", + "**/stash": true, + "**/build": true, + "**/var": true, + "**/dependency": true + } +} diff --git a/src/MulleObjCUniverse.h b/src/MulleObjCUniverse.h index 801e64ba..cf3295f2 100644 --- a/src/MulleObjCUniverse.h +++ b/src/MulleObjCUniverse.h @@ -14,14 +14,14 @@ #include "include.h" -MULLE_C_CONST_NON_NULL_RETURN +MULLE_C_CONST_NONNULL_RETURN static inline struct _mulle_objc_universe *MulleObjCGetUniverse( void) { return( mulle_objc_global_inlineget_universe( __MULLE_OBJC_UNIVERSEID__)); } -MULLE_C_CONST_NON_NULL_RETURN +MULLE_C_CONST_NONNULL_RETURN static inline struct _mulle_objc_universe *MulleObjCObjectGetUniverse( id self) { if( ! self) diff --git a/src/class/NSObject.m b/src/class/NSObject.m index c83c8842..152fc647 100644 --- a/src/class/NSObject.m +++ b/src/class/NSObject.m @@ -311,6 +311,8 @@ - (BOOL) __isClassClusterPlaceholderObject universe = _mulle_objc_infraclass_get_universe( infraCls); placeholderInfracls = mulle_objc_universe_lookup_infraclass_nofail( universe, classid); + _mulle_objc_class_setup( _mulle_objc_infraclass_as_class( placeholderInfracls)); + placeholder = _MulleObjCClassAllocateObject( placeholderInfracls, 0); placeholder->_cls = infraCls; _mulle_objc_object_constantify_noatomic( placeholder); @@ -334,12 +336,14 @@ + (mulle_objc_classid_t) __instantiatePlaceholderClassid + (instancetype) instantiate { struct _mulle_objc_object *placeholder; + mulle_objc_classid_t classid; retry: placeholder = _mulle_objc_infraclass_get_placeholder( self); if( ! placeholder) { - placeholder = _MulleObjCClassNewInstantiatePlaceholder( self, [self __instantiatePlaceholderClassid]); + classid = [self __instantiatePlaceholderClassid]; + placeholder = _MulleObjCClassNewInstantiatePlaceholder( self, classid); if( ! _mulle_objc_infraclass_set_placeholder( self, placeholder)) { _MulleObjCObjectFree( (id) placeholder); diff --git a/src/class/NSThread.m b/src/class/NSThread.m index 036fe35c..d72a71e5 100644 --- a/src/class/NSThread.m +++ b/src/class/NSThread.m @@ -121,9 +121,6 @@ static void _mulle_objc_thread_become_universethread( struct _mulle_objc_unive assert( thread != _mulle_objc_universe_get_thread( universe)); rc = _mulle_objc_universe_retain( universe); - if( universe->debug.trace.universe) - mulle_objc_universe_trace( universe, "mulle-thread %p retained the universe (%ld)", - (void *) thread, rc); // during the main thread bang, this is already done mulle_objc_thread_setup_threadinfo( universe); @@ -141,7 +138,6 @@ static void _mulle_objc_thread_become_universethread( struct _mulle_objc_unive { mulle_thread_t thread; - // // the universe will do this, if we are the // "main" thread @@ -152,9 +148,6 @@ static void _mulle_objc_thread_become_universethread( struct _mulle_objc_unive if( unset) mulle_objc_thread_unset_threadinfo( universe); // can't call Objective-C anymore - if( universe->debug.trace.universe) - mulle_objc_universe_trace( universe, "mulle-thread %p releases the universe", - (void *) thread); _mulle_objc_universe_release( universe); } @@ -219,12 +212,15 @@ static void _MulleThreadDeregisterInUniverse( NSThread *threadObject, threadObject = [NSThread new]; _mulle_atomic_pointer_nonatomic_write( &threadObject->_thread, (void *) mulle_thread_self()); - _MulleThreadRegisterInUniverse( threadObject, universe, NO); - - // create pool configuration + // + // create pool configuration, ahead of register so it can + // send a notification + // assert( mulle_objc_universe_lookup_infraclass_nofail( universe, @selector( NSAutoreleasePool))); mulle_objc_thread_new_poolconfiguration( universe); + _MulleThreadRegisterInUniverse( threadObject, universe, NO); + return( threadObject); } @@ -635,19 +631,27 @@ static void bouncyBounce( void *arg) // so register this thread to be able to to ObjC calls _mulle_objc_thread_become_universethread( universe); + // + // create pool configuration, ahead of register so it can + // send a notification + // + assert( mulle_objc_universe_lookup_infraclass_nofail( universe, @selector( NSAutoreleasePool))); + mulle_objc_thread_new_poolconfiguration( universe); + // make threadObject known to universe and thread _MulleThreadRegisterInUniverse( threadObject, universe, YES); // the caller will have retained it on out behalf already once, // so reduce this again, and also the thread count now + // + // for a short moment, the number of threads will be one too high + // but its important so you don get races if you are polling + // +mulleIsMultiThreaded + // _mulle_objc_universe_release( universe); info = _mulle_objc_universe_get_universefoundationinfo( universe); _mulle_atomic_pointer_decrement( &info->thread.n_threads); - - // create autoreleaspool - mulle_objc_thread_new_poolconfiguration( universe); - [threadObject main]; } diff --git a/src/function/MulleObjCAllocation.h b/src/function/MulleObjCAllocation.h index 3ee43719..283efc05 100644 --- a/src/function/MulleObjCAllocation.h +++ b/src/function/MulleObjCAllocation.h @@ -113,6 +113,7 @@ static inline void MulleObjCObjectDeallocateMemory( id self, void *p) // resist the urge to add placeholder detection code here +// resist the urge to add _mulle_objc_class_setup here __attribute__((returns_nonnull)) static inline id _MulleObjCClassAllocateObject( Class infraCls, NSUInteger extra) { diff --git a/src/function/MulleObjCFunctions.h b/src/function/MulleObjCFunctions.h index 3675af54..6a26413a 100644 --- a/src/function/MulleObjCFunctions.h +++ b/src/function/MulleObjCFunctions.h @@ -433,3 +433,19 @@ static inline void *MulleObjCInstanceGetExtraBytes( id obj) } NSUInteger MulleObjCClassGetLoadAddress( Class cls); + + +// +// In your +load methods, if you cache the class for use in C functions +// you must ensure, that the class is already properly loaded and +// initialized (this will trigger +initialize). You could also +// "just" call [self class] +// +//static void MulleObjCClassTouch( Class cls) +//{ +// struct _mulle_objc_class *p; + +// p = _mulle_objc_infraclass_as_class( cls); +// _mulle_objc_class_setup( p); +//} + diff --git a/src/mulle-objc-threadfoundationinfo.h b/src/mulle-objc-threadfoundationinfo.h index 928db6ec..af99ffa7 100644 --- a/src/mulle-objc-threadfoundationinfo.h +++ b/src/mulle-objc-threadfoundationinfo.h @@ -93,7 +93,7 @@ static inline struct _mulle_objc_poolconfiguration * /* * Universe interface */ -MULLE_C_CONST_NON_NULL_RETURN +MULLE_C_CONST_NONNULL_RETURN struct _mulle_objc_threadfoundationinfo * mulle_objc_thread_get_threadfoundationinfo( struct _mulle_objc_universe *universe); diff --git a/src/mulle-objc-threadfoundationinfo.m b/src/mulle-objc-threadfoundationinfo.m index 273c4781..0973090c 100644 --- a/src/mulle-objc-threadfoundationinfo.m +++ b/src/mulle-objc-threadfoundationinfo.m @@ -40,7 +40,7 @@ #import "NSThread.h" -MULLE_C_CONST_NON_NULL_RETURN +MULLE_C_CONST_NONNULL_RETURN struct _mulle_objc_threadfoundationinfo * mulle_objc_thread_get_threadfoundationinfo( struct _mulle_objc_universe *universe) { diff --git a/src/mulle-objc-universeconfiguration.m b/src/mulle-objc-universeconfiguration.m index 9612ff99..e79beb19 100644 --- a/src/mulle-objc-universeconfiguration.m +++ b/src/mulle-objc-universeconfiguration.m @@ -202,8 +202,7 @@ static void reset_testallocator( struct _mulle_objc_universe *universe) config->universe.allocator, &config->foundation.exceptiontable); - roots->teardown_callback = config->callbacks.teardown; - + roots->teardown_callback = config->callbacks.teardown; foundation.universefriend.data = roots; foundation.staticstringclass = config->universe.staticstringclass; foundation.universefriend.finalizer = foundationinfo_finalize; diff --git a/src/mulle-objc-universefoundationinfo-private.h b/src/mulle-objc-universefoundationinfo-private.h index 729d01ba..32356f97 100644 --- a/src/mulle-objc-universefoundationinfo-private.h +++ b/src/mulle-objc-universefoundationinfo-private.h @@ -109,7 +109,7 @@ struct _mulle_objc_universefoundationinfo }; -MULLE_C_CONST_NON_NULL_RETURN static inline +MULLE_C_CONST_NONNULL_RETURN static inline struct _mulle_objc_universefoundationinfo * _mulle_objc_universe_get_universefoundationinfo( struct _mulle_objc_universe *universe) { diff --git a/src/protocol/MulleObjCClassCluster.m b/src/protocol/MulleObjCClassCluster.m index c4c9118f..52fe8824 100644 --- a/src/protocol/MulleObjCClassCluster.m +++ b/src/protocol/MulleObjCClassCluster.m @@ -148,14 +148,23 @@ void _mulle_objc_warn_classcluster( struct _mulle_objc_infraclass *self) if( ! strncmp( name, "NS", 2) || ! strncmp( name, "MulleObjC", 9)) { - fprintf( stderr, "warning: Class %08x \"%s\" is a subclass of " - "MulleObjCClassCluster but it gets allocated directly.\n" - "(Non classcluster Foundation subclasses should implement " - "+alloc, for user classes this is fine as\n" - "NSAllocateObject will be used)\n" - "break on _mulle_objc_warn_classcluster to debug)\n", - _mulle_objc_infraclass_get_classid( self), - name); + struct _mulle_objc_universe *universe; + + universe = _mulle_objc_infraclass_get_universe( self); + mulle_objc_universe_fprintf( + universe, + stderr, + "warning: Class %08x \"%s\" is a subclass of " + "MulleObjCClassCluster but it gets allocated directly.\n" + "(Non classcluster Foundation subclasses should implement " + "+alloc, for user classes this is fine as\n" + "NSAllocateObject will be used)\n" + "break on _mulle_objc_warn_classcluster to debug)\n", + _mulle_objc_infraclass_get_classid( self), + name); + + if( universe->debug.warn.crash) + abort(); } } #endif diff --git a/src/protocol/MulleObjCSingleton.m b/src/protocol/MulleObjCSingleton.m index c80403dd..060b7b5a 100644 --- a/src/protocol/MulleObjCSingleton.m +++ b/src/protocol/MulleObjCSingleton.m @@ -80,11 +80,16 @@ void MulleObjCSingletonMarkClassAsSingleton( Class self) _mulle_objc_infraclass_set_state_bit( self, MULLE_OBJC_INFRA_IS_SINGLETON); #if DEBUG else - fprintf( stderr, "warning: Class %08x \"%s\" is a subclass of " - "MulleObjCSingleton but does not implement it " - "as a protocol\n", - _mulle_objc_infraclass_get_classid( self), - _mulle_objc_infraclass_get_name( self)); + { + mulle_objc_universe_fprintf( + _mulle_objc_infraclass_get_universe( self), + stderr, + "warning: Class %08x \"%s\" is a subclass of " + "MulleObjCSingleton but does not implement it " + "as a protocol\n", + _mulle_objc_infraclass_get_classid( self), + _mulle_objc_infraclass_get_name( self)); + } #endif } @@ -126,12 +131,14 @@ + (void) unload } -static id MulleObjCSingletonNew( Class self) +MULLE_C_NONNULL_RETURN +static id MulleObjCSingletonNew( Class self) { id singleton; mulle_objc_implementation_t imp; mulle_objc_methodid_t sel; struct _mulle_objc_class *cls; + struct _mulle_objc_universe *universe; // // avoid +alloc here so that subclass can "abort" on alloc if desired @@ -139,6 +146,23 @@ static id MulleObjCSingletonNew( Class self) // because they are a) often complex like NSNotificationCenter and // b) the user will expect to "leak" there // + + // ensure +initialize has run though (like [self class]) + _mulle_objc_infraclass_setup_if_needed( self); + + universe = _mulle_objc_infraclass_get_universe( self); + if( ! _mulle_objc_infraclass_get_state_bit( self, MULLE_OBJC_INFRA_IS_SINGLETON)) + { + __mulle_objc_universe_raise_internalinconsistency( universe, + "MULLE_OBJC_INFRA_IS_SINGLETON (%s) bit is missing on class " + "\"%s\" %p with id %x (%s)", + _mulle_objc_global_lookup_state_bit_name( MULLE_OBJC_INFRA_IS_SINGLETON), + _mulle_objc_infraclass_get_name( self), + self, + _mulle_objc_infraclass_get_classid( self), + Self._useEphemeralSingleton > 0 ? "ephemeral": "static"); + } + singleton = NSAllocateObject( self, 0, NULL); // allow __initSingleton and init, but prefer __initSingleton @@ -153,6 +177,9 @@ static id MulleObjCSingletonNew( Class self) if( imp) singleton = (*imp)( singleton, sel, singleton); + if( ! singleton) + abort(); + // not really clear what to do/expect if singleton is nil return( (id) singleton); } @@ -162,7 +189,7 @@ static id MulleObjCSingletonNew( Class self) // for the receiver the returnvalue is considered autoreleased, he doesn't // have to retain it, if he doesn't want to keep it // -id MulleObjCSingletonCreate( Class self) +id MulleObjCSingletonCreate( Class self) { id singleton; id dup; @@ -185,21 +212,10 @@ id MulleObjCSingletonCreate( Class self) if( singleton) return( singleton); - if( ! _mulle_objc_infraclass_get_state_bit( self, MULLE_OBJC_INFRA_IS_SINGLETON)) - { - __mulle_objc_universe_raise_internalinconsistency( universe, - "MULLE_OBJC_INFRA_IS_SINGLETON bit is missing on class " - "\"%s\" with id %x", _mulle_objc_infraclass_get_name( self), - _mulle_objc_infraclass_get_classid( self)); - } - singleton = [MulleObjCSingletonNew( self) autorelease]; - if( ! singleton) - abort(); - - dup = _mulle_concurrent_hashmap_register( &Self._ephemeralSingletonInstances, - (intptr_t) self, - singleton); + dup = _mulle_concurrent_hashmap_register( &Self._ephemeralSingletonInstances, + (intptr_t) self, + singleton); if( dup == MULLE_CONCURRENT_INVALID_POINTER) abort(); return( dup ? dup : singleton); @@ -212,19 +228,7 @@ id MulleObjCSingletonCreate( Class self) if( singleton) return( singleton); - if( ! _mulle_objc_infraclass_get_state_bit( self, MULLE_OBJC_INFRA_IS_SINGLETON)) - { - universe = _mulle_objc_infraclass_get_universe( self); - __mulle_objc_universe_raise_internalinconsistency( universe, - "MULLE_OBJC_INFRA_IS_SINGLETON bit is missing on class " - "\"%s\" with id %x", _mulle_objc_infraclass_get_name( self), - _mulle_objc_infraclass_get_classid( self)); - } - singleton = MulleObjCSingletonNew( self); - if( ! singleton) - abort(); - if( _mulle_objc_infraclass_set_singleton( self, (void *) singleton)) { _mulle_objc_object_constantify_noatomic( singleton); // like autorelease @@ -237,6 +241,7 @@ id MulleObjCSingletonCreate( Class self) singleton); return( singleton); } + [singleton release]; } } @@ -250,8 +255,12 @@ - (void) dealloc (intptr_t) _mulle_objc_object_get_isa( self), self); - imp = MulleObjCObjectSearchOverriddenIMP( self, @selector( dealloc), @selector( MulleObjCSingleton), 0); - assert( imp != (IMP) _mulle_objc_class_lookup_implementation( _mulle_objc_object_get_isa( self), @selector( dealloc))); + imp = MulleObjCObjectSearchOverriddenIMP( self, + @selector( dealloc), + @selector( MulleObjCSingleton), + 0); + assert( imp != (IMP) _mulle_objc_class_lookup_implementation( _mulle_objc_object_get_isa( self), + @selector( dealloc))); (*imp)( self, @selector( dealloc), self); } diff --git a/test/NSInvocation/tough-invoke.m b/test/NSInvocation/tough-invoke.m index de0deb37..71df9577 100644 --- a/test/NSInvocation/tough-invoke.m +++ b/test/NSInvocation/tough-invoke.m @@ -79,9 +79,9 @@ - (long long) foo:(short) a :(id) b : (char) c :(double) d : (char) e : (NSRange // example frame x86_64 on mac : // the padding is filled with garbage (also in c)! // - // 0x7ffeefbff030: 0x00000012 0x00000000 (a) 0x00400390 0x00000001 (b) - // 0x7ffeefbff040: 0xefbff0d0 (c) 0x00007ffe (grbg) 0x47ae147b 0x40327ae1 (d) - // 0x7ffeefbff050: 0x000000ee (e) 0x0000000e (grbg) 0x00000012 0x00000000 (f.location) + // 0x7ffeefbff030: 0xgggg0012 (a) 0xgggggggg 0x00400390 0x00000001 (b) + // 0x7ffeefbff040: 0xggggggd0 (c) 0xgggggggg (grbg) 0x47ae147b 0x40327ae1 (d) + // 0x7ffeefbff050: 0xggggggee (e) 0xgggggggg (grbg) 0x00000012 0x00000000 (f.location) // 0x7ffeefbff060: 0x00000030 0x00000000 (f.length) // should stradle two blocks at least diff --git a/test/cache/grow.m b/test/cache/grow.m new file mode 100644 index 00000000..99678448 --- /dev/null +++ b/test/cache/grow.m @@ -0,0 +1,307 @@ +#include + +@interface Foo +@end + +@implementation Foo + ++ (id) alloc +{ + return( mulle_objc_infraclass_alloc_instance( (struct _mulle_objc_infraclass *) self)); +} + +- (void) dealloc +{ + mulle_objc_object_free( self); +} + + +- (void) a_0000 {} +- (void) a_0001 {} +- (void) a_0002 {} +- (void) a_0003 {} +- (void) a_0004 {} +- (void) a_0005 {} +- (void) a_0006 {} +- (void) a_0007 {} +- (void) a_0008 {} +- (void) a_0009 {} +- (void) a_000a {} +- (void) a_000b {} +- (void) a_000c {} +- (void) a_000d {} +- (void) a_000e {} +- (void) a_000f {} + +- (void) a_0010 {} +- (void) a_0011 {} +- (void) a_0012 {} +- (void) a_0013 {} +- (void) a_0014 {} +- (void) a_0015 {} +- (void) a_0016 {} +- (void) a_0017 {} +- (void) a_0018 {} +- (void) a_0019 {} +- (void) a_001a {} +- (void) a_001b {} +- (void) a_001c {} +- (void) a_001d {} +- (void) a_001e {} +- (void) a_001f {} + +- (void) a_0020 {} +- (void) a_0021 {} +- (void) a_0022 {} +- (void) a_0023 {} +- (void) a_0024 {} +- (void) a_0025 {} +- (void) a_0026 {} +- (void) a_0027 {} +- (void) a_0028 {} +- (void) a_0029 {} +- (void) a_002a {} +- (void) a_002b {} +- (void) a_002c {} +- (void) a_002d {} +- (void) a_002e {} +- (void) a_002f {} + +- (void) a_0030 {} +- (void) a_0031 {} +- (void) a_0032 {} +- (void) a_0033 {} +- (void) a_0034 {} +- (void) a_0035 {} +- (void) a_0036 {} +- (void) a_0037 {} +- (void) a_0038 {} +- (void) a_0039 {} +- (void) a_003a {} +- (void) a_003b {} +- (void) a_003c {} +- (void) a_003d {} +- (void) a_003e {} +- (void) a_003f {} + +- (void) b_0000 {} +- (void) b_0001 {} +- (void) b_0002 {} +- (void) b_0003 {} +- (void) b_0004 {} +- (void) b_0005 {} +- (void) b_0006 {} +- (void) b_0007 {} +- (void) b_0008 {} +- (void) b_0009 {} +- (void) b_000a {} +- (void) b_000b {} +- (void) b_000c {} +- (void) b_000d {} +- (void) b_000e {} +- (void) b_000f {} + +- (void) b_0010 {} +- (void) b_0011 {} +- (void) b_0012 {} +- (void) b_0013 {} +- (void) b_0014 {} +- (void) b_0015 {} +- (void) b_0016 {} +- (void) b_0017 {} +- (void) b_0018 {} +- (void) b_0019 {} +- (void) b_001a {} +- (void) b_001b {} +- (void) b_001c {} +- (void) b_001d {} +- (void) b_001e {} +- (void) b_001f {} + +- (void) b_0020 {} +- (void) b_0021 {} +- (void) b_0022 {} +- (void) b_0023 {} +- (void) b_0024 {} +- (void) b_0025 {} +- (void) b_0026 {} +- (void) b_0027 {} +- (void) b_0028 {} +- (void) b_0029 {} +- (void) b_002a {} +- (void) b_002b {} +- (void) b_002c {} +- (void) b_002d {} +- (void) b_002e {} +- (void) b_002f {} + +- (void) b_0030 {} +- (void) b_0031 {} +- (void) b_0032 {} +- (void) b_0033 {} +- (void) b_0034 {} +- (void) b_0035 {} +- (void) b_0036 {} +- (void) b_0037 {} +- (void) b_0038 {} +- (void) b_0039 {} +- (void) b_003a {} +- (void) b_003b {} +- (void) b_003c {} +- (void) b_003d {} +- (void) b_003e {} +- (void) b_003f {} + +@end + + + +main() +{ + Foo *foo; + + // this should grow the cache a couple of times + // calling all those methods + // + foo = [Foo alloc]; + + [foo a_0000]; + [foo a_0001]; + [foo a_0002]; + [foo a_0003]; + [foo a_0004]; + [foo a_0005]; + [foo a_0006]; + [foo a_0007]; + [foo a_0008]; + [foo a_0009]; + [foo a_000a]; + [foo a_000b]; + [foo a_000c]; + [foo a_000d]; + [foo a_000e]; + [foo a_000f]; + + [foo a_0010]; + [foo a_0011]; + [foo a_0012]; + [foo a_0013]; + [foo a_0014]; + [foo a_0015]; + [foo a_0016]; + [foo a_0017]; + [foo a_0018]; + [foo a_0019]; + [foo a_001a]; + [foo a_001b]; + [foo a_001c]; + [foo a_001d]; + [foo a_001e]; + [foo a_001f]; + + [foo a_0020]; + [foo a_0021]; + [foo a_0022]; + [foo a_0023]; + [foo a_0024]; + [foo a_0025]; + [foo a_0026]; + [foo a_0027]; + [foo a_0028]; + [foo a_0029]; + [foo a_002a]; + [foo a_002b]; + [foo a_002c]; + [foo a_002d]; + [foo a_002e]; + [foo a_002f]; + + [foo a_0030]; + [foo a_0031]; + [foo a_0032]; + [foo a_0033]; + [foo a_0034]; + [foo a_0035]; + [foo a_0036]; + [foo a_0037]; + [foo a_0038]; + [foo a_0039]; + [foo a_003a]; + [foo a_003b]; + [foo a_003c]; + [foo a_003d]; + [foo a_003e]; + [foo a_003f]; + + [foo b_0000]; + [foo b_0001]; + [foo b_0002]; + [foo b_0003]; + [foo b_0004]; + [foo b_0005]; + [foo b_0006]; + [foo b_0007]; + [foo b_0008]; + [foo b_0009]; + [foo b_000a]; + [foo b_000b]; + [foo b_000c]; + [foo b_000d]; + [foo b_000e]; + [foo b_000f]; + + [foo b_0010]; + [foo b_0011]; + [foo b_0012]; + [foo b_0013]; + [foo b_0014]; + [foo b_0015]; + [foo b_0016]; + [foo b_0017]; + [foo b_0018]; + [foo b_0019]; + [foo b_001a]; + [foo b_001b]; + [foo b_001c]; + [foo b_001d]; + [foo b_001e]; + [foo b_001f]; + + [foo b_0020]; + [foo b_0021]; + [foo b_0022]; + [foo b_0023]; + [foo b_0024]; + [foo b_0025]; + [foo b_0026]; + [foo b_0027]; + [foo b_0028]; + [foo b_0029]; + [foo b_002a]; + [foo b_002b]; + [foo b_002c]; + [foo b_002d]; + [foo b_002e]; + [foo b_002f]; + + [foo b_0030]; + [foo b_0031]; + [foo b_0032]; + [foo b_0033]; + [foo b_0034]; + [foo b_0035]; + [foo b_0036]; + [foo b_0037]; + [foo b_0038]; + [foo b_0039]; + [foo b_003a]; + [foo b_003b]; + [foo b_003c]; + [foo b_003d]; + [foo b_003e]; + [foo b_003f]; + + [foo dealloc]; + + return( 0); +}