

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

          ZINPUT.DAT

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


8501
98
Ciarcia's Circuit Cellar: Understanding Linear Power Supplies
1
CIARCIA        S
Steve Ciarcia
5
LINEAR
POWERSUPPLY
SUPPLY
DESIGN
REGULATOR
8501
113
The Visual Mind and the Macintosh
1
BENZON         B
Bill Benzon
5
MACINTOSH
MACPAINT
APPLE
ART
GRAPHICS
8501
135
A Glimpse into Future Television
1
NADAN          J
Joseph S. Nadan
6
TELEVISION
TV
HDTV
NSC
FUTURE
VIDEO
8501
155
Microsoft Macintosh BASIC Version 2.0
1
WILLIAMS       G
Gregg Williams
5
APPLE
MICROSOFT
MACINTOSH
BASIC
MBASIC
8501
167
The Apple Story, Part 2: More History and the Apple III
2
WILLIAMS       G
Gregg Williams
MOORE          R
Rob Moore
5
HISTORY
WOZNIAK
APPLEIII
SWEET16
SOS
8501
183
Uninterruptible Power Supplies
1
RYNONE         W
William Rynone
4
POWERSUPPLY
SUPPLY
UNINTERRUPTIBLE
UPS
8501
197
An Introduction to Fiber Optics, Part 2: Connections and Networks
1
SHUFORD        R
Richard S. Shuford
5
OPTICS
FIBEROPTICS
NETWORKS
ETHERNET
LANS
8501
211
Algorithms for a Variable-Precision Calculator
1
NILSON         P
Paul A. Nilson
3
ALGORITHMS
CALCULATOR
MATHEMATICS
8501
223
Audio-Frequency Analyzer
1
BANES          V
Vince Banes
7
AUDIO
IBM
STEREO
ADC
DAC
VCO
FREQUENCY
8501
255
Font Design for Personal Workstations
1
BIGELOW        C
Charles Bigelow
5
FONTS
WORKSTATION
DISPLAY
GRAPHICS
PRINTER
8501
275
Expert Systems - Myth or Reality?
1
DAMBROSIO      B
Bruce D'Ambrosio
6
EXPERT
ARTIFICIAL
INTELLIGENCE
AI
KNOWLEDGE
INFERENCE
8501
290
The HP 110 Portable Computer
1
HAAS           M
Mark Haas
10
PORTABLE
HP110
8086
80C86
LAPSIZED
HEWLETTPACKARD
PAM
MSDOS
LCD
HPIL
8501
305
Gifford's MP/M 8-16
1
STROM          C
Charles H. Strom
7
MPM
S100
CPM
MULTIUSER
GIFFORD
8085
8088
8501
317
Lotus's Symphony
1
POUNTAIN       D
Dick Pountain
5
LOTUS
SPREADSHEET
SYMPHONY
123
IBM
8501
329
MagicPrint
1
MILLER         A
Alan R. Miller
5
PRINTER
CPM
MSDOS
MAGICPRINT
WORDPROCESSING
8501
337
The Hewlett-Packard ThinkJet Printer
1
HAAS           M
Mark Haas
7
HEWLETTPACKARD
HP
PRINTER
INKJET
IBM
APPLE
THINKJET
8501
345
The TI Omni 800/Model 855 Printer
1
HAAS           M
Mark Haas
6
TI
TEXASINSTRUMENT
PRINTER
OMNI800
FONTS
855
8502
98
The HP Integral Personal Computer
1
ROBINSON       P
Phillip Robinson
8
HP
HEWLETTPACKARD
INTEGRAL
UNIX
THINKJET
INKJET
ELECTROLUMINESCE
FLATSCREEN
8502
104
Ciarcia's Circuit Cellar: Build a Serial EPROM Programmer
1
CIARCIA        S
Steve Ciarcia
4
CIARCIA
SERIAL
EPROM
PROGRAMMER
8502
120
The Macintosh Office
2
MARKOFF        J
John Markoff
ROBINSON       P
Phillip Robinson
8
APPLE
APPLETALK
MACINTOSH
LASERPRINTER
PRINTER
NETWORK
POSTSCRIPT
LASERWRITER
8502
138
C to Pascal
1
CARNEVALE      T
Ted Carnevale
2
C
PASCAL
8502
147
Simulate a Servo System
1
STAUFFER       D
Don Stauffer
5
SIMULATION
SIMULATE
SERVO
ENGINEERING
PHYSICS
8502
163
Introduction to Image Processing
1
STAR           J
Jeffrey L. Star
3
IMAGE
IMAGEPROCESSING
GRAPHICS
8502
177
The Birth of a Computer
1
NASH           J
John C. Nash
4
TURING
WILKINSON
ACE
EDSAC
8502
199
A Low-Cost Date-Acquisition System
2
OKAMURA        K
Kiyohisa Okamura
AGHAITABRIZ    K
Kamyab Aghai-Tabriz
3
DATAACQUISITION
ADC
COMMODORE64
8502
207
Fourier Smoothing Withoug the Fast Fourier Transform
2
AUBANEL        E
Eric E. Aubanel
OLDHAM         K
Keith B. Oldham
6
FOURIER
FASTFOURIER
TRANSFORM
NOISE
ALGORITHM
MATHEMATICS
8502
223
Paranoia: A Floating-Point Benchmark
1
KARPINSKI      R
Richard Karpinski
3
FLOATINGPOINT
PARANOIA
BENCHMARK
8502
239
Modeling Mass-Action Kinetics
1
CURTIS         A
Alan Curtis
7
KINETICS
MODELING
SCIENCE
PHYSICS
MASSACTION
SIMULATION
SIMULATE
8502
251
Viewing Molecules with the Macintosh
1
KIRKLAND       E
Earl J. Kirkland
9
MACINTOSH
APPLE
MOLECULES
PHYSICS
SIMULATION
SIMULATE
GRAPHICS
SCIENCE
3D
8502
263
Laboratory Interfacing
1
FORD           L
Lincoln E. Ford PHD
5
LABORATORY
SCIENCE
INTERFACING
MEDICINE
ADC
8502
269
Interfacing for Data Acquisition
1
CLUNE          T
Thomas R. Clune
5
INTERFACING
DATAACQUISITION
ADC
IEEE488
HPIB
8502
291
NewWord
2
HEILBORN       J
John Heilborn
REEL           N
Nanci Reel
3
WORDPROCESSING
WORDSTAR
NEWWORD
8502
295
Janus/Ada
1
WELCH          M
Mark J. Welch
5
JANUSADA
ADA
LANGUAGE
MSDOS
CPM
8502
302
The Epson Geneva PX-8
1
MALLOY         R
Rich Malloy
6
EPSON
GENEVAPX8
Z80
PORTABLE
CPM
LCD
8502
311
Two Modula-2 Compilers for the IBM PC
1
BOWYER         K
Kevin Bowyer
3
MODULA2
IBM
LANGUAGE
8502
317
E-Mail for the Masses
1
RASH           W
Wayne Rash Jr.
6
EMAIL
MCIMAIL
EASYLINK
WESTERNUNION
COMMUNICATIONS
MAIL
8502
325
Mannesmann Tally MT 160
1
WELCH          M
Mark J. Welch
5
MANNESMANNTALLY
MT160
PRINTER
MATRIX
DOTMATRIX
@





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

          ZINPUT.FRM

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



