xref: /csrg-svn/old/sh/expand.c (revision 35683)
114478Ssam #ifndef lint
2*35683Sbostic static char sccsid[] = "@(#)expand.c	4.6 09/22/88";
314478Ssam #endif
46691Smckusick 
56691Smckusick #
66691Smckusick /*
76691Smckusick  *	UNIX shell
86691Smckusick  *
96691Smckusick  *	S. R. Bourne
106691Smckusick  *	Bell Telephone Laboratories
116691Smckusick  *
126691Smckusick  */
136691Smckusick 
146691Smckusick #include	"defs.h"
156691Smckusick #include	<sys/param.h>
166691Smckusick #include	<sys/stat.h>
1713559Ssam #include	<sys/dir.h>
186691Smckusick 
196691Smckusick 
206691Smckusick 
216691Smckusick /* globals (file name generation)
226691Smckusick  *
236691Smckusick  * "*" in params matches r.e ".*"
246691Smckusick  * "?" in params matches r.e. "."
256691Smckusick  * "[...]" in params matches character class
266691Smckusick  * "[...a-z...]" in params matches a through z.
276691Smckusick  *
286691Smckusick  */
296691Smckusick 
306691Smckusick PROC VOID	addg();
316691Smckusick 
326691Smckusick 
expand(as,rflg)336691Smckusick INT	expand(as,rflg)
346691Smckusick 	STRING		as;
356691Smckusick {
366691Smckusick 	INT		count;
376691Smckusick 	DIR		*dirf;
386691Smckusick 	BOOL		dir=0;
396691Smckusick 	STRING		rescan = 0;
406691Smckusick 	REG STRING	s, cs;
416691Smckusick 	ARGPTR		schain = gchain;
426691Smckusick 	struct direct	*dp;
436691Smckusick 	STATBUF		statb;
446691Smckusick 
456691Smckusick 	IF trapnote&SIGSET THEN return(0); FI
466691Smckusick 
476691Smckusick 	s=cs=as;
486691Smckusick 
496691Smckusick 	/* check for meta chars */
506691Smckusick 	BEGIN
516691Smckusick 	   REG BOOL slash; slash=0;
526691Smckusick 	   WHILE !fngchar(*cs)
536691Smckusick 	   DO	IF *cs++==0
546691Smckusick 		THEN	IF rflg ANDF slash THEN break; ELSE return(0) FI
556691Smckusick 		ELIF *cs=='/'
566691Smckusick 		THEN	slash++;
576691Smckusick 		FI
586691Smckusick 	   OD
596691Smckusick 	END
606691Smckusick 
616691Smckusick 	LOOP	IF cs==s
626691Smckusick 		THEN	s=nullstr;
636691Smckusick 			break;
646691Smckusick 		ELIF *--cs == '/'
656691Smckusick 		THEN	*cs=0;
666691Smckusick 			IF s==cs THEN s="/" FI
676691Smckusick 			break;
686691Smckusick 		FI
696691Smckusick 	POOL
706691Smckusick 	IF stat(s,&statb)>=0
716691Smckusick 	    ANDF (statb.st_mode&S_IFMT)==S_IFDIR
7211751Ssam 	    ANDF (dirf=opendir(s)) != NULL
736691Smckusick 	THEN	dir++;
746691Smckusick 	FI
756691Smckusick 	count=0;
766691Smckusick 	IF *cs==0 THEN *cs++=0200 FI
776691Smckusick 	IF dir
786691Smckusick 	THEN	/* check for rescan */
796691Smckusick 		REG STRING rs; rs=cs;
806691Smckusick 
816691Smckusick 		REP	IF *rs=='/' THEN rescan=rs; *rs=0; gchain=0 FI
826691Smckusick 		PER	*rs++ DONE
836691Smckusick 
8412992Ssam 		IF setjmp(INTbuf) == 0 THEN trapjmp[INTR] = 1; FI
8512992Ssam 		WHILE (trapnote&SIGSET) == 0 ANDF (dp = readdir(dirf)) != NULL
866691Smckusick 		DO	IF (*dp->d_name=='.' ANDF *cs!='.')
876691Smckusick 			THEN	continue;
886691Smckusick 			FI
896691Smckusick 			IF gmatch(dp->d_name, cs)
906691Smckusick 			THEN	addg(s,dp->d_name,rescan); count++;
916691Smckusick 			FI
926691Smckusick 		OD
9312992Ssam 		closedir(dirf); trapjmp[INTR] = 0;
946691Smckusick 
956691Smckusick 		IF rescan
966691Smckusick 		THEN	REG ARGPTR	rchain;
976691Smckusick 			rchain=gchain; gchain=schain;
986691Smckusick 			IF count
996691Smckusick 			THEN	count=0;
1006691Smckusick 				WHILE rchain
1016691Smckusick 				DO	count += expand(rchain->argval,1);
1026691Smckusick 					rchain=rchain->argnxt;
1036691Smckusick 				OD
1046691Smckusick 			FI
1056691Smckusick 			*rescan='/';
1066691Smckusick 		FI
1076691Smckusick 	FI
1086691Smckusick 
1096691Smckusick 	BEGIN
1106691Smckusick 	   REG CHAR	c;
1116691Smckusick 	   s=as;
1126691Smckusick 	   WHILE c = *s
1136691Smckusick 	   DO	*s++=(c&STRIP?c:'/') OD
1146691Smckusick 	END
1156691Smckusick 	return(count);
1166691Smckusick }
1176691Smckusick 
gmatch(s,p)1186691Smckusick gmatch(s, p)
1196691Smckusick 	REG STRING	s, p;
1206691Smckusick {
1216691Smckusick 	REG INT		scc;
1226691Smckusick 	CHAR		c;
1236691Smckusick 
1246691Smckusick 	IF scc = *s++
1256691Smckusick 	THEN	IF (scc &= STRIP)==0
1266691Smckusick 		THEN	scc=0200;
1276691Smckusick 		FI
1286691Smckusick 	FI
1296691Smckusick 	SWITCH c = *p++ IN
1306691Smckusick 
1316691Smckusick 	    case '[':
1326691Smckusick 		{BOOL ok; INT lc;
1336691Smckusick 		ok=0; lc=077777;
1346691Smckusick 		WHILE c = *p++
1356691Smckusick 		DO	IF c==']'
1366691Smckusick 			THEN	return(ok?gmatch(s,p):0);
1376691Smckusick 			ELIF c==MINUS
1386691Smckusick 			THEN	IF lc<=scc ANDF scc<=(*p++) THEN ok++ FI
1396691Smckusick 			ELSE	IF scc==(lc=(c&STRIP)) THEN ok++ FI
1406691Smckusick 			FI
1416691Smckusick 		OD
1426691Smckusick 		return(0);
1436691Smckusick 		}
1446691Smckusick 
1456691Smckusick 	    default:
1466691Smckusick 		IF (c&STRIP)!=scc THEN return(0) FI
1476691Smckusick 
1486691Smckusick 	    case '?':
1496691Smckusick 		return(scc?gmatch(s,p):0);
1506691Smckusick 
1516691Smckusick 	    case '*':
1526691Smckusick 		IF *p==0 THEN return(1) FI
1536691Smckusick 		--s;
1546691Smckusick 		WHILE *s
1556691Smckusick 		DO  IF gmatch(s++,p) THEN return(1) FI OD
1566691Smckusick 		return(0);
1576691Smckusick 
1586691Smckusick 	    case 0:
1596691Smckusick 		return(scc==0);
1606691Smckusick 	ENDSW
1616691Smckusick }
1626691Smckusick 
addg(as1,as2,as3)1636691Smckusick LOCAL VOID	addg(as1,as2,as3)
1646691Smckusick 	STRING		as1, as2, as3;
1656691Smckusick {
1666691Smckusick 	REG STRING	s1, s2;
1676691Smckusick 	REG INT		c;
1686691Smckusick 
1696691Smckusick 	s2 = locstak()+BYTESPERWORD;
1706691Smckusick 
1716691Smckusick 	s1=as1;
1726691Smckusick 	WHILE c = *s1++
1736691Smckusick 	DO	IF (c &= STRIP)==0
1746691Smckusick 		THEN	*s2++='/';
1756691Smckusick 			break;
1766691Smckusick 		FI
1776691Smckusick 		*s2++=c;
1786691Smckusick 	OD
1796691Smckusick 	s1=as2;
1806691Smckusick 	WHILE *s2 = *s1++ DO s2++ OD
1816691Smckusick 	IF s1=as3
1826691Smckusick 	THEN	*s2++='/';
1836691Smckusick 		WHILE *s2++ = *++s1 DONE
1846691Smckusick 	FI
185*35683Sbostic 	makearg((ARGPTR)endstak(s2));
1866691Smckusick }
1876691Smckusick 
makearg(args)1886691Smckusick makearg(args)
189*35683Sbostic 	REG ARGPTR	args;
1906691Smckusick {
1916691Smckusick 	args->argnxt=gchain;
1926691Smckusick 	gchain=args;
1936691Smckusick }
1946691Smckusick 
195