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