2 * Copyright (c) 1980, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 static char sccsid[] = "@(#)exp.c 8.1 (Berkeley) 5/31/93";
40 #include <sys/types.h>
46 #endif /* SHORT_STRINGS */
56 #define IGNORE 1 /* in ignore, it means to ignore value, just parse */
57 #define NOGLOB 2 /* in ignore, it means not to globone */
73 static int exp1 __P((Char ***, bool));
74 static int exp2 __P((Char ***, bool));
75 static int exp2a __P((Char ***, bool));
76 static int exp2b __P((Char ***, bool));
77 static int exp2c __P((Char ***, bool));
78 static Char * exp3 __P((Char ***, bool));
79 static Char * exp3a __P((Char ***, bool));
80 static Char * exp4 __P((Char ***, bool));
81 static Char * exp5 __P((Char ***, bool));
82 static Char * exp6 __P((Char ***, bool));
83 static void evalav __P((Char **));
84 static int isa __P((Char *, int));
85 static int egetn __P((Char *));
88 static void etracc __P((char *, Char *, Char ***));
89 static void etraci __P((char *, int, Char ***));
104 register int p1 = exp1(vp, ignore);
107 etraci("exp0 p1", p1, vp);
109 if (**vp && eq(**vp, STRor2)) {
113 p2 = exp0(vp, (ignore & IGNORE) || p1);
115 etraci("exp0 p2", p2, vp);
127 register int p1 = exp2(vp, ignore);
130 etraci("exp1 p1", p1, vp);
132 if (**vp && eq(**vp, STRand2)) {
136 p2 = exp1(vp, (ignore & IGNORE) || !p1);
138 etraci("exp1 p2", p2, vp);
150 register int p1 = exp2a(vp, ignore);
153 etraci("exp3 p1", p1, vp);
155 if (**vp && eq(**vp, STRor)) {
159 p2 = exp2(vp, ignore);
161 etraci("exp3 p2", p2, vp);
173 register int p1 = exp2b(vp, ignore);
176 etraci("exp2a p1", p1, vp);
178 if (**vp && eq(**vp, STRcaret)) {
182 p2 = exp2a(vp, ignore);
184 etraci("exp2a p2", p2, vp);
196 register int p1 = exp2c(vp, ignore);
199 etraci("exp2b p1", p1, vp);
201 if (**vp && eq(**vp, STRand)) {
205 p2 = exp2b(vp, ignore);
207 etraci("exp2b p2", p2, vp);
219 register Char *p1 = exp3(vp, ignore);
224 etracc("exp2c p1", p1, vp);
226 if ((i = isa(**vp, EQOP)) != 0) {
228 if (i == EQMATCH || i == NOTEQMATCH)
230 p2 = exp3(vp, ignore);
232 etracc("exp2c p2", p2, vp);
234 if (!(ignore & IGNORE))
267 register Char *p1, *p2;
270 p1 = exp3a(vp, ignore);
272 etracc("exp3 p1", p1, vp);
274 if ((i = isa(**vp, RELOP)) != 0) {
276 if (**vp && eq(**vp, STRequal))
278 p2 = exp3(vp, ignore);
280 etracc("exp3 p2", p2, vp);
282 if (!(ignore & IGNORE))
286 i = egetn(p1) > egetn(p2);
290 i = egetn(p1) >= egetn(p2);
294 i = egetn(p1) < egetn(p2);
298 i = egetn(p1) <= egetn(p2);
313 register Char *p1, *p2, *op;
316 p1 = exp4(vp, ignore);
318 etracc("exp3a p1", p1, vp);
321 if (op && any("<>", op[0]) && op[0] == op[1]) {
323 p2 = exp3a(vp, ignore);
325 etracc("exp3a p2", p2, vp);
328 i = egetn(p1) << egetn(p2);
330 i = egetn(p1) >> egetn(p2);
343 register Char *p1, *p2;
346 p1 = exp5(vp, ignore);
348 etracc("exp4 p1", p1, vp);
350 if (isa(**vp, ADDOP)) {
351 register Char *op = *(*vp)++;
353 p2 = exp4(vp, ignore);
355 etracc("exp4 p2", p2, vp);
357 if (!(ignore & IGNORE))
361 i = egetn(p1) + egetn(p2);
365 i = egetn(p1) - egetn(p2);
380 register Char *p1, *p2;
383 p1 = exp6(vp, ignore);
385 etracc("exp5 p1", p1, vp);
387 if (isa(**vp, MULOP)) {
388 register Char *op = *(*vp)++;
390 p2 = exp5(vp, ignore);
392 etracc("exp5 p2", p2, vp);
394 if (!(ignore & IGNORE))
398 i = egetn(p1) * egetn(p2);
428 register Char *cp, *dp, *ep;
431 stderror(ERR_NAME | ERR_EXPRESSION);
432 if (eq(**vp, STRbang)) {
434 cp = exp6(vp, ignore);
436 etracc("exp6 ! cp", cp, vp);
442 if (eq(**vp, STRtilde)) {
444 cp = exp6(vp, ignore);
446 etracc("exp6 ~ cp", cp, vp);
452 if (eq(**vp, STRLparen)) {
454 ccode = exp0(vp, ignore);
456 etraci("exp6 () ccode", ccode, vp);
458 if (*vp == 0 || **vp == 0 || ***vp != ')')
459 stderror(ERR_NAME | ERR_EXPRESSION);
461 return (putn(ccode));
463 if (eq(**vp, STRLbrace)) {
465 struct command faket;
468 faket.t_dtyp = NODE_COMMAND;
470 faket.t_dcar = faket.t_dcdr = faket.t_dspr = NULL;
471 faket.t_dcom = fakecom;
472 fakecom[0] = STRfakecom;
478 stderror(ERR_NAME | ERR_MISSING, '}');
479 if (eq(*(*vp)++, STRRbrace))
483 return (Strsave(STRNULL));
485 if (pfork(&faket, -1) == 0) {
493 etraci("exp6 {} status", egetn(value(STRstatus)), vp);
495 return (putn(egetn(value(STRstatus)) == 0));
497 if (isa(**vp, ANYOP))
498 return (Strsave(STRNULL));
500 if (*cp == '-' && any("erwxfdzopls", cp[1])) {
504 stderror(ERR_NAME | ERR_FILEINQ);
506 * Detect missing file names by checking for operator in the file name
507 * position. However, if an operator name appears there, we must make
508 * sure that there's no file by that name (e.g., "/") before announcing
509 * an error. Even this check isn't quite right, since it doesn't take
510 * globbing into account.
512 if (isa(**vp, ANYOP) && stat(short2str(**vp), &stb))
513 stderror(ERR_NAME | ERR_FILENAME);
517 return (Strsave(STRNULL));
518 ep = globone(dp, G_ERROR);
522 i = !access(short2str(ep), R_OK);
526 i = !access(short2str(ep), W_OK);
530 i = !access(short2str(ep), X_OK);
536 cp[1] == 'l' ? lstat(short2str(ep), &stb) :
538 stat(short2str(ep), &stb)) {
540 return (Strsave(STR0));
545 i = S_ISREG(stb.st_mode);
549 i = S_ISDIR(stb.st_mode);
554 i = S_ISFIFO(stb.st_mode);
562 i = S_ISLNK(stb.st_mode);
570 i = S_ISSOCK(stb.st_mode);
577 i = stb.st_size == 0;
585 i = stb.st_uid == uid;
590 etraci("exp6 -? i", i, vp);
596 etracc("exp6 default", cp, vp);
598 return (ignore & NOGLOB ? Strsave(cp) : globone(cp, G_ERROR));
605 struct wordent paraml1;
606 register struct wordent *hp = ¶ml1;
608 register struct wordent *wdp = hp;
610 set(STRstatus, Strsave(STR0));
611 hp->prev = hp->next = hp;
614 register struct wordent *new =
615 (struct wordent *) xcalloc(1, sizeof *wdp);
621 wdp->word = Strsave(*v++);
625 t = syntax(paraml1.next, ¶ml1, 0);
628 execute(t, -1, NULL, NULL);
629 freelex(¶ml1), freesyn(t);
638 return ((what & RESTOP) != 0);
640 if (what & ADDOP && (*cp == '+' || *cp == '-'))
642 if (what & MULOP && (*cp == '*' || *cp == '/' || *cp == '%'))
644 if (what & RESTOP && (*cp == '(' || *cp == ')' || *cp == '!' ||
645 *cp == '~' || *cp == '^' || *cp == '"'))
648 else if (cp[2] == 0) {
650 if (cp[0] == '|' && cp[1] == '&')
652 if (cp[0] == '<' && cp[1] == '<')
654 if (cp[0] == '>' && cp[1] == '>')
664 else if (cp[0] == '!') {
685 if (*cp && *cp != '-' && !Isdigit(*cp))
686 stderror(ERR_NAME | ERR_EXPRESSION);
699 (void) fprintf(csherr, "%s=%d\t", str, i);
701 (void) fprintf(csherr, "\n");
709 (void) fprintf(csherr, "%s=%s\t", str, vis_str(cp));
711 (void) fprintf(csherr, "\n");