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