1
2#import <objc/objc.h>
3
4#if defined (__GNU_LIBOBJC__)
5
6#warning Unable to build NSBlocks for this runtime.
7
8/* FIXME ... these let us link, but blocks will be broken.
9 */
10void *_NSConcreteStackBlock;
11BOOL objc_create_block_classes_as_subclasses_of(Class super)
12{
13  return NO;
14}
15
16#else
17
18#import <objc/objc-api.h>
19#import "ObjectiveC2/objc/runtime.h"
20
21#import "ObjectiveC2/objc/blocks_runtime.h"
22#include <assert.h>
23
24struct objc_class _NSConcreteGlobalBlock;
25struct objc_class _NSConcreteStackBlock;
26
27static struct objc_class _NSConcreteGlobalBlockMeta;
28static struct objc_class _NSConcreteStackBlockMeta;
29
30static struct objc_class _NSBlock;
31static struct objc_class _NSBlockMeta;
32
33void __objc_update_dispatch_table_for_class(Class);
34extern struct sarray *__objc_uninstalled_dtable;
35extern objc_mutex_t __objc_runtime_mutex;
36
37static void
38createNSBlockSubclass(Class superclass, Class newClass,
39  Class metaClass, char *name)
40{
41  // Initialize the metaclass
42  metaClass->class_pointer = superclass->class_pointer;
43  metaClass->super_class = superclass->class_pointer;
44  metaClass->info = _CLS_META;
45  metaClass->dtable = __objc_uninstalled_dtable;
46
47  // Set up the new class
48  newClass->class_pointer = metaClass;
49  newClass->super_class = superclass;
50  newClass->name = name;
51  newClass->info = _CLS_CLASS;
52  newClass->dtable = __objc_uninstalled_dtable;
53
54  // Initialize the dispatch table for the class and metaclass.
55  __objc_update_dispatch_table_for_class(metaClass);
56  __objc_update_dispatch_table_for_class(newClass);
57  CLS_SETINITIALIZED(metaClass);
58  CLS_SETINITIALIZED(newClass);
59  CLS_SETRESOLV(metaClass);
60  CLS_SETRESOLV(newClass);
61  // Add pointer from super class
62  objc_mutex_lock(__objc_runtime_mutex);
63  newClass->sibling_class = newClass->super_class->subclass_list;
64  newClass->super_class->subclass_list = newClass;
65  metaClass->sibling_class = metaClass->super_class->subclass_list;
66  metaClass->super_class->subclass_list = metaClass;
67  objc_mutex_unlock(__objc_runtime_mutex);
68}
69
70#define NEW_CLASS(super, sub) \
71	createNSBlockSubclass(super, &sub, &sub ## Meta, #sub)
72
73BOOL objc_create_block_classes_as_subclasses_of(Class super)
74{
75  if (_NSBlock.super_class != NULL) { return NO; }
76
77  NEW_CLASS(super, _NSBlock);
78  NEW_CLASS(&_NSBlock, _NSConcreteStackBlock);
79  NEW_CLASS(&_NSBlock, _NSConcreteGlobalBlock);
80  return YES;
81}
82
83#endif /* defined (__GNU_LIBOBJC__) */
84
85