The format of the data in ZINPUT.DAT is as follows (notice that
each data item is on a separate line by itself):

YYMM                    -- Date of the issue the article was in.
PPP                     -- Page number the Article was on
<TITLE>                 -- Article's title (up to 80 characters)
N                       -- Number of Authors
LLLLLLLLLLLLLLLF        -- Author key. (See note 1 below).
<AUTHOR NAME>           -- Author's name.  Up to 20 characters.
..repeat N times...     -- Author key and author's name repeats N times.
M                       -- Number of keywords (topics)
<KEYWORD>               -- Keyword -- up to 16 characters
..repeat M times...     -- Keywords repeat M times.
YYMM                    -- Date of issue of next article
..repeats..             -- The structure repeats for however many articles
                        --   you want to store
@                       -- The "@" character indicates termination.  It
                        --   must come after the last keyword of the last
                        --   article.

Note 1. The author's key consists of last name plus first initial.
The last name can be up to 15 characters long.  The first initial
MUST be the 16th character on the line.  So, "Steve Ciarcia" would
become:
CIARCIA        S
1234567890123456    <--- character position.

--Rick Grehan





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

          ZMAKEF.C

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



/*
** This program allows you to create ZSAM key and data files.
** In other words, it creates the file and writes the initial
** header information.  The files are empty and ready to use.
**
** For KEY files, you'll need:
**   a) The file name.  It is created in the current directory.
**   b) The file type. "K" means it's a key file with an associated
**      data file.  "O" means it's keyonly (gungily supported in
**      ZSAM).  A keyonly file has no associated data file, and
**      it meant to be used as a sorting vehicle.
**   c) The keylength (up to 64).
** For DATA files, you'll need:
**   a) The file name.
**   b) The file type.  "S" is a simple file (one record per
**      key).  "C" is a complex file (multiple records per key).
**   c) The record length.  Minimum (what?  there's a minimum?)
**      is 3 bytes.
*/
#include <stdio.h>
#include <fcntl.h>
#include <sys\stat.h>

/*
** ZSAM Globals
*/

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

/*
** 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
#define KHEADPAD 512-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
#define IDATOFF sizeof(zdat_header)-20

/*
** ZSAM interface storage.
*/

unsigned int    zkfno;          /* Current key file number */
unsigned int    zdfno;          /* Current data file number */
unsigned int    zkfhand[nzkfiles];  /* Array of handles to key files */
unsigned 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;

