1*12992Ssam /* expand.c 4.3 83/06/10 */ 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> 156691Smckusick #include <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 82*12992Ssam IF setjmp(INTbuf) == 0 THEN trapjmp[INTR] = 1; FI 83*12992Ssam 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 91*12992Ssam 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