home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / jove-4.16-src.tgz / tar.out / bsd / jove / fp.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  7KB  |  395 lines

  1. /************************************************************************
  2.  * This program is Copyright (C) 1986-1996 by Jonathan Payne.  JOVE is  *
  3.  * provided to you without charge, and with no warranty.  You may give  *
  4.  * away copies of JOVE, including sources, provided that this notice is *
  5.  * included in all the files.                                           *
  6.  ************************************************************************/
  7.  
  8. #include "jove.h"
  9. #include "fp.h"
  10. #include "jctype.h"
  11. #include "disp.h"
  12. #include "fmt.h"
  13.  
  14. #ifdef MAC
  15. #    include "mac.h"
  16. #else /* !MAC */
  17. #    include <sys/stat.h>
  18. #    ifndef MSFILESYSTEM
  19. #        include <sys/file.h>
  20. #    else /* MSFILESYSTEM */
  21. #        include <fcntl.h>
  22. #        include <io.h>
  23. #    endif /* MSFILESYSTEM */
  24. #endif /* !MAC */
  25.  
  26. #include <errno.h>
  27.  
  28. #ifdef RAINBOW
  29. private int rbwrite proto((int, char *, int));
  30. #endif
  31.  
  32. #ifndef L_SET
  33. # define L_SET 0
  34. #endif
  35.  
  36. #define MAXFILES    20    /* good enough for my purposes */
  37.  
  38. private File    openfiles[MAXFILES];    /* must be zeroed initially */
  39.  
  40. File *
  41. fd_open(name, flags, fd, buffer, buf_size)
  42. char    *name,
  43.     *buffer;
  44. int    flags,
  45.     fd,
  46.     buf_size;
  47. {
  48.     register File    *fp;
  49.     register int    i;
  50.  
  51.     for (fp = openfiles, i = 0; i < MAXFILES; i++, fp++)
  52.         if (fp->f_flags == 0)
  53.             break;
  54.     if (i == MAXFILES)
  55.         complain("[Too many open files!]");
  56.     fp->f_bufsize = buf_size;
  57.     fp->f_cnt = 0;
  58.     fp->f_fd = fd;
  59.     fp->f_flags = flags;
  60.     if (buffer == NULL) {
  61.         buffer = emalloc((size_t)buf_size);
  62.         fp->f_flags |= F_MYBUF;
  63.     }
  64.     fp->f_base = fp->f_ptr = buffer;
  65.     fp->f_name = copystr(name);
  66.  
  67.     return fp;
  68. }
  69.  
  70. void
  71. gc_openfiles()
  72. {
  73.     register File    *fp;
  74.  
  75.     for (fp = openfiles; fp < &openfiles[MAXFILES]; fp++)
  76.         if (fp->f_flags != 0 && (fp->f_flags & F_LOCKED) == 0)
  77.             f_close(fp);
  78. }
  79.  
  80. File *
  81. f_open(name, flags, buffer, buf_size)
  82. char    *name,
  83.     *buffer;
  84. int    flags,
  85.     buf_size;
  86. {
  87.     register int    fd;
  88.  
  89.     switch (F_MODE(flags)) {
  90.     case F_READ:
  91. #ifdef MSFILESYSTEM
  92.         fd = open(name, O_RDONLY|O_BINARY);
  93. #else
  94.         fd = open(name, 0);
  95. #endif
  96.         break;
  97.  
  98.     case F_APPEND:
  99. #ifdef MSFILESYSTEM
  100.         fd = open(name, O_WRONLY|O_BINARY);
  101. #else
  102.         fd = open(name, 1);
  103. #endif
  104.         if (fd != -1) {
  105.             (void) lseek(fd, 0L, 2);
  106.             break;
  107.         }
  108.         /* FALLTHROUGH */
  109.     case F_WRITE:
  110. #ifdef MSFILESYSTEM
  111.         fd = open(name, O_CREAT|O_TRUNC|O_BINARY|O_RDWR, S_IWRITE|S_IREAD);
  112. #else
  113.         fd = creat(name, CreatMode);
  114. #endif
  115.         break;
  116.  
  117.     default:
  118.         fd = -1;    /* avoid uninitialized complaint from gcc -W */
  119.         error("invalid F_MODE");
  120.         /* NOTREACHED */
  121.     }
  122.     if (fd == -1)
  123.         return NULL;
  124.     return fd_open(name, flags, fd, buffer, buf_size);
  125. }
  126.  
  127. void
  128. f_close(fp)
  129. File    *fp;
  130. {
  131.     if ((fp->f_flags & (F_WRITE|F_APPEND))
  132.     && (fp->f_flags & F_ERR) == 0)
  133.     {
  134.         flushout(fp);
  135. #ifdef USE_FSYNC
  136.         (void) fsync(fp->f_fd);
  137. #endif
  138.     }
  139.     (void) close(fp->f_fd);
  140.     if (fp->f_flags & F_MYBUF)
  141.         free((UnivPtr) fp->f_base);
  142.     free((UnivPtr) fp->f_name);
  143.     fp->f_flags = 0;    /* indicates that we're available */
  144. }
  145.  
  146. ZXchar
  147. f_filbuf(fp)
  148. File    *fp;
  149. {
  150.     if (fp->f_flags & (F_EOF|F_ERR))
  151.         return EOF;
  152.     fp->f_ptr = fp->f_base;
  153. #ifndef MSDOS
  154.     do {
  155. #endif /* MSDOS */
  156.         fp->f_cnt = read(fp->f_fd, (UnivPtr) fp->f_base, (size_t) fp->f_bufsize);
  157. #ifndef MSDOS
  158.     } while (fp->f_cnt == -1 && errno == EINTR);
  159. #endif /* MSDOS */
  160.     if (fp->f_cnt == -1) {
  161.         /* I/O error -- treat as EOF */
  162.         writef("[Read error: %s]", strerror(errno));
  163.         fp->f_flags |= F_ERR | F_EOF;
  164.         return EOF;
  165.     }
  166.     if (fp->f_cnt == 0) {
  167.         fp->f_flags |= F_EOF;
  168.         return EOF;
  169.     }
  170.     io_chars += fp->f_cnt;
  171.     return f_getc(fp);
  172. }
  173.  
  174. void
  175. putstr(s)
  176. register const char    *s;
  177. {
  178.     register char    c;
  179.  
  180.     while ((c = *s++) != '\0')
  181.         scr_putchar(c);
  182. }
  183.  
  184. void
  185. fputnchar(s, n, fp)
  186. register char    *s;
  187. register int    n;
  188. register File    *fp;
  189. {
  190.     while (--n >= 0)
  191.         f_putc(*s++, fp);
  192. }
  193.  
  194. #ifndef NO_JSTDOUT
  195. void
  196. flushscreen()
  197. {
  198.     flushout(jstdout);
  199. }
  200. #endif /* !NO_JSTDOUT */
  201.  
  202. void
  203. f_seek(fp, offset)
  204. register File    *fp;
  205. off_t    offset;
  206. {
  207.     if (fp->f_flags & (F_WRITE|F_APPEND))
  208.         flushout(fp);
  209.     fp->f_cnt = 0;        /* next read will f_filbuf(), next write
  210.                    will flush() with no bad effects */
  211.     lseek(fp->f_fd, (long) offset, L_SET);
  212. }
  213.  
  214. void
  215. flushout(fp)
  216. register File    *fp;
  217. {
  218.     if (fp->f_flags & (F_READ | F_STRING | F_ERR)) {
  219.         if (fp->f_flags != F_STRING)
  220.             abort();    /* IMPOSSIBLE */
  221.         /* We just banged into the end of a string.
  222.          * In the interests of continuing, we will cause
  223.          * the rest of the output to be be heaped in the
  224.          * last position.  Surely it will end up as a NUL. UGH!
  225.          */
  226.         fp->f_cnt = 1;
  227.         fp->f_ptr = &fp->f_base[fp->f_bufsize - 1];
  228.     } else {
  229.         char    *p = fp->f_base;
  230.  
  231.         for (;;) {
  232.             SSIZE_T
  233.                 n = fp->f_ptr - p,
  234.                 wr;
  235.  
  236.             if (n <= 0)
  237.                 break;
  238. #ifdef RAINBOW
  239.             wr = rbwrite(fp->f_fd, (UnivPtr) p, (size_t)n);
  240. #else
  241.             wr = write(fp->f_fd, (UnivPtr) p, (size_t)n);
  242. #endif
  243.             if (wr >= 0) {
  244.                 p += wr;
  245.             } else if (errno != EINTR) {
  246. #ifndef NO_JSTDOUT
  247.                 if (fp == jstdout)
  248.                     break;    /* bail out, silently */
  249. #endif
  250.                 fp->f_flags |= F_ERR;
  251.                 error("[I/O error(%s); file = %s, fd = %d]",
  252.                     strerror(errno), fp->f_name, fp->f_fd);
  253.             }
  254.         }
  255.  
  256.         fp->f_cnt = fp->f_bufsize;
  257.         fp->f_ptr = fp->f_base;
  258.     }
  259. }
  260.  
  261. bool
  262. f_gets(fp, buf, max)
  263. register File    *fp;
  264. char    *buf;
  265. size_t    max;
  266. {
  267.     register char    *cp = buf;
  268.     register ZXchar    c;
  269.     char    *endp = buf + max - 1;
  270.  
  271.     if (fp->f_flags & F_EOF)
  272.         return YES;
  273.     while ((c = f_getc(fp)) != EOF && c != EOL) {
  274.         /* We can't store NUL in our buffer, so ignore it.
  275.          * Similarly, we can only store characters less than NCHARS.
  276.          * Of course, with a little ingenuity we could store NUL:
  277.          * NUL could be represented by EOL.
  278.          */
  279.         if (c == '\0'
  280. #if NCHARS != UCHAR_ROOF
  281.         || c >= NCHARS
  282. #endif
  283.         )
  284.             continue;
  285.  
  286.         if (cp >= endp) {
  287.             add_mess(" [Line too long]");
  288.             rbell();
  289.             return YES;
  290.         }
  291.         *cp++ = c;
  292.     }
  293.     *cp = '\0';
  294.     if (c == EOF) {
  295.         if (cp != buf)
  296.             add_mess(" [Incomplete last line]");
  297.         return YES;
  298.     }
  299. #ifdef USE_CRLF
  300.     /* a CR followed by a LF is treated as a NL.
  301.      * Bug: the line-buffer is effectively shortened by one character.
  302.      */
  303.     if (cp != buf && cp[-1] == '\r')
  304.         *--cp = '\0';
  305. #endif /* USE_CRLF */
  306.     io_lines += 1;
  307.     return NO;    /* this means okay */
  308. }
  309.  
  310. /* skip to beginning of next line, i.e., next read returns first
  311.    character of new line */
  312.  
  313. void
  314. f_toNL(fp)
  315. register File    *fp;
  316. {
  317.     if (fp->f_flags & F_EOF)
  318.         return;
  319.     for (;;) {
  320.         switch (f_getc(fp)) {
  321.         case EOF:
  322.             fp->f_flags |= F_EOF;
  323.             /*FALLTHROUGH*/
  324.         case EOL:
  325.             return;
  326.         }
  327.     }
  328. }
  329.  
  330. #ifdef PIPEPROCS
  331. size_t
  332. f_readn(fp, addr, n)
  333. register File    *fp;
  334. register char    *addr;
  335. size_t    n;
  336. {
  337.     register size_t    nleft;
  338.  
  339.     for (nleft = n; nleft > 0; nleft--) {
  340.         ZXchar    c = f_getc(fp);
  341.  
  342.         if (f_eof(fp))
  343.             break;
  344.         *addr++ = c;
  345.     }
  346.     return n - nleft;
  347. }
  348. #endif /* PIPEPROCS */
  349.  
  350. /* ScrBufSize is the size of the buffer for jstdout.  It is also the
  351.  * number of characters to be output between checks for input, so
  352.  * it is meaningful even if jstdout isn't used.  Its value is set by
  353.  * settout based on the baud rate of output (on systems with baud rates).
  354.  */
  355. #ifdef NO_JSTDOUT
  356. int    ScrBufSize = 256;
  357. #else
  358. int    ScrBufSize = 1;    /* until settout decides a better value & allocates a buf */
  359. #endif
  360.  
  361. #ifndef NO_JSTDOUT
  362. private char    one_buf;
  363.  
  364. private File    stdout_File = {1, 1, 1, F_WRITE, &one_buf, &one_buf, (char *)NULL};
  365. File    *jstdout = &stdout_File;
  366. #endif
  367.  
  368. #ifdef RAINBOW
  369.  
  370. /*
  371.  * use the Rainbow's video output function
  372.  */
  373.  
  374. #include <dos.h>
  375.  
  376. private int
  377. rbwrite(fd, buf, cnt)
  378. int fd;
  379. char *buf;
  380. int cnt;
  381. {
  382.     union REGS vr;
  383.  
  384.     if (fd != 1) {
  385.         write(fd, buf, cnt);
  386.     } else {
  387.         while (cnt-- > 0) {
  388.             vr.x.ax = *buf++;
  389.             vr.x.di = 0;
  390.             int86(0x18, &vr, &vr);
  391.         }
  392.     }
  393. }
  394. #endif /* RAINBOW */
  395.