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