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 | |
| parent | b4cedd4c9ae0ea31986973b7b3e6956937aafa32 (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.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 = { #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-\*-\?-'`" |
