ref: 755880b19f365c3f98eac5c7de1d8b25f773ace3
parent: c5c79d61e67f2c74a8d57eb1aeea87a23eeadd87
author: cinap_lenrek <[email protected]>
date: Wed Feb 16 13:07:21 EST 2022
rc: fix globbing with lists (thanks qwx) Pattern matching with lists no longer works: ; ls /tmp/*.c /tmp/npage.c /tmp/pagedebug.c /tmp/pageold.c /tmp/scheduler.c /tmp/writeimagetest.c ; ls /tmp/^(*.c) ls: /tmp/*.c: '/tmp/*.c' directory entry not found ; 9fs dump ; bind /n/dump/2021/1002/amd64/bin/rc /bin/rc ; rc ; ls /tmp/^(*.c) /tmp/npage.c /tmp/pagedebug.c /tmp/pageold.c /tmp/scheduler.c /tmp/writeimagetest.c the fix: we have to propagate the glob attribute thru lists as well. before it was only handled for single words and propagated thru concatenations... the Xglob instruction now works on list, and we propagate the glob attribute thru PAREN and WORDS and ARGLIST nodes. also, avoid using negative numbers for the Tree.glob field as char might be unsigned on some targets.
--- a/sys/src/cmd/rc/code.c
+++ b/sys/src/cmd/rc/code.c
@@ -58,8 +58,8 @@
* called on a tree where we expect eigther
* a pattern or a string instead of a glob to
* remove the GLOB chars from the strings
- * or set glob to -1 for pattern so not Xglob
- * is inserted when compiling the tree.
+ * or set glob to 2 for pattern so Xglob
+ * is not inserted when compiling the tree.
*/
void
noglobs(tree *t, int pattern)
@@ -69,13 +69,13 @@
return;
if(t->type==WORD && t->glob){
if(pattern)
- t->glob=-1;
+ t->glob=2;
else{
deglob(t->str);
t->glob=0;
}
}
- if(t->type==WORDS || t->type=='^'){
+ if(t->type==PAREN || t->type==WORDS || t->type=='^'){
t->glob=0;
noglobs(c1, pattern);
t = c0;
@@ -425,7 +425,7 @@
emitf(Xpipewait);
break;
}
- if(t->glob > 0)
+ if(t->glob==1)
emitf(Xglob);
if(t->type!=NOT && t->type!=';')
lex->iflast = t->type==IF;
--- a/sys/src/cmd/rc/exec.c
+++ b/sys/src/cmd/rc/exec.c
@@ -305,7 +305,7 @@
* Xfalse{...} execute {} if false
* Xfn(name){... Xreturn} define function
* Xfor(var, list){... Xreturn} for loop
- * Xglob(word) glob word inplace
+ * Xglob(list) glob a list of words inplace
* Xjump[addr] goto
* Xlocal(name, val) create local variable, assign value
* Xmark mark stack
@@ -1152,7 +1152,12 @@
void
Xglob(void)
{
- globword(runq->argv->words);
+ word *a, *x;
+
+ for(a = runq->argv->words; a; a = x){
+ x = a->next;
+ globword(a);
+ }
}
void
--- a/sys/src/cmd/rc/rc.h
+++ b/sys/src/cmd/rc/rc.h
@@ -43,7 +43,7 @@
int type;
int rtype, fd0, fd1; /* details of REDIR PIPE DUP tokens */
int line;
- char glob; /* 0=string, 1=glob, -1=pattern see globprop() and noglobs() */
+ char glob; /* 0=string, 1=glob, 2=pattern see globprop() and noglobs() */
char quoted;
char iskw;
char *str;
--- a/sys/src/cmd/rc/syn.y
+++ b/sys/src/cmd/rc/syn.y
@@ -71,8 +71,8 @@
| FN words brace {$$=tree2(FN, $2, $3);}
| FN words {$$=tree1(FN, $2);}
simple: first
-| simple word {$$=tree2(ARGLIST, $1, $2);}
-| simple redir {$$=tree2(ARGLIST, $1, $2);}
+| simple word {$$=globprop(tree2(ARGLIST, $1, $2));}
+| simple redir {$$=globprop(tree2(ARGLIST, $1, $2));}
first: comword
| first '^' word {$$=globprop(tree2('^', $1, $3));}
word: keyword {lex->lastword=1; $1->type=WORD;}
@@ -85,7 +85,7 @@
| WORD
| '`' brace {$$=tree2('`', (tree*)0, $2);}
| '`' word brace {$$=tree2('`', $2, $3);}
-| '(' words ')' {$$=tree1(PAREN, $2);}
+| '(' words ')' {$$=globprop(tree1(PAREN, $2));}
| REDIR brace {$$=mung1($1, $2); $$->type=PIPEFD;}
keyword: FOR|IN|WHILE|IF|NOT|TWIDDLE|BANG|SUBSHELL|SWITCH|FN
words: {$$=(tree*)0;}
--- a/sys/src/cmd/rc/tree.c
+++ b/sys/src/cmd/rc/tree.c
@@ -158,12 +158,22 @@
{
tree *c0 = t->child[0];
tree *c1 = t->child[1];
- if(t->glob==0){
- if(c0->glob || c1->glob){
- if(c0->glob)
- c0->glob=-1;
- if(c1->glob)
- c1->glob=-1;
+ if(c1==0){
+ while(c0 && c0->type==WORDS){
+ c1 = c0->child[1];
+ if(c1 && c1->glob){
+ c1->glob=2;
+ t->glob=1;
+ }
+ c0 = c0->child[0];
+ }
+ } else {
+ if(c0->glob){
+ c0->glob=2;
+ t->glob=1;
+ }
+ if(c1->glob){
+ c1->glob=2;
t->glob=1;
}
}