consistency with tty.c about value for "no pgrp"
[unix-history] / usr / src / bin / csh / exp.c
CommitLineData
ecc449eb
KB
1/*-
2 * Copyright (c) 1980, 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.redist.c%
b79f4fa9
DF
6 */
7
35371dec 8#ifndef lint
6e37afca 9static char sccsid[] = "@(#)exp.c 5.7 (Berkeley) %G%";
ecc449eb 10#endif /* not lint */
843d5d49
BJ
11
12#include "sh.h"
13
843d5d49
BJ
14#define IGNORE 1 /* in ignore, it means to ignore value, just parse */
15#define NOGLOB 2 /* in ignore, it means not to globone */
16
17#define ADDOP 1
18#define MULOP 2
19#define EQOP 4
20#define RELOP 8
21#define RESTOP 16
22#define ANYOP 31
23
24#define EQEQ 1
25#define GTR 2
26#define LSS 4
27#define NOTEQ 6
28#define EQMATCH 7
29#define NOTEQMATCH 8
30
6e37afca
KB
31static int exp1();
32static int exp2();
33static int exp2a();
34static int exp2b();
35static int exp2c();
36static Char *exp3();
37static Char *exp3a();
38static Char *exp4();
39static Char *exp5();
40static Char *exp6();
41static void evalav();
42static int isa();
43static int egetn();
44
45#ifdef EDEBUG
46static void etracc();
47static void etraci();
48#endif
49
50int
843d5d49 51exp(vp)
6e37afca 52 register Char ***vp;
843d5d49 53{
6e37afca 54 return (exp0(vp, 0));
843d5d49
BJ
55}
56
6e37afca 57int
843d5d49 58exp0(vp, ignore)
6e37afca
KB
59 register Char ***vp;
60 bool ignore;
843d5d49 61{
6e37afca
KB
62 register int p1 = exp1(vp, ignore);
63
843d5d49 64#ifdef EDEBUG
6e37afca 65 etraci("exp0 p1", p1, vp);
843d5d49 66#endif
6e37afca
KB
67 if (**vp && eq(**vp, STRor2)) {
68 register int p2;
843d5d49 69
6e37afca
KB
70 (*vp)++;
71 p2 = exp0(vp, (ignore & IGNORE) || p1);
843d5d49 72#ifdef EDEBUG
6e37afca 73 etraci("exp0 p2", p2, vp);
843d5d49 74#endif
6e37afca
KB
75 return (p1 || p2);
76 }
77 return (p1);
843d5d49
BJ
78}
79
6e37afca 80static int
843d5d49 81exp1(vp, ignore)
6e37afca
KB
82 register Char ***vp;
83 bool ignore;
843d5d49 84{
6e37afca 85 register int p1 = exp2(vp, ignore);
843d5d49
BJ
86
87#ifdef EDEBUG
6e37afca 88 etraci("exp1 p1", p1, vp);
843d5d49 89#endif
6e37afca
KB
90 if (**vp && eq(**vp, STRand2)) {
91 register int p2;
843d5d49 92
6e37afca
KB
93 (*vp)++;
94 p2 = exp1(vp, (ignore & IGNORE) || !p1);
843d5d49 95#ifdef EDEBUG
6e37afca 96 etraci("exp1 p2", p2, vp);
843d5d49 97#endif
6e37afca
KB
98 return (p1 && p2);
99 }
100 return (p1);
843d5d49
BJ
101}
102
6e37afca 103static int
843d5d49 104exp2(vp, ignore)
6e37afca
KB
105 register Char ***vp;
106 bool ignore;
843d5d49 107{
6e37afca 108 register int p1 = exp2a(vp, ignore);
843d5d49
BJ
109
110#ifdef EDEBUG
6e37afca 111 etraci("exp3 p1", p1, vp);
843d5d49 112#endif
6e37afca
KB
113 if (**vp && eq(**vp, STRor)) {
114 register int p2;
843d5d49 115
6e37afca
KB
116 (*vp)++;
117 p2 = exp2(vp, ignore);
843d5d49 118#ifdef EDEBUG
6e37afca 119 etraci("exp3 p2", p2, vp);
843d5d49 120#endif
6e37afca
KB
121 return (p1 | p2);
122 }
123 return (p1);
843d5d49
BJ
124}
125
6e37afca 126static int
843d5d49 127exp2a(vp, ignore)
6e37afca
KB
128 register Char ***vp;
129 bool ignore;
843d5d49 130{
6e37afca 131 register int p1 = exp2b(vp, ignore);
843d5d49
BJ
132
133#ifdef EDEBUG
6e37afca 134 etraci("exp2a p1", p1, vp);
843d5d49 135#endif
6e37afca
KB
136 if (**vp && eq(**vp, STRcaret)) {
137 register int p2;
843d5d49 138
6e37afca
KB
139 (*vp)++;
140 p2 = exp2a(vp, ignore);
843d5d49 141#ifdef EDEBUG
6e37afca 142 etraci("exp2a p2", p2, vp);
843d5d49 143#endif
6e37afca
KB
144 return (p1 ^ p2);
145 }
146 return (p1);
843d5d49
BJ
147}
148
6e37afca 149static int
843d5d49 150exp2b(vp, ignore)
6e37afca
KB
151 register Char ***vp;
152 bool ignore;
843d5d49 153{
6e37afca 154 register int p1 = exp2c(vp, ignore);
843d5d49
BJ
155
156#ifdef EDEBUG
6e37afca 157 etraci("exp2b p1", p1, vp);
843d5d49 158#endif
6e37afca
KB
159 if (**vp && eq(**vp, STRand)) {
160 register int p2;
843d5d49 161
6e37afca
KB
162 (*vp)++;
163 p2 = exp2b(vp, ignore);
843d5d49 164#ifdef EDEBUG
6e37afca 165 etraci("exp2b p2", p2, vp);
843d5d49 166#endif
6e37afca
KB
167 return (p1 & p2);
168 }
169 return (p1);
843d5d49
BJ
170}
171
6e37afca 172static int
843d5d49 173exp2c(vp, ignore)
6e37afca
KB
174 register Char ***vp;
175 bool ignore;
843d5d49 176{
6e37afca
KB
177 register Char *p1 = exp3(vp, ignore);
178 register Char *p2;
179 register int i;
843d5d49
BJ
180
181#ifdef EDEBUG
6e37afca 182 etracc("exp2c p1", p1, vp);
843d5d49 183#endif
6e37afca
KB
184 if (i = isa(**vp, EQOP)) {
185 (*vp)++;
186 if (i == EQMATCH || i == NOTEQMATCH)
187 ignore |= NOGLOB;
188 p2 = exp3(vp, ignore);
843d5d49 189#ifdef EDEBUG
6e37afca 190 etracc("exp2c p2", p2, vp);
843d5d49 191#endif
6e37afca
KB
192 if (!(ignore & IGNORE))
193 switch (i) {
194
195 case EQEQ:
196 i = eq(p1, p2);
197 break;
198
199 case NOTEQ:
200 i = !eq(p1, p2);
201 break;
202
203 case EQMATCH:
204 i = Gmatch(p1, p2);
205 break;
206
207 case NOTEQMATCH:
208 i = !Gmatch(p1, p2);
209 break;
210 }
211 xfree((ptr_t) p1);
212 xfree((ptr_t) p2);
843d5d49 213 return (i);
6e37afca
KB
214 }
215 i = egetn(p1);
216 xfree((ptr_t) p1);
217 return (i);
843d5d49
BJ
218}
219
6e37afca 220static Char *
843d5d49 221exp3(vp, ignore)
6e37afca
KB
222 register Char ***vp;
223 bool ignore;
843d5d49 224{
6e37afca
KB
225 register Char *p1, *p2;
226 register int i;
843d5d49 227
6e37afca 228 p1 = exp3a(vp, ignore);
843d5d49 229#ifdef EDEBUG
6e37afca 230 etracc("exp3 p1", p1, vp);
843d5d49 231#endif
6e37afca
KB
232 if (i = isa(**vp, RELOP)) {
233 (*vp)++;
234 if (**vp && eq(**vp, STRequal))
235 i |= 1, (*vp)++;
236 p2 = exp3(vp, ignore);
843d5d49 237#ifdef EDEBUG
6e37afca 238 etracc("exp3 p2", p2, vp);
843d5d49 239#endif
6e37afca
KB
240 if (!(ignore & IGNORE))
241 switch (i) {
242
243 case GTR:
244 i = egetn(p1) > egetn(p2);
245 break;
246
247 case GTR | 1:
248 i = egetn(p1) >= egetn(p2);
249 break;
250
251 case LSS:
252 i = egetn(p1) < egetn(p2);
253 break;
254
255 case LSS | 1:
256 i = egetn(p1) <= egetn(p2);
257 break;
258 }
259 xfree((ptr_t) p1);
260 xfree((ptr_t) p2);
261 return (putn(i));
262 }
263 return (p1);
843d5d49
BJ
264}
265
6e37afca 266static Char *
843d5d49 267exp3a(vp, ignore)
6e37afca
KB
268 register Char ***vp;
269 bool ignore;
843d5d49 270{
6e37afca
KB
271 register Char *p1, *p2, *op;
272 register int i;
843d5d49 273
6e37afca 274 p1 = exp4(vp, ignore);
843d5d49 275#ifdef EDEBUG
6e37afca 276 etracc("exp3a p1", p1, vp);
843d5d49 277#endif
6e37afca
KB
278 op = **vp;
279 if (op && any("<>", op[0]) && op[0] == op[1]) {
280 (*vp)++;
281 p2 = exp3a(vp, ignore);
843d5d49 282#ifdef EDEBUG
6e37afca
KB
283 etracc("exp3a p2", p2, vp);
284#endif
285 if (op[0] == '<')
286 i = egetn(p1) << egetn(p2);
287 else
288 i = egetn(p1) >> egetn(p2);
289 xfree((ptr_t) p1);
290 xfree((ptr_t) p2);
291 return (putn(i));
292 }
293 return (p1);
843d5d49
BJ
294}
295
6e37afca 296static Char *
843d5d49 297exp4(vp, ignore)
6e37afca
KB
298 register Char ***vp;
299 bool ignore;
843d5d49 300{
6e37afca
KB
301 register Char *p1, *p2;
302 register int i = 0;
843d5d49 303
6e37afca 304 p1 = exp5(vp, ignore);
843d5d49 305#ifdef EDEBUG
6e37afca 306 etracc("exp4 p1", p1, vp);
843d5d49 307#endif
6e37afca
KB
308 if (isa(**vp, ADDOP)) {
309 register Char *op = *(*vp)++;
843d5d49 310
6e37afca 311 p2 = exp4(vp, ignore);
843d5d49 312#ifdef EDEBUG
6e37afca 313 etracc("exp4 p2", p2, vp);
843d5d49 314#endif
6e37afca
KB
315 if (!(ignore & IGNORE))
316 switch (op[0]) {
317
318 case '+':
319 i = egetn(p1) + egetn(p2);
320 break;
321
322 case '-':
323 i = egetn(p1) - egetn(p2);
324 break;
325 }
326 xfree((ptr_t) p1);
327 xfree((ptr_t) p2);
328 return (putn(i));
329 }
330 return (p1);
843d5d49
BJ
331}
332
6e37afca 333static Char *
843d5d49 334exp5(vp, ignore)
6e37afca
KB
335 register Char ***vp;
336 bool ignore;
843d5d49 337{
6e37afca
KB
338 register Char *p1, *p2;
339 register int i = 0;
843d5d49 340
6e37afca 341 p1 = exp6(vp, ignore);
843d5d49 342#ifdef EDEBUG
6e37afca 343 etracc("exp5 p1", p1, vp);
843d5d49 344#endif
6e37afca
KB
345 if (isa(**vp, MULOP)) {
346 register Char *op = *(*vp)++;
843d5d49 347
6e37afca 348 p2 = exp5(vp, ignore);
843d5d49 349#ifdef EDEBUG
6e37afca
KB
350 etracc("exp5 p2", p2, vp);
351#endif
352 if (!(ignore & IGNORE))
353 switch (op[0]) {
354
355 case '*':
356 i = egetn(p1) * egetn(p2);
357 break;
358
359 case '/':
360 i = egetn(p2);
361 if (i == 0)
362 stderror(ERR_DIV0);
363 i = egetn(p1) / i;
364 break;
365
366 case '%':
367 i = egetn(p2);
368 if (i == 0)
369 stderror(ERR_MOD0);
370 i = egetn(p1) % i;
371 break;
372 }
373 xfree((ptr_t) p1);
374 xfree((ptr_t) p2);
375 return (putn(i));
376 }
377 return (p1);
843d5d49
BJ
378}
379
6e37afca 380static Char *
843d5d49 381exp6(vp, ignore)
6e37afca
KB
382 register Char ***vp;
383 bool ignore;
843d5d49 384{
6e37afca
KB
385 int ccode, i = 0;
386 register Char *cp, *dp, *ep;
387
388 if (**vp == 0)
389 stderror(ERR_NAME | ERR_EXPRESSION);
390 if (eq(**vp, STRbang)) {
391 (*vp)++;
392 cp = exp6(vp, ignore);
843d5d49 393#ifdef EDEBUG
6e37afca 394 etracc("exp6 ! cp", cp, vp);
843d5d49 395#endif
6e37afca
KB
396 i = egetn(cp);
397 xfree((ptr_t) cp);
398 return (putn(!i));
399 }
400 if (eq(**vp, STRtilde)) {
401 (*vp)++;
402 cp = exp6(vp, ignore);
843d5d49 403#ifdef EDEBUG
6e37afca 404 etracc("exp6 ~ cp", cp, vp);
843d5d49 405#endif
6e37afca
KB
406 i = egetn(cp);
407 xfree((ptr_t) cp);
408 return (putn(~i));
409 }
410 if (eq(**vp, STRLparen)) {
411 (*vp)++;
412 ccode = exp0(vp, ignore);
843d5d49 413#ifdef EDEBUG
6e37afca 414 etraci("exp6 () ccode", ccode, vp);
843d5d49 415#endif
6e37afca
KB
416 if (*vp == 0 || **vp == 0 || ***vp != ')')
417 stderror(ERR_NAME | ERR_EXPRESSION);
418 (*vp)++;
419 return (putn(ccode));
420 }
421 if (eq(**vp, STRLbrace)) {
422 register Char **v;
423 struct command faket;
424 Char *fakecom[2];
425
426 faket.t_dtyp = NODE_COMMAND;
427 faket.t_dflg = 0;
428 faket.t_dcar = faket.t_dcdr = faket.t_dspr =
429 (struct command *) 0;
430 faket.t_dcom = fakecom;
431 fakecom[0] = STRfakecom;
432 fakecom[1] = NULL;
433 (*vp)++;
434 v = *vp;
435 for (;;) {
436 if (!**vp)
437 stderror(ERR_NAME | ERR_MISSING, '}');
438 if (eq(*(*vp)++, STRRbrace))
439 break;
440 }
441 if (ignore & IGNORE)
442 return (Strsave(STRNULL));
443 psavejob();
444 if (pfork(&faket, -1) == 0) {
445 *--(*vp) = 0;
446 evalav(v);
447 exitstat();
843d5d49 448 }
6e37afca
KB
449 pwait();
450 prestjob();
843d5d49 451#ifdef EDEBUG
6e37afca
KB
452 etraci("exp6 {} status", egetn(value(STRstatus)), vp);
453#endif
454 return (putn(egetn(value(STRstatus)) == 0));
455 }
456 if (isa(**vp, ANYOP))
457 return (Strsave(STRNULL));
458 cp = *(*vp)++;
459 if (*cp == '-' && any("erwxfdzopls", cp[1])) {
460 struct stat stb;
461
462 if (cp[2] != '\0')
463 stderror(ERR_NAME | ERR_FILEINQ);
464 /*
465 * Detect missing file names by checking for operator in the file name
466 * position. However, if an operator name appears there, we must make
467 * sure that there's no file by that name (e.g., "/") before announcing
468 * an error. Even this check isn't quite right, since it doesn't take
469 * globbing into account.
470 */
471 if (isa(**vp, ANYOP) && stat(short2str(**vp), &stb))
472 stderror(ERR_NAME | ERR_FILENAME);
473
474 dp = *(*vp)++;
475 if (ignore & IGNORE)
476 return (Strsave(STRNULL));
477 ep = globone(dp, G_ERROR);
478 switch (cp[1]) {
479
480 case 'r':
481 i = !access(short2str(ep), R_OK);
482 break;
483
484 case 'w':
485 i = !access(short2str(ep), W_OK);
486 break;
487
488 case 'x':
489 i = !access(short2str(ep), X_OK);
490 break;
491
492 default:
493 if (
494#ifdef S_IFLNK
495 cp[1] == 'l' ? lstat(short2str(ep), &stb) :
496#endif
497 stat(short2str(ep), &stb)) {
498 xfree((ptr_t) ep);
499 return (Strsave(STR0));
500 }
501 switch (cp[1]) {
502
503 case 'f':
504 i = S_ISREG(stb.st_mode);
505 break;
506
507 case 'd':
508 i = S_ISDIR(stb.st_mode);
509 break;
510
511 case 'p':
512#ifdef S_ISFIFO
513 i = S_ISFIFO(stb.st_mode);
514#else
515 i = 0;
516#endif
517 break;
518
519 case 'l':
520#ifdef S_ISLNK
521 i = S_ISLNK(stb.st_mode);
522#else
523 i = 0;
843d5d49 524#endif
6e37afca
KB
525 break;
526
527 case 's':
528#ifdef S_ISSOCK
529 i = S_ISSOCK(stb.st_mode);
530#else
531 i = 0;
532#endif
533 break;
534
535 case 'z':
536 i = stb.st_size == 0;
537 break;
538
539 case 'e':
540 i = 1;
541 break;
542
543 case 'o':
544 i = stb.st_uid == uid;
545 break;
546 }
843d5d49 547 }
843d5d49 548#ifdef EDEBUG
6e37afca 549 etraci("exp6 -? i", i, vp);
843d5d49 550#endif
6e37afca
KB
551 xfree((ptr_t) ep);
552 return (putn(i));
553 }
843d5d49 554#ifdef EDEBUG
6e37afca 555 etracc("exp6 default", cp, vp);
843d5d49 556#endif
6e37afca 557 return (ignore & NOGLOB ? Strsave(cp) : globone(cp, G_ERROR));
843d5d49
BJ
558}
559
6e37afca 560static void
843d5d49 561evalav(v)
6e37afca 562 register Char **v;
843d5d49 563{
6e37afca
KB
564 struct wordent paraml1;
565 register struct wordent *hp = &paraml1;
566 struct command *t;
567 register struct wordent *wdp = hp;
568
569 set(STRstatus, Strsave(STR0));
570 hp->prev = hp->next = hp;
571 hp->word = STRNULL;
572 while (*v) {
573 register struct wordent *new =
574 (struct wordent *) xcalloc(1, sizeof *wdp);
575
576 new->prev = wdp;
577 new->next = hp;
578 wdp->next = new;
579 wdp = new;
580 wdp->word = Strsave(*v++);
581 }
582 hp->prev = wdp;
583 alias(&paraml1);
584 t = syntax(paraml1.next, &paraml1, 0);
585 if (seterr)
586 stderror(ERR_OLD);
587 execute(t, -1);
588 freelex(&paraml1), freesyn(t);
843d5d49
BJ
589}
590
6e37afca 591static int
843d5d49 592isa(cp, what)
6e37afca
KB
593 register Char *cp;
594 register int what;
843d5d49 595{
6e37afca
KB
596 if (cp == 0)
597 return ((what & RESTOP) != 0);
598 if (cp[1] == 0) {
599 if (what & ADDOP && (*cp == '+' || *cp == '-'))
600 return (1);
601 if (what & MULOP && (*cp == '*' || *cp == '/' || *cp == '%'))
602 return (1);
603 if (what & RESTOP && (*cp == '(' || *cp == ')' || *cp == '!' ||
604 *cp == '~' || *cp == '^' || *cp == '"'))
605 return (1);
606 }
607 else if (cp[2] == 0) {
608 if (what & RESTOP) {
609 if (cp[0] == '|' && cp[1] == '&')
610 return (1);
611 if (cp[0] == '<' && cp[1] == '<')
612 return (1);
613 if (cp[0] == '>' && cp[1] == '>')
614 return (1);
843d5d49 615 }
6e37afca
KB
616 if (what & EQOP) {
617 if (cp[0] == '=') {
618 if (cp[1] == '=')
619 return (EQEQ);
620 if (cp[1] == '~')
621 return (EQMATCH);
622 }
623 else if (cp[0] == '!') {
624 if (cp[1] == '=')
625 return (NOTEQ);
626 if (cp[1] == '~')
627 return (NOTEQMATCH);
628 }
843d5d49 629 }
6e37afca
KB
630 }
631 if (what & RELOP) {
632 if (*cp == '<')
633 return (LSS);
634 if (*cp == '>')
635 return (GTR);
636 }
637 return (0);
843d5d49
BJ
638}
639
6e37afca 640static int
843d5d49 641egetn(cp)
6e37afca 642 register Char *cp;
843d5d49 643{
6e37afca
KB
644 if (*cp && *cp != '-' && !Isdigit(*cp))
645 stderror(ERR_NAME | ERR_EXPRESSION);
646 return (getn(cp));
843d5d49
BJ
647}
648
649/* Phew! */
650
651#ifdef EDEBUG
6e37afca 652static void
843d5d49 653etraci(str, i, vp)
6e37afca
KB
654 char *str;
655 int i;
656 Char ***vp;
843d5d49 657{
6e37afca
KB
658 xprintf("%s=%d\t", str, i);
659 blkpr(*vp);
660 xprintf("\n");
843d5d49 661}
6e37afca 662static void
843d5d49 663etracc(str, cp, vp)
6e37afca
KB
664 char *str;
665 Char *cp;
666 Char ***vp;
843d5d49 667{
6e37afca
KB
668 xprintf("%s=%s\t", str, cp);
669 blkpr(*vp);
670 xprintf("\n");
843d5d49
BJ
671}
672#endif