diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 66c03dce7..90c922325 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -150,6 +150,8 @@ expr_t *new_integer_expr (int integer_val); expr_t *new_uinteger_expr (unsigned int uinteger_val); expr_t *new_short_expr (short short_val); +expr_t *constant_expr (expr_t *var); + expr_t *new_bind_expr (expr_t *e1, expr_t *e2); expr_t *new_self_expr (void); expr_t *new_this_expr (void); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index b1911e550..b27a72a04 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -605,6 +605,32 @@ new_short_expr (short short_val) return e; } +expr_t * +constant_expr (expr_t *var) +{ + if (var->type != ex_def || !var->e.def->constant) { + error (var, "internal error"); + abort (); + } + switch (var->e.def->type->type) { + case ev_string: + return new_string_expr (G_GETSTR (var->e.def->ofs)); + case ev_float: + return new_float_expr (G_FLOAT (var->e.def->ofs)); + case ev_vector: + return new_vector_expr (G_VECTOR (var->e.def->ofs)); + case ev_field: + return new_field_expr (G_var (integer, var->e.def->ofs)); + case ev_integer: + return new_integer_expr (G_INT (var->e.def->ofs)); + case ev_uinteger: + return new_uinteger_expr (G_INT (var->e.def->ofs)); + default: + error (var, "internal error"); + abort (); + } +} + expr_t * new_bind_expr (expr_t *e1, expr_t *e2) { @@ -2309,6 +2335,8 @@ init_elements (def_t *def, expr_t *eles) count = def->type->num_parms; } for (i = 0, e = eles->e.block.head; i < count; i++, e = e->next) { + if (e->type == ex_def && e->e.def->constant) + e = constant_expr (e); if (e->type == ex_block) { warning (e, "not yet implemented"); } else if (e->type >= ex_string) { diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 4cbc957c0..98d047b31 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -275,6 +275,8 @@ enum | NAME '=' expr { $$ = 0; + if ($3->type == ex_def && $3->e.def->constant) + $3 = constant_expr ($3); if ($3->type < ex_string) { error ($3, "non-constant initializer"); } else if ($3->type != ex_integer) { @@ -413,6 +415,8 @@ var_initializer assign_expr (new_def_expr ($0), $2)); def_initialized ($0); } else { + if ($2->type == ex_def && $2->e.def->constant) + $2 = constant_expr ($2); if ($2->type >= ex_string) { if ($0->constant) { error ($2, "%s re-initialized", $0->name); diff --git a/tools/qfcc/source/switch.c b/tools/qfcc/source/switch.c index 4d9144001..6f7c7d074 100644 --- a/tools/qfcc/source/switch.c +++ b/tools/qfcc/source/switch.c @@ -96,6 +96,8 @@ case_label_expr (switch_block_t *switch_block, expr_t *value) if (value) convert_name (value); + if (value->type == ex_def && value->e.def->constant) + value = constant_expr (value); if (value && value->type < ex_string) { error (value, "non-constant case value"); free (cl);