a small dbms (reposting sources) 2 of 3

Ozan Yigit oz at yetti.UUCP
Tue Sep 3 06:41:35 AEST 1985


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



More information about the Comp.sources.unix mailing list