mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-21 18:01:15 +00:00
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.
This commit is contained in:
parent
6ad13faf98
commit
b35561504c
9 changed files with 378 additions and 135 deletions
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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
|
||||
//@{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue