date and time created 91/03/14 12:01:54 by donn
[unix-history] / usr / src / bin / csh / exp.c
CommitLineData
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 8static 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
34exp(vp)
35 register char ***vp;
36{
37
38 return (exp0(vp, 0));
39}
40
41exp0(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
63exp1(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
84exp2(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
106exp2a(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
128exp2b(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
150exp2c(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
195char *
196exp3(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
239char *
240exp3a(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
268char *
269exp4(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
303char *
304exp5(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
348char *
349exp6(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
488evalav(v)
489 register char **v;
490{
491 struct wordent paraml;
492 register struct wordent *hp = &paraml;
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(&paraml);
510 t = syntax(paraml.next, &paraml, 0);
511 if (err)
512 error(err);
513 execute(t, -1);
514 freelex(&paraml), freesyn(t);
515}
516
517isa(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
564egetn(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
576etraci(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
587etracc(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