1 /* expand.c 4.1 82/05/07 */ 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))>0 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 WHILE (dp = readdir(dirf)) != NULL ANDF (trapnote&SIGSET) == 0 83 DO IF (*dp->d_name=='.' ANDF *cs!='.') 84 THEN continue; 85 FI 86 IF gmatch(dp->d_name, cs) 87 THEN addg(s,dp->d_name,rescan); count++; 88 FI 89 OD 90 closedir(dirf); 91 92 IF rescan 93 THEN REG ARGPTR rchain; 94 rchain=gchain; gchain=schain; 95 IF count 96 THEN count=0; 97 WHILE rchain 98 DO count += expand(rchain->argval,1); 99 rchain=rchain->argnxt; 100 OD 101 FI 102 *rescan='/'; 103 FI 104 FI 105 106 BEGIN 107 REG CHAR c; 108 s=as; 109 WHILE c = *s 110 DO *s++=(c&STRIP?c:'/') OD 111 END 112 return(count); 113 } 114 115 gmatch(s, p) 116 REG STRING s, p; 117 { 118 REG INT scc; 119 CHAR c; 120 121 IF scc = *s++ 122 THEN IF (scc &= STRIP)==0 123 THEN scc=0200; 124 FI 125 FI 126 SWITCH c = *p++ IN 127 128 case '[': 129 {BOOL ok; INT lc; 130 ok=0; lc=077777; 131 WHILE c = *p++ 132 DO IF c==']' 133 THEN return(ok?gmatch(s,p):0); 134 ELIF c==MINUS 135 THEN IF lc<=scc ANDF scc<=(*p++) THEN ok++ FI 136 ELSE IF scc==(lc=(c&STRIP)) THEN ok++ FI 137 FI 138 OD 139 return(0); 140 } 141 142 default: 143 IF (c&STRIP)!=scc THEN return(0) FI 144 145 case '?': 146 return(scc?gmatch(s,p):0); 147 148 case '*': 149 IF *p==0 THEN return(1) FI 150 --s; 151 WHILE *s 152 DO IF gmatch(s++,p) THEN return(1) FI OD 153 return(0); 154 155 case 0: 156 return(scc==0); 157 ENDSW 158 } 159 160 LOCAL VOID addg(as1,as2,as3) 161 STRING as1, as2, as3; 162 { 163 REG STRING s1, s2; 164 REG INT c; 165 166 s2 = locstak()+BYTESPERWORD; 167 168 s1=as1; 169 WHILE c = *s1++ 170 DO IF (c &= STRIP)==0 171 THEN *s2++='/'; 172 break; 173 FI 174 *s2++=c; 175 OD 176 s1=as2; 177 WHILE *s2 = *s1++ DO s2++ OD 178 IF s1=as3 179 THEN *s2++='/'; 180 WHILE *s2++ = *++s1 DONE 181 FI 182 makearg(endstak(s2)); 183 } 184 185 makearg(args) 186 REG STRING args; 187 { 188 args->argnxt=gchain; 189 gchain=args; 190 } 191 192