xref: /netbsd-src/bin/csh/exp.c (revision 1767ce60a2fbaa51b3860ae327733a38db5c12f1)
1*1767ce60Schristos /* $NetBSD: exp.c,v 1.22 2019/01/05 16:54:00 christos Exp $ */
249f0ad86Scgd 
361f28255Scgd /*-
4cee2bad8Smycroft  * Copyright (c) 1980, 1991, 1993
5cee2bad8Smycroft  *	The Regents of the University of California.  All rights reserved.
661f28255Scgd  *
761f28255Scgd  * Redistribution and use in source and binary forms, with or without
861f28255Scgd  * modification, are permitted provided that the following conditions
961f28255Scgd  * are met:
1061f28255Scgd  * 1. Redistributions of source code must retain the above copyright
1161f28255Scgd  *    notice, this list of conditions and the following disclaimer.
1261f28255Scgd  * 2. Redistributions in binary form must reproduce the above copyright
1361f28255Scgd  *    notice, this list of conditions and the following disclaimer in the
1461f28255Scgd  *    documentation and/or other materials provided with the distribution.
15b5b29542Sagc  * 3. Neither the name of the University nor the names of its contributors
1661f28255Scgd  *    may be used to endorse or promote products derived from this software
1761f28255Scgd  *    without specific prior written permission.
1861f28255Scgd  *
1961f28255Scgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2061f28255Scgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2161f28255Scgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2261f28255Scgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2361f28255Scgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2461f28255Scgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2561f28255Scgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2661f28255Scgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2761f28255Scgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2861f28255Scgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2961f28255Scgd  * SUCH DAMAGE.
3061f28255Scgd  */
3161f28255Scgd 
328ea378c6Schristos #include <sys/cdefs.h>
3361f28255Scgd #ifndef lint
3449f0ad86Scgd #if 0
3549f0ad86Scgd static char sccsid[] = "@(#)exp.c	8.1 (Berkeley) 5/31/93";
3649f0ad86Scgd #else
37*1767ce60Schristos __RCSID("$NetBSD: exp.c,v 1.22 2019/01/05 16:54:00 christos Exp $");
3849f0ad86Scgd #endif
3961f28255Scgd #endif /* not lint */
4061f28255Scgd 
4161f28255Scgd #include <sys/types.h>
4261f28255Scgd #include <sys/stat.h>
43b771e65bSwiz 
4418158540Swiz #include <stdarg.h>
4561f28255Scgd #include <stdlib.h>
4661f28255Scgd #include <unistd.h>
47b771e65bSwiz 
48cee2bad8Smycroft #ifndef SHORT_STRINGS
49cee2bad8Smycroft #include <string.h>
50cee2bad8Smycroft #endif /* SHORT_STRINGS */
51b771e65bSwiz 
5261f28255Scgd #include "csh.h"
5361f28255Scgd #include "extern.h"
5461f28255Scgd 
5561f28255Scgd #define IGNORE	1	/* in ignore, it means to ignore value, just parse */
5661f28255Scgd #define NOGLOB	2	/* in ignore, it means not to globone */
5761f28255Scgd 
5861f28255Scgd #define	ADDOP	1
5961f28255Scgd #define	MULOP	2
6061f28255Scgd #define	EQOP	4
6161f28255Scgd #define	RELOP	8
6261f28255Scgd #define	RESTOP	16
6361f28255Scgd #define	ANYOP	31
6461f28255Scgd 
6561f28255Scgd #define	EQEQ	1
6661f28255Scgd #define	GTR	2
6761f28255Scgd #define	LSS	4
6861f28255Scgd #define	NOTEQ	6
6961f28255Scgd #define EQMATCH 7
7061f28255Scgd #define NOTEQMATCH 8
7161f28255Scgd 
72b79c2ef2Schristos static int exp1(Char ***, int);
73b79c2ef2Schristos static int csh_exp2(Char ***, int);
74b79c2ef2Schristos static int exp2a(Char ***, int);
75b79c2ef2Schristos static int exp2b(Char ***, int);
76b79c2ef2Schristos static int exp2c(Char ***, int);
77b79c2ef2Schristos static Char *exp3(Char ***, int);
78b79c2ef2Schristos static Char *exp3a(Char ***, int);
79b79c2ef2Schristos static Char *exp4(Char ***, int);
80b79c2ef2Schristos static Char *exp5(Char ***, int);
81b79c2ef2Schristos static Char *exp6(Char ***, int);
82b771e65bSwiz static void evalav(Char **);
83b771e65bSwiz static int isa(Char *, int);
84b771e65bSwiz static int egetn(Char *);
8561f28255Scgd 
8661f28255Scgd #ifdef EDEBUG
87b771e65bSwiz static void etracc(char *, Char *, Char ***);
88b771e65bSwiz static void etraci(char *, int, Char ***);
8961f28255Scgd #endif
9061f28255Scgd 
9161f28255Scgd int
expr(Char *** vp)92b771e65bSwiz expr(Char ***vp)
9361f28255Scgd {
9461f28255Scgd     return (exp0(vp, 0));
9561f28255Scgd }
9661f28255Scgd 
9761f28255Scgd int
exp0(Char *** vp,int ignore)98b79c2ef2Schristos exp0(Char ***vp, int ignore)
9961f28255Scgd {
100b771e65bSwiz     int p1;
10161f28255Scgd 
102b771e65bSwiz     p1 = exp1(vp, ignore);
10361f28255Scgd #ifdef EDEBUG
10461f28255Scgd     etraci("exp0 p1", p1, vp);
10561f28255Scgd #endif
10661f28255Scgd     if (**vp && eq(**vp, STRor2)) {
10776adbe2bStls 	int p2;
10861f28255Scgd 
10961f28255Scgd 	(*vp)++;
11061f28255Scgd 	p2 = exp0(vp, (ignore & IGNORE) || p1);
11161f28255Scgd #ifdef EDEBUG
11261f28255Scgd 	etraci("exp0 p2", p2, vp);
11361f28255Scgd #endif
11461f28255Scgd 	return (p1 || p2);
11561f28255Scgd     }
11661f28255Scgd     return (p1);
11761f28255Scgd }
11861f28255Scgd 
11961f28255Scgd static int
exp1(Char *** vp,int ignore)120b79c2ef2Schristos exp1(Char ***vp, int ignore)
12161f28255Scgd {
122b771e65bSwiz     int p1;
12361f28255Scgd 
1244d375f23Smrg     p1 = csh_exp2(vp, ignore);
12561f28255Scgd #ifdef EDEBUG
12661f28255Scgd     etraci("exp1 p1", p1, vp);
12761f28255Scgd #endif
12861f28255Scgd     if (**vp && eq(**vp, STRand2)) {
12976adbe2bStls 	int p2;
13061f28255Scgd 
13161f28255Scgd 	(*vp)++;
13261f28255Scgd 	p2 = exp1(vp, (ignore & IGNORE) || !p1);
13361f28255Scgd #ifdef EDEBUG
13461f28255Scgd 	etraci("exp1 p2", p2, vp);
13561f28255Scgd #endif
13661f28255Scgd 	return (p1 && p2);
13761f28255Scgd     }
13861f28255Scgd     return (p1);
13961f28255Scgd }
14061f28255Scgd 
14161f28255Scgd static int
csh_exp2(Char *** vp,int ignore)142b79c2ef2Schristos csh_exp2(Char ***vp, int ignore)
14361f28255Scgd {
144b771e65bSwiz     int p1;
14561f28255Scgd 
146b771e65bSwiz     p1 = exp2a(vp, ignore);
14761f28255Scgd #ifdef EDEBUG
14861f28255Scgd     etraci("exp3 p1", p1, vp);
14961f28255Scgd #endif
15061f28255Scgd     if (**vp && eq(**vp, STRor)) {
15176adbe2bStls 	int p2;
15261f28255Scgd 
15361f28255Scgd 	(*vp)++;
1544d375f23Smrg 	p2 = csh_exp2(vp, ignore);
15561f28255Scgd #ifdef EDEBUG
15661f28255Scgd 	etraci("exp3 p2", p2, vp);
15761f28255Scgd #endif
15861f28255Scgd 	return (p1 | p2);
15961f28255Scgd     }
16061f28255Scgd     return (p1);
16161f28255Scgd }
16261f28255Scgd 
16361f28255Scgd static int
exp2a(Char *** vp,int ignore)164b79c2ef2Schristos exp2a(Char ***vp, int ignore)
16561f28255Scgd {
166b771e65bSwiz     int p1;
16761f28255Scgd 
168b771e65bSwiz     p1 = exp2b(vp, ignore);
16961f28255Scgd #ifdef EDEBUG
17061f28255Scgd     etraci("exp2a p1", p1, vp);
17161f28255Scgd #endif
17261f28255Scgd     if (**vp && eq(**vp, STRcaret)) {
17376adbe2bStls 	int p2;
17461f28255Scgd 
17561f28255Scgd 	(*vp)++;
17661f28255Scgd 	p2 = exp2a(vp, ignore);
17761f28255Scgd #ifdef EDEBUG
17861f28255Scgd 	etraci("exp2a p2", p2, vp);
17961f28255Scgd #endif
18061f28255Scgd 	return (p1 ^ p2);
18161f28255Scgd     }
18261f28255Scgd     return (p1);
18361f28255Scgd }
18461f28255Scgd 
18561f28255Scgd static int
exp2b(Char *** vp,int ignore)186b79c2ef2Schristos exp2b(Char ***vp, int ignore)
18761f28255Scgd {
188b771e65bSwiz     int p1;
18961f28255Scgd 
190b771e65bSwiz     p1 = exp2c(vp, ignore);
19161f28255Scgd #ifdef EDEBUG
19261f28255Scgd     etraci("exp2b p1", p1, vp);
19361f28255Scgd #endif
19461f28255Scgd     if (**vp && eq(**vp, STRand)) {
19576adbe2bStls 	int p2;
19661f28255Scgd 
19761f28255Scgd 	(*vp)++;
19861f28255Scgd 	p2 = exp2b(vp, ignore);
19961f28255Scgd #ifdef EDEBUG
20061f28255Scgd 	etraci("exp2b p2", p2, vp);
20161f28255Scgd #endif
20261f28255Scgd 	return (p1 & p2);
20361f28255Scgd     }
20461f28255Scgd     return (p1);
20561f28255Scgd }
20661f28255Scgd 
20761f28255Scgd static int
exp2c(Char *** vp,int ignore)208b79c2ef2Schristos exp2c(Char ***vp, int ignore)
20961f28255Scgd {
210b771e65bSwiz     Char *p1, *p2;
21176adbe2bStls     int i;
21261f28255Scgd 
213b771e65bSwiz     p1 = exp3(vp, ignore);
21461f28255Scgd #ifdef EDEBUG
21561f28255Scgd     etracc("exp2c p1", p1, vp);
21661f28255Scgd #endif
217cee2bad8Smycroft     if ((i = isa(**vp, EQOP)) != 0) {
21861f28255Scgd 	(*vp)++;
21961f28255Scgd 	if (i == EQMATCH || i == NOTEQMATCH)
22061f28255Scgd 	    ignore |= NOGLOB;
22161f28255Scgd 	p2 = exp3(vp, ignore);
22261f28255Scgd #ifdef EDEBUG
22361f28255Scgd 	etracc("exp2c p2", p2, vp);
22461f28255Scgd #endif
22561f28255Scgd 	if (!(ignore & IGNORE))
22661f28255Scgd 	    switch (i) {
22761f28255Scgd 	    case EQEQ:
22861f28255Scgd 		i = eq(p1, p2);
22961f28255Scgd 		break;
23061f28255Scgd 	    case EQMATCH:
23161f28255Scgd 		i = Gmatch(p1, p2);
23261f28255Scgd 		break;
233b771e65bSwiz 	    case NOTEQ:
234b771e65bSwiz 		i = !eq(p1, p2);
235b771e65bSwiz 		break;
23661f28255Scgd 	    case NOTEQMATCH:
23761f28255Scgd 		i = !Gmatch(p1, p2);
23861f28255Scgd 		break;
23961f28255Scgd 	    }
240*1767ce60Schristos 	free(p1);
241*1767ce60Schristos 	free(p2);
24261f28255Scgd 	return (i);
24361f28255Scgd     }
24461f28255Scgd     i = egetn(p1);
245*1767ce60Schristos     free(p1);
24661f28255Scgd     return (i);
24761f28255Scgd }
24861f28255Scgd 
24961f28255Scgd static Char *
exp3(Char *** vp,int ignore)250b79c2ef2Schristos exp3(Char ***vp, int ignore)
25161f28255Scgd {
25276adbe2bStls     Char *p1, *p2;
25376adbe2bStls     int i;
25461f28255Scgd 
25561f28255Scgd     p1 = exp3a(vp, ignore);
25661f28255Scgd #ifdef EDEBUG
25761f28255Scgd     etracc("exp3 p1", p1, vp);
25861f28255Scgd #endif
259cee2bad8Smycroft     if ((i = isa(**vp, RELOP)) != 0) {
26061f28255Scgd 	(*vp)++;
26161f28255Scgd 	if (**vp && eq(**vp, STRequal))
26261f28255Scgd 	    i |= 1, (*vp)++;
26361f28255Scgd 	p2 = exp3(vp, ignore);
26461f28255Scgd #ifdef EDEBUG
26561f28255Scgd 	etracc("exp3 p2", p2, vp);
26661f28255Scgd #endif
26761f28255Scgd 	if (!(ignore & IGNORE))
26861f28255Scgd 	    switch (i) {
26961f28255Scgd 	    case GTR:
27061f28255Scgd 		i = egetn(p1) > egetn(p2);
27161f28255Scgd 		break;
27261f28255Scgd 	    case GTR | 1:
27361f28255Scgd 		i = egetn(p1) >= egetn(p2);
27461f28255Scgd 		break;
27561f28255Scgd 	    case LSS:
27661f28255Scgd 		i = egetn(p1) < egetn(p2);
27761f28255Scgd 		break;
27861f28255Scgd 	    case LSS | 1:
27961f28255Scgd 		i = egetn(p1) <= egetn(p2);
28061f28255Scgd 		break;
28161f28255Scgd 	    }
282*1767ce60Schristos 	free(p1);
283*1767ce60Schristos 	free(p2);
28461f28255Scgd 	return (putn(i));
28561f28255Scgd     }
28661f28255Scgd     return (p1);
28761f28255Scgd }
28861f28255Scgd 
28961f28255Scgd static Char *
exp3a(Char *** vp,int ignore)290b79c2ef2Schristos exp3a(Char ***vp, int ignore)
29161f28255Scgd {
292b771e65bSwiz     Char *op, *p1, *p2;
29376adbe2bStls     int i;
29461f28255Scgd 
29561f28255Scgd     p1 = exp4(vp, ignore);
29661f28255Scgd #ifdef EDEBUG
29761f28255Scgd     etracc("exp3a p1", p1, vp);
29861f28255Scgd #endif
29961f28255Scgd     op = **vp;
30061f28255Scgd     if (op && any("<>", op[0]) && op[0] == op[1]) {
30161f28255Scgd 	(*vp)++;
30261f28255Scgd 	p2 = exp3a(vp, ignore);
30361f28255Scgd #ifdef EDEBUG
30461f28255Scgd 	etracc("exp3a p2", p2, vp);
30561f28255Scgd #endif
30661f28255Scgd 	if (op[0] == '<')
30761f28255Scgd 	    i = egetn(p1) << egetn(p2);
30861f28255Scgd 	else
30961f28255Scgd 	    i = egetn(p1) >> egetn(p2);
310*1767ce60Schristos 	free(p1);
311*1767ce60Schristos 	free(p2);
31261f28255Scgd 	return (putn(i));
31361f28255Scgd     }
31461f28255Scgd     return (p1);
31561f28255Scgd }
31661f28255Scgd 
31761f28255Scgd static Char *
exp4(Char *** vp,int ignore)318b79c2ef2Schristos exp4(Char ***vp, int ignore)
31961f28255Scgd {
32076adbe2bStls     Char *p1, *p2;
321b771e65bSwiz     int i;
32261f28255Scgd 
323b771e65bSwiz     i = 0;
32461f28255Scgd     p1 = exp5(vp, ignore);
32561f28255Scgd #ifdef EDEBUG
32661f28255Scgd     etracc("exp4 p1", p1, vp);
32761f28255Scgd #endif
32861f28255Scgd     if (isa(**vp, ADDOP)) {
329b771e65bSwiz 	Char *op;
33061f28255Scgd 
331b771e65bSwiz 	op = *(*vp)++;
33261f28255Scgd 	p2 = exp4(vp, ignore);
33361f28255Scgd #ifdef EDEBUG
33461f28255Scgd 	etracc("exp4 p2", p2, vp);
33561f28255Scgd #endif
33661f28255Scgd 	if (!(ignore & IGNORE))
33761f28255Scgd 	    switch (op[0]) {
33861f28255Scgd 	    case '+':
33961f28255Scgd 		i = egetn(p1) + egetn(p2);
34061f28255Scgd 		break;
34161f28255Scgd 	    case '-':
34261f28255Scgd 		i = egetn(p1) - egetn(p2);
34361f28255Scgd 		break;
34461f28255Scgd 	    }
345*1767ce60Schristos 	free(p1);
346*1767ce60Schristos 	free(p2);
34761f28255Scgd 	return (putn(i));
34861f28255Scgd     }
34961f28255Scgd     return (p1);
35061f28255Scgd }
35161f28255Scgd 
35261f28255Scgd static Char *
exp5(Char *** vp,int ignore)353b79c2ef2Schristos exp5(Char ***vp, int ignore)
35461f28255Scgd {
35576adbe2bStls     Char *p1, *p2;
356b771e65bSwiz     int i;
35761f28255Scgd 
358b771e65bSwiz     i = 0;
35961f28255Scgd     p1 = exp6(vp, ignore);
36061f28255Scgd #ifdef EDEBUG
36161f28255Scgd     etracc("exp5 p1", p1, vp);
36261f28255Scgd #endif
36361f28255Scgd     if (isa(**vp, MULOP)) {
364b771e65bSwiz 	Char *op;
36561f28255Scgd 
366b771e65bSwiz 	op = *(*vp)++;
36761f28255Scgd 	p2 = exp5(vp, ignore);
36861f28255Scgd #ifdef EDEBUG
36961f28255Scgd 	etracc("exp5 p2", p2, vp);
37061f28255Scgd #endif
37161f28255Scgd 	if (!(ignore & IGNORE))
37261f28255Scgd 	    switch (op[0]) {
37361f28255Scgd 	    case '*':
37461f28255Scgd 		i = egetn(p1) * egetn(p2);
37561f28255Scgd 		break;
37661f28255Scgd 	    case '/':
37761f28255Scgd 		i = egetn(p2);
378ee9e50eaSmycroft 		if (i == 0)
37961f28255Scgd 		    stderror(ERR_DIV0);
38061f28255Scgd 		i = egetn(p1) / i;
38161f28255Scgd 		break;
38261f28255Scgd 	    case '%':
38361f28255Scgd 		i = egetn(p2);
384ee9e50eaSmycroft 		if (i == 0)
38561f28255Scgd 		    stderror(ERR_MOD0);
38661f28255Scgd 		i = egetn(p1) % i;
38761f28255Scgd 		break;
38861f28255Scgd 	    }
389*1767ce60Schristos 	free(p1);
390*1767ce60Schristos 	free(p2);
39161f28255Scgd 	return (putn(i));
39261f28255Scgd     }
39361f28255Scgd     return (p1);
39461f28255Scgd }
39561f28255Scgd 
39661f28255Scgd static Char *
exp6(Char *** vp,int ignore)397b79c2ef2Schristos exp6(Char ***vp, int ignore)
39861f28255Scgd {
39976adbe2bStls     Char *cp, *dp, *ep;
400b771e65bSwiz     int ccode, i;
40161f28255Scgd 
402b771e65bSwiz     i = 0;
403ee9e50eaSmycroft     if (**vp == 0)
40461f28255Scgd 	stderror(ERR_NAME | ERR_EXPRESSION);
40561f28255Scgd     if (eq(**vp, STRbang)) {
40661f28255Scgd 	(*vp)++;
40761f28255Scgd 	cp = exp6(vp, ignore);
40861f28255Scgd #ifdef EDEBUG
40961f28255Scgd 	etracc("exp6 ! cp", cp, vp);
41061f28255Scgd #endif
41161f28255Scgd 	i = egetn(cp);
412*1767ce60Schristos 	free(cp);
41361f28255Scgd 	return (putn(!i));
41461f28255Scgd     }
41561f28255Scgd     if (eq(**vp, STRtilde)) {
41661f28255Scgd 	(*vp)++;
41761f28255Scgd 	cp = exp6(vp, ignore);
41861f28255Scgd #ifdef EDEBUG
41961f28255Scgd 	etracc("exp6 ~ cp", cp, vp);
42061f28255Scgd #endif
42161f28255Scgd 	i = egetn(cp);
422*1767ce60Schristos 	free(cp);
42361f28255Scgd 	return (putn(~i));
42461f28255Scgd     }
42561f28255Scgd     if (eq(**vp, STRLparen)) {
42661f28255Scgd 	(*vp)++;
42761f28255Scgd 	ccode = exp0(vp, ignore);
42861f28255Scgd #ifdef EDEBUG
42961f28255Scgd 	etraci("exp6 () ccode", ccode, vp);
43061f28255Scgd #endif
43178b76e57Schristos 	if (**vp == 0 || ***vp != ')')
43261f28255Scgd 	    stderror(ERR_NAME | ERR_EXPRESSION);
43361f28255Scgd 	(*vp)++;
43461f28255Scgd 	return (putn(ccode));
43561f28255Scgd     }
43661f28255Scgd     if (eq(**vp, STRLbrace)) {
43761f28255Scgd 	struct command faket;
43861f28255Scgd 	Char *fakecom[2];
439b771e65bSwiz 	Char **v;
44061f28255Scgd 
44161f28255Scgd 	faket.t_dtyp = NODE_COMMAND;
44261f28255Scgd 	faket.t_dflg = 0;
44361f28255Scgd 	faket.t_dcar = faket.t_dcdr = faket.t_dspr = NULL;
44461f28255Scgd 	faket.t_dcom = fakecom;
44561f28255Scgd 	fakecom[0] = STRfakecom;
44661f28255Scgd 	fakecom[1] = NULL;
44761f28255Scgd 	(*vp)++;
44861f28255Scgd 	v = *vp;
44961f28255Scgd 	for (;;) {
450ee9e50eaSmycroft 	    if (!**vp)
45161f28255Scgd 		stderror(ERR_NAME | ERR_MISSING, '}');
45261f28255Scgd 	    if (eq(*(*vp)++, STRRbrace))
45361f28255Scgd 		break;
45461f28255Scgd 	}
45561f28255Scgd 	if (ignore & IGNORE)
45661f28255Scgd 	    return (Strsave(STRNULL));
45761f28255Scgd 	psavejob();
45861f28255Scgd 	if (pfork(&faket, -1) == 0) {
45961f28255Scgd 	    *--(*vp) = 0;
46061f28255Scgd 	    evalav(v);
46161f28255Scgd 	    exitstat();
46261f28255Scgd 	}
46361f28255Scgd 	pwait();
46461f28255Scgd 	prestjob();
46561f28255Scgd #ifdef EDEBUG
46661f28255Scgd 	etraci("exp6 {} status", egetn(value(STRstatus)), vp);
46761f28255Scgd #endif
46861f28255Scgd 	return (putn(egetn(value(STRstatus)) == 0));
46961f28255Scgd     }
47061f28255Scgd     if (isa(**vp, ANYOP))
47161f28255Scgd 	return (Strsave(STRNULL));
47261f28255Scgd     cp = *(*vp)++;
47361f28255Scgd     if (*cp == '-' && any("erwxfdzopls", cp[1])) {
47461f28255Scgd 	struct stat stb;
47561f28255Scgd 
476ee9e50eaSmycroft 	if (cp[2] != '\0')
47761f28255Scgd 	    stderror(ERR_NAME | ERR_FILEINQ);
47861f28255Scgd 	/*
47961f28255Scgd 	 * Detect missing file names by checking for operator in the file name
48061f28255Scgd 	 * position.  However, if an operator name appears there, we must make
48161f28255Scgd 	 * sure that there's no file by that name (e.g., "/") before announcing
48261f28255Scgd 	 * an error.  Even this check isn't quite right, since it doesn't take
48361f28255Scgd 	 * globbing into account.
48461f28255Scgd 	 */
485ee9e50eaSmycroft 	if (isa(**vp, ANYOP) && stat(short2str(**vp), &stb))
48661f28255Scgd 	    stderror(ERR_NAME | ERR_FILENAME);
48761f28255Scgd 
48861f28255Scgd 	dp = *(*vp)++;
48961f28255Scgd 	if (ignore & IGNORE)
49061f28255Scgd 	    return (Strsave(STRNULL));
49161f28255Scgd 	ep = globone(dp, G_ERROR);
49261f28255Scgd 	switch (cp[1]) {
49361f28255Scgd 	case 'r':
49461f28255Scgd 	    i = !access(short2str(ep), R_OK);
49561f28255Scgd 	    break;
49661f28255Scgd 	case 'w':
49761f28255Scgd 	    i = !access(short2str(ep), W_OK);
49861f28255Scgd 	    break;
49961f28255Scgd 	case 'x':
50061f28255Scgd 	    i = !access(short2str(ep), X_OK);
50161f28255Scgd 	    break;
50261f28255Scgd 	default:
5036de13662Smycroft 	    if (cp[1] == 'l' ?
5046de13662Smycroft 		lstat(short2str(ep), &stb) : stat(short2str(ep), &stb)) {
505*1767ce60Schristos 		free(ep);
50661f28255Scgd 		return (Strsave(STR0));
50761f28255Scgd 	    }
50861f28255Scgd 	    switch (cp[1]) {
50961f28255Scgd 	    case 'd':
51061f28255Scgd 		i = S_ISDIR(stb.st_mode);
51161f28255Scgd 		break;
512b771e65bSwiz 	    case 'e':
513b771e65bSwiz 		i = 1;
51461f28255Scgd 		break;
515b771e65bSwiz 	    case 'f':
516b771e65bSwiz 		i = S_ISREG(stb.st_mode);
517b771e65bSwiz 		break;
51861f28255Scgd 	    case 'l':
51961f28255Scgd #ifdef S_ISLNK
52061f28255Scgd 		i = S_ISLNK(stb.st_mode);
52161f28255Scgd #else
52261f28255Scgd 		i = 0;
52361f28255Scgd #endif
52461f28255Scgd 		break;
525b771e65bSwiz 	    case 'o':
5269050ab5cSlukem 		i = stb.st_uid == (uid_t)uid;
527b771e65bSwiz 		break;
528b771e65bSwiz 	    case 'p':
529b771e65bSwiz #ifdef S_ISFIFO
530b771e65bSwiz 		i = S_ISFIFO(stb.st_mode);
531b771e65bSwiz #else
532b771e65bSwiz 		i = 0;
533b771e65bSwiz #endif
534b771e65bSwiz 		break;
53561f28255Scgd 	    case 's':
53661f28255Scgd #ifdef S_ISSOCK
53761f28255Scgd 		i = S_ISSOCK(stb.st_mode);
53861f28255Scgd #else
53961f28255Scgd 		i = 0;
54061f28255Scgd #endif
54161f28255Scgd 		break;
54261f28255Scgd 	    case 'z':
54361f28255Scgd 		i = stb.st_size == 0;
54461f28255Scgd 		break;
54561f28255Scgd 	    }
54661f28255Scgd 	}
54761f28255Scgd #ifdef EDEBUG
54861f28255Scgd 	etraci("exp6 -? i", i, vp);
54961f28255Scgd #endif
550*1767ce60Schristos 	free(ep);
55161f28255Scgd 	return (putn(i));
55261f28255Scgd     }
55361f28255Scgd #ifdef EDEBUG
55461f28255Scgd     etracc("exp6 default", cp, vp);
55561f28255Scgd #endif
55661f28255Scgd     return (ignore & NOGLOB ? Strsave(cp) : globone(cp, G_ERROR));
55761f28255Scgd }
55861f28255Scgd 
55961f28255Scgd static void
evalav(Char ** v)560b771e65bSwiz evalav(Char **v)
56161f28255Scgd {
562b771e65bSwiz     struct wordent *hp, paraml1, *wdp;
56361f28255Scgd     struct command *t;
56461f28255Scgd 
565b771e65bSwiz     hp = &paraml1;
566b771e65bSwiz     wdp = hp;
56761f28255Scgd     set(STRstatus, Strsave(STR0));
56861f28255Scgd     hp->prev = hp->next = hp;
56961f28255Scgd     hp->word = STRNULL;
57061f28255Scgd     while (*v) {
571b771e65bSwiz 	struct wordent *new;
57261f28255Scgd 
573b771e65bSwiz 	new = (struct wordent *)xcalloc(1, sizeof *wdp);
57461f28255Scgd 	new->prev = wdp;
57561f28255Scgd 	new->next = hp;
57661f28255Scgd 	wdp->next = new;
57761f28255Scgd 	wdp = new;
57861f28255Scgd 	wdp->word = Strsave(*v++);
57961f28255Scgd     }
58061f28255Scgd     hp->prev = wdp;
58161f28255Scgd     alias(&paraml1);
58261f28255Scgd     t = syntax(paraml1.next, &paraml1, 0);
583ee9e50eaSmycroft     if (seterr)
58461f28255Scgd 	stderror(ERR_OLD);
58561f28255Scgd     execute(t, -1, NULL, NULL);
58661f28255Scgd     freelex(&paraml1), freesyn(t);
58761f28255Scgd }
58861f28255Scgd 
58961f28255Scgd static int
isa(Char * cp,int what)590b771e65bSwiz isa(Char *cp, int what)
59161f28255Scgd {
59261f28255Scgd     if (cp == 0)
59361f28255Scgd 	return ((what & RESTOP) != 0);
59461f28255Scgd     if (cp[1] == 0) {
59561f28255Scgd 	if (what & ADDOP && (*cp == '+' || *cp == '-'))
59661f28255Scgd 	    return (1);
59761f28255Scgd 	if (what & MULOP && (*cp == '*' || *cp == '/' || *cp == '%'))
59861f28255Scgd 	    return (1);
59961f28255Scgd 	if (what & RESTOP && (*cp == '(' || *cp == ')' || *cp == '!' ||
60061f28255Scgd 			      *cp == '~' || *cp == '^' || *cp == '"'))
60161f28255Scgd 	    return (1);
60261f28255Scgd     }
60361f28255Scgd     else if (cp[2] == 0) {
60461f28255Scgd 	if (what & RESTOP) {
60561f28255Scgd 	    if (cp[0] == '|' && cp[1] == '&')
60661f28255Scgd 		return (1);
60761f28255Scgd 	    if (cp[0] == '<' && cp[1] == '<')
60861f28255Scgd 		return (1);
60961f28255Scgd 	    if (cp[0] == '>' && cp[1] == '>')
61061f28255Scgd 		return (1);
61161f28255Scgd 	}
61261f28255Scgd 	if (what & EQOP) {
61361f28255Scgd 	    if (cp[0] == '=') {
61461f28255Scgd 		if (cp[1] == '=')
61561f28255Scgd 		    return (EQEQ);
61661f28255Scgd 		if (cp[1] == '~')
61761f28255Scgd 		    return (EQMATCH);
61861f28255Scgd 	    }
61961f28255Scgd 	    else if (cp[0] == '!') {
62061f28255Scgd 		if (cp[1] == '=')
62161f28255Scgd 		    return (NOTEQ);
62261f28255Scgd 		if (cp[1] == '~')
62361f28255Scgd 		    return (NOTEQMATCH);
62461f28255Scgd 	    }
62561f28255Scgd 	}
62661f28255Scgd     }
62761f28255Scgd     if (what & RELOP) {
62861f28255Scgd 	if (*cp == '<')
62961f28255Scgd 	    return (LSS);
63061f28255Scgd 	if (*cp == '>')
63161f28255Scgd 	    return (GTR);
63261f28255Scgd     }
63361f28255Scgd     return (0);
63461f28255Scgd }
63561f28255Scgd 
63661f28255Scgd static int
egetn(Char * cp)637b771e65bSwiz egetn(Char *cp)
63861f28255Scgd {
639ee9e50eaSmycroft     if (*cp && *cp != '-' && !Isdigit(*cp))
64061f28255Scgd 	stderror(ERR_NAME | ERR_EXPRESSION);
64161f28255Scgd     return (getn(cp));
64261f28255Scgd }
64361f28255Scgd 
64461f28255Scgd /* Phew! */
64561f28255Scgd 
64661f28255Scgd #ifdef EDEBUG
64761f28255Scgd static void
etraci(char * str,int i,Char *** vp)648b771e65bSwiz etraci(char *str, int i, Char ***vp)
64961f28255Scgd {
650cee2bad8Smycroft     (void)fprintf(csherr, "%s=%d\t", str, i);
651cee2bad8Smycroft     blkpr(csherr, *vp);
652cee2bad8Smycroft     (void)fprintf(csherr, "\n");
65361f28255Scgd }
65461f28255Scgd static void
etracc(char * str,Char * cp,Char *** vp)655b771e65bSwiz etracc(char *str, Char *cp, Char ***vp)
65661f28255Scgd {
657cee2bad8Smycroft     (void)fprintf(csherr, "%s=%s\t", str, vis_str(cp));
658cee2bad8Smycroft     blkpr(csherr, *vp);
659cee2bad8Smycroft     (void)fprintf(csherr, "\n");
66061f28255Scgd }
66161f28255Scgd #endif
662