Dec 092017
 
This is the 8088 assembly language source for ZSAM, the B-Tree file management system described in "Some Assembly Required", BYTE Magazine.
File ATREES.ZIP from The Programmer’s Corner in
Category Files from Magazines
This is the 8088 assembly language source for ZSAM, the B-Tree file management system described in “Some Assembly Required”, BYTE Magazine.
File Name File Size Zip Size Zip Type
TRENKEY1.TXT 53888 8158 deflated
TRENKEY2.TXT 66184 11562 deflated
TRENKEY3.TXT 33024 7611 deflated

Download File ATREES.ZIP Here

Contents of the TRENKEY1.TXT file





===============================

README.DOC

===============================



*** ZSAM ***

In this archive, you should find the following files:

ZSAM.ASM This is the 8088 assembly language source for ZSAM, the
B-Tree file management system described in "Some Assembly
Required", BYTE Magazine. The code is compatible with
Borland's TASM assembler, and with a little work you
should be able to feed it to MASM.

ZTEMPL.C A "template" file containing all the C interface source
code. Use this when you're building a ZSAM application.

ZMAKEF.C This program lets you build ZSAM key and data files.
Its prompts should be pretty explanatory. There are
also comments in the source to help you.

ZMAKEBIB.C This program builds the key and data files used in the
bibliography database described in part III of
"Trees 'N Keys".

ZINPUT.DAT Raw data that you can feed to ZMAKEBIB.C.

ZINPUT.FRM A description of the format of the data in ZINPUT.DAT.

ZSAM is more-or-less in the public domain. You may use it, pass it
along to others, and do whatever you want. If you end up modifying it
and using it in a commercial application, please give conspicuous
mention of its source (namely, me....Rick Grehan). I'll try and
keep updates coming as I have time to make them.

Though I won't classify ZSAM as shareware, I have spent a great deal of
time putting it together. Above-and-beyond the call of duty, you might
say. Any kind of donation you'd care to submit would be appreciated...
particularly if you end up making something worthwhile for yourself out
of ZSAM. I'm not going to make any hard-and-fast rules about this, 'cause
I know you've already laid out some cash just to get the article and
download the source.

Rick Grehan
Senior Testing Editor
BYTE Magazine
One Phoenix Mill Lane
Peterborough, NH 03458




===============================

ZBYTEBIB.C

===============================



/*
** This program is the user-lookup module for the bibliography system
** given in part III of "Trees 'N Keys", BYTE Magazine.
** It assumes that you've already build the 8 database files using
** ZMAKEBIB.C.
*/

#include
#include
#include

/*
** ZSAM Globals
*/

#define nzkfiles 4 /* Number of key files */
#define nzdfiles 4 /* Number of data files */

#define KNODESIZE 512 /* Size of key node */
/*
** ZSAM structure definitions.
*/

typedef unsigned char byte;

typedef struct { /* Key file header */
char kftype; /* Key file type, "K" or "O" */
unsigned int rootsc; /* Root sector */
unsigned int nokeysl; /* Number of keys, lo */
byte nokeysh; /* Number of keys, hi */
unsigned int kavsec; /* Key avail list head */
unsigned int nxkysc; /* Next free sector */
byte keylen; /* Key length */
byte maxks; /* Maximum keys per sector (node) */
unsigned int ackysc; /* Actual key sector in buffer */
byte misc[48]; /* Transient storage */
} zkey_header;

#define KHEADSIZE sizeof(zkey_header)-48

typedef struct { /* Data file header */
char dftype; /* Data file type, "S" or "C" */
unsigned int reclen; /* Record length */
unsigned int norecsl; /* Number of records, lo */
byte norecsh; /* Number of records, hi */
unsigned int davlo; /* Avail list, lo */
byte davhi; /* Avail list, hi */
unsigned int nxdalo; /* Next data record, lo */
byte nxdahi; /* Next data record, hi */
char misc[20]; /* Transient storage */
} zdat_header;
#define DHEADSIZE sizeof(zdat_header)-20

/*
** ZSAM interface storage.
*/

unsigned int zkfno; /* Current key file number */
unsigned int zdfno; /* Current data file number */
int zkfhand[nzkfiles]; /* Array of handles to key files */
int zdfhand[nzdfiles]; /* Array of handles to data files */
zkey_header *keyhead[nzkfiles]; /* Pointers to key file header storage */
zdat_header *dathead[nzdfiles]; /* Pointers to data file header storage */
char *keybuf[nzkfiles]; /* Pointers to key file buffers */
char *datbuf[nzdfiles]; /* Pointers to data file buffers */
long zoffset; /* Offset into files */

/*
** A pointer to the following structure (zsams) is passed
** to the ZSAM assembly routines.
*/
typedef struct {
unsigned int funct; /* Function code */
char *kbuf; /* Pointer to current key buffer */
char *dbuf; /* Pointer to current data buffer */
char *key; /* Pointer to current key */
char *rec; /* Pointer to current data record */
zkey_header *keyhd; /* Pointer to current key file header */
zdat_header *dathd; /* Pointer to current data file header */
} zsamstr;

zsamstr zsams;

extern int errno;


/*
** Local file definitions
*/
#define MASTER_KEY 0
#define TITLE_DAT 0
#define KEYWORD_KEY 1
#define KEYWORD_DAT 1
#define AUTHMAST_KEY 2
#define AUTHMAST_DAT 2
#define AUTHNAME_KEY 3
#define AUTHNAME_DAT 3

/* ************************************************************ */
/* Close all open files. */
/* ************************************************************ */
int closeall()
{
zclosek(0); zclosed(0);
zclosek(1); zclosed(1);
zclosek(2); zclosed(2);
zclosek(3); zclosed(3);
return;
}

/* ************************************************************ */
/* int slmenu() */
/* Handles menu selection. */
/* Returns: 0 - exit 1 - keyword */
/* 2 - date 3 - author */
/* ************************************************************ */
int slmenu()
{
int sel;
char sele[10];

/* DISPLAY THE MENU */
printf("\n\n");
printf(" Select one of the following--\n\n");
printf(" A -- Search by keyword\n");
printf(" B -- Search by date\n");
printf(" C -- Search by author\n");
printf(" X -- Exit\n\n");

/* GET SELECTION */
sel=-1;
do {
printf(" Enter selection:");
gets(sele);
switch (sele[0]) {

case 'a':
case 'A': sel=1; /* SEARCH BY KEYWORD */
break;

case 'b':
case 'B': sel=2; /* SEARCH BY DATE */
break;

case 'c':
case 'C': sel=3; /* SEARCH BY AUTHOR */
break;

case 'x':
case 'X': sel=0; /* EXIT */
break;

default: printf("*Unrecognized entry-try again*\n");
break;
}
} while(sel==-1);
return (sel);
}

