From: Wolfgang Bumiller Date: Sat, 27 Apr 2013 14:55:28 +0000 (+0200) Subject: Merge branch 'master' into cooking X-Git-Tag: v0.3.0~151^2~62 X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=commitdiff_plain;h=9ace0811ce3eaf8a7a62664a4a6ed483a6c00a67;hp=d4b0e1f588cb033cd4400cde4bbc4357c1776f94 Merge branch 'master' into cooking --- diff --git a/ast.c b/ast.c index 3e5d304..1e2836f 100644 --- a/ast.c +++ b/ast.c @@ -317,8 +317,9 @@ ast_value* ast_value_new(lex_ctx ctx, const char *name, int t) self->cvq = CV_NONE; self->hasvalue = false; self->isimm = false; - self->uses = 0; + self->uses = 0; memset(&self->constval, 0, sizeof(self->constval)); + self->initlist = NULL; self->ir_v = NULL; self->ir_values = NULL; @@ -362,6 +363,20 @@ void ast_value_delete(ast_value* self) if (self->desc) mem_d(self->desc); + if (self->initlist) { + if (self->expression.next->expression.vtype == TYPE_STRING) { + /* strings are allocated, free them */ + size_t i, len = vec_size(self->initlist); + /* in theory, len should be expression.count + * but let's not take any chances */ + for (i = 0; i < len; ++i) { + if (self->initlist[i].vstring) + mem_d(self->initlist[i].vstring); + } + } + vec_free(self->initlist); + } + ast_expression_delete((ast_expression*)self); mem_d(self); } diff --git a/ast.h b/ast.h index bae07db..98ad792 100644 --- a/ast.h +++ b/ast.h @@ -161,6 +161,15 @@ typedef struct * typedef float foo; * is like creating a 'float foo', foo serving as the type's name. */ +typedef union { + double vfloat; + int vint; + vector vvec; + const char *vstring; + int ventity; + ast_function *vfunc; + ast_value *vfield; +} basic_value_t; struct ast_value_s { ast_expression_common expression; @@ -179,15 +188,12 @@ struct ast_value_s bool isfield; /* this declares a field */ bool isimm; /* an immediate, not just const */ bool hasvalue; - union { - double vfloat; - int vint; - vector vvec; - const char *vstring; - int ventity; - ast_function *vfunc; - ast_value *vfield; - } constval; + basic_value_t constval; + /* for TYPE_ARRAY we have an optional vector + * of constants when an initializer list + * was provided. + */ + basic_value_t *initlist; /* usecount for the parser */ size_t uses; diff --git a/parser.c b/parser.c index 7fba786..a09a54a 100644 --- a/parser.c +++ b/parser.c @@ -5623,7 +5623,7 @@ skipvar: } } - if (parser->tok != '{') { + if (parser->tok != '{' || var->expression.vtype != TYPE_FUNCTION) { if (parser->tok != '=') { parseerror(parser, "missing semicolon or initializer, got: `%s`", parser_tokval(parser)); break; @@ -5725,7 +5725,22 @@ skipvar: break; } } - else if (parser->tok == '{' || parser->tok == '[') + else if (var->expression.vtype == TYPE_ARRAY && parser->tok == '{') + { + if (localblock) { + /* Note that fteqcc and most others don't even *have* + * local arrays, so this is not a high priority. + */ + parseerror(parser, "TODO: initializers for local arrays"); + break; + } + /* +static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma, bool truthvalue, bool with_labels); +*/ + parseerror(parser, "TODO: initializing global arrays is not supported yet!"); + break; + } + else if (var->expression.vtype == TYPE_FUNCTION && (parser->tok == '{' || parser->tok == '[')) { if (localblock) { parseerror(parser, "cannot declare functions within functions");