Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!gatech!akgua!mhuxv!mhuxf!mhuxm!mhuxn!ihnp4!inuxc!pur-ee!j.cc.purdue.edu!doc From: doc@pucc-j.UUCP Newsgroups: mod.amiga.sources Subject: sdb Database (2 of 3) Message-ID: <1851@j.cc.purdue.edu> Date: Fri, 22-Aug-86 18:46:03 EDT Article-I.D.: j.1851 Posted: Fri Aug 22 18:46:03 1986 Date-Received: Sun, 24-Aug-86 09:03:49 EDT Sender: doc@j.cc.purdue.edu Organization: Purdue University Computing Center Lines: 2129 Approved: doc@pucc-j.UUCP # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # int.c # io.c # scn.c # cmd.c # This archive created: Fri Aug 22 17:39:48 1986 # By: Craig Norborg (Purdue University Computing Center) cat << \SHAR_EOF > int.c /* SDB - boolean expression evaluator */ #include "sdbio.h" static struct operand *stack[STACKMAX],**sptr; static union codecell *cptr; /* db_interpret - interpret a boolean expression */ int db_interpret(slptr) struct sel *slptr; { struct operand *result; int r; /* check for empty where clause */ if ((cptr = slptr->sl_where) == NULL) return (TRUE); /* setup stack */ sptr = stack; /* execute the code */ while ((*(*cptr++).c_operator)()) ; /* get the result from the top of stack */ result = *--sptr; r = result->o_value.ov_boolean; if (result->o_type == TEMP) free(result); /* make sure the stack is empty */ while (sptr != stack) { if ((*sptr)->o_type == TEMP) free(*sptr); sptr -= 1; } /* return result */ return (r); } int db_xstop() { return (FALSE); } int db_xpush() { *sptr++ = (*cptr++).c_operand; } int db_xand() { return (boolean('&')); } int db_xor() { return (boolean('|')); } static int boolean(opr) { struct operand *lval,*rval,*result; int lv,rv,r; rval = *--sptr; lval = *--sptr; lv = lval->o_value.ov_boolean; rv = rval->o_value.ov_boolean; if ((result = malloc(sizeof(struct operand))) == NULL) return (db_ferror(INSMEM)); result->o_type = TEMP; switch (opr) { case '&': r = (lv && rv); break; case '|': r = (lv || rv); break; } result->o_value.ov_boolean = r; *sptr++ = result; if (lval->o_type == TEMP) free(lval); if (rval->o_type == TEMP) free(rval); return (TRUE); } int db_xnot() { struct operand *val,*result; val = *--sptr; if ((result = malloc(sizeof(struct operand))) == NULL) return (db_ferror(INSMEM)); result->o_type = TEMP; result->o_value.ov_boolean = !val->o_value.ov_boolean; *sptr++ = result; if (val->o_type == TEMP) free(val); return (TRUE); } int db_xlss() { return (compare(LSS)); } int db_xleq() { return (compare(LEQ)); } int db_xeql() { return (compare(EQL)); } int db_xgeq() { return (compare(GEQ)); } int db_xgtr() { return (compare(GTR)); } int db_xneq() { return (compare(NEQ)); } static int compare(cmp) { struct operand *lval,*rval,*result; int i; rval = *--sptr; lval = *--sptr; if ((result = malloc(sizeof(struct operand))) == NULL) return (db_ferror(INSMEM)); result->o_type = TEMP; if (lval->o_value.ov_char.ovc_type == TCHAR) i = comp(lval,rval); else i = ncomp(lval,rval); switch (cmp) { case LSS: i = (i < 0); break; case LEQ: i = (i <= 0); break; case EQL: i = (i == 0); break; case GEQ: i = (i >= 0); break; case GTR: i = (i > 0); break; case NEQ: i = (i != 0); break; } result->o_value.ov_boolean = i; *sptr++ = result; if (lval->o_type == TEMP) free(lval); if (rval->o_type == TEMP) free(rval); return (TRUE); } static int comp(lval,rval) struct operand *lval,*rval; { char *lptr,*rptr; int lctr,rctr; int len; lptr = lval->o_value.ov_char.ovc_string; lctr = lval->o_value.ov_char.ovc_length; rptr = rval->o_value.ov_char.ovc_string; rctr = rval->o_value.ov_char.ovc_length; while (lctr > 0 && (lptr[lctr-1] == 0 || lptr[lctr-1] == ' ')) lctr--; while (rctr > 0 && (rptr[rctr-1] == 0 || rptr[rctr-1] == ' ')) rctr--; if (lctr < rctr) len = lctr; else len = rctr; while ((len--) > 0) { if (*lptr++ != *rptr++) if (*--lptr < *--rptr) return (-1); else return (1); } if (lctr == rctr) return (0); else if (lctr < rctr) return (-1); else return (1); } static int ncomp(lval,rval) struct operand *lval,*rval; { char lstr[NUMBERMAX+1],rstr[NUMBERMAX+1]; int len; strncpy(lstr,lval->o_value.ov_char.ovc_string, (len = lval->o_value.ov_char.ovc_length)); lstr[len] = EOS; strncpy(rstr,rval->o_value.ov_char.ovc_string, (len = rval->o_value.ov_char.ovc_length)); rstr[len] = EOS; return (db_cmp(lstr,rstr)); } SHAR_EOF cat << \SHAR_EOF > io.c /* SDB - relation file I/O routines */ #include #include "sdbio.h" /* global error code variable */ int dbv_errcode; /* list of currently loaded relation definitions */ static struct relation *relations = NULL; /* rfind - find the specified relation */ static struct relation *rfind(rname) char *rname; { int fd; char filename[RNSIZE+5]; struct relation *rptr; /* look for relation in list currently loaded */ for (rptr = relations; rptr != NULL; rptr = rptr->rl_next) if (db_sncmp(rname,rptr->rl_name,RNSIZE) == 0) return (rptr); /* create a file name */ make_fname(filename,rname); /* lookup the relation file */ #ifdef Lattice if ((fd = open(filename,0x8000)) == -1) /*dns*/ #else if ((fd = open(filename,0)) == -1) #endif return (db_nerror(RELFNF)); /* allocate a new relation structure */ if ((rptr = malloc(sizeof(struct relation))) == NULL) { close(fd); return (db_nerror(INSMEM)); } /* initialize the relation structure */ rptr->rl_scnref = 0; /* read the header block */ if ( read(fd,&rptr->rl_header,512) != 512) { free(rptr); close(fd); return (db_nerror(BADHDR)); } /* close the relation file */ close(fd); /* extract header information */ rptr->rl_tcnt = db_cvword(rptr->rl_header.hd_tcnt); rptr->rl_tmax = db_cvword(rptr->rl_header.hd_tmax); rptr->rl_data = db_cvword(rptr->rl_header.hd_data); rptr->rl_size = db_cvword(rptr->rl_header.hd_size); /* store the relation name */ strncpy(rptr->rl_name,rname,RNSIZE); /* link new relation into relation list */ rptr->rl_next = relations; relations = rptr; /* return the new relation structure pointer */ return (rptr); } /* db_ropen - open a relation file */ struct scan *db_ropen(rname) char *rname; { struct relation *rptr; struct scan *sptr; char filename[RNSIZE+5]; /* find the relation definition */ if ((rptr = rfind(rname)) == NULL) return (NULL); /* allocate a new scan structure */ if ((sptr = malloc(sizeof(struct scan))) == NULL) return (db_nerror(INSMEM)); /* allocate a tuple buffer */ if ((sptr->sc_tuple = malloc(rptr->rl_size)) == NULL) { free(sptr); return (db_nerror(INSMEM)); } /* initialize the scan structure */ sptr->sc_relation = rptr; /* store the relation struct addrs */ sptr->sc_dtnum = 0; /* desired tuple (non-existant) */ sptr->sc_atnum = 0; /* actual tuple (non-existant) */ sptr->sc_store = FALSE; /* no store done since open */ /* open relation file if necessary */ if (rptr->rl_scnref++ == 0) { /* create the relation file name */ make_fname(filename,rname); /* open the relation file */ #ifdef Lattice if ((rptr->rl_fd = open(filename,0x8002)) == -1) { /*dns*/ #else if ((rptr->rl_fd = open(filename,2)) == -1) { #endif rptr->rl_scnref--; free(sptr->sc_tuple); free(sptr); return (db_nerror(RELFNF)); } } /* return the new scan structure pointer */ return (sptr); } /* db_rclose - close the relation file */ int db_rclose(sptr) struct scan *sptr; { struct relation *rptr,*lastrptr; /* close relation file if this is the last reference */ if (--sptr->sc_relation->rl_scnref == 0) { /* rewrite header if any stores took place */ if (sptr->sc_store) { /* store the tuple count back in the header */ db_cvbytes(sptr->sc_relation->rl_tcnt, sptr->sc_relation->rl_header.hd_tcnt); /* write the header block */ lseek(sptr->sc_relation->rl_fd,0L,0); if (write(sptr->sc_relation->rl_fd, &sptr->sc_relation->rl_header,512) != 512) { close(sptr->sc_relation->rl_fd); free(sptr->sc_tuple); free(sptr); return (db_ferror(BADHDR)); } } /* close the relation file */ close(sptr->sc_relation->rl_fd); /* free the relation header */ lastrptr = NULL; for (rptr = relations; rptr != NULL; rptr = rptr->rl_next) { if (rptr == sptr->sc_relation) { if (lastrptr == NULL) relations = rptr->rl_next; else lastrptr->rl_next = rptr->rl_next; } lastrptr = rptr; } free(sptr->sc_relation); } /* free the scan structure */ free(sptr->sc_tuple); free(sptr); /* return successfully */ return (TRUE); } /* db_rcompress - compress a relation file */ int db_rcompress(sptr) struct scan *sptr; { unsigned int next,nextfree,tcnt; /* get the last used tuple */ tcnt = sptr->sc_relation->rl_tcnt; /* loop through all of the tuples */ for (next = nextfree = 1; next <= tcnt; next++) { /* read the tuple */ seek(sptr,next); if (read(sptr->sc_relation->rl_fd, sptr->sc_tuple,sptr->sc_relation->rl_size) != sptr->sc_relation->rl_size) return (db_ferror(TUPINP)); /* rewrite the tuple if it is active */ if (sptr->sc_tuple[0] == ACTIVE) { /* rewrite it only if it must move */ if (next != nextfree) { /* write the tuple */ seek(sptr,nextfree); if (write(sptr->sc_relation->rl_fd, sptr->sc_tuple,sptr->sc_relation->rl_size) != sptr->sc_relation->rl_size) return (db_ferror(TUPOUT)); } /* update the next free tuple number */ nextfree += 1; } } /* update the tuple count */ sptr->sc_relation->rl_tcnt = nextfree - 1; /* remember which tuple is in the buffer */ sptr->sc_atnum = sptr->sc_relation->rl_tcnt; /* reset the desired tuple */ sptr->sc_dtnum = 0; /* remember that the index needs rewriting */ sptr->sc_store = TRUE; /* return successfully */ return (TRUE); } /* db_rbegin - begin scan at first tuple in relation */ db_rbegin(sptr) struct scan *sptr; { /* begin with the first tuple in the file */ sptr->sc_dtnum = 0; } /* db_rfetch - fetch the next tuple from the relation file */ int db_rfetch(sptr) struct scan *sptr; { /* look for an active tuple */ while (TRUE) { /* check for this being the last tuple */ if (!db_rget(sptr,sptr->sc_dtnum + 1)) return (FALSE); /* increment the tuple number */ sptr->sc_dtnum += 1; /* return if the tuple found is active */ if (sptr->sc_tuple[0] == ACTIVE) return (TRUE); } } /* db_rupdate - update the current tuple */ int db_rupdate(sptr) struct scan *sptr; { /* make sure the status byte indicates an active tuple */ sptr->sc_tuple[0] = ACTIVE; /* write the tuple */ return (db_rput(sptr,sptr->sc_atnum)); } /* db_rdelete - delete the current tuple */ int db_rdelete(sptr) struct scan *sptr; { /* make sure the status byte indicates a deleted tuple */ sptr->sc_tuple[0] = DELETED; /* write the tuple */ return (db_rput(sptr,sptr->sc_atnum)); } /* db_rstore - store a new tuple */ int db_rstore(sptr) struct scan *sptr; { /* make sure there's room for this tuple */ if (sptr->sc_relation->rl_tcnt == sptr->sc_relation->rl_tmax) return (db_ferror(RELFUL)); /* make sure the status byte indicates an active tuple */ sptr->sc_tuple[0] = ACTIVE; /* write the tuple */ if (!db_rput(sptr,sptr->sc_relation->rl_tcnt + 1)) return (FALSE); /* update the tuple count */ sptr->sc_relation->rl_tcnt += 1; /* remember that a tuple was stored */ sptr->sc_store = TRUE; /* return successfully */ return (TRUE); } /* db_rget - get a tuple from the relation file */ int db_rget(sptr,tnum) struct scan *sptr; unsigned int tnum; { /* check to see if the tuple is already in the buffer */ if (tnum == sptr->sc_atnum) return (TRUE); /* check for this being beyond the last tuple */ if (tnum > sptr->sc_relation->rl_tcnt) return (db_ferror(TUPINP)); /* read the tuple */ seek(sptr,tnum); if (read(sptr->sc_relation->rl_fd, sptr->sc_tuple,sptr->sc_relation->rl_size) != sptr->sc_relation->rl_size) return (db_ferror(TUPINP)); /* remember which tuple is in the buffer */ sptr->sc_atnum = tnum; /* return successfully */ return (TRUE); } /* db_rput - put a tuple to a relation file */ int db_rput(sptr,tnum) struct scan *sptr; unsigned int tnum; { /* check for this being beyond the maximum tuple */ if (tnum > sptr->sc_relation->rl_tmax) return (db_ferror(TUPOUT)); /* write the tuple */ seek(sptr,tnum); if (write(sptr->sc_relation->rl_fd, sptr->sc_tuple,sptr->sc_relation->rl_size) != sptr->sc_relation->rl_size) return (db_ferror(TUPOUT)); /* remember which tuple is in the buffer */ sptr->sc_atnum = tnum; /* return successfully */ return (TRUE); } /* seek - seek a tuple in a relation file */ static seek(sptr,tnum) struct scan *sptr; unsigned int tnum; { long offset; offset = (long) sptr->sc_relation->rl_data + ((long) (tnum - 1) * (long) sptr->sc_relation->rl_size); lseek(sptr->sc_relation->rl_fd,offset,0); } /* make_fname - make a relation name into a file name */ static make_fname(fname,rname) char *fname,*rname; { strncpy(fname,rname,RNSIZE); fname[RNSIZE] = 0; strcat(fname,".sdb"); } /* db_nerror - store the error code and return NULL */ int db_nerror(errcode) int errcode; { dbv_errcode = errcode; return (NULL); } /* db_ferror - store the error code and return FALSE */ int db_ferror(errcode) int errcode; { dbv_errcode = errcode; return (FALSE); } /* db_cvword - convert 2 bytes to a word */ int db_cvword(bytes) char bytes[2]; { return (((bytes[1] & 0377) << 8) + (bytes[0] & 0377)); } /* db_cvbytes - convert a word to 2 bytes */ db_cvbytes(word,bytes) int word; char bytes[2]; { bytes[0] = word; bytes[1] = word >> 8; } SHAR_EOF cat << \SHAR_EOF > scn.c /* SDB - token scanning routines */ #include #include "sdbio.h" int dbv_token; /* current token */ int dbv_tvalue; /* integer token value */ char dbv_tstring[STRINGMAX+1]; /* string token value */ struct ifile *dbv_ifp; /* indirect file context */ struct macro *dbv_macros; /* macro definitions */ int dbv_fold; /* case fold alpha comparisons */ static char *iprompt,*cprompt; /* input prompts */ static char cmdline[LINEMAX+2],*lptr; /* current line and pointer */ static int atbol; /* flag indicating at bol */ static int savech; /* lookahead character */ static int savetkn; /* lookahead token */ static char *keywords[] = { /* keyword table */ "ascending", "by", "char", "compress", "create", "define", "delete", "descending", "exit", "export", "extract", "from", "help", "insert", "import", "into", "num", "print", "quit", "select", "set", "show", "sort", "update", "using", "where", NULL }; static int keytokens[] = { /* token values for each keyword */ ASCENDING, BY, CHAR, COMPRESS, CREATE, DEFINE, DELETE, DESCENDING, EXIT, EXPORT, EXTRACT, FROM, HELP, INSERT, IMPORT, INTO, NUM, PRINT, EXIT, SELECT, SET, SHOW, SORT, UPDATE, USING, WHERE, NULL }; /* db_sinit - initialize the scanner */ db_sinit() { /* at beginning of line */ atbol = TRUE; /* make the command line null */ lptr = NULL; /* no lookahead yet */ savech = EOS; savetkn = NULL; /* no indirect command files */ dbv_ifp = NULL; /* no macros defined */ dbv_macros = NULL; /* fold alpha comparisons */ dbv_fold = TRUE; } /* db_prompt(ip,cp) - initialize prompt strings */ db_prompt(ip,cp) char *ip,*cp; { /* save initial and continuation prompt strings */ iprompt = ip; cprompt = cp; } /* db_scan(fmt,args) - initiate line scan command parsing */ db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) { /* convert the command line and arguments */ sprintf(cmdline,fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10); /* start at the beginning of the command line */ lptr = cmdline; iprompt = NULL; dbv_ifp = NULL; /* no lookahead yet */ savech = EOS; savetkn = NULL; /* fold alpha comparisons */ dbv_fold = TRUE; } /* db_flush - flush the current input line */ int db_flush() { while (savech != '\n') if (savech > ' ') return (db_ferror(SYNTAX)); else savech = getchx(); savech = EOS; atbol = TRUE; return (TRUE); } /* db_gline - get a line from the current input */ char *db_gline(buf) char *buf; { int ch,i; for (i = 0; (ch = getch()) != '\n' && ch != -1; ) if (i < LINEMAX) buf[i++] = ch; else { printf("*** line too long ***\nRetype> "); i = 0; } buf[i] = EOS; return (buf); } /* db_ifile - setup an indirect command file */ int db_ifile(fname) char *fname; { struct ifile *new_ifp; if ((new_ifp = malloc(sizeof(struct ifile))) == NULL) return (db_ferror(INSMEM)); else if ((new_ifp->if_fp = fopen(fname,"r")) == NULL) { free(new_ifp); return (db_ferror(INDFNF)); } new_ifp->if_mtext = NULL; new_ifp->if_savech = savech; new_ifp->if_lptr = lptr; new_ifp->if_next = dbv_ifp; dbv_ifp = new_ifp; /* return successfully */ return (TRUE); } /* db_kill - kill indirect command file input */ db_kill() { struct ifile *old_ifp; while ((old_ifp = dbv_ifp) != NULL) { dbv_ifp = old_ifp->if_next; if (old_ifp->if_fp != NULL) fclose(old_ifp->if_fp); savech = old_ifp->if_savech; lptr = old_ifp->if_lptr; free(old_ifp); } while (savech != '\n') savech = getchx(); savech = EOS; savetkn = NULL; atbol = TRUE; } /* db_token - return the current input token */ int db_token() { struct macro *mptr; struct ifile *new_ifp; /* find a token that's not a macro call */ while (db_xtoken() == ID) { /* check for a macro call */ for (mptr = dbv_macros; mptr != NULL; mptr = mptr->mc_next) if (db_scmp(dbv_tstring,mptr->mc_name) == 0) { if ((new_ifp = malloc(sizeof(struct ifile))) == NULL) printf("*** error expanding macro: %s ***\n",dbv_tstring); else { new_ifp->if_fp = NULL; new_ifp->if_mtext = mptr->mc_mtext->mt_next; new_ifp->if_lptr = lptr; lptr = mptr->mc_mtext->mt_text; new_ifp->if_savech = savech; savech = EOS; new_ifp->if_next = dbv_ifp; dbv_ifp = new_ifp; } savetkn = NULL; break; } if (mptr == NULL) break; } return (dbv_token); } /* db_xtoken - return the current input token */ int db_xtoken() { int ch; /* check for a saved token */ if ((dbv_token = savetkn) != NULL) return (dbv_token); /* get the next non-blank character */ ch = nextch(); /* check type of character */ if (isalpha(ch)) /* identifier or keyword */ get_id(); else if (isdigit(ch)) /* number */ get_number(); else if (ch == '"') /* string */ get_string(); else if (get_rel()) /* relational operator */ ; else /* single character token */ dbv_token = getch(); /* save the lookahead token */ savetkn = dbv_token; /* return the token */ return (dbv_token); } /* db_ntoken - get next token (after skipping the current one) */ int db_ntoken() { /* get the current token */ db_token(); /* make sure another is read on next call */ savetkn = NULL; /* return the current token */ return (dbv_token); } /* db_xntoken - get next token (after skipping the current one) */ int db_xntoken() { /* get the current token */ db_xtoken(); /* make sure another is read on next call */ savetkn = NULL; /* return the current token */ return (dbv_token); } /* db_scmp - compare two strings */ int db_scmp(str1,str2) char *str1,*str2; { if (dbv_fold) return (scmp(str1,str2)); else return (strcmp(str1,str2)); } /* db_sncmp - compare two strings with a maximum length */ int db_sncmp(str1,str2,len) char *str1,*str2; int len; { if (dbv_fold) return (sncmp(str1,str2,len)); else return (strncmp(str1,str2,len)); } /* scmp - compare two strings with alpha case folding */ static int scmp(str1,str2) char *str1,*str2; { int ch1,ch2; /* compare each character */ while (*str1 && *str2) { /* fold the character from the first string */ if (isupper(*str1)) ch1 = tolower(*str1++); else ch1 = *str1++; /* fold the character from the second string */ if (isupper(*str2)) ch2 = tolower(*str2++); else ch2 = *str2++; /* compare the characters */ if (ch1 != ch2) if (ch1 < ch2) return (-1); else return (1); } /* check for strings of different lengths */ if (*str1 == *str2) return (0); else if (*str1 == 0) return (-1); else return (1); } /* sncmp - compare two strings with alpha case folding and a maximum length */ static int sncmp(str1,str2,len) char *str1,*str2; int len; { int ch1,ch2; /* compare each character */ while (*str1 && *str2 && len > 0) { /* fold the character from the first string */ if (isupper(*str1)) ch1 = tolower(*str1++); else ch1 = *str1++; /* fold the character from the second string */ if (isupper(*str2)) ch2 = tolower(*str2++); else ch2 = *str2++; /* compare the characters */ if (ch1 != ch2) if (ch1 < ch2) return (-1); else return (1); /* decrement the string length */ len--; } /* check for strings of different lengths */ if (len == 0 || *str1 == *str2) return (0); else if (*str1 == 0) return (-1); else return (1); } /* get_id - get a keyword or a user identifier */ static get_id() { int ch,nchars,i; /* input letters and digits */ ch = nextch(); nchars = 0; while (isalpha(ch) || isdigit(ch)) { if (nchars < KEYWORDMAX) dbv_tstring[nchars++] = ch; getch(); ch = thisch(); } /* terminate the keyword */ dbv_tstring[nchars] = EOS; /* assume its an identifier */ dbv_token = ID; /* check for keywords */ for (i = 0; keywords[i] != NULL; i++) if (db_scmp(dbv_tstring,keywords[i]) == 0) dbv_token = keytokens[i]; } /* get_number - get a number */ static get_number() { int ch,ndigits,nodot; /* read digits and at most one decimal point */ ch = nextch(); ndigits = 0; nodot = TRUE; while (isdigit(ch) || (nodot && ch == '.')) { if (ch == '.') nodot = FALSE; if (ndigits < NUMBERMAX) dbv_tstring[ndigits++] = ch; getch(); ch = thisch(); } /* terminate the number */ dbv_tstring[ndigits] = EOS; /* get the value of the number */ sscanf(dbv_tstring,"%d",&dbv_tvalue); /* token is a number */ dbv_token = NUMBER; } /* get_string - get a string */ static get_string() { int ch,nchars; /* skip the opening quote */ getch(); /* read characters until a closing quote is found */ ch = thisch(); nchars = 0; while (ch && ch != '"') { if (nchars < STRINGMAX) dbv_tstring[nchars++] = ch; getch(); ch = thisch(); } /* terminate the string */ dbv_tstring[nchars] = EOS; /* skip the closing quote */ getch(); /* token is a string */ dbv_token = STRING; } /* get_rel - get a relational operator */ static int get_rel() { int ch; switch (ch = nextch()) { case '=': getch(); dbv_token = EQL; return (TRUE);; case '<': getch(); ch = nextch(); if (ch == '>') { getch(); dbv_token = NEQ; } else if (ch == '=') { getch(); dbv_token = LEQ; } else dbv_token = LSS; return (TRUE);; case '>': getch(); ch = nextch(); if (ch == '=') { getch(); dbv_token = GEQ; } else dbv_token = GTR; return (TRUE);; default: return (FALSE); } } /* getch - get the next character */ static int getch() { char fname[STRINGMAX+1]; int ch,i; /* return the lookahead character if there is one */ if (savech != EOS) { ch = savech; savech = EOS; return (ch); } /* get a character */ ch = getchx(); /* skip spaces at the beginning of a command */ if (atbol && iprompt != NULL) while (ch <= ' ') ch = getchx(); /* use continuation prompt next time */ iprompt = NULL; /* check for indirect command file */ while (ch == '@') { for (i = 0; (savech = getchx()) > ' '; ) if (i < STRINGMAX) fname[i++] = savech; fname[i] = 0; if (db_ifile(fname) != TRUE) printf("*** error opening command file: %s ***\n",fname); ch = getchx(); } /* return the character */ return (ch); } /* getchx - get the next character */ static int getchx() { struct ifile *old_ifp; int ch; /* check for input from buffer */ if (lptr != NULL) { while (*lptr == EOS) if (dbv_ifp != NULL) if (dbv_ifp->if_mtext == NULL) { old_ifp = dbv_ifp; ch = dbv_ifp->if_savech; savech = EOS; lptr = dbv_ifp->if_lptr; dbv_ifp = dbv_ifp->if_next; free(old_ifp); if (ch != EOS) return (ch); if (lptr == NULL) break; } else { lptr = dbv_ifp->if_mtext->mt_text; dbv_ifp->if_mtext = dbv_ifp->if_mtext->mt_next; } else return (EOS); if (lptr != NULL) return (*lptr++); } /* print prompt if necessary */ if (atbol && dbv_ifp == NULL) { /*dns*/ if (iprompt != NULL) printf("%s",iprompt); else if (cprompt != NULL) printf("%s",cprompt); #ifdef Lattice fflush(stdout); /*dns*/ #endif } /*dns*/ if (dbv_ifp == NULL) if ((ch = getcx(stdin)) == '\n') atbol = TRUE; else atbol = FALSE; else { if ((ch = getcx(dbv_ifp->if_fp)) == -1) { old_ifp = dbv_ifp; ch = dbv_ifp->if_savech; savech = EOS; lptr = dbv_ifp->if_lptr; dbv_ifp = dbv_ifp->if_next; fclose(old_ifp->if_fp); free(old_ifp); } } /* return the character */ return (ch); } /* thisch - get the current character */ static int thisch() { /* get a lookahead character */ if (savech == EOS) savech = getch(); /* return lookahead character */ return (savech); } /* nextch - get the next non-blank character */ static int nextch() { int ch; /* skip blank characters */ while ((ch = thisch()) <= ' ' && ch != EOS) getch(); /* return the first non-blank */ return (ch); } SHAR_EOF cat << \SHAR_EOF > cmd.c /* SDB - command parser */ #include #include "sdbio.h" extern int dbv_token; extern char dbv_tstring[]; extern int dbv_tvalue; extern struct ifile *dbv_ifp; extern struct macro *dbv_macros; extern int dbv_fold; #ifdef Lattice int _fmode = 0; /*dns*/ #endif /* db_parse - parse a command */ int db_parse(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9) char *fmt; { int sts; /* check for a command line */ if (fmt != NULL) db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9); /* determine the statement type */ switch (db_ntoken()) { case ';': sts = TRUE; break; case COMPRESS: sts = db_squeeze(NULL); break; case CREATE: sts = create(); break; case DEFINE: sts = mc_define(); break; case DELETE: sts = delete(); break; case EXIT: exit(); case EXPORT: sts = db_export(NULL); break; case EXTRACT: sts = db_extract(NULL); break; case HELP: sts = help(); break; case IMPORT: sts = db_import(NULL); break; case INSERT: sts = insert(); break; case PRINT: sts = print(); break; case SELECT: sts = select(); break; case SET: sts = set(); break; case SHOW: sts = mc_show(); break; case SORT: sts = db_sort(NULL); break; case UPDATE: sts = update(); break; default: return (db_ferror(SYNTAX)); } return (sts); } /* help - print a short help message */ static int help() { FILE *fp; int ch; if ((fp = fopen("sdb.hlp","r")) != NULL) { /* while ((ch = agetc(fp)) != EOF) dns */ while ((ch = getc(fp)) != EOF) putchar(ch); fclose(fp); } else printf("No online help available. Read the manual\n"); /* return successfully */ return (TRUE); } /* create - create a new relation */ static int create() { struct relation *rptr; char aname[STRINGMAX+1]; int atype; /* get relation name */ if (db_ntoken() != ID) return (db_ferror(SYNTAX)); /* start relation creation */ if ((rptr = db_rcreate(dbv_tstring)) == NULL) return (FALSE); /* check for attribute list */ if (db_ntoken() != '(') { free(rptr); return (db_ferror(SYNTAX)); } /* parse the attributes */ while (TRUE) { /* get the attribute name */ if (db_ntoken() != ID) { free(rptr); return (db_ferror(SYNTAX)); } strcpy(aname,dbv_tstring); /* get the attribute type */ db_ntoken(); if (dbv_token == CHAR) atype = TCHAR; else if (dbv_token == NUM) atype = TNUM; else { free(rptr); return (db_ferror(SYNTAX)); } /* get the attribute size */ if (db_ntoken() != NUMBER) { free(rptr); return (db_ferror(SYNTAX)); } /* add the attribute */ if (!db_rcattr(rptr,aname,atype,dbv_tvalue)) { free(rptr); return (FALSE); } /* check for end of attributes */ if (db_token() != ID) break; } /* check for attribute list end */ if (db_ntoken() != ')') { free(rptr); return (db_ferror(SYNTAX)); } /* check for relation size */ if (db_ntoken() != NUMBER) { free(rptr); return (db_ferror(SYNTAX)); } /* finish relation creation */ if (!db_rcheader(rptr)) return (FALSE); if (!db_rctuples(rptr,dbv_tvalue)) return (FALSE); if (!db_rcdone(rptr)) return (FALSE); /* return successfully */ return (TRUE); } /* insert - insert a tuple into a relation */ static int insert() { struct scan *sptr; struct attribute *aptr; char aname[ANSIZE+1],avalue[STRINGMAX+1]; int tcnt,astart,i; /* get relation name */ if (db_token() == ID) db_ntoken(); else strcpy(dbv_tstring,"sdbcur"); /* make sure that the rest of the line is blank */ if (!db_flush()) return (FALSE); /* open the relation */ if ((sptr = db_ropen(dbv_tstring)) == NULL) return (FALSE); /* insert tuples */ for (tcnt = 0; ; tcnt++) { /* print separator if not the first tuple */ if (tcnt != 0) printf("----\n"); /* get attribute values */ astart = 1; for (i = 0; i < NATTRS; i++) { /* get a pointer to the current attribute */ aptr = &sptr->sc_relation->rl_header.hd_attrs[i]; /* check for the last attribute */ if (aptr->at_name[0] == 0) break; /* get the attribute name */ strncpy(aname,aptr->at_name,ANSIZE); aname[ANSIZE] = 0; /* setup null prompt strings */ db_prompt(NULL,NULL); /* prompt and input attribute value */ while (TRUE) { if (dbv_ifp == NULL) if (strlen(aname) < 8) printf("%s\t\t: ",aname); else printf("%s\t: ",aname); if (db_gline(avalue) != NULL) break; } /* check for last insert */ if (i == 0 && avalue[0] == EOS) break; /* store the attribute value */ db_aput(aptr,&sptr->sc_tuple[astart],avalue); /* update the attribute start */ astart += aptr->at_size; } /* check for last insert */ if (avalue[0] == EOS) break; /* store the new tuple */ if (!db_rstore(sptr)) { db_rclose(sptr); return (FALSE); } } /* close the relation */ db_rclose(sptr); /* check number of tuples inserted */ if (tcnt != 0) { /* print tuple count */ printf("[ %d inserted ]\n",tcnt); } else printf("[ none inserted ]\n"); /* return successfully */ return (TRUE); } /* delete - delete tuples from a relation */ static int delete() { struct sel *slptr; struct srel *srptr; int tcnt; /* parse the retrieval clause */ if ((slptr = db_retrieve(NULL)) == NULL) return (FALSE); /* loop through the retrieved tuples */ for (tcnt = 0; db_fetch(slptr); tcnt++) /* delete the retrieved tuples */ for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next) if (!db_rdelete(srptr->sr_scan)) { db_done(slptr); return (FALSE); } /* finish the retrieval */ db_done(slptr); /* check number of tuples deleted */ if (tcnt != 0) { /* print tuple count */ printf("[ %d deleted ]\n",tcnt); } else printf("[ none deleted ]\n"); /* return successfully */ return (TRUE); } /* update - update tuples from a relation */ static int update() { struct sel *slptr; struct sattr *saptr; struct attribute *aptr; char aname[ANSIZE+1],avalue[STRINGMAX+1],*ap; int tcnt; /* parse the selection clause */ if ((slptr = db_select(NULL)) == NULL) return (FALSE); /* make sure that the rest of the line is blank */ if (!db_flush()) { db_done(slptr); return (FALSE); } /* loop through the selected tuples */ for (tcnt = 0; db_fetch(slptr); tcnt++) { /* print separator if not the first tuple */ if (tcnt != 0) printf("----\n"); /* loop through the selected attributes */ for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) { /* get the attribute pointer */ aptr = saptr->sa_attr; /* get the attribute name */ strncpy(aname,aptr->at_name,ANSIZE); aname[ANSIZE] = 0; /* get the attribute value */ db_aget(aptr,saptr->sa_aptr,avalue); for (ap = avalue; isspace(*ap); ap++) ; /* print it */ if (strlen(aname) < 8) printf("%s\t\t: %s\n",aname,ap); else printf("%s\t: %s\n",aname,ap); /* setup null prompt strings */ db_prompt(NULL,NULL); /* prompt and input attribute value */ while (TRUE) { if (strlen(aname) < 8) printf("%s\t\t: ",aname); else printf("%s\t: ",aname); if (db_gline(avalue) != NULL) break; } /* store the attribute value */ if (avalue[0] != EOS) { db_aput(aptr,saptr->sa_aptr,avalue); saptr->sa_srel->sr_update = TRUE; } } /* update the tuples */ db_update(slptr); } /* finish the selection */ db_done(slptr); /* check number of tuples updated */ if (tcnt != 0) { /* print tuple count */ printf("[ %d updated ]\n",tcnt); } else printf("[ none updated ]\n"); /* return successfully */ return (TRUE); } /* print - print tuples from a set of relations */ static int print() { struct sel *slptr; FILE *ffp,*ofp; int tcnt; /* parse the using clause */ if (!using(&ffp,".frm")) return (FALSE); /* parse the select clause */ if ((slptr = db_select(NULL)) == NULL) return (FALSE); /* parse the into clause */ if (!db_to(&ofp,".txt")) { db_done(slptr); return (FALSE); } /* check for normal or formated output */ if (ffp == NULL) tcnt = table(ofp,slptr); else tcnt = form(ofp,slptr,ffp); /* finish the selection */ db_done(slptr); /* close the form definition file */ if (ffp != NULL) fclose(ffp); /* close the output file */ if (ofp != stdout) fclose(ofp); /* check number of tuples selected */ if (tcnt != 0) printf("[ %d found ]\n",tcnt); else printf("[ none found ]\n"); /* return successfully */ return (TRUE); } /* select - select tuples from a set of relations */ static int select() { struct sel *slptr; struct relation *rptr; struct sattr *saptr; char *aname,*tbuf; int tcnt,abase,i; /* parse the select clause */ if ((slptr = db_select(NULL)) == NULL) return (FALSE); /* create a new relation */ if ((rptr = db_rcreate("sdbcur")) == NULL) { db_done(slptr); return (FALSE); } /* create the selected attributes */ for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) { /* decide which attribute name to use */ if ((aname = saptr->sa_name) == NULL) aname = saptr->sa_aname; /* add the attribute */ if (!db_rcattr(rptr,aname,saptr->sa_attr->at_type, saptr->sa_attr->at_size)) { free(rptr); db_done(slptr); return (FALSE); } } /* create the relation header */ if (!db_rcheader(rptr)) { db_done(slptr); return (FALSE); } /* allocate and initialize a tuple buffer */ if ((tbuf = calloc(1,rptr->rl_size)) == NULL) { db_rcdone(rptr); return (db_ferror(INSMEM)); } tbuf[0] = ACTIVE; /* loop through the selected tuples */ for (tcnt = 0; db_fetch(slptr); tcnt++) { /* create the tuple from the selected attributes */ abase = 1; for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) { for (i = 0; i < saptr->sa_attr->at_size; i++) tbuf[abase + i] = saptr->sa_aptr[i]; abase += i; } /* write the tuple */ if (write(rptr->rl_fd,tbuf,rptr->rl_size) != rptr->rl_size) { db_rcdone(rptr); free(tbuf); return (db_ferror(INSBLK)); } rptr->rl_tcnt++; rptr->rl_tmax++; } /* finish the selection */ db_done(slptr); /* finish relation creation */ if (!db_rcdone(rptr)) return (FALSE); /* check number of tuples selected */ if (tcnt != 0) printf("[ %d found ]\n",tcnt); else printf("[ none found ]\n"); /* return successfully */ return (TRUE); } /* mc_define - define a macro */ static int mc_define() { struct macro *mptr,*mlast; struct mtext *tptr,*tlast; char textline[LINEMAX+1]; /* get macro name */ if (db_xntoken() != ID) return (db_ferror(SYNTAX)); /* make sure that the rest of the line is blank */ if (!db_flush()) return (FALSE); /* find the macro in the macro table and free it */ for (mptr = dbv_macros, mlast = NULL; mptr != NULL; mlast = mptr, mptr = mptr->mc_next) if (db_scmp(mptr->mc_name,dbv_tstring) == 0) { if (mlast == NULL) dbv_macros = mptr->mc_next; else mlast->mc_next = mptr->mc_next; mc_free(mptr); } /* allocate and initialize a macro structure */ if ((mptr = malloc(sizeof(struct macro))) == NULL) return (db_ferror(INSMEM)); if ((mptr->mc_name = malloc(strlen(dbv_tstring)+1)) == NULL) { free(mptr); return (db_ferror(INSMEM)); } strcpy(mptr->mc_name,dbv_tstring); mptr->mc_mtext = NULL; /* setup null prompt strings */ db_prompt(NULL,"SDB-DEF> "); /* get definition text */ for (tlast = NULL; ; tlast = tptr) { /* get a line */ db_gline(textline); if (textline[0] == EOS || textline[0] == '\n') break; /* allocate a macro text structure */ if ((tptr = malloc(sizeof(struct mtext))) == NULL) { mc_free(mptr); return (db_ferror(INSMEM)); } if ((tptr->mt_text = malloc(strlen(textline)+1)) == NULL) { mc_free(mptr); return (db_ferror(INSMEM)); } strcpy(tptr->mt_text,textline); tptr->mt_next = NULL; /* link it into the macro list */ if (tlast == NULL) mptr->mc_mtext = tptr; else tlast->mt_next = tptr; } /* link the new macro into the macro list */ if (tlast == NULL) mc_free(mptr); else { mptr->mc_next = dbv_macros; dbv_macros = mptr; } /* return successfully */ return (TRUE); } /* mc_show - show a macro */ static int mc_show() { struct macro *mptr; struct mtext *tptr; /* get macro name */ if (db_xntoken() != ID) return (db_ferror(SYNTAX)); /* find the macro in the macro table */ for (mptr = dbv_macros; mptr != NULL; mptr = mptr->mc_next) if (db_scmp(mptr->mc_name,dbv_tstring) == 0) { for (tptr = mptr->mc_mtext; tptr != NULL; tptr = tptr->mt_next) printf("\t%s\n",tptr->mt_text); break; } /* check for successful search */ if (mptr == NULL) printf("*** no macro named: %s ***\n",dbv_tstring); /* return successfully */ return (TRUE); } /* mc_free - free a macro definition */ static mc_free(mptr) struct macro *mptr; { struct mtext *tptr; while ((tptr = mptr->mc_mtext) != NULL) { mptr->mc_mtext = tptr->mt_next; free(tptr->mt_text); free(tptr); } free(mptr->mc_name); free(mptr); } /* db_to - redirect output into a file */ int db_to(pfp,ext) FILE **pfp; char *ext; { #ifdef vms int fd; #endif /* assume no into clause */ *pfp = stdout; /* check for "into " */ if (db_token() != INTO) return (TRUE); db_ntoken(); if (db_ntoken() == ID) strcat(dbv_tstring,ext); else if (dbv_token != STRING) return (db_ferror(SYNTAX)); /* open the output file */ #ifdef vms if ((fd = creat(dbv_tstring,0,"rfm=var","rat=cr")) == -1) return (db_ferror(OUTCRE)); *pfp = fdopen(fd,"w"); #else #ifdef Lattice _fmode = 0x8000; /*dns*/ #endif *pfp = fopen(dbv_tstring,"w"); /*dns*/ #ifdef Lattice _fmode = 0; /*dns*/ #endif if (*pfp == NULL) /*dns*/ return (db_ferror(OUTCRE)); /*dns*/ #endif /* return successfully */ return (TRUE); } /* using - get form definition file spec */ static int using(pfp,ext) FILE **pfp; char *ext; { /* assume no using clause */ *pfp = NULL; /* check for "using " */ if (db_token() != USING) return (TRUE); db_ntoken(); if (db_ntoken() == ID) strcat(dbv_tstring,ext); else if (dbv_token != STRING) return (db_ferror(SYNTAX)); /* open the input file */ if ((*pfp = fopen(dbv_tstring,"r")) == NULL) return (db_ferror(INPFNF)); /* return successfully */ return (TRUE); } /* table - output a relation table */ static int table(fp,slptr) FILE *fp; struct sel *slptr; { int tcnt; /* loop through the selected tuples */ for (tcnt = 0; db_fetch(slptr); tcnt++) { /* print table head on first tuple selected */ if (tcnt == 0) db_thead(fp,slptr); /* print the tuple */ db_tentry(fp,slptr); } /* print table foot */ if (tcnt != 0) db_tfoot(fp,slptr); /* return the tuple count */ return (tcnt); } /* form - process a form */ static int form(ofp,slptr,ffp) FILE *ofp; struct sel *slptr; FILE *ffp; { char aname[ANSIZE+1]; int ch,tcnt,pad; /* loop through the selected tuples */ for (tcnt = 0; db_fetch(slptr); tcnt++) { /* reposition the form definition file */ fseek(ffp,0L,0); /* process the form */ while ((ch = getc(ffp)) != -1) if (ch == '<') { get_aname(ffp,aname,&pad); put_avalue(ofp,slptr,aname,pad); } else putc(ch,ofp); } /* return the tuple count */ return (tcnt); } /* get_aname - get an attribute name (and padding flag [mpk]) */ static get_aname(fp,aname,pad) FILE *fp; char *aname; int *pad; { int ch; if ((ch = getc(fp)) != '$') { /* mpk */ ungetc(ch,fp); /* put it back! */ *pad = 1; } else *pad = 0; while ((ch = getc(fp)) != '>') if (!isspace(ch)) *aname++ = ch; *aname = 0; } /* put_avalue - output attribute value */ static put_avalue(fp,slptr,aname,pad) FILE *fp; struct sel *slptr; char *aname; int pad; { struct sattr *saptr; char *saname; int i; /* loop through the selected attributes */ for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) { /* check the selected attribute name */ if ((saname = saptr->sa_name) == NULL) saname = saptr->sa_aname; if (db_scmp(saname,aname) == 0) break; } if (saptr == NULL) { fprintf(fp,""); return; } /* get the attribute value */ for (i = 0; i < saptr->sa_attr->at_size; i++) if (saptr->sa_aptr[i] != 0) putc(saptr->sa_aptr[i],fp); else if (pad) /* MPK 25-Mar-1986 */ putc(' ',fp); } /* set - set internal parameters */ static int set() { int value; /* process each set request */ while (db_token() == ID) { /* skip the identifier */ db_ntoken(); /* check for "no" */ if (db_scmp(dbv_tstring,"no") == 0) { value = FALSE; if (db_token() != ID) return (db_ferror(BADSET)); db_ntoken(); } else value = TRUE; /* check for parameter to set */ if (db_scmp(dbv_tstring,"fold") == 0) dbv_fold = value; else return (db_ferror(BADSET)); } /* return successfully */ return (TRUE); } SHAR_EOF # End of shell archive exit 0