+ if (!localblock) {
+ /* Deal with end_sys_ vars */
+ was_end = false;
+ if (!strcmp(var->name, "end_sys_globals")) {
+ parser->crc_globals = parser->globals_count;
+ was_end = true;
+ }
+ else if (!strcmp(var->name, "end_sys_fields")) {
+ parser->crc_fields = parser->fields_count;
+ was_end = true;
+ }
+ if (was_end && var->expression.vtype == TYPE_FIELD) {
+ if (parsewarning(parser, WARN_END_SYS_FIELDS,
+ "global '%s' hint should not be a field",
+ parser_tokval(parser)))
+ {
+ retval = false;
+ goto cleanup;
+ }
+ }
+
+ if (!nofields && var->expression.vtype == TYPE_FIELD)
+ {
+ /* deal with field declarations */
+ old = parser_find_field(parser, var->name);
+ if (old) {
+ if (parsewarning(parser, WARN_FIELD_REDECLARED, "field `%s` already declared here: %s:%i",
+ var->name, ast_ctx(old).file, (int)ast_ctx(old).line))
+ {
+ retval = false;
+ goto cleanup;
+ }
+ ast_delete(var);
+ var = NULL;
+ goto skipvar;
+ /*
+ parseerror(parser, "field `%s` already declared here: %s:%i",
+ var->name, ast_ctx(old).file, ast_ctx(old).line);
+ retval = false;
+ goto cleanup;
+ */
+ }
+ if (opts_standard == COMPILER_QCC &&
+ (old = parser_find_global(parser, var->name)))
+ {
+ parseerror(parser, "cannot declare a field and a global of the same name with -std=qcc");
+ parseerror(parser, "field `%s` already declared here: %s:%i",
+ var->name, ast_ctx(old).file, ast_ctx(old).line);
+ retval = false;
+ goto cleanup;
+ }
+ }
+ else
+ {
+ /* deal with other globals */
+ old = parser_find_global(parser, var->name);
+ if (old && var->expression.vtype == TYPE_FUNCTION && old->expression.vtype == TYPE_FUNCTION)
+ {
+ /* This is a function which had a prototype */
+ if (!ast_istype(old, ast_value)) {
+ parseerror(parser, "internal error: prototype is not an ast_value");
+ retval = false;
+ goto cleanup;
+ }
+ proto = (ast_value*)old;
+ if (!ast_compare_type((ast_expression*)proto, (ast_expression*)var)) {
+ parseerror(parser, "conflicting types for `%s`, previous declaration was here: %s:%i",
+ proto->name,
+ ast_ctx(proto).file, ast_ctx(proto).line);
+ retval = false;
+ goto cleanup;
+ }
+ /* we need the new parameter-names */
+ for (i = 0; i < proto->expression.params_count; ++i)
+ ast_value_set_name(proto->expression.params[i], var->expression.params[i]->name);
+ ast_delete(var);
+ var = proto;
+ }
+ else
+ {
+ /* other globals */
+ if (old) {
+ parseerror(parser, "global `%s` already declared here: %s:%i",
+ var->name, ast_ctx(old).file, ast_ctx(old).line);
+ retval = false;
+ goto cleanup;
+ }
+ if (opts_standard == COMPILER_QCC &&
+ (old = parser_find_field(parser, var->name)))
+ {
+ parseerror(parser, "cannot declare a field and a global of the same name with -std=qcc");
+ parseerror(parser, "global `%s` already declared here: %s:%i",
+ var->name, ast_ctx(old).file, ast_ctx(old).line);
+ retval = false;
+ goto cleanup;
+ }
+ }
+ }
+ }
+ else /* it's not a global */
+ {
+ old = parser_find_local(parser, var->name, parser->blocklocal, &isparam);
+ if (old && !isparam) {
+ parseerror(parser, "local `%s` already declared here: %s:%i",
+ var->name, ast_ctx(old).file, (int)ast_ctx(old).line);
+ retval = false;
+ goto cleanup;
+ }
+ old = parser_find_local(parser, var->name, 0, &isparam);
+ if (old && isparam) {
+ if (parsewarning(parser, WARN_LOCAL_SHADOWS,
+ "local `%s` is shadowing a parameter", var->name))
+ {
+ parseerror(parser, "local `%s` already declared here: %s:%i",
+ var->name, ast_ctx(old).file, (int)ast_ctx(old).line);
+ retval = false;
+ goto cleanup;
+ }
+ if (opts_standard != COMPILER_GMQCC) {
+ ast_delete(var);
+ var = NULL;
+ goto skipvar;
+ }
+ }
+ }
+
+ /* Part 2:
+ * Create the global/local, and deal with vector types.
+ */
+ if (!proto) {
+ if (var->expression.vtype == TYPE_VECTOR)
+ isvector = true;
+ else if (var->expression.vtype == TYPE_FIELD &&
+ var->expression.next->expression.vtype == TYPE_VECTOR)
+ isvector = true;
+
+ if (isvector) {
+ if (!create_vector_members(parser, var, ve)) {
+ retval = false;
+ goto cleanup;
+ }
+ }
+
+ varent.name = util_strdup(var->name);
+ varent.var = (ast_expression*)var;
+
+ if (!localblock) {
+ /* deal with global variables, fields, functions */
+ if (!nofields && var->expression.vtype == TYPE_FIELD) {
+ if (!(retval = parser_t_fields_add(parser, varent)))
+ goto cleanup;
+ if (isvector) {
+ for (i = 0; i < 3; ++i) {
+ if (!(retval = parser_t_fields_add(parser, ve[i])))
+ break;
+ }
+ if (!retval) {
+ parser->fields_count -= i+1;
+ goto cleanup;
+ }
+ }
+ }
+ else {
+ if (!(retval = parser_t_globals_add(parser, varent)))
+ goto cleanup;
+ if (isvector) {
+ for (i = 0; i < 3; ++i) {
+ if (!(retval = parser_t_globals_add(parser, ve[i])))
+ break;
+ }
+ if (!retval) {
+ parser->globals_count -= i+1;
+ goto cleanup;
+ }
+ }
+ }
+ } else {
+ if (!(retval = parser_t_locals_add(parser, varent)))
+ goto cleanup;
+ if (!(retval = ast_block_locals_add(localblock, var))) {
+ parser->locals_count--;
+ goto cleanup;
+ }
+ if (isvector) {
+ for (i = 0; i < 3; ++i) {
+ if (!(retval = parser_t_locals_add(parser, ve[i])))
+ break;
+ if (!(retval = ast_block_collect(localblock, ve[i].var)))
+ break;
+ ve[i].var = NULL; /* from here it's being collected in the block */
+ }
+ if (!retval) {
+ parser->locals_count -= i+1;
+ localblock->locals_count--;
+ goto cleanup;
+ }
+ }
+ }
+
+ varent.name = NULL;
+ ve[0].name = ve[1].name = ve[2].name = NULL;
+ ve[0].var = ve[1].var = ve[2].var = NULL;
+ cleanvar = false;
+ }
+ /* Part 2.2
+ * deal with arrays
+ */
+ if (var->expression.vtype == TYPE_ARRAY) {
+ char name[1024];
+ snprintf(name, sizeof(name), "%s::SET", var->name);
+ if (!parser_create_array_setter(parser, var, name))
+ goto cleanup;
+ snprintf(name, sizeof(name), "%s::GET", var->name);
+ if (!parser_create_array_getter(parser, var, name))
+ goto cleanup;
+ }
+
+skipvar:
+ if (parser->tok == ';') {
+ ast_delete(basetype);
+ if (!parser_next(parser)) {
+ parseerror(parser, "error after variable declaration");
+ return false;
+ }
+ return true;
+ }
+
+ if (parser->tok == ',')
+ goto another;
+
+ if (!var || (!localblock && !nofields && basetype->expression.vtype == TYPE_FIELD)) {
+ parseerror(parser, "missing comma or semicolon while parsing variables");
+ break;
+ }
+