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