quakeforge/tools/qfcc/source/expr.c

1332 lines
26 KiB
C
Raw Normal View History

#include <stdlib.h>
#include <QF/mathlib.h>
#include <QF/va.h>
#include "qfcc.h"
#include "scope.h"
#include "qc-parse.h"
extern function_t *current_func;
int lineno_base;
static etype_t qc_types[] = {
ev_void, // ex_label
ev_void, // ex_block
ev_void, // ex_expr
ev_void, // ex_uexpr
ev_void, // ex_def
ev_string, // ex_string
ev_float, // ex_float
ev_vector, // ex_vector
ev_entity, // ex_entity
ev_field, // ex_field
ev_func, // ex_func
ev_pointer, // ex_pointer
ev_quaternion, // ex_quaternion
ev_integer, // ex_integer
};
static type_t *types[] = {
&type_void,
&type_string,
&type_float,
&type_vector,
&type_entity,
&type_field,
&type_function,
&type_pointer,
&type_quaternion,
&type_integer,
};
static expr_type expr_types[] = {
ex_label, // ev_void (ick)
ex_string, // ev_string
ex_float, // ev_float
ex_vector, // ev_vector
ex_entity, // ev_entity
ex_field, // ev_field
ex_func, // ev_func
ex_pointer, // ev_pointer
ex_quaternion, // ev_quaternion
ex_integer, // ev_integer
};
static const char *type_names[] = {
"void",
"string",
"float",
"vector",
"entity",
"field",
"function",
"pointer",
"quaternion",
"int",
};
static etype_t
get_type (expr_t *e)
{
switch (e->type) {
case ex_label:
case ex_block:
return ev_void;
case ex_expr:
case ex_uexpr:
return e->e.expr.type->type;
case ex_def:
return e->e.def->type->type;
case ex_string:
case ex_float:
case ex_vector:
case ex_entity:
case ex_field:
case ex_func:
case ex_pointer:
case ex_quaternion:
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
case ex_integer:
return qc_types[e->type];
}
return ev_void;
}
2001-06-28 21:26:40 +00:00
expr_t *
error (expr_t *e, const char *fmt, ...)
{
va_list args;
string_t file = s_file;
int line = pr_source_line;
va_start (args, fmt);
if (e) {
file = e->file;
line = e->line;
}
fprintf (stderr, "%s:%d: ", strings + file, line);
vfprintf (stderr, fmt, args);
fputs ("\n", stderr);
if (e) {
e = new_expr ();
e->type = ex_integer;
2001-06-28 21:26:40 +00:00
}
va_end (args);
pr_error_count++;
return e;
}
void
warning (expr_t *e, const char *fmt, ...)
{
va_list args;
string_t file = s_file;
int line = pr_source_line;
if (options.warn_error) {
options.warn_error = 0; // only want to do this once
error (e, "warnings treated as errors");
}
2001-06-28 21:26:40 +00:00
va_start (args, fmt);
if (e) {
file = e->file;
line = e->line;
}
fprintf (stderr, "%s:%d: warning:", strings + file, line);
vfprintf (stderr, fmt, args);
fputs ("\n", stderr);
va_end (args);
}
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
const char *
get_op_string (int op)
{
switch (op) {
case OR:
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
return "||";
case AND:
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
return "&&";
case EQ:
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
return "==";
case NE:
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
return "!=";
case LE:
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
return "<=";
case GE:
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
return ">=";
case LT:
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
return "<";
case GT:
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
return ">";
case '=':
return "=";
case '+':
return "+";
case '-':
return "-";
case '*':
return "*";
case '/':
return "/";
case '&':
return "&";
case '|':
return "|";
case '!':
return "!";
case '(':
return "(";
case '.':
return ".";
case 'i':
return "<if>";
case 'n':
return "<ifnot>";
case 'g':
return "<goto>";
case 'r':
return "<return>";
default:
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
return "unknown";
}
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
}
expr_t *
type_mismatch (expr_t *e1, expr_t *e2, int op)
{
etype_t t1, t2;
t1 = get_type (e1);
t2 = get_type (e2);
return error (e1, "type mismatch: %s %s %s",
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
type_names[t1], get_op_string (op), type_names[t2]);
}
expr_t *
new_expr (void)
{
expr_t *e = calloc (1, sizeof (expr_t));
e->line = pr_source_line;
e->file = s_file;
return e;
}
expr_t *
2001-06-26 02:46:02 +00:00
new_label_expr (void)
{
static int label = 0;
int lnum = ++label;
const char *fname = current_func->def->name;
expr_t *l = new_expr ();
l->type = ex_label;
l->e.label.name = malloc (1 + strlen (fname) + 1 + ceil (log10 (lnum)) + 1);
sprintf (l->e.label.name, "$%s_%d", fname, lnum);
return l;
}
expr_t *
new_block_expr (void)
{
expr_t *b = new_expr ();
b->type = ex_block;
b->e.block.head = 0;
b->e.block.tail = &b->e.block.head;
return b;
}
2001-06-26 02:46:02 +00:00
expr_t *
new_binary_expr (int op, expr_t *e1, expr_t *e2)
{
expr_t *e = new_expr ();
e->type = ex_expr;
e->e.expr.op = op;
e->e.expr.e1 = e1;
e->e.expr.e2 = e2;
return e;
}
expr_t *
new_unary_expr (int op, expr_t *e1)
{
expr_t *e = new_expr ();
e->type = ex_uexpr;
e->e.expr.op = op;
e->e.expr.e1 = e1;
return e;
}
expr_t *
append_expr (expr_t *block, expr_t *e)
{
if (block->type != ex_block)
abort ();
if (!e)
return block;
*block->e.block.tail = e;
block->e.block.tail = &e->next;
return block;
}
void
print_expr (expr_t *e)
{
printf (" ");
if (!e) {
printf ("(nil)");
return;
}
switch (e->type) {
case ex_label:
printf ("%s", e->e.label.name);
break;
case ex_block:
printf ("{\n");
for (e = e->e.block.head; e; e = e->next) {
print_expr (e);
puts("");
}
printf ("}");
break;
case ex_expr:
print_expr (e->e.expr.e1);
if (e->e.expr.op == 'c') {
expr_t *p = e->e.expr.e2;
printf ("(");
while (p) {
print_expr (p);
if (p->next)
printf (",");
p = p->next;
}
printf (")");
} else {
print_expr (e->e.expr.e2);
printf (" %s", get_op_string (e->e.expr.op));
}
break;
case ex_uexpr:
print_expr (e->e.expr.e1);
printf (" u%s", get_op_string (e->e.expr.op));
break;
case ex_def:
printf ("%s", e->e.def->name);
break;
case ex_string:
printf ("\"%s\"", e->e.string_val);
break;
case ex_float:
printf ("%g", e->e.float_val);
break;
case ex_vector:
printf ("'%g", e->e.vector_val[0]);
printf ( " %g", e->e.vector_val[1]);
printf ( " %g'", e->e.vector_val[2]);
break;
case ex_quaternion:
printf ("'%g", e->e.quaternion_val[0]);
printf (" %g", e->e.quaternion_val[1]);
printf (" %g", e->e.quaternion_val[2]);
printf (" %g'", e->e.quaternion_val[3]);
break;
case ex_entity:
case ex_field:
case ex_func:
case ex_pointer:
case ex_integer:
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
printf ("%d", e->e.integer_val);
break;
}
}
static expr_t *
do_op_string (int op, expr_t *e1, expr_t *e2)
{
int len;
char *buf;
char *s1, *s2;
s1 = e1->e.string_val;
s2 = e2->e.string_val;
switch (op) {
case '+':
len = strlen (s1) + strlen (s2) + 1;
buf = malloc (len);
strcpy (buf, s1);
strcat (buf, s2);
e1->e.string_val = buf;
break;
case LT:
e1->type = ex_integer;
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
e1->e.integer_val = strcmp (s1, s2) < 0;
break;
case GT:
e1->type = ex_integer;
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
e1->e.integer_val = strcmp (s1, s2) > 0;
break;
case LE:
e1->type = ex_integer;
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
e1->e.integer_val = strcmp (s1, s2) <= 0;
break;
case GE:
e1->type = ex_integer;
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
e1->e.integer_val = strcmp (s1, s2) >= 0;
break;
case EQ:
e1->type = ex_integer;
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
e1->e.integer_val = strcmp (s1, s2) == 0;
break;
case NE:
e1->type = ex_integer;
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
e1->e.integer_val = strcmp (s1, s2) != 0;
break;
default:
2001-06-28 21:26:40 +00:00
return error (e1, "invalid operand for string");
}
return e1;
}
static expr_t *
do_op_float (int op, expr_t *e1, expr_t *e2)
{
float f1, f2;
f1 = e1->e.float_val;
f2 = e2->e.float_val;
switch (op) {
case '+':
e1->e.float_val += f2;
break;
case '-':
e1->e.float_val -= f2;
break;
case '*':
e1->e.float_val *= f2;
break;
case '/':
e1->e.float_val /= f2;
break;
case '&':
e1->e.float_val = (int)f1 & (int)f2;
break;
case '|':
2001-07-19 03:00:35 +00:00
e1->e.float_val = (int)f1 | (int)f2;
break;
case AND:
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
e1->type = ex_integer;
e1->e.integer_val = f1 && f2;
break;
case OR:
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
e1->type = ex_integer;
e1->e.integer_val = f1 || f2;
break;
case LT:
e1->type = ex_integer;
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
e1->e.integer_val = f1 < f2;
break;
case GT:
e1->type = ex_integer;
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
e1->e.integer_val = f1 > f2;
break;
case LE:
e1->type = ex_integer;
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
e1->e.integer_val = f1 <= f2;
break;
case GE:
e1->type = ex_integer;
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
e1->e.integer_val = f1 >= f2;
break;
case EQ:
e1->type = ex_integer;
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
e1->e.integer_val = f1 == f2;
break;
case NE:
e1->type = ex_integer;
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
e1->e.integer_val = f1 != f2;
break;
default:
2001-06-28 21:26:40 +00:00
return error (e1, "invalid operand for string");
}
return e1;
}
static expr_t *
do_op_vector (int op, expr_t *e1, expr_t *e2)
{
float *v1, *v2;
v1 = e1->e.vector_val;
v2 = e2->e.vector_val;
switch (op) {
case '+':
VectorAdd (v1, v2, v1);
break;
case '-':
VectorSubtract (v1, v2, v1);
break;
case '*':
e1->type = ex_float;
e1->e.float_val = DotProduct (v1, v2);
break;
case EQ:
e1->type = ex_integer;
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
e1->e.integer_val = (v1[0] == v2[0])
&& (v1[1] == v2[1])
&& (v1[2] == v2[2]);
break;
case NE:
e1->type = ex_integer;
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
e1->e.integer_val = (v1[0] == v2[0])
|| (v1[1] != v2[1])
|| (v1[2] != v2[2]);
break;
default:
2001-06-28 21:26:40 +00:00
return error (e1, "invalid operand for string");
}
return e1;
}
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
static expr_t *
do_op_integer (int op, expr_t *e1, expr_t *e2)
{
int i1, i2;
i1 = e1->e.integer_val;
i2 = e2->e.integer_val;
switch (op) {
case '+':
e1->e.integer_val += i2;
break;
case '-':
e1->e.integer_val -= i2;
break;
case '*':
e1->e.integer_val *= i2;
break;
case '/':
e1->e.integer_val /= i2;
break;
case '&':
e1->e.integer_val = i1 & i2;
break;
case '|':
e1->e.integer_val = i1 | i2;
break;
case AND:
e1->e.integer_val = i1 && i2;
break;
case OR:
e1->e.integer_val = i1 || i2;
break;
case LT:
e1->type = ex_integer;
e1->e.integer_val = i1 < i2;
break;
case GT:
e1->type = ex_integer;
e1->e.integer_val = i1 > i2;
break;
case LE:
e1->type = ex_integer;
e1->e.integer_val = i1 <= i2;
break;
case GE:
e1->type = ex_integer;
e1->e.integer_val = i1 >= i2;
break;
case EQ:
e1->type = ex_integer;
e1->e.integer_val = i1 == i2;
break;
case NE:
e1->type = ex_integer;
e1->e.integer_val = i1 != i2;
break;
default:
return error (e1, "invalid operand for string");
}
return e1;
}
static expr_t *
do_op_huh (int op, expr_t *e1, expr_t *e2)
{
2001-06-28 21:26:40 +00:00
return error (e1, "funny constant");
}
static expr_t *(*do_op[]) (int op, expr_t *e1, expr_t *e2) = {
do_op_huh,
do_op_string,
do_op_float,
do_op_vector,
do_op_huh,
do_op_huh,
do_op_huh,
do_op_huh,
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
do_op_huh,
do_op_integer,
};
static expr_t *
binary_const (int op, expr_t *e1, expr_t *e2)
{
etype_t t1, t2;
//expr_t *e;
t1 = get_type (e1);
t2 = get_type (e2);
if (t1 == t2) {
return do_op[t1](op, e1, e2);
} else {
return type_mismatch (e1, e2, op);
}
}
static expr_t *
field_expr (expr_t *e1, expr_t *e2)
{
etype_t t1, t2;
expr_t *e;
t1 = get_type (e1);
t2 = get_type (e2);
2001-06-27 21:43:10 +00:00
if (t1 != ev_entity || t2 != ev_field) {
2001-06-28 21:26:40 +00:00
return error (e1, "type missmatch for .");
}
e = new_binary_expr ('.', e1, e2);
e->e.expr.type = (e2->type == ex_def)
? e2->e.def->type->aux_type
: e2->e.expr.type;
return e;
}
static expr_t *
test_expr (expr_t *e, int test)
{
expr_t *new = 0;
if (!test)
return unary_expr ('!', e);
switch (get_type (e)) {
case ev_type_count:
case ev_void:
error (e, "internal error");
abort ();
case ev_string:
new = new_expr ();
new->type = ex_string;
break;
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
case ev_integer:
return e;
case ev_float:
new = new_expr ();
new->type = ex_float;
break;
case ev_vector:
new = new_expr ();
new->type = ex_vector;
break;
case ev_entity:
new = new_expr ();
new->type = ex_entity;
break;
case ev_field:
new = new_expr ();
new->type = ex_field;
break;
case ev_func:
new = new_expr ();
new->type = ex_func;
break;
case ev_pointer:
new = new_expr ();
new->type = ex_pointer;
break;
case ev_quaternion:
new = new_expr ();
new->type = ex_quaternion;
break;
}
return binary_expr (NE, e, new);
}
void
convert_int (expr_t *e)
{
e->type = ex_float;
e->e.float_val = e->e.integer_val;
}
expr_t *
binary_expr (int op, expr_t *e1, expr_t *e2)
{
etype_t t1, t2;
type_t *type = 0;
expr_t *e;
if (op == '.')
return field_expr (e1, e2);
if (op == OR || op == AND) {
e1 = test_expr (e1, true);
e2 = test_expr (e2, true);
}
t1 = get_type (e1);
t2 = get_type (e2);
if (t1 == ev_void || t2 == ev_void) {
error (e1, "internal error");
abort ();
}
if (e1->type == ex_integer
&& (t2 == ev_float || t2 == ev_vector || t2 == ev_quaternion)) {
convert_int (e1);
t1 = ev_float;
} else if (e2->type == ex_integer
&& (t1 == ev_float || t1 == ev_vector || t1 == ev_quaternion)) {
convert_int (e2);
t2 = ev_float;
}
if (e1->type >= ex_string && e2->type >= ex_string)
return binary_const (op, e1, e2);
2001-06-28 15:20:31 +00:00
if ((op == '&' || op == '|')
&& e1->type == ex_uexpr && e1->e.expr.op == '!' && !e1->paren) {
2001-06-28 21:26:40 +00:00
warning (e1, "ambiguous logic. Suggest explicit parentheses with expressions involving ! and %c", op);
2001-06-28 15:20:31 +00:00
}
if (t1 != t2) {
switch (t1) {
case ev_float:
if (t2 == ev_vector) {
type = &type_vector;
} else {
goto type_mismatch;
}
break;
case ev_vector:
if (t2 == ev_float) {
type = &type_vector;
} else {
goto type_mismatch;
}
break;
case ev_field:
if (e1->e.expr.type->aux_type->type == t2) {
type = e1->e.expr.type->aux_type;
} else {
goto type_mismatch;
}
break;
default:
type_mismatch:
return type_mismatch (e1, e2, op);
}
} else {
type = types[t1];
}
if ((op >= OR && op <= GT) || op == '>' || op == '<')
type = &type_integer;
else if (op == '*' && t1 == ev_vector && t2 == ev_vector)
type = &type_float;
if (op == '=' && e1->type == ex_expr && e1->e.expr.op == '.') {
e1->e.expr.type = &type_pointer;
}
if (!type)
error (e1, "internal error");
e = new_binary_expr (op, e1, e2);
e->e.expr.type = type;
return e;
}
expr_t *
unary_expr (int op, expr_t *e)
{
switch (op) {
case '-':
switch (e->type) {
case ex_label:
case ex_block:
abort ();
case ex_uexpr:
if (e->e.expr.op == '-')
return e->e.expr.e1;
case ex_expr:
case ex_def:
{
expr_t *n = new_unary_expr (op, e);
n->e.expr.type = (e->type == ex_def)
? e->e.def->type
: e->e.expr.type;
return n;
}
case ex_integer:
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
e->e.integer_val *= -1;
return e;
case ex_float:
e->e.float_val *= -1;
return e;
case ex_string:
case ex_entity:
case ex_field:
case ex_func:
case ex_pointer:
2001-06-28 21:26:40 +00:00
return error (e, "invalid type for unary -");
case ex_vector:
e->e.vector_val[0] *= -1;
e->e.vector_val[1] *= -1;
e->e.vector_val[2] *= -1;
return e;
case ex_quaternion:
e->e.quaternion_val[0] *= -1;
e->e.quaternion_val[1] *= -1;
e->e.quaternion_val[2] *= -1;
e->e.quaternion_val[3] *= -1;
return e;
}
break;
case '!':
switch (e->type) {
case ex_label:
case ex_block:
abort ();
case ex_uexpr:
case ex_expr:
case ex_def:
{
expr_t *n = new_unary_expr (op, e);
n->e.expr.type = &type_integer;
return n;
}
case ex_integer:
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
e->e.integer_val = !e->e.integer_val;
return e;
case ex_float:
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
e->e.integer_val = !e->e.float_val;
e->type = ex_integer;
return e;
case ex_string:
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
e->e.integer_val = !e->e.string_val || !e->e.string_val[0];
e->type = ex_integer;
return e;
case ex_vector:
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
e->e.integer_val = !e->e.vector_val[0]
&& !e->e.vector_val[1]
&& !e->e.vector_val[2];
e->type = ex_integer;
return e;
case ex_quaternion:
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
e->e.integer_val = !e->e.quaternion_val[0]
&& !e->e.quaternion_val[1]
&& !e->e.quaternion_val[2]
&& !e->e.quaternion_val[3];
e->type = ex_integer;
return e;
case ex_entity:
case ex_field:
case ex_func:
case ex_pointer:
error (e, "internal error");
abort ();
}
break;
default:
abort ();
}
2001-06-28 21:26:40 +00:00
error (e, "internal error");
abort ();
}
expr_t *
function_expr (expr_t *e1, expr_t *e2)
{
etype_t t1;
expr_t *e;
int parm_count = 0;
type_t *ftype;
int i;
t1 = get_type (e1);
if (t1 != ev_func) {
if (e1->type == ex_def)
return error (e1, "Called object \"%s\" is not a function",
e1->e.def->name);
else
return error (e1, "Called object is not a function");
}
if (e1->type == ex_def && e2 && e2->type == ex_string) {
//FIXME eww, I hate this, but it's needed :(
//FIXME make a qc hook? :)
def_t *func = e1->e.def;
def_t *e = PR_ReuseConstant (e2, 0);
if (strncmp (func->name, "precache_sound", 14) == 0)
PrecacheSound (e, func->name[4]);
else if (strncmp (func->name, "precache_model", 14) == 0)
PrecacheModel (e, func->name[14]);
else if (strncmp (func->name, "precache_file", 13) == 0)
PrecacheFile (e, func->name[13]);
}
ftype = e1->type == ex_def
? e1->e.def->type
: e1->e.expr.type;
for (e = e2; e; e = e->next)
parm_count++;
if (parm_count > 8) {
return error (e1, "more than 8 parameters");
}
if (ftype->num_parms != -1) {
expr_t *err = 0;
if (parm_count > ftype->num_parms) {
2001-06-28 21:26:40 +00:00
return error (e1, "too many arguments");
} else if (parm_count < ftype->num_parms) {
2001-06-28 21:26:40 +00:00
return error (e1, "too few arguments");
}
for (i = parm_count, e = e2; i > 0; i--, e = e->next) {
type_t *t;
if (e->type == ex_expr) {
t = e->e.expr.type;
} else if (e->type == ex_def) {
t = e->e.def->type;
} else {
if (ftype->parm_types[i - 1] == &type_float
&& e->type == ex_integer) {
e->type = ex_float;
e->e.float_val = e->e.integer_val;
}
t = types[get_type (e)];
}
if (t != ftype->parm_types[i - 1])
err = error (e, "type mismatch for parameter %d of %s",
i, e1->e.def->name);
}
if (err)
return err;
}
e = new_binary_expr ('c', e1, e2);
e->e.expr.type = ftype->aux_type;
return e;
}
2001-07-23 02:27:46 +00:00
expr_t *
return_expr (function_t *f, expr_t *e)
{
if (!e) {
if (f->def->type->aux_type != &type_void)
return error (e, "return from non-void function without a value");
} else {
type_t *t;
if (f->def->type->aux_type == &type_void)
return error (e, "returning a value for a void function");
if (e->type == ex_expr) {
t = e->e.expr.type;
} else if (e->type == ex_def) {
t = e->e.def->type;
} else {
if (f->def->type->aux_type == &type_float
&& e->type == ex_integer) {
e->type = ex_float;
e->e.float_val = e->e.integer_val;
}
t = types[get_type (e)];
}
if (f->def->type->aux_type != t)
return error (e, "type mismatch for return value of %s",
2001-07-23 05:46:00 +00:00
f->def->name);
2001-07-23 02:27:46 +00:00
}
return new_unary_expr ('r', e);
}
def_t *
emit_statement (int sline, opcode_t *op, def_t *var_a, def_t *var_b, def_t *var_c)
{
dstatement_t *statement;
def_t *ret;
Initial integer type support. qfcc /is/ partially broken when it comes to integer constants and float function args/return values. pr_comp.h: o add the integer opcodes to pr_opcode_e pr_edict.c: o add "quaternion" and "integer" to type_name[] o support quatnernion and integers types when printing values o support the integer opcodes when bounds checking pr_exec.c o enable the integer opcodes pr_opcode: o add the integer opcodes to the opcode table o logical operators all result in an integer rather than a value expr.h: o rename int_val to integer_val qfcc.h: o kill another magic number expr.c: o move the opcode to string conversion out of type_mismatch and into get_op_string o rename int_val to integer_val o general integer type support. o generate an internal comipiler error for null opcodes rather than segging. pr_imm.c: o rename int_val to integer_val o support integer constants, converting to float when needed. pr_lex.c: o magic number death and support quaternions and integers in type_size[] qc-lex.l o rename int_val to integer_val o support quaternion and integer type keywords qc-parse.y: o rename int_val to integer_val o use binary_expr instead of new_binary_expr for local initialized variables builtins.c: o rename int_val to integer_val o fix most (all?) of the INT related FIXMEs defs.qc: o use integer instead of float where it makes sense main.c: o read_result is now integer rather than float main.qc: o float -> integer where appropriate o new test for int const to float arg
2001-07-23 01:31:22 +00:00
if (!op) {
expr_t e;
e.line = sline;
e.file = s_file;
error (&e, "ice ice baby\n");
abort ();
}
if (options.debug) {
int line = sline - lineno_base;
if (line != linenos[num_linenos - 1].line) {
pr_lineno_t *lineno = new_lineno ();
lineno->line = line;
lineno->fa.addr = numstatements;
}
}
statement = &statements[numstatements];
numstatements++;
statement_linenums[statement - statements] = pr_source_line;
statement->op = op->opcode;
statement->a = var_a ? var_a->ofs : 0;
statement->b = var_b ? var_b->ofs : 0;
if (op->type_c == ev_void || op->right_associative) {
// ifs, gotos, and assignments don't need vars allocated
var_c = NULL;
statement->c = 0;
ret = var_a;
} else { // allocate result space
if (!var_c)
var_c = PR_GetTempDef (types[op->type_c], pr_scope);
statement->c = var_c->ofs;
ret = var_c;
}
PR_AddStatementRef (var_a, statement, 0);
PR_AddStatementRef (var_b, statement, 1);
PR_AddStatementRef (var_c, statement, 2);
if (op->right_associative)
return var_a;
return var_c;
}
def_t *emit_sub_expr (expr_t *e, def_t *dest);
2001-06-26 20:06:56 +00:00
void
emit_branch (int line, opcode_t *op, expr_t *e, expr_t *l)
2001-06-26 20:06:56 +00:00
{
dstatement_t *st;
statref_t *ref;
def_t *def = 0;
if (e)
def = emit_sub_expr (e, 0);
st = &statements[numstatements];
emit_statement (line, op, def, 0, 0);
2001-06-26 20:06:56 +00:00
if (l->e.label.statement) {
if (op == op_goto)
st->a = l->e.label.statement - st;
else
st->b = l->e.label.statement - st;
} else {
ref = PR_NewStatref (st, op != op_goto);
ref->next = l->e.label.refs;
l->e.label.refs = ref;
}
}
def_t *
emit_function_call (expr_t *e, def_t *dest)
{
def_t *func = emit_sub_expr (e->e.expr.e1, 0);
def_t parm;
def_t *arg;
expr_t *earg;
opcode_t *op;
int count = 0, ind;
for (earg = e->e.expr.e2; earg; earg = earg->next)
count++;
ind = count;
for (earg = e->e.expr.e2; earg; earg = earg->next) {
ind--;
parm = def_parms[ind];
parm.type = types[get_type (earg)];
arg = emit_sub_expr (earg, &parm);
if (earg->type != ex_expr) {
op = PR_Opcode_Find ("=", 5, arg, &parm, &parm);
emit_statement (e->line, op, arg, &parm, 0);
}
}
op = PR_Opcode_Find (va ("<CALL%d>", count), -1, &def_function, &def_void, &def_void);
emit_statement (e->line, op, func, 0, 0);
def_ret.type = func->type->aux_type;
2001-06-26 23:42:11 +00:00
if (dest) {
op = PR_Opcode_Find ("=", 5, dest, &def_ret, &def_ret);
emit_statement (e->line, op, &def_ret, dest, 0);
2001-06-26 23:42:11 +00:00
return dest;
} else {
return &def_ret;
}
}
def_t *
emit_assign_expr (expr_t *e, def_t *dest)
{
def_t *def_a, *def_b;
opcode_t *op;
expr_t *e1 = e->e.expr.e1;
expr_t *e2 = e->e.expr.e2;
def_a = emit_sub_expr (e1, 0);
if (def_a->type == &type_pointer) {
def_b = emit_sub_expr (e2, 0);
op = PR_Opcode_Find ("=", 5, def_a, def_b, def_b);
emit_statement (e->line, op, def_b, def_a, 0);
} else {
if (def_a->initialized) {
if (options.cow) {
int size = type_size [def_a->type->type];
int ofs = PR_NewLocation (def_a->type);
memcpy (pr_globals + ofs, pr_globals + def_a->ofs, size);
def_a->ofs = ofs;
def_a->initialized = 0;
warning (e1, "assignment to constant %s", def_a->name);
} else {
2001-06-28 21:26:40 +00:00
error (e1, "assignment to constant %s", def_a->name);
}
}
if (e2->type == ex_expr) {
def_b = emit_sub_expr (e2, def_a);
} else {
def_b = emit_sub_expr (e2, 0);
op = PR_Opcode_Find ("=", 5, def_a, def_b, def_b);
emit_statement (e->line, op, def_b, def_a, 0);
}
if (!def_b->name)
dest = def_a;
if (dest) {
op = PR_Opcode_Find ("=", 5, dest, def_b, def_b);
emit_statement (e->line, op, def_b, dest, 0);
}
}
return def_b;
}
def_t *
emit_sub_expr (expr_t *e, def_t *dest)
{
opcode_t *op;
char *operator;
def_t *def_a, *def_b;
int priority;
switch (e->type) {
case ex_label:
case ex_block:
error (e, "internal error");
abort ();
case ex_expr:
if (e->e.expr.op == 'c')
return emit_function_call (e, dest);
if (e->e.expr.op == '=')
return emit_assign_expr (e, dest);
def_a = emit_sub_expr (e->e.expr.e1, 0);
def_b = emit_sub_expr (e->e.expr.e2, 0);
switch (e->e.expr.op) {
case AND:
operator = "&&";
priority = 6;
break;
case OR:
operator = "||";
priority = 6;
break;
case EQ:
operator = "==";
priority = 4;
break;
case NE:
operator = "!=";
priority = 4;
break;
case LE:
operator = "<=";
priority = 4;
break;
case GE:
operator = ">=";
priority = 4;
break;
case LT:
operator = "<";
priority = 4;
break;
case GT:
operator = ">";
priority = 4;
break;
case '+':
operator = "+";
priority = 3;
break;
case '-':
operator = "-";
priority = 3;
break;
case '*':
operator = "*";
priority = 2;
break;
case '/':
operator = "/";
priority = 2;
break;
case '&':
operator = "&";
priority = 2;
break;
case '|':
operator = "|";
priority = 2;
break;
case '.':
operator = ".";
priority = 1;
break;
default:
abort ();
}
if (!dest)
dest = PR_GetTempDef (e->e.expr.type, pr_scope);
op = PR_Opcode_Find (operator, priority, def_a, def_b, dest);
return emit_statement (e->line, op, def_a, def_b, dest);
case ex_uexpr:
if (e->e.expr.op == '!') {
operator = "!";
priority = -1;
def_a = emit_sub_expr (e->e.expr.e1, 0);
def_b = &def_void;
} else if (e->e.expr.op == '-') {
static expr_t zero;
zero.type = expr_types[get_type (e->e.expr.e1)];
operator = "-";
priority = 3;
def_a = PR_ReuseConstant (&zero, 0);
def_b = emit_sub_expr (e->e.expr.e1, 0);
} else {
abort ();
}
op = PR_Opcode_Find (operator, priority, def_a, def_b, dest);
return emit_statement (e->line, op, def_a, def_b, dest);
case ex_def:
return e->e.def;
case ex_string:
case ex_float:
case ex_vector:
case ex_entity:
case ex_field:
case ex_func:
case ex_pointer:
case ex_quaternion:
case ex_integer:
return PR_ReuseConstant (e, 0);
}
return 0;
}
void
emit_expr (expr_t *e)
{
def_t *def;
2001-06-26 19:54:50 +00:00
def_t *def_a;
def_t *def_b;
statref_t *ref;
label_t *label;
//opcode_t *op;
switch (e->type) {
case ex_label:
label = &e->e.label;
label->statement = &statements[numstatements];
for (ref = label->refs; ref; ref = ref->next) {
switch (ref->field) {
case 0:
ref->statement->a = label->statement - ref->statement;
break;
case 1:
ref->statement->b = label->statement - ref->statement;
break;
case 2:
ref->statement->c = label->statement - ref->statement;
break;
default:
abort();
}
}
break;
case ex_block:
for (e = e->e.block.head; e; e = e->next)
emit_expr (e);
break;
case ex_expr:
switch (e->e.expr.op) {
case '=':
emit_assign_expr (e, 0);
break;
case 'n':
emit_branch (e->line, op_ifnot, e->e.expr.e1, e->e.expr.e2);
break;
case 'i':
emit_branch (e->line, op_if, e->e.expr.e1, e->e.expr.e2);
break;
case 'c':
2001-06-26 20:06:56 +00:00
emit_function_call (e, 0);
break;
case 's':
2001-06-26 19:54:50 +00:00
def_a = emit_sub_expr (e->e.expr.e1, 0);
def_b = emit_sub_expr (e->e.expr.e2, 0);
emit_statement (e->line, op_state, def_a, def_b, 0);
break;
default:
warning (e, "Ignoring useless expression");
2001-06-28 21:26:40 +00:00
break;
}
break;
case ex_uexpr:
switch (e->e.expr.op) {
case 'r':
def = 0;
if (e->e.expr.e1)
def = emit_sub_expr (e->e.expr.e1, 0);
emit_statement (e->line, op_return, def, 0, 0);
break;
case 'g':
emit_branch (e->line, op_goto, 0, e->e.expr.e1);
break;
default:
warning (e, "Ignoring useless expression");
emit_expr (e->e.expr.e1);
break;
}
break;
case ex_def:
case ex_string:
case ex_float:
case ex_vector:
case ex_entity:
case ex_field:
case ex_func:
case ex_pointer:
case ex_quaternion:
case ex_integer:
warning (e, "Ignoring useless expression");
break;
}
PR_FreeTempDefs ();
}