[net.sources] a small dbms

oz@yetti.UUCP (Ozan Yigit) (09/02/85)

I apologize. The second part of the previous posting was way too
big for some sites. It got chopped off. Here is a reposting of
all C sources, in three little parts. Some have inquired for the
source for the formatted documentation. Unfortunately, it was missing
from the decus tape. Also, you will notice that there is no man page,
nor a makefile.

Oz
------------- SNIP ------- SNIP -------- SNIP -------------------
#!/bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #!/bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	cmd.c
#	com.c
#	cre.c
#	err.c
#	iex.c
# This archive created: Mon Sep  2 16:30:16 1985
export PATH; PATH=/bin:$PATH
echo shar: extracting "'cmd.c'" '(20167 characters)'
if test -f 'cmd.c'
then
	echo shar: over-writing existing file "'cmd.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'cmd.c'
X/* SDB - command parser */
X
X#include "stdio.h"
X#include "sdbio.h"
X
Xextern int dbv_token;
Xextern char dbv_tstring[];
Xextern int dbv_tvalue;
Xextern struct ifile *dbv_ifp;
Xextern struct macro *dbv_macros;
Xextern int dbv_fold;
X
X#ifdef Lattice
Xint _fmode = 0;  /*dns*/
X#endif
X
X/* db_parse - parse a command */
Xint db_parse(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
X  char *fmt;
X{
X    int sts;
X
X    /* check for a command line */
X    if (fmt != NULL)
X        db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);
X
X    /* determine the statement type */
X    switch (db_ntoken()) {
X    case ';':   sts = TRUE;
X                break;
X    case COMPRESS:
X                sts = db_squeeze(NULL);
X                break;
X    case CREATE:
X                sts = create();
X                break;
X    case DEFINE:
X                sts = mc_define();
X                break;
X    case DELETE:
X                sts = delete();
X                break;
X    case EXIT:
X                exit();
X    case EXPORT:
X                sts = db_export(NULL);
X                break;
X    case EXTRACT:
X                sts = db_extract(NULL);
X                break;
X    case HELP:
X                sts = help();
X                break;
X    case IMPORT:
X                sts = db_import(NULL);
X                break;
X    case INSERT:
X                sts = insert();
X                break;
X    case PRINT:
X                sts = print();
X                break;
X    case SELECT:
X                sts = select();
X                break;
X    case SET:
X                sts = set();
X                break;
X    case SHOW:
X                sts = mc_show();
X                break;
X    case SORT:
X                sts = db_sort(NULL);
X                break;
X    case UPDATE:
X                sts = update();
X                break;
X    default:
X                return (db_ferror(SYNTAX));
X    }
X
X    return (sts);
X}
X
X/* help - print a short help message */
Xstatic int help()
X{
X    FILE *fp;
X    int ch;
X
X    if ((fp = fopen("sdb.hlp","r")) != NULL) {
X     /* while ((ch = agetc(fp)) != EOF)    dns */
X        while ((ch =  getc(fp)) != EOF)
X            putchar(ch);
X        fclose(fp);
X    }
X    else
X        printf("No online help available.  Read the manual\n");
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* create - create a new relation */
Xstatic int create()
X{
X    struct relation *rptr;
X    char aname[STRINGMAX+1];
X    int atype;
X
X    /* get relation name */
X    if (db_ntoken() != ID)
X        return (db_ferror(SYNTAX));
X
X    /* start relation creation */
X    if ((rptr = db_rcreate(dbv_tstring)) == NULL)
X        return (FALSE);
X
X    /* check for attribute list */
X    if (db_ntoken() != '(') {
X        free(rptr);
X        return (db_ferror(SYNTAX));
X    }
X
X    /* parse the attributes */
X    while (TRUE) {
X
X        /* get the attribute name */
X        if (db_ntoken() != ID) {
X            free(rptr);
X            return (db_ferror(SYNTAX));
X        }
X        strcpy(aname,dbv_tstring);
X
X        /* get the attribute type */
X        db_ntoken();
X        if (dbv_token == CHAR)
X            atype = TCHAR;
X        else if (dbv_token == NUM)
X            atype = TNUM;
X        else {
X            free(rptr);
X            return (db_ferror(SYNTAX));
X        }
X
X        /* get the attribute size */
X        if (db_ntoken() != NUMBER) {
X            free(rptr);
X            return (db_ferror(SYNTAX));
X        }
X
X        /* add the attribute */
X        if (!db_rcattr(rptr,aname,atype,dbv_tvalue)) {
X            free(rptr);
X            return (FALSE);
X        }
X
X        /* check for end of attributes */
X        if (db_token() != ID)
X            break;
X    }
X
X    /* check for attribute list end */
X    if (db_ntoken() != ')') {
X        free(rptr);
X        return (db_ferror(SYNTAX));
X    }
X
X    /* check for relation size */
X    if (db_ntoken() != NUMBER) {
X        free(rptr);
X        return (db_ferror(SYNTAX));
X    }
X
X    /* finish relation creation */
X    if (!db_rcheader(rptr))
X        return (FALSE);
X    if (!db_rctuples(rptr,dbv_tvalue))
X        return (FALSE);
X    if (!db_rcdone(rptr))
X        return (FALSE);
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* insert - insert a tuple into a relation */
Xstatic int insert()
X{
X    struct scan *sptr;
X    struct attribute *aptr;
X    char aname[ANSIZE+1],avalue[STRINGMAX+1];
X    int tcnt,astart,i;
X
X    /* get relation name */
X    if (db_token() == ID)
X        db_ntoken();
X    else
X        strcpy(dbv_tstring,"sdbcur");
X
X    /* make sure that the rest of the line is blank */
X    if (!db_flush())
X        return (FALSE);
X
X    /* open the relation */
X    if ((sptr = db_ropen(dbv_tstring)) == NULL)
X        return (FALSE);
X
X    /* insert tuples */
X    for (tcnt = 0; ; tcnt++) {
X
X        /* print separator if not the first tuple */
X        if (tcnt != 0)
X            printf("----\n");
X
X        /* get attribute values */
X        astart = 1;
X        for (i = 0; i < NATTRS; i++) {
X
X            /* get a pointer to the current attribute */
X            aptr = &sptr->sc_relation->rl_header.hd_attrs[i];
X
X            /* check for the last attribute */
X            if (aptr->at_name[0] == 0)
X                break;
X
X            /* get the attribute name */
X            strncpy(aname,aptr->at_name,ANSIZE); aname[ANSIZE] = 0;
X
X            /* setup null prompt strings */
X            db_prompt(NULL,NULL);
X
X            /* prompt and input attribute value */
X            while (TRUE) {
X                if (dbv_ifp == NULL)
X                    if (strlen(aname) < 8)
X                        printf("%s\t\t: ",aname);
X                    else
X                        printf("%s\t: ",aname);
X                if (db_gline(avalue) != NULL)
X                    break;
X            }
X
X            /* check for last insert */
X            if (i == 0 && avalue[0] == EOS)
X                break;
X
X            /* store the attribute value */
X            db_aput(aptr,&sptr->sc_tuple[astart],avalue);
X
X            /* update the attribute start */
X            astart += aptr->at_size;
X        }
X
X        /* check for last insert */
X        if (avalue[0] == EOS)
X            break;
X
X        /* store the new tuple */
X        if (!db_rstore(sptr)) {
X            db_rclose(sptr);
X            return (FALSE);
X        }
X    }
X
X    /* close the relation */
X    db_rclose(sptr);
X
X    /* check number of tuples inserted */
X    if (tcnt != 0) {
X
X        /* print tuple count */
X        printf("[ %d inserted ]\n",tcnt);
X    }
X    else
X        printf("[ none inserted ]\n");
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* delete - delete tuples from a relation */
Xstatic int delete()
X{
X    struct sel *slptr;
X    struct srel *srptr;
X    int tcnt;
X
X    /* parse the retrieval clause */
X    if ((slptr = db_retrieve(NULL)) == NULL)
X        return (FALSE);
X
X    /* loop through the retrieved tuples */
X    for (tcnt = 0; db_fetch(slptr); tcnt++)
X
X        /* delete the retrieved tuples */
X        for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next)
X            if (!db_rdelete(srptr->sr_scan)) {
X                db_done(slptr);
X                return (FALSE);
X            }
X
X    /* finish the retrieval */
X    db_done(slptr);
X
X    /* check number of tuples deleted */
X    if (tcnt != 0) {
X
X        /* print tuple count */
X        printf("[ %d deleted ]\n",tcnt);
X    }
X    else
X        printf("[ none deleted ]\n");
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* update - update tuples from a relation */
Xstatic int update()
X{
X    struct sel *slptr;
X    struct sattr *saptr;
X    struct attribute *aptr;
X    char aname[ANSIZE+1],avalue[STRINGMAX+1],*ap;
X    int tcnt;
X
X    /* parse the selection clause */
X    if ((slptr = db_select(NULL)) == NULL)
X        return (FALSE);
X
X    /* make sure that the rest of the line is blank */
X    if (!db_flush()) {
X        db_done(slptr);
X        return (FALSE);
X    }
X
X    /* loop through the selected tuples */
X    for (tcnt = 0; db_fetch(slptr); tcnt++) {
X
X        /* print separator if not the first tuple */
X        if (tcnt != 0)
X            printf("----\n");
X
X        /* loop through the selected attributes */
X        for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {
X
X            /* get the attribute pointer */
X            aptr = saptr->sa_attr;
X
X            /* get the attribute name */
X            strncpy(aname,aptr->at_name,ANSIZE); aname[ANSIZE] = 0;
X
X            /* get the attribute value */
X            db_aget(aptr,saptr->sa_aptr,avalue);
X            for (ap = avalue; isspace(*ap); ap++)
X                ;
X
X            /* print it */
X            if (strlen(aname) < 8)
X                printf("%s\t\t: %s\n",aname,ap);
X            else
X                printf("%s\t: %s\n",aname,ap);
X
X            /* setup null prompt strings */
X            db_prompt(NULL,NULL);
X
X            /* prompt and input attribute value */
X            while (TRUE) {
X                if (strlen(aname) < 8)
X                    printf("%s\t\t: ",aname);
X                else
X                    printf("%s\t: ",aname);
X                if (db_gline(avalue) != NULL)
X                    break;
X            }
X
X            /* store the attribute value */
X            if (avalue[0] != EOS) {
X                db_aput(aptr,saptr->sa_aptr,avalue);
X                saptr->sa_srel->sr_update = TRUE;
X            }
X        }
X
X        /* update the tuples */
X        db_update(slptr);
X    }
X
X    /* finish the selection */
X    db_done(slptr);
X
X    /* check number of tuples updated */
X    if (tcnt != 0) {
X
X        /* print tuple count */
X        printf("[ %d updated ]\n",tcnt);
X    }
X    else
X        printf("[ none updated ]\n");
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* print - print tuples from a set of relations */
Xstatic int print()
X{
X    struct sel *slptr;
X    FILE *ffp,*ofp;
X    int tcnt;
X
X    /* parse the using clause */
X    if (!using(&ffp,".frm"))
X        return (FALSE);
X
X    /* parse the select clause */
X    if ((slptr = db_select(NULL)) == NULL)
X        return (FALSE);
X
X    /* parse the into clause */
X    if (!db_to(&ofp,".txt")) {
X        db_done(slptr);
X        return (FALSE);
X    }
X
X    /* check for normal or formated output */
X    if (ffp == NULL)
X        tcnt = table(ofp,slptr);
X    else
X        tcnt = form(ofp,slptr,ffp);
X
X    /* finish the selection */
X    db_done(slptr);
X
X    /* close the form definition file */
X    if (ffp != NULL)
X        fclose(ffp);
X
X    /* close the output file */
X    if (ofp != stdout)
X        fclose(ofp);
X
X    /* check number of tuples selected */
X    if (tcnt != 0)
X        printf("[ %d found ]\n",tcnt);
X    else
X        printf("[ none found ]\n");
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* select - select tuples from a set of relations */
Xstatic int select()
X{
X    struct sel *slptr;
X    struct relation *rptr;
X    struct sattr *saptr;
X    char *aname,*tbuf;
X    int tcnt,abase,i;
X
X    /* parse the select clause */
X    if ((slptr = db_select(NULL)) == NULL)
X        return (FALSE);
X
X    /* create a new relation */
X    if ((rptr = db_rcreate("sdbcur")) == NULL) {
X        db_done(slptr);
X        return (FALSE);
X    }
X
X    /* create the selected attributes */
X    for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {
X
X        /* decide which attribute name to use */
X        if ((aname = saptr->sa_name) == NULL)
X            aname = saptr->sa_aname;
X
X        /* add the attribute */
X        if (!db_rcattr(rptr,aname,saptr->sa_attr->at_type,
X                                  saptr->sa_attr->at_size)) {
X            free(rptr);
X            db_done(slptr);
X            return (FALSE);
X        }
X    }
X
X    /* create the relation header */
X    if (!db_rcheader(rptr)) {
X        db_done(slptr);
X        return (FALSE);
X    }
X
X    /* allocate and initialize a tuple buffer */
X    if ((tbuf = calloc(1,rptr->rl_size)) == NULL) {
X        db_rcdone(rptr);
X        return (db_ferror(INSMEM));
X    }
X    tbuf[0] = ACTIVE;
X
X    /* loop through the selected tuples */
X    for (tcnt = 0; db_fetch(slptr); tcnt++) {
X
X        /* create the tuple from the selected attributes */
X        abase = 1;
X        for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {
X            for (i = 0; i < saptr->sa_attr->at_size; i++)
X                tbuf[abase + i] = saptr->sa_aptr[i];
X            abase += i;
X        }
X
X        /* write the tuple */
X        if (write(rptr->rl_fd,tbuf,rptr->rl_size) != rptr->rl_size) {
X            db_rcdone(rptr);
X            free(tbuf);
X            return (db_ferror(INSBLK));
X        }
X        rptr->rl_tcnt++;
X        rptr->rl_tmax++;
X    }
X
X    /* finish the selection */
X    db_done(slptr);
X
X    /* finish relation creation */
X    if (!db_rcdone(rptr))
X        return (FALSE);
X
X    /* check number of tuples selected */
X    if (tcnt != 0)
X        printf("[ %d found ]\n",tcnt);
X    else
X        printf("[ none found ]\n");
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* mc_define - define a macro */
Xstatic int mc_define()
X{
X    struct macro *mptr,*mlast;
X    struct mtext *tptr,*tlast;
X    char textline[LINEMAX+1];
X
X    /* get macro name */
X    if (db_xntoken() != ID)
X        return (db_ferror(SYNTAX));
X
X    /* make sure that the rest of the line is blank */
X    if (!db_flush())
X        return (FALSE);
X
X    /* find the macro in the macro table and free it */
X    for (mptr = dbv_macros, mlast = NULL; mptr != NULL; mlast = mptr, mptr = mptr->mc_next)
X        if (db_scmp(mptr->mc_name,dbv_tstring) == 0) {
X            if (mlast == NULL)
X                dbv_macros = mptr->mc_next;
X            else
X                mlast->mc_next = mptr->mc_next;
X            mc_free(mptr);
X        }
X
X    /* allocate and initialize a macro structure */
X    if ((mptr = malloc(sizeof(struct macro))) == NULL)
X        return (db_ferror(INSMEM));
X    if ((mptr->mc_name = malloc(strlen(dbv_tstring)+1)) == NULL) {
X        free(mptr);
X        return (db_ferror(INSMEM));
X    }
X    strcpy(mptr->mc_name,dbv_tstring);
X    mptr->mc_mtext = NULL;
X
X    /* setup null prompt strings */
X    db_prompt(NULL,"SDB-DEF> ");
X
X    /* get definition text */
X    for (tlast = NULL; ; tlast = tptr) {
X
X        /* get a line */
X        db_gline(textline);
X        if (textline[0] == EOS || textline[0] == '\n')
X            break;
X
X        /* allocate a macro text structure */
X        if ((tptr = malloc(sizeof(struct mtext))) == NULL) {
X            mc_free(mptr);
X            return (db_ferror(INSMEM));
X        }
X        if ((tptr->mt_text = malloc(strlen(textline)+1)) == NULL) {
X            mc_free(mptr);
X            return (db_ferror(INSMEM));
X        }
X        strcpy(tptr->mt_text,textline);
X        tptr->mt_next = NULL;
X
X        /* link it into the macro list */
X        if (tlast == NULL)
X            mptr->mc_mtext = tptr;
X        else
X            tlast->mt_next = tptr;
X    }
X
X    /* link the new macro into the macro list */
X    if (tlast == NULL)
X        mc_free(mptr);
X    else {
X        mptr->mc_next = dbv_macros;
X        dbv_macros = mptr;
X    }
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* mc_show - show a macro */
Xstatic int mc_show()
X{
X    struct macro *mptr;
X    struct mtext *tptr;
X
X    /* get macro name */
X    if (db_xntoken() != ID)
X        return (db_ferror(SYNTAX));
X
X    /* find the macro in the macro table */
X    for (mptr = dbv_macros; mptr != NULL; mptr = mptr->mc_next)
X        if (db_scmp(mptr->mc_name,dbv_tstring) == 0) {
X            for (tptr = mptr->mc_mtext; tptr != NULL; tptr = tptr->mt_next)
X                printf("\t%s\n",tptr->mt_text);
X            break;
X        }
X
X    /* check for successful search */
X    if (mptr == NULL)
X        printf("*** no macro named: %s ***\n",dbv_tstring);
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* mc_free - free a macro definition */
Xstatic mc_free(mptr)
X  struct macro *mptr;
X{
X    struct mtext *tptr;
X
X    while ((tptr = mptr->mc_mtext) != NULL) {
X        mptr->mc_mtext = tptr->mt_next;
X        free(tptr->mt_text);
X        free(tptr);
X    }
X    free(mptr->mc_name);
X    free(mptr);
X}
X
X/* db_to - redirect output into a file */
Xint db_to(pfp,ext)
X  FILE **pfp; char *ext;
X{
X#ifdef vms
X    int fd;
X#endif
X
X    /* assume no into clause */
X    *pfp = stdout;
X
X    /* check for "into <fname>" */
X    if (db_token() != INTO)
X        return (TRUE);
X    db_ntoken();
X    if (db_ntoken() == ID)
X        strcat(dbv_tstring,ext);
X    else if (dbv_token != STRING)
X        return (db_ferror(SYNTAX));
X
X    /* open the output file */
X#ifdef vms
X    if ((fd = creat(dbv_tstring,0,"rfm=var","rat=cr")) == -1)
X        return (db_ferror(OUTCRE));
X    *pfp = fdopen(fd,"w");
X#else
X#ifdef Lattice
X    _fmode = 0x8000;  /*dns*/
X#endif
X    *pfp = fopen(dbv_tstring,"w");  /*dns*/
X#ifdef Lattice
X    _fmode = 0;       /*dns*/
X#endif
X    if (*pfp == NULL)               /*dns*/
X        return (db_ferror(OUTCRE)); /*dns*/
X#endif
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* using - get form definition file spec */
Xstatic int using(pfp,ext)
X  FILE **pfp; char *ext;
X{
X    /* assume no using clause */
X    *pfp = NULL;
X
X    /* check for "using <fname>" */
X    if (db_token() != USING)
X        return (TRUE);
X    db_ntoken();
X    if (db_ntoken() == ID)
X        strcat(dbv_tstring,ext);
X    else if (dbv_token != STRING)
X        return (db_ferror(SYNTAX));
X
X    /* open the input file */
X    if ((*pfp = fopen(dbv_tstring,"r")) == NULL)
X        return (db_ferror(INPFNF));
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* table - output a relation table */
Xstatic int table(fp,slptr)
X  FILE *fp; struct sel *slptr;
X{
X    int tcnt;
X
X    /* loop through the selected tuples */
X    for (tcnt = 0; db_fetch(slptr); tcnt++) {
X
X        /* print table head on first tuple selected */
X        if (tcnt == 0)
X            db_thead(fp,slptr);
X
X        /* print the tuple */
X        db_tentry(fp,slptr);
X    }
X
X    /* print table foot */
X    if (tcnt != 0)
X        db_tfoot(fp,slptr);
X
X    /* return the tuple count */
X    return (tcnt);
X}
X
X/* form - process a form */
Xstatic int form(ofp,slptr,ffp)
X  FILE *ofp; struct sel *slptr; FILE *ffp;
X{
X    char aname[ANSIZE+1];
X    int ch,tcnt;
X
X    /* loop through the selected tuples */
X    for (tcnt = 0; db_fetch(slptr); tcnt++) {
X
X        /* reposition the form definition file */
X        fseek(ffp,0L,0);
X
X        /* process the form */
X        while ((ch = getc(ffp)) != -1)
X            if (ch == '<') {
X                get_aname(ffp,aname);
X                put_avalue(ofp,slptr,aname);
X            }
X            else
X                putc(ch,ofp);
X    }
X
X    /* return the tuple count */
X    return (tcnt);
X}
X
X/* get_aname - get an attribute name */
Xstatic get_aname(fp,aname)
X  FILE *fp; char *aname;
X{
X    int ch;
X
X    while ((ch = getc(fp)) != '>')
X        if (!isspace(ch))
X            *aname++ = ch;
X    *aname = 0;
X}
X
X/* put_avalue - output attribute value */
Xstatic put_avalue(fp,slptr,aname)
X  FILE *fp; struct sel *slptr; char *aname;
X{
X    struct sattr *saptr;
X    char *saname;
X    int i;
X
X    /* loop through the selected attributes */
X    for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {
X
X        /* check the selected attribute name */
X        if ((saname = saptr->sa_name) == NULL)
X            saname = saptr->sa_aname;
X        if (db_scmp(saname,aname) == 0)
X            break;
X    }
X
X    if (saptr == NULL) {
X        fprintf(fp,"<error>");
X        return;
X    }
X
X    /* get the attribute value */
X    for (i = 0; i < saptr->sa_attr->at_size; i++)
X        if (saptr->sa_aptr[i] != 0)
X            putc(saptr->sa_aptr[i],fp);
X        else
X            putc(' ',fp);
X}
X
X/* set - set internal parameters */
Xstatic int set()
X{
X    int value;
X
X    /* process each set request */
X    while (db_token() == ID) {
X
X        /* skip the identifier */
X        db_ntoken();
X
X        /* check for "no" */
X        if (db_scmp(dbv_tstring,"no") == 0) {
X            value = FALSE;
X            if (db_token() != ID)
X                return (db_ferror(BADSET));
X            db_ntoken();
X        }
X        else
X            value = TRUE;
X
X        /* check for parameter to set */
X        if (db_scmp(dbv_tstring,"fold") == 0)
X            dbv_fold = value;
X        else
X            return (db_ferror(BADSET));
X    }
X
X    /* return successfully */
X    return (TRUE);
X}
X
SHAR_EOF
if test 20167 -ne "`wc -c 'cmd.c'`"
then
	echo shar: error transmitting "'cmd.c'" '(should have been 20167 characters)'
fi
echo shar: extracting "'com.c'" '(9887 characters)'
if test -f 'com.c'
then
	echo shar: over-writing existing file "'com.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'com.c'
X/* SDB - expression compiler
X    syntax:
X        <expr>          ::= <lor> <EOS>
X        <lor>           ::= <land> { '|' <land> }
X        <land>          ::= <relat> { '&' <relat> }
X        <relat>         ::= <primary> { <relop> <primary> }
X        <primary>       ::= <factor> | <unop> <unary>
X        <factor>        ::= <number> | <string> | '(' <query> ')'
X        <number>        ::= <digit> | <number> <digit>
X        <string>        ::= '"' <chars> '"'
X        <chars>         ::= nil | <chars> <character>
X        <relop>         ::= '=' | '<>' | '<' | '>' | '<=' | '>='
X        <unop>          ::= '+' | '-' | '~'
X*/
X
X#include "sdbio.h"
X
Xextern int dbv_token;
Xextern char dbv_tstring[];
Xextern int dbv_tvalue;
X
Xextern int db_xand();
Xextern int db_xor();
Xextern int db_xnot();
Xextern int db_xlss();
Xextern int db_xleq();
Xextern int db_xeql();
Xextern int db_xgeq();
Xextern int db_xgtr();
Xextern int db_xneq();
Xextern int db_xpush();
Xextern int db_xstop();
X
Xstatic union codecell code[CODEMAX+1];
Xstatic int cndx;
Xstatic struct sel *selptr;
X
X/* compile - compile a boolean expression */
Xint db_compile(slptr)
X  struct sel *slptr;
X{
X    int result,i;
X    union codecell *cptr;
X#ifdef Lattice
X    int (*dns)();  /*dns*/
X#endif
X
X    /* save the selection structure pointer */
X    selptr = slptr;
X
X    /* initialize the code array index */
X    cndx = 0;
X
X    /* parse the boolean expression */
X    if (!expr(&result)) {
X        code[cndx++].c_operator = db_xstop;
X        freelit(code);
X        return (FALSE);
X    }
X
X    /* terminate the code */
X    code[cndx++].c_operator = db_xstop;
X
X    /* allocate space for the code array */
X    if ((cptr = malloc(sizeof(union codecell) * cndx)) == NULL) {
X        freelit(code);
X        return (FALSE);
X    }
X
X    /* store the code into the code array */
X    slptr->sl_where = cptr;
X    for (i = 0; i < cndx; i++) {
X        (*cptr++).c_operator = code[i].c_operator;
X#ifndef Lattice
X        if (code[i].c_operator == db_xpush)
X#else
X        if ( code[i].c_operator == (dns=db_xpush) )  /*dns*/
X#endif
X            (*cptr++).c_operand = code[++i].c_operand;
X    }
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* db_fcode - free a code array */
Xdb_fcode(slptr)
X  struct sel *slptr;
X{
X    /* make sure there is a where clause */
X    if (slptr->sl_where == NULL)
X        return;
X
X    /* free the literals */
X    freelit(slptr->sl_where);
X
X    /* free the code array */
X    free(slptr->sl_where);
X}
X
X/* operator - insert an operator into the code array */
Xstatic int operator(opr)
X  int (*opr)();
X{
X    /* insert the operator */
X    if (cndx < CODEMAX)
X        code[cndx++].c_operator = opr;
X    else
X        return (db_ferror(CDSIZE));
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* operand - insert an operand into the code array */
Xstatic int operand(opr)
X  struct operand *opr;
X{
X    /* insert the push operator */
X    if (!operator(db_xpush))
X        return (FALSE);
X
X    /* insert the operand */
X    if (cndx < CODEMAX)
X        code[cndx++].c_operand = opr;
X    else
X        return (db_ferror(CDSIZE));
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* expr - compile an expression */
Xstatic int expr(result)
X  int *result;
X{
X    int lval,rval;
X
X    if (!land(&lval))
X        return (FALSE);
X    while (db_token() == '|') {
X        db_ntoken();
X        if (!land(&rval))
X            return (FALSE);
X        if (!operator(db_xor))
X            return (FALSE);
X    }
X    *result = lval;
X    return (TRUE);
X}
X
Xstatic int land(result)
X  int *result;
X{
X    int lval,rval;
X
X    if (!relat(&lval))
X        return (FALSE);
X    while (db_token() == '&') {
X        db_ntoken();
X        if (!relat(&rval))
X            return (FALSE);
X        if (!operator(db_xand))
X            return (FALSE);
X    }
X    *result = lval;
X    return (TRUE);
X}
X
Xstatic int relat(result)
X  int *result;
X{
X    int lval,rval;
X    int tkn;
X
X    if (!primary(&lval))
X        return (FALSE);
X    while (db_token() <= LSS && dbv_token >= GTR) {
X        tkn = db_ntoken();
X        if (!primary(&rval))
X            return (FALSE);
X        switch (tkn) {
X        case LSS:
X                if (!operator(db_xlss))
X                    return (FALSE);
X                break;
X        case LEQ:
X                if (!operator(db_xleq))
X                    return (FALSE);
X                break;
X        case EQL:
X                if (!operator(db_xeql))
X                    return (FALSE);
X                break;
X        case NEQ:
X                if (!operator(db_xneq))
X                    return (FALSE);
X                break;
X        case GEQ:
X                if (!operator(db_xgeq))
X                    return (FALSE);
X                break;
X        case GTR:
X                if (!operator(db_xgtr))
X                    return (FALSE);
X                break;
X        }
X    }
X    *result = lval;
X    return (TRUE);
X}
X
Xstatic int primary(result)
X  int *result;
X{
X    int val;
X    int tkn;
X
X    if (db_token() == '~') {
X        tkn = db_ntoken();
X        if (!primary(&val))
X            return (FALSE);
X        switch (tkn) {
X        case '~':
X                if (!operator(db_xnot))
X                    return (FALSE);
X                break;
X        }
X    }
X    else
X        if (!factor(&val))
X            return (FALSE);
X    *result = val;
X    return (TRUE);
X}
X
Xstatic int factor(result)
X  int *result;
X{
X    int val;
X
X    if (db_token() == '(') {
X        db_ntoken();
X        if (!expr(&val))
X            return (FALSE);
X        if (db_token() != ')')
X            return (db_ferror(SYNTAX));
X        db_ntoken();
X    }
X    else
X        if (!get_operand(&val))
X            return (FALSE);
X    *result = val;
X    return (TRUE);
X}
X
X/* get_operand - get an operand (number, string, or attribute) */
Xstatic int get_operand(result)
X  int *result;
X{
X    /* determine operand type */
X    if (db_ntoken() == NUMBER)
X        return (get_number(result));
X    else if (dbv_token == ID)
X        return (get_attr(result));
X    else if (dbv_token == STRING)
X        return (get_string(result));
X    else
X        return (db_ferror(SYNTAX));
X}
X
X/* get_attr - get an attribute argument */
Xstatic int get_attr(result)
X  int *result;
X{
X    struct operand *opr;
X    char rname[RNSIZE+1],aname[ANSIZE+1];
X    char *aptr; int atype,alen;
X
X    /* save the attribute name */
X    strncpy(aname,dbv_tstring,ANSIZE); aname[ANSIZE] = EOS;
X
X    /* check for a "." indicating a qualified attribute name */
X    if (db_token() == '.') {
X        db_ntoken();
X
X        /* the previous ID was really a relation name */
X        strcpy(rname,aname);
X
X        /* check for the real attribute name */
X        if (db_ntoken() != ID)
X            return (db_ferror(SYNTAX));
X
X        /* save the attribute name */
X        strncpy(aname,dbv_tstring,ANSIZE); aname[ANSIZE] = EOS;
X
X        /* lookup the attribute name */
X        if (!db_sattr(selptr,rname,aname,&atype,&aptr,&alen))
X            return (FALSE);
X    }
X    else
X        if (!db_sattr(selptr,NULL,aname,&atype,&aptr,&alen))
X            return (FALSE);
X
X    /* get a new operand structure */
X    if ((opr = malloc(sizeof(struct operand))) == NULL)
X        return (db_ferror(INSMEM));
X
X    /* initialize the new operand structure */
X    opr->o_type = ATTR;
X    opr->o_value.ov_char.ovc_type = atype;
X    opr->o_value.ov_char.ovc_string = aptr;
X    opr->o_value.ov_char.ovc_length = alen;
X
X    /* insert the operand into the code array */
X    if (!operand(opr)) {
X        free(opr);
X        return (FALSE);
X    }
X
X    /* store operand type */
X    *result = atype;
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* get_number - get a numeric operand */
Xstatic int get_number(result)
X  int *result;
X{
X    struct operand *opr;
X
X    /* get a new operand structure */
X    if ((opr = malloc(sizeof(struct operand))) == NULL)
X        return (db_ferror(INSMEM));
X
X    /* initialize the new operand structure */
X    opr->o_type = LITERAL;
X    if ((opr->o_value.ov_char.ovc_string =
X                malloc(strlen(dbv_tstring)+1)) == NULL) {
X        free(opr);
X        return (db_ferror(INSMEM));
X    }
X    opr->o_value.ov_char.ovc_type = TNUM;
X    strcpy(opr->o_value.ov_char.ovc_string,dbv_tstring);
X    opr->o_value.ov_char.ovc_length = strlen(dbv_tstring);
X
X    /* insert the operand into the code array */
X    if (!operand(opr)) {
X        free(opr->o_value.ov_char.ovc_string); free(opr);
X        return (FALSE);
X    }
X
X    /* operand type is number */
X    *result = TNUM;
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* get_string - get a string operand */
Xstatic int get_string(result)
X  int *result;
X{
X    struct operand *opr;
X
X    /* get a new operand structure */
X    if ((opr = malloc(sizeof(struct operand))) == NULL)
X        return (db_ferror(INSMEM));
X
X    /* initialize the new operand structure */
X    opr->o_type = LITERAL;
X    if ((opr->o_value.ov_char.ovc_string =
X                malloc(strlen(dbv_tstring)+1)) == NULL) {
X        free(opr);
X        return (db_ferror(INSMEM));
X    }
X    opr->o_value.ov_char.ovc_type = TCHAR;
X    strcpy(opr->o_value.ov_char.ovc_string,dbv_tstring);
X    opr->o_value.ov_char.ovc_length = strlen(dbv_tstring);
X
X    /* insert the operand into the code array */
X    if (!operand(opr)) {
X        free(opr->o_value.ov_char.ovc_string); free(opr);
X        return (FALSE);
X    }
X
X    /* operand type is character */
X    *result = TCHAR;
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* freelit - free the literals in a code array */
Xstatic freelit(cptr)
X  union codecell *cptr;
X{
X#ifdef Lattice
X    int (*dns)();  /*dns*/
X    for (; (*cptr).c_operator != (dns=db_xstop); cptr++)  /*dns*/
X        if ((*cptr).c_operator == (dns=db_xpush) )        /*dns*/
X#else
X    for (; (*cptr).c_operator != db_xstop; cptr++)
X        if ((*cptr).c_operator == db_xpush )
X#endif
X            if ((*++cptr).c_operand->o_type == LITERAL)
X                free((*cptr).c_operand->o_value.ov_char.ovc_string);
X}
X
SHAR_EOF
if test 9887 -ne "`wc -c 'com.c'`"
then
	echo shar: error transmitting "'com.c'" '(should have been 9887 characters)'
fi
echo shar: extracting "'cre.c'" '(3881 characters)'
if test -f 'cre.c'
then
	echo shar: over-writing existing file "'cre.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'cre.c'
X/* SDB - relation creation routines */
X
X#include "sdbio.h"
X
X/* db_rcreate(rname) - begin the creation of a new relation */
Xstruct relation *db_rcreate(rname)
X  char *rname;
X{
X    struct relation *rptr;
X
X    /* allocate the relation structure */
X    if ((rptr = calloc(1,sizeof(struct relation))) == NULL)
X        return (db_nerror(INSMEM));
X
X    /* initialize the relation structure */
X    strncpy(rptr->rl_name,rname,RNSIZE);
X    rptr->rl_tcnt = 0;
X    rptr->rl_tmax = 0;
X    rptr->rl_data = 512;
X    rptr->rl_size = 1;
X    rptr->rl_header.hd_attrs[0].at_name[0] = 0;
X
X    /* return the new relation structure pointer */
X    return (rptr);
X}
X
X/* db_rcheader - create the relation header */
Xint db_rcheader(rptr)
X  struct relation *rptr;
X{
X    char rname[RNSIZE+1],filename[RNSIZE+13];
X
X    /* initialize the relation file header */
X    db_cvbytes(rptr->rl_tcnt,rptr->rl_header.hd_tcnt);
X    db_cvbytes(rptr->rl_tmax,rptr->rl_header.hd_tmax);
X    db_cvbytes(rptr->rl_data,rptr->rl_header.hd_data);
X    db_cvbytes(rptr->rl_size,rptr->rl_header.hd_size);
X
X    /* create the relation file name */
X    strncpy(rname,rptr->rl_name,RNSIZE); rname[RNSIZE] = 0;
X    sprintf(filename,"%s.sdb",rname);
X
X    /* create the relation file */
X    if ((rptr->rl_fd = creat(filename,0)) == -1) {
X        free(rptr);
X        return (db_ferror(RELCRE));
X    }
X
X    /* write the header to the relation file */
X    if (write(rptr->rl_fd,&rptr->rl_header,512) != 512) {
X        close(rptr->rl_fd);
X        free(rptr);
X        return (db_ferror(BADHDR));
X    }
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* db_rctuples - create the relation tuples */
Xint db_rctuples(rptr,tcnt)
X  struct relation *rptr; unsigned int tcnt;
X{
X    unsigned int i;
X    char *tbuf;
X
X    /* store the number of tuples */
X    rptr->rl_tmax = tcnt;
X
X    /* allocate a tuple buffer */
X    if ((tbuf = calloc(1,rptr->rl_size)) == NULL)
X        return (db_ferror(INSMEM));
X
X    /* write null tuples into the file */
X    for (i = 0; i < tcnt; i++)
X        if (write(rptr->rl_fd,tbuf,rptr->rl_size) != rptr->rl_size) {
X            free(tbuf);
X            return (db_ferror(INSBLK));
X        }
X
X    /* free the tuple buffer */
X    free(tbuf);
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* db_rcdone(rptr) - finish the creation of a new relation */
Xint db_rcdone(rptr)
X  struct relation *rptr;
X{
X    /* initialize the relation file header */
X    db_cvbytes(rptr->rl_tcnt,rptr->rl_header.hd_tcnt);
X    db_cvbytes(rptr->rl_tmax,rptr->rl_header.hd_tmax);
X
X    /* write the header to the relation file */
X    lseek(rptr->rl_fd,0L,0);
X    if (write(rptr->rl_fd,&rptr->rl_header,512) != 512) {
X        close(rptr->rl_fd);
X        free(rptr);
X        return (db_ferror(BADHDR));
X    }
X
X   /* close the relation file */
X    close(rptr->rl_fd);
X
X    /* free the relation structure */
X    free(rptr);
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* db_rcattr(rptr,aname,type,size) - add an attribute to relation being created */
Xint db_rcattr(rptr,aname,type,size)
X  struct relation *rptr; char *aname; int type,size;
X{
X    int i;
X
X    /* look for attribute name */
X    for (i = 0; i < NATTRS; i++)
X        if (rptr->rl_header.hd_attrs[i].at_name[0] == 0)
X            break;
X        else if (db_sncmp(aname,rptr->rl_header.hd_attrs[i].at_name,ANSIZE) == 0)
X            return (db_ferror(DUPATT));
X
X    /* check for too many attributes */
X    if (i == NATTRS)
X        return (db_ferror(MAXATT));
X
X    /* store the new attribute */
X    strncpy(rptr->rl_header.hd_attrs[i].at_name,aname,ANSIZE);
X    rptr->rl_header.hd_attrs[i].at_type = type;
X    rptr->rl_header.hd_attrs[i].at_size = size;
X
X    /* terminate the attribute table */
X    if (++i != NATTRS)
X        rptr->rl_header.hd_attrs[i].at_name[0] = 0;
X
X    /* update the tuple size */
X    rptr->rl_size += size;
X
X    /* return successfully */
X    return (TRUE);
X}
X
SHAR_EOF
if test 3881 -ne "`wc -c 'cre.c'`"
then
	echo shar: error transmitting "'cre.c'" '(should have been 3881 characters)'
fi
echo shar: extracting "'err.c'" '(1630 characters)'
if test -f 'err.c'
then
	echo shar: over-writing existing file "'err.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'err.c'
X/* SDB - error messages */
X
X#include "sdbio.h"
X
Xchar *db_ertxt(msg)
X  int msg;
X{
X    char *txt;
X
X    /* select the appropriate message text */
X    switch (msg) {
X    case INSMEM:
X        txt = "insufficient memory";
X        break;
X    case RELFNF:
X        txt = "relation file not found";
X        break;
X    case BADHDR:
X        txt = "bad relation header";
X        break;
X    case TUPINP:
X        txt = "tuple input error";
X        break;
X    case TUPOUT:
X        txt = "tuple output error";
X        break;
X    case RELFUL:
X        txt = "relation file full";
X        break;
X    case RELCRE:
X        txt = "error creating relation file";
X        break;
X    case DUPATT:
X        txt = "duplicate attribute";
X        break;
X    case MAXATT:
X        txt = "too many attributes";
X        break;
X    case INSBLK:
X        txt = "insufficient disk space";
X        break;
X    case SYNTAX:
X        txt = "syntax error";
X        break;
X    case ATUNDF:
X        txt = "undefined attribute";
X        break;
X    case ATAMBG:
X        txt = "ambiguous attribute";
X        break;
X    case RLUNDF:
X        txt = "undefined relation";
X        break;
X    case CDSIZE:
X        txt = "boolean expression too complex";
X        break;
X    case INPFNF:
X        txt = "input file not found";
X        break;
X    case OUTCRE:
X        txt = "error creating output file";
X        break;
X    case INDFNF:
X        txt = "indirect command file not found";
X        break;
X    case BADSET:
X        txt = "bad set parameter";
X        break;
X    default:
X        txt = "undefined error";
X        break;
X    }
X
X    /* return the message text */
X    return (txt);
X}
X
SHAR_EOF
if test 1630 -ne "`wc -c 'err.c'`"
then
	echo shar: error transmitting "'err.c'" '(should have been 1630 characters)'
fi
echo shar: extracting "'iex.c'" '(6728 characters)'
if test -f 'iex.c'
then
	echo shar: over-writing existing file "'iex.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'iex.c'
X/* SDB - import/export command routines */
X
X#include "stdio.h"
X#include "sdbio.h"
X
Xextern int dbv_token;
Xextern char dbv_tstring[];
Xextern int dbv_tvalue;
X
X/* db_import - import tuples from a file */
Xint *db_import(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
X  char *fmt;
X{
X    struct scan *sptr;
X    struct attribute *aptr;
X    char fname[STRINGMAX+1],avalue[STRINGMAX+1];
X    int tcnt,astart,i,eofile;
X    FILE *fp;
X
X    /* check for a command line */
X    if (fmt != NULL)
X        db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);
X
X    /* checks for "<filename> into <relation-name>" */
X    if (db_ntoken() == ID)
X        strcat(dbv_tstring,".dat");
X    else if (dbv_token != STRING)
X        return (db_ferror(SYNTAX));
X    strcpy(fname,dbv_tstring);
X    if (db_ntoken() != INTO)
X        return (db_ferror(SYNTAX));
X    if (db_ntoken() != ID)
X        return (db_ferror(SYNTAX));
X
X    /* open the relation */
X    if ((sptr = db_ropen(dbv_tstring)) == NULL)
X        return (FALSE);
X
X    /* open the input file */
X    if ((fp = fopen(fname,"r")) == NULL)
X        return (db_ferror(INPFNF));
X
X    /* import tuples */
X    eofile = FALSE;
X    for (tcnt = 0; ; tcnt++) {
X
X        /* get attribute values */
X        astart = 1;
X        for (i = 0; i < NATTRS; i++) {
X
X            /* get a pointer to the current attribute */
X            aptr = &sptr->sc_relation->rl_header.hd_attrs[i];
X
X            /* check for the last attribute */
X            if (aptr->at_name[0] == 0)
X                break;
X
X            /* input the tuple */
X            if (fgets(avalue,STRINGMAX,fp) == 0) {
X                eofile = TRUE;
X                break;
X            }
X            avalue[strlen(avalue)-1] = EOS;
X
X            /* store the attribute value */
X            db_aput(aptr,&sptr->sc_tuple[astart],avalue);
X
X            /* update the attribute start */
X            astart += aptr->at_size;
X        }
X
X        /* store the new tuple */
X        if (!eofile) {
X            if (!db_rstore(sptr)) {
X                db_rclose(sptr);
X                return (FALSE);
X            }
X        }
X        else
X            break;
X    }
X
X    /* close the relation */
X    db_rclose(sptr);
X
X    /* close the input file */
X    fclose(fp);
X
X    /* check number of tuples imported */
X    if (tcnt != 0) {
X
X        /* print tuple count */
X        printf("[ %d imported ]\n",tcnt);
X    }
X    else
X        printf("[ none imported ]\n");
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* db_export - export tuples to a file */
Xint *db_export(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
X  char *fmt;
X{
X    struct scan *sptr;
X    struct attribute *aptr;
X    char rname[STRINGMAX+1],avalue[STRINGMAX+1];
X    int tcnt,astart,i;
X    FILE *fp;
X
X    /* check for a command line */
X    if (fmt != NULL)
X        db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);
X
X    /* checks for "<relation-name> [ into <filename> ]" */
X    if (db_ntoken() != ID)
X        return (db_ferror(SYNTAX));
X    strcpy(rname,dbv_tstring);
X    if (!db_to(&fp,".dat"))
X        return (FALSE);
X
X    /* open the relation */
X    if ((sptr = db_ropen(rname)) == NULL)
X        return (FALSE);
X
X    /* export tuples */
X    for (tcnt = 0; db_rfetch(sptr); tcnt++) {
X
X        /* get attribute values */
X        astart = 1;
X        for (i = 0; i < NATTRS; i++) {
X
X            /* get a pointer to the current attribute */
X            aptr = &sptr->sc_relation->rl_header.hd_attrs[i];
X
X            /* check for the last attribute */
X            if (aptr->at_name[0] == 0)
X                break;
X
X            /* get the attribute value */
X            db_aget(aptr,&sptr->sc_tuple[astart],avalue);
X
X            /* output the tuple */
X            fprintf(fp,"%s\n",avalue);
X
X            /* update the attribute start */
X            astart += aptr->at_size;
X        }
X    }
X
X    /* close the relation */
X    db_rclose(sptr);
X
X    /* close the output file */
X    if (fp != stdout)
X        fclose(fp);
X
X    /* check number of tuples exported */
X    if (tcnt != 0) {
X
X        /* print tuple count */
X        printf("[ %d exported ]\n",tcnt);
X    }
X    else
X        printf("[ none exported ]\n");
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* db_squeeze - squeeze deleted tuples from a relation file */
Xint *db_squeeze(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
X  char *fmt;
X{
X    struct scan *sptr;
X
X    /* check for a command line */
X    if (fmt != NULL)
X        db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);
X
X    /* checks for "<relation-name>" */
X    if (db_ntoken() != ID)
X        return (db_ferror(SYNTAX));
X
X    /* open the relation */
X    if ((sptr = db_ropen(dbv_tstring)) == NULL)
X        return (FALSE);
X
X    /* compress the relation file */
X    if (!db_rcompress(sptr)) {
X        db_rclose(sptr);
X        return (FALSE);
X    }
X
X    /* close the relation */
X    db_rclose(sptr);
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* db_extract - extract a relation definition */
Xint *db_extract(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
X  char *fmt;
X{
X    struct scan *sptr;
X    struct attribute *aptr;
X    char rname[STRINGMAX+1],aname[ANSIZE+1],*atype;
X    int i;
X    FILE *fp;
X
X    /* check for a command line */
X    if (fmt != NULL)
X        db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);
X
X    /* checks for "<relation-name> [ into <filename> ]" */
X    if (db_ntoken() != ID)
X        return (db_ferror(SYNTAX));
X    strcpy(rname,dbv_tstring);
X    if (!db_to(&fp,".def"))
X        return (FALSE);
X
X    /* open the relation */
X    if ((sptr = db_ropen(rname)) == NULL)
X        return (FALSE);
X
X    /* output the relation definition */
X    fprintf(fp,"create %s (\n",rname);
X
X    /* get attribute values */
X    for (i = 0; i < NATTRS; i++) {
X
X        /* get a pointer to the current attribute */
X        aptr = &sptr->sc_relation->rl_header.hd_attrs[i];
X
X        /* check for the last attribute */
X        if (aptr->at_name[0] == 0)
X            break;
X
X        /* get the attribute name */
X        strncpy(aname,aptr->at_name,ANSIZE); aname[ANSIZE] = 0;
X
X        /* determine the attribute type */
X        switch (aptr->at_type) {
X        case TCHAR:
X                atype = "char";
X                break;
X        case TNUM:
X                atype = "num";
X                break;
X        default:
X                atype = "<error>";
X                break;
X        }
X
X        /* output the attribute definition */
X        if (strlen(aname) < 8)
X            fprintf(fp,"\t%s\t\t%s\t%d\n",aname,atype,aptr->at_size);
X        else
X            fprintf(fp,"\t%s\t%s\t%d\n",aname,atype,aptr->at_size);
X    }
X
X    /* output the relation size */
X    fprintf(fp,") %d\n",sptr->sc_relation->rl_tmax);
X
X    /* close the relation */
X    db_rclose(sptr);
X
X    /* close the output file */
X    if (fp != stdout)
X        fclose(fp);
X
X    /* return successfully */
X    return (TRUE);
X}
X
SHAR_EOF
if test 6728 -ne "`wc -c 'iex.c'`"
then
	echo shar: error transmitting "'iex.c'" '(should have been 6728 characters)'
fi
#	End of shell archive
exit 0
-- 
Usenet: [decvax|allegra|linus|ihnp4]!utzoo!yetti!oz
Bitnet: oz@[yusol|yuyetti]
	You see things; and you say "WHY?"
	But I dream things that never were;
	and say "WHY NOT?"
			G. Bernard Shaw (Back to Methuselah)

oz@yetti.UUCP (Ozan Yigit) (09/02/85)

------------- SNIP --------- SNIP ------------ SNIP ------------
#!/bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #!/bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	int.c
#	io.c
#	mth.c
#	pcjunk.c
#	scn.c
# This archive created: Mon Sep  2 16:30:44 1985
export PATH; PATH=/bin:$PATH
echo shar: extracting "'int.c'" '(4388 characters)'
if test -f 'int.c'
then
	echo shar: over-writing existing file "'int.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'int.c'
X/* SDB - boolean expression evaluator */
X
X#include "sdbio.h"
X
Xstatic struct operand *stack[STACKMAX],**sptr;
Xstatic union codecell *cptr;
X
X/* db_interpret - interpret a boolean expression */
Xint db_interpret(slptr)
X  struct sel *slptr;
X{
X    struct operand *result;
X    int r;
X
X    /* check for empty where clause */
X    if ((cptr = slptr->sl_where) == NULL)
X        return (TRUE);
X
X    /* setup stack */
X    sptr = stack;
X
X    /* execute the code */
X    while ((*(*cptr++).c_operator)())
X        ;
X
X    /* get the result from the top of stack */
X    result = *--sptr;
X    r = result->o_value.ov_boolean;
X    if (result->o_type == TEMP)
X        free(result);
X
X    /* make sure the stack is empty */
X    while (sptr != stack) {
X        if ((*sptr)->o_type == TEMP)
X            free(*sptr);
X        sptr -= 1;
X    }
X
X    /* return result */
X    return (r);
X}
X
Xint db_xstop()
X{
X    return (FALSE);
X}
X
Xint db_xpush()
X{
X    *sptr++ = (*cptr++).c_operand;
X}
X
Xint db_xand()
X{
X    return (boolean('&'));
X}
X
Xint db_xor()
X{
X    return (boolean('|'));
X}
X
Xstatic int boolean(opr)
X{
X    struct operand *lval,*rval,*result;
X    int lv,rv,r;
X
X    rval = *--sptr; lval = *--sptr;
X    lv = lval->o_value.ov_boolean;
X    rv = rval->o_value.ov_boolean;
X
X    if ((result = malloc(sizeof(struct operand))) == NULL)
X        return (db_ferror(INSMEM));
X    result->o_type = TEMP;
X    switch (opr) {
X    case '&':   r = (lv && rv);
X                break;
X    case '|':   r = (lv || rv);
X                break;
X    }
X    result->o_value.ov_boolean = r;
X    *sptr++ = result;
X    if (lval->o_type == TEMP)
X        free(lval);
X    if (rval->o_type == TEMP)
X        free(rval);
X    return (TRUE);
X}
X
Xint db_xnot()
X{
X    struct operand *val,*result;
X
X    val = *--sptr;
X    if ((result = malloc(sizeof(struct operand))) == NULL)
X        return (db_ferror(INSMEM));
X    result->o_type = TEMP;
X    result->o_value.ov_boolean = !val->o_value.ov_boolean;
X    *sptr++ = result;
X    if (val->o_type == TEMP)
X        free(val);
X    return (TRUE);
X}
X
Xint db_xlss()
X{
X    return (compare(LSS));
X}
X
Xint db_xleq()
X{
X    return (compare(LEQ));
X}
X
Xint db_xeql()
X{
X    return (compare(EQL));
X}
X
Xint db_xgeq()
X{
X    return (compare(GEQ));
X}
X
Xint db_xgtr()
X{
X    return (compare(GTR));
X}
X
Xint db_xneq()
X{
X    return (compare(NEQ));
X}
X
Xstatic int compare(cmp)
X{
X    struct operand *lval,*rval,*result;
X    int i;
X
X    rval = *--sptr; lval = *--sptr;
X    if ((result = malloc(sizeof(struct operand))) == NULL)
X        return (db_ferror(INSMEM));
X    result->o_type = TEMP;
X
X    if (lval->o_value.ov_char.ovc_type == TCHAR)
X        i = comp(lval,rval);
X    else
X        i = ncomp(lval,rval);
X
X    switch (cmp) {
X    case LSS:   i = (i < 0);
X                break;
X    case LEQ:   i = (i <= 0);
X                break;
X    case EQL:   i = (i == 0);
X                break;
X    case GEQ:   i = (i >= 0);
X                break;
X    case GTR:   i = (i > 0);
X                break;
X    case NEQ:   i = (i != 0);
X                break;
X    }
X    result->o_value.ov_boolean = i;
X    *sptr++ = result;
X    if (lval->o_type == TEMP)
X        free(lval);
X    if (rval->o_type == TEMP)
X        free(rval);
X    return (TRUE);
X}
X
Xstatic int comp(lval,rval)
X  struct operand *lval,*rval;
X{
X    char *lptr,*rptr; int lctr,rctr;
X    int len;
X
X    lptr = lval->o_value.ov_char.ovc_string;
X    lctr = lval->o_value.ov_char.ovc_length;
X    rptr = rval->o_value.ov_char.ovc_string;
X    rctr = rval->o_value.ov_char.ovc_length;
X
X    while (lctr > 0 && (lptr[lctr-1] == 0 || lptr[lctr-1] == ' '))
X        lctr--;
X    while (rctr > 0 && (rptr[rctr-1] == 0 || rptr[rctr-1] == ' '))
X        rctr--;
X
X    if (lctr < rctr)
X        len = lctr;
X    else
X        len = rctr;
X
X    while ((len--) > 0) {
X        if (*lptr++ != *rptr++)
X            if (*--lptr < *--rptr)
X                return (-1);
X            else
X                return (1);
X    }
X
X    if (lctr == rctr)
X        return (0);
X    else if (lctr < rctr)
X        return (-1);
X    else
X        return (1);
X}
X
Xstatic int ncomp(lval,rval)
X  struct operand *lval,*rval;
X{
X    char lstr[NUMBERMAX+1],rstr[NUMBERMAX+1];
X    int len;
X
X    strncpy(lstr,lval->o_value.ov_char.ovc_string,
X          (len = lval->o_value.ov_char.ovc_length)); lstr[len] = EOS;
X    strncpy(rstr,rval->o_value.ov_char.ovc_string,
X          (len = rval->o_value.ov_char.ovc_length)); rstr[len] = EOS;
X
X    return (db_cmp(lstr,rstr));
X}
X
SHAR_EOF
if test 4388 -ne "`wc -c 'int.c'`"
then
	echo shar: error transmitting "'int.c'" '(should have been 4388 characters)'
fi
echo shar: extracting "'io.c'" '(10454 characters)'
if test -f 'io.c'
then
	echo shar: over-writing existing file "'io.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'io.c'
X/* SDB - relation file I/O routines */
X
X#include "stdio.h"
X#include "sdbio.h"
X
X/* global error code variable */
Xint dbv_errcode;
X
X/* list of currently loaded relation definitions */
Xstatic struct relation *relations = NULL;
X
X/* rfind - find the specified relation */
Xstatic struct relation *rfind(rname)
X  char *rname;
X{
X    int fd;
X    char filename[RNSIZE+5];
X    struct relation *rptr;
X
X    /* look for relation in list currently loaded */
X    for (rptr = relations; rptr != NULL; rptr = rptr->rl_next)
X        if (db_sncmp(rname,rptr->rl_name,RNSIZE) == 0)
X            return (rptr);
X
X    /* create a file name */
X    make_fname(filename,rname);
X
X    /* lookup the relation file */
X#ifdef Lattice
X    if ((fd = open(filename,0x8000)) == -1)  /*dns*/
X#else
X    if ((fd = open(filename,0)) == -1)
X#endif
X        return (db_nerror(RELFNF));
X
X    /* allocate a new relation structure */
X    if ((rptr = malloc(sizeof(struct relation))) == NULL) {
X        close(fd);
X        return (db_nerror(INSMEM));
X    }
X
X    /* initialize the relation structure */
X    rptr->rl_scnref = 0;
X
X    /* read the header block */
X    if ( read(fd,&rptr->rl_header,512) != 512) {
X        free(rptr);
X        close(fd);
X        return (db_nerror(BADHDR));
X    }
X
X    /* close the relation file */
X    close(fd);
X
X    /* extract header information */
X    rptr->rl_tcnt = db_cvword(rptr->rl_header.hd_tcnt);
X    rptr->rl_tmax = db_cvword(rptr->rl_header.hd_tmax);
X    rptr->rl_data = db_cvword(rptr->rl_header.hd_data);
X    rptr->rl_size = db_cvword(rptr->rl_header.hd_size);
X
X    /* store the relation name */
X    strncpy(rptr->rl_name,rname,RNSIZE);
X
X    /* link new relation into relation list */
X    rptr->rl_next = relations;
X    relations = rptr;
X
X    /* return the new relation structure pointer */
X    return (rptr);
X}
X
X/* db_ropen - open a relation file */
Xstruct scan *db_ropen(rname)
X  char *rname;
X{
X    struct relation *rptr;
X    struct scan *sptr;
X    char filename[RNSIZE+5];
X
X    /* find the relation definition */
X    if ((rptr = rfind(rname)) == NULL)
X        return (NULL);
X
X    /* allocate a new scan structure */
X    if ((sptr = malloc(sizeof(struct scan))) == NULL)
X        return (db_nerror(INSMEM));
X
X    /* allocate a tuple buffer */
X    if ((sptr->sc_tuple = malloc(rptr->rl_size)) == NULL) {
X        free(sptr);
X        return (db_nerror(INSMEM));
X    }
X
X    /* initialize the scan structure */
X    sptr->sc_relation = rptr;           /* store the relation struct addrs */
X    sptr->sc_dtnum = 0;                 /* desired tuple (non-existant) */
X    sptr->sc_atnum = 0;                 /* actual tuple (non-existant) */
X    sptr->sc_store = FALSE;             /* no store done since open */
X
X    /* open relation file if necessary */
X    if (rptr->rl_scnref++ == 0) {
X
X        /* create the relation file name */
X        make_fname(filename,rname);
X
X        /* open the relation file */
X#ifdef Lattice
X        if ((rptr->rl_fd = open(filename,0x8002)) == -1) {  /*dns*/
X#else
X        if ((rptr->rl_fd = open(filename,2)) == -1) {
X#endif
X            rptr->rl_scnref--;
X            free(sptr->sc_tuple); free(sptr);
X            return (db_nerror(RELFNF));
X        }
X    }
X
X    /* return the new scan structure pointer */
X    return (sptr);
X}
X
X/* db_rclose - close the relation file */
Xint db_rclose(sptr)
X  struct scan *sptr;
X{
X    struct relation *rptr,*lastrptr;
X
X    /* close relation file if this is the last reference */
X    if (--sptr->sc_relation->rl_scnref == 0) {
X
X        /* rewrite header if any stores took place */
X        if (sptr->sc_store) {
X
X            /* store the tuple count back in the header */
X            db_cvbytes(sptr->sc_relation->rl_tcnt,
X                       sptr->sc_relation->rl_header.hd_tcnt);
X
X            /* write the header block */
X            lseek(sptr->sc_relation->rl_fd,0L,0);
X            if (write(sptr->sc_relation->rl_fd,
X                      &sptr->sc_relation->rl_header,512) != 512) {
X                close(sptr->sc_relation->rl_fd);
X                free(sptr->sc_tuple); free(sptr);
X                return (db_ferror(BADHDR));
X            }
X        }
X
X        /* close the relation file */
X        close(sptr->sc_relation->rl_fd);
X
X        /* free the relation header */
X        lastrptr = NULL;
X        for (rptr = relations; rptr != NULL; rptr = rptr->rl_next) {
X            if (rptr == sptr->sc_relation) {
X                if (lastrptr == NULL)
X                    relations = rptr->rl_next;
X                else
X                    lastrptr->rl_next = rptr->rl_next;
X            }
X            lastrptr = rptr;
X        }
X        free(sptr->sc_relation);
X    }
X
X    /* free the scan structure */
X    free(sptr->sc_tuple); free(sptr);
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* db_rcompress - compress a relation file */
Xint db_rcompress(sptr)
X  struct scan *sptr;
X{
X    unsigned int next,nextfree,tcnt;
X
X    /* get the last used tuple */
X    tcnt = sptr->sc_relation->rl_tcnt;
X
X    /* loop through all of the tuples */
X    for (next = nextfree = 1; next <= tcnt; next++) {
X
X        /* read the tuple */
X        seek(sptr,next);
X        if (read(sptr->sc_relation->rl_fd,
X                 sptr->sc_tuple,sptr->sc_relation->rl_size)
X                        != sptr->sc_relation->rl_size)
X            return (db_ferror(TUPINP));
X
X        /* rewrite the tuple if it is active */
X        if (sptr->sc_tuple[0] == ACTIVE) {
X
X            /* rewrite it only if it must move */
X            if (next != nextfree) {
X
X                /* write the tuple */
X                seek(sptr,nextfree);
X                if (write(sptr->sc_relation->rl_fd,
X                          sptr->sc_tuple,sptr->sc_relation->rl_size)
X                                != sptr->sc_relation->rl_size)
X                    return (db_ferror(TUPOUT));
X            }
X
X            /* update the next free tuple number */
X            nextfree += 1;
X        }
X    }
X
X    /* update the tuple count */
X    sptr->sc_relation->rl_tcnt = nextfree - 1;
X
X    /* remember which tuple is in the buffer */
X    sptr->sc_atnum = sptr->sc_relation->rl_tcnt;
X
X    /* reset the desired tuple */
X    sptr->sc_dtnum = 0;
X
X    /* remember that the index needs rewriting */
X    sptr->sc_store = TRUE;
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* db_rbegin - begin scan at first tuple in relation */
Xdb_rbegin(sptr)
X  struct scan *sptr;
X{
X    /* begin with the first tuple in the file */
X    sptr->sc_dtnum = 0;
X}
X
X/* db_rfetch - fetch the next tuple from the relation file */
Xint db_rfetch(sptr)
X  struct scan *sptr;
X{
X    /* look for an active tuple */
X    while (TRUE) {
X
X        /* check for this being the last tuple */
X        if (!db_rget(sptr,sptr->sc_dtnum + 1))
X            return (FALSE);
X
X        /* increment the tuple number */
X        sptr->sc_dtnum += 1;
X
X        /* return if the tuple found is active */
X        if (sptr->sc_tuple[0] == ACTIVE)
X            return (TRUE);
X    }
X}
X
X/* db_rupdate - update the current tuple */
Xint db_rupdate(sptr)
X  struct scan *sptr;
X{
X    /* make sure the status byte indicates an active tuple */
X    sptr->sc_tuple[0] = ACTIVE;
X
X    /* write the tuple */
X    return (db_rput(sptr,sptr->sc_atnum));
X}
X
X/* db_rdelete - delete the current tuple */
Xint db_rdelete(sptr)
X  struct scan *sptr;
X{
X    /* make sure the status byte indicates a deleted tuple */
X    sptr->sc_tuple[0] = DELETED;
X
X    /* write the tuple */
X    return (db_rput(sptr,sptr->sc_atnum));
X}
X
X/* db_rstore - store a new tuple */
Xint db_rstore(sptr)
X  struct scan *sptr;
X{
X    /* make sure there's room for this tuple */
X    if (sptr->sc_relation->rl_tcnt == sptr->sc_relation->rl_tmax)
X        return (db_ferror(RELFUL));
X
X    /* make sure the status byte indicates an active tuple */
X    sptr->sc_tuple[0] = ACTIVE;
X
X    /* write the tuple */
X    if (!db_rput(sptr,sptr->sc_relation->rl_tcnt + 1))
X        return (FALSE);
X
X    /* update the tuple count */
X    sptr->sc_relation->rl_tcnt += 1;
X
X    /* remember that a tuple was stored */
X    sptr->sc_store = TRUE;
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* db_rget - get a tuple from the relation file */
Xint db_rget(sptr,tnum)
X  struct scan *sptr; unsigned int tnum;
X{
X    /* check to see if the tuple is already in the buffer */
X    if (tnum == sptr->sc_atnum)
X        return (TRUE);
X
X    /* check for this being beyond the last tuple */
X    if (tnum > sptr->sc_relation->rl_tcnt)
X        return (db_ferror(TUPINP));
X
X    /* read the tuple */
X    seek(sptr,tnum);
X    if (read(sptr->sc_relation->rl_fd,
X             sptr->sc_tuple,sptr->sc_relation->rl_size)
X                != sptr->sc_relation->rl_size)
X        return (db_ferror(TUPINP));
X
X    /* remember which tuple is in the buffer */
X    sptr->sc_atnum = tnum;
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* db_rput - put a tuple to a relation file */
Xint db_rput(sptr,tnum)
X  struct scan *sptr; unsigned int tnum;
X{
X    /* check for this being beyond the maximum tuple */
X    if (tnum > sptr->sc_relation->rl_tmax)
X        return (db_ferror(TUPOUT));
X
X    /* write the tuple */
X    seek(sptr,tnum);
X    if (write(sptr->sc_relation->rl_fd,
X              sptr->sc_tuple,sptr->sc_relation->rl_size)
X                != sptr->sc_relation->rl_size)
X        return (db_ferror(TUPOUT));
X
X    /* remember which tuple is in the buffer */
X    sptr->sc_atnum = tnum;
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* seek - seek a tuple in a relation file */
Xstatic seek(sptr,tnum)
X  struct scan *sptr; unsigned int tnum;
X{
X    long offset;
X
X    offset = (long) sptr->sc_relation->rl_data +
X                ((long) (tnum - 1) * (long) sptr->sc_relation->rl_size);
X    lseek(sptr->sc_relation->rl_fd,offset,0);
X}
X
X/* make_fname - make a relation name into a file name */
Xstatic make_fname(fname,rname)
X  char *fname,*rname;
X{
X    strncpy(fname,rname,RNSIZE); fname[RNSIZE] = 0;
X    strcat(fname,".sdb");
X}
X
X/* db_nerror - store the error code and return NULL */
Xint db_nerror(errcode)
X  int errcode;
X{
X    dbv_errcode = errcode;
X    return (NULL);
X}
X
X/* db_ferror - store the error code and return FALSE */
Xint db_ferror(errcode)
X  int errcode;
X{
X    dbv_errcode = errcode;
X    return (FALSE);
X}
X
X/* db_cvword - convert 2 bytes to a word */
Xint db_cvword(bytes)
X  char bytes[2];
X{
X    return (((bytes[1] & 0377) << 8) + (bytes[0] & 0377));
X}
X
X/* db_cvbytes - convert a word to 2 bytes */
Xdb_cvbytes(word,bytes)
X  int word; char bytes[2];
X{
X    bytes[0] = word;
X    bytes[1] = word >> 8;
X}
X
SHAR_EOF
if test 10454 -ne "`wc -c 'io.c'`"
then
	echo shar: error transmitting "'io.c'" '(should have been 10454 characters)'
fi
echo shar: extracting "'mth.c'" '(7647 characters)'
if test -f 'mth.c'
then
	echo shar: over-writing existing file "'mth.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'mth.c'
X/* SDB - string arithmetic routines */
X
X#include "ctype.h"  /*dns*/
X
X/* useful definitions */
X#define TRUE            1
X#define FALSE           0
X#define NUMBERMAX       99
X#define EOS             0
X
X/* db_cmp - compare two signed numeric strings */
Xint db_cmp(arg1,arg2)
X  char *arg1,*arg2;
X{
X    int sign1,sign2;
X
X    /* get the signs of the arguments */
X    sign1 = getsign(&arg1);
X    sign2 = getsign(&arg2);
X
X    /* compute the result */
X    if (sign1 == sign2) {
X        if (sign1 == 1)
X            return (compare(arg1,arg2));
X        else
X            return (compare(arg2,arg1));
X    }
X
X    /* signs are different */
X    return (sign1);
X}
X
X/* db_add - add two signed numeric strings */
Xdb_add(result,arg1,arg2)
X  char *result,*arg1,*arg2;
X{
X    int signr,sign1,sign2;
X    char rtmp[NUMBERMAX+2],*rptr;
X
X    /* get the signs of the arguments */
X    sign1 = getsign(&arg1);
X    sign2 = getsign(&arg2);
X
X    /* compute the result */
X    if (sign1 == sign2) {
X        signr = sign1;
X        add(rtmp,arg1,arg2);
X    }
X    else
X        switch (compare(arg1,arg2)) {
X        case -1:
X                signr = sign2;
X                sub(rtmp,arg2,arg1);
X                break;
X        case 0:
X                strcpy(result,"0");
X                return;
X        case 1:
X                signr = sign1;
X                sub(rtmp,arg1,arg2);
X                break;
X        }
X
X    /* insert the sign */
X    if (signr == -1)
X        strcpy(result,"-");
X    else
X        result[0] = EOS;
X
X    /* eliminate possible leading zeros */
X    for (rptr = rtmp; *rptr == '0'; rptr++)
X        ;
X
X    /* copy the result */
X    if (*rptr != EOS)
X        strcat(result,rptr);
X    else
X        strcat(result,"0");
X}
X
X/* db_sub - subtract two signed numeric strings */
Xdb_sub(result,arg1,arg2)
X  char *result,*arg1,*arg2;
X{
X    int signr,sign1,sign2;
X    char rtmp[NUMBERMAX+2],*rptr;
X
X    /* get the signs of the arguments */
X    sign1 = getsign(&arg1);
X    sign2 = getsign(&arg2);
X
X    /* invert the sign of arg2 */
X    sign2 = -sign2;
X
X    /* compute the result */
X    if (sign1 == sign2) {
X        signr = sign1;
X        add(rtmp,arg1,arg2);
X    }
X    else
X        switch (compare(arg1,arg2)) {
X        case -1:
X                signr = sign2;
X                sub(rtmp,arg2,arg1);
X                break;
X        case 0:
X                strcpy(result,"0");
X                return;
X        case 1:
X                signr = sign1;
X                sub(rtmp,arg1,arg2);
X                break;
X        }
X
X    /* insert the sign */
X    if (signr == -1)
X        strcpy(result,"-");
X    else
X        result[0] = EOS;
X
X    /* eliminate a possible leading zero */
X    for (rptr = rtmp; *rptr == '0'; rptr++)
X        ;
X
X    /* copy the result */
X    if (*rptr != EOS)
X        strcat(result,rptr);
X    else
X        strcat(result,"0");
X}
X
X/* add - add two unsigned numeric strings */
Xstatic add(result,arg1,arg2)
X  char *result,*arg1,arg2;
X{
X    char *vr,*v1,*v2,*vx;
X    int carry,i,nmin,nmax,nd1,nd2;
X
X
X    /* get number of digits in each argument */
X    nd1 = getlen(arg1);
X    nd2 = getlen(arg2);
X
X    /* compute the address of the last digit + 1 */
X    v1 = arg1 + nd1;
X    v2 = arg2 + nd2;
X
X    /* compute minimum and maximum of nd1 and nd2 */
X    if (nd1 < nd2) {
X        nmin = -nd1;
X        nmax = -nd2;
X        vx = v2;
X    }
X    else {
X        nmin = -nd2;
X        nmax = -nd1;
X        vx = v1;
X    }
X
X    /* compute the address of the last result digit + 1 */
X    vr = result - nmax; vr[0] = EOS;
X
X    /* initialize the carry */
X    carry = 0;
X
X    /* add the digits */
X    for (i = -1; i >= nmin; i--) {
X
X        /* check for decimal point */
X        if (v1[i] == '.')
X            vr[i] = '.';
X        else {
X
X            /* add the current pair of digits with the carry */
X            vr[i] = v1[i] + v2[i] + carry - '0';
X
X            /* check for carry */
X            if (vr[i] > '9') {
X                vr[i] -= 10;
X                carry = 1;
X            }
X            else
X                carry = 0;
X        }
X    }
X
X    /* add the remaining digits */
X    for (; i >= nmax; i--) {
X
X        /* add the current digit with the carry */
X        vr[i] = vx[i] + carry;
X
X        /* check for carry */
X        if (vr[i] > '9') {
X            vr[i] -= 10;
X            carry = 1;
X        }
X        else
X            carry = 0;
X    }
X
X    /* check for a carry out and shift digits if necessary */
X    if (carry == 1) {
X
X        /* shift the digits */
X        for (i = -nmax; i >= 0; i--)
X            result[i+1] = result[i];
X        result[0] = '1';
X    }
X}
X
X/* sub - subtract two unsigned numeric strings */
Xstatic sub(result,arg1,arg2)
X  char *result,*arg1,arg2;
X{
X    char *vr,*v1,*v2,*vx;
X    int borrow,i,nmin,nmax,nd1,nd2;
X
X    /* get number of digits in each argument */
X    nd1 = getlen(arg1);
X    nd2 = getlen(arg2);
X
X    /* compute the address of the last digit + 1 */
X    v1 = arg1 + nd1;
X    v2 = arg2 + nd2;
X
X    /* compute minimum and maximum of nd1 and nd2 */
X    if (nd1 < nd2) {
X        nmin = -nd1;
X        nmax = -nd2;
X        vx = v2;
X    }
X    else {
X        nmin = -nd2;
X        nmax = -nd1;
X        vx = v1;
X    }
X
X    /* compute the address of the last result digit + 1 */
X    vr = result - nmax; vr[0] = EOS;
X
X    /* initialize the borrow */
X    borrow = 0;
X
X    /* subtract the digits */
X    for (i = -1; i >= nmin; i--) {
X
X        /* check for decimal point */
X        if (v1[i] == '.')
X            vr[i] = '.';
X        else {
X
X            /* subtract the current pair of digits with the borrow */
X            vr[i] = v1[i] - v2[i] - borrow + '0';
X
X            /* check for borrow */
X            if (vr[i] < '0') {
X                vr[i] += 10;
X                borrow = 1;
X            }
X            else
X                borrow = 0;
X        }
X    }
X
X    /* subtract the remaining digits */
X    for (; i >= nmax; i--) {
X
X        /* subtract the current digit with the borrow */
X        vr[i] = vx[i] - borrow;
X
X        /* check for borrow */
X        if (vr[i] < '0') {
X            vr[i] += 10;
X            borrow = 1;
X        }
X        else
X            borrow = 0;
X    }
X}
X
X/* getsign - get the sign of a numeric string */
Xstatic int getsign(parg)
X  char **parg;
X{
X    int sign;
X    char *p;
X
X    /* eliminate leading spaces */
X    while (isspace(**parg))
X        *parg += 1;
X
X    /* get the sign */
X    switch (**parg) {
X    case '+':   *parg += 1;
X                sign = 1;
X                break;
X    case '-':   *parg += 1;
X                sign = -1;
X                break;
X    default:    sign = 1;
X                break;
X    }
X
X    /* eliminate leading spaces and zeros */
X    while (isspace(**parg) || **parg == '0')
X        *parg += 1;
X
X    /* if the value is zero, make sure that the sign is positive */
X    switch (**parg) {
X    case EOS:   sign = 1;
X                break;
X    case '.':   for (p = *parg + 1; *p == '0'; p++)
X                    ;
X                if (*p == EOS)
X                    sign = 1;
X                break;
X    }
X
X    /* return the sign */
X    return (sign);
X}
X
X/* getlen - get the length of a numeric string */
Xstatic int getlen(arg)
X  char *arg;
X{
X    int len;
X
X    /* get the length of the string */
X    len = strlen(arg);
X
X    /* eliminate trailing spaces */
X    while (isspace(arg[len-1]))
X        len -= 1;
X
X    /* return the length */
X    return (len);
X}
X
X/* compare - compare two unsigned numeric strings */
Xstatic int compare(arg1,arg2)
X  char *arg1,*arg2;
X{
X    int len1,len2;
X
X    /* compare lengths */
X    if ((len1 = getlen(arg1)) != (len2 = getlen(arg2)))
X        if (len1 < len2)
X            return (-1);
X        else
X            return (1);
X
X    /* compare strings */
X    return (strcmp(arg1,arg2));
X}
X
SHAR_EOF
if test 7647 -ne "`wc -c 'mth.c'`"
then
	echo shar: error transmitting "'mth.c'" '(should have been 7647 characters)'
fi
echo shar: extracting "'pcjunk.c'" '(1360 characters)'
if test -f 'pcjunk.c'
then
	echo shar: over-writing existing file "'pcjunk.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'pcjunk.c'
X/*  PCJUNK.C     Misc. procedures */
X
X#include "stdio.h"
X#include "sdbio.h"
X
X/*    Replaces JUNK.C for the IBM/PC version            dns */
X
X
Xchar *alloc(n)
Xint n;
X{
X   return (char*) malloc(n);
X}
X
X
Xint getcx(fp)
X  FILE *fp;
X{
X    static char buf[LINEMAX] = {0};
X    static char *pbuf = buf;
X    int ch, i;
X
X    if (fp!=stdin)
X       if ((ch = getc(fp)) == '\r')
X          return getc(fp);
X       else
X          return ch;
X
X    if (*pbuf > 0)
X       return *pbuf++;
X
X    pbuf = buf;
X    for (i = 0; (ch = getc(fp)) != -1; )
X        if (i < LINEMAX)  {
X            if (ch == ESC)     { i=0;  putchar('\n'); fflush(stdout); }  else
X            if (ch == BS)      { if (i>0)  i--;                       }  else
X               buf[i++] = ch;
X            if (ch == '\n')    break;
X            }
X        else {
X            printf("*** line too long ***\nRetype> ");
X            i = 0;
X        }
X    buf[i] = EOS;
X    return getcx(fp);
X}
X
X
X
X/*    string copy up to n characters    */
Xstrncpy(to, from, n)
Xchar *to, *from;
Xint n;
X{
X  char *cp;
X
X  for( cp=to; n-- && (*cp++ = *from++);  ) ;
X  if( n<0 )   *cp = 0;
X  return to;
X}
X
X
X/*    string compare up to n characters     */
Xstrncmp(s1, s2, n)
Xchar *s1, *s2;
Xint n;
X{
X
X  for( ;n-- && (*s1==*s2); s2++ )
X     if( !*s1++ )
X        return 0;
X  if( n < 0 )
X     return 0;
X  if( *s1 < *s2 )
X     return -1;
X  return 1;
X}
SHAR_EOF
if test 1360 -ne "`wc -c 'pcjunk.c'`"
then
	echo shar: error transmitting "'pcjunk.c'" '(should have been 1360 characters)'
fi
echo shar: extracting "'scn.c'" '(14358 characters)'
if test -f 'scn.c'
then
	echo shar: over-writing existing file "'scn.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'scn.c'
X/* SDB - token scanning routines */
X
X#include "stdio.h"
X#include "sdbio.h"
X
Xint dbv_token;                          /* current token */
Xint dbv_tvalue;                         /* integer token value */
Xchar dbv_tstring[STRINGMAX+1];          /* string token value */
Xstruct ifile *dbv_ifp;                  /* indirect file context */
Xstruct macro *dbv_macros;               /* macro definitions */
Xint dbv_fold;                           /* case fold alpha comparisons */
X
Xstatic char *iprompt,*cprompt;          /* input prompts */
Xstatic char cmdline[LINEMAX+2],*lptr;   /* current line and pointer */
Xstatic int atbol;                       /* flag indicating at bol */
Xstatic int savech;                      /* lookahead character */
Xstatic int savetkn;                     /* lookahead token */
Xstatic char *keywords[] = {             /* keyword table */
X    "ascending",
X    "by",
X    "char",
X    "compress",
X    "create",
X    "define",
X    "delete",
X    "descending",
X    "exit",
X    "export",
X    "extract",
X    "from",
X    "help",
X    "insert",
X    "import",
X    "into",
X    "num",
X    "print",
X    "select",
X    "set",
X    "show",
X    "sort",
X    "update",
X    "using",
X    "where",
X    NULL
X};
Xstatic int keytokens[] = {              /* token values for each keyword */
X    ASCENDING,
X    BY,
X    CHAR,
X    COMPRESS,
X    CREATE,
X    DEFINE,
X    DELETE,
X    DESCENDING,
X    EXIT,
X    EXPORT,
X    EXTRACT,
X    FROM,
X    HELP,
X    INSERT,
X    IMPORT,
X    INTO,
X    NUM,
X    PRINT,
X    SELECT,
X    SET,
X    SHOW,
X    SORT,
X    UPDATE,
X    USING,
X    WHERE,
X    NULL
X};
X
X/* db_sinit - initialize the scanner */
Xdb_sinit()
X{
X    /* at beginning of line */
X    atbol = TRUE;
X
X    /* make the command line null */
X    lptr = NULL;
X
X    /* no lookahead yet */
X    savech = EOS;
X    savetkn = NULL;
X
X    /* no indirect command files */
X    dbv_ifp = NULL;
X
X    /* no macros defined */
X    dbv_macros = NULL;
X
X    /* fold alpha comparisons */
X    dbv_fold = TRUE;
X}
X
X/* db_prompt(ip,cp) - initialize prompt strings */
Xdb_prompt(ip,cp)
X  char *ip,*cp;
X{
X    /* save initial and continuation prompt strings */
X    iprompt = ip;
X    cprompt = cp;
X}
X
X/* db_scan(fmt,args) - initiate line scan command parsing */
Xdb_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
X{
X    /* convert the command line and arguments */
X    sprintf(cmdline,fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10);
X
X    /* start at the beginning of the command line */
X    lptr = cmdline;
X    iprompt = NULL;
X    dbv_ifp = NULL;
X
X    /* no lookahead yet */
X    savech = EOS;
X    savetkn = NULL;
X
X    /* fold alpha comparisons */
X    dbv_fold = TRUE;
X}
X
X/* db_flush - flush the current input line */
Xint db_flush()
X{
X    while (savech != '\n')
X        if (savech > ' ')
X            return (db_ferror(SYNTAX));
X        else
X            savech = getchx();
X
X    savech = EOS;
X    atbol = TRUE;
X    return (TRUE);
X}
X
X/* db_gline - get a line from the current input */
Xchar *db_gline(buf)
X  char *buf;
X{
X    int ch,i;
X
X    for (i = 0; (ch = getch()) != '\n' && ch != -1; )
X        if (i < LINEMAX)
X            buf[i++] = ch;
X        else {
X            printf("*** line too long ***\nRetype> ");
X            i = 0;
X        }
X    buf[i] = EOS;
X
X    return (buf);
X}
X
X/* db_ifile - setup an indirect command file */
Xint db_ifile(fname)
X  char *fname;
X{
X    struct ifile *new_ifp;
X
X    if ((new_ifp = malloc(sizeof(struct ifile))) == NULL)
X        return (db_ferror(INSMEM));
X    else if ((new_ifp->if_fp = fopen(fname,"r")) == NULL) {
X        free(new_ifp);
X        return (db_ferror(INDFNF));
X    }
X    new_ifp->if_mtext = NULL;
X    new_ifp->if_savech = savech;
X    new_ifp->if_lptr = lptr;
X    new_ifp->if_next = dbv_ifp;
X    dbv_ifp = new_ifp;
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* db_kill - kill indirect command file input */
Xdb_kill()
X{
X    struct ifile *old_ifp;
X
X    while ((old_ifp = dbv_ifp) != NULL) {
X        dbv_ifp = old_ifp->if_next;
X        if (old_ifp->if_fp != NULL)
X            fclose(old_ifp->if_fp);
X        savech = old_ifp->if_savech;
X        lptr = old_ifp->if_lptr;
X        free(old_ifp);
X    }
X
X    while (savech != '\n')
X        savech = getchx();
X
X    savech = EOS;
X    savetkn = NULL;
X    atbol = TRUE;
X}
X
X/* db_token - return the current input token */
Xint db_token()
X{
X    struct macro *mptr;
X    struct ifile *new_ifp;
X
X    /* find a token that's not a macro call */
X    while (db_xtoken() == ID) {
X
X        /* check for a macro call */
X        for (mptr = dbv_macros; mptr != NULL; mptr = mptr->mc_next)
X            if (db_scmp(dbv_tstring,mptr->mc_name) == 0) {
X                if ((new_ifp = malloc(sizeof(struct ifile))) == NULL)
X                    printf("*** error expanding macro: %s ***\n",dbv_tstring);
X                else {
X                    new_ifp->if_fp = NULL;
X                    new_ifp->if_mtext = mptr->mc_mtext->mt_next;
X                    new_ifp->if_lptr = lptr; lptr = mptr->mc_mtext->mt_text;
X                    new_ifp->if_savech = savech; savech = EOS;
X                    new_ifp->if_next = dbv_ifp;
X                    dbv_ifp = new_ifp;
X                }
X                savetkn = NULL;
X                break;
X            }
X
X        if (mptr == NULL)
X            break;
X    }
X
X    return (dbv_token);
X}
X
X/* db_xtoken - return the current input token */
Xint db_xtoken()
X{
X    int ch;
X
X    /* check for a saved token */
X    if ((dbv_token = savetkn) != NULL)
X        return (dbv_token);
X
X    /* get the next non-blank character */
X    ch = nextch();
X
X    /* check type of character */
X    if (isalpha(ch))                    /* identifier or keyword */
X        get_id();
X    else if (isdigit(ch))               /* number */
X        get_number();
X    else if (ch == '"')                 /* string */
X        get_string();
X    else if (get_rel())                 /* relational operator */
X        ;
X    else                                /* single character token */
X        dbv_token = getch();
X
X    /* save the lookahead token */
X    savetkn = dbv_token;
X
X    /* return the token */
X    return (dbv_token);
X}
X
X/* db_ntoken - get next token (after skipping the current one) */
Xint db_ntoken()
X{
X    /* get the current token */
X    db_token();
X
X    /* make sure another is read on next call */
X    savetkn = NULL;
X
X    /* return the current token */
X    return (dbv_token);
X}
X
X/* db_xntoken - get next token (after skipping the current one) */
Xint db_xntoken()
X{
X    /* get the current token */
X    db_xtoken();
X
X    /* make sure another is read on next call */
X    savetkn = NULL;
X
X    /* return the current token */
X    return (dbv_token);
X}
X
X/* db_scmp - compare two strings */
Xint db_scmp(str1,str2)
X  char *str1,*str2;
X{
X    if (dbv_fold)
X        return (scmp(str1,str2));
X    else
X        return (strcmp(str1,str2));
X}
X
X/* db_sncmp - compare two strings with a maximum length */
Xint db_sncmp(str1,str2,len)
X  char *str1,*str2; int len;
X{
X    if (dbv_fold)
X        return (sncmp(str1,str2,len));
X    else
X        return (strncmp(str1,str2,len));
X}
X
X/* scmp - compare two strings with alpha case folding */
Xstatic int scmp(str1,str2)
X  char *str1,*str2;
X{
X    int ch1,ch2;
X
X    /* compare each character */
X    while (*str1 && *str2) {
X
X        /* fold the character from the first string */
X        if (isupper(*str1))
X            ch1 = tolower(*str1++);
X        else
X            ch1 = *str1++;
X
X        /* fold the character from the second string */
X        if (isupper(*str2))
X            ch2 = tolower(*str2++);
X        else
X            ch2 = *str2++;
X
X        /* compare the characters */
X        if (ch1 != ch2)
X            if (ch1 < ch2)
X                return (-1);
X            else
X                return (1);
X    }
X
X    /* check for strings of different lengths */
X    if (*str1 == *str2)
X        return (0);
X    else if (*str1 == 0)
X        return (-1);
X    else
X        return (1);
X}
X
X/* sncmp - compare two strings with alpha case folding and a maximum length */
Xstatic int sncmp(str1,str2,len)
X  char *str1,*str2; int len;
X{
X    int ch1,ch2;
X
X    /* compare each character */
X    while (*str1 && *str2 && len > 0) {
X
X        /* fold the character from the first string */
X        if (isupper(*str1))
X            ch1 = tolower(*str1++);
X        else
X            ch1 = *str1++;
X
X        /* fold the character from the second string */
X        if (isupper(*str2))
X            ch2 = tolower(*str2++);
X        else
X            ch2 = *str2++;
X
X        /* compare the characters */
X        if (ch1 != ch2)
X            if (ch1 < ch2)
X                return (-1);
X            else
X                return (1);
X
X        /* decrement the string length */
X        len--;
X    }
X
X    /* check for strings of different lengths */
X    if (len == 0 || *str1 == *str2)
X        return (0);
X    else if (*str1 == 0)
X        return (-1);
X    else
X        return (1);
X}
X
X/* get_id - get a keyword or a user identifier */
Xstatic get_id()
X{
X    int ch,nchars,i;
X
X    /* input letters and digits */
X    ch = nextch();
X    nchars = 0;
X    while (isalpha(ch) || isdigit(ch)) {
X        if (nchars < KEYWORDMAX)
X            dbv_tstring[nchars++] = ch;
X        getch(); ch = thisch();
X    }
X
X    /* terminate the keyword */
X    dbv_tstring[nchars] = EOS;
X
X    /* assume its an identifier */
X    dbv_token = ID;
X
X    /* check for keywords */
X    for (i = 0; keywords[i] != NULL; i++)
X        if (db_scmp(dbv_tstring,keywords[i]) == 0)
X            dbv_token = keytokens[i];
X}
X
X/* get_number - get a number */
Xstatic get_number()
X{
X    int ch,ndigits,nodot;
X
X    /* read digits and at most one decimal point */
X    ch = nextch();
X    ndigits = 0; nodot = TRUE;
X    while (isdigit(ch) || (nodot && ch == '.')) {
X        if (ch == '.')
X            nodot = FALSE;
X        if (ndigits < NUMBERMAX)
X            dbv_tstring[ndigits++] = ch;
X        getch(); ch = thisch();
X    }
X
X    /* terminate the number */
X    dbv_tstring[ndigits] = EOS;
X
X    /* get the value of the number */
X    sscanf(dbv_tstring,"%d",&dbv_tvalue);
X
X    /* token is a number */
X    dbv_token = NUMBER;
X}
X
X/* get_string - get a string */
Xstatic get_string()
X{
X    int ch,nchars;
X
X    /* skip the opening quote */
X    getch();
X
X    /* read characters until a closing quote is found */
X    ch = thisch();
X    nchars = 0;
X    while (ch && ch != '"') {
X        if (nchars < STRINGMAX)
X            dbv_tstring[nchars++] = ch;
X        getch(); ch = thisch();
X    }
X
X    /* terminate the string */
X    dbv_tstring[nchars] = EOS;
X
X    /* skip the closing quote */
X    getch();
X
X    /* token is a string */
X    dbv_token = STRING;
X}
X
X/* get_rel - get a relational operator */
Xstatic int get_rel()
X{
X    int ch;
X
X    switch (ch = nextch()) {
X    case '=':
X            getch();
X            dbv_token = EQL;
X            return (TRUE);;
X    case '<':
X            getch(); ch = nextch();
X            if (ch == '>') {
X                getch();
X                dbv_token = NEQ;
X            }
X            else if (ch == '=') {
X                getch();
X                dbv_token = LEQ;
X            }
X            else
X                dbv_token = LSS;
X            return (TRUE);;
X    case '>':
X            getch(); ch = nextch();
X            if (ch == '=') {
X                getch();
X                dbv_token = GEQ;
X            }
X            else
X                dbv_token = GTR;
X            return (TRUE);;
X    default:
X            return (FALSE);
X    }
X}
X
X/* getch - get the next character */
Xstatic int getch()
X{
X    char fname[STRINGMAX+1];
X    int ch,i;
X
X    /* return the lookahead character if there is one */
X    if (savech != EOS) {
X        ch = savech;
X        savech = EOS;
X        return (ch);
X    }
X
X    /* get a character */
X    ch = getchx();
X
X    /* skip spaces at the beginning of a command */
X    if (atbol && iprompt != NULL)
X        while (ch <= ' ')
X            ch = getchx();
X
X    /* use continuation prompt next time */
X    iprompt = NULL;
X
X    /* check for indirect command file */
X    while (ch == '@') {
X        for (i = 0; (savech = getchx()) > ' '; )
X            if (i < STRINGMAX)
X                fname[i++] = savech;
X        fname[i] = 0;
X        if (db_ifile(fname) != TRUE)
X            printf("*** error opening command file: %s ***\n",fname);
X        ch = getchx();
X    }
X
X    /* return the character */
X    return (ch);
X}
X
X/* getchx - get the next character */
Xstatic int getchx()
X{
X    struct ifile *old_ifp;
X    int ch;
X
X    /* check for input from buffer */
X    if (lptr != NULL) {
X        while (*lptr == EOS)
X            if (dbv_ifp != NULL)
X                if (dbv_ifp->if_mtext == NULL) {
X                    old_ifp = dbv_ifp;
X                    ch = dbv_ifp->if_savech; savech = EOS;
X                    lptr = dbv_ifp->if_lptr;
X                    dbv_ifp = dbv_ifp->if_next;
X                    free(old_ifp);
X                    if (ch != EOS)
X                        return (ch);
X                    if (lptr == NULL)
X                        break;
X                }
X                else {
X                    lptr = dbv_ifp->if_mtext->mt_text;
X                    dbv_ifp->if_mtext = dbv_ifp->if_mtext->mt_next;
X                }
X            else
X                return (EOS);
X
X        if (lptr != NULL)
X            return (*lptr++);
X    }
X
X    /* print prompt if necessary */
X    if (atbol && dbv_ifp == NULL)  {  /*dns*/
X        if (iprompt != NULL)
X            printf("%s",iprompt);
X        else if (cprompt != NULL)
X            printf("%s",cprompt);
X#ifdef Lattice
X        fflush(stdout); /*dns*/
X#endif
X        } /*dns*/
X
X    if (dbv_ifp == NULL)
X        if ((ch = getcx(stdin)) == '\n')
X            atbol = TRUE;
X        else
X            atbol = FALSE;
X    else {
X        if ((ch = getcx(dbv_ifp->if_fp)) == -1) {
X            old_ifp = dbv_ifp;
X            ch = dbv_ifp->if_savech; savech = EOS;
X            lptr = dbv_ifp->if_lptr;
X            dbv_ifp = dbv_ifp->if_next;
X            fclose(old_ifp->if_fp);
X            free(old_ifp);
X        }
X    }
X
X    /* return the character */
X    return (ch);
X}
X
X/* thisch - get the current character */
Xstatic int thisch()
X{
X    /* get a lookahead character */
X    if (savech == EOS)
X        savech = getch();
X
X    /* return lookahead character */
X    return (savech);
X}
X
X/* nextch - get the next non-blank character */
Xstatic int nextch()
X{
X    int ch;
X
X    /* skip blank characters */
X    while ((ch = thisch()) <= ' ' && ch != EOS)
X        getch();
X
X    /* return the first non-blank */
X    return (ch);
X}
X
SHAR_EOF
if test 14358 -ne "`wc -c 'scn.c'`"
then
	echo shar: error transmitting "'scn.c'" '(should have been 14358 characters)'
fi
#	End of shell archive
exit 0
-- 
Usenet: [decvax|allegra|linus|ihnp4]!utzoo!yetti!oz
Bitnet: oz@[yusol|yuyetti]
	You see things; and you say "WHY?"
	But I dream things that never were;
	and say "WHY NOT?"
			G. Bernard Shaw (Back to Methuselah)

oz@yetti.UUCP (Ozan Yigit) (09/02/85)

---------------- SNIP ----------- SNIP -------------- SNIP --------
#!/bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #!/bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	sdb.c
#	sel.c
#	srt.c
#	tbl.c
#	sdbio.h
# This archive created: Mon Sep  2 16:31:17 1985
export PATH; PATH=/bin:$PATH
echo shar: extracting "'sdb.c'" '(367 characters)'
if test -f 'sdb.c'
then
	echo shar: over-writing existing file "'sdb.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'sdb.c'
X/* SDB - main routine */
X
X#include "stdio.h"
X#include "sdbio.h"
X
Xextern int dbv_errcode;
X
Xmain()
X{
X    printf("SDB - version 2.0\n");
X    db_sinit();
X    db_ifile("sdb.ini");
X
X    while (TRUE) {
X        db_prompt("SDB> ","\t> ");
X        if (!db_parse(NULL)) {
X            printf("** error: %s ***\n",db_ertxt(dbv_errcode));
X            db_kill();
X        }
X    }
X}
X
SHAR_EOF
if test 367 -ne "`wc -c 'sdb.c'`"
then
	echo shar: error transmitting "'sdb.c'" '(should have been 367 characters)'
fi
echo shar: extracting "'sel.c'" '(20482 characters)'
if test -f 'sel.c'
then
	echo shar: over-writing existing file "'sel.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'sel.c'
X/* SDB - select data from the database */
X
X#include "sdbio.h"
X
Xextern int dbv_token;
Xextern char dbv_tstring[];
Xextern int dbv_tvalue;
X
X/* db_select - select a set of tuples from a set of relations */
Xstruct sel *db_select(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
X  char *fmt;
X{
X    struct sel *slptr;
X
X    /* check for a command line */
X    if (fmt != NULL)
X        db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);
X
X    /* allocate a sel structure */
X    if ((slptr = malloc(sizeof(struct sel))) == NULL)
X        return (db_nerror(INSMEM));
X
X    /* initialize the structure */
X    slptr->sl_rels = NULL;
X    slptr->sl_attrs = NULL;
X    slptr->sl_where = NULL;
X    slptr->sl_bindings = NULL;
X
X    /* parse the list of selected attributes */
X    if (!get_sattrs(slptr)) {
X        db_done(slptr);
X        return (NULL);
X    }
X
X    /* check for "from" clause */
X    if (db_token() == FROM) {
X        db_ntoken();
X        if (!get_srels(slptr)) {
X            db_done(slptr);
X            return (NULL);
X        }
X    }
X    else {
X        if (!srelation(slptr,"sdbcur",NULL)) {
X            db_done(slptr);
X            return (NULL);
X        }
X    }
X
X    /* check the list of selected attributes */
X    if (!check_attrs(slptr)) {
X        db_done(slptr);
X        return (NULL);
X    }
X
X    /* check for the existance of a "where" clause */
X    if (db_token() == WHERE) {
X        db_ntoken();
X
X        /* parse the boolean expression */
X        if (!db_compile(slptr)) {
X            db_done(slptr);
X            return (FALSE);
X        }
X    }
X
X    /* return the new selection structure */
X    return (slptr);
X}
X
X/* db_retrieve - retrieve a set of tuples from a set of relations */
Xstruct sel *db_retrieve(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
X  char *fmt;
X{
X    struct sel *slptr;
X
X    /* check for a command line */
X    if (fmt != NULL)
X        db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);
X
X    /* allocate a sel structure */
X    if ((slptr = malloc(sizeof(struct sel))) == NULL)
X        return (db_nerror(INSMEM));
X
X    /* initialize the structure */
X    slptr->sl_rels = NULL;
X    slptr->sl_attrs = NULL;
X    slptr->sl_where = NULL;
X    slptr->sl_bindings = NULL;
X
X    /* check for selected relations clause */
X    if (db_token() == ID) {
X        if (!get_srels(slptr)) {
X            db_done(slptr);
X            return (NULL);
X        }
X    }
X    else {
X        if (!srelation(slptr,"sdbcur",NULL)) {
X            db_done(slptr);
X            return (NULL);
X        }
X    }
X
X    /* check the list of selected attributes */
X    if (!check_attrs(slptr)) {
X        db_done(slptr);
X        return (NULL);
X    }
X
X    /* check for the existance of a "where" clause */
X    if (db_token() == WHERE) {
X        db_ntoken();
X
X        /* parse the boolean expression */
X        if (!db_compile(slptr)) {
X            db_done(slptr);
X            return (FALSE);
X        }
X    }
X
X    /* return the new selection structure */
X    return (slptr);
X}
X
X/* db_done(slptr) - finish a selection */
Xdb_done(slptr)
X  struct sel *slptr;
X{
X    struct sattr *saptr,*nxtsa;
X    struct srel *srptr,*nxtsr;
X    struct binding *bdptr,*nxtbd;
X
X    /* free the selected attribute blocks */
X    for (saptr = slptr->sl_attrs; saptr != NULL; saptr = nxtsa) {
X        nxtsa = saptr->sa_next;
X        if (saptr->sa_rname != NULL)
X            free(saptr->sa_rname);
X        free(saptr->sa_aname);
X        if (saptr->sa_name != NULL)
X            free(saptr->sa_name);
X        free(saptr);
X    }
X
X    /* close the scans and free the selected relation blocks */
X    for (srptr = slptr->sl_rels; srptr != NULL; srptr = nxtsr) {
X        nxtsr = srptr->sr_next;
X        if (srptr->sr_name != NULL)
X            free(srptr->sr_name);
X        db_rclose(srptr->sr_scan);
X        free(srptr);
X    }
X
X    /* free the where clause */
X    db_fcode(slptr);
X
X    /* free the user bindings */
X    for (bdptr = slptr->sl_bindings; bdptr != NULL; bdptr = nxtbd) {
X        nxtbd = bdptr->bd_next;
X        free(bdptr);
X    }
X
X    /* free the selection structure */
X    free(slptr);
X}
X
X/* db_fetch(slptr) - fetch the next tuple from a selection */
Xint db_fetch(slptr)
X  struct sel *slptr;
X{
X    struct srel *srptr;
X    struct binding *bdptr;
X
X    /* clear the update flags */
X    for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next)
X        srptr->sr_update = FALSE;
X
X    /* find a matching tuple */
X    while (process(slptr->sl_rels))
X        if (db_interpret(slptr)) {
X            for (bdptr = slptr->sl_bindings; bdptr != NULL; bdptr = bdptr->bd_next)
X                db_aget(bdptr->bd_attr,bdptr->bd_vtuple,bdptr->bd_vuser);
X            return (TRUE);
X        }
X
X    /* no matches, failure return */
X    return (FALSE);
X}
X
X/* db_update - update modified tuples */
Xint db_update(slptr)
X  struct sel *slptr;
X{
X    struct srel *srptr;
X
X    /* check each selected relation for updates */
X    for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next)
X        if (srptr->sr_update)
X            if (!db_rupdate(srptr->sr_scan))
X                return (FALSE);
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* db_store - store tuples */
Xint db_store(slptr)
X  struct sel *slptr;
X{
X    struct srel *srptr;
X
X    /* check each selected relation for stores */
X    for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next)
X        if (srptr->sr_update)
X            if (!db_rstore(srptr->sr_scan))
X                return (FALSE);
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* db_bind - bind a user buffer to the value of an attribute */
Xint db_bind(slptr,rname,aname,avalue)
X  struct sel *slptr; char *rname,*aname,*avalue;
X{
X    struct binding *newbd;
X    struct srel *srptr;
X
X    /* allocate and initialize a binding structure */
X    if ((newbd = malloc(sizeof(struct binding))) == NULL)
X        return (db_ferror(INSMEM));
X    newbd->bd_vuser = avalue;
X
X    /* find the attribute */
X    if (!find_attr(slptr,rname,aname,&newbd->bd_vtuple,&srptr,&newbd->bd_attr))
X        return (FALSE);
X
X    /* link the new binding into the binding list */
X    newbd->bd_next = slptr->sl_bindings;
X    slptr->sl_bindings = newbd;
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* db_get - get the value of an attribute */
Xint db_get(slptr,rname,aname,avalue)
X  struct sel *slptr; char *rname,*aname,*avalue;
X{
X    struct srel *srptr;
X    struct attribute *aptr;
X    char *vptr;
X
X    /* find the attribute */
X    if (!find_attr(slptr,rname,aname,&vptr,&srptr,&aptr))
X        return (FALSE);
X
X    /* get the attribute value */
X    db_aget(aptr,vptr,avalue);
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* db_put - put the value of an attribute */
Xint db_put(slptr,rname,aname,avalue)
X  struct sel *slptr; char *rname,*aname,*avalue;
X{
X    struct srel *srptr;
X    struct attribute *aptr;
X    char *vptr;
X
X    /* find the attribute */
X    if (!find_attr(slptr,rname,aname,&vptr,&srptr,&aptr))
X        return (FALSE);
X
X    /* put the attribute value */
X    db_aput(aptr,vptr,avalue);
X
X    /* mark the tuple as updated */
X    srptr->sr_update = TRUE;
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* db_sattr - get selected attribute type, pointer, and length */
Xint db_sattr(slptr,rname,aname,ptype,pptr,plen)
X  struct sel *slptr; char *rname,*aname;
X  int *ptype; char **pptr; int *plen;
X{
X    struct srel *srptr;
X    struct attribute *aptr;
X
X    if (!find_attr(slptr,rname,aname,pptr,&srptr,&aptr))
X        return (FALSE);
X    *ptype = aptr->at_type;
X    *plen = aptr->at_size;
X    return (TRUE);
X}
X
X/* get_sattrs(slptr) - get selected attributes */
Xstatic get_sattrs(slptr)
X  struct sel *slptr;
X{
X    struct sattr *newsattr,*lastsattr;
X
X    /* check for "*" or blank field meaning all attributes are selected */
X    if (db_token() == '*') {
X        db_ntoken();
X        return (TRUE);
X    }
X    else if (db_token() != ID)
X        return (TRUE);
X
X    /* parse a list of attribute names */
X    lastsattr = NULL;
X    while (TRUE) {
X
X        /* get attribute name */
X        if (db_ntoken() != ID)
X            return (db_ferror(SYNTAX));
X
X        /* allocate a selected attribute structure */
X        if ((newsattr = malloc(sizeof(struct sattr))) == NULL)
X            return (db_ferror(INSMEM));
X
X        /* initialize the selected attribute structure */
X        newsattr->sa_next = NULL;
X
X        /* save the attribute name */
X        if ((newsattr->sa_aname = malloc(strlen(dbv_tstring)+1)) == NULL) {
X            free(newsattr);
X            return (db_ferror(INSMEM));
X        }
X        strcpy(newsattr->sa_aname,dbv_tstring);
X
X        /* check for "." meaning "<rel-name>.<att-name>" */
X        if (db_token() == '.') {
X            db_ntoken();
X
X            /* the previous ID was really the relation name */
X            newsattr->sa_rname = newsattr->sa_aname;
X
X            /* check for attribute name */
X            if (db_ntoken() != ID) {
X                free(newsattr->sa_aname); free(newsattr);
X                return (db_ferror(SYNTAX));
X            }
X
X            /* save the attribute name */
X            if ((newsattr->sa_aname = malloc(strlen(dbv_tstring)+1)) == NULL) {
X                free(newsattr->sa_aname); free(newsattr);
X                return (db_ferror(INSMEM));
X            }
X            strcpy(newsattr->sa_aname,dbv_tstring);
X        }
X        else
X            newsattr->sa_rname = NULL;
X
X        /* check for alternate attribute name */
X        if (db_token() == ID) {
X            db_ntoken();
X
X            /* allocate space for the alternate name */
X            if ((newsattr->sa_name = malloc(strlen(dbv_tstring)+1)) == NULL) {
X                if (newsattr->sa_rname != NULL)
X                    free(newsattr->sa_rname);
X                free(newsattr->sa_aname);
X                free(newsattr);
X                return (db_ferror(INSMEM));
X            }
X            strcpy(newsattr->sa_name,dbv_tstring);
X        }
X        else
X            newsattr->sa_name = NULL;
X
X        /* link the selected attribute structure into the list */
X        if (lastsattr == NULL)
X            slptr->sl_attrs = newsattr;
X        else
X            lastsattr->sa_next = newsattr;
X        lastsattr = newsattr;
X
X        /* check for more attributes */
X        if (db_token() != ',')
X            break;
X        db_ntoken();
X    }
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* get_srels(slptr) - get selected relations */
Xstatic get_srels(slptr)
X  struct sel *slptr;
X{
X    char rname[KEYWORDMAX+1],*aname;
X
X    /* get the list of selected relations */
X    while (TRUE) {
X
X        /* check for relation name */
X        if (db_ntoken() != ID)
X            return (db_ferror(SYNTAX));
X        strcpy(rname,dbv_tstring);
X
X        /* check for alternate relation name */
X        if (db_token() == ID) {
X            db_ntoken();
X            aname = dbv_tstring;
X        }
X        else
X            aname = NULL;
X
X        /* add the relation name to the list */
X        if (!srelation(slptr,rname,aname))
X            return (FALSE);
X
X        /* check for more selected relations */
X        if (db_token() != ',')
X            break;
X        db_ntoken();
X    }
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* srelation - select a relation */
Xstatic srelation(slptr,rname,aname)
X  struct sel *slptr; char *rname,*aname;
X{
X    struct srel *srptr,*newsrel;
X
X    /* allocate a new selected relation structure */
X    if ((newsrel = malloc(sizeof(struct srel))) == NULL)
X        return (db_ferror(INSMEM));
X
X    /* initialize the new selected relation structure */
X    newsrel->sr_ctuple = FALSE;
X    newsrel->sr_update = FALSE;
X    newsrel->sr_next = NULL;
X
X    /* open the relation */
X    if ((newsrel->sr_scan = db_ropen(rname)) == NULL) {
X        free(newsrel);
X        return (FALSE);
X    }
X
X    /* check for alternate relation name */
X    if (aname != NULL) {
X
X        /* allocate space for the alternate name */
X        if ((newsrel->sr_name = malloc(strlen(aname)+1)) == NULL) {
X            free(newsrel);
X            return (db_ferror(INSMEM));
X        }
X        strcpy(newsrel->sr_name,aname);
X    }
X    else
X        newsrel->sr_name = NULL;
X
X    /* find the end of the list of relation names */
X    for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next)
X        if (srptr->sr_next == NULL)
X            break;
X
X    /* link the new selected relation structure into the list */
X    if (srptr == NULL)
X        slptr->sl_rels = newsrel;
X    else
X        srptr->sr_next = newsrel;
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* check_attrs(slptr) - check the list of selected attributes */
Xstatic int check_attrs(slptr)
X  struct sel *slptr;
X{
X    struct sattr *saptr;
X
X    /* check for all attributes selected */
X    if (slptr->sl_attrs == NULL)
X        return (all_attrs(slptr));
X
X    /* check each selected attribute */
X    for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next)
X        if (!find_attr(slptr,saptr->sa_rname,saptr->sa_aname,
X                        &saptr->sa_aptr,&saptr->sa_srel,&saptr->sa_attr))
X            return (FALSE);
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* all_attrs(slptr) - create a list of all attributes */
Xstatic int all_attrs(slptr)
X  struct sel *slptr;
X{
X    struct sattr *newsattr,*lastsattr;
X    struct srel *srptr;
X    struct attribute *aptr;
X    int i,astart;
X
X    /* loop through each selected relation */
X    lastsattr = NULL;
X    for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next) {
X
X        /* loop through each attribute within the relation */
X        astart = 1;
X        for (i = 0; i < NATTRS; i++) {
X
X            /* get a pointer to the current attribute */
X            aptr = &srptr->sr_scan->sc_relation->rl_header.hd_attrs[i];
X
X            /* check for last attribute */
X            if (aptr->at_name[0] == 0)
X                break;
X
X            /* allocate a new selected attribute structure */
X            if ((newsattr = malloc(sizeof(struct sattr))) == NULL)
X                return (db_ferror(INSMEM));
X
X            /* initialize the new selected attribute structure */
X            newsattr->sa_name = NULL;
X            newsattr->sa_srel = srptr;
X            newsattr->sa_aptr = srptr->sr_scan->sc_tuple + astart;
X            newsattr->sa_attr = aptr;
X            newsattr->sa_next = NULL;
X
X            /* save the relation name */
X            if ((newsattr->sa_rname = malloc(RNSIZE+1)) == NULL) {
X                free(newsattr);
X                return (db_ferror(INSMEM));
X            }
X            strncpy(newsattr->sa_rname,
X                    srptr->sr_scan->sc_relation->rl_name,
X                    RNSIZE);
X            newsattr->sa_rname[RNSIZE] = 0;
X
X            /* save the attribute name */
X            if ((newsattr->sa_aname = malloc(ANSIZE+1)) == NULL) {
X                free(newsattr->sa_rname);
X                free(newsattr);
X                return (db_ferror(INSMEM));
X            }
X            strncpy(newsattr->sa_aname,
X                    srptr->sr_scan->sc_relation->rl_header.hd_attrs[i].at_name,
X                    ANSIZE);
X            newsattr->sa_aname[ANSIZE] = 0;
X
X            /* link the selected attribute into the list */
X            if (lastsattr == NULL)
X                slptr->sl_attrs = newsattr;
X            else
X                lastsattr->sa_next = newsattr;
X            lastsattr = newsattr;
X
X            /* update the attribute start */
X            astart += aptr->at_size;
X        }
X    }
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* find_attr - find a named attribute */
Xstatic int find_attr(slptr,rname,aname,paptr,psrel,pattr)
X  struct sel *slptr; char *rname,*aname;
X  char **paptr; struct attribute **pattr;
X{
X    /* check for unqualified or qualified attribute names */
X    if (rname == NULL)
X        return (uattr(slptr,aname,paptr,psrel,pattr));
X    else
X        return (qattr(slptr,rname,aname,paptr,psrel,pattr));
X}
X
X/* uattr - find an unqualified attribute name */
Xstatic int uattr(slptr,aname,paptr,psrel,pattr)
X  struct sel *slptr; char *aname;
X  char **paptr; struct srel **psrel; struct attribute **pattr;
X{
X    struct srel *srptr;
X    struct attribute *aptr;
X    int i,astart;
X
X    /* loop through each selected relation */
X    *pattr = NULL;
X    for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next) {
X
X        /* loop through each attribute within the relation */
X        astart = 1;
X        for (i = 0; i < NATTRS; i++) {
X
X            /* get a pointer to the current attribute */
X            aptr = &srptr->sr_scan->sc_relation->rl_header.hd_attrs[i];
X
X            /* check for last attribute */
X            if (aptr->at_name[0] == 0)
X                break;
X
X            /* check for attribute name match */
X            if (db_sncmp(aname,aptr->at_name,ANSIZE) == 0) {
X                if (*pattr != NULL)
X                    return (db_ferror(ATAMBG));
X                *paptr = srptr->sr_scan->sc_tuple + astart;
X                *psrel = srptr;
X                *pattr = aptr;
X            }
X
X            /* update the attribute start */
X            astart += aptr->at_size;
X        }
X    }
X
X    /* check whether attribute was found */
X    if (*pattr == NULL)
X        return (db_ferror(ATUNDF));
X
X    /* return successfully */
X    return (TRUE);
X}
X
X/* qattr - find a qualified attribute name */
Xstatic int qattr(slptr,rname,aname,paptr,psrel,pattr)
X  struct sel *slptr; char *rname,*aname;
X  char **paptr; struct srel **psrel; struct attribute **pattr;
X{
X    struct srel *srptr;
X    struct attribute *aptr;
X    char *crname;
X    int i,astart;
X
X    /* loop through each selected relation */
X    for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next) {
X
X        /* get relation name */
X        if ((crname = srptr->sr_name) == NULL)
X            crname = srptr->sr_scan->sc_relation->rl_name;
X
X        /* check for relation name match */
X        if (db_sncmp(rname,crname,RNSIZE) == 0) {
X
X            /* loop through each attribute within the relation */
X            astart = 1;
X            for (i = 0; i < NATTRS; i++) {
X
X                /* get a pointer to the current attribute */
X                aptr = &srptr->sr_scan->sc_relation->rl_header.hd_attrs[i];
X
X                /* check for last attribute */
X                if (aptr->at_name[0] == 0)
X                    break;
X
X                /* check for attribute name match */
X                if (db_sncmp(aname,aptr->at_name,ANSIZE) == 0) {
X                    *paptr = srptr->sr_scan->sc_tuple + astart;
X                    *psrel = srptr;
X                    *pattr = aptr;
X                    return (TRUE);
X                }
X
X                /* update the attribute start */
X                astart += aptr->at_size;
X            }
X
X            /* attribute name not found */
X            return (db_ferror(ATUNDF));
X        }
X    }
X
X    /* relation name not found */
X    return (db_ferror(RLUNDF));
X}
X
X/* process(srptr) - process each tuple in a relation cross-product */
Xstatic int process(srptr)
X  struct srel *srptr;
X{
X    /* always get a new tuple if this is the last relation in the list */
X    if (srptr->sr_next == NULL) {
X
X        /* check for beginning of new scan */
X        if (!srptr->sr_ctuple)
X            db_rbegin(srptr->sr_scan);
X
X        /* return the next tuple in the relation */
X        return (srptr->sr_ctuple = db_rfetch(srptr->sr_scan));
X    }
X
X    /* check for beginning of new scan */
X    if (!srptr->sr_ctuple) {
X        db_rbegin(srptr->sr_scan);
X
X        /* get the first tuple */
X        if (!db_rfetch(srptr->sr_scan))
X            return (FALSE);
X    }
X
X    /* look for a match with the remaining relations in list */
X    while (!process(srptr->sr_next))
X
X        /* get the next tuple in the scan */
X        if (!db_rfetch(srptr->sr_scan))
X            return (srptr->sr_ctuple = FALSE);
X
X    /* found a match at this level */
X    return (srptr->sr_ctuple = TRUE);
X}
X
X/* db_aget - get the value of an attribute */
Xdb_aget(aptr,vptr,avalue)
X  struct attribute *aptr; char *vptr,*avalue;
X{
X    int i;
X
X    /* get the attribute value */
X    for (i = 0; i < aptr->at_size; i++)
X        *avalue++ = vptr[i];
X    *avalue = EOS;
X}
X
X/* db_aput - put the value of an attribute */
Xdb_aput(aptr,vptr,avalue)
X  struct attribute *aptr; char *vptr,*avalue;
X{
X    int i;
X
X    /* initialize counter */
X    i = 0;
X
X    /* right justify numbers */
X    if (aptr->at_type == TNUM)
X        for (; i < aptr->at_size - strlen(avalue); i++)
X            vptr[i] = ' ';
X
X    /* put the attribute value */
X    for (; i < aptr->at_size; i++)
X        if (*avalue == 0)
X            vptr[i] = 0;
X        else
X            vptr[i] = *avalue++;
X}
X
SHAR_EOF
if test 20482 -ne "`wc -c 'sel.c'`"
then
	echo shar: error transmitting "'sel.c'" '(should have been 20482 characters)'
fi
echo shar: extracting "'srt.c'" '(8289 characters)'
if test -f 'srt.c'
then
	echo shar: over-writing existing file "'srt.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'srt.c'
X/* SDB - sort routines */
X
X#include "stdio.h"
X#include "sdbio.h"
X
Xextern int dbv_token;
Xextern char dbv_tstring[];
Xextern int dbv_tvalue;
X
X/* get_skeys - get sort key list */
Xstatic struct skey *get_skeys(sptr)
X  struct scan *sptr;
X{
X    struct skey *skeys,*newskey,*lastskey;
X
X    /* parse a list of attribute names */
X    skeys = lastskey = NULL;
X    while (TRUE) {
X
X        /* get attribute name */
X        if (db_ntoken() != ID)
X            return (db_nerror(SYNTAX));
X
X        /* allocate a sort key structure */
X        if ((newskey = malloc(sizeof(struct skey))) == NULL)
X            return (db_nerror(INSMEM));
X
X        /* initialize the sort key structure */
X        newskey->sk_next = NULL;
X
X        /* lookup the attribute name */
X        if (!find_attr(sptr,newskey,dbv_tstring)) {
X            free(newskey);
X            return (NULL);
X        }
X
X        /* check for ascending or descending */
X        if (db_token() == ASCENDING || dbv_token == DESCENDING) {
X            newskey->sk_type = dbv_token;
X            db_ntoken();
X        }
X        else
X            newskey->sk_type = ASCENDING;
X
X        /* link the sort key structure into the list */
X        if (lastskey == NULL)
X            skeys = newskey;
X        else
X            lastskey->sk_next = newskey;
X        lastskey = newskey;
X
X        /* check for more attributes */
X        if (db_token() != ',')
X            break;
X        db_ntoken();
X    }
X
X    /* return successfully */
X    return (skeys);
X}
X
X/* db_sort - sort tuples in a relation */
Xint *db_sort(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
X  char *fmt;
X{
X    struct scan *sptr1,*sptr2,*sptr3;   /*dns*/
X    struct skey *skeys;
X    int result;
X
X    /* check for a command line */
X    if (fmt != NULL)
X        db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);
X
X    /* checks for relation name */
X    if (db_token() == ID)
X        db_ntoken();
X    else
X        strcpy(dbv_tstring,"sdbcur");
X
X    /* open the relation */
X    if ((sptr1 = db_ropen(dbv_tstring)) == NULL)
X        return (FALSE);
X    if ((sptr2 = db_ropen(dbv_tstring)) == NULL) {
X        db_rclose(sptr1);
X        return (FALSE);
X        }
X    if ((sptr3 = db_ropen(dbv_tstring)) == NULL) {   /*dns*/
X        db_rclose(sptr1);                            /*dns*/
X        db_rclose(sptr2);                            /*dns*/
X        return (FALSE);                              /*dns*/
X        }
X
X    /* checks for "<relation-name> by <sort-list>" */
X    if (db_ntoken() != BY)
X        return (db_ferror(SYNTAX));
X    if ((skeys = get_skeys(sptr1)) == NULL) {
X        db_rclose(sptr1);
X        db_rclose(sptr2);
X        db_rclose(sptr3);  /*dns*/
X        return (FALSE);
X       }
X
X    /* do the sort */
X    result = sort(skeys,sptr1,sptr2,sptr3);  /*dns*/
X
X    /* close the relation */
X    db_rclose(sptr1);
X    db_rclose(sptr2);
X    db_rclose(sptr3);     /*dns*/
X
X    /* free the sort keys */
X    free_skeys(skeys);
X
X    return (result);
X}
X
X/* free_skeys - free a list of sort keys */
Xstatic free_skeys(skeys)
X  struct skey *skeys;
X{
X    struct skey *thisskey;
X
X    for (thisskey = skeys; skeys != NULL; thisskey = skeys) {
X        skeys = skeys->sk_next;
X        free(thisskey);
X    }
X}
X
X/* find_attr - find an attribute */
Xstatic int find_attr(sptr,newskey,aname)
X  struct scan *sptr; struct skey *newskey; char *aname;
X{
X    struct attribute *aptr;
X    int i,astart;
X
X    /* loop through each attribute within the relation */
X    astart = 1;
X    for (i = 0; i < NATTRS; i++) {
X
X        /* get a pointer to the current attribute */
X        aptr = &sptr->sc_relation->rl_header.hd_attrs[i];
X
X        /* check for last attribute */
X        if (aptr->at_name[0] == 0)
X            break;
X
X        /* check for attribute name match */
X        if (db_sncmp(aname,aptr->at_name,ANSIZE) == 0) {
X            newskey->sk_start = astart;
X            newskey->sk_aptr = aptr;
X            return (TRUE);
X        }
X
X        /* update the attribute start */
X        astart += aptr->at_size;
X    }
X
X    /* attribute name not found */
X    return (db_ferror(ATUNDF));
X}
X
X/* sort - sort the relation */
Xstatic int sort(skeys,sptr1,sptr2,sptr3)
X  struct skey *skeys; struct scan *sptr1,*sptr2,*sptr3;
X{
X/*  unsigned int j,k,l,r;          dns */
X    long int passes,swaps;           /*dns*/
X    int i, j, m, n;         /*dns*/
X    int rec1 = 0;           /*dns*/
X    int rec2 = 0;           /*dns*/
X    int rec3 = 0;           /*dns*/
X    int dns = 0;            /*dns*/
X    FILE *test;             /*dns*/
X
X    passes = 0L;
X    swaps = 0L;
X
X    /*dns --->   */
X    test = fopen("sort.dat", "w");
X    n = sptr1->sc_relation->rl_tcnt;
X    m = n;
X
X    while( m>1 )   {
X       passes++;
X       if ((m/=3.14159) < 1)  m = 1;
X       for ( j=1; j<=n-m; j++ )  {
X          if( rec1 != j+m )  {
X             if(dns) fprintf(test,"Read1: %d\n", j+m);
X             if (!db_rget(sptr1, rec1=j+m))  return (FALSE);
X             }
X          for ( i=j; i>=1; i-=m ) {
X             if( rec2 != i )   {
X                if(dns) fprintf(test,"Read2: %d\n", i);
X                if (!db_rget(sptr2, rec2=i))  return (FALSE);
X                }
X             if (compare(skeys,sptr1,sptr2) > 0)
X                break;
X             if(rec3 != i+m)  {
X                if(dns) fprintf(test,"Read3: %d\n", i+m);
X                if (!db_rget(sptr3, rec3=i+m))  return (FALSE);
X                }
X             if(dns) fprintf(test,"Write 3,2: %d from %d\n", i+m, i);
X             assign( sptr3, sptr2 );
X             swaps++;
X             }
X          if(rec1 != i+m)  {
X             if(rec3 != i+m)  {
X                if(dns) fprintf(test,"Read 3: %d\n", i+m);
X                if (!db_rget(sptr3, rec3=i+m))  return (FALSE);
X                }
X             if(dns) fprintf(test,"Write 3,1: %d from %d\n", i+m, j+m);
X             assign( sptr3, sptr1 );
X             swaps++;
X             }
X          }
X       }
X       fclose(test);
X
X/*
X    l = 2;
X    r = sptr1->sc_relation->rl_tcnt;
X    k = r;
X
X    do {
X        for (j = r; j >= l; j--) {
X            if (!db_rget(sptr1,j-1))
X                return (FALSE);
X            if (!db_rget(sptr2,j))
X                return (FALSE);
X            if (compare(skeys,sptr1,sptr2) > 0) {
X                swap(sptr1,sptr2);
X                k = j;
X                swaps++;
X            }
X        }
X        l = k + 1;
X        for (j = l; j <= r; j++) {
X            if (!db_rget(sptr1,j-1))
X                return (FALSE);
X            if (!db_rget(sptr2,j))
X                return (FALSE);
X            if (compare(skeys,sptr1,sptr2) > 0) {
X                swap(sptr1,sptr2);
X                k = j;
X                swaps++;
X            }
X        }
X        r = k - 1;
X        passes++;
X    } while (l <= r);
X*/
X
X    printf("[ Passes: %ld  Swaps: %ld ]\n",passes,swaps);
X
X    return (TRUE);
X}
X
X/* compare - compare two tuples */
Xstatic int compare(skeys,sptr1,sptr2)
X  struct skey *skeys; struct scan *sptr1,*sptr2;
X{
X    struct skey *cskey;
X    int result;
X
X    for (cskey = skeys; cskey != NULL; cskey = cskey->sk_next)
X        if ((result = cattr(cskey,sptr1,sptr2)) != 0)
X            break;
X
X    return (result);
X}
X
X/* cattr - compare two attributes */
Xstatic int cattr(cskey,sptr1,sptr2)
X  struct skey *cskey; struct scan *sptr1,*sptr2;
X{
X    int astart,aend,i;
X
X    astart = cskey->sk_start;
X    aend = astart + cskey->sk_aptr->at_size;
X
X    for (i = astart; i < aend; i++)
X        if (sptr1->sc_tuple[i] != sptr2->sc_tuple[i])
X            break;
X
X    if (i == aend)
X        return (0);
X
X    if (sptr1->sc_tuple[i] < sptr2->sc_tuple[i])
X        if (cskey->sk_type == ASCENDING)
X            return (-1);
X        else
X            return (1);
X    else
X        if (cskey->sk_type == ASCENDING)
X            return (1);
X        else
X            return (-1);
X}
X
X/* swap - swap two tuples */
X/* dns
Xstatic int swap(sptr1,sptr2)
X  struct scan *sptr1,*sptr2;
X{
X    unsigned int tnum1,tnum2;
X
X    tnum1 = sptr1->sc_atnum;
X    tnum2 = sptr2->sc_atnum;
X
X    if (!db_rput(sptr1,tnum2))
X        return (FALSE);
X    if (!db_rput(sptr2,tnum1))
X        return (FALSE);
X
X    return (TRUE);
X}
X  dns  */
X
X
X/* assign - assign one tupple to another */
Xstatic int assign(sptr1,sptr2)
X  struct scan *sptr1,*sptr2;
X{
X    unsigned int tnum1,tnum2;
X
X    tnum1 = sptr1->sc_atnum;
X
X    if (!db_rput(sptr2,tnum1))
X        return (FALSE);
X
X    return (TRUE);
X}
X
SHAR_EOF
if test 8289 -ne "`wc -c 'srt.c'`"
then
	echo shar: error transmitting "'srt.c'" '(should have been 8289 characters)'
fi
echo shar: extracting "'tbl.c'" '(2554 characters)'
if test -f 'tbl.c'
then
	echo shar: over-writing existing file "'tbl.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'tbl.c'
X/* SDB - table output routines */
X
X#include "stdio.h"
X#include "sdbio.h"
X
Xstatic char buffer[TABLEMAX+1];
Xint bndx;
X
X/* db_thead - print a table header */
Xdb_thead(fp,slptr)
X  FILE *fp; struct sel *slptr;
X{
X    struct sattr *saptr;
X    int twidth,fwidth,i;
X    char *aname;
X
X    /* compute the table width */
X    twidth = 1;
X    for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next)
X        twidth += saptr->sa_attr->at_size + 3;
X
X    /* print the top line of the table */
X    bstart();
X    for (i = 0; i < twidth; i++)
X        binsert('-');
X    bprint(fp);
X
X    /* print the label line of the table */
X    bstart();
X    for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {
X        fwidth = saptr->sa_attr->at_size;
X        binsert('|'); binsert(' ');
X        if ((aname = saptr->sa_name) == NULL)
X            aname = saptr->sa_aname;
X        for (i = 0; i < fwidth; i++)
X            if (*aname != 0)
X                binsert(*aname++);
X            else
X                binsert(' ');
X        binsert(' ');
X    }
X    binsert('|');
X    bprint(fp);
X
X    /* print the line under the labels */
X    bstart();
X    for (i = 0; i < twidth; i++)
X        binsert('-');
X    bprint(fp);
X}
X
X/* db_tfoot - print a table foot */
Xdb_tfoot(fp,slptr)
X  FILE *fp; struct sel *slptr;
X{
X    struct sattr *saptr;
X    int twidth,i;
X
X    /* compute the table width */
X    twidth = 1;
X    for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next)
X        twidth += saptr->sa_attr->at_size + 3;
X
X    /* print the line at the foot of the table */
X    bstart();
X    for (i = 0; i < twidth; i++)
X        binsert('-');
X    bprint(fp);
X}
X
X/* db_tentry - print a table entry */
Xdb_tentry(fp,slptr)
X  FILE *fp; struct sel *slptr;
X{
X    struct sattr *saptr;
X    int fwidth,i;
X
X    /* print a table entry */
X    bstart();
X    for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {
X        fwidth = saptr->sa_attr->at_size;
X        binsert('|'); binsert(' ');
X        for (i = 0; i < fwidth; i++)
X            if (saptr->sa_aptr[i] != 0)
X                binsert(saptr->sa_aptr[i]);
X            else
X                binsert(' ');
X        binsert(' ');
X    }
X    binsert('|');
X    bprint(fp);
X}
X
X/* bstart - start building a line */
Xstatic bstart()
X{
X    bndx = 0;
X}
X
X/* binsert - insert a character into the buffer */
Xstatic binsert(ch)
X  int ch;
X{
X    if (bndx < TABLEMAX)
X        buffer[bndx++] = ch;
X}
X
X/* bprint - print the current line */
Xstatic bprint(fp)
X  FILE *fp;
X{
X    buffer[bndx] = EOS;
X    fprintf(fp,"%s\n",buffer);
X}
X
SHAR_EOF
if test 2554 -ne "`wc -c 'tbl.c'`"
then
	echo shar: error transmitting "'tbl.c'" '(should have been 2554 characters)'
fi
echo shar: extracting "'sdbio.h'" '(7764 characters)'
if test -f 'sdbio.h'
then
	echo shar: over-writing existing file "'sdbio.h'"
fi
sed 's/^X//' << \SHAR_EOF > 'sdbio.h'
X/* SDB - definition file */
X
X#include "ctype.h"  /*dns*/
X
X/* compiler specific stuff  (dns) */
X#define Lattice
X
X/* useful definitions */
X#define TRUE            1
X#define FALSE           0
X#ifndef NULL
X#define NULL            0
X#endif
X
X/* Character definitions   (dns) */
X#define BS  0x8       /*dns*/
X#define CR  0xD       /*dns*/
X#define FF  0xC       /*dns*/
X#define ESC 0x1B      /*dns*/
X
X/* program limits */
X#define LINEMAX         132     /* maximum input line length */
X#define TABLEMAX        132     /* maximum table output line */
X#define KEYWORDMAX      10      /* maximum keyword length */
X#define NUMBERMAX       20      /* maximum number length */
X#define STRINGMAX       132     /* maximum string length */
X#define CODEMAX         100     /* maximum length of code array */
X#define STACKMAX        20      /* maximum interpreter stack size */
X
X/* token definitions */
X#define EOS             0
X#define LSS             -1
X#define LEQ             -2
X#define EQL             -3
X#define NEQ             -4
X#define GEQ             -5
X#define GTR             -6
X#define SELECT          -7
X#define FROM            -8
X#define WHERE           -9
X#define CREATE          -10
X#define DELETE          -11
X#define INSERT          -12
X#define EXIT            -13
X#define CHAR            -14
X#define NUM             -15
X#define ID              -16
X#define STRING          -17
X#define NUMBER          -18
X#define UPDATE          -19
X#define PRINT           -20
X#define IMPORT          -21
X#define EXPORT          -22
X#define INTO            -23
X#define HELP            -24
X#define COMPRESS        -25
X#define EXTRACT         -26
X#define DEFINE          -27
X#define SHOW            -28
X#define USING           -29
X#define SORT            -30
X#define BY              -31
X#define ASCENDING       -32
X#define DESCENDING      -33
X#define SET             -34
X
X/* operand types */
X#define LITERAL 1
X#define ATTR    2
X#define TEMP    3
X
X/* attribute data types */
X#define TCHAR   1
X#define TNUM    2
X
X/* tuple status codes */
X#define UNUSED  0
X#define ACTIVE  1
X#define DELETED 2
X
X/* relation header page format definitions */
X#define RNSIZE          10      /* size of a relation name */
X#define HSIZE           16      /* size of a relation entry */
X#define ASIZE           16      /* size of a attribute entry */
X#define ANSIZE          10      /* size of a attribute name */
X#define NATTRS          31      /* number of attributes in header block */
X
X/* error code definitions */
X#define END             0       /* end of retrieval set */
X#define INSMEM          1       /* insufficient memory */
X#define RELFNF          2       /* relation file not found */
X#define BADHDR          3       /* bad relation file header */
X#define TUPINP          4       /* tuple input error */
X#define TUPOUT          5       /* tuple output error */
X#define RELFUL          6       /* relation file full */
X#define RELCRE          7       /* error creating relation file */
X#define DUPATT          8       /* duplicate attribute on relation create */
X#define MAXATT          9       /* too many attributes on relation create */
X#define INSBLK          10      /* insufficient disk blocks */
X#define SYNTAX          11      /* command syntax error */
X#define ATUNDF          12      /* attribute name undefined */
X#define ATAMBG          13      /* attribute name ambiguous */
X#define RLUNDF          14      /* relation name undefined */
X#define CDSIZE          15      /* boolean expression code too big */
X#define INPFNF          16      /* input file not found */
X#define OUTCRE          17      /* output file creation error */
X#define INDFNF          18      /* indirect command file not found */
X#define BADSET          19      /* bad set parameter */
X
Xstruct attribute {
X    char at_name[ANSIZE];       /* attribute name */
X    char at_type;               /* attribute type */
X    char at_size;               /* attribute size in bytes */
X    char at_scale;              /* attribute scale factor (for numeric only) */
X    char at_unused[ASIZE-ANSIZE-3];     /* unused space */
X};
X
Xstruct header {         /* sizeof(struct header) must be 512 bytes */
X    char hd_tcnt[2];            /* # of tuples in relation */
X    char hd_tmax[2];            /* maximum # of tuples */
X    char hd_data[2];            /* offset to first data byte */
X    char hd_size[2];            /* size of each tuple in bytes */
X    char hd_unused[HSIZE-8];    /* unused space */
X    struct attribute hd_attrs[NATTRS];  /* table of attributes */
X};
X
Xstruct relation {
X    char rl_name[RNSIZE];       /* relation name */
X    unsigned int rl_tcnt;       /* # of tuples in relation (from hd_tcnt) */
X    unsigned int rl_tmax;       /* maximum # of tuples (from hd_tmax) */
X    int rl_data;                /* offset to first data byte (from hd_data) */
X    int rl_size;                /* size of eachtuple in bytes (from hd_size) */
X    int rl_store;               /* flag indicating a store happened */
X    int rl_fd;                  /* file descriptor for relation file */
X    int rl_scnref;              /* number of scans referencing this relation */
X    struct header rl_header;    /* the relation file header block */
X    struct relation *rl_next;   /* pointer to next relation */
X};
X
Xstruct scan {
X    struct relation *sc_relation;       /* pointer to relation definition */
X    unsigned int sc_dtnum;              /* desired tuple number */
X    unsigned int sc_atnum;              /* actual tuple number */
X    int sc_store;                       /* flag indicating a store happened */
X    char *sc_tuple;                     /* tuple buffer */
X};
X
Xstruct srel {
X    char *sr_name;                      /* alternate relation name */
X    struct scan *sr_scan;               /* relation scan structure ptr */
X    int sr_ctuple;                      /* current tuple flag */
X    int sr_update;                      /* updated tuple flag */
X    struct srel *sr_next;               /* next selected relation in list */
X};
X
Xstruct sattr {
X    char *sa_rname;                     /* relation name */
X    char *sa_aname;                     /* attribute name */
X    char *sa_name;                      /* alternate attribute name */
X    char *sa_aptr;                      /* pointer to attr in tuple buffer */
X    struct srel *sa_srel;               /* pointer to the selected relation */
X    struct attribute *sa_attr;          /* attribute structure ptr */
X    struct sattr *sa_next;              /* next selected attribute in list */
X};
X
Xstruct operand {
X    int o_type;
X    union  {
X        struct {
X            int ovc_type;
X            char *ovc_string;
X            int ovc_length;
X        } ov_char;
X        int ov_boolean;
X    } o_value;
X};
X
Xunion codecell {
X    int (*c_operator)();
X    struct operand *c_operand;
X};
X
Xstruct binding {
X    struct attribute *bd_attr;          /* bound attribute */
X    char *bd_vtuple;                    /* pointer to value in tuple */
X    char *bd_vuser;                     /* pointer to user buffer */
X    struct binding *bd_next;            /* next binding */
X};
X
Xstruct sel {
X    struct srel *sl_rels;               /* selected relations */
X    struct sattr *sl_attrs;             /* selected attributes */
X    union codecell *sl_where;           /* where clause */
X    struct binding *sl_bindings;        /* user variable bindings */
X};
X
Xstruct mtext {
X    char *mt_text;
X    struct mtext *mt_next;
X};
X
Xstruct macro {
X    char *mc_name;
X    struct mtext *mc_mtext;
X    struct macro *mc_next;
X};
X
Xstruct ifile {
X    char *if_fp;
X    struct mtext *if_mtext;
X    char *if_cmdline;
X    int if_savech;
X    char *if_lptr;
X    struct ifile *if_next;
X};
X
Xstruct skey {
X    int sk_type;
X    struct attribute *sk_aptr;
X    int sk_start;
X    struct skey *sk_next;
X};
X
SHAR_EOF
if test 7764 -ne "`wc -c 'sdbio.h'`"
then
	echo shar: error transmitting "'sdbio.h'" '(should have been 7764 characters)'
fi
#	End of shell archive
exit 0
-- 
Usenet: [decvax|allegra|linus|ihnp4]!utzoo!yetti!oz
Bitnet: oz@[yusol|yuyetti]
	You see things; and you say "WHY?"
	But I dream things that never were;
	and say "WHY NOT?"
			G. Bernard Shaw (Back to Methuselah)