ING_DB
This commit is contained in:
parent
ab5f16e2a3
commit
2199bf4643
|
|
@ -0,0 +1,316 @@
|
|||
# include <stdio.h>
|
||||
# include "gen.h"
|
||||
# include "../h/dbs.h"
|
||||
# include "../h/aux.h"
|
||||
# include "../h/tree.h"
|
||||
# include "../h/symbol.h"
|
||||
# include "../h/pipes.h"
|
||||
# include "decomp.h"
|
||||
|
||||
/*
|
||||
** BYEVAL - process aggregate function
|
||||
**
|
||||
** Byeval is passed the root of the original query
|
||||
** tree and the root of the aggregate function to
|
||||
** be processed.
|
||||
**
|
||||
** It first creates a temporary relation which will
|
||||
** hold the aggregate result. The format of the relation
|
||||
** is:
|
||||
** SYSNAMExxxxxaa(count, by-dom1, ... , by-domn, ag1, ... , agm)
|
||||
**
|
||||
** The relation is moved into the range table and will become
|
||||
** a part of the query.
|
||||
**
|
||||
** If there are any occurences of the variables
|
||||
** from the by-domains, anywhere in the original query tree,
|
||||
** the aggregate relation is linked on all by-domains in the
|
||||
** original query tree.
|
||||
**
|
||||
** If the aggregate is unique, multivariable, or has a
|
||||
** qualification, then special processing is done.
|
||||
**
|
||||
** If the aggregate is qualified then the by-domains are
|
||||
** projected into the result relation. This guarantees that
|
||||
** every value of the by-domains will be represented in the
|
||||
** aggregate result.
|
||||
**
|
||||
** If the aggregate is unique or multivariable, then another
|
||||
** temporary relation is created and the values which will be
|
||||
** aggregated; along with the by-domains, are retrieved into
|
||||
** the temporary relation.
|
||||
**
|
||||
** If unique, then duplicates are removed from the temporary relation.
|
||||
**
|
||||
** Next the result relation for the aggregate is modified
|
||||
** to hash in order to speed up the processing of the aggregate
|
||||
** and guarantee that there are no duplicates in the bylist.
|
||||
**
|
||||
** The aggregate is then run, and if a temporary relation was
|
||||
** created (eg. unique or multivar aggregate) then it is destroyed.
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
QTREE *byeval(root, aghead, agvar)
|
||||
QTREE *root; /* root of orig query */
|
||||
QTREE *aghead; /* root of ag fcn sub-tree */
|
||||
int agvar; /* variable number assigned to this aggregate */
|
||||
{
|
||||
register QTREE *q;
|
||||
register QTREE *ag;
|
||||
register QTREE *resdom;
|
||||
register QTREE *r;
|
||||
int temp_relnum;
|
||||
int i;
|
||||
int filled;
|
||||
QTREE *lnodv[MAXDOM + 2];
|
||||
QTREE *save_node[MAXDOM + 2];
|
||||
char agbuf[AGBUFSIZ];
|
||||
char nums[2];
|
||||
int relnum;
|
||||
register QTREE *byhead;
|
||||
register QTREE **alnp;
|
||||
int bydoms;
|
||||
int bymap;
|
||||
int primeag;
|
||||
int srcmap;
|
||||
extern int derror();
|
||||
extern QTREE *copytree();
|
||||
extern QTREE *makavar();
|
||||
extern QTREE *makresdom();
|
||||
extern QTREE *makroot();
|
||||
|
||||
# ifdef xDTR1
|
||||
AAtTfp(7, -1, "BYEVAL\n");
|
||||
# endif
|
||||
|
||||
ag = aghead;
|
||||
byhead = ag->left;
|
||||
|
||||
/* first create the aggregate result relation */
|
||||
/* params for create */
|
||||
|
||||
initp(); /* init globals for setp */
|
||||
setp("0"); /* initial relstat field */
|
||||
relnum = rnum_alloc();
|
||||
setp(rnum_convert(relnum));
|
||||
setp("count"); /* domain 1 - count field per BY value */
|
||||
setp("i4"); /* format of count field */
|
||||
|
||||
i = bydoms = lnode(byhead->left, lnodv, 0);
|
||||
lnodv[i] = 0;
|
||||
alnp = &lnodv[++i];
|
||||
i = lnode(byhead->right, lnodv, i);
|
||||
lnodv[i] = 0;
|
||||
|
||||
domnam(lnodv, "by"); /* BY list domains */
|
||||
domnam(alnp, "ag"); /* aggregate value domains */
|
||||
|
||||
call_dbu(mdCREATE, FALSE);
|
||||
|
||||
Rangev[agvar].relnum = relnum;
|
||||
# ifdef xDTR1
|
||||
AAtTfp(7, 7, "agvar=%d,rel=%s\n", agvar, rnum_convert(relnum));
|
||||
# endif
|
||||
|
||||
bymap = varfind(byhead->left, (QTREE *) 0);
|
||||
|
||||
/*
|
||||
** Find all variables in the tree in which you are nested.
|
||||
** Do not look at any other aggregates in the tree. Just in
|
||||
** case the root is an aggregate, explicitly look at its
|
||||
** two descendents.
|
||||
*/
|
||||
srcmap = varfind(root->left, ag) | varfind(root->right, ag);
|
||||
# ifdef xDTR1
|
||||
AAtTfp(7, 8, "bymap=0%o,srcmap=0%o\n", bymap, srcmap);
|
||||
# endif
|
||||
|
||||
if (bymap & srcmap)
|
||||
modqual(root, lnodv, srcmap, agvar);
|
||||
|
||||
/* if aggregate is unique or there is a qualification
|
||||
** or aggregate is multi-var, then special processing is done */
|
||||
|
||||
temp_relnum = NORESULT;
|
||||
filled = FALSE;
|
||||
primeag = prime(byhead->right);
|
||||
if (ag->right->sym.type != QLEND || ((ROOT_NODE *) ag)->tvarc > 1 || primeag)
|
||||
{
|
||||
/* init a buffer for new tree components */
|
||||
initbuf(agbuf, AGBUFSIZ, AGBUFFULL, derror);
|
||||
|
||||
/* make a root for a new tree */
|
||||
q = makroot(agbuf);
|
||||
|
||||
/*
|
||||
** Create a RESDOM for each by-domain in the original
|
||||
** aggregate. Rather than using the existing by-domain
|
||||
** function, a copy is used instead. This is necessary
|
||||
** since that subtree might be needed later (if modqual())
|
||||
** decided to use it. Decomp does not restore the trees
|
||||
** it uses and thus the by-domains might be altered.
|
||||
*/
|
||||
for (i = 0; r = lnodv[i]; i++)
|
||||
{
|
||||
resdom = makresdom(agbuf, r);
|
||||
((RES_NODE *) resdom)->resno = i + 2;
|
||||
resdom->right = copytree(r->right, agbuf);
|
||||
resdom->left = q->left;
|
||||
q->left = resdom;
|
||||
}
|
||||
mapvar(q, 0); /* make maps on root */
|
||||
# ifdef xDTR1
|
||||
if (AAtTf(7, 2))
|
||||
printree(q, "by-domains");
|
||||
# endif
|
||||
|
||||
/* if agg is qualified, project by-domains into result */
|
||||
if (ag->right->sym.type != QLEND)
|
||||
{
|
||||
filled = TRUE;
|
||||
i = Sourcevar; /* save value */
|
||||
decomp(q, mdRETR, relnum);
|
||||
Sourcevar = i; /* restore value */
|
||||
}
|
||||
|
||||
/* if agg is prime or multivar, compute into temp rel */
|
||||
if (((ROOT_NODE *) ag)->tvarc > 1 || primeag)
|
||||
{
|
||||
q->right = ag->right; /* give q the qualification */
|
||||
ag->right = Qle; /* remove qualification from ag */
|
||||
|
||||
/* put aop resdoms on tree */
|
||||
for (i = bydoms + 1; r = lnodv[i]; i++)
|
||||
{
|
||||
resdom = makresdom(agbuf, r);
|
||||
resdom->right = r->right;
|
||||
resdom->left = q->left;
|
||||
q->left = resdom;
|
||||
|
||||
/* make aop refer to temp relation */
|
||||
r->right = makavar(resdom, FREEVAR, i);
|
||||
}
|
||||
|
||||
/* assign result domain numbers */
|
||||
for (resdom = q->left; resdom->sym.type != TREE; resdom = resdom->left)
|
||||
((RES_NODE *) resdom)->resno = --i;
|
||||
|
||||
/*
|
||||
** change by-list in agg to reference new source rel.
|
||||
** Save the old bylist to be restored at the end of
|
||||
** this aggregate.
|
||||
*/
|
||||
for (i = 0; resdom = lnodv[i]; i++)
|
||||
{
|
||||
save_node[i] = resdom->right;
|
||||
resdom->right = makavar(resdom, FREEVAR, i + 1);
|
||||
}
|
||||
|
||||
mapvar(q, 0);
|
||||
# ifdef xDTR1
|
||||
if (AAtTf(7, 3))
|
||||
printree(q, "new ag src");
|
||||
# endif
|
||||
|
||||
/* create temp relation */
|
||||
temp_relnum = mak_t_rel(q, "a", -1);
|
||||
decomp(q, mdRETR, temp_relnum);
|
||||
Rangev[FREEVAR].relnum = temp_relnum;
|
||||
Sourcevar = FREEVAR;
|
||||
if (primeag)
|
||||
removedups(FREEVAR);
|
||||
# ifdef xDTR1
|
||||
if (AAtTf(7, 4))
|
||||
printree(ag, "new agg");
|
||||
# endif
|
||||
}
|
||||
}
|
||||
|
||||
/* set up parameters for modify to hash */
|
||||
initp();
|
||||
setp(rnum_convert(relnum));
|
||||
setp("hash"); /* modify the empty rel to hash */
|
||||
setp("num"); /* code to indicate numeric domain names */
|
||||
nums[1] = '\0';
|
||||
for (i = 0; i < bydoms; i++)
|
||||
{
|
||||
nums[0] = i + 2;
|
||||
setp(nums);
|
||||
}
|
||||
setp("");
|
||||
|
||||
/* set up fill factor information */
|
||||
setp("minpages");
|
||||
if (filled)
|
||||
{
|
||||
setp("1");
|
||||
setp("fillfactor");
|
||||
setp("100");
|
||||
}
|
||||
else
|
||||
setp("10");
|
||||
specclose(relnum);
|
||||
call_dbu(mdMODIFY, FALSE);
|
||||
|
||||
|
||||
Newq = 1;
|
||||
Newr = TRUE;
|
||||
call_ovqp(ag, mdRETR, relnum);
|
||||
|
||||
Newq = 0;
|
||||
/* if temp relation was used, destroy it */
|
||||
if (temp_relnum != NORESULT)
|
||||
{
|
||||
for (i = 0; resdom = lnodv[i]; i++)
|
||||
resdom->right = save_node[i];
|
||||
dstr_rel(temp_relnum);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
modqual(root, lnodv, srcmap, agvar)
|
||||
QTREE *root;
|
||||
QTREE *lnodv[];
|
||||
int srcmap;
|
||||
int agvar;
|
||||
{
|
||||
register QTREE *and_eq;
|
||||
register QTREE *afcn;
|
||||
register int i;
|
||||
extern QTREE *copytree();
|
||||
extern QTREE *makavar();
|
||||
extern QTREE *need();
|
||||
|
||||
# ifdef xDTR1
|
||||
AAtTfp(14, 5, "modqual 0%o\n", srcmap);
|
||||
# endif
|
||||
|
||||
for (i = 0; afcn = lnodv[i]; i++)
|
||||
{
|
||||
/* 'AND' node */
|
||||
and_eq = need(Qbuf, QT_HDR_SIZ + AND_SIZ);
|
||||
and_eq->sym.type = AND;
|
||||
and_eq->sym.len = AND_SIZ;
|
||||
((ROOT_NODE *) and_eq)->tvarc = 0;
|
||||
((ROOT_NODE *) and_eq)->lvarc = 0;
|
||||
((ROOT_NODE *) and_eq)->lvarm = 0;
|
||||
((ROOT_NODE *) and_eq)->rvarm = 0;
|
||||
and_eq->right = root->right;
|
||||
root->right = and_eq;
|
||||
|
||||
/* 'EQ' node */
|
||||
and_eq->left = need(Qbuf, QT_HDR_SIZ + OP_SIZ);
|
||||
and_eq = and_eq->left;
|
||||
and_eq->sym.type = BOP;
|
||||
and_eq->sym.len = OP_SIZ;
|
||||
((OP_NODE *) and_eq)->opno = (int) opEQ;
|
||||
|
||||
/* bydomain opEQ var */
|
||||
and_eq->right = copytree(afcn->right, Qbuf); /* a-fcn (in Source) specifying BY domain */
|
||||
and_eq->left = makavar(afcn, agvar, i + 2); /* VAR ref BY domain */
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,384 @@
|
|||
# include <stdio.h>
|
||||
# include "gen.h"
|
||||
# include "../h/dbs.h"
|
||||
# include "../h/symbol.h"
|
||||
# include "../h/tree.h"
|
||||
# include "../h/pipes.h"
|
||||
# include "ovqp.h"
|
||||
# include "strategy.h"
|
||||
|
||||
int Nsimp; /* Current no. entries in Simp vector */
|
||||
struct simp Simp[NSIMP];
|
||||
|
||||
/*
|
||||
** Findsimps searches the qualification for
|
||||
** occurances of simple clauses. In its
|
||||
** current crude implementation it only finds
|
||||
** clauses of the form:
|
||||
**
|
||||
** var relop constant or constant relop var
|
||||
**
|
||||
** it does not use simple clauses with 'OR's
|
||||
** nor does it accept clauses of the form
|
||||
**
|
||||
** var relop constant + constant etc.
|
||||
**
|
||||
** Findsimps knows about pattern matching characters
|
||||
** and treats char constants containing pm chars
|
||||
** specially. For example
|
||||
** var >= "xx*" --> var >= "xx"
|
||||
** var <= "xx*" --> var <= "xx\0177"
|
||||
** var = "xx*" --> var >= "xx" and var <= "xx\0177"
|
||||
** If the first char is a pm char then the clause is not
|
||||
** considered as a simple clause. Also notice that the conversion
|
||||
** is done only once. If the next time Newq = FALSE, then findsimps()
|
||||
** isn't called. This works because a pm char can only come from
|
||||
** the user and not from a relation. Thus during tuple substition
|
||||
** a constant with a pm will never change.
|
||||
*/
|
||||
|
||||
findsimps()
|
||||
{
|
||||
register SYMBOL *c;
|
||||
register int t;
|
||||
int length;
|
||||
register SYMBOL **q;
|
||||
int attno;
|
||||
int rel;
|
||||
int found;
|
||||
SYMBOL *xc;
|
||||
extern SYMBOL *cpsym();
|
||||
|
||||
# ifdef xOTR1
|
||||
AAtTfp(21, 0, "FINDSIMPS\n");
|
||||
# endif
|
||||
Nsimp = 0;
|
||||
found = FALSE;
|
||||
q = Qlist; /* q holds pointer to qualification */
|
||||
|
||||
if (!q)
|
||||
return (0);
|
||||
|
||||
|
||||
for (t = ctou((*q)->type); t != QLEND; t = ctou((*++q)->type))
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
case VAR:
|
||||
attno = ctou(*(*q)->value); /* save att number */
|
||||
if ((t = ctou((*++q)->type)) == INT
|
||||
|| t == FLOAT || t == CHAR || t == S_VAR)
|
||||
{
|
||||
c = *q; /* save pointer to value symbol */
|
||||
t = ctou((*++q)->type);
|
||||
if ((rel = relop(*q, FALSE)) >= 0
|
||||
&& (t = ctou((*++q)->type)) == AND)
|
||||
{
|
||||
/* found a simple clause */
|
||||
found = TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case S_VAR:
|
||||
case INT:
|
||||
case FLOAT:
|
||||
case CHAR:
|
||||
c = *q++;
|
||||
if ((t = ctou((*q)->type)) == VAR)
|
||||
{
|
||||
attno = ctou(*(*q)->value);
|
||||
t = ctou((*++q)->type);
|
||||
if ((rel = relop(*q, TRUE)) >= 0 && (t = ctou((*++q)->type)) == AND)
|
||||
{
|
||||
/* found a simple clause */
|
||||
found = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
/* a simple clause has been found.
|
||||
** Check that the constant contains
|
||||
** at least one char before any pattern
|
||||
** matching char. If there is a pattern
|
||||
** matching char then special processing
|
||||
** must be done.
|
||||
*/
|
||||
|
||||
found = FALSE;
|
||||
if (length = check(c))
|
||||
{
|
||||
|
||||
/*
|
||||
** If length is zero then the first char was
|
||||
** a pattern matching char. If length < 0 then
|
||||
** no pattern matching char, and finally
|
||||
** if length > 0 then length is the number of
|
||||
** chars before the first pattern matching char
|
||||
*/
|
||||
if (length > 0)
|
||||
{
|
||||
switch (rel)
|
||||
{
|
||||
|
||||
case opEQ:
|
||||
/*
|
||||
** Create two simple clauses:
|
||||
** One below the value and the
|
||||
** other above the value.
|
||||
*/
|
||||
xc = cpsym(c, length, opLTLE);
|
||||
add_simp(xc, opLTLE, attno);
|
||||
rel = (int) opGTGE;
|
||||
/* fall through to GTGE case */
|
||||
|
||||
case opGTGE:
|
||||
c = cpsym(c, length, opGTGE);
|
||||
break;
|
||||
|
||||
case opLTLE:
|
||||
c = cpsym(c, length, opLTLE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (add_simp(c, rel, attno))
|
||||
break; /* no more room in simps */
|
||||
}
|
||||
}
|
||||
while (t != AND) /* skip to next AND */
|
||||
t = ctou((*++q)->type);
|
||||
}
|
||||
# ifdef xOTR1
|
||||
AAtTfp(21, 2, "FINDSIMPS: rets %d\n", Nsimp);
|
||||
# endif
|
||||
return (Nsimp);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** RELOP determines whether a symbol is a
|
||||
** usable relational operator ie. =,>,>=,<,<=
|
||||
**
|
||||
** returns the type of the relational
|
||||
** operator if found, else it returns
|
||||
** -1
|
||||
**
|
||||
** Items are normalized to be in the form:
|
||||
** var relop constant. If reverse is TRUE then
|
||||
** complement the sense of the relop. Reverse will
|
||||
** be TRUE is the simple clause was found in the
|
||||
** form constant relop var.
|
||||
*/
|
||||
relop(s, reverse)
|
||||
register SYMBOL *s;
|
||||
register int reverse;
|
||||
{
|
||||
register int v;
|
||||
|
||||
v = -1; /* assume failure */
|
||||
if (s->type == BOP)
|
||||
{
|
||||
switch (ctou(*s->value))
|
||||
{
|
||||
case opEQ:
|
||||
v = (int) opEQ;
|
||||
break;
|
||||
|
||||
case opLT:
|
||||
case opLE:
|
||||
v = (int) opLTLE;
|
||||
if (reverse)
|
||||
v = (int) opGTGE;
|
||||
break;
|
||||
|
||||
case opGT:
|
||||
case opGE:
|
||||
v = (int) opGTGE;
|
||||
if (reverse)
|
||||
v = (int) opLTLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (v);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** CHECK checks the symbol for
|
||||
** pattern matching characters.
|
||||
** If any are found then check returns
|
||||
** the number of characters before the
|
||||
** first pattern matching character.
|
||||
**
|
||||
** If no pattern matching chars are found
|
||||
** then check returns -1.
|
||||
**
|
||||
** note that PAT_RBRAC need not be checked for
|
||||
** since it is not a pattern matching char unless
|
||||
** PAT_LBRAC appears before it.
|
||||
**
|
||||
** PAT_LBRAC is treated specially in cpsym().
|
||||
** If any are detected, then length until the
|
||||
** first PAT_ANY or PAT_ONE is returned.
|
||||
*/
|
||||
check(s)
|
||||
register SYMBOL *s;
|
||||
{
|
||||
register char *cp;
|
||||
register int len;
|
||||
register int flag;
|
||||
|
||||
# ifdef xOTR1
|
||||
if (AAtTfp(21, 4, "CHECK: sym"))
|
||||
prsym(s);
|
||||
# endif
|
||||
if (s->type == CHAR)
|
||||
{
|
||||
flag = FALSE;
|
||||
cp = (char *) s->value; /* the string is a literal */
|
||||
len = ctou(s->len);
|
||||
while (len--)
|
||||
{
|
||||
switch (*cp++)
|
||||
{
|
||||
case PAT_ANY:
|
||||
case PAT_ONE:
|
||||
return ((ctou(s->len)) - len - 1);
|
||||
|
||||
case PAT_LBRAC:
|
||||
flag = TRUE;
|
||||
}
|
||||
}
|
||||
if (flag)
|
||||
return (ctou(s->len)); /* constant had PAT_LBRAC char */
|
||||
}
|
||||
return (-1); /* ok */
|
||||
}
|
||||
|
||||
|
||||
# ifdef EBCDIC
|
||||
# define LAST_CHAR 0377
|
||||
# else
|
||||
# define LAST_CHAR 0177
|
||||
# endif
|
||||
|
||||
/*
|
||||
** CPSYM -- copy a symbol to a new buffer area.
|
||||
** If op is opLTLE then add a pad character
|
||||
** whose value is the largest possible char
|
||||
** value.
|
||||
**
|
||||
** If any ranges of characters are found,
|
||||
** then the lowest/highest char is taken from
|
||||
** range.
|
||||
*/
|
||||
SYMBOL *cpsym(konst, len, op)
|
||||
SYMBOL *konst;
|
||||
int len;
|
||||
int op;
|
||||
{
|
||||
register SYMBOL *s;
|
||||
register char *cp;
|
||||
register int i;
|
||||
register char *sp;
|
||||
register int c;
|
||||
register int nc;
|
||||
extern char *Ovqpbuf;
|
||||
extern char *need();
|
||||
|
||||
i = len;
|
||||
len += SYM_HDR_SIZ;
|
||||
if (op == (int) opLTLE)
|
||||
len++;
|
||||
s = (SYMBOL *) need(Ovqpbuf, len);
|
||||
s->type = CHAR;
|
||||
sp = (char *) s->value;
|
||||
cp = (char *) konst->value;
|
||||
|
||||
while (i--)
|
||||
{
|
||||
/* copy chars processing LBRAC chars if any */
|
||||
if ((c = *cp++) == PAT_LBRAC)
|
||||
{
|
||||
/* if string is empty, ignore it */
|
||||
if (i == 0)
|
||||
break;
|
||||
|
||||
c = *cp++;
|
||||
i--;
|
||||
|
||||
if (c == PAT_RBRAC)
|
||||
continue; /* empty [] */
|
||||
|
||||
while (i-- && ((nc = *cp++) != PAT_RBRAC))
|
||||
{
|
||||
/* ignore '-' */
|
||||
if (nc == '-')
|
||||
continue;
|
||||
|
||||
/* check for char larger/smaller than 'c' */
|
||||
if (op == (int) opLTLE)
|
||||
{
|
||||
if (nc > c)
|
||||
c = nc;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nc < c)
|
||||
c = nc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*sp++ = c; /* copy next char */
|
||||
}
|
||||
if (op == (int) opLTLE)
|
||||
*sp++ = LAST_CHAR;
|
||||
s->len = sp - (char *) s->value;
|
||||
|
||||
return (s);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** ADD_SIMP -- add a simple clause to the list of
|
||||
** simple clauses. As a side effect the Nsimp
|
||||
** is incremented. If there is no room return
|
||||
** TRUE else return FALSE
|
||||
*/
|
||||
add_simp(konst, rel, attno)
|
||||
register SYMBOL *konst;
|
||||
register int rel;
|
||||
int attno;
|
||||
{
|
||||
register struct simp *s;
|
||||
|
||||
if (Nsimp == NSIMP)
|
||||
return (TRUE); /* no more room */
|
||||
|
||||
s = &Simp[Nsimp++];
|
||||
|
||||
s->att = attno;
|
||||
s->konst = konst;
|
||||
s->relop = rel;
|
||||
|
||||
# ifdef xOTR1
|
||||
if (AAtTf(21, 3))
|
||||
prsimp(s);
|
||||
# endif
|
||||
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
|
||||
# ifdef xOTR1
|
||||
prsimp(s)
|
||||
register struct simp *s;
|
||||
{
|
||||
printf("simp:relop=%d,att=%d,val=", s->relop, s->att);
|
||||
prsym(s->konst);
|
||||
}
|
||||
# endif
|
||||
Loading…
Reference in New Issue