commit f2593570542c7916d04f30e54f685eeb92cf5b90
parent 91e4a06811bd9d9358b2154bbf060de5250dd5db
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Sat, 12 Dec 2015 11:33:55 +0100
Add basic skeleton for s command
This code only parses the input and set the variables
that are needed in the next step, go through the lines
addressed and apply the substituion.
Diffstat:
M | ed.c | | | 85 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 85 insertions(+), 0 deletions(-)
diff --git a/ed.c b/ed.c
@@ -48,6 +48,9 @@ char *ocmdline;
size_t cmdsiz, cmdcap;
int repidx;
+int gsub;
+char *lhs, *rhs;
+
static void
error(char *msg)
{
@@ -801,6 +804,83 @@ execsh(void)
}
static void
+getlhs(int delim)
+{
+ int c;
+ char *s;
+
+ back(c = input());
+ if (c == delim) {
+ if ((s = lastre) == NULL)
+ error("No previous substitution");
+ } else {
+ s = getregex(delim);
+ }
+ free(lhs);
+ if ((lhs = strdup(s)) == NULL)
+ error("out of memory");
+
+ compile(lhs);
+ if (input() != delim)
+ error("invalid pattern delimiter");
+}
+
+static void
+getrhs(int delim)
+{
+ char *repl;
+ int c;
+ size_t n, siz, cap;
+
+ repl = NULL;
+ siz = cap = 0;
+ while ((c = input()) != '\n' && c != EOF && c != delim) {
+ if (c == '\\') {
+ if (isdigit(c = input()))
+ back(c);
+ }
+ repl = addchar(c, repl, &siz, &cap);
+ }
+ back(c);
+ repl = addchar('\0', repl, &siz, &cap);
+
+ if (!strcmp("%", repl)) {
+ free(repl);
+ if (!rhs)
+ error("no previous substitution");
+ } else {
+ free(rhs);
+ rhs = repl;
+ }
+}
+
+static void
+subs(void)
+{
+ int c, delim;
+
+
+ if ((delim = input()) == '\n') {
+ if (!rhs || !lhs)
+ error("no previous substitution");
+ } else {
+ gsub = 0;
+ getlhs(delim);
+ getrhs(delim);
+
+ if (c == delim) {
+ if ((c = input()) == 'g')
+ gsub = 1;
+ else
+ back(c);
+ } else {
+ pflag = 'p';
+ back(c);
+ }
+ }
+}
+
+static void
docmd(void)
{
char *s, cmd;
@@ -879,6 +959,11 @@ repeat:
deflines(lastln, lastln);
printf("%d\n", line1);
break;
+ case 's':
+ deflines(curln, curln);
+ subs();
+ chkprint(1);
+ break;
case 'i':
if (nlines > 1)
goto bad_address;