summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2025-09-02 11:46:11 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2025-09-02 11:46:11 +0200
commit106546961db9b30ca44894a3a09fa3113ed85e46 (patch)
treee829c69532b2879ff22b4e024b083bc5d8dbbcd9
parentb4cedd4c9ae0ea31986973b7b3e6956937aafa32 (diff)
ash: implement <<<here_string syntax
function old new delta write2pipe - 133 +133 .rodata 105992 106009 +17 readtoken1 3101 3111 +10 cmdtxt 631 641 +10 nodesize 27 28 +1 redirect 961 916 -45 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 4/1 up/down: 171/-45) Total: 126 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/ash.c87
-rw-r--r--shell/ash_test/ash-heredoc/herestring1.right33
-rwxr-xr-xshell/ash_test/ash-heredoc/herestring1.tests35
3 files changed, 129 insertions, 26 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 7a4f7c6a8..b845ac393 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -950,14 +950,15 @@ static const char dolatstr[] ALIGN1 = {
#endif
#define NCLOBBER 18
#define NFROM 19
-#define NFROMTO 20
-#define NAPPEND 21
-#define NTOFD 22
-#define NFROMFD 23
-#define NHERE 24
-#define NXHERE 25
-#define NNOT 26
-#define N_NUMBER 27
+#define NFROMSTR 20
+#define NFROMTO 21
+#define NAPPEND 22
+#define NTOFD 23
+#define NFROMFD 24
+#define NHERE 25
+#define NXHERE 26
+#define NNOT 27
+#define N_NUMBER 28
union node;
@@ -1388,6 +1389,7 @@ shcmd(union node *cmd, FILE *fp)
#endif
case NTOFD: s = ">&"; dftfd = 1; break;
case NFROM: s = "<"; break;
+ case NFROMSTR: s = "<<<"; break;
case NFROMFD: s = "<&"; break;
case NFROMTO: s = "<>"; break;
default: s = "*error*"; break;
@@ -5180,6 +5182,9 @@ cmdtxt(union node *n)
case NXHERE:
p = "<<...";
goto dotail2;
+ case NFROMSTR:
+ p = "<<<";
+ goto dotail2;
case NCASE:
cmdputs("case ");
cmdputs(n->ncase.expr->narg.text);
@@ -5633,25 +5638,9 @@ stoppedjobs(void)
* data to a pipe. If the document is short, we can stuff the data in
* the pipe without forking.
*/
-/* openhere needs this forward reference */
-static void expandhere(union node *arg);
static int
-openhere(union node *redir)
+write2pipe(int pip[2], const char *p, size_t len)
{
- char *p;
- int pip[2];
- size_t len = 0;
-
- if (pipe(pip) < 0)
- ash_msg_and_raise_perror("can't create pipe");
-
- p = redir->nhere.doc->narg.text;
- if (redir->type == NXHERE) {
- expandhere(redir->nhere.doc);
- p = stackblock();
- }
-
- len = strlen(p);
if (len <= PIPE_BUF) {
xwrite(pip[1], p, len);
goto out;
@@ -5673,6 +5662,42 @@ openhere(union node *redir)
return pip[0];
}
+/* openhere needs this forward reference */
+static void expandhere(union node *arg);
+static int
+openhere(union node *redir)
+{
+ char *p;
+ int pip[2];
+
+ if (pipe(pip) < 0)
+ ash_msg_and_raise_perror("can't create pipe");
+
+ p = redir->nhere.doc->narg.text;
+ if (redir->type == NXHERE) {
+ expandhere(redir->nhere.doc);
+ p = stackblock();
+ }
+
+ return write2pipe(pip, p, strlen(p));
+}
+
+static int
+openherestr(char *str)
+{
+ int pip[2];
+ size_t len;
+
+ if (pipe(pip) < 0)
+ ash_msg_and_raise_perror("can't create pipe");
+
+ len = strlen(str);
+ str[len] = '\n';
+ write2pipe(pip, str, len + 1);
+ str[len] = '\0';
+ return pip[0];
+}
+
static int
openredirect(union node *redir)
{
@@ -5687,6 +5712,9 @@ openredirect(union node *redir)
do_open:
f = sh_open(redir->nfile.expfname, flags, 0);
break;
+ case NFROMSTR:
+ f = openherestr(redir->nfile.expfname);
+ break;
case NFROMTO:
flags = O_RDWR|O_CREAT;
goto do_open;
@@ -9188,6 +9216,7 @@ calcsize(int funcblocksize, union node *n)
#endif
case NCLOBBER:
case NFROM:
+ case NFROMSTR:
case NFROMTO:
case NAPPEND:
funcblocksize = calcsize(funcblocksize, n->nfile.fname);
@@ -9310,6 +9339,7 @@ copynode(union node *n)
#endif
case NCLOBBER:
case NFROM:
+ case NFROMSTR:
case NFROMTO:
case NAPPEND:
new->nfile.fname = copynode(n->nfile.fname);
@@ -9778,6 +9808,7 @@ expredir(union node *n)
switch (redir->type) {
case NFROMTO:
case NFROM:
+ case NFROMSTR:
case NTO:
#if BASH_REDIR_OUTPUT
case NTO2:
@@ -12970,6 +13001,11 @@ parseredir: {
c = pgetc_eatbnl();
switch (c) {
case '<':
+ c = pgetc_eatbnl();
+ if (c == '<') {
+ np->type = NFROMSTR;
+ break;
+ }
if (sizeof(struct nfile) != sizeof(struct nhere)) {
np = stzalloc(sizeof(struct nhere));
/*np->nfile.fd = 0; - stzalloc did it */
@@ -12977,7 +13013,6 @@ parseredir: {
np->type = NHERE;
heredoc = stzalloc(sizeof(struct heredoc));
heredoc->here = np;
- c = pgetc_eatbnl();
if (c == '-') {
heredoc->striptabs = 1;
} else {
diff --git a/shell/ash_test/ash-heredoc/herestring1.right b/shell/ash_test/ash-heredoc/herestring1.right
new file mode 100644
index 000000000..555937daa
--- /dev/null
+++ b/shell/ash_test/ash-heredoc/herestring1.right
@@ -0,0 +1,33 @@
+one
+_two
+\_three
+\_four
+\_two
+\_three
+\\_four
+two_newlines
+
+/bin/c*
+star_*
+star_*
+star_*
+star_\*
+star_*
+star_\*
+line1
+line2
+ line3
+line1
+line2
+ line3
+512
+256
+128
+64
+32
+16
+8
+4
+2
+v-$a-\t-\-\"-\x-`-\--\z-\*-\?-
+v-$a-\t-\-"-\x-`-\--\z-\*-\?-
diff --git a/shell/ash_test/ash-heredoc/herestring1.tests b/shell/ash_test/ash-heredoc/herestring1.tests
new file mode 100755
index 000000000..fb7bd0dda
--- /dev/null
+++ b/shell/ash_test/ash-heredoc/herestring1.tests
@@ -0,0 +1,35 @@
+cat <<<one
+cat <<<\_two
+cat <<<"\_three"
+cat <<<'\_four'
+cat <<<\\_two
+cat <<<"\\_three"
+cat <<<'\\_four'
+
+cat <<<$'two_newlines\n'
+
+cat <<</bin/c*
+
+cat <<<star_*
+cat <<<star_\*
+cat <<<"star_*"
+cat <<<"star_\*"
+cat <<<'star_*'
+cat <<<'star_\*'
+
+var=$'line1
+line2
+ line3'
+
+cat <<<$var
+
+cat <<<"$var"
+
+i=10
+until test $((--i)) = 0; do
+ cat <<<$((2**i))
+done
+
+a=qwerty
+cat <<<`echo v'-$a-\t-\\-\"-\x-\`-\--\z-\*-\?-'`
+cat <<<"`echo v'-$a-\t-\\-\"-\x-\`-\--\z-\*-\?-'`"