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)
MFC after:	3 weeks
This commit is contained in:
Pedro F. Giffuni 2016-05-07 01:44:22 +00:00
parent dc9643853d
commit b6f5aa5715
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=299211

View File

@ -379,7 +379,7 @@ substitute(struct s_command *cp)
{ {
SPACE tspace; SPACE tspace;
regex_t *re; regex_t *re;
regoff_t re_off, slen; regoff_t slen;
int lastempty, n; int lastempty, n;
char *s; char *s;
@ -400,61 +400,55 @@ substitute(struct s_command *cp)
n = cp->u.s->n; n = cp->u.s->n;
lastempty = 1; lastempty = 1;
switch (n) { do {
case 0: /* Global */ /* Copy the leading retained string. */
do { if (n <= 1 && match[0].rm_so)
if (lastempty || match[0].rm_so != match[0].rm_eo) { cspace(&SS, s, match[0].rm_so, APPEND);
/* 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. */
regsub(&SS, s, cp->u.s->new);
}
/* Move past this match. */ /* Skip zero-length matches right after other matches. */
if (match[0].rm_so != match[0].rm_eo) { if (lastempty || match[0].rm_so ||
s += match[0].rm_eo; match[0].rm_so != match[0].rm_eo) {
slen -= match[0].rm_eo; if (n <= 1) {
lastempty = 0; /* Want this match: append replacement. */
regsub(&SS, s, cp->u.s->new);
if (n == 1)
n = -1;
} else { } else {
if (match[0].rm_so < slen) /* Want a later match: append original. */
cspace(&SS, s + match[0].rm_so, 1, if (match[0].rm_eo)
APPEND); cspace(&SS, s, match[0].rm_eo, APPEND);
s += match[0].rm_so + 1; n--;
slen -= match[0].rm_so + 1;
lastempty = 1;
} }
} 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 */ /* Move past this match. */
/* 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. */
s += match[0].rm_eo; s += match[0].rm_eo;
slen -= 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); cspace(&SS, s, slen, APPEND);
break;
}
/* /*
* Swap the substitute space and the pattern space, and make sure * Swap the substitute space and the pattern space, and make sure