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