/* ************************************************************ */
/* kwstrip(keywrd) */
/* Strips unwanted characters out of keyword. */
/* Also performs case translation. */
/* ************************************************************ */
kwstrip(keywrd)
char keywrd[17];
{
char tmp[17],c;
int i,j;

/* CLEAR OUT tmp[] */
for (i=0;i<17;++i) tmp[i]='\0';

/* MOVE KEYWORD TO TMP - TRANSLATE AS YOU GO */
j=0;
for (i=0;i<17;++i)
{ c=keywrd[i];
if (c>='a' && c<='z') c-=32;
if ((c>='A' && c<='Z')||(c>='0' && c<='9'))
tmp[j++]=c;
}
/* MOVE BACK */
for (i=0;i<17;++i) keywrd[i]=tmp[i];
}


/* ************************************************************ */
/* dispart(artkey,auth) */
/* Display an article. *artkey points to master key. */
/* If auth=1, display authors. */
/* ************************************************************ */
dispart(artkey,auth)
char *artkey;
int auth;
{
char title[81],authors[21],year[3],month[3];
unsigned int pg;

/* BUILD THE ARTICLE'S MASTER KEY */
year[0]=artkey[0]; year[1]=artkey[1]; year[2]='\0';
month[0]=artkey[2]; month[1]=artkey[3]; month[2]='\0';
printf("Date: %s/%s \n",year,month);
pg=artkey[5]&255+256*(artkey[4]&255);
printf("Page: %d \n",pg);
title[80]='\0';

/* READ MASTER INDEX */
zreadkr(MASTER_KEY,TITLE_DAT,artkey,title);
printf("%s \n",title);
if (auth) /* SHOW AUTHORS? */
{ authors[20]='\0';
/* READ THROUGH LIST OF AUTHORS' NAMES */
zreadkr(AUTHNAME_KEY,AUTHNAME_DAT,artkey,authors);
printf("by: %s\n",authors);
while (zreadndr(AUTHNAME_DAT,authors)==0)
printf(" %s\n",authors);
}
printf("--------------------\n");
}

/* ************************************************************ */
/* srchkwd() */
/* SEARCH BY KEYWORD MAIN ROUTINE */
/* Note that this routine matches substrings. So, for example */
/* if you enter "APPLE" for a keyword, it will match */
/* "APPLE", "APPLEII", and "APPLEIII". This might cause */
/* an article to appear more than once on a keyword search, */
/* if more than one of the above keywords has been stored for */
/* that article. */
/* ************************************************************ */
srchkwd()
{
int i,ii,auth;
char keywd[20],savkey[20],mastkey[8],ans[10];

printf("Enter keyword (16 chars max):");
for (i=0;i<17;++i) keywd[i]='\0';
gets(keywd);
kwstrip(keywd); /* FIX UP KEYWORD */
printf("Display authors?(Y/N):");
gets(ans);
if (ans[0]=='y' || ans[0]=='Y') auth=1;
else auth=0;

/* START LOOKING */
strcpy(savkey,keywd); /* SAVE A COPY OF KEYWORD */
printf("\n");
ii=zreadkr(KEYWORD_KEY,KEYWORD_DAT,keywd,mastkey);
do {
if (ii==0)
do { dispart(mastkey,auth);
} while(zreadndr(KEYWORD_DAT,mastkey)==0);
ii=zreadnkr(KEYWORD_KEY,KEYWORD_DAT,keywd,mastkey);
if (ii==0)
if (strncmp(savkey,keywd,strlen(savkey))!=0) ++ii;
} while (ii==0);
}

/* ************************************************************ */
/* srchauth() */
/* SEARCH BY AUTHOR */
/* ************************************************************ */
srchauth()
{
int i,ii,auth;
int autlen;
char authky[17],savkey[17],ans[10],mastkey[8];

for(i=0;i<17;++i) authky[i]='\0';
printf("Enter author's last name (15 chars max):");
gets(authky);
autlen=strlen(authky); /* SAVE CURRENT LENGTH */
for (i=autlen;i<16;++i)
authky[i]='\040'; /* PAD WITH BLANKS */
printf("Enter author's 1st initial:");
gets(ans);
if (strlen(ans))
{ authky[15]=ans[0];
autlen=16; /* RESET CURRENT LENGTH */
}
auth=1; /* ASSUME HE WANTS NAMES */

/* START LOOKING */
strcpy(savkey,authky); /* SAVE ORIGINAL KEY */
printf("\n");
ii=zreadkr(AUTHMAST_KEY,AUTHMAST_DAT,authky,mastkey);
do {
if (ii==0)
do { dispart(mastkey,auth);
} while(zreadndr(AUTHMAST_DAT,mastkey)==0);
ii=zreadnkr(AUTHMAST_KEY,AUTHMAST_DAT,authky,mastkey);
if (ii==0)
if(strncmp(savkey,authky,autlen)!=0) ++ii;
} while (ii==0);
}

/* ************************************************************ */
/* srchdat() */
/* Search by date. */
/* ************************************************************ */
srchdat()

{
int ii,auth,i;
char mastkey[8],savkey[8],ans[10],title[81];

printf("Enter year:");
gets(mastkey);
printf("Enter month:");
gets(&mastkey[2]);
for (i=4;i<7;++i) mastkey[i]='\0';
printf("Display authors?(Y/N):");
gets(ans);
if (ans[0]=='y' || ans[0]=='Y') auth=1; else auth=0;

/* START LOOKING */
strcpy(savkey,mastkey); /* SAVE A COPY OF ORIGINAL KEY */
printf("\n");
if (zreadkr(MASTER_KEY,TITLE_DAT,mastkey,title)==0)
dispart (mastkey,auth);
do {
ii=zreadnkr(MASTER_KEY,TITLE_DAT,mastkey,title);
if (ii==0)
if (strncmp(savkey,mastkey,strlen(savkey))!=0)
++ii;
else
dispart(mastkey,auth);
} while (ii==0);
}

