xref: /original-bsd/old/sh/expand.c (revision b017b91b)
180753333Ssam #ifndef lint
2*b017b91bSbostic static char sccsid[] = "@(#)expand.c	4.6 09/22/88";
380753333Ssam #endif
45057c271Smckusick 
55057c271Smckusick #
65057c271Smckusick /*
75057c271Smckusick  *	UNIX shell
85057c271Smckusick  *
95057c271Smckusick  *	S. R. Bourne
105057c271Smckusick  *	Bell Telephone Laboratories
115057c271Smckusick  *
125057c271Smckusick  */
135057c271Smckusick 
145057c271Smckusick #include	"defs.h"
155057c271Smckusick #include	<sys/param.h>
165057c271Smckusick #include	<sys/stat.h>
17f85d2790Ssam #include	<sys/dir.h>
185057c271Smckusick 
195057c271Smckusick 
205057c271Smckusick 
215057c271Smckusick /* globals (file name generation)
225057c271Smckusick  *
235057c271Smckusick  * "*" in params matches r.e ".*"
245057c271Smckusick  * "?" in params matches r.e. "."
255057c271Smckusick  * "[...]" in params matches character class
265057c271Smckusick  * "[...a-z...]" in params matches a through z.
275057c271Smckusick  *
285057c271Smckusick  */
295057c271Smckusick 
305057c271Smckusick PROC VOID	addg();
315057c271Smckusick 
325057c271Smckusick 
expand(as,rflg)335057c271Smckusick INT	expand(as,rflg)
345057c271Smckusick 	STRING		as;
355057c271Smckusick {
365057c271Smckusick 	INT		count;
375057c271Smckusick 	DIR		*dirf;
385057c271Smckusick 	BOOL		dir=0;
395057c271Smckusick 	STRING		rescan = 0;
405057c271Smckusick 	REG STRING	s, cs;
415057c271Smckusick 	ARGPTR		schain = gchain;
425057c271Smckusick 	struct direct	*dp;
435057c271Smckusick 	STATBUF		statb;
445057c271Smckusick 
455057c271Smckusick 	IF trapnote&SIGSET THEN return(0); FI
465057c271Smckusick 
475057c271Smckusick 	s=cs=as;
485057c271Smckusick 
495057c271Smckusick 	/* check for meta chars */
505057c271Smckusick 	BEGIN
515057c271Smckusick 	   REG BOOL slash; slash=0;
525057c271Smckusick 	   WHILE !fngchar(*cs)
535057c271Smckusick 	   DO	IF *cs++==0
545057c271Smckusick 		THEN	IF rflg ANDF slash THEN break; ELSE return(0) FI
555057c271Smckusick 		ELIF *cs=='/'
565057c271Smckusick 		THEN	slash++;
575057c271Smckusick 		FI
585057c271Smckusick 	   OD
595057c271Smckusick 	END
605057c271Smckusick 
615057c271Smckusick 	LOOP	IF cs==s
625057c271Smckusick 		THEN	s=nullstr;
635057c271Smckusick 			break;
645057c271Smckusick 		ELIF *--cs == '/'
655057c271Smckusick 		THEN	*cs=0;
665057c271Smckusick 			IF s==cs THEN s="/" FI
675057c271Smckusick 			break;
685057c271Smckusick 		FI
695057c271Smckusick 	POOL
705057c271Smckusick 	IF stat(s,&statb)>=0
715057c271Smckusick 	    ANDF (statb.st_mode&S_IFMT)==S_IFDIR
727cd8b56eSsam 	    ANDF (dirf=opendir(s)) != NULL
735057c271Smckusick 	THEN	dir++;
745057c271Smckusick 	FI
755057c271Smckusick 	count=0;
765057c271Smckusick 	IF *cs==0 THEN *cs++=0200 FI
775057c271Smckusick 	IF dir
785057c271Smckusick 	THEN	/* check for rescan */
795057c271Smckusick 		REG STRING rs; rs=cs;
805057c271Smckusick 
815057c271Smckusick 		REP	IF *rs=='/' THEN rescan=rs; *rs=0; gchain=0 FI
825057c271Smckusick 		PER	*rs++ DONE
835057c271Smckusick 
844b5c1b9fSsam 		IF setjmp(INTbuf) == 0 THEN trapjmp[INTR] = 1; FI
854b5c1b9fSsam 		WHILE (trapnote&SIGSET) == 0 ANDF (dp = readdir(dirf)) != NULL
865057c271Smckusick 		DO	IF (*dp->d_name=='.' ANDF *cs!='.')
875057c271Smckusick 			THEN	continue;
885057c271Smckusick 			FI
895057c271Smckusick 			IF gmatch(dp->d_name, cs)
905057c271Smckusick 			THEN	addg(s,dp->d_name,rescan); count++;
915057c271Smckusick 			FI
925057c271Smckusick 		OD
934b5c1b9fSsam 		closedir(dirf); trapjmp[INTR] = 0;
945057c271Smckusick 
955057c271Smckusick 		IF rescan
965057c271Smckusick 		THEN	REG ARGPTR	rchain;
975057c271Smckusick 			rchain=gchain; gchain=schain;
985057c271Smckusick 			IF count
995057c271Smckusick 			THEN	count=0;
1005057c271Smckusick 				WHILE rchain
1015057c271Smckusick 				DO	count += expand(rchain->argval,1);
1025057c271Smckusick 					rchain=rchain->argnxt;
1035057c271Smckusick 				OD
1045057c271Smckusick 			FI
1055057c271Smckusick 			*rescan='/';
1065057c271Smckusick 		FI
1075057c271Smckusick 	FI
1085057c271Smckusick 
1095057c271Smckusick 	BEGIN
1105057c271Smckusick 	   REG CHAR	c;
1115057c271Smckusick 	   s=as;
1125057c271Smckusick 	   WHILE c = *s
1135057c271Smckusick 	   DO	*s++=(c&STRIP?c:'/') OD
1145057c271Smckusick 	END
1155057c271Smckusick 	return(count);
1165057c271Smckusick }
1175057c271Smckusick 
gmatch(s,p)1185057c271Smckusick gmatch(s, p)
1195057c271Smckusick 	REG STRING	s, p;
1205057c271Smckusick {
1215057c271Smckusick 	REG INT		scc;
1225057c271Smckusick 	CHAR		c;
1235057c271Smckusick 
1245057c271Smckusick 	IF scc = *s++
1255057c271Smckusick 	THEN	IF (scc &= STRIP)==0
1265057c271Smckusick 		THEN	scc=0200;
1275057c271Smckusick 		FI
1285057c271Smckusick 	FI
1295057c271Smckusick 	SWITCH c = *p++ IN
1305057c271Smckusick 
1315057c271Smckusick 	    case '[':
1325057c271Smckusick 		{BOOL ok; INT lc;
1335057c271Smckusick 		ok=0; lc=077777;
1345057c271Smckusick 		WHILE c = *p++
1355057c271Smckusick 		DO	IF c==']'
1365057c271Smckusick 			THEN	return(ok?gmatch(s,p):0);
1375057c271Smckusick 			ELIF c==MINUS
1385057c271Smckusick 			THEN	IF lc<=scc ANDF scc<=(*p++) THEN ok++ FI
1395057c271Smckusick 			ELSE	IF scc==(lc=(c&STRIP)) THEN ok++ FI
1405057c271Smckusick 			FI
1415057c271Smckusick 		OD
1425057c271Smckusick 		return(0);
1435057c271Smckusick 		}
1445057c271Smckusick 
1455057c271Smckusick 	    default:
1465057c271Smckusick 		IF (c&STRIP)!=scc THEN return(0) FI
1475057c271Smckusick 
1485057c271Smckusick 	    case '?':
1495057c271Smckusick 		return(scc?gmatch(s,p):0);
1505057c271Smckusick 
1515057c271Smckusick 	    case '*':
1525057c271Smckusick 		IF *p==0 THEN return(1) FI
1535057c271Smckusick 		--s;
1545057c271Smckusick 		WHILE *s
1555057c271Smckusick 		DO  IF gmatch(s++,p) THEN return(1) FI OD
1565057c271Smckusick 		return(0);
1575057c271Smckusick 
1585057c271Smckusick 	    case 0:
1595057c271Smckusick 		return(scc==0);
1605057c271Smckusick 	ENDSW
1615057c271Smckusick }
1625057c271Smckusick 
addg(as1,as2,as3)1635057c271Smckusick LOCAL VOID	addg(as1,as2,as3)
1645057c271Smckusick 	STRING		as1, as2, as3;
1655057c271Smckusick {
1665057c271Smckusick 	REG STRING	s1, s2;
1675057c271Smckusick 	REG INT		c;
1685057c271Smckusick 
1695057c271Smckusick 	s2 = locstak()+BYTESPERWORD;
1705057c271Smckusick 
1715057c271Smckusick 	s1=as1;
1725057c271Smckusick 	WHILE c = *s1++
1735057c271Smckusick 	DO	IF (c &= STRIP)==0
1745057c271Smckusick 		THEN	*s2++='/';
1755057c271Smckusick 			break;
1765057c271Smckusick 		FI
1775057c271Smckusick 		*s2++=c;
1785057c271Smckusick 	OD
1795057c271Smckusick 	s1=as2;
1805057c271Smckusick 	WHILE *s2 = *s1++ DO s2++ OD
1815057c271Smckusick 	IF s1=as3
1825057c271Smckusick 	THEN	*s2++='/';
1835057c271Smckusick 		WHILE *s2++ = *++s1 DONE
1845057c271Smckusick 	FI
185*b017b91bSbostic 	makearg((ARGPTR)endstak(s2));
1865057c271Smckusick }
1875057c271Smckusick 
makearg(args)1885057c271Smckusick makearg(args)
189*b017b91bSbostic 	REG ARGPTR	args;
1905057c271Smckusick {
1915057c271Smckusick 	args->argnxt=gchain;
1925057c271Smckusick 	gchain=args;
1935057c271Smckusick }
1945057c271Smckusick 
195