commit 13aeb0226d445fbf9e821699ae8ab67fd624489f
parent ee3e77b402e49dba4684f245ffd2094c57554eb1
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Sun, 13 Dec 2015 11:23:25 +0100
First functional version of 's' command
This version tries to hide the use of regexec
as much as possible. All the work is done in
3 functions, addpre, addsub and addpost,
which copy the text before the match,
the text of the substitution and the text
after the match.
Diffstat:
M | ed.c | | | 106 | ++++++++++++++++++++++++++++++++++++++++++++++--------------------------------- |
1 file changed, 62 insertions(+), 44 deletions(-)
diff --git a/ed.c b/ed.c
@@ -49,6 +49,7 @@ char *ocmdline;
size_t cmdsiz, cmdcap;
int repidx;
char *rhs;
+char *lastmatch;
static void
error(char *msg)
@@ -319,9 +320,17 @@ compile(int delim)
}
static int
-match(int num, int flags)
+match(int num)
{
- return !regexec(pattern, gettxt(num), 10, matchs, flags);
+ lastmatch = gettxt(num);
+ return !regexec(pattern, lastmatch, 10, matchs, 0);
+}
+
+static int
+rematch(int num)
+{
+ lastmatch += matchs[0].rm_eo;
+ return !regexec(pattern, lastmatch, 10, matchs, 0);
}
static int
@@ -332,7 +341,7 @@ search(int way)
i = curln;
do {
i = (way == '?') ? prevln(i) : nextln(i);
- if (match(i, 0))
+ if (match(i))
return i;
} while (i != curln);
@@ -841,6 +850,8 @@ getnth(void)
if ((c = input()) == 'g') {
return -1;
} else if (isdigit(c)) {
+ if (c == '0')
+ return -1;
return c - '0';
} else {
back(c);
@@ -849,60 +860,67 @@ getnth(void)
}
static void
+addpre(char **s, size_t *cap, size_t *siz)
+{
+ char *p;
+
+ for (p = lastmatch; p < lastmatch + matchs[0].rm_so; ++p)
+ *s = addchar(*p, *s, cap, siz);
+}
+
+static void
+addpost(char **s, size_t *cap, size_t *siz)
+{
+ char c, *p;
+
+ for (p = lastmatch + matchs[0].rm_eo; c = *p; ++p)
+ *s = addchar(c, *s, cap, siz);
+ *s = addchar('\0', *s, cap, siz);
+}
+
+static void
+addsub(char **s, size_t *cap, size_t *siz)
+{
+ char *p, c;
+
+ for (p = rhs; c = *p; ++p)
+ *s = addchar(c, *s, cap, siz);
+}
+
+static void
subline(int num, int nth)
{
- char *s, *p, *t, c, *q;
- size_t siz, cap;
- static char *line;
- regmatch_t m[10], *mp;
-
- free(line);
- line = NULL;
-
- p = s = gettxt(num);
- while (nth--) {
- if (!regexec(pattern, s, 10, m, 0))
- return;
- p += m[0].rm_eo;
- if (nth <= 0)
- break;
- }
+ int m, changed;
+ static char *s;
+ static size_t siz, cap;
- siz = cap = 0;
- for (t = s; p > t; ++t)
- line = addchar(*t++, line, &cap, &siz);
-
- for (t = rhs; c = *t; ++t) {
- switch (c) {
- case '\\':
- if (!isdigit(*t))
- goto add_char;
- mp = &m[*t++ - '0'];
- goto add_string;
- case '&':
- mp = &m[0];
- add_string:
- for (q = s + mp->rm_so; q < s + mp->rm_eo; ++q)
- line = addchar(*q, line, &cap, &siz);
- break;
- default:
- add_char:
- line = addchar(c, line, &cap, &siz);
+ siz = 0;
+ for (m = match(num); m; m = rematch(num)) {
+ if (--nth > 0)
+ continue;
+ changed = 1;
+ addpre(&s, &cap, &siz);
+ addsub(&s, &cap, &siz);
+ if (nth == 0)
break;
- }
}
+ if (!changed)
+ return;
+ addpost(&s, &cap, &siz);
+ delete(num, num);
+ curln = prevln(num);
+ inject(s);
}
static void
subst(void)
{
- int delim, nth, i;
- char *s;
+ int nth, i;
nth = getnth();
-
for (i = line1; i <= line2; i = nextln(i))
subline(i, nth);
+ curln = line2;
}
static void
@@ -1152,7 +1170,7 @@ chkglobal(void)
if (i >= line1 && i <= line2)
v = 0;
else
- v = match(i, 0) == dir;
+ v = match(i) == dir;
setglobal(i, v);
}