|
|
1.1 root 1: /* @(#)expand.c 1.4 */
2: /*
3: * UNIX shell
4: *
5: * Bell Telephone Laboratories
6: *
7: */
8:
9: #include "defs.h"
10: #include <sys/types.h>
11: #include <sys/stat.h>
12: #ifdef BSD4_2
13: #include <sys/dir.h>
14: #else
15: #include <ndir.h>
16: #endif
17:
18: #ifdef BSD4_2
19: #define DIRSIZE MAXNAMELEN
20: #else
21: #define DIRSIZE 14
22: #endif
23: #ifndef MAXNAMELEN
24: #define MAXNAMELEN 255
25: #endif
26:
27:
28: static char entry[DIRSIZE+1];
29:
30: /*
31: * globals (file name generation)
32: *
33: * "*" in params matches r.e ".*"
34: * "?" in params matches r.e. "."
35: * "[...]" in params matches character class
36: * "[...a-z...]" in params matches a through z.
37: *
38: */
39:
40: static addg();
41:
42: expand(as, rcnt)
43: char *as;
44: {
45: int count;
46: DIR *dirf;
47: struct direct *e;
48: BOOL dir = 0;
49: char *rescan = 0;
50: register char *s, *cs;
51: struct argnod *schain = gchain;
52: BOOL slash;
53:
54: if (trapnote & SIGSET)
55: return(0);
56: s = cs = as;
57: /*
58: * check for meta chars
59: */
60: {
61: register BOOL open;
62:
63: slash = 0;
64: open = 0;
65: do
66: {
67: switch (*cs++)
68: {
69: case 0:
70: if (rcnt && slash)
71: break;
72: else
73: return(0);
74:
75: case '/':
76: slash++;
77: open = 0;
78: continue;
79:
80: case '[':
81: open++;
82: continue;
83:
84: case ']':
85: if (open == 0)
86: continue;
87:
88: case '?':
89: case '*':
90: if (rcnt > slash)
91: continue;
92: else
93: cs--;
94: break;
95:
96:
97: default:
98: continue;
99: }
100: break;
101: } while (TRUE);
102: }
103:
104: for (;;)
105: {
106: if (cs == s)
107: {
108: s = nullstr;
109: break;
110: }
111: else if (*--cs == '/')
112: {
113: *cs = 0;
114: if (s == cs)
115: s = "/";
116: break;
117: }
118: }
119:
120: if ((dirf = opendir(*s ? s : ".")) != 0)
121: dir = TRUE;
122:
123: count = 0;
124: if (*cs == 0)
125: *cs++ = 0200;
126:
127: if(dir)
128: {
129: register char *rs;
130:
131: rs = cs;
132: do
133: {
134: if (*rs == '/')
135: {
136: rescan = rs;
137: *rs = 0;
138: gchain = 0;
139: }
140: } while (*rs++);
141:
142: while ((e = readdir(dirf)) && (trapnote & SIGSET) == 0)
143: {
144: *(movstrn(e->d_name, entry, DIRSIZE)) = 0;
145: if (entry[0] == '.' && *cs != '.')
146: {
147: if (entry[1] == 0)
148: continue;
149: if (entry[1] == '.' && entry[2] == 0)
150: continue;
151: }
152:
153: if (gmatch(entry, cs))
154: {
155: addg(s, entry, rescan);
156: count++;
157: }
158: }
159: closedir(dirf);
160:
161: if (rescan)
162: {
163: register struct argnod *rchain;
164:
165: rchain = gchain;
166: gchain = schain;
167: if (count)
168: {
169: count = 0;
170: while (rchain)
171: {
172: count += expand(rchain->argval, slash + 1);
173: rchain = rchain->argnxt;
174: }
175: }
176: *rescan = '/';
177: }
178: }
179:
180: {
181: register char c;
182:
183: s = as;
184: while (c = *s)
185: *s++ = (c & STRIP ? c : '/');
186: }
187: return(count);
188: }
189:
190:
191:
192: gmatch(s, p)
193: register char *s, *p;
194: {
195: register int scc;
196: char c;
197:
198: if (scc = *s++)
199: {
200: if ((scc &= STRIP) == 0)
201: scc=0200;
202: }
203: switch (c = *p++)
204: {
205: case '[':
206: {
207: BOOL ok;
208: int lc;
209: int notflag = 0;
210:
211: ok = 0;
212: lc = 077777;
213: if (*p == '^')
214: {
215: notflag = 1;
216: p++;
217: }
218: while (c = *p++)
219: {
220: if (c == ']')
221: return(ok ? gmatch(s, p) : 0);
222: else if (c == MINUS)
223: {
224: if (notflag)
225: {
226: if (scc < lc || scc > *(p++))
227: ok++;
228: else
229: return(0);
230: }
231: else
232: {
233: if (lc <= scc && scc <= (*p++))
234: ok++;
235: }
236: }
237: else
238: {
239: lc = c & STRIP;
240: if (notflag)
241: {
242: if (scc && scc != lc)
243: ok++;
244: else
245: return(0);
246: }
247: else
248: {
249: if (scc == lc)
250: ok++;
251: }
252: }
253: }
254: return(0);
255: }
256:
257: default:
258: if ((c & STRIP) != scc)
259: return(0);
260:
261: case '?':
262: return(scc ? gmatch(s, p) : 0);
263:
264: case '*':
265: while (*p == '*')
266: p++;
267:
268: if (*p == 0)
269: return(1);
270: --s;
271: while (*s)
272: {
273: if (gmatch(s++, p))
274: return(1);
275: }
276: return(0);
277:
278: case 0:
279: return(scc == 0);
280: }
281: }
282:
283: static
284: addg(as1, as2, as3)
285: char *as1, *as2, *as3;
286: {
287: register char *s1;
288: register int c;
289:
290: staktop = locstak() + BYTESPERWORD;
291: s1 = as1;
292: while (c = *s1++)
293: {
294: if ((c &= STRIP) == 0)
295: {
296: pushstak('/');
297: break;
298: }
299: pushstak(c);
300: }
301: s1 = as2;
302: while (c = *s1++)
303: pushstak(c);
304: if (s1 = as3)
305: {
306: pushstak('/');
307: do
308: pushstak(*++s1);
309: while(*s1);
310: }
311: makearg((struct argnod *)fixstak());
312: }
313:
314: makearg(args)
315: register struct argnod *args;
316: {
317: args->argnxt = gchain;
318: gchain = args;
319: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.