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

  1. /* sub.c: This file contains the substitution routines for the ed
  2.    line editor */
  3. /* ed line editor.
  4.    Copyright (C) 1993 Andrew Moore, Talke Studio
  5.    All Rights Reserved
  6.  
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2, or (at your option)
  10.    any later version.
  11.  
  12.    This program is distributed in the hope that it will be useful, but
  13.    WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.    General Public License for more details.
  16.  
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21.  
  22. #ifndef lint
  23. static char *rcsid = "@(#)$Id: sub.c,v 1.2 1994/02/20 03:27:53 alm Exp $";
  24. #endif /* not lint */
  25.  
  26. #include "ed.h"
  27.  
  28.  
  29. char *rhbuf;            /* rhs substitution buffer */
  30. int rhbufsz;            /* rhs substitution buffer size */
  31. int rhbufi;            /* rhs substitution buffer index */
  32.  
  33. /* extract_subst_tail: extract substitution tail from the command buffer */
  34. int
  35. extract_subst_tail (flagp, np)
  36.      int *flagp;
  37.      int *np;
  38. {
  39.   char delimiter;
  40.  
  41.   *flagp = *np = 0;
  42.   if ((delimiter = *ibufp) == '\n')
  43.     {
  44.       rhbufi = 0;
  45.       *flagp = GPR;
  46.       return 0;
  47.     }
  48.   else if (extract_subst_template () == NULL)
  49.     return ERR;
  50.   else if (*ibufp == '\n')
  51.     {
  52.       *flagp = GPR;
  53.       return 0;
  54.     }
  55.   else if (*ibufp == delimiter)
  56.     ibufp++;
  57.   if ('1' <= *ibufp && *ibufp <= '9')
  58.     {
  59.       STRTOL (*np, ibufp);
  60.       return 0;
  61.     }
  62.   else if (*ibufp == 'g')
  63.     {
  64.       ibufp++;
  65.       *flagp = GSG;
  66.       return 0;
  67.     }
  68.   return 0;
  69. }
  70.  
  71.  
  72. /* extract_subst_template: return pointer to copy of substitution template
  73.    in the command buffer */
  74. char *
  75. extract_subst_template ()
  76. {
  77.   int n = 0;
  78.   int i = 0;
  79.   char c;
  80.   char delimiter = *ibufp++;
  81.  
  82.   if (*ibufp == '%' && *(ibufp + 1) == delimiter)
  83.     {
  84.       ibufp++;
  85.       if (!rhbuf)
  86.     sprintf (errmsg, "no previous substitution");
  87.       return rhbuf;
  88.     }
  89.   while (*ibufp != delimiter)
  90.     {
  91.       REALLOC (rhbuf, rhbufsz, i + 2, NULL);
  92.       if ((c = rhbuf[i++] = *ibufp++) == '\n' && *ibufp == '\0')
  93.     {
  94.       i--, ibufp--;
  95.       break;
  96.     }
  97.       else if (c != '\\')
  98.     ;
  99.       else if ((rhbuf[i++] = *ibufp++) != '\n')
  100.     ;
  101.       else if (!isglobal)
  102.     {
  103.       while ((n = get_tty_line ()) == 0 ||
  104.          n > 0 && ibuf[n - 1] != '\n')
  105.         clearerr (stdin);
  106.       if (n < 0)
  107.         return NULL;
  108.     }
  109.     }
  110.   REALLOC (rhbuf, rhbufsz, i + 1, NULL);
  111.   rhbuf[rhbufi = i] = '\0';
  112.   return rhbuf;
  113. }
  114.  
  115.  
  116. char *rbuf;            /* substitute_matching_text buffer */
  117. int rbufsz;            /* substitute_matching_text buffer size */
  118.  
  119. /* search_and_replace: for each line in a range, change text matching a pattern
  120.    according to a substitution template; return status  */
  121. int
  122. search_and_replace (pat, gflag, kth)
  123.      pattern_t *pat;
  124.      int gflag;
  125.      int kth;
  126. {
  127.   undo_t *up;
  128.   char *txt;
  129.   char *eot;
  130.   long lc;
  131.   int nsubs = 0;
  132.   line_t *lp;
  133.   int len;
  134.  
  135.   current_addr = first_addr - 1;
  136.   for (lc = 0; lc <= second_addr - first_addr; lc++)
  137.     {
  138.       lp = get_addressed_line_node (++current_addr);
  139.       if ((len = substitute_matching_text (pat, lp, gflag, kth)) < 0)
  140.     return ERR;
  141.       else if (len)
  142.     {
  143.       up = NULL;
  144.       if (delete_lines (current_addr, current_addr) < 0)
  145.         return ERR;
  146.       txt = rbuf;
  147.       eot = rbuf + len;
  148.       SPL1 ();
  149.       do
  150.         {
  151.           if ((txt = put_sbuf_line (txt)) == NULL)
  152.         {
  153.           SPL0 ();
  154.           return ERR;
  155.         }
  156.           else if (up)
  157.         up->t = get_addressed_line_node (current_addr);
  158.           else if ((up = push_undo_stack (UADD,
  159.                        current_addr, current_addr)) == NULL)
  160.         {
  161.           SPL0 ();
  162.           return ERR;
  163.         }
  164.         }
  165.       while (txt != eot);
  166.       SPL0 ();
  167.       nsubs++;
  168.     }
  169.     }
  170.   if (nsubs == 0 && !(gflag & GLB))
  171.     {
  172.       sprintf (errmsg, "no match");
  173.       return ERR;
  174.     }
  175.   else if ((gflag & (GPR | GLS | GNP)) &&
  176.        display_lines (current_addr, current_addr, gflag) < 0)
  177.     return ERR;
  178.   return 0;
  179. }
  180.  
  181.  
  182. /* substitute_matching_text: replace text matched by a pattern according to
  183.    a substitution template; return pointer to the modified text */
  184. int
  185. substitute_matching_text (pat, lp, gflag, kth)
  186.      pattern_t *pat;
  187.      line_t *lp;
  188.      int gflag;
  189.      int kth;
  190. {
  191.   int off = 0;
  192.   int changed = 0;
  193.   int matchno = 0;
  194.   int i = 0;
  195.   regmatch_t rm[SE_MAX];
  196.   char *txt;
  197.   char *eot;
  198.  
  199.   if ((txt = get_sbuf_line (lp)) == NULL)
  200.     return ERR;
  201.   if (isbinary)
  202.     NUL_TO_NEWLINE (txt, lp->len);
  203.   eot = txt + lp->len;
  204.   if (!regexec (pat, txt, SE_MAX, rm, 0))
  205.     {
  206.       do
  207.     {
  208.       if (!kth || kth == ++matchno)
  209.         {
  210.           changed++;
  211.           i = rm[0].rm_so;
  212.           REALLOC (rbuf, rbufsz, off + i, ERR);
  213.           if (isbinary)
  214.         NEWLINE_TO_NUL (txt, rm[0].rm_eo);
  215.           memcpy (rbuf + off, txt, i);
  216.           off += i;
  217.           if ((off = apply_subst_template (txt, rm, off,
  218.                            pat->re_nsub)) < 0)
  219.         return ERR;
  220.         }
  221.       else
  222.         {
  223.           i = rm[0].rm_eo;
  224.           REALLOC (rbuf, rbufsz, off + i, ERR);
  225.           if (isbinary)
  226.         NEWLINE_TO_NUL (txt, i);
  227.           memcpy (rbuf + off, txt, i);
  228.           off += i;
  229.         }
  230.       txt += rm[0].rm_eo;
  231.     }
  232.       while (*txt && (!changed || (gflag & GSG) && rm[0].rm_eo) &&
  233.          !regexec (pat, txt, SE_MAX, rm, REG_NOTBOL));
  234.       i = eot - txt;
  235.       REALLOC (rbuf, rbufsz, off + i + 2, ERR);
  236.       if (i > 0 && !rm[0].rm_eo && (gflag & GSG))
  237.     {
  238.       sprintf (errmsg, "infinite substitution loop");
  239.       return ERR;
  240.     }
  241.       if (isbinary)
  242.     NEWLINE_TO_NUL (txt, i);
  243.       memcpy (rbuf + off, txt, i);
  244.       memcpy (rbuf + off + i, "\n", 2);
  245.     }
  246.   return changed ? off + i + 1 : 0;
  247. }
  248.  
  249.  
  250. /* apply_subst_template: modify text according to a substitution template;
  251.    return offset to end of modified text */
  252. int
  253. apply_subst_template (boln, rm, off, re_nsub)
  254.      char *boln;
  255.      regmatch_t *rm;
  256.      int off;
  257.      int re_nsub;
  258. {
  259.   int j = 0;
  260.   int k = 0;
  261.   int n;
  262.   char *sub = rhbuf;
  263.  
  264.   for (; sub - rhbuf < rhbufi; sub++)
  265.     if (*sub == '&')
  266.       {
  267.     j = rm[0].rm_so;
  268.     k = rm[0].rm_eo;
  269.     REALLOC (rbuf, rbufsz, off + k - j, ERR);
  270.     while (j < k)
  271.       rbuf[off++] = boln[j++];
  272.       }
  273.     else if (*sub == '\\' && '1' <= *++sub && *sub <= '9' &&
  274.          (n = *sub - '0') <= re_nsub)
  275.       {
  276.     j = rm[n].rm_so;
  277.     k = rm[n].rm_eo;
  278.     REALLOC (rbuf, rbufsz, off + k - j, ERR);
  279.     while (j < k)
  280.       rbuf[off++] = boln[j++];
  281.       }
  282.     else
  283.       {
  284.     REALLOC (rbuf, rbufsz, off + 1, ERR);
  285.     rbuf[off++] = *sub;
  286.       }
  287.   REALLOC (rbuf, rbufsz, off + 1, ERR);
  288.   rbuf[off] = '\0';
  289.   return off;
  290. }
  291.