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