1*80753333Ssam #ifndef lint 2*80753333Ssam static char sccsid[] = "@(#)expand.c 4.5 08/11/83"; 3*80753333Ssam #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 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 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 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 1855057c271Smckusick makearg(endstak(s2)); 1865057c271Smckusick } 1875057c271Smckusick 1885057c271Smckusick makearg(args) 1895057c271Smckusick REG STRING args; 1905057c271Smckusick { 1915057c271Smckusick args->argnxt=gchain; 1925057c271Smckusick gchain=args; 1935057c271Smckusick } 1945057c271Smckusick 195