1*11751Ssam /* expand.c 4.2 83/03/28 */ 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 70*11751Ssam 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 826691Smckusick WHILE (dp = readdir(dirf)) != NULL ANDF (trapnote&SIGSET) == 0 836691Smckusick DO IF (*dp->d_name=='.' ANDF *cs!='.') 846691Smckusick THEN continue; 856691Smckusick FI 866691Smckusick IF gmatch(dp->d_name, cs) 876691Smckusick THEN addg(s,dp->d_name,rescan); count++; 886691Smckusick FI 896691Smckusick OD 906691Smckusick closedir(dirf); 916691Smckusick 926691Smckusick IF rescan 936691Smckusick THEN REG ARGPTR rchain; 946691Smckusick rchain=gchain; gchain=schain; 956691Smckusick IF count 966691Smckusick THEN count=0; 976691Smckusick WHILE rchain 986691Smckusick DO count += expand(rchain->argval,1); 996691Smckusick rchain=rchain->argnxt; 1006691Smckusick OD 1016691Smckusick FI 1026691Smckusick *rescan='/'; 1036691Smckusick FI 1046691Smckusick FI 1056691Smckusick 1066691Smckusick BEGIN 1076691Smckusick REG CHAR c; 1086691Smckusick s=as; 1096691Smckusick WHILE c = *s 1106691Smckusick DO *s++=(c&STRIP?c:'/') OD 1116691Smckusick END 1126691Smckusick return(count); 1136691Smckusick } 1146691Smckusick 1156691Smckusick gmatch(s, p) 1166691Smckusick REG STRING s, p; 1176691Smckusick { 1186691Smckusick REG INT scc; 1196691Smckusick CHAR c; 1206691Smckusick 1216691Smckusick IF scc = *s++ 1226691Smckusick THEN IF (scc &= STRIP)==0 1236691Smckusick THEN scc=0200; 1246691Smckusick FI 1256691Smckusick FI 1266691Smckusick SWITCH c = *p++ IN 1276691Smckusick 1286691Smckusick case '[': 1296691Smckusick {BOOL ok; INT lc; 1306691Smckusick ok=0; lc=077777; 1316691Smckusick WHILE c = *p++ 1326691Smckusick DO IF c==']' 1336691Smckusick THEN return(ok?gmatch(s,p):0); 1346691Smckusick ELIF c==MINUS 1356691Smckusick THEN IF lc<=scc ANDF scc<=(*p++) THEN ok++ FI 1366691Smckusick ELSE IF scc==(lc=(c&STRIP)) THEN ok++ FI 1376691Smckusick FI 1386691Smckusick OD 1396691Smckusick return(0); 1406691Smckusick } 1416691Smckusick 1426691Smckusick default: 1436691Smckusick IF (c&STRIP)!=scc THEN return(0) FI 1446691Smckusick 1456691Smckusick case '?': 1466691Smckusick return(scc?gmatch(s,p):0); 1476691Smckusick 1486691Smckusick case '*': 1496691Smckusick IF *p==0 THEN return(1) FI 1506691Smckusick --s; 1516691Smckusick WHILE *s 1526691Smckusick DO IF gmatch(s++,p) THEN return(1) FI OD 1536691Smckusick return(0); 1546691Smckusick 1556691Smckusick case 0: 1566691Smckusick return(scc==0); 1576691Smckusick ENDSW 1586691Smckusick } 1596691Smckusick 1606691Smckusick LOCAL VOID addg(as1,as2,as3) 1616691Smckusick STRING as1, as2, as3; 1626691Smckusick { 1636691Smckusick REG STRING s1, s2; 1646691Smckusick REG INT c; 1656691Smckusick 1666691Smckusick s2 = locstak()+BYTESPERWORD; 1676691Smckusick 1686691Smckusick s1=as1; 1696691Smckusick WHILE c = *s1++ 1706691Smckusick DO IF (c &= STRIP)==0 1716691Smckusick THEN *s2++='/'; 1726691Smckusick break; 1736691Smckusick FI 1746691Smckusick *s2++=c; 1756691Smckusick OD 1766691Smckusick s1=as2; 1776691Smckusick WHILE *s2 = *s1++ DO s2++ OD 1786691Smckusick IF s1=as3 1796691Smckusick THEN *s2++='/'; 1806691Smckusick WHILE *s2++ = *++s1 DONE 1816691Smckusick FI 1826691Smckusick makearg(endstak(s2)); 1836691Smckusick } 1846691Smckusick 1856691Smckusick makearg(args) 1866691Smckusick REG STRING args; 1876691Smckusick { 1886691Smckusick args->argnxt=gchain; 1896691Smckusick gchain=args; 1906691Smckusick } 1916691Smckusick 192