[hackers] [sbase][PATCH] ed: Implement command expansion for io commands

From: Santtu Lakkala <inz_AT_inz.fi>
Date: Fri, 30 Jan 2026 13:21:00 +0200

Split command expansion functionality from execsh() for reuse in the
read and write commands. Adjust getfname() to leave the command in the
input buffer for extraction by the new expandcmd().
---
 ed.c | 95 +++++++++++++++++++++++++++++++++---------------------------
 1 file changed, 52 insertions(+), 43 deletions(-)
diff --git a/ed.c b/ed.c
index fa1b758..59101d3 100644
--- a/ed.c
+++ b/ed.c
_AT_@ -751,6 +751,51 @@ chksignals(void)
 	}
 }
 
+static const char *
+expandcmd(void)
+{
+	static String cmd;
+	char *p;
+	int c, repl = 0;
+
+	skipblank();
+	if ((c = input()) != '!') {
+		back(c);
+		string(&cmd);
+	} else if (cmd.siz) {
+		--cmd.siz;
+		repl = 1;
+	} else {
+		error("no previous command");
+	}
+
+	while ((c = input()) != '\0') {
+		switch (c) {
+		case '%':
+			if (savfname[0] == '\0')
+				error("no current filename");
+			repl = 1;
+			for (p = savfname; *p; ++p)
+				addchar(*p, &cmd);
+			break;
+		case '\\':
+			c = input();
+			if (c != '%') {
+				back(c);
+				c = '\\';
+			}
+		default:
+			addchar(c, &cmd);
+		}
+	}
+	addchar('\0', &cmd);
+
+	if (repl)
+		puts(cmd.str);
+
+	return cmd.str;
+}
+
 static void
 dowrite(const char *fname, int trunc)
 {
_AT_@ -768,8 +813,7 @@ dowrite(const char *fname, int trunc)
 
 	if(fname[0] == '!') {
 		sh = 1;
-		fname++;
-		if((fp = popen(fname, "w")) == NULL)
+		if((fp = popen(expandcmd(), "w")) == NULL)
 			error("bad exec");
 	} else {
 		sh = 0;
_AT_@ -822,8 +866,7 @@ doread(const char *fname)
 
 	if(fname[0] == '!') {
 		sh = 1;
-		fname++;
-		if((fp = popen(fname, "r")) == NULL)
+		if((fp = popen(expandcmd(), "r")) == NULL)
 			error("bad exec");
 	} else if ((fp = fopen(fname, "r")) == NULL) {
 		error("cannot open input file");
_AT_@ -931,6 +974,10 @@ getfname(int comm)
 	static char fname[FILENAME_MAX];
 
 	skipblank();
+	if ((c = input()) == '!') {
+		return strcpy(fname, "!");
+	}
+	back(c);
 	for (bp = fname; bp < &fname[FILENAME_MAX]; *bp++ = c) {
 		if ((c = input()) == '\0')
 			break;
_AT_@ -1076,45 +1123,7 @@ copy(int where)
 static void
 execsh(void)
 {
-	static String cmd;
-	char *p;
-	int c, repl = 0;
-
-	skipblank();
-	if ((c = input()) != '!') {
-		back(c);
-		string(&cmd);
-	} else if (cmd.siz) {
-		--cmd.siz;
-		repl = 1;
-	} else {
-		error("no previous command");
-	}
-
-	while ((c = input()) != '\0') {
-		switch (c) {
-		case '%':
-			if (savfname[0] == '\0')
-				error("no current filename");
-			repl = 1;
-			for (p = savfname; *p; ++p)
-				addchar(*p, &cmd);
-			break;
-		case '\\':
-			c = input();
-			if (c != '%') {
-				back(c);
-				c = '\\';
-			}
-		default:
-			addchar(c, &cmd);
-		}
-	}
-	addchar('\0', &cmd);
-
-	if (repl)
-		puts(cmd.str);
-	system(cmd.str);
+	system(expandcmd());
 	if (optdiag)
 		puts("!");
 }
-- 
2.42.0
Received on Fri Jan 30 2026 - 12:21:00 CET

This archive was generated by hypermail 2.3.0 : Fri Jan 30 2026 - 12:24:31 CET