a small dbms - part 2
Ozan Yigit
oz at yetti.UUCP
Tue Aug 27 05:44:42 AEST 1985
This is the last part of the dbms: all the source files.
This stuff compiles under 4.2 BSD and VENIX (vers. 7) just
fine.
Oz
------------ SNIP SNIP SNIP -------------------------------
#!/bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #!/bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# cmd.c
# com.c
# cre.c
# err.c
# iex.c
# int.c
# io.c
# mth.c
# pcjunk.c
# scn.c
# sdb.c
# sel.c
# srt.c
# tbl.c
# sdbio.h
# This archive created: Mon Aug 26 15:39:01 1985
export PATH; PATH=/bin:$PATH
echo shar: extracting "'cmd.c'" '(20167 characters)'
if test -f 'cmd.c'
then
echo shar: over-writing existing file "'cmd.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'cmd.c'
X/* SDB - command parser */
X
X#include "stdio.h"
X#include "sdbio.h"
X
Xextern int dbv_token;
Xextern char dbv_tstring[];
Xextern int dbv_tvalue;
Xextern struct ifile *dbv_ifp;
Xextern struct macro *dbv_macros;
Xextern int dbv_fold;
X
X#ifdef Lattice
Xint _fmode = 0; /*dns*/
X#endif
X
X/* db_parse - parse a command */
Xint db_parse(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
X char *fmt;
X{
X int sts;
X
X /* check for a command line */
X if (fmt != NULL)
X db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);
X
X /* determine the statement type */
X switch (db_ntoken()) {
X case ';': sts = TRUE;
X break;
X case COMPRESS:
X sts = db_squeeze(NULL);
X break;
X case CREATE:
X sts = create();
X break;
X case DEFINE:
X sts = mc_define();
X break;
X case DELETE:
X sts = delete();
X break;
X case EXIT:
X exit();
X case EXPORT:
X sts = db_export(NULL);
X break;
X case EXTRACT:
X sts = db_extract(NULL);
X break;
X case HELP:
X sts = help();
X break;
X case IMPORT:
X sts = db_import(NULL);
X break;
X case INSERT:
X sts = insert();
X break;
X case PRINT:
X sts = print();
X break;
X case SELECT:
X sts = select();
X break;
X case SET:
X sts = set();
X break;
X case SHOW:
X sts = mc_show();
X break;
X case SORT:
X sts = db_sort(NULL);
X break;
X case UPDATE:
X sts = update();
X break;
X default:
X return (db_ferror(SYNTAX));
X }
X
X return (sts);
X}
X
X/* help - print a short help message */
Xstatic int help()
X{
X FILE *fp;
X int ch;
X
X if ((fp = fopen("sdb.hlp","r")) != NULL) {
X /* while ((ch = agetc(fp)) != EOF) dns */
X while ((ch = getc(fp)) != EOF)
X putchar(ch);
X fclose(fp);
X }
X else
X printf("No online help available. Read the manual\n");
X
X /* return successfully */
X return (TRUE);
X}
X
X/* create - create a new relation */
Xstatic int create()
X{
X struct relation *rptr;
X char aname[STRINGMAX+1];
X int atype;
X
X /* get relation name */
X if (db_ntoken() != ID)
X return (db_ferror(SYNTAX));
X
X /* start relation creation */
X if ((rptr = db_rcreate(dbv_tstring)) == NULL)
X return (FALSE);
X
X /* check for attribute list */
X if (db_ntoken() != '(') {
X free(rptr);
X return (db_ferror(SYNTAX));
X }
X
X /* parse the attributes */
X while (TRUE) {
X
X /* get the attribute name */
X if (db_ntoken() != ID) {
X free(rptr);
X return (db_ferror(SYNTAX));
X }
X strcpy(aname,dbv_tstring);
X
X /* get the attribute type */
X db_ntoken();
X if (dbv_token == CHAR)
X atype = TCHAR;
X else if (dbv_token == NUM)
X atype = TNUM;
X else {
X free(rptr);
X return (db_ferror(SYNTAX));
X }
X
X /* get the attribute size */
X if (db_ntoken() != NUMBER) {
X free(rptr);
X return (db_ferror(SYNTAX));
X }
X
X /* add the attribute */
X if (!db_rcattr(rptr,aname,atype,dbv_tvalue)) {
X free(rptr);
X return (FALSE);
X }
X
X /* check for end of attributes */
X if (db_token() != ID)
X break;
X }
X
X /* check for attribute list end */
X if (db_ntoken() != ')') {
X free(rptr);
X return (db_ferror(SYNTAX));
X }
X
X /* check for relation size */
X if (db_ntoken() != NUMBER) {
X free(rptr);
X return (db_ferror(SYNTAX));
X }
X
X /* finish relation creation */
X if (!db_rcheader(rptr))
X return (FALSE);
X if (!db_rctuples(rptr,dbv_tvalue))
X return (FALSE);
X if (!db_rcdone(rptr))
X return (FALSE);
X
X /* return successfully */
X return (TRUE);
X}
X
X/* insert - insert a tuple into a relation */
Xstatic int insert()
X{
X struct scan *sptr;
X struct attribute *aptr;
X char aname[ANSIZE+1],avalue[STRINGMAX+1];
X int tcnt,astart,i;
X
X /* get relation name */
X if (db_token() == ID)
X db_ntoken();
X else
X strcpy(dbv_tstring,"sdbcur");
X
X /* make sure that the rest of the line is blank */
X if (!db_flush())
X return (FALSE);
X
X /* open the relation */
X if ((sptr = db_ropen(dbv_tstring)) == NULL)
X return (FALSE);
X
X /* insert tuples */
X for (tcnt = 0; ; tcnt++) {
X
X /* print separator if not the first tuple */
X if (tcnt != 0)
X printf("----\n");
X
X /* get attribute values */
X astart = 1;
X for (i = 0; i < NATTRS; i++) {
X
X /* get a pointer to the current attribute */
X aptr = &sptr->sc_relation->rl_header.hd_attrs[i];
X
X /* check for the last attribute */
X if (aptr->at_name[0] == 0)
X break;
X
X /* get the attribute name */
X strncpy(aname,aptr->at_name,ANSIZE); aname[ANSIZE] = 0;
X
X /* setup null prompt strings */
X db_prompt(NULL,NULL);
X
X /* prompt and input attribute value */
X while (TRUE) {
X if (dbv_ifp == NULL)
X if (strlen(aname) < 8)
X printf("%s\t\t: ",aname);
X else
X printf("%s\t: ",aname);
X if (db_gline(avalue) != NULL)
X break;
X }
X
X /* check for last insert */
X if (i == 0 && avalue[0] == EOS)
X break;
X
X /* store the attribute value */
X db_aput(aptr,&sptr->sc_tuple[astart],avalue);
X
X /* update the attribute start */
X astart += aptr->at_size;
X }
X
X /* check for last insert */
X if (avalue[0] == EOS)
X break;
X
X /* store the new tuple */
X if (!db_rstore(sptr)) {
X db_rclose(sptr);
X return (FALSE);
X }
X }
X
X /* close the relation */
X db_rclose(sptr);
X
X /* check number of tuples inserted */
X if (tcnt != 0) {
X
X /* print tuple count */
X printf("[ %d inserted ]\n",tcnt);
X }
X else
X printf("[ none inserted ]\n");
X
X /* return successfully */
X return (TRUE);
X}
X
X/* delete - delete tuples from a relation */
Xstatic int delete()
X{
X struct sel *slptr;
X struct srel *srptr;
X int tcnt;
X
X /* parse the retrieval clause */
X if ((slptr = db_retrieve(NULL)) == NULL)
X return (FALSE);
X
X /* loop through the retrieved tuples */
X for (tcnt = 0; db_fetch(slptr); tcnt++)
X
X /* delete the retrieved tuples */
X for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next)
X if (!db_rdelete(srptr->sr_scan)) {
X db_done(slptr);
X return (FALSE);
X }
X
X /* finish the retrieval */
X db_done(slptr);
X
X /* check number of tuples deleted */
X if (tcnt != 0) {
X
X /* print tuple count */
X printf("[ %d deleted ]\n",tcnt);
X }
X else
X printf("[ none deleted ]\n");
X
X /* return successfully */
X return (TRUE);
X}
X
X/* update - update tuples from a relation */
Xstatic int update()
X{
X struct sel *slptr;
X struct sattr *saptr;
X struct attribute *aptr;
X char aname[ANSIZE+1],avalue[STRINGMAX+1],*ap;
X int tcnt;
X
X /* parse the selection clause */
X if ((slptr = db_select(NULL)) == NULL)
X return (FALSE);
X
X /* make sure that the rest of the line is blank */
X if (!db_flush()) {
X db_done(slptr);
X return (FALSE);
X }
X
X /* loop through the selected tuples */
X for (tcnt = 0; db_fetch(slptr); tcnt++) {
X
X /* print separator if not the first tuple */
X if (tcnt != 0)
X printf("----\n");
X
X /* loop through the selected attributes */
X for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {
X
X /* get the attribute pointer */
X aptr = saptr->sa_attr;
X
X /* get the attribute name */
X strncpy(aname,aptr->at_name,ANSIZE); aname[ANSIZE] = 0;
X
X /* get the attribute value */
X db_aget(aptr,saptr->sa_aptr,avalue);
X for (ap = avalue; isspace(*ap); ap++)
X ;
X
X /* print it */
X if (strlen(aname) < 8)
X printf("%s\t\t: %s\n",aname,ap);
X else
X printf("%s\t: %s\n",aname,ap);
X
X /* setup null prompt strings */
X db_prompt(NULL,NULL);
X
X /* prompt and input attribute value */
X while (TRUE) {
X if (strlen(aname) < 8)
X printf("%s\t\t: ",aname);
X else
X printf("%s\t: ",aname);
X if (db_gline(avalue) != NULL)
X break;
X }
X
X /* store the attribute value */
X if (avalue[0] != EOS) {
X db_aput(aptr,saptr->sa_aptr,avalue);
X saptr->sa_srel->sr_update = TRUE;
X }
X }
X
X /* update the tuples */
X db_update(slptr);
X }
X
X /* finish the selection */
X db_done(slptr);
X
X /* check number of tuples updated */
X if (tcnt != 0) {
X
X /* print tuple count */
X printf("[ %d updated ]\n",tcnt);
X }
X else
X printf("[ none updated ]\n");
X
X /* return successfully */
X return (TRUE);
X}
X
X/* print - print tuples from a set of relations */
Xstatic int print()
X{
X struct sel *slptr;
X FILE *ffp,*ofp;
X int tcnt;
X
X /* parse the using clause */
X if (!using(&ffp,".frm"))
X return (FALSE);
X
X /* parse the select clause */
X if ((slptr = db_select(NULL)) == NULL)
X return (FALSE);
X
X /* parse the into clause */
X if (!db_to(&ofp,".txt")) {
X db_done(slptr);
X return (FALSE);
X }
X
X /* check for normal or formated output */
X if (ffp == NULL)
X tcnt = table(ofp,slptr);
X else
X tcnt = form(ofp,slptr,ffp);
X
X /* finish the selection */
X db_done(slptr);
X
X /* close the form definition file */
X if (ffp != NULL)
X fclose(ffp);
X
X /* close the output file */
X if (ofp != stdout)
X fclose(ofp);
X
X /* check number of tuples selected */
X if (tcnt != 0)
X printf("[ %d found ]\n",tcnt);
X else
X printf("[ none found ]\n");
X
X /* return successfully */
X return (TRUE);
X}
X
X/* select - select tuples from a set of relations */
Xstatic int select()
X{
X struct sel *slptr;
X struct relation *rptr;
X struct sattr *saptr;
X char *aname,*tbuf;
X int tcnt,abase,i;
X
X /* parse the select clause */
X if ((slptr = db_select(NULL)) == NULL)
X return (FALSE);
X
X /* create a new relation */
X if ((rptr = db_rcreate("sdbcur")) == NULL) {
X db_done(slptr);
X return (FALSE);
X }
X
X /* create the selected attributes */
X for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {
X
X /* decide which attribute name to use */
X if ((aname = saptr->sa_name) == NULL)
X aname = saptr->sa_aname;
X
X /* add the attribute */
X if (!db_rcattr(rptr,aname,saptr->sa_attr->at_type,
X saptr->sa_attr->at_size)) {
X free(rptr);
X db_done(slptr);
X return (FALSE);
X }
X }
X
X /* create the relation header */
X if (!db_rcheader(rptr)) {
X db_done(slptr);
X return (FALSE);
X }
X
X /* allocate and initialize a tuple buffer */
X if ((tbuf = calloc(1,rptr->rl_size)) == NULL) {
X db_rcdone(rptr);
X return (db_ferror(INSMEM));
X }
X tbuf[0] = ACTIVE;
X
X /* loop through the selected tuples */
X for (tcnt = 0; db_fetch(slptr); tcnt++) {
X
X /* create the tuple from the selected attributes */
X abase = 1;
X for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {
X for (i = 0; i < saptr->sa_attr->at_size; i++)
X tbuf[abase + i] = saptr->sa_aptr[i];
X abase += i;
X }
X
X /* write the tuple */
X if (write(rptr->rl_fd,tbuf,rptr->rl_size) != rptr->rl_size) {
X db_rcdone(rptr);
X free(tbuf);
X return (db_ferror(INSBLK));
X }
X rptr->rl_tcnt++;
X rptr->rl_tmax++;
X }
X
X /* finish the selection */
X db_done(slptr);
X
X /* finish relation creation */
X if (!db_rcdone(rptr))
X return (FALSE);
X
X /* check number of tuples selected */
X if (tcnt != 0)
X printf("[ %d found ]\n",tcnt);
X else
X printf("[ none found ]\n");
X
X /* return successfully */
X return (TRUE);
X}
X
X/* mc_define - define a macro */
Xstatic int mc_define()
X{
X struct macro *mptr,*mlast;
X struct mtext *tptr,*tlast;
X char textline[LINEMAX+1];
X
X /* get macro name */
X if (db_xntoken() != ID)
X return (db_ferror(SYNTAX));
X
X /* make sure that the rest of the line is blank */
X if (!db_flush())
X return (FALSE);
X
X /* find the macro in the macro table and free it */
X for (mptr = dbv_macros, mlast = NULL; mptr != NULL; mlast = mptr, mptr = mptr->mc_next)
X if (db_scmp(mptr->mc_name,dbv_tstring) == 0) {
X if (mlast == NULL)
X dbv_macros = mptr->mc_next;
X else
X mlast->mc_next = mptr->mc_next;
X mc_free(mptr);
X }
X
X /* allocate and initialize a macro structure */
X if ((mptr = malloc(sizeof(struct macro))) == NULL)
X return (db_ferror(INSMEM));
X if ((mptr->mc_name = malloc(strlen(dbv_tstring)+1)) == NULL) {
X free(mptr);
X return (db_ferror(INSMEM));
X }
X strcpy(mptr->mc_name,dbv_tstring);
X mptr->mc_mtext = NULL;
X
X /* setup null prompt strings */
X db_prompt(NULL,"SDB-DEF> ");
X
X /* get definition text */
X for (tlast = NULL; ; tlast = tptr) {
X
X /* get a line */
X db_gline(textline);
X if (textline[0] == EOS || textline[0] == '\n')
X break;
X
X /* allocate a macro text structure */
X if ((tptr = malloc(sizeof(struct mtext))) == NULL) {
X mc_free(mptr);
X return (db_ferror(INSMEM));
X }
X if ((tptr->mt_text = malloc(strlen(textline)+1)) == NULL) {
X mc_free(mptr);
X return (db_ferror(INSMEM));
X }
X strcpy(tptr->mt_text,textline);
X tptr->mt_next = NULL;
X
X /* link it into the macro list */
X if (tlast == NULL)
X mptr->mc_mtext = tptr;
X else
X tlast->mt_next = tptr;
X }
X
X /* link the new macro into the macro list */
X if (tlast == NULL)
X mc_free(mptr);
X else {
X mptr->mc_next = dbv_macros;
X dbv_macros = mptr;
X }
X
X /* return successfully */
X return (TRUE);
X}
X
X/* mc_show - show a macro */
Xstatic int mc_show()
X{
X struct macro *mptr;
X struct mtext *tptr;
X
X /* get macro name */
X if (db_xntoken() != ID)
X return (db_ferror(SYNTAX));
X
X /* find the macro in the macro table */
X for (mptr = dbv_macros; mptr != NULL; mptr = mptr->mc_next)
X if (db_scmp(mptr->mc_name,dbv_tstring) == 0) {
X for (tptr = mptr->mc_mtext; tptr != NULL; tptr = tptr->mt_next)
X printf("\t%s\n",tptr->mt_text);
X break;
X }
X
X /* check for successful search */
X if (mptr == NULL)
X printf("*** no macro named: %s ***\n",dbv_tstring);
X
X /* return successfully */
X return (TRUE);
X}
X
X/* mc_free - free a macro definition */
Xstatic mc_free(mptr)
X struct macro *mptr;
X{
X struct mtext *tptr;
X
X while ((tptr = mptr->mc_mtext) != NULL) {
X mptr->mc_mtext = tptr->mt_next;
X free(tptr->mt_text);
X free(tptr);
X }
X free(mptr->mc_name);
X free(mptr);
X}
X
X/* db_to - redirect output into a file */
Xint db_to(pfp,ext)
X FILE **pfp; char *ext;
X{
X#ifdef vms
X int fd;
X#endif
X
X /* assume no into clause */
X *pfp = stdout;
X
X /* check for "into <fname>" */
X if (db_token() != INTO)
X return (TRUE);
X db_ntoken();
X if (db_ntoken() == ID)
X strcat(dbv_tstring,ext);
X else if (dbv_token != STRING)
X return (db_ferror(SYNTAX));
X
X /* open the output file */
X#ifdef vms
X if ((fd = creat(dbv_tstring,0,"rfm=var","rat=cr")) == -1)
X return (db_ferror(OUTCRE));
X *pfp = fdopen(fd,"w");
X#else
X#ifdef Lattice
X _fmode = 0x8000; /*dns*/
X#endif
X *pfp = fopen(dbv_tstring,"w"); /*dns*/
X#ifdef Lattice
X _fmode = 0; /*dns*/
X#endif
X if (*pfp == NULL) /*dns*/
X return (db_ferror(OUTCRE)); /*dns*/
X#endif
X
X /* return successfully */
X return (TRUE);
X}
X
X/* using - get form definition file spec */
Xstatic int using(pfp,ext)
X FILE **pfp; char *ext;
X{
X /* assume no using clause */
X *pfp = NULL;
X
X /* check for "using <fname>" */
X if (db_token() != USING)
X return (TRUE);
X db_ntoken();
X if (db_ntoken() == ID)
X strcat(dbv_tstring,ext);
X else if (dbv_token != STRING)
X return (db_ferror(SYNTAX));
X
X /* open the input file */
X if ((*pfp = fopen(dbv_tstring,"r")) == NULL)
X return (db_ferror(INPFNF));
X
X /* return successfully */
X return (TRUE);
X}
X
X/* table - output a relation table */
Xstatic int table(fp,slptr)
X FILE *fp; struct sel *slptr;
X{
X int tcnt;
X
X /* loop through the selected tuples */
X for (tcnt = 0; db_fetch(slptr); tcnt++) {
X
X /* print table head on first tuple selected */
X if (tcnt == 0)
X db_thead(fp,slptr);
X
X /* print the tuple */
X db_tentry(fp,slptr);
X }
X
X /* print table foot */
X if (tcnt != 0)
X db_tfoot(fp,slptr);
X
X /* return the tuple count */
X return (tcnt);
X}
X
X/* form - process a form */
Xstatic int form(ofp,slptr,ffp)
X FILE *ofp; struct sel *slptr; FILE *ffp;
X{
X char aname[ANSIZE+1];
X int ch,tcnt;
X
X /* loop through the selected tuples */
X for (tcnt = 0; db_fetch(slptr); tcnt++) {
X
X /* reposition the form definition file */
X fseek(ffp,0L,0);
X
X /* process the form */
X while ((ch = getc(ffp)) != -1)
X if (ch == '<') {
X get_aname(ffp,aname);
X put_avalue(ofp,slptr,aname);
X }
X else
X putc(ch,ofp);
X }
X
X /* return the tuple count */
X return (tcnt);
X}
X
X/* get_aname - get an attribute name */
Xstatic get_aname(fp,aname)
X FILE *fp; char *aname;
X{
X int ch;
X
X while ((ch = getc(fp)) != '>')
X if (!isspace(ch))
X *aname++ = ch;
X *aname = 0;
X}
X
X/* put_avalue - output attribute value */
Xstatic put_avalue(fp,slptr,aname)
X FILE *fp; struct sel *slptr; char *aname;
X{
X struct sattr *saptr;
X char *saname;
X int i;
X
X /* loop through the selected attributes */
X for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {
X
X /* check the selected attribute name */
X if ((saname = saptr->sa_name) == NULL)
X saname = saptr->sa_aname;
X if (db_scmp(saname,aname) == 0)
X break;
X }
X
X if (saptr == NULL) {
X fprintf(fp,"<error>");
X return;
X }
X
X /* get the attribute value */
X for (i = 0; i < saptr->sa_attr->at_size; i++)
X if (saptr->sa_aptr[i] != 0)
X putc(saptr->sa_aptr[i],fp);
X else
X putc(' ',fp);
X}
X
X/* set - set internal parameters */
Xstatic int set()
X{
X int value;
X
X /* process each set request */
X while (db_token() == ID) {
X
X /* skip the identifier */
X db_ntoken();
X
X /* check for "no" */
X if (db_scmp(dbv_tstring,"no") == 0) {
X value = FALSE;
X if (db_token() != ID)
X return (db_ferror(BADSET));
X db_ntoken();
X }
X else
X value = TRUE;
X
X /* check for parameter to set */
X if (db_scmp(dbv_tstring,"fold") == 0)
X dbv_fold = value;
X else
X return (db_ferror(BADSET));
X }
X
X /* return successfully */
X return (TRUE);
X}
X
SHAR_EOF
if test 20167 -ne "`wc -c 'cmd.c'`"
then
echo shar: error transmitting "'cmd.c'" '(should have been 20167 characters)'
fi
echo shar: extracting "'com.c'" '(9887 characters)'
if test -f 'com.c'
then
echo shar: over-writing existing file "'com.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'com.c'
X/* SDB - expression compiler
X syntax:
X <expr> ::= <lor> <EOS>
X <lor> ::= <land> { '|' <land> }
X <land> ::= <relat> { '&' <relat> }
X <relat> ::= <primary> { <relop> <primary> }
X <primary> ::= <factor> | <unop> <unary>
X <factor> ::= <number> | <string> | '(' <query> ')'
X <number> ::= <digit> | <number> <digit>
X <string> ::= '"' <chars> '"'
X <chars> ::= nil | <chars> <character>
X <relop> ::= '=' | '<>' | '<' | '>' | '<=' | '>='
X <unop> ::= '+' | '-' | '~'
X*/
X
X#include "sdbio.h"
X
Xextern int dbv_token;
Xextern char dbv_tstring[];
Xextern int dbv_tvalue;
X
Xextern int db_xand();
Xextern int db_xor();
Xextern int db_xnot();
Xextern int db_xlss();
Xextern int db_xleq();
Xextern int db_xeql();
Xextern int db_xgeq();
Xextern int db_xgtr();
Xextern int db_xneq();
Xextern int db_xpush();
Xextern int db_xstop();
X
Xstatic union codecell code[CODEMAX+1];
Xstatic int cndx;
Xstatic struct sel *selptr;
X
X/* compile - compile a boolean expression */
Xint db_compile(slptr)
X struct sel *slptr;
X{
X int result,i;
X union codecell *cptr;
X#ifdef Lattice
X int (*dns)(); /*dns*/
X#endif
X
X /* save the selection structure pointer */
X selptr = slptr;
X
X /* initialize the code array index */
X cndx = 0;
X
X /* parse the boolean expression */
X if (!expr(&result)) {
X code[cndx++].c_operator = db_xstop;
X freelit(code);
X return (FALSE);
X }
X
X /* terminate the code */
X code[cndx++].c_operator = db_xstop;
X
X /* allocate space for the code array */
X if ((cptr = malloc(sizeof(union codecell) * cndx)) == NULL) {
X freelit(code);
X return (FALSE);
X }
X
X /* store the code into the code array */
X slptr->sl_where = cptr;
X for (i = 0; i < cndx; i++) {
X (*cptr++).c_operator = code[i].c_operator;
X#ifndef Lattice
X if (code[i].c_operator == db_xpush)
X#else
X if ( code[i].c_operator == (dns=db_xpush) ) /*dns*/
X#endif
X (*cptr++).c_operand = code[++i].c_operand;
X }
X
X /* return successfully */
X return (TRUE);
X}
X
X/* db_fcode - free a code array */
Xdb_fcode(slptr)
X struct sel *slptr;
X{
X /* make sure there is a where clause */
X if (slptr->sl_where == NULL)
X return;
X
X /* free the literals */
X freelit(slptr->sl_where);
X
X /* free the code array */
X free(slptr->sl_where);
X}
X
X/* operator - insert an operator into the code array */
Xstatic int operator(opr)
X int (*opr)();
X{
X /* insert the operator */
X if (cndx < CODEMAX)
X code[cndx++].c_operator = opr;
X else
X return (db_ferror(CDSIZE));
X
X /* return successfully */
X return (TRUE);
X}
X
X/* operand - insert an operand into the code array */
Xstatic int operand(opr)
X struct operand *opr;
X{
X /* insert the push operator */
X if (!operator(db_xpush))
X return (FALSE);
X
X /* insert the operand */
X if (cndx < CODEMAX)
X code[cndx++].c_operand = opr;
X else
X return (db_ferror(CDSIZE));
X
X /* return successfully */
X return (TRUE);
X}
X
X/* expr - compile an expression */
Xstatic int expr(result)
X int *result;
X{
X int lval,rval;
X
X if (!land(&lval))
X return (FALSE);
X while (db_token() == '|') {
X db_ntoken();
X if (!land(&rval))
X return (FALSE);
X if (!operator(db_xor))
X return (FALSE);
X }
X *result = lval;
X return (TRUE);
X}
X
Xstatic int land(result)
X int *result;
X{
X int lval,rval;
X
X if (!relat(&lval))
X return (FALSE);
X while (db_token() == '&') {
X db_ntoken();
X if (!relat(&rval))
X return (FALSE);
X if (!operator(db_xand))
X return (FALSE);
X }
X *result = lval;
X return (TRUE);
X}
X
Xstatic int relat(result)
X int *result;
X{
X int lval,rval;
X int tkn;
X
X if (!primary(&lval))
X return (FALSE);
X while (db_token() <= LSS && dbv_token >= GTR) {
X tkn = db_ntoken();
X if (!primary(&rval))
X return (FALSE);
X switch (tkn) {
X case LSS:
X if (!operator(db_xlss))
X return (FALSE);
X break;
X case LEQ:
X if (!operator(db_xleq))
X return (FALSE);
X break;
X case EQL:
X if (!operator(db_xeql))
X return (FALSE);
X break;
X case NEQ:
X if (!operator(db_xneq))
X return (FALSE);
X break;
X case GEQ:
X if (!operator(db_xgeq))
X return (FALSE);
X break;
X case GTR:
X if (!operator(db_xgtr))
X return (FALSE);
X break;
X }
X }
X *result = lval;
X return (TRUE);
X}
X
Xstatic int primary(result)
X int *result;
X{
X int val;
X int tkn;
X
X if (db_token() == '~') {
X tkn = db_ntoken();
X if (!primary(&val))
X return (FALSE);
X switch (tkn) {
X case '~':
X if (!operator(db_xnot))
X return (FALSE);
X break;
X }
X }
X else
X if (!factor(&val))
X return (FALSE);
X *result = val;
X return (TRUE);
X}
X
Xstatic int factor(result)
X int *result;
X{
X int val;
X
X if (db_token() == '(') {
X db_ntoken();
X if (!expr(&val))
X return (FALSE);
X if (db_token() != ')')
X return (db_ferror(SYNTAX));
X db_ntoken();
X }
X else
X if (!get_operand(&val))
X return (FALSE);
X *result = val;
X return (TRUE);
X}
X
X/* get_operand - get an operand (number, string, or attribute) */
Xstatic int get_operand(result)
X int *result;
X{
X /* determine operand type */
X if (db_ntoken() == NUMBER)
X return (get_number(result));
X else if (dbv_token == ID)
X return (get_attr(result));
X else if (dbv_token == STRING)
X return (get_string(result));
X else
X return (db_ferror(SYNTAX));
X}
X
X/* get_attr - get an attribute argument */
Xstatic int get_attr(result)
X int *result;
X{
X struct operand *opr;
X char rname[RNSIZE+1],aname[ANSIZE+1];
X char *aptr; int atype,alen;
X
X /* save the attribute name */
X strncpy(aname,dbv_tstring,ANSIZE); aname[ANSIZE] = EOS;
X
X /* check for a "." indicating a qualified attribute name */
X if (db_token() == '.') {
X db_ntoken();
X
X /* the previous ID was really a relation name */
X strcpy(rname,aname);
X
X /* check for the real attribute name */
X if (db_ntoken() != ID)
X return (db_ferror(SYNTAX));
X
X /* save the attribute name */
X strncpy(aname,dbv_tstring,ANSIZE); aname[ANSIZE] = EOS;
X
X /* lookup the attribute name */
X if (!db_sattr(selptr,rname,aname,&atype,&aptr,&alen))
X return (FALSE);
X }
X else
X if (!db_sattr(selptr,NULL,aname,&atype,&aptr,&alen))
X return (FALSE);
X
X /* get a new operand structure */
X if ((opr = malloc(sizeof(struct operand))) == NULL)
X return (db_ferror(INSMEM));
X
X /* initialize the new operand structure */
X opr->o_type = ATTR;
X opr->o_value.ov_char.ovc_type = atype;
X opr->o_value.ov_char.ovc_string = aptr;
X opr->o_value.ov_char.ovc_length = alen;
X
X /* insert the operand into the code array */
X if (!operand(opr)) {
X free(opr);
X return (FALSE);
X }
X
X /* store operand type */
X *result = atype;
X
X /* return successfully */
X return (TRUE);
X}
X
X/* get_number - get a numeric operand */
Xstatic int get_number(result)
X int *result;
X{
X struct operand *opr;
X
X /* get a new operand structure */
X if ((opr = malloc(sizeof(struct operand))) == NULL)
X return (db_ferror(INSMEM));
X
X /* initialize the new operand structure */
X opr->o_type = LITERAL;
X if ((opr->o_value.ov_char.ovc_string =
X malloc(strlen(dbv_tstring)+1)) == NULL) {
X free(opr);
X return (db_ferror(INSMEM));
X }
X opr->o_value.ov_char.ovc_type = TNUM;
X strcpy(opr->o_value.ov_char.ovc_string,dbv_tstring);
X opr->o_value.ov_char.ovc_length = strlen(dbv_tstring);
X
X /* insert the operand into the code array */
X if (!operand(opr)) {
X free(opr->o_value.ov_char.ovc_string); free(opr);
X return (FALSE);
X }
X
X /* operand type is number */
X *result = TNUM;
X
X /* return successfully */
X return (TRUE);
X}
X
X/* get_string - get a string operand */
Xstatic int get_string(result)
X int *result;
X{
X struct operand *opr;
X
X /* get a new operand structure */
X if ((opr = malloc(sizeof(struct operand))) == NULL)
X return (db_ferror(INSMEM));
X
X /* initialize the new operand structure */
X opr->o_type = LITERAL;
X if ((opr->o_value.ov_char.ovc_string =
X malloc(strlen(dbv_tstring)+1)) == NULL) {
X free(opr);
X return (db_ferror(INSMEM));
X }
X opr->o_value.ov_char.ovc_type = TCHAR;
X strcpy(opr->o_value.ov_char.ovc_string,dbv_tstring);
X opr->o_value.ov_char.ovc_length = strlen(dbv_tstring);
X
X /* insert the operand into the code array */
X if (!operand(opr)) {
X free(opr->o_value.ov_char.ovc_string); free(opr);
X return (FALSE);
X }
X
X /* operand type is character */
X *result = TCHAR;
X
X /* return successfully */
X return (TRUE);
X}
X
X/* freelit - free the literals in a code array */
Xstatic freelit(cptr)
X union codecell *cptr;
X{
X#ifdef Lattice
X int (*dns)(); /*dns*/
X for (; (*cptr).c_operator != (dns=db_xstop); cptr++) /*dns*/
X if ((*cptr).c_operator == (dns=db_xpush) ) /*dns*/
X#else
X for (; (*cptr).c_operator != db_xstop; cptr++)
X if ((*cptr).c_operator == db_xpush )
X#endif
X if ((*++cptr).c_operand->o_type == LITERAL)
X free((*cptr).c_operand->o_value.ov_char.ovc_string);
X}
X
SHAR_EOF
if test 9887 -ne "`wc -c 'com.c'`"
then
echo shar: error transmitting "'com.c'" '(should have been 9887 characters)'
fi
echo shar: extracting "'cre.c'" '(3881 characters)'
if test -f 'cre.c'
then
echo shar: over-writing existing file "'cre.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'cre.c'
X/* SDB - relation creation routines */
X
X#include "sdbio.h"
X
X/* db_rcreate(rname) - begin the creation of a new relation */
Xstruct relation *db_rcreate(rname)
X char *rname;
X{
X struct relation *rptr;
X
X /* allocate the relation structure */
X if ((rptr = calloc(1,sizeof(struct relation))) == NULL)
X return (db_nerror(INSMEM));
X
X /* initialize the relation structure */
X strncpy(rptr->rl_name,rname,RNSIZE);
X rptr->rl_tcnt = 0;
X rptr->rl_tmax = 0;
X rptr->rl_data = 512;
X rptr->rl_size = 1;
X rptr->rl_header.hd_attrs[0].at_name[0] = 0;
X
X /* return the new relation structure pointer */
X return (rptr);
X}
X
X/* db_rcheader - create the relation header */
Xint db_rcheader(rptr)
X struct relation *rptr;
X{
X char rname[RNSIZE+1],filename[RNSIZE+13];
X
X /* initialize the relation file header */
X db_cvbytes(rptr->rl_tcnt,rptr->rl_header.hd_tcnt);
X db_cvbytes(rptr->rl_tmax,rptr->rl_header.hd_tmax);
X db_cvbytes(rptr->rl_data,rptr->rl_header.hd_data);
X db_cvbytes(rptr->rl_size,rptr->rl_header.hd_size);
X
X /* create the relation file name */
X strncpy(rname,rptr->rl_name,RNSIZE); rname[RNSIZE] = 0;
X sprintf(filename,"%s.sdb",rname);
X
X /* create the relation file */
X if ((rptr->rl_fd = creat(filename,0)) == -1) {
X free(rptr);
X return (db_ferror(RELCRE));
X }
X
X /* write the header to the relation file */
X if (write(rptr->rl_fd,&rptr->rl_header,512) != 512) {
X close(rptr->rl_fd);
X free(rptr);
X return (db_ferror(BADHDR));
X }
X
X /* return successfully */
X return (TRUE);
X}
X
X/* db_rctuples - create the relation tuples */
Xint db_rctuples(rptr,tcnt)
X struct relation *rptr; unsigned int tcnt;
X{
X unsigned int i;
X char *tbuf;
X
X /* store the number of tuples */
X rptr->rl_tmax = tcnt;
X
X /* allocate a tuple buffer */
X if ((tbuf = calloc(1,rptr->rl_size)) == NULL)
X return (db_ferror(INSMEM));
X
X /* write null tuples into the file */
X for (i = 0; i < tcnt; i++)
X if (write(rptr->rl_fd,tbuf,rptr->rl_size) != rptr->rl_size) {
X free(tbuf);
X return (db_ferror(INSBLK));
X }
X
X /* free the tuple buffer */
X free(tbuf);
X
X /* return successfully */
X return (TRUE);
X}
X
X/* db_rcdone(rptr) - finish the creation of a new relation */
Xint db_rcdone(rptr)
X struct relation *rptr;
X{
X /* initialize the relation file header */
X db_cvbytes(rptr->rl_tcnt,rptr->rl_header.hd_tcnt);
X db_cvbytes(rptr->rl_tmax,rptr->rl_header.hd_tmax);
X
X /* write the header to the relation file */
X lseek(rptr->rl_fd,0L,0);
X if (write(rptr->rl_fd,&rptr->rl_header,512) != 512) {
X close(rptr->rl_fd);
X free(rptr);
X return (db_ferror(BADHDR));
X }
X
X /* close the relation file */
X close(rptr->rl_fd);
X
X /* free the relation structure */
X free(rptr);
X
X /* return successfully */
X return (TRUE);
X}
X
X/* db_rcattr(rptr,aname,type,size) - add an attribute to relation being created */
Xint db_rcattr(rptr,aname,type,size)
X struct relation *rptr; char *aname; int type,size;
X{
X int i;
X
X /* look for attribute name */
X for (i = 0; i < NATTRS; i++)
X if (rptr->rl_header.hd_attrs[i].at_name[0] == 0)
X break;
X else if (db_sncmp(aname,rptr->rl_header.hd_attrs[i].at_name,ANSIZE) == 0)
X return (db_ferror(DUPATT));
X
X /* check for too many attributes */
X if (i == NATTRS)
X return (db_ferror(MAXATT));
X
X /* store the new attribute */
X strncpy(rptr->rl_header.hd_attrs[i].at_name,aname,ANSIZE);
X rptr->rl_header.hd_attrs[i].at_type = type;
X rptr->rl_header.hd_attrs[i].at_size = size;
X
X /* terminate the attribute table */
X if (++i != NATTRS)
X rptr->rl_header.hd_attrs[i].at_name[0] = 0;
X
X /* update the tuple size */
X rptr->rl_size += size;
X
X /* return successfully */
X return (TRUE);
X}
X
SHAR_EOF
if test 3881 -ne "`wc -c 'cre.c'`"
then
echo shar: error transmitting "'cre.c'" '(should have been 3881 characters)'
fi
echo shar: extracting "'err.c'" '(1630 characters)'
if test -f 'err.c'
then
echo shar: over-writing existing file "'err.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'err.c'
X/* SDB - error messages */
X
X#include "sdbio.h"
X
Xchar *db_ertxt(msg)
X int msg;
X{
X char *txt;
X
X /* select the appropriate message text */
X switch (msg) {
X case INSMEM:
X txt = "insufficient memory";
X break;
X case RELFNF:
X txt = "relation file not found";
X break;
X case BADHDR:
X txt = "bad relation header";
X break;
X case TUPINP:
X txt = "tuple input error";
X break;
X case TUPOUT:
X txt = "tuple output error";
X break;
X case RELFUL:
X txt = "relation file full";
X break;
X case RELCRE:
X txt = "error creating relation file";
X break;
X case DUPATT:
X txt = "duplicate attribute";
X break;
X case MAXATT:
X txt = "too many attributes";
X break;
X case INSBLK:
X txt = "insufficient disk space";
X break;
X case SYNTAX:
X txt = "syntax error";
X break;
X case ATUNDF:
X txt = "undefined attribute";
X break;
X case ATAMBG:
X txt = "ambiguous attribute";
X break;
X case RLUNDF:
X txt = "undefined relation";
X break;
X case CDSIZE:
X txt = "boolean expression too complex";
X break;
X case INPFNF:
X txt = "input file not found";
X break;
X case OUTCRE:
X txt = "error creating output file";
X break;
X case INDFNF:
X txt = "indirect command file not found";
X break;
X case BADSET:
X txt = "bad set parameter";
X break;
X default:
X txt = "undefined error";
X break;
X }
X
X /* return the message text */
X return (txt);
X}
X
SHAR_EOF
if test 1630 -ne "`wc -c 'err.c'`"
then
echo shar: error transmitting "'err.c'" '(should have been 1630 characters)'
fi
echo shar: extracting "'iex.c'" '(6728 characters)'
if test -f 'iex.c'
then
echo shar: over-writing existing file "'iex.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'iex.c'
X/* SDB - import/export command routines */
X
X#include "stdio.h"
X#include "sdbio.h"
X
Xextern int dbv_token;
Xextern char dbv_tstring[];
Xextern int dbv_tvalue;
X
X/* db_import - import tuples from a file */
Xint *db_import(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
X char *fmt;
X{
X struct scan *sptr;
X struct attribute *aptr;
X char fname[STRINGMAX+1],avalue[STRINGMAX+1];
X int tcnt,astart,i,eofile;
X FILE *fp;
X
X /* check for a command line */
X if (fmt != NULL)
X db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);
X
X /* checks for "<filename> into <relation-name>" */
X if (db_ntoken() == ID)
X strcat(dbv_tstring,".dat");
X else if (dbv_token != STRING)
X return (db_ferror(SYNTAX));
X strcpy(fname,dbv_tstring);
X if (db_ntoken() != INTO)
X return (db_ferror(SYNTAX));
X if (db_ntoken() != ID)
X return (db_ferror(SYNTAX));
X
X /* open the relation */
X if ((sptr = db_ropen(dbv_tstring)) == NULL)
X return (FALSE);
X
X /* open the input file */
X if ((fp = fopen(fname,"r")) == NULL)
X return (db_ferror(INPFNF));
X
X /* import tuples */
X eofile = FALSE;
X for (tcnt = 0; ; tcnt++) {
X
X /* get attribute values */
X astart = 1;
X for (i = 0; i < NATTRS; i++) {
X
X /* get a pointer to the current attribute */
X aptr = &sptr->sc_relation->rl_header.hd_attrs[i];
X
X /* check for the last attribute */
X if (aptr->at_name[0] == 0)
X break;
X
X /* input the tuple */
X if (fgets(avalue,STRINGMAX,fp) == 0) {
X eofile = TRUE;
X break;
X }
X avalue[strlen(avalue)-1] = EOS;
X
X /* store the attribute value */
X db_aput(aptr,&sptr->sc_tuple[astart],avalue);
X
X /* update the attribute start */
X astart += aptr->at_size;
X }
X
X /* store the new tuple */
X if (!eofile) {
X if (!db_rstore(sptr)) {
X db_rclose(sptr);
X return (FALSE);
X }
X }
X else
X break;
X }
X
X /* close the relation */
X db_rclose(sptr);
X
X /* close the input file */
X fclose(fp);
X
X /* check number of tuples imported */
X if (tcnt != 0) {
X
X /* print tuple count */
X printf("[ %d imported ]\n",tcnt);
X }
X else
X printf("[ none imported ]\n");
X
X /* return successfully */
X return (TRUE);
X}
X
X/* db_export - export tuples to a file */
Xint *db_export(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
X char *fmt;
X{
X struct scan *sptr;
X struct attribute *aptr;
X char rname[STRINGMAX+1],avalue[STRINGMAX+1];
X int tcnt,astart,i;
X FILE *fp;
X
X /* check for a command line */
X if (fmt != NULL)
X db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);
X
X /* checks for "<relation-name> [ into <filename> ]" */
X if (db_ntoken() != ID)
X return (db_ferror(SYNTAX));
X strcpy(rname,dbv_tstring);
X if (!db_to(&fp,".dat"))
X return (FALSE);
X
X /* open the relation */
X if ((sptr = db_ropen(rname)) == NULL)
X return (FALSE);
X
X /* export tuples */
X for (tcnt = 0; db_rfetch(sptr); tcnt++) {
X
X /* get attribute values */
X astart = 1;
X for (i = 0; i < NATTRS; i++) {
X
X /* get a pointer to the current attribute */
X aptr = &sptr->sc_relation->rl_header.hd_attrs[i];
X
X /* check for the last attribute */
X if (aptr->at_name[0] == 0)
X break;
X
X /* get the attribute value */
X db_aget(aptr,&sptr->sc_tuple[astart],avalue);
X
X /* output the tuple */
X fprintf(fp,"%s\n",avalue);
X
X /* update the attribute start */
X astart += aptr->at_size;
X }
X }
X
X /* close the relation */
X db_rclose(sptr);
X
X /* close the output file */
X if (fp != stdout)
X fclose(fp);
X
X /* check number of tuples exported */
X if (tcnt != 0) {
X
X /* print tuple count */
X printf("[ %d exported ]\n",tcnt);
X }
X else
X printf("[ none exported ]\n");
X
X /* return successfully */
X return (TRUE);
X}
X
X/* db_squeeze - squeeze deleted tuples from a relation file */
Xint *db_squeeze(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
X char *fmt;
X{
X struct scan *sptr;
X
X /* check for a command line */
X if (fmt != NULL)
X db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);
X
X /* checks for "<relation-name>" */
X if (db_ntoken() != ID)
X return (db_ferror(SYNTAX));
X
X /* open the relation */
X if ((sptr = db_ropen(dbv_tstring)) == NULL)
X return (FALSE);
X
X /* compress the relation file */
X if (!db_rcompress(sptr)) {
X db_rclose(sptr);
X return (FALSE);
X }
X
X /* close the relation */
X db_rclose(sptr);
X
X /* return successfully */
X return (TRUE);
X}
X
X/* db_extract - extract a relation definition */
Xint *db_extract(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
X char *fmt;
X{
X struct scan *sptr;
X struct attribute *aptr;
X char rname[STRINGMAX+1],aname[ANSIZE+1],*atype;
X int i;
X FILE *fp;
X
X /* check for a command line */
X if (fmt != NULL)
X db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);
X
X /* checks for "<relation-name> [ into <filename> ]" */
X if (db_ntoken() != ID)
X return (db_ferror(SYNTAX));
X strcpy(rname,dbv_tstring);
X if (!db_to(&fp,".def"))
X return (FALSE);
X
X /* open the relation */
X if ((sptr = db_ropen(rname)) == NULL)
X return (FALSE);
X
X /* output the relation definition */
X fprintf(fp,"create %s (\n",rname);
X
X /* get attribute values */
X for (i = 0; i < NATTRS; i++) {
X
X /* get a pointer to the current attribute */
X aptr = &sptr->sc_relation->rl_header.hd_attrs[i];
X
X /* check for the last attribute */
X if (aptr->at_name[0] == 0)
X break;
X
X /* get the attribute name */
X strncpy(aname,aptr->at_name,ANSIZE); aname[ANSIZE] = 0;
X
X /* determine the attribute type */
X switch (aptr->at_type) {
X case TCHAR:
X atype = "char";
X break;
X case TNUM:
X atype = "num";
X break;
X default:
X atype = "<error>";
X break;
X }
X
X /* output the attribute definition */
X if (strlen(aname) < 8)
X fprintf(fp,"\t%s\t\t%s\t%d\n",aname,atype,aptr->at_size);
X else
X fprintf(fp,"\t%s\t%s\t%d\n",aname,atype,aptr->at_size);
X }
X
X /* output the relation size */
X fprintf(fp,") %d\n",sptr->sc_relation->rl_tmax);
X
X /* close the relation */
X db_rclose(sptr);
X
X /* close the output file */
X if (fp != stdout)
X fclose(fp);
X
X /* return successfully */
X return (TRUE);
X}
X
SHAR_EOF
if test 6728 -ne "`wc -c 'iex.c'`"
then
echo shar: error transmitting "'iex.c'" '(should have been 6728 characters)'
fi
echo shar: extracting "'int.c'" '(4388 characters)'
if test -f 'int.c'
then
echo shar: over-writing existing file "'int.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'int.c'
X/* SDB - boolean expression evaluator */
X
X#include "sdbio.h"
X
Xstatic struct operand *stack[STACKMAX],**sptr;
Xstatic union codecell *cptr;
X
X/* db_interpret - interpret a boolean expression */
Xint db_interpret(slptr)
X struct sel *slptr;
X{
X struct operand *result;
X int r;
X
X /* check for empty where clause */
X if ((cptr = slptr->sl_where) == NULL)
X return (TRUE);
X
X /* setup stack */
X sptr = stack;
X
X /* execute the code */
X while ((*(*cptr++).c_operator)())
X ;
X
X /* get the result from the top of stack */
X result = *--sptr;
X r = result->o_value.ov_boolean;
X if (result->o_type == TEMP)
X free(result);
X
X /* make sure the stack is empty */
X while (sptr != stack) {
X if ((*sptr)->o_type == TEMP)
X free(*sptr);
X sptr -= 1;
X }
X
X /* return result */
X return (r);
X}
X
Xint db_xstop()
X{
X return (FALSE);
X}
X
Xint db_xpush()
X{
X *sptr++ = (*cptr++).c_operand;
X}
X
Xint db_xand()
X{
X return (boolean('&'));
X}
X
Xint db_xor()
X{
X return (boolean('|'));
X}
X
Xstatic int boolean(opr)
X{
X struct operand *lval,*rval,*result;
X int lv,rv,r;
X
X rval = *--sptr; lval = *--sptr;
X lv = lval->o_value.ov_boolean;
X rv = rval->o_value.ov_boolean;
X
X if ((result = malloc(sizeof(struct operand))) == NULL)
X return (db_ferror(INSMEM));
X result->o_type = TEMP;
X switch (opr) {
X case '&': r = (lv && rv);
X break;
X case '|': r = (lv || rv);
X break;
X }
X result->o_value.ov_boolean = r;
X *sptr++ = result;
X if (lval->o_type == TEMP)
X free(lval);
X if (rval->o_type == TEMP)
X free(rval);
X return (TRUE);
X}
X
Xint db_xnot()
X{
X struct operand *val,*result;
X
X val = *--sptr;
X if ((result = malloc(sizeof(struct operand))) == NULL)
X return (db_ferror(INSMEM));
X result->o_type = TEMP;
X result->o_value.ov_boolean = !val->o_value.ov_boolean;
X *sptr++ = result;
X if (val->o_type == TEMP)
X free(val);
X return (TRUE);
X}
X
Xint db_xlss()
X{
X return (compare(LSS));
X}
X
Xint db_xleq()
X{
X return (compare(LEQ));
X}
X
Xint db_xeql()
X{
X return (compare(EQL));
X}
X
Xint db_xgeq()
X{
X return (compare(GEQ));
X}
X
Xint db_xgtr()
X{
X return (compare(GTR));
X}
X
Xint db_xneq()
X{
X return (compare(NEQ));
X}
X
Xstatic int compare(cmp)
X{
X struct operand *lval,*rval,*result;
X int i;
X
X rval = *--sptr; lval = *--sptr;
X if ((result = malloc(sizeof(struct operand))) == NULL)
X return (db_ferror(INSMEM));
X result->o_type = TEMP;
X
X if (lval->o_value.ov_char.ovc_type == TCHAR)
X i = comp(lval,rval);
X else
X i = ncomp(lval,rval);
X
X switch (cmp) {
X case LSS: i = (i < 0);
X break;
X case LEQ: i = (i <= 0);
X break;
X case EQL: i = (i == 0);
X break;
X case GEQ: i = (i >= 0);
X break;
X case GTR: i = (i > 0);
X break;
X case NEQ: i = (i != 0);
X break;
X }
X result->o_value.ov_boolean = i;
X *sptr++ = result;
X if (lval->o_type == TEMP)
X free(lval);
X if (rval->o_type == TEMP)
X free(rval);
X return (TRUE);
X}
X
Xstatic int comp(lval,rval)
X struct operand *lval,*rval;
X{
X char *lptr,*rptr; int lctr,rctr;
X int len;
X
X lptr = lval->o_value.ov_char.ovc_string;
X lctr = lval->o_value.ov_char.ovc_length;
X rptr = rval->o_value.ov_char.ovc_string;
X rctr = rval->o_value.ov_char.ovc_length;
X
X while (lctr > 0 && (lptr[lctr-1] == 0 || lptr[lctr-1] == ' '))
X lctr--;
X while (rctr > 0 && (rptr[rctr-1] == 0 || rptr[rctr-1] == ' '))
X rctr--;
X
X if (lctr < rctr)
X len = lctr;
X else
X len = rctr;
X
X while ((len--) > 0) {
X if (*lptr++ != *rptr++)
X if (*--lptr < *--rptr)
X return (-1);
X else
X return (1);
X }
X
X if (lctr == rctr)
X return (0);
X else if (lctr < rctr)
X return (-1);
X else
X return (1);
X}
X
Xstatic int ncomp(lval,rval)
X struct operand *lval,*rval;
X{
X char lstr[NUMBERMAX+1],rstr[NUMBERMAX+1];
X int len;
X
X strncpy(lstr,lval->o_value.ov_char.ovc_string,
X (len = lval->o_value.ov_char.ovc_length)); lstr[len] = EOS;
X strncpy(rstr,rval->o_value.ov_char.ovc_string,
X (len = rval->o_value.ov_char.ovc_length)); rstr[len] = EOS;
X
X return (db_cmp(lstr,rstr));
X}
X
SHAR_EOF
if test 4388 -ne "`wc -c 'int.c'`"
then
echo shar: error transmitting "'int.c'" '(should have been 4388 characters)'
fi
echo shar: extracting "'io.c'" '(10454 characters)'
if test -f 'io.c'
then
echo shar: over-writing existing file "'io.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'io.c'
X/* SDB - relation file I/O routines */
X
X#include "stdio.h"
X#include "sdbio.h"
X
X/* global error code variable */
Xint dbv_errcode;
X
X/* list of currently loaded relation definitions */
Xstatic struct relation *relations = NULL;
X
X/* rfind - find the specified relation */
Xstatic struct relation *rfind(rname)
X char *rname;
X{
X int fd;
X char filename[RNSIZE+5];
X struct relation *rptr;
X
X /* look for relation in list currently loaded */
X for (rptr = relations; rptr != NULL; rptr = rptr->rl_next)
X if (db_sncmp(rname,rptr->rl_name,RNSIZE) == 0)
X return (rptr);
X
X /* create a file name */
X make_fname(filename,rname);
X
X /* lookup the relation file */
X#ifdef Lattice
X if ((fd = open(filename,0x8000)) == -1) /*dns*/
X#else
X if ((fd = open(filename,0)) == -1)
X#endif
X return (db_nerror(RELFNF));
X
X /* allocate a new relation structure */
X if ((rptr = malloc(sizeof(struct relation))) == NULL) {
X close(fd);
X return (db_nerror(INSMEM));
X }
X
X /* initialize the relation structure */
X rptr->rl_scnref = 0;
X
X /* read the header block */
X if ( read(fd,&rptr->rl_header,512) != 512) {
X free(rptr);
X close(fd);
X return (db_nerror(BADHDR));
X }
X
X /* close the relation file */
X close(fd);
X
X /* extract header information */
X rptr->rl_tcnt = db_cvword(rptr->rl_header.hd_tcnt);
X rptr->rl_tmax = db_cvword(rptr->rl_header.hd_tmax);
X rptr->rl_data = db_cvword(rptr->rl_header.hd_data);
X rptr->rl_size = db_cvword(rptr->rl_header.hd_size);
X
X /* store the relation name */
X strncpy(rptr->rl_name,rname,RNSIZE);
X
X /* link new relation into relation list */
X rptr->rl_next = relations;
X relations = rptr;
X
X /* return the new relation structure pointer */
X return (rptr);
X}
X
X/* db_ropen - open a relation file */
Xstruct scan *db_ropen(rname)
X char *rname;
X{
X struct relation *rptr;
X struct scan *sptr;
X char filename[RNSIZE+5];
X
X /* find the relation definition */
X if ((rptr = rfind(rname)) == NULL)
X return (NULL);
X
X /* allocate a new scan structure */
X if ((sptr = malloc(sizeof(struct scan))) == NULL)
X return (db_nerror(INSMEM));
X
X /* allocate a tuple buffer */
X if ((sptr->sc_tuple = malloc(rptr->rl_size)) == NULL) {
X free(sptr);
X return (db_nerror(INSMEM));
X }
X
X /* initialize the scan structure */
X sptr->sc_relation = rptr; /* store the relation struct addrs */
X sptr->sc_dtnum = 0; /* desired tuple (non-existant) */
X sptr->sc_atnum = 0; /* actual tuple (non-existant) */
X sptr->sc_store = FALSE; /* no store done since open */
X
X /* open relation file if necessary */
X if (rptr->rl_scnref++ == 0) {
X
X /* create the relation file name */
X make_fname(filename,rname);
X
X /* open the relation file */
X#ifdef Lattice
X if ((rptr->rl_fd = open(filename,0x8002)) == -1) { /*dns*/
X#else
X if ((rptr->rl_fd = open(filename,2)) == -1) {
X#endif
X rptr->rl_scnref--;
X free(sptr->sc_tuple); free(sptr);
X return (db_nerror(RELFNF));
X }
X }
X
X /* return the new scan structure pointer */
X return (sptr);
X}
X
X/* db_rclose - close the relation file */
Xint db_rclose(sptr)
X struct scan *sptr;
X{
X struct relation *rptr,*lastrptr;
X
X /* close relation file if this is the last reference */
X if (--sptr->sc_relation->rl_scnref == 0) {
X
X /* rewrite header if any stores took place */
X if (sptr->sc_store) {
X
X /* store the tuple count back in the header */
X db_cvbytes(sptr->sc_relation->rl_tcnt,
X sptr->sc_relation->rl_header.hd_tcnt);
X
X /* write the header block */
X lseek(sptr->sc_relation->rl_fd,0L,0);
X if (write(sptr->sc_relation->rl_fd,
X &sptr->sc_relation->rl_header,512) != 512) {
X close(sptr->sc_relation->rl_fd);
X free(sptr->sc_tuple); free(sptr);
X return (db_ferror(BADHDR));
X }
X }
X
X /* close the relation file */
X close(sptr->sc_relation->rl_fd);
X
X /* free the relation header */
X lastrptr = NULL;
X for (rptr = relations; rptr != NULL; rptr = rptr->rl_next) {
X if (rptr == sptr->sc_relation) {
X if (lastrptr == NULL)
X relations = rptr->rl_next;
X else
X lastrptr->rl_next = rptr->rl_next;
X }
X lastrptr = rptr;
X }
X free(sptr->sc_relation);
X }
X
X /* free the scan structure */
X free(sptr->sc_tuple); free(sptr);
X
X /* return successfully */
X return (TRUE);
X}
X
X/* db_rcompress - compress a relation file */
Xint db_rcompress(sptr)
X struct scan *sptr;
X{
X unsigned int next,nextfree,tcnt;
X
X /* get the last used tuple */
X tcnt = sptr->sc_relation->rl_tcnt;
X
X /* loop through all of the tuples */
X for (next = nextfree = 1; next <= tcnt; next++) {
X
X /* read the tuple */
X seek(sptr,next);
X if (read(sptr->sc_relation->rl_fd,
X sptr->sc_tuple,sptr->sc_relation->rl_size)
X != sptr->sc_relation->rl_size)
X return (db_ferror(TUPINP));
X
X /* rewrite the tuple if it is active */
X if (sptr->sc_tuple[0] == ACTIVE) {
X
X /* rewrite it only if it must move */
X if (next != nextfree) {
X
X /* write the tuple */
X seek(sptr,nextfree);
X if (write(sptr->sc_relation->rl_fd,
X sptr->sc_tuple,sptr->sc_relation->rl_size)
X != sptr->sc_relation->rl_size)
X return (db_ferror(TUPOUT));
X }
X
X /* update the next free tuple number */
X nextfree += 1;
X }
X }
X
X /* update the tuple count */
X sptr->sc_relation->rl_tcnt = nextfree - 1;
X
X /* remember which tuple is in the buffer */
X sptr->sc_atnum = sptr->sc_relation->rl_tcnt;
X
X /* reset the desired tuple */
X sptr->sc_dtnum = 0;
X
X /* remember that the index needs rewriting */
X sptr->sc_store = TRUE;
X
X /* return successfully */
X return (TRUE);
X}
X
X/* db_rbegin - begin scan at first tuple in relation */
Xdb_rbegin(sptr)
X struct scan *sptr;
X{
X /* begin with the first tuple in the file */
X sptr->sc_dtnum = 0;
X}
X
X/* db_rfetch - fetch the next tuple from the relation file */
Xint db_rfetch(sptr)
X struct scan *sptr;
X{
X /* look for an active tuple */
X while (TRUE) {
X
X /* check for this being the last tuple */
X if (!db_rget(sptr,sptr->sc_dtnum + 1))
X return (FALSE);
X
X /* increment the tuple number */
X sptr->sc_dtnum += 1;
X
X /* return if the tuple found is active */
X if (sptr->sc_tuple[0] == ACTIVE)
X return (TRUE);
X }
X}
X
X/* db_rupdate - update the current tuple */
Xint db_rupdate(sptr)
X struct scan *sptr;
X{
X /* make sure the status byte indicates an active tuple */
X sptr->sc_tuple[0] = ACTIVE;
X
X /* write the tuple */
X return (db_rput(sptr,sptr->sc_atnum));
X}
X
X/* db_rdelete - delete the current tuple */
Xint db_rdelete(sptr)
X struct scan *sptr;
X{
X /* make sure the status byte indicates a deleted tuple */
X sptr->sc_tuple[0] = DELETED;
X
X /* write the tuple */
X return (db_rput(sptr,sptr->sc_atnum));
X}
X
X/* db_rstore - store a new tuple */
Xint db_rstore(sptr)
X struct scan *sptr;
X{
X /* make sure there's room for this tuple */
X if (sptr->sc_relation->rl_tcnt == sptr->sc_relation->rl_tmax)
X return (db_ferror(RELFUL));
X
X /* make sure the status byte indicates an active tuple */
X sptr->sc_tuple[0] = ACTIVE;
X
X /* write the tuple */
X if (!db_rput(sptr,sptr->sc_relation->rl_tcnt + 1))
X return (FALSE);
X
X /* update the tuple count */
X sptr->sc_relation->rl_tcnt += 1;
X
X /* remember that a tuple was stored */
X sptr->sc_store = TRUE;
X
X /* return successfully */
X return (TRUE);
X}
X
X/* db_rget - get a tuple from the relation file */
Xint db_rget(sptr,tnum)
X struct scan *sptr; unsigned int tnum;
X{
X /* check to see if the tuple is already in the buffer */
X if (tnum == sptr->sc_atnum)
X return (TRUE);
X
X /* check for this being beyond the last tuple */
X if (tnum > sptr->sc_relation->rl_tcnt)
X return (db_ferror(TUPINP));
X
X /* read the tuple */
X seek(sptr,tnum);
X if (read(sptr->sc_relation->rl_fd,
X sptr->sc_tuple,sptr->sc_relation->rl_size)
X != sptr->sc_relation->rl_size)
X return (db_ferror(TUPINP));
X
X /* remember which tuple is in the buffer */
X sptr->sc_atnum = tnum;
X
X /* return successfully */
X return (TRUE);
X}
X
X/* db_rput - put a tuple to a relation file */
Xint db_rput(sptr,tnum)
X struct scan *sptr; unsigned int tnum;
X{
X /* check for this being beyond the maximum tuple */
X if (tnum > sptr->sc_relation->rl_tmax)
X return (db_ferror(TUPOUT));
X
X /* write the tuple */
X seek(sptr,tnum);
X if (write(sptr->sc_relation->rl_fd,
X sptr->sc_tuple,sptr->sc_relation->rl_size)
X != sptr->sc_relation->rl_size)
X return (db_ferror(TUPOUT));
X
X /* remember which tuple is in the buffer */
X sptr->sc_atnum = tnum;
X
X /* return successfully */
X return (TRUE);
X}
X
X/* seek - seek a tuple in a relation file */
Xstatic seek(sptr,tnum)
X struct scan *sptr; unsigned int tnum;
X{
X long offset;
X
X offset = (long) sptr->sc_relation->rl_data +
X ((long) (tnum - 1) * (long) sptr->sc_relation->rl_size);
X lseek(sptr->sc_relation->rl_fd,offset,0);
X}
X
X/* make_fname - make a relation name into a file name */
Xstatic make_fname(fname,rname)
X char *fname,*rname;
X{
X strncpy(fname,rname,RNSIZE); fname[RNSIZE] = 0;
X strcat(fname,".sdb");
X}
X
X/* db_nerror - store the error code and return NULL */
Xint db_nerror(errcode)
X int errcode;
X{
X dbv_errcode = errcode;
X return (NULL);
X}
X
X/* db_ferror - store the error code and return FALSE */
Xint db_ferror(errcode)
X int errcode;
X{
X dbv_errcode = errcode;
X return (FALSE);
X}
X
X/* db_cvword - convert 2 bytes to a word */
Xint db_cvword(bytes)
X char bytes[2];
X{
X return (((bytes[1] & 0377) << 8) + (bytes[0] & 0377));
X}
X
X/* db_cvbytes - convert a word to 2 bytes */
Xdb_cvbytes(word,bytes)
X int word; char bytes[2];
X{
X bytes[0] = word;
X bytes[1] = word >> 8;
X}
X
SHAR_EOF
if test 10454 -ne "`wc -c 'io.c'`"
then
echo shar: error transmitting "'io.c'" '(should have been 10454 characters)'
fi
echo shar: extracting "'mth.c'" '(7647 characters)'
if test -f 'mth.c'
then
echo shar: over-writing existing file "'mth.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'mth.c'
X/* SDB - string arithmetic routines */
X
X#include "ctype.h" /*dns*/
X
X/* useful definitions */
X#define TRUE 1
X#define FALSE 0
X#define NUMBERMAX 99
X#define EOS 0
X
X/* db_cmp - compare two signed numeric strings */
Xint db_cmp(arg1,arg2)
X char *arg1,*arg2;
X{
X int sign1,sign2;
X
X /* get the signs of the arguments */
X sign1 = getsign(&arg1);
X sign2 = getsign(&arg2);
X
X /* compute the result */
X if (sign1 == sign2) {
X if (sign1 == 1)
X return (compare(arg1,arg2));
X else
X return (compare(arg2,arg1));
X }
X
X /* signs are different */
X return (sign1);
X}
X
X/* db_add - add two signed numeric strings */
Xdb_add(result,arg1,arg2)
X char *result,*arg1,*arg2;
X{
X int signr,sign1,sign2;
X char rtmp[NUMBERMAX+2],*rptr;
X
X /* get the signs of the arguments */
X sign1 = getsign(&arg1);
X sign2 = getsign(&arg2);
X
X /* compute the result */
X if (sign1 == sign2) {
X signr = sign1;
X add(rtmp,arg1,arg2);
X }
X else
X switch (compare(arg1,arg2)) {
X case -1:
X signr = sign2;
X sub(rtmp,arg2,arg1);
X break;
X case 0:
X strcpy(result,"0");
X return;
X case 1:
X signr = sign1;
X sub(rtmp,arg1,arg2);
X break;
X }
X
X /* insert the sign */
X if (signr == -1)
X strcpy(result,"-");
X else
X result[0] = EOS;
X
X /* eliminate possible leading zeros */
X for (rptr = rtmp; *rptr == '0'; rptr++)
X ;
X
X /* copy the result */
X if (*rptr != EOS)
X strcat(result,rptr);
X else
X strcat(result,"0");
X}
X
X/* db_sub - subtract two signed numeric strings */
Xdb_sub(result,arg1,arg2)
X char *result,*arg1,*arg2;
X{
X int signr,sign1,sign2;
X char rtmp[NUMBERMAX+2],*rptr;
X
X /* get the signs of the arguments */
X sign1 = getsign(&arg1);
X sign2 = getsign(&arg2);
X
X /* invert the sign of arg2 */
X sign2 = -sign2;
X
X /* compute the result */
X if (sign1 == sign2) {
X signr = sign1;
X add(rtmp,arg1,arg2);
X }
X else
X switch (compare(arg1,arg2)) {
X case -1:
X signr = sign2;
X sub(rtmp,arg2,arg1);
X break;
X case 0:
X strcpy(result,"0");
X return;
X case 1:
X signr = sign1;
X sub(rtmp,arg1,arg2);
X break;
X }
X
X /* insert the sign */
X if (signr == -1)
X strcpy(result,"-");
X else
X result[0] = EOS;
X
X /* eliminate a possible leading zero */
X for (rptr = rtmp; *rptr == '0'; rptr++)
X ;
X
X /* copy the result */
X if (*rptr != EOS)
X strcat(result,rptr);
X else
X strcat(result,"0");
X}
X
X/* add - add two unsigned numeric strings */
Xstatic add(result,arg1,arg2)
X char *result,*arg1,arg2;
X{
X char *vr,*v1,*v2,*vx;
X int carry,i,nmin,nmax,nd1,nd2;
X
X
X /* get number of digits in each argument */
X nd1 = getlen(arg1);
X nd2 = getlen(arg2);
X
X /* compute the address of the last digit + 1 */
X v1 = arg1 + nd1;
X v2 = arg2 + nd2;
X
X /* compute minimum and maximum of nd1 and nd2 */
X if (nd1 < nd2) {
X nmin = -nd1;
X nmax = -nd2;
X vx = v2;
X }
X else {
X nmin = -nd2;
X nmax = -nd1;
X vx = v1;
X }
X
X /* compute the address of the last result digit + 1 */
X vr = result - nmax; vr[0] = EOS;
X
X /* initialize the carry */
X carry = 0;
X
X /* add the digits */
X for (i = -1; i >= nmin; i--) {
X
X /* check for decimal point */
X if (v1[i] == '.')
X vr[i] = '.';
X else {
X
X /* add the current pair of digits with the carry */
X vr[i] = v1[i] + v2[i] + carry - '0';
X
X /* check for carry */
X if (vr[i] > '9') {
X vr[i] -= 10;
X carry = 1;
X }
X else
X carry = 0;
X }
X }
X
X /* add the remaining digits */
X for (; i >= nmax; i--) {
X
X /* add the current digit with the carry */
X vr[i] = vx[i] + carry;
X
X /* check for carry */
X if (vr[i] > '9') {
X vr[i] -= 10;
X carry = 1;
X }
X else
X carry = 0;
X }
X
X /* check for a carry out and shift digits if necessary */
X if (carry == 1) {
X
X /* shift the digits */
X for (i = -nmax; i >= 0; i--)
X result[i+1] = result[i];
X result[0] = '1';
X }
X}
X
X/* sub - subtract two unsigned numeric strings */
Xstatic sub(result,arg1,arg2)
X char *result,*arg1,arg2;
X{
X char *vr,*v1,*v2,*vx;
X int borrow,i,nmin,nmax,nd1,nd2;
X
X /* get number of digits in each argument */
X nd1 = getlen(arg1);
X nd2 = getlen(arg2);
X
X /* compute the address of the last digit + 1 */
X v1 = arg1 + nd1;
X v2 = arg2 + nd2;
X
X /* compute minimum and maximum of nd1 and nd2 */
X if (nd1 < nd2) {
X nmin = -nd1;
X nmax = -nd2;
X vx = v2;
X }
X else {
X nmin = -nd2;
X nmax = -nd1;
X vx = v1;
X }
X
X /* compute the address of the last result digit + 1 */
X vr = result - nmax; vr[0] = EOS;
X
X /* initialize the borrow */
X borrow = 0;
X
X /* subtract the digits */
X for (i = -1; i >= nmin; i--) {
X
X /* check for decimal point */
X if (v1[i] == '.')
X vr[i] = '.';
X else {
X
X /* subtract the current pair of digits with the borrow */
X vr[i] = v1[i] - v2[i] - borrow + '0';
X
X /* check for borrow */
X if (vr[i] < '0') {
X vr[i] += 10;
X borrow = 1;
X }
X else
X borrow = 0;
X }
X }
X
X /* subtract the remaining digits */
X for (; i >= nmax; i--) {
X
X /* subtract the current digit with the borrow */
X vr[i] = vx[i] - borrow;
X
X /* check for borrow */
X if (vr[i] < '0') {
X vr[i] += 10;
X borrow = 1;
X }
X else
X borrow = 0;
X }
X}
X
X/* getsign - get the sign of a numeric string */
Xstatic int getsign(parg)
X char **parg;
X{
X int sign;
X char *p;
X
X /* eliminate leading spaces */
X while (isspace(**parg))
X *parg += 1;
X
X /* get the sign */
X switch (**parg) {
X case '+': *parg += 1;
X sign = 1;
X break;
X case '-': *parg += 1;
X sign = -1;
X break;
X default: sign = 1;
X break;
X }
X
X /* eliminate leading spaces and zeros */
X while (isspace(**parg) || **parg == '0')
X *parg += 1;
X
X /* if the value is zero, make sure that the sign is positive */
X switch (**parg) {
X case EOS: sign = 1;
X break;
X case '.': for (p = *parg + 1; *p == '0'; p++)
X ;
X if (*p == EOS)
X sign = 1;
X break;
X }
X
X /* return the sign */
X return (sign);
X}
X
X/* getlen - get the length of a numeric string */
Xstatic int getlen(arg)
X char *arg;
X{
X int len;
X
X /* get the length of the string */
X len = strlen(arg);
X
X /* eliminate trailing spaces */
X while (isspace(arg[len-1]))
X len -= 1;
X
X /* return the length */
X return (len);
X}
X
X/* compare - compare two unsigned numeric strings */
Xstatic int compare(arg1,arg2)
X char *arg1,*arg2;
X{
X int len1,len2;
X
X /* compare lengths */
X if ((len1 = getlen(arg1)) != (len2 = getlen(arg2)))
X if (len1 < len2)
X return (-1);
X else
X return (1);
X
X /* compare strings */
X return (strcmp(arg1,arg2));
X}
X
SHAR_EOF
if test 7647 -ne "`wc -c 'mth.c'`"
then
echo shar: error transmitting "'mth.c'" '(should have been 7647 characters)'
fi
echo shar: extracting "'pcjunk.c'" '(1360 characters)'
if test -f 'pcjunk.c'
then
echo shar: over-writing existing file "'pcjunk.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'pcjunk.c'
X/* PCJUNK.C Misc. procedures */
X
X#include "stdio.h"
X#include "sdbio.h"
X
X/* Replaces JUNK.C for the IBM/PC version dns */
X
X
Xchar *alloc(n)
Xint n;
X{
X return (char*) malloc(n);
X}
X
X
Xint getcx(fp)
X FILE *fp;
X{
X static char buf[LINEMAX] = {0};
X static char *pbuf = buf;
X int ch, i;
X
X if (fp!=stdin)
X if ((ch = getc(fp)) == '\r')
X return getc(fp);
X else
X return ch;
X
X if (*pbuf > 0)
X return *pbuf++;
X
X pbuf = buf;
X for (i = 0; (ch = getc(fp)) != -1; )
X if (i < LINEMAX) {
X if (ch == ESC) { i=0; putchar('\n'); fflush(stdout); } else
X if (ch == BS) { if (i>0) i--; } else
X buf[i++] = ch;
X if (ch == '\n') break;
X }
X else {
X printf("*** line too long ***\nRetype> ");
X i = 0;
X }
X buf[i] = EOS;
X return getcx(fp);
X}
X
X
X
X/* string copy up to n characters */
Xstrncpy(to, from, n)
Xchar *to, *from;
Xint n;
X{
X char *cp;
X
X for( cp=to; n-- && (*cp++ = *from++); ) ;
X if( n<0 ) *cp = 0;
X return to;
X}
X
X
X/* string compare up to n characters */
Xstrncmp(s1, s2, n)
Xchar *s1, *s2;
Xint n;
X{
X
X for( ;n-- && (*s1==*s2); s2++ )
X if( !*s1++ )
X return 0;
X if( n < 0 )
X return 0;
X if( *s1 < *s2 )
X return -1;
X return 1;
X}
SHAR_EOF
if test 1360 -ne "`wc -c 'pcjunk.c'`"
then
echo shar: error transmitting "'pcjunk.c'" '(should have been 1360 characters)'
fi
echo shar: extracting "'scn.c'" '(14358 characters)'
if test -f 'scn.c'
then
echo shar: over-writing existing file "'scn.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'scn.c'
X/* SDB - token scanning routines */
X
X#include "stdio.h"
X#include "sdbio.h"
X
Xint dbv_token; /* current token */
Xint dbv_tvalue; /* integer token value */
Xchar dbv_tstring[STRINGMAX+1]; /* string token value */
Xstruct ifile *dbv_ifp; /* indirect file context */
Xstruct macro *dbv_macros; /* macro definitions */
Xint dbv_fold; /* case fold alpha comparisons */
X
Xstatic char *iprompt,*cprompt; /* input prompts */
Xstatic char cmdline[LINEMAX+2],*lptr; /* current line and pointer */
Xstatic int atbol; /* flag indicating at bol */
Xstatic int savech; /* lookahead character */
Xstatic int savetkn; /* lookahead token */
Xstatic char *keywords[] = { /* keyword table */
X "ascending",
X "by",
X "char",
X "compress",
X "create",
X "define",
X "delete",
X "descending",
X "exit",
X "export",
X "extract",
X "from",
X "help",
X "insert",
X "import",
X "into",
X "num",
X "print",
X "select",
X "set",
X "show",
X "sort",
X "update",
X "using",
X "where",
X NULL
X};
Xstatic int keytokens[] = { /* token values for each keyword */
X ASCENDING,
X BY,
X CHAR,
X COMPRESS,
X CREATE,
X DEFINE,
X DELETE,
X DESCENDING,
X EXIT,
X EXPORT,
X EXTRACT,
X FROM,
X HELP,
X INSERT,
X IMPORT,
X INTO,
X NUM,
X PRINT,
X SELECT,
X SET,
X SHOW,
X SORT,
X UPDATE,
X USING,
X WHERE,
X NULL
X};
X
X/* db_sinit - initialize the scanner */
Xdb_sinit()
X{
X /* at beginning of line */
X atbol = TRUE;
X
X /* make the command line null */
X lptr = NULL;
X
X /* no lookahead yet */
X savech = EOS;
X savetkn = NULL;
X
X /* no indirect command files */
X dbv_ifp = NULL;
X
X /* no macros defined */
X dbv_macros = NULL;
X
X /* fold alpha comparisons */
X dbv_fold = TRUE;
X}
X
X/* db_prompt(ip,cp) - initialize prompt strings */
Xdb_prompt(ip,cp)
X char *ip,*cp;
X{
X /* save initial and continuation prompt strings */
X iprompt = ip;
X cprompt = cp;
X}
X
X/* db_scan(fmt,args) - initiate line scan command parsing */
Xdb_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)
X{
X /* convert the command line and arguments */
X sprintf(cmdline,fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10);
X
X /* start at the beginning of the command line */
X lptr = cmdline;
X iprompt = NULL;
X dbv_ifp = NULL;
X
X /* no lookahead yet */
X savech = EOS;
X savetkn = NULL;
X
X /* fold alpha comparisons */
X dbv_fold = TRUE;
X}
X
X/* db_flush - flush the current input line */
Xint db_flush()
X{
X while (savech != '\n')
X if (savech > ' ')
X return (db_ferror(SYNTAX));
X else
X savech = getchx();
X
X savech = EOS;
X atbol = TRUE;
X return (TRUE);
X}
X
X/* db_gline - get a line from the current input */
Xchar *db_gline(buf)
X char *buf;
X{
X int ch,i;
X
X for (i = 0; (ch = getch()) != '\n' && ch != -1; )
X if (i < LINEMAX)
X buf[i++] = ch;
X else {
X printf("*** line too long ***\nRetype> ");
X i = 0;
X }
X buf[i] = EOS;
X
X return (buf);
X}
X
X/* db_ifile - setup an indirect command file */
Xint db_ifile(fname)
X char *fname;
X{
X struct ifile *new_ifp;
X
X if ((new_ifp = malloc(sizeof(struct ifile))) == NULL)
X return (db_ferror(INSMEM));
X else if ((new_ifp->if_fp = fopen(fname,"r")) == NULL) {
X free(new_ifp);
X return (db_ferror(INDFNF));
X }
X new_ifp->if_mtext = NULL;
X new_ifp->if_savech = savech;
X new_ifp->if_lptr = lptr;
X new_ifp->if_next = dbv_ifp;
X dbv_ifp = new_ifp;
X
X /* return successfully */
X return (TRUE);
X}
X
X/* db_kill - kill indirect command file input */
Xdb_kill()
X{
X struct ifile *old_ifp;
X
X while ((old_ifp = dbv_ifp) != NULL) {
X dbv_ifp = old_ifp->if_next;
X if (old_ifp->if_fp != NULL)
X fclose(old_ifp->if_fp);
X savech = old_ifp->if_savech;
X lptr = old_ifp->if_lptr;
X free(old_ifp);
X }
X
X while (savech != '\n')
X savech = getchx();
X
X savech = EOS;
X savetkn = NULL;
X atbol = TRUE;
X}
X
X/* db_token - return the current input token */
Xint db_token()
X{
X struct macro *mptr;
X struct ifile *new_ifp;
X
X /* find a token that's not a macro call */
X while (db_xtoken() == ID) {
X
X /* check for a macro call */
X for (mptr = dbv_macros; mptr != NULL; mptr = mptr->mc_next)
X if (db_scmp(dbv_tstring,mptr->mc_name) == 0) {
X if ((new_ifp = malloc(sizeof(struct ifile))) == NULL)
X printf("*** error expanding macro: %s ***\n",dbv_tstring);
X else {
X new_ifp->if_fp = NULL;
X new_ifp->if_mtext = mptr->mc_mtext->mt_next;
X new_ifp->if_lptr = lptr; lptr = mptr->mc_mtext->mt_text;
X new_ifp->if_savech = savech; savech = EOS;
X new_ifp->if_next = dbv_ifp;
X dbv_ifp = new_ifp;
X }
X savetkn = NULL;
X break;
X }
X
X if (mptr == NULL)
X break;
X }
X
X return (dbv_token);
X}
X
X/* db_xtoken - return the current input token */
Xint db_xtoken()
X{
X int ch;
X
X /* check for a saved token */
X if ((dbv_token = savetkn) != NULL)
X return (dbv_token);
X
X /* get the next non-blank character */
X ch = nextch();
X
X /* check type of character */
X if (isalpha(ch)) /* identifier or keyword */
X get_id();
X else if (isdigit(ch)) /* number */
X get_number();
X else if (ch == '"') /* string */
X get_string();
X else if (get_rel()) /* relational operator */
X ;
X else /* single character token */
X dbv_token = getch();
X
X /* save the lookahead token */
X savetkn = dbv_token;
X
X /* return the token */
X return (dbv_token);
X}
X
X/* db_ntoken - get next token (after skipping the current one) */
Xint db_ntoken()
X{
X /* get the current token */
X db_token();
X
X /* make sure another is read on next call */
X savetkn = NULL;
X
X /* return the current token */
X return (dbv_token);
X}
X
X/* db_xntoken - get next token (after skipping the current one) */
Xint db_xntoken()
X{
X /* get the current token */
X db_xtoken();
X
X /* make sure another is read on next call */
X savetkn = NULL;
X
X /* return the current token */
X return (dbv_token);
X}
X
X/* db_scmp - compare two strings */
Xint db_scmp(str1,str2)
X char *str1,*str2;
X{
X if (dbv_fold)
X return (scmp(str1,str2));
X else
X return (strcmp(str1,str2));
X}
X
X/* db_sncmp - compare two strings with a maximum length */
Xint db_sncmp(str1,str2,len)
X char *str1,*str2; int len;
X{
X if (dbv_fold)
X return (sncmp(str1,str2,len));
X else
X return (strncmp(str1,str2,len));
X}
X
X/* scmp - compare two strings with alpha case folding */
Xstatic int scmp(str1,str2)
X char *str1,*str2;
X{
X int ch1,ch2;
X
X /* compare each character */
X while (*str1 && *str2) {
X
X /* fold the character from the first string */
X if (isupper(*str1))
X ch1 = tolower(*str1++);
X else
X ch1 = *str1++;
X
X /* fold the character from the second string */
X if (isupper(*str2))
X ch2 = tolower(*str2++);
X else
X ch2 = *str2++;
X
X /* compare the characters */
X if (ch1 != ch2)
X if (ch1 < ch2)
X return (-1);
X else
X return (1);
X }
X
X /* check for strings of different lengths */
X if (*str1 == *str2)
X return (0);
X else if (*str1 == 0)
X return (-1);
X else
X return (1);
X}
X
X/* sncmp - compare two strings with alpha case folding and a maximum length */
Xstatic int sncmp(str1,str2,len)
X char *str1,*str2; int len;
X{
X int ch1,ch2;
X
X /* compare each character */
X while (*str1 && *str2 && len > 0) {
X
X /* fold the character from the first string */
X if (isupper(*str1))
X ch1 = tolower(*str1++);
X else
X ch1 = *str1++;
X
X /* fold the character from the second string */
X if (isupper(*str2))
X ch2 = tolower(*str2++);
X else
X ch2 = *str2++;
X
X /* compare the characters */
X if (ch1 != ch2)
X if (ch1 < ch2)
X return (-1);
X else
X return (1);
X
X /* decrement the string length */
X len--;
X }
X
X /* check for strings of different lengths */
X if (len == 0 || *str1 == *str2)
X return (0);
X else if (*str1 == 0)
X return (-1);
X else
X return (1);
X}
X
X/* get_id - get a keyword or a user identifier */
Xstatic get_id()
X{
X int ch,nchars,i;
X
X /* input letters and digits */
X ch = nextch();
X nchars = 0;
X while (isalpha(ch) || isdigit(ch)) {
X if (nchars < KEYWORDMAX)
X dbv_tstring[nchars++] = ch;
X getch(); ch = thisch();
X }
X
X /* terminate the keyword */
X dbv_tstring[nchars] = EOS;
X
X /* assume its an identifier */
X dbv_token = ID;
X
X /* check for keywords */
X for (i = 0; keywords[i] != NULL; i++)
X if (db_scmp(dbv_tstring,keywords[i]) == 0)
X dbv_token = keytokens[i];
X}
X
X/* get_number - get a number */
Xstatic get_number()
X{
X int ch,ndigits,nodot;
X
X /* read digits and at most one decimal point */
X ch = nextch();
X ndigits = 0; nodot = TRUE;
X while (isdigit(ch) || (nodot && ch == '.')) {
X if (ch == '.')
X nodot = FALSE;
X if (ndigits < NUMBERMAX)
X dbv_tstring[ndigits++] = ch;
X getch(); ch = thisch();
X }
X
X /* terminate the number */
X dbv_tstring[ndigits] = EOS;
X
X /* get the value of the number */
X sscanf(dbv_tstring,"%d",&dbv_tvalue);
X
X /* token is a number */
X dbv_token = NUMBER;
X}
X
X/* get_string - get a string */
Xstatic get_string()
X{
X int ch,nchars;
X
X /* skip the opening quote */
X getch();
X
X /* read characters until a closing quote is found */
X ch = thisch();
X nchars = 0;
X while (ch && ch != '"') {
X if (nchars < STRINGMAX)
X dbv_tstring[nchars++] = ch;
X getch(); ch = thisch();
X }
X
X /* terminate the string */
X dbv_tstring[nchars] = EOS;
X
X /* skip the closing quote */
X getch();
X
X /* token is a string */
X dbv_token = STRING;
X}
X
X/* get_rel - get a relational operator */
Xstatic int get_rel()
X{
X int ch;
X
X switch (ch = nextch()) {
X case '=':
X getch();
X dbv_token = EQL;
X return (TRUE);;
X case '<':
X getch(); ch = nextch();
X if (ch == '>') {
X getch();
X dbv_token = NEQ;
X }
X else if (ch == '=') {
X getch();
X dbv_token = LEQ;
X }
X else
X dbv_token = LSS;
X return (TRUE);;
X case '>':
X getch(); ch = nextch();
X if (ch == '=') {
X getch();
X dbv_token = GEQ;
X }
X else
X dbv_token = GTR;
X return (TRUE);;
X default:
X return (FALSE);
X }
X}
X
X/* getch - get the next character */
Xstatic int getch()
X{
X char fname[STRINGMAX+1];
X int ch,i;
X
X /* return the lookahead character if there is one */
X if (savech != EOS) {
X ch = savech;
X savech = EOS;
X return (ch);
X }
X
X /* get a character */
X ch = getchx();
X
X /* skip spaces at the beginning of a command */
X if (atbol && iprompt != NULL)
X while (ch <= ' ')
X ch = getchx();
X
X /* use continuation prompt next time */
X iprompt = NULL;
X
X /* check for indirect command file */
X while (ch == '@') {
X for (i = 0; (savech = getchx()) > ' '; )
X if (i < STRINGMAX)
X fname[i++] = savech;
X fname[i] = 0;
X if (db_ifile(fname) != TRUE)
X printf("*** error opening command file: %s ***\n",fname);
X ch = getchx();
X }
X
X /* return the character */
X return (ch);
X}
X
X/* getchx - get the next character */
Xstatic int getchx()
X{
X struct ifile *old_ifp;
X int ch;
X
X /* check for input from buffer */
X if (lptr != NULL) {
X while (*lptr == EOS)
X if (dbv_ifp != NULL)
X if (dbv_ifp->if_mtext == NULL) {
X old_ifp = dbv_ifp;
X ch = dbv_ifp->if_savech; savech = EOS;
X lptr = dbv_ifp->if_lptr;
X dbv_ifp = dbv_ifp->if_next;
X free(old_ifp);
X if (ch != EOS)
X return (ch);
X if (lptr == NULL)
X break;
X }
X else {
X lptr = dbv_ifp->if_mtext->mt_text;
X dbv_ifp->if_mtext = dbv_ifp->if_mtext->mt_next;
X }
X else
X return (EOS);
X
X if (lptr != NULL)
X return (*lptr++);
X }
X
X /* print prompt if necessary */
X if (atbol && dbv_ifp == NULL) { /*dns*/
X if (iprompt != NULL)
X printf("%s",iprompt);
X else if (cprompt != NULL)
X printf("%s",cprompt);
X#ifdef Lattice
X fflush(stdout); /*dns*/
X#endif
X } /*dns*/
X
X if (dbv_ifp == NULL)
X if ((ch = getcx(stdin)) == '\n')
X atbol = TRUE;
X else
X atbol = FALSE;
X else {
X if ((ch = getcx(dbv_ifp->if_fp)) == -1) {
X old_ifp = dbv_ifp;
X ch = dbv_ifp->if_savech; savech = EOS;
X lptr = dbv_ifp->if_lptr;
X dbv_ifp = dbv_ifp->if_next;
X fclose(old_ifp->if_fp);
X free(old_ifp);
X }
X }
X
X /* return the character */
X return (ch);
X}
X
X/* thisch - get the current character */
Xstatic int thisch()
X{
X /* get a lookahead character */
X if (savech == EOS)
X savech = getch();
X
X /* return lookahead character */
X return (savech);
X}
X
X/* nextch - get the next non-blank character */
Xstatic int nextch()
X{
X int ch;
X
X /* skip blank characters */
X while ((ch = thisch()) <= ' ' && ch != EOS)
X getch();
X
X /* return the first non-blank */
X return (ch);
X}
X
SHAR_EOF
if test 14358 -ne "`wc -c 'scn.c'`"
then
echo shar: error transmitting "'scn.c'" '(should have been 14358 characters)'
fi
echo shar: extracting "'sdb.c'" '(367 characters)'
if test -f 'sdb.c'
then
echo shar: over-writing existing file "'sdb.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'sdb.c'
X/* SDB - main routine */
X
X#include "stdio.h"
X#include "sdbio.h"
X
Xextern int dbv_errcode;
X
Xmain()
X{
X printf("SDB - version 2.0\n");
X db_sinit();
X db_ifile("sdb.ini");
X
X while (TRUE) {
X db_prompt("SDB> ","\t> ");
X if (!db_parse(NULL)) {
X printf("** error: %s ***\n",db_ertxt(dbv_errcode));
X db_kill();
X }
X }
X}
X
SHAR_EOF
if test 367 -ne "`wc -c 'sdb.c'`"
then
echo shar: error transmitting "'sdb.c'" '(should have been 367 characters)'
fi
echo shar: extracting "'sel.c'" '(20482 characters)'
if test -f 'sel.c'
then
echo shar: over-writing existing file "'sel.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'sel.c'
X/* SDB - select data from the database */
X
X#include "sdbio.h"
X
Xextern int dbv_token;
Xextern char dbv_tstring[];
Xextern int dbv_tvalue;
X
X/* db_select - select a set of tuples from a set of relations */
Xstruct sel *db_select(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
X char *fmt;
X{
X struct sel *slptr;
X
X /* check for a command line */
X if (fmt != NULL)
X db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);
X
X /* allocate a sel structure */
X if ((slptr = malloc(sizeof(struct sel))) == NULL)
X return (db_nerror(INSMEM));
X
X /* initialize the structure */
X slptr->sl_rels = NULL;
X slptr->sl_attrs = NULL;
X slptr->sl_where = NULL;
X slptr->sl_bindings = NULL;
X
X /* parse the list of selected attributes */
X if (!get_sattrs(slptr)) {
X db_done(slptr);
X return (NULL);
X }
X
X /* check for "from" clause */
X if (db_token() == FROM) {
X db_ntoken();
X if (!get_srels(slptr)) {
X db_done(slptr);
X return (NULL);
X }
X }
X else {
X if (!srelation(slptr,"sdbcur",NULL)) {
X db_done(slptr);
X return (NULL);
X }
X }
X
X /* check the list of selected attributes */
X if (!check_attrs(slptr)) {
X db_done(slptr);
X return (NULL);
X }
X
X /* check for the existance of a "where" clause */
X if (db_token() == WHERE) {
X db_ntoken();
X
X /* parse the boolean expression */
X if (!db_compile(slptr)) {
X db_done(slptr);
X return (FALSE);
X }
X }
X
X /* return the new selection structure */
X return (slptr);
X}
X
X/* db_retrieve - retrieve a set of tuples from a set of relations */
Xstruct sel *db_retrieve(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
X char *fmt;
X{
X struct sel *slptr;
X
X /* check for a command line */
X if (fmt != NULL)
X db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);
X
X /* allocate a sel structure */
X if ((slptr = malloc(sizeof(struct sel))) == NULL)
X return (db_nerror(INSMEM));
X
X /* initialize the structure */
X slptr->sl_rels = NULL;
X slptr->sl_attrs = NULL;
X slptr->sl_where = NULL;
X slptr->sl_bindings = NULL;
X
X /* check for selected relations clause */
X if (db_token() == ID) {
X if (!get_srels(slptr)) {
X db_done(slptr);
X return (NULL);
X }
X }
X else {
X if (!srelation(slptr,"sdbcur",NULL)) {
X db_done(slptr);
X return (NULL);
X }
X }
X
X /* check the list of selected attributes */
X if (!check_attrs(slptr)) {
X db_done(slptr);
X return (NULL);
X }
X
X /* check for the existance of a "where" clause */
X if (db_token() == WHERE) {
X db_ntoken();
X
X /* parse the boolean expression */
X if (!db_compile(slptr)) {
X db_done(slptr);
X return (FALSE);
X }
X }
X
X /* return the new selection structure */
X return (slptr);
X}
X
X/* db_done(slptr) - finish a selection */
Xdb_done(slptr)
X struct sel *slptr;
X{
X struct sattr *saptr,*nxtsa;
X struct srel *srptr,*nxtsr;
X struct binding *bdptr,*nxtbd;
X
X /* free the selected attribute blocks */
X for (saptr = slptr->sl_attrs; saptr != NULL; saptr = nxtsa) {
X nxtsa = saptr->sa_next;
X if (saptr->sa_rname != NULL)
X free(saptr->sa_rname);
X free(saptr->sa_aname);
X if (saptr->sa_name != NULL)
X free(saptr->sa_name);
X free(saptr);
X }
X
X /* close the scans and free the selected relation blocks */
X for (srptr = slptr->sl_rels; srptr != NULL; srptr = nxtsr) {
X nxtsr = srptr->sr_next;
X if (srptr->sr_name != NULL)
X free(srptr->sr_name);
X db_rclose(srptr->sr_scan);
X free(srptr);
X }
X
X /* free the where clause */
X db_fcode(slptr);
X
X /* free the user bindings */
X for (bdptr = slptr->sl_bindings; bdptr != NULL; bdptr = nxtbd) {
X nxtbd = bdptr->bd_next;
X free(bdptr);
X }
X
X /* free the selection structure */
X free(slptr);
X}
X
X/* db_fetch(slptr) - fetch the next tuple from a selection */
Xint db_fetch(slptr)
X struct sel *slptr;
X{
X struct srel *srptr;
X struct binding *bdptr;
X
X /* clear the update flags */
X for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next)
X srptr->sr_update = FALSE;
X
X /* find a matching tuple */
X while (process(slptr->sl_rels))
X if (db_interpret(slptr)) {
X for (bdptr = slptr->sl_bindings; bdptr != NULL; bdptr = bdptr->bd_next)
X db_aget(bdptr->bd_attr,bdptr->bd_vtuple,bdptr->bd_vuser);
X return (TRUE);
X }
X
X /* no matches, failure return */
X return (FALSE);
X}
X
X/* db_update - update modified tuples */
Xint db_update(slptr)
X struct sel *slptr;
X{
X struct srel *srptr;
X
X /* check each selected relation for updates */
X for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next)
X if (srptr->sr_update)
X if (!db_rupdate(srptr->sr_scan))
X return (FALSE);
X
X /* return successfully */
X return (TRUE);
X}
X
X/* db_store - store tuples */
Xint db_store(slptr)
X struct sel *slptr;
X{
X struct srel *srptr;
X
X /* check each selected relation for stores */
X for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next)
X if (srptr->sr_update)
X if (!db_rstore(srptr->sr_scan))
X return (FALSE);
X
X /* return successfully */
X return (TRUE);
X}
X
X/* db_bind - bind a user buffer to the value of an attribute */
Xint db_bind(slptr,rname,aname,avalue)
X struct sel *slptr; char *rname,*aname,*avalue;
X{
X struct binding *newbd;
X struct srel *srptr;
X
X /* allocate and initialize a binding structure */
X if ((newbd = malloc(sizeof(struct binding))) == NULL)
X return (db_ferror(INSMEM));
X newbd->bd_vuser = avalue;
X
X /* find the attribute */
X if (!find_attr(slptr,rname,aname,&newbd->bd_vtuple,&srptr,&newbd->bd_attr))
X return (FALSE);
X
X /* link the new binding into the binding list */
X newbd->bd_next = slptr->sl_bindings;
X slptr->sl_bindings = newbd;
X
X /* return successfully */
X return (TRUE);
X}
X
X/* db_get - get the value of an attribute */
Xint db_get(slptr,rname,aname,avalue)
X struct sel *slptr; char *rname,*aname,*avalue;
X{
X struct srel *srptr;
X struct attribute *aptr;
X char *vptr;
X
X /* find the attribute */
X if (!find_attr(slptr,rname,aname,&vptr,&srptr,&aptr))
X return (FALSE);
X
X /* get the attribute value */
X db_aget(aptr,vptr,avalue);
X
X /* return successfully */
X return (TRUE);
X}
X
X/* db_put - put the value of an attribute */
Xint db_put(slptr,rname,aname,avalue)
X struct sel *slptr; char *rname,*aname,*avalue;
X{
X struct srel *srptr;
X struct attribute *aptr;
X char *vptr;
X
X /* find the attribute */
X if (!find_attr(slptr,rname,aname,&vptr,&srptr,&aptr))
X return (FALSE);
X
X /* put the attribute value */
X db_aput(aptr,vptr,avalue);
X
X /* mark the tuple as updated */
X srptr->sr_update = TRUE;
X
X /* return successfully */
X return (TRUE);
X}
X
X/* db_sattr - get selected attribute type, pointer, and length */
Xint db_sattr(slptr,rname,aname,ptype,pptr,plen)
X struct sel *slptr; char *rname,*aname;
X int *ptype; char **pptr; int *plen;
X{
X struct srel *srptr;
X struct attribute *aptr;
X
X if (!find_attr(slptr,rname,aname,pptr,&srptr,&aptr))
X return (FALSE);
X *ptype = aptr->at_type;
X *plen = aptr->at_size;
X return (TRUE);
X}
X
X/* get_sattrs(slptr) - get selected attributes */
Xstatic get_sattrs(slptr)
X struct sel *slptr;
X{
X struct sattr *newsattr,*lastsattr;
X
X /* check for "*" or blank field meaning all attributes are selected */
X if (db_token() == '*') {
X db_ntoken();
X return (TRUE);
X }
X else if (db_token() != ID)
X return (TRUE);
X
X /* parse a list of attribute names */
X lastsattr = NULL;
X while (TRUE) {
X
X /* get attribute name */
X if (db_ntoken() != ID)
X return (db_ferror(SYNTAX));
X
X /* allocate a selected attribute structure */
X if ((newsattr = malloc(sizeof(struct sattr))) == NULL)
X return (db_ferror(INSMEM));
X
X /* initialize the selected attribute structure */
X newsattr->sa_next = NULL;
X
X /* save the attribute name */
X if ((newsattr->sa_aname = malloc(strlen(dbv_tstring)+1)) == NULL) {
X free(newsattr);
X return (db_ferror(INSMEM));
X }
X strcpy(newsattr->sa_aname,dbv_tstring);
X
X /* check for "." meaning "<rel-name>.<att-name>" */
X if (db_token() == '.') {
X db_ntoken();
X
X /* the previous ID was really the relation name */
X newsattr->sa_rname = newsattr->sa_aname;
X
X /* check for attribute name */
X if (db_ntoken() != ID) {
X free(newsattr->sa_aname); free(newsattr);
X return (db_ferror(SYNTAX));
X }
X
X /* save the attribute name */
X if ((newsattr->sa_aname = malloc(strlen(dbv_tstring)+1)) == NULL) {
X free(newsattr->sa_aname); free(newsattr);
X return (db_ferror(INSMEM));
X }
X strcpy(newsattr->sa_aname,dbv_tstring);
X }
X else
X newsattr->sa_rname = NULL;
X
X /* check for alternate attribute name */
X if (db_token() == ID) {
X db_ntoken();
X
X /* allocate space for the alternate name */
X if ((newsattr->sa_name = malloc(strlen(dbv_tstring)+1)) == NULL) {
X if (newsattr->sa_rname != NULL)
X free(newsattr->sa_rname);
X free(newsattr->sa_aname);
X free(newsattr);
X return (db_ferror(INSMEM));
X }
X strcpy(newsattr->sa_name,dbv_tstring);
X }
X else
X newsattr->sa_name = NULL;
X
X /* link the selected attribute structure into the list */
X if (lastsattr == NULL)
X slptr->sl_attrs = newsattr;
X else
X lastsattr->sa_next = newsattr;
X lastsattr = newsattr;
X
X /* check for more attributes */
X if (db_token() != ',')
X break;
X db_ntoken();
X }
X
X /* return successfully */
X return (TRUE);
X}
X
X/* get_srels(slptr) - get selected relations */
Xstatic get_srels(slptr)
X struct sel *slptr;
X{
X char rname[KEYWORDMAX+1],*aname;
X
X /* get the list of selected relations */
X while (TRUE) {
X
X /* check for relation name */
X if (db_ntoken() != ID)
X return (db_ferror(SYNTAX));
X strcpy(rname,dbv_tstring);
X
X /* check for alternate relation name */
X if (db_token() == ID) {
X db_ntoken();
X aname = dbv_tstring;
X }
X else
X aname = NULL;
X
X /* add the relation name to the list */
X if (!srelation(slptr,rname,aname))
X return (FALSE);
X
X /* check for more selected relations */
X if (db_token() != ',')
X break;
X db_ntoken();
X }
X
X /* return successfully */
X return (TRUE);
X}
X
X/* srelation - select a relation */
Xstatic srelation(slptr,rname,aname)
X struct sel *slptr; char *rname,*aname;
X{
X struct srel *srptr,*newsrel;
X
X /* allocate a new selected relation structure */
X if ((newsrel = malloc(sizeof(struct srel))) == NULL)
X return (db_ferror(INSMEM));
X
X /* initialize the new selected relation structure */
X newsrel->sr_ctuple = FALSE;
X newsrel->sr_update = FALSE;
X newsrel->sr_next = NULL;
X
X /* open the relation */
X if ((newsrel->sr_scan = db_ropen(rname)) == NULL) {
X free(newsrel);
X return (FALSE);
X }
X
X /* check for alternate relation name */
X if (aname != NULL) {
X
X /* allocate space for the alternate name */
X if ((newsrel->sr_name = malloc(strlen(aname)+1)) == NULL) {
X free(newsrel);
X return (db_ferror(INSMEM));
X }
X strcpy(newsrel->sr_name,aname);
X }
X else
X newsrel->sr_name = NULL;
X
X /* find the end of the list of relation names */
X for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next)
X if (srptr->sr_next == NULL)
X break;
X
X /* link the new selected relation structure into the list */
X if (srptr == NULL)
X slptr->sl_rels = newsrel;
X else
X srptr->sr_next = newsrel;
X
X /* return successfully */
X return (TRUE);
X}
X
X/* check_attrs(slptr) - check the list of selected attributes */
Xstatic int check_attrs(slptr)
X struct sel *slptr;
X{
X struct sattr *saptr;
X
X /* check for all attributes selected */
X if (slptr->sl_attrs == NULL)
X return (all_attrs(slptr));
X
X /* check each selected attribute */
X for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next)
X if (!find_attr(slptr,saptr->sa_rname,saptr->sa_aname,
X &saptr->sa_aptr,&saptr->sa_srel,&saptr->sa_attr))
X return (FALSE);
X
X /* return successfully */
X return (TRUE);
X}
X
X/* all_attrs(slptr) - create a list of all attributes */
Xstatic int all_attrs(slptr)
X struct sel *slptr;
X{
X struct sattr *newsattr,*lastsattr;
X struct srel *srptr;
X struct attribute *aptr;
X int i,astart;
X
X /* loop through each selected relation */
X lastsattr = NULL;
X for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next) {
X
X /* loop through each attribute within the relation */
X astart = 1;
X for (i = 0; i < NATTRS; i++) {
X
X /* get a pointer to the current attribute */
X aptr = &srptr->sr_scan->sc_relation->rl_header.hd_attrs[i];
X
X /* check for last attribute */
X if (aptr->at_name[0] == 0)
X break;
X
X /* allocate a new selected attribute structure */
X if ((newsattr = malloc(sizeof(struct sattr))) == NULL)
X return (db_ferror(INSMEM));
X
X /* initialize the new selected attribute structure */
X newsattr->sa_name = NULL;
X newsattr->sa_srel = srptr;
X newsattr->sa_aptr = srptr->sr_scan->sc_tuple + astart;
X newsattr->sa_attr = aptr;
X newsattr->sa_next = NULL;
X
X /* save the relation name */
X if ((newsattr->sa_rname = malloc(RNSIZE+1)) == NULL) {
X free(newsattr);
X return (db_ferror(INSMEM));
X }
X strncpy(newsattr->sa_rname,
X srptr->sr_scan->sc_relation->rl_name,
X RNSIZE);
X newsattr->sa_rname[RNSIZE] = 0;
X
X /* save the attribute name */
X if ((newsattr->sa_aname = malloc(ANSIZE+1)) == NULL) {
X free(newsattr->sa_rname);
X free(newsattr);
X return (db_ferror(INSMEM));
X }
X strncpy(newsattr->sa_aname,
X srptr->sr_scan->sc_relation->rl_header.hd_attrs[i].at_name,
X ANSIZE);
X newsattr->sa_aname[ANSIZE] = 0;
X
X /* link the selected attribute into the list */
X if (lastsattr == NULL)
X slptr->sl_attrs = newsattr;
X else
X lastsattr->sa_next = newsattr;
X lastsattr = newsattr;
X
X /* update the attribute start */
X astart += aptr->at_size;
X }
X }
X
X /* return successfully */
X return (TRUE);
X}
X
X/* find_attr - find a named attribute */
Xstatic int find_attr(slptr,rname,aname,paptr,psrel,pattr)
X struct sel *slptr; char *rname,*aname;
X char **paptr; struct attribute **pattr;
X{
X /* check for unqualified or qualified attribute names */
X if (rname == NULL)
X return (uattr(slptr,aname,paptr,psrel,pattr));
X else
X return (qattr(slptr,rname,aname,paptr,psrel,pattr));
X}
X
X/* uattr - find an unqualified attribute name */
Xstatic int uattr(slptr,aname,paptr,psrel,pattr)
X struct sel *slptr; char *aname;
X char **paptr; struct srel **psrel; struct attribute **pattr;
X{
X struct srel *srptr;
X struct attribute *aptr;
X int i,astart;
X
X /* loop through each selected relation */
X *pattr = NULL;
X for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next) {
X
X /* loop through each attribute within the relation */
X astart = 1;
X for (i = 0; i < NATTRS; i++) {
X
X /* get a pointer to the current attribute */
X aptr = &srptr->sr_scan->sc_relation->rl_header.hd_attrs[i];
X
X /* check for last attribute */
X if (aptr->at_name[0] == 0)
X break;
X
X /* check for attribute name match */
X if (db_sncmp(aname,aptr->at_name,ANSIZE) == 0) {
X if (*pattr != NULL)
X return (db_ferror(ATAMBG));
X *paptr = srptr->sr_scan->sc_tuple + astart;
X *psrel = srptr;
X *pattr = aptr;
X }
X
X /* update the attribute start */
X astart += aptr->at_size;
X }
X }
X
X /* check whether attribute was found */
X if (*pattr == NULL)
X return (db_ferror(ATUNDF));
X
X /* return successfully */
X return (TRUE);
X}
X
X/* qattr - find a qualified attribute name */
Xstatic int qattr(slptr,rname,aname,paptr,psrel,pattr)
X struct sel *slptr; char *rname,*aname;
X char **paptr; struct srel **psrel; struct attribute **pattr;
X{
X struct srel *srptr;
X struct attribute *aptr;
X char *crname;
X int i,astart;
X
X /* loop through each selected relation */
X for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next) {
X
X /* get relation name */
X if ((crname = srptr->sr_name) == NULL)
X crname = srptr->sr_scan->sc_relation->rl_name;
X
X /* check for relation name match */
X if (db_sncmp(rname,crname,RNSIZE) == 0) {
X
X /* loop through each attribute within the relation */
X astart = 1;
X for (i = 0; i < NATTRS; i++) {
X
X /* get a pointer to the current attribute */
X aptr = &srptr->sr_scan->sc_relation->rl_header.hd_attrs[i];
X
X /* check for last attribute */
X if (aptr->at_name[0] == 0)
X break;
X
X /* check for attribute name match */
X if (db_sncmp(aname,aptr->at_name,ANSIZE) == 0) {
X *paptr = srptr->sr_scan->sc_tuple + astart;
X *psrel = srptr;
X *pattr = aptr;
X return (TRUE);
X }
X
X /* update the attribute start */
X astart += aptr->at_size;
X }
X
X /* attribute name not found */
X return (db_ferror(ATUNDF));
X }
X }
X
X /* relation name not found */
X return (db_ferror(RLUNDF));
X}
X
X/* process(srptr) - process each tuple in a relation cross-product */
Xstatic int process(srptr)
X struct srel *srptr;
X{
X /* always get a new tuple if this is the last relation in the list */
X if (srptr->sr_next == NULL) {
X
X /* check for beginning of new scan */
X if (!srptr->sr_ctuple)
X db_rbegin(srptr->sr_scan);
X
X /* return the next tuple in the relation */
X return (srptr->sr_ctuple = db_rfetch(srptr->sr_scan));
X }
X
X /* check for beginning of new scan */
X if (!srptr->sr_ctuple) {
X db_rbegin(srptr->sr_scan);
X
X /* get the first tuple */
X if (!db_rfetch(srptr->sr_scan))
X return (FALSE);
X }
X
X /* look for a match with the remaining relations in list */
X while (!process(srptr->sr_next))
X
X /* get the next tuple in the scan */
X if (!db_rfetch(srptr->sr_scan))
X return (srptr->sr_ctuple = FALSE);
X
X /* found a match at this level */
X return (srptr->sr_ctuple = TRUE);
X}
X
X/* db_aget - get the value of an attribute */
Xdb_aget(aptr,vptr,avalue)
X struct attribute *aptr; char *vptr,*avalue;
X{
X int i;
X
X /* get the attribute value */
X for (i = 0; i < aptr->at_size; i++)
X *avalue++ = vptr[i];
X *avalue = EOS;
X}
X
X/* db_aput - put the value of an attribute */
Xdb_aput(aptr,vptr,avalue)
X struct attribute *aptr; char *vptr,*avalue;
X{
X int i;
X
X /* initialize counter */
X i = 0;
X
X /* right justify numbers */
X if (aptr->at_type == TNUM)
X for (; i < aptr->at_size - strlen(avalue); i++)
X vptr[i] = ' ';
X
X /* put the attribute value */
X for (; i < aptr->at_size; i++)
X if (*avalue == 0)
X vptr[i] = 0;
X else
X vptr[i] = *avalue++;
X}
X
SHAR_EOF
if test 20482 -ne "`wc -c 'sel.c'`"
then
echo shar: error transmitting "'sel.c'" '(should have been 20482 characters)'
fi
echo shar: extracting "'srt.c'" '(8289 characters)'
if test -f 'srt.c'
then
echo shar: over-writing existing file "'srt.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'srt.c'
X/* SDB - sort routines */
X
X#include "stdio.h"
X#include "sdbio.h"
X
Xextern int dbv_token;
Xextern char dbv_tstring[];
Xextern int dbv_tvalue;
X
X/* get_skeys - get sort key list */
Xstatic struct skey *get_skeys(sptr)
X struct scan *sptr;
X{
X struct skey *skeys,*newskey,*lastskey;
X
X /* parse a list of attribute names */
X skeys = lastskey = NULL;
X while (TRUE) {
X
X /* get attribute name */
X if (db_ntoken() != ID)
X return (db_nerror(SYNTAX));
X
X /* allocate a sort key structure */
X if ((newskey = malloc(sizeof(struct skey))) == NULL)
X return (db_nerror(INSMEM));
X
X /* initialize the sort key structure */
X newskey->sk_next = NULL;
X
X /* lookup the attribute name */
X if (!find_attr(sptr,newskey,dbv_tstring)) {
X free(newskey);
X return (NULL);
X }
X
X /* check for ascending or descending */
X if (db_token() == ASCENDING || dbv_token == DESCENDING) {
X newskey->sk_type = dbv_token;
X db_ntoken();
X }
X else
X newskey->sk_type = ASCENDING;
X
X /* link the sort key structure into the list */
X if (lastskey == NULL)
X skeys = newskey;
X else
X lastskey->sk_next = newskey;
X lastskey = newskey;
X
X /* check for more attributes */
X if (db_token() != ',')
X break;
X db_ntoken();
X }
X
X /* return successfully */
X return (skeys);
X}
X
X/* db_sort - sort tuples in a relation */
Xint *db_sort(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
X char *fmt;
X{
X struct scan *sptr1,*sptr2,*sptr3; /*dns*/
X struct skey *skeys;
X int result;
X
X /* check for a command line */
X if (fmt != NULL)
X db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);
X
X /* checks for relation name */
X if (db_token() == ID)
X db_ntoken();
X else
X strcpy(dbv_tstring,"sdbcur");
X
X /* open the relation */
X if ((sptr1 = db_ropen(dbv_tstring)) == NULL)
X return (FALSE);
X if ((sptr2 = db_ropen(dbv_tstring)) == NULL) {
X db_rclose(sptr1);
X return (FALSE);
X }
X if ((sptr3 = db_ropen(dbv_tstring)) == NULL) { /*dns*/
X db_rclose(sptr1); /*dns*/
X db_rclose(sptr2); /*dns*/
X return (FALSE); /*dns*/
X }
X
X /* checks for "<relation-name> by <sort-list>" */
X if (db_ntoken() != BY)
X return (db_ferror(SYNTAX));
X if ((skeys = get_skeys(sptr1)) == NULL) {
X db_rclose(sptr1);
X db_rclose(sptr2);
X db_rclose(sptr3); /*dns*/
X return (FALSE);
X }
X
X /* do the sort */
X result = sort(skeys,sptr1,sptr2,sptr3); /*dns*/
X
X /* close the relation */
X db_rclose(sptr1);
X db_rclose(sptr2);
X db_rclose(sptr3); /*dns*/
X
X /* free the sort keys */
X free_skeys(skeys);
X
X return (result);
X}
X
X/* free_skeys - free a list of sort keys */
Xstatic free_skeys(skeys)
X struct skey *skeys;
X{
X struct skey *thisskey;
X
X for (thisskey = skeys; skeys != NULL; thisskey = skeys) {
X skeys = skeys->sk_next;
X free(thisskey);
X }
X}
X
X/* find_attr - find an attribute */
Xstatic int find_attr(sptr,newskey,aname)
X struct scan *sptr; struct skey *newskey; char *aname;
X{
X struct attribute *aptr;
X int i,astart;
X
X /* loop through each attribute within the relation */
X astart = 1;
X for (i = 0; i < NATTRS; i++) {
X
X /* get a pointer to the current attribute */
X aptr = &sptr->sc_relation->rl_header.hd_attrs[i];
X
X /* check for last attribute */
X if (aptr->at_name[0] == 0)
X break;
X
X /* check for attribute name match */
X if (db_sncmp(aname,aptr->at_name,ANSIZE) == 0) {
X newskey->sk_start = astart;
X newskey->sk_aptr = aptr;
X return (TRUE);
X }
X
X /* update the attribute start */
X astart += aptr->at_size;
X }
X
X /* attribute name not found */
X return (db_ferror(ATUNDF));
X}
X
X/* sort - sort the relation */
Xstatic int sort(skeys,sptr1,sptr2,sptr3)
X struct skey *skeys; struct scan *sptr1,*sptr2,*sptr3;
X{
X/* unsigned int j,k,l,r; dns */
X long int passes,swaps; /*dns*/
X int i, j, m, n; /*dns*/
X int rec1 = 0; /*dns*/
X int rec2 = 0; /*dns*/
X int rec3 = 0; /*dns*/
X int dns = 0; /*dns*/
X FILE *test; /*dns*/
X
X passes = 0L;
X swaps = 0L;
X
X /*dns ---> */
X test = fopen("sort.dat", "w");
X n = sptr1->sc_relation->rl_tcnt;
X m = n;
X
X while( m>1 ) {
X passes++;
X if ((m/=3.14159) < 1) m = 1;
X for ( j=1; j<=n-m; j++ ) {
X if( rec1 != j+m ) {
X if(dns) fprintf(test,"Read1: %d\n", j+m);
X if (!db_rget(sptr1, rec1=j+m)) return (FALSE);
X }
X for ( i=j; i>=1; i-=m ) {
X if( rec2 != i ) {
X if(dns) fprintf(test,"Read2: %d\n", i);
X if (!db_rget(sptr2, rec2=i)) return (FALSE);
X }
X if (compare(skeys,sptr1,sptr2) > 0)
X break;
X if(rec3 != i+m) {
X if(dns) fprintf(test,"Read3: %d\n", i+m);
X if (!db_rget(sptr3, rec3=i+m)) return (FALSE);
X }
X if(dns) fprintf(test,"Write 3,2: %d from %d\n", i+m, i);
X assign( sptr3, sptr2 );
X swaps++;
X }
X if(rec1 != i+m) {
X if(rec3 != i+m) {
X if(dns) fprintf(test,"Read 3: %d\n", i+m);
X if (!db_rget(sptr3, rec3=i+m)) return (FALSE);
X }
X if(dns) fprintf(test,"Write 3,1: %d from %d\n", i+m, j+m);
X assign( sptr3, sptr1 );
X swaps++;
X }
X }
X }
X fclose(test);
X
X/*
X l = 2;
X r = sptr1->sc_relation->rl_tcnt;
X k = r;
X
X do {
X for (j = r; j >= l; j--) {
X if (!db_rget(sptr1,j-1))
X return (FALSE);
X if (!db_rget(sptr2,j))
X return (FALSE);
X if (compare(skeys,sptr1,sptr2) > 0) {
X swap(sptr1,sptr2);
X k = j;
X swaps++;
X }
X }
X l = k + 1;
X for (j = l; j <= r; j++) {
X if (!db_rget(sptr1,j-1))
X return (FALSE);
X if (!db_rget(sptr2,j))
X return (FALSE);
X if (compare(skeys,sptr1,sptr2) > 0) {
X swap(sptr1,sptr2);
X k = j;
X swaps++;
X }
X }
X r = k - 1;
X passes++;
X } while (l <= r);
X*/
X
X printf("[ Passes: %ld Swaps: %ld ]\n",passes,swaps);
X
X return (TRUE);
X}
X
X/* compare - compare two tuples */
Xstatic int compare(skeys,sptr1,sptr2)
X struct skey *skeys; struct scan *sptr1,*sptr2;
X{
X struct skey *cskey;
X int result;
X
X for (cskey = skeys; cskey != NULL; cskey = cskey->sk_next)
X if ((result = cattr(cskey,sptr1,sptr2)) != 0)
X break;
X
X return (result);
X}
X
X/* cattr - compare two attributes */
Xstatic int cattr(cskey,sptr1,sptr2)
X struct skey *cskey; struct scan *sptr1,*sptr2;
X{
X int astart,aend,i;
X
X astart = cskey->sk_start;
X aend = astart + cskey->sk_aptr->at_size;
X
X for (i = astart; i < aend; i++)
X if (sptr1->sc_tuple[i] != sptr2->sc_tuple[i])
X break;
X
X if (i == aend)
X return (0);
X
X if (sptr1->sc_tuple[i] < sptr2->sc_tuple[i])
X if (cskey->sk_type == ASCENDING)
X return (-1);
X else
X return (1);
X else
X if (cskey->sk_type == ASCENDING)
X return (1);
X else
X return (-1);
X}
X
X/* swap - swap two tuples */
X/* dns
Xstatic int swap(sptr1,sptr2)
X struct scan *sptr1,*sptr2;
X{
X unsigned int tnum1,tnum2;
X
X tnum1 = sptr1->sc_atnum;
X tnum2 = sptr2->sc_atnum;
X
X if (!db_rput(sptr1,tnum2))
X return (FALSE);
X if (!db_rput(sptr2,tnum1))
X return (FALSE);
X
X return (TRUE);
X}
X dns */
X
X
X/* assign - assign one tupple to another */
Xstatic int assign(sptr1,sptr2)
X struct scan *sptr1,*sptr2;
X{
X unsigned int tnum1,tnum2;
X
X tnum1 = sptr1->sc_atnum;
X
X if (!db_rput(sptr2,tnum1))
X return (FALSE);
X
X return (TRUE);
X}
X
SHAR_EOF
if test 8289 -ne "`wc -c 'srt.c'`"
then
echo shar: error transmitting "'srt.c'" '(should have been 8289 characters)'
fi
echo shar: extracting "'tbl.c'" '(2554 characters)'
if test -f 'tbl.c'
then
echo shar: over-writing existing file "'tbl.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'tbl.c'
X/* SDB - table output routines */
X
X#include "stdio.h"
X#include "sdbio.h"
X
Xstatic char buffer[TABLEMAX+1];
Xint bndx;
X
X/* db_thead - print a table header */
Xdb_thead(fp,slptr)
X FILE *fp; struct sel *slptr;
X{
X struct sattr *saptr;
X int twidth,fwidth,i;
X char *aname;
X
X /* compute the table width */
X twidth = 1;
X for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next)
X twidth += saptr->sa_attr->at_size + 3;
X
X /* print the top line of the table */
X bstart();
X for (i = 0; i < twidth; i++)
X binsert('-');
X bprint(fp);
X
X /* print the label line of the table */
X bstart();
X for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {
X fwidth = saptr->sa_attr->at_size;
X binsert('|'); binsert(' ');
X if ((aname = saptr->sa_name) == NULL)
X aname = saptr->sa_aname;
X for (i = 0; i < fwidth; i++)
X if (*aname != 0)
X binsert(*aname++);
X else
X binsert(' ');
X binsert(' ');
X }
X binsert('|');
X bprint(fp);
X
X /* print the line under the labels */
X bstart();
X for (i = 0; i < twidth; i++)
X binsert('-');
X bprint(fp);
X}
X
X/* db_tfoot - print a table foot */
Xdb_tfoot(fp,slptr)
X FILE *fp; struct sel *slptr;
X{
X struct sattr *saptr;
X int twidth,i;
X
X /* compute the table width */
X twidth = 1;
X for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next)
X twidth += saptr->sa_attr->at_size + 3;
X
X /* print the line at the foot of the table */
X bstart();
X for (i = 0; i < twidth; i++)
X binsert('-');
X bprint(fp);
X}
X
X/* db_tentry - print a table entry */
Xdb_tentry(fp,slptr)
X FILE *fp; struct sel *slptr;
X{
X struct sattr *saptr;
X int fwidth,i;
X
X /* print a table entry */
X bstart();
X for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {
X fwidth = saptr->sa_attr->at_size;
X binsert('|'); binsert(' ');
X for (i = 0; i < fwidth; i++)
X if (saptr->sa_aptr[i] != 0)
X binsert(saptr->sa_aptr[i]);
X else
X binsert(' ');
X binsert(' ');
X }
X binsert('|');
X bprint(fp);
X}
X
X/* bstart - start building a line */
Xstatic bstart()
X{
X bndx = 0;
X}
X
X/* binsert - insert a character into the buffer */
Xstatic binsert(ch)
X int ch;
X{
X if (bndx < TABLEMAX)
X buffer[bndx++] = ch;
X}
X
X/* bprint - print the current line */
Xstatic bprint(fp)
X FILE *fp;
X{
X buffer[bndx] = EOS;
X fprintf(fp,"%s\n",buffer);
X}
X
SHAR_EOF
if test 2554 -ne "`wc -c 'tbl.c'`"
then
echo shar: error transmitting "'tbl.c'" '(should have been 2554 characters)'
fi
echo shar: extracting "'sdbio.h'" '(7764 characters)'
if test -f 'sdbio.h'
then
echo shar: over-writing existing file "'sdbio.h'"
fi
sed 's/^X//' << \SHAR_EOF > 'sdbio.h'
X/* SDB - definition file */
X
X#include "ctype.h" /*dns*/
X
X/* compiler specific stuff (dns) */
X#define Lattice
X
X/* useful definitions */
X#define TRUE 1
X#define FALSE 0
X#ifndef NULL
X#define NULL 0
X#endif
X
X/* Character definitions (dns) */
X#define BS 0x8 /*dns*/
X#define CR 0xD /*dns*/
X#define FF 0xC /*dns*/
X#define ESC 0x1B /*dns*/
X
X/* program limits */
X#define LINEMAX 132 /* maximum input line length */
X#define TABLEMAX 132 /* maximum table output line */
X#define KEYWORDMAX 10 /* maximum keyword length */
X#define NUMBERMAX 20 /* maximum number length */
X#define STRINGMAX 132 /* maximum string length */
X#define CODEMAX 100 /* maximum length of code array */
X#define STACKMAX 20 /* maximum interpreter stack size */
X
X/* token definitions */
X#define EOS 0
X#define LSS -1
X#define LEQ -2
X#define EQL -3
X#define NEQ -4
X#define GEQ -5
X#define GTR -6
X#define SELECT -7
X#define FROM -8
X#define WHERE -9
X#define CREATE -10
X#define DELETE -11
X#define INSERT -12
X#define EXIT -13
X#define CHAR -14
X#define NUM -15
X#define ID -16
X#define STRING -17
X#define NUMBER -18
X#define UPDATE -19
X#define PRINT -20
X#define IMPORT -21
X#define EXPORT -22
X#define INTO -23
X#define HELP -24
X#define COMPRESS -25
X#define EXTRACT -26
X#define DEFINE -27
X#define SHOW -28
X#define USING -29
X#define SORT -30
X#define BY -31
X#define ASCENDING -32
X#define DESCENDING -33
X#define SET -34
X
X/* operand types */
X#define LITERAL 1
X#define ATTR 2
X#define TEMP 3
X
X/* attribute data types */
X#define TCHAR 1
X#define TNUM 2
X
X/* tuple status codes */
X#define UNUSED 0
X#define ACTIVE 1
X#define DELETED 2
X
X/* relation header page format definitions */
X#define RNSIZE 10 /* size of a relation name */
X#define HSIZE 16 /* size of a relation entry */
X#define ASIZE 16 /* size of a attribute entry */
X#define ANSIZE 10 /* size of a attribute name */
X#define NATTRS 31 /* number of attributes in header block */
X
X/* error code definitions */
X#define END 0 /* end of retrieval set */
X#define INSMEM 1 /* insufficient memory */
X#define RELFNF 2 /* relation file not found */
X#define BADHDR 3 /* bad relation file header */
X#define TUPINP 4 /* tuple input error */
X#define TUPOUT 5 /* tuple output error */
X#define RELFUL 6 /* relation file full */
X#define RELCRE 7 /* error creating relation file */
X#define DUPATT 8 /* duplicate attribute on relation create */
X#define MAXATT 9 /* too many attributes on relation create */
X#define INSBLK 10 /* insufficient disk blocks */
X#define SYNTAX 11 /* command syntax error */
X#define ATUNDF 12 /* attribute name undefined */
X#define ATAMBG 13 /* attribute name ambiguous */
X#define RLUNDF 14 /* relation name undefined */
X#define CDSIZE 15 /* boolean expression code too big */
X#define INPFNF 16 /* input file not found */
X#define OUTCRE 17 /* output file creation error */
X#define INDFNF 18 /* indirect command file not found */
X#define BADSET 19 /* bad set parameter */
X
Xstruct attribute {
X char at_name[ANSIZE]; /* attribute name */
X char at_type; /* attribute type */
X char at_size; /* attribute size in bytes */
X char at_scale; /* attribute scale factor (for numeric only) */
X char at_unused[ASIZE-ANSIZE-3]; /* unused space */
X};
X
Xstruct header { /* sizeof(struct header) must be 512 bytes */
X char hd_tcnt[2]; /* # of tuples in relation */
X char hd_tmax[2]; /* maximum # of tuples */
X char hd_data[2]; /* offset to first data byte */
X char hd_size[2]; /* size of each tuple in bytes */
X char hd_unused[HSIZE-8]; /* unused space */
X struct attribute hd_attrs[NATTRS]; /* table of attributes */
X};
X
Xstruct relation {
X char rl_name[RNSIZE]; /* relation name */
X unsigned int rl_tcnt; /* # of tuples in relation (from hd_tcnt) */
X unsigned int rl_tmax; /* maximum # of tuples (from hd_tmax) */
X int rl_data; /* offset to first data byte (from hd_data) */
X int rl_size; /* size of eachtuple in bytes (from hd_size) */
X int rl_store; /* flag indicating a store happened */
X int rl_fd; /* file descriptor for relation file */
X int rl_scnref; /* number of scans referencing this relation */
X struct header rl_header; /* the relation file header block */
X struct relation *rl_next; /* pointer to next relation */
X};
X
Xstruct scan {
X struct relation *sc_relation; /* pointer to relation definition */
X unsigned int sc_dtnum; /* desired tuple number */
X unsigned int sc_atnum; /* actual tuple number */
X int sc_store; /* flag indicating a store happened */
X char *sc_tuple; /* tuple buffer */
X};
X
Xstruct srel {
X char *sr_name; /* alternate relation name */
X struct scan *sr_scan; /* relation scan structure ptr */
X int sr_ctuple; /* current tuple flag */
X int sr_update; /* updated tuple flag */
X struct srel *sr_next; /* next selected relation in list */
X};
X
Xstruct sattr {
X char *sa_rname; /* relation name */
X char *sa_aname; /* attribute name */
X char *sa_name; /* alternate attribute name */
X char *sa_aptr; /* pointer to attr in tuple buffer */
X struct srel *sa_srel; /* pointer to the selected relation */
X struct attribute *sa_attr; /* attribute structure ptr */
X struct sattr *sa_next; /* next selected attribute in list */
X};
X
Xstruct operand {
X int o_type;
X union {
X struct {
X int ovc_type;
X char *ovc_string;
X int ovc_length;
X } ov_char;
X int ov_boolean;
X } o_value;
X};
X
Xunion codecell {
X int (*c_operator)();
X struct operand *c_operand;
X};
X
Xstruct binding {
X struct attribute *bd_attr; /* bound attribute */
X char *bd_vtuple; /* pointer to value in tuple */
X char *bd_vuser; /* pointer to user buffer */
X struct binding *bd_next; /* next binding */
X};
X
Xstruct sel {
X struct srel *sl_rels; /* selected relations */
X struct sattr *sl_attrs; /* selected attributes */
X union codecell *sl_where; /* where clause */
X struct binding *sl_bindings; /* user variable bindings */
X};
X
Xstruct mtext {
X char *mt_text;
X struct mtext *mt_next;
X};
X
Xstruct macro {
X char *mc_name;
X struct mtext *mc_mtext;
X struct macro *mc_next;
X};
X
Xstruct ifile {
X char *if_fp;
X struct mtext *if_mtext;
X char *if_cmdline;
X int if_savech;
X char *if_lptr;
X struct ifile *if_next;
X};
X
Xstruct skey {
X int sk_type;
X struct attribute *sk_aptr;
X int sk_start;
X struct skey *sk_next;
X};
X
SHAR_EOF
if test 7764 -ne "`wc -c 'sdbio.h'`"
then
echo shar: error transmitting "'sdbio.h'" '(should have been 7764 characters)'
fi
# End of shell archive
exit 0
--
Usenet: [decvax|allegra|linus|ihnp4]!utzoo!yetti!oz
Bitnet: oz@[yusol|yuyetti]
You see things; and you say "WHY?"
But I dream things that never were;
and say "WHY NOT?"
G. Bernard Shaw (Back to Methuselah)
More information about the Comp.sources.unix
mailing list