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