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