home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / EDITOR / MG2A_SRC.ZIP / SYS / AMIGA / FILEIO.C < prev    next >
Encoding:
C/C++ Source or Header  |  1988-08-23  |  12.2 KB  |  536 lines

  1. /*
  2.  * Name:    MG 2a401
  3.  *        Commodore Amiga file I/O.
  4.  * Last edit:    05-May-88 swalton@solar.stanford.edu
  5.  * Next-to-Last edit:    16-Dec-87 mic@emx.utexas.edu
  6.  * Created:    23-Jul-86 mic@emx.utexas.edu
  7.  *
  8.  * Read and write ASCII files. All of the low level file I/O
  9.  * knowledge is here.  Uses AmigaDOS standard I/O and does its
  10.  * own dynamic buffering; this seems to save about 2K worth
  11.  * of space in the executable image.
  12.  */
  13.  
  14. #ifdef        LATTICE
  15. #include    <string.h>
  16. #include    <exec/types.h>
  17. #endif
  18. #include    <exec/memory.h>
  19. #include    <libraries/dos.h>
  20. #include    <libraries/dosextens.h>
  21. #ifdef        USE_ARP
  22. #include    "libraries/arpbase.h"
  23. #else
  24. #define FCHARS    32L
  25. #endif
  26.  
  27. #undef    TRUE
  28. #undef    FALSE
  29. #include    "def.h"
  30.  
  31. #define    NIOBUF            4096
  32.  
  33. extern ULONG            Rename(), UnLock(), Close(), FreeMem();
  34. extern LONG            Write(), Read();
  35. extern UBYTE            *AllocMem();
  36. extern struct FileLock        *Lock();
  37. extern struct FileHandle    *Open();
  38.  
  39. static struct FileHandle    *ffh = 0;
  40. static UBYTE            *iobuf;
  41. static int            ibufo, niobuf;
  42. static LONG            iostat, access_mode;
  43. #ifdef    MANX
  44. extern char            *strncpy(), *strncat(), *index(), *rindex();
  45. #endif
  46. #ifdef    LATTICE
  47. extern char            *malloc() ;
  48. #define    index    strchr
  49. #define rindex    strrchr
  50. #endif
  51.  
  52. #define    getch()        (ibufo == niobuf) ? FillBuf() : iobuf[ibufo++]
  53. #define putch(c)    {if (niobuf == NIOBUF) FlushBuf(); iobuf[niobuf++] = c;}
  54.  
  55. /*
  56.  * Open the Emacs internal file for reading.
  57.  */
  58. ffropen(fn)
  59. char    *fn;
  60. {
  61.     if ((iobuf = AllocMem((ULONG) NIOBUF, 0L)) == NULL)
  62.         return (FIOERR);
  63.  
  64.     if ((ffh = Open(fn, access_mode = MODE_OLDFILE)) == 0L) {
  65.         FreeMem(iobuf, (ULONG) NIOBUF);
  66.         return (FIOFNF);
  67.     }
  68.     ibufo = niobuf = 0;
  69.     return (FIOSUC);
  70. }
  71.  
  72. /*
  73.  * Open a file for writing.  Return TRUE if all
  74.  * is well, and FALSE on error (cannot create).
  75.  */
  76.  
  77. ffwopen(fn)
  78. char    *fn;
  79. {
  80.     if ((iobuf = AllocMem((ULONG) NIOBUF, 0L)) == NULL)
  81.         return (FIOERR);
  82.     if ((ffh = Open(fn, access_mode = MODE_NEWFILE)) == 0L) {
  83.         ewprintf("Cannot open file for writing");
  84.         FreeMem(iobuf, (ULONG) NIOBUF);
  85.         return (FIOERR);
  86.     }
  87.     niobuf = 0;
  88.     iostat = NIOBUF;    /* pretend we wrote out a full buffer last time */
  89.     return (FIOSUC);
  90. }
  91.  
  92. /*
  93.  * Close a file, flushing the output buffer.  Should look at
  94.  * the status.
  95.  */
  96. ffclose()
  97. {
  98.     if (access_mode == MODE_NEWFILE)
  99.         FlushBuf();
  100.     if (ffh)
  101.         (void) Close(ffh);
  102.     if (iobuf)
  103.         FreeMem(iobuf, (ULONG) NIOBUF);
  104.     return (FIOSUC);
  105. }
  106.  
  107. /*
  108.  * Write a buffer to the already opened file. bp points to the
  109.  * buffer. Return the status. Check only at the newline and
  110.  * end of buffer.
  111.  */
  112. ffputbuf(bp)
  113. BUFFER *bp;
  114. {
  115.     register char *cp;
  116.     register char *cpend;
  117.     register LINE *lp;
  118.     register LINE *lpend;
  119.  
  120.     lpend = bp->b_linep;
  121.     lp = lforw(lpend);
  122.     do {
  123.     cp = <ext(lp)[0];        /* begining of line    */
  124.     cpend = &cp[llength(lp)];    /* end of line        */
  125.     while(cp != cpend)
  126.         putch(*(cp++));        /* putch only evalutes its arg once */
  127.     lp = lforw(lp);
  128.     if(lp == lpend) break;        /* no implied newline on last line */
  129.     putch('\n');
  130.     } while(iostat > 0L);
  131.  
  132.     if(iostat == -1L) {
  133.     ewprintf("Write I/O error");
  134.     return FIOERR;
  135.     }
  136.     return FIOSUC;
  137. }
  138.  
  139. /*
  140.  * Read a line from a file, and store the bytes
  141.  * in the supplied buffer. Stop on end of file or end of
  142.  * line.  When FIOEOF is returned, there is a valid line
  143.  * of data without the normally implied \n.
  144.  */
  145. ffgetline(buf, nbuf, nbytes)
  146. register char    *buf;
  147. register int    nbuf;
  148. register int    *nbytes;
  149. {
  150.     register int    c;
  151.     register int    i;
  152.  
  153.     i = 0;
  154.     while((c = getch())!=EOF && c!='\n') {
  155.         buf[i++] = c;
  156.         if (i >= nbuf) return FIOLONG;
  157.     }
  158.     if (c == EOF  && (iostat == -1L)) {
  159.         ewprintf("File read error");
  160.         return FIOERR;
  161.     }
  162.     *nbytes = i;
  163.     return c==EOF ? FIOEOF : FIOSUC;
  164. }
  165.  
  166. #ifndef    NO_BACKUP
  167. /*
  168.  * Rename the current file into a backup copy,
  169.  * possibly after deleting the original file.
  170.  */
  171. fbackupfile(fname)
  172. char    *fname;
  173. {
  174.     struct FileLock *twiddle, *lock;
  175.     char buffer[NFILEN];
  176.  
  177.     (void) strncpy(buffer,fname,NFILEN - 1);
  178.     (void) strcat(buffer,"~");
  179.  
  180.     lock = Lock(fname,(ULONG)EXCLUSIVE_LOCK);/* does file exist?    */
  181.     if (!lock)
  182.         return (FALSE);            /* nope, return error    */
  183.  
  184.     twiddle = Lock(buffer,(ULONG)EXCLUSIVE_LOCK);
  185.     if (twiddle) {                /* delete old backup    */
  186.         UnLock(twiddle);        /* let it go        */
  187.         if (!DeleteFile(buffer)) {
  188.             UnLock(lock);
  189.             return (FALSE);
  190.         }
  191.         twiddle = NULL;
  192.     }
  193.     /* rename file to backup name (after unlocking the file)
  194.      */
  195.     UnLock(lock);
  196.     return (int) Rename(fname,buffer);
  197. }
  198. #endif    NO_BACKUP
  199.  
  200. #ifndef    NO_STARTUP
  201. /*
  202.  * Return name of user's startup file.  On Amiga, make it
  203.  * .mg in the current directory, then s:.mg
  204.  */
  205.  
  206. static char startname[] = ".mg";
  207. static char altstartname[] = "s:.mg";
  208.  
  209. char *startupfile()
  210. {
  211.     struct FileLock *lock;
  212.  
  213.     if (lock = Lock(startname,(ULONG)SHARED_LOCK)) {
  214.         UnLock(lock);
  215.         return(startname);
  216.     }
  217.     if (lock = Lock(altstartname,(ULONG)SHARED_LOCK)) { /* alternate */
  218.         UnLock(lock);
  219.         return (altstartname);
  220.     }
  221.     return (NULL);
  222. }
  223. #endif    NO_STARTUP
  224.  
  225. /*
  226.  * The string "fn" is a file name. Perform any required name adjustments,
  227.  * including conversion to a fully qualified path if NO_DIR isn't defined.
  228.  */
  229.  
  230. #define MAX_ELEMS      8        /* Maximum number of elements    */
  231. extern char MyDirName[];
  232.  
  233. char *adjustname(fn)
  234. register char    *fn;
  235. {
  236. #ifndef NO_DIR
  237.     static char fnb[MAX_ELEMS*FCHARS + 1];
  238.     struct FileLock *lock;
  239.     long PathName();
  240.     void TackOn();
  241.     char *dup, *p;
  242.  
  243.     if (!index(fn, ':')) {            /* no device        */
  244.         strcpy(fnb, MyDirName);
  245.         TackOn(fnb, fn);
  246.         if (!index(fn, '/'))        /* completely bare name */
  247.             return fnb;
  248.     } else
  249.         strcpy(fnb, fn);
  250.     /*
  251.      * Else fn has some path components in it.  We try to PathName
  252.      * the whole thing first, but since the file specified by fn
  253.      * may not exist, we PathName the leading part and TackOn the
  254.      * trailing part if it doesn't.
  255.      */
  256.     if (lock = Lock(fnb, SHARED_LOCK)) {
  257.         if (PathName(lock, fnb, (long) MAX_ELEMS) !=0) {
  258.             UnLock(lock);
  259.             return fnb;
  260.         }
  261.         ewprintf("adjustname: PathName() failed!");
  262.         UnLock(lock);
  263.         return fn;
  264.     }
  265.     if (!(p = rindex(fnb, '/')))
  266.         p = index(fnb, ':');
  267.     p++;
  268.     strcpy((dup = malloc(strlen(p) + 1)), p);
  269.     *p = '\0';
  270.     if (lock = Lock(fnb, SHARED_LOCK)) {
  271.         if (PathName(lock, fnb, (long) MAX_ELEMS) != 0) {
  272.             UnLock(lock);
  273.             TackOn(fnb, dup);
  274.             free(dup);
  275.             return fnb;
  276.         }
  277.         ewprintf("adjustname: PathName() failed!");
  278.         UnLock(lock);
  279.     }
  280.     free(dup);
  281. #endif
  282.     return fn;                /* if all else fails    */
  283. }
  284.  
  285. /*
  286.  * Functions to read/write into the I/O buffer
  287.  */
  288.  
  289. int FlushBuf()
  290. {
  291.     if (niobuf > 0) {
  292.         iostat = Write(ffh, iobuf, (ULONG) niobuf);
  293.         niobuf = 0;
  294.     }
  295. }
  296.  
  297. /*
  298.  * Fill up the input buffer and return the first character in it.
  299.  */
  300. int FillBuf()
  301. {
  302.     if ((iostat = Read(ffh, iobuf, (ULONG) NIOBUF)) <= 0L)
  303.         return (EOF);
  304.     ibufo = 0;
  305.     niobuf = (int) iostat;
  306.     return (int) (iobuf[ibufo++]);
  307. }
  308.  
  309. #ifndef NO_DIRED
  310.  
  311. #include "kbd.h"
  312.  
  313. copy(frname, toname)
  314. char *frname, *toname;
  315. {
  316. #ifdef    MANX
  317.     return fexecl("copy", "copy", frname, toname, (char *) 0);
  318. #endif
  319. #ifdef    LATTICE
  320.     int    error ;
  321.     if (error = forkl("copy", "copy", frname, toname, (char *) 0, (char *) 0, 2))
  322.         return error ;
  323.     return (int) wait(2) ;
  324. #endif
  325. }
  326.  
  327. BUFFER *dired_(dirname)
  328. char *dirname;
  329. {
  330.     register BUFFER *bp;
  331.     char line[256];
  332.     BUFFER *findbuffer();
  333.     char *tmpname, *mktemp();
  334.     int i;
  335.     VOID lfree();
  336.  
  337.     if((dirname = adjustname(dirname)) == NULL) {
  338.     ewprintf("Bad directory name");
  339.     return NULL;
  340.     }
  341.     if(!isdirectory(dirname)) {
  342.     ewprintf("Not a directory: %s", dirname);
  343.     return NULL;
  344.     }
  345.     if((bp = findbuffer(dirname)) == NULL) {
  346.     ewprintf("Could not create buffer");
  347.     return NULL;
  348.     }
  349.     bclear(bp);                /* clear out leftover garbage    */
  350.     (void) strcpy(line, "list >");
  351.     (void) strncat(line, tmpname = mktemp("ram:mgXXX.XXX"), sizeof(line));
  352.     (void) strncat(line, " \"", sizeof(line));
  353.     (void) strncat(line, dirname, sizeof(line));
  354.     (void) strncat(line, "\"", sizeof(line));
  355.     Execute(line, 0L, 0L);
  356.     if (ffropen(tmpname) != FIOSUC) {
  357.      ewprintf("Can't open temporary dir file");
  358.      return NULL;
  359.     }
  360.     if (ffgetline(line, sizeof(line), &i) != FIOSUC ||
  361.     strncmp(line, "Directory", 9) != 0) {
  362.     ffclose();
  363.     DeleteFile(tmpname);
  364.     ewprintf("No such directory: `%s'", dirname);
  365.         return NULL;
  366.     }
  367.     line[0] = line[1] = ' ';
  368.     while (ffgetline(&line[2], sizeof(line)-3, &i) == FIOSUC) {
  369.     line[i+2] = '\0';
  370.     (VOID) addline(bp, line);
  371.     }
  372.     ffclose();
  373.     DeleteFile(tmpname);
  374.     bp->b_dotp = lforw(bp->b_linep);        /* go to first line */
  375.     (VOID) strncpy(bp->b_fname, dirname, NFILEN);
  376.     if((bp->b_modes[0] = name_mode("dired")) == NULL) {
  377.     bp->b_modes[0] = &map_table[0];
  378.     ewprintf("Could not find mode dired");
  379.     return NULL;
  380.     }
  381.     bp->b_nmodes = 0;
  382.     return bp;
  383. }
  384.  
  385. #ifdef    LATTICE
  386. char *
  387. mktemp(pattern)
  388. char *pattern;
  389. {
  390. /* quick hack mktemp for this purpose only */
  391.     register char        *name, *printo ;
  392.     register unsigned short    counter = 0 ;
  393.  
  394.     if ((name = malloc(strlen(pattern) + 5)) == NULL)
  395.         panic("Manx sucks rocks!") ;
  396.     (VOID) strcpy(name, pattern) ;
  397.     printo = name + strlen(name) ;
  398.     do
  399.         (void) sprintf(printo, "%d", counter += 1) ;
  400.         while (counter > 0 && access(name, 0) == 0) ;
  401.     if (counter == 0) panic("Manx _really_ sucks!") ;
  402.     return name ;
  403. }
  404. #endif
  405.  
  406. #define LIST_LINE_LENGTH 58            /* Size of line from List */
  407.  
  408. d_makename(lp, fn)
  409. register LINE *lp;
  410. register char *fn;
  411. {
  412.     register char *cp;
  413.     int n = 2;
  414.  
  415.     if(llength(lp) < LIST_LINE_LENGTH) return ABORT;
  416.     if(lgetc(lp, 2) == ':') return ABORT;    /* FileNote line    */
  417.     (VOID) strcpy(fn, curbp->b_fname);
  418.     cp = fn + strlen(fn);
  419.     if ((cp[-1] != ':') && (cp[-1] != '/'))    /* append '/' if needed    */
  420.     *cp++ = '/';
  421.     while (lgetc(lp, n) != ' ') {
  422.     *cp++ = lgetc(lp, n);
  423.     n++;
  424.     }
  425.     *cp = '\0';
  426.     return strncmp(&lp->l_text[31], "Dir", 3) == 0;
  427. }
  428.  
  429. static isdirectory(name)
  430. char *name;
  431. {
  432.     struct FileLock *lock;
  433.     struct FileInfoBlock *fib;
  434.     int result;
  435.  
  436.     if ((lock = Lock(name, ACCESS_READ)) == NULL)
  437.     return FALSE;
  438.     if ((fib = (struct FileInfoBlock *)
  439.        AllocMem((long)sizeof(struct FileInfoBlock),MEMF_PUBLIC))==NULL) {
  440.     UnLock(lock);
  441.     return FALSE;
  442.     }
  443.     result = (fib->fib_DirEntryType > 0L) ? TRUE : FALSE;
  444.     FreeMem(fib,(long)sizeof(struct FileInfoBlock));
  445.     UnLock(lock);
  446.     return result;
  447. }
  448.  
  449. #endif
  450.  
  451. #ifndef USE_ARP
  452.  
  453. /*
  454.  * Here are work-alikes for the few ARP commands now used by the
  455.  * Amiga version of mg.  These may go away if we require ARP in future.
  456.  */
  457.  
  458. Strcmp(s1, s2)
  459. register char *s1, *s2;
  460. {
  461.     while (tolower(*s1) == tolower(*s2)) {
  462.         if (*s1 == '\0')
  463.             return 0;
  464.         s1++; s2++;
  465.     }
  466.     return (tolower(*s1) < tolower(*s2) ? -1 : 1);
  467. }
  468.  
  469. /*
  470.  * This PathName function shamelessly stolen from the Matt Dillon Shell.
  471.  * It is a slight mod of that program's get_pwd routine, from comm1.c.
  472.  */
  473. long
  474. PathName(flock, pwdstr, nentries)
  475. struct Lock *flock;
  476. long nentries;
  477. char *pwdstr;
  478. {
  479.  
  480.    char *ptr;
  481.    char *name;
  482.    int err=0;
  483.  
  484.    struct FileLock *lock, *newlock, *ParentDir(), *DupLock();
  485.    long Examine();
  486.    struct FileInfoBlock *fib;
  487.    int i, len, n;
  488.  
  489.    lock = DupLock(flock);
  490.    n = nentries * FCHARS + 1;
  491.          
  492.    fib = (struct FileInfoBlock *)AllocMem((long)sizeof(struct FileInfoBlock),
  493.                          MEMF_PUBLIC);
  494.    pwdstr[i = n-1] = '\0';
  495.  
  496.    while (lock) {
  497.       newlock = ParentDir(lock);
  498.       if (!Examine(lock, fib)) ++err;
  499.       name = fib->fib_FileName;
  500.       if (*name == '\0')        /* HACK TO FIX RAM: DISK BUG */
  501.      name = "RAM";
  502.       len = strlen(name);
  503.       if (newlock) {
  504.      if (i == n-1) {
  505.         i -= len;
  506.         movmem(name, pwdstr + i, len);
  507.      } else {
  508.         i -= len + 1;
  509.         movmem(name, pwdstr + i, len);
  510.         pwdstr[i+len] = '/';
  511.      }
  512.       } else {
  513.      i -= len + 1;
  514.      movmem(name, pwdstr + i, len);
  515.      pwdstr[i+len] = ':';
  516.       }
  517.       UnLock(lock);
  518.       lock = newlock;
  519.    }
  520.    FreeMem(fib, (long)sizeof(struct FileInfoBlock));
  521.    movmem(pwdstr + i, pwdstr, n - i);
  522.    if (err) return(0L);
  523.    return((long) n - i - 1);
  524. }
  525.  
  526. void TackOn(path, file)
  527. char *path, *file;
  528. {
  529.     if (*file != '\0') {
  530.         if (path[strlen(path)-1] != ':')
  531.             strcat(path, "/");
  532.         strcat(path, file);
  533.     }
  534. }
  535. #endif
  536.