shithub: rc

Download patch

ref: 024840612b2fca4f1d5251d002b43ed642230a26
parent: 9a50c1d21b9336ec5f7b4f2703d7c432479d1302
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Wed Feb 16 13:08:55 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/code.c	Mon Jan 10 12:42:57 2022
+++ b/code.c	Wed Feb 16 13:08:55 2022
@@ -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/exec.c	Mon Jan 10 12:42:57 2022
+++ b/exec.c	Wed Feb 16 13:08:55 2022
@@ -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/rc.h	Mon Jan 10 12:42:57 2022
+++ b/rc.h	Wed Feb 16 13:08:55 2022
@@ -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/syn.y	Mon Jan 10 12:42:57 2022
+++ b/syn.y	Wed Feb 16 13:08:55 2022
@@ -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/tree.c	Mon Jan 10 12:42:57 2022
+++ b/tree.c	Wed Feb 16 13:08:55 2022
@@ -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;
 		}
 	}