This commit is contained in:
Oliver Lehmann 1989-04-03 19:44:14 +00:00
parent d86a2ba4c1
commit 9f95488636
17 changed files with 1976 additions and 0 deletions

View File

@ -0,0 +1,52 @@
# include <stdio.h>
/*
** 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);
}

View File

@ -0,0 +1,140 @@
# include <stdio.h>
# 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);
}
}

View File

@ -0,0 +1,66 @@
# include <stdio.h>
# 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);
}
}
}

View File

@ -0,0 +1,225 @@
# include <stdio.h>
# 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);
}

View File

@ -0,0 +1,64 @@
# include <stdio.h>
# 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();
}

View File

@ -0,0 +1,162 @@
# include <stdio.h>
# 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);
}

View File

@ -0,0 +1,67 @@
# include <stdio.h>
# 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();
}

View File

@ -0,0 +1,48 @@
# include <stdio.h>
# 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);
}

View File

@ -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
};

View File

@ -0,0 +1,68 @@
# include <stdio.h>
# 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;
}

View File

@ -0,0 +1,140 @@
# include <stdio.h>
# 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);
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -0,0 +1,329 @@
# include <stdio.h>
# 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);
}

View File

@ -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);
}

View File

@ -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");
}

View File

@ -0,0 +1,140 @@
# include <stdio.h>
# 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);
}