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