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 = ¶ml1;
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(¶ml1);
58261f28255Scgd t = syntax(paraml1.next, ¶ml1, 0);
583ee9e50eaSmycroft if (seterr)
58461f28255Scgd stderror(ERR_OLD);
58561f28255Scgd execute(t, -1, NULL, NULL);
58661f28255Scgd freelex(¶ml1), 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