date and time created 93/01/23 11:21:42 by bostic
authorKeith Bostic <bostic@ucbvax.Berkeley.EDU>
Sun, 24 Jan 1993 03:21:42 +0000 (19:21 -0800)
committerKeith Bostic <bostic@ucbvax.Berkeley.EDU>
Sun, 24 Jan 1993 03:21:42 +0000 (19:21 -0800)
SCCS-vsn: contrib/ed/sub.c 5.1

usr/src/contrib/ed/sub.c [new file with mode: 0644]

diff --git a/usr/src/contrib/ed/sub.c b/usr/src/contrib/ed/sub.c
new file mode 100644 (file)
index 0000000..987c545
--- /dev/null
@@ -0,0 +1,304 @@
+/*-
+ * Copyright (c) 1992 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rodney Ruddock of the University of Guelph.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)sub.c      5.1 (Berkeley) %G%";
+#endif /* not lint */
+
+#include "ed.h"
+
+/*
+ * The substitute command. It's big because of the backward compatability.
+ */
+
+void
+s(inputt, errnum)
+
+FILE *inputt;
+int *errnum;
+
+{
+  static int l_count2=1, l_global=0, l_print=0, l_first_pass_flag=0;
+  static char *l_match=NULL, *l_repl=NULL;
+  int l_s_flag, l_count, l_matched, l_nflag, l_cnt, yy, l_sr_flag=0, l_err, l_sl;
+  char *l_match2=NULL, *l_local=NULL, *l_local_temp=NULL;
+  LINE *l_s_ret, *l_temp_line, *l_temp_line2, *l_kval, *l_last;
+#ifndef REG_STARTEND
+  size_t l_offset=0;
+#endif
+
+  if (start_default && End_default)
+    start = End = current;
+  else if (start_default)
+    start = End;
+  if (start == NULL)
+    {
+      *errnum = -1;
+      return;
+    }
+  start_default = End_default = 0;
+
+  l_sl = ss = getc(inputt);
+   if (l_first_pass_flag == 0)
+    l_match = l_repl = NULL;
+  l_match2 = get_pattern(l_sl, inputt, errnum, 0);
+  if (sigint_flag)
+    SIGINT_ACTION;
+  if (*errnum < 0)
+    {
+      if ((*errnum == -2) && (l_sl != '\n'))
+        return;
+      if ((l_match2 == NULL) || (strlen(l_match2) > 4) || (l_first_pass_flag == 0))
+        return;
+      *errnum = 0;
+      l_sr_flag = -1;
+      for (yy=0; yy<(strlen(l_match2)); yy++)
+         {
+           switch (l_match2[yy])
+                 {
+                   case '\n': ss = getc(inputt);
+                              goto bcg1;
+                              break;
+                   case 'r': l_sr_flag = 1;
+                             break;
+                   case 'p': l_print = (l_print)?0:1;
+                             break;
+                   case 'g': l_global = (l_global)?0:1;
+                             break;
+                   case 'N': l_count2 = 1;
+                             break;
+                   default: *errnum = -1;
+                            strcpy(help_msg, "illegal modifier to s");
+                            return;
+                 } /* end-switch */
+         } /* end-for */
+      ss = getc(inputt);
+      if (l_sr_flag == 1)
+        goto bcg2;
+      else
+        goto bcg1;
+    }
+
+  if (l_first_pass_flag)
+    {
+      free(l_match);
+      free(l_repl);
+    }
+  else
+      l_first_pass_flag = 1;
+  l_match = l_match2;
+  *errnum = 0;
+  l_repl = get_pattern(ss, inputt, errnum, 1);
+  if (sigint_flag)
+    SIGINT_ACTION;
+  l_global = l_print = 0;
+  if (*errnum < 0)
+    {
+      if ((*errnum == -1) && (ss == '\n'))
+          l_print = (int)1; /* note: \n still in stream for next getc */
+      else
+        return;
+    }
+  *errnum = 0;
+
+  l_count2 = 1;
+
+  while (((ss=getc(inputt)) != '\n') && (ss != EOF))
+       {
+         if (ss == 'g')
+           l_global = 1;
+         else if (ss == 'p')
+           l_print = (l_print | (int)1);
+         else if (ss == 'n')
+           l_print = (l_print | (int)2);
+         else if (ss == 'l')
+           l_print = (l_print | (int)4);
+         else if ((ss > ('0'-1)) && (ss < ('9'+1)))
+             l_count2 = dig_num_conv(inputt, errnum);
+         else
+           {
+             *errnum = -1;
+             strcpy(help_msg, "illegal command option");
+             return;
+           }
+       }
+
+bcg1:
+  if ((RE_flag == 0) && (l_match[1] == '\0'))
+    {
+      *errnum = -1;
+      ungetc(ss, inputt);
+      return;
+    }
+  else if ((l_sr_flag == 0) && (l_match[1] || (RE_patt == NULL)))
+    {
+      free(RE_patt);
+      RE_patt = (char *)malloc(sizeof(char)*(2+strlen(l_match)));
+      bcopy(l_match, RE_patt);
+    }
+  RE_sol = (l_match[1] == '^')?1:0;
+  if ((l_match[1]) && (regfree(&RE_comp), l_err = regcomp(&RE_comp, &l_match[1], 0)))
+    {
+      regerror(l_err, &RE_comp, help_msg, 128);
+      *errnum = -1;
+      RE_flag = 0;
+      ungetc(ss, inputt);
+      return;
+    }
+  RE_flag = 1;
+  if (sigint_flag)
+    SIGINT_ACTION;
+bcg2:
+  current = start;
+  l_s_flag = 0;
+  do
+    {
+      if (sigint_flag)
+        SIGINT_ACTION;
+      RE_match[0].rm_eo = 0;
+      get_line(current->handle, current->len);
+      l_count = l_count2;
+      l_local = text;
+#ifndef REG_STARTEND
+      l_offset = 0;
+#endif
+      do
+        {
+          RE_match[0].rm_so = RE_match[0].rm_eo;
+#ifdef REG_STARTEND
+          l_matched = regexec_n(&RE_comp, l_local, (size_t)RE_SEC, RE_match, 0, l_count, (size_t)current->len, 0);
+#else
+          l_matched = regexec_n(&RE_comp, l_local, (size_t)RE_SEC, RE_match, 0, l_count, &l_offset, 0);
+#endif
+          if (l_matched == 0)
+            {
+              if ((l_s_flag == 0) && (g_flag == 0))
+                u_clr_stk();
+              l_count = l_s_flag = 1;
+              /* the l_local passed into re_replace is not freed in re_replace
+               * because it is "text", the global line holder, for the first
+               * pass through this loop. The value returned by re_replace is
+               * a new string (with the first replacement in it). If the 'g'
+               * flag was set with substitute then this new string is passed in
+               * for the second pass and can be freed once re_replace is done
+               * with it. (...and so on for the rest of the 'g' passes.
+               * RE_match[0].rm_eo is changed in re_replace to be the
+               * new location of the next character immediately after
+               * the replacement since it is likely the position of that
+               * character has changed because of the replacement.
+               */
+#ifdef REG_STARTEND
+              l_local = re_replace(l_local, (size_t)(RE_SEC-1), RE_match, &l_repl[1]);
+#else
+              l_local = re_replace(l_local, (size_t)(RE_SEC-1), RE_match, &l_repl[1], l_offset);
+#endif
+            }
+          if (l_global == 0)
+            break;
+          if (l_local[RE_match[0].rm_eo] == '\0')
+            break;
+        } while (!l_matched);
+
+      l_cnt = l_nflag = 0;
+      l_kval = current;
+      l_temp_line = current->above;
+      l_temp_line2 = current->below;
+      l_local_temp = l_local;
+      while (1)
+           {
+             /* make the new string the one for this line. Check if
+              * it needs to be split.
+              */
+             if ((l_local[l_cnt] == '\n') || (l_local[l_cnt] == '\0'))
+               {
+                 if (l_local[l_cnt] == '\0')
+                   l_nflag = 1;
+                 l_local[l_cnt] = '\0';
+                 l_s_ret = (LINE *)malloc(sizeof(LINE));
+                 if (l_s_ret == NULL)
+                   {
+                     *errnum = -1;
+                     strcpy(help_msg, "out of memory error");
+                     return;
+                   }
+                 (l_s_ret->len) = strlen(l_local);
+                 (l_s_ret->handle) = add_line(l_local, l_s_ret->len);
+                 (l_s_ret->above) = l_temp_line;
+                 (l_s_ret->below) = NULL;
+                 if (l_temp_line == NULL)
+                   top = l_s_ret;
+                 else
+                   {
+                     u_add_stk(&(l_temp_line->below));
+                     (l_temp_line->below) = l_s_ret;
+                   }
+                 l_temp_line = l_s_ret;
+                 if ((l_local[l_cnt] == '\0') && (l_nflag == 1))
+                   break;
+                 else
+                   {
+                     l_local = &(l_local[l_cnt+1]);
+                     l_cnt = 0;
+                   }
+               } /* end-if */
+             else
+               l_cnt++;
+           } /* end-while */
+      (l_s_ret->below) = l_temp_line2;
+      ku_chk(current, current, l_kval->below);
+      if (current == End)
+        End = l_s_ret;
+      current = l_s_ret;
+      l_last = current;
+      if (l_temp_line2 == NULL)
+        bottom = l_s_ret;
+      else
+        {
+          u_add_stk(&(l_temp_line2->above));
+          (l_temp_line2->above) = current;
+        }
+      if (l_local_temp != text)
+        free(l_local_temp);
+      current = current->below;
+    } while (current != (End->below));
+
+  if (l_s_flag == 0)
+    {
+      current = start;
+      strcpy(help_msg, "no matches found for substitution");
+      *errnum = -1;
+      ungetc('\n', inputt);
+      return;
+    }
+
+  change_flag = 1;
+  current = l_last;
+
+  if (l_print > 0)
+    {
+      start = End = current;
+      ungetc(ss, inputt);
+      if (l_print == (l_print | (int)1))
+        p(inputt, errnum, 0);
+      if (l_print == (l_print | (int)2))
+        p(inputt, errnum, 1);
+      if (l_print == (l_print | (int)4))
+        l(inputt, errnum);
+      if (*errnum < 0)
+        return;
+    }
+
+  if (l_sr_flag == -1)
+    {
+      regfree(&RE_comp);
+      regcomp(&RE_comp, &RE_patt[1], 0);
+    }
+  *errnum = 1;
+} /* end-s */