|
|
BSD 4.3
# include <stdio.h>
# include <ingres.h>
# include <aux.h>
# include <tree.h>
# include <pv.h>
# include "parser.h"
# include <symbol.h>
# include <sccs.h>
# include <errors.h>
SCCSID(@(#)tree.c 8.3 2/8/85)
/*
** TREE
** FUNCTION TO ADD NODE TO QUERY TREE
** RETURN VALUE IS POINTER TO NODE JUST CREATED
*/
QTREE *
tree(lptr, rptr, typ, len, valu, attnum)
QTREE *lptr;
QTREE *rptr;
char typ;
int len;
register int valu;
register struct atstash *attnum;
{
register QTREE *tptr;
extern char Trfrmt;
extern char Trfrml;
extern char *need();
extern QTREE *norm();
extern int Err_current;
# ifdef xPTR3
tTfp(55, 0, "tree type(%d), len(%d), value(%d).\n", typ, len, valu);
# endif
if (Err_current)
return (NULL);
/* Following is a hack. Sorry about that John. */
if (typ == AND)
len = sizeof (struct rootnode) - sizeof (short);
tptr = (QTREE *) need(Qbuf, QT_HDR_SIZ + len);
tptr->left = lptr;
tptr->right = rptr;
tptr->sym.type = typ;
tptr->sym.len = len;
switch (typ)
{
case VAR:
tptr->sym.value.sym_var.varno = valu & I1MASK;
tptr->sym.value.sym_var.attno = attnum->atbid;
tptr->sym.value.sym_var.varfrmt = attnum->atbfrmt;
tptr->sym.value.sym_var.varfrml = attnum->atbfrml;
tptr->sym.value.sym_var.valptr = NULL;
tptr->sym.value.sym_var.varstr = NULL;
break;
case ROOT:
case AGHEAD:
tptr->sym.value.sym_root.rootuser = valu;
break;
case TREE:
case BYHEAD:
case AND:
case OR:
case QLEND:
break;
case UOP:
case BOP:
tptr->sym.value.sym_op.opno = valu;
format(tptr);
break;
case COP:
if ((tptr->sym.value.sym_op.opno = getcop(valu)) == BADCOP)
{
/* bad const operator */
par_error(BADCONSTOP, WARN, valu, 0);
return(NULL);
}
break;
case AOP:
format(tptr->right);
tptr->sym.value.sym_op.agfrmt = Trfrmt;
tptr->sym.value.sym_op.agfrml = Trfrml;
case RESDOM:
tptr->sym.value.sym_resdom.resno = valu;
format(tptr);
tptr->sym.value.sym_resdom.resfrmt = Trfrmt;
tptr->sym.value.sym_resdom.resfrml = Trfrml;
break;
default:
/* INT, FLOAT, CHAR */
bmove(valu, &tptr->sym.value, len & I1MASK);
break;
}
return (tptr);
}
/*
** WINDUP
** assign resno's to resdoms of an agg fcn
*/
windup(ptr)
QTREE *ptr;
{
register int tot;
register int kk;
register QTREE *t;
/* COUNT THE RESDOM'S OF THIS TARGET LIST */
kk = 1;
for (t = ptr; t; t = t->left)
kk++;
tot = 1;
for (t=ptr; t;t = t->left)
t->sym.value.sym_resdom.resno = kk - tot++;
}
/*
** ADDRESDOM - makes a new entry for the target list
**
** Trname must contain the name of the resdom to
** use for the header, create and Rsdmno for append, replace
**
** the parameters are pointers to the subtrees to be
** suspended from the node
*/
QTREE *
addresdom(lptr, rptr)
QTREE *lptr, *rptr;
{
register QTREE *rtval;
register struct atstash *aptr;
char buf[10]; /* buffer type and length in ascii for dbu */
extern int Opflag;
extern int Rsdmno;
extern int Equel;
extern int Resrng;
extern char Trfrmt;
extern char Trfrml;
extern char *Trname;
extern PARRNG Parrng[];
extern QTREE *tree();
extern struct atstash *attlookup();
int temp;
switch (Opflag)
{
case mdSTOP:
rtval = NULL;
break;
case mdRETR:
case mdRET_UNI:
case mdVIEW:
Rsdmno++;
if (Rsdmno >= MAXDOM)
/* too many resdoms */
par_error(RESXTRA, FATAL, 0);
rtval = tree(lptr, rptr, RESDOM, sizeof (struct resdomnode), Rsdmno);
if (!Equel || Resrng)
{
/* buffer info for header or CREATE */
setp(PV_STR, Trname);
buf[0] = Trfrmt & I1MASK;
smove(iocv(Trfrml & I1MASK), &buf[1]);
setp(PV_STR, buf);
}
break;
default:
/*
** for append and replace, the result domain
** number is determined by the location of
** the attribute in the result relation
*/
if (sequal(Trname, "tid"))
/* attrib not found */
par_error(NOATTRIN, WARN, Trname,
trim_relname(Parrng[Resrng].vardesc.reldum.relid), 0);
# ifdef DISTRIB
if (sequal(Trname, "sid"))
/* attrib not found */
par_error(NOATTRIN, WARN, Trname,
trim_relname(Parrng[Resrng].vardesc.reldum.relid), 0);
# endif
aptr = attlookup(Resrng, Trname);
Rsdmno = aptr->atbid;
rtval = tree(lptr, rptr, RESDOM, sizeof (struct resdomnode), Rsdmno);
if (Opflag != mdPROT) /* INTEGRITY not possible here */
attcheck(aptr);
break;
}
return (rtval);
}
/*
** GETCOP
** routine to lookup 'string' in constant operators table
** constant table is declared in tables.y
** structure is defined in ../parser.h
*/
getcop(string)
char *string;
{
register struct constop *cpt;
register char *sptr;
extern struct constop Coptab[];
sptr = string;
for (cpt = Coptab; cpt->copname; cpt++)
if (sequal(sptr, cpt->copname))
return (cpt->copnum);
return (BADCOP);
}
/*
** SUBSTRING
** creates structure to save delimiters of a substring
** structure is defined in ../h/tree.h
*/
STRKEEPER
*substring(str,isname)
char *str;
int isname;
{
extern char *need();
STRKEEPER *s;
s = (STRKEEPER *) need(Qbuf,sizeof(STRKEEPER));
s->number[0] = 1;
s->string[0] = str;
if (isname)
s->flag[0] = 1;
if (str == NULL)
s->flag[0] |= 2;
return(s);
}
STRKEEPER
*endvals(interval,left,right)
STRKEEPER *interval;
int left,right;
{
if (left == '(')
interval->type[0] = OPEN;
else
interval->type[0] = CLOSED;
if (right == ')')
interval->type[1] = OPEN;
else
interval->type[1] = CLOSED;
return(interval);
}
setnumber(interval,num)
STRKEEPER *interval;
int *num;
{
interval->number[0] = *num;
}
groupstrings(left,right)
STRKEEPER *left,*right;
{
left->string[1] = right->string[0];
left->flag[1] = right->flag[0];
left->number[1] = right->number[0];
}
/*
** CHECK_BNF -- check the legality of a simplified BNF defnition
**
** Parameters:
** str-- the string to be checked
**
** Returns:
** 0 - the string is legal
** <0 - the string is not legal
** -1 : bracket,brace not matched
** -2 : hyphen misused
**
** Called by:
** make_tuples
**
** Comments:
** the string may not contain nested braces or brackets
** these chars have special meaning and must be
** backslashed: { } [ ] - \
**
*/
check_bnf(str)
char *str;
{
char *temp; /* temp ptr to string */
int len; /* length of string */
char ch; /* ptr to one char of string */
char nextch;
int inbrace=0; /* keeps track of braces */
int inbrak=0; /* keeps track of brackets */
len = strlen(str);
temp = str;
while (len > 0)
{
len--;
ch = *temp++;
switch (ch)
{
case LBRACKET:
if (!inbrace)
inbrak++;
else
return(-1);
break;
case RBRACKET:
inbrak--;
if (inbrak != 0)
return(-1);
break;
case LBRACE:
if (!inbrak)
inbrace++;
else
return(-1);
break;
case RBRACE:
inbrace--;
if (inbrace != 0)
return(-1);
break;
case '-':
return(-2);
break;
case '\\':
*temp++;
break;
default:
nextch = *temp;
if (nextch == '-')
{
*temp++;
len--;
if (!len)
return(-2);
ch = *temp;
switch(ch)
{
case LBRACKET:
case RBRACKET:
case LBRACE:
case RBRACE:
case '-':
return(-2);
break;
case '\\':
*temp++;
break;
default:
break;
}
}
}
}
if ((inbrace) || (inbrak))
return(-1);
return(0);
}
/*
** MAKE_TUPLES -- create the tuples for the 'rdelim' relation
** as specified by a user-defined delimitor
**
** Paramaters:
** desc--descriptor for the relation
** group--group name for the delimitor
** delim--name of the delimitor
** str-bnf string specifying the delimitor
**
** Returns:
** 0 if successful
** <0 if not successful
** -1,-2: BNF expression not legal
**
*/
make_tuples(desc,group,delim,str)
DESC *desc;
char *group;
char *delim;
char *str;
{
int err; /* error status of bnf string */
char *map; /* pointer to next string to make into bitmap */
int len; /* len of str */
int mlen; /* len of substring to make into bitmap */
int order; /* order of bitmap */
int type; /* type of interval ONE or ZEROMORE */
char ch; /* pointer to current char */
err = check_bnf(str);
if (err < 0)
return(err);
len = strlen(str);
order = 0;
while (len > 0)
{
order++;
map = str;
mlen = 0;
ch = *str++;
len--;
switch (ch)
{
case LBRACKET:
type = ONE;
map = str;
while ((ch = *str++) != RBRACKET)
{
mlen++;
len--;
if (ch == '\\')
{
ch = *str++;
mlen++;
len--;
}
}
len--;
break;
case LBRACE:
type = ZEROMORE;
map = str;
while ((ch = *str++) != RBRACE)
{
mlen++;
len--;
if (ch == '\\')
{
ch = *str++;
mlen++;
len--;
}
}
len--;
break;
default:
type = ONE;
if (ch == '\\')
{
map = str;
ch = *str++;
len--;
mlen = 1;
}
if (*str == '-')
{
*str++;
len--;
mlen++;
*str++;
len--;
mlen++;
}
else
mlen = 1;
break;
}
create_tup(desc,order,group,delim,type,map,mlen);
}
return(0);
}
/*
** CREATE_TUP-- create a tuple in the 'rdelim' relation
**
** Parameters:
** desc - descriptor for the relation
** order - order field for tuple
** group - group field for tuple
** delim - delim field for tuple
** type - type field for tuple
** str - string to be converted into bitmap
** strlen - length of str
**
** Called by:
** make_tuples
*/
create_tup(desc,order,group,delim,type,str,strlen)
DESC *desc;
int order;
char *group;
char *delim;
int type;
char *str;
int strlen;
{
DELIM_TUP *tuple;
char bitmap[BITMAPLEN];
TID *tid;
char *malloc();
char *make_dmap();
char b[BITMAPLEN];
int i;
tuple = (DELIM_TUP *) malloc (sizeof(DELIM_TUP));
tuple->order = order;
strcpy(tuple->group,group);
strcpy(tuple->delim,delim);
tuple->type = type;
make_dmap(str,strlen,b);
for ( i= 0; i< BITMAPLEN; i++)
tuple->bitmap[i] = b[i];
insert(desc,&tid,tuple,1);
}
/*
** MAKE_DMAP -- given a BNF string, make the corresponding bitmap
**
** Parameters:
** str - BNF string
** len - length of string
**
** Called by:
** create_tup
**
** Returns:
** pointer to the bitmap of 16 chars
**
** Comments:
** The bitmap is formed of 16 chars. The total bits
** (128) represents the characters of the ASCII set.
** If the BNF string indicates a character, the bit
** corresponding to that char is set in the bitmap.
** All other bits are reset.
*/
char *
make_dmap(str,len,b)
char *str;
int len;
char *b;
{
char ch;
char nextch;
int i;
# ifdef xPTR3
tTfp(42,0,"DMAP: str = %s, len = %d\n",str,len);
# endif
for (i = 0; i < ACHARS; i++)
reset(b,i);
while (len > 0)
{
ch = *str++;
len--;
if (ch == '\\')
{
ch = *str++;
len--;
}
if ( (len > 0) && (*str == '-'))
{
*str++;
len--;
nextch = *str++;
len--;
for (i = ch; i <= nextch; i++)
{
set(b,i);
}
}
else
{
set(b,ch);
}
}
return(b);
}
/*
** SET,RESET -- bitmap setting routines
**
** Parameters:
** map: the array of chars which forms the bitmap
** n: the bit to set or reset
**
** Called by:
** make_bitmap
**
*/
set(map,n)
char *map;
int n;
{
map[n/BITS] |= (1<<(n%BITS));
}
reset(map,n)
char *map;
int n;
{
map[n/BITS] &= ((1<<(n%BITS)) ^ MAXFIELD);
}
test(map,n)
char *map;
int n;
{
return ((map[n/BITS] & (1<<(n%BITS))) != 0);
}
/*
** MAKE_LIST -- puts the delimitors to be used in the delim queue
**
** Parameters:
** desc - descriptor for the relation
** group - group of delims to use
**
** Returns:
** 0 if ok
** -1 if no delims could be found in the specified group
**
** Comments:
** given a group name, adds all delimitors in that
** group to the head of the delim queue, which is
** pointed to by Delimhead.
** if the queue is empty, the predefined delimitors
** 'w' and 'c' will be added to the list
*/
make_list(desc,group)
DESC *desc;
char *group;
{
DELIM_TUP tuple;
TID lotid, hitid;
extern DELIMLIST *Delimhead;
DELIMLIST *d;
DMAP *map, *m;
char delim[12];
int start = 1;
extern char *malloc();
int i;
int notfound = 1;
# ifdef xPTR3
tTfp(42,0,"Make_list: group = %s\n", group);
# endif
if (!strcmp (group,"system"))
{
predef_delims();
return(0);
}
if (find(desc,LRANGEKEY, &lotid, &hitid, group) < 0)
return(-1);
find(desc,HRANGEKEY, &lotid, &hitid, group);
while (!get(desc, &lotid, &hitid, &tuple, 1))
{
if (strcmp(tuple.group, group))
{
continue;
}
notfound = FALSE;
/* check if it is a new delimitor */
if (strcmp(tuple.delim, delim))
start = 1;
/* start a new delimitor node */
if (start)
{
d = (DELIMLIST *) malloc( sizeof(DELIMLIST));
strcpy(delim, tuple.delim);
strcpy(d->group,tuple.group);
strcpy(d->delim,delim);
d->back = Delimhead;
Delimhead = d;
map = (DMAP *) malloc(sizeof(DMAP));
map->order = tuple.order;
map->type = tuple.type;
for ( i = 0; i < BITMAPLEN; i++)
map->bits[i] = tuple.bitmap[i];
map->next = NULL;
d->maptr = map;
m = map;
start = 0;
}
else /* add another bitmap to the delimitor node */
{
map = (DMAP *) malloc(sizeof(DMAP));
map->order = tuple.order;
map->type = tuple.type;
for ( i = 0; i < BITMAPLEN; i++)
map->bits[i] = tuple.bitmap[i];
map->next = NULL;
m->next = map;
m = m->next;
}
}
/*prlist(Delimhead); */
if (notfound)
return(-1);
return(0);
}
/*
** PREDEF_DELIMS - add the predefined delims to the queue
**
** Called by:
** make_list
**
** Side Effects:
** the delim queue pointed to by Delimhead
** is initialized with the delims 'w' and 'c'.
**
*/
predef_delims()
{
DELIMLIST *d;
DMAP *m, *m2;
int i;
d = (DELIMLIST * ) malloc(sizeof(DELIMLIST));
strcpy(d->group, "system");
strcpy(d->delim, "c");
d->back = NULL;
m = (DMAP *) malloc(sizeof (DMAP));
m->order = 1;
m->type = 0;
for (i = ' '; i <= '~'; i++)
set(m->bits, i);
m->next = NULL;
d->maptr = m;
Delimhead = d;
d = (DELIMLIST * ) malloc(sizeof(DELIMLIST));
strcpy(d->group, "system");
strcpy(d->delim, "w");
d->back = NULL;
m = (DMAP *) malloc(sizeof (DMAP));
m->order = 1;
m->type = 0;
for (i = 'A'; i <= 'Z'; i++)
set(m->bits, i);
for (i = 'a'; i <= 'z'; i++)
set(m->bits, i);
d->maptr = m;
m2 = (DMAP *) malloc(sizeof(DMAP));
m2->order = 2;
m2->type = 1;
for (i = 'A'; i <= 'Z'; i++)
set(m2->bits, i);
for (i = 'a'; i <= 'z'; i++)
set(m2->bits, i);
m->next = m2;
m2->next = NULL;
d->back = Delimhead;
Delimhead = d;
}
/*
** PRLIST -- print contents of delimiter queue
*/
prlist(d)
struct delimlist *d;
{
struct delimlist *q;
DMAP *m;
int i;
printf("DELIM QUEUE:\n");
q = d;
while (q != NULL)
{
printf("-------------------------------------------------------\n");
printf("NODE: group= %s, delim = %s \n", q->group, q->delim);
m = q->maptr;
while (m != NULL)
{
printf("maps:\n");
printf("order = %d, type = %d \n", m->order, m->type);
for (i = 0; i < ACHARS; i++)
printf("%d ", test(m->bits,i));
printf("\n");
m = m->next;
}
q = q->back;
printf("-------------------------------------------------------\n");
}
return(0);
}
/*
** SHRINK_LIST -- remove the delims in specified group from list
**
** Parameters:
** group - name of the group to remove
**
*/
shrink_list(group)
char *group;
{
struct delimlist *p, *q;
extern struct delimlist *Delimhead;
/* may not delete sytem delims */
if (!strcmp(group, "system"))
return(-1);
p = Delimhead;
while ((p != NULL) && (strcmp(p->group, group)))
{
q = p;
p = p->back;
}
if (p == NULL)
{
return(-1); /* error group not found */
}
while(!strcmp(p->group, group))
{
if (p == Delimhead)
Delimhead = p->back;
else
q->back = p->back;
if (p->back == NULL)
{
return(0);
}
p = p-> back;
}
/* prlist(Delimhead); */
return(0);
}
/*
** DESTROY_DELIM -- remove the group of delims from the relation 'rdelim'
**
** Parameters:
** group - the group of delims to remove
**
** Called By:
** grammar.y
**
** Returns:
** 0 if delims were successfully removed
** -1 if delims were not found in relation
*/
destroy_delim(desc, group)
DESC *desc;
char *group;
{
DELIM_TUP tuple;
TID lotid,hitid;
int notfound = 1;
if (find(desc,LRANGEKEY, &lotid, &hitid, group) < 0)
return(-1);
find(desc,HRANGEKEY, &lotid, &hitid, group);
while (!get(desc, &lotid, &hitid, &tuple, 1))
{
if (!strcmp(tuple.group, group))
{
notfound = 0;
delete(desc,&lotid);
}
}
if (notfound)
return(-1);
return(0);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.