diff --git a/WEGA/contrib/ingres/dbs/src/gutil/fgetline.c b/WEGA/contrib/ingres/dbs/src/gutil/fgetline.c new file mode 100644 index 0000000..fefb43d --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/gutil/fgetline.c @@ -0,0 +1,52 @@ +# include + +/* +** FGETLINE -- get line from file +** +** This routine reads a single newline-terminated line from +** a file. +** +** Parameters: +** buf -- the buffer in which to place the result. +** maxch -- the maximum number of characters the +** buffer can hold. +** iop -- the file from which to read the characters. +** +** Returns: +** 0 -- end-of-file or error. +** else -- 'buf'. +*/ +char *fgetline(buf, maxch, iop) +char *buf; +int maxch; +register FILE *iop; +{ + register char *p; + register int n; + register int c; + + p = buf; + + for (n = maxch; n > 0; n--) + { + c = getc(iop); + + /* test for end-of-file or error */ + if (c == EOF) + { + *p = 0; + return ((char *) 0); + } + + /* test for newline */ + if (c == '\n') + break; + + /* insert character into buffer */ + *p++ = c; + } + + /* null-terminate the string */ + *p = 0; + return (buf); +} diff --git a/WEGA/contrib/ingres/dbs/src/gutil/syserr.c b/WEGA/contrib/ingres/dbs/src/gutil/syserr.c new file mode 100644 index 0000000..bb1d811 --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/gutil/syserr.c @@ -0,0 +1,140 @@ +# include +# include "gen.h" + +/* +** AAsyserr -- SYStem ERRor message print and abort +** +** AAsyserr acts like a printf with up to five arguments. +** +** If the first argument to AAsyserr is not zero, +** the error messages are prepended. +** +** If the extern variable 'AAproc_name' is assigned to a +** string, that string is prepended to the message. +** +** All arguments must be null-terminated. +** +** The function pointed to by 'AAexitfn' is then called. +** It is initialized to be 'exit'. +*/ + +char *AAproc_name; +int AAccerror; +extern exit(); +int (*AAexitfn)() = exit; + +# ifdef P8000 +AAsyserr(err, p0, p1, p2, p3, p4, p5) +# else +AAsyserr(err, p0) +# endif +register int err; +char *p0; +# ifdef P8000 +char *p1; +char *p2; +char *p3; +char *p4; +char *p5; +# endif +{ + register int exitvalue; + char buf[256]; + extern int errno; + extern char *AAgetformat(); +# ifndef P8000 + register char **p; + + p = &p0; +# endif + exitvalue = -1; + + putchar('\n'); + if (err) + { + if (AAproc_name) + printf("%s\n", AAproc_name); + printf("\007DB\terror\t%d\n", err); + if (errno) + printf("BS\terror\t%d\n", exitvalue = errno); + if (AAccerror) + printf("ACCESS\terror\t%d\n", AAccerror); +# ifdef P8000 + printf(AAgetformat(err, buf), p0, p1, p2, p3, p4, p5); +# else + printf(AAgetformat(err, buf), p[0], p[1], p[2], p[3], p[4], p[5]); +# endif + } + else +# ifdef P8000 + printf(p0, p1, p2, p3, p4, p5); +# else + printf(p[0], p[1], p[2], p[3], p[4], p[5]); +# endif + printf("\007\n"); + AAunlall(); + fflush(stdout); + sync(); + (*AAexitfn)(exitvalue); +} + +char *AAgetformat(err, buf) +int err; +char *buf; +{ + register int c; + register char *p; + register FILE *iop; + short i; +# ifdef SETBUF + char iobufx[BUFSIZ]; +# endif + extern char *AAerrfn(); + + /* open the appropriate error file */ + if (!(iop = fopen(AAerrfn(err / 1000), "r"))) + return (""); +# ifdef SETBUF + setbuf(iop, iobufx); +# endif + + /* read in the code and check for correct */ + for ( ; ; ) + { + p = buf; + while ((c = getc(iop)) != '\t') + { + if (c <= 0) + /* no code exists */ + goto fmt_err; + *p++ = c; + } + *p = 0; + if (AA_atoi(buf, &i)) + goto fmt_err; + if (i != err) + { + while ((c = getc(iop)) != ERRDELIM) + if (c <= 0) + goto fmt_err; + getc(iop); /* throw out the newline */ + continue; + } + + /* got the correct line */ + p = buf; + while ((c = getc(iop)) != ERRDELIM) + { + if (c <= 0) + { + fmt_err: + fclose(iop); + return (""); + } + *p++ = c; + } + *p = 0; + fclose(iop); + return (buf); + } +} diff --git a/WEGA/contrib/ingres/dbs/src/iutil/getnuser.c b/WEGA/contrib/ingres/dbs/src/iutil/getnuser.c new file mode 100644 index 0000000..69ddcf2 --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/iutil/getnuser.c @@ -0,0 +1,66 @@ +# include +# include "gen.h" +# include "../h/dbs.h" +# include "../h/aux.h" + +/* +** GETNUSER -- get line from user file based on name +** +** Given a user name as a string, this routine returns the +** corresponding line from AA_USERS into a buffer. +** +** Parameters: +** name -- the name of the user +** buf -- a buf to dump the line in (declare as +** char buf[MAXLINE + 1] +** +** Returns: +** zero -- success +** one -- failure (user not present) +*/ +getnuser(name, buf) +char *name; +char buf[]; +{ + register int c; + register char *bp; + register FILE *userf; +# ifdef SETBUF + char userbuf[BUFSIZ]; +# endif + + if (!(userf = fopen(AAztack(AApath, AA_USERS), "r"))) + AAsyserr(15001); +# ifdef SETBUF + setbuf(userf, userbuf); +# endif + + for ( ; ; ) + { + bp = buf; + while ((c = getc(userf)) != '\n') + { + if (c == EOF) + { + fclose(userf); + return (1); + } + *bp++ = c; + } + *bp++ = '\0'; + bp = buf; + while ((c = *bp++) != ':') + if (!c) + { + fclose(userf); + return (1); + } + *--bp = 0; + if (AAsequal(buf, name)) + { + fclose(userf); + *bp = ':'; + return (0); + } + } +} diff --git a/WEGA/contrib/ingres/dbs/src/monitor/buf.c b/WEGA/contrib/ingres/dbs/src/monitor/buf.c new file mode 100644 index 0000000..8d4c5b9 --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/monitor/buf.c @@ -0,0 +1,225 @@ +# include +# include "buf.h" +# include "gen.h" + +static char *Buf_flat; + +/* +** BUFFER MANIPULATION ROUTINES +** +** +** +** BUFPUT -- put character onto buffer +** +** The character 'c' is put onto the buffer 'bp'. If the buffer +** need be extended it is. +*/ +bufput(c, bp) +int c; +register struct buf **bp; +{ + register struct buf *b; + register struct buf *a; + extern struct buf *bufalloc(); + + if (!(b = *bp) || b->ptr >= &b->buffer[BUFSIZE]) + { + /* allocate new buffer segment */ + a = bufalloc(sizeof (struct buf)); + a->nextb = b; + a->ptr = a->buffer; + *bp = b = a; + } + + *b->ptr++ = c; +} + + +/* +** BUFGET -- get character off of buffer +** +** The buffer is popped and the character is returned. If the +** segment is then empty, it is returned to the free list. +*/ +bufget(bp) +register struct buf **bp; +{ + register struct buf *b; + register int c; + + if (!(b = *bp) || b->ptr == b->buffer) + return (0); /* buffer is empty -- return end of file */ + + c = *--(b->ptr); + + /* check to see if we have emptied the (non-initial) segment */ + if (b->ptr == b->buffer && b->nextb) + { + /* deallocate segment */ + *bp = b->nextb; + buffree(b); + } + + return (c); +} + + +/* +** BUFPURGE -- return an entire buffer to the free list +** +** The buffer is emptied and returned to the free list. This +** routine should be called when the buffer is to no longer +** be used. +*/ +bufpurge(bp) +register struct buf **bp; +{ + register struct buf *b; + register struct buf *a; + + b = *bp; + *bp = (struct buf *) 0; + + /* return the segments to the free list */ + while (b) + { + a = b->nextb; + buffree(b); + b = a; + } +} + + +/* +** BUFFLUSH -- flush a buffer +** +** The named buffer is truncated to zero length. However, the +** segments of the buffer are not returned to the system. +*/ +bufflush(bp) +register struct buf **bp; +{ + register struct buf *b; + + if (!(b = *bp)) + return; + + /* return second and subsequent segments to the system */ + bufpurge(&b->nextb); + + /* truncate this buffer to zero length */ + b->ptr = b->buffer; +} + + +/* +** BUFCRUNCH -- flatten a series of buffers to a string +** +** The named buffer is flattenned to a conventional C string, +** null terminated. The buffer is deallocated. The string is +** allocated "somewhere" off in memory, and a pointer to it +** is returned. +*/ +char *bufcrunch(buffer) +register struct buf **buffer; +{ + register char *p; + extern char *bufflatten(); + + p = bufflatten(*buffer, 1); + *p = 0; + *buffer = (struct buf *) 0; + return (Buf_flat); +} + + +char *bufflatten(b, length) +register struct buf *b; +int length; +{ + register char *p; + register char *q; + extern char *bufflatten(); + extern struct buf *bufalloc(); + + /* see if we have advanced to beginning of buffer */ + if (!b) /* yes, allocate the string */ + return (Buf_flat = (char *) bufalloc(length)); + + /* no, keep moving back */ + p = (char *) bufflatten(b->nextb, length + (b->ptr - b->buffer)); + + /* copy buffer into string */ + for (q = b->buffer; q < b->ptr; ) + *p++ = *q++; + + /* deallocate the segment */ + buffree(b); + + /* process next segment */ + return (p); +} + + +/* +** BUFALLOC -- allocate clear memory +** +** This is similar to the system alloc routine except that +** it has no error return, and memory is guaranteed to be clear +** when you return. +** +** It might be nice to rewrite this later to avoid the nasty +** memory fragmentation that alloc() tends toward. +** +** The error processing might have to be modified if used anywhere +** other than DBS. +*/ +struct buf *bufalloc(size) +register int size; +{ + register struct buf *p; + extern int (*AAexitfn)(); /* defined in AAsyserr.c */ + extern char *malloc(); + + if (!(p = (struct buf *) malloc(size))) + { + printf("%sMACRO processor: Speicherueberlauf\n", ERROR); + fflush(stdout); + (*AAexitfn)(-1); + } + + bufclear(p, size); + + return (p); +} + + +/* +** BUFCLEAR -- clear a block of core memory +** +** Parameters: +** buf -- pointer to area +** size -- size in bytes +*/ +bufclear(buf, size) +register char *buf; +register int size; +{ + register char *b; + + for (b = &buf[size]; buf < b; ) + *buf++ = 0; +} + + +/* +** BUFFREE -- free memory +*/ +buffree(ptr) +register char *ptr; +{ + if (!ptr) + AAsyserr(16000); + + free(ptr); +} diff --git a/WEGA/contrib/ingres/dbs/src/monitor/edit.c b/WEGA/contrib/ingres/dbs/src/monitor/edit.c new file mode 100644 index 0000000..441b77e --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/monitor/edit.c @@ -0,0 +1,64 @@ +# include +# include "gen.h" +# include "../h/dbs.h" +# include "../h/aux.h" +# include "../h/bs.h" +# include "monitor.h" + +/* +** CALL TEXT EDITOR +** +** The BS text editor is called. The actual call is to +** the macro EDITOR. If that fails, /bin/ed is called. +** This routine suppressed the autoclear function. +*/ +edit() +{ + register int i; + register char *p; + register char *editfile; + extern int exit(); + extern int (*AAexitfn)(); + extern char *getfilename(); + extern char *macro(); + + editfile = getfilename(); + if (!*editfile) + editfile = Qbname; + + Autoclear = 0; + fclose(Qryiop); + + /* FORK PROCESS & INVOKE THE EDITOR */ + fflush(stdout); + if ((Xwaitpid = fork()) < 0) + { + printf("CANNOT FORK\n"); + return; + } + if (!Xwaitpid) + { + AAexitfn = exit; + setuid(getuid()); + setgid(getgid()); + for (i = 3; i < MAXFILES; i++) + close(i); +# ifdef MACRO + if (!(p = macro(EDITOR))) +# endif + p = BIN_ED; + if (Nodayfile >= 0) + printf(">>%s\n", p); + fflush(stdout); + execlp(p, p, editfile, (char *) 0); + if (Nodayfile >= 0) + { + printf("CANNOT EXEC\n"); + fflush(stdout); + } + exit(-1); + } + + /* WAIT FOR PROCESS TO DIE */ + xwait(); +} diff --git a/WEGA/contrib/ingres/dbs/src/monitor/quit.c b/WEGA/contrib/ingres/dbs/src/monitor/quit.c new file mode 100644 index 0000000..441e02f --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/monitor/quit.c @@ -0,0 +1,162 @@ +# include +# include "gen.h" +# include "../h/dbs.h" +# include "../h/aux.h" +# include "../h/pipes.h" +# include "monitor.h" + +/* list of fatal signals */ +static char *Siglist[] = +{ + "Signal 0", + "hangup", + "interrupt", + "quit", + "illegal instruction", + "trace trap", + "IOT instruction", + "EMT instruction", + "floating point exception", + "kill", + "bus error", + "segmentation violation", + "bad argument to system call", + "write on broken pipe or link with no one to read it", + "alarm clock", + "software termination signal" +}; + +/* +** QUIT DBS +** +** This routine starts the death of the other processes. It +** then prints out the logout message, and then waits for the +** rest of the system to die. Note, however, that no relations +** are removed; this must be done using the PURGE command. +*/ +quit() +{ + register int ndx; + register int pidptr; + register int err; + int status; + int pidlist[50]; + char buf[100]; + char indexx[0400]; + extern int (*AAexitfn)(); + extern exit(); + extern int sys_nerr; + extern char *sys_errlist[]; + extern char *AAcustomer(); + extern long time(); + extern char *ctime(); + +# ifdef xMTR1 + AAtTfp(1, -1, "entered QUIT\n"); +# endif + + /* INTERCEPT ALL FURTHER INTERRUPTS */ + signal(1, (int (*)()) 1); + signal(2, (int (*)()) 1); + signal(3, (int (*)()) 1); + AAexitfn = exit; + + close(W_down); + +# ifdef xMTR3 + AAtTfp(1, 2, "unlinking %s\n", Qbname); +# endif + + /* REMOVE THE QUERY-BUFFER FILE */ + fclose(Qryiop); + unlink(Qbname); +# ifdef MACRO + if (Trapfile) + fclose(Trapfile); +# endif + pidptr = 0; + err = 0; + + /* clear out the system error index table */ + for (ndx = 0; ndx < 0400; ndx++) + indexx[ndx] = 0; + + /* wait for all process to terminate */ + while ((ndx = wait(&status)) != -1) + { +# ifdef xMTR2 + AAtTfp(1, 5, "QUIT: pid %u: 0%o/0%o\n", ndx, status >> 8, status & 0177); +# endif + pidlist[pidptr++] = ndx; + if (status & 0177) + { + printf("%u: ", ndx); + ndx = status & 0177; + if (ndx > sizeof Siglist / sizeof Siglist[0]) + printf("Abnormal Termination %u", ndx); + else + printf("%s", Siglist[ndx]); + if (status & 0200) + printf(" -- Core Dumped"); + putchar('\n'); + err++; + indexx[0377 - ndx]++; + } + else + indexx[(status >> 8) & 0377]++; + } + if (err) + { + printf("pid list:"); + for (ndx = 0; ndx < pidptr; ndx++) + printf(" %u", pidlist[ndx]); + putchar('\n'); + } + + /* print index of system errors */ + err = 0; + for (ndx = 1; ndx <= 0377; ndx++) + { + if (!indexx[ndx]) + continue; + if (ndx <= sys_nerr) + { + if (!err) + printf("\nBS error dictionary:\n"); + printf("%3d: %s\n", ndx, sys_errlist[ndx]); + } + if (!err) + err = ndx; + } + if (err > 0 && err <= sys_nerr) + putchar('\n'); + + /* PRINT LOG CUE ? */ + if (Nodayfile >= 0) + { + printf(LOG_1, AAversion); + time(buf); +# ifdef ESER_VMX + printf("%s\n%s", AAcustomer(), ctime(*((long *) buf))); +# else + printf("%s\n%s", AAcustomer(), ctime(buf)); +# endif + if (!getuser(AAusercode, buf)) + { + for (ndx = 0; buf[ndx]; ndx++) + if (buf[ndx] == ':') + break; + buf[ndx] = 0; + printf(LOG_21, buf); + } + else + printf(LOG_22); + printf(LOG_3); + } +# ifdef xMTR1 + AAtTfp(1, 3, "QUIT: exit(%d)\n", err); +# endif + AAunlall(); + fflush(stdout); + exit(err); +} diff --git a/WEGA/contrib/ingres/dbs/src/monitor/shell.c b/WEGA/contrib/ingres/dbs/src/monitor/shell.c new file mode 100644 index 0000000..fd70315 --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/monitor/shell.c @@ -0,0 +1,67 @@ +# include +# include "gen.h" +# include "../h/dbs.h" +# include "../h/aux.h" +# include "../h/bs.h" +# include "monitor.h" + +/* +** CALL BS SHELL +** +** The BS shell is called. Shell() first tries to call an +** alternate shell defined by the macro SHELL, and if it fails +** calls BIN_SH. +** +** If an argument is supplied, it is a shell file which is +** supplied to the shell. +*/ +shell() +{ + register int i; + register char *shellfile; + register char *sh_arg; + extern int exit(); + extern int (*AAexitfn)(); + extern char *macro(); + extern char *getfilename(); + + sh_arg = "-c"; + shellfile = getfilename(); + if (!*shellfile) + { +# ifdef MACRO + if (!(shellfile = macro(SHELL))) +# endif + sh_arg = "-i"; + } + + fclose(Qryiop); + + fflush(stdout); + if ((Xwaitpid = fork()) == -1) + { + printf("CANNOT FORK\n"); + return; + } + if (!Xwaitpid) + { + AAexitfn = exit; + setuid(getuid()); + setgid(getgid()); + for (i = 3; i < MAXFILES; i++) + close(i); + if (Nodayfile >= 0) + printf(">>%s\n", shellfile? shellfile: BIN_SH); + fflush(stdout); + execlp(BIN_SH, BIN_SH, sh_arg, shellfile, (char *) 0); + if (Nodayfile >= 0) + { + printf("CANNOT EXEC\n"); + fflush(stdout); + } + exit(-1); + } + + /* wait for shell to complete */ + xwait(); +} diff --git a/WEGA/contrib/ingres/dbs/src/monitor/writeout.c b/WEGA/contrib/ingres/dbs/src/monitor/writeout.c new file mode 100644 index 0000000..e4dcaf4 --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/monitor/writeout.c @@ -0,0 +1,48 @@ +# include +# include "gen.h" +# include "../h/dbs.h" +# include "../h/aux.h" +# include "monitor.h" + +/* +** WRITE OUT QUERY BUFFER TO BS FILE +** +** The logical buffer is written to a BS file, the name of which +** must follow the \w command. +*/ +writeout() +{ + register int i; + register char *file; + register int source; + register int dest; + char buf[BUFSIZ]; + extern char *getfilename(); + + file = getfilename(); + if (!*file || *file == '-') + { + printf("%sUnakzeptabler file name `%s'\n", ERROR, file); + return; + } + + if ((dest = creat(file, 0644)) < 0) + { + printf("%screate WRITE file `%s'\n", ERROR, file); + return; + } + + if (!Nautoclear) + Autoclear = 1; + + if ((source = open(Qbname, 0)) < 0) + AAsyserr(16025, Qbname); + + fflush(Qryiop); + + while ((i = read(source, buf, sizeof buf)) > 0) + write(dest, buf, i); + + close(source); + close(dest); +} diff --git a/WEGA/contrib/ingres/dbs/src/qrymod/cat_desc.c b/WEGA/contrib/ingres/dbs/src/qrymod/cat_desc.c new file mode 100644 index 0000000..20d734d --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/qrymod/cat_desc.c @@ -0,0 +1,24 @@ +# include "gen.h" +# include "../h/dbs.h" +# include "../h/aux.h" +# include "../h/access.h" + +/* +** SYSTEM RELATION DESCRIPTOR CACHE DEFINITION +** +** *** TOOLED FOR QUERY MODIFICATION PROCESS *** +*/ + +DESC Reldes; +DESC Prodes; +DESC Intdes; +DESC Treedes; + +struct desxx Desxx[] = +{ + AA_REL, &Reldes, &AAdmin.adreld, + AA_PROTECT, &Prodes, (DESC *) 0, + AA_INTEG, &Intdes, (DESC *) 0, + AA_TREE, &Treedes, (DESC *) 0, + (char *) 0 +}; diff --git a/WEGA/contrib/ingres/dbs/src/qrymod/d_view.c b/WEGA/contrib/ingres/dbs/src/qrymod/d_view.c new file mode 100644 index 0000000..1b085b8 --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/qrymod/d_view.c @@ -0,0 +1,68 @@ +# include +# include "gen.h" +# include "../h/dbs.h" +# include "../h/aux.h" +# include "../h/pipes.h" +# include "../h/tree.h" +# include "../h/symbol.h" +# include "../h/catalog.h" +# include "qrymod.h" + +extern QTREE *Treeroot; +extern DESC Reldes; +extern struct pipfrmt Pipe; + +/* +** D_VIEW -- define view +** +** This procedure connects the tree in with the AA_REL catalog +** and inserts the view tree into the AA_TREE catalog. +** +** The information in the pipe is expected to come as follows: +** create for view, with S_VIEW bit set so that a +** physical relation is not created. +** define tree, which will put the translation tree +** into the AA_TREE catalog. +** define view, which will connect the two together. +** The first two absolutely must be done before +** this step can be called. +*/ +d_view() +{ + char viewid[MAXNAME + 1]; + + /* + ** Read parameters. + ** Only parameter is view name (which must match the + ** name of the Resultvar). + */ + + if (rdpipe(P_NORM, &Pipe, R_up, viewid, 0) > MAXNAME + 1) + AAsyserr(19019); + AApad(viewid, MAXNAME); + + /* done with pipe... */ + rdpipe(P_SYNC, &Pipe, R_up); + +# ifdef xQTR3 + /* do some extra validation */ + if (!Treeroot) + AAsyserr(19020); + if (Qmode != mdDEFINE) + AAsyserr(19021, Qmode); + if (Resultvar < 0) + AAsyserr(19022, Resultvar); + if (!Rangev[Resultvar].rused || !AAbequal(Rangev[Resultvar].relid, viewid, MAXNAME)) + AAsyserr(19023, Rangev[Resultvar].rused, Rangev[Resultvar].relid); +# endif + + Rangev[Resultvar].rused = FALSE; + Resultvar = -1; + Qmode = -1; + + /* output tree to AA_TREE catalog */ + puttree(Treeroot, viewid, AAusercode, mdVIEW); + + /* clear Treeroot to detect some errors */ + Treeroot = (QTREE *) 0; +} diff --git a/WEGA/contrib/ingres/dbs/src/qrymod/fillprotup.c b/WEGA/contrib/ingres/dbs/src/qrymod/fillprotup.c new file mode 100644 index 0000000..2a08069 --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/qrymod/fillprotup.c @@ -0,0 +1,140 @@ +# include +# include "gen.h" +# include "../h/dbs.h" +# include "../h/aux.h" +# include "../h/bs.h" +# include "../h/catalog.h" +# include "../h/pipes.h" +# include "qrymod.h" + +extern struct pipfrmt Pipe; + +/* +** FILLPROTUP -- fill the protection tuple from pipe. +** +** This routine is broken off from d_prot.c so that we +** don't get symbol table overflows. +** +** Parameters: +** protup -- pointer to the protection tuple to fill. +** +** Returns: +** A bool telling whether we have PERMIT ALL TO ALL +** permission. +** +** Side Effects: +** The R_up pipe is flushed. +*/ +fillprotup(protup) +struct protect *protup; +{ + register struct protect *pt; + register int i; + register char *p; + char buf[30]; + int all_pro; + short ix; + char ubuf[MAXLINE + 1]; + + /* + ** Fill in the protection tuple with the information + ** from the parser, validating as we go. + ** + ** Also, determine if we have a PERMIT xx to ALL + ** with no further qualification case. The variable + ** 'all_pro' is set to reflect this. + */ + + all_pro = TRUE; + pt = protup; + + /* read operation set */ + if (rdpipe(P_NORM, &Pipe, R_up, buf, 0) <= 0) + AAsyserr(19030); + if (AA_atoi(buf, &ix)) + AAsyserr(19031, buf); + pt->proopset = ix; + if ((ctoi(pt->proopset) & PRO_RETR) != 0) + pt->proopset |= PRO_TEST | PRO_AGGR; + + /* read relation name */ + if (rdpipe(P_NORM, &Pipe, R_up, buf, 0) > MAXNAME + 1) + AAsyserr(19032); + AApmove(buf, pt->prorelid, MAXNAME, ' '); + + /* read relation owner */ + if (rdpipe(P_NORM, &Pipe, R_up, buf, 0) != 3) + AAsyserr(19033); + AAbmove(buf, pt->prorelown, 2); + + /* read user name */ + rdpipe(P_NORM, &Pipe, R_up, buf, 0); + if (AAsequal(buf, "all")) + AAbmove(" ", pt->prouser, 2); + else + { + /* look up user in AA_USERS */ + if (getnuser(buf, ubuf)) + far_error(3591, -1, Resultvar, buf, (char *) 0); + for (p = ubuf; *p != ':' && *p != 0; p++) + continue; + AAbmove(++p, pt->prouser, 2); + if (p[0] == ':' || p[1] == ':' || p[2] != ':') + AAsyserr(19034, ubuf); + all_pro = FALSE; + } + + /* read terminal id */ + rdpipe(P_NORM, &Pipe, R_up, buf, 0); + if (AAsequal(buf, "all")) + { + AAbmove(" ", pt->proterm, PROTERM); + } + else + { + if (AAbequal(buf, "tty", 3)) + AApmove(&buf[3], pt->proterm, PROTERM, ' '); + else + AApmove(buf, pt->proterm, PROTERM, ' '); + all_pro = FALSE; + } + + /* read starting time of day */ + rdpipe(P_NORM, &Pipe, R_up, buf, 0); + if (AA_atoi(buf, &ix)) + AAsyserr(19035, buf); + pt->protodbgn = ix; + if (ix > 0) + all_pro = FALSE; + + /* read ending time of day */ + rdpipe(P_NORM, &Pipe, R_up, buf, 0); + if (AA_atoi(buf, &ix)) + AAsyserr(19036, buf); + pt->protodend = ix; + if (ix < 24 * 60 - 1) + all_pro = FALSE; + + /* read beginning day of week */ + rdpipe(P_NORM, &Pipe, R_up, buf, 0); + i = cvt_dow(buf); + if (i < 0) + far_error(3594, -1, Resultvar, buf, (char *) 0); /* bad dow */ + pt->prodowbgn = i; + if (i > 0) + all_pro = FALSE; + + /* read ending day of week */ + rdpipe(P_NORM, &Pipe, R_up, buf, 0); + i = cvt_dow(buf); + if (i < 0) + far_error(3594, -1, Resultvar, buf, (char *) 0); /* bad dow */ + pt->prodowend = i; + if (i < 6) + all_pro = FALSE; + + /* finished with pipe... */ + rdpipe(P_SYNC, &Pipe, R_up); + + return (all_pro); +} diff --git a/WEGA/contrib/ingres/dbs/src/qrymod/qrymod.c b/WEGA/contrib/ingres/dbs/src/qrymod/qrymod.c new file mode 100644 index 0000000..8695499 --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/qrymod/qrymod.c @@ -0,0 +1,45 @@ +# include "gen.h" +# include "../h/dbs.h" +# include "../h/aux.h" +# include "../h/tree.h" +# include "qrymod.h" + +/* +** QRYMOD -- main driver for query modification +** +** Reads in the query tree, performs the modifications, writes +** it out, and does process syncronization with below. The +** calling routine must sync with the process above. +** +** Parameters: +** root1 -- a pointer to the tree to modify. +** +** Returns: +** A pointer to the modified tree. +*/ +QTREE *qrymod(root1) +QTREE *root1; +{ + register QTREE *root; + extern QTREE *view(); + extern QTREE *integrity(); + extern QTREE *protect(); + + root = root1; + +# ifdef xQTR1 + if (AAtTf(1, 0)) + treepr(root, "->QRYMOD"); +# endif + + /* view processing */ + root = view(root); + + /* integrity processing */ + root = integrity(root); + + /* protection processing */ + root = protect(root); + + return (root); +} diff --git a/WEGA/contrib/ingres/dbs/src/qrymod/range.c b/WEGA/contrib/ingres/dbs/src/qrymod/range.c new file mode 100644 index 0000000..b1589e9 --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/qrymod/range.c @@ -0,0 +1,186 @@ +# include "gen.h" +# include "../h/dbs.h" +# include "../h/symbol.h" +# include "../h/tree.h" +# include "qrymod.h" + +/* +** RANGE.C -- range table manipulation +** +** Defines: +** declare -- declare variable +** clrrange -- clear range table +** mapvars -- map varno's in a tree to unique numbers +** Remap[] -- a mapping from specified (preferred) varno's +** to actual varno's. -1 indicates no mapping. +** Presumably this cannot be set when reading an +** original query tree, but can happen easily when +** reading a tree from AA_TREE catalog. +** Rangev[] -- the range table. +*/ + +int Remap[MAXVAR + 1]; +struct rngtab Rangev[MAXVAR + 1]; + +/* +** CLRRANGE -- clear range table(s) +** +** The range table (Rangev) and range table map (Remap) are +** initialized in one of two ways. +** +** Parameters: +** prim -- if TRUE, the primary range table (Rangev) +** is cleared and Remap is set to be FULL (for +** reading in an initial query). If FALSE, +** Rangev is untouched, but Remap is cleared. +** +** Side Effects: +** Rangev[i].rused set to FALSE for all entries. +** Remap[i] set to -1 or MAXVAR + 1 for all entries. +*/ +clrrange(prim) +register int prim; +{ + register int i; + + for (i = 0; i < MAXVAR + 1; i++) + { + if (prim) + { + Rangev[i].rused = FALSE; + Remap[i] = MAXVAR + 1; + } + else + Remap[i] = -1; + } +} + + +/* +** DECLARE -- declare a range variable +** +** A range variable is declared. If possible, the preferred varno +** stated is used (this is the one already in the tree). This +** should always be possible when reading the original tree (and +** should probably stay this way to make debugging easier). When +** not possible, a new varno is chosen, and Remap[oldvarno] is +** set to newvarno, so that the tree can later be patched up by +** 'mapvars' (below). +** +** Parameters: +** varno -- the preferred varno. +** name -- the relation name. +** stat -- the 'relstat' of this relation. +** +** Side Effects: +** Rangev and possible Remap are updated. No Rangev +** entry is ever touched if the 'rused' field +** is set. +*/ +declare(varno, name, owner, stat) +int varno; +char *name; +char owner[2]; +int stat; +{ + register int i; + register int vn; + register int s; + + vn = varno; + s = stat; + + /* check for preferred slot in range table available */ + if (Rangev[vn].rused) + { + /* used: check if really redeclared */ + if (Remap[vn] >= 0) + AAsyserr(19047, vn); + + /* try to find another slot */ + for (i = 0; i < MAXVAR + 1; i++) + if (!Rangev[i].rused) + break; + + if (i >= MAXVAR + 1) + { + far_error(3100, Qmode, -1, name, (char *) 0); /* too many variables */ + } + + Remap[vn] = i; + vn = i; + } + + /* declare variable in the guaranteed empty slot */ + AAbmove(name, Rangev[vn].relid, MAXNAME); + AAbmove(owner, Rangev[vn].rowner, 2); + Rangev[vn].rstat = s; + Rangev[vn].rused = TRUE; + +# ifdef xQTR2 + AAtTfp(11, 0, "DECLARE: %d, %.12s, %.2s, 0%o into slot %d\n", + varno, name, owner, s, vn); +# endif +# ifdef xQTR3 + AAtTfp(11, 1, "DECLARE: %.12s%.2s 0%o %d\n", Rangev[vn].relid, + Rangev[vn].rowner, Rangev[vn].rstat, Rangev[vn].rused); +# endif +} + + +/* +** MAPVARS -- remap varno's to be unique in AA_TREE tree +** +** A tree is scanned for VAR nodes; when found, the +** mapping defined in Remap[] is applied. This is done so that +** varno's as defined in trees in the AA_TREE catalog will be +** unique with respect to varno's in the user's query tree. For +** example, if the view definition uses variable 1 and the user's +** query also uses variable 1, the routine 'declare' will (when +** called to define the view definition varno 1) allocate a new +** varno (e.g. 3) in a free slot in the range table, and put +** the index of the new slot into the corresponding word of Remap; +** in this example, Remap[1] == 3. This routine does the actual +** mapping in the tree. +** +** Parameters: +** tree -- pointer to tree to be remapped. +** +** Side Effects: +** the tree pointed to by 'tree' is modified according +** to Remap[]. +*/ +mapvars(tree) +QTREE *tree; +{ + register QTREE *t; + register int i; + + t = tree; +# ifdef xQTR3 + if (AAtTf(12, 0) && t != NULL && t->sym.type == ROOT) + { + treepr(t, "mapvars:"); + for (i = 0; i < MAXVAR + 1; i++) + if (Rangev[i].rused && Remap[i] >= 0) + printf("\t%d => %d\n", i, Remap[i]); + } +# endif + + while (t != NULL) + { + /* map right subtree */ + mapvars(t->right); + + /* check this node */ + if (t->sym.type == VAR) + { + i = ((VAR_NODE *) t)->varno; + if ((i = Remap[i]) >= 0) + ((VAR_NODE *) t)->varno = i; + } + + /* map left subtree (iteratively) */ + t = t->left; + } +} diff --git a/WEGA/contrib/ingres/dbs/src/qrymod/readtree.c b/WEGA/contrib/ingres/dbs/src/qrymod/readtree.c new file mode 100644 index 0000000..ffe818a --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/qrymod/readtree.c @@ -0,0 +1,329 @@ +# include +# include "gen.h" +# include "../h/dbs.h" +# include "../h/catalog.h" +# include "../h/tree.h" +# include "../h/symbol.h" +# include "../h/pipes.h" +# include "qrymod.h" + +/* +** READTREE.C -- query tree input procedures +** +** This file contains routines to read trees from pipes and +** catalogs. +** +** Defines: +** readqry +** readsymbol +** readtree +** pipetrrd +** relntrrd +** gettree +** Qmode +** Resultvar +*/ + +extern struct pipfrmt Pipe; +extern struct pipfrmt Outpipe; + +int Qmode; /* Query mode */ +int Resultvar; /* Result variable number */ + +/* +** 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, initialize) +int (*rdfn)(); /* tree read function */ +int initialize; /* if set, initialize Qbuf */ +{ + register SYMBOL *s; + SRCID locbuf; + register QTREE *rtval; + register char *p; + extern xerror(); + extern char *readtree(); + extern QTREE *trbuild(); + +# ifdef xQTR1 + AAtTfp(70, 0, "READQRY:\n"); +# endif + + if (initialize) + { + /* initialize for new query block */ + initbuf(Qbuf, QBUFSIZ, QBUFFULL, xerror); + clrrange(TRUE); + Resultvar = -1; + Qmode = -1; + } + else + clrrange(FALSE); + + s = (SYMBOL *) &locbuf; + + /* read symbols from input */ + for ( ; ; ) + { + readsymbol(s, rdfn); +# ifdef xQTR1 + if (AAtTfp(70, 1, "%d, %d, %d/", + s->type, s->len, ctou(s->value[0]))) + { + if (s->type == SOURCEID) + printf("%.12s", ((SRCID *) s)->srcname); + putchar('\n'); + } +# endif + switch (s->type) + { + case QMODE: + if (Qmode != -1) + AAsyserr(19048); + Qmode = s->value[0]; + break; + + case RESULTVAR: + if (Resultvar != -1) + AAsyserr(19049); + Resultvar = s->value[0]; + break; + + case SOURCEID: + declare(((SRCID *) s)->srcvar, ((SRCID *) s)->srcname, ((SRCID *) s)->srcown, ((SRCID *) s)->srcstat); + break; + + case TREE: /* beginning of tree, no more other stuff */ + p = readtree(s, rdfn); + rtval = trbuild(p); + if (!rtval) + far_error(STACKFULL, -1, -1, (char *) 0); + return (rtval); + + default: + AAsyserr(19050, s->type); + } + } +} + + +/* +** READSYMBOL +** reads in one symbol from pipe into symbol struct. +*/ +readsymbol(dest, rdfn) +char *dest; /* if non-zero, pts to allocated space */ +int (*rdfn)(); /* tree read function */ +{ + register int len; + register SYMBOL *p; + extern char *need(); + + /* check if enough space for type and len of sym */ + p = (SYMBOL *) (dest? dest: need(Qbuf, SYM_HDR_SIZ)); + if ((*rdfn)(p, TYP_LEN_SIZ) < TYP_LEN_SIZ) + goto err3; + len = ctou(p->len); + if (len) + { + if (!dest) + { + /* this will be contiguous with above need call */ + need(Qbuf, len); + } + if ((*rdfn)(p->value, len) < len) + goto err3; + } + + return; + +err3: + AAsyserr(19051); +} + + +/* +** READTREE +** reads in tree symbols into a buffer up to a root (end) symbol +*/ +char *readtree(tresym, rdfn) +SYMBOL *tresym; +int (*rdfn)(); +{ + register QTREE *nod; + register char *rtval; + extern char *need(); + + rtval = need(Qbuf, QT_HDR_SIZ); + AAbmove(tresym, &(((QTREE *) rtval)->sym), TYP_LEN_SIZ); /* insert type and len of TREE node */ + for ( ; ; ) + { + /* space for left & right pointers */ + nod = (QTREE *) need(Qbuf, QT_PTR_SIZ); + readsymbol((char *) 0, rdfn); +# ifdef xQTR1 + if (AAtTf(70, 2)) + nodepr(nod, TRUE); +# endif + if (nod->sym.type == ROOT) + return (rtval); + } +} + + +/* +** PIPETRRD -- read tree from R_up pipe +** +** This routine looks like a rdpipe with only the last two +** parameters. +** +** Parameters: +** ptr -- pointer to data area +** cnt -- byte count +** +** Returns: +** actual number of bytes read +*/ +pipetrrd(ptr, cnt) +register char *ptr; +register int cnt; +{ + return (rdpipe(P_NORM, &Pipe, R_up, ptr, cnt)); +} + + +/* +** RELNTRRD -- read tree from AA_TREE relation +** +** This looks exactly like the 'pipetrrd' call, except that info +** comes from the AA_TREE catalog instead of from the pipe. It +** must be initialized by calling it with a NULL pointer and +** the segment name wanted as 'treeid'. +** +** Parameters: +** ptr -- NULL -- "initialize". +** else -- pointer to read area. +** cnt -- count of number of bytes to read. +** treeid -- if ptr == NULL, this is the tree id, +** otherwise this parameter is not supplied. +** +** Returns: +** count of actual number of bytes read. +** +** Side Effects: +** static variables are adjusted correctly. Note that +** this routine can be used on only one tree +** at one time. +*/ +relntrrd(ptr, cnt, treerelid, treeowner, treetype, treeid) +char *ptr; +int cnt; +char *treerelid; +char *treeowner; +char treetype; +int treeid; +{ + static struct tree trseg; + static char *trp; + static short seqno; + register char *p; + register int n; + register int i; + struct tree trkey; + struct tup_id tid; + + p = ptr; + n = cnt; + + if (!p) + { + /* initialize -- make buffer appear empty */ + trp = &trseg.treetree[sizeof trseg.treetree]; + AAbmove(treerelid, trseg.treerelid, MAXNAME); + AAbmove(treeowner, trseg.treeowner, 2); + trseg.treetype = treetype; + trseg.treeid = treeid; + seqno = 0; + opencatalog(AA_TREE, 0); + +# ifdef xQTR2 + AAtTfp(70, 6, "RELNTRRD: n=%.12s o=%.2s t=%d i=%d\n", + treerelid, treeowner, treetype, treeid); +# endif + + return (0); + } + + /* fetch characters */ + while (n-- > 0) + { + /* check for segment empty */ + if (trp >= &trseg.treetree[sizeof trseg.treetree]) + { + /* then read new segment */ + AAam_clearkeys(&Treedes); + AAam_setkey(&Treedes, &trkey, trseg.treerelid, TREERELID); + AAam_setkey(&Treedes, &trkey, trseg.treeowner, TREEOWNER); + AAam_setkey(&Treedes, &trkey, &trseg.treetype, TREETYPE); + AAam_setkey(&Treedes, &trkey, &trseg.treeid, TREEID); + AAam_setkey(&Treedes, &trkey, &seqno, TREESEQ); + seqno++; + if (i = AAgetequal(&Treedes, &trkey, &trseg, &tid)) + AAsyserr(19052, i); + trp = &trseg.treetree[0]; + } + + /* do actual character fetch */ + *p++ = *trp++; + } + + return (cnt); +} + + +/* +** GETTREE -- get tree from AA_TREE catalog +** +** This function, given an internal treeid, fetches and builds +** that tree from the AA_TREE catalog. There is nothing exciting +** except the mapping of variables, done by mapvars(). +** +** Parameters: +** treeid -- internal id of tree to fetch and build. +** init -- passed to 'readqry' to tell whether or not +** to initialize the query buffer. +** +** Returns: +** Pointer to root of tree. +*/ +QTREE *gettree(treerelid, treeowner, treetype, treeid, init) +char *treerelid; +char *treeowner; +char treetype; +int treeid; +int init; +{ + register QTREE *t; + extern int relntrrd(); + + /* initialize relntrrd() for this treeid */ + relntrrd(NULL, 0, treerelid, treeowner, treetype, treeid); + + /* read and build query tree */ + t = readqry(relntrrd, init); + + /* remap varno's to be unique */ + if (!init) + mapvars(t); + + return (t); +} diff --git a/WEGA/contrib/ingres/dbs/src/qrymod/tree.c b/WEGA/contrib/ingres/dbs/src/qrymod/tree.c new file mode 100644 index 0000000..a53ec90 --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/qrymod/tree.c @@ -0,0 +1,47 @@ +# include "gen.h" +# include "../h/dbs.h" +# include "../h/tree.h" +# include "../h/symbol.h" +# include "qrymod.h" + +/* +** TREE -- create new tree node. +** +** This is a stripped down version of the same thing in the +** parser. +** +** It only knows about lengths of zero and two. +** +** Parameters: +** lptr -- the left pointer. +** rptr -- the right pointer. +** typ -- the node type. +** len -- the node length. +** value -- the node value. +** +** Returns: +** A pointer to the created node. +*/ +QTREE *tree(lptr, rptr, typ, len, value) +QTREE *lptr; +QTREE *rptr; +char typ; +int len; +int value; +{ + register QTREE *tptr; + extern char *need(); + register int l; + + l = len; + + tptr = (QTREE *) need(Qbuf, l + QT_HDR_SIZ); + tptr->left = lptr; + tptr->right = rptr; + tptr->sym.type = typ; + tptr->sym.len = l; + + if (l > 0) + tptr->sym.value[0] = value; + return (tptr); +} diff --git a/WEGA/contrib/ingres/dbs/src/qrymod/treepr.c b/WEGA/contrib/ingres/dbs/src/qrymod/treepr.c new file mode 100644 index 0000000..b955da0 --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/qrymod/treepr.c @@ -0,0 +1,173 @@ +# include "gen.h" +# include "../h/dbs.h" +# include "../h/symbol.h" +# include "../h/tree.h" +# include "../h/aux.h" +# include "qrymod.h" + +/* +** TREEPR -- print tree for debugging +** +** This module prints a tree for debugging purposes. There are +** two interfaces: treepr prints an entire treeree, and nodepr +** prints a single node. +** +** Defines: +** treepr -- tree print interface. +** rcsvtrpr -- the recursive part to traverse the tree. +** nodepr -- node print interface. +*/ + +extern char *Qmdname[]; /* defined in util.c */ + +/* +** TREEPR -- print tree for debugging +** +** This routine prints a tree for debugging. +** +** Parameters: +** t -- root of tree to be printed +** label -- label to print for identifying the tree. NULL +** is OK and produces a default label. +*/ +treepr(tree, label) +register QTREE *tree; +register char *label; +{ + register int i; + + /* print label */ + putchar('\n'); + if (label != (char *) 0) + printf("%s ", label); + printf("Querytree @ 0%o:\n", tree); + + /* print range table */ + for (i = 0; i < MAXVAR + 1; i++) + { + if (!Rangev[i].rused) + continue; + printf("range of %d is %.12s [O=%.2s, S=0%o]\n", + i, Rangev[i].relid, Rangev[i].rowner, Rangev[i].rstat); + } + + /* print query type */ + if (Qmode >= 0) + printf("%s ", Qmdname[Qmode]); + + /* print result relation if realistic */ + if (Resultvar >= 0) + printf("Resultvar %d ", Resultvar); + putchar('\n'); + + /* print tree */ + rcsvtrpr(tree); + + /* print exciting final stuff */ + putchar('\n'); +} + + +/* +** RCSVTRPR -- traverse and print tree +** +** This function does the real stuff for treepr. It recursively +** traverses the tree in postfix order, printing each node. +** +** Parameters: +** tree -- the root of the tree to print. +*/ +rcsvtrpr(tree) +register QTREE *tree; +{ + while (tree != (QTREE *) 0) + { + rcsvtrpr(tree->left); + nodepr(tree, FALSE); + tree = tree->right; + } +} + + +/* +** NODEPR -- print node for debugging +** +** Parameters: +** tree -- the node to print. +*/ +nodepr(tree) +register QTREE *tree; +{ + register int ty; + register int l; + register char *cp; + + ty = tree->sym.type; + l = ctou(tree->sym.len); + + printf("0%o: 0%o, 0%o/ ", tree, tree->left, tree->right); + printf("%d, %d: ", ty, l); + + switch (ty) + { + case VAR: + printf("%d.%d [%d/%d]", + ((VAR_NODE *) tree)->varno, ((VAR_NODE *) tree)->attno, + ((VAR_NODE *) tree)->frmt, ctou(((VAR_NODE *) tree)->frml)); + break; + + case RESDOM: + printf("%d [%d/%d]", ((RES_NODE *) tree)->resno, + ((VAR_NODE *) tree)->frmt, ((VAR_NODE *) tree)->frml); + break; + + case AOP: + printf("%d [%d/%d] [%d/%d]", ((RES_NODE *) tree)->resno, + ((VAR_NODE *) tree)->frmt, ((VAR_NODE *) tree)->frml, + ((AOP_NODE *) tree)->agfrmt, ((AOP_NODE *) tree)->agfrml); + break; + + case UOP: + case BOP: + case COP: + case INT: + switch (tree->sym.len) + { + case sizeof (char): + case sizeof (short): + printf("%d", tree->sym.value[0]); + break; + + case sizeof (long): + printf("%ld", ((I4TYPE *) tree->sym.value)->i4type); + break; + } + break; + + case FLOAT: + printf("%.10f", ((I4TYPE *) tree->sym.value)->i4type); + break; + + case CHAR: + cp = (char *) tree->sym.value; + while (l--) + { + putchar(*cp); + cp++; + } + break; + + case TREE: + case AND: + case OR: + case QLEND: + case BYHEAD: + case ROOT: + case AGHEAD: + break; + + default: + AAsyserr(19053, ty); + } + printf("/\n"); +} diff --git a/WEGA/contrib/ingres/dbs/src/qrymod/writetree.c b/WEGA/contrib/ingres/dbs/src/qrymod/writetree.c new file mode 100644 index 0000000..a82caef --- /dev/null +++ b/WEGA/contrib/ingres/dbs/src/qrymod/writetree.c @@ -0,0 +1,140 @@ +# include +# include "gen.h" +# include "../h/dbs.h" +# include "../h/aux.h" +# include "../h/pipes.h" +# include "../h/tree.h" +# include "../h/symbol.h" +# include "qrymod.h" + +/* +** WRITETREE.C -- query tree output routines +** +** These routines write out a query tree in internal format. +** +** Defines: +** writetree +** writeqry +** writesym +*/ + +extern struct pipfrmt Pipe; +extern struct pipfrmt Outpipe; + +/* +** WRITETREE -- write a query tree +** +** A query tree is written to the down pipe. The parameter is +** the root of the tree to be written. +** +** Parameters: +** q1 -- the root of the tree to write. +** wrfn -- the function to call to do physical +** writes. +*/ +writetree(q1, wrfn) +QTREE *q1; +int (*wrfn)(); +{ + register QTREE *q; + register int l; + register char t; + + q = q1; + + /* write the subtrees */ + if (q->left != NULL) + writetree(q->left, wrfn); + if (q->right != NULL) + writetree(q->right, wrfn); + + /* write this node */ + t = q->sym.type; + if (t == AND || t == ROOT || t == AGHEAD) + q->sym.len = 0; + (*wrfn)(&(q->sym), TYP_LEN_SIZ); + if (l = ctou(q->sym.len)) + (*wrfn)(q->sym.value, l); +# ifdef xQTR1 + if (AAtTf(70, 5)) + nodepr(q, TRUE); +# endif +} + + +/* +** WRITEQRY -- write a whole query +** +** An entire query is written, including range table, and so +** forth. +** +** Parameters: +** root -- the root of the tree to write. +** wrfn -- the function to do the physical write. +*/ +writeqry(root, wrfn) +QTREE *root; +int (*wrfn)(); +{ + register int i; + short resvar; + SRCID sid; + + /* write the query mode */ + if (Qmode >= 0) + { + resvar = Qmode; + writesym(QMODE, sizeof (short), &resvar, wrfn); + } + + /* write the range table */ + for (i = 0; i < MAXVAR + 1; i++) + { + if (Rangev[i].rused) + { + ((SYMBOL *) &sid)->type = SOURCEID; + ((SYMBOL *) &sid)->len = SRC_SIZ; + AApmove(Rangev[i].relid, sid.srcname, MAXNAME, ' '); + sid.srcvar = i; + sid.srcstat = Rangev[i].rstat; + AAbmove(Rangev[i].rowner, sid.srcown, 2); + (*wrfn)(&sid, TYP_LEN_SIZ); + (*wrfn)(&sid.srcvar, SRC_SIZ); + } + } + + /* write a possible result variable */ + if (Resultvar >= 0) + { + resvar = Resultvar; + writesym(RESULTVAR, sizeof (short), &resvar, wrfn); + } + + /* write the tree */ + writetree(root, wrfn); +} + + +/* +** WRITESYM -- write a symbol block +** +** A single symbol entry of the is written. +** a 'value' of zero will not be written. +*/ +writesym(typ, len, value, wrfn) +int typ; +int len; +char *value; +int (*wrfn)(); +{ + SYMBOL sym; + register char *v; + register int l; + + sym.type = ctou(typ); + sym.len = l = ctou(len); + (*wrfn)(&sym, TYP_LEN_SIZ); + v = value; + if (v != 0) + (*wrfn)(v, l); +}