Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!gatech!akgua!mhuxv!mhuxf!mhuxm!mhuxn!ihnp4!inuxc!pur-ee!j.cc.purdue.edu!doc From: doc@pucc-j.UUCP Newsgroups: mod.amiga.sources Subject: sdb Database (1 of 3) Message-ID: <1850@j.cc.purdue.edu> Date: Fri, 22-Aug-86 18:45:52 EDT Article-I.D.: j.1850 Posted: Fri Aug 22 18:45:52 1986 Date-Received: Sun, 24-Aug-86 09:03:09 EDT Sender: doc@j.cc.purdue.edu Organization: Purdue University Computing Center Lines: 2105 Approved: doc@pucc-j.UUCP [ 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 #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 ( ) - create a new relation insert - insert tuples into a relation delete ; - delete tuples from relations update from ; - update tuples within a relation print [] from [] ; - print tuples sort by ; - sort a relation file import into - import tuples from a file export [] ; - export tuples to a file extract [] ; - extract definition to a file compress - compress a relation file define - define a macro exit - exit SDB ::= using ::= into ::= ::= [where ] ::= ::= s> ::= [ .] ::= * | s> ::= { ascending | descending } ::= 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 #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 #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 #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 " into " */ 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 " [ into ]" */ 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 "" */ 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 " [ into ]" */ 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 = ""; 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 /*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 /*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 #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 " by " */ 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: ::= ::= { '|' } ::= { '&' } ::= { } ::= | ::= | | '(' ')' ::= | ::= '"' '"' ::= nil | ::= '=' | '<>' | '<' | '>' | '<=' | '>=' ::= '+' | '-' | '~' */ #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