This commit is contained in:
Oliver Lehmann 1989-12-11 11:20:48 +00:00
parent 30af3311d4
commit f94914987d
1 changed files with 714 additions and 0 deletions

View File

@ -0,0 +1,714 @@
# include <stdio.h>
# include "gen.h"
# include "../h/dbs.h"
# include "../h/aux.h"
# include "../h/catalog.h"
# ifdef BC
# define AND 0
# define AOP 4 /* AGGREGATE OPERATORS */
# define BOP 3 /* BINARY OPERATORS */
# define COP 5 /* CONSTANT OPERATORS */
# define OR 1
# define RESDOM 11 /* RESULT DOMAIN NUMBER */
# define UOP 2 /* UNARY OPERATORS */
# define mdDEL 4
# define mdREPL 3
# define opABS 10
# define opADD 0
# define opANY 8
# define opASCII 7
# define opATAN 3
# define opAVG 4
# define opAVGU 5
# define opCNT 0
# define opCNTU 1
# define opCONCAT 12
# define opCOS 4
# define opDBA 0
# define opDIV 3
# define opEQ 5
# define opEXP 11
# define opFLT4 15
# define opFLT8 16
# define opGAMMA 5
# define opGE 10
# define opGT 9
# define opINT1 12
# define opINT2 13
# define opINT4 14
# define opLE 8
# define opLOG 6
# define opLT 7
# define opMAX 7
# define opMIN 6
# define opMINUS 1
# define opMOD 11
# define opMUL 2
# define opNE 6
# define opNOT 2
# define opPLUS 0
# define opPOW 4
# define opSIN 8
# define opSQRT 9
# define opSUB 1
# define opSUM 2
# define opSUMU 3
# define opUSERCODE 1
# else
# include "../h/symbol.h"
# endif
# include "../h/tree.h"
# include "../h/access.h"
# include "../h/pipes.h"
# include "ovqp.h"
struct stacksym Stack[STACKSIZ]; /* stack for OVQP interpreter */
extern double pow();
extern double sqrt();
extern double log();
extern double exp();
extern double sin();
extern double cos();
extern double atan();
extern double gamma();
/*
** INTERPRET
**
** Processes the retrieved tuple from the Source relation
** according to the symbols in the list. Recognition
** of characteristic delimiters and separators initiates
** action appropriate to a target list or qualification list
** as the case may be.
**
** Between delimiters, the symbol list is expected to be in
** Polish postfix form. A qualification list is further
** expected to be in conjunctive normal form, with Boolean
** operators infixed.
*/
SYMBOL *interpret(list)
SYMBOL **list; /* ptr to list of sym pointers */
{
register struct stacksym *tos;
register short *val1; /* ptr to value of operand 1 */
register short *val2; /* ptr to value of operand 2 */
register SYMBOL *op1; /* operand popped off stack */
register SYMBOL *op2; /* operand popped off stack */
register int opval;
int optype;
int l1;
char *s1;
int byflag;
long hitid;
extern char *AAusercode;
extern ov_err();
int cb_mark;
extern char *Ovqpbuf;
# ifdef xOTR1
AAtTfp(23, 0, "INTERP: list=0%o\n", list);
# endif
# ifdef xOTM
if (AAtTf(76, 2))
timtrace(11, 0);
# endif
byflag = (list == Bylist); /* set byflag if aggregate function */
tos = Stack - 1;
/* reset the concat and ascii operator buffer */
seterr(Ovqpbuf, CBUFULL, ov_err);
cb_mark = markbuf(Ovqpbuf);
loop:
# ifdef xOTR1
if (AAtTf(23, 1) && tos >= Stack)
{
printf("\ttops of stack=");
prstack(tos); /* print top of stack element */
}
# endif
/* check for stack overflow */
l1 = getsymbol(++tos, &list);
if (l1)
{
# ifdef xOTM
if (AAtTf(76, 2))
timtrace(12, 0);
# endif
freebuf(Ovqpbuf, cb_mark);
return ((SYMBOL *) tos);
}
optype = ((SYMBOL *) tos)->type;
opval = *((SYMBOL *) tos)->value;
tos--; /* assume that stack will be poped */
switch (optype)
{
case INT:
case FLOAT:
case CHAR:
++tos; /* just leave symbol on stack */
goto loop;
case COP:
++tos; /* new symbol goes on stack */
((SYMBOL *) tos)->type = CHAR;
val1 = ((SYMBOL *) tos)->value;
switch (opval)
{
case opDBA:
((STRINGP *) val1)->stringp = AAdmin.adhdr.adowner;
((SYMBOL *) tos)->len = sizeof (short);
goto loop;
case opUSERCODE:
((STRINGP *) val1)->stringp = AAusercode;
((SYMBOL *) tos)->len = sizeof (short);
goto loop;
}
case AND: /* if top value false return immediately */
if (!*((SYMBOL *) tos)->value)
{
# ifdef xOTM
if (AAtTf(76, 2))
timtrace(12, 0);
# endif
freebuf(Ovqpbuf, cb_mark);
return ((SYMBOL *) tos);
}
else
--tos;
freebuf(Ovqpbuf, cb_mark);
goto loop;
case OR: /* if top value is true then skip to
** end of disjunction. */
if (*((SYMBOL *) tos)->value)
{
tos++;
do
{
getsymbol(tos, &list);
} while (((SYMBOL *) tos)->type != AND);
optype = AND;
--tos;
}
--tos;
goto loop;
case RESDOM:
freebuf(Ovqpbuf, cb_mark); /* init the concat and ascii buffer */
val1 = ((SYMBOL *) tos)->value;
if (Result)
{
if (opval) /* if gt zero then opval represents a real domain */
{
if (byflag)
opval++; /* skip over count field for ag functs */
rcvt(tos, Result->relfrmt[opval], Result->relfrml[opval]);
tout(tos, Outtup+Result->reloff[opval], Result->relfrml[opval]);
}
else /* opval refers to the tid and this is an update */
{
Uptid = ((I4TYPE *) val1)->i4type; /* copy tid */
if (Ov_qmode == ((int) mdREPL) || (Diffrel && Ov_qmode == ((int) mdDEL) && ctoi(Result->reldum.relindxd) == SECBASE ))
{
/* Origtup must be left with the orig
** unaltered tuple, and Outtup must
** be initialized with the orig tuple.
**
** Outtup only matters with REPL.
** Scan() sets up Origtup so when
** Source == Result, origtup is already
** correct.
*/
if (Diffrel)
{
if (l1 = AAam_get(Result, &Uptid, &hitid, Origtup, CURTUP))
AAsyserr(17002, Uptid, l1);
AAbmove(Origtup, Outtup, Result->reldum.relwid);
}
else
{
AAbmove(Intup, Outtup, Result->reldum.relwid);
}
}
}
}
else
{
if (Eql)
eqlatt(tos); /* send attribute to EQL */
else
{
s1 = (char *) ((SYMBOL *) tos)->value;
if (((SYMBOL *) tos)->type == CHAR)
s1 = ((STRINGP *) s1)->stringp;
else if (((SYMBOL *) tos)->type == INT && ((SYMBOL *) tos)->len == sizeof (char))
((I1TYPE *) s1)->i1type = ((I2TYPE *) s1)->i2type;
# ifndef NO_F4
else if (((SYMBOL *) tos)->type == FLOAT && ((SYMBOL *) (tos + 1))->len == sizeof (float))
{
((F4TYPE *) s1)->f4type = ((F8TYPE *) s1)->f8type;
((SYMBOL *) tos)->len = sizeof (float);
}
# endif
/* print attribute */
AApratt(((SYMBOL *) tos)->type, ctou(((SYMBOL *) tos)->len), s1);
}
}
--tos;
goto loop;
case BOP:
op2 = (SYMBOL *) tos--;
op1 = (SYMBOL *) tos;
typecheck(op1, op2, opval);
val1 = op1->value;
val2 = op2->value;
switch (((SYMBOL *) tos)->type)
{
case INT:
switch (((SYMBOL *) tos)->len)
{
case sizeof (char):
case sizeof (short):
switch (opval)
{
case opADD:
*val1 += *val2;
goto loop;
case opSUB:
*val1 -= *val2;
goto loop;
case opMUL:
*val1 *= *val2;
goto loop;
case opDIV:
*val1 /= *val2;
goto loop;
case opMOD:
*val1 %= *val2;
goto loop;
case opPOW:
itof8(op1);
itof8(op2);
((F8TYPE *) val1)->f8type = pow(((F8TYPE *) val1)->f8type, ((F8TYPE *) val2)->f8type);
goto loop;
/* relational operator */
default:
l1 = *val1 - *val2;
*val1 = relop_interp(opval, l1);
goto loop;
}
case sizeof (long):
switch (opval)
{
case opADD:
((I4TYPE *) val1)->i4type += ((I4TYPE *) val2)->i4type;
goto loop;
case opSUB:
((I4TYPE *) val1)->i4type -= ((I4TYPE *) val2)->i4type;
goto loop;
case opMUL:
((I4TYPE *) val1)->i4type *= ((I4TYPE *) val2)->i4type;
goto loop;
case opDIV:
((I4TYPE *) val1)->i4type /= ((I4TYPE *) val2)->i4type;
goto loop;
case opMOD:
((I4TYPE *) val1)->i4type %= ((I4TYPE *) val2)->i4type;
goto loop;
case opPOW:
itof8(op1);
itof8(op2);
((F8TYPE *) val1)->f8type = pow(((F8TYPE *) val1)->f8type, ((F8TYPE *) val2)->f8type);
goto loop;
/* relational operator */
default:
((SYMBOL *) tos)->len = sizeof (short);
if (((I4TYPE *) val1)->i4type > ((I4TYPE *) val2)->i4type)
l1 = 1;
else
if (((I4TYPE *) val1)->i4type == ((I4TYPE *) val2)->i4type)
l1 = 0;
else
l1 = -1;
*val1 = relop_interp(opval, l1);
goto loop;
}
}
case FLOAT:
switch (opval)
{
case opADD:
((F8TYPE *) val1)->f8type += ((F8TYPE *) val2)->f8type;
goto loop;
case opSUB:
((F8TYPE *) val1)->f8type -= ((F8TYPE *) val2)->f8type;
goto loop;
case opMUL:
((F8TYPE *) val1)->f8type *= ((F8TYPE *) val2)->f8type;
goto loop;
case opDIV:
((F8TYPE *) val1)->f8type /= ((F8TYPE *) val2)->f8type;
goto loop;
case opPOW:
((F8TYPE *) val1)->f8type = pow(((F8TYPE *) val1)->f8type, ((F8TYPE *) val2)->f8type);
goto loop;
default:
((SYMBOL *) tos)->type = INT;
((SYMBOL *) tos)->len = sizeof (short);
if (((F8TYPE *) val1)->f8type > ((F8TYPE *) val2)->f8type)
l1 = 1;
else
if (((F8TYPE *) val1)->f8type == ((F8TYPE *) val2)->f8type)
l1 = 0;
else
l1 = -1;
*val1 = relop_interp(opval, l1);
goto loop;
}
case CHAR:
if (opval == (int) opCONCAT)
{
concatsym(op1, op2); /* concatenate the two symbols */
goto loop;
}
l1 = lexcomp(((STRINGP *) val1)->stringp, ctou(op1->len), ((STRINGP *) val2)->stringp, ctou(op2->len));
((SYMBOL *) tos)->type = INT;
((SYMBOL *) tos)->len = sizeof (short);
*val1 = relop_interp(opval, l1);
goto loop;
} /* end of BOP */
case UOP:
val1 = ((SYMBOL *) tos)->value;
switch (opval)
{
case opMINUS:
case opABS:
if (((SYMBOL *) tos)->type == CHAR)
ov_err(BADUOPC);
l1 = opval == (int) opMINUS;
switch (((SYMBOL *) tos)->type)
{
case INT:
switch (((SYMBOL *) tos)->len)
{
case sizeof (char):
case sizeof (short):
if (l1 || (*val1 < 0))
*val1 = -*val1;
goto loop;
case sizeof (long):
if (l1 || (((I4TYPE *) val1)->i4type < 0))
((I4TYPE *) val1)->i4type = -((I4TYPE *) val1)->i4type;
goto loop;
}
case FLOAT:
if (l1 || (((F8TYPE *) val1)->f8type < 0.0))
((F8TYPE *) val1)->f8type = -(((F8TYPE *) val1)->f8type);
goto loop;
}
case opNOT:
*val1 = !*val1;
case opPLUS:
if (((SYMBOL *) tos)->type == CHAR)
ov_err(BADUOPC);
goto loop;
case opASCII:
ascii(tos);
goto loop;
case opINT1:
typecoerce(tos, INT, 1);
goto loop;
case opINT2:
typecoerce(tos, INT, sizeof (short));
goto loop;
case opINT4:
typecoerce(tos, INT, sizeof (long));
goto loop;
# ifndef NO_F4
case opFLT4:
typecoerce(tos, FLOAT, sizeof (float));
goto loop;
# endif
case opFLT8:
typecoerce(tos, FLOAT, sizeof (double));
goto loop;
default:
if (((SYMBOL *) tos)->type == CHAR)
ov_err(BADUOPC);
if (((SYMBOL *) tos)->type == INT)
itof8(tos);
switch (opval)
{
case opATAN:
((F8TYPE *) val1)->f8type = atan(((F8TYPE *) val1)->f8type);
goto loop;
case opGAMMA:
((F8TYPE *) val1)->f8type = gamma(((F8TYPE *) val1)->f8type);
goto loop;
case opLOG:
((F8TYPE *) val1)->f8type = log(((F8TYPE *) val1)->f8type);
goto loop;
case opSIN:
((F8TYPE *) val1)->f8type = sin(((F8TYPE *) val1)->f8type);
goto loop;
case opCOS:
((F8TYPE *) val1)->f8type = cos(((F8TYPE *) val1)->f8type);
goto loop;
case opSQRT:
((F8TYPE *) val1)->f8type = sqrt(((F8TYPE *) val1)->f8type);
goto loop;
case opEXP:
((F8TYPE *) val1)->f8type = exp(((F8TYPE *) val1)->f8type);
goto loop;
default:
AAsyserr(17003, opval);
}
}
case AOP:
aop_interp(opval, tos);
goto loop;
}
}
/*
** relop_interp interprets the relational operators
** (ie. EQ, NE etc.) and returns true or false
** by evaluating i.
**
** i should be greater than, equal or less than zero.
*/
relop_interp(opval, i)
register int opval;
register int i;
{
switch (opval)
{
case opEQ:
return (i == 0);
case opNE:
return (i != 0);
case opLT:
return (i < 0);
case opLE:
return (i <= 0);
case opGT:
return (i > 0);
case opGE:
return (i >= 0);
default:
AAsyserr(17004, opval);
}
}
/*
** Aggregate values are stored in Outtup. Tend points
** to the spot for the next aggregate. Aop_interp()
** computes the value for the aggregate and leaves
** the result in the position pointed to by Tend.
*/
aop_interp(opval, tos)
int opval;
register struct stacksym *tos;
{
register char *number;
register int i;
register int l1;
register char *val;
char val_buf[sizeof (double)];
number = val_buf;
/* note: this assumes that there are always */
/* sizeof (double) bytes which can be moved. */
/* if it moves beyond Tend, it's ok */
AAbmove(Tend, number, sizeof (double));
val = (char *) ((SYMBOL *) tos)->value;
switch (opval)
{
case opSUMU:
case opSUM:
if (*Counter <= 1)
goto puta;
switch (((SYMBOL *) tos)->type)
{
case INT:
switch (((SYMBOL *) tos)->len)
{
case sizeof (char):
((I2TYPE *) val)->i2type += ctoi(((I1TYPE *) number)->i1type);
goto puta;
case sizeof (short):
((I2TYPE *) val)->i2type += ((I2TYPE *) number)->i2type;
goto puta;
case sizeof (long):
((I4TYPE *) val)->i4type += ((I4TYPE *) number)->i4type;
goto puta;
}
case FLOAT:
# ifndef NO_F4
if (((SYMBOL *) tos)->len == sizeof (float))
((F8TYPE *) number)->f8type = ((F4TYPE *) number)->f4type;
# endif
((F8TYPE *) val)->f8type += ((F8TYPE *) number)->f8type;
goto puta;
default:
ov_err(BADSUMC); /* cant sum char fields */
}
case opCNTU:
case opCNT:
((SYMBOL *) tos)->type = CNTTYPE;
((SYMBOL *) tos)->len = CNTLEN;
((I4TYPE *) val)->i4type = *Counter;
goto puta;
case opANY:
((SYMBOL *) tos)->type = ANYTYPE;
((SYMBOL *) tos)->len = ANYLEN;
if (*Counter)
{
((I2TYPE *) val)->i2type = 1;
if (!Bylist && (Agcount == 1))
Targvc = 0; /* if simple agg. stop scan */
}
else
((I2TYPE *) val)->i2type = 0;
goto puta;
case opMIN:
case opMAX:
if (*Counter <= 1)
goto puta;
switch (((SYMBOL *) tos)->type)
{
case INT:
switch (((SYMBOL *) tos)->len)
{
case sizeof (char):
i = (ctoi(((I1TYPE *) val)->i1type) < ctoi(((I1TYPE *) number)->i1type));
break;
case sizeof (short):
i = (((I2TYPE *) val)->i2type < ((I2TYPE *) number)->i2type);
break;
case sizeof (long):
i = (((I4TYPE *) val)->i4type < ((I4TYPE *) number)->i4type);
break;
}
break;
case FLOAT:
# ifndef NO_F4
if (((SYMBOL *) tos)->len == sizeof (float))
((F8TYPE *) number)->f8type = ((F4TYPE *) number)->f4type;
# endif
i = (((F8TYPE *) val)->f8type < ((F8TYPE *) number)->f8type);
break;
case CHAR:
l1 = ctou(((SYMBOL *) tos)->len);
i = (lexcomp(((STRINGP *) val)->stringp, l1, Tend, l1) < 0);
break;
default:
AAsyserr(17005, ((SYMBOL *) tos)->type);
}
/* check result of comparison */
if (opval == (int) opMAX)
i = !i; /* complement test for opMAX */
if (i)
goto puta; /* condition true. new value */
/* condition false. Keep old value */
goto done;
case opAVGU:
case opAVG:
if (((SYMBOL *) tos)->type == INT)
itof8(tos);
else
if (((SYMBOL *) tos)->type == CHAR)
ov_err(BADAVG);
if (*Counter > 1)
{
((F8TYPE *) val)->f8type = ((F8TYPE *) number)->f8type + (((F8TYPE *) val)->f8type - ((F8TYPE *) number)->f8type)/ *Counter;
}
((SYMBOL *) tos)->len = sizeof (double);
goto puta;
default:
AAsyserr(17006, ((SYMBOL *) tos)->type);
}
puta:
tout(tos, Tend, ((SYMBOL *) tos)->len);
done:
Tend += ctou(((SYMBOL *) tos)->len);
}