home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume14 / jove4.9 / part03 / fp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-04-25  |  7.6 KB  |  439 lines

  1. /***************************************************************************
  2.  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  3.  * is 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 "io.h"
  10. #include "ctype.h"
  11. #include "termcap.h"
  12.  
  13. #ifdef MAC
  14. #    include "mac.h"
  15. #else
  16. #    include <sys/stat.h>
  17. #    ifndef MSDOS
  18. #        include <sys/file.h>
  19. #    else /* MSDOS */
  20. #        include <fcntl.h>
  21. #        include <io.h>
  22. #    endif /* MSDOS */
  23. #endif /* MAC */
  24.  
  25. #include <errno.h>
  26.  
  27. #ifdef MAC
  28. #    undef private
  29. #    define private
  30. #endif
  31.  
  32. #ifdef    LINT_ARGS
  33. private File * f_alloc(char *, int, int, char *, int);
  34. #ifdef RAINBOW
  35. private int rbwrite(int, char *, int);
  36. #endif
  37. #else
  38. private File * f_alloc();
  39. #ifdef RAINBOW
  40. private int rbwrite();
  41. #endif
  42. #endif    /* LINT_ARGS */
  43.  
  44. #ifdef MAC
  45. #    undef private
  46. #    define private static
  47. #endif
  48.  
  49. #ifndef L_SET
  50. #    define L_SET 0
  51. #endif
  52.  
  53. #define MAXFILES    20    /* good enough for my purposes */
  54.  
  55. private File    _openfiles[MAXFILES] = {0};
  56.  
  57. private File *
  58. f_alloc(name, flags, fd, buffer, buf_size)
  59. char    *name,
  60.     *buffer;
  61. {
  62.     register File    *fp;
  63.     register int    i;
  64.  
  65.     for (fp = _openfiles, i = 0; i < MAXFILES; i++, fp++)
  66.         if (fp->f_flags == 0)
  67.             break;
  68.     if (i == MAXFILES)
  69.         complain("[Too many open files!]");
  70.     fp->f_bufsize = buf_size;
  71.     fp->f_cnt = 0;
  72.     fp->f_fd = fd;
  73.     fp->f_flags = flags;
  74.     if (buffer == 0) {
  75.         buffer = emalloc(buf_size);
  76.         fp->f_flags |= F_MYBUF;
  77.     }
  78.     fp->f_base = fp->f_ptr = buffer;
  79.     fp->f_name = copystr(name);
  80.  
  81.     return fp;
  82. }
  83.  
  84. void
  85. gc_openfiles()
  86. {
  87.     register File    *fp;
  88.  
  89.     for (fp = _openfiles; fp < &_openfiles[MAXFILES]; fp++)
  90.         if (fp->f_flags != 0 && (fp->f_flags & F_LOCKED) == 0)
  91.             f_close(fp);
  92. }
  93.  
  94. File *
  95. fd_open(name, flags, fd, buffer, bsize)
  96. char    *name,
  97.     *buffer;
  98. {
  99.     return f_alloc(name, flags, fd, buffer, bsize);
  100. }
  101.  
  102. File *
  103. f_open(name, flags, buffer, buf_size)
  104. char    *name,
  105.     *buffer;
  106. {
  107.     register int    fd;
  108.     int    mode = F_MODE(flags);
  109.  
  110.     if (mode == F_READ)
  111.         fd = open(name, 0);
  112.     if (mode == F_APPEND) {
  113.         fd = open(name, 1);
  114.         if (fd == -1)
  115.             mode = F_WRITE;
  116.         else
  117.             (void) lseek(fd, 0L, 2);
  118.     }
  119.     if (mode == F_WRITE)
  120.         fd = creat(name, CreatMode);
  121.     if (fd == -1)
  122.         return NIL;
  123. #ifdef MSDOS
  124.     else
  125.         setmode(fd, 0x8000);
  126. #endif /* MSDOS */
  127.     return f_alloc(name, flags, fd, buffer, buf_size);
  128. }
  129.  
  130. void
  131. f_close(fp)
  132. File    *fp;
  133. {
  134.     flush(fp);
  135. #ifdef BSD4_2 
  136.     if (fp->f_flags & (F_WRITE|F_APPEND))
  137.         (void) fsync(fp->f_fd);
  138. #endif 
  139.     (void) close(fp->f_fd);
  140.     if (fp->f_flags & F_MYBUF)
  141.         free(fp->f_base);
  142.     free(fp->f_name);
  143.     fp->f_flags = 0;    /* indicates that we're available */
  144. }
  145.  
  146. int
  147. 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, fp->f_base, fp->f_bufsize);
  157. #ifndef MSDOS
  158.     while (fp->f_cnt == -1 && errno == EINTR);
  159. #endif /* MSDOS */
  160.     if (fp->f_cnt == -1) {
  161.         printf("[Read error %d]", errno);
  162.         fp->f_flags |= F_ERR;
  163.     }
  164.     if (fp->f_cnt == 0) {
  165.         fp->f_flags |= F_EOF;
  166.         return EOF;
  167.     }
  168.     io_chars += fp->f_cnt;
  169.     return getc(fp);
  170. }
  171.  
  172. void
  173. putstr(s)
  174. register char    *s;
  175. {
  176. #ifndef IBMPC
  177.     register int    c;
  178.  
  179.     while (c = *s++)
  180.         putchar(c);
  181. #else /* IBMPC */
  182.     write_emif(s);
  183. #endif /* IBMPC */
  184. }
  185.  
  186. void
  187. fputnchar(s, n, fp)
  188. register char    *s;
  189. register int    n;
  190. register File    *fp;
  191. {
  192.     while (--n >= 0)
  193.         putc(*s++, fp);
  194. }
  195.  
  196. void
  197. flusho()
  198. {
  199. #ifndef IBMPC
  200.     _flush(EOF, stdout);
  201. #endif /* IBMPC */
  202. }
  203.  
  204. void
  205. flush(fp)
  206. File    *fp;
  207. {
  208.     _flush(EOF, fp);
  209. }
  210.  
  211. void
  212. f_seek(fp, offset)
  213. register File    *fp;
  214. off_t    offset;
  215. {
  216.     if (fp->f_flags & F_WRITE)
  217.         flush(fp);
  218.     fp->f_cnt = 0;        /* next read will filbuf(), next write
  219.                    will flush() with no bad effects */
  220.     lseek(fp->f_fd, (long) offset, L_SET);
  221. }
  222.  
  223. int        /* is void - but for lints sake */
  224. _flush(c, fp)
  225. register File    *fp;
  226. {
  227.     register int    n;
  228.  
  229.     if (fp->f_flags & (F_READ | F_STRING | F_ERR))
  230.         return EOF;
  231.     if (((n = (fp->f_ptr - fp->f_base)) > 0) &&
  232. #ifndef RAINBOW
  233.         (write(fp->f_fd, fp->f_base, n) != n) &&
  234. #else
  235.         (rbwrite(fp->f_fd, fp->f_base, n) != n) &&
  236. #endif
  237.         (fp != stdout)) {
  238.             fp->f_flags |= F_ERR;
  239.         error("[I/O error(%d); file = %s, fd = %d]",
  240.             errno, fp->f_name, fp->f_fd);
  241.     }
  242.  
  243.     fp->f_cnt = fp->f_bufsize;
  244.     fp->f_ptr = fp->f_base;
  245.     if (c != EOF)
  246.         return putc(c, fp);
  247. }
  248.  
  249. int
  250. f_gets(fp, buf, max)
  251. register File    *fp;
  252. char    *buf;
  253. {
  254.     register char    *cp = buf;
  255.     register int    c;
  256.     char    *endp = buf + max - 1;
  257.  
  258.     if (fp->f_flags & F_EOF)
  259.         return EOF;
  260.     while (((c = getc(fp)) != EOF) && (c != '\n')) {
  261.         if (c == '\0')  /* possibly different from NULL */
  262.             break;        /* sorry we don't read nulls */
  263. #ifdef MSDOS
  264.         if (c == '\r') {
  265.             if ((c = getc(fp)) == '\n')
  266.                break;
  267.             else
  268.                *cp++ = '\r';
  269.         }
  270. #endif /* MSDOS */
  271.         if (cp >= endp) {
  272.             add_mess(" [Line too long]");
  273.             rbell();
  274.             return EOF;
  275.         }
  276.         *cp++ = c;
  277.     }
  278.     *cp = '\0';
  279.     if (c == EOF) {
  280.         if (cp != buf)
  281.             add_mess(" [Incomplete last line]");
  282.         fp->f_flags |= F_EOF;
  283.         return EOF;
  284.     }
  285.     io_lines += 1;
  286.     return 0;    /* this means okay */
  287. }
  288.  
  289. /* skip to beginning of next line, i.e., next read returns first
  290.    character of new line */
  291.  
  292. void
  293. f_toNL(fp)
  294. register File    *fp;
  295. {
  296.     register int    c;
  297.  
  298.     if (fp->f_flags & F_EOF)
  299.         return;
  300.     while (((c = getc(fp)) != EOF) && (c != '\n'))
  301.         ;
  302.     if (c == EOF)
  303.         fp->f_flags |= F_EOF;
  304. }
  305.  
  306. void
  307. f_readn(fp, addr, n)
  308. register File    *fp;
  309. register char    *addr;
  310. register int    n;
  311. {
  312.     while (--n >= 0)
  313.         *addr++ = getc(fp);
  314. }
  315.  
  316. int
  317. f_getint(fp)
  318. File    *fp;
  319. {
  320.     int    n = 0,
  321.         c;
  322.  
  323.     while (isdigit(c = getc(fp)))
  324.         n = (n * 10) + c;
  325.     return n;
  326. }
  327.  
  328. /* Deals with output to the terminal, setting up the amount of characters
  329.    to be buffered depending on the output baud rate.  Why it's in a 
  330.    separate file I don't know ... */
  331.  
  332. private char    one_buf;
  333.  
  334. int    BufSize = 1;
  335.  
  336. private File    _stdout = {1, 1, 1, F_WRITE, &one_buf, &one_buf};
  337. File    *stdout = &_stdout;
  338.  
  339. /* put a string with padding */
  340.  
  341. #ifndef IBMPC
  342. void
  343. tputc(c)
  344. {
  345.     putchar(c);
  346. }
  347.  
  348. #undef putchar        /* for files which forget to include io.h,
  349.                        here's a real putchar procedure. */
  350. void
  351. putchar(c)
  352. {
  353.     putc(c, stdout);
  354. }
  355.  
  356. #endif /* IBMPC */
  357. #ifndef MAC
  358. void
  359. putpad(str, lines)
  360. char    *str;
  361. {
  362. #ifndef IBMPC
  363.     if (str)
  364.         tputs(str, lines, tputc);
  365. #else /* IBMPC */
  366.     write_emif(str);
  367. #endif /* IBMPC */
  368. }
  369. #endif
  370.  
  371. /* Determine the number of characters to buffer at each baud rate.  The
  372.    lower the number, the quicker the response when new input arrives.  Of
  373.    course the lower the number, the more prone the program is to stop in
  374.    output.  Decide what matters most to you. This sets BufSize to the right
  375.    number or chars, and initiaizes `stdout'.  */
  376.  
  377. void
  378. settout(ttbuf)
  379. char    *ttbuf;
  380. {
  381. #ifndef MAC
  382. #ifndef MSDOS
  383.     static int speeds[] = {
  384.         1,    /* 0    */
  385.         1,    /* 50    */
  386.         1,    /* 75    */
  387.         1,    /* 110    */
  388.         1,    /* 134    */
  389.         1,    /* 150    */
  390.         1,    /* 200    */
  391.         2,    /* 300    */
  392.         4,    /* 600    */
  393.         8,    /* 1200 */
  394.         16,    /* 1800    */
  395.         32,    /* 2400    */
  396.         128,    /* 4800    */
  397.         256,    /* 9600    */
  398.         512,    /* EXTA    */
  399.         1024    /* EXT    */
  400.     };
  401.     flusho();        /* flush the one character buffer */
  402.     BufSize = min(MAXTTYBUF, speeds[ospeed] * max(LI / 24, 1));
  403.     stdout = fd_open("/dev/tty", F_WRITE|F_LOCKED, 1, ttbuf, BufSize);
  404. #else /* MSDOS */
  405. #ifndef IBMPC
  406.     flusho();        /* flush the one character buffer */
  407.     BufSize = BUFSIZ; 
  408.     stdout = fd_open("con", F_WRITE|F_LOCKED, 1, ttbuf, BufSize);
  409. #endif    /* IBMPC */
  410. #endif /* MSDOS */
  411. #endif /* MAC */
  412. }
  413.  
  414. #ifdef RAINBOW
  415.  
  416. /*
  417.  * use the Rainbow's video output function
  418.  */
  419.  
  420. #include <dos.h>
  421.  
  422. private int
  423. rbwrite(fd, buf, cnt)
  424. char *buf;
  425. {
  426.     union REGS vr;
  427.  
  428.     if (fd != 1) {
  429.         write(fd, buf, cnt);
  430.     } else {
  431.         while (cnt-- > 0) {
  432.             vr.x.ax = *buf++;
  433.             vr.x.di = 0;
  434.             int86(0x18, &vr, &vr);
  435.         }
  436.     }
  437. }
  438. #endif /* RAINBOW */
  439.