# include "../ingres.h" # include "../aux.h" # include "../tree.h" # include "../symbol.h" # include "ovqp.h" /* ** TYPECHECK ** ** Performs typechecking and conversions where appropriate . ** Prohibits mixed type expressions. */ typecheck(pp1, pp2, opval) struct symbol *pp1, *pp2; int opval; { register struct symbol *p1, *p2; register int i; p1 = pp1; p2 = pp2; i = (p1->type == CHAR & p2->type == CHAR); /* c is true only if both are chars */ switch (opval) { case opCONCAT: if (!i) ov_err(NUMERIC); /* numeric in a char operator */ return; /* else no further checking is needed */ case opADD: case opSUB: case opMUL: case opDIV: case opPOW: case opMOD: if (i) ov_err(BADCHAR); /* arithmetic operation on two character fields */ } /* first check for identical types of symbols */ if (p1->type == p2->type) { if (p1->len == p2->len) return; /* lengths are different. make p2 point to the smaller one */ if (p1->len < p2->len) { p2 = p1; p1 = pp2; } switch (p2->type) { case INT: if (p1->len == 4) i2toi4(p2); case CHAR: return; /* done if char or int */ case FLOAT: f8tof4(p2); return; } } /* at least one symbol is an INT or FLOAT. The other can't be a CHAR */ if (p1->type == CHAR || p2->type == CHAR) ov_err(BADMIX); /* attempting binary operation on one CHAR field with a numeric */ /* one symbol is an INT and the other a FLOAT */ if (p2->type == INT) { /* exchange so that p1 is an INT and p2 is a FLOAT */ p1 = p2; p2 = pp1; } /* p1 is an INT and p2 a FLOAT */ itof(p1); if (p2->len == 4) f8tof4(p2); } typecoerce(tosx, ntype, nlen) struct stacksym *tosx; int ntype; int nlen; /* ** Coerce the top of stack symbol to the ** specified type and length. If the current ** value is a character then it must be converted ** to numeric. A user error will occure is the ** char is not syntaxtically correct. */ { register struct stacksym *tos; register char *cp; register int *val; int ret; char temp[256]; tos = tosx; if (tos->type == CHAR) { val = tos->value; cp = temp; bmove(cpderef(tos->value), cp, tos->len & I1MASK); cp[tos->len & I1MASK] = '\0'; if (ntype == FLOAT) ret = atof(cp, val); else { if (nlen == 4) ret = atol(cp, val); else ret = atoi(cp, val); } if (ret < 0) ov_err(CHARCONVERT); tos->type = ntype; tos->len = nlen; } else rcvt(tos, ntype, nlen); } i2toi4(pp) struct symbol *pp; { register struct symbol *p; p = pp; i4deref(p->value) = i2deref(p->value); p->len = 4; } i4toi2(pp) struct symbol *pp; { register struct symbol *p; p = pp; i2deref(p->value) = i4deref(p->value); p->len = 2; } itof(pp) struct symbol *pp; { register struct symbol *p; p = pp; if (p->len == 4) f8deref(p->value) = i4deref(p->value); else f8deref(p->value) = i2deref(p->value); p->type = FLOAT; p->len= 8; } ftoi2(pp) struct symbol *pp; { register struct symbol *p; p = pp; i2deref(p->value) = f8deref(p->value); p->type = INT; p->len = 2; } ftoi4(pp) struct symbol *pp; { register struct symbol *p; p = pp; i4deref(p->value) = f8deref(p->value); p->type = INT; p->len = 4; } f8tof4(pp) struct symbol *pp; { register struct symbol *p; p = pp; f4deref(p->value) = f8deref(p->value); p->len = 4; }