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