home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
vol_100
/
126_01
/
raniolib.c
< prev
next >
Wrap
Text File
|
1985-03-10
|
9KB
|
285 lines
/*********************************************************************\
** .---------------------------------------------------------------. **
** | | **
** | | **
** | Copyright (c) 1981, 1982, 1983 by Eric Martz. | **
** | | **
** | | **
** | Permission is hereby granted to use this source | **
** | code only for non-profit purposes. Publication of | **
** | all or any part of this source code, as well as | **
** | use for business purposes is forbidden without | **
** | written permission of the author and copyright | **
** | holder: | **
** | | **
** | Eric Martz | **
** | POWER TOOLS | **
** | 48 Hunter's Hill Circle | **
** | Amherst MA 01002 USA | **
** | | **
** | | **
** `---------------------------------------------------------------' **
\*********************************************************************/
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/*
#define DEBUG 1
*/
#include <bdscio.h>
#include "bdscio+.h"
#define BUF 512
/* RANDOM I/O LIBRARY
ranfget(buf,fp,offset,bytecnt)
ranfput(
ranrec(buf, rw, fp, record)
seekend(fp,offset)
*/
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/*
These functions must be used in conjunction with fio1.h, fio2.h, fio3.h,
and the renamed BDS library functions described therein.
See also a-open.c, getc.c, putc.c, rawgetc.c supplied on this disk.
*/
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
ranfget(buf,fp,offset,bytecnt)
/* THIS FUNCTION READS FROM THE FILE SPECIFIED BY fp A STRING
BEGINNING AT A RANDOM POSITION IN A FILE. THE OFFSET WHERE
READING BEGINS IS INDICATED BY offset, A POINTER TO A STRUCTURE
WHICH CONTAINS AN UNSIGNED seccnt AND AN INT charcnt (SEE
bdscio+.h). IF bytecnt IS 0, ranfget() STOPS AT THE NEXT NEWLINE
IN THE FILE, WHICH IS NOT PUT INTO BUF. IF bytecnt IS A POSITIVE
INTEGER, ranfget() READS THE SPECIFIED NUMBER OF
BYTES, */
/* ASSUMES INPUT FILE IS OPEN */
char *buf;
FILE *fp;
struct foffset *offset;
int bytecnt;
{
int check, i;
seek(fp->_fd,offset->record,0);
check = read(fp->_fd,fp->_buff,NSECTS);
if (check == ERROR) {
printf("DISK READ ERROR (ranfget)\n");
exit(0);
}
fp->_nextp = fp->_buff + offset->byte;
fp->_nleft = (check * SECSIZ) - offset->byte;
if (!bytecnt) {
check = fnnlgetl(buf,fp,BUF);
if (!check) goto bad;
}
else {
for (i=0; i<=bytecnt-1; i++) {
check = rawgetc(fp);
/* rawgetc() IS EQUIVALENT TO BDSC getc() WHICH PASSES ALL
CHARACTERS THROUGH. I HAVE MODIFIED getc() TO RETURN EOF (-1) WHEN IT GETS
A ^Z (CPMEOF), IN ACCORD WITH STANDARD K&R C. */
if (check EQ EOF) {
bad:
fprintf(STDERR,
"ATTEMPT TO READ PAST EOF (ranfget)\n");
exit(0);
}
buf[i] = check;
}
/* NO NULL APPENDED TO buf HERE ON ASSUMPTION CALLING PROGRAM
DOES NOT REQUIRE A NULL TERMINATED STRING */
}
return(0);
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
ranfput(buf, fp, offset, bytecount)
/* PUTS bytecount BYTES (OR THE NULL-TERMINATED STRING IN buf IF
bytecount IS 0; NULL IS NOT WRITTEN INTO FILE) INTO FILE
BEGINNING AT THE RANDOM RECORD/BYTE SPECIFIED BY offset.
ASSUMES FILE IS OPEN, AND WILL BE CLOSED BY THE CALLING PROGRAM
AFTER ranfput RETURNS.
*/
char *buf;
FILE *fp;
struct foffset *offset;
int bytecount;
{
char recbuf[129];
int i, recpos, atrec;
#ifdef DEBUG
printf("RANFPUT bytes %d:\n",bytecount);
for (i=0;i<=bytecount-1;i++)dispchar(buf[i]);
printf("\n");
#endif
atrec = offset->record;
ranrec(recbuf,'r',fp,atrec); /* read current record */
#ifdef DEBUG
printf("OLD RECORD FROM FILE:\n",bytecount);
for (i=0;i<RECSIZ;i++)dispchar(recbuf[i]);
printf("\n");
#endif
recpos = offset->byte;
if (bytecount) {
for (i=0; i<bytecount; i++, recpos++) {
if (recpos EQ 128) { /* this byte is first in next record */
ranrec(recbuf,'w',fp,atrec);
ranrec(recbuf,'r',fp,++atrec);
recpos = 0;
}
recbuf[recpos] = buf[i];
}
}
else {
i = 0;
while (buf[i]) {
if (recpos EQ 128) { /* this byte is first in next record */
ranrec(recbuf,'w',fp,atrec);
ranrec(recbuf,'r',fp,++atrec);
recpos = 0;
}
recbuf[recpos] = buf[i++];
recpos++;
}
}
ranrec(recbuf,'w',fp,atrec); /* flush final record */
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
ranrec(buf, rw, fp, record)
/* READS OR WRITES A RANDOMLY POSITIONED RECORD (128 BYTES
REGARDLESS OF DISK FORMAT) USING CP/M 2.2 BDOS CALLS.
rw MUST BE 'r' OR 'w'; NO ERROR CHECKING IS DONE. FILE MUST BE
OPEN BEFORE CALL AND MUST BE CLOSED AFTER ranrec WRITE CALLS.
*/
char *buf, rw;
FILE *fp;
int record;
{
int *pi, c;
char *pfcb; /* POINTER TO CP/M FILE CONTROL BLOCK */
/* SET RANDOM RECORD NUMBER IN FCB */
pfcb = fcbaddr(fp->_fd);
pi = 33 + pfcb;
*pi = record;
/* SET SO-CALLED DMA ADDRESS */
/* n.b.: if this is done before the above call to fcbaddr the
function fails -- ?? */
bdos(26,buf);
if (rw EQ 'r') bdos(33,pfcb); /* READ */
else bdos(34,pfcb); /* OR WRITE */
putchar('\0'); /* required to fix a bug in CP/M! */
bdos(26,0x80); /* RESTORE SO-CALLED DMA ADDRESS TO ITS USUAL
VALUE*/
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
seekend(fp,offset)
/* THE FILE MUST HAVE BEEN OPENED FOR APPEND (fopen(filename,
"a")) PRIOR TO CALLING seekend(). seekend() POSITIONS THE
POINTERS IN THE FILE BUFFER _buf SO THAT THE NEXT CHARACTER
WRITTEN WILL BE APPENDED TO EXISTING CONTENTS OF THE FILE, I.E.
WILL OVERWRITE THE PREVIOUS ^Z.
IN SOME APPLICATIONS, IT IS LATER DESIRED TO READ THE SAME STRING
RANDOMLY FROM THE FILE, SO THE OFFSET IS NEEDED. FOR THIS
PURPOSE, seekend() PROVIDES IN offset (SEE bdscio+.h) THE NEEDED
INFORMATION. ranfget() CAN LATER BE CALLED WITH THIS offset. */
FILE *fp;
struct foffset *offset;
{
char *fcb, *fcbaddr(), bdos();
int i, c, getc(), *pi;
fcb = fcbaddr(fp->_fd); /* GET POINTER TO FILE CONTROL BLOCK */
#ifdef DEBUG
showfcb(fcb);
#endif
bdos(35,fcb); /* INSTALL RECORD COUNT IN FILE CONTROL BLOCK */
#ifdef DEBUG
showfcb(fcb);
#endif
if (*(fcb+35) == 1) {
printf("RECORD COUNT IS 65536;\n");
printf("TOO LARGE FOR SEEKEND DURING OPEN FOR APPEND\n");
exit(0);
}
/* GET COUNT OF FILLED SECTORS WRITTEN = TOTAL SECTORS - 1 */
pi = fcb+33;
offset->record = (*pi)-1;
/* SEEK TO BEGINNING OF LAST SECTOR */
seek(fp->_fd,offset->record,0);
/* GET COUNT OF CHARACTERS IN LAST SECTOR BY LOOKING FOR CTRL-Z */
fp->_nleft = 0; /* forces reading of new sector with getc() */
for (i=1; i <= (SECSIZ) && ((c=getc(fp)) != EOF); i++);
/* IN MY LIBRARY, getc() HAS BEEN MODIFIED TO RETURN EOF WHEN A CPMEOF
(^Z) IS READ, SO AS TO BE CONSISTENT WITH K&R C */
if (c == EOF) {
ungetc(CPMEOF,fp); /* NOT c ! ALSO, SINCE THIS ASSIGNS CPMEOF
TO *_nextp, GETC MUST INCREMENT _nextp
EVEN ON EOF! */
i -= 1;
}
offset->byte = i;
/* ABOVE CALL TO getc() READS ONLY ONE SECTOR AND SETS *_nleft=128--;
SINCE A BUFFER FOR WRITING ALWAYS HAS 1024 AVAILABLE (AND THIS IS
ASSUMED BY fflush()) WE NEXT CORRECT NLEFT TO INDICATE TRUE ROOM
REMAINING IN THE BUFFER */
fp->_nleft += (NSECTS - 1) * SECSIZ;
/* SEEK AGAIN SO THAT THE NEXT WRITE (BY THE PROGRAM WHICH CALLED
seekend() WILL REWRITE THE PRESENT LAST SECTOR */
seek(fp->_fd,offset->record,0);
#ifdef DEBUG
printf("fp=%u, offset=%u, record=%u, byte=%d\n",
fp, offset, offset->record, offset->byte);
#endif
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* END OF RANDOM I/O LIBRARY */
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
checkbig(m,s)
/* ROUTINE TO WRITE TO STDERR STRINGS TOO BIG FOR fprintf() */
char *m, *s;
{
/* m IS FOR A MESSAGE */
while (*m) putc(*m++,STDERR);
if (*s) {
putc('<',STDERR);
while (*s) putc(*s++,STDERR);
if (*(s-1) NE NEWLINE)
fputs(">\n",STDERR);
}
}
ABOV