X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=parser.c;h=ea4930f02b79f8d0d4b4f52e4a6e9fdee7d1b94c;hp=14f78035004e07c9689ec6e8b54fab451be5342c;hb=c8c25ef6f7b6182c7fb45032fdc12493f12d9670;hpb=125d039e3d2ee0779a1329f8767a0993e294a45f diff --git a/parser.c b/parser.c index 14f7803..ea4930f 100644 --- a/parser.c +++ b/parser.c @@ -31,8 +31,8 @@ /* beginning of locals */ #define PARSER_HT_LOCALS 2 -#define PARSER_HT_SIZE 128 -#define TYPEDEF_HT_SIZE 16 +#define PARSER_HT_SIZE 512 +#define TYPEDEF_HT_SIZE 512 typedef struct parser_s { lex_file *lex; @@ -49,6 +49,7 @@ typedef struct parser_s { size_t translated; ht ht_imm_string; + ht ht_imm_string_dotranslate; /* must be deleted first, they reference immediates and values */ ast_value **accessors; @@ -257,17 +258,15 @@ static char *parser_strdup(const char *str) static ast_value* parser_const_string(parser_t *parser, const char *str, bool dotranslate) { - size_t hash = util_hthash(parser->ht_imm_string, str); + ht ht_string = (dotranslate) + ? parser->ht_imm_string_dotranslate + : parser->ht_imm_string; + ast_value *out; - if ( (out = (ast_value*)util_htgeth(parser->ht_imm_string, str, hash)) ) { - if (dotranslate && out->name[0] == '#') { - char name[32]; - util_snprintf(name, sizeof(name), "dotranslate_%lu", (unsigned long)(parser->translated++)); - ast_value_set_name(out, name); - out->expression.flags |= AST_FLAG_INCLUDE_DEF; - } + size_t hash = util_hthash(ht_string, str); + + if ((out = (ast_value*)util_htgeth(ht_string, str, hash))) return out; - } /* for (i = 0; i < vec_size(parser->imm_string); ++i) { if (!strcmp(parser->imm_string[i]->constval.vstring, str)) @@ -281,12 +280,14 @@ static ast_value* parser_const_string(parser_t *parser, const char *str, bool do out->expression.flags |= AST_FLAG_INCLUDE_DEF; } else out = ast_value_new(parser_ctx(parser), "#IMMEDIATE", TYPE_STRING); + out->cvq = CV_CONST; out->hasvalue = true; out->isimm = true; out->constval.vstring = parser_strdup(str); vec_push(parser->imm_string, out); - util_htseth(parser->ht_imm_string, str, hash, out); + util_htseth(ht_string, str, hash, out); + return out; } @@ -949,7 +950,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) if (exprs[1]->vtype != TYPE_FLOAT) { ast_type_to_string(exprs[0], ty1, sizeof(ty1)); ast_type_to_string(exprs[1], ty2, sizeof(ty2)); - compile_error(ctx, "invalid types used in expression: cannot divide tyeps %s and %s", ty1, ty2); + compile_error(ctx, "invalid types used in expression: cannot divide types %s and %s", ty1, ty2); return false; } if (exprs[0]->vtype == TYPE_FLOAT) { @@ -980,7 +981,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) { ast_type_to_string(exprs[0], ty1, sizeof(ty1)); ast_type_to_string(exprs[1], ty2, sizeof(ty2)); - compile_error(ctx, "invalid types used in expression: cannot divide tyeps %s and %s", ty1, ty2); + compile_error(ctx, "invalid types used in expression: cannot divide types %s and %s", ty1, ty2); return false; } break; @@ -1041,20 +1042,20 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) * Further more, the only time it is legal to do XOR otherwise * is when both operand are floats. This nicely crafted if * statement catches them all. - * + * * In the event that the first operand is a vector, two * possible situations can arise, thus, each element of * vector A (operand A) is exclusive-ORed with the corresponding * element of vector B (operand B), If B is scalar, the * scalar value is first replicated for each element. - * + * * The QCVM itself lacks a BITXOR instruction. Thus emulating * the mathematics of it is required. The following equation * is used: (LHS | RHS) & ~(LHS & RHS). However, due to the * QCVM also lacking a BITNEG instruction, we need to emulate * ~FOO with -1 - FOO, the whole process becoming this nicely * crafted expression: (LHS | RHS) & (-1 - (LHS & RHS)). - * + * * When A is not scalar, this process is repeated for all * components of vector A with the value in operand B, * only if operand B is scalar. When A is not scalar, and B @@ -1062,7 +1063,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) * components of the vector A with the components of vector B. * Finally when A is scalar and B is scalar, this process is * simply used once for A and B being LHS and RHS respectfully. - * + * * Yes the semantics are a bit strange (no pun intended). * But then again BITXOR is strange itself, consdering it's * commutative, assocative, and elements of the BITXOR operation @@ -1098,7 +1099,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) ) ); expr->refs = AST_REF_NONE; - + out = (ast_expression*) ast_binary_new( ctx, @@ -1151,7 +1152,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) } } } - + break; case opid2('<','<'): @@ -2056,7 +2057,7 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels) correct = correct_str(&corr, parser->correct_variables[i], parser_tokval(parser)); if (strcmp(correct, parser_tokval(parser))) { break; - } else if (correct) { + } else { mem_d(correct); correct = NULL; } @@ -2514,7 +2515,8 @@ static ast_expression* process_condition(parser_t *parser, ast_expression *cond, } unary = (ast_unary*)cond; - while (ast_istype(cond, ast_unary) && unary->op == INSTR_NOT_F) + /* ast_istype dereferences cond, should test here for safety */ + while (cond && ast_istype(cond, ast_unary) && unary->op == INSTR_NOT_F) { cond = unary->operand; unary->operand = NULL; @@ -2754,7 +2756,12 @@ static bool parse_dowhile(parser_t *parser, ast_block *block, ast_expression **o if (vec_last(parser->breaks) != label || vec_last(parser->continues) != label) { parseerror(parser, "internal error: label stack corrupted"); rv = false; - ast_delete(*out); + /* + * Test for NULL otherwise ast_delete dereferences null pointer + * and boom. + */ + if (*out) + ast_delete(*out); *out = NULL; } else { @@ -3622,7 +3629,8 @@ static bool parse_goto(parser_t *parser, ast_expression **out) if (!(expression = parse_expression(parser, false, true)) || !(*out = parse_goto_computed(parser, &expression))) { parseerror(parser, "invalid goto expression"); - ast_unref(expression); + if(expression) + ast_unref(expression); return false; } @@ -6298,6 +6306,7 @@ parser_t *parser_create() parser->aliases = util_htnew(PARSER_HT_SIZE); parser->ht_imm_string = util_htnew(512); + parser->ht_imm_string_dotranslate = util_htnew(512); /* corrector */ vec_push(parser->correct_variables, correct_trie_new()); @@ -6415,6 +6424,7 @@ static void parser_remove_ast(parser_t *parser) vec_free(parser->functions); vec_free(parser->imm_vector); vec_free(parser->imm_string); + util_htdel(parser->ht_imm_string_dotranslate); util_htdel(parser->ht_imm_string); vec_free(parser->imm_float); vec_free(parser->globals); @@ -6453,7 +6463,7 @@ static void parser_remove_ast(parser_t *parser) ast_value_delete(parser->const_vec[0]); ast_value_delete(parser->const_vec[1]); ast_value_delete(parser->const_vec[2]); - + if (parser->reserved_version) ast_value_delete(parser->reserved_version);