/*
** Create a zsam key file.
** Returns 0 if ok, -1 if error (error code in errno).
*/
zcreate_kfile(fname,ftype,keyl)
char *fname;                            /* File pathname */
char ftype;                             /* File type */
int keyl;                               /* Key length for this file */
{
        zkey_header create_header;      /* Header for file to create */
        int fhand;
        int werr;
        int i;
        /* Pad used to "fill out a sector" */
        char pad[KHEADPAD];
        for(i=0;i<KHEADPAD;++i)
          pad[i]=' ';
        /* Calculate maximum number of keys per node */
        create_header.maxks = (512-3) / (keyl+5);

        /* Build rest of header stuff */
        create_header.kftype = ftype;
        create_header.keylen = keyl;
        create_header.rootsc = 0;
        create_header.nokeysl = 0;
        create_header.nokeysh = 0;
        create_header.kavsec = 0;
        create_header.nxkysc = 1;
        create_header.ackysc = 0;

        /* Create the file */
        fhand = open(fname,O_RDWR | O_CREAT | O_BINARY,
                S_IREAD | S_IWRITE);
        if(fhand==NULL) return(-1);

        /* Write the header information */
        werr = write(fhand,&create_header,KHEADSIZE);
        if((werr<0)||(werr!=KHEADSIZE)) return (-1);
        werr = write(fhand,pad,KHEADPAD);
printf("%d\n",werr);
        if((werr<0)||(werr!=KHEADPAD)) return(-1);

        return(0);
}

/*
** Create a zsam data file.
*/
zcreate_dfile(fname,ftype,recl)
char *fname;
char ftype;
unsigned int recl;
{
        zdat_header create_header;
        int fhand;
        int werr;

        /* Load stuff into the header */
        create_header.dftype = ftype;
        create_header.reclen = recl;
        create_header.norecsl = 0;
        create_header.norecsh = 0;
        create_header.davlo = 0;
        create_header.davhi = 0;
        create_header.nxdalo = 1;
        create_header.nxdahi = 0;

        /* Create the file */
        fhand = open(fname,O_RDWR | O_CREAT | O_BINARY,
                S_IREAD | S_IWRITE);
        if(fhand==NULL) return(-1);

        /* Write the header information */
        werr = write(fhand,&create_header,DHEADSIZE);
        if((werr<0)||(werr!=DHEADSIZE)) return (-1);

        return(0);
}

main()
{
        char choice[2];                 /* Selection choice */
        char kfname[40],dfname[40];
        char kfilet[2],dfilet[2];
        int keylen,reclen;

        /* Find out what the use wants to do */
        printf("Create ZSAM files...\n\n");

        while(1) {

        printf("Do you want to create\n");
        printf("   K - a key file, or\n");
        printf("   D - a data file?\n");
        printf("Choice (X to exit):");
        scanf("%s",choice);

        switch(choice[0]) {

                case 'K':
                case 'k':
                  printf("\n");
                  printf("Enter key file name:");
                  scanf("%s",kfname);
                  printf("Enter key length:");
                  scanf("%d",&keylen);
                  do {
                   kfilet[0]=' ';
                   printf("Enter file type (K or O):");
                   scanf("%s",kfilet);
                  } while((kfilet[0]!='K')&&(kfilet[0]!='O'));
                  zcreate_kfile(kfname,kfilet[0],keylen);
                  break;

                case 'D':
                case 'd':
                  printf("\n");
                  printf("Enter data file name:");
                  scanf("%s",dfname);
                  printf("Enter record length:");
                  scanf("%d",&reclen);
                  do {
                   dfilet[0]=' ';
                   printf("Enter file type (S or C):");
                   scanf("%s",dfilet);
                  } while((dfilet[0]!='S')&&(dfilet[0]!='C'));
                  zcreate_dfile(dfname,dfilet[0],reclen);
                  break;

                case 'X':
                case 'x':
                        exit(0);

                default:
                  printf("Eh?\n\n");
                  break;
        }

        }
}





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

          ZTEMPL.C

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



/*
** ZSAM INTERFACE TEMPLATE
**
** This file contains:
**   a) The structure and global data definitions for ZSAM
**   b) The ZSAM functions that actually call the B-Tree routines
**      in ZSAM.ASM.
**   c) The low-level file I/O functions called by the B-Tree routines.
**
** Source code in this file is compatible with Turbo C.  You'll need
** to build it with the Small Model to be compatible with what's in
** ZSAM.ASM.
*/


/*
** ZSAM Globals
*/


/* You have to define beforehand how many key files and data files
** the application will have open at a given time. */
#define nzkfiles ?              /* Number of key files */
#define nzdfiles ?              /* 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;


/*
**         >>>>>>> YOUR PROGRAM GOES HERE <<<<<<<<
*/

/****************************************/
/*      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: These routines don't do any error checking.  You may want to
** add error checking if it'll help you sleep better.
*/

/*
** 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);
        write(zkfhand[zkfno],keybuf[zkfno],KNODESIZE);

        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);
        write(zdfhand[zdfno],datbuf[zdfno],count);

        return;
}



