src/cmd/rc: import rc syntax `delim{cmd} for splitting commands from 9atom

Co-authored-by: <ori@eigenstate.org>
This commit is contained in:
lufia
2025-07-21 13:36:21 +09:00
committed by Dan Cross
parent cc89d24235
commit 8ff39da062
7 changed files with 38 additions and 10 deletions

View File

@@ -228,6 +228,8 @@ The value is a single string containing the components of the named variable
separated by spaces. A variable with zero elements yields the empty string. separated by spaces. A variable with zero elements yields the empty string.
.HP .HP
.BI `{ command } .BI `{ command }
.HP
.BI ` "split " { command }
.br .br
.I rc .I rc
executes the executes the
@@ -240,6 +242,8 @@ If
.B $ifs .B $ifs
is not otherwise set, its value is is not otherwise set, its value is
.BR "'\ \et\en'" . .BR "'\ \et\en'" .
In the second form of the command, split is used instead of
.BR $ifs .
.HP .HP
.BI <{ command } .BI <{ command }
.HP .HP

View File

@@ -94,6 +94,8 @@ outcode(tree *t, int eflag)
{ {
int p, q; int p, q;
tree *tt; tree *tt;
char *ifs;
if(t==0) if(t==0)
return; return;
if(t->type!=NOT && t->type!=';') if(t->type!=NOT && t->type!=';')
@@ -141,14 +143,26 @@ outcode(tree *t, int eflag)
emitf(Xconc); emitf(Xconc);
break; break;
case '`': case '`':
emitf(Xmark);
if(c0){
outcode(c0, 0);
emitf(Xglob);
}else{
if((ifs = strdup("ifs")) == nil)
sysfatal("strdup: %r");
emitf(Xmark);
emitf(Xword);
emits(ifs);
emitf(Xdol);
}
emitf(Xbackq); emitf(Xbackq);
if(havefork){ if(havefork){
p = emiti(0); p = emiti(0);
outcode(c0, 0); outcode(c1, 0);
emitf(Xexit); emitf(Xexit);
stuffdot(p); stuffdot(p);
} else } else
emits(fnstr(c0)); emits(fnstr(c1));
break; break;
case ANDAND: case ANDAND:
outcode(c0, 0); outcode(c0, 0);

View File

@@ -218,7 +218,7 @@ main(int argc, char *argv[])
* Xappend(file)[fd] open file to append * Xappend(file)[fd] open file to append
* Xassign(name, val) assign val to name * Xassign(name, val) assign val to name
* Xasync{... Xexit} make thread for {}, no wait * Xasync{... Xexit} make thread for {}, no wait
* Xbackq{... Xreturn} make thread for {}, push stdout * Xbackq(split){... Xreturn} make thread for {}, push stdout
* Xbang complement condition * Xbang complement condition
* Xcase(pat, value){...} exec code on match, leave (value) on * Xcase(pat, value){...} exec code on match, leave (value) on
* stack * stack

View File

@@ -115,12 +115,14 @@ Xbackq(void)
int c, n; int c, n;
char *s, *ewd=&wd[8192], *stop, *q; char *s, *ewd=&wd[8192], *stop, *q;
struct io *f; struct io *f;
var *ifs = vlook("ifs");
word *v, *nextv; word *v, *nextv;
int pfd[2]; int pfd[2];
int pid; int pid;
Rune r; Rune r;
stop = ifs->val?ifs->val->word:"";
stop = "";
if(runq->argv && runq->argv->words)
stop = runq->argv->words->word;
if(pipe(pfd)<0){ if(pipe(pfd)<0){
Xerror("can't make pipe"); Xerror("can't make pipe");
return; return;
@@ -168,6 +170,7 @@ Xbackq(void)
} }
closeio(f); closeio(f);
Waitfor(pid, 0); Waitfor(pid, 0);
poplist(); /* ditch split in "stop" */
/* v points to reversed arglist -- reverse it onto argv */ /* v points to reversed arglist -- reverse it onto argv */
while(v){ while(v){
nextv = v->next; nextv = v->next;

View File

@@ -409,7 +409,8 @@ yyword(int tok, int *ptok, int eqok)
// | '"' word {$$=tree1('"', $2);} // | '"' word {$$=tree1('"', $2);}
// | COUNT word {$$=tree1(COUNT, $2);} // | COUNT word {$$=tree1(COUNT, $2);}
// | WORD // | WORD
// | '`' brace {$$=tree1('`', $2);} // | '`' brace {$$=tree2('`', (struct tree*)0, $2);}
// | '`' word brace {$$=tree2('`', $2, $3);}
// | '(' words ')' {$$=tree1(PAREN, $2);} // | '(' words ')' {$$=tree1(PAREN, $2);}
// | REDIR brace {$$=mung1($1, $2); $$->type=PIPEFD;} // | REDIR brace {$$=mung1($1, $2); $$->type=PIPEFD;}
// keyword: FOR|IN|WHILE|IF|NOT|TWIDDLE|BANG|SUBSHELL|SWITCH|FN // keyword: FOR|IN|WHILE|IF|NOT|TWIDDLE|BANG|SUBSHELL|SWITCH|FN
@@ -499,8 +500,13 @@ word1(int tok, int *ptok)
return tree1(COUNT, word1(yylex(), ptok)); return tree1(COUNT, word1(yylex(), ptok));
case '`': case '`':
// | '`' brace {$$=tree1('`', $2);} // | '`' brace {$$=tree2('`', (struct tree*)0, $2);}
t = tree1('`', brace(yylex())); // | '`' word brace {$$=tree2('`', $2, $3);}
w = nil;
tok = dropsp(yylex());
if(iswordtok(tok))
w = yyword(tok, &tok, 1);
t = tree2('`', w, brace(tok));
*ptok = yylex(); *ptok = yylex();
return t; return t;

View File

@@ -32,7 +32,7 @@ pcmd(io *f, tree *t)
break; break;
case '^': pfmt(f, "%t^%t", c0, c1); case '^': pfmt(f, "%t^%t", c0, c1);
break; break;
case '`': pfmt(f, "`%t", c0); case '`': pfmt(f, "`%t%t", c0, c1);
break; break;
case ANDAND: pfmt(f, "%t && %t", c0, c1); case ANDAND: pfmt(f, "%t && %t", c0, c1);
break; break;

View File

@@ -83,7 +83,8 @@ comword: '$' word {$$=tree1('$', $2);}
| '"' word {$$=tree1('"', $2);} | '"' word {$$=tree1('"', $2);}
| COUNT word {$$=tree1(COUNT, $2);} | COUNT word {$$=tree1(COUNT, $2);}
| WORD | WORD
| '`' brace {$$=tree1('`', $2);} | '`' brace {$$=tree2('`', (struct tree*)0, $2);}
| '`' word brace {$$=tree2('`', $2, $3);}
| '(' words ')' {$$=tree1(PAREN, $2);} | '(' words ')' {$$=tree1(PAREN, $2);}
| REDIRW brace {$$=mung1($1, $2); $$->type=PIPEFD;} | REDIRW brace {$$=mung1($1, $2); $$->type=PIPEFD;}
keyword: FOR|IN|WHILE|IF|NOT|TWIDDLE|BANG|SUBSHELL|SWITCH|FN keyword: FOR|IN|WHILE|IF|NOT|TWIDDLE|BANG|SUBSHELL|SWITCH|FN