/* ************************************************************ */
/* MAIN ROUTINE */
/* ************************************************************ */
main ()
{

int select;
/* OPEN ALL FILES */
zopenk("MINDEX.KEY",MASTER_KEY); /* Master index */
zopend("TITLES.DAT",TITLE_DAT); /* Titles data file */

zopenk("KEYWORDS.KEY",KEYWORD_KEY); /* Keywords index */
zopend("KEYWORDS.DAT",KEYWORD_DAT); /* Data file */

zopenk("AUTHOR.KEY",AUTHMAST_KEY); /* Author index */
zopend("AUTHOR.DAT",AUTHMAST_DAT); /* Data file */

zopenk("AUTHNAM.KEY",AUTHNAME_KEY); /* Author's name index */
zopend("AUTHNAM.DAT",AUTHNAME_DAT); /* Author's name data file */

printf ("\n\n BYTE BIBLIO-SYSTEM \n\n");

do {
select=slmenu(); /* GET SELECTION */
switch (select) {

case 1: srchkwd(); /* SEARCH BY KEYWORD */
break;

case 2: srchdat(); /* SEARCH BY DATE */
break;

case 3: srchauth(); /* SEARCH BY AUTHOR */
break;

case 0: closeall(); /* EXIT */
printf ("\n\n\n");
printf ("* EXIT *\n");
break;
}
} while (select);
exit(0);
}

/****************************************/
/* ZSAM ENTRY POINTS FOLLOW */
/****************************************/

/*
** Open a key file.
** RETURNS: 0 successful, error number if not.
** If return is a -1, look in errno for system error.
** If return is -2, malloc failed - not enough space
** to open the file.
** If return is -3, the file is not a ZSAM file.
*/
int zopenk(fname,fnum)
char *fname; /* File name */
unsigned int fnum; /* File number */
{

char filetype;

zkfno=fnum;

/* Open the file and store the handle */
zkfhand[zkfno]=open(fname,O_RDWR | O_BINARY);
if(zkfhand[zkfno]==-1) return(-1);

/* Allocate space for key file header */
keyhead[zkfno] = (zkey_header *)malloc(sizeof(zkey_header));
if(keyhead[zkfno]==NULL) return(-2);

/* Allocate space for key file buffer */
keybuf[zkfno] = (char *)malloc(KNODESIZE);
if(keybuf[zkfno]==NULL)
{ free((void *)keyhead[zkfno]);
return(-2);
}

/* Read in the header information */
lseek(zkfhand[zkfno],SEEK_SET,0L);
read(zkfhand[zkfno],(void *)keyhead[zkfno],KHEADSIZE);
filetype = keyhead[zkfno]->kftype;
if((filetype!='K')&&(filetype!='O'))
{ close(zkfhand[zkfno]);
free((void *)keyhead[zkfno]);
return(-3);
}

/* All went well */
keyhead[zkfno]->ackysc=0; /* Nothing in buffer yet */
zrewindk(zkfno); /* Rewind the file */
return(0);
}


/*
** Open a data file.
** File number is assumed to be in zdfno.
** RETURNS: 0 successful, error number if not.
** If return is a -1, look in errno for system error.
** If return is -2, malloc failed - not enough space
** to open the file.
** If return is -3, the file is not a ZSAM file.
*/
int zopend(fname,fnum)
char *fname; /* File name */
unsigned int fnum; /* Data file number */
{

char filetype;
int dfbsize; /* Data file buffer size */

zdfno = fnum;

/* Open the file and store the handle */
zdfhand[zdfno]=open(fname,O_RDWR | O_BINARY);
if(zdfhand[zdfno]==-1) return(-1);

/* Allocate space for key file header */
dathead[zdfno] = (zdat_header *)malloc(sizeof(zdat_header));
if(dathead[zdfno]==NULL) return(-2);

/* Read in the header information */
lseek(zdfhand[zdfno],SEEK_SET,0L);
read(zdfhand[zdfno],(void *)dathead[zdfno],DHEADSIZE);
filetype = dathead[zkfno]->dftype;
if((filetype!='S')&&(filetype!='C'))
{ close(zdfhand[zdfno]);
free((void *)dathead[zdfno]);
return(-3);
}

/* Allocate space for data file buffer */
dfbsize = dathead[zdfno]->reclen;
if(dathead[zdfno]->dftype=='C') dfbsize+=6;
datbuf[zdfno]=(char *)malloc(dfbsize);
if(datbuf[zdfno]==NULL)
{ free((void *)dathead[zdfno]);
close(zdfhand[zdfno]);
return(-2);
}

/* All went well */
return(0);
}


/*
** Close a key file.
*/
int zclosek(fnum)
unsigned int fnum; /* key file number */
{

zkfno=fnum;

/* Write the header information back out */
lseek(zkfhand[zkfno],SEEK_SET,0L);
write(zkfhand[zkfno],(void *)keyhead[zkfno],KHEADSIZE);

/* Close the file */
close(zkfhand[zkfno]);

return(0);
}

/*
** Close a data file.
*/
int zclosed(fnum)
unsigned int fnum; /* Data file number */
{
zdfno=fnum;

/* Write the header information back out */
lseek(zdfhand[zdfno],SEEK_SET,0L);
write(zdfhand[zdfno],(void *)dathead[zdfno],DHEADSIZE);

/* Close the file */
close(zdfhand[zdfno]);

return(0);
}

/*
** Rewind a key file.
** This routine sets the keyfile to its logical start.
** Returns ZSAM error number
*/
int zrewindk(fnum)
unsigned int fnum; /* Key file number */
{
zkfno=fnum;
zsams.funct=0; /* Rewind function */
zsams.keyhd=keyhead[zkfno]; /* Send header info */
return(zsam(&zsams));
}

/*
** Read key record.
** Search the keyfile for ZKEY, copy the associated record into ZREC.
** Returns ZSAM error code.
*/
int zreadkr(kfile,dfile,zkey,zrec)
unsigned int kfile; /* Key file */
unsigned int dfile; /* Data file */
char *zkey; /* Pointer to key string */
char *zrec; /* Pointer to data record */
{
zkfno=kfile;
zdfno=dfile;
zsams.funct = 1; /* Set function code */
zsams.kbuf = keybuf[zkfno]; /* Key file node buffer */
zsams.dbuf = datbuf[zdfno]; /* Data file buffer */
zsams.keyhd = keyhead[zkfno]; /* Key file header info */
zsams.dathd = dathead[zdfno]; /* Data file header info */
zsams.key = zkey; /* Key string */
zsams.rec = zrec; /* Record string */
return(zsam(&zsams));
}

