version 1.17, 2011/07/26 08:47:07 |
version 1.18, 2011/09/17 15:29:19 |
|
|
{ |
{ |
SPACE tspace; |
SPACE tspace; |
regex_t *re; |
regex_t *re; |
size_t re_off, slen; |
regoff_t slen; |
int n, lastempty; |
int n, lastempty; |
char *s; |
char *s; |
|
|
|
|
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 == 0) |
/* 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); |
else |
n--; |
cspace(&SS, s + match[0].rm_so, 1, |
|
APPEND); |
|
s += match[0].rm_so + 1; |
|
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) { |
|
s += match[0].rm_eo; |
|
slen -= match[0].rm_eo; |
|
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 |