home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / code / microema.sit / src / fileio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-06-09  |  10.1 KB  |  496 lines  |  [TEXT/Earl]

  1. /*
  2.  * The routines in this file read and write ASCII files from the disk. All of
  3.  * the knowledge about files are here.
  4.  */
  5.  
  6. #include    <stdio.h>
  7. #include    "estruct.h"
  8. #include    "edef.h"
  9. #if FINDER
  10. #if MPW
  11. #include <errors.h>
  12. #define CtoPstr c2pstr
  13. #include <Memory.h>
  14. #include <Resources.h>
  15. #else
  16. #include <MemoryMgr.h>
  17. #include <ResourceMgr.h>
  18. #endif
  19. Handle hfline = NULL;
  20. char *CtoPstr();
  21. short _iovrefnum;
  22. static short _iofrefnum;
  23. #else
  24. FILE    *ffp;        /* File pointer, all functions. */
  25. int eofflag;        /* end-of-file flag */
  26. #endif
  27. #if FINDER
  28. static char eolstr[1] = "\r";
  29. #define eolchar eolstr[0]
  30. /*
  31.  * PBClear() - Clear all fields of a ParamBlockRec.
  32.  * Better safe than sorry.  This also saves code size, since other
  33.  * routines do not need to clear fields explicitly.
  34.  */
  35. PBClear(pb)
  36. long *pb;
  37. {
  38.     int i = sizeof(ParamBlockRec)/4;
  39.     for(;i--;){
  40.         *pb++ = 0L;
  41.     }
  42. }
  43. #endif
  44. /*
  45.  * Open a file for reading.
  46.  */
  47. ffropen(fn)
  48. char    *fn;
  49. {
  50. #if MAC
  51.     char pname[NFILEN];
  52.     FInfo info;
  53.     strcpy(pname,fn);
  54.     CtoPstr(pname);
  55.     if(FSOpen(pname,_iovrefnum,&_iofrefnum)!=noErr){
  56.         mlwrite("File not found.");
  57.         return FIOFNF;
  58.     }
  59. /*
  60.  * Three file types are defined.  
  61.  * 'TEXT' is for regular MacOS files.  Line ends with '\r'.
  62.  *
  63.  * 'A/UX' is for A/UX 1.0 files.  This is undocumented.  Line ends with '\012'.
  64.  *
  65.  * Any other file type, we assume it is a binary file, and use '\0'
  66.  * as the line separator.  This is handy for patching object libraries,
  67.  * but is not so good for other file types which happen to have real 
  68.  * text embedded in them.
  69.  *
  70.  * Hey, we can't know everything, can we?
  71.  *
  72.  */
  73.     GetFInfo(pname,_iovrefnum,&info);
  74.     if(info.fdType == 'A/UX'){
  75.         eolchar = '\012';
  76.     }else if(info.fdType == 'TEXT'){
  77.         eolchar = '\015';
  78.     }else{
  79.         eolchar = '\0';
  80.     }
  81. #else
  82.     if ((ffp=fopen(fn, "r")) == NULL)
  83.         return (FIOFNF);
  84.     eofflag = FALSE;
  85. #endif
  86.     return (FIOSUC);
  87. }
  88.  
  89. /*
  90.  * Open a file for writing. Return TRUE if all is well, and FALSE on error
  91.  * (cannot create).
  92.  */
  93. ffwopen(fn)
  94. char    *fn;
  95. {
  96. #if MAC
  97.     char pname[NFILEN];
  98.     register LINE *lp;
  99.     register long bytes;
  100.     long    nbytes;
  101.     FInfo info;
  102.     strcpy(pname,fn);
  103.     CtoPstr(pname);
  104. /*
  105.  * If the file exists, open it for writing, set the EOF of the data
  106.  * fork to 0L, allocate enough space to save the current buffer,
  107.  * leave the present Resource Fork intact.  Otherwise, create a
  108.  * new file with no Resource Fork.
  109.  */
  110.     if(FSOpen(pname,curbp->b_ioWDDirID,&_iofrefnum)!=noErr){
  111.         if(Create(pname,_iovrefnum,'Earl','TEXT')!=noErr){
  112.             mlwrite("New file not created");
  113.             return FIOERR;
  114.         }
  115.         else if(FSOpen(pname,curbp->b_ioWDDirID,&_iofrefnum)!=noErr){
  116.             mlwrite("New file not opened!");
  117.             return FIOERR;
  118.         }
  119.     }
  120.     GetFInfo(pname,curbp->b_ioWDDirID,&info);
  121.     if(info.fdType == 'A/UX'){
  122.         eolchar = '\012';
  123.     }else if(info.fdType == 'TEXT'){
  124.         eolchar = '\015';
  125.     }else{
  126.         eolchar = '\0';
  127.     }
  128.  
  129.     lp = lforw(curbp->b_linep);
  130.     bytes = 0L;
  131.     while (lp != curbp->b_linep) {    /* Count bytes in buffer. */
  132.         bytes += (long)llength(lp)+1L;
  133.         lp = lforw(lp);
  134.     }
  135.     bytes++;            /* Might write extra newline! */
  136. /*
  137.  * Error if not enough disk space, or cannot get/set EOF.
  138.  */
  139.     if(GetEOF(_iofrefnum,&nbytes)!=noErr){
  140.         mlwrite("Cannot get EOF");
  141.         (void)FSClose(_iofrefnum);
  142.         return FIOERR;
  143.     }
  144.     if(nbytes < bytes){
  145.         nbytes = bytes - nbytes;
  146.         if(SetFPos(_iofrefnum,fsFromLEOF,0L)!=noErr){
  147.             mlwrite("Cannot set file position");
  148.             (void)FSClose(_iofrefnum);
  149.             return FIOERR;
  150.         }
  151.         if(Allocate(_iofrefnum,&nbytes) != noErr){
  152.             mlwrite("Insufficient disk space, sorry.");
  153.             (void)FSClose(_iofrefnum);
  154.             return FIOERR;
  155.         }
  156.     }
  157.     nbytes = bytes;
  158.     if(SetEOF(_iofrefnum,0L)!=noErr){
  159.         mlwrite("Cannot set EOF");
  160.         (void)FSClose(_iofrefnum);
  161.         return FIOERR;
  162.     }
  163.     if(SetFPos(_iofrefnum,fsFromStart,0L)!=noErr){
  164.         mlwrite("Cannot set file position");
  165.         (void)FSClose(_iofrefnum);
  166.         return FIOERR;
  167.     }
  168.     return FIOSUC;
  169. #else
  170. #if    VMS
  171.     register int    fd;
  172.  
  173.     if ((fd=creat(fn, 0666, "rfm=var", "rat=cr")) < 0
  174.     || (ffp=fdopen(fd, "w")) == NULL) {
  175. #else
  176.     if ((ffp=fopen(fn, "w")) == NULL) {
  177. #endif
  178.         mlwrite("Cannot open file for writing");
  179.         return (FIOERR);
  180.     }
  181.     return (FIOSUC);
  182. #endif
  183. }
  184.  
  185. /*
  186.  * Close a file. Should look at the status in all systems.
  187.  */
  188. ffclose()
  189. {
  190. #if FINDER
  191.     ParamBlockRec iopb;
  192.     register ParmBlkPtr pb = &iopb;
  193.     if(hfline != NULL){
  194.         DisposHandle(hfline);
  195.         hfline = NULL;
  196.         fline = NULL;
  197.         flen = 0;
  198.     }
  199. #else
  200.     /* free this since we do not need it anymore */
  201.     if (fline != NULL) {
  202.         free(fline);
  203.         fline = NULL;
  204.         flen = 0;
  205.     }
  206. #endif
  207. #if FINDER
  208.     if(FSClose(_iofrefnum) != noErr){
  209.         return FIOERR;
  210.     }else{
  211.         PBClear(pb);
  212.         pb->volumeParam.ioVRefNum = curbp->b_ioWDDirID;
  213.         PBGetVInfo(pb,false);
  214.         PBFlushVol(pb,false);    /* Make sure it winds up on disk. */
  215.     }
  216.     return FIOSUC;
  217. }
  218. #else
  219. #if    MSDOS & CTRLZ
  220.     fputc(26, ffp);     /* add a ^Z at the end of the file */
  221. #endif
  222.     
  223. #if    V7 | USG | BSD | (MSDOS & (LATTICE | MSC | TURBO)) | (ST520 & MWC)
  224.     if (fclose(ffp) != FALSE) {
  225.         mlwrite("Error closing file");
  226.         return(FIOERR);
  227.     }
  228.     return(FIOSUC);
  229. #else
  230.     fclose(ffp);
  231.     return (FIOSUC);
  232. #endif
  233. }
  234. #endif
  235.  
  236. /*
  237.  * Write a line to the already opened file. The "buf" points to the buffer,
  238.  * and the "nbuf" is its length, less the free newline. Return the status.
  239.  * Check only at the newline.
  240.  */
  241. ffputline(buf, nbuf)
  242. char    buf[];
  243. {
  244. #if FINDER        /* We don't do CRYPT. */
  245.     long lnbuf = nbuf;
  246.     if(FSWrite(_iofrefnum,&lnbuf,buf) != noErr){
  247.         mlwrite("Write I/O error");
  248.         return (FIOERR);
  249.     }
  250.     lnbuf = 1L;
  251.     if(FSWrite(_iofrefnum,&lnbuf,eolstr) != noErr){
  252.         mlwrite("Write I/O error");
  253.         return (FIOERR);
  254.     }
  255.     return (FIOSUC);
  256. #else
  257.     register int    i;
  258. #if    CRYPT
  259.     char c;     /* character to translate */
  260.  
  261.     if (cryptflag) {
  262.         for (i = 0; i < nbuf; ++i) {
  263.             c = buf[i] & 0xff;
  264.             crypt(&c, 1);
  265.             fputc(c, ffp);
  266.         }
  267.     } else
  268.         for (i = 0; i < nbuf; ++i)
  269.             fputc(buf[i]&0xFF, ffp);
  270. #else
  271.     for (i = 0; i < nbuf; ++i)
  272.         fputc(buf[i]&0xFF, ffp);
  273. #endif
  274. #if    ST520 & ADDCR
  275.     fputc(CR, ffp);
  276. #endif    
  277.     fputc(eolchar, ffp);
  278.  
  279.     if (ferror(ffp)) {
  280.         mlwrite("Write I/O error");
  281.         return (FIOERR);
  282.     }
  283.  
  284.     return (FIOSUC);
  285. #endif
  286. }
  287.  
  288. /*
  289.  * Read a line from a file, and store the bytes in the supplied buffer. The
  290.  * "nbuf" is the length of the buffer. Complain about long lines and lines
  291.  * at the end of the file that don't have a newline present. Check for I/O
  292.  * errors too. Return status.
  293.  * Macintosh note:  In this implementation, "fline" is actually a dereferenced
  294.  * Handle.  If we get a long line, we unlock and resize the Handle, then set
  295.  * fline to the new pointer.  Definitely superior to the vanilla code, below!
  296.  */
  297. ffgetline(n)
  298. int *n;
  299. {
  300. #if FINDER
  301.     ParamBlockRec iopb;
  302.     register ParmBlkPtr pb = &iopb;
  303. #endif
  304.     register int c;     /* current character read */
  305.     register int i;     /* current index into fline */
  306.     register char *tmpline; /* temp storage for expanding line */
  307.  
  308.     /* if we are at the end...return it */
  309. #if FINDER
  310.     if(hfline == NULL){
  311.         hfline = NewHandle((long)NSTRING);
  312.         if(hfline == NULL) return FIOMEM;
  313.         HLock(hfline);
  314.         fline = *hfline;
  315.         flen = NSTRING;
  316.     }
  317.     if(flen > NSTRING){
  318.         HUnlock(hfline);
  319.         SetHandleSize(hfline,(long)NSTRING);    /* No error (smaller). */
  320.         HLock(hfline);
  321.         fline = *hfline;
  322.         flen = NSTRING;
  323.     }
  324. #else
  325.  
  326.     if (eofflag)
  327.         return(FIOEOF);
  328.     /* dump fline if it ended up too big */
  329.     if (flen > NSTRING && fline != NULL) {
  330.         free(fline);
  331.         fline = NULL;
  332.         flen = 0;
  333.     }
  334.  
  335.     /* if we don't have an fline, allocate one */
  336.     if (fline == NULL)
  337.         if ((fline = malloc(flen = NSTRING)) == NULL){
  338.             flen = 0;
  339.             return(FIOMEM);
  340.         }
  341. #endif
  342. #if FINDER
  343.     tmpline = fline;
  344.     i=0;
  345.     PBClear(pb);
  346. retry:    
  347.     pb->ioParam.ioRefNum = _iofrefnum;
  348.     pb->ioParam.ioPosMode = 0x0080 | (eolchar << 8);
  349.     pb->ioParam.ioBuffer = tmpline;
  350.     pb->ioParam.ioReqCount = NSTRING;
  351.     PBRead(pb,FALSE);
  352.     i += (int)pb->ioParam.ioActCount;
  353.     pb->ioParam.ioResult =
  354.         (pb->ioParam.ioResult == eofErr ? 0 : pb->ioParam.ioResult);
  355.     if ((int)pb->ioParam.ioActCount >= NSTRING) {
  356.                 HUnlock(hfline);
  357.                 SetHandleSize(hfline,(long)(flen+=NSTRING));
  358.                 if(MemError() != noErr){
  359.                     DisposHandle(hfline);
  360.                     hfline = NULL;
  361.                     fline = NULL;
  362.                     flen = 0;
  363.                     return FIOMEM;
  364.                 }else{
  365.                     HLock(hfline);
  366.                     fline = *hfline;
  367.                 }
  368.             tmpline = fline + flen - NSTRING;
  369.             goto retry;
  370.         }
  371.    if (pb->ioParam.ioResult) {
  372.             mlwrite("File read error");
  373.             return (FIOERR);
  374.         }
  375.  
  376.     if ((int)pb->ioParam.ioActCount == 0)    return (FIOEOF);
  377.     if(fline[i-1] == eolchar)
  378.         i--;
  379. #else
  380.     /* read the line in */
  381.     i = 0;
  382.     while ((c = fgetc(ffp)) != EOF && c != eolchar) {
  383.         fline[i++] = c;
  384.         /* if it's longer, get more room */
  385.         if (i >= flen) {
  386.             if ((tmpline = malloc(flen+NSTRING)) == NULL)
  387.                 return(FIOMEM);
  388.             strncpy(tmpline, fline, flen);
  389.             flen += NSTRING;
  390.             free(fline);
  391.             fline = tmpline;
  392.         }
  393.     }
  394.  
  395. #if    ST520
  396.     if(fline[i-1] == CR)
  397.         i--;
  398. #endif
  399.  
  400.     /* test for any errors that may have occured */
  401.     if (c == EOF) {
  402.         if (ferror(ffp)) {
  403.             mlwrite("File read error");
  404.             return(FIOERR);
  405.         }
  406.  
  407.         if (i != 0)
  408.             eofflag = TRUE;
  409.         else
  410.             return(FIOEOF);
  411.     }
  412.  
  413.     /* terminate and decrypt the string */
  414. #endif
  415.     fline[i] = 0;
  416.  
  417. #if    CRYPT
  418.     if (cryptflag)
  419.         crypt(fline, strlen(fline));
  420. #endif
  421.     *n = i;
  422.     return(FIOSUC);
  423. }
  424. #if FINDER
  425. /*
  426.  * Does a file exist?  Used by startup code.
  427.  */
  428. fexist(fn)
  429. char    *fn;
  430. {
  431. #if FINDER
  432.     ParamBlockRec iopb;
  433.     register ParmBlkPtr pb = &iopb;
  434. #endif
  435.     int result;
  436.     char pname[NFILEN];
  437.     strcpy(pname,fn);
  438.     CtoPstr(pname);
  439.     PBClear(pb);
  440.     pb->ioParam.ioNamePtr = (StringPtr)pname;
  441.     pb->ioParam.ioVRefNum = _iovrefnum;
  442.     if(PBGetFInfo(pb,FALSE))return (FALSE);
  443.     else return TRUE;
  444. }
  445. #else
  446.  
  447. int fexist(fname)    /* does <fname> exist on disk? */
  448.  
  449. char *fname;        /* file to check for existance */
  450.  
  451. {
  452.     FILE *fp;
  453.  
  454.     /* try to open the file for reading */
  455.     fp = fopen(fname, "r");
  456.  
  457.     /* if it fails, just return false! */
  458.     if (fp == NULL)
  459.         return(FALSE);
  460.  
  461.     /* otherwise, close it and report true */
  462.     fclose(fp);
  463.     return(TRUE);
  464. }
  465. #endif
  466. #if    AZTEC & MSDOS
  467. #undef    fgetc
  468. /*    a1getc:     Get an ascii char from the file input stream
  469.             but DO NOT strip the high bit
  470. */
  471.  
  472. int a1getc(fp)
  473.  
  474. FILE *fp;
  475.  
  476. {
  477.     int c;        /* translated character */
  478.  
  479.     c = getc(fp);    /* get the character */
  480.  
  481.     /* if its a <LF> char, throw it out  */
  482.     while (c == 10)
  483.         c = getc(fp);
  484.  
  485.     /* if its a <RETURN> char, change it to a LF */
  486.     if (c == CR)
  487.         c = LF;
  488.  
  489.     /* if its a ^Z, its an EOF */
  490.     if (c == 26)
  491.         c = EOF;
  492.  
  493.     return(c);
  494. }
  495. #endif
  496.