/*
** Read next keyed record.
** Searches in kfile for the inorder successor of the current
** key. Copies the new key into ZKEY and the associated data record
** into ZREC.
** Returns ZSAM error code.
*/
int zreadnkr(kfile,dfile,zkey,zrec)
unsigned int kfile; /* Key file number */
unsigned int dfile; /* Data file number */
char *zkey; /* Key string */
char *zrec; /* Data record string */
{
zkfno=kfile;
zdfno=dfile;
zsams.funct = 2; /* Set function code */
zsams.kbuf = keybuf[zkfno]; /* Key file node buffer */
zsams.dbuf = datbuf[zdfno]; /* Data file buffer */
zsams.keyhd = keyhead[zkfno]; /* Key file header info */
zsams.dathd = dathead[zdfno]; /* Data file header info */
zsams.key = zkey; /* Key string */
zsams.rec = zrec; /* Record string */
return(zsam(&zsams));
}

/*
** Read next data record.
** dfile must be a complex data file.
** This routine searches for the next record in the current record
** set and copies that record into ZREC.
** Returns ZSAM error number.
*/
int zreadndr(dfile,zrec)
unsigned int dfile; /* Data file number */
char *zrec; /* Record string */
{
zdfno=dfile;

zsams.funct = 3; /* Set function code */
zsams.dbuf = datbuf[zdfno]; /* Data file buffer */
zsams.dathd = dathead[zdfno]; /* Data file header info */
zsams.rec = zrec; /* Record string */
return(zsam(&zsams));
}

/*
** Create keyed record.
** Adds the key in ZKEY into kfile. Creates a new record in dfile,
** loads that record with ZREC, and attaches it to ZKEY.
*/
int zcreatkr(kfile,dfile,zkey,zrec)
unsigned int kfile; /* Key file number */
unsigned int dfile; /* Data file number */
char *zkey; /* Key string */
char *zrec; /* Data record string */
{
zkfno=kfile;
zdfno=dfile;
zsams.funct = 4; /* Set function code */
zsams.kbuf = keybuf[zkfno]; /* Key file node buffer */
zsams.dbuf = datbuf[zdfno]; /* Data file buffer */
zsams.keyhd = keyhead[zkfno]; /* Key file header info */
zsams.dathd = dathead[zdfno]; /* Data file header info */
zsams.key = zkey; /* Key string */
zsams.rec = zrec; /* Record string */
return(zsam(&zsams));
}

/*
** Insert key.
** The key in ZKEY is added to kfile. Whatever is the current record
** in dfile is associated with that key. (A new data record is NOT
** created.)
** Returns ZSAM error code.
*/
int zinsertk(kfile,dfile,zkey)
unsigned int kfile; /* Key file number */
unsigned int dfile; /* Data file number */
char *zkey; /* Key string */
{
zkfno=kfile;
zdfno=dfile;
zsams.funct = 5; /* Set function code */
zsams.kbuf = keybuf[zkfno]; /* Key file node buffer */
zsams.keyhd = keyhead[zkfno]; /* Key file header info */
zsams.dathd = dathead[zdfno]; /* Data file header info */
zsams.key = zkey; /* Key string */
return(zsam(&zsams));
}


/*
** Write data record.
** The contents of ZREC overwrite the contents of dfile's current record.
** Returns ZSAM error code.
*/
zwritedr(dfile,zrec)
unsigned int dfile; /* Data file number */
char *zrec; /* Record string */
{
zdfno=dfile;
zsams.funct = 6; /* Set function code */
zsams.dathd = dathead[zdfno]; /* Data file header info */
zsams.dbuf = datbuf[zdfno];
zsams.rec = zrec; /* Record string */
return(zsam(&zsams));
}

/*
** Append data record.
** dfile must be a complex data file. A new data record is created in
** dfile and is attached to the current record set. The contents of
** ZREC are written into this new record.
** Returns ZSAM error code.
*/
zappenddr(dfile,zrec)
unsigned int dfile; /* Data file number */
char *zrec; /* Record string */
{
zdfno=dfile;
zsams.funct = 7; /* Set function code */
zsams.keyhd = keyhead[zkfno]; /* Key file header info */
zsams.dathd = dathead[zdfno]; /* Data file header info */
zsams.rec = zrec; /* Record string */
return(zsam(&zsams));
}

/*
** Delete keyed record.
** kfile is searched for ZKEY. If found, ZKEY is deleted and the
** record (or record set) in dfile associated with ZKEY is deleted
** from dfile.
** Returns ZSAM error code.
*/
zdelkr(kfile,dfile,zkey)
unsigned int kfile; /* Key file number */
unsigned int dfile; /* Data file number */
char *zkey; /* Key string */
{
zkfno=kfile;
zdfno=dfile;
zsams.funct = 8; /* Set function code */
zsams.kbuf = keybuf[zkfno]; /* Key file node buffer */
zsams.dbuf = datbuf[zdfno]; /* Data file buffer */
zsams.keyhd = keyhead[zkfno]; /* Key file header info */
zsams.dathd = dathead[zdfno]; /* Data file header info */
zsams.key = zkey; /* Key string */
return(zsam(&zsams));
}

/*
** Delete key.
** kfile is searched for ZKEY. If ZKEY is found, it is deleted.
**
*/
zdelk(kfile,zkey)
unsigned int kfile; /* Key file number */
char *zkey; /* Key string */
{
zkfno=kfile;
zsams.funct = 9; /* Set function code */
zsams.kbuf = keybuf[zkfno]; /* Key file node buffer */
zsams.keyhd = keyhead[zkfno]; /* Key file header info */
zsams.key = zkey; /* Key string */
return(zsam(&zsams));
}

/*
** Delete data record.
** dfile must be a complex file. The current record in dfile is
** deleted from the record set.
** Returns ZSAM error code.
*/
zdeld(dfile)
unsigned int dfile; /* Data file number */
{
zdfno=dfile;
zsams.funct = 10; /* Set function code */
zsams.dathd = dathead[zdfno]; /* Data file header info */
zsams.dbuf = datbuf[zdfno]; /* Data file record buffer */
return(zsam(&zsams));
}

