1*6691Smckusick /* expand.c 4.1 82/05/07 */ 2*6691Smckusick 3*6691Smckusick # 4*6691Smckusick /* 5*6691Smckusick * UNIX shell 6*6691Smckusick * 7*6691Smckusick * S. R. Bourne 8*6691Smckusick * Bell Telephone Laboratories 9*6691Smckusick * 10*6691Smckusick */ 11*6691Smckusick 12*6691Smckusick #include "defs.h" 13*6691Smckusick #include <sys/param.h> 14*6691Smckusick #include <sys/stat.h> 15*6691Smckusick #include <dir.h> 16*6691Smckusick 17*6691Smckusick 18*6691Smckusick 19*6691Smckusick /* globals (file name generation) 20*6691Smckusick * 21*6691Smckusick * "*" in params matches r.e ".*" 22*6691Smckusick * "?" in params matches r.e. "." 23*6691Smckusick * "[...]" in params matches character class 24*6691Smckusick * "[...a-z...]" in params matches a through z. 25*6691Smckusick * 26*6691Smckusick */ 27*6691Smckusick 28*6691Smckusick PROC VOID addg(); 29*6691Smckusick 30*6691Smckusick 31*6691Smckusick INT expand(as,rflg) 32*6691Smckusick STRING as; 33*6691Smckusick { 34*6691Smckusick INT count; 35*6691Smckusick DIR *dirf; 36*6691Smckusick BOOL dir=0; 37*6691Smckusick STRING rescan = 0; 38*6691Smckusick REG STRING s, cs; 39*6691Smckusick ARGPTR schain = gchain; 40*6691Smckusick struct direct *dp; 41*6691Smckusick STATBUF statb; 42*6691Smckusick 43*6691Smckusick IF trapnote&SIGSET THEN return(0); FI 44*6691Smckusick 45*6691Smckusick s=cs=as; 46*6691Smckusick 47*6691Smckusick /* check for meta chars */ 48*6691Smckusick BEGIN 49*6691Smckusick REG BOOL slash; slash=0; 50*6691Smckusick WHILE !fngchar(*cs) 51*6691Smckusick DO IF *cs++==0 52*6691Smckusick THEN IF rflg ANDF slash THEN break; ELSE return(0) FI 53*6691Smckusick ELIF *cs=='/' 54*6691Smckusick THEN slash++; 55*6691Smckusick FI 56*6691Smckusick OD 57*6691Smckusick END 58*6691Smckusick 59*6691Smckusick LOOP IF cs==s 60*6691Smckusick THEN s=nullstr; 61*6691Smckusick break; 62*6691Smckusick ELIF *--cs == '/' 63*6691Smckusick THEN *cs=0; 64*6691Smckusick IF s==cs THEN s="/" FI 65*6691Smckusick break; 66*6691Smckusick FI 67*6691Smckusick POOL 68*6691Smckusick IF stat(s,&statb)>=0 69*6691Smckusick ANDF (statb.st_mode&S_IFMT)==S_IFDIR 70*6691Smckusick ANDF (dirf=opendir(s))>0 71*6691Smckusick THEN dir++; 72*6691Smckusick FI 73*6691Smckusick count=0; 74*6691Smckusick IF *cs==0 THEN *cs++=0200 FI 75*6691Smckusick IF dir 76*6691Smckusick THEN /* check for rescan */ 77*6691Smckusick REG STRING rs; rs=cs; 78*6691Smckusick 79*6691Smckusick REP IF *rs=='/' THEN rescan=rs; *rs=0; gchain=0 FI 80*6691Smckusick PER *rs++ DONE 81*6691Smckusick 82*6691Smckusick WHILE (dp = readdir(dirf)) != NULL ANDF (trapnote&SIGSET) == 0 83*6691Smckusick DO IF (*dp->d_name=='.' ANDF *cs!='.') 84*6691Smckusick THEN continue; 85*6691Smckusick FI 86*6691Smckusick IF gmatch(dp->d_name, cs) 87*6691Smckusick THEN addg(s,dp->d_name,rescan); count++; 88*6691Smckusick FI 89*6691Smckusick OD 90*6691Smckusick closedir(dirf); 91*6691Smckusick 92*6691Smckusick IF rescan 93*6691Smckusick THEN REG ARGPTR rchain; 94*6691Smckusick rchain=gchain; gchain=schain; 95*6691Smckusick IF count 96*6691Smckusick THEN count=0; 97*6691Smckusick WHILE rchain 98*6691Smckusick DO count += expand(rchain->argval,1); 99*6691Smckusick rchain=rchain->argnxt; 100*6691Smckusick OD 101*6691Smckusick FI 102*6691Smckusick *rescan='/'; 103*6691Smckusick FI 104*6691Smckusick FI 105*6691Smckusick 106*6691Smckusick BEGIN 107*6691Smckusick REG CHAR c; 108*6691Smckusick s=as; 109*6691Smckusick WHILE c = *s 110*6691Smckusick DO *s++=(c&STRIP?c:'/') OD 111*6691Smckusick END 112*6691Smckusick return(count); 113*6691Smckusick } 114*6691Smckusick 115*6691Smckusick gmatch(s, p) 116*6691Smckusick REG STRING s, p; 117*6691Smckusick { 118*6691Smckusick REG INT scc; 119*6691Smckusick CHAR c; 120*6691Smckusick 121*6691Smckusick IF scc = *s++ 122*6691Smckusick THEN IF (scc &= STRIP)==0 123*6691Smckusick THEN scc=0200; 124*6691Smckusick FI 125*6691Smckusick FI 126*6691Smckusick SWITCH c = *p++ IN 127*6691Smckusick 128*6691Smckusick case '[': 129*6691Smckusick {BOOL ok; INT lc; 130*6691Smckusick ok=0; lc=077777; 131*6691Smckusick WHILE c = *p++ 132*6691Smckusick DO IF c==']' 133*6691Smckusick THEN return(ok?gmatch(s,p):0); 134*6691Smckusick ELIF c==MINUS 135*6691Smckusick THEN IF lc<=scc ANDF scc<=(*p++) THEN ok++ FI 136*6691Smckusick ELSE IF scc==(lc=(c&STRIP)) THEN ok++ FI 137*6691Smckusick FI 138*6691Smckusick OD 139*6691Smckusick return(0); 140*6691Smckusick } 141*6691Smckusick 142*6691Smckusick default: 143*6691Smckusick IF (c&STRIP)!=scc THEN return(0) FI 144*6691Smckusick 145*6691Smckusick case '?': 146*6691Smckusick return(scc?gmatch(s,p):0); 147*6691Smckusick 148*6691Smckusick case '*': 149*6691Smckusick IF *p==0 THEN return(1) FI 150*6691Smckusick --s; 151*6691Smckusick WHILE *s 152*6691Smckusick DO IF gmatch(s++,p) THEN return(1) FI OD 153*6691Smckusick return(0); 154*6691Smckusick 155*6691Smckusick case 0: 156*6691Smckusick return(scc==0); 157*6691Smckusick ENDSW 158*6691Smckusick } 159*6691Smckusick 160*6691Smckusick LOCAL VOID addg(as1,as2,as3) 161*6691Smckusick STRING as1, as2, as3; 162*6691Smckusick { 163*6691Smckusick REG STRING s1, s2; 164*6691Smckusick REG INT c; 165*6691Smckusick 166*6691Smckusick s2 = locstak()+BYTESPERWORD; 167*6691Smckusick 168*6691Smckusick s1=as1; 169*6691Smckusick WHILE c = *s1++ 170*6691Smckusick DO IF (c &= STRIP)==0 171*6691Smckusick THEN *s2++='/'; 172*6691Smckusick break; 173*6691Smckusick FI 174*6691Smckusick *s2++=c; 175*6691Smckusick OD 176*6691Smckusick s1=as2; 177*6691Smckusick WHILE *s2 = *s1++ DO s2++ OD 178*6691Smckusick IF s1=as3 179*6691Smckusick THEN *s2++='/'; 180*6691Smckusick WHILE *s2++ = *++s1 DONE 181*6691Smckusick FI 182*6691Smckusick makearg(endstak(s2)); 183*6691Smckusick } 184*6691Smckusick 185*6691Smckusick makearg(args) 186*6691Smckusick REG STRING args; 187*6691Smckusick { 188*6691Smckusick args->argnxt=gchain; 189*6691Smckusick gchain=args; 190*6691Smckusick } 191*6691Smckusick 192