summary refs log tree commit diff
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2018-03-25 15:55:40 +0800
committerHerbert Xu <herbert@gondor.apana.org.au>2018-04-02 23:30:44 +0800
commit325a460c7942aa79bb97303e129980db8afd177c (patch)
tree34365d2826b7d2ed19a04d997af9b35d346f9173
parentbuiltin: Fix echo performance regression (diff)
downloaddash-325a460c7942aa79bb97303e129980db8afd177c.tar.gz
dash-325a460c7942aa79bb97303e129980db8afd177c.zip
builtin: Move echo space/nl handling into print_escape_str
Currently echocmd uses print_escape_str to do everything apart
from printing the spaces/newlines separating its arguments.  This
patch moves the actual printing into print_escape_str as well
using the format parameter.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--src/bltin/printf.c23
1 files changed, 13 insertions, 10 deletions
diff --git a/src/bltin/printf.c b/src/bltin/printf.c
index eaf14b6..7785735 100644
--- a/src/bltin/printf.c
+++ b/src/bltin/printf.c
@@ -103,6 +103,8 @@ static int print_escape_str(const char *f, int *param, int *array, char *s)
 	len = q - p;
 	total = len - 1;
 
+	q[-1] = (!!((f[1] - 's') | done) - 1) & f[2];
+	total += !!q[-1];
 	if (f[1] == 's')
 		goto easy;
 
@@ -455,21 +457,22 @@ check_conversion(const char *s, const char *ep)
 int
 echocmd(int argc, char **argv)
 {
+	const char *lastfmt = snlfmt;
 	int nonl;
 
-	nonl = *++argv ? equal(*argv, "-n") : 0;
-	argv += nonl;
+	if (*++argv && equal(*argv, "-n")) {
+		argv++;
+		lastfmt = "%s";
+	}
 
 	do {
-		int c;
+		const char *fmt = "%s ";
+		char *s = *argv;
 
-		if (likely(*argv))
-			nonl += print_escape_str("%s", NULL, NULL, *argv++);
-		if (likely((nonl + !*argv) > 1))
-			break;
+		if (!s || !*++argv)
+			fmt = lastfmt;
 
-		c = *argv ? ' ' : '\n';
-		out1c(c);
-	} while (*argv);
+		nonl = print_escape_str(fmt, NULL, NULL, s ?: nullstr);
+	} while (!nonl && *argv);
 	return 0;
 }