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