Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 24 May 2016 03:08:32 +0000 (UTC)
From:      "Pedro F. Giffuni" <pfg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r300555 - stable/10/usr.bin/sed
Message-ID:  <201605240308.u4O38WWQ098664@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201605240308.u4O38WWQ098664>