/*
** Rewind a data record set.
** dfile must be a complex data file. The current record set is
** set to its logical beginning so that a call to zreadndr() will
** return the first record in the set.
*/
zrewindd(dfile)
unsigned int dfile; /* Data file number */
{
zdfno=dfile;
zsams.funct = 11; /* Set function code */
zsams.dathd = dathead[zdfno]; /* Data file header info */
zsams.dbuf = datbuf[zdfno]; /* Data file record buffer */
return(zsam(&zsams));
}

/*
** FOLLOWING ARE THE ROUTINES THAT ZSAM CALLS TO
** DO ITS FILE I/O.
*/

/*
** zgetks() - Get a keyfile sector.
*/
zgetks(node)
unsigned int node;
{
/* Calculate offset (multiply by 512) */
zoffset = ((long)node) << 9;

lseek(zkfhand[zkfno],zoffset,0);
read(zkfhand[zkfno],keybuf[zkfno],KNODESIZE);


return;
}

/*
** zputks() - Put a keyfile sector.
*/
zputks(node)
unsigned int node;
{
/* Calculate offset */
zoffset = ((long)node) << 9;

lseek(zkfhand[zkfno],zoffset,0);
if(write(zkfhand[zkfno],keybuf[zkfno],KNODESIZE)!=KNODESIZE)
{ printf("Error writing key file: %d",zkfno);
exit(0);
}

return;
}

/*
** zgetdr() - Get a data file record.
*/
zgetdr(recl,offset,recordn,count)
unsigned int recl;
unsigned int offset;
unsigned long recordn;
unsigned int count;
{
/* Calculate true offset */
zoffset = (long)recl * (long)(recordn-1) +
(long)offset + DHEADSIZE;

lseek(zdfhand[zdfno],zoffset,0);
read(zdfhand[zdfno],datbuf[zdfno],count);

return;
}

/*
** zputdr() - Put a data record.
*/

zputdr(recl,offset,recordn,count)
unsigned int recl; /* Record length for this data file */
unsigned int offset; /* Offset into record */
unsigned long recordn; /* Record number */
unsigned int count; /* Number of bytes */
{
/* Calculate true offset */
zoffset = (long)recl * (long)(recordn-1) +
(long)offset + DHEADSIZE;

lseek(zdfhand[zdfno],zoffset,0);
if(write(zdfhand[zdfno],datbuf[zdfno],count)!=count)
{ printf("Error writing data file %d",zdfno);
exit(0);
}

return;
}




===============================

ZMAKEBIB.C

===============================




/*
** This program builds the bibliography database described in part III
** of "Trees 'N Keys" (Some Assembly Required, BYTE Magazine).
** It prompts for the input data filename, then reads that file and
** updates the database. Notice that this program doesn't create
** the database files (you have to use ZMAKEF to do that), it simply
** information to them. This means that you can keep adding stuff to
** the database 'til the cows come home....or your disk fills up.
*/

#include
#include
#include

/*
** ZSAM Globals
*/

#define nzkfiles 4 /* Number of key files */
#define nzdfiles 4 /* Number of data files */

#define KNODESIZE 512 /* Size of a key node */
/*
** ZSAM structure definitions.
*/

typedef unsigned char byte;

typedef struct { /* Key file header */
char kftype; /* Key file type, "K" or "O" */
unsigned int rootsc; /* Root sector */
unsigned int nokeysl; /* Number of keys, lo */
byte nokeysh; /* Number of keys, hi */
unsigned int kavsec; /* Key avail list head */
unsigned int nxkysc; /* Next free sector */
byte keylen; /* Key length */
byte maxks; /* Maximum keys per sector (node) */
unsigned int ackysc; /* Actual key sector in buffer */
byte misc[48]; /* Transient storage */
} zkey_header;

#define KHEADSIZE sizeof(zkey_header)-48

typedef struct { /* Data file header */
char dftype; /* Data file type, "S" or "C" */
unsigned int reclen; /* Record length */
unsigned int norecsl; /* Number of records, lo */
byte norecsh; /* Number of records, hi */
unsigned int davlo; /* Avail list, lo */
byte davhi; /* Avail list, hi */
unsigned int nxdalo; /* Next data record, lo */
byte nxdahi; /* Next data record, hi */
char misc[20]; /* Transient storage */
} zdat_header;
#define DHEADSIZE sizeof(zdat_header)-20

/*
** ZSAM interface storage.
*/

unsigned int zkfno; /* Current key file number */
unsigned int zdfno; /* Current data file number */
int zkfhand[nzkfiles]; /* Array of handles to key files */
int zdfhand[nzdfiles]; /* Array of handles to data files */
zkey_header *keyhead[nzkfiles]; /* Pointers to key file header storage */
zdat_header *dathead[nzdfiles]; /* Pointers to data file header storage */
char *keybuf[nzkfiles]; /* Pointers to key file buffers */
char *datbuf[nzdfiles]; /* Pointers to data file buffers */
long zoffset; /* Offset into files */

/*
** A pointer to the following structure (zsams) is passed
** to the ZSAM assembly routines.
*/
typedef struct {
unsigned int funct; /* Function code */
char *kbuf; /* Pointer to current key buffer */
char *dbuf; /* Pointer to current data buffer */
char *key; /* Pointer to current key */
char *rec; /* Pointer to current data record */
zkey_header *keyhd; /* Pointer to current key file header */
zdat_header *dathd; /* Pointer to current data file header */
} zsamstr;

zsamstr zsams;

extern int errno;

/*
** File definitions. Notice that ZSAM file numbers are assigned by
** *YOU* (the caller), not ZSAM. So, since I've set nzfiles and
** ndfiles to 4, I can reference key files and data files 0-3.
*/
#define MASTER_KEY 0
#define TITLE_DAT 0
#define KEYWORDS_KEY 1
#define KEYWORDS_DAT 1
#define AUTHMAST_KEY 2
#define AUTHMAST_DAT 2
#define AUTHNAME_KEY 3
#define AUTHNAME_DAT 3

