a small dbms - part 2

Ozan Yigit oz at yetti.UUCP
Tue Aug 27 05:44:42 AEST 1985


This is the last part of the dbms: all the source files.
This stuff compiles under 4.2 BSD and VENIX (vers. 7) just
fine.

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
#	int.c
#	io.c
#	mth.c
#	pcjunk.c
#	scn.c
#	sdb.c
#	sel.c
#	srt.c
#	tbl.c
#	sdbio.h
# This archive created: Mon Aug 26 15:39:01 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
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
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)



More information about the Comp.sources.unix mailing list