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