ed

simple ed
git clone git://git.2f30.org/ed
Log | Files | Refs | LICENSE

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:
Med.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); }