summaryrefslogtreecommitdiff
path: root/Objective-C/JIGS/ObjcRuntimeUtilities.c
blob: f909e0a611d448432719d2dd190f2063c641f10b (plain)
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
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/* ObjcRuntimeUtilities.m - Utilities to add classes and methods 
   in the Objective-C runtime, at runtime.

   Copyright (C) 2000 Free Software Foundation, Inc.
   
   Written by:  Nicola Pero <nicola@brainstorm.co.uk>
   Date: June 2000
   
   This file is part of the GNUstep Java Interface Library.

   It was partially derived by: 

   --
   gg_class.m - interface between guile and GNUstep
   Copyright (C) 1998 Free Software Foundation, Inc.

   Written by:  Richard Frith-Macdonald <richard@brainstorm.co.uk>
   Date: September 1998

   This file is part of the GNUstep-Guile 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.
   */ 

/* This file is a C file so that we can declare and use
 * __objc_exec_class() without conflicting with the declaration and
 * usage of the ObjC compiler.
 */

/*
 *	NOTE - OBJC_VERSION needs to be defined to be the version of the
 *	Objective-C runtime you are using.  You can find this in the file
 *	'init.c' in the GNU objective-C runtime source.
 */
#define	OBJC_VERSION	8

/* FIXME: This should be something like an #ifndef __NEXT_RUNTIME__, but
   __NEXT_RUNTIME__ isn't defined in C code. */
#ifndef __APPLE__

#include "ObjcRuntimeUtilities.h"
#include <string.h>

#ifndef objc_EXPORT
#if libobjc_ISDLL /* linking against DLL version of libobjc */
#  define objc_EXPORT  extern __declspec(dllimport)
#else 
#  define objc_EXPORT  extern
#endif
#endif

BOOL ObjcUtilities_new_class (const char *name, 
			      const char *superclassName, 
			      int ivarNumber, ...)
{
  objc_EXPORT void __objc_exec_class (Module_t module);
  objc_EXPORT void __objc_resolve_class_links ();
  Module_t module;
  Symtab_t symtab;
  Class super_class;
  Class new_class;
  int ivarsize;
  
  //
  // Check that the name for the new class isn't already in use.
  //
  if (objc_lookup_class (name) != Nil) 
    {
      return NO;
    }

  //
  // Check that the superclass exists.
  //
  super_class = objc_lookup_class (superclassName);
  if (super_class == Nil)
    {
      return NO;
    }

  //
  // Prepare a fake module containing only this class.
  //
  module = objc_calloc (1, sizeof (Module));
  module->version = OBJC_VERSION;
  module->size = sizeof (Module);
  module->name = objc_malloc (strlen (name) + 15);
  strcpy ((char*)module->name, "GNUstep-Proxy-");
  strcat ((char*)module->name, name);
  module->symtab = objc_calloc (1, sizeof (Symtab));
  
  symtab = module->symtab;
  symtab->sel_ref_cnt = 0;
  symtab->refs = 0;
  symtab->cls_def_cnt = 1; // We are defining a single class.
  symtab->cat_def_cnt = 0; // But no categories 
  // Allocate space for two classes (the class and its meta class)
  symtab->defs[0] = objc_calloc (2, sizeof (struct objc_class));
  symtab->defs[1] = 0;    // NULL terminate the list.
  
  //
  //	Build class structure.
  //

  // Class
  new_class = (Class)symtab->defs[0];

  // NB: There is a trick here. 
  // The runtime system will look up the name in the following string,
  // and replace it with a pointer to the actual superclass structure.
  // This also means the type of pointer will change, that's why we 
  // need to force it with a (void *)
  new_class->super_class = (void *)superclassName;

  new_class->name = objc_malloc (strlen (name) + 1);
  strcpy ((char*)new_class->name, name);
  new_class->version = 0;
  new_class->info = _CLS_CLASS;
  ivarsize = super_class->instance_size;

  if (ivarNumber > 0)
    {
      // Prepare ivars
      va_list  ap;
      struct objc_ivar *ivar;
      int size, i;

      size = sizeof (struct objc_ivar_list);
      size += (ivarNumber - 1) * sizeof (struct objc_ivar);

      new_class->ivars = (struct objc_ivar_list*) objc_malloc (size);
      new_class->ivars->ivar_count = ivarNumber;
      
      va_start (ap, ivarNumber);
      
      ivar = new_class->ivars->ivar_list;
      
      for (i = 0; i < ivarNumber; i++)
	{
	  char *name = strdup (va_arg (ap, char *));
	  char *type = strdup (va_arg (ap, char *));
	  
	  int	align;
	  
	  ivar->ivar_name = name;
	  ivar->ivar_type = type;
      
	  align = objc_alignof_type (ivar->ivar_type); // pad to alignment
	  ivarsize = align * ((ivarsize + align - 1) /align); // ROUND
	  ivar->ivar_offset = ivarsize;
	  ivarsize += objc_sizeof_type (ivar->ivar_type);
	  ivar++;
	}
      va_end (ap);
    }
  
  new_class->instance_size = ivarsize;
  
  // Meta class
  new_class->class_pointer = &new_class[1];
  new_class->class_pointer->super_class = (void *)superclassName;
  new_class->class_pointer->name = new_class->name;
  new_class->class_pointer->version = 0;
  new_class->class_pointer->info = _CLS_META;
  new_class->class_pointer->instance_size 
    = super_class->class_pointer->instance_size;

  // Insert our new class into the runtime.
  __objc_exec_class (module);
  __objc_resolve_class_links();

  return YES;
}

MethodList *ObjcUtilities_alloc_method_list (int count)
{
  MethodList *ml;
  int extra;

  extra = (sizeof (struct objc_method)) * (count - 1);
  ml = objc_calloc (1, sizeof(MethodList) + extra);
  ml->method_count = count;  
  return ml;
}

void ObjcUtilities_insert_method_in_list (MethodList *ml, 
					  int index, const char *name, 
					  const char *types, IMP imp)
{
  Method *method;

  method = &(ml->method_list[index]);
  method->method_name = (void *)strdup (name);
  method->method_types = strdup (types);
  method->method_imp = imp;
}

void ObjcUtilities_register_method_list (Class class, MethodList *ml)
{
  objc_EXPORT void class_add_method_list (Class class, MethodList_t list);
  objc_EXPORT objc_mutex_t __objc_runtime_mutex;
  
  objc_mutex_lock (__objc_runtime_mutex);
  class_add_method_list (class, ml);
  objc_mutex_unlock (__objc_runtime_mutex);
}

#endif