From c248372e200510010e5cff55532fd683b8474727 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 23 Jul 2001 01:31:22 +0000 Subject: [PATCH] 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 --- include/QF/pr_comp.h | 22 ++++ libs/gamecode/pr_edict.c | 35 +++++- libs/gamecode/pr_exec.c | 28 +++-- libs/gamecode/pr_opcode.c | 74 +++++++----- tools/qfcc/include/expr.h | 2 +- tools/qfcc/include/qfcc.h | 2 +- tools/qfcc/source/expr.c | 228 +++++++++++++++++++++++------------ tools/qfcc/source/pr_imm.c | 22 ++-- tools/qfcc/source/pr_lex.c | 2 +- tools/qfcc/source/qc-lex.l | 30 ++--- tools/qfcc/source/qc-parse.y | 10 +- tools/qwaq/builtins.c | 40 +++--- tools/qwaq/defs.qc | 16 +-- tools/qwaq/main.c | 4 +- tools/qwaq/main.qc | 14 ++- 15 files changed, 349 insertions(+), 180 deletions(-) diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index f18089f70..ad9e71384 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -137,6 +137,28 @@ typedef enum { OP_GE_S, OP_LT_S, OP_GT_S, + + OP_ADD_I, + OP_SUB_I, + OP_MUL_I, + OP_DIV_I, + OP_BITAND_I, + OP_BITOR_I, + OP_GE_I, + OP_LE_I, + OP_GT_I, + OP_LT_I, + OP_AND_I, + OP_OR_I, + OP_NOT_I, + OP_EQ_I, + OP_NE_I, + OP_STORE_I, + OP_STOREP_I, + OP_LOAD_I, + + OP_CONV_IF, + OP_CONV_FI, } pr_opcode_e; typedef struct diff --git a/libs/gamecode/pr_edict.c b/libs/gamecode/pr_edict.c index 9cf3a731b..341ea4441 100644 --- a/libs/gamecode/pr_edict.c +++ b/libs/gamecode/pr_edict.c @@ -66,7 +66,7 @@ int type_size[8] = { sizeof (void *) / 4 }; -char *type_name[8] = { +char *type_name[ev_type_count] = { "void", "string", "float", @@ -75,6 +75,8 @@ char *type_name[8] = { "field", "function", "pointer", + "quaternion", + "integer", }; ddef_t *ED_FieldAtOfs (progs_t * pr, int ofs); @@ -376,11 +378,20 @@ PR_ValueString (progs_t * pr, etype_t type, pr_type_t *val) break; case ev_vector: snprintf (line, sizeof (line), "'%5.1f %5.1f %5.1f'", - val->vector_var[0], val->vector_var[1], val->vector_var[2]); + val->vector_var[0], val->vector_var[1], + val->vector_var[2]); break; case ev_pointer: strcpy (line, "pointer"); break; + case ev_quaternion: + snprintf (line, sizeof (line), "'%5.1f %5.1f %5.1f %5.1f'", + val->vector_var[0], val->vector_var[1], + val->vector_var[2], val->vector_var[3]); + break; + case ev_integer: + snprintf (line, sizeof (line), "%d", val->integer_var); + break; default: snprintf (line, sizeof (line), "bad type %i", type); break; @@ -1224,6 +1235,24 @@ PR_LoadProgs (progs_t * pr, const char *progsname) case OP_LOAD_S: case OP_LOAD_FNC: case OP_LOAD_V: + case OP_ADD_I: + case OP_SUB_I: + case OP_MUL_I: + case OP_DIV_I: + case OP_BITAND_I: + case OP_BITOR_I: + case OP_GE_I: + case OP_LE_I: + case OP_GT_I: + case OP_LT_I: + case OP_AND_I: + case OP_OR_I: + case OP_NOT_I: + case OP_EQ_I: + case OP_NE_I: + case OP_LOAD_I: + case OP_CONV_IF: + case OP_CONV_FI: if ((unsigned short) st->a >= pr->progs->numglobals || (unsigned short) st->b >= pr->progs->numglobals || (unsigned short) st->c >= pr->progs->numglobals) @@ -1257,6 +1286,8 @@ PR_LoadProgs (progs_t * pr, const char *progsname) case OP_STATE: case OP_STOREP_V: case OP_STORE_V: + case OP_STORE_I: + case OP_STOREP_I: if ((unsigned short) st->a >= pr->progs->numglobals || (unsigned short) st->b >= pr->progs->numglobals) PR_Error diff --git a/libs/gamecode/pr_exec.c b/libs/gamecode/pr_exec.c index ec9b80909..1f70cfd7e 100644 --- a/libs/gamecode/pr_exec.c +++ b/libs/gamecode/pr_exec.c @@ -621,8 +621,6 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum) ed->v[pr->fields.frame].float_var = OPA.float_var; ed->v[pr->fields.think].func_var = OPB.func_var; break; -// LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized -/* case OP_ADD_I: OPC.integer_var = OPA.integer_var + OPB.integer_var; break; @@ -632,6 +630,7 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum) case OP_MUL_I: OPC.integer_var = OPA.integer_var * OPB.integer_var; break; +/* case OP_DIV_VF: { float temp = 1.0f / OPB.float_var; @@ -641,6 +640,7 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum) OPC.vector_var[2] = temp * OPA.vector_var[2]; } break; +*/ case OP_DIV_I: OPC.integer_var = OPA.integer_var / OPB.integer_var; break; @@ -657,31 +657,31 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum) OPC.integer_var = OPA.integer_var | OPB.integer_var; break; case OP_GE_I: - OPC.float_var = OPA.integer_var >= OPB.integer_var; + OPC.integer_var = OPA.integer_var >= OPB.integer_var; break; case OP_LE_I: - OPC.float_var = OPA.integer_var <= OPB.integer_var; + OPC.integer_var = OPA.integer_var <= OPB.integer_var; break; case OP_GT_I: - OPC.float_var = OPA.integer_var > OPB.integer_var; + OPC.integer_var = OPA.integer_var > OPB.integer_var; break; case OP_LT_I: - OPC.float_var = OPA.integer_var < OPB.integer_var; + OPC.integer_var = OPA.integer_var < OPB.integer_var; break; case OP_AND_I: - OPC.float_var = OPA.integer_var && OPB.integer_var; + OPC.integer_var = OPA.integer_var && OPB.integer_var; break; case OP_OR_I: - OPC.float_var = OPA.integer_var || OPB.integer_var; + OPC.integer_var = OPA.integer_var || OPB.integer_var; break; case OP_NOT_I: - OPC.float_var = !OPA.integer_var; + OPC.integer_var = !OPA.integer_var; break; case OP_EQ_I: - OPC.float_var = OPA.integer_var == OPB.integer_var; + OPC.integer_var = OPA.integer_var == OPB.integer_var; break; case OP_NE_I: - OPC.float_var = OPA.integer_var != OPB.integer_var; + OPC.integer_var = OPA.integer_var != OPB.integer_var; break; case OP_STORE_I: OPB.integer_var = OPA.integer_var; @@ -702,7 +702,7 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum) (pr, "Progs attempted to write to an engine edict field\n"); return; } - ptr = (eval_t *) ((byte *) *pr->edicts + OPB.integer_var); + ptr = (pr_type_t*)((int)*pr->edicts + OPB.integer_var); ptr->integer_var = OPA.integer_var; break; case OP_LOAD_I: @@ -721,9 +721,11 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum) return; } ed = PROG_TO_EDICT (pr, OPA.entity_var); - OPC.integer_var = ((eval_t *) ((int *) &ed->v + OPB.integer_var))->integer_var; + OPC.integer_var = ed->v[OPB.integer_var].integer_var; break; +// LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized +/* case OP_GSTOREP_I: case OP_GSTOREP_F: case OP_GSTOREP_ENT: diff --git a/libs/gamecode/pr_opcode.c b/libs/gamecode/pr_opcode.c index f682e3902..dc78266e0 100644 --- a/libs/gamecode/pr_opcode.c +++ b/libs/gamecode/pr_opcode.c @@ -50,26 +50,26 @@ opcode_t pr_opcodes[] = { {"-", "sub.f", OP_SUB_F, 3, false, ev_float, ev_float, ev_float, PROG_ID_VERSION}, {"-", "sub.v", OP_SUB_V, 3, false, ev_vector, ev_vector, ev_vector, PROG_ID_VERSION}, - {"==", "eq.f", OP_EQ_F, 4, false, ev_float, ev_float, ev_float, PROG_ID_VERSION}, - {"==", "eq.v", OP_EQ_V, 4, false, ev_vector, ev_vector, ev_float, PROG_ID_VERSION}, - {"==", "eq.s", OP_EQ_S, 4, false, ev_string, ev_string, ev_float, PROG_ID_VERSION}, - {"==", "eq.e", OP_EQ_E, 4, false, ev_entity, ev_entity, ev_float, PROG_ID_VERSION}, - {"==", "eq.fnc", OP_EQ_FNC, 4, false, ev_func, ev_func, ev_float, PROG_ID_VERSION}, + {"==", "eq.f", OP_EQ_F, 4, false, ev_float, ev_float, ev_integer, PROG_ID_VERSION}, + {"==", "eq.v", OP_EQ_V, 4, false, ev_vector, ev_vector, ev_integer, PROG_ID_VERSION}, + {"==", "eq.s", OP_EQ_S, 4, false, ev_string, ev_string, ev_integer, PROG_ID_VERSION}, + {"==", "eq.e", OP_EQ_E, 4, false, ev_entity, ev_entity, ev_integer, PROG_ID_VERSION}, + {"==", "eq.fnc", OP_EQ_FNC, 4, false, ev_func, ev_func, ev_integer, PROG_ID_VERSION}, - {"!=", "ne.f", OP_NE_F, 4, false, ev_float, ev_float, ev_float, PROG_ID_VERSION}, - {"!=", "ne.v", OP_NE_V, 4, false, ev_vector, ev_vector, ev_float, PROG_ID_VERSION}, - {"!=", "ne.s", OP_NE_S, 4, false, ev_string, ev_string, ev_float, PROG_ID_VERSION}, - {"!=", "ne.e", OP_NE_E, 4, false, ev_entity, ev_entity, ev_float, PROG_ID_VERSION}, - {"!=", "ne.fnc", OP_NE_FNC, 4, false, ev_func, ev_func, ev_float, PROG_ID_VERSION}, + {"!=", "ne.f", OP_NE_F, 4, false, ev_float, ev_float, ev_integer, PROG_ID_VERSION}, + {"!=", "ne.v", OP_NE_V, 4, false, ev_vector, ev_vector, ev_integer, PROG_ID_VERSION}, + {"!=", "ne.s", OP_NE_S, 4, false, ev_string, ev_string, ev_integer, PROG_ID_VERSION}, + {"!=", "ne.e", OP_NE_E, 4, false, ev_entity, ev_entity, ev_integer, PROG_ID_VERSION}, + {"!=", "ne.fnc", OP_NE_FNC, 4, false, ev_func, ev_func, ev_integer, PROG_ID_VERSION}, - {"<=", "le", OP_LE, 4, false, ev_float, ev_float, ev_float, PROG_ID_VERSION}, - {">=", "ge", OP_GE, 4, false, ev_float, ev_float, ev_float, PROG_ID_VERSION}, - {"<=", "le.s", OP_LE_S, 4, false, ev_string, ev_string, ev_float, PROG_VERSION}, - {">=", "ge.s", OP_GE_S, 4, false, ev_string, ev_string, ev_float, PROG_VERSION}, - {"<", "lt", OP_LT, 4, false, ev_float, ev_float, ev_float, PROG_ID_VERSION}, - {">", "gt", OP_GT, 4, false, ev_float, ev_float, ev_float, PROG_ID_VERSION}, - {"<", "lt.s", OP_LT_S, 4, false, ev_string, ev_string, ev_float, PROG_VERSION}, - {">", "gt.s", OP_GT_S, 4, false, ev_string, ev_string, ev_float, PROG_VERSION}, + {"<=", "le", OP_LE, 4, false, ev_float, ev_float, ev_integer, PROG_ID_VERSION}, + {">=", "ge", OP_GE, 4, false, ev_float, ev_float, ev_integer, PROG_ID_VERSION}, + {"<=", "le.s", OP_LE_S, 4, false, ev_string, ev_string, ev_integer, PROG_VERSION}, + {">=", "ge.s", OP_GE_S, 4, false, ev_string, ev_string, ev_integer, PROG_VERSION}, + {"<", "lt", OP_LT, 4, false, ev_float, ev_float, ev_integer, PROG_ID_VERSION}, + {">", "gt", OP_GT, 4, false, ev_float, ev_float, ev_integer, PROG_ID_VERSION}, + {"<", "lt.s", OP_LT_S, 4, false, ev_string, ev_string, ev_integer, PROG_VERSION}, + {">", "gt.s", OP_GT_S, 4, false, ev_string, ev_string, ev_integer, PROG_VERSION}, {".", "load.f", OP_LOAD_F, 1, false, ev_entity, ev_field, ev_float, PROG_ID_VERSION}, {".", "load.v", OP_LOAD_V, 1, false, ev_entity, ev_field, ev_vector, PROG_ID_VERSION}, @@ -96,14 +96,14 @@ opcode_t pr_opcodes[] = { {"", "return", OP_RETURN, -1, false, ev_void, ev_void, ev_void, PROG_ID_VERSION}, - {"!", "not.f", OP_NOT_F, -1, false, ev_float, ev_void, ev_float, PROG_ID_VERSION}, - {"!", "not.v", OP_NOT_V, -1, false, ev_vector, ev_void, ev_float, PROG_ID_VERSION}, - {"!", "not.s", OP_NOT_S, -1, false, ev_string, ev_void, ev_float, PROG_ID_VERSION}, - {"!", "not.ent", OP_NOT_ENT, -1, false, ev_entity, ev_void, ev_float, PROG_ID_VERSION}, - {"!", "not.fnc", OP_NOT_FNC, -1, false, ev_func, ev_void, ev_float, PROG_ID_VERSION}, + {"!", "not.f", OP_NOT_F, -1, false, ev_float, ev_void, ev_integer, PROG_ID_VERSION}, + {"!", "not.v", OP_NOT_V, -1, false, ev_vector, ev_void, ev_integer, PROG_ID_VERSION}, + {"!", "not.s", OP_NOT_S, -1, false, ev_string, ev_void, ev_integer, PROG_ID_VERSION}, + {"!", "not.ent", OP_NOT_ENT, -1, false, ev_entity, ev_void, ev_integer, PROG_ID_VERSION}, + {"!", "not.fnc", OP_NOT_FNC, -1, false, ev_func, ev_void, ev_integer, PROG_ID_VERSION}, - {"", "if", OP_IF, -1, false, ev_float, ev_float, ev_void, PROG_ID_VERSION}, - {"", "ifnot", OP_IFNOT, -1, false, ev_float, ev_float, ev_void, PROG_ID_VERSION}, + {"", "if", OP_IF, -1, false, ev_integer, ev_integer, ev_void, PROG_ID_VERSION}, + {"", "ifnot", OP_IFNOT, -1, false, ev_integer, ev_integer, ev_void, PROG_ID_VERSION}, // calls returns REG_RETURN {"", "call0", OP_CALL0, -1, false, ev_func, ev_void, ev_void, PROG_ID_VERSION}, @@ -120,11 +120,31 @@ opcode_t pr_opcodes[] = { {"", "goto", OP_GOTO, -1, false, ev_float, ev_void, ev_void, PROG_ID_VERSION}, - {"&&", "and", OP_AND, 6, false, ev_float, ev_float, ev_float, PROG_ID_VERSION}, - {"||", "or", OP_OR, 6, false, ev_float, ev_float, ev_float, PROG_ID_VERSION}, + {"&&", "and", OP_AND, 6, false, ev_float, ev_float, ev_integer, PROG_ID_VERSION}, + {"||", "or", OP_OR, 6, false, ev_float, ev_float, ev_integer, PROG_ID_VERSION}, {"&", "bitand", OP_BITAND, 2, false, ev_float, ev_float, ev_float, PROG_ID_VERSION}, {"|", "bitor", OP_BITOR, 2, false, ev_float, ev_float, ev_float, PROG_ID_VERSION}, + + {"+", "add.i", OP_ADD_I, 3, false, ev_integer, ev_integer, ev_integer, PROG_VERSION}, + {"-", "sub.i", OP_SUB_I, 3, false, ev_integer, ev_integer, ev_integer, PROG_VERSION}, + {"*", "mul.i", OP_MUL_I, 2, false, ev_integer, ev_integer, ev_integer, PROG_VERSION}, + {"/", "div.i", OP_DIV_I, 2, false, ev_integer, ev_integer, ev_integer, PROG_VERSION}, + {"&", "bitand.i", OP_BITAND_I, 2, false, ev_integer, ev_integer, ev_integer, PROG_VERSION}, + {"|", "bitor.i", OP_BITOR_I, 2, false, ev_integer, ev_integer, ev_integer, PROG_VERSION}, + {">=", "ge.i", OP_GE_I, 4, false, ev_integer, ev_integer, ev_integer, PROG_VERSION}, + {"<=", "le.i", OP_LE_I, 4, false, ev_integer, ev_integer, ev_integer, PROG_VERSION}, + {">", "gt.i", OP_GT_I, 4, false, ev_integer, ev_integer, ev_integer, PROG_VERSION}, + {"<", "lt.i", OP_LT_I, 4, false, ev_integer, ev_integer, ev_integer, PROG_VERSION}, + {"&&", "and.i", OP_AND_I, 6, false, ev_integer, ev_integer, ev_integer, PROG_VERSION}, + {"||", "or.i", OP_OR_I, 6, false, ev_integer, ev_integer, ev_integer, PROG_VERSION}, + {"!", "not.i", OP_NOT_I, -1, false, ev_integer, ev_integer, ev_integer, PROG_VERSION}, + {"==", "eq.i", OP_EQ_I, 4, false, ev_integer, ev_integer, ev_integer, PROG_VERSION}, + {"!=", "ne.i", OP_NE_I, 4, false, ev_integer, ev_integer, ev_integer, PROG_VERSION}, + {"=", "store.i", OP_STORE_I, 5, true, ev_integer, ev_integer, ev_integer, PROG_VERSION}, + {"=", "storep.i", OP_STOREP_I, 5, true, ev_pointer, ev_integer, ev_integer, PROG_VERSION}, + {".", "load.i", OP_LOAD_I, 1, false, ev_entity, ev_field, ev_integer, PROG_VERSION}, + {0}, }; diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index f82170b0c..ad81a8f85 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -52,7 +52,7 @@ typedef struct expr_s { int func_val; int pointer_val; float quaternion_val[4]; - int int_val; + int integer_val; } e; } expr_t; diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index b61fb51f3..07e6ef120 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -318,7 +318,7 @@ typedef union eval_s union eval_s *ptr; } eval_t; -extern int type_size[8]; +extern int type_size[ev_type_count]; extern def_t *def_for_type[8]; extern type_t type_void; diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index e4a1ded4b..2e75fb0a9 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -88,11 +88,8 @@ get_type (expr_t *e) case ex_func: case ex_pointer: case ex_quaternion: + case ex_integer: return qc_types[e->type]; - case ex_integer: //FIXME int should stay int, at least until code generation - e->type = ex_float; - e->e.float_val = e->e.int_val; - return ev_float; } return ev_void; } @@ -144,62 +141,62 @@ warning (expr_t *e, const char *fmt, ...) va_end (args); } +const char * +get_op_string (int op) +{ + switch (op) { + case OR: + return "||"; + case AND: + return "&&"; + case EQ: + return "=="; + case NE: + return "!="; + case LE: + return "<="; + case GE: + return ">="; + case LT: + return "<"; + case GT: + return ">"; + case '=': + return "="; + case '+': + return "+"; + case '-': + return "-"; + case '*': + return "*"; + case '/': + return "/"; + case '&': + return "&"; + case '|': + return "|"; + case '!': + return "!"; + case '(': + return "("; + case '.': + return "."; + default: + return "unknown"; + } +} + expr_t * type_mismatch (expr_t *e1, expr_t *e2, int op) { etype_t t1, t2; - char opname[4]; t1 = get_type (e1); t2 = get_type (e2); - switch (op) { - case OR: - opname[0] = '|'; - opname[1] = '|'; - opname[2] = 0; - break; - case AND: - opname[0] = '&'; - opname[1] = '&'; - opname[2] = 0; - break; - case EQ: - opname[0] = '='; - opname[1] = '='; - opname[2] = 0; - break; - case NE: - opname[0] = '!'; - opname[1] = '='; - opname[2] = 0; - break; - case LE: - opname[0] = '<'; - opname[1] = '='; - opname[2] = 0; - break; - case GE: - opname[0] = '>'; - opname[1] = '='; - opname[2] = 0; - break; - case LT: - opname[0] = '<'; - opname[1] = 0; - break; - case GT: - opname[0] = '>'; - opname[1] = 0; - break; - default: - opname[0] = op; - opname[1] = 0; - break; - } return error (e1, "type mismatch: %s %s %s", - type_names[t1], opname, type_names[t2]); + type_names[t1], get_op_string (op), type_names[t2]); } expr_t * @@ -348,7 +345,7 @@ print_expr (expr_t *e) case ex_func: case ex_pointer: case ex_integer: - printf ("%d", e->e.int_val); + printf ("%d", e->e.integer_val); break; } } @@ -373,27 +370,27 @@ do_op_string (int op, expr_t *e1, expr_t *e2) break; case LT: e1->type = ex_integer; - e1->e.int_val = strcmp (s1, s2) < 0; + e1->e.integer_val = strcmp (s1, s2) < 0; break; case GT: e1->type = ex_integer; - e1->e.int_val = strcmp (s1, s2) > 0; + e1->e.integer_val = strcmp (s1, s2) > 0; break; case LE: e1->type = ex_integer; - e1->e.int_val = strcmp (s1, s2) <= 0; + e1->e.integer_val = strcmp (s1, s2) <= 0; break; case GE: e1->type = ex_integer; - e1->e.int_val = strcmp (s1, s2) >= 0; + e1->e.integer_val = strcmp (s1, s2) >= 0; break; case EQ: e1->type = ex_integer; - e1->e.int_val = strcmp (s1, s2) == 0; + e1->e.integer_val = strcmp (s1, s2) == 0; break; case NE: e1->type = ex_integer; - e1->e.int_val = strcmp (s1, s2) != 0; + e1->e.integer_val = strcmp (s1, s2) != 0; break; default: return error (e1, "invalid operand for string"); @@ -429,34 +426,36 @@ do_op_float (int op, expr_t *e1, expr_t *e2) e1->e.float_val = (int)f1 | (int)f2; break; case AND: - e1->e.float_val = f1 && f2; + e1->type = ex_integer; + e1->e.integer_val = f1 && f2; break; case OR: - e1->e.float_val += f1 || f2; + e1->type = ex_integer; + e1->e.integer_val = f1 || f2; break; case LT: e1->type = ex_integer; - e1->e.int_val = f1 < f2; + e1->e.integer_val = f1 < f2; break; case GT: e1->type = ex_integer; - e1->e.int_val = f1 > f2; + e1->e.integer_val = f1 > f2; break; case LE: e1->type = ex_integer; - e1->e.int_val = f1 <= f2; + e1->e.integer_val = f1 <= f2; break; case GE: e1->type = ex_integer; - e1->e.int_val = f1 >= f2; + e1->e.integer_val = f1 >= f2; break; case EQ: e1->type = ex_integer; - e1->e.int_val = f1 == f2; + e1->e.integer_val = f1 == f2; break; case NE: e1->type = ex_integer; - e1->e.int_val = f1 != f2; + e1->e.integer_val = f1 != f2; break; default: return error (e1, "invalid operand for string"); @@ -485,13 +484,13 @@ do_op_vector (int op, expr_t *e1, expr_t *e2) break; case EQ: e1->type = ex_integer; - e1->e.int_val = (v1[0] == v2[0]) + e1->e.integer_val = (v1[0] == v2[0]) && (v1[1] == v2[1]) && (v1[2] == v2[2]); break; case NE: e1->type = ex_integer; - e1->e.int_val = (v1[0] == v2[0]) + e1->e.integer_val = (v1[0] == v2[0]) || (v1[1] != v2[1]) || (v1[2] != v2[2]); break; @@ -501,6 +500,70 @@ do_op_vector (int op, expr_t *e1, expr_t *e2) return e1; } +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; + printf ("%d %s %d\n", i1, get_op_string (op), i2); + + 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) { @@ -516,6 +579,8 @@ static expr_t *(*do_op[]) (int op, expr_t *e1, expr_t *e2) = { do_op_huh, do_op_huh, do_op_huh, + do_op_huh, + do_op_integer, }; static expr_t * @@ -563,7 +628,6 @@ test_expr (expr_t *e, int test) return unary_expr ('!', e); switch (get_type (e)) { - case ev_integer://FIXME just return e when int opcodes are supported case ev_type_count: case ev_void: error (e, "internal error"); @@ -572,6 +636,7 @@ test_expr (expr_t *e, int test) new = new_expr (); new->type = ex_string; break; + case ev_integer: case ev_float: return e; case ev_vector: @@ -633,7 +698,7 @@ binary_expr (int op, expr_t *e1, expr_t *e2) if (t1 == t2) { expr_t *e = new_binary_expr (op, e1, e2); if ((op >= OR && op <= GT) || (op == '*' && t1 == ev_vector)) - e->e.expr.type = &type_float; + e->e.expr.type = &type_integer; else e->e.expr.type = types[t1]; if (op == '=' && e1->type == ex_expr && e1->e.expr.op == '.') { @@ -647,6 +712,12 @@ binary_expr (int op, expr_t *e1, expr_t *e2) expr_t *e = new_binary_expr (op, e1, e2); e->e.expr.type = &type_vector; return e; + } else if (e2->type == ex_integer) { + expr_t *e = new_binary_expr (op, e1, e2); + e->e.expr.type = &type_float; + e2->type = ex_float; + e2->e.float_val = e2->e.integer_val; + return e; } else { goto type_mismatch; } @@ -695,7 +766,7 @@ unary_expr (int op, expr_t *e) return n; } case ex_integer: - e->e.int_val *= -1; + e->e.integer_val *= -1; return e; case ex_float: e->e.float_val *= -1; @@ -733,24 +804,24 @@ unary_expr (int op, expr_t *e) return n; } case ex_integer: - e->e.int_val = !e->e.int_val; + e->e.integer_val = !e->e.integer_val; return e; case ex_float: - e->e.int_val = !e->e.float_val; + e->e.integer_val = !e->e.float_val; e->type = ex_integer; return e; case ex_string: - e->e.int_val = !e->e.string_val || !e->e.string_val[0]; + e->e.integer_val = !e->e.string_val || !e->e.string_val[0]; e->type = ex_integer; return e; case ex_vector: - e->e.int_val = !e->e.vector_val[0] + 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: - e->e.int_val = !e->e.quaternion_val[0] + e->e.integer_val = !e->e.quaternion_val[0] && !e->e.quaternion_val[1] && !e->e.quaternion_val[2] && !e->e.quaternion_val[3]; @@ -830,6 +901,13 @@ emit_statement (int sline, opcode_t *op, def_t *var_a, def_t *var_b, def_t *var_ dstatement_t *statement; def_t *ret; + 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; diff --git a/tools/qfcc/source/pr_imm.c b/tools/qfcc/source/pr_imm.c index dcdb51796..ab34cdbab 100644 --- a/tools/qfcc/source/pr_imm.c +++ b/tools/qfcc/source/pr_imm.c @@ -32,6 +32,7 @@ static hashtab_t *field_imm_defs; static hashtab_t *func_imm_defs; static hashtab_t *pointer_imm_defs; static hashtab_t *quaternion_imm_defs; +static hashtab_t *integer_imm_defs; static const char * string_imm_get_key (void *_def, void *unused) @@ -176,32 +177,39 @@ PR_ReuseConstant (expr_t *expr, def_t *def) func_imm_defs = Hash_NewTable (16381, int_imm_get_key, 0, "func"); pointer_imm_defs = Hash_NewTable (16381, int_imm_get_key, 0, "pointer"); quaternion_imm_defs = Hash_NewTable (16381, quaternion_imm_get_key, 0, 0); + integer_imm_defs = Hash_NewTable (16381, int_imm_get_key, 0, "integer"); } switch (e.type) { case ex_entity: - sprintf (rep, "\001entity:%08X\001", e.e.int_val); + sprintf (rep, "\001entity:%08X\001", e.e.integer_val); tab = float_imm_defs; type = &type_entity; break; case ex_field: - sprintf (rep, "\001field:%08X\001", e.e.int_val); + sprintf (rep, "\001field:%08X\001", e.e.integer_val); tab = float_imm_defs; type = &type_field; break; case ex_func: - sprintf (rep, "\001func:%08X\001", e.e.int_val); + sprintf (rep, "\001func:%08X\001", e.e.integer_val); tab = float_imm_defs; type = &type_function; break; case ex_pointer: - sprintf (rep, "\001pointer:%08X\001", e.e.int_val); + sprintf (rep, "\001pointer:%08X\001", e.e.integer_val); tab = pointer_imm_defs; type = &type_pointer; break; case ex_integer: - e.e.float_val = e.e.int_val; //FIXME want ints rather than floats + if (!def || def->type != &type_float) { + sprintf (rep, "\001integer:%08X\001", e.e.integer_val); + tab = integer_imm_defs; + type = &type_integer; + break; + } + e.e.float_val = e.e.integer_val; case ex_float: - sprintf (rep, "\001float:%08X\001", e.e.int_val); + sprintf (rep, "\001float:%08X\001", e.e.integer_val); tab = float_imm_defs; type = &type_float; break; @@ -258,7 +266,7 @@ PR_ReuseConstant (expr_t *expr, def_t *def) cn->initialized = 1; // copy the immediate to the global area if (e.type == ex_string) - e.e.int_val = CopyString (e.e.string_val); + e.e.integer_val = CopyString (e.e.string_val); memcpy (pr_globals + cn->ofs, &e.e, 4 * type_size[type->type]); diff --git a/tools/qfcc/source/pr_lex.c b/tools/qfcc/source/pr_lex.c index 4306a9c2f..25c7fab36 100644 --- a/tools/qfcc/source/pr_lex.c +++ b/tools/qfcc/source/pr_lex.c @@ -65,7 +65,7 @@ type_t type_integer = { ev_integer, &def_integer }; type_t type_floatfield = { ev_field, &def_field, NULL, &type_float }; -int type_size[8] = { 1, 1, 1, 3, 1, 1, 1, 1 }; +int type_size[ev_type_count] = { 1, 1, 1, 3, 1, 1, 1, 1, 4, 1 }; def_t def_void = { &type_void, "temp" }; def_t def_string = { &type_string, "temp" }; diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index beb406ad4..abfee4e94 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -47,7 +47,7 @@ m ([\-+]?) "//".* /* nothing to do */ {DIGIT}+ { - yylval.int_val = atoi (yytext); + yylval.integer_val = atoi (yytext); return INT_VAL; } @@ -144,18 +144,20 @@ typedef struct { } keyword_t; static keyword_t keywords[] = { - {"float", TYPE, &type_float }, - {"vector", TYPE, &type_vector}, - {"entity", TYPE, &type_entity}, - {"string", TYPE, &type_string}, - {"void", TYPE, &type_void }, - {"local", LOCAL, 0 }, - {"return", RETURN, 0 }, - {"while", WHILE, 0 }, - {"do", DO, 0 }, - {"if", IF, 0 }, - {"else", ELSE, 0 }, - {"for", FOR, 0 }, + {"void", TYPE, &type_void }, + {"float", TYPE, &type_float }, + {"string", TYPE, &type_string }, + {"vector", TYPE, &type_vector }, + {"entity", TYPE, &type_entity }, + {"quaternion", TYPE, &type_quaternion}, + {"integer", TYPE, &type_integer }, + {"local", LOCAL, 0 }, + {"return", RETURN, 0 }, + {"while", WHILE, 0 }, + {"do", DO, 0 }, + {"if", IF, 0 }, + {"else", ELSE, 0 }, + {"for", FOR, 0 }, }; static const char * @@ -240,7 +242,7 @@ do_grab (char *token) return -grab_other; frame = Hash_Find (frame_tab, token); if (frame) { - yylval.int_val = frame->num; + yylval.integer_val = frame->num; return INT_VAL; } return 0; diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index d406b8ed2..8f78ef4a5 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -37,7 +37,7 @@ typedef struct { def_t *def; type_t *type; expr_t *expr; - int int_val; + int integer_val; float float_val; char *string_val; float vector_val[3]; @@ -55,7 +55,7 @@ typedef struct { %left '.' %token NAME STRING_VAL -%token INT_VAL +%token INT_VAL %token FLOAT_VAL %token VECTOR_VAL %token QUATERNION_VAL @@ -206,7 +206,7 @@ opt_initializer expr_t *e = new_expr (); e->type = ex_def; e->e.def = current_def; - append_expr (local_expr, new_binary_expr ('=', e, $2)); + append_expr (local_expr, binary_expr ('=', e, $2)); } else { current_def = PR_ReuseConstant ($2, current_def); } @@ -223,7 +223,7 @@ opt_initializer f = new_function (); f->builtin = $3->type == ex_integer - ? $3->e.int_val : (int)$3->e.float_val; + ? $3->e.integer_val : (int)$3->e.float_val; f->def = current_def; build_function (f); finish_function (f); @@ -501,7 +501,7 @@ const { $$ = new_expr (); $$->type = ex_integer; - $$->e.int_val = $1; + $$->e.integer_val = $1; } ; diff --git a/tools/qwaq/builtins.c b/tools/qwaq/builtins.c index 64fa434a3..606925aab 100644 --- a/tools/qwaq/builtins.c +++ b/tools/qwaq/builtins.c @@ -8,10 +8,10 @@ #include #include -#define RETURN_EDICT(p, e) ((p)->pr_globals[OFS_RETURN].int_var = EDICT_TO_PROG(p, e)) -#define RETURN_STRING(p, s) ((p)->pr_globals[OFS_RETURN].int_var = PR_SetString((p), s)) +#define RETURN_EDICT(p, e) ((p)->pr_globals[OFS_RETURN].integer_var = EDICT_TO_PROG(p, e)) +#define RETURN_STRING(p, s) ((p)->pr_globals[OFS_RETURN].integer_var = PR_SetString((p), s)) -float *read_result; //FIXME: eww +int *read_result; //FIXME: eww static void bi_fixme (progs_t *pr) @@ -37,37 +37,37 @@ bi_GarbageCollect (progs_t *pr) static void bi_errno (progs_t *pr) { - G_FLOAT (pr, OFS_RETURN) = errno; + G_INT (pr, OFS_RETURN) = errno; } static void -bi_strerror (progs_t *pr) // FIXME: make INT when qc int +bi_strerror (progs_t *pr) { - int err = G_FLOAT (pr, OFS_PARM0); + int err = G_INT (pr, OFS_PARM0); RETURN_STRING (pr, strerror (err)); } static void -bi_open (progs_t *pr) // FIXME: make INT when qc int +bi_open (progs_t *pr) { char *path = G_STRING (pr, OFS_PARM0); - int flags = G_FLOAT (pr, OFS_PARM1); - int mode = G_FLOAT (pr, OFS_PARM2); + int flags = G_INT (pr, OFS_PARM1); + int mode = G_INT (pr, OFS_PARM2); G_INT (pr, OFS_RETURN) = open (path, flags, mode); } static void -bi_close (progs_t *pr) // FIXME: make INT when qc int +bi_close (progs_t *pr) { int handle = G_INT (pr, OFS_PARM0); - G_FLOAT (pr, OFS_RETURN) = close (handle); + G_INT (pr, OFS_RETURN) = close (handle); } static void -bi_read (progs_t *pr) // FIXME: make INT when qc int +bi_read (progs_t *pr) { int handle = G_INT (pr, OFS_PARM0); - int count = G_FLOAT (pr, OFS_PARM1); + int count = G_INT (pr, OFS_PARM1); int res; char *buffer; @@ -81,23 +81,23 @@ bi_read (progs_t *pr) // FIXME: make INT when qc int } static void -bi_write (progs_t *pr) // FIXME: make INT when qc int +bi_write (progs_t *pr) { int handle = G_INT (pr, OFS_PARM0); char *buffer = G_STRING (pr, OFS_PARM1); - int count = G_FLOAT (pr, OFS_PARM2); + int count = G_INT (pr, OFS_PARM2); - G_FLOAT (pr, OFS_RETURN) = write (handle, buffer, count); + G_INT (pr, OFS_RETURN) = write (handle, buffer, count); } static void -bi_seek (progs_t *pr) // FIXME: make INT when qc int +bi_seek (progs_t *pr) { int handle = G_INT (pr, OFS_PARM0); - int pos = G_FLOAT (pr, OFS_PARM1); - int whence = G_FLOAT (pr, OFS_PARM2); + int pos = G_INT (pr, OFS_PARM1); + int whence = G_INT (pr, OFS_PARM2); - G_FLOAT (pr, OFS_RETURN) = lseek (handle, pos, whence); + G_INT (pr, OFS_RETURN) = lseek (handle, pos, whence); } static void diff --git a/tools/qwaq/defs.qc b/tools/qwaq/defs.qc index 1cba4b46f..666384bc1 100644 --- a/tools/qwaq/defs.qc +++ b/tools/qwaq/defs.qc @@ -1,12 +1,12 @@ void (string str) print = #1; void () garbage_collect = #2; -float () errno = #3; -string (float err) strerror = #4; -float (...) open = #5; // string path, float flags[, float mode] -float (float handle) close = #6; -string (float handle, float count) read = #7; // FIXME: cf read_result -float (float handle, string buffer, float count) write = #8; -float (float handle, float pos, float whence) seek = #9; +integer () errno = #3; +string (integer err) strerror = #4; +integer (...) open = #5; // string path, float flags[, float mode] +integer (integer handle) close = #6; +string (integer handle, integer count) read = #7; // FIXME: cf read_result +integer (integer handle, string buffer, integer count) write = #8; +integer (integer handle, integer pos, integer whence) seek = #9; void() traceon = #10; // turns statment trace on void() traceoff = #11; @@ -14,7 +14,7 @@ void() traceoff = #11; float time; entity self; -float read_result; // FIXME: hacky (cf read) +integer read_result; // FIXME: hacky (cf read) .float nextthink; .void() think; diff --git a/tools/qwaq/main.c b/tools/qwaq/main.c index cc70148a1..3192c14a1 100644 --- a/tools/qwaq/main.c +++ b/tools/qwaq/main.c @@ -22,7 +22,7 @@ void BI_Init (progs_t *progs); extern char *type_name[]; extern cvar_t *developer; -extern float *read_result; //FIXME: eww +extern int *read_result; //FIXME: eww int main () @@ -101,7 +101,7 @@ main () } printf ("\n"); #endif - read_result = (float*)PR_GetGlobalPointer (&progs, "read_result"); + read_result = (int*)PR_GetGlobalPointer (&progs, "read_result"); main_func = PR_GetFunctionIndex (&progs, "main"); PR_ExecuteProgram (&progs, main_func); return G_FLOAT (&progs, OFS_RETURN); diff --git a/tools/qwaq/main.qc b/tools/qwaq/main.qc index 11cc84d69..a1bf20634 100644 --- a/tools/qwaq/main.qc +++ b/tools/qwaq/main.qc @@ -14,7 +14,7 @@ void () eek; float () main = { local float messed_or; - local float handle; + local integer handle; local string buffer; traceon(); @@ -45,7 +45,7 @@ float () baz = void (float x) test = { local string str; - local float urk = 0; + local integer urk = 0; if (urk) { urk = foo || snafu; @@ -68,6 +68,11 @@ void () blarg = } }; +float (float baz) test_int = +{ + return baz; +}; + .entity owner; entity sent; void () eek = @@ -76,6 +81,7 @@ void () eek = if (sent && sent.owner != self ) self.origin = '0 0 0'; self.origin = self.origin + '1 2 3'; + test_int (1); traceoff(); }; @@ -87,6 +93,6 @@ void () assign = foo = bar; foo = bar = 1; foo = bar = bar + 1; - foo = self.nextthink = self.nextthink + 1; - self.frame = self.nextthink = self.nextthink + 1; + foo = self.nextthink = self.nextthink + 1.0; + self.frame = self.nextthink = self.nextthink + 1.0; };