# include "ctlmod.h" # include # include # include # include # include # include SCCSID(@(#)readqry.c 8.3 12/8/85) /* ** READQRY ** ** Reads in query symbols from input pipe into core ** locations and sets up information needed for later ** processing. ** ** Returns ptr to root of querytree ** ** Locbuf is a 'struct srcid' since that is the largest node of ** a QMODE, SOURCEID, or RESULTVAR node. */ QTREE * readqry(rdfn, fnparam, initialize) int (*rdfn)(); /* tree read function */ int fnparam; /* parameter to pass to rdfn */ bool initialize; /* if set, initialize Qbuf */ { register QTREE *q; register QTREE *rtval; register DESC *d; extern QTREE *readtree(); extern char *xalloc(); extern QTREE *trbuild(); int mark; extern QTREE *readsym(); int i; int j; # ifdef xCTR1 if (tTf(10, 8)) printf("READQRY:\n"); # endif if (initialize) { /* initialize for new query block */ clrrange(); Qt.qt_resvar = -1; Qt.qt_qmode = -1; } for (i = 0; i < MAXRANGE; i++) Qt.qt_remap[i] = i; mark = markbuf(Qbuf); /* read symbols from input */ for (;;) { freebuf(Qbuf, mark); q = readsym(rdfn, fnparam); switch (q->sym.type) { case QMODE: if (Qt.qt_qmode != -1) syserr("readqry: two qmodes"); Qt.qt_qmode = q->sym.value.sym_data.i2type; break; case RESULTVAR: if (Qt.qt_resvar != -1) syserr("readqry: two resultvars"); Qt.qt_resvar = q->sym.value.sym_data.i2type; break; case SOURCEID: d = (DESC *) xalloc(sizeof *d); bmove((char *) &q->sym.value.sym_srcid.srcdesc, (char *) d, sizeof *d); i = q->sym.value.sym_srcid.srcvar; j = declare(i, d); if (j != i && initialize) syserr("readqry: declare(%d)=%d", i, j); Qt.qt_remap[i] = j; break; case TREE: /* beginning of tree, no more other stuff */ q = readtree(q, rdfn, fnparam); rtval = trbuild(q); if (rtval == NULL) error(STACKFULL, 0); return (rtval); default: syserr("readqry: bad symbol %d", q->sym.type); } } } /* ** READSYM ** reads in one symbol from pipe into symbol struct. */ QTREE * readsym(rdfn, fnparam) int (*rdfn)(); /* tree read function */ char *fnparam; { register int len; register int t; register QTREE *q; extern char *need(); int rlen; q = (QTREE *) need(Qbuf, QT_HDR_SIZ); if ((*rdfn)(fnparam, &q->sym, TYP_LEN_SIZ) < TYP_LEN_SIZ) syserr("readsym: read sym"); rlen = len = q->sym.len & I1MASK; t = q->sym.type; switch (t) { case AND: if (len < 6) len = 6; break; case ROOT: case AGHEAD: if (len < 8) len = 8; break; } q->sym.len = len; if (len != 0) { /* this will be contiguous with above need call */ need(Qbuf, len); } if (rlen != 0) { if ((*rdfn)(fnparam, &q->sym.value, rlen) < rlen) syserr("readsym: read val (sym=%d,%d)", t, rlen); } switch (t) { case ROOT: q->sym.value.sym_root.rootuser = TRUE; break; case AGHEAD: q->sym.value.sym_root.rootuser = FALSE; break; } # ifdef xCTR1 if (tTf(10, 9)) nodepr(q); # endif xCTR1 return (q); } /* ** READTREE ** ** reads in tree symbols into a buffer up to a root (end) symbol ** */ QTREE * readtree(tresym, rdfn, fnparam) QTREE *tresym; int (*rdfn)(); char *fnparam; { register QTREE *q; register QTREE *rtval; extern char *need(); rtval = tresym; for(;;) { /* space for left & right pointers */ q = readsym(rdfn, fnparam); if (q->sym.type == ROOT) return (rtval); } } /* ** TRBUILD -- Rebuild a tree in memory ** ** Trbuild is called with a pointer to the TREE node of ** a query already in memory. It rebuilds the pointer ** structure assuming the querytree is in postfix order. ** ** Parameters: ** bufptr - a pointer to the TREE node ** ** Returns: ** NULL - Internal stack overflow (STACKSIZ) ** pointer to the ROOT node ** ** Side Effects: ** All left & right pointers are rebuilt. ** ** Called By: ** readqry ** ** Syserrs: ** syserr if there are too many leaf nodes or too ** few child nodes */ QTREE * trbuild(bufptr) QTREE *bufptr; { register QTREE **stackptr; register char *p; register SYMBOL *s; QTREE *treestack[STACKSIZ]; extern bool leaf(); stackptr = treestack; /*XXX*/ for (p = (char *) bufptr;; p += QT_HDR_SIZ + ((s->len + 3) & 0374)) { s = &((QTREE *)p)->sym; ((QTREE *)p)->left = ((QTREE *)p)->right = 0; /* reunite p with left and right children on stack, if any*/ if (!leaf((QTREE *) p)) /* this node has children */ { if (s->type != UOP) if (stackptr <= treestack) { err: syserr("trbuild:too few nodes"); } else ((QTREE *)p)->right = *(--stackptr); if (s->type != AOP) if (stackptr <= treestack) goto err; else ((QTREE *)p)->left = *(--stackptr); } /* ** If this is a ROOT node then the tree is complete. ** verify that there are no extra nodes in the ** treestack. */ if (s->type == ROOT) /* root node */ { if (stackptr != treestack) syserr("trbuild:xtra nodes"); return ((QTREE *)p); } /* stack p */ if (stackptr-treestack >= STACKSIZ) return (NULL); /* error:stack full */ *(stackptr++) = (QTREE *) p; } } bool leaf(p) QTREE *p; { switch (p->sym.type) { case VAR: case TREE: case QLEND: case INT: case FLOAT: case CHAR: case COP: return(TRUE); default: return(FALSE); } }