home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol075 / vfile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1984-04-29  |  8.7 KB  |  281 lines

  1.   /***********************************************************\
  2.   *                                                           *
  3.   *   VFILE consists of 5 functions which simulate a "BASIC   *
  4.   *   RANDOM FILE" structure using fixed length records of    *
  5.   *   varying pre-specified size. A record may be up to 255   *
  6.   *   chars long. It is the programmer's responsibility to    *
  7.   *   keep track of the contents of his record, and VFILE's   *
  8.   *   responsibility to write and read the record to and from *
  9.   *   the correct position in file.  Record numbers are       *
  10.   *   maximum 32767. VFILE will give ERROR if reading past    *
  11.   *   end of file or exceeding legal bounds.  It will pad     *
  12.   *   as-yet-unwritten internal records with nulls. An error  *
  13.   *   is returned if there is not enough disk space for       *
  14.   *   either the record or the padding.  There is a sixth     *
  15.   *   function (vset), which is used internally.              *
  16.   *                                                           *
  17.   *   The structure "_vbuf" must be included in the           *
  18.   *   programme, and each file must reserve a VBUFSIZ area    *
  19.   *   for buffering.  This area will vary depending on NSECTS *
  20.   *   in BDSCIO.H   THE VALUE OF NSECTS MUST BE GREATER       *
  21.   *   THAN TWO.  The definitions of _vbuf and VBUFSIZ         *
  22.   *   should eventually find their way into BDSCIO.H          *
  23.   *   I have included them in this source for clarity.        *
  24.   *                                                           *
  25.   *   telend finds the end of any sequential file and returns *
  26.   *   its record number.  Only sequential extents are searched*
  27.   *   (i.e. it may not work on random files)                  *
  28.   *                                                           *
  29.   \************************************************************
  30.  
  31.  
  32.  
  33.  
  34.     Version 1.0  (c) 1980     Greg Lister
  35.  
  36.                 Software Source
  37.                 P.O. Box 364
  38.                 Edgecliff   2027
  39.  
  40.                 Australia
  41.  
  42.  
  43.         19th November, 1980                */
  44.  
  45.  
  46.  
  47.  
  48. #include "bdscio.h"
  49. #define VBUFSIZ NSECTS * SECSIZ + 14
  50.  
  51. struct _vbuf
  52. {   int fd;    /* File Descriptor */
  53.     int eof;    /* Actual EOF of file */
  54.     int pos;    /* Current record's position in buffer */
  55.     int len;    /* Record length */
  56.     int sta;    /* Start sector of buffer */
  57.     int cnt;    /* Number of sectors in buffer */
  58.     int wflag;    /* flag set if buffer written to */
  59.     char buffer[NSECTS * SECSIZ];
  60. };
  61.  
  62.  
  63. vset(recno,vbuf)
  64.     int recno;
  65.     struct _vbuf *vbuf;
  66.     /************************************************\
  67.     *                                                *
  68.     *   Sets up buffer for random reads and writes.  *
  69.     *   Flushes buffer if necessary and fills buffer *
  70.     *   with required data. Sets pointer to beginning*
  71.     *   of r/w record.  Fills unwritten buffer with  *
  72.     *   nulls.  Returns ERROR if cannot flush or     *
  73.     *   if hard read error.  Returns NULL if         *
  74.     *   required buffer is not yet written. Returns  *
  75.     *   -2 if required sector (128 byte) is not yet  *
  76.     *   written. Else returns valid sectors in buf.  *
  77.     *                                                *
  78.     \************************************************/
  79. {
  80.    int tmp,blkno,bss,blkoff,secno,bufsec,endrec;
  81.  
  82.    blkno=recno>>7;        /* Block Number */
  83.  
  84.    bss=blkno*vbuf->len;        /* Block start Sector */
  85.  
  86.    blkoff=(recno%128)*vbuf->len;    /* Offset into Block */
  87.  
  88.    secno=bss+(blkoff>>7);    /* Sector # of start of rec */
  89.  
  90.    endrec=bss+((blkoff+vbuf->len-1)>>7);/* Sec# END of rec */
  91.  
  92.    bufsec=(secno/(NSECTS-2))*(NSECTS-2); /* Start sec of buf */
  93.  
  94.    vbuf->pos=vbuf->buffer+((secno-bufsec)<<7)+(blkoff%128);
  95.  
  96.    if(bufsec!=vbuf->sta)
  97.    {    if(vbuf->wflag)
  98.     {   seek(vbuf->fd,vbuf->sta,0);
  99.            if(write(vbuf->fd,vbuf->buffer,vbuf->cnt)<vbuf->cnt)
  100.         return ERROR;
  101.         if((tmp=tell(vbuf->fd))>vbuf->eof)
  102.         vbuf->eof=tmp;
  103.         vbuf->wflag=0;
  104.     }
  105.     if((vbuf->sta=bufsec)>vbuf->eof) return NULL;
  106.     seek(vbuf->fd,bufsec,0);
  107.     if((vbuf->cnt=read(vbuf->fd,vbuf->buffer,NSECTS))<0)
  108.         return ERROR;
  109.     if(vbuf->cnt!=NSECTS)
  110.         fillb(vbuf->buffer+(vbuf->cnt<<7),
  111.         vbuf->buffer+(NSECTS<<7),0,0);
  112.    }
  113.  
  114.    if(endrec-bufsec>=vbuf->cnt) return -2;
  115.    return vbuf->cnt;
  116. }
  117.  
  118.  
  119. vwrite(recno,vbuf,str)
  120.     int recno;
  121.     struct _vbuf *vbuf;
  122.     char *str;
  123.  
  124.     /********************************************************\
  125.     *                                                        *
  126.     *   Writes data at str to file vbuf at recno.  Pads file *
  127.     *    with NULLS if skipping unwritten sections of file.   *
  128.     *    Returns ERROR if full disk, unopened file etc        *
  129.     *    Returns ERROR if bad record #;  else returns OK      *
  130.     *                                                        *
  131.     \********************************************************/
  132.  
  133. {   int tmp,tmp1,tmp2;
  134.  
  135.     if(recno<0) return ERROR;
  136.     if((tmp=vset(recno,vbuf))==-1) return ERROR;
  137.       if(tmp==0)
  138.       { fillb(vbuf->buffer,NSECTS<<7,0,1);
  139.     seek(vbuf->fd,vbuf->eof,0);
  140.     while((vbuf->eof=tell(vbuf->fd))<vbuf->sta)
  141.     if(write(vbuf->fd,vbuf->buffer,1)>1) return ERROR;
  142.       }
  143.       movmem(str,vbuf->pos,vbuf->len);
  144.       tmp2=vbuf->buffer;
  145.       tmp1=(127+vbuf->pos-tmp2+vbuf->len)>>7;
  146.       if(tmp1>vbuf->cnt)
  147.     vbuf->cnt=tmp1;
  148.       vbuf->wflag=1;
  149.     return OK;
  150. }
  151.  
  152.  
  153. vread(recno,vbuf,str)
  154.     int recno;
  155.     struct _vbuf *vbuf;
  156.     char str[];
  157.  
  158.     /************************************************\
  159.     *                                                *
  160.     *   Reads record 'recno' from file to 'str'.     *
  161.     *   Returns ERROR if hard error (unopened        *
  162.     *   file etc) or if attempt is made to read      *
  163.     *   past current end of file.  Returns no of     *
  164.     *   secs read in.   ERROR if bad recno.          *
  165.     *                                                *
  166.     \************************************************/
  167.  
  168. {   int tmp;
  169.     if(recno<0) return ERROR;
  170.     tmp=vbuf->sta;
  171.     if(vset(recno,vbuf)<1)
  172.     {
  173.     vbuf->sta=tmp;
  174.     return ERROR;
  175.     }
  176.     movmem(vbuf->pos,str,vbuf->len);
  177.     return vbuf->cnt;
  178. }
  179.  
  180.  
  181. vclose(vbuf)
  182.    struct _vbuf *vbuf;
  183.  
  184.     /************************************************\
  185.     *                                                *
  186.     *   Closes file using vbuf.  Returns OK if       *
  187.     *   closed successfully.  ERROR if error.        *
  188.     *                                                *
  189.     \************************************************/
  190.  
  191. {   if(vbuf->wflag)
  192.     {    seek(vbuf->fd,vbuf->sta,0);
  193.     if(write(vbuf->fd,vbuf->buffer,vbuf->cnt)<0)
  194.         return ERROR;
  195.     }
  196.     return close(vbuf->fd);
  197. }
  198.  
  199.  
  200.  
  201. vopen(filename,vbuf,reclen)
  202.     int reclen;
  203.     char filename[];
  204.     struct _vbuf *vbuf;
  205.  
  206.     /************************************************\
  207.     *                                                *
  208.     *   Opens filename for v-format buffered io      *
  209.     *   Reclen is the specified record length        *
  210.     *   (may be up to 255 chars).  Vbuf is a         *
  211.     *   VBUFSIZ buffer ((128 * NSECTS)+14)           *
  212.     *   **NOTE** NSECTS must be 3 or more for this   *
  213.     *   file structure to work.                      *
  214.     *   Returns ERROR if reclen is out of range      *
  215.     *   or if open error occurs (ie file doesn't     *
  216.     *   exist - use vcreat)                          *
  217.     *                                                *
  218.     \************************************************/
  219.  
  220. {   if((vbuf->len=reclen)>255)return ERROR;
  221.     if(reclen<0) return ERROR;
  222.     if((vbuf->fd=open(filename,2))<0) return ERROR;
  223.     vbuf->sta=vbuf->cnt=-1;
  224.     vbuf->wflag=0;
  225.     vbuf->pos=vbuf->buffer;
  226.     vbuf->eof=telend(filename);
  227.     return vbuf->fd;
  228. }
  229.  
  230.  
  231. vcreat(filename,vbuf,reclen)
  232.     int reclen;
  233.     char filename[];
  234.     struct _vbuf *vbuf;
  235.     /************************************************\
  236.     *                                                *
  237.     *   Creates a file as vopen (see above)          *
  238.     *                                                *
  239.     \************************************************/
  240. {   fabort(creat(filename));
  241.     return vopen(filename,vbuf,reclen);
  242. }
  243.  
  244.  
  245.  
  246.  
  247.  
  248.  
  249.  
  250.  
  251.  
  252.  
  253.  
  254.  
  255.  
  256.  
  257.  
  258.  
  259. telend(filename)
  260. char *filename;
  261.     /************************************************\
  262.     *                                                *
  263.     *   returns number of last 128-byte record in    *
  264.     *   file 'filename'.  Returns NULL if file       *
  265.     *   is either nonexistent or empty.              *
  266.     *                                                *
  267.     \************************************************/
  268. {
  269.     int recnt;
  270.     char fcb[38],ex;
  271.     setfcb(fcb,filename);
  272.     ex=recnt=0;
  273.     while(1)
  274.     {    fcb[12]=ex++;
  275.     if((bdos(15,fcb))==255) break;
  276.     recnt+=fcb[15];
  277.     }
  278.     return recnt;
  279. }
  280.  
  281.