From 6ecb7072575b1bacd65ff3e066a716521f57fe3e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 30 Jul 2003 04:11:45 +0000 Subject: [PATCH] revamp the struct system so "struct foo;" does the right thing (ala C) --- ruamoko/cl_menu/controls_o.qc | 3 +- ruamoko/include/InputLine.h | 4 +- ruamoko/include/List.h | 10 +- ruamoko/include/draw.h | 4 +- ruamoko/include/hash.h | 2 +- ruamoko/include/plist.h | 3 +- ruamoko/include/qfile.h | 2 +- ruamoko/lib/List.r | 7 + tools/qfcc/include/class.h | 8 +- tools/qfcc/include/struct.h | 41 ++++-- tools/qfcc/include/type.h | 10 +- tools/qfcc/source/class.c | 38 ++++-- tools/qfcc/source/def.c | 7 +- tools/qfcc/source/emit.c | 16 ++- tools/qfcc/source/expr.c | 26 ++-- tools/qfcc/source/method.c | 8 +- tools/qfcc/source/qc-lex.l | 2 +- tools/qfcc/source/qc-parse.y | 33 ++--- tools/qfcc/source/struct.c | 160 +++++++++++++--------- tools/qfcc/source/type.c | 242 ++++++++++++++++++---------------- 20 files changed, 367 insertions(+), 259 deletions(-) diff --git a/ruamoko/cl_menu/controls_o.qc b/ruamoko/cl_menu/controls_o.qc index 5a960c2a0..7069bce9e 100644 --- a/ruamoko/cl_menu/controls_o.qc +++ b/ruamoko/cl_menu/controls_o.qc @@ -41,11 +41,12 @@ Array movement_bindings; Array misc_bindings; Array weapon_bindings; -struct binding_t = { +struct binding_s = { string text; string command; string keys; }; +typedef struct binding_s binding_t; binding_t [16] movement_binding_list = { {"Jump/Swin up", "+jump"}, diff --git a/ruamoko/include/InputLine.h b/ruamoko/include/InputLine.h index ecdf01244..6575ce5c0 100644 --- a/ruamoko/include/InputLine.h +++ b/ruamoko/include/InputLine.h @@ -4,7 +4,7 @@ #include "Object.h" struct _inputline_t = {}; // opaque type :) -typedef _inputline_t [] inputline_t; +typedef struct _inputline_t [] inputline_t; @extern inputline_t (integer lines, integer size, integer prompt) InputLine_Create; @extern void (inputline_t il, void [] data) InputLine_SetUserData; @@ -26,7 +26,7 @@ struct il_data_t = { @interface InputLine: Object { - il_data_t control; + struct il_data_t control; inputline_t il; } diff --git a/ruamoko/include/List.h b/ruamoko/include/List.h index 0c6ae2c13..4882825da 100644 --- a/ruamoko/include/List.h +++ b/ruamoko/include/List.h @@ -3,17 +3,11 @@ #include "Object.h" -struct list_bucket_t = { - list_bucket_t [] next; - list_bucket_t [][] prev; - id obj; -}; - @interface List: Object { integer count; - list_bucket_t [] head; - list_bucket_t [][] tail; + struct list_bucket_s [] head; + struct list_bucket_s [][] tail; } - (id) init; - (void) free; diff --git a/ruamoko/include/draw.h b/ruamoko/include/draw.h index 16f285e8e..5d6392033 100644 --- a/ruamoko/include/draw.h +++ b/ruamoko/include/draw.h @@ -7,7 +7,7 @@ struct _qpic_t = { integer width; integer height; }; -typedef _qpic_t [] qpic_t; +typedef struct _qpic_t [] qpic_t; @extern qpic_t (string name, integer alpha) Draw_CachePic; @@ -25,7 +25,7 @@ typedef _qpic_t [] qpic_t; @interface QPic : Object { string name; - _qpic_t size; + struct _qpic_t size; BOOL centered; } -initName:(string)n; diff --git a/ruamoko/include/hash.h b/ruamoko/include/hash.h index 1fa3bc709..85af1d174 100644 --- a/ruamoko/include/hash.h +++ b/ruamoko/include/hash.h @@ -2,7 +2,7 @@ #define __ruamoko_hash_h struct _hashtab_t = {}; -typedef _hashtab_t [] hashtab_t; +typedef struct _hashtab_t [] hashtab_t; @extern hashtab_t () Hash_NewTable; @extern void () Hash_SetHashCompare; diff --git a/ruamoko/include/plist.h b/ruamoko/include/plist.h index f789e54c7..4cd915719 100644 --- a/ruamoko/include/plist.h +++ b/ruamoko/include/plist.h @@ -1,7 +1,8 @@ #ifndef __ruamoko_plist_h #define __ruamoko_plist_h -struct plitem_t = {integer [2] dummy;}; +struct plitem_s = {integer [2] dummy;}; +typedef struct plitem_s plitem_t; @extern plitem_t (string str) PL_GetPropertyList; @extern plitem_t (plitem_t item, string key) PL_ObjectForKey; diff --git a/ruamoko/include/qfile.h b/ruamoko/include/qfile.h index 27153ec9c..e1fa259b6 100644 --- a/ruamoko/include/qfile.h +++ b/ruamoko/include/qfile.h @@ -2,7 +2,7 @@ #define __ruamoko_qfile_h struct _qfile_t = {}; -typedef _qfile_t [] QFile; +typedef struct _qfile_t [] QFile; @extern integer (string old, string new) Qrename; @extern integer (string path) Qremove; diff --git a/ruamoko/lib/List.r b/ruamoko/lib/List.r index de79defaa..71e76cb09 100644 --- a/ruamoko/lib/List.r +++ b/ruamoko/lib/List.r @@ -1,5 +1,12 @@ #include "List.h" +struct list_bucket_s = { + struct list_bucket_s [] next; + struct list_bucket_s [][] prev; + id obj; +}; +typedef struct list_bucket_s list_bucket_t; + @implementation List - (id) init diff --git a/tools/qfcc/include/class.h b/tools/qfcc/include/class.h index f12f86a24..f3a89e4dd 100644 --- a/tools/qfcc/include/class.h +++ b/tools/qfcc/include/class.h @@ -45,7 +45,7 @@ typedef struct class_s { const char *name; struct class_s *super_class; struct category_s *categories; - struct type_s *ivars; + struct struct_s *ivars; struct methodlist_s *methods; struct protocollist_s *protocols; struct def_s *def; @@ -73,15 +73,15 @@ extern class_type_t *current_class; struct expr_s; struct method_s; struct protocol_s; -struct type_s; struct def_s *class_def (class_type_t *class_type, int external); void class_init (void); 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, struct expr_s *protocols); -void class_add_ivars (class_t *class, struct type_s *ivars); -void class_check_ivars (class_t *class, struct type_s *ivars); +struct struct_s *class_new_ivars (class_t *class); +void class_add_ivars (class_t *class, struct struct_s *ivars); +void class_check_ivars (class_t *class, struct struct_s *ivars); void class_begin (class_type_t *class_type); void class_finish (class_type_t *class_type); int class_access (class_type_t *current_class, class_t *class); diff --git a/tools/qfcc/include/struct.h b/tools/qfcc/include/struct.h index 07cf6b12a..750cb7cc4 100644 --- a/tools/qfcc/include/struct.h +++ b/tools/qfcc/include/struct.h @@ -36,20 +36,31 @@ typedef enum { vis_private, vis_protected, vis_public, -} visibility_t; +} visibility_type; + +typedef enum { + str_none, + str_struct, + str_union, +} struct_type; typedef struct struct_field_s { struct struct_field_s *next; const char *name; struct type_s *type; int offset; - visibility_t visibility; + visibility_type visibility; } struct_field_t; typedef struct struct_s { const char *name; struct type_s *type; - int is_union; + struct_type stype; + struct hashtab_s *struct_fields; + struct_field_t *struct_head; + struct_field_t **struct_tail; + int size; + void *return_addr; // who allocated this } struct_t; typedef struct enum_s { @@ -57,18 +68,17 @@ typedef struct enum_s { int value; } enum_t; -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_field_t *new_struct_field (struct_t *strct, struct type_s *type, + const char *name, + visibility_type visibility); +struct_field_t *struct_find_field (struct_t *strct, const char *name); +int struct_compare_fields (struct_t *s1, struct_t *s2); struct type_s *init_struct (struct_t *strct, struct type_s *type, - const char *name); -struct type_s *new_struct (const char *name); -struct type_s *new_union (const char *name); -struct type_s *find_struct (const char *name); -void copy_struct_fields (struct type_s *dst, struct type_s *src); + struct_type stype, const char *name); +struct_t *get_struct (const char *name, int create); +void copy_struct_fields (struct_t *dst, struct_t *src); -struct def_s *emit_struct (struct type_s *strct, const char *name); +struct def_s *emit_struct (struct_t *strct, const char *name); void process_enum (struct expr_s *enm); struct expr_s *get_enum (const char *name); @@ -76,4 +86,9 @@ struct expr_s *get_enum (const char *name); void clear_structs (void); void clear_enums (void); +struct_t *new_struct (const char *name); +struct_t *new_union (const char *name); +struct_t *decl_struct (const char *name); +struct_t *decl_union (const char *name); + #endif//__struct_h diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index deb93d9f9..85f905739 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -42,10 +42,10 @@ typedef struct type_s { struct type_s *aux_type; // return type or field type int num_parms; // -1 = variable args struct type_s *parm_types[MAX_PARMS]; // only [num_parms] allocated - struct hashtab_s *struct_fields; - struct struct_field_s *struct_head; - struct struct_field_s **struct_tail; - struct class_s *class; // for ev_class + union { + struct class_s *class; // for ev_class + struct struct_s *strct; // for ev_struct + } s; } type_t; extern type_t type_void; @@ -78,7 +78,7 @@ extern type_t type_va_list; extern type_t type_param; extern type_t type_zero; -extern type_t *vector_struct; +extern struct struct_s *vector_struct; struct dstring_s; diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index 17a8eb7cf..73b6923e7 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -122,7 +122,7 @@ get_class (const char *name, int create) c = calloc (sizeof (class_t), 1); c->name = name; new = *type_Class.aux_type; - new.class = c; + new.s.class = c; c->type = pointer_type (find_type (&new)); c->class_type.is_class = 1; c->class_type.c.class = c; @@ -212,9 +212,10 @@ class_begin (class_type_t *class_type) EMIT_STRING (meta->name, class->name); meta->info = _PR_CLS_META; meta->instance_size = type_size (type_Class.aux_type); - EMIT_DEF (meta->ivars, emit_struct (type_Class.aux_type, "Class")); - EMIT_DEF (meta->protocols, emit_protocol_list (class->protocols, - class->name)); + EMIT_DEF (meta->ivars, + emit_struct (type_Class.aux_type->s.class->ivars, "Class")); + EMIT_DEF (meta->protocols, + emit_protocol_list (class->protocols, class->name)); class->def->initialized = class->def->constant = 1; class->def->nosave = 1; @@ -311,7 +312,7 @@ class_finish (class_type_t *class_type) EMIT_DEF (meta->methods, emit_methods (class->methods, class->name, 0)); - cls->instance_size = type_size (class->ivars); + cls->instance_size = class->ivars? type_size (class->ivars->type) : 0; EMIT_DEF (cls->ivars, emit_struct (class->ivars, class->name)); EMIT_DEF (cls->methods, emit_methods (class->methods, class->name, 1)); @@ -481,14 +482,24 @@ category_compare (void *_c1, void *_c2, void *unused) && strcmp (c1->class->name, c2->class->name) == 0; } +struct_t * +class_new_ivars (class_t *class) +{ + struct_t *ivars = new_struct (0); + if (class->super_class) + new_struct_field (ivars, class->super_class->ivars->type, 0, + vis_private); + return ivars; +} + void -class_add_ivars (class_t *class, struct type_s *ivars) +class_add_ivars (class_t *class, struct_t *ivars) { class->ivars = ivars; } void -class_check_ivars (class_t *class, struct type_s *ivars) +class_check_ivars (class_t *class, struct_t *ivars) { if (!struct_compare_fields (class->ivars, ivars)) warning (0, "instance variable missmatch for %s", class->name); @@ -603,7 +614,7 @@ class_finish_module (void) int num_classes = 0; int num_categories = 0; int i; - type_t *symtab_type; + struct_t *symtab_type; def_t *symtab_def; pr_symtab_t *symtab; pointer_t *def_ptr; @@ -628,13 +639,15 @@ class_finish_module (void) } if (!num_classes && !num_categories) return; - symtab_type = new_struct (0); + symtab_type = get_struct (0, 1); + init_struct (symtab_type, new_type (), str_struct, 0); new_struct_field (symtab_type, &type_integer, "sel_ref_cnt", vis_public); new_struct_field (symtab_type, &type_integer, "cls_def_cnt", vis_public); new_struct_field (symtab_type, &type_integer, "cat_def_cnt", vis_public); for (i = 0; i < num_classes + num_categories; i++) new_struct_field (symtab_type, &type_pointer, 0, vis_public); - symtab_def = get_def (symtab_type, "_OBJ_SYMTAB", pr.scope, st_static); + symtab_def = get_def (symtab_type->type, "_OBJ_SYMTAB", pr.scope, + st_static); symtab_def->initialized = symtab_def->constant = 1; symtab_def->nosave = 1; symtab = &G_STRUCT (pr_symtab_t, symtab_def->ofs); @@ -779,13 +792,14 @@ def_t * emit_protocol_list (protocollist_t *protocols, const char *name) { def_t *proto_list_def; - type_t *protocol_list; + struct_t *protocol_list; pr_protocol_list_t *proto_list; int i; if (!protocols) return 0; - protocol_list = new_struct (0); + protocol_list = get_struct (0, 1); + init_struct (protocol_list, new_type (), str_struct, 0); new_struct_field (protocol_list, &type_pointer, "next", vis_public); new_struct_field (protocol_list, &type_integer, "count", vis_public); for (i = 0; i < protocols->count; i++) diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index c8c0dacec..c475c4f28 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -94,7 +94,7 @@ check_for_name (type_t *type, const char *name, scope_t *scope, } if (!name) return 0; - if (scope->type == sc_global && (find_struct (name) || get_enum (name))) { + if (scope->type == sc_global && get_enum (name)) { error (0, "%s redeclared", name); return 0; } @@ -102,8 +102,11 @@ check_for_name (type_t *type, const char *name, scope_t *scope, def = (def_t *) Hash_Find (defs_by_name, name); if (def) { if (storage != st_none && scope == def->scope) - if (type && def->type != type) + if (type && def->type != type) { + print_type (type); + print_type (def->type); error (0, "Type mismatch on redeclaration of %s", name); + } if (storage == st_none || def->scope == scope) return def; } diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index 8bf8bdcde..1cc97f947 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -342,13 +342,13 @@ emit_move_expr (expr_t *e) if (dst_type->type == ev_struct && src_type->type == ev_struct) { size_expr = new_short_expr (type_size (dst->type)); } else if (dst_type->type == ev_struct) { - if (dst->alias) - dst = dst->alias; + //if (dst->alias) + // dst = dst->alias; dst = emit_sub_expr (address_expr (new_def_expr (dst), 0, 0), 0); size_expr = new_integer_expr (type_size (dst_type)); } else if (src_type->type == ev_struct) { - if (src->alias) - src = src->alias; + //if (src->alias) + // src = src->alias; src = emit_sub_expr (address_expr (new_def_expr (src), 0, 0), 0); size_expr = new_integer_expr (type_size (dst_type->aux_type)); } else { @@ -401,6 +401,14 @@ emit_deref_expr (expr_t *e, def_t *dest) } return d; } + if (e->type == ex_uexpr && e->e.expr.op == '&' + && e->e.expr.e1->type == ex_def) { + d = new_def (e->e.expr.type->aux_type, 0, current_scope); + d->alias = e->e.expr.e1->e.def; + d->local = d->alias->local; + d->ofs = d->alias->ofs; + return d; + } if (!dest) { dest = get_tempdef (type, current_scope); dest->users += 2; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 9de72d44b..3b59cab69 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -1119,6 +1119,7 @@ field_expr (expr_t *e1, expr_t *e2) int i; struct_field_t *field; class_t *class; + struct_t *strct; if (e1->type == ex_error) return e1; @@ -1129,7 +1130,11 @@ field_expr (expr_t *e1, expr_t *e2) check_initialized (e1); if (e2->type != ex_name) return error (e2, "structure field name expected"); - field = struct_find_field (t1, e2->e.string_val); + if (t1->type == ev_struct) + strct = t1->s.strct; + else + strct = t1->s.class->ivars; + field = struct_find_field (strct, e2->e.string_val); if (!field) return error (e2, "structure has no field %s", e2->e.string_val); @@ -1142,7 +1147,7 @@ field_expr (expr_t *e1, expr_t *e2) switch (t1->aux_type->type) { case ev_struct: if (e2->type == ex_name) { - field = struct_find_field (t1->aux_type, + field = struct_find_field (t1->aux_type->s.strct, e2->e.string_val); if (!field) return error (e2, "structure has no field %s", @@ -1157,7 +1162,7 @@ field_expr (expr_t *e1, expr_t *e2) if (e2->type == ex_name) { int protected; - class = t1->aux_type->class; + class = t1->aux_type->s.class; protected = class_access (current_class, class); field = class_find_ivar (class, protected, e2->e.string_val); @@ -2070,7 +2075,7 @@ expr_t * address_expr (expr_t *e1, expr_t *e2, type_t *t) { expr_t *e; - type_t *type = 0; + type_t *type; if (e1->type == ex_error) return e1; @@ -2100,7 +2105,7 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) e->e.pointer.def = def; } else { e = new_unary_expr ('&', e1); - e->e.expr.type = pointer_type (type); + e->e.expr.type = pointer_type (t); } break; } @@ -2119,7 +2124,6 @@ address_expr (expr_t *e1, expr_t *e2, type_t *t) case ex_uexpr: if (e1->e.expr.op == '.') { e = e1->e.expr.e1; - type = get_type (e)->aux_type; if (e->type == ex_expr && e->e.expr.op == '.') { e->e.expr.type = e->e.expr.type; e->e.expr.op = '&'; @@ -2324,11 +2328,11 @@ init_elements (def_t *def, expr_t *eles) } else if (def->type->type == ev_struct) { struct_field_t *field; - for (i = 0, field = def->type->struct_head; field; + for (i = 0, field = def->type->s.strct->struct_head; field; i++, field = field->next) ; elements = calloc (i, sizeof (def_t)); - for (i = 0, field = def->type->struct_head; field; + for (i = 0, field = def->type->s.strct->struct_head; field; i++, field = field->next) { elements[i].type = field->type; elements[i].ofs = def->ofs + field->offset; @@ -2343,9 +2347,9 @@ init_elements (def_t *def, expr_t *eles) free (elements); return; } - if (count > def->type->num_parms) { + if (count > num_params) { warning (eles, "excessive elements in initializer"); - count = def->type->num_parms; + count = num_params; } for (i = 0, e = eles->e.block.head; i < count; i++, e = e->next) { g = G_POINTER (pr_type_t, elements[i].ofs); @@ -2485,7 +2489,7 @@ message_expr (expr_t *receiver, keywordarg_t *message) || (rec_type->aux_type->type != ev_object && rec_type->aux_type->type != ev_class)) return error (receiver, "not a class/object"); - class = rec_type->aux_type->class; + class = rec_type->aux_type->s.class; } method = class_message_response (class, class_msg, selector); diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index c363b98b3..3ab4f60bc 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -316,7 +316,7 @@ emit_methods (methodlist_t *_methods, const char *name, int instance) int i, count; def_t *methods_def; pr_method_list_t *methods; - type_t *method_list; + struct_t *method_list; if (!_methods) return 0; @@ -329,12 +329,14 @@ emit_methods (methodlist_t *_methods, const char *name, int instance) } if (!count) return 0; - method_list = new_struct (0); + method_list = get_struct (0, 1); + init_struct (method_list, new_type (), str_struct, 0); new_struct_field (method_list, &type_pointer, "method_next", vis_public); new_struct_field (method_list, &type_integer, "method_count", vis_public); for (i = 0; i < count; i++) new_struct_field (method_list, type_Method.aux_type, 0, vis_public); - methods_def = get_def (method_list, va ("_OBJ_%s_METHODS_%s", type, name), + 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; diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index beb468619..579f0bbe7 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -378,7 +378,7 @@ type_or_name (char *token) if (token[0] == '@') { return '@'; } - if ((type = find_struct (token)) || (type = get_typedef (token))) { + if ((type = get_typedef (token))) { yylval.type = type; return TYPE; } diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index cc4b62327..9ae125f64 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -118,6 +118,7 @@ expr_t *argv_expr (void); struct protocol_s *protocol; struct keywordarg_s *keywordarg; struct methodlist_s *methodlist; + struct struct_s *strct; } %right '=' ASX PAS /* pointer assign */ @@ -172,7 +173,7 @@ expr_t *argv_expr (void); %type category_name new_category_name %type protocol_name %type methodprotolist methodprotolist2 -%type ivar_decl_list +%type ivar_decl_list %expect 4 @@ -186,9 +187,9 @@ expr_t *local_expr; expr_t *break_label; expr_t *continue_label; switch_block_t *switch_block; -type_t *struct_type; -visibility_t current_visibility; -type_t *current_ivars; +struct_t *current_struct; +visibility_type current_visibility; +struct_t *current_ivars; scope_t *current_scope; storage_class_t current_storage; @@ -209,9 +210,11 @@ def | storage_class type { $$ = $2; } def_list { } | storage_class '{' simple_defs '}' { } | STRUCT NAME - { struct_type = new_struct ($2); } '=' '{' struct_defs '}' { } + { current_struct = new_struct ($2); } '=' '{' struct_defs '}' { } | UNION NAME - { struct_type = new_union ($2); } '=' '{' struct_defs '}' { } + { current_struct = new_union ($2); } '=' '{' struct_defs '}' { } + | STRUCT NAME { decl_struct ($2)->type; } + | UNION NAME { decl_union ($2)->type; } | ENUM '{' enum_list opt_comma '}' { process_enum ($3); } | TYPEDEF type NAME @@ -246,7 +249,7 @@ struct_defs class_t *class = get_class ($3, 0); if (class) { - copy_struct_fields (struct_type, class->ivars); + copy_struct_fields (current_struct, class->ivars); } else { error (0, "undefined symbol `%s'", $3); } @@ -320,6 +323,8 @@ type_name } $$ = class->type; } + | STRUCT NAME { $$ = decl_struct ($2)->type; } + | UNION NAME { $$ = decl_union ($2)->type; } ; function_decl @@ -372,7 +377,7 @@ struct_def_list ; struct_def_item - : NAME { new_struct_field (struct_type, $0, $1, vis_public); } + : NAME { new_struct_field (current_struct, $0, $1, vis_public); } ; def_list @@ -1022,7 +1027,8 @@ classdef END { current_class = 0; } | INTERFACE new_class_name protocolrefs { class_add_protocol_methods ($2, $3); $$ = $2; } - methodprotolist { class_add_methods ($2, $5); } + { class_add_ivars ($2, class_new_ivars ($2)); } + methodprotolist { class_add_methods ($2, $6); } END { current_class = 0; } | INTERFACE new_class_with_super protocolrefs { class_add_protocol_methods ($2, $3);} @@ -1032,7 +1038,8 @@ classdef END { current_class = 0; } | INTERFACE new_class_with_super protocolrefs { class_add_protocol_methods ($2, $3); $$ = $2; } - methodprotolist { class_add_methods ($2, $5); } + { class_add_ivars ($2, class_new_ivars ($2)); } + methodprotolist { class_add_methods ($2, $6); } END { current_class = 0; } | INTERFACE new_category_name protocolrefs { category_add_protocol_methods ($2, $3); $$ = $2->class;} @@ -1078,11 +1085,7 @@ ivar_decl_list : /* */ { current_visibility = vis_protected; - current_ivars = new_struct (0); - if ($0->super_class) - new_struct_field (current_ivars, - $0->super_class->ivars, 0, - vis_private); + current_ivars = class_new_ivars ($0); } ivar_decl_list_2 { diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 36035bc50..6bb787098 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -79,8 +79,8 @@ enums_get_key (void *e, void *unused) } struct_field_t * -new_struct_field (type_t *strct, type_t *type, const char *name, - visibility_t visibility) +new_struct_field (struct_t *strct, type_t *type, const char *name, + visibility_type visibility) { struct_field_t *field; @@ -90,13 +90,14 @@ new_struct_field (type_t *strct, type_t *type, const char *name, field->visibility = visibility; field->name = name; field->type = type; - if (((struct_t *) strct->class)->is_union) { + if (strct->stype == str_union) { int size = type_size (type); field->offset = 0; - strct->num_parms = strct->num_parms > size ? strct->num_parms : size; + if (size > strct->size) + strct->size = size; } else { - field->offset = strct->num_parms; - strct->num_parms += type_size (type); + field->offset = strct->size;; + strct->size += type_size (type); } field->next = 0; *strct->struct_tail = field; @@ -107,7 +108,7 @@ new_struct_field (type_t *strct, type_t *type, const char *name, } struct_field_t * -struct_find_field (type_t *strct, const char *name) +struct_find_field (struct_t *strct, const char *name) { if (!structs || !strct) return 0; @@ -115,66 +116,46 @@ struct_find_field (type_t *strct, const char *name) } type_t * -init_struct (struct_t *strct, type_t *type, const char *name) +init_struct (struct_t *strct, type_t *type, struct_type stype, + const char *name) { - strct->name = name ? save_string (name) : 0; + if (name) + strct->name = save_string (name); strct->type = type; 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); - strct->type->class = (struct class_s *)strct; - strct->is_union = 0; + strct->struct_tail = &strct->struct_head; + strct->struct_fields = Hash_NewTable (61, struct_field_get_key, 0, 0); + strct->type->s.strct = strct; + strct->stype = stype; if (name) { - strct->type->name = save_string (name); + strct->type->name = strct->name; Hash_Add (structs, strct); } return strct->type; } -type_t * -new_struct (const char *name) +struct_t * +get_struct (const char *name, int create) { - struct_t *strct; - - if (!structs) { - structs = Hash_NewTable (16381, structs_get_key, 0, 0); - } - if (name) { - strct = (struct_t *) Hash_Find (structs, name); - if (strct) { - error (0, "duplicate struct definition: `%s'", name); - return 0; - } - } - strct = malloc (sizeof (struct_t)); - return init_struct (strct, new_type (), name); -} - -type_t * -new_union (const char *name) -{ - type_t *un = new_struct (name); - - if (un) - ((struct_t *) un->class)->is_union = 1; - return un; -} - -type_t * -find_struct (const char *name) -{ - struct_t *strct; + struct_t *s; if (!structs) - return 0; - strct = (struct_t *) Hash_Find (structs, name); - if (strct) - return strct->type; - return 0; + structs = Hash_NewTable (16381, structs_get_key, 0, 0); + if (name) { + s = Hash_Find (structs, name); + if (s || !create) + return s; + } + s = calloc (sizeof (struct_t), 1); + s->name = name; + s->return_addr = __builtin_return_address (0); + if (name) + Hash_Add (structs, s); + return s; } void -copy_struct_fields (type_t *dst, type_t *src) +copy_struct_fields (struct_t *dst, struct_t *src) { struct_field_t *s; @@ -185,7 +166,7 @@ copy_struct_fields (type_t *dst, type_t *src) } int -struct_compare_fields (struct type_s *s1, struct type_s *s2) +struct_compare_fields (struct_t *s1, struct_t *s2) { struct_field_t *f1 = s1->struct_head; struct_field_t *f2 = s2->struct_head; @@ -200,14 +181,75 @@ struct_compare_fields (struct type_s *s1, struct type_s *s2) return !((!f1) ^ !(f2)); } +static struct_t * +start_struct (const char *name, struct_type stype) +{ + struct_t *strct = get_struct (name, 1); + if (strct->struct_head) { + error (0, "%s redeclared", name); + goto err; + } + if (strct->stype != str_none && strct->stype != stype) { + error (0, "%s defined as wrong kind of tag", name); + goto err; + } + if (!strct->type) + init_struct (strct, new_type (), stype, 0); + return strct; +err: + strct = get_struct (0, 0); + init_struct (strct, new_type (), stype, 0); + return strct; +} + +struct_t * +new_struct (const char *name) +{ + return start_struct (name, str_struct); +} + +struct_t * +new_union (const char *name) +{ + return start_struct (name, str_union); +} + +static struct_t * +check_struct (const char *name, struct_type stype) +{ + struct_t *strct = get_struct (name, 0); + + if (!strct) + return start_struct (name, stype); + if (strct->stype != stype) { + error (0, "%s defined as wrong kind of tag", name); + strct = get_struct (0, 0); + init_struct (strct, new_type (), stype, 0); + } + return strct; +} + +struct_t * +decl_struct (const char *name) +{ + + return check_struct (name, str_struct); +} + +struct_t * +decl_union (const char *name) +{ + return check_struct (name, str_union); +} + def_t * -emit_struct(type_t *strct, const char *name) +emit_struct(struct_t *strct, const char *name) { struct_field_t *field; int i, count; def_t *ivars_def; pr_ivar_list_t *ivars; - type_t *ivar_list; + struct_t *ivar_list; dstring_t *encoding = dstring_newstr (); dstring_t *ivars_name = dstring_newstr (); @@ -221,10 +263,11 @@ emit_struct(type_t *strct, const char *name) for (i = 0; i < count; i++) new_struct_field (ivar_list, type_ivar, 0, vis_public); dsprintf (ivars_name, "_OBJ_INSTANCE_VARIABLES_%s", name); - ivars_def = get_def (ivar_list, ivars_name->str, pr.scope, st_none); + ivars_def = get_def (ivar_list->type, ivars_name->str, pr.scope, st_none); if (ivars_def) goto done; - ivars_def = get_def (ivar_list, ivars_name->str, pr.scope, st_static); + ivars_def = get_def (ivar_list->type, ivars_name->str, pr.scope, + st_static); ivars_def->initialized = ivars_def->constant = 1; ivars_def->nosave = 1; ivars = &G_STRUCT (pr_ivar_list_t, ivars_def->ofs); @@ -277,8 +320,7 @@ process_enum (expr_t *enm) val = name->e.expr.e2; name = name->e.expr.e1; } - if ((structs && find_struct (name->e.string_val)) - || get_enum (name->e.string_val) + if (get_enum (name->e.string_val) || get_def (NULL, name->e.string_val, pr.scope, st_none)) { error (name, "%s redeclared", name->e.string_val); continue; diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index f1ade9ddf..6dae78854 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -98,7 +98,7 @@ type_t type_va_list; type_t type_param; type_t type_zero; -type_t *vector_struct; +struct_t *vector_struct; type_t type_floatfield = { ev_field, ".float", NULL, &type_float }; @@ -135,7 +135,7 @@ find_type (type_t *type) if (check->type != type->type || check->aux_type != type->aux_type || check->num_parms != type->num_parms - || check->class != type->class) + || check->s.class != type->s.class) continue; if (check->type != ev_func) @@ -279,7 +279,7 @@ print_type (type_t *type) break; case ev_object: case ev_class: - printf (" %s", type->class->name); + printf (" %s", type->s.class->name); break; case ev_struct: printf (" %s %s", pr_type_name[type->type], type->name); @@ -369,15 +369,21 @@ _encode_type (dstring_t *encoding, type_t *type, int level) if (type->name) { dstring_appendstr (encoding, type->name); } else if (type->type == ev_object || type->type == ev_class) { - dstring_appendstr (encoding, type->class->name); + dstring_appendstr (encoding, type->s.class->name); } if (level < 2) { + struct_t *s; if (type->type == ev_struct - && ((struct_t *)type->class)->is_union) + && type->s.strct->stype == str_union) dstring_appendstr (encoding, "-"); else dstring_appendstr (encoding, "="); - for (field = type->struct_head; field; field = field->next) + if (type->type == ev_struct) { + s = type->s.strct; + } else { + s = type->s.class->ivars; + } + for (field = s->struct_head; field; field = field->next) _encode_type (encoding, field->type, level + 1); } dstring_appendstr (encoding, "}"); @@ -407,6 +413,7 @@ static type_t * _parse_type (const char **str) { type_t new; + struct_t *strct; dstring_t *name; const char *s; @@ -464,9 +471,10 @@ _parse_type (const char **str) return 0; dstring_appendsubstr (name, *str, s - *str); *str = s; + strct = 0; if (name->str[0]) - new.aux_type = find_struct (name->str); - if (new.aux_type) { + strct = get_struct (name->str, 0); + if (strct) { dstring_delete (name); if (**str == '=' || **str == '-') { (*str)++; @@ -476,24 +484,25 @@ _parse_type (const char **str) if (**str != '}') return 0; (*str)++; - return new.aux_type; + return strct->type; } if (**str != '=' && **str != '-') { dstring_delete (name); return 0; } - new.aux_type = new_struct (*name->str ? name->str : 0); + strct = get_struct (*name->str ? name->str : 0, 1); if (**str == '-') - ((struct_t *) new.aux_type->class)->is_union = 1; + init_struct (strct, new_type (), str_union, 0); + else + init_struct (strct, new_type (), str_struct, 0); dstring_delete (name); (*str)++; while (**str && **str != '}') - new_struct_field (new.aux_type, _parse_type (str), 0, - vis_public); + new_struct_field (strct, _parse_type (str), 0, vis_public); if (**str != '}') return 0; (*str)++; - return new.aux_type; + return strct->type; case '[': new.type = ev_array; while (isdigit ((byte)**str)) { @@ -536,8 +545,8 @@ type_assignable (type_t *dst, type_t *src) if ((dst->type != ev_object && dst->type != ev_class) || (src->type != ev_object && src->type != ev_class)) return 0; - dst_class = dst->class; - src_class = src->class; + dst_class = dst->s.class; + src_class = src->s.class; //printf ("%s %s\n", dst_class->class_name, src_class->class_name); if (!dst_class || dst_class == &class_id) return 1; @@ -556,9 +565,6 @@ type_assignable (type_t *dst, type_t *src) int type_size (type_t *type) { - struct_field_t *field; - int size; - if (!type) return 0; switch (type->type) { @@ -578,14 +584,12 @@ type_size (type_t *type) case ev_type_count: return pr_type_size[type->type]; case ev_struct: - return type->num_parms; + return type->s.strct->size; case ev_object: case ev_class: - for (size = 0, field = type->struct_head; - field; - field = field->next) - size += type_size (field->type); - return size; + if (!type->s.class->ivars) + return 0; + return type->s.class->ivars->size; case ev_array: return type->num_parms * type_size (type->aux_type); } @@ -596,113 +600,121 @@ void init_types (void) { type_t *type; + struct_t *strct; - init_struct (malloc (sizeof (struct_t)), type = &type_zero, 0); - ((struct_t *) type->class)->is_union = 1; - new_struct_field (type, &type_string, "string_val", vis_public); - new_struct_field (type, &type_float, "float_val", vis_public); - new_struct_field (type, &type_entity, "entity_val", vis_public); - new_struct_field (type, &type_field, "field_val", vis_public); - new_struct_field (type, &type_function, "func_val", vis_public); - new_struct_field (type, &type_pointer, "pointer_val", vis_public); - new_struct_field (type, &type_integer, "integer_val", vis_public); - new_struct_field (type, &type_uinteger, "uinteger_val", vis_public); - - init_struct (malloc (sizeof (struct_t)), type = &type_param, 0); - ((struct_t *) type->class)->is_union = 1; - new_struct_field (type, &type_string, "string_val", vis_public); - new_struct_field (type, &type_float, "float_val", vis_public); - new_struct_field (type, &type_vector, "vector_val", vis_public); - new_struct_field (type, &type_entity, "entity_val", vis_public); - new_struct_field (type, &type_field, "field_val", vis_public); - new_struct_field (type, &type_function, "func_val", vis_public); - new_struct_field (type, &type_pointer, "pointer_val", vis_public); - new_struct_field (type, &type_integer, "integer_val", vis_public); - new_struct_field (type, &type_uinteger, "uinteger_val", vis_public); + strct = calloc (sizeof (struct_t), 1); + init_struct (strct, &type_zero, str_union, 0); + new_struct_field (strct, &type_string, "string_val", vis_public); + new_struct_field (strct, &type_float, "float_val", vis_public); + new_struct_field (strct, &type_entity, "entity_val", vis_public); + new_struct_field (strct, &type_field, "field_val", vis_public); + new_struct_field (strct, &type_function, "func_val", vis_public); + new_struct_field (strct, &type_pointer, "pointer_val", vis_public); + new_struct_field (strct, &type_integer, "integer_val", vis_public); + new_struct_field (strct, &type_uinteger, "uinteger_val", vis_public); if (options.traditional) return; - type = vector_struct = new_struct (0); - new_struct_field (type, &type_float, "x", vis_public); - new_struct_field (type, &type_float, "y", vis_public); - new_struct_field (type, &type_float, "z", vis_public); + strct = vector_struct = get_struct (0, 1); + init_struct (strct, new_type (), str_struct, 0); + new_struct_field (strct, &type_float, "x", vis_public); + new_struct_field (strct, &type_float, "y", vis_public); + new_struct_field (strct, &type_float, "z", vis_public); - type = type_SEL.aux_type = new_struct (0); - new_struct_field (type, &type_string, "sel_id", vis_public); - new_struct_field (type, &type_string, "sel_types", vis_public); + strct = get_struct (0, 1); + init_struct (strct, new_type (), str_struct, 0); + new_struct_field (strct, &type_string, "sel_id", vis_public); + new_struct_field (strct, &type_string, "sel_types", vis_public); + type_SEL.aux_type = strct->type; - type = type_Method.aux_type = new_struct (0); - new_struct_field (type, type_SEL.aux_type, "method_name", vis_public); - new_struct_field (type, &type_string, "method_types", vis_public); - new_struct_field (type, &type_IMP, "method_imp", vis_public); + 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_string, "method_types", vis_public); + new_struct_field (strct, &type_IMP, "method_imp", vis_public); + type_Method.aux_type = strct->type; - type = type_Class.aux_type = new_struct (0); + strct = get_struct (0, 1); + init_struct (strct, type = new_type (), str_struct, 0); type->type = ev_class; - type->class = &class_Class; - class_Class.ivars = type_Class.aux_type; - new_struct_field (type, &type_Class, "class_pointer", vis_public); - new_struct_field (type, &type_Class, "super_class", vis_public); - new_struct_field (type, &type_string, "name", vis_public); - new_struct_field (type, &type_integer, "version", vis_public); - new_struct_field (type, &type_integer, "info", vis_public); - new_struct_field (type, &type_integer, "instance_size", vis_public); - new_struct_field (type, &type_pointer, "ivars", vis_public); - new_struct_field (type, &type_pointer, "methods", vis_public); - new_struct_field (type, &type_pointer, "dtable", vis_public); - new_struct_field (type, &type_pointer, "subclass_list", vis_public); - new_struct_field (type, &type_pointer, "sibling_class", vis_public); - new_struct_field (type, &type_pointer, "protocols", vis_public); - new_struct_field (type, &type_pointer, "gc_object_type", vis_public); + type->s.class = &class_Class; + new_struct_field (strct, &type_Class, "class_pointer", vis_public); + new_struct_field (strct, &type_Class, "super_class", vis_public); + new_struct_field (strct, &type_string, "name", vis_public); + new_struct_field (strct, &type_integer, "version", vis_public); + new_struct_field (strct, &type_integer, "info", vis_public); + new_struct_field (strct, &type_integer, "instance_size", vis_public); + new_struct_field (strct, &type_pointer, "ivars", vis_public); + new_struct_field (strct, &type_pointer, "methods", vis_public); + new_struct_field (strct, &type_pointer, "dtable", vis_public); + new_struct_field (strct, &type_pointer, "subclass_list", vis_public); + new_struct_field (strct, &type_pointer, "sibling_class", vis_public); + new_struct_field (strct, &type_pointer, "protocols", vis_public); + new_struct_field (strct, &type_pointer, "gc_object_type", vis_public); + type_Class.aux_type = strct->type; + class_Class.ivars = strct; - type = type_Protocol.aux_type = new_struct (0); + strct = get_struct (0, 1); + init_struct (strct, type = new_type (), str_struct, 0); type->type = ev_class; - type->class = &class_Protocol; - class_Protocol.ivars = type_Protocol.aux_type; - new_struct_field (type, &type_Class, "class_pointer", vis_public); - new_struct_field (type, &type_string, "protocol_name", vis_public); - new_struct_field (type, &type_pointer, "protocol_list", vis_public); - new_struct_field (type, &type_pointer, "instance_methods", vis_public); - new_struct_field (type, &type_pointer, "class_methods", vis_public); + type->s.class = &class_Protocol; + new_struct_field (strct, &type_Class, "class_pointer", vis_public); + new_struct_field (strct, &type_string, "protocol_name", vis_public); + new_struct_field (strct, &type_pointer, "protocol_list", vis_public); + new_struct_field (strct, &type_pointer, "instance_methods", vis_public); + new_struct_field (strct, &type_pointer, "class_methods", vis_public); + type_Protocol.aux_type = strct->type; + class_Protocol.ivars = strct; - type = type_id.aux_type = new_struct ("id"); + strct = get_struct (0, 1); + init_struct (strct, type = new_type (), str_struct, 0); type->type = ev_object; - type->class = &class_id; - class_id.ivars = type_id.aux_type; - new_struct_field (type, &type_Class, "class_pointer", vis_public); + type->s.class = &class_id; + new_struct_field (strct, &type_Class, "class_pointer", vis_public); + type_id.aux_type = strct->type; + class_id.ivars = strct; - type = type_category = new_struct (0); - new_struct_field (type, &type_string, "category_name", vis_public); - new_struct_field (type, &type_string, "class_name", vis_public); - new_struct_field (type, &type_pointer, "instance_methods", vis_public); - new_struct_field (type, &type_pointer, "class_methods", vis_public); - new_struct_field (type, &type_pointer, "protocols", 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); + new_struct_field (strct, &type_string, "class_name", vis_public); + new_struct_field (strct, &type_pointer, "instance_methods", vis_public); + new_struct_field (strct, &type_pointer, "class_methods", vis_public); + new_struct_field (strct, &type_pointer, "protocols", vis_public); + type_category = strct->type; - type = type_ivar = new_struct (0); - new_struct_field (type, &type_string, "ivar_name", vis_public); - new_struct_field (type, &type_string, "ivar_type", vis_public); - new_struct_field (type, &type_integer, "ivar_offset", vis_public); + strct = get_struct (0, 1); + init_struct (strct, new_type (), str_struct, 0); + new_struct_field (strct, &type_string, "ivar_name", vis_public); + new_struct_field (strct, &type_string, "ivar_type", vis_public); + new_struct_field (strct, &type_integer, "ivar_offset", vis_public); + type_ivar = strct->type; - init_struct (malloc (sizeof (struct_t)), &type_va_list, 0); - new_struct_field (&type_va_list, &type_integer, "count", vis_public); - new_struct_field (&type_va_list, pointer_type (&type_param), "list", - vis_public); + strct = calloc (sizeof (struct_t), 1); + init_struct (strct, &type_va_list, str_union, 0); + new_struct_field (strct, &type_integer, "count", vis_public); + new_struct_field (strct, pointer_type (&type_param), "list", vis_public); - type = type_Super.aux_type = new_struct ("Super"); - new_struct_field (type, &type_id, "self", vis_public); - new_struct_field (type, &type_Class, "class", vis_public); + strct = get_struct ("Super", 1); + init_struct (strct, new_type (), str_struct, 0); + new_struct_field (strct, &type_id, "self", vis_public); + new_struct_field (strct, &type_Class, "class", vis_public); + type_Super.aux_type = strct->type; #if 0 type = type_module = new_struct ("obj_module_t"); - new_struct_field (type, &type_integer, "version", vis_public); - new_struct_field (type, &type_integer, "size", vis_public); - new_struct_field (type, &type_string, "name", vis_public); - new_struct_field (type, &type_pointer, "symtab", vis_public); + new_struct_field (strct, &type_integer, "version", vis_public); + new_struct_field (strct, &type_integer, "size", vis_public); + new_struct_field (strct, &type_string, "name", vis_public); + new_struct_field (strct, &type_pointer, "symtab", vis_public); #endif } void chain_initial_types (void) { + struct_t *strct; + chain_type (&type_void); chain_type (&type_string); chain_type (&type_float); @@ -738,16 +750,18 @@ chain_initial_types (void) type_supermsg.parm_types[0] = &type_Super; chain_type (&type_supermsg); - type_module = new_struct ("obj_module_t"); - new_struct_field (type_module, &type_integer, "version", vis_public); - new_struct_field (type_module, &type_integer, "size", vis_public); - new_struct_field (type_module, &type_string, "name", vis_public); - new_struct_field (type_module, &type_pointer, "symtab", vis_public); + strct = get_struct ("obj_module_s", 1); + init_struct (strct, new_type (), str_struct, 0); + new_struct_field (strct, &type_integer, "version", vis_public); + new_struct_field (strct, &type_integer, "size", vis_public); + new_struct_field (strct, &type_string, "name", vis_public); + new_struct_field (strct, &type_pointer, "symtab", vis_public); + type_module = strct->type; + new_typedef ("obj_module_t", type_module); chain_type (type_module); - chain_type (&type_obj_exec_class); - type_obj_exec_class.parm_types[0] = pointer_type (type_module); + chain_type (&type_obj_exec_class); } void