/* 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;
size_t translated;
ht ht_imm_string;
+ ht ht_imm_string_dotranslate;
/* must be deleted first, they reference immediates and values */
ast_value **accessors;
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))
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;
}
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) {
{
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;
* 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
* 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
)
);
expr->refs = AST_REF_NONE;
-
+
out = (ast_expression*)
ast_binary_new(
ctx,
}
}
}
-
+
break;
case opid2('<','<'):
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;
}
}
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;
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 {
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());
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);
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);