diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index 0d482b963..acd5f1998 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -70,9 +70,16 @@ typedef enum storage_class_e { } storage_class_t; def_t *new_def (const char *name, struct type_s *type, - struct defspace_s *scope, storage_class_t storage); + struct defspace_s *space, storage_class_t storage); void free_def (def_t *def); void def_to_ddef (def_t *def, ddef_t *ddef, int aux); +struct symbol_s; +struct expr_s; + +void initialize_def (struct symbol_s *sym, struct type_s *type, + struct expr_s *init, struct defspace_s *space, + storage_class_t storage); + #endif//__def_h diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index ab37b8e98..6cee6e7a1 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -57,6 +57,7 @@ static __attribute__ ((used)) const char rcsid[] = #include "reloc.h" #include "strpool.h" #include "struct.h" +#include "symtab.h" #include "type.h" static def_t *free_defs; @@ -149,3 +150,69 @@ def_to_ddef (def_t *def, ddef_t *ddef, int aux) ddef->ofs = def->offset; ddef->s_name = ReuseString (def->name); } + +void +initialize_def (symbol_t *sym, type_t *type, expr_t *init, defspace_t *space, + storage_class_t storage) +{ + if (sym->table == current_symtab) { + if (sym->sy_type != sy_var || sym->type != type) { + error (0, "%s redefined", sym->name); + sym = new_symbol (sym->name); + } else { + // is var and same type + if (!sym->s.def) + internal_error (0, "half defined var"); + if (storage == st_extern) { + if (init) + warning (0, "initializing external variable"); + return; + } + if (init && sym->s.def->initialized) { + error (0, "%s redefined", sym->name); + return; + } + } + } else if (sym->table) { + sym = new_symbol (sym->name); + } + sym->type = type; + symtab_addsymbol (current_symtab, sym); + if (storage == st_global && init) { + sym->sy_type = sy_const; + memset (&sym->s.value, 0, sizeof (&sym->s.value)); + if (init->type != ex_value) { //FIXME arrays/structs + error (0, "non-constant initializier"); + } else { + sym->s.value = init->e.value; + } + return; + } + if (sym->s.def && sym->s.def->external) { + free_def (sym->s.def); + sym->s.def = 0; + } + if (!sym->s.def) + sym->s.def = new_def (sym->name, type, space, storage); + if (storage == st_extern) { + if (init) + warning (0, "initializing external variable"); + return; + } + if (!init) + return; + if (!type_assignable (type, get_type (init))) { + error (init, "type mismatch in initializer"); + return; + } + if (local_expr) { + append_expr (local_expr, assign_expr (new_symbol_expr (sym), init)); + } else { + if (init->type != ex_value) { //FIXME arrays/structs + error (0, "non-constant initializier"); + return; + } + memcpy (D_POINTER (void, sym->s.def), &init->e.value, + type_size (type) * sizeof (pr_type_t)); + } +} diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 286b5d1c1..da3bbb701 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -163,8 +163,9 @@ int yylex (void); %type fdef_name cfunction_def func_def %type function_decl %type param param_list -%type opt_initializer methoddef var_initializer -%type opt_expr fexpr expr element_list element_list1 element +%type methoddef +%type opt_initializer var_initializer +%type opt_expr fexpr expr element_list element %type opt_state_expr think opt_step array_decl texpr %type statement statements statement_block %type label break_label continue_label @@ -192,7 +193,6 @@ int yylex (void); function_t *current_func; param_t *current_params; -expr_t *current_init; class_type_t *current_class; expr_t *local_expr; vis_e current_visibility; @@ -508,10 +508,8 @@ def_list def_item : def_name opt_initializer { - $1 = check_redefined ($1); - $1->type = $0; - $1->visibility = current_visibility; - symtab_addsymbol (current_symtab, $1); + initialize_def ($1, $0, $2, pr.near_data, //FIXME right space + current_storage); } ; @@ -583,35 +581,24 @@ def_name ; opt_initializer - : /*empty*/ - { - } + : /*empty*/ { $$ = 0; } | var_initializer { $$ = $1; } ; var_initializer - : '=' expr // don't bother folding twice - { - } - | '=' '{' { } element_list '}' - { - } + : '=' fexpr { $$ = $2; } + | '=' '{' element_list opt_comma '}' { $$ = $3; } ; opt_state_expr - : /* emtpy */ - { - $$ = 0; - } - | '[' fexpr ',' think opt_step ']' - { - $$ = build_state_expr ($2, $4, $5); - } + : /* emtpy */ { $$ = 0; } + | '[' fexpr ',' think opt_step ']' { $$ = build_state_expr ($2, $4, $5); } ; think : def_name { + internal_error (0, "FIXME"); } | '(' fexpr ')' { @@ -625,45 +612,20 @@ opt_step ; element_list - : /* empty */ - { - $$ = new_block_expr (); - } - | element_list1 opt_comma - { - $$ = current_init; - } - ; - -element_list1 : element { - append_expr (current_init, $1); + $$ = new_block_expr (); + append_expr ($$, $1); } - | element_list1 ',' element + | element_list ',' element { - append_expr (current_init, $3); + append_expr ($$, $3); } ; element - : '{' - { - $$ = current_init; - current_init = new_block_expr (); - } - element_list - { - current_init = $2; - } - '}' - { - $$ = $3; - } - | fexpr - { - $$ = $1; - } + : '{' element_list opt_comma '}' { $$ = $2; } + | fexpr { $$ = $1; } ; opt_comma