xref: /csrg-svn/old/sh/expand.c (revision 6691)
1*6691Smckusick /*	expand.c	4.1	82/05/07	*/
2*6691Smckusick 
3*6691Smckusick #
4*6691Smckusick /*
5*6691Smckusick  *	UNIX shell
6*6691Smckusick  *
7*6691Smckusick  *	S. R. Bourne
8*6691Smckusick  *	Bell Telephone Laboratories
9*6691Smckusick  *
10*6691Smckusick  */
11*6691Smckusick 
12*6691Smckusick #include	"defs.h"
13*6691Smckusick #include	<sys/param.h>
14*6691Smckusick #include	<sys/stat.h>
15*6691Smckusick #include	<dir.h>
16*6691Smckusick 
17*6691Smckusick 
18*6691Smckusick 
19*6691Smckusick /* globals (file name generation)
20*6691Smckusick  *
21*6691Smckusick  * "*" in params matches r.e ".*"
22*6691Smckusick  * "?" in params matches r.e. "."
23*6691Smckusick  * "[...]" in params matches character class
24*6691Smckusick  * "[...a-z...]" in params matches a through z.
25*6691Smckusick  *
26*6691Smckusick  */
27*6691Smckusick 
28*6691Smckusick PROC VOID	addg();
29*6691Smckusick 
30*6691Smckusick 
31*6691Smckusick INT	expand(as,rflg)
32*6691Smckusick 	STRING		as;
33*6691Smckusick {
34*6691Smckusick 	INT		count;
35*6691Smckusick 	DIR		*dirf;
36*6691Smckusick 	BOOL		dir=0;
37*6691Smckusick 	STRING		rescan = 0;
38*6691Smckusick 	REG STRING	s, cs;
39*6691Smckusick 	ARGPTR		schain = gchain;
40*6691Smckusick 	struct direct	*dp;
41*6691Smckusick 	STATBUF		statb;
42*6691Smckusick 
43*6691Smckusick 	IF trapnote&SIGSET THEN return(0); FI
44*6691Smckusick 
45*6691Smckusick 	s=cs=as;
46*6691Smckusick 
47*6691Smckusick 	/* check for meta chars */
48*6691Smckusick 	BEGIN
49*6691Smckusick 	   REG BOOL slash; slash=0;
50*6691Smckusick 	   WHILE !fngchar(*cs)
51*6691Smckusick 	   DO	IF *cs++==0
52*6691Smckusick 		THEN	IF rflg ANDF slash THEN break; ELSE return(0) FI
53*6691Smckusick 		ELIF *cs=='/'
54*6691Smckusick 		THEN	slash++;
55*6691Smckusick 		FI
56*6691Smckusick 	   OD
57*6691Smckusick 	END
58*6691Smckusick 
59*6691Smckusick 	LOOP	IF cs==s
60*6691Smckusick 		THEN	s=nullstr;
61*6691Smckusick 			break;
62*6691Smckusick 		ELIF *--cs == '/'
63*6691Smckusick 		THEN	*cs=0;
64*6691Smckusick 			IF s==cs THEN s="/" FI
65*6691Smckusick 			break;
66*6691Smckusick 		FI
67*6691Smckusick 	POOL
68*6691Smckusick 	IF stat(s,&statb)>=0
69*6691Smckusick 	    ANDF (statb.st_mode&S_IFMT)==S_IFDIR
70*6691Smckusick 	    ANDF (dirf=opendir(s))>0
71*6691Smckusick 	THEN	dir++;
72*6691Smckusick 	FI
73*6691Smckusick 	count=0;
74*6691Smckusick 	IF *cs==0 THEN *cs++=0200 FI
75*6691Smckusick 	IF dir
76*6691Smckusick 	THEN	/* check for rescan */
77*6691Smckusick 		REG STRING rs; rs=cs;
78*6691Smckusick 
79*6691Smckusick 		REP	IF *rs=='/' THEN rescan=rs; *rs=0; gchain=0 FI
80*6691Smckusick 		PER	*rs++ DONE
81*6691Smckusick 
82*6691Smckusick 		WHILE (dp = readdir(dirf)) != NULL ANDF (trapnote&SIGSET) == 0
83*6691Smckusick 		DO	IF (*dp->d_name=='.' ANDF *cs!='.')
84*6691Smckusick 			THEN	continue;
85*6691Smckusick 			FI
86*6691Smckusick 			IF gmatch(dp->d_name, cs)
87*6691Smckusick 			THEN	addg(s,dp->d_name,rescan); count++;
88*6691Smckusick 			FI
89*6691Smckusick 		OD
90*6691Smckusick 		closedir(dirf);
91*6691Smckusick 
92*6691Smckusick 		IF rescan
93*6691Smckusick 		THEN	REG ARGPTR	rchain;
94*6691Smckusick 			rchain=gchain; gchain=schain;
95*6691Smckusick 			IF count
96*6691Smckusick 			THEN	count=0;
97*6691Smckusick 				WHILE rchain
98*6691Smckusick 				DO	count += expand(rchain->argval,1);
99*6691Smckusick 					rchain=rchain->argnxt;
100*6691Smckusick 				OD
101*6691Smckusick 			FI
102*6691Smckusick 			*rescan='/';
103*6691Smckusick 		FI
104*6691Smckusick 	FI
105*6691Smckusick 
106*6691Smckusick 	BEGIN
107*6691Smckusick 	   REG CHAR	c;
108*6691Smckusick 	   s=as;
109*6691Smckusick 	   WHILE c = *s
110*6691Smckusick 	   DO	*s++=(c&STRIP?c:'/') OD
111*6691Smckusick 	END
112*6691Smckusick 	return(count);
113*6691Smckusick }
114*6691Smckusick 
115*6691Smckusick gmatch(s, p)
116*6691Smckusick 	REG STRING	s, p;
117*6691Smckusick {
118*6691Smckusick 	REG INT		scc;
119*6691Smckusick 	CHAR		c;
120*6691Smckusick 
121*6691Smckusick 	IF scc = *s++
122*6691Smckusick 	THEN	IF (scc &= STRIP)==0
123*6691Smckusick 		THEN	scc=0200;
124*6691Smckusick 		FI
125*6691Smckusick 	FI
126*6691Smckusick 	SWITCH c = *p++ IN
127*6691Smckusick 
128*6691Smckusick 	    case '[':
129*6691Smckusick 		{BOOL ok; INT lc;
130*6691Smckusick 		ok=0; lc=077777;
131*6691Smckusick 		WHILE c = *p++
132*6691Smckusick 		DO	IF c==']'
133*6691Smckusick 			THEN	return(ok?gmatch(s,p):0);
134*6691Smckusick 			ELIF c==MINUS
135*6691Smckusick 			THEN	IF lc<=scc ANDF scc<=(*p++) THEN ok++ FI
136*6691Smckusick 			ELSE	IF scc==(lc=(c&STRIP)) THEN ok++ FI
137*6691Smckusick 			FI
138*6691Smckusick 		OD
139*6691Smckusick 		return(0);
140*6691Smckusick 		}
141*6691Smckusick 
142*6691Smckusick 	    default:
143*6691Smckusick 		IF (c&STRIP)!=scc THEN return(0) FI
144*6691Smckusick 
145*6691Smckusick 	    case '?':
146*6691Smckusick 		return(scc?gmatch(s,p):0);
147*6691Smckusick 
148*6691Smckusick 	    case '*':
149*6691Smckusick 		IF *p==0 THEN return(1) FI
150*6691Smckusick 		--s;
151*6691Smckusick 		WHILE *s
152*6691Smckusick 		DO  IF gmatch(s++,p) THEN return(1) FI OD
153*6691Smckusick 		return(0);
154*6691Smckusick 
155*6691Smckusick 	    case 0:
156*6691Smckusick 		return(scc==0);
157*6691Smckusick 	ENDSW
158*6691Smckusick }
159*6691Smckusick 
160*6691Smckusick LOCAL VOID	addg(as1,as2,as3)
161*6691Smckusick 	STRING		as1, as2, as3;
162*6691Smckusick {
163*6691Smckusick 	REG STRING	s1, s2;
164*6691Smckusick 	REG INT		c;
165*6691Smckusick 
166*6691Smckusick 	s2 = locstak()+BYTESPERWORD;
167*6691Smckusick 
168*6691Smckusick 	s1=as1;
169*6691Smckusick 	WHILE c = *s1++
170*6691Smckusick 	DO	IF (c &= STRIP)==0
171*6691Smckusick 		THEN	*s2++='/';
172*6691Smckusick 			break;
173*6691Smckusick 		FI
174*6691Smckusick 		*s2++=c;
175*6691Smckusick 	OD
176*6691Smckusick 	s1=as2;
177*6691Smckusick 	WHILE *s2 = *s1++ DO s2++ OD
178*6691Smckusick 	IF s1=as3
179*6691Smckusick 	THEN	*s2++='/';
180*6691Smckusick 		WHILE *s2++ = *++s1 DONE
181*6691Smckusick 	FI
182*6691Smckusick 	makearg(endstak(s2));
183*6691Smckusick }
184*6691Smckusick 
185*6691Smckusick makearg(args)
186*6691Smckusick 	REG STRING	args;
187*6691Smckusick {
188*6691Smckusick 	args->argnxt=gchain;
189*6691Smckusick 	gchain=args;
190*6691Smckusick }
191*6691Smckusick 
192