diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2025-09-02 11:46:11 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2025-09-02 11:46:11 +0200 |
| commit | 106546961db9b30ca44894a3a09fa3113ed85e46 (patch) | |
| tree | e829c69532b2879ff22b4e024b083bc5d8dbbcd9 /shell | |
| parent | b4cedd4c9ae0ea31986973b7b3e6956937aafa32 (diff) | |
| download | busybox-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.c | 87 | ||||
| -rw-r--r-- | shell/ash_test/ash-heredoc/herestring1.right | 33 | ||||
| -rwxr-xr-x | shell/ash_test/ash-heredoc/herestring1.tests | 35 |
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 | ||
| 962 | union node; | 963 | union 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 */ | ||
| 5637 | static void expandhere(union node *arg); | ||
| 5638 | static int | 5641 | static int |
| 5639 | openhere(union node *redir) | 5642 | write2pipe(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 */ | ||
| 5666 | static void expandhere(union node *arg); | ||
| 5667 | static int | ||
| 5668 | openhere(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 | |||
| 5685 | static int | ||
| 5686 | openherestr(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 | |||
| 5676 | static int | 5701 | static int |
| 5677 | openredirect(union node *redir) | 5702 | openredirect(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 @@ | |||
| 1 | one | ||
| 2 | _two | ||
| 3 | \_three | ||
| 4 | \_four | ||
| 5 | \_two | ||
| 6 | \_three | ||
| 7 | \\_four | ||
| 8 | two_newlines | ||
| 9 | |||
| 10 | /bin/c* | ||
| 11 | star_* | ||
| 12 | star_* | ||
| 13 | star_* | ||
| 14 | star_\* | ||
| 15 | star_* | ||
| 16 | star_\* | ||
| 17 | line1 | ||
| 18 | line2 | ||
| 19 | line3 | ||
| 20 | line1 | ||
| 21 | line2 | ||
| 22 | line3 | ||
| 23 | 512 | ||
| 24 | 256 | ||
| 25 | 128 | ||
| 26 | 64 | ||
| 27 | 32 | ||
| 28 | 16 | ||
| 29 | 8 | ||
| 30 | 4 | ||
| 31 | 2 | ||
| 32 | v-$a-\t-\-\"-\x-`-\--\z-\*-\?- | ||
| 33 | 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 @@ | |||
| 1 | cat <<<one | ||
| 2 | cat <<<\_two | ||
| 3 | cat <<<"\_three" | ||
| 4 | cat <<<'\_four' | ||
| 5 | cat <<<\\_two | ||
| 6 | cat <<<"\\_three" | ||
| 7 | cat <<<'\\_four' | ||
| 8 | |||
| 9 | cat <<<$'two_newlines\n' | ||
| 10 | |||
| 11 | cat <<</bin/c* | ||
| 12 | |||
| 13 | cat <<<star_* | ||
| 14 | cat <<<star_\* | ||
| 15 | cat <<<"star_*" | ||
| 16 | cat <<<"star_\*" | ||
| 17 | cat <<<'star_*' | ||
| 18 | cat <<<'star_\*' | ||
| 19 | |||
| 20 | var=$'line1 | ||
| 21 | line2 | ||
| 22 | line3' | ||
| 23 | |||
| 24 | cat <<<$var | ||
| 25 | |||
| 26 | cat <<<"$var" | ||
| 27 | |||
| 28 | i=10 | ||
| 29 | until test $((--i)) = 0; do | ||
| 30 | cat <<<$((2**i)) | ||
| 31 | done | ||
| 32 | |||
| 33 | a=qwerty | ||
| 34 | cat <<<`echo v'-$a-\t-\\-\"-\x-\`-\--\z-\*-\?-'` | ||
| 35 | cat <<<"`echo v'-$a-\t-\\-\"-\x-\`-\--\z-\*-\?-'`" | ||
