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