From b35561504c14e4a562c42dfc5f039090f8a56d87 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 10 Nov 2004 05:37:00 +0000 Subject: [PATCH] do proper selector registration. unfortunatly, I discovered I'd created pr_method_t incorrectly and so had to bump the progs version again This is an imperfect revision of history. --- include/QF/pr_comp.h | 2 +- include/QF/pr_obj.h | 2 +- include/QF/progs.h | 12 +- libs/ruamoko/rua_obj.c | 380 ++++++++++++++++++++++++++---------- tools/qfcc/include/method.h | 6 +- tools/qfcc/include/type.h | 4 +- tools/qfcc/source/expr.c | 6 +- tools/qfcc/source/method.c | 60 +++++- tools/qfcc/source/type.c | 41 +++- 9 files changed, 378 insertions(+), 135 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index 5f987613c..fee066010 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -370,7 +370,7 @@ typedef struct pr_va_list_s { } pr_va_list_t; #define PROG_ID_VERSION 6 -#define PROG_VERSION 0x00fff004 // MMmmmRRR 0.fff.004 (hex) +#define PROG_VERSION 0x00fff005 // MMmmmRRR 0.fff.005 (hex) typedef struct dprograms_s { unsigned int version; diff --git a/include/QF/pr_obj.h b/include/QF/pr_obj.h index e6b431057..9e28de4fa 100644 --- a/include/QF/pr_obj.h +++ b/include/QF/pr_obj.h @@ -128,7 +128,7 @@ typedef struct pr_method_list_s { pointer_t method_next; int method_count; struct pr_method_s { - pr_sel_t method_name; + pointer_t method_name; // pr_sel_t string_t method_types; func_t method_imp; // typedef id (id, SEL, ...) IMP } method_list[1]; diff --git a/include/QF/progs.h b/include/QF/progs.h index 10c8cb3d9..66cd85858 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -1220,13 +1220,17 @@ struct progs_s { pr_resource_t *resources; struct hashtab_s *resource_hash; - // obj info - struct hashtab_s *selectors; + /// obj info + //@{ + int selector_index; + int selector_index_max; + void *selector_sels; + string_t *selector_names; + struct hashtab_s *selector_hash; struct hashtab_s *classes; struct hashtab_s *categories; struct hashtab_s *protocols; - - // debug info + //@} /// debug info //@{ diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 9f9df6ae9..c87056d59 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -59,9 +59,10 @@ static void } static const char * -selector_get_key (void *s, void *pr) +selector_get_key (void *s, void *_pr) { - return PR_GetString ((progs_t *)pr, ((pr_sel_t *)s)->sel_id); + progs_t *pr = (progs_t *) _pr; + return PR_GetString (pr, pr->selector_names[(int) s]); } static const char * @@ -94,22 +95,12 @@ category_compare (void *_c1, void *_c2, void *_pr) return strcmp (cat1, cat2) == 0 && strcmp (cls1, cls2) == 0; } - -static void -dump_ivars (progs_t *pr, pointer_t _ivars) +static inline int +sel_eq (pr_sel_t *s1, pr_sel_t *s2) { - pr_ivar_list_t *ivars; - int i; - - if (!_ivars) - return; - ivars = &G_STRUCT (pr, pr_ivar_list_t, _ivars); - for (i = 0; i < ivars->ivar_count; i++) { - Sys_Printf (" %s %s %d\n", - PR_GetString (pr, ivars->ivar_list[i].ivar_name), - PR_GetString (pr, ivars->ivar_list[i].ivar_type), - ivars->ivar_list[i].ivar_offset); - } + if (!s1 || !s2) + return s1 == s2; + return s1->sel_id == s2->sel_id; } static int @@ -171,99 +162,270 @@ finish_class (progs_t *pr, pr_class_t *class, pointer_t object_ptr) class->super_class); } -static void -finish_category (progs_t *pr, pr_category_t *category) -{ - const char *class_name = PR_GetString (pr, category->class_name); - const char *category_name = PR_GetString (pr, category->category_name); - pr_class_t *class = Hash_Find (pr->classes, class_name); - pr_method_list_t *method_list; +//==================================================================== + +static int +add_sel_name (progs_t *pr, const char *name) +{ + int ind = ++pr->selector_index; + int size, i; + + if (pr->selector_index > pr->selector_index_max) { + size = pr->selector_index_max + 128; + pr->selector_sels = realloc (pr->selector_sels, + size * sizeof (obj_list *)); + pr->selector_names = realloc (pr->selector_names, + size * sizeof (string_t)); + for (i = pr->selector_index_max; i < size; i++) { + ((obj_list **) pr->selector_sels)[i] = 0; + pr->selector_names[i] = 0; + } + pr->selector_index_max = size; + } + pr->selector_names[ind] = PR_SetString (pr, name); + return ind; +} + +static pr_sel_t * +sel_register_typed_name (progs_t *pr, const char *name, const char *types, + pr_sel_t *sel) +{ + int index; + int is_new = 0; + obj_list *l; + + index = (int) Hash_Find (pr->selector_hash, name); + if (index) { + for (l = ((obj_list **) pr->selector_sels)[index]; l; l = l->next) { + pr_sel_t *s = l->data; + if (!types || !s->sel_types) { + if (!s->sel_types && !types) { + if (sel) { + sel->sel_id = index; + return sel; + } + return s; + } + } else if (strcmp (PR_GetString (pr, s->sel_types), types) == 0) { + if (sel) { + sel->sel_id = index; + return sel; + } + return s; + } + } + } else { + index = add_sel_name (pr, name); + is_new = 1; + } + if (!sel) + sel = PR_Zone_Malloc (pr, sizeof (pr_sel_t)); + + sel->sel_id = index; + sel->sel_types = PR_SetString (pr, types); + + l = obj_list_new (); + l->data = sel; + l->next = ((obj_list **) pr->selector_sels)[index]; + ((obj_list **) pr->selector_sels)[index] = l; + + if (is_new) + Hash_Add (pr->selector_hash, (void *)index); + + return sel; +} + +static pr_sel_t * +sel_register_name (progs_t *pr, const char *name) +{ + return sel_register_typed_name (pr, name, 0, 0); +} + +static void +register_selectors_from_list (progs_t *pr, pr_method_list_t *method_list) +{ + int i; + + for (i = 0; i < method_list->method_count; i++) { + pr_method_t *method = &method_list->method_list[i]; + const char *name = PR_GetString (pr, method->method_name); + const char *types = PR_GetString (pr, method->method_types); + pr_sel_t *sel = sel_register_typed_name (pr, name, types, 0); + method->method_name = PR_SetPointer (pr, sel); + } +} + +static void +obj_register_selectors_from_class (progs_t *pr, pr_class_t *class) +{ + pr_method_list_t *method_list = &G_STRUCT (pr, pr_method_list_t, + class->methods); + while (method_list) { + register_selectors_from_list (pr, method_list); + method_list = &G_STRUCT (pr, pr_method_list_t, + method_list->method_next); + } +} + +static void +obj_init_protocols (progs_t *pr, pr_protocol_list_t *protos) +{ + pr_class_t *proto_class; + pr_protocol_t *proto; + int i; + + if (!protos) + return; + + if (!(proto_class = Hash_Find (pr->classes, "Protocol"))) { + pr->unclaimed_proto_list = list_cons (protos, + pr->unclaimed_proto_list); + return; + } + + for (i = 0; i < protos->count; i++) { + proto = &G_STRUCT (pr, pr_protocol_t, protos->list[i]); + if (!proto->class_pointer) { + proto->class_pointer = PR_SetPointer (pr, proto_class); + obj_init_protocols (pr, &G_STRUCT (pr, pr_protocol_list_t, + proto->protocol_list)); + } else { + PR_RunError (pr, "protocol broken"); + } + } +} + +static void +class_add_method_list (progs_t *pr, pr_class_t *class, pr_method_list_t *list) +{ + int i; + + for (i = 0; i < list->method_count; i++) { + pr_method_t *method = &list->method_list[i]; + if (method->method_name) { + const char *name = PR_GetString (pr, method->method_name); + const char *types = PR_GetString (pr, method->method_types); + pr_sel_t *sel = sel_register_typed_name (pr, name, types, 0); + method->method_name = PR_SetPointer (pr, sel); + } + } + + list->method_next = class->methods; + class->methods = PR_SetPointer (pr, list); +} + +static void +obj_class_add_protocols (progs_t *pr, pr_class_t *class, + pr_protocol_list_t *protos) +{ + if (!protos) + return; + + protos->next = class->protocols; + class->protocols = protos->next; +} + +static void +finish_category (progs_t *pr, pr_category_t *category, pr_class_t *class) +{ + pr_method_list_t *method_list; + pr_protocol_list_t *protocol_list; - if (!class) - PR_Error (pr, "broken category %s (%s): class %s not found", - class_name, category_name, class_name); if (category->instance_methods) { method_list = &G_STRUCT (pr, pr_method_list_t, category->instance_methods); - method_list->method_next = class->methods; - class->methods = category->instance_methods; + class_add_method_list (pr, class, method_list); } if (category->class_methods) { pr_class_t *meta = &G_STRUCT (pr, pr_class_t, class->class_pointer); method_list = &G_STRUCT (pr, pr_method_list_t, category->class_methods); - method_list->method_next = meta->methods; - meta->methods = category->class_methods; + class_add_method_list (pr, meta, method_list); + } + if (category->protocols) { + protocol_list = &G_STRUCT (pr, pr_protocol_list_t, + category->protocols); + obj_init_protocols (pr, protocol_list); + obj_class_add_protocols (pr, class, protocol_list); } } static void -rua___obj_exec_class (progs_t *pr) +obj_send_message_in_list (progs_t *pr, pr_method_list_t *method_list, + pr_class_t *class, pr_sel_t *op) { - pr_module_t *module = &P_STRUCT (pr, pr_module_t, 0); - pr_symtab_t *symtab; - pr_sel_t *sel; - pointer_t *ptr; int i; - //int d = developer->int_val; - if (!module) + if (!method_list) return; - //developer->int_val = 1; - symtab = &G_STRUCT (pr, pr_symtab_t, module->symtab); - if (!symtab) - return; - Sys_DPrintf ("Initializing %s module\n" - "symtab @ %d : %d selector%s, %d class%s and %d categor%s\n", - PR_GetString (pr, module->name), module->symtab, - symtab->sel_ref_cnt, symtab->sel_ref_cnt == 1 ? "" : "s", - symtab->cls_def_cnt, symtab->cls_def_cnt == 1 ? "" : "es", - symtab->cat_def_cnt, symtab->cat_def_cnt == 1 ? "y" : "ies"); - sel = &G_STRUCT (pr, pr_sel_t, symtab->refs); - for (i = 0; i < symtab->sel_ref_cnt; i++) { - Sys_DPrintf (" %s\n", PR_GetString (pr, sel->sel_id)); - Hash_Add (pr->selectors, sel); - sel++; - } - ptr = symtab->defs; - for (i = 0; i < symtab->cls_def_cnt; i++) { - pr_class_t *class = &G_STRUCT (pr, pr_class_t, *ptr); - pr_class_t *meta = &G_STRUCT (pr, pr_class_t, class->class_pointer); - Sys_DPrintf ("Class %s @ %d\n", PR_GetString (pr, class->name), *ptr); - Sys_DPrintf (" class pointer: %d\n", class->class_pointer); - Sys_DPrintf (" super class: %s\n", - PR_GetString (pr, class->super_class)); - Sys_DPrintf (" instance variables: %d @ %d\n", class->instance_size, - class->ivars); - if (developer->int_val) - dump_ivars (pr, class->ivars); - Sys_DPrintf (" instance methods: %d\n", class->methods); - Sys_DPrintf (" protocols: %d\n", class->protocols); - Sys_DPrintf (" class methods: %d\n", meta->methods); - Sys_DPrintf (" instance variables: %d @ %d\n", meta->instance_size, - meta->ivars); - if (developer->int_val) - dump_ivars (pr, meta->ivars); + obj_send_message_in_list (pr, &G_STRUCT (pr, pr_method_list_t, + method_list->method_next), + class, op); - Hash_Add (pr->classes, class); - ptr++; + for (i = 0; i < method_list->method_count; i++) { + pr_method_t *mth = &method_list->method_list[i]; + if (mth->method_name && sel_eq (&G_STRUCT (pr, pr_sel_t, + mth->method_name), op) + && !Hash_FindElement (pr->load_methods, (void *)mth->method_imp)) { + Hash_AddElement (pr->load_methods, (void *)mth->method_imp); + + PR_ExecuteProgram (pr, mth->method_imp); + break; + } } - for (i = 0; i < symtab->cat_def_cnt; i++) { - pr_category_t *category = &G_STRUCT (pr, pr_category_t, *ptr); - Sys_DPrintf ("Category %s (%s) @ %d\n", - PR_GetString (pr, category->class_name), - PR_GetString (pr, category->category_name), *ptr); - Sys_DPrintf (" instance methods: %d\n", category->instance_methods); - Sys_DPrintf (" class methods: %d\n", category->class_methods); - Sys_DPrintf (" protocols: %d\n", category->protocols); - Hash_AddElement (pr->categories, category); - ptr++; - } - //developer->int_val = d; } -//==================================================================== +static void +send_load (progs_t *pr, class_tree *tree, int level) +{ + pr_sel_t *load_sel = sel_register_name (pr, "load"); + pr_class_t *class = tree->class; + pr_class_t *meta = &G_STRUCT (pr, pr_class_t, class->class_pointer); + pr_method_list_t *method_list = &G_STRUCT (pr, pr_method_list_t, + meta->methods); + + obj_send_message_in_list (pr, method_list, class, load_sel); +} + +static void +obj_send_load (progs_t *pr) +{ + obj_list *m; + + if (pr->unresolved_classes) { + pr_class_t *class = ((obj_list *) pr->unresolved_classes)->data; + const char *super_class = PR_GetString (pr, class->super_class); + while (Hash_Find (pr->classes, super_class)) { + list_remove ((obj_list **) &pr->unresolved_classes); + if (pr->unresolved_classes) { + class = ((obj_list *) pr->unresolved_classes)->data; + super_class = PR_GetString (pr, class->super_class); + } else { + break; + } + } + if (pr->unresolved_classes) + return; + } + + //XXX constant string stuff here (see init.c in libobjc source) + + for (m = pr->module_list; m; m = m->next) + obj_create_classes_tree (pr, m->data); + while (pr->class_tree_list) { + obj_preorder_traverse (pr, ((obj_list *) pr->class_tree_list)->data, + 0, send_load); + obj_postorder_traverse (pr, ((obj_list *) pr->class_tree_list)->data, + 0, obj_destroy_class_tree_node); + list_remove ((obj_list **) &pr->class_tree_list); + } + //XXX callback + //for (m = pr->module_list; m; m = m->next) + // obj_create_classes_tree (pr, m->data); + obj_list_free (pr->module_list); + pr->module_list = 0; +} static pr_method_t * obj_find_message (progs_t *pr, pr_class_t *class, pr_sel_t *selector) @@ -271,6 +433,7 @@ obj_find_message (progs_t *pr, pr_class_t *class, pr_sel_t *selector) pr_class_t *c = class; pr_method_list_t *method_list; pr_method_t *method; + pr_sel_t *sel; int i; while (c) { @@ -278,7 +441,8 @@ obj_find_message (progs_t *pr, pr_class_t *class, pr_sel_t *selector) while (method_list) { for (i = 0, method = method_list->method_list; i < method_list->method_count; i++, method++) { - if (method->method_name.sel_id == selector->sel_id) + sel = &G_STRUCT (pr, pr_sel_t, method->method_name); + if (sel->sel_id == selector->sel_id) return method; } method_list = &G_STRUCT (pr, pr_method_list_t, @@ -579,13 +743,18 @@ static void rua_sel_get_name (progs_t *pr) { pr_sel_t *sel = &P_STRUCT (pr, pr_sel_t, 0); - R_INT (pr) = sel->sel_id; + + if (sel->sel_id > 0 && sel->sel_id <= pr->selector_index) + R_STRING (pr) = pr->selector_names[sel->sel_id]; + else + R_STRING (pr) = 0; } static void rua_sel_get_type (progs_t *pr) { pr_sel_t *sel = &P_STRUCT (pr, pr_sel_t, 0); + R_INT (pr) = sel->sel_types; } @@ -593,24 +762,24 @@ static void rua_sel_get_uid (progs_t *pr) { const char *name = P_GSTRING (pr, 0); - pr_sel_t *sel = Hash_Find (pr->selectors, name); - RETURN_POINTER (pr, sel); + + RETURN_POINTER (pr, sel_register_typed_name (pr, name, 0, 0)); } static void rua_sel_register_name (progs_t *pr) { - //const char *name = P_GSTRING (pr, 0); - //XXX - PR_RunError (pr, "%s, not implemented", __FUNCTION__); + const char *name = P_GSTRING (pr, 0); + + RETURN_POINTER (pr, sel_register_typed_name (pr, name, 0, 0)); } static void rua_sel_is_mapped (progs_t *pr) { - //pr_sel_t *sel = &P_STRUCT (pr, pr_sel_t, 0); - //XXX - PR_RunError (pr, "%s, not implemented", __FUNCTION__); + // FIXME might correspond to a string + pr_sel_t *sel = &P_STRUCT (pr, pr_sel_t, 0); + R_INT (pr) = sel->sel_id > 0 && sel->sel_id <= pr->selector_index; } //==================================================================== @@ -1049,10 +1218,19 @@ rua_init_finish (progs_t *pr) static int rua_init_runtime (progs_t *pr) { - if (!pr->selectors) - pr->selectors = Hash_NewTable (1021, selector_get_key, 0, pr); + ddef_t *def; + int i; + + if (!pr->selector_hash) + pr->selector_hash = Hash_NewTable (1021, selector_get_key, 0, pr); else - Hash_FlushTable (pr->selectors); + Hash_FlushTable (pr->selector_hash); + pr->selector_index = 0; + for (i = 0; i < pr->selector_index_max; i++) { + obj_list_free (((obj_list **) pr->selector_sels)[i]); + ((obj_list **) pr->selector_sels)[i] = 0; + pr->selector_names[i] = 0; + } if (!pr->classes) pr->classes = Hash_NewTable (1021, class_get_key, 0, pr); diff --git a/tools/qfcc/include/method.h b/tools/qfcc/include/method.h index 82037b37a..3079b390f 100644 --- a/tools/qfcc/include/method.h +++ b/tools/qfcc/include/method.h @@ -88,13 +88,15 @@ struct expr_s *send_message (int super); method_t *find_method (const char *sel_name); void selector_name (struct dstring_s *sel_id, keywordarg_t *selector); -void selector_types (struct dstring_s *sel_types, keywordarg_t *selector); -int selector_index (const char *sel_id, const char *sel_types); +void method_types (struct dstring_s *sel_types, method_t *method); +int selector_index (const char *sel_id); selector_t *get_selector (struct expr_s *sel); struct def_s *emit_selectors(void); struct def_s *emit_methods (methodlist_t *methods, const char *name, int instance); +struct def_s *emit_method_descriptions (methodlist_t *_methods, + const char *name, int instance); void clear_selectors (void); diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index 8562da3fe..d0f356ae2 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -76,6 +76,7 @@ extern type_t type_IMP; extern type_t type_supermsg; extern type_t type_obj_exec_class; extern type_t type_Method; +extern type_t type_method_description; extern type_t *type_category; extern type_t *type_ivar; extern type_t *type_module; @@ -97,7 +98,8 @@ type_t *field_type (type_t *aux); type_t *pointer_type (type_t *aux); type_t *array_type (type_t *aux, int size); void print_type (type_t *type); -void encode_type (struct dstring_s *encodking, type_t *type); +const char *encode_params (type_t *type); +void encode_type (struct dstring_s *encoding, type_t *type); type_t *parse_type (const char *str); int type_assignable (type_t *dst, type_t *src); int type_size (type_t *type); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index c4f9ebda4..8d371e485 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -2564,7 +2564,6 @@ expr_t * selector_expr (keywordarg_t *selector) { dstring_t *sel_id = dstring_newstr (); - dstring_t *sel_types = dstring_newstr (); expr_t *sel; def_t *sel_def; int index; @@ -2572,15 +2571,12 @@ selector_expr (keywordarg_t *selector) selector = copy_keywordargs (selector); selector = (keywordarg_t *) reverse_params ((param_t *) selector); selector_name (sel_id, selector); - selector_types (sel_types, selector); - //printf ("'%s' '%s'\n", sel_id->str, sel_types->str); - index = selector_index (sel_id->str, sel_types->str); + index = selector_index (sel_id->str); index *= type_size (type_SEL.aux_type); sel_def = get_def (type_SEL.aux_type, "_OBJ_SELECTOR_TABLE", pr.scope, st_extern); sel = new_def_expr (sel_def); dstring_delete (sel_id); - dstring_delete (sel_types); return address_expr (sel, new_short_expr (index), 0); } diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index ce4c98b0c..af40694a1 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -100,7 +100,7 @@ new_method (type_t *ret_type, param_t *selector, param_t *opt_parms) meth->type = parse_params (ret_type, meth->params); selector_name (name, (keywordarg_t *)selector); - selector_types (types, (keywordarg_t *)selector); + method_types (types, meth); meth->name = name->str; meth->types = types->str; free (name); @@ -126,7 +126,7 @@ copy_method (method_t *method) meth->instance = method->instance; meth->selector = self->next->next; meth->params = self; - meth->type = parse_params (method->type->aux_type, meth->params); + meth->type = method->type; meth->name = method->name; meth->types = method->types; return meth; @@ -276,9 +276,10 @@ selector_name (dstring_t *sel_id, keywordarg_t *selector) } void -selector_types (dstring_t *sel_types, keywordarg_t *selector) +method_types (dstring_t *sel_types, method_t *method) { dstring_clearstr (sel_types); + encode_type (sel_types, method->type); } static hashtab_t *sel_hash; @@ -291,7 +292,7 @@ sel_get_hash (void *_sel, void *unused) selector_t *sel = (selector_t *) _sel; unsigned long hash; - hash = Hash_String (sel->name) ^ Hash_String (sel->types); + hash = Hash_String (sel->name); return hash; } @@ -303,8 +304,6 @@ sel_compare (void *_s1, void *_s2, void *unused) int cmp; cmp = strcmp (s1->name, s2->name) == 0; - if (cmp) - cmp = strcmp (s1->types, s2->types) == 0; return cmp; } @@ -324,9 +323,9 @@ sel_index_compare (void *_s1, void *_s2, void *unused) } int -selector_index (const char *sel_id, const char *sel_types) +selector_index (const char *sel_id) { - selector_t _sel = {save_string (sel_id), save_string (sel_types), 0}; + selector_t _sel = {save_string (sel_id), 0, 0}; selector_t *sel = &_sel; if (!sel_hash) { @@ -422,8 +421,7 @@ emit_methods (methodlist_t *_methods, const char *name, int instance) for (i = 0, method = _methods->head; method; method = method->next) { if (!method->instance != !instance || !method->def) continue; - EMIT_STRING (methods->method_list[i].method_name.sel_id, method->name); - EMIT_STRING (methods->method_list[i].method_name.sel_types, method->types); + EMIT_STRING (methods->method_list[i].method_name, method->name); EMIT_STRING (methods->method_list[i].method_types, method->types); methods->method_list[i].method_imp = G_FUNCTION (method->def->ofs); if (method->func) { @@ -435,6 +433,48 @@ emit_methods (methodlist_t *_methods, const char *name, int instance) return methods_def; } +def_t * +emit_method_descriptions (methodlist_t *_methods, const char *name, + int instance) +{ + const char *type = instance ? "PROTOCOL_INSTANCE" : "PROTOCOL_CLASS"; + method_t *method; + int i, count; + def_t *methods_def; + pr_method_description_list_t *methods; + struct_t *method_list; + + if (!_methods) + return 0; + + for (count = 0, method = _methods->head; method; method = method->next) + if (!method->instance == !instance) + count++; + if (!count) + return 0; + method_list = get_struct (0, 1); + init_struct (method_list, new_type (), str_struct, 0); + new_struct_field (method_list, &type_integer, "count", vis_public); + for (i = 0; i < count; i++) + new_struct_field (method_list, &type_method_description, 0, + vis_public); + methods_def = get_def (method_list->type, + va ("_OBJ_%s_METHODS_%s", type, name), + pr.scope, st_static); + methods_def->initialized = methods_def->constant = 1; + methods_def->nosave = 1; + methods = &G_STRUCT (pr_method_description_list_t, methods_def->ofs); + methods->count = count; + for (i = 0, method = _methods->head; method; method = method->next) { + if (!method->instance != !instance || !method->def) + continue; + EMIT_STRING (methods->list[i].name, method->name); + EMIT_STRING (methods->list[i].types, method->types); + i++; + } + return methods_def; +} + void clear_selectors (void) { diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index 6c290dda6..a9887f803 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -85,6 +85,7 @@ type_t type_supermsg = { ev_func, ".supermsg", NULL, &type_id, -3, type_t type_obj_exec_class = { ev_func, "function", NULL, &type_void, 1, { 0 }}; type_t type_Method = { ev_pointer, "Method" }; type_t type_Super = { ev_pointer, "Super" }; +type_t type_method_description = { ev_struct, "obj_method_description" }; type_t *type_category; type_t *type_ivar; type_t *type_module; @@ -280,13 +281,35 @@ print_type (type_t *type) } } +const char * +encode_params (type_t *type) +{ + const char *ret; + dstring_t *encoding = dstring_newstr (); + int i, count; + + if (type->num_parms < 0) + count = -type->num_parms - 1; + else + count = type->num_parms; + for (i = 0; i < count; i++) + encode_type (encoding, type->parm_types[i]); + if (type->num_parms < 0) + dstring_appendstr (encoding, "."); + + ret = save_string (encoding->str); + dstring_delete (encoding); + return ret; +} + static void _encode_type (dstring_t *encoding, type_t *type, int level) { struct_field_t *field; - int i, count; struct_t *strct; + if (!type) + return; switch (type->type) { case ev_void: dstring_appendstr (encoding, "v"); @@ -310,14 +333,7 @@ _encode_type (dstring_t *encoding, type_t *type, int level) case ev_func: dstring_appendstr (encoding, "("); _encode_type (encoding, type->aux_type, level + 1); - if (type->num_parms < 0) - count = -type->num_parms - 1; - else - count = type->num_parms; - for (i = 0; i < count; i++) - _encode_type (encoding, type->parm_types[i], level + 1); - if (type->num_parms < 0) - dstring_appendstr (encoding, "."); + dstring_appendstr (encoding, encode_params (type)); dstring_appendstr (encoding, ")"); break; case ev_pointer: @@ -669,7 +685,7 @@ init_types (void) strct = get_struct (0, 1); init_struct (strct, new_type (), str_struct, 0); - new_struct_field (strct, type_SEL.aux_type, "method_name", vis_public); + new_struct_field (strct, &type_SEL, "method_name", vis_public); new_struct_field (strct, &type_string, "method_types", vis_public); new_struct_field (strct, &type_IMP, "method_imp", vis_public); type_Method.aux_type = strct->type; @@ -714,6 +730,11 @@ init_types (void) type_id.aux_type = strct->type; class_id.ivars = strct; + strct = get_struct (0, 1); + init_struct (strct, &type_method_description, str_struct, 0); + new_struct_field (strct, &type_string, "name", vis_public); + new_struct_field (strct, &type_string, "types", vis_public); + strct = get_struct (0, 1); init_struct (strct, new_type (), str_struct, 0); new_struct_field (strct, &type_string, "category_name", vis_public);