🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: mod.amiga.sources
1 messages
1 total messages Started by doc Fri, 22 Aug 1986 22:45
sdb Database (1 of 3)
#24
Author: doc
Date: Fri, 22 Aug 1986 22:45
2105 lines
54647 bytes
    [ moderators note:  Makefile included should work with Aztec C.  The file
    pcjunk.c was for IBM pc stuff.  It should not be needed, but it put in
    for completeness...  Note it is not included in OBJ in makefile ]


I found this on the Spring 1984 DECUS VAX SIG tape.  I compiled it
on my Amiga with Lattice C version 3.03, encountering no problems
that I can remember (but it's been a few months since then...).  Since
it was written to run on a 16-bit machine to start with, there shouldn't
be any real problems compiling it with Manx Aztec using 16-bit ints.

I have made one change to what I found on the tape: when printing out
a tuple using a form (.FRM) definition, you can use a dollar sign at
the beginning of an attribute to indicate that no padding should be
done. This helps when preparing things like form letters, where you
definitely *don't* want the records to be padded.

To build SDB, compile *.c into *.o, then ALink WITH sdb.lnk.

Enjoy!

Mic Kaczmarczik
User Services Digital Support Group
University of Texas at Austin Computation Center

UUCP:	...!ihnp4!seismo!ut-sally!ut-ngp!mic
ARPA:	mic@ngp.cc.utexas.edu
	cc.kaczmarczik@a20.cc.utexas.edu

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	readme
#	readme.too
#	aaareadme.txt
#	Makefile
#	sdb.lnk
#	sdb.c
#	sdb.hlp
#	pcjunk.c
#	junk.c
#	tbl.c
#	iex.c
#	mth.c
#	sdbio.h
#	srt.c
#	com.c
# This archive created: Fri Aug 22 17:39:24 1986
# By:	Craig Norborg (Purdue University Computing Center)
cat << \SHAR_EOF > readme


     SDB was obtained from the CNODE bulletin board at 617-470-2548
     in Amherst, Mass.  It was converted to the IBM PC using the Lattice
     C Compiler.

     To try some other compiler or system, see comments and settings in
     the front of SDBIO.H and things in PCJUNK.C.

     David N. Smith
     44 Ole Musket Lane
     Danbury, CT 06810

     24 January 1984

SHAR_EOF
cat << \SHAR_EOF > readme.too
I found this on the Spring 1984 DECUS VAX SIG tape.  I compiled it
on my Amiga with Lattice C version 3.03, encountering no problems
that I can remember (but it's been a few months since then...).  Since
it was written to run on a 16-bit machine to start with, there shouldn't
be any real problems compiling it with Manx Aztec using 16-bit ints.

I have made one change to what I found on the tape: when printing out
a tuple using a form (.FRM) definition, you can use a dollar sign at
the beginning of an attribute to indicate that no padding should be
done. This helps when preparing things like form letters, where you
definitely *don't* want the records to be padded.

To build SDB, compile *.c into *.o, then ALink WITH sdb.lnk.

Enjoy!

Mic Kaczmarczik
User Services Digital Support Group
University of Texas at Austin Computation Center

UUCP:	...!ihnp4!seismo!ut-sally!ut-ngp!mic
ARPA:	mic@ngp.cc.utexas.edu
	cc.kaczmarczik@a20.cc.utexas.edu
SHAR_EOF
cat << \SHAR_EOF > aaareadme.txt
This area contains a simple DBMS system in C. Originally for VAX, it
has been somewhat modified for IBMPC but since full sources are
here, it shouldn't be too hard to change back if anyone needs it.
	From a PC-sig disk (#147).
SHAR_EOF
cat << \SHAR_EOF > Makefile
SRC =   cmd.c com.c cre.c err.c iex.c int.c io.c junk.c mth.c pcjunk.c \
	scn.c sdb.c sel.c srt.c tbl.c
OBJ =   cmd.o com.o cre.o err.o iex.o int.o io.o junk.o mth.o \
	scn.o sdb.o sel.o srt.o tbl.o
HDR =	sdbio.h
FILES = aaareadme.txt readme readme.too sdb.hlp sdb.lnk sdb.mem

all: sdb

sdb: $(OBJ)
	cc $(CFLAGS) $(OBJ) -o sdb

cmd.o: cmd.c sdbio.h

com.o: com.c sdbio.h

cre.o: cre.c sdbio.h

err.o: err.c sdbio.h

iex.o: iex.c sdbio.h

int.o: int.c sdbio.h

io.o: io.c sdbio.h

junk.o: junk.c sdbio.h

mth.o: mth.c

pcjunk.o: pcjunk.c sdbio.h

scn.o: scn.c sdbio.h

sdb.o: sdb.c sdbio.h

sel.o: sdbio.h sel.c

srt.o: sdbio.h srt.c

tbl.o: sdbio.h tbl.c
SHAR_EOF
cat << \SHAR_EOF > sdb.lnk
FROM df0:lib/Lstartup.obj,*
int.o,*
cmd.o,*
sel.o,*
tbl.o,*
mth.o,*
scn.o,*
err.o,*
cre.o,*
iex.o,*
io.o,*
srt.o,*
com.o,*
junk.o,*
sdb.o
TO SDB
LIBRARY df0:lib/lc.lib,df0:lib/amiga.lib
SHAR_EOF
cat << \SHAR_EOF > sdb.c
/* SDB - main routine */

#include <stdio.h>
#include "sdbio.h"

extern int dbv_errcode;

main()
{
    printf("SDB - version 2.0\n");
    db_sinit();
    db_ifile("sdb.ini");

    while (TRUE) {
        db_prompt("SDB> ","\t> ");
        if (!db_parse(NULL)) {
            printf("** error: %s ***\n",db_ertxt(dbv_errcode));
            db_kill();
        }
    }
}

SHAR_EOF
cat << \SHAR_EOF > sdb.hlp
create <rname> ( <adefs> ) <size>       - create a new relation
insert <rname>                          - insert tuples into a relation
delete <rse> ;                          - delete tuples from relations
update <anames> from <rse> ;            - update tuples within a relation
print [<u>] <anames> from <rse> [<i>] ; - print tuples
sort <rname> by <snames> ;              - sort a relation file
import <fname> into <rname>             - import tuples from a file
export <rname> [<i>] ;                  - export tuples to a file
extract <rname> [<i>] ;                 - extract definition to a file
compress <rname>                        - compress a relation file
define <mname>                          - define a macro
exit                                    - exit SDB

<u>             ::=     using <fname>
<i>             ::=     into <fname>
<adefs>         ::=     <a list of attribute definitions>
<rse>           ::=     <rnames> [where <boolean-expression>]
<rname>         ::=     <a relation name>
<rnames>        ::=     <a comma separated list of <rname>s>
<aname>         ::=     [<rname> .] <an attribute name>
<anames>        ::=     * | <a comma separated list of <aname>s>
<sname>         ::=     <aname> { ascending | descending }
<snames>        ::=     <a comma separated list of <sname>s>
SHAR_EOF
cat << \SHAR_EOF > pcjunk.c
/*  PCJUNK.C     Misc. procedures */

#include "stdio.h"
#include "sdbio.h"

/*    Replaces JUNK.C for the IBM/PC version            dns */


char *alloc(n)
int n;
{
   return (char*) malloc(n);
}


int getcx(fp)
  FILE *fp;
{
    static char buf[LINEMAX] = {0};
    static char *pbuf = buf;
    int ch, i;

    if (fp!=stdin)
       if ((ch = getc(fp)) == '\r')
          return getc(fp);
       else
          return ch;

    if (*pbuf > 0)
       return *pbuf++;

    pbuf = buf;
    for (i = 0; (ch = getc(fp)) != -1; )
        if (i < LINEMAX)  {
            if (ch == ESC)     { i=0;  putchar('\n'); fflush(stdout); }  else
            if (ch == BS)      { if (i>0)  i--;                       }  else
               buf[i++] = ch;
            if (ch == '\n')    break;
            }
        else {
            printf("*** line too long ***\nRetype> ");
            i = 0;
        }
    buf[i] = EOS;
    return getcx(fp);
}



/*    string copy up to n characters    */
strncpy(to, from, n)
char *to, *from;
int n;
{
  char *cp;

  for( cp=to; n-- && (*cp++ = *from++);  ) ;
  if( n<0 )   *cp = 0;
  return to;
}


/*    string compare up to n characters     */
strncmp(s1, s2, n)
char *s1, *s2;
int n;
{

  for( ;n-- && (*s1==*s2); s2++ )
     if( !*s1++ )
        return 0;
  if( n < 0 )
     return 0;
  if( *s1 < *s2 )
     return -1;
  return 1;
}
SHAR_EOF
cat << \SHAR_EOF > junk.c
/*  PCJUNK.C     Misc. procedures */

#include <stdio.h>
#include "sdbio.h"

/*    Replaces JUNK.C for the IBM/PC version            dns */


char *alloc(n)
int n;
{
   return (char*) malloc(n);
}


int getcx(fp)
  FILE *fp;
{
#ifdef Lattice
    static char buf[LINEMAX] = {0};
    static char *pbuf = buf;
    int ch, i;

    if (fp!=stdin)
       if ((ch = getc(fp)) == '\r')
          return getc(fp);
       else
          return ch;

    if (*pbuf > 0)
       return *pbuf++;

    pbuf = buf;
    for (i = 0; (ch = getc(fp)) != -1; )
        if (i < LINEMAX)  {
            if (ch == ESC)     { i=0;  putchar('\n'); fflush(stdout); }  else
            if (ch == BS)      { if (i>0)  i--;                       }  else
               buf[i++] = ch;
            if (ch == '\n')    break;
            }
        else {
            printf("*** line too long ***\nRetype> ");
            i = 0;
        }
    buf[i] = EOS;
    return getcx(fp);
#else
    return(getc(fp));
#endif
}



/*    string copy up to n characters    */
#ifdef Lattice
strncpy(to, from, n)
char *to, *from;
int n;
{
  char *cp;

  for( cp=to; n-- && (*cp++ = *from++);  ) ;
  if( n<0 )   *cp = 0;
  return to;
}


/*    string compare up to n characters     */
strncmp(s1, s2, n)
char *s1, *s2;
int n;
{

  for( ;n-- && (*s1==*s2); s2++ )
     if( !*s1++ )
        return 0;
  if( n < 0 )
     return 0;
  if( *s1 < *s2 )
     return -1;
  return 1;
}
#endif


SHAR_EOF
cat << \SHAR_EOF > tbl.c
/* SDB - table output routines */

#include <stdio.h>
#include "sdbio.h"

static char buffer[TABLEMAX+1];
int bndx;

/* db_thead - print a table header */
db_thead(fp,slptr)
  FILE *fp; struct sel *slptr;
{
    struct sattr *saptr;
    int twidth,fwidth,i;
    char *aname;

    /* compute the table width */
    twidth = 1;
    for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next)
        twidth += saptr->sa_attr->at_size + 3;

    /* print the top line of the table */
    bstart();
    for (i = 0; i < twidth; i++)
        binsert('-');
    bprint(fp);

    /* print the label line of the table */
    bstart();
    for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {
        fwidth = saptr->sa_attr->at_size;
        binsert('|'); binsert(' ');
        if ((aname = saptr->sa_name) == NULL)
            aname = saptr->sa_aname;
        for (i = 0; i < fwidth; i++)
            if (*aname != 0)
                binsert(*aname++);
            else
                binsert(' ');
        binsert(' ');
    }
    binsert('|');
    bprint(fp);

    /* print the line under the labels */
    bstart();
    for (i = 0; i < twidth; i++)
        binsert('-');
    bprint(fp);
}

/* db_tfoot - print a table foot */
db_tfoot(fp,slptr)
  FILE *fp; struct sel *slptr;
{
    struct sattr *saptr;
    int twidth,i;

    /* compute the table width */
    twidth = 1;
    for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next)
        twidth += saptr->sa_attr->at_size + 3;

    /* print the line at the foot of the table */
    bstart();
    for (i = 0; i < twidth; i++)
        binsert('-');
    bprint(fp);
}

/* db_tentry - print a table entry */
db_tentry(fp,slptr)
  FILE *fp; struct sel *slptr;
{
    struct sattr *saptr;
    int fwidth,i;

    /* print a table entry */
    bstart();
    for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {
        fwidth = saptr->sa_attr->at_size;
        binsert('|'); binsert(' ');
        for (i = 0; i < fwidth; i++)
            if (saptr->sa_aptr[i] != 0)
                binsert(saptr->sa_aptr[i]);
            else
                binsert(' ');
        binsert(' ');
    }
    binsert('|');
    bprint(fp);
}

/* bstart - start building a line */
static bstart()
{
    bndx = 0;
}

/* binsert - insert a character into the buffer */
static binsert(ch)
  int ch;
{
    if (bndx < TABLEMAX)
        buffer[bndx++] = ch;
}

/* bprint - print the current line */
static bprint(fp)
  FILE *fp;
{
    buffer[bndx] = EOS;
    fprintf(fp,"%s\n",buffer);
}
SHAR_EOF
cat << \SHAR_EOF > iex.c
/* SDB - import/export command routines */

#include <stdio.h>
#include "sdbio.h"

extern int dbv_token;
extern char dbv_tstring[];
extern int dbv_tvalue;

/* db_import - import tuples from a file */
int *db_import(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
  char *fmt;
{
    struct scan *sptr;
    struct attribute *aptr;
    char fname[STRINGMAX+1],avalue[STRINGMAX+1];
    int tcnt,astart,i,eofile;
    FILE *fp;

    /* check for a command line */
    if (fmt != NULL)
        db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);

    /* checks for "<filename> into <relation-name>" */
    if (db_ntoken() == ID)
        strcat(dbv_tstring,".dat");
    else if (dbv_token != STRING)
        return (db_ferror(SYNTAX));
    strcpy(fname,dbv_tstring);
    if (db_ntoken() != INTO)
        return (db_ferror(SYNTAX));
    if (db_ntoken() != ID)
        return (db_ferror(SYNTAX));

    /* open the relation */
    if ((sptr = db_ropen(dbv_tstring)) == NULL)
        return (FALSE);

    /* open the input file */
    if ((fp = fopen(fname,"r")) == NULL)
        return (db_ferror(INPFNF));

    /* import tuples */
    eofile = FALSE;
    for (tcnt = 0; ; tcnt++) {

        /* get attribute values */
        astart = 1;
        for (i = 0; i < NATTRS; i++) {

            /* get a pointer to the current attribute */
            aptr = &sptr->sc_relation->rl_header.hd_attrs[i];

            /* check for the last attribute */
            if (aptr->at_name[0] == 0)
                break;

            /* input the tuple */
            if (fgets(avalue,STRINGMAX,fp) == 0) {
                eofile = TRUE;
                break;
            }
            avalue[strlen(avalue)-1] = EOS;

            /* store the attribute value */
            db_aput(aptr,&sptr->sc_tuple[astart],avalue);

            /* update the attribute start */
            astart += aptr->at_size;
        }

        /* store the new tuple */
        if (!eofile) {
            if (!db_rstore(sptr)) {
                db_rclose(sptr);
                return (FALSE);
            }
        }
        else
            break;
    }

    /* close the relation */
    db_rclose(sptr);

    /* close the input file */
    fclose(fp);

    /* check number of tuples imported */
    if (tcnt != 0) {

        /* print tuple count */
        printf("[ %d imported ]\n",tcnt);
    }
    else
        printf("[ none imported ]\n");

    /* return successfully */
    return (TRUE);
}

/* db_export - export tuples to a file */
int *db_export(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
  char *fmt;
{
    struct scan *sptr;
    struct attribute *aptr;
    char rname[STRINGMAX+1],avalue[STRINGMAX+1];
    int tcnt,astart,i;
    FILE *fp;

    /* check for a command line */
    if (fmt != NULL)
        db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);

    /* checks for "<relation-name> [ into <filename> ]" */
    if (db_ntoken() != ID)
        return (db_ferror(SYNTAX));
    strcpy(rname,dbv_tstring);
    if (!db_to(&fp,".dat"))
        return (FALSE);

    /* open the relation */
    if ((sptr = db_ropen(rname)) == NULL)
        return (FALSE);

    /* export tuples */
    for (tcnt = 0; db_rfetch(sptr); tcnt++) {

        /* get attribute values */
        astart = 1;
        for (i = 0; i < NATTRS; i++) {

            /* get a pointer to the current attribute */
            aptr = &sptr->sc_relation->rl_header.hd_attrs[i];

            /* check for the last attribute */
            if (aptr->at_name[0] == 0)
                break;

            /* get the attribute value */
            db_aget(aptr,&sptr->sc_tuple[astart],avalue);

            /* output the tuple */
            fprintf(fp,"%s\n",avalue);

            /* update the attribute start */
            astart += aptr->at_size;
        }
    }

    /* close the relation */
    db_rclose(sptr);

    /* close the output file */
    if (fp != stdout)
        fclose(fp);

    /* check number of tuples exported */
    if (tcnt != 0) {

        /* print tuple count */
        printf("[ %d exported ]\n",tcnt);
    }
    else
        printf("[ none exported ]\n");

    /* return successfully */
    return (TRUE);
}

/* db_squeeze - squeeze deleted tuples from a relation file */
int *db_squeeze(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
  char *fmt;
{
    struct scan *sptr;

    /* check for a command line */
    if (fmt != NULL)
        db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);

    /* checks for "<relation-name>" */
    if (db_ntoken() != ID)
        return (db_ferror(SYNTAX));

    /* open the relation */
    if ((sptr = db_ropen(dbv_tstring)) == NULL)
        return (FALSE);

    /* compress the relation file */
    if (!db_rcompress(sptr)) {
        db_rclose(sptr);
        return (FALSE);
    }

    /* close the relation */
    db_rclose(sptr);

    /* return successfully */
    return (TRUE);
}

/* db_extract - extract a relation definition */
int *db_extract(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
  char *fmt;
{
    struct scan *sptr;
    struct attribute *aptr;
    char rname[STRINGMAX+1],aname[ANSIZE+1],*atype;
    int i;
    FILE *fp;

    /* check for a command line */
    if (fmt != NULL)
        db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);

    /* checks for "<relation-name> [ into <filename> ]" */
    if (db_ntoken() != ID)
        return (db_ferror(SYNTAX));
    strcpy(rname,dbv_tstring);
    if (!db_to(&fp,".def"))
        return (FALSE);

    /* open the relation */
    if ((sptr = db_ropen(rname)) == NULL)
        return (FALSE);

    /* output the relation definition */
    fprintf(fp,"create %s (\n",rname);

    /* get attribute values */
    for (i = 0; i < NATTRS; i++) {

        /* get a pointer to the current attribute */
        aptr = &sptr->sc_relation->rl_header.hd_attrs[i];

        /* check for the last attribute */
        if (aptr->at_name[0] == 0)
            break;

        /* get the attribute name */
        strncpy(aname,aptr->at_name,ANSIZE); aname[ANSIZE] = 0;

        /* determine the attribute type */
        switch (aptr->at_type) {
        case TCHAR:
                atype = "char";
                break;
        case TNUM:
                atype = "num";
                break;
        default:
                atype = "<error>";
                break;
        }

        /* output the attribute definition */
        if (strlen(aname) < 8)
            fprintf(fp,"\t%s\t\t%s\t%d\n",aname,atype,aptr->at_size);
        else
            fprintf(fp,"\t%s\t%s\t%d\n",aname,atype,aptr->at_size);
    }

    /* output the relation size */
    fprintf(fp,") %d\n",sptr->sc_relation->rl_tmax);

    /* close the relation */
    db_rclose(sptr);

    /* close the output file */
    if (fp != stdout)
        fclose(fp);

    /* return successfully */
    return (TRUE);
}
SHAR_EOF
cat << \SHAR_EOF > mth.c
/* SDB - string arithmetic routines */

#include <ctype.h>  /*dns*/

/* useful definitions */
#define TRUE            1
#define FALSE           0
#define NUMBERMAX       99
#define EOS             0

/* db_cmp - compare two signed numeric strings */
int db_cmp(arg1,arg2)
  char *arg1,*arg2;
{
    int sign1,sign2;

    /* get the signs of the arguments */
    sign1 = getsign(&arg1);
    sign2 = getsign(&arg2);

    /* compute the result */
    if (sign1 == sign2) {
        if (sign1 == 1)
            return (compare(arg1,arg2));
        else
            return (compare(arg2,arg1));
    }

    /* signs are different */
    return (sign1);
}

/* db_add - add two signed numeric strings */
db_add(result,arg1,arg2)
  char *result,*arg1,*arg2;
{
    int signr,sign1,sign2;
    char rtmp[NUMBERMAX+2],*rptr;

    /* get the signs of the arguments */
    sign1 = getsign(&arg1);
    sign2 = getsign(&arg2);

    /* compute the result */
    if (sign1 == sign2) {
        signr = sign1;
        add(rtmp,arg1,arg2);
    }
    else
        switch (compare(arg1,arg2)) {
        case -1:
                signr = sign2;
                sub(rtmp,arg2,arg1);
                break;
        case 0:
                strcpy(result,"0");
                return;
        case 1:
                signr = sign1;
                sub(rtmp,arg1,arg2);
                break;
        }

    /* insert the sign */
    if (signr == -1)
        strcpy(result,"-");
    else
        result[0] = EOS;

    /* eliminate possible leading zeros */
    for (rptr = rtmp; *rptr == '0'; rptr++)
        ;

    /* copy the result */
    if (*rptr != EOS)
        strcat(result,rptr);
    else
        strcat(result,"0");
}

/* db_sub - subtract two signed numeric strings */
db_sub(result,arg1,arg2)
  char *result,*arg1,*arg2;
{
    int signr,sign1,sign2;
    char rtmp[NUMBERMAX+2],*rptr;

    /* get the signs of the arguments */
    sign1 = getsign(&arg1);
    sign2 = getsign(&arg2);

    /* invert the sign of arg2 */
    sign2 = -sign2;

    /* compute the result */
    if (sign1 == sign2) {
        signr = sign1;
        add(rtmp,arg1,arg2);
    }
    else
        switch (compare(arg1,arg2)) {
        case -1:
                signr = sign2;
                sub(rtmp,arg2,arg1);
                break;
        case 0:
                strcpy(result,"0");
                return;
        case 1:
                signr = sign1;
                sub(rtmp,arg1,arg2);
                break;
        }

    /* insert the sign */
    if (signr == -1)
        strcpy(result,"-");
    else
        result[0] = EOS;

    /* eliminate a possible leading zero */
    for (rptr = rtmp; *rptr == '0'; rptr++)
        ;

    /* copy the result */
    if (*rptr != EOS)
        strcat(result,rptr);
    else
        strcat(result,"0");
}

/* add - add two unsigned numeric strings */
static add(result,arg1,arg2)
  char *result,*arg1,arg2;
{
    char *vr,*v1,*v2,*vx;
    int carry,i,nmin,nmax,nd1,nd2;


    /* get number of digits in each argument */
    nd1 = getlen(arg1);
    nd2 = getlen(arg2);

    /* compute the address of the last digit + 1 */
    v1 = arg1 + nd1;
    v2 = arg2 + nd2;

    /* compute minimum and maximum of nd1 and nd2 */
    if (nd1 < nd2) {
        nmin = -nd1;
        nmax = -nd2;
        vx = v2;
    }
    else {
        nmin = -nd2;
        nmax = -nd1;
        vx = v1;
    }

    /* compute the address of the last result digit + 1 */
    vr = result - nmax; vr[0] = EOS;

    /* initialize the carry */
    carry = 0;

    /* add the digits */
    for (i = -1; i >= nmin; i--) {

        /* check for decimal point */
        if (v1[i] == '.')
            vr[i] = '.';
        else {

            /* add the current pair of digits with the carry */
            vr[i] = v1[i] + v2[i] + carry - '0';

            /* check for carry */
            if (vr[i] > '9') {
                vr[i] -= 10;
                carry = 1;
            }
            else
                carry = 0;
        }
    }

    /* add the remaining digits */
    for (; i >= nmax; i--) {

        /* add the current digit with the carry */
        vr[i] = vx[i] + carry;

        /* check for carry */
        if (vr[i] > '9') {
            vr[i] -= 10;
            carry = 1;
        }
        else
            carry = 0;
    }

    /* check for a carry out and shift digits if necessary */
    if (carry == 1) {

        /* shift the digits */
        for (i = -nmax; i >= 0; i--)
            result[i+1] = result[i];
        result[0] = '1';
    }
}

/* sub - subtract two unsigned numeric strings */
static sub(result,arg1,arg2)
  char *result,*arg1,arg2;
{
    char *vr,*v1,*v2,*vx;
    int borrow,i,nmin,nmax,nd1,nd2;

    /* get number of digits in each argument */
    nd1 = getlen(arg1);
    nd2 = getlen(arg2);

    /* compute the address of the last digit + 1 */
    v1 = arg1 + nd1;
    v2 = arg2 + nd2;

    /* compute minimum and maximum of nd1 and nd2 */
    if (nd1 < nd2) {
        nmin = -nd1;
        nmax = -nd2;
        vx = v2;
    }
    else {
        nmin = -nd2;
        nmax = -nd1;
        vx = v1;
    }

    /* compute the address of the last result digit + 1 */
    vr = result - nmax; vr[0] = EOS;

    /* initialize the borrow */
    borrow = 0;

    /* subtract the digits */
    for (i = -1; i >= nmin; i--) {

        /* check for decimal point */
        if (v1[i] == '.')
            vr[i] = '.';
        else {

            /* subtract the current pair of digits with the borrow */
            vr[i] = v1[i] - v2[i] - borrow + '0';

            /* check for borrow */
            if (vr[i] < '0') {
                vr[i] += 10;
                borrow = 1;
            }
            else
                borrow = 0;
        }
    }

    /* subtract the remaining digits */
    for (; i >= nmax; i--) {

        /* subtract the current digit with the borrow */
        vr[i] = vx[i] - borrow;

        /* check for borrow */
        if (vr[i] < '0') {
            vr[i] += 10;
            borrow = 1;
        }
        else
            borrow = 0;
    }
}

/* getsign - get the sign of a numeric string */
static int getsign(parg)
  char **parg;
{
    int sign;
    char *p;

    /* eliminate leading spaces */
    while (isspace(**parg))
        *parg += 1;

    /* get the sign */
    switch (**parg) {
    case '+':   *parg += 1;
                sign = 1;
                break;
    case '-':   *parg += 1;
                sign = -1;
                break;
    default:    sign = 1;
                break;
    }

    /* eliminate leading spaces and zeros */
    while (isspace(**parg) || **parg == '0')
        *parg += 1;

    /* if the value is zero, make sure that the sign is positive */
    switch (**parg) {
    case EOS:   sign = 1;
                break;
    case '.':   for (p = *parg + 1; *p == '0'; p++)
                    ;
                if (*p == EOS)
                    sign = 1;
                break;
    }

    /* return the sign */
    return (sign);
}

/* getlen - get the length of a numeric string */
static int getlen(arg)
  char *arg;
{
    int len;

    /* get the length of the string */
    len = strlen(arg);

    /* eliminate trailing spaces */
    while (isspace(arg[len-1]))
        len -= 1;

    /* return the length */
    return (len);
}

/* compare - compare two unsigned numeric strings */
static int compare(arg1,arg2)
  char *arg1,*arg2;
{
    int len1,len2;

    /* compare lengths */
    if ((len1 = getlen(arg1)) != (len2 = getlen(arg2)))
        if (len1 < len2)
            return (-1);
        else
            return (1);

    /* compare strings */
    return (strcmp(arg1,arg2));
}

SHAR_EOF
cat << \SHAR_EOF > sdbio.h
/* SDB - definition file */

#include <ctype.h>  /*dns*/

/* compiler specific stuff  (dns) */
/* #define Lattice */

/* useful definitions */
#define TRUE            1
#define FALSE           0
#ifndef NULL
#define NULL            0
#endif

/* Character definitions   (dns) */
#define BS  0x8       /*dns*/
#define CR  0xD       /*dns*/
#define FF  0xC       /*dns*/
#define ESC 0x1B      /*dns*/

/* program limits */
#define LINEMAX         132     /* maximum input line length */
#define TABLEMAX        132     /* maximum table output line */
#define KEYWORDMAX      10      /* maximum keyword length */
#define NUMBERMAX       20      /* maximum number length */
#define STRINGMAX       132     /* maximum string length */
#define CODEMAX         100     /* maximum length of code array */
#define STACKMAX        20      /* maximum interpreter stack size */

/* token definitions */
#define EOS             0
#define LSS             -1
#define LEQ             -2
#define EQL             -3
#define NEQ             -4
#define GEQ             -5
#define GTR             -6
#define SELECT          -7
#define FROM            -8
#define WHERE           -9
#define CREATE          -10
#define DELETE          -11
#define INSERT          -12
#define EXIT            -13
#define CHAR            -14
#define NUM             -15
#define ID              -16
#define STRING          -17
#define NUMBER          -18
#define UPDATE          -19
#define PRINT           -20
#define IMPORT          -21
#define EXPORT          -22
#define INTO            -23
#define HELP            -24
#define COMPRESS        -25
#define EXTRACT         -26
#define DEFINE          -27
#define SHOW            -28
#define USING           -29
#define SORT            -30
#define BY              -31
#define ASCENDING       -32
#define DESCENDING      -33
#define SET             -34

/* operand types */
#define LITERAL 1
#define ATTR    2
#define TEMP    3

/* attribute data types */
#define TCHAR   1
#define TNUM    2

/* tuple status codes */
#define UNUSED  0
#define ACTIVE  1
#define DELETED 2

/* relation header page format definitions */
#define RNSIZE          10      /* size of a relation name */
#define HSIZE           16      /* size of a relation entry */
#define ASIZE           16      /* size of a attribute entry */
#define ANSIZE          10      /* size of a attribute name */
#define NATTRS          31      /* number of attributes in header block */

/* error code definitions */
#define END             0       /* end of retrieval set */
#define INSMEM          1       /* insufficient memory */
#define RELFNF          2       /* relation file not found */
#define BADHDR          3       /* bad relation file header */
#define TUPINP          4       /* tuple input error */
#define TUPOUT          5       /* tuple output error */
#define RELFUL          6       /* relation file full */
#define RELCRE          7       /* error creating relation file */
#define DUPATT          8       /* duplicate attribute on relation create */
#define MAXATT          9       /* too many attributes on relation create */
#define INSBLK          10      /* insufficient disk blocks */
#define SYNTAX          11      /* command syntax error */
#define ATUNDF          12      /* attribute name undefined */
#define ATAMBG          13      /* attribute name ambiguous */
#define RLUNDF          14      /* relation name undefined */
#define CDSIZE          15      /* boolean expression code too big */
#define INPFNF          16      /* input file not found */
#define OUTCRE          17      /* output file creation error */
#define INDFNF          18      /* indirect command file not found */
#define BADSET          19      /* bad set parameter */

struct attribute {
    char at_name[ANSIZE];       /* attribute name */
    char at_type;               /* attribute type */
    char at_size;               /* attribute size in bytes */
    char at_scale;              /* attribute scale factor (for numeric only) */
    char at_unused[ASIZE-ANSIZE-3];     /* unused space */
};

struct header {         /* sizeof(struct header) must be 512 bytes */
    char hd_tcnt[2];            /* # of tuples in relation */
    char hd_tmax[2];            /* maximum # of tuples */
    char hd_data[2];            /* offset to first data byte */
    char hd_size[2];            /* size of each tuple in bytes */
    char hd_unused[HSIZE-8];    /* unused space */
    struct attribute hd_attrs[NATTRS];  /* table of attributes */
};

struct relation {
    char rl_name[RNSIZE];       /* relation name */
    unsigned int rl_tcnt;       /* # of tuples in relation (from hd_tcnt) */
    unsigned int rl_tmax;       /* maximum # of tuples (from hd_tmax) */
    int rl_data;                /* offset to first data byte (from hd_data) */
    int rl_size;                /* size of eachtuple in bytes (from hd_size) */
    int rl_store;               /* flag indicating a store happened */
    int rl_fd;                  /* file descriptor for relation file */
    int rl_scnref;              /* number of scans referencing this relation */
    struct header rl_header;    /* the relation file header block */
    struct relation *rl_next;   /* pointer to next relation */
};

struct scan {
    struct relation *sc_relation;       /* pointer to relation definition */
    unsigned int sc_dtnum;              /* desired tuple number */
    unsigned int sc_atnum;              /* actual tuple number */
    int sc_store;                       /* flag indicating a store happened */
    char *sc_tuple;                     /* tuple buffer */
};

struct srel {
    char *sr_name;                      /* alternate relation name */
    struct scan *sr_scan;               /* relation scan structure ptr */
    int sr_ctuple;                      /* current tuple flag */
    int sr_update;                      /* updated tuple flag */
    struct srel *sr_next;               /* next selected relation in list */
};

struct sattr {
    char *sa_rname;                     /* relation name */
    char *sa_aname;                     /* attribute name */
    char *sa_name;                      /* alternate attribute name */
    char *sa_aptr;                      /* pointer to attr in tuple buffer */
    struct srel *sa_srel;               /* pointer to the selected relation */
    struct attribute *sa_attr;          /* attribute structure ptr */
    struct sattr *sa_next;              /* next selected attribute in list */
};

struct operand {
    int o_type;
    union  {
        struct {
            int ovc_type;
            char *ovc_string;
            int ovc_length;
        } ov_char;
        int ov_boolean;
    } o_value;
};

union codecell {
    int (*c_operator)();
    struct operand *c_operand;
};

struct binding {
    struct attribute *bd_attr;          /* bound attribute */
    char *bd_vtuple;                    /* pointer to value in tuple */
    char *bd_vuser;                     /* pointer to user buffer */
    struct binding *bd_next;            /* next binding */
};

struct sel {
    struct srel *sl_rels;               /* selected relations */
    struct sattr *sl_attrs;             /* selected attributes */
    union codecell *sl_where;           /* where clause */
    struct binding *sl_bindings;        /* user variable bindings */
};

struct mtext {
    char *mt_text;
    struct mtext *mt_next;
};

struct macro {
    char *mc_name;
    struct mtext *mc_mtext;
    struct macro *mc_next;
};

struct ifile {
    char *if_fp;
    struct mtext *if_mtext;
    char *if_cmdline;
    int if_savech;
    char *if_lptr;
    struct ifile *if_next;
};

struct skey {
    int sk_type;
    struct attribute *sk_aptr;
    int sk_start;
    struct skey *sk_next;
};

SHAR_EOF
cat << \SHAR_EOF > srt.c
/* SDB - sort routines */

#include <stdio.h>
#include "sdbio.h"

extern int dbv_token;
extern char dbv_tstring[];
extern int dbv_tvalue;

/* get_skeys - get sort key list */
static struct skey *get_skeys(sptr)
  struct scan *sptr;
{
    struct skey *skeys,*newskey,*lastskey;

    /* parse a list of attribute names */
    skeys = lastskey = NULL;
    while (TRUE) {

        /* get attribute name */
        if (db_ntoken() != ID)
            return (db_nerror(SYNTAX));

        /* allocate a sort key structure */
        if ((newskey = malloc(sizeof(struct skey))) == NULL)
            return (db_nerror(INSMEM));

        /* initialize the sort key structure */
        newskey->sk_next = NULL;

        /* lookup the attribute name */
        if (!find_attr(sptr,newskey,dbv_tstring)) {
            free(newskey);
            return (NULL);
        }

        /* check for ascending or descending */
        if (db_token() == ASCENDING || dbv_token == DESCENDING) {
            newskey->sk_type = dbv_token;
            db_ntoken();
        }
        else
            newskey->sk_type = ASCENDING;

        /* link the sort key structure into the list */
        if (lastskey == NULL)
            skeys = newskey;
        else
            lastskey->sk_next = newskey;
        lastskey = newskey;

        /* check for more attributes */
        if (db_token() != ',')
            break;
        db_ntoken();
    }

    /* return successfully */
    return (skeys);
}

/* db_sort - sort tuples in a relation */
int *db_sort(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
  char *fmt;
{
    struct scan *sptr1,*sptr2,*sptr3;   /*dns*/
    struct skey *skeys;
    int result;

    /* check for a command line */
    if (fmt != NULL)
        db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);

    /* checks for relation name */
    if (db_token() == ID)
        db_ntoken();
    else
        strcpy(dbv_tstring,"sdbcur");

    /* open the relation */
    if ((sptr1 = db_ropen(dbv_tstring)) == NULL)
        return (FALSE);
    if ((sptr2 = db_ropen(dbv_tstring)) == NULL) {
        db_rclose(sptr1);
        return (FALSE);
        }
    if ((sptr3 = db_ropen(dbv_tstring)) == NULL) {   /*dns*/
        db_rclose(sptr1);                            /*dns*/
        db_rclose(sptr2);                            /*dns*/
        return (FALSE);                              /*dns*/
        }

    /* checks for "<relation-name> by <sort-list>" */
    if (db_ntoken() != BY)
        return (db_ferror(SYNTAX));
    if ((skeys = get_skeys(sptr1)) == NULL) {
        db_rclose(sptr1);
        db_rclose(sptr2);
        db_rclose(sptr3);  /*dns*/
        return (FALSE);
       }

    /* do the sort */
    result = sort(skeys,sptr1,sptr2,sptr3);  /*dns*/

    /* close the relation */
    db_rclose(sptr1);
    db_rclose(sptr2);
    db_rclose(sptr3);     /*dns*/

    /* free the sort keys */
    free_skeys(skeys);

    return (result);
}

/* free_skeys - free a list of sort keys */
static free_skeys(skeys)
  struct skey *skeys;
{
    struct skey *thisskey;

    for (thisskey = skeys; skeys != NULL; thisskey = skeys) {
        skeys = skeys->sk_next;
        free(thisskey);
    }
}

/* find_attr - find an attribute */
static int find_attr(sptr,newskey,aname)
  struct scan *sptr; struct skey *newskey; char *aname;
{
    struct attribute *aptr;
    int i,astart;

    /* loop through each attribute within the relation */
    astart = 1;
    for (i = 0; i < NATTRS; i++) {

        /* get a pointer to the current attribute */
        aptr = &sptr->sc_relation->rl_header.hd_attrs[i];

        /* check for last attribute */
        if (aptr->at_name[0] == 0)
            break;

        /* check for attribute name match */
        if (db_sncmp(aname,aptr->at_name,ANSIZE) == 0) {
            newskey->sk_start = astart;
            newskey->sk_aptr = aptr;
            return (TRUE);
        }

        /* update the attribute start */
        astart += aptr->at_size;
    }

    /* attribute name not found */
    return (db_ferror(ATUNDF));
}

/* sort - sort the relation */
static int sort(skeys,sptr1,sptr2,sptr3)
  struct skey *skeys; struct scan *sptr1,*sptr2,*sptr3;
{
/*  unsigned int j,k,l,r;          dns */
    long int passes,swaps;           /*dns*/
    int i, j, m, n;         /*dns*/
    int rec1 = 0;           /*dns*/
    int rec2 = 0;           /*dns*/
    int rec3 = 0;           /*dns*/
    int dns = 0;            /*dns*/
    FILE *test;             /*dns*/

    passes = 0L;
    swaps = 0L;

    /*dns --->   */
    test = fopen("sort.dat", "w");
    n = sptr1->sc_relation->rl_tcnt;
    m = n;

    while( m>1 )   {
       passes++;
       if ((m/=3.14159) < 1)  m = 1;
       for ( j=1; j<=n-m; j++ )  {
          if( rec1 != j+m )  {
             if(dns) fprintf(test,"Read1: %d\n", j+m);
             if (!db_rget(sptr1, rec1=j+m))  return (FALSE);
             }
          for ( i=j; i>=1; i-=m ) {
             if( rec2 != i )   {
                if(dns) fprintf(test,"Read2: %d\n", i);
                if (!db_rget(sptr2, rec2=i))  return (FALSE);
                }
             if (compare(skeys,sptr1,sptr2) > 0)
                break;
             if(rec3 != i+m)  {
                if(dns) fprintf(test,"Read3: %d\n", i+m);
                if (!db_rget(sptr3, rec3=i+m))  return (FALSE);
                }
             if(dns) fprintf(test,"Write 3,2: %d from %d\n", i+m, i);
             assign( sptr3, sptr2 );
             swaps++;
             }
          if(rec1 != i+m)  {
             if(rec3 != i+m)  {
                if(dns) fprintf(test,"Read 3: %d\n", i+m);
                if (!db_rget(sptr3, rec3=i+m))  return (FALSE);
                }
             if(dns) fprintf(test,"Write 3,1: %d from %d\n", i+m, j+m);
             assign( sptr3, sptr1 );
             swaps++;
             }
          }
       }
       fclose(test);

/*
    l = 2;
    r = sptr1->sc_relation->rl_tcnt;
    k = r;

    do {
        for (j = r; j >= l; j--) {
            if (!db_rget(sptr1,j-1))
                return (FALSE);
            if (!db_rget(sptr2,j))
                return (FALSE);
            if (compare(skeys,sptr1,sptr2) > 0) {
                swap(sptr1,sptr2);
                k = j;
                swaps++;
            }
        }
        l = k + 1;
        for (j = l; j <= r; j++) {
            if (!db_rget(sptr1,j-1))
                return (FALSE);
            if (!db_rget(sptr2,j))
                return (FALSE);
            if (compare(skeys,sptr1,sptr2) > 0) {
                swap(sptr1,sptr2);
                k = j;
                swaps++;
            }
        }
        r = k - 1;
        passes++;
    } while (l <= r);
*/

    printf("[ Passes: %ld  Swaps: %ld ]\n",passes,swaps);

    return (TRUE);
}

/* compare - compare two tuples */
static int compare(skeys,sptr1,sptr2)
  struct skey *skeys; struct scan *sptr1,*sptr2;
{
    struct skey *cskey;
    int result;

    for (cskey = skeys; cskey != NULL; cskey = cskey->sk_next)
        if ((result = cattr(cskey,sptr1,sptr2)) != 0)
            break;

    return (result);
}

/* cattr - compare two attributes */
static int cattr(cskey,sptr1,sptr2)
  struct skey *cskey; struct scan *sptr1,*sptr2;
{
    int astart,aend,i;

    astart = cskey->sk_start;
    aend = astart + cskey->sk_aptr->at_size;

    for (i = astart; i < aend; i++)
        if (sptr1->sc_tuple[i] != sptr2->sc_tuple[i])
            break;

    if (i == aend)
        return (0);

    if (sptr1->sc_tuple[i] < sptr2->sc_tuple[i])
        if (cskey->sk_type == ASCENDING)
            return (-1);
        else
            return (1);
    else
        if (cskey->sk_type == ASCENDING)
            return (1);
        else
            return (-1);
}

/* swap - swap two tuples */
/* dns
static int swap(sptr1,sptr2)
  struct scan *sptr1,*sptr2;
{
    unsigned int tnum1,tnum2;

    tnum1 = sptr1->sc_atnum;
    tnum2 = sptr2->sc_atnum;

    if (!db_rput(sptr1,tnum2))
        return (FALSE);
    if (!db_rput(sptr2,tnum1))
        return (FALSE);

    return (TRUE);
}
  dns  */


/* assign - assign one tupple to another */
static int assign(sptr1,sptr2)
  struct scan *sptr1,*sptr2;
{
    unsigned int tnum1,tnum2;

    tnum1 = sptr1->sc_atnum;

    if (!db_rput(sptr2,tnum1))
        return (FALSE);

    return (TRUE);
}
SHAR_EOF
cat << \SHAR_EOF > com.c
/* SDB - expression compiler
    syntax:
        <expr>          ::= <lor> <EOS>
        <lor>           ::= <land> { '|' <land> }
        <land>          ::= <relat> { '&' <relat> }
        <relat>         ::= <primary> { <relop> <primary> }
        <primary>       ::= <factor> | <unop> <unary>
        <factor>        ::= <number> | <string> | '(' <query> ')'
        <number>        ::= <digit> | <number> <digit>
        <string>        ::= '"' <chars> '"'
        <chars>         ::= nil | <chars> <character>
        <relop>         ::= '=' | '<>' | '<' | '>' | '<=' | '>='
        <unop>          ::= '+' | '-' | '~'
*/

#include "sdbio.h"

extern int dbv_token;
extern char dbv_tstring[];
extern int dbv_tvalue;

extern int db_xand();
extern int db_xor();
extern int db_xnot();
extern int db_xlss();
extern int db_xleq();
extern int db_xeql();
extern int db_xgeq();
extern int db_xgtr();
extern int db_xneq();
extern int db_xpush();
extern int db_xstop();

static union codecell code[CODEMAX+1];
static int cndx;
static struct sel *selptr;

/* compile - compile a boolean expression */
int db_compile(slptr)
  struct sel *slptr;
{
    int result,i;
    union codecell *cptr;
#ifdef Lattice
    int (*dns)();  /*dns*/
#endif

    /* save the selection structure pointer */
    selptr = slptr;

    /* initialize the code array index */
    cndx = 0;

    /* parse the boolean expression */
    if (!expr(&result)) {
        code[cndx++].c_operator = db_xstop;
        freelit(code);
        return (FALSE);
    }

    /* terminate the code */
    code[cndx++].c_operator = db_xstop;

    /* allocate space for the code array */
    if ((cptr = malloc(sizeof(union codecell) * cndx)) == NULL) {
        freelit(code);
        return (FALSE);
    }

    /* store the code into the code array */
    slptr->sl_where = cptr;
    for (i = 0; i < cndx; i++) {
        (*cptr++).c_operator = code[i].c_operator;
#ifndef Lattice
        if (code[i].c_operator == db_xpush)
#else
        if ( code[i].c_operator == (dns=db_xpush) )  /*dns*/
#endif
            (*cptr++).c_operand = code[++i].c_operand;
    }

    /* return successfully */
    return (TRUE);
}

/* db_fcode - free a code array */
db_fcode(slptr)
  struct sel *slptr;
{
    /* make sure there is a where clause */
    if (slptr->sl_where == NULL)
        return;

    /* free the literals */
    freelit(slptr->sl_where);

    /* free the code array */
    free(slptr->sl_where);
}

/* operator - insert an operator into the code array */
static int operator(opr)
  int (*opr)();
{
    /* insert the operator */
    if (cndx < CODEMAX)
        code[cndx++].c_operator = opr;
    else
        return (db_ferror(CDSIZE));

    /* return successfully */
    return (TRUE);
}

/* operand - insert an operand into the code array */
static int operand(opr)
  struct operand *opr;
{
    /* insert the push operator */
    if (!operator(db_xpush))
        return (FALSE);

    /* insert the operand */
    if (cndx < CODEMAX)
        code[cndx++].c_operand = opr;
    else
        return (db_ferror(CDSIZE));

    /* return successfully */
    return (TRUE);
}

/* expr - compile an expression */
static int expr(result)
  int *result;
{
    int lval,rval;

    if (!land(&lval))
        return (FALSE);
    while (db_token() == '|') {
        db_ntoken();
        if (!land(&rval))
            return (FALSE);
        if (!operator(db_xor))
            return (FALSE);
    }
    *result = lval;
    return (TRUE);
}

static int land(result)
  int *result;
{
    int lval,rval;

    if (!relat(&lval))
        return (FALSE);
    while (db_token() == '&') {
        db_ntoken();
        if (!relat(&rval))
            return (FALSE);
        if (!operator(db_xand))
            return (FALSE);
    }
    *result = lval;
    return (TRUE);
}

static int relat(result)
  int *result;
{
    int lval,rval;
    int tkn;

    if (!primary(&lval))
        return (FALSE);
    while (db_token() <= LSS && dbv_token >= GTR) {
        tkn = db_ntoken();
        if (!primary(&rval))
            return (FALSE);
        switch (tkn) {
        case LSS:
                if (!operator(db_xlss))
                    return (FALSE);
                break;
        case LEQ:
                if (!operator(db_xleq))
                    return (FALSE);
                break;
        case EQL:
                if (!operator(db_xeql))
                    return (FALSE);
                break;
        case NEQ:
                if (!operator(db_xneq))
                    return (FALSE);
                break;
        case GEQ:
                if (!operator(db_xgeq))
                    return (FALSE);
                break;
        case GTR:
                if (!operator(db_xgtr))
                    return (FALSE);
                break;
        }
    }
    *result = lval;
    return (TRUE);
}

static int primary(result)
  int *result;
{
    int val;
    int tkn;

    if (db_token() == '~') {
        tkn = db_ntoken();
        if (!primary(&val))
            return (FALSE);
        switch (tkn) {
        case '~':
                if (!operator(db_xnot))
                    return (FALSE);
                break;
        }
    }
    else
        if (!factor(&val))
            return (FALSE);
    *result = val;
    return (TRUE);
}

static int factor(result)
  int *result;
{
    int val;

    if (db_token() == '(') {
        db_ntoken();
        if (!expr(&val))
            return (FALSE);
        if (db_token() != ')')
            return (db_ferror(SYNTAX));
        db_ntoken();
    }
    else
        if (!get_operand(&val))
            return (FALSE);
    *result = val;
    return (TRUE);
}

/* get_operand - get an operand (number, string, or attribute) */
static int get_operand(result)
  int *result;
{
    /* determine operand type */
    if (db_ntoken() == NUMBER)
        return (get_number(result));
    else if (dbv_token == ID)
        return (get_attr(result));
    else if (dbv_token == STRING)
        return (get_string(result));
    else
        return (db_ferror(SYNTAX));
}

/* get_attr - get an attribute argument */
static int get_attr(result)
  int *result;
{
    struct operand *opr;
    char rname[RNSIZE+1],aname[ANSIZE+1];
    char *aptr; int atype,alen;

    /* save the attribute name */
    strncpy(aname,dbv_tstring,ANSIZE); aname[ANSIZE] = EOS;

    /* check for a "." indicating a qualified attribute name */
    if (db_token() == '.') {
        db_ntoken();

        /* the previous ID was really a relation name */
        strcpy(rname,aname);

        /* check for the real attribute name */
        if (db_ntoken() != ID)
            return (db_ferror(SYNTAX));

        /* save the attribute name */
        strncpy(aname,dbv_tstring,ANSIZE); aname[ANSIZE] = EOS;

        /* lookup the attribute name */
        if (!db_sattr(selptr,rname,aname,&atype,&aptr,&alen))
            return (FALSE);
    }
    else
        if (!db_sattr(selptr,NULL,aname,&atype,&aptr,&alen))
            return (FALSE);

    /* get a new operand structure */
    if ((opr = malloc(sizeof(struct operand))) == NULL)
        return (db_ferror(INSMEM));

    /* initialize the new operand structure */
    opr->o_type = ATTR;
    opr->o_value.ov_char.ovc_type = atype;
    opr->o_value.ov_char.ovc_string = aptr;
    opr->o_value.ov_char.ovc_length = alen;

    /* insert the operand into the code array */
    if (!operand(opr)) {
        free(opr);
        return (FALSE);
    }

    /* store operand type */
    *result = atype;

    /* return successfully */
    return (TRUE);
}

/* get_number - get a numeric operand */
static int get_number(result)
  int *result;
{
    struct operand *opr;

    /* get a new operand structure */
    if ((opr = malloc(sizeof(struct operand))) == NULL)
        return (db_ferror(INSMEM));

    /* initialize the new operand structure */
    opr->o_type = LITERAL;
    if ((opr->o_value.ov_char.ovc_string =
                malloc(strlen(dbv_tstring)+1)) == NULL) {
        free(opr);
        return (db_ferror(INSMEM));
    }
    opr->o_value.ov_char.ovc_type = TNUM;
    strcpy(opr->o_value.ov_char.ovc_string,dbv_tstring);
    opr->o_value.ov_char.ovc_length = strlen(dbv_tstring);

    /* insert the operand into the code array */
    if (!operand(opr)) {
        free(opr->o_value.ov_char.ovc_string); free(opr);
        return (FALSE);
    }

    /* operand type is number */
    *result = TNUM;

    /* return successfully */
    return (TRUE);
}

/* get_string - get a string operand */
static int get_string(result)
  int *result;
{
    struct operand *opr;

    /* get a new operand structure */
    if ((opr = malloc(sizeof(struct operand))) == NULL)
        return (db_ferror(INSMEM));

    /* initialize the new operand structure */
    opr->o_type = LITERAL;
    if ((opr->o_value.ov_char.ovc_string =
                malloc(strlen(dbv_tstring)+1)) == NULL) {
        free(opr);
        return (db_ferror(INSMEM));
    }
    opr->o_value.ov_char.ovc_type = TCHAR;
    strcpy(opr->o_value.ov_char.ovc_string,dbv_tstring);
    opr->o_value.ov_char.ovc_length = strlen(dbv_tstring);

    /* insert the operand into the code array */
    if (!operand(opr)) {
        free(opr->o_value.ov_char.ovc_string); free(opr);
        return (FALSE);
    }

    /* operand type is character */
    *result = TCHAR;

    /* return successfully */
    return (TRUE);
}

/* freelit - free the literals in a code array */
static freelit(cptr)
  union codecell *cptr;
{
#ifdef Lattice
    int (*dns)();  /*dns*/
    for (; (*cptr).c_operator != (dns=db_xstop); cptr++)  /*dns*/
        if ((*cptr).c_operator == (dns=db_xpush) )        /*dns*/
#else
    for (; (*cptr).c_operator != db_xstop; cptr++)
        if ((*cptr).c_operator == db_xpush )
#endif
            if ((*++cptr).c_operand->o_type == LITERAL)
                free((*cptr).c_operand->o_value.ov_char.ovc_string);
}
SHAR_EOF
#	End of shell archive
exit 0
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads