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