mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
Move the constant expression values into their own struct.
This commit is contained in:
parent
ff6e1b4d6c
commit
e08efe036b
13 changed files with 704 additions and 764 deletions
|
@ -54,17 +54,7 @@ typedef enum {
|
|||
ex_temp, ///< temporary variable (::ex_temp_t)
|
||||
|
||||
ex_nil, ///< umm, nil, null. nuff said (0 of any type)
|
||||
ex_string, ///< string constant (expr_t::e::string_val)
|
||||
ex_float, ///< float constant (expr_t::e::float_val)
|
||||
ex_vector, ///< vector constant (expr_t::e::vector_val)
|
||||
ex_entity, ///< entity constant (expr_t::e::entity_val)
|
||||
ex_field, ///< field constant
|
||||
ex_func, ///< function constant (expr_t::e::func_val)
|
||||
ex_pointer, ///< pointer constant (expr_t::e::pointer)
|
||||
ex_quaternion, ///< quaternion constant (expr_t::e::quaternion_val)
|
||||
ex_integer, ///< integer constant (expr_t::e::integer_val)
|
||||
ex_uinteger, ///< unsigned integer constant (expr_t::e::uinteger_val)
|
||||
ex_short, ///< short constant (expr_t::e::short_val)
|
||||
ex_value, ///< constant value (::ex_value_t)
|
||||
} expr_type;
|
||||
|
||||
/** Binary and unary expressions.
|
||||
|
@ -163,6 +153,22 @@ typedef struct {
|
|||
struct expr_s *step; ///< time step until the next state
|
||||
} ex_state_t;
|
||||
|
||||
typedef struct ex_value_s {
|
||||
etype_t type;
|
||||
union {
|
||||
const char *string_val; ///< string constant
|
||||
float float_val; ///< float constant
|
||||
float vector_val[3]; ///< vector constant
|
||||
int entity_val; ///< entity constant
|
||||
int func_val; ///< function constant
|
||||
ex_pointer_t pointer; ///< pointer constant
|
||||
float quaternion_val[4]; ///< quaternion constant
|
||||
int integer_val; ///< integer constant
|
||||
unsigned uinteger_val; ///< unsigned integer constant
|
||||
short short_val; ///< short constant
|
||||
} v;
|
||||
} ex_value_t;
|
||||
|
||||
#define POINTER_VAL(p) (((p).def ? (p).def->ofs : 0) + (p).val)
|
||||
|
||||
typedef struct expr_s {
|
||||
|
@ -181,23 +187,11 @@ typedef struct expr_s {
|
|||
struct def_s *def; ///< def reference expression
|
||||
struct symbol_s *symbol; ///< symbol reference expression
|
||||
ex_temp_t temp; ///< temporary variable expression
|
||||
|
||||
const char *string_val; ///< string constant
|
||||
float float_val; ///< float constant
|
||||
float vector_val[3]; ///< vector constant
|
||||
int entity_val; ///< entity constant
|
||||
int func_val; ///< function constant
|
||||
ex_pointer_t pointer; ///< pointer constant
|
||||
float quaternion_val[4]; ///< quaternion constant
|
||||
int integer_val; ///< integer constant
|
||||
unsigned uinteger_val; ///< unsigned integer constant
|
||||
short short_val; ///< short constant
|
||||
ex_value_t value; ///< constant value
|
||||
} e;
|
||||
} expr_t;
|
||||
|
||||
extern etype_t qc_types[];
|
||||
extern struct type_s *ev_types[];
|
||||
extern expr_type expr_types[];
|
||||
|
||||
/** Report a type mismatch error.
|
||||
|
||||
|
@ -368,6 +362,7 @@ expr_t *new_name_expr (const char *name);
|
|||
(expr_t::e::string_val).
|
||||
*/
|
||||
expr_t *new_string_expr (const char *string_val);
|
||||
const char *expr_string (expr_t *e);
|
||||
|
||||
/** Create a new float constant expression node.
|
||||
|
||||
|
@ -376,6 +371,7 @@ expr_t *new_string_expr (const char *string_val);
|
|||
(expr_t::e::float_val).
|
||||
*/
|
||||
expr_t *new_float_expr (float float_val);
|
||||
float expr_float (expr_t *e);
|
||||
|
||||
/** Create a new vector constant expression node.
|
||||
|
||||
|
@ -384,6 +380,7 @@ expr_t *new_float_expr (float float_val);
|
|||
(expr_t::e::vector_val).
|
||||
*/
|
||||
expr_t *new_vector_expr (const float *vector_val);
|
||||
const float *expr_vector (expr_t *e);
|
||||
|
||||
/** Create a new entity constant expression node.
|
||||
|
||||
|
@ -428,6 +425,7 @@ expr_t *new_pointer_expr (int val, struct type_s *type, struct def_s *def);
|
|||
(expr_t::e::quaternion_val).
|
||||
*/
|
||||
expr_t *new_quaternion_expr (const float *quaternion_val);
|
||||
const float *expr_quaternion (expr_t *e);
|
||||
|
||||
/** Create a new integer constant expression node.
|
||||
|
||||
|
@ -436,14 +434,7 @@ expr_t *new_quaternion_expr (const float *quaternion_val);
|
|||
(expr_t::e::integer_val).
|
||||
*/
|
||||
expr_t *new_integer_expr (int integer_val);
|
||||
|
||||
/** Create a new unsigned integer constant expression node.
|
||||
|
||||
\param uinteger_val The unsigned integer constant being represented.
|
||||
\return The new unsigned integer constant expression node
|
||||
(expr_t::e::uinteger_val).
|
||||
*/
|
||||
expr_t *new_uinteger_expr (unsigned int uinteger_val);
|
||||
int expr_integer (expr_t *e);
|
||||
|
||||
/** Create a new short constant expression node.
|
||||
|
||||
|
@ -452,6 +443,7 @@ expr_t *new_uinteger_expr (unsigned int uinteger_val);
|
|||
(expr_t::e::short_val).
|
||||
*/
|
||||
expr_t *new_short_expr (short short_val);
|
||||
short expr_short (expr_t *e);
|
||||
|
||||
/** Check of the expression refers to a constant value.
|
||||
|
||||
|
@ -481,6 +473,13 @@ int is_math (int op);
|
|||
*/
|
||||
int is_logic (int op);
|
||||
|
||||
int is_string_val (expr_t *e);
|
||||
int is_float_val (expr_t *e);
|
||||
int is_vector_val (expr_t *e);
|
||||
int is_quaternion_val (expr_t *e);
|
||||
int is_integer_val (expr_t *e);
|
||||
int is_short_val (expr_t *e);
|
||||
|
||||
/** Convert a constant def to a constant expression.
|
||||
|
||||
\param var The def to convert.
|
||||
|
@ -572,12 +571,8 @@ expr_t *append_expr (expr_t *block, expr_t *e);
|
|||
void print_expr (expr_t *e);
|
||||
|
||||
void convert_int (expr_t *e);
|
||||
void convert_uint (expr_t *e);
|
||||
void convert_short (expr_t *e);
|
||||
void convert_uint_int (expr_t *e);
|
||||
void convert_int_uint (expr_t *e);
|
||||
void convert_short_int (expr_t *e);
|
||||
void convert_short_uint (expr_t *e);
|
||||
void convert_nil (expr_t *e, struct type_s *t);
|
||||
|
||||
expr_t *test_expr (expr_t *e, int test);
|
||||
|
|
|
@ -552,8 +552,8 @@ class_message_response (class_t *class, int class_msg, expr_t *sel)
|
|||
class_t *c = class;
|
||||
category_t *cat;
|
||||
|
||||
if (sel->type != ex_pointer
|
||||
&& sel->e.pointer.type != type_SEL.t.fldptr.type) {
|
||||
if (sel->type != ex_value && sel->e.value.type != ev_pointer
|
||||
&& sel->e.value.v.pointer.type != type_SEL.t.fldptr.type) {
|
||||
error (sel, "not a selector");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -94,8 +94,12 @@ do_op_string (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
|||
if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2))
|
||||
return e;
|
||||
|
||||
s1 = e1->e.string_val ? e1->e.string_val : "";
|
||||
s2 = e2->e.string_val ? e2->e.string_val : "";
|
||||
s1 = expr_string (e1);
|
||||
s2 = expr_string (e2);
|
||||
if (!s1)
|
||||
s1 = "";
|
||||
if (!s2)
|
||||
s2 = "";
|
||||
|
||||
switch (op) {
|
||||
case '+':
|
||||
|
@ -104,36 +108,32 @@ do_op_string (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
|||
dstring_clearstr (temp_str);
|
||||
dstring_appendstr (temp_str, s1);
|
||||
dstring_appendstr (temp_str, s2);
|
||||
e1->e.string_val = save_string (temp_str->str);
|
||||
e = new_string_expr (save_string (temp_str->str));
|
||||
break;
|
||||
case LT:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = strcmp (s1, s2) < 0;
|
||||
e = new_integer_expr (strcmp (s1, s2) < 0);
|
||||
break;
|
||||
case GT:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = strcmp (s1, s2) > 0;
|
||||
e = new_integer_expr (strcmp (s1, s2) > 0);
|
||||
break;
|
||||
case LE:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = strcmp (s1, s2) <= 0;
|
||||
e = new_integer_expr (strcmp (s1, s2) <= 0);
|
||||
break;
|
||||
case GE:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = strcmp (s1, s2) >= 0;
|
||||
e = new_integer_expr (strcmp (s1, s2) >= 0);
|
||||
break;
|
||||
case EQ:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = strcmp (s1, s2) == 0;
|
||||
e = new_integer_expr (strcmp (s1, s2) == 0);
|
||||
break;
|
||||
case NE:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = strcmp (s1, s2) != 0;
|
||||
e = new_integer_expr (strcmp (s1, s2));
|
||||
break;
|
||||
default:
|
||||
internal_error (e1, 0);
|
||||
}
|
||||
return e1;
|
||||
e->file = e1->file;
|
||||
e->line = e1->line;
|
||||
return e;
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
|
@ -143,15 +143,18 @@ convert_to_float (expr_t *e)
|
|||
return e;
|
||||
|
||||
switch (e->type) {
|
||||
case ex_integer:
|
||||
convert_int (e);
|
||||
return e;
|
||||
case ex_uinteger:
|
||||
convert_uint (e);
|
||||
return e;
|
||||
case ex_short:
|
||||
convert_short (e);
|
||||
return e;
|
||||
case ex_value:
|
||||
switch (e->e.value.type) {
|
||||
case ev_integer:
|
||||
convert_int (e);
|
||||
return e;
|
||||
case ev_short:
|
||||
convert_short (e);
|
||||
return e;
|
||||
default:
|
||||
internal_error (e, 0);
|
||||
}
|
||||
break;
|
||||
case ex_def:
|
||||
case ex_expr:
|
||||
case ex_uexpr:
|
||||
|
@ -209,108 +212,103 @@ do_op_float (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
|||
}
|
||||
e->e.expr.type = type;
|
||||
|
||||
if (op == '*' && is_constant (e1) && e1->e.float_val == 1)
|
||||
if (op == '*' && is_constant (e1) && expr_float (e1) == 1)
|
||||
return e2;
|
||||
if (op == '*' && is_constant (e2) && e2->e.float_val == 1)
|
||||
if (op == '*' && is_constant (e2) && expr_float (e2) == 1)
|
||||
return e1;
|
||||
if (op == '*' && is_constant (e1) && e1->e.float_val == 0)
|
||||
if (op == '*' && is_constant (e1) && expr_float (e1) == 0)
|
||||
return e1;
|
||||
if (op == '*' && is_constant (e2) && e2->e.float_val == 0)
|
||||
if (op == '*' && is_constant (e2) && expr_float (e2) == 0)
|
||||
return e2;
|
||||
if (op == '/' && is_constant (e2) && e2->e.float_val == 1)
|
||||
if (op == '/' && is_constant (e2) && expr_float (e2) == 1)
|
||||
return e1;
|
||||
if (op == '/' && is_constant (e2) && e2->e.float_val == 0)
|
||||
if (op == '/' && is_constant (e2) && expr_float (e2) == 0)
|
||||
return error (e, "division by zero");
|
||||
if (op == '/' && is_constant (e1) && e1->e.float_val == 0)
|
||||
if (op == '/' && is_constant (e1) && expr_float (e1) == 0)
|
||||
return e1;
|
||||
if (op == '+' && is_constant (e1) && e1->e.float_val == 0)
|
||||
if (op == '+' && is_constant (e1) && expr_float (e1) == 0)
|
||||
return e2;
|
||||
if (op == '+' && is_constant (e2) && e2->e.float_val == 0)
|
||||
if (op == '+' && is_constant (e2) && expr_float (e2) == 0)
|
||||
return e1;
|
||||
if (op == '-' && is_constant (e2) && e2->e.float_val == 0)
|
||||
if (op == '-' && is_constant (e2) && expr_float (e2) == 0)
|
||||
return e1;
|
||||
|
||||
if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2))
|
||||
return e;
|
||||
|
||||
f1 = e1->e.float_val;
|
||||
f2 = e2->e.float_val;
|
||||
f1 = expr_float (e1);
|
||||
f2 = expr_float (e2);
|
||||
|
||||
switch (op) {
|
||||
case '+':
|
||||
e1->e.float_val += f2;
|
||||
e = new_float_expr (f1 + f2);
|
||||
break;
|
||||
case '-':
|
||||
e1->e.float_val -= f2;
|
||||
e = new_float_expr (f1 - f2);
|
||||
break;
|
||||
case '*':
|
||||
e1->e.float_val *= f2;
|
||||
e = new_float_expr (f1 * f2);
|
||||
break;
|
||||
case '/':
|
||||
if (!f2)
|
||||
return error (e1, "divide by zero");
|
||||
e1->e.float_val /= f2;
|
||||
e = new_float_expr (f1 / f2);
|
||||
break;
|
||||
case '&':
|
||||
e1->e.float_val = (int) f1 & (int) f2;
|
||||
e = new_float_expr ((int)f1 & (int)f2);
|
||||
break;
|
||||
case '|':
|
||||
e1->e.float_val = (int) f1 | (int) f2;
|
||||
e = new_float_expr ((int)f1 | (int)f2);
|
||||
break;
|
||||
case '^':
|
||||
e1->e.float_val = (int) f1 ^ (int) f2;
|
||||
e = new_float_expr ((int)f1 ^ (int)f2);
|
||||
break;
|
||||
case '%':
|
||||
e1->e.float_val = (int) f1 % (int) f2;
|
||||
e = new_float_expr ((int)f1 % (int)f2);
|
||||
break;
|
||||
case SHL:
|
||||
e1->e.float_val = (int) f1 << (int) f2;
|
||||
e = new_float_expr ((int)f1 << (int)f2);
|
||||
break;
|
||||
case SHR:
|
||||
e1->e.float_val = (int) f1 >> (int) f2;
|
||||
e = new_float_expr ((int)f1 >> (int)f2);
|
||||
break;
|
||||
case AND:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = f1 && f2;
|
||||
e = new_integer_expr (f1 && f2);
|
||||
break;
|
||||
case OR:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = f1 || f2;
|
||||
e = new_integer_expr (f1 || f2);
|
||||
break;
|
||||
case LT:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = f1 < f2;
|
||||
e = new_integer_expr (f1 < f2);
|
||||
break;
|
||||
case GT:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = f1 > f2;
|
||||
e = new_integer_expr (f1 > f2);
|
||||
break;
|
||||
case LE:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = f1 <= f2;
|
||||
e = new_integer_expr (f1 <= f2);
|
||||
break;
|
||||
case GE:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = f1 >= f2;
|
||||
e = new_integer_expr (f1 >= f2);
|
||||
break;
|
||||
case EQ:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = f1 == f2;
|
||||
e = new_integer_expr (f1 == f2);
|
||||
break;
|
||||
case NE:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = f1 != f2;
|
||||
e = new_integer_expr (f1 != f2);
|
||||
break;
|
||||
default:
|
||||
internal_error (e1, 0);
|
||||
}
|
||||
return e1;
|
||||
e->file = e1->file;
|
||||
e->line = e1->line;
|
||||
return e;
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
||||
{
|
||||
float *v1, *v2;
|
||||
const float *v1, *v2;
|
||||
vec3_t v;
|
||||
static int valid[] = {'=', 'b', '+', '-', '*', EQ, NE, 0};
|
||||
expr_t *t;
|
||||
|
||||
|
@ -342,69 +340,69 @@ do_op_vector (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
|||
e->e.expr.type = &type_vector;
|
||||
}
|
||||
|
||||
if (op == '*' && is_constant (e1) && e1->type == ex_float
|
||||
&& e1->e.float_val == 1)
|
||||
return e2;
|
||||
if (op == '*' && is_constant (e2) && e2->type == ex_float
|
||||
&& e2->e.float_val == 1)
|
||||
if (op == '*' && is_float_val (e2) && expr_float (e2) == 1)
|
||||
return e1;
|
||||
if (op == '*' && is_constant (e1) && e1->type == ex_float
|
||||
&& e1->e.float_val == 0)
|
||||
if (op == '*' && is_float_val (e2) && expr_float (e2) == 0)
|
||||
return new_vector_expr (vec3_origin);
|
||||
if (op == '*' && is_constant (e2) && e2->type == ex_float
|
||||
&& e2->e.float_val == 0)
|
||||
return new_vector_expr (vec3_origin);
|
||||
if (op == '/' && is_constant (e2) && e2->type == ex_float
|
||||
&& e2->e.float_val == 1)
|
||||
if (op == '/' && is_float_val (e2) && expr_float (e2) == 1)
|
||||
return e1;
|
||||
if (op == '/' && is_constant (e2) && e2->type == ex_float
|
||||
&& e2->e.float_val == 0)
|
||||
if (op == '/' && is_float_val (e2) && expr_float (e2) == 0)
|
||||
return error (e, "division by zero");
|
||||
if (op == '+' && is_constant (e1) && VectorIsZero (e1->e.vector_val))
|
||||
if (op == '+' && is_constant (e1) && VectorIsZero (expr_vector (e1)))
|
||||
return e2;
|
||||
if (op == '+' && is_constant (e2) && VectorIsZero (e2->e.vector_val))
|
||||
if (op == '+' && is_constant (e2) && VectorIsZero (expr_vector (e2)))
|
||||
return e1;
|
||||
if (op == '-' && is_constant (e2) && VectorIsZero (e2->e.vector_val))
|
||||
if (op == '-' && is_constant (e1) && VectorIsZero (expr_vector (e1))) {
|
||||
vec3_t v;
|
||||
VectorNegate (expr_vector (e2), v);
|
||||
e = new_vector_expr (v);
|
||||
e->file = e2->file;
|
||||
e->line = e2->line;
|
||||
return e;
|
||||
}
|
||||
if (op == '-' && is_constant (e2) && VectorIsZero (expr_vector (e2)))
|
||||
return e1;
|
||||
|
||||
if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2))
|
||||
return e;
|
||||
|
||||
v1 = e1->e.vector_val;
|
||||
v2 = e2->e.vector_val;
|
||||
v1 = expr_vector (e1);
|
||||
v2 = expr_vector (e2);
|
||||
|
||||
switch (op) {
|
||||
case '+':
|
||||
VectorAdd (v1, v2, v1);
|
||||
VectorAdd (v1, v2, v);
|
||||
e = new_vector_expr (v);
|
||||
break;
|
||||
case '-':
|
||||
VectorSubtract (v1, v2, v1);
|
||||
VectorSubtract (v1, v2, v);
|
||||
e = new_vector_expr (v);
|
||||
break;
|
||||
case '/':
|
||||
if (!v2[0])
|
||||
return error (e1, "divide by zero");
|
||||
VectorScale (v1, 1 / v2[0], v1);
|
||||
VectorScale (v1, 1 / v2[0], v);
|
||||
break;
|
||||
case '*':
|
||||
if (get_type (e2) == &type_vector) {
|
||||
e1->type = ex_float;
|
||||
e1->e.float_val = DotProduct (v1, v2);
|
||||
e = new_float_expr (DotProduct (v1, v2));
|
||||
} else {
|
||||
VectorScale (v1, v2[0], v1);
|
||||
VectorScale (v1, v2[0], v);
|
||||
e = new_vector_expr (v);
|
||||
}
|
||||
break;
|
||||
case EQ:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = VectorCompare (v1, v2);
|
||||
e = new_integer_expr (VectorCompare (v1, v2));
|
||||
break;
|
||||
case NE:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = !VectorCompare (v1, v2);
|
||||
e = new_integer_expr (!VectorCompare (v1, v2));
|
||||
break;
|
||||
default:
|
||||
internal_error (e1, 0);
|
||||
}
|
||||
return e1;
|
||||
e->file = e1->file;
|
||||
e->line = e1->line;
|
||||
return e;
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
|
@ -498,18 +496,21 @@ do_op_pointer (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
|||
static expr_t *
|
||||
do_op_quaternion (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
||||
{
|
||||
float *q1, *q2;
|
||||
const float *q1, *q2;
|
||||
quat_t q;
|
||||
static int valid[] = {'=', 'b', '+', '-', '*', EQ, NE, 0};
|
||||
expr_t *t;
|
||||
|
||||
if (get_type (e1) != &type_quaternion) {
|
||||
|
||||
if (op != '*')
|
||||
if (op != '*' || op != '/')
|
||||
return error (e1, "invalid operand for quaternion");
|
||||
|
||||
t = e1;
|
||||
e->e.expr.e1 = e1 = e2;
|
||||
e2 = t;
|
||||
if (op == '*') {
|
||||
t = e1;
|
||||
e->e.expr.e1 = e1 = e2;
|
||||
e2 = t;
|
||||
}
|
||||
}
|
||||
if (get_type (e2) != &type_quaternion) {
|
||||
e->e.expr.e2 = e2 = convert_to_float (e2);
|
||||
|
@ -528,70 +529,65 @@ do_op_quaternion (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
|||
e->e.expr.type = &type_quaternion;
|
||||
}
|
||||
|
||||
if (op == '*' && is_constant (e1) && e1->type == ex_float
|
||||
&& e1->e.float_val == 1)
|
||||
return e2;
|
||||
if (op == '*' && is_constant (e2) && e2->type == ex_float
|
||||
&& e2->e.float_val == 1)
|
||||
if (op == '*' && is_float_val (e2) && expr_float (e2) == 1)
|
||||
return e1;
|
||||
if (op == '*' && is_constant (e1) && e1->type == ex_float
|
||||
&& e1->e.float_val == 0)
|
||||
if (op == '*' && is_float_val (e2) && expr_float (e2) == 0)
|
||||
return new_quaternion_expr (quat_origin);
|
||||
if (op == '*' && is_constant (e2) && e2->type == ex_float
|
||||
&& e2->e.float_val == 0)
|
||||
return new_quaternion_expr (quat_origin);
|
||||
if (op == '/' && is_constant (e2) && e2->type == ex_float
|
||||
&& e2->e.float_val == 1)
|
||||
if (op == '/' && is_float_val (e2) && expr_float (e2) == 1)
|
||||
return e1;
|
||||
if (op == '/' && is_constant (e2) && e2->type == ex_float
|
||||
&& e2->e.float_val == 0)
|
||||
if (op == '/' && is_float_val (e2) && expr_float (e2) == 0)
|
||||
return error (e, "division by zero");
|
||||
if (op == '+' && is_constant (e1) && QuatIsZero (e1->e.quaternion_val))
|
||||
if (op == '+' && is_constant (e1) && QuatIsZero (expr_quaternion (e1)))
|
||||
return e2;
|
||||
if (op == '+' && is_constant (e2) && QuatIsZero (e2->e.quaternion_val))
|
||||
if (op == '+' && is_constant (e2) && QuatIsZero (expr_quaternion (e2)))
|
||||
return e1;
|
||||
if (op == '-' && is_constant (e2) && QuatIsZero (e2->e.quaternion_val))
|
||||
if (op == '-' && is_constant (e2) && QuatIsZero (expr_quaternion (e2)))
|
||||
return e1;
|
||||
|
||||
if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2))
|
||||
return e;
|
||||
|
||||
q1 = e1->e.quaternion_val;
|
||||
q2 = e2->e.quaternion_val;
|
||||
q1 = expr_quaternion (e1);
|
||||
q2 = expr_quaternion (e2);
|
||||
|
||||
switch (op) {
|
||||
case '+':
|
||||
QuatAdd (q1, q2, q1);
|
||||
QuatAdd (q1, q2, q);
|
||||
e = new_quaternion_expr (q);
|
||||
break;
|
||||
case '-':
|
||||
QuatSubtract (q1, q2, q1);
|
||||
QuatSubtract (q1, q2, q);
|
||||
e = new_quaternion_expr (q);
|
||||
break;
|
||||
case '/':
|
||||
if (!q2[0])
|
||||
return error (e1, "divide by zero");
|
||||
QuatScale (q1, 1 / q2[0], q1);
|
||||
q1[3] /= q2[0];
|
||||
if (is_float_val (e2)) {
|
||||
QuatScale (q1, 1 / expr_float (e2), q);
|
||||
} else {
|
||||
QuatInverse (q2, q);
|
||||
QuatScale (q2, expr_float (e1), q);
|
||||
}
|
||||
e = new_quaternion_expr (q);
|
||||
break;
|
||||
case '*':
|
||||
if (get_type (e2) == &type_quaternion) {
|
||||
QuatMult (q1, q2, q1);
|
||||
QuatMult (q1, q2, q);
|
||||
} else {
|
||||
QuatScale (q1, q2[0], q1);
|
||||
q1[3] *= q2[0];
|
||||
QuatScale (q1, q2[0], q);
|
||||
}
|
||||
e = new_quaternion_expr (q);
|
||||
break;
|
||||
case EQ:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = QuatCompare (q1, q2);
|
||||
e = new_integer_expr (QuatCompare (q1, q2));
|
||||
break;
|
||||
case NE:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = !QuatCompare (q1, q2);
|
||||
e = new_integer_expr (!QuatCompare (q1, q2));
|
||||
break;
|
||||
default:
|
||||
internal_error (e1, 0);
|
||||
}
|
||||
return e1;
|
||||
e->file = e1->file;
|
||||
e->line = e1->line;
|
||||
return e;
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
|
@ -606,10 +602,10 @@ do_op_integer (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
|||
if (!valid_op (op, valid))
|
||||
return error (e1, "invalid operand for integer");
|
||||
|
||||
if (e1->type == ex_short)
|
||||
if (is_short_val (e1))
|
||||
convert_short_int (e1);
|
||||
|
||||
if (e2->type == ex_short)
|
||||
if (is_short_val (e2))
|
||||
convert_short_int (e2);
|
||||
|
||||
if (is_compare (op) || is_logic (op)) {
|
||||
|
@ -621,100 +617,96 @@ do_op_integer (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
|||
e->e.expr.type = &type_integer;
|
||||
}
|
||||
|
||||
if (op == '*' && is_constant (e1) && e1->e.integer_val == 1)
|
||||
if (op == '*' && is_constant (e1) && expr_integer (e1) == 1)
|
||||
return e2;
|
||||
if (op == '*' && is_constant (e2) && e2->e.integer_val == 1)
|
||||
if (op == '*' && is_constant (e2) && expr_integer (e2) == 1)
|
||||
return e1;
|
||||
if (op == '*' && is_constant (e1) && e1->e.integer_val == 0)
|
||||
if (op == '*' && is_constant (e1) && expr_integer (e1) == 0)
|
||||
return e1;
|
||||
if (op == '*' && is_constant (e2) && e2->e.integer_val == 0)
|
||||
if (op == '*' && is_constant (e2) && expr_integer (e2) == 0)
|
||||
return e2;
|
||||
if (op == '/' && is_constant (e2) && e2->e.integer_val == 1)
|
||||
if (op == '/' && is_constant (e2) && expr_integer (e2) == 1)
|
||||
return e1;
|
||||
if (op == '/' && is_constant (e2) && e2->e.integer_val == 0)
|
||||
if (op == '/' && is_constant (e2) && expr_integer (e2) == 0)
|
||||
return error (e, "division by zero");
|
||||
if (op == '/' && is_constant (e1) && e1->e.integer_val == 0)
|
||||
if (op == '/' && is_constant (e1) && expr_integer (e1) == 0)
|
||||
return e1;
|
||||
if (op == '+' && is_constant (e1) && e1->e.integer_val == 0)
|
||||
if (op == '+' && is_constant (e1) && expr_integer (e1) == 0)
|
||||
return e2;
|
||||
if (op == '+' && is_constant (e2) && e2->e.integer_val == 0)
|
||||
if (op == '+' && is_constant (e2) && expr_integer (e2) == 0)
|
||||
return e1;
|
||||
if (op == '-' && is_constant (e2) && e2->e.integer_val == 0)
|
||||
if (op == '-' && is_constant (e2) && expr_integer (e2) == 0)
|
||||
return e1;
|
||||
|
||||
if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2))
|
||||
return e;
|
||||
|
||||
i1 = e1->e.integer_val;
|
||||
i2 = e2->e.integer_val;
|
||||
i1 = expr_integer (e1);
|
||||
i2 = expr_integer (e2);
|
||||
|
||||
switch (op) {
|
||||
case '+':
|
||||
e1->e.integer_val += i2;
|
||||
e = new_integer_expr (i1 + i2);
|
||||
break;
|
||||
case '-':
|
||||
e1->e.integer_val -= i2;
|
||||
e = new_integer_expr (i1 - i2);
|
||||
break;
|
||||
case '*':
|
||||
e1->e.integer_val *= i2;
|
||||
e = new_integer_expr (i1 * i2);
|
||||
break;
|
||||
case '/':
|
||||
if (options.warnings.integer_divide)
|
||||
warning (e2, "%d / %d == %d", i1, i2, i1 / i2);
|
||||
e1->e.integer_val /= i2;
|
||||
e = new_integer_expr (i1 / i2);
|
||||
break;
|
||||
case '&':
|
||||
e1->e.integer_val = i1 & i2;
|
||||
e = new_integer_expr (i1 & i2);
|
||||
break;
|
||||
case '|':
|
||||
e1->e.integer_val = i1 | i2;
|
||||
e = new_integer_expr (i1 | i2);
|
||||
break;
|
||||
case '^':
|
||||
e1->e.integer_val = i1 ^ i2;
|
||||
e = new_integer_expr (i1 ^ i2);
|
||||
break;
|
||||
case '%':
|
||||
e1->e.integer_val = i1 % i2;
|
||||
e = new_integer_expr (i1 % i2);
|
||||
break;
|
||||
case SHL:
|
||||
e1->e.integer_val = i1 << i2;
|
||||
e = new_integer_expr (i1 << i2);
|
||||
break;
|
||||
case SHR:
|
||||
e1->e.integer_val = i1 >> i2;
|
||||
e = new_integer_expr (i1 >> i2);
|
||||
break;
|
||||
case AND:
|
||||
e1->e.integer_val = i1 && i2;
|
||||
e = new_integer_expr (i1 && i2);
|
||||
break;
|
||||
case OR:
|
||||
e1->e.integer_val = i1 || i2;
|
||||
e = new_integer_expr (i1 || i2);
|
||||
break;
|
||||
case LT:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = i1 < i2;
|
||||
e = new_integer_expr (i1 < i2);
|
||||
break;
|
||||
case GT:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = i1 > i2;
|
||||
e = new_integer_expr (i1 > i2);
|
||||
break;
|
||||
case LE:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = i1 <= i2;
|
||||
e = new_integer_expr (i1 <= i2);
|
||||
break;
|
||||
case GE:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = i1 >= i2;
|
||||
e = new_integer_expr (i1 >= i2);
|
||||
break;
|
||||
case EQ:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = i1 == i2;
|
||||
e = new_integer_expr (i1 == i2);
|
||||
break;
|
||||
case NE:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = i1 != i2;
|
||||
e = new_integer_expr (i1 != i2);
|
||||
break;
|
||||
default:
|
||||
internal_error (e1, 0);
|
||||
}
|
||||
return e1;
|
||||
e->file = e1->file;
|
||||
e->line = e1->line;
|
||||
return e;
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
|
@ -741,76 +733,72 @@ do_op_short (int op, expr_t *e, expr_t *e1, expr_t *e2)
|
|||
if (op == '=' || op == 'b' || !is_constant (e1) || !is_constant (e2))
|
||||
return e;
|
||||
|
||||
i1 = e1->e.short_val;
|
||||
i2 = e2->e.short_val;
|
||||
i1 = expr_short (e1);
|
||||
i2 = expr_short (e2);
|
||||
|
||||
switch (op) {
|
||||
case '+':
|
||||
e1->e.short_val += i2;
|
||||
e = new_short_expr (i1 + i2);
|
||||
break;
|
||||
case '-':
|
||||
e1->e.short_val -= i2;
|
||||
e = new_short_expr (i1 - i2);
|
||||
break;
|
||||
case '*':
|
||||
e1->e.short_val *= i2;
|
||||
e = new_short_expr (i1 * i2);
|
||||
break;
|
||||
case '/':
|
||||
if (options.warnings.integer_divide)
|
||||
warning (e2, "%d / %d == %d", i1, i2, i1 / i2);
|
||||
e1->e.short_val /= i2;
|
||||
e = new_short_expr (i1 / i2);
|
||||
break;
|
||||
case '&':
|
||||
e1->e.short_val = i1 & i2;
|
||||
e = new_short_expr (i1 & i2);
|
||||
break;
|
||||
case '|':
|
||||
e1->e.short_val = i1 | i2;
|
||||
e = new_short_expr (i1 | i2);
|
||||
break;
|
||||
case '^':
|
||||
e1->e.short_val = i1 ^ i2;
|
||||
e = new_short_expr (i1 ^ i2);
|
||||
break;
|
||||
case '%':
|
||||
e1->e.short_val = i1 % i2;
|
||||
e = new_short_expr (i1 % i2);
|
||||
break;
|
||||
case SHL:
|
||||
e1->e.short_val = i1 << i2;
|
||||
e = new_short_expr (i1 << i2);
|
||||
break;
|
||||
case SHR:
|
||||
e1->e.short_val = i1 >> i2;
|
||||
e = new_short_expr (i1 >> i2);
|
||||
break;
|
||||
case AND:
|
||||
e1->e.short_val = i1 && i2;
|
||||
e = new_short_expr (i1 && i2);
|
||||
break;
|
||||
case OR:
|
||||
e1->e.short_val = i1 || i2;
|
||||
e = new_short_expr (i1 || i2);
|
||||
break;
|
||||
case LT:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = i1 < i2;
|
||||
e = new_integer_expr (i1 < i2);
|
||||
break;
|
||||
case GT:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = i1 > i2;
|
||||
e = new_integer_expr (i1 > i2);
|
||||
break;
|
||||
case LE:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = i1 <= i2;
|
||||
e = new_integer_expr (i1 <= i2);
|
||||
break;
|
||||
case GE:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = i1 >= i2;
|
||||
e = new_integer_expr (i1 >= i2);
|
||||
break;
|
||||
case EQ:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = i1 == i2;
|
||||
e = new_integer_expr (i1 == i2);
|
||||
break;
|
||||
case NE:
|
||||
e1->type = ex_integer;
|
||||
e1->e.integer_val = i1 != i2;
|
||||
e = new_integer_expr (i1 != i2);
|
||||
break;
|
||||
default:
|
||||
internal_error (e1, 0);
|
||||
}
|
||||
return e1;
|
||||
e->file = e1->file;
|
||||
e->line = e1->line;
|
||||
return e;
|
||||
}
|
||||
|
||||
static expr_t *
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -543,7 +543,7 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val)
|
|||
error (bi_val, "%s redefined", sym->name);
|
||||
return 0;
|
||||
}
|
||||
if (bi_val->type != ex_integer && bi_val->type != ex_float) {
|
||||
if (!is_integer_val (bi_val) && !is_float_val (bi_val)) {
|
||||
error (bi_val, "invalid constant for = #");
|
||||
return 0;
|
||||
}
|
||||
|
@ -554,9 +554,10 @@ build_builtin_function (symbol_t *sym, expr_t *bi_val)
|
|||
sym->s.func->sym = sym;
|
||||
add_function (sym->s.func);
|
||||
|
||||
bi = bi_val->e.integer_val;
|
||||
if (bi_val->type == ex_integer)
|
||||
bi = (int)bi_val->e.float_val;
|
||||
if (is_integer_val (bi_val))
|
||||
bi = expr_integer (bi_val);
|
||||
else
|
||||
bi = expr_float (bi_val);
|
||||
sym->s.func->builtin = bi;
|
||||
//reloc_def_func (sym->s.func, def->ofs);
|
||||
build_function (sym->s.func);
|
||||
|
|
|
@ -170,53 +170,48 @@ ReuseConstant (expr_t *expr, def_t *def)
|
|||
cn = 0;
|
||||
if (e.type == ex_nil)
|
||||
convert_nil (&e, def->type);
|
||||
switch (e.type) {
|
||||
case ex_entity:
|
||||
if (!is_constant (&e))
|
||||
abort ();
|
||||
switch (extract_type (&e)) {
|
||||
case ev_entity:
|
||||
tab = entity_imm_defs;
|
||||
type = &type_entity;
|
||||
break;
|
||||
case ex_field:
|
||||
case ev_field:
|
||||
tab = field_imm_defs;
|
||||
type = &type_field;
|
||||
break;
|
||||
case ex_func:
|
||||
case ev_func:
|
||||
tab = func_imm_defs;
|
||||
type = &type_function;
|
||||
break;
|
||||
case ex_pointer:
|
||||
case ev_pointer:
|
||||
tab = pointer_imm_defs;
|
||||
type = &type_pointer;
|
||||
break;
|
||||
case ex_integer:
|
||||
case ex_uinteger:
|
||||
case ev_integer:
|
||||
if (!def || def->type != &type_float) {
|
||||
tab = integer_imm_defs;
|
||||
//FIXME
|
||||
//if (e.type == ex_uinteger)
|
||||
// type = &type_uinteger;
|
||||
//else
|
||||
type = &type_integer;
|
||||
type = &type_integer;
|
||||
break;
|
||||
}
|
||||
if (e.type == ex_uinteger)
|
||||
e.e.float_val = e.e.uinteger_val;
|
||||
else
|
||||
e.e.float_val = e.e.integer_val;
|
||||
e.type = ex_float;
|
||||
case ex_float:
|
||||
e.e.value.v.float_val = expr_integer (&e);
|
||||
e.e.value.type = ev_float;
|
||||
e.type = ex_value;
|
||||
case ev_float:
|
||||
tab = float_imm_defs;
|
||||
type = &type_float;
|
||||
break;
|
||||
case ex_string:
|
||||
e.e.integer_val = ReuseString (e.e.string_val);
|
||||
case ev_string:
|
||||
e.e.value.v.integer_val = ReuseString (expr_string (&e));
|
||||
tab = string_imm_defs;
|
||||
type = &type_string;
|
||||
break;
|
||||
case ex_vector:
|
||||
case ev_vector:
|
||||
tab = vector_imm_defs;
|
||||
type = &type_vector;
|
||||
break;
|
||||
case ex_quaternion:
|
||||
case ev_quat:
|
||||
tab = quaternion_imm_defs;
|
||||
type = &type_quaternion;
|
||||
break;
|
||||
|
@ -269,22 +264,22 @@ ReuseConstant (expr_t *expr, def_t *def)
|
|||
cn->initialized = cn->constant = 1;
|
||||
cn->nosave = 1;
|
||||
// copy the immediate to the global area
|
||||
switch (e.type) {
|
||||
case ex_string:
|
||||
switch (e.e.value.type) {
|
||||
case ev_string:
|
||||
reloc = new_reloc (cn->ofs, rel_def_string);
|
||||
break;
|
||||
case ex_func:
|
||||
if (e.e.func_val)
|
||||
case ev_func:
|
||||
if (e.e.value.v.func_val)
|
||||
reloc = new_reloc (cn->ofs, rel_def_func);
|
||||
break;
|
||||
case ex_field:
|
||||
if (e.e.pointer.def)
|
||||
reloc_def_field_ofs (e.e.pointer.def, cn->ofs);
|
||||
case ev_field:
|
||||
if (e.e.value.v.pointer.def)
|
||||
reloc_def_field_ofs (e.e.value.v.pointer.def, cn->ofs);
|
||||
break;
|
||||
case ex_pointer:
|
||||
if (e.e.pointer.def) {
|
||||
EMIT_DEF_OFS (G_INT (cn->ofs), e.e.pointer.def);
|
||||
e.e.pointer.def->users--;
|
||||
case ev_pointer:
|
||||
if (e.e.value.v.pointer.def) {
|
||||
EMIT_DEF_OFS (G_INT (cn->ofs), e.e.value.v.pointer.def);
|
||||
e.e.value.v.pointer.def->users--;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -350,7 +350,7 @@ selector_index (const char *sel_id)
|
|||
selector_t *
|
||||
get_selector (expr_t *sel)
|
||||
{
|
||||
selector_t _sel = {0, 0, sel->e.pointer.val};
|
||||
selector_t _sel = {0, 0, sel->e.value.v.pointer.val};
|
||||
_sel.index /= type_size (type_SEL.t.fldptr.type);
|
||||
return (selector_t *) Hash_FindElement (sel_index_hash, &_sel);
|
||||
}
|
||||
|
@ -534,7 +534,7 @@ method_check_params (method_t *method, expr_t *args)
|
|||
mtype->t.func.param_types[i], t);
|
||||
}
|
||||
} else {
|
||||
if (e->type == ex_integer && options.warnings.vararg_integer)
|
||||
if (is_integer_val (e) && options.warnings.vararg_integer)
|
||||
warning (e, "passing integer consant into ... function");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -124,7 +124,7 @@ STRING \"(\\.|[^"\\])*\"
|
|||
const char *c = yytext + yyleng - 1;
|
||||
int i = strtol (yytext, 0, 0);
|
||||
if (*c == 'u' || *c == 'U')
|
||||
yylval.expr = new_uinteger_expr (i);
|
||||
yylval.expr = new_integer_expr (i);//FIXME
|
||||
else
|
||||
yylval.expr = new_integer_expr (i);
|
||||
return CONST;
|
||||
|
|
|
@ -365,7 +365,7 @@ non_field_type
|
|||
| non_field_type array_decl
|
||||
{
|
||||
if ($2)
|
||||
$$ = array_type ($1, $2->e.integer_val);
|
||||
$$ = array_type ($1, $2->e.value.v.integer_val);
|
||||
else
|
||||
$$ = pointer_type ($1);
|
||||
}
|
||||
|
@ -465,7 +465,8 @@ array_decl
|
|||
: '[' fexpr ']'
|
||||
{
|
||||
$2 = constant_expr ($2);
|
||||
if ($2->type != ex_integer || $2->e.integer_val < 1) {
|
||||
if (($2->type != ex_value && $2->e.value.type != ev_integer)
|
||||
|| $2->e.value.v.integer_val < 1) {
|
||||
error (0, "invalid array size");
|
||||
$$ = 0;
|
||||
} else {
|
||||
|
|
|
@ -610,15 +610,13 @@ finish_compilation (void)
|
|||
return !errors;
|
||||
|
||||
if (options.code.progsversion != PROG_ID_VERSION) {
|
||||
e.type = ex_integer;
|
||||
e.e.integer_val = type_size (&type_param);
|
||||
e = *new_integer_expr (type_size (&type_param));
|
||||
ReuseConstant (&e, get_def (&type_integer, ".param_size", pr.scope,
|
||||
st_global));
|
||||
}
|
||||
|
||||
if (options.code.debug) {
|
||||
e.type = ex_string;
|
||||
e.e.string_val = debugfile;
|
||||
e = *new_string_expr (debugfile);
|
||||
ReuseConstant (&e, get_def (&type_string, ".debug_file", pr.scope,
|
||||
st_global));
|
||||
}
|
||||
|
|
|
@ -220,7 +220,7 @@ type
|
|||
: standard_type
|
||||
| ARRAY '[' CONST RANGE CONST ']' OF standard_type
|
||||
{
|
||||
$$ = based_array_type ($8, $3->e.integer_val, $5->e.integer_val);
|
||||
$$ = based_array_type ($8, expr_integer ($3), expr_integer ($5));
|
||||
}
|
||||
;
|
||||
|
||||
|
|
|
@ -163,12 +163,12 @@ add_enum (symbol_t *enm, symbol_t *name, expr_t *val)
|
|||
value = ((symbol_t *)(*enum_tab->symtail))->s.value + 1;
|
||||
if (val) {
|
||||
val = constant_expr (val);
|
||||
if (val->type < ex_nil)
|
||||
if (!is_constant (val))
|
||||
error (val, "non-constant initializer");
|
||||
else if (val->type != ex_integer)
|
||||
else if (!is_integer_val (val))
|
||||
error (val, "invalid initializer type");
|
||||
else
|
||||
value = val->e.integer_val;
|
||||
value = expr_integer (val);
|
||||
}
|
||||
name->s.value = value;
|
||||
symtab_addsymbol (enum_tab, name);
|
||||
|
|
|
@ -52,6 +52,7 @@ static __attribute__ ((used)) const char rcsid[] =
|
|||
#include "qfcc.h"
|
||||
#include "reloc.h"
|
||||
#include "switch.h"
|
||||
#include "symtab.h"
|
||||
#include "type.h"
|
||||
|
||||
#include "qc-parse.h"
|
||||
|
@ -64,6 +65,14 @@ typedef struct case_node_s {
|
|||
struct case_node_s *left, *right;
|
||||
} case_node_t;
|
||||
|
||||
static uintptr_t
|
||||
get_value (expr_t *e)
|
||||
{
|
||||
if (e->type == ex_symbol)
|
||||
return e->e.symbol->s.value;
|
||||
return e->e.value.v.integer_val;
|
||||
}
|
||||
|
||||
static uintptr_t
|
||||
get_hash (void *_cl, void *unused)
|
||||
{
|
||||
|
@ -71,9 +80,7 @@ get_hash (void *_cl, void *unused)
|
|||
|
||||
if (!cl->value)
|
||||
return 0;
|
||||
if (cl->value->type == ex_string)
|
||||
return (uintptr_t) cl->value->e.string_val;
|
||||
return cl->value->e.integer_val;
|
||||
return get_value (cl->value);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -83,16 +90,17 @@ compare (void *_cla, void *_clb, void *unused)
|
|||
case_label_t *clb = (case_label_t *) _clb;
|
||||
expr_t *v1 = cla->value;
|
||||
expr_t *v2 = clb->value;
|
||||
uintptr_t val1, val2;
|
||||
|
||||
if (v1 == v2)
|
||||
return 1;
|
||||
if ((v1 && !v2) || (!v1 && v2))
|
||||
return 0;
|
||||
if (v1->type != v2->type)
|
||||
if (extract_type (v1) != extract_type (v2))
|
||||
return 0;
|
||||
if (v1->type == ex_string)
|
||||
return v1->e.string_val == v2->e.string_val;
|
||||
return v1->e.integer_val == v2->e.integer_val;
|
||||
val1 = get_value (v1);
|
||||
val2 = get_value (v1);
|
||||
return val1 == val2;
|
||||
}
|
||||
|
||||
struct expr_s *
|
||||
|
@ -145,22 +153,20 @@ label_compare (const void *_a, const void *_b)
|
|||
const case_label_t **b = (const case_label_t **) _b;
|
||||
const char *s1, *s2;
|
||||
|
||||
switch ((*a)->value->type) {
|
||||
case ex_string:
|
||||
s1 = (*a)->value->e.string_val ? (*a)->value->e.string_val : "";
|
||||
s2 = (*b)->value->e.string_val ? (*b)->value->e.string_val : "";
|
||||
return strcmp (s1, s2);
|
||||
break;
|
||||
case ex_float:
|
||||
return (*a)->value->e.float_val - (*b)->value->e.float_val;
|
||||
break;
|
||||
case ex_integer:
|
||||
return (*a)->value->e.integer_val - (*b)->value->e.integer_val;
|
||||
break;
|
||||
default:
|
||||
error (0, "internal compiler error in switch");
|
||||
abort ();
|
||||
if (is_string_val ((*a)->value)) {
|
||||
s1 = expr_string ((*a)->value);
|
||||
if (!s1)
|
||||
s1 = "";
|
||||
s2 = expr_string ((*b)->value);
|
||||
if (!s2)
|
||||
s2 = "";
|
||||
return strcmp (s1, s2);
|
||||
} else if (is_float_val ((*a)->value)) {
|
||||
return expr_float ((*a)->value) - expr_float ((*b)->value);
|
||||
} else if (is_integer_val ((*a)->value)) {
|
||||
return expr_integer ((*a)->value) - expr_integer ((*b)->value);
|
||||
}
|
||||
internal_error (0, "in switch");
|
||||
}
|
||||
|
||||
static case_node_t *
|
||||
|
@ -178,11 +184,11 @@ new_case_node (expr_t *low, expr_t *high)
|
|||
} else {
|
||||
int size;
|
||||
|
||||
if (low->type != ex_integer) {
|
||||
if (!is_integer_val (low)) {
|
||||
error (low, "switch: internal error");
|
||||
abort ();
|
||||
}
|
||||
size = high->e.integer_val - low->e.integer_val + 1;
|
||||
size = expr_integer (high) - expr_integer (low) + 1;
|
||||
node->labels = calloc (size, sizeof (case_node_t *));
|
||||
}
|
||||
node->left = node->right = 0;
|
||||
|
@ -223,18 +229,18 @@ build_case_tree (case_label_t **labels, int count, int range)
|
|||
if (!nodes)
|
||||
Sys_Error ("out of memory");
|
||||
|
||||
if (range && labels[0]->value->type == ex_integer) {
|
||||
if (range && is_integer_val (labels[0]->value)) {
|
||||
for (i = 0; i < count - 1; i = j, num_nodes++) {
|
||||
for (j = i + 1; j < count; j++) {
|
||||
if (labels[j]->value->e.integer_val
|
||||
- labels[j - 1]->value->e.integer_val > 1)
|
||||
if (expr_integer (labels[j]->value)
|
||||
- expr_integer (labels[j - 1]->value) > 1)
|
||||
break;
|
||||
}
|
||||
nodes[num_nodes] = new_case_node (labels[i]->value,
|
||||
labels[j - 1]->value);
|
||||
for (k = i; k < j; k++)
|
||||
nodes[num_nodes]->labels[labels[k]->value->e.integer_val
|
||||
- labels[i]->value->e.integer_val]
|
||||
nodes[num_nodes]->labels[expr_integer (labels[k]->value)
|
||||
- expr_integer (labels[i]->value)]
|
||||
= labels[k]->label;
|
||||
}
|
||||
if (i < count) {
|
||||
|
@ -297,15 +303,15 @@ build_switch (expr_t *sw, case_node_t *tree, int op, expr_t *sw_val,
|
|||
build_switch (sw, tree->right, op, sw_val, temp, default_label);
|
||||
}
|
||||
} else {
|
||||
int low = tree->low->e.integer_val;
|
||||
int high = tree->high->e.integer_val;
|
||||
int low = expr_integer (tree->low);
|
||||
int high = expr_integer (tree->high);
|
||||
def_t *def;
|
||||
expr_t *table;
|
||||
const char *name = new_label_name ();
|
||||
int i;
|
||||
expr_t *range = binary_expr ('-', tree->high, tree->low);
|
||||
|
||||
range->type = ex_uinteger;
|
||||
range = fold_constants (range);
|
||||
|
||||
//FIXME unsigned int better?
|
||||
def = get_def (array_type (&type_integer, high - low + 1), name,
|
||||
|
|
Loading…
Reference in a new issue