aboutsummaryrefslogtreecommitdiff
path: root/shell
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 /shell
parentb4cedd4c9ae0ea31986973b7b3e6956937aafa32 (diff)
downloadbusybox-w32-106546961db9b30ca44894a3a09fa3113ed85e46.tar.gz
busybox-w32-106546961db9b30ca44894a3a09fa3113ed85e46.tar.bz2
busybox-w32-106546961db9b30ca44894a3a09fa3113ed85e46.zip
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>
Diffstat (limited to 'shell')
-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 = {
950#endif 950#endif
951#define NCLOBBER 18 951#define NCLOBBER 18
952#define NFROM 19 952#define NFROM 19
953#define NFROMTO 20 953#define NFROMSTR 20
954#define NAPPEND 21 954#define NFROMTO 21
955#define NTOFD 22 955#define NAPPEND 22
956#define NFROMFD 23 956#define NTOFD 23
957#define NHERE 24 957#define NFROMFD 24
958#define NXHERE 25 958#define NHERE 25
959#define NNOT 26 959#define NXHERE 26
960#define N_NUMBER 27 960#define NNOT 27
961#define N_NUMBER 28
961 962
962union node; 963union node;
963 964
@@ -1388,6 +1389,7 @@ shcmd(union node *cmd, FILE *fp)
1388#endif 1389#endif
1389 case NTOFD: s = ">&"; dftfd = 1; break; 1390 case NTOFD: s = ">&"; dftfd = 1; break;
1390 case NFROM: s = "<"; break; 1391 case NFROM: s = "<"; break;
1392 case NFROMSTR: s = "<<<"; break;
1391 case NFROMFD: s = "<&"; break; 1393 case NFROMFD: s = "<&"; break;
1392 case NFROMTO: s = "<>"; break; 1394 case NFROMTO: s = "<>"; break;
1393 default: s = "*error*"; break; 1395 default: s = "*error*"; break;
@@ -5180,6 +5182,9 @@ cmdtxt(union node *n)
5180 case NXHERE: 5182 case NXHERE:
5181 p = "<<..."; 5183 p = "<<...";
5182 goto dotail2; 5184 goto dotail2;
5185 case NFROMSTR:
5186 p = "<<<";
5187 goto dotail2;
5183 case NCASE: 5188 case NCASE:
5184 cmdputs("case "); 5189 cmdputs("case ");
5185 cmdputs(n->ncase.expr->narg.text); 5190 cmdputs(n->ncase.expr->narg.text);
@@ -5633,25 +5638,9 @@ stoppedjobs(void)
5633 * data to a pipe. If the document is short, we can stuff the data in 5638 * data to a pipe. If the document is short, we can stuff the data in
5634 * the pipe without forking. 5639 * the pipe without forking.
5635 */ 5640 */
5636/* openhere needs this forward reference */
5637static void expandhere(union node *arg);
5638static int 5641static int
5639openhere(union node *redir) 5642write2pipe(int pip[2], const char *p, size_t len)
5640{ 5643{
5641 char *p;
5642 int pip[2];
5643 size_t len = 0;
5644
5645 if (pipe(pip) < 0)
5646 ash_msg_and_raise_perror("can't create pipe");
5647
5648 p = redir->nhere.doc->narg.text;
5649 if (redir->type == NXHERE) {
5650 expandhere(redir->nhere.doc);
5651 p = stackblock();
5652 }
5653
5654 len = strlen(p);
5655 if (len <= PIPE_BUF) { 5644 if (len <= PIPE_BUF) {
5656 xwrite(pip[1], p, len); 5645 xwrite(pip[1], p, len);
5657 goto out; 5646 goto out;
@@ -5673,6 +5662,42 @@ openhere(union node *redir)
5673 return pip[0]; 5662 return pip[0];
5674} 5663}
5675 5664
5665/* openhere needs this forward reference */
5666static void expandhere(union node *arg);
5667static int
5668openhere(union node *redir)
5669{
5670 char *p;
5671 int pip[2];
5672
5673 if (pipe(pip) < 0)
5674 ash_msg_and_raise_perror("can't create pipe");
5675
5676 p = redir->nhere.doc->narg.text;
5677 if (redir->type == NXHERE) {
5678 expandhere(redir->nhere.doc);
5679 p = stackblock();
5680 }
5681
5682 return write2pipe(pip, p, strlen(p));
5683}
5684
5685static int
5686openherestr(char *str)
5687{
5688 int pip[2];
5689 size_t len;
5690
5691 if (pipe(pip) < 0)
5692 ash_msg_and_raise_perror("can't create pipe");
5693
5694 len = strlen(str);
5695 str[len] = '\n';
5696 write2pipe(pip, str, len + 1);
5697 str[len] = '\0';
5698 return pip[0];
5699}
5700
5676static int 5701static int
5677openredirect(union node *redir) 5702openredirect(union node *redir)
5678{ 5703{
@@ -5687,6 +5712,9 @@ openredirect(union node *redir)
5687 do_open: 5712 do_open:
5688 f = sh_open(redir->nfile.expfname, flags, 0); 5713 f = sh_open(redir->nfile.expfname, flags, 0);
5689 break; 5714 break;
5715 case NFROMSTR:
5716 f = openherestr(redir->nfile.expfname);
5717 break;
5690 case NFROMTO: 5718 case NFROMTO:
5691 flags = O_RDWR|O_CREAT; 5719 flags = O_RDWR|O_CREAT;
5692 goto do_open; 5720 goto do_open;
@@ -9188,6 +9216,7 @@ calcsize(int funcblocksize, union node *n)
9188#endif 9216#endif
9189 case NCLOBBER: 9217 case NCLOBBER:
9190 case NFROM: 9218 case NFROM:
9219 case NFROMSTR:
9191 case NFROMTO: 9220 case NFROMTO:
9192 case NAPPEND: 9221 case NAPPEND:
9193 funcblocksize = calcsize(funcblocksize, n->nfile.fname); 9222 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
@@ -9310,6 +9339,7 @@ copynode(union node *n)
9310#endif 9339#endif
9311 case NCLOBBER: 9340 case NCLOBBER:
9312 case NFROM: 9341 case NFROM:
9342 case NFROMSTR:
9313 case NFROMTO: 9343 case NFROMTO:
9314 case NAPPEND: 9344 case NAPPEND:
9315 new->nfile.fname = copynode(n->nfile.fname); 9345 new->nfile.fname = copynode(n->nfile.fname);
@@ -9778,6 +9808,7 @@ expredir(union node *n)
9778 switch (redir->type) { 9808 switch (redir->type) {
9779 case NFROMTO: 9809 case NFROMTO:
9780 case NFROM: 9810 case NFROM:
9811 case NFROMSTR:
9781 case NTO: 9812 case NTO:
9782#if BASH_REDIR_OUTPUT 9813#if BASH_REDIR_OUTPUT
9783 case NTO2: 9814 case NTO2:
@@ -12970,6 +13001,11 @@ parseredir: {
12970 c = pgetc_eatbnl(); 13001 c = pgetc_eatbnl();
12971 switch (c) { 13002 switch (c) {
12972 case '<': 13003 case '<':
13004 c = pgetc_eatbnl();
13005 if (c == '<') {
13006 np->type = NFROMSTR;
13007 break;
13008 }
12973 if (sizeof(struct nfile) != sizeof(struct nhere)) { 13009 if (sizeof(struct nfile) != sizeof(struct nhere)) {
12974 np = stzalloc(sizeof(struct nhere)); 13010 np = stzalloc(sizeof(struct nhere));
12975 /*np->nfile.fd = 0; - stzalloc did it */ 13011 /*np->nfile.fd = 0; - stzalloc did it */
@@ -12977,7 +13013,6 @@ parseredir: {
12977 np->type = NHERE; 13013 np->type = NHERE;
12978 heredoc = stzalloc(sizeof(struct heredoc)); 13014 heredoc = stzalloc(sizeof(struct heredoc));
12979 heredoc->here = np; 13015 heredoc->here = np;
12980 c = pgetc_eatbnl();
12981 if (c == '-') { 13016 if (c == '-') {
12982 heredoc->striptabs = 1; 13017 heredoc->striptabs = 1;
12983 } else { 13018 } 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 @@
1one
2_two
3\_three
4\_four
5\_two
6\_three
7\\_four
8two_newlines
9
10/bin/c*
11star_*
12star_*
13star_*
14star_\*
15star_*
16star_\*
17line1
18line2
19 line3
20line1
21line2
22 line3
23512
24256
25128
2664
2732
2816
298
304
312
32v-$a-\t-\-\"-\x-`-\--\z-\*-\?-
33v-$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 @@
1cat <<<one
2cat <<<\_two
3cat <<<"\_three"
4cat <<<'\_four'
5cat <<<\\_two
6cat <<<"\\_three"
7cat <<<'\\_four'
8
9cat <<<$'two_newlines\n'
10
11cat <<</bin/c*
12
13cat <<<star_*
14cat <<<star_\*
15cat <<<"star_*"
16cat <<<"star_\*"
17cat <<<'star_*'
18cat <<<'star_\*'
19
20var=$'line1
21line2
22 line3'
23
24cat <<<$var
25
26cat <<<"$var"
27
28i=10
29until test $((--i)) = 0; do
30 cat <<<$((2**i))
31done
32
33a=qwerty
34cat <<<`echo v'-$a-\t-\\-\"-\x-\`-\--\z-\*-\?-'`
35cat <<<"`echo v'-$a-\t-\\-\"-\x-\`-\--\z-\*-\?-'`"