1 | #define Extern extern
|
---|
2 | #include <sys/types.h>
|
---|
3 | #include <sys/stat.h>
|
---|
4 | #include <sys/dir.h>
|
---|
5 | #include <limits.h>
|
---|
6 | #include <signal.h>
|
---|
7 | #include <errno.h>
|
---|
8 | #include <setjmp.h>
|
---|
9 | #include "sh.h"
|
---|
10 |
|
---|
11 | /* -------- eval.c -------- */
|
---|
12 | /* #include "sh.h" */
|
---|
13 | /* #include "word.h" */
|
---|
14 |
|
---|
15 | /*
|
---|
16 | * ${}
|
---|
17 | * `command`
|
---|
18 | * blank interpretation
|
---|
19 | * quoting
|
---|
20 | * glob
|
---|
21 | */
|
---|
22 |
|
---|
23 | _PROTOTYPE(static int expand, (char *cp, struct wdblock **wbp, int f ));
|
---|
24 | _PROTOTYPE(static char *blank, (int f ));
|
---|
25 | _PROTOTYPE(static int dollar, (int quoted ));
|
---|
26 | _PROTOTYPE(static int grave, (int quoted ));
|
---|
27 | _PROTOTYPE(void globname, (char *we, char *pp ));
|
---|
28 | _PROTOTYPE(static char *generate, (char *start1, char *end1, char *middle, char *end ));
|
---|
29 | _PROTOTYPE(static int anyspcl, (struct wdblock *wb ));
|
---|
30 | _PROTOTYPE(static int xstrcmp, (char *p1, char *p2 ));
|
---|
31 | _PROTOTYPE(void glob0, (char *a0, unsigned int a1, int a2, int (*a3)(char *, char *)));
|
---|
32 | _PROTOTYPE(void glob1, (char *base, char *lim ));
|
---|
33 | _PROTOTYPE(void glob2, (char *i, char *j ));
|
---|
34 | _PROTOTYPE(void glob3, (char *i, char *j, char *k ));
|
---|
35 | _PROTOTYPE(char *memcopy, (char *ato, char *from, int nb ));
|
---|
36 |
|
---|
37 | char **
|
---|
38 | eval(ap, f)
|
---|
39 | register char **ap;
|
---|
40 | int f;
|
---|
41 | {
|
---|
42 | struct wdblock *wb;
|
---|
43 | char **wp;
|
---|
44 | char **wf;
|
---|
45 | jmp_buf ev;
|
---|
46 |
|
---|
47 | wp = NULL;
|
---|
48 | wb = NULL;
|
---|
49 | wf = NULL;
|
---|
50 | if (newenv(setjmp(errpt = ev)) == 0) {
|
---|
51 | while (*ap && isassign(*ap))
|
---|
52 | expand(*ap++, &wb, f & ~DOGLOB);
|
---|
53 | if (flag['k']) {
|
---|
54 | for (wf = ap; *wf; wf++) {
|
---|
55 | if (isassign(*wf))
|
---|
56 | expand(*wf, &wb, f & ~DOGLOB);
|
---|
57 | }
|
---|
58 | }
|
---|
59 | for (wb = addword((char *)0, wb); *ap; ap++) {
|
---|
60 | if (!flag['k'] || !isassign(*ap))
|
---|
61 | expand(*ap, &wb, f & ~DOKEY);
|
---|
62 | }
|
---|
63 | wb = addword((char *)0, wb);
|
---|
64 | wp = getwords(wb);
|
---|
65 | quitenv();
|
---|
66 | } else
|
---|
67 | gflg = 1;
|
---|
68 | return(gflg? (char **)NULL: wp);
|
---|
69 | }
|
---|
70 |
|
---|
71 | /*
|
---|
72 | * Make the exported environment from the exported
|
---|
73 | * names in the dictionary. Keyword assignments
|
---|
74 | * will already have been done.
|
---|
75 | */
|
---|
76 | char **
|
---|
77 | makenv()
|
---|
78 |
|
---|
79 | {
|
---|
80 | register struct wdblock *wb;
|
---|
81 | register struct var *vp;
|
---|
82 |
|
---|
83 | wb = NULL;
|
---|
84 | for (vp = vlist; vp; vp = vp->next)
|
---|
85 | if (vp->status & EXPORT)
|
---|
86 | wb = addword(vp->name, wb);
|
---|
87 | wb = addword((char *)0, wb);
|
---|
88 | return(getwords(wb));
|
---|
89 | }
|
---|
90 |
|
---|
91 | char *
|
---|
92 | evalstr(cp, f)
|
---|
93 | register char *cp;
|
---|
94 | int f;
|
---|
95 | {
|
---|
96 | struct wdblock *wb;
|
---|
97 |
|
---|
98 | wb = NULL;
|
---|
99 | if (expand(cp, &wb, f)) {
|
---|
100 | if (wb == NULL || wb->w_nword == 0 || (cp = wb->w_words[0]) == NULL)
|
---|
101 | cp = "";
|
---|
102 | DELETE(wb);
|
---|
103 | } else
|
---|
104 | cp = NULL;
|
---|
105 | return(cp);
|
---|
106 | }
|
---|
107 |
|
---|
108 | static int
|
---|
109 | expand(cp, wbp, f)
|
---|
110 | register char *cp;
|
---|
111 | register struct wdblock **wbp;
|
---|
112 | int f;
|
---|
113 | {
|
---|
114 | jmp_buf ev;
|
---|
115 |
|
---|
116 | gflg = 0;
|
---|
117 | if (cp == NULL)
|
---|
118 | return(0);
|
---|
119 | if (!anys("$`'\"", cp) &&
|
---|
120 | !anys(ifs->value, cp) &&
|
---|
121 | ((f&DOGLOB)==0 || !anys("[*?", cp))) {
|
---|
122 | cp = strsave(cp, areanum);
|
---|
123 | if (f & DOTRIM)
|
---|
124 | unquote(cp);
|
---|
125 | *wbp = addword(cp, *wbp);
|
---|
126 | return(1);
|
---|
127 | }
|
---|
128 | if (newenv(setjmp(errpt = ev)) == 0) {
|
---|
129 | PUSHIO(aword, cp, strchar);
|
---|
130 | e.iobase = e.iop;
|
---|
131 | while ((cp = blank(f)) && gflg == 0) {
|
---|
132 | e.linep = cp;
|
---|
133 | cp = strsave(cp, areanum);
|
---|
134 | if ((f&DOGLOB) == 0) {
|
---|
135 | if (f & DOTRIM)
|
---|
136 | unquote(cp);
|
---|
137 | *wbp = addword(cp, *wbp);
|
---|
138 | } else
|
---|
139 | *wbp = glob(cp, *wbp);
|
---|
140 | }
|
---|
141 | quitenv();
|
---|
142 | } else
|
---|
143 | gflg = 1;
|
---|
144 | return(gflg == 0);
|
---|
145 | }
|
---|
146 |
|
---|
147 | /*
|
---|
148 | * Blank interpretation and quoting
|
---|
149 | */
|
---|
150 | static char *
|
---|
151 | blank(f)
|
---|
152 | int f;
|
---|
153 | {
|
---|
154 | register c, c1;
|
---|
155 | register char *sp;
|
---|
156 | int scanequals, foundequals;
|
---|
157 |
|
---|
158 | sp = e.linep;
|
---|
159 | scanequals = f & DOKEY;
|
---|
160 | foundequals = 0;
|
---|
161 |
|
---|
162 | loop:
|
---|
163 | switch (c = subgetc('"', foundequals)) {
|
---|
164 | case 0:
|
---|
165 | if (sp == e.linep)
|
---|
166 | return(0);
|
---|
167 | *e.linep++ = 0;
|
---|
168 | return(sp);
|
---|
169 |
|
---|
170 | default:
|
---|
171 | if (f & DOBLANK && any(c, ifs->value))
|
---|
172 | goto loop;
|
---|
173 | break;
|
---|
174 |
|
---|
175 | case '"':
|
---|
176 | case '\'':
|
---|
177 | scanequals = 0;
|
---|
178 | if (INSUB())
|
---|
179 | break;
|
---|
180 | for (c1 = c; (c = subgetc(c1, 1)) != c1;) {
|
---|
181 | if (c == 0)
|
---|
182 | break;
|
---|
183 | if (c == '\'' || !any(c, "$`\""))
|
---|
184 | c |= QUOTE;
|
---|
185 | *e.linep++ = c;
|
---|
186 | }
|
---|
187 | c = 0;
|
---|
188 | }
|
---|
189 | unget(c);
|
---|
190 | if (!letter(c))
|
---|
191 | scanequals = 0;
|
---|
192 | for (;;) {
|
---|
193 | c = subgetc('"', foundequals);
|
---|
194 | if (c == 0 ||
|
---|
195 | (f & DOBLANK && any(c, ifs->value)) ||
|
---|
196 | (!INSUB() && any(c, "\"'"))) {
|
---|
197 | scanequals = 0;
|
---|
198 | unget(c);
|
---|
199 | if (any(c, "\"'"))
|
---|
200 | goto loop;
|
---|
201 | break;
|
---|
202 | }
|
---|
203 | if (scanequals)
|
---|
204 | if (c == '=') {
|
---|
205 | foundequals = 1;
|
---|
206 | scanequals = 0;
|
---|
207 | }
|
---|
208 | else if (!letnum(c))
|
---|
209 | scanequals = 0;
|
---|
210 | *e.linep++ = c;
|
---|
211 | }
|
---|
212 | *e.linep++ = 0;
|
---|
213 | return(sp);
|
---|
214 | }
|
---|
215 |
|
---|
216 | /*
|
---|
217 | * Get characters, substituting for ` and $
|
---|
218 | */
|
---|
219 | int
|
---|
220 | subgetc(ec, quoted)
|
---|
221 | register char ec;
|
---|
222 | int quoted;
|
---|
223 | {
|
---|
224 | register char c;
|
---|
225 |
|
---|
226 | again:
|
---|
227 | c = getc(ec);
|
---|
228 | if (!INSUB() && ec != '\'') {
|
---|
229 | if (c == '`') {
|
---|
230 | if (grave(quoted) == 0)
|
---|
231 | return(0);
|
---|
232 | e.iop->task = XGRAVE;
|
---|
233 | goto again;
|
---|
234 | }
|
---|
235 | if (c == '$' && (c = dollar(quoted)) == 0) {
|
---|
236 | e.iop->task = XDOLL;
|
---|
237 | goto again;
|
---|
238 | }
|
---|
239 | }
|
---|
240 | return(c);
|
---|
241 | }
|
---|
242 |
|
---|
243 | /*
|
---|
244 | * Prepare to generate the string returned by ${} substitution.
|
---|
245 | */
|
---|
246 | static int
|
---|
247 | dollar(quoted)
|
---|
248 | int quoted;
|
---|
249 | {
|
---|
250 | int otask;
|
---|
251 | struct io *oiop;
|
---|
252 | char *dolp;
|
---|
253 | register char *s, c, *cp;
|
---|
254 | struct var *vp;
|
---|
255 |
|
---|
256 | c = readc();
|
---|
257 | s = e.linep;
|
---|
258 | if (c != '{') {
|
---|
259 | *e.linep++ = c;
|
---|
260 | if (letter(c)) {
|
---|
261 | while ((c = readc())!=0 && letnum(c))
|
---|
262 | if (e.linep < elinep)
|
---|
263 | *e.linep++ = c;
|
---|
264 | unget(c);
|
---|
265 | }
|
---|
266 | c = 0;
|
---|
267 | } else {
|
---|
268 | oiop = e.iop;
|
---|
269 | otask = e.iop->task;
|
---|
270 | e.iop->task = XOTHER;
|
---|
271 | while ((c = subgetc('"', 0))!=0 && c!='}' && c!='\n')
|
---|
272 | if (e.linep < elinep)
|
---|
273 | *e.linep++ = c;
|
---|
274 | if (oiop == e.iop)
|
---|
275 | e.iop->task = otask;
|
---|
276 | if (c != '}') {
|
---|
277 | err("unclosed ${");
|
---|
278 | gflg++;
|
---|
279 | return(c);
|
---|
280 | }
|
---|
281 | }
|
---|
282 | if (e.linep >= elinep) {
|
---|
283 | err("string in ${} too long");
|
---|
284 | gflg++;
|
---|
285 | e.linep -= 10;
|
---|
286 | }
|
---|
287 | *e.linep = 0;
|
---|
288 | if (*s)
|
---|
289 | for (cp = s+1; *cp; cp++)
|
---|
290 | if (any(*cp, "=-+?")) {
|
---|
291 | c = *cp;
|
---|
292 | *cp++ = 0;
|
---|
293 | break;
|
---|
294 | }
|
---|
295 | if (s[1] == 0 && (*s == '*' || *s == '@')) {
|
---|
296 | if (dolc > 1) {
|
---|
297 | /* currently this does not distinguish $* and $@ */
|
---|
298 | /* should check dollar */
|
---|
299 | e.linep = s;
|
---|
300 | PUSHIO(awordlist, dolv+1, dolchar);
|
---|
301 | return(0);
|
---|
302 | } else { /* trap the nasty ${=} */
|
---|
303 | s[0] = '1';
|
---|
304 | s[1] = 0;
|
---|
305 | }
|
---|
306 | }
|
---|
307 | e.linep = s;
|
---|
308 | vp = lookup(s);
|
---|
309 | if ((dolp = vp->value) == null) {
|
---|
310 | switch (c) {
|
---|
311 | case '=':
|
---|
312 | if (digit(*s)) {
|
---|
313 | err("cannot use ${...=...} with $n");
|
---|
314 | gflg++;
|
---|
315 | break;
|
---|
316 | }
|
---|
317 | cp = evalstr(strsave(cp, areanum),DOSUB);
|
---|
318 | setval(vp, cp);
|
---|
319 | dolp = vp->value;
|
---|
320 | break;
|
---|
321 |
|
---|
322 | case '-':
|
---|
323 | dolp = evalstr(strsave(cp, areanum),DOSUB);
|
---|
324 | break;
|
---|
325 |
|
---|
326 | case '?':
|
---|
327 | if (*cp == 0) {
|
---|
328 | prs("missing value for ");
|
---|
329 | err(s);
|
---|
330 | } else
|
---|
331 | err(evalstr(strsave(cp, areanum),DOSUB));
|
---|
332 | gflg++;
|
---|
333 | break;
|
---|
334 | }
|
---|
335 | } else if (c == '+') {
|
---|
336 | dolp = evalstr(strsave(cp, areanum),DOSUB);
|
---|
337 | }
|
---|
338 | if (flag['u'] && dolp == null) {
|
---|
339 | prs("unset variable: ");
|
---|
340 | err(s);
|
---|
341 | gflg++;
|
---|
342 | }
|
---|
343 | PUSHIO(aword, dolp, quoted ? qstrchar : strchar);
|
---|
344 | return(0);
|
---|
345 | }
|
---|
346 |
|
---|
347 | /*
|
---|
348 | * Run the command in `...` and read its output.
|
---|
349 | */
|
---|
350 | static int
|
---|
351 | grave(quoted)
|
---|
352 | int quoted;
|
---|
353 | {
|
---|
354 | int otask;
|
---|
355 | struct io *oiop;
|
---|
356 | register char *cp,*s;
|
---|
357 | register int i,c;
|
---|
358 | int pf[2];
|
---|
359 |
|
---|
360 | c = readc();
|
---|
361 | s = e.linep;
|
---|
362 | *e.linep++ = c;
|
---|
363 | oiop = e.iop;
|
---|
364 | otask = e.iop->task;
|
---|
365 | e.iop->task = XOTHER;
|
---|
366 | while ((c = subgetc('\'', 0))!=0 && c!='`')
|
---|
367 | if (e.linep < elinep)
|
---|
368 | *e.linep++ = c;
|
---|
369 | if (oiop == e.iop)
|
---|
370 | e.iop->task = otask;
|
---|
371 | if (c != '`') {
|
---|
372 | err("no closing `");
|
---|
373 | return(0);
|
---|
374 | }
|
---|
375 | if (openpipe(pf) < 0)
|
---|
376 | return(0);
|
---|
377 | if ((i = fork()) == -1) {
|
---|
378 | closepipe(pf);
|
---|
379 | err("try again");
|
---|
380 | return(0);
|
---|
381 | }
|
---|
382 | if (i != 0) {
|
---|
383 | e.linep = s;
|
---|
384 | close(pf[1]);
|
---|
385 | PUSHIO(afile, remap(pf[0]), quoted? qgravechar: gravechar);
|
---|
386 | return(1);
|
---|
387 | }
|
---|
388 | *e.linep = 0;
|
---|
389 | /* allow trapped signals */
|
---|
390 | for (i=0; i<=_NSIG; i++)
|
---|
391 | if (ourtrap[i] && signal(i, SIG_IGN) != SIG_IGN)
|
---|
392 | signal(i, SIG_DFL);
|
---|
393 | dup2(pf[1], 1);
|
---|
394 | closepipe(pf);
|
---|
395 | flag['e'] = 0;
|
---|
396 | flag['v'] = 0;
|
---|
397 | flag['n'] = 0;
|
---|
398 | cp = strsave(e.linep = s, 0);
|
---|
399 | areanum = 1;
|
---|
400 | inithere();
|
---|
401 | freearea(areanum); /* free old space */
|
---|
402 | e.oenv = NULL;
|
---|
403 | e.iop = (e.iobase = iostack) - 1;
|
---|
404 | unquote(cp);
|
---|
405 | talking = 0;
|
---|
406 | PUSHIO(aword, cp, nlchar);
|
---|
407 | onecommand();
|
---|
408 | exit(1);
|
---|
409 | }
|
---|
410 |
|
---|
411 | char *
|
---|
412 | unquote(as)
|
---|
413 | register char *as;
|
---|
414 | {
|
---|
415 | register char *s;
|
---|
416 |
|
---|
417 | if ((s = as) != NULL)
|
---|
418 | while (*s)
|
---|
419 | *s++ &= ~QUOTE;
|
---|
420 | return(as);
|
---|
421 | }
|
---|
422 |
|
---|
423 | /* -------- glob.c -------- */
|
---|
424 | /* #include "sh.h" */
|
---|
425 |
|
---|
426 | /*
|
---|
427 | * glob
|
---|
428 | */
|
---|
429 |
|
---|
430 | #define scopy(x) strsave((x), areanum)
|
---|
431 | #define BLKSIZ 512
|
---|
432 | #define NDENT ((BLKSIZ+sizeof(struct direct)-1)/sizeof(struct direct))
|
---|
433 |
|
---|
434 | static struct wdblock *cl, *nl;
|
---|
435 | static char spcl[] = "[?*";
|
---|
436 |
|
---|
437 | struct wdblock *
|
---|
438 | glob(cp, wb)
|
---|
439 | char *cp;
|
---|
440 | struct wdblock *wb;
|
---|
441 | {
|
---|
442 | register i;
|
---|
443 | register char *pp;
|
---|
444 |
|
---|
445 | if (cp == 0)
|
---|
446 | return(wb);
|
---|
447 | i = 0;
|
---|
448 | for (pp = cp; *pp; pp++)
|
---|
449 | if (any(*pp, spcl))
|
---|
450 | i++;
|
---|
451 | else if (!any(*pp & ~QUOTE, spcl))
|
---|
452 | *pp &= ~QUOTE;
|
---|
453 | if (i != 0) {
|
---|
454 | for (cl = addword(scopy(cp), (struct wdblock *)0); anyspcl(cl); cl = nl) {
|
---|
455 | nl = newword(cl->w_nword*2);
|
---|
456 | for(i=0; i<cl->w_nword; i++) { /* for each argument */
|
---|
457 | for (pp = cl->w_words[i]; *pp; pp++)
|
---|
458 | if (any(*pp, spcl)) {
|
---|
459 | globname(cl->w_words[i], pp);
|
---|
460 | break;
|
---|
461 | }
|
---|
462 | if (*pp == '\0')
|
---|
463 | nl = addword(scopy(cl->w_words[i]), nl);
|
---|
464 | }
|
---|
465 | for(i=0; i<cl->w_nword; i++)
|
---|
466 | DELETE(cl->w_words[i]);
|
---|
467 | DELETE(cl);
|
---|
468 | }
|
---|
469 | for(i=0; i<cl->w_nword; i++)
|
---|
470 | unquote(cl->w_words[i]);
|
---|
471 | glob0((char *)cl->w_words, cl->w_nword, sizeof(char *), xstrcmp);
|
---|
472 | if (cl->w_nword) {
|
---|
473 | for (i=0; i<cl->w_nword; i++)
|
---|
474 | wb = addword(cl->w_words[i], wb);
|
---|
475 | DELETE(cl);
|
---|
476 | return(wb);
|
---|
477 | }
|
---|
478 | }
|
---|
479 | wb = addword(unquote(cp), wb);
|
---|
480 | return(wb);
|
---|
481 | }
|
---|
482 |
|
---|
483 | void
|
---|
484 | globname(we, pp)
|
---|
485 | char *we;
|
---|
486 | register char *pp;
|
---|
487 | {
|
---|
488 | register char *np, *cp;
|
---|
489 | char *name, *gp, *dp;
|
---|
490 | int dn, j, n, k;
|
---|
491 | struct direct ent[NDENT];
|
---|
492 | char dname[NAME_MAX+1];
|
---|
493 | struct stat dbuf;
|
---|
494 |
|
---|
495 | for (np = we; np != pp; pp--)
|
---|
496 | if (pp[-1] == '/')
|
---|
497 | break;
|
---|
498 | for (dp = cp = space((int)(pp-np)+3); np < pp;)
|
---|
499 | *cp++ = *np++;
|
---|
500 | *cp++ = '.';
|
---|
501 | *cp = '\0';
|
---|
502 | for (gp = cp = space(strlen(pp)+1); *np && *np != '/';)
|
---|
503 | *cp++ = *np++;
|
---|
504 | *cp = '\0';
|
---|
505 | dn = open(dp, 0);
|
---|
506 | if (dn < 0) {
|
---|
507 | DELETE(dp);
|
---|
508 | DELETE(gp);
|
---|
509 | return;
|
---|
510 | }
|
---|
511 | dname[NAME_MAX] = '\0';
|
---|
512 | while ((n = read(dn, (char *)ent, sizeof(ent))) >= sizeof(*ent)) {
|
---|
513 | n /= sizeof(*ent);
|
---|
514 | for (j=0; j<n; j++) {
|
---|
515 | if (ent[j].d_ino == 0)
|
---|
516 | continue;
|
---|
517 | strncpy(dname, ent[j].d_name, NAME_MAX);
|
---|
518 | if (dname[0] == '.')
|
---|
519 | if (*gp != '.')
|
---|
520 | continue;
|
---|
521 | for(k=0; k<NAME_MAX; k++)
|
---|
522 | if (any(dname[k], spcl))
|
---|
523 | dname[k] |= QUOTE;
|
---|
524 | if (gmatch(dname, gp)) {
|
---|
525 | name = generate(we, pp, dname, np);
|
---|
526 | if (*np && !anys(np, spcl)) {
|
---|
527 | if (stat(name,&dbuf)) {
|
---|
528 | DELETE(name);
|
---|
529 | continue;
|
---|
530 | }
|
---|
531 | }
|
---|
532 | nl = addword(name, nl);
|
---|
533 | }
|
---|
534 | }
|
---|
535 | }
|
---|
536 | close(dn);
|
---|
537 | DELETE(dp);
|
---|
538 | DELETE(gp);
|
---|
539 | }
|
---|
540 |
|
---|
541 | /*
|
---|
542 | * generate a pathname as below.
|
---|
543 | * start..end1 / middle end
|
---|
544 | * the slashes come for free
|
---|
545 | */
|
---|
546 | static char *
|
---|
547 | generate(start1, end1, middle, end)
|
---|
548 | char *start1;
|
---|
549 | register char *end1;
|
---|
550 | char *middle, *end;
|
---|
551 | {
|
---|
552 | char *p;
|
---|
553 | register char *op, *xp;
|
---|
554 |
|
---|
555 | p = op = space((int)(end1-start1)+strlen(middle)+strlen(end)+2);
|
---|
556 | for (xp = start1; xp != end1;)
|
---|
557 | *op++ = *xp++;
|
---|
558 | for (xp = middle; (*op++ = *xp++) != '\0';)
|
---|
559 | ;
|
---|
560 | op--;
|
---|
561 | for (xp = end; (*op++ = *xp++) != '\0';)
|
---|
562 | ;
|
---|
563 | return(p);
|
---|
564 | }
|
---|
565 |
|
---|
566 | static int
|
---|
567 | anyspcl(wb)
|
---|
568 | register struct wdblock *wb;
|
---|
569 | {
|
---|
570 | register i;
|
---|
571 | register char **wd;
|
---|
572 |
|
---|
573 | wd = wb->w_words;
|
---|
574 | for (i=0; i<wb->w_nword; i++)
|
---|
575 | if (anys(spcl, *wd++))
|
---|
576 | return(1);
|
---|
577 | return(0);
|
---|
578 | }
|
---|
579 |
|
---|
580 | static int
|
---|
581 | xstrcmp(p1, p2)
|
---|
582 | char *p1, *p2;
|
---|
583 | {
|
---|
584 | return(strcmp(*(char **)p1, *(char **)p2));
|
---|
585 | }
|
---|
586 |
|
---|
587 | /* -------- word.c -------- */
|
---|
588 | /* #include "sh.h" */
|
---|
589 | /* #include "word.h" */
|
---|
590 |
|
---|
591 | #define NSTART 16 /* default number of words to allow for initially */
|
---|
592 |
|
---|
593 | struct wdblock *
|
---|
594 | newword(nw)
|
---|
595 | register int nw;
|
---|
596 | {
|
---|
597 | register struct wdblock *wb;
|
---|
598 |
|
---|
599 | wb = (struct wdblock *) space(sizeof(*wb) + nw*sizeof(char *));
|
---|
600 | wb->w_bsize = nw;
|
---|
601 | wb->w_nword = 0;
|
---|
602 | return(wb);
|
---|
603 | }
|
---|
604 |
|
---|
605 | struct wdblock *
|
---|
606 | addword(wd, wb)
|
---|
607 | char *wd;
|
---|
608 | register struct wdblock *wb;
|
---|
609 | {
|
---|
610 | register struct wdblock *wb2;
|
---|
611 | register nw;
|
---|
612 |
|
---|
613 | if (wb == NULL)
|
---|
614 | wb = newword(NSTART);
|
---|
615 | if ((nw = wb->w_nword) >= wb->w_bsize) {
|
---|
616 | wb2 = newword(nw * 2);
|
---|
617 | memcopy((char *)wb2->w_words, (char *)wb->w_words, nw*sizeof(char *));
|
---|
618 | wb2->w_nword = nw;
|
---|
619 | DELETE(wb);
|
---|
620 | wb = wb2;
|
---|
621 | }
|
---|
622 | wb->w_words[wb->w_nword++] = wd;
|
---|
623 | return(wb);
|
---|
624 | }
|
---|
625 |
|
---|
626 | char **
|
---|
627 | getwords(wb)
|
---|
628 | register struct wdblock *wb;
|
---|
629 | {
|
---|
630 | register char **wd;
|
---|
631 | register nb;
|
---|
632 |
|
---|
633 | if (wb == NULL)
|
---|
634 | return((char **)NULL);
|
---|
635 | if (wb->w_nword == 0) {
|
---|
636 | DELETE(wb);
|
---|
637 | return((char **)NULL);
|
---|
638 | }
|
---|
639 | wd = (char **) space(nb = sizeof(*wd) * wb->w_nword);
|
---|
640 | memcopy((char *)wd, (char *)wb->w_words, nb);
|
---|
641 | DELETE(wb); /* perhaps should done by caller */
|
---|
642 | return(wd);
|
---|
643 | }
|
---|
644 |
|
---|
645 | _PROTOTYPE(int (*func), (char *, char *));
|
---|
646 | int globv;
|
---|
647 |
|
---|
648 | void
|
---|
649 | glob0(a0, a1, a2, a3)
|
---|
650 | char *a0;
|
---|
651 | unsigned a1;
|
---|
652 | int a2;
|
---|
653 | _PROTOTYPE(int (*a3), (char *, char *));
|
---|
654 | {
|
---|
655 | func = a3;
|
---|
656 | globv = a2;
|
---|
657 | glob1(a0, a0 + a1 * a2);
|
---|
658 | }
|
---|
659 |
|
---|
660 | void
|
---|
661 | glob1(base, lim)
|
---|
662 | char *base, *lim;
|
---|
663 | {
|
---|
664 | register char *i, *j;
|
---|
665 | int v2;
|
---|
666 | char *lptr, *hptr;
|
---|
667 | int c;
|
---|
668 | unsigned n;
|
---|
669 |
|
---|
670 |
|
---|
671 | v2 = globv;
|
---|
672 |
|
---|
673 | top:
|
---|
674 | if ((n=(int)(lim-base)) <= v2)
|
---|
675 | return;
|
---|
676 | n = v2 * (n / (2*v2));
|
---|
677 | hptr = lptr = base+n;
|
---|
678 | i = base;
|
---|
679 | j = lim-v2;
|
---|
680 | for(;;) {
|
---|
681 | if (i < lptr) {
|
---|
682 | if ((c = (*func)(i, lptr)) == 0) {
|
---|
683 | glob2(i, lptr -= v2);
|
---|
684 | continue;
|
---|
685 | }
|
---|
686 | if (c < 0) {
|
---|
687 | i += v2;
|
---|
688 | continue;
|
---|
689 | }
|
---|
690 | }
|
---|
691 |
|
---|
692 | begin:
|
---|
693 | if (j > hptr) {
|
---|
694 | if ((c = (*func)(hptr, j)) == 0) {
|
---|
695 | glob2(hptr += v2, j);
|
---|
696 | goto begin;
|
---|
697 | }
|
---|
698 | if (c > 0) {
|
---|
699 | if (i == lptr) {
|
---|
700 | glob3(i, hptr += v2, j);
|
---|
701 | i = lptr += v2;
|
---|
702 | goto begin;
|
---|
703 | }
|
---|
704 | glob2(i, j);
|
---|
705 | j -= v2;
|
---|
706 | i += v2;
|
---|
707 | continue;
|
---|
708 | }
|
---|
709 | j -= v2;
|
---|
710 | goto begin;
|
---|
711 | }
|
---|
712 |
|
---|
713 |
|
---|
714 | if (i == lptr) {
|
---|
715 | if (lptr-base >= lim-hptr) {
|
---|
716 | glob1(hptr+v2, lim);
|
---|
717 | lim = lptr;
|
---|
718 | } else {
|
---|
719 | glob1(base, lptr);
|
---|
720 | base = hptr+v2;
|
---|
721 | }
|
---|
722 | goto top;
|
---|
723 | }
|
---|
724 |
|
---|
725 |
|
---|
726 | glob3(j, lptr -= v2, i);
|
---|
727 | j = hptr -= v2;
|
---|
728 | }
|
---|
729 | }
|
---|
730 |
|
---|
731 | void
|
---|
732 | glob2(i, j)
|
---|
733 | char *i, *j;
|
---|
734 | {
|
---|
735 | register char *index1, *index2, c;
|
---|
736 | int m;
|
---|
737 |
|
---|
738 | m = globv;
|
---|
739 | index1 = i;
|
---|
740 | index2 = j;
|
---|
741 | do {
|
---|
742 | c = *index1;
|
---|
743 | *index1++ = *index2;
|
---|
744 | *index2++ = c;
|
---|
745 | } while(--m);
|
---|
746 | }
|
---|
747 |
|
---|
748 | void
|
---|
749 | glob3(i, j, k)
|
---|
750 | char *i, *j, *k;
|
---|
751 | {
|
---|
752 | register char *index1, *index2, *index3;
|
---|
753 | int c;
|
---|
754 | int m;
|
---|
755 |
|
---|
756 | m = globv;
|
---|
757 | index1 = i;
|
---|
758 | index2 = j;
|
---|
759 | index3 = k;
|
---|
760 | do {
|
---|
761 | c = *index1;
|
---|
762 | *index1++ = *index3;
|
---|
763 | *index3++ = *index2;
|
---|
764 | *index2++ = c;
|
---|
765 | } while(--m);
|
---|
766 | }
|
---|
767 |
|
---|
768 | char *
|
---|
769 | memcopy(ato, from, nb)
|
---|
770 | register char *ato, *from;
|
---|
771 | register int nb;
|
---|
772 | {
|
---|
773 | register char *to;
|
---|
774 |
|
---|
775 | to = ato;
|
---|
776 | while (--nb >= 0)
|
---|
777 | *to++ = *from++;
|
---|
778 | return(ato);
|
---|
779 | }
|
---|