Commit | Line | Data |
---|---|---|
b79f4fa9 DF |
1 | /* |
2 | * Copyright (c) 1980 Regents of the University of California. | |
094e80ed | 3 | * All rights reserved. The Berkeley Software License Agreement |
b79f4fa9 DF |
4 | * specifies the terms and conditions for redistribution. |
5 | */ | |
6 | ||
35371dec | 7 | #ifndef lint |
24f22c48 | 8 | static char *sccsid = "@(#)exp.c 5.3 (Berkeley) %G%"; |
094e80ed | 9 | #endif |
843d5d49 BJ |
10 | |
11 | #include "sh.h" | |
12 | ||
13 | /* | |
14 | * C shell | |
15 | */ | |
16 | ||
17 | #define IGNORE 1 /* in ignore, it means to ignore value, just parse */ | |
18 | #define NOGLOB 2 /* in ignore, it means not to globone */ | |
19 | ||
20 | #define ADDOP 1 | |
21 | #define MULOP 2 | |
22 | #define EQOP 4 | |
23 | #define RELOP 8 | |
24 | #define RESTOP 16 | |
25 | #define ANYOP 31 | |
26 | ||
27 | #define EQEQ 1 | |
28 | #define GTR 2 | |
29 | #define LSS 4 | |
30 | #define NOTEQ 6 | |
31 | #define EQMATCH 7 | |
32 | #define NOTEQMATCH 8 | |
33 | ||
34 | exp(vp) | |
35 | register char ***vp; | |
36 | { | |
37 | ||
38 | return (exp0(vp, 0)); | |
39 | } | |
40 | ||
41 | exp0(vp, ignore) | |
42 | register char ***vp; | |
43 | bool ignore; | |
44 | { | |
45 | register int p1 = exp1(vp, ignore); | |
46 | ||
47 | #ifdef EDEBUG | |
48 | etraci("exp0 p1", p1, vp); | |
49 | #endif | |
50 | if (**vp && eq(**vp, "||")) { | |
51 | register int p2; | |
52 | ||
53 | (*vp)++; | |
54 | p2 = exp0(vp, (ignore&IGNORE) || p1); | |
55 | #ifdef EDEBUG | |
56 | etraci("exp0 p2", p2, vp); | |
57 | #endif | |
58 | return (p1 || p2); | |
59 | } | |
60 | return (p1); | |
61 | } | |
62 | ||
63 | exp1(vp, ignore) | |
64 | register char ***vp; | |
65 | { | |
66 | register int p1 = exp2(vp, ignore); | |
67 | ||
68 | #ifdef EDEBUG | |
69 | etraci("exp1 p1", p1, vp); | |
70 | #endif | |
71 | if (**vp && eq(**vp, "&&")) { | |
72 | register int p2; | |
73 | ||
74 | (*vp)++; | |
75 | p2 = exp1(vp, (ignore&IGNORE) || !p1); | |
76 | #ifdef EDEBUG | |
77 | etraci("exp1 p2", p2, vp); | |
78 | #endif | |
79 | return (p1 && p2); | |
80 | } | |
81 | return (p1); | |
82 | } | |
83 | ||
84 | exp2(vp, ignore) | |
85 | register char ***vp; | |
86 | bool ignore; | |
87 | { | |
88 | register int p1 = exp2a(vp, ignore); | |
89 | ||
90 | #ifdef EDEBUG | |
91 | etraci("exp3 p1", p1, vp); | |
92 | #endif | |
93 | if (**vp && eq(**vp, "|")) { | |
94 | register int p2; | |
95 | ||
96 | (*vp)++; | |
97 | p2 = exp2(vp, ignore); | |
98 | #ifdef EDEBUG | |
99 | etraci("exp3 p2", p2, vp); | |
100 | #endif | |
101 | return (p1 | p2); | |
102 | } | |
103 | return (p1); | |
104 | } | |
105 | ||
106 | exp2a(vp, ignore) | |
107 | register char ***vp; | |
108 | bool ignore; | |
109 | { | |
110 | register int p1 = exp2b(vp, ignore); | |
111 | ||
112 | #ifdef EDEBUG | |
113 | etraci("exp2a p1", p1, vp); | |
114 | #endif | |
115 | if (**vp && eq(**vp, "^")) { | |
116 | register int p2; | |
117 | ||
118 | (*vp)++; | |
119 | p2 = exp2a(vp, ignore); | |
120 | #ifdef EDEBUG | |
121 | etraci("exp2a p2", p2, vp); | |
122 | #endif | |
123 | return (p1 ^ p2); | |
124 | } | |
125 | return (p1); | |
126 | } | |
127 | ||
128 | exp2b(vp, ignore) | |
129 | register char ***vp; | |
130 | bool ignore; | |
131 | { | |
132 | register int p1 = exp2c(vp, ignore); | |
133 | ||
134 | #ifdef EDEBUG | |
135 | etraci("exp2b p1", p1, vp); | |
136 | #endif | |
137 | if (**vp && eq(**vp, "&")) { | |
138 | register int p2; | |
139 | ||
140 | (*vp)++; | |
141 | p2 = exp2b(vp, ignore); | |
142 | #ifdef EDEBUG | |
143 | etraci("exp2b p2", p2, vp); | |
144 | #endif | |
145 | return (p1 & p2); | |
146 | } | |
147 | return (p1); | |
148 | } | |
149 | ||
150 | exp2c(vp, ignore) | |
151 | register char ***vp; | |
152 | bool ignore; | |
153 | { | |
154 | register char *p1 = exp3(vp, ignore); | |
155 | register char *p2; | |
156 | register int i; | |
157 | ||
158 | #ifdef EDEBUG | |
159 | etracc("exp2c p1", p1, vp); | |
160 | #endif | |
161 | if (i = isa(**vp, EQOP)) { | |
162 | (*vp)++; | |
163 | if (i == EQMATCH || i == NOTEQMATCH) | |
164 | ignore |= NOGLOB; | |
165 | p2 = exp3(vp, ignore); | |
166 | #ifdef EDEBUG | |
167 | etracc("exp2c p2", p2, vp); | |
168 | #endif | |
169 | if (!(ignore&IGNORE)) switch (i) { | |
170 | ||
171 | case EQEQ: | |
172 | i = eq(p1, p2); | |
173 | break; | |
174 | ||
175 | case NOTEQ: | |
176 | i = !eq(p1, p2); | |
177 | break; | |
178 | ||
179 | case EQMATCH: | |
180 | i = Gmatch(p1, p2); | |
181 | break; | |
182 | ||
183 | case NOTEQMATCH: | |
184 | i = !Gmatch(p1, p2); | |
185 | break; | |
186 | } | |
187 | xfree(p1), xfree(p2); | |
188 | return (i); | |
189 | } | |
190 | i = egetn(p1); | |
191 | xfree(p1); | |
192 | return (i); | |
193 | } | |
194 | ||
195 | char * | |
196 | exp3(vp, ignore) | |
197 | register char ***vp; | |
198 | bool ignore; | |
199 | { | |
200 | register char *p1, *p2; | |
201 | register int i; | |
202 | ||
203 | p1 = exp3a(vp, ignore); | |
204 | #ifdef EDEBUG | |
205 | etracc("exp3 p1", p1, vp); | |
206 | #endif | |
207 | if (i = isa(**vp, RELOP)) { | |
208 | (*vp)++; | |
209 | if (**vp && eq(**vp, "=")) | |
210 | i |= 1, (*vp)++; | |
211 | p2 = exp3(vp, ignore); | |
212 | #ifdef EDEBUG | |
213 | etracc("exp3 p2", p2, vp); | |
214 | #endif | |
215 | if (!(ignore&IGNORE)) switch (i) { | |
216 | ||
217 | case GTR: | |
218 | i = egetn(p1) > egetn(p2); | |
219 | break; | |
220 | ||
221 | case GTR|1: | |
222 | i = egetn(p1) >= egetn(p2); | |
223 | break; | |
224 | ||
225 | case LSS: | |
226 | i = egetn(p1) < egetn(p2); | |
227 | break; | |
228 | ||
229 | case LSS|1: | |
230 | i = egetn(p1) <= egetn(p2); | |
231 | break; | |
232 | } | |
233 | xfree(p1), xfree(p2); | |
234 | return (putn(i)); | |
235 | } | |
236 | return (p1); | |
237 | } | |
238 | ||
239 | char * | |
240 | exp3a(vp, ignore) | |
241 | register char ***vp; | |
242 | bool ignore; | |
243 | { | |
244 | register char *p1, *p2, *op; | |
245 | register int i; | |
246 | ||
247 | p1 = exp4(vp, ignore); | |
248 | #ifdef EDEBUG | |
249 | etracc("exp3a p1", p1, vp); | |
250 | #endif | |
251 | op = **vp; | |
252 | if (op && any(op[0], "<>") && op[0] == op[1]) { | |
253 | (*vp)++; | |
254 | p2 = exp3a(vp, ignore); | |
255 | #ifdef EDEBUG | |
256 | etracc("exp3a p2", p2, vp); | |
257 | #endif | |
258 | if (op[0] == '<') | |
259 | i = egetn(p1) << egetn(p2); | |
260 | else | |
261 | i = egetn(p1) >> egetn(p2); | |
262 | xfree(p1), xfree(p2); | |
263 | return (putn(i)); | |
264 | } | |
265 | return (p1); | |
266 | } | |
267 | ||
268 | char * | |
269 | exp4(vp, ignore) | |
270 | register char ***vp; | |
271 | bool ignore; | |
272 | { | |
273 | register char *p1, *p2; | |
274 | register int i = 0; | |
275 | ||
276 | p1 = exp5(vp, ignore); | |
277 | #ifdef EDEBUG | |
278 | etracc("exp4 p1", p1, vp); | |
279 | #endif | |
280 | if (isa(**vp, ADDOP)) { | |
281 | register char *op = *(*vp)++; | |
282 | ||
283 | p2 = exp4(vp, ignore); | |
284 | #ifdef EDEBUG | |
285 | etracc("exp4 p2", p2, vp); | |
286 | #endif | |
287 | if (!(ignore&IGNORE)) switch (op[0]) { | |
288 | ||
289 | case '+': | |
290 | i = egetn(p1) + egetn(p2); | |
291 | break; | |
292 | ||
293 | case '-': | |
294 | i = egetn(p1) - egetn(p2); | |
295 | break; | |
296 | } | |
297 | xfree(p1), xfree(p2); | |
298 | return (putn(i)); | |
299 | } | |
300 | return (p1); | |
301 | } | |
302 | ||
303 | char * | |
304 | exp5(vp, ignore) | |
305 | register char ***vp; | |
306 | bool ignore; | |
307 | { | |
308 | register char *p1, *p2; | |
309 | register int i = 0; | |
310 | ||
311 | p1 = exp6(vp, ignore); | |
312 | #ifdef EDEBUG | |
313 | etracc("exp5 p1", p1, vp); | |
314 | #endif | |
315 | if (isa(**vp, MULOP)) { | |
316 | register char *op = *(*vp)++; | |
317 | ||
318 | p2 = exp5(vp, ignore); | |
319 | #ifdef EDEBUG | |
320 | etracc("exp5 p2", p2, vp); | |
321 | #endif | |
322 | if (!(ignore&IGNORE)) switch (op[0]) { | |
323 | ||
324 | case '*': | |
325 | i = egetn(p1) * egetn(p2); | |
326 | break; | |
327 | ||
328 | case '/': | |
329 | i = egetn(p2); | |
330 | if (i == 0) | |
331 | error("Divide by 0"); | |
332 | i = egetn(p1) / i; | |
333 | break; | |
334 | ||
335 | case '%': | |
336 | i = egetn(p2); | |
337 | if (i == 0) | |
338 | error("Mod by 0"); | |
339 | i = egetn(p1) % i; | |
340 | break; | |
341 | } | |
342 | xfree(p1), xfree(p2); | |
343 | return (putn(i)); | |
344 | } | |
345 | return (p1); | |
346 | } | |
347 | ||
348 | char * | |
349 | exp6(vp, ignore) | |
350 | register char ***vp; | |
351 | { | |
352 | int ccode, i; | |
353 | register char *cp, *dp, *ep; | |
354 | ||
220a00f7 KM |
355 | if (**vp == 0) |
356 | bferr("Expression syntax"); | |
843d5d49 BJ |
357 | if (eq(**vp, "!")) { |
358 | (*vp)++; | |
359 | cp = exp6(vp, ignore); | |
360 | #ifdef EDEBUG | |
361 | etracc("exp6 ! cp", cp, vp); | |
362 | #endif | |
363 | i = egetn(cp); | |
364 | xfree(cp); | |
365 | return (putn(!i)); | |
366 | } | |
367 | if (eq(**vp, "~")) { | |
368 | (*vp)++; | |
369 | cp = exp6(vp, ignore); | |
370 | #ifdef EDEBUG | |
371 | etracc("exp6 ~ cp", cp, vp); | |
372 | #endif | |
373 | i = egetn(cp); | |
374 | xfree(cp); | |
375 | return (putn(~i)); | |
376 | } | |
377 | if (eq(**vp, "(")) { | |
378 | (*vp)++; | |
379 | ccode = exp0(vp, ignore); | |
380 | #ifdef EDEBUG | |
381 | etraci("exp6 () ccode", ccode, vp); | |
382 | #endif | |
383 | if (*vp == 0 || **vp == 0 || ***vp != ')') | |
384 | bferr("Expression syntax"); | |
385 | (*vp)++; | |
386 | return (putn(ccode)); | |
387 | } | |
388 | if (eq(**vp, "{")) { | |
389 | register char **v; | |
390 | struct command faket; | |
391 | char *fakecom[2]; | |
392 | ||
393 | faket.t_dtyp = TCOM; | |
394 | faket.t_dflg = 0; | |
395 | faket.t_dcar = faket.t_dcdr = faket.t_dspr = (struct command *)0; | |
396 | faket.t_dcom = fakecom; | |
397 | fakecom[0] = "{ ... }"; | |
398 | fakecom[1] = NOSTR; | |
399 | (*vp)++; | |
400 | v = *vp; | |
401 | for (;;) { | |
402 | if (!**vp) | |
403 | bferr("Missing }"); | |
404 | if (eq(*(*vp)++, "}")) | |
405 | break; | |
406 | } | |
407 | if (ignore&IGNORE) | |
408 | return (""); | |
409 | psavejob(); | |
410 | if (pfork(&faket, -1) == 0) { | |
411 | *--(*vp) = 0; | |
412 | evalav(v); | |
413 | exitstat(); | |
414 | } | |
415 | pwait(); | |
416 | prestjob(); | |
417 | #ifdef EDEBUG | |
418 | etraci("exp6 {} status", egetn(value("status")), vp); | |
419 | #endif | |
420 | return (putn(egetn(value("status")) == 0)); | |
421 | } | |
422 | if (isa(**vp, ANYOP)) | |
423 | return (""); | |
424 | cp = *(*vp)++; | |
425 | if (*cp == '-' && any(cp[1], "erwxfdzo")) { | |
426 | struct stat stb; | |
427 | ||
428 | if (isa(**vp, ANYOP)) | |
429 | bferr("Missing file name"); | |
430 | dp = *(*vp)++; | |
431 | if (ignore&IGNORE) | |
432 | return (""); | |
433 | ep = globone(dp); | |
434 | switch (cp[1]) { | |
435 | ||
436 | case 'r': | |
437 | i = !access(ep, 4); | |
438 | break; | |
439 | ||
440 | case 'w': | |
441 | i = !access(ep, 2); | |
442 | break; | |
443 | ||
444 | case 'x': | |
445 | i = !access(ep, 1); | |
446 | break; | |
447 | ||
448 | default: | |
449 | if (stat(ep, &stb)) { | |
450 | xfree(ep); | |
451 | return ("0"); | |
452 | } | |
453 | switch (cp[1]) { | |
454 | ||
455 | case 'f': | |
456 | i = (stb.st_mode & S_IFMT) == S_IFREG; | |
457 | break; | |
458 | ||
459 | case 'd': | |
460 | i = (stb.st_mode & S_IFMT) == S_IFDIR; | |
461 | break; | |
462 | ||
463 | case 'z': | |
464 | i = stb.st_size == 0; | |
465 | break; | |
466 | ||
467 | case 'e': | |
468 | i = 1; | |
469 | break; | |
470 | ||
471 | case 'o': | |
472 | i = stb.st_uid == uid; | |
473 | break; | |
474 | } | |
475 | } | |
476 | #ifdef EDEBUG | |
477 | etraci("exp6 -? i", i, vp); | |
478 | #endif | |
479 | xfree(ep); | |
480 | return (putn(i)); | |
481 | } | |
482 | #ifdef EDEBUG | |
483 | etracc("exp6 default", cp, vp); | |
484 | #endif | |
24f22c48 | 485 | return (ignore&NOGLOB ? savestr(cp) : globone(cp)); |
843d5d49 BJ |
486 | } |
487 | ||
488 | evalav(v) | |
489 | register char **v; | |
490 | { | |
491 | struct wordent paraml; | |
492 | register struct wordent *hp = ¶ml; | |
493 | struct command *t; | |
494 | register struct wordent *wdp = hp; | |
495 | ||
496 | set("status", "0"); | |
497 | hp->prev = hp->next = hp; | |
498 | hp->word = ""; | |
499 | while (*v) { | |
500 | register struct wordent *new = (struct wordent *) calloc(1, sizeof *wdp); | |
501 | ||
502 | new->prev = wdp; | |
503 | new->next = hp; | |
504 | wdp->next = new; | |
505 | wdp = new; | |
506 | wdp->word = savestr(*v++); | |
507 | } | |
508 | hp->prev = wdp; | |
509 | alias(¶ml); | |
510 | t = syntax(paraml.next, ¶ml, 0); | |
511 | if (err) | |
512 | error(err); | |
513 | execute(t, -1); | |
514 | freelex(¶ml), freesyn(t); | |
515 | } | |
516 | ||
517 | isa(cp, what) | |
518 | register char *cp; | |
519 | register int what; | |
520 | { | |
521 | ||
522 | if (cp == 0) | |
523 | return ((what & RESTOP) != 0); | |
524 | if (cp[1] == 0) { | |
35371dec | 525 | if (what & ADDOP && (*cp == '+' || *cp == '-')) |
843d5d49 | 526 | return (1); |
35371dec | 527 | if (what & MULOP && (*cp == '*' || *cp == '/' || *cp == '%')) |
843d5d49 | 528 | return (1); |
35371dec EW |
529 | if (what & RESTOP && (*cp == '(' || *cp == ')' || *cp == '!' || |
530 | *cp == '~' || *cp == '^' || *cp == '"')) | |
843d5d49 | 531 | return (1); |
35371dec EW |
532 | } else if (cp[2] == 0) { |
533 | if (what & RESTOP) { | |
534 | if (cp[0] == '|' && cp[1] == '&') | |
535 | return (1); | |
536 | if (cp[0] == '<' && cp[1] == '<') | |
537 | return (1); | |
538 | if (cp[0] == '>' && cp[1] == '>') | |
539 | return (1); | |
540 | } | |
541 | if (what & EQOP) { | |
542 | if (cp[0] == '=') { | |
543 | if (cp[1] == '=') | |
544 | return (EQEQ); | |
545 | if (cp[1] == '~') | |
546 | return (EQMATCH); | |
547 | } else if (cp[0] == '!') { | |
548 | if (cp[1] == '=') | |
549 | return (NOTEQ); | |
550 | if (cp[1] == '~') | |
551 | return (NOTEQMATCH); | |
552 | } | |
553 | } | |
843d5d49 | 554 | } |
35371dec EW |
555 | if (what & RELOP) { |
556 | if (*cp == '<') | |
557 | return (LSS); | |
558 | if (*cp == '>') | |
559 | return (GTR); | |
843d5d49 | 560 | } |
843d5d49 BJ |
561 | return (0); |
562 | } | |
563 | ||
564 | egetn(cp) | |
565 | register char *cp; | |
566 | { | |
567 | ||
568 | if (*cp && *cp != '-' && !digit(*cp)) | |
569 | bferr("Expression syntax"); | |
570 | return (getn(cp)); | |
571 | } | |
572 | ||
573 | /* Phew! */ | |
574 | ||
575 | #ifdef EDEBUG | |
576 | etraci(str, i, vp) | |
577 | char *str; | |
578 | int i; | |
579 | char ***vp; | |
580 | { | |
581 | ||
582 | printf("%s=%d\t", str, i); | |
583 | blkpr(*vp); | |
584 | printf("\n"); | |
585 | } | |
586 | ||
587 | etracc(str, cp, vp) | |
588 | char *str, *cp; | |
589 | char ***vp; | |
590 | { | |
591 | ||
592 | printf("%s=%s\t", str, cp); | |
593 | blkpr(*vp); | |
594 | printf("\n"); | |
595 | } | |
596 | #endif |