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.
This commit is contained in:
cinap_lenrek 2022-02-16 18:07:21 +00:00
parent c5c79d61e6
commit 755880b19f
5 changed files with 32 additions and 17 deletions

View file

@ -58,8 +58,8 @@ compile(tree *t)
* called on a tree where we expect eigther * called on a tree where we expect eigther
* a pattern or a string instead of a glob to * a pattern or a string instead of a glob to
* remove the GLOB chars from the strings * remove the GLOB chars from the strings
* or set glob to -1 for pattern so not Xglob * or set glob to 2 for pattern so Xglob
* is inserted when compiling the tree. * is not inserted when compiling the tree.
*/ */
void void
noglobs(tree *t, int pattern) noglobs(tree *t, int pattern)
@ -69,13 +69,13 @@ Again:
return; return;
if(t->type==WORD && t->glob){ if(t->type==WORD && t->glob){
if(pattern) if(pattern)
t->glob=-1; t->glob=2;
else{ else{
deglob(t->str); deglob(t->str);
t->glob=0; t->glob=0;
} }
} }
if(t->type==WORDS || t->type=='^'){ if(t->type==PAREN || t->type==WORDS || t->type=='^'){
t->glob=0; t->glob=0;
noglobs(c1, pattern); noglobs(c1, pattern);
t = c0; t = c0;
@ -425,7 +425,7 @@ outcode(tree *t, int eflag)
emitf(Xpipewait); emitf(Xpipewait);
break; break;
} }
if(t->glob > 0) if(t->glob==1)
emitf(Xglob); emitf(Xglob);
if(t->type!=NOT && t->type!=';') if(t->type!=NOT && t->type!=';')
lex->iflast = t->type==IF; lex->iflast = t->type==IF;

View file

@ -305,7 +305,7 @@ main(int argc, char *argv[])
* Xfalse{...} execute {} if false * Xfalse{...} execute {} if false
* Xfn(name){... Xreturn} define function * Xfn(name){... Xreturn} define function
* Xfor(var, list){... Xreturn} for loop * Xfor(var, list){... Xreturn} for loop
* Xglob(word) glob word inplace * Xglob(list) glob a list of words inplace
* Xjump[addr] goto * Xjump[addr] goto
* Xlocal(name, val) create local variable, assign value * Xlocal(name, val) create local variable, assign value
* Xmark mark stack * Xmark mark stack
@ -1152,7 +1152,12 @@ Xfor(void)
void void
Xglob(void) Xglob(void)
{ {
globword(runq->argv->words); word *a, *x;
for(a = runq->argv->words; a; a = x){
x = a->next;
globword(a);
}
} }
void void

View file

@ -43,7 +43,7 @@ struct tree{
int type; int type;
int rtype, fd0, fd1; /* details of REDIR PIPE DUP tokens */ int rtype, fd0, fd1; /* details of REDIR PIPE DUP tokens */
int line; 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 quoted;
char iskw; char iskw;
char *str; char *str;

View file

@ -71,8 +71,8 @@ cmd: {$$=0;}
| FN words brace {$$=tree2(FN, $2, $3);} | FN words brace {$$=tree2(FN, $2, $3);}
| FN words {$$=tree1(FN, $2);} | FN words {$$=tree1(FN, $2);}
simple: first simple: first
| simple word {$$=tree2(ARGLIST, $1, $2);} | simple word {$$=globprop(tree2(ARGLIST, $1, $2));}
| simple redir {$$=tree2(ARGLIST, $1, $2);} | simple redir {$$=globprop(tree2(ARGLIST, $1, $2));}
first: comword first: comword
| first '^' word {$$=globprop(tree2('^', $1, $3));} | first '^' word {$$=globprop(tree2('^', $1, $3));}
word: keyword {lex->lastword=1; $1->type=WORD;} word: keyword {lex->lastword=1; $1->type=WORD;}
@ -85,7 +85,7 @@ comword: '$' word {$$=tree1('$', $2);}
| WORD | WORD
| '`' brace {$$=tree2('`', (tree*)0, $2);} | '`' brace {$$=tree2('`', (tree*)0, $2);}
| '`' word brace {$$=tree2('`', $2, $3);} | '`' word brace {$$=tree2('`', $2, $3);}
| '(' words ')' {$$=tree1(PAREN, $2);} | '(' words ')' {$$=globprop(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
words: {$$=(tree*)0;} words: {$$=(tree*)0;}

View file

@ -158,12 +158,22 @@ globprop(tree *t)
{ {
tree *c0 = t->child[0]; tree *c0 = t->child[0];
tree *c1 = t->child[1]; tree *c1 = t->child[1];
if(t->glob==0){ if(c1==0){
if(c0->glob || c1->glob){ while(c0 && c0->type==WORDS){
if(c0->glob) c1 = c0->child[1];
c0->glob=-1; if(c1 && c1->glob){
if(c1->glob) c1->glob=2;
c1->glob=-1; 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; t->glob=1;
} }
} }