Author: pfg
Date: Tue May 24 03:08:32 2016
New Revision: 300555
URL: https://svnweb.freebsd.org/changeset/base/300555

Log:
  sed: rewrite the main loop.
  
  Rewrite the main loop of the "sed s/..." command, shortening it by ten
  lines and simplifying it by removing the switch statement implementing
  /g, /1, and /2 separately and repetitively.
  
  This will be needed to bring a fix from OpenBSD later.
  
  Obtained from:        OpenBSD (schwarze CVS Rev. 1.18)

Modified:
  stable/10/usr.bin/sed/process.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/usr.bin/sed/process.c
==============================================================================
--- stable/10/usr.bin/sed/process.c     Tue May 24 03:00:24 2016        
(r300554)
+++ stable/10/usr.bin/sed/process.c     Tue May 24 03:08:32 2016        
(r300555)
@@ -369,7 +369,7 @@ substitute(struct s_command *cp)
 {
        SPACE tspace;
        regex_t *re;
-       regoff_t re_off, slen;
+       regoff_t slen;
        int lastempty, n;
        char *s;
 
@@ -390,61 +390,55 @@ substitute(struct s_command *cp)
        n = cp->u.s->n;
        lastempty = 1;
 
-       switch (n) {
-       case 0:                                 /* Global */
-               do {
-                       if (lastempty || match[0].rm_so != match[0].rm_eo) {
-                               /* Locate start of replaced string. */
-                               re_off = match[0].rm_so;
-                               /* Copy leading retained string. */
-                               cspace(&SS, s, re_off, APPEND);
-                               /* Add in regular expression. */
+       do {
+               /* Copy the leading retained string. */
+               if (n <= 1 && match[0].rm_so)
+                       cspace(&SS, s, match[0].rm_so, APPEND);
+
+               /* Skip zero-length matches right after other matches. */
+               if (lastempty || match[0].rm_so ||
+                   match[0].rm_so != match[0].rm_eo) {
+                       if (n <= 1) {
+                               /* Want this match: append replacement. */
                                regsub(&SS, s, cp->u.s->new);
-                       }
-
-                       /* Move past this match. */
-                       if (match[0].rm_so != match[0].rm_eo) {
-                               s += match[0].rm_eo;
-                               slen -= match[0].rm_eo;
-                               lastempty = 0;
+                               if (n == 1)
+                                       n = -1;
                        } else {
-                               if (match[0].rm_so < slen)
-                                       cspace(&SS, s + match[0].rm_so, 1,
-                                           APPEND);
-                               s += match[0].rm_so + 1;
-                               slen -= match[0].rm_so + 1;
-                               lastempty = 1;
+                               /* Want a later match: append original. */
+                               if (match[0].rm_eo)
+                                       cspace(&SS, s, match[0].rm_eo, APPEND);
+                               n--;
                        }
-               } while (slen >= 0 && regexec_e(re, s, REG_NOTBOL, 0, slen));
-               /* Copy trailing retained string. */
-               if (slen > 0)
-                       cspace(&SS, s, slen, APPEND);
-               break;
-       default:                                /* Nth occurrence */
-               while (--n) {
-                       if (match[0].rm_eo == match[0].rm_so)
-                               match[0].rm_eo = match[0].rm_so + 1;
-                       s += match[0].rm_eo;
-                       slen -= match[0].rm_eo;
-                       if (slen < 0)
-                               return (0);
-                       if (!regexec_e(re, s, REG_NOTBOL, 0, slen))
-                               return (0);
                }
-               /* FALLTHROUGH */
-       case 1:                                 /* 1st occurrence */
-               /* Locate start of replaced string. */
-               re_off = match[0].rm_so + (s - ps);
-               /* Copy leading retained string. */
-               cspace(&SS, ps, re_off, APPEND);
-               /* Add in regular expression. */
-               regsub(&SS, s, cp->u.s->new);
-               /* Copy trailing retained string. */
+
+               /* Move past this match. */
                s += match[0].rm_eo;
                slen -= match[0].rm_eo;
+
+               /*
+                * After a zero-length match, advance one byte,
+                * and at the end of the line, terminate.
+                */
+               if (match[0].rm_so == match[0].rm_eo) {
+                       if (*s == '\0' || *s == '\n')
+                               slen = -1;
+                       else
+                               slen--;
+                       if (*s != '\0')
+                               cspace(&SS, s++, 1, APPEND);
+                       lastempty = 1;
+               } else
+                       lastempty = 0;
+
+       } while (n >= 0 && slen >= 0 && regexec_e(re, s, REG_NOTBOL, 0, slen));
+
+       /* Did not find the requested number of matches. */
+       if (n > 1)
+               return (0);
+
+       /* Copy the trailing retained string. */
+       if (slen > 0)
                cspace(&SS, s, slen, APPEND);
-               break;
-       }
 
        /*
         * Swap the substitute space and the pattern space, and make sure
_______________________________________________
svn-src-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to