From 308fa78fc6608456219aa14dc4940102a092d2b9 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 15 May 2002 19:10:23 +0000 Subject: [PATCH] lots of obj work --- tools/qfcc/include/class.h | 30 +++++-- tools/qfcc/include/method.h | 3 +- tools/qfcc/include/struct.h | 1 + tools/qfcc/source/class.c | 91 ++++++++++++++++++-- tools/qfcc/source/method.c | 6 +- tools/qfcc/source/qc-parse.y | 162 ++++++++++++++++++++++------------- tools/qfcc/source/struct.c | 19 +++- 7 files changed, 236 insertions(+), 76 deletions(-) diff --git a/tools/qfcc/include/class.h b/tools/qfcc/include/class.h index 4bc62cdab..c61a0dc96 100644 --- a/tools/qfcc/include/class.h +++ b/tools/qfcc/include/class.h @@ -34,25 +34,41 @@ typedef struct class_s { int defined; - const char *name; - struct class_s *base; - struct methodlist_s *methods; + const char *class_name; + const char *category_name; + struct class_s *super_class; struct type_s *ivars; + struct methodlist_s *methods; + struct protocollist_s *protocols; } class_t; +struct protocol_s; +struct type_s; + +class_t *get_class (const char *name, int create); +void class_add_methods (class_t *class, struct methodlist_s *methods); +void class_add_protocol_methods (class_t *class, expr_t *protocols); +void class_add_protocol (class_t *class, struct protocol_s *protocol); +void class_check_ivars (class_t *class, struct type_s *ivars); +struct def_s *class_def (class_t *class); +class_t *get_category (const char *class_name, const char *category_name, + int create); + typedef struct protocol_s { const char *name; struct methodlist_s *methods; } protocol_t; -class_t *get_class (const char *name, int create); -void class_add_methods (class_t *class, struct methodlist_s *methods); -void class_add_protocol_methods (class_t *class, expr_t *protocols); -struct def_s *class_def (class_t *class); +typedef struct protocollist_s { + int count; + protocol_t **list; +} protocollist_t; protocol_t *get_protocol (const char *name, int create); void protocol_add_methods (protocol_t *protocol, struct methodlist_s *methods); void protocol_add_protocol_methods (protocol_t *protocol, expr_t *protocols); struct def_s *protocol_def (protocol_t *protocol); +protocollist_t *new_protocollist (void); +void add_protocol (protocollist_t *protocollist, protocol_t *protocol); #endif//__class_h diff --git a/tools/qfcc/include/method.h b/tools/qfcc/include/method.h index 14bc82b86..ec8214eed 100644 --- a/tools/qfcc/include/method.h +++ b/tools/qfcc/include/method.h @@ -62,8 +62,7 @@ struct dstring_s; method_t *new_method (type_t *ret_type, param_t *selector, param_t *opt_parms); void add_method (methodlist_t *methodlist, method_t *method); -def_t *method_def (struct class_s *class, struct class_s *category, - method_t *method); +def_t *method_def (struct class_s *class, method_t *method); methodlist_t *new_methodlist (void); void copy_methods (methodlist_t *dst, methodlist_t *src); diff --git a/tools/qfcc/include/struct.h b/tools/qfcc/include/struct.h index 3a00933d6..d05589310 100644 --- a/tools/qfcc/include/struct.h +++ b/tools/qfcc/include/struct.h @@ -49,6 +49,7 @@ typedef struct struct_field_s { struct_field_t *new_struct_field (struct type_s *strct, struct type_s *type, const char *name, visibility_t visibility); struct_field_t *struct_find_field (struct type_s *strct, const char *name); +int struct_compare_fields (struct type_s *s1, struct type_s *s2); struct type_s *new_struct (const char *name); struct type_s *find_struct (const char *name); void copy_struct_fields (struct type_s *dst, struct type_s *src); diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 0c237bad8..945f1ba9f 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -37,15 +37,17 @@ static const char rcsid[] = #include "class.h" #include "method.h" +#include "struct.h" #include "type.h" static hashtab_t *class_hash; +static hashtab_t *category_hash; static hashtab_t *protocol_hash; static const char * class_get_key (void *class, void *unused) { - return ((class_t *) class)->name; + return ((class_t *) class)->class_name; } static const char * @@ -68,8 +70,9 @@ get_class (const char *name, int create) } c = calloc (sizeof (class_t), 1); - c->name = name; - Hash_Add (class_hash, c); + c->class_name = name; + if (name) + Hash_Add (class_hash, c); return c; } @@ -105,10 +108,68 @@ class_add_protocol_methods (class_t *class, expr_t *protocols) } } +void +class_add_protocol (class_t *class, protocol_t *protocol) +{ + if (!class->protocols) + class->protocols = new_protocollist (); + add_protocol (class->protocols, protocol); +} + +static unsigned long +category_get_hash (void *_c, void *unused) +{ + class_t *c = (class_t *) _c; + return Hash_String (c->class_name) ^ Hash_String (c->category_name); +} + +static int +category_compare (void *_c1, void *_c2, void *unused) +{ + class_t *c1 = (class_t *) _c1; + class_t *c2 = (class_t *) _c2; + return strcmp (c1->class_name, c2->class_name) == 0 + && strcmp (c1->category_name, c2->category_name) == 0; +} + +void +class_check_ivars (class_t *class, struct type_s *ivars) +{ + if (!struct_compare_fields (class->ivars, ivars)) + warning (0, "instance variable missmatch for %s", class->class_name); + class->ivars = ivars; +} + +class_t * +get_category (const char *class_name, const char *category_name, int create) +{ + class_t *c; + + if (!category_hash) { + category_hash = Hash_NewTable (1021, 0, 0, 0); + Hash_SetHashCompare (category_hash, + category_get_hash, category_compare); + } + if (class_name && category_name) { + class_t _c = {0, class_name, category_name}; + + c = Hash_FindElement (category_hash, &_c); + if (c || !create) + return c; + } + + c = calloc (sizeof (class_t), 1); + c->class_name = class_name; + c->class_name = category_name; + if (class_name && category_name) + Hash_AddElement (category_hash, c); + return c; +} + def_t * class_def (class_t *class) { - return PR_GetDef (&type_Class, class->name, 0, &numpr_globals); + return PR_GetDef (&type_Class, class->class_name, 0, &numpr_globals); } protocol_t * @@ -124,7 +185,8 @@ get_protocol (const char *name, int create) p = calloc (sizeof (protocol_t), 1); p->name = name; - Hash_Add (protocol_hash, p); + if (name) + Hash_Add (protocol_hash, p); return p; } @@ -163,3 +225,22 @@ protocol_def (protocol_t *protocol) { return PR_GetDef (&type_Protocol, protocol->name, 0, &numpr_globals); } + +protocollist_t * +new_protocollist (void) +{ + protocollist_t *protocollist = malloc (sizeof (protocollist_t)); + + protocollist->count = 0; + protocollist->list = 0; + return protocollist; +} + +void +add_protocol (protocollist_t *protocollist, protocol_t *protocol) +{ + protocollist->list = realloc (protocollist->list, + (protocollist->count + 1) + * sizeof (protocollist_t)); + protocollist->list[protocollist->count++] = protocol; +} diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 849ce2fc6..43c156c7f 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -77,7 +77,7 @@ add_method (methodlist_t *methodlist, method_t *method) } def_t * -method_def (class_t *class, class_t *category, method_t *method) +method_def (class_t *class, method_t *method) { dstring_t *str = dstring_newstr (); dstring_t *sel = dstring_newstr (); @@ -87,8 +87,8 @@ method_def (class_t *class, class_t *category, method_t *method) selector_name (sel, (keywordarg_t *)method->selector); dsprintf (str, "_%c_%s_%s_%s", method->instance ? 'i' : 'c', - class->name, - category ? category->name : "", + class->class_name, + class->category_name ? class->category_name : "", sel->str); for (s = str->str; *s; s++) if (*s == ':') diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 05b464ac6..878496d3b 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -54,6 +54,14 @@ yyerror (const char *s) error (0, "%s %s\n", yytext, s); } +void +parse_error (void) +{ + error (0, "parse error before %s", yytext); +} + +#define PARSE_ERROR do { parse_error (); YYERROR; } while (0) + int yylex (void); type_t *build_type (int is_field, type_t *type); @@ -133,9 +141,11 @@ void free_local_inits (hashtab_t *def_list); %type protocolrefs %type messageargs keywordarg keywordarglist selectorarg %type keywordnamelist keywordname -%type class_name new_class_name +%type class_name new_class_name class_with_super new_class_with_super +%type category_name new_category_name %type protocol_name %type methodprotolist methodprotolist2 +%type ivar_decl_list %expect 2 // statement : if | if else, defs : defs def ';' | defs obj_def @@ -153,6 +163,7 @@ expr_t *continue_label; switch_block_t *switch_block; type_t *struct_type; visibility_t current_visibility; +type_t *current_ivars; def_t *pr_scope; // the function being parsed, or NULL string_t s_file; // filename for function definition @@ -165,7 +176,7 @@ int element_flag; defs : /* empty */ - | defs def ';' + | defs {if (current_class) PARSE_ERROR;} def ';' | defs obj_def ; @@ -853,8 +864,13 @@ obj_def : classdef | classdecl | protocoldef - | methoddef + | { if (!current_class) PARSE_ERROR; } methoddef | END + { + if (!current_class) + PARSE_ERROR; + current_class = 0; + } ; identifier_list @@ -888,6 +904,7 @@ class_name error (0, "undefined symbol `%s'", $1); $$ = get_class (0, 1); } + current_class = $$; } ; @@ -902,70 +919,91 @@ new_class_name current_class = $$; } +class_with_super + : class_name ':' class_name + { + if ($1->super_class != $3) + error (0, "%s is not a super class of %s", + $3->class_name, $1->class_name); + $$ = $1; + current_class = $$; + } + ; + +new_class_with_super + : new_class_name ':' class_name + { + $1->super_class = $3; + $$ = $1; + } + ; + +category_name + : NAME '(' NAME ')' + { + $$ = get_category ($1, $3, 0); + if (!$$) { + error (0, "undefined category `%s (%s)'", $1, $3); + $$ = get_category (0, 0, 1); + } + current_class = $$; + } + ; + +new_category_name + : NAME '(' NAME ')' + { + $$ = get_category ($1, $3, 1); + if ($$->defined) { + error (0, "redefinition of category `%s (%s)'", $1, $3); + $$ = get_category (0, 0, 1); + } + current_class = $$; + } + ; + protocol_name : NAME { - $$ = get_protocol ($1, 1); - if ($$->methods) { + $$ = get_protocol ($1, 0); + if ($$) { error (0, "redefinition of %s", $1); $$ = get_protocol (0, 1); + } else { + $$ = get_protocol ($1, 1); } } -classdef /* XXX */ +classdef : INTERFACE new_class_name protocolrefs { class_add_protocol_methods ($2, $3); } - '{' { $2->ivars = new_struct (0); } - ivar_decl_list '}' + '{' ivar_decl_list '}' { $2->ivars = $6; } methodprotolist { class_add_methods ($2, $9); } - END + END { current_class = 0; } | INTERFACE new_class_name protocolrefs { class_add_protocol_methods ($2, $3); } methodprotolist { class_add_methods ($2, $5); } - END - | INTERFACE new_class_name ':' class_name - protocolrefs { class_add_protocol_methods ($2, $5); } - '{' - { - $2->ivars = new_struct (0); - copy_struct_fields ($2->ivars, $4->ivars); - } - ivar_decl_list '}' - methodprotolist { class_add_methods ($2, $11); } - END - | INTERFACE new_class_name ':' class_name - protocolrefs { class_add_protocol_methods ($2, $5); } - methodprotolist { class_add_methods ($2, $7); } - END - | INTERFACE new_class_name '(' class_name ')' - protocolrefs { class_add_protocol_methods ($2, $6); } - methodprotolist { class_add_methods ($2, $8); } - END - | IMPLEMENTATION class_name '{' - { - $2->ivars = new_struct (0); - current_class = $2; - } - ivar_decl_list '}' - | IMPLEMENTATION class_name { current_class = $2; } - | IMPLEMENTATION class_name ':' class_name '{' - { - if ($4 != $2->base) - warning (0, "%s is not a super class of %s", - $4->name, $2->name); - $2->ivars = new_struct (0); - copy_struct_fields ($2->ivars, $4->ivars); - current_class = $2; - } - ivar_decl_list '}' - | IMPLEMENTATION class_name ':' class_name - { - if ($4 != $2->base) - warning (0, "%s is not a super class of %s", - $4->name, $2->name); - current_class = $2; - } - | IMPLEMENTATION class_name '(' class_name ')' { current_class = $2; } + END { current_class = 0; } + | INTERFACE new_class_with_super + protocolrefs { class_add_protocol_methods ($2, $3); } + '{' ivar_decl_list '}' { $2->ivars = $6; } + methodprotolist { class_add_methods ($2, $9); } + END { current_class = 0; } + | INTERFACE new_class_with_super + protocolrefs { class_add_protocol_methods ($2, $3); } + methodprotolist { class_add_methods ($2, $5); } + END { current_class = 0; } + | INTERFACE new_category_name + protocolrefs { class_add_protocol_methods ($2, $3); } + methodprotolist { class_add_methods ($2, $5); } + END { current_class = 0; } + | IMPLEMENTATION class_name + '{' ivar_decl_list '}' { class_check_ivars ($2, $4); } + | IMPLEMENTATION class_name + | IMPLEMENTATION class_with_super + '{' ivar_decl_list '}' { class_check_ivars ($2, $4); } + | IMPLEMENTATION class_with_super + | IMPLEMENTATION category_name ; protocoldef @@ -981,7 +1019,15 @@ protocolrefs ; ivar_decl_list - : ivar_decl_list visibility_spec ivar_decls + : { current_ivars = new_struct (0); } ivar_decl_list_2 + { + $$ = current_ivars; + current_ivars = 0; + } + ; + +ivar_decl_list_2 + : ivar_decl_list_2 visibility_spec ivar_decls | ivar_decls ; @@ -997,7 +1043,7 @@ ivar_decls ; ivar_decl - : type ivars { current_type = $1; } + : type { current_type = $1; } ivars ; ivars @@ -1008,7 +1054,7 @@ ivars ivar_declarator : NAME { - new_struct_field (current_class->ivars, current_type, + new_struct_field (current_ivars, current_type, $1, current_visibility); } ; @@ -1018,7 +1064,7 @@ methoddef methoddecl opt_state_expr { $2->instance = 0; - current_def = $2->def = method_def (current_class, 0, $2); + current_def = $2->def = method_def (current_class, $2); current_params = $2->params; } begin_function statement_block end_function @@ -1036,7 +1082,7 @@ methoddef methoddecl opt_state_expr { $2->instance = 1; - current_def = $2->def = method_def (current_class, 0, $2); + current_def = $2->def = method_def (current_class, $2); current_params = $2->params; } begin_function statement_block end_function diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index a162f9243..f7a865e16 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -117,7 +117,8 @@ new_struct (const char *name) strct->type->type = ev_struct; strct->type->struct_tail = &strct->type->struct_head; strct->type->struct_fields = Hash_NewTable (61, struct_field_get_key, 0, 0); - Hash_Add (structs, strct); + if (name) + Hash_Add (structs, strct); return strct->type; } @@ -145,6 +146,22 @@ copy_struct_fields (type_t *dst, type_t *src) new_struct_field (dst, s->type, s->name, s->visibility); } +int +struct_compare_fields (struct type_s *s1, struct type_s *s2) +{ + struct_field_t *f1 = s1->struct_head; + struct_field_t *f2 = s2->struct_head; + + while (f1 && f2) { + if (strcmp (f1->name, f2->name) + || f1->type != f2->type) + return 0; + f1 = f1->next; + f2 = f2->next; + } + return !((!f1) ^ !(f2)); +} + void process_enum (expr_t *enm) {