Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/5/84; site yetti.UUCP Path: utzoo!utcs!mnetor!yetti!oz From: oz@yetti.UUCP (Ozan Yigit) Newsgroups: net.sources Subject: a small dbms (reposting sources) 2 of 3 Message-ID: <246@yetti.UUCP> Date: Mon, 2-Sep-85 16:41:35 EDT Article-I.D.: yetti.246 Posted: Mon Sep 2 16:41:35 1985 Date-Received: Mon, 2-Sep-85 19:15:52 EDT Reply-To: oz@yetti.UUCP (Ozan Yigit) Organization: York University Computer Science Lines: 1764 Keywords: dbms ------------- 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)