/*
** User globals
*/
char difname[80]; /* Dictionary input filename */
char mastkey[10]; /* Master key */
char strng[80]; /* Temp. storage string for conversion */
int pg; /* Page number */
char title[80]; /* Story title */
int nauths; /* Number of authors */
char authky[20]; /* Author key */
char authrc[30]; /* Author's name record */
char temprc[80]; /* Temporary record */
int nkeys; /* Number of keys */
char keywd[20]; /* Keyword */
int i; /* Increment */
int j; /* Increment */
FILE *difile; /* Dictionary input file */

/* ************************************************************ */
/* MAIN ROUTINE FOLLOWS */
/* ************************************************************ */
main ()
{

/*
** Open all the ZSAM index and data files.
*/

zopenk("MINDEX.KEY",MASTER_KEY); /* Master index */
zopend("TITLES.DAT",TITLE_DAT); /* Titles data file */

/* NOTE: The KEYWORDS files are what I called the TOPICS files in
** the article. I changed it in the article so novice readers
** wouldn't get confused between "keys" and "keywords". */
zopenk("KEYWORDS.KEY",KEYWORDS_KEY); /* Keywords index */
zopend("KEYWORDS.DAT",KEYWORDS_DAT); /* Data file */

zopenk("AUTHOR.KEY",AUTHMAST_KEY); /* Author index */
zopend("AUTHOR.DAT",AUTHMAST_DAT); /* Data file */

zopenk("AUTHNAM.KEY",AUTHNAME_KEY); /* Author's name index */
zopend("AUTHNAM.DAT",AUTHNAME_DAT); /* Author's name data file */

/*
** Open the input file.
*/

printf("Enter data input filename:");
scanf("%s",difname);
if ((difile=fopen(difname,"r"))==NULL)
{ printf("*ERROR OPENING INPUT FILE-ABORTING*\n");
closeall();
exit(0);
}

/*
** MAIN LOOP -
** Read the issue date.
*/
fgets(mastkey,10,difile);

do {
/*
** Read page number.
*/
fgets(strng,10,difile);
sscanf(strng,"%d",&pg);

/*
** Build the master key. Notice that you have to
** flip the bytes for the page number so that the high
** byte comes first. This ensures that the keys will be
** stored in proper sorting order in the file.
*/
mastkey[4]=(unsigned char)(pg>>8);
mastkey[5]=(unsigned char)(pg & 255);
mastkey[6]='\000';
/*
** See if the key already exists, if it does, increment the
** last byte of mastkey[] and try again. Ultimately, we'll
** hit upon a unique key for this entry.
*/
while(zreadkr(MASTER_KEY,TITLE_DAT,mastkey,title)
== 0)
++mastkey[6];
/*
** We now have a unique key in mastkey[] - read in and
** attach title.
*/
for (i=0;i<81;++i) title[i]='\000';
fgets(title,82,difile);
zcreatkr(MASTER_KEY,TITLE_DAT,mastkey,title);

/*
** Now read in the names of the authors who wrote the article.
*/
fgets(strng,80,difile);
sscanf(strng,"%d",&nauths);
for (i=0;i { for (j=0;j<17;++j) authky[j]='\000';
fgets(authky,20,difile);
for (j=0;j<21;++j) authrc[j]='\000';
fgets(authrc,22,difile);
/*
** Build list of master keys appended to author key.
*/
if( zreadkr(AUTHMAST_KEY,AUTHMAST_DAT,authky,temprc)
== 0)
zappenddr(AUTHMAST_DAT,mastkey);
else
zcreatkr(AUTHMAST_KEY,AUTHMAST_DAT,authky,mastkey);
/*
** Add author's name to author file.
*/

if(zreadkr(AUTHNAME_KEY,AUTHNAME_DAT,mastkey,temprc)
== 0)
zappenddr(AUTHNAME_DAT,authrc);
else
zcreatkr(AUTHNAME_KEY,AUTHNAME_DAT,mastkey,authrc);
}
/*
** Read in keywords and add to keyword index.
*/
fgets(strng,80,difile);
sscanf(strng,"%d",&nkeys);
for (i=0;i {
for (j=0;j<17;++j) keywd[j]='\000';
fgets(keywd,18,difile);
if (zreadkr(KEYWORDS_KEY,KEYWORDS_DAT,keywd,temprc)
== 0)
zappenddr(KEYWORDS_DAT,mastkey);
else
zcreatkr(KEYWORDS_KEY,KEYWORDS_DAT,keywd,mastkey);
}
/*
** Read next date and continue. A "@" character indicates EOF.
*/
fgets(mastkey,10,difile);
} while (mastkey[0]!='@');
fclose (difile);
closeall();
printf("\nNORMAL TERMINATION...WHEW\n");
exit(0);
}


/*
** This routine closes all the ZSAM files that are open
** for this program.
*/
closeall()
{
zclosek(0); zclosed(0);
zclosek(1); zclosed(1);
zclosek(2); zclosed(2);
zclosek(3); zclosed(3);
return;
}

/****************************************/
/* ZSAM ENTRY POINTS FOLLOW */
/****************************************/

/*
** Open a key file.
** RETURNS: 0 successful, error number if not.
** If return is a -1, look in errno for system error.
** If return is -2, malloc failed - not enough space
** to open the file.
** If return is -3, the file is not a ZSAM file.
*/
int zopenk(fname,fnum)
char *fname; /* File name */
unsigned int fnum; /* File number */
{

char filetype;

zkfno=fnum;

/* Open the file and store the handle */
zkfhand[zkfno]=open(fname,O_RDWR | O_BINARY);
if(zkfhand[zkfno]==-1) return(-1);

/* Allocate space for key file header */
keyhead[zkfno] = (zkey_header *)malloc(sizeof(zkey_header));
if(keyhead[zkfno]==NULL) return(-2);

/* Allocate space for key file buffer */
keybuf[zkfno] = (char *)malloc(KNODESIZE);
if(keybuf[zkfno]==NULL)
{ free((void *)keyhead[zkfno]);
return(-2);
}

/* Read in the header information */
lseek(zkfhand[zkfno],SEEK_SET,0L);
read(zkfhand[zkfno],(void *)keyhead[zkfno],KHEADSIZE);
filetype = keyhead[zkfno]->kftype;
if((filetype!='K')&&(filetype!='O'))
{ close(zkfhand[zkfno]);
free((void *)keyhead[zkfno]);
return(-3);
}

/* All went well */
keyhead[zkfno]->ackysc=0; /* Nothing in buffer yet */
zrewindk(zkfno); /* Rewind the file */
return(0);
}


/*
** Open a data file.
** File number is assumed to be in zdfno.
** RETURNS: 0 successful, error number if not.
** If return is a -1, look in errno for system error.
** If return is -2, malloc failed - not enough space
** to open the file.
** If return is -3, the file is not a ZSAM file.
*/
int zopend(fname,fnum)
char *fname; /* File name */
unsigned int fnum; /* Data file number */
{

char filetype;
int dfbsize; /* Data file buffer size */

zdfno = fnum;

/* Open the file and store the handle */
zdfhand[zdfno]=open(fname,O_RDWR | O_BINARY);
if(zdfhand[zdfno]==-1) return(-1);

/* Allocate space for key file header */
dathead[zdfno] = (zdat_header *)malloc(sizeof(zdat_header));
if(dathead[zdfno]==NULL) return(-2);

/* Read in the header information */
lseek(zdfhand[zdfno],SEEK_SET,0L);
read(zdfhand[zdfno],(void *)dathead[zdfno],DHEADSIZE);
filetype = dathead[zkfno]->dftype;
if((filetype!='S')&&(filetype!='C'))
{ close(zdfhand[zdfno]);
free((void *)dathead[zdfno]);
return(-3);
}

/* Allocate space for data file buffer */
dfbsize = dathead[zdfno]->reclen;
if(dathead[zdfno]->dftype=='C') dfbsize+=6;
datbuf[zdfno]=(char *)malloc(dfbsize);
if(datbuf[zdfno]==NULL)
{ free((void *)dathead[zdfno]);
close(zdfhand[zdfno]);
return(-2);
}

/* All went well */
return(0);
}


/*
** Close a key file.
*/
int zclosek(fnum)
unsigned int fnum; /* key file number */
{

zkfno=fnum;

/* Write the header information back out */
lseek(zkfhand[zkfno],SEEK_SET,0L);
write(zkfhand[zkfno],(void *)keyhead[zkfno],KHEADSIZE);

/* Close the file */
close(zkfhand[zkfno]);

return(0);
}

/*
** Close a data file.
*/
int zclosed(fnum)
unsigned int fnum; /* Data file number */
{
zdfno=fnum;

/* Write the header information back out */
lseek(zdfhand[zdfno],SEEK_SET,0L);
write(zdfhand[zdfno],(void *)dathead[zdfno],DHEADSIZE);

/* Close the file */
close(zdfhand[zdfno]);

return(0);
}

/*
** Rewind a key file.
** This routine sets the keyfile to its logical start.
** Returns ZSAM error number
*/
int zrewindk(fnum)
unsigned int fnum; /* Key file number */
{
zkfno=fnum;
zsams.funct=0; /* Rewind function */
zsams.keyhd=keyhead[zkfno]; /* Send header info */
return(zsam(&zsams));
}

/*
** Read key record.
** Search the keyfile for ZKEY, copy the associated record into ZREC.
** Returns ZSAM error code.
*/
int zreadkr(kfile,dfile,zkey,zrec)
unsigned int kfile; /* Key file */
unsigned int dfile; /* Data file */
char *zkey; /* Pointer to key string */
char *zrec; /* Pointer to data record */
{
zkfno=kfile;
zdfno=dfile;
zsams.funct = 1; /* Set function code */
zsams.kbuf = keybuf[zkfno]; /* Key file node buffer */
zsams.dbuf = datbuf[zdfno]; /* Data file buffer */
zsams.keyhd = keyhead[zkfno]; /* Key file header info */
zsams.dathd = dathead[zdfno]; /* Data file header info */
zsams.key = zkey; /* Key string */
zsams.rec = zrec; /* Record string */
return(zsam(&zsams));
}

/*
** Read next keyed record.
** Searches in kfile for the inorder successor of the current
** key. Copies the new key into ZKEY and the associated data record
** into ZREC.
** Returns ZSAM error code.
*/
int zreadnkr(kfile,dfile,zkey,zrec)
unsigned int kfile; /* Key file number */
unsigned int dfile; /* Data file number */
char *zkey; /* Key string */
char *zrec; /* Data record string */
{
zkfno=kfile;
zdfno=dfile;
zsams.funct = 2; /* Set function code */
zsams.kbuf = keybuf[zkfno]; /* Key file node buffer */
zsams.dbuf = datbuf[zdfno]; /* Data file buffer */
zsams.keyhd = keyhead[zkfno]; /* Key file header info */
zsams.dathd = dathead[zdfno]; /* Data file header info */
zsams.key = zkey; /* Key string */
zsams.rec = zrec; /* Record string */
return(zsam(&zsams));
}

/*
** Read next data record.
** dfile must be a complex data file.
** This routine searches for the next record in the current record
** set and copies that record into ZREC.
** Returns ZSAM error number.
*/
int zreadndr(dfile,zrec)
unsigned int dfile; /* Data file number */
char *zrec; /* Record string */
{
zdfno=dfile;
zsams.funct = 3; /* Set function code */
zsams.dbuf = datbuf[zdfno]; /* Data file buffer */
zsams.dathd = dathead[zdfno]; /* Data file header info */
zsams.rec = zrec; /* Record string */
return(zsam(&zsams));
}

/*
** Create keyed record.
** Adds the key in ZKEY into kfile. Creates a new record in dfile,
** loads that record with ZREC, and attaches it to ZKEY.
*/
int zcreatkr(kfile,dfile,zkey,zrec)
unsigned int kfile; /* Key file number */
unsigned int dfile; /* Data file number */
char *zkey; /* Key string */
char *zrec; /* Data record string */
{
zkfno=kfile;
zdfno=dfile;
zsams.funct = 4; /* Set function code */
zsams.kbuf = keybuf[zkfno]; /* Key file node buffer */
zsams.dbuf = datbuf[zdfno]; /* Data file buffer */
zsams.keyhd = keyhead[zkfno]; /* Key file header info */
zsams.dathd = dathead[zdfno]; /* Data file header info */
zsams.key = zkey; /* Key string */
zsams.rec = zrec; /* Record string */
return(zsam(&zsams));
}

/*
** Insert key.
** The key in ZKEY is added to kfile. Whatever is the current record
** in dfile is associated with that key. (A new data record is NOT
** created.)
** Returns ZSAM error code.
*/
int zinsertk(kfile,dfile,zkey)
unsigned int kfile; /* Key file number */
unsigned int dfile; /* Data file number */
char *zkey; /* Key string */
{
zkfno=kfile;
zdfno=dfile;
zsams.funct = 5; /* Set function code */
zsams.kbuf = keybuf[zkfno]; /* Key file node buffer */
zsams.keyhd = keyhead[zkfno]; /* Key file header info */
zsams.dathd = dathead[zdfno]; /* Data file header info */
zsams.key = zkey; /* Key string */
return(zsam(&zsams));
}

/*
** Write data record.
** The contents of ZREC overwrite the contents of dfile's current record.
** Returns ZSAM error code.
*/
zwritedr(dfile,zrec)
unsigned int dfile; /* Data file number */
char *zrec; /* Record string */
{
zdfno=dfile;
zsams.funct = 6; /* Set function code */
zsams.dathd = dathead[zdfno]; /* Data file header info */
zsams.dbuf = datbuf[zdfno];
zsams.rec = zrec; /* Record string */
return(zsam(&zsams));
}

/*
** Append data record.
** dfile must be a complex data file. A new data record is created in
** dfile and is attached to the current record set. The contents of
** ZREC are written into this new record.
** Returns ZSAM error code.
*/
zappenddr(dfile,zrec)
unsigned int dfile; /* Data file number */
char *zrec; /* Record string */
{
zdfno=dfile;
zsams.funct = 7; /* Set function code */
zsams.keyhd = keyhead[zkfno]; /* Key file header info */
zsams.dathd = dathead[zdfno]; /* Data file header info */
zsams.rec = zrec; /* Record string */
return(zsam(&zsams));
}

/*
** Delete keyed record.
** kfile is searched for ZKEY. If found, ZKEY is deleted and the
** record (or record set) in dfile associated with ZKEY is deleted
** from dfile.
** Returns ZSAM error code.
*/
zdelkr(kfile,dfile,zkey)
unsigned int kfile; /* Key file number */
unsigned int dfile; /* Data file number */
char *zkey; /* Key string */
{
zkfno=kfile;
zdfno=dfile;
zsams.funct = 8; /* Set function code */
zsams.kbuf = keybuf[zkfno]; /* Key file node buffer */
zsams.dbuf = datbuf[zdfno]; /* Data file buffer */
zsams.keyhd = keyhead[zkfno]; /* Key file header info */
zsams.dathd = dathead[zdfno]; /* Data file header info */
zsams.key = zkey; /* Key string */
return(zsam(&zsams));
}

/*
** Delete key.
** kfile is searched for ZKEY. If ZKEY is found, it is deleted.
**
*/
zdelk(kfile,zkey)
unsigned int kfile; /* Key file number */
char *zkey; /* Key string */
{
zkfno=kfile;
zsams.funct = 9; /* Set function code */
zsams.kbuf = keybuf[zkfno]; /* Key file node buffer */
zsams.keyhd = keyhead[zkfno]; /* Key file header info */
zsams.key = zkey; /* Key string */
return(zsam(&zsams));
}

/*
** Delete data record.
** dfile must be a complex file. The current record in dfile is
** deleted from the record set.
** Returns ZSAM error code.
*/
zdeld(dfile)
unsigned int dfile; /* Data file number */
{
zdfno=dfile;
zsams.funct = 10; /* Set function code */
zsams.dathd = dathead[zdfno]; /* Data file header info */
zsams.dbuf = datbuf[zdfno]; /* Data file record buffer */
return(zsam(&zsams));
}

/*
** Rewind a data record set.
** dfile must be a complex data file. The current record set is
** set to its logical beginning so that a call to zreadndr() will
** return the first record in the set.
*/
zrewindd(dfile)
unsigned int dfile; /* Data file number */
{
zdfno=dfile;
zsams.funct = 11; /* Set function code */
zsams.dathd = dathead[zdfno]; /* Data file header info */
zsams.dbuf = datbuf[zdfno]; /* Data file record buffer */
return(zsam(&zsams));
}

/*
** FOLLOWING ARE THE ROUTINES THAT ZSAM CALLS TO
** DO ITS FILE I/O.
** Note: I've modified these routines so that they do check
** for number of bytes written. This was for my own debug
** information and if you think it slows things down too much
** (cough) you can take the if statements out. -- RG
*/

/*
** zgetks() - Get a keyfile sector.
*/
zgetks(node)
unsigned int node;
{
/* Calculate offset (multiply by 512) */
zoffset = ((long)node) << 9;

lseek(zkfhand[zkfno],zoffset,0);
read(zkfhand[zkfno],keybuf[zkfno],KNODESIZE);

return;
}

/*
** zputks() - Put a keyfile sector.
*/
zputks(node)
unsigned int node;
{
/* Calculate offset */
zoffset = ((long)node) << 9;

lseek(zkfhand[zkfno],zoffset,0);
if(write(zkfhand[zkfno],keybuf[zkfno],KNODESIZE)!=KNODESIZE)
{ printf("Error writing key file: %d",zkfno);
exit(0);
}

return;
}

/*
** zgetdr() - Get a data file record.
*/
zgetdr(recl,offset,recordn,count)
unsigned int recl;
unsigned int offset;
unsigned long recordn;
unsigned int count;
{
/* Calculate true offset */
zoffset = (long)recl * (long)(recordn-1) +
(long)offset + DHEADSIZE;

lseek(zdfhand[zdfno],zoffset,0);
read(zdfhand[zdfno],datbuf[zdfno],count);

return;
}

/*
** zputdr() - Put a data record.
*/

zputdr(recl,offset,recordn,count)
unsigned int recl; /* Record length for this data file */
unsigned int offset; /* Offset into record */
unsigned long recordn; /* Record number */
unsigned int count; /* Number of bytes */
{
/* Calculate true offset */
zoffset = (long)recl * (long)(recordn-1) +
(long)offset + DHEADSIZE;

lseek(zdfhand[zdfno],zoffset,0);
if(write(zdfhand[zdfno],datbuf[zdfno],count)!=count)
{ printf("Error writing data file %d",zdfno);
exit(0);
}

return;
}



 December 9, 2017  Add comments

Leave a Reply