home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD1.bin / gnu / src / amiga / ed-0.1-src.lha / ed-0.1 / io.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-19  |  8.5 KB  |  394 lines

  1. /* io.c: This file contains the i/o routines for the ed line editor */
  2. /* ed line editor.
  3.    Copyright (C) 1993 Andrew Moore, Talke Studio
  4.    All Rights Reserved
  5.  
  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2, or (at your option)
  9.    any later version.
  10.  
  11.    This program is distributed in the hope that it will be useful, but
  12.    WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.    General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. */
  20.  
  21. #ifndef lint
  22. static char *rcsid = "@(#)$Id: io.c,v 1.4 1994/03/19 21:55:22 alm Exp $";
  23. #endif /* not lint */
  24.  
  25. #include "ed.h"
  26.  
  27.  
  28. extern int scripted;
  29.  
  30. /* read_file: read a named file/pipe into the buffer; return line count */
  31. long
  32. read_file (fn, n)
  33.      char *fn;
  34.      long n;
  35. {
  36.   FILE *fp;
  37.   long size;
  38.  
  39.  
  40.   fp = (*fn == '!') ? popen (fn + 1, "r") : fopen (strip_escapes (fn), "r");
  41.   if (fp == NULL)
  42.     {
  43.       fprintf (stderr, "%s: %s\n", fn, strerror (errno));
  44.       sprintf (errmsg, "cannot open input file");
  45.       return ERR;
  46.     }
  47.   else if ((size = read_stream (fp, n)) < 0)
  48.     return ERR;
  49.   else if (((*fn == '!') ? pclose (fp) : fclose (fp)) < 0)
  50.     {
  51.       fprintf (stderr, "%s: %s\n", fn, strerror (errno));
  52.       sprintf (errmsg, "cannot close input file");
  53.       return ERR;
  54.     }
  55.   fprintf (stderr, !scripted ? "%lu\n" : "", size);
  56.   return current_addr - n;
  57. }
  58.  
  59.  
  60. char *sbuf;            /* file i/o buffer */
  61. int sbufsz;            /* file i/o buffer size */
  62. int newline_added;        /* if set, newline appended to input file */
  63.  
  64. /* read_stream: read a stream into the editor buffer; return status */
  65. long
  66. read_stream (fp, n)
  67.      FILE *fp;
  68.      long n;
  69. {
  70.   line_t *lp = get_addressed_line_node (n);
  71.   undo_t *up = NULL;
  72.   unsigned long size = 0;
  73.   int o_newline_added = newline_added;
  74.   int o_isbinary = isbinary;
  75.   int appended = (n == addr_last);
  76.   int len;
  77.  
  78.   isbinary = newline_added = 0;
  79.   for (current_addr = n; (len = get_stream_line (fp)) > 0; size += len)
  80.     {
  81.       SPL1 ();
  82.       if (put_sbuf_line (sbuf) == NULL)
  83.     {
  84.       SPL0 ();
  85.       return ERR;
  86.     }
  87.       lp = lp->q_forw;
  88.       if (up)
  89.     up->t = lp;
  90.       else if ((up = push_undo_stack (UADD, current_addr,
  91.                       current_addr)) == NULL)
  92.     {
  93.       SPL0 ();
  94.       return ERR;
  95.     }
  96.       SPL0 ();
  97.     }
  98.   if (len < 0)
  99.     return ERR;
  100.   if (appended && size && o_isbinary && o_newline_added)
  101.     fputs ("newline inserted\n", stderr);
  102.   else if (newline_added && (!appended || !isbinary && !o_isbinary))
  103.     fputs ("newline appended\n", stderr);
  104.   if (isbinary && newline_added && !appended)
  105.     size += 1;
  106.   if (!size)
  107.     newline_added = 1;
  108.   newline_added = appended ? newline_added : o_newline_added;
  109.   isbinary = isbinary | o_isbinary;
  110.   return size;
  111. }
  112.  
  113.  
  114. /* get_stream_line: read a line of text from a stream; return line length */
  115. int
  116. get_stream_line (fp)
  117.      FILE *fp;
  118. {
  119.   register int c;
  120.   register int i = 0;
  121.  
  122.   while (((c = getc (fp)) != EOF || !feof (fp) &&
  123.       !ferror (fp)) && c != '\n')
  124.     {
  125.       REALLOC (sbuf, sbufsz, i + 1, ERR);
  126.       if (!(sbuf[i++] = c))
  127.     isbinary = 1;
  128.     }
  129.   REALLOC (sbuf, sbufsz, i + 2, ERR);
  130.   if (c == '\n')
  131.     sbuf[i++] = c;
  132.   else if (ferror (fp))
  133.     {
  134.       fprintf (stderr, "%s\n", strerror (errno));
  135.       sprintf (errmsg, "cannot read input file");
  136.       return ERR;
  137.     }
  138.   else if (i)
  139.     {
  140.       sbuf[i++] = '\n';
  141.       newline_added = 1;
  142.     }
  143.   sbuf[i] = '\0';
  144.   return (isbinary && newline_added && i) ? --i : i;
  145. }
  146.  
  147.  
  148. /* write_file: write a range of lines to a named file/pipe; return line count */
  149. long
  150. write_file (fn, mode, n, m)
  151.      char *fn;
  152.      char *mode;
  153.      long n;
  154.      long m;
  155. {
  156.   FILE *fp;
  157.   long size;
  158.  
  159.   fp = (*fn == '!') ? popen (fn + 1, "w") : fopen (strip_escapes (fn), mode);
  160.   if (fp == NULL)
  161.     {
  162.       fprintf (stderr, "%s: %s\n", fn, strerror (errno));
  163.       sprintf (errmsg, "cannot open output file");
  164.       return ERR;
  165.     }
  166.   else if ((size = write_stream (fp, n, m)) < 0)
  167.     return ERR;
  168.   else if (((*fn == '!') ? pclose (fp) : fclose (fp)) < 0)
  169.     {
  170.       fprintf (stderr, "%s: %s\n", fn, strerror (errno));
  171.       sprintf (errmsg, "cannot close output file");
  172.       return ERR;
  173.     }
  174.   fprintf (stderr, !scripted ? "%lu\n" : "", size);
  175.   return n ? m - n + 1 : 0;
  176. }
  177.  
  178.  
  179. /* write_stream: write a range of lines to a stream; return status */
  180. long
  181. write_stream (fp, n, m)
  182.      FILE *fp;
  183.      long n;
  184.      long m;
  185. {
  186.   line_t *lp = get_addressed_line_node (n);
  187.   unsigned long size = 0;
  188.   char *s;
  189.   int len;
  190.  
  191.   for (; n && n <= m; n++, lp = lp->q_forw)
  192.     {
  193.       if ((s = get_sbuf_line (lp)) == NULL)
  194.     return ERR;
  195.       len = lp->len;
  196.       if (n != addr_last || !isbinary || !newline_added)
  197.     s[len++] = '\n';
  198.       if (put_stream_line (fp, s, len) < 0)
  199.     return ERR;
  200.       size += len;
  201.     }
  202.   return size;
  203. }
  204.  
  205.  
  206. /* put_stream_line: write a line of text to a stream; return status */
  207. int
  208. put_stream_line (fp, s, len)
  209.      FILE *fp;
  210.      char *s;
  211.      int len;
  212. {
  213.   while (len--)
  214.     if (fputc (*s++, fp) < 0)
  215.       {
  216.     fprintf (stderr, "%s\n", strerror (errno));
  217.     sprintf (errmsg, "cannot write file");
  218.     return ERR;
  219.       }
  220.   return 0;
  221. }
  222.  
  223. /* get_extended_line: get a an extended line from stdin */
  224. char *
  225. get_extended_line (sizep, nonl)
  226.      int *sizep;
  227.      int nonl;
  228. {
  229.   static char *cvbuf = NULL;    /* buffer */
  230.   static int cvbufsz = 0;    /* buffer size */
  231.  
  232.   int l, n;
  233.   char *t = ibufp;
  234.  
  235.   while (*t++ != '\n')
  236.     ;
  237.   if ((l = t - ibufp) < 2 || !has_trailing_escape (ibufp, ibufp + l - 1))
  238.     {
  239.       *sizep = l;
  240.       return ibufp;
  241.     }
  242.   *sizep = -1;
  243.   REALLOC (cvbuf, cvbufsz, l, NULL);
  244.   memcpy (cvbuf, ibufp, l);
  245.   *(cvbuf + --l - 1) = '\n';    /* strip trailing esc */
  246.   if (nonl)
  247.     l--;            /* strip newline */
  248.   for (;;)
  249.     {
  250.       if ((n = get_tty_line ()) < 0)
  251.     return NULL;
  252.       else if (n == 0 || ibuf[n - 1] != '\n')
  253.     {
  254.       sprintf (errmsg, "unexpected end-of-file");
  255.       return NULL;
  256.     }
  257.       REALLOC (cvbuf, cvbufsz, l + n, NULL);
  258.       memcpy (cvbuf + l, ibuf, n);
  259.       l += n;
  260.       if (n < 2 || !has_trailing_escape (cvbuf, cvbuf + l - 1))
  261.     break;
  262.       *(cvbuf + --l - 1) = '\n';    /* strip trailing esc */
  263.       if (nonl)
  264.     l--;            /* strip newline */
  265.     }
  266.   REALLOC (cvbuf, cvbufsz, l + 1, NULL);
  267.   cvbuf[l] = '\0';
  268.   *sizep = l;
  269.   return cvbuf;
  270. }
  271.  
  272.  
  273. /* get_tty_line: read a line of text from stdin; return line length */
  274. int
  275. get_tty_line ()
  276. {
  277.   register int oi = 0;
  278.   register int i = 0;
  279.   int c;
  280.  
  281.   /* Read stdin one character at a time to avoid i/o contention
  282.      with shell escapes invoked by nonterminal input, e.g.,
  283.      ed - <<EOF
  284.      !cat
  285.      hello, world
  286.      EOF */
  287.   for (;;)
  288.     switch (c = getchar ())
  289.       {
  290.       default:
  291.     oi = 0;
  292.     REALLOC (ibuf, ibufsz, i + 2, ERR);
  293.     if (!(ibuf[i++] = c))
  294.       isbinary = 1;
  295.     if (c != '\n')
  296.       continue;
  297.     lineno++;
  298.     ibuf[i] = '\0';
  299.     ibufp = ibuf;
  300.     return i;
  301.       case EOF:
  302.     if (ferror (stdin))
  303.       {
  304.         fprintf (stderr, "stdin: %s\n", strerror (errno));
  305.         sprintf (errmsg, "cannot read stdin");
  306.         clearerr (stdin);
  307.         ibufp = NULL;
  308.         return ERR;
  309.       }
  310.     else
  311.       {
  312.         clearerr (stdin);
  313.         if (i != oi)
  314.           {
  315.         oi = i;
  316.         continue;
  317.           }
  318.         else if (i)
  319.           ibuf[i] = '\0';
  320.         ibufp = ibuf;
  321.         return i;
  322.       }
  323.       }
  324. }
  325.  
  326.  
  327.  
  328. #define ESCAPES "\a\b\f\n\r\t\v\\"
  329. #define ESCCHARS "abfnrtv\\"
  330.  
  331. extern int rows;
  332. extern int cols;
  333.  
  334. /* put_tty_line: print text to stdout */
  335. int
  336. put_tty_line (s, l, n, gflag)
  337.      char *s;
  338.      int l;
  339.      long n;
  340.      int gflag;
  341. {
  342.   int col = 0;
  343.   int lc = 0;
  344.   char *cp;
  345.  
  346.   if (gflag & GNP)
  347.     {
  348.       printf ("%ld\t", n);
  349.       col = 8;
  350.     }
  351.   for (; l--; s++)
  352.     {
  353.       if ((gflag & GLS) && ++col > cols)
  354.     {
  355.       fputs ("\\\n", stdout);
  356.       col = 1;
  357.       if (!traditional && !scripted && !isglobal && ++lc > rows)
  358.         {
  359.           lc = 0;
  360.           fputs ("Press <RETURN> to continue... ", stdout);
  361.           fflush (stdout);
  362.           if (get_tty_line () < 0)
  363.         return ERR;
  364.         }
  365.     }
  366.       if (gflag & GLS)
  367.     {
  368.       if (31 < *s && *s < 127 && *s != '\\')
  369.         putchar (*s);
  370.       else
  371.         {
  372.           putchar ('\\');
  373.           col++;
  374.           if (*s && (cp = strchr (ESCAPES, *s)) != NULL)
  375.         putchar (ESCCHARS[cp - ESCAPES]);
  376.           else
  377.         {
  378.           putchar ((((unsigned char) *s & 0300) >> 6) + '0');
  379.           putchar ((((unsigned char) *s & 070) >> 3) + '0');
  380.           putchar (((unsigned char) *s & 07) + '0');
  381.           col += 2;
  382.         }
  383.         }
  384.  
  385.     }
  386.       else
  387.     putchar (*s);
  388.     }
  389.   if (!traditional && (gflag & GLS))
  390.     putchar ('$');
  391.   putchar ('\n');
  392.   return 0;
  393. }
  394.