diff --git a/tools/qfcc/source/dot_expr.c b/tools/qfcc/source/dot_expr.c index e5b5e87ea..04784856a 100644 --- a/tools/qfcc/source/dot_expr.c +++ b/tools/qfcc/source/dot_expr.c @@ -90,6 +90,8 @@ get_op_string (int op) case SHR: return ">>"; case '.': return "."; case 'C': return ""; + case CROSS: return "@cross"; + case DOT: return "@dot"; default: return "unknown"; } diff --git a/tools/qfcc/source/expr_binary.c b/tools/qfcc/source/expr_binary.c index f533b38cd..47dc3ae5c 100644 --- a/tools/qfcc/source/expr_binary.c +++ b/tools/qfcc/source/expr_binary.c @@ -52,6 +52,7 @@ static expr_t *func_compare (int op, expr_t *e1, expr_t *e2); static expr_t *inverse_multiply (int op, expr_t *e1, expr_t *e2); static expr_t *double_compare (int op, expr_t *e1, expr_t *e2); static expr_t *vector_compare (int op, expr_t *e1, expr_t *e2); +static expr_t *vector_multiply (int op, expr_t *e1, expr_t *e2); static expr_type_t string_string[] = { {'+', &type_string}, @@ -145,7 +146,9 @@ static expr_type_t vector_float[] = { static expr_type_t vector_vector[] = { {'+', &type_vector}, {'-', &type_vector}, - {'*', &type_float}, + {DOT, &type_vector}, + {CROSS, &type_vector}, + {'*', 0, 0, 0, vector_multiply}, {EQ, 0, 0, 0, vector_compare}, {NE, 0, 0, 0, vector_compare}, {0, 0} @@ -738,6 +741,20 @@ vector_compare (int op, expr_t *e1, expr_t *e2) return new_horizontal_expr (hop, e, &type_int); } +static expr_t *vector_multiply (int op, expr_t *e1, expr_t *e2) +{ + expr_t *e = new_binary_expr ('*', e1, e2); + if (options.code.progsversion < PROG_VERSION) { + // vector * vector is dot product in v6 progs (ick) + e->e.expr.type = &type_float; + } else { + // component-wise multiplication + e->e.expr.type = &type_vector; + } + + return e; +} + static expr_t * double_compare (int op, expr_t *e1, expr_t *e2) { diff --git a/tools/qfcc/source/qc-lex.l b/tools/qfcc/source/qc-lex.l index 7ce445539..c2db6db0c 100644 --- a/tools/qfcc/source/qc-lex.l +++ b/tools/qfcc/source/qc-lex.l @@ -386,6 +386,9 @@ static keyword_t qf_keywords[] = { {"@args", ARGS, 0 }, {"@va_list", TYPE, &type_va_list }, {"@param", TYPE, &type_param }, + + {"@cross", CROSS, 0 }, + {"@dot", DOT, 0 }, }; // These keywors are always available. Other than @system and @overload, they diff --git a/tools/qfcc/source/qc-parse.y b/tools/qfcc/source/qc-parse.y index 0e23c1eb2..7d294db13 100644 --- a/tools/qfcc/source/qc-parse.y +++ b/tools/qfcc/source/qc-parse.y @@ -139,6 +139,7 @@ int yylex (void); %left SHL SHR %left '+' '-' %left '*' '/' '%' MOD +%left CROSS DOT %right SIZEOF UNARY INCOP %left HYPERUNARY %left '.' '(' '[' @@ -1621,6 +1622,8 @@ expr | expr '^' expr { $$ = binary_expr ('^', $1, $3); } | expr '%' expr { $$ = binary_expr ('%', $1, $3); } | expr MOD expr { $$ = binary_expr (MOD, $1, $3); } + | expr CROSS expr { $$ = binary_expr (CROSS, $1, $3); } + | expr DOT expr { $$ = binary_expr (DOT, $1, $3); } ; texpr diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 3de08e449..bce46f8cd 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -604,6 +604,8 @@ convert_op (int op) case SHL: return "shl"; case SHR: return "shr"; case '.': return "load"; + case CROSS: return "cross"; + case DOT: return "dot"; default: return 0; } @@ -1568,6 +1570,14 @@ expr_expr (sblock_t *sblock, expr_t *e, operand_t **op) if (strcmp (opcode, "ne") == 0 && is_string (get_type (e->e.expr.e1))) { opcode = "cmp"; } + if (strcmp (opcode, "dot") == 0) { + if (is_vector (get_type (e->e.expr.e1))) { + opcode = "vdot"; + } + if (is_quaternion (get_type (e->e.expr.e1))) { + opcode = "qdot"; + } + } s = new_statement (st_expr, opcode, e); sblock = statement_subexpr (sblock, e->e.expr.e1, &s->opa); sblock = statement_subexpr (sblock, e->e.expr.e2, &s->opb);