1 /*
2 	class.c
3 
4 	QC class support code
5 
6 	Copyright (C) 2002 Bill Currie
7 
8 	Author: Bill Currie <bill@taniwha.org>
9 	Date: 2002/5/7
10 
11 	This program is free software; you can redistribute it and/or
12 	modify it under the terms of the GNU General Public License
13 	as published by the Free Software Foundation; either version 2
14 	of the License, or (at your option) any later version.
15 
16 	This program is distributed in the hope that it will be useful,
17 	but WITHOUT ANY WARRANTY; without even the implied warranty of
18 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 
20 	See the GNU General Public License for more details.
21 
22 	You should have received a copy of the GNU General Public License
23 	along with this program; if not, write to:
24 
25 		Free Software Foundation, Inc.
26 		59 Temple Place - Suite 330
27 		Boston, MA  02111-1307, USA
28 
29 */
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33 
34 #ifdef HAVE_STRING_H
35 # include <string.h>
36 #endif
37 #ifdef HAVE_STRINGS_H
38 # include <strings.h>
39 #endif
40 #include <stdlib.h>
41 
42 #include "QF/dstring.h"
43 #include "QF/hash.h"
44 #include "QF/pr_obj.h"
45 #include "QF/va.h"
46 
47 #include "qfcc.h"
48 
49 #include "codespace.h"
50 #include "class.h"
51 #include "def.h"
52 #include "defspace.h"
53 #include "diagnostic.h"
54 #include "emit.h"
55 #include "expr.h"
56 #include "method.h"
57 #include "options.h"
58 #include "reloc.h"
59 #include "shared.h"
60 #include "strpool.h"
61 #include "struct.h"
62 #include "symtab.h"
63 #include "type.h"
64 #include "value.h"
65 
66 static hashtab_t *class_hash;
67 static hashtab_t *category_hash;
68 static hashtab_t *protocol_hash;
69 
70 // these will be built up further
71 type_t      type_obj_selector = { ev_invalid, 0, ty_struct};
72 type_t      type_SEL = { ev_pointer, "SEL", ty_none, {{&type_obj_selector}}};
73 type_t      type_IMP = { ev_func, "IMP", ty_none,
74 						 {{&type_id, -3, {&type_id, &type_SEL}}}};
75 type_t      type_obj_super = { ev_invalid, 0 };
76 type_t      type_SuperPtr = { ev_pointer, 0, ty_none, {{&type_obj_super}}};
77 type_t      type_supermsg = { ev_func, ".supermsg", ty_none,
78 							  {{&type_id, -3, {&type_SuperPtr, &type_SEL}}}};
79 type_t      type_obj_method = { ev_invalid, 0, ty_struct };
80 type_t      type_obj_method_description = { ev_invalid, 0, ty_struct };
81 type_t      type_obj_category = { ev_invalid, 0, ty_struct};
82 type_t      type_obj_ivar = { ev_invalid, 0, ty_struct};
83 type_t      type_obj_module = { ev_invalid, 0, ty_struct};
84 type_t      type_moduleptr = { ev_pointer, 0, ty_none, {{&type_obj_module}}};
85 type_t      type_obj_exec_class = { ev_func, 0, ty_none,
86 									{{&type_void, 1, { &type_moduleptr }}}};
87 
88 type_t      type_obj_object = {ev_invalid, 0, ty_struct};
89 type_t      type_id = { ev_pointer, "id", ty_none, {{&type_obj_object}}};
90 type_t      type_obj_class = { ev_invalid, 0, ty_struct};
91 type_t      type_Class = { ev_pointer, 0, ty_none, {{&type_obj_class}}};
92 type_t      type_obj_protocol = { ev_invalid, 0, ty_struct};
93 
94 int         obj_initialized = 0;
95 
96 static struct_def_t sel_struct[] = {
97 	{"sel_id",    &type_string},
98 	{"sel_types", &type_string},
99 	{0, 0}
100 };
101 
102 static struct_def_t method_struct[] = {
103 	{"method_name",  &type_SEL},
104 	{"method_types", &type_string},
105 	{"method_imp",   &type_IMP},
106 	{0, 0}
107 };
108 
109 static struct_def_t method_desc_struct[] = {
110 	{"name",  &type_string},
111 	{"types", &type_string},
112 	{0, 0}
113 };
114 
115 static struct_def_t category_struct[] = {
116 	{"category_name",    &type_string},
117 	{"class_name",       &type_string},
118 	{"instance_methods", &type_pointer},
119 	{"class_methods",    &type_pointer},
120 	{"protocols",        &type_pointer},
121 	{0, 0}
122 };
123 
124 static struct_def_t ivar_struct[] = {
125 	{"ivar_name",   &type_string},
126 	{"ivar_type",   &type_string},
127 	{"ivar_offset", &type_integer},
128 	{0, 0}
129 };
130 
131 static struct_def_t super_struct[] = {
132 	{"self", &type_id},
133 	{"class", &type_Class},
134 	{0, 0}
135 };
136 
137 static struct_def_t module_struct[] = {
138 	{"version", &type_integer},
139 	{"size",    &type_integer},
140 	{"name",    &type_string},
141 	{"symtab",  &type_pointer},
142 	{0, 0}
143 };
144 
145 static struct_def_t class_struct[] = {
146 	{"class_pointer",  &type_Class},
147 	{"super_class",    &type_Class},
148 	{"name",           &type_string},
149 	{"version",        &type_integer},
150 	{"info",           &type_integer},
151 	{"instance_size",  &type_integer},
152 	{"ivars",          &type_pointer},
153 	{"methods",        &type_pointer},
154 	{"dtable",         &type_pointer},
155 	{"subclass_list",  &type_pointer},
156 	{"sibling_class",  &type_pointer},
157 	{"protocols",      &type_pointer},
158 	{"gc_object_type", &type_pointer},
159 	{0, 0}
160 };
161 
162 static struct_def_t protocol_struct[] = {
163 	{"class_pointer",    &type_Class},
164 	{"protocol_name",    &type_string},
165 	{"protocol_list",    &type_pointer},
166 	{"instance_methods", &type_pointer},
167 	{"class_methods",    &type_pointer},
168 	{0, 0}
169 };
170 
171 static struct_def_t object_struct[] = {
172 	{"class_pointer", &type_Class},
173 	{0, 0}
174 };
175 
176 int
obj_is_id(const type_t * type)177 obj_is_id (const type_t *type)
178 {
179 	if (type == &type_id)
180 		return 1;
181 	// type may be a qualified id, in which case it will be a pointer to
182 	// a qualified obj_object struct
183 	if (type->type != ev_pointer)
184 		return 0;
185 	if (!is_struct (type->t.fldptr.type))
186 		return 0;
187 	// if the the symtabs match, then type is id in disguise
188 	if (type->t.fldptr.type->t.symtab == type_obj_object.t.symtab)
189 		return 1;
190 	return 0;
191 }
192 
193 int
obj_is_class(const type_t * type)194 obj_is_class (const type_t *type)
195 {
196 	if (type->type == ev_invalid && type->meta == ty_class)
197 		return 1;
198 	return 0;
199 }
200 
201 int
obj_is_Class(const type_t * type)202 obj_is_Class (const type_t *type)
203 {
204 	if (type == &type_Class)
205 		return 1;
206 	// type may be a qualified Class, in which case it will be a pointer to
207 	// a qualified obj_class struct
208 	if (type->type != ev_pointer)
209 		return 0;
210 	if (!is_struct (type->t.fldptr.type))
211 		return 0;
212 	// if the the symtabs match, then type is Class in disguise
213 	if (type->t.fldptr.type->t.symtab == type_obj_class.t.symtab)
214 		return 1;
215 	return 0;
216 }
217 
218 int
obj_is_classptr(const type_t * type)219 obj_is_classptr (const type_t *type)
220 {
221 	// easy cases first :)
222 	if (obj_is_id (type) || obj_is_Class (type))
223 		return 1;
224 	if (type->type != ev_pointer)
225 		return 0;
226 	type = type->t.fldptr.type;
227 	if (obj_is_class (type))
228 		return 1;
229 	return 0;
230 }
231 
232 static protocollist_t *
obj_get_class_protos(const type_t * type)233 obj_get_class_protos (const type_t *type)
234 {
235 	if (is_pointer (type))
236 		type = type->t.fldptr.type;
237 	if (obj_is_class (type))
238 		return type->t.class->protocols;
239 	return 0;
240 }
241 
242 static protocollist_t *
obj_get_protos(const type_t * type)243 obj_get_protos (const type_t *type)
244 {
245 	if (is_pointer (type))
246 		type = type->t.fldptr.type;
247 	return type->protos;
248 }
249 
250 static category_t *
obj_get_categories(const type_t * type)251 obj_get_categories (const type_t *type)
252 {
253 	if (is_pointer (type))
254 		type = type->t.fldptr.type;
255 	if (obj_is_class (type))
256 		return type->t.class->categories;
257 	return 0;
258 }
259 
260 static const char *
obj_classname(const type_t * type)261 obj_classname (const type_t *type)
262 {
263 	static dstring_t *str;
264 	protocollist_t *protos;
265 
266 	if (!str)
267 		str = dstring_new ();
268 	dstring_clearstr (str);
269 	if (obj_is_id (type)) {
270 		dstring_copystr (str, "id");
271 	} else if (obj_is_Class (type)) {
272 		dstring_copystr (str, "Class");
273 	} else {
274 		if (is_pointer (type))
275 			type = type->t.fldptr.type;
276 		if (obj_is_class (type))
277 			dstring_copystr (str, type->t.class->name);
278 	}
279 	if ((protos = obj_get_protos (type)))
280 		print_protocollist (str, protos);
281 	return str->str;
282 }
283 
284 static int
category_implements(category_t * cat,protocol_t * protocol)285 category_implements (category_t *cat, protocol_t *protocol)
286 {
287 	for (; cat; cat = cat->next) {
288 		if (!cat->protocols)
289 			continue;
290 		if (procollist_find_protocol (cat->protocols, protocol))
291 			return 1;
292 	}
293 	return 0;
294 }
295 
296 int
obj_types_assignable(const type_t * dst,const type_t * src)297 obj_types_assignable (const type_t *dst, const type_t *src)
298 {
299 	class_t    *dst_class, *src_class;
300 	category_t *cat;
301 	int         dst_is_proto, src_is_proto;
302 	protocollist_t *dst_protos = 0, *src_protos = 0;
303 	int         i;
304 
305 	//puts ("%$$\"$#%");
306 	if (!obj_is_classptr (dst) || !obj_is_classptr (src))
307 		return -1;
308 
309 	dst_is_proto = obj_is_id (dst) && (dst_protos = obj_get_protos (dst));
310 	src_is_proto = obj_is_id (src) && (src_protos = obj_get_protos (src));
311 
312 	if (dst_is_proto) {
313 		if (src_is_proto) {
314 			// id <protos> = id <protos>
315 			for (i = 0; i < dst_protos->count; i++) {
316 				if (!procollist_find_protocol (src_protos,
317 											   dst_protos->list[i])) {
318 					warning (0, "type %s does not conform to the %s protocol",
319 							 obj_classname (src), dst_protos->list[i]->name);
320 					return 1;
321 				}
322 			}
323 		} else if (!obj_is_id (src)) {
324 			src_protos = obj_get_class_protos (src);
325 			for (i = 0; i < dst_protos->count; i++) {
326 				if (procollist_find_protocol (src_protos, dst_protos->list[i]))
327 					continue;
328 				cat = obj_get_categories (src);
329 				if (cat && category_implements (cat, dst_protos->list[i]))
330 					continue;
331 				warning (0, "class %s does not implement to the %s protocol",
332 						 obj_classname (src), dst_protos->list[i]->name);
333 				return 1;
334 			}
335 			return 1;
336 		}
337 	} else if (src_is_proto) {
338 	} else {
339 	}
340 	if (obj_is_id (dst) || obj_is_id (src))
341 		return 1;
342 
343 	// check dst is a base class of src
344 	dst_class = dst->t.fldptr.type->t.class;
345 	src_class = src->t.fldptr.type->t.class;
346 	//printf ("%s %s\n", dst_class->name, src_class->name);
347 	while (dst_class != src_class && src_class) {
348 		src_class = src_class->super_class;
349 		//if (src_class)
350 		//	printf ("%s %s\n", dst_class->name, src_class->name);
351 	}
352 	if (dst_class == src_class)
353 		return 1;
354 	return 0;
355 }
356 
357 static const char *
class_get_key(const void * class,void * unused)358 class_get_key (const void *class, void *unused)
359 {
360 	return ((class_t *) class)->name;
361 }
362 
363 static const char *
protocol_get_key(const void * protocol,void * unused)364 protocol_get_key (const void *protocol, void *unused)
365 {
366 	return ((protocol_t *) protocol)->name;
367 }
368 
369 const char *
get_class_name(class_type_t * class_type,int pretty)370 get_class_name (class_type_t *class_type, int pretty)
371 {
372 	switch (class_type->type) {
373 		case ct_class:
374 			if (pretty)
375 				return class_type->c.class->name;
376 			else
377 				return va ("%s_", class_type->c.class->name);
378 		case ct_category:
379 			if (pretty)
380 				return va ("%s (%s)", class_type->c.category->class->name,
381 						   class_type->c.category->name);
382 			else
383 				return va ("%s_%s", class_type->c.category->class->name,
384 						   class_type->c.category->name);
385 		case ct_protocol:
386 			return va ("<%s>", class_type->c.protocol->name);
387 	}
388 	return "???";
389 }
390 
391 symbol_t *
class_symbol(class_type_t * class_type,int external)392 class_symbol (class_type_t *class_type, int external)
393 {
394 	const char *name = 0;
395 	type_t     *type = 0;
396 	symbol_t   *sym;
397 
398 	switch (class_type->type) {
399 		case ct_category:
400 			name = va ("_OBJ_CATEGORY_%s_%s",
401 					   class_type->c.category->class->name,
402 					   class_type->c.category->name);
403 			type = &type_obj_category;
404 			break;
405 		case ct_class:
406 			name = va ("_OBJ_CLASS_%s", class_type->c.class->name);
407 			type = &type_obj_class;
408 			break;
409 		case ct_protocol:
410 			return 0;		// probably in error recovery
411 	}
412 	sym = make_symbol (name, type, pr.far_data,
413 					   external ? sc_extern : sc_global);
414 	if (!sym->table)
415 		symtab_addsymbol (pr.symtab, sym);
416 	return sym;
417 }
418 
419 static class_t *
_get_class(symbol_t * sym,int create)420 _get_class (symbol_t *sym, int create)
421 {
422 	class_t    *c;
423 
424 	if (!class_hash)
425 		class_hash = Hash_NewTable (1021, class_get_key, 0, 0);
426 	if (sym) {
427 		c = Hash_Find (class_hash, sym->name);
428 		if (c || !create)
429 			return c;
430 	}
431 
432 	c = calloc (sizeof (class_t), 1);
433 	c->methods = new_methodlist ();
434 	c->class_type.type = ct_class;
435 	c->class_type.c.class = c;
436 	if (sym) {
437 		c->name = sym->name;
438 		Hash_Add (class_hash, c);
439 		sym->sy_type = sy_class;
440 	}
441 
442 	sym = class_symbol (&c->class_type, 1);
443 	c->def = sym->s.def;
444 
445 	return c;
446 }
447 
448 class_t *
get_class(symbol_t * sym,int create)449 get_class (symbol_t *sym, int create)
450 {
451 	class_t    *c;
452 	type_t      new;
453 
454 	if (!(c = _get_class (sym, create)))
455 		return c;
456 
457 	memset (&new, 0, sizeof (new));
458 	new.type = ev_invalid;
459 	new.name = c->name;
460 	new.meta = ty_class;
461 	new.t.class = c;
462 	c->type = find_type (&new);
463 	if (sym)
464 		sym->type = c->type;
465 	return c;
466 }
467 
468 static void
set_self_type(class_t * class,method_t * method)469 set_self_type (class_t *class, method_t *method)
470 {
471 	if (method->instance)
472 		method->params->type = pointer_type (class->type);
473 	else
474 		method->params->type = &type_Class;
475 }
476 
477 static void
methods_set_self_type(class_t * class,methodlist_t * methods)478 methods_set_self_type (class_t *class, methodlist_t *methods)
479 {
480 	method_t   *method;
481 
482 	for (method = methods->head; method; method = method->next)
483 		set_self_type (class, method);
484 }
485 
486 void
class_add_methods(class_t * class,methodlist_t * methods)487 class_add_methods (class_t *class, methodlist_t *methods)
488 {
489 	if (!methods)
490 		return;
491 
492 	*class->methods->tail = methods->head;
493 	class->methods->tail = methods->tail;
494 	free (methods);
495 
496 	methods_set_self_type (class, class->methods);
497 }
498 
499 void
class_add_protocols(class_t * class,protocollist_t * protocols)500 class_add_protocols (class_t *class, protocollist_t *protocols)
501 {
502 	int         i;
503 	protocol_t *p;
504 	methodlist_t *methods;
505 
506 	if (!protocols)
507 		return;
508 
509 	methods = class->methods;
510 
511 	for (i = 0; i < protocols->count; i++) {
512 		p = protocols->list[i];
513 		copy_methods (methods, p->methods);
514 		if (p->protocols)
515 			class_add_protocols (class, p->protocols);
516 	}
517 	class->protocols = protocols;
518 }
519 
520 static void
begin_category(category_t * category)521 begin_category (category_t *category)
522 {
523 	pr_category_t *pr_category;
524 	class_t    *class = category->class;
525 	symbol_t   *sym;
526 	def_t      *def;
527 	defspace_t *space;
528 
529 	current_class = &category->class_type;
530 	sym = class_symbol (current_class, 0);
531 	category->def = def = sym->s.def;
532 	def->initialized = def->constant = def->nosave = 1;
533 	space = def->space;
534 
535 	pr_category = &D_STRUCT (pr_category_t, def);
536 	EMIT_STRING (space, pr_category->category_name, category->name);
537 	EMIT_STRING (space, pr_category->class_name, class->name);
538 	EMIT_DEF (space, pr_category->protocols,
539 			  emit_protocol_list (category->protocols,
540 								  va ("%s_%s", class->name, category->name)));
541 }
542 
543 typedef struct {
544 	int         count;
545 	symbol_t   *ivars;
546 	dstring_t  *encoding;
547 } ivar_data_t;
548 
549 static void
emit_ivar_count(def_t * def,void * data,int index)550 emit_ivar_count (def_t *def, void *data, int index)
551 {
552 	ivar_data_t *ivar_data = (ivar_data_t *) data;
553 
554 	if (def->type != &type_integer)
555 		internal_error (0, "%s: expected integer def", __FUNCTION__);
556 	D_INT (def) = ivar_data->count;
557 }
558 
559 static void
emit_ivar_list_item(def_t * def,void * data,int index)560 emit_ivar_list_item (def_t *def, void *data, int index)
561 {
562 	ivar_data_t *ivar_data = (ivar_data_t *) data;
563 	symbol_t   *ivar_sym;
564 	pr_ivar_t  *ivar;
565 	defspace_t *space;
566 
567 #if 0
568 	//FIXME the type is dynamic, so need a way to pass it before it cn be
569 	//checked
570 	if (def->type != &XXX)
571 		internal_error (0, "%s: expected XXX def",
572 						__FUNCTION__);
573 #endif
574 	if (index < 0 || index >= ivar_data->count)
575 		internal_error (0, "%s: out of bounds index: %d %d",
576 						__FUNCTION__, index, ivar_data->count);
577 
578 	for (ivar_sym = ivar_data->ivars; ivar_sym; ivar_sym = ivar_sym->next) {
579 		if (ivar_sym->sy_type != sy_var)
580 			continue;
581 		if (!index--)
582 			break;
583 	}
584 
585 	ivar = D_POINTER (pr_ivar_t, def);
586 	space = def->space;
587 	dstring_clearstr (ivar_data->encoding);
588 
589 	EMIT_STRING (space, ivar->ivar_name, ivar_sym->name);
590 	encode_type (ivar_data->encoding, ivar_sym->type);
591 	EMIT_STRING (space, ivar->ivar_type, ivar_data->encoding->str);
592 	ivar->ivar_offset = ivar_sym->s.offset;
593 }
594 
595 static def_t *
emit_ivars(symtab_t * ivars,const char * name)596 emit_ivars (symtab_t *ivars, const char *name)
597 {
598 	static struct_def_t ivar_list_struct[] = {
599 		{"ivar_count", &type_integer, emit_ivar_count},
600 		{"ivar_list",  0,             emit_ivar_list_item},
601 		{0, 0}
602 	};
603 	ivar_data_t ivar_data = {0, 0, 0};
604 	symbol_t   *s;
605 	def_t      *def;
606 
607 	ivar_data.encoding = dstring_newstr ();
608 	if (ivars) {
609 		ivar_data.ivars = ivars->symbols;
610 		for (s = ivars->symbols; s; s = s->next)
611 			if (s->sy_type == sy_var)
612 				ivar_data.count++;
613 	}
614 	ivar_list_struct[1].type = array_type (&type_obj_ivar, ivar_data.count);
615 
616 	def = emit_structure (va ("_OBJ_INSTANCE_VARIABLES_%s", name), 's',
617 						  ivar_list_struct, 0, &ivar_data, sc_static);
618 
619 	dstring_delete (ivar_data.encoding);
620 	return def;
621 }
622 
623 static void
begin_class(class_t * class)624 begin_class (class_t *class)
625 {
626 	def_t      *meta_def;
627 	pr_class_t *meta;
628 	pr_class_t *pr_class;
629 	symbol_t   *sym;
630 	def_t      *def;
631 	defspace_t *space;
632 
633 	sym = make_symbol (va ("_OBJ_METACLASS_%s", class->name),
634 					   &type_obj_class, pr.far_data, sc_static);
635 	meta_def = sym->s.def;
636 	meta_def->initialized = meta_def->constant = meta_def->nosave = 1;
637 	space = meta_def->space;
638 	meta = &D_STRUCT (pr_class_t, meta_def);
639 	EMIT_STRING (space, meta->class_pointer, class->name);
640 	if (class->super_class)
641 		EMIT_STRING (space, meta->super_class, class->super_class->name);
642 	EMIT_STRING (space, meta->name, class->name);
643 	meta->info = _PR_CLS_META;
644 	meta->instance_size = type_size (&type_obj_class);
645 	EMIT_DEF (space, meta->ivars,
646 			  emit_ivars (type_obj_class.t.class->ivars, "Class"));
647 	current_class = &class->class_type;
648 	sym = class_symbol (current_class, 0);
649 	class->def = def = sym->s.def;
650 	def->initialized = def->constant = def->nosave = 1;
651 	space = def->space;
652 
653 	pr_class = &D_STRUCT (pr_class_t, def);
654 	EMIT_DEF (space, pr_class->class_pointer, meta_def);
655 	if (class->super_class) {
656 		class_type_t class_type = {ct_class, {0}};
657 		class_type.c.class = class->super_class;
658 		EMIT_STRING (space, pr_class->super_class, class->super_class->name);
659 		class_symbol (&class_type, 1);
660 	}
661 	EMIT_STRING (space, pr_class->name, class->name);
662 	pr_class->info = _PR_CLS_CLASS;
663 	EMIT_DEF (space, pr_class->protocols,
664 			  emit_protocol_list (class->protocols, class->name));
665 }
666 
667 void
class_begin(class_type_t * class_type)668 class_begin (class_type_t *class_type)
669 {
670 	if (current_class) {
671 		warning (0, "‘@end’ missing in implementation context");
672 		class_finish (current_class);
673 		current_class = 0;
674 	}
675 	switch (class_type->type) {
676 		case ct_category:
677 			begin_category (class_type->c.category);
678 			break;
679 		case ct_class:
680 			begin_class (class_type->c.class);
681 			break;
682 		case ct_protocol:
683 			return;			// probably error recovery
684 	}
685 }
686 
687 void
emit_class_ref(const char * class_name)688 emit_class_ref (const char *class_name)
689 {
690 	symbol_t   *ref_sym;
691 	symbol_t   *name_sym;
692 	def_t      *ref_def;
693 	def_t      *name_def;
694 
695 	ref_sym = make_symbol (va (".obj_class_ref_%s", class_name), &type_pointer,
696 						   pr.far_data, sc_static);
697 	if (!ref_sym->table)
698 		symtab_addsymbol (pr.symtab, ref_sym);
699 	ref_def = ref_sym->s.def;
700 	if (ref_def->initialized)
701 		return;
702 	ref_def->initialized = ref_def->constant = ref_def->nosave = 1;
703 	name_sym = make_symbol (va (".obj_class_name_%s", class_name),
704 							&type_pointer, pr.far_data, sc_extern);
705 	if (!name_sym->table)
706 		symtab_addsymbol (pr.symtab, name_sym);
707 	name_def = name_sym->s.def;
708 	if (!name_def->external)
709 		D_INT (ref_def) = name_def->offset;
710 	reloc_def_def (name_def, ref_def);
711 }
712 
713 static void
emit_class_name(const char * class_name)714 emit_class_name (const char *class_name)
715 {
716 	symbol_t   *name_sym;
717 	def_t      *name_def;
718 
719 	name_sym = make_symbol (va (".obj_class_name_%s", class_name),
720 							&type_pointer, pr.far_data, sc_global);
721 	if (!name_sym->table)
722 		symtab_addsymbol (pr.symtab, name_sym);
723 	name_def = name_sym->s.def;
724 	if (name_def->initialized)
725 		return;
726 	name_def->initialized = name_def->constant = 1;
727 	name_def->nosave = 1;
728 	D_INT (name_def) = 0;
729 }
730 
731 void
emit_category_ref(const char * class_name,const char * category_name)732 emit_category_ref (const char *class_name, const char *category_name)
733 {
734 	symbol_t   *ref_sym;
735 	symbol_t   *name_sym;
736 	def_t      *ref_def;
737 	def_t      *name_def;
738 
739 	ref_sym = make_symbol (va (".obj_category_ref_%s_%s",
740 						   class_name, category_name),
741 					   &type_pointer, pr.far_data, sc_static);
742 	if (!ref_sym->table)
743 		symtab_addsymbol (pr.symtab, ref_sym);
744 	ref_def = ref_sym->s.def;
745 	if (ref_def->initialized)
746 		return;
747 	ref_def->initialized = ref_def->constant = 1;
748 	ref_def->nosave = 1;
749 	name_sym = make_symbol (va (".obj_category_name_%s_%s",
750 						   class_name, category_name),
751 					   &type_pointer, pr.far_data, sc_extern);
752 	if (!name_sym->table)
753 		symtab_addsymbol (pr.symtab, name_sym);
754 	name_def = name_sym->s.def;
755 	if (!name_def->external)
756 		D_INT (ref_def) = name_def->offset;
757 	reloc_def_def (name_def, ref_def);
758 }
759 
760 static void
emit_category_name(const char * class_name,const char * category_name)761 emit_category_name (const char *class_name, const char *category_name)
762 {
763 	symbol_t   *name_sym;
764 	def_t      *name_def;
765 
766 	name_sym = make_symbol (va (".obj_category_name_%s_%s",
767 							    class_name, category_name),
768 							&type_pointer, pr.far_data, sc_global);
769 	if (!name_sym->table)
770 		symtab_addsymbol (pr.symtab, name_sym);
771 	name_def = name_sym->s.def;
772 	if (name_def->initialized)
773 		return;
774 	name_def->initialized = name_def->constant = 1;
775 	name_def->nosave = 1;
776 	D_INT (name_def) = 0;
777 }
778 
779 static void
finish_category(category_t * category)780 finish_category (category_t *category)
781 {
782 	pr_category_t *pr_category;
783 	class_t    *class = category->class;
784 	char       *name;
785 	defspace_t *space;
786 
787 	if (!category->def)	// probably in error recovery
788 		return;
789 	name = nva ("%s_%s", class->name, category->name);
790 	pr_category = &D_STRUCT (pr_category_t, category->def);
791 	space = category->def->space;
792 	EMIT_DEF (space, pr_category->instance_methods,
793 			emit_methods (category->methods, name, 1));
794 	EMIT_DEF (space, pr_category->class_methods,
795 			emit_methods (category->methods, name, 0));
796 	free (name);
797 	emit_class_ref (class->name);
798 	emit_category_name (class->name, category->name);
799 }
800 
801 static void
finish_class(class_t * class)802 finish_class (class_t *class)
803 {
804 	pr_class_t *meta;
805 	pr_class_t *cls;
806 	defspace_t *space;
807 
808 	if (pr.error_count)	// probably in error recovery
809 		return;
810 	space = class->def->space;
811 	cls = &D_STRUCT (pr_class_t, class->def);
812 
813 	meta = &G_STRUCT (space, pr_class_t, cls->class_pointer);
814 
815 	EMIT_DEF (space, meta->methods, emit_methods (class->methods,
816 												  class->name, 0));
817 
818 	cls->instance_size = type_size (class->type);
819 	EMIT_DEF (space, cls->ivars, emit_ivars (class->ivars, class->name));
820 	EMIT_DEF (space, cls->methods, emit_methods (class->methods,
821 												 class->name, 1));
822 	if (class->super_class)
823 		emit_class_ref (class->super_class->name);
824 	emit_class_name (class->name);
825 }
826 
827 void
class_finish(class_type_t * class_type)828 class_finish (class_type_t *class_type)
829 {
830 	switch (class_type->type) {
831 		case ct_category:
832 			finish_category (class_type->c.category);
833 			break;
834 		case ct_class:
835 			finish_class (class_type->c.class);
836 			break;
837 		case ct_protocol:
838 			return;			// probably in error recovery
839 	}
840 }
841 
842 class_t *
extract_class(class_type_t * class_type)843 extract_class (class_type_t *class_type)
844 {
845 	switch (class_type->type) {
846 		case ct_class:
847 			return current_class->c.class;
848 		case ct_category:
849 			return current_class->c.category->class;
850 		case ct_protocol:
851 			return 0;		// probably in error recovery
852 	}
853 	return 0;				// should not happen
854 }
855 
856 int
class_access(class_type_t * class_type,class_t * class)857 class_access (class_type_t *class_type, class_t *class)
858 {
859 	class_t    *cur;
860 	if (class_type) {
861 		if (!(cur = extract_class (class_type)))
862 			return vis_private;
863 		if (cur == class)
864 			return vis_private;
865 		cur = cur->super_class;
866 		while (cur) {
867 			if (cur == class)
868 				return vis_protected;
869 			cur = cur->super_class;
870 		}
871 	}
872 	return vis_public;
873 }
874 
875 symbol_t *
class_find_ivar(class_t * class,int vis,const char * name)876 class_find_ivar (class_t *class, int vis, const char *name)
877 {
878 	symbol_t   *ivar;
879 
880 	ivar = symtab_lookup (class->ivars, name);
881 	if (ivar) {
882 		if (ivar->visibility > (vis_t) vis)
883 			goto access_error;
884 		return ivar;
885 	}
886 	error (0, "%s.%s does not exist", class->name, name);
887 	return 0;
888 access_error:
889 	error (0, "%s.%s is not accessable here", class->name, name);
890 	return 0;
891 }
892 
893 method_t *
class_find_method(class_type_t * class_type,method_t * method)894 class_find_method (class_type_t *class_type, method_t *method)
895 {
896 	methodlist_t *methods = 0, *start_methods;
897 	method_t   *m;
898 	dstring_t  *sel;
899 	class_t    *class = 0, *start_class;
900 
901 	switch (class_type->type) {
902 		case ct_category:
903 			methods = class_type->c.category->methods;
904 			class = class_type->c.category->class;
905 			break;
906 		case ct_class:
907 			class = class_type->c.class;
908 			methods = class->methods;
909 			break;
910 		case ct_protocol:
911 			return 0;		// probably in error recovery
912 	}
913 	start_methods = methods;
914 	start_class = class;
915 	while (class) {
916 		for (m = methods->head; m; m = m->next)
917 			if (method_compare (method, m)) {
918 				if (m->type != method->type)
919 					error (0, "method type mismatch");
920 				if (methods != start_methods) {
921 					m = copy_method (m);
922 					set_self_type (start_class, m);
923 					add_method (start_methods, m);
924 				}
925 				method_set_param_names (m, method);
926 				return m;
927 			}
928 		if (class->methods == methods)
929 			class = class->super_class;
930 		else
931 			methods = class->methods;
932 	}
933 	sel = dstring_newstr ();
934 	selector_name (sel, (keywordarg_t *)method->selector);
935 	set_self_type (start_class, method);
936 	add_method (start_methods, method);
937 	dstring_delete (sel);
938 	return method;
939 }
940 
941 method_t *
class_message_response(class_t * class,int class_msg,expr_t * sel)942 class_message_response (class_t *class, int class_msg, expr_t *sel)
943 {
944 	selector_t *selector;
945 	method_t   *m;
946 	class_t    *c = class;
947 	category_t *cat;
948 
949 	selector = get_selector (sel);
950 	if (!selector)
951 		return 0;
952 	if (class && class->type != &type_obj_object) {
953 		while (c) {
954 			for (cat = c->categories; cat; cat = cat->next) {
955 				for (m = cat->methods->head; m; m = m->next) {
956 					if (((!c->super_class && class_msg)
957 						 || class_msg != m->instance)
958 						&& strcmp (selector->name, m->name) == 0)
959 						return m;
960 				}
961 			}
962 			for (m = c->methods->head; m; m = m->next) {
963 				if (((!c->super_class && class_msg)
964 					 || class_msg != m->instance)
965 					&& strcmp (selector->name, m->name) == 0)
966 					return m;
967 			}
968 			c = c->super_class;
969 		}
970 		//FIXME right option?
971 		if (options.warnings.interface_check)
972 			warning (sel, "%s may not respond to %c%s", class->name,
973 					 class_msg ? '+' : '-', selector->name);
974 	}
975 	m = find_method (selector->name);
976 	if (m)
977 		return m;
978 	//FIXME right option?
979 	if (options.warnings.interface_check)
980 		warning (sel, "could not find method for %c%s",
981 				 class_msg ? '+' : '-', selector->name);
982 	return 0;
983 }
984 
985 static uintptr_t
category_get_hash(const void * _c,void * unused)986 category_get_hash (const void *_c, void *unused)
987 {
988 	category_t *c = (category_t *) _c;
989 	return Hash_String (c->name) ^ Hash_String (c->class->name);
990 }
991 
992 static int
category_compare(const void * _c1,const void * _c2,void * unused)993 category_compare (const void *_c1, const void *_c2, void *unused)
994 {
995 	category_t *c1 = (category_t *) _c1;
996 	category_t *c2 = (category_t *) _c2;
997 	return strcmp (c1->name, c2->name) == 0
998 		&& strcmp (c1->class->name, c2->class->name) == 0;
999 }
1000 
1001 symtab_t *
class_new_ivars(class_t * class)1002 class_new_ivars (class_t *class)
1003 {
1004 	symtab_t   *ivars;
1005 	symtab_t   *super_ivars = 0;
1006 
1007 	if (class->super_class)
1008 		super_ivars = class->super_class->ivars;
1009 	ivars = new_symtab (super_ivars, stab_local);
1010 	return ivars;
1011 }
1012 
1013 void
class_add_ivars(class_t * class,symtab_t * ivars)1014 class_add_ivars (class_t *class, symtab_t *ivars)
1015 {
1016 	int         base = 0;
1017 	symbol_t   *sym;
1018 
1019 	if (class->super_class)
1020 		base = type_size (class->super_class->type);
1021 	for (sym = ivars->symbols; sym; sym = sym->next)
1022 		sym->s.offset += base;
1023 	class->ivars = ivars;
1024 }
1025 
1026 static int
compare_symbols(symbol_t * s1,symbol_t * s2)1027 compare_symbols (symbol_t *s1, symbol_t *s2)
1028 {
1029 	if (s1->visibility != s2->visibility)
1030 		return 0;
1031 	if (s1->name != s2->name)	// works thanks to save_string
1032 		return 0;
1033 	if (s1->sy_type != s2->sy_type)
1034 		return 0;
1035 	if (s1->type != s2->type)
1036 		return 0;
1037 	return 1;
1038 }
1039 
1040 void
class_check_ivars(class_t * class,symtab_t * ivars)1041 class_check_ivars (class_t *class, symtab_t *ivars)
1042 {
1043 	symbol_t   *civ, *iv;
1044 	int         missmatch = 0;
1045 
1046 	if (!class->ivars != !ivars) {
1047 		missmatch = 1;
1048 	} else if (ivars) {
1049 		for (civ = class->ivars->symbols, iv = ivars->symbols;
1050 			 civ && iv; civ = civ->next, iv = iv->next) {
1051 			if (!compare_symbols (civ, iv)) {
1052 				missmatch = 1;
1053 				break;
1054 			}
1055 		}
1056 	}
1057 	//FIXME right option?
1058 	if (missmatch && options.warnings.interface_check)
1059 		warning (0, "instance variable missmatch for %s", class->name);
1060 	class_add_ivars (class, ivars);
1061 }
1062 
1063 category_t *
get_category(symbol_t * class_name,const char * category_name,int create)1064 get_category (symbol_t *class_name, const char *category_name, int create)
1065 {
1066 	category_t *category;
1067 	class_t    *class;
1068 
1069 	if (!category_hash) {
1070 		category_hash = Hash_NewTable (1021, 0, 0, 0);
1071 		Hash_SetHashCompare (category_hash,
1072 				category_get_hash, category_compare);
1073 	}
1074 	class = get_class (class_name, 0);
1075 	if (!class) {
1076 		error (0, "undefined class %s", class_name->name);
1077 		return 0;
1078 	}
1079 	if (class_name && category_name) {
1080 		category_t  _c = {0, category_name, class};
1081 
1082 		category = Hash_FindElement (category_hash, &_c);
1083 		if (category || !create)
1084 			return category;
1085 	}
1086 
1087 	category = calloc (sizeof (category_t), 1);
1088 	category->next = class->categories;
1089 	class->categories = category;
1090 	category->name = category_name;
1091 	category->class = class;
1092 	category->methods = new_methodlist ();
1093 	category->class_type.type = ct_category;
1094 	category->class_type.c.category = category;
1095 	if (class_name && category_name)
1096 		Hash_AddElement (category_hash, category);
1097 	return category;
1098 }
1099 
1100 void
category_add_methods(category_t * category,methodlist_t * methods)1101 category_add_methods (category_t *category, methodlist_t *methods)
1102 {
1103 	if (!methods)
1104 		return;
1105 	*category->methods->tail = methods->head;
1106 	category->methods->tail = methods->tail;
1107 	free (methods);
1108 
1109 	methods_set_self_type (category->class, category->methods);
1110 }
1111 
1112 void
category_add_protocols(category_t * category,protocollist_t * protocols)1113 category_add_protocols (category_t *category, protocollist_t *protocols)
1114 {
1115 	int         i;
1116 	protocol_t *p;
1117 	methodlist_t *methods;
1118 
1119 	if (!protocols)
1120 		return;
1121 
1122 	methods = category->methods;
1123 
1124 	for (i = 0; i < protocols->count; i++) {
1125 		p = protocols->list[i];
1126 		copy_methods (methods, p->methods);
1127 		if (p->protocols)
1128 			category_add_protocols (category, p->protocols);
1129 	}
1130 	category->protocols = protocols;
1131 }
1132 
1133 symbol_t *
class_pointer_symbol(class_t * class)1134 class_pointer_symbol (class_t *class)
1135 {
1136 	def_t      *def;
1137 	symbol_t   *sym;
1138 	class_type_t class_type = {ct_class, {0}};
1139 
1140 	class_type.c.class = class;
1141 
1142 	sym = make_symbol (va ("_OBJ_CLASS_POINTER_%s", class->name),
1143 					   &type_Class,
1144 					   pr.near_data, sc_static);
1145 	if (!sym->table)
1146 		symtab_addsymbol (pr.symtab, sym);
1147 	def = sym->s.def;
1148 	if (def->initialized)
1149 		return sym;
1150 	def->initialized = def->constant = 1;
1151 	def->nosave = 1;
1152 	if (!class->def)
1153 		class->def = class_symbol (&class_type, 1)->s.def;
1154 	if (!class->def->external)
1155 		D_INT (def) = class->def->offset;
1156 	reloc_def_def (class->def, def);
1157 	return sym;
1158 }
1159 
1160 
1161 typedef struct {
1162 	def_t      *refs;
1163 	class_t   **classes;
1164 	int         cls_def_cnt;
1165 	category_t **categories;
1166 	int         cat_def_cnt;
1167 } obj_symtab_data_t;
1168 
1169 static void
emit_symtab_ref_cnt(def_t * def,void * data,int index)1170 emit_symtab_ref_cnt (def_t *def, void *data, int index)
1171 {
1172 	obj_symtab_data_t *da = (obj_symtab_data_t *)data;
1173 
1174 	if (def->type != &type_integer)
1175 		internal_error (0, "%s: expected integer def", __FUNCTION__);
1176 	D_INT (def) = 0;
1177 	if (da->refs)
1178 		D_INT (def) = da->refs->type->t.array.size;
1179 }
1180 
1181 static void
emit_symtab_refs(def_t * def,void * data,int index)1182 emit_symtab_refs (def_t *def, void *data, int index)
1183 {
1184 	obj_symtab_data_t *da = (obj_symtab_data_t *)data;
1185 
1186 	if (def->type != &type_SEL)
1187 		internal_error (0, "%s: expected SEL def", __FUNCTION__);
1188 	D_INT (def) = 0;
1189 	if (da->refs)
1190 		EMIT_DEF (def->space, D_INT (def), da->refs);
1191 }
1192 
1193 static void
emit_symtab_cls_def_cnt(def_t * def,void * data,int index)1194 emit_symtab_cls_def_cnt (def_t *def, void *data, int index)
1195 {
1196 	obj_symtab_data_t *da = (obj_symtab_data_t *)data;
1197 
1198 	if (def->type != &type_integer)
1199 		internal_error (0, "%s: expected integer def", __FUNCTION__);
1200 	D_INT (def) = da->cls_def_cnt;
1201 }
1202 
1203 static void
emit_symtab_cat_def_cnt(def_t * def,void * data,int index)1204 emit_symtab_cat_def_cnt (def_t *def, void *data, int index)
1205 {
1206 	obj_symtab_data_t *da = (obj_symtab_data_t *)data;
1207 
1208 	if (def->type != &type_integer)
1209 		internal_error (0, "%s: expected integer def", __FUNCTION__);
1210 	D_INT (def) = da->cat_def_cnt;
1211 }
1212 
1213 static void
emit_symtab_defs(def_t * def,void * data,int index)1214 emit_symtab_defs (def_t *def, void *data, int index)
1215 {
1216 	obj_symtab_data_t *da = (obj_symtab_data_t *)data;
1217 
1218 	if (!is_array (def->type) || def->type->t.array.type->type != ev_pointer)
1219 		internal_error (0, "%s: expected array of pointers def", __FUNCTION__);
1220 	if (index < 0 || index >= da->cls_def_cnt + da->cat_def_cnt)
1221 		internal_error (0, "%s: out of bounds index: %d %d",
1222 						__FUNCTION__, index,
1223 						da->cls_def_cnt + da->cat_def_cnt);
1224 
1225 	if (index < da->cls_def_cnt) {
1226 		class_t   **cl;
1227 		for (cl = da->classes; *cl; cl++)
1228 			if ((*cl)->def && !(*cl)->def->external)
1229 				if (!index--)
1230 					break;
1231 		EMIT_DEF (def->space, D_INT (def), (*cl)->def);
1232 	} else {
1233 		category_t **ca;
1234 		index -= da->cls_def_cnt;
1235 		for (ca = da->categories; *ca; ca++)
1236 			if ((*ca)->def && !(*ca)->def->external)
1237 				if (!index--)
1238 					break;
1239 		EMIT_DEF (def->space, D_INT (def), (*ca)->def);
1240 	}
1241 }
1242 
1243 void
class_finish_module(void)1244 class_finish_module (void)
1245 {
1246 	static struct_def_t symtab_struct[] = {
1247 		{"sel_ref_cnt",	&type_integer, emit_symtab_ref_cnt},
1248 		{"refs",		&type_SEL,     emit_symtab_refs},
1249 		{"cls_def_cnt",	&type_integer, emit_symtab_cls_def_cnt},
1250 		{"cat_def_cnt",	&type_integer, emit_symtab_cat_def_cnt},
1251 		{"defs",		0,             emit_symtab_defs},
1252 		{0, 0}
1253 	};
1254 
1255 	obj_symtab_data_t data = {0, 0, 0, 0, 0};
1256 
1257 	class_t   **cl;
1258 	category_t **ca;
1259 	def_t      *symtab_def;
1260 	symbol_t   *module_sym;
1261 	pr_module_t *module;
1262 	symbol_t   *exec_class_sym;
1263 	symbol_t   *init_sym;
1264 	expr_t     *init_expr;
1265 	storage_class_t save_storage;
1266 
1267 	data.refs = emit_selectors ();
1268 	if (class_hash) {
1269 		data.classes = (class_t **) Hash_GetList (class_hash);
1270 		for (cl = data.classes; *cl; cl++)
1271 			if ((*cl)->def && !(*cl)->def->external)
1272 				data.cls_def_cnt++;
1273 	}
1274 	if (category_hash) {
1275 		data.categories = (category_t **) Hash_GetList (category_hash);
1276 		for (ca = data.categories; *ca; ca++)
1277 			if ((*ca)->def && !(*ca)->def->external)
1278 				data.cat_def_cnt++;
1279 	}
1280 	if (!data.refs && !data.cls_def_cnt && !data.cat_def_cnt)
1281 		return;
1282 	symtab_struct[4].type = array_type (&type_pointer,
1283 										data.cls_def_cnt + data.cat_def_cnt);
1284 	symtab_def = emit_structure ("_OBJ_SYMTAB", 's', symtab_struct, 0, &data,
1285 								 sc_static);
1286 	free (data.classes);
1287 	free (data.categories);
1288 
1289 	module_sym = make_symbol ("_OBJ_MODULE", &type_obj_module, pr.far_data,
1290 							  sc_static);
1291 	symtab_addsymbol (current_symtab, module_sym);
1292 	module = &D_STRUCT (pr_module_t, module_sym->s.def);
1293 	module->size = type_size (&type_obj_module);
1294 	EMIT_STRING (module_sym->s.def->space, module->name,
1295 				 GETSTR (pr.source_file));
1296 	EMIT_DEF (module_sym->s.def->space, module->symtab, symtab_def);
1297 
1298 	exec_class_sym = symtab_lookup (pr.symtab, "__obj_exec_class");
1299 	if (!exec_class_sym) {
1300 		exec_class_sym = new_symbol_type ("__obj_exec_class",
1301 										  &type_obj_exec_class);
1302 		exec_class_sym = function_symbol (exec_class_sym, 0, 1);
1303 		make_function (exec_class_sym, 0, exec_class_sym->table->space,
1304 					   sc_extern);
1305 	}
1306 
1307 	init_sym = new_symbol_type (".ctor", &type_function);
1308 	init_sym = function_symbol (init_sym, 0, 1);
1309 
1310 	init_expr = new_block_expr ();
1311 	append_expr (init_expr,
1312 			build_function_call (new_symbol_expr (exec_class_sym),
1313 								 exec_class_sym->type,
1314 								 address_expr (new_symbol_expr (module_sym),
1315 									 		   0, 0)));
1316 
1317 	save_storage = current_storage;
1318 	current_storage = sc_static;
1319 	current_func = begin_function (init_sym, 0, current_symtab, 1);
1320 	build_code_function (init_sym, 0, init_expr);;
1321 	current_func = 0;
1322 	current_storage = save_storage;
1323 }
1324 
1325 protocol_t *
get_protocol(const char * name,int create)1326 get_protocol (const char *name, int create)
1327 {
1328 	protocol_t    *p;
1329 
1330 	if (!protocol_hash)
1331 		protocol_hash = Hash_NewTable (1021, protocol_get_key, 0, 0);
1332 
1333 	if (name) {
1334 		p = Hash_Find (protocol_hash, name);
1335 		if (p || !create)
1336 			return p;
1337 	}
1338 
1339 	p = calloc (sizeof (protocol_t), 1);
1340 	p->name = name;
1341 	p->methods = new_methodlist ();
1342 	p->class_type.type = ct_protocol;
1343 	p->class_type.c.protocol = p;
1344 	if (name)
1345 		Hash_Add (protocol_hash, p);
1346 	return p;
1347 }
1348 
1349 void
protocol_add_methods(protocol_t * protocol,methodlist_t * methods)1350 protocol_add_methods (protocol_t *protocol, methodlist_t *methods)
1351 {
1352 	if (!methods)
1353 		return;
1354 	*protocol->methods->tail = methods->head;
1355 	protocol->methods->tail = methods->tail;
1356 	free (methods);
1357 }
1358 
1359 void
protocol_add_protocols(protocol_t * protocol,protocollist_t * protocols)1360 protocol_add_protocols (protocol_t *protocol, protocollist_t *protocols)
1361 {
1362 	protocol->protocols = protocols;
1363 }
1364 
1365 def_t *
protocol_def(protocol_t * protocol)1366 protocol_def (protocol_t *protocol)
1367 {
1368 	return make_symbol (protocol->name, &type_obj_protocol,
1369 						pr.far_data, sc_static)->s.def;
1370 }
1371 
1372 protocollist_t *
new_protocol_list(void)1373 new_protocol_list (void)
1374 {
1375 	protocollist_t *protocollist = malloc (sizeof (protocollist_t));
1376 
1377 	protocollist->count = 0;
1378 	protocollist->list = 0;
1379 	return protocollist;
1380 }
1381 
1382 protocollist_t *
add_protocol(protocollist_t * protocollist,const char * name)1383 add_protocol (protocollist_t *protocollist, const char *name)
1384 {
1385 	protocol_t *protocol = get_protocol (name, 0);
1386 
1387 	if (!protocol) {
1388 		error (0, "undefined protocol `%s'", name);
1389 		return protocollist;
1390 	}
1391 	protocollist->count++;
1392 	protocollist->list = realloc (protocollist->list,
1393 								  sizeof (protocol_t) * protocollist->count);
1394 	protocollist->list[protocollist->count - 1] = protocol;
1395 	return protocollist;
1396 }
1397 
1398 int
procollist_find_protocol(protocollist_t * protocollist,protocol_t * proto)1399 procollist_find_protocol (protocollist_t *protocollist, protocol_t *proto)
1400 {
1401 	int         i;
1402 	if (!protocollist)
1403 		return 0;
1404 	for (i = 0; i < protocollist->count; i++)
1405 		if (protocollist->list[i] == proto)
1406 			return 1;
1407 	return 0;
1408 }
1409 
1410 int
compare_protocols(protocollist_t * protos1,protocollist_t * protos2)1411 compare_protocols (protocollist_t *protos1, protocollist_t *protos2)
1412 {
1413 	int         i;
1414 
1415 	if (protos1 == protos2)
1416 		return 1;
1417 	if (!protos1 || !protos2)
1418 		return 0;
1419 	if (protos1->count != protos2->count)
1420 		return 0;
1421 	for (i = 0; i < protos1->count; i++)
1422 		if (!procollist_find_protocol (protos2, protos1->list[i]))
1423 			return 0;
1424 	return 1;
1425 }
1426 
1427 void
print_protocollist(dstring_t * dstr,protocollist_t * protocollist)1428 print_protocollist (dstring_t *dstr, protocollist_t *protocollist)
1429 {
1430 	int         i;
1431 	dstring_appendstr (dstr, "<");
1432 	for (i = 0; i < protocollist->count; i++)
1433 		dasprintf (dstr, "%s%s", i ? "," : "", protocollist->list[i]->name);
1434 	dstring_appendstr (dstr, ">");
1435 }
1436 
1437 def_t *
emit_protocol(protocol_t * protocol)1438 emit_protocol (protocol_t *protocol)
1439 {
1440 	def_t      *proto_def;
1441 	pr_protocol_t *proto;
1442 	defspace_t *space;
1443 
1444 	proto_def = make_symbol (va ("_OBJ_PROTOCOL_%s", protocol->name),
1445 							 &type_obj_protocol, pr.far_data, sc_static)->s.def;
1446 	if (proto_def->initialized)
1447 		return proto_def;
1448 	proto_def->initialized = proto_def->constant = 1;
1449 	proto_def->nosave = 1;
1450 	space = proto_def->space;
1451 	proto = &D_STRUCT (pr_protocol_t, proto_def);
1452 	proto->class_pointer = 0;
1453 	EMIT_STRING (space, proto->protocol_name, protocol->name);
1454 	EMIT_DEF (space, proto->protocol_list,
1455 			  emit_protocol_list (protocol->protocols,
1456 								  va ("PROTOCOL_%s", protocol->name)));
1457 	EMIT_DEF (space, proto->instance_methods,
1458 			  emit_method_descriptions (protocol->methods, protocol->name, 1));
1459 	EMIT_DEF (space, proto->class_methods,
1460 			  emit_method_descriptions (protocol->methods, protocol->name, 0));
1461 	emit_class_ref ("Protocol");
1462 	return proto_def;
1463 }
1464 
1465 def_t *
emit_protocol_list(protocollist_t * protocols,const char * name)1466 emit_protocol_list (protocollist_t *protocols, const char *name)
1467 {
1468 	//FIXME use emit_struct
1469 	static struct_def_t proto_list_struct[] = {
1470 		{"next",	&type_pointer},
1471 		{"count",	&type_integer},
1472 		{"list",	0},				// type will be filled in at run time
1473 		{0, 0},
1474 	};
1475 	type_t     *proto_list_type;
1476 	def_t      *proto_list_def;
1477 	defspace_t *space;
1478 	pr_protocol_list_t *proto_list;
1479 	int         i;
1480 
1481 	if (!protocols)
1482 		return 0;
1483 	proto_list_struct[2].type = array_type (&type_pointer, protocols->count);
1484 	proto_list_type = make_structure (0, 's', proto_list_struct, 0)->type;
1485 	proto_list_def = make_symbol (va ("_OBJ_PROTOCOLS_%s", name),
1486 								  proto_list_type,
1487 								  pr.far_data, sc_static)->s.def;
1488 	proto_list_def->initialized = proto_list_def->constant = 1;
1489 	proto_list_def->nosave = 1;
1490 	space = proto_list_def->space;
1491 	proto_list = &D_STRUCT (pr_protocol_list_t, proto_list_def);
1492 	proto_list->next = 0;
1493 	proto_list->count = protocols->count;
1494 	for (i = 0; i < protocols->count; i++)
1495 		EMIT_DEF (space, proto_list->list[i],
1496 				  emit_protocol (protocols->list[i]));
1497 	return proto_list_def;
1498 }
1499 
1500 void
clear_classes(void)1501 clear_classes (void)
1502 {
1503 	if (class_hash)
1504 		Hash_FlushTable (class_hash);
1505 	if (protocol_hash)
1506 		Hash_FlushTable (protocol_hash);
1507 	if (category_hash)
1508 		Hash_FlushTable (category_hash);
1509 	obj_initialized = 0;
1510 }
1511 
1512 symtab_t *
class_to_struct(class_t * class,symtab_t * symtab)1513 class_to_struct (class_t *class, symtab_t *symtab)
1514 {
1515 	symtab_t   *parent = symtab->parent;
1516 	symtab_t   *ivars = class->ivars;
1517 	symtab_t   *ancestor;
1518 
1519 	if (!ivars)
1520 		return symtab;
1521 
1522 	// disconnect the struct symbol table from the scope
1523 	symtab->parent = 0;
1524 	// find the ancestor of the ivars symbol table chain
1525 	for (ancestor = ivars; ancestor->parent; ancestor = ancestor->parent)
1526 		;
1527 	// connect the ivars symbol table chain to the struct symbol table
1528 	ancestor->parent = symtab;
1529 	// create a new struct symbol table from the ivars symbol table chain
1530 	symtab = symtab_flat_copy (ivars, 0);
1531 	// disconnect the ivars symbol table chain
1532 	ancestor->parent = 0;
1533 	// connect the new struct symbol table to the scope
1534 	symtab->parent = parent;
1535 	return symtab;
1536 }
1537 
1538 symtab_t *
class_ivar_scope(class_type_t * class_type,symtab_t * parent)1539 class_ivar_scope (class_type_t *class_type, symtab_t *parent)
1540 {
1541 	class_t    *class = extract_class (class_type);
1542 	if (!class->ivars)
1543 		return 0;
1544 	return symtab_flat_copy (class->ivars, parent);
1545 }
1546 
1547 void
class_finish_ivar_scope(class_type_t * class_type,symtab_t * ivar_scope,symtab_t * param_scope)1548 class_finish_ivar_scope (class_type_t *class_type, symtab_t *ivar_scope,
1549 						 symtab_t *param_scope)
1550 {
1551 	class_t    *class = extract_class (class_type);
1552 	type_t     *class_ptr = pointer_type (class->type);
1553 	symbol_t   *sym;
1554 	symbol_t   *self;
1555 	expr_t     *self_expr;
1556 
1557 	if (!ivar_scope)
1558 		return;
1559 	self = symtab_lookup (param_scope, "self");
1560 	if (!self)
1561 		internal_error (0, "I've lost my self!");
1562 	self_expr = new_symbol_expr (self);
1563 	if (self->type != class_ptr) {
1564 		debug (0, "class method scope");
1565 		//FIXME should generate a warning on access
1566 		self_expr = cast_expr (class_ptr, self_expr);
1567 	}
1568 	for (sym = ivar_scope->symbols; sym; sym = sym->next) {
1569 		if (sym->sy_type != sy_var)
1570 			continue;
1571 		sym->sy_type = sy_expr;
1572 		sym->s.expr = binary_expr ('.', copy_expr (self_expr),
1573 								   new_symbol_expr (new_symbol (sym->name)));
1574 	}
1575 }
1576 
1577 static void
init_objective_structs(void)1578 init_objective_structs (void)
1579 {
1580 	make_structure ("obj_selector", 's', sel_struct, &type_obj_selector);
1581 	chain_type (&type_obj_selector);
1582 	chain_type (&type_SEL);
1583 	chain_type (&type_IMP);
1584 
1585 	make_structure ("obj_method", 's', method_struct, &type_obj_method);
1586 	chain_type (&type_obj_method);
1587 
1588 	make_structure ("obj_method_description", 's', method_desc_struct,
1589 					&type_obj_method_description);
1590 	chain_type (&type_obj_method_description);
1591 
1592 	make_structure ("obj_category", 's', category_struct, &type_obj_category);
1593 	chain_type (&type_obj_category);
1594 
1595 	make_structure ("obj_ivar", 's', ivar_struct, &type_obj_ivar);
1596 	chain_type (&type_obj_ivar);
1597 
1598 	make_structure ("obj_super", 's', super_struct, &type_obj_super);
1599 	chain_type (&type_obj_super);
1600 	chain_type (&type_SuperPtr);
1601 	chain_type (&type_supermsg);
1602 
1603 	symtab_addsymbol (current_symtab, new_symbol ("id"));
1604 }
1605 
1606 static void
init_classes(void)1607 init_classes (void)
1608 {
1609 	make_structure ("obj_class", 's', class_struct, &type_obj_class);
1610 	chain_type (&type_obj_class);
1611 	chain_type (&type_Class);
1612 	make_structure ("obj_object", 's', object_struct, &type_obj_object);
1613 	chain_type (&type_obj_object);
1614 	chain_type (&type_id);
1615 	make_structure ("obj_protocol", 's', protocol_struct, &type_obj_protocol);
1616 	chain_type (&type_obj_protocol);
1617 }
1618 
1619 static void
class_init_obj_module(void)1620 class_init_obj_module (void)
1621 {
1622 	make_structure ("obj_module", 's', module_struct, &type_obj_module);
1623 
1624 	chain_type (&type_obj_module);
1625 	chain_type (&type_moduleptr);
1626 	chain_type (&type_obj_exec_class);
1627 }
1628 
1629 void
class_init(void)1630 class_init (void)
1631 {
1632 	symtab_t   *cs = current_symtab;
1633 
1634 	current_symtab = pr.symtab;
1635 	class_init_obj_module ();
1636 	init_classes ();
1637 	init_objective_structs ();
1638 	obj_initialized = 1;
1639 
1640 	current_symtab = cs;
1641 }
1642