xref: /freebsd/contrib/tcsh/sh.exp.c (revision 29301572)
129301572SMark Peek /* $Header: /src/pub/tcsh/sh.exp.c,v 3.40 2002/03/08 17:36:46 christos Exp $ */
2c80476e4SDavid E. O'Brien /*
3c80476e4SDavid E. O'Brien  * sh.exp.c: Expression evaluations
4c80476e4SDavid E. O'Brien  */
5c80476e4SDavid E. O'Brien /*-
6c80476e4SDavid E. O'Brien  * Copyright (c) 1980, 1991 The Regents of the University of California.
7c80476e4SDavid E. O'Brien  * All rights reserved.
8c80476e4SDavid E. O'Brien  *
9c80476e4SDavid E. O'Brien  * Redistribution and use in source and binary forms, with or without
10c80476e4SDavid E. O'Brien  * modification, are permitted provided that the following conditions
11c80476e4SDavid E. O'Brien  * are met:
12c80476e4SDavid E. O'Brien  * 1. Redistributions of source code must retain the above copyright
13c80476e4SDavid E. O'Brien  *    notice, this list of conditions and the following disclaimer.
14c80476e4SDavid E. O'Brien  * 2. Redistributions in binary form must reproduce the above copyright
15c80476e4SDavid E. O'Brien  *    notice, this list of conditions and the following disclaimer in the
16c80476e4SDavid E. O'Brien  *    documentation and/or other materials provided with the distribution.
1729301572SMark Peek  * 3. Neither the name of the University nor the names of its contributors
18c80476e4SDavid E. O'Brien  *    may be used to endorse or promote products derived from this software
19c80476e4SDavid E. O'Brien  *    without specific prior written permission.
20c80476e4SDavid E. O'Brien  *
21c80476e4SDavid E. O'Brien  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22c80476e4SDavid E. O'Brien  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23c80476e4SDavid E. O'Brien  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24c80476e4SDavid E. O'Brien  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25c80476e4SDavid E. O'Brien  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26c80476e4SDavid E. O'Brien  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27c80476e4SDavid E. O'Brien  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28c80476e4SDavid E. O'Brien  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29c80476e4SDavid E. O'Brien  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30c80476e4SDavid E. O'Brien  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31c80476e4SDavid E. O'Brien  * SUCH DAMAGE.
32c80476e4SDavid E. O'Brien  */
33c80476e4SDavid E. O'Brien #include "sh.h"
34c80476e4SDavid E. O'Brien 
3529301572SMark Peek RCSID("$Id: sh.exp.c,v 3.40 2002/03/08 17:36:46 christos Exp $")
3629301572SMark Peek 
3729301572SMark Peek #include "tw.h"
38c80476e4SDavid E. O'Brien 
39c80476e4SDavid E. O'Brien /*
40c80476e4SDavid E. O'Brien  * C shell
41c80476e4SDavid E. O'Brien  */
42c80476e4SDavid E. O'Brien 
43c80476e4SDavid E. O'Brien #define TEXP_IGNORE 1	/* in ignore, it means to ignore value, just parse */
44c80476e4SDavid E. O'Brien #define TEXP_NOGLOB 2	/* in ignore, it means not to globone */
45c80476e4SDavid E. O'Brien 
46c80476e4SDavid E. O'Brien #define	ADDOP	1
47c80476e4SDavid E. O'Brien #define	MULOP	2
48c80476e4SDavid E. O'Brien #define	EQOP	4
49c80476e4SDavid E. O'Brien #define	RELOP	8
50c80476e4SDavid E. O'Brien #define	RESTOP	16
51c80476e4SDavid E. O'Brien #define	ANYOP	31
52c80476e4SDavid E. O'Brien 
53c80476e4SDavid E. O'Brien #define	EQEQ	1
54c80476e4SDavid E. O'Brien #define	GTR	2
55c80476e4SDavid E. O'Brien #define	LSS	4
56c80476e4SDavid E. O'Brien #define	NOTEQ	6
57c80476e4SDavid E. O'Brien #define EQMATCH 7
58c80476e4SDavid E. O'Brien #define NOTEQMATCH 8
59c80476e4SDavid E. O'Brien 
60c80476e4SDavid E. O'Brien static	int	 sh_access	__P((Char *, int));
61c80476e4SDavid E. O'Brien static	int	 exp1		__P((Char ***, bool));
62c80476e4SDavid E. O'Brien static	int	 exp2		__P((Char ***, bool));
63c80476e4SDavid E. O'Brien static	int	 exp2a		__P((Char ***, bool));
64c80476e4SDavid E. O'Brien static	int	 exp2b		__P((Char ***, bool));
65c80476e4SDavid E. O'Brien static	int	 exp2c		__P((Char ***, bool));
66c80476e4SDavid E. O'Brien static	Char 	*exp3		__P((Char ***, bool));
67c80476e4SDavid E. O'Brien static	Char 	*exp3a		__P((Char ***, bool));
68c80476e4SDavid E. O'Brien static	Char 	*exp4		__P((Char ***, bool));
69c80476e4SDavid E. O'Brien static	Char 	*exp5		__P((Char ***, bool));
70c80476e4SDavid E. O'Brien static	Char 	*exp6		__P((Char ***, bool));
71c80476e4SDavid E. O'Brien static	void	 evalav		__P((Char **));
72c80476e4SDavid E. O'Brien static	int	 isa		__P((Char *, int));
73c80476e4SDavid E. O'Brien static	int	 egetn		__P((Char *));
74c80476e4SDavid E. O'Brien 
75c80476e4SDavid E. O'Brien 
76c80476e4SDavid E. O'Brien #ifdef EDEBUG
77c80476e4SDavid E. O'Brien static	void	 etracc		__P((char *, Char *, Char ***));
78c80476e4SDavid E. O'Brien static	void	 etraci		__P((char *, int, Char ***));
79c80476e4SDavid E. O'Brien #endif /* EDEBUG */
80c80476e4SDavid E. O'Brien 
81c80476e4SDavid E. O'Brien 
82c80476e4SDavid E. O'Brien /*
83c80476e4SDavid E. O'Brien  * shell access function according to POSIX and non POSIX
84c80476e4SDavid E. O'Brien  * From Beto Appleton (beto@aixwiz.aix.ibm.com)
85c80476e4SDavid E. O'Brien  */
86c80476e4SDavid E. O'Brien static int
87c80476e4SDavid E. O'Brien sh_access(fname, mode)
88c80476e4SDavid E. O'Brien     Char *fname;
89c80476e4SDavid E. O'Brien     int mode;
90c80476e4SDavid E. O'Brien {
91c80476e4SDavid E. O'Brien #if defined(POSIX) && !defined(USE_ACCESS)
92c80476e4SDavid E. O'Brien     struct stat     statb;
93c80476e4SDavid E. O'Brien #endif /* POSIX */
94c80476e4SDavid E. O'Brien     char *name = short2str(fname);
95c80476e4SDavid E. O'Brien 
96c80476e4SDavid E. O'Brien     if (*name == '\0')
97c80476e4SDavid E. O'Brien 	return 1;
98c80476e4SDavid E. O'Brien 
99c80476e4SDavid E. O'Brien #if !defined(POSIX) || defined(USE_ACCESS)
100c80476e4SDavid E. O'Brien     return access(name, mode);
101c80476e4SDavid E. O'Brien #else /* POSIX */
102c80476e4SDavid E. O'Brien 
103c80476e4SDavid E. O'Brien     /*
104c80476e4SDavid E. O'Brien      * POSIX 1003.2-d11.2
105c80476e4SDavid E. O'Brien      *	-r file		True if file exists and is readable.
106c80476e4SDavid E. O'Brien      *	-w file		True if file exists and is writable.
107c80476e4SDavid E. O'Brien      *			True shall indicate only that the write flag is on.
108c80476e4SDavid E. O'Brien      *			The file shall not be writable on a read-only file
109c80476e4SDavid E. O'Brien      *			system even if this test indicates true.
110c80476e4SDavid E. O'Brien      *	-x file		True if file exists and is executable.
111c80476e4SDavid E. O'Brien      *			True shall indicate only that the execute flag is on.
112c80476e4SDavid E. O'Brien      *			If file is a directory, true indicates that the file
113c80476e4SDavid E. O'Brien      *			can be searched.
114c80476e4SDavid E. O'Brien      */
115c80476e4SDavid E. O'Brien     if (mode != W_OK && mode != X_OK)
116c80476e4SDavid E. O'Brien 	return access(name, mode);
117c80476e4SDavid E. O'Brien 
118c80476e4SDavid E. O'Brien     if (stat(name, &statb) == -1)
119c80476e4SDavid E. O'Brien 	return 1;
120c80476e4SDavid E. O'Brien 
121c80476e4SDavid E. O'Brien     if (access(name, mode) == 0) {
122c80476e4SDavid E. O'Brien #ifdef S_ISDIR
123c80476e4SDavid E. O'Brien 	if (S_ISDIR(statb.st_mode) && mode == X_OK)
124c80476e4SDavid E. O'Brien 	    return 0;
125c80476e4SDavid E. O'Brien #endif /* S_ISDIR */
126c80476e4SDavid E. O'Brien 
127c80476e4SDavid E. O'Brien 	/* root needs permission for someone */
128c80476e4SDavid E. O'Brien 	switch (mode) {
129c80476e4SDavid E. O'Brien 	case W_OK:
130c80476e4SDavid E. O'Brien 	    mode = S_IWUSR | S_IWGRP | S_IWOTH;
131c80476e4SDavid E. O'Brien 	    break;
132c80476e4SDavid E. O'Brien 	case X_OK:
133c80476e4SDavid E. O'Brien 	    mode = S_IXUSR | S_IXGRP | S_IXOTH;
134c80476e4SDavid E. O'Brien 	    break;
135c80476e4SDavid E. O'Brien 	default:
136c80476e4SDavid E. O'Brien 	    abort();
137c80476e4SDavid E. O'Brien 	    break;
138c80476e4SDavid E. O'Brien 	}
139c80476e4SDavid E. O'Brien 
140c80476e4SDavid E. O'Brien     }
141c80476e4SDavid E. O'Brien 
142c80476e4SDavid E. O'Brien     else if (euid == statb.st_uid)
143c80476e4SDavid E. O'Brien 	mode <<= 6;
144c80476e4SDavid E. O'Brien 
145c80476e4SDavid E. O'Brien     else if (egid == statb.st_gid)
146c80476e4SDavid E. O'Brien 	mode <<= 3;
147c80476e4SDavid E. O'Brien 
148c80476e4SDavid E. O'Brien # ifdef NGROUPS_MAX
149c80476e4SDavid E. O'Brien     else {
150c80476e4SDavid E. O'Brien #  if defined(__386BSD__) || defined(BSD4_4)
151c80476e4SDavid E. O'Brien     /*
152c80476e4SDavid E. O'Brien      * These two decided that setgroup() should take an array of int's
153c80476e4SDavid E. O'Brien      * and they define _SC_NGROUPS_MAX without having sysconf
154c80476e4SDavid E. O'Brien      */
155c80476e4SDavid E. O'Brien #   undef _SC_NGROUPS_MAX
156c80476e4SDavid E. O'Brien #   if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__bsdi__)
157c80476e4SDavid E. O'Brien #    define GID_T gid_t
158c80476e4SDavid E. O'Brien #   else
159c80476e4SDavid E. O'Brien #    define GID_T int
160c80476e4SDavid E. O'Brien #   endif
161c80476e4SDavid E. O'Brien #  else
162c80476e4SDavid E. O'Brien #   define GID_T gid_t
163c80476e4SDavid E. O'Brien #  endif /* __386BSD__ || BSD4_4 */
164c80476e4SDavid E. O'Brien 	/* you can be in several groups */
165c80476e4SDavid E. O'Brien 	long	n;
166c80476e4SDavid E. O'Brien 	GID_T	*groups;
167c80476e4SDavid E. O'Brien 
168c80476e4SDavid E. O'Brien 	/*
169c80476e4SDavid E. O'Brien 	 * Try these things to find a positive maximum groups value:
170c80476e4SDavid E. O'Brien 	 *   1) sysconf(_SC_NGROUPS_MAX)
171c80476e4SDavid E. O'Brien 	 *   2) NGROUPS_MAX
172c80476e4SDavid E. O'Brien 	 *   3) getgroups(0, unused)
173c80476e4SDavid E. O'Brien 	 * Then allocate and scan the groups array if one of these worked.
174c80476e4SDavid E. O'Brien 	 */
175c80476e4SDavid E. O'Brien #  ifdef _SC_NGROUPS_MAX
176c80476e4SDavid E. O'Brien 	if ((n = sysconf(_SC_NGROUPS_MAX)) == -1)
177c80476e4SDavid E. O'Brien #  endif /* _SC_NGROUPS_MAX */
178c80476e4SDavid E. O'Brien 	    n = NGROUPS_MAX;
179c80476e4SDavid E. O'Brien 	if (n <= 0)
180c80476e4SDavid E. O'Brien 	    n = getgroups(0, (GID_T *) NULL);
181c80476e4SDavid E. O'Brien 
182c80476e4SDavid E. O'Brien 	if (n > 0) {
183c80476e4SDavid E. O'Brien 	    groups = (GID_T *) xmalloc((size_t) (n * sizeof(GID_T)));
184c80476e4SDavid E. O'Brien 	    n = getgroups((int) n, groups);
185c80476e4SDavid E. O'Brien 	    while (--n >= 0)
186c80476e4SDavid E. O'Brien 		if (groups[n] == statb.st_gid) {
187c80476e4SDavid E. O'Brien 		    mode <<= 3;
188c80476e4SDavid E. O'Brien 		    break;
189c80476e4SDavid E. O'Brien 		}
190c80476e4SDavid E. O'Brien 	}
191c80476e4SDavid E. O'Brien     }
192c80476e4SDavid E. O'Brien # endif /* NGROUPS_MAX */
193c80476e4SDavid E. O'Brien 
194c80476e4SDavid E. O'Brien     if (statb.st_mode & mode)
195c80476e4SDavid E. O'Brien 	return 0;
196c80476e4SDavid E. O'Brien     else
197c80476e4SDavid E. O'Brien 	return 1;
198c80476e4SDavid E. O'Brien #endif /* !POSIX */
199c80476e4SDavid E. O'Brien }
200c80476e4SDavid E. O'Brien 
201c80476e4SDavid E. O'Brien int
202c80476e4SDavid E. O'Brien expr(vp)
203c80476e4SDavid E. O'Brien     register Char ***vp;
204c80476e4SDavid E. O'Brien {
205c80476e4SDavid E. O'Brien     return (exp0(vp, 0));
206c80476e4SDavid E. O'Brien }
207c80476e4SDavid E. O'Brien 
208c80476e4SDavid E. O'Brien int
209c80476e4SDavid E. O'Brien exp0(vp, ignore)
210c80476e4SDavid E. O'Brien     register Char ***vp;
211c80476e4SDavid E. O'Brien     bool    ignore;
212c80476e4SDavid E. O'Brien {
213c80476e4SDavid E. O'Brien     register int p1 = exp1(vp, ignore);
214c80476e4SDavid E. O'Brien 
215c80476e4SDavid E. O'Brien #ifdef EDEBUG
216c80476e4SDavid E. O'Brien     etraci("exp0 p1", p1, vp);
217c80476e4SDavid E. O'Brien #endif /* EDEBUG */
218c80476e4SDavid E. O'Brien     if (**vp && eq(**vp, STRor2)) {
219c80476e4SDavid E. O'Brien 	register int p2;
220c80476e4SDavid E. O'Brien 
221c80476e4SDavid E. O'Brien 	(*vp)++;
222c80476e4SDavid E. O'Brien 	p2 = exp0(vp, (ignore & TEXP_IGNORE) || p1);
223c80476e4SDavid E. O'Brien #ifdef EDEBUG
224c80476e4SDavid E. O'Brien 	etraci("exp0 p2", p2, vp);
225c80476e4SDavid E. O'Brien #endif /* EDEBUG */
226c80476e4SDavid E. O'Brien 	return (p1 || p2);
227c80476e4SDavid E. O'Brien     }
228c80476e4SDavid E. O'Brien     return (p1);
229c80476e4SDavid E. O'Brien }
230c80476e4SDavid E. O'Brien 
231c80476e4SDavid E. O'Brien static int
232c80476e4SDavid E. O'Brien exp1(vp, ignore)
233c80476e4SDavid E. O'Brien     register Char ***vp;
234c80476e4SDavid E. O'Brien     bool    ignore;
235c80476e4SDavid E. O'Brien {
236c80476e4SDavid E. O'Brien     register int p1 = exp2(vp, ignore);
237c80476e4SDavid E. O'Brien 
238c80476e4SDavid E. O'Brien #ifdef EDEBUG
239c80476e4SDavid E. O'Brien     etraci("exp1 p1", p1, vp);
240c80476e4SDavid E. O'Brien #endif /* EDEBUG */
241c80476e4SDavid E. O'Brien     if (**vp && eq(**vp, STRand2)) {
242c80476e4SDavid E. O'Brien 	register int p2;
243c80476e4SDavid E. O'Brien 
244c80476e4SDavid E. O'Brien 	(*vp)++;
245c80476e4SDavid E. O'Brien 	p2 = exp1(vp, (ignore & TEXP_IGNORE) || !p1);
246c80476e4SDavid E. O'Brien #ifdef EDEBUG
247c80476e4SDavid E. O'Brien 	etraci("exp1 p2", p2, vp);
248c80476e4SDavid E. O'Brien #endif /* EDEBUG */
249c80476e4SDavid E. O'Brien 	return (p1 && p2);
250c80476e4SDavid E. O'Brien     }
251c80476e4SDavid E. O'Brien     return (p1);
252c80476e4SDavid E. O'Brien }
253c80476e4SDavid E. O'Brien 
254c80476e4SDavid E. O'Brien static int
255c80476e4SDavid E. O'Brien exp2(vp, ignore)
256c80476e4SDavid E. O'Brien     register Char ***vp;
257c80476e4SDavid E. O'Brien     bool    ignore;
258c80476e4SDavid E. O'Brien {
259c80476e4SDavid E. O'Brien     register int p1 = exp2a(vp, ignore);
260c80476e4SDavid E. O'Brien 
261c80476e4SDavid E. O'Brien #ifdef EDEBUG
262c80476e4SDavid E. O'Brien     etraci("exp3 p1", p1, vp);
263c80476e4SDavid E. O'Brien #endif /* EDEBUG */
264c80476e4SDavid E. O'Brien     if (**vp && eq(**vp, STRor)) {
265c80476e4SDavid E. O'Brien 	register int p2;
266c80476e4SDavid E. O'Brien 
267c80476e4SDavid E. O'Brien 	(*vp)++;
268c80476e4SDavid E. O'Brien 	p2 = exp2(vp, ignore);
269c80476e4SDavid E. O'Brien #ifdef EDEBUG
270c80476e4SDavid E. O'Brien 	etraci("exp3 p2", p2, vp);
271c80476e4SDavid E. O'Brien #endif /* EDEBUG */
272c80476e4SDavid E. O'Brien 	return (p1 | p2);
273c80476e4SDavid E. O'Brien     }
274c80476e4SDavid E. O'Brien     return (p1);
275c80476e4SDavid E. O'Brien }
276c80476e4SDavid E. O'Brien 
277c80476e4SDavid E. O'Brien static int
278c80476e4SDavid E. O'Brien exp2a(vp, ignore)
279c80476e4SDavid E. O'Brien     register Char ***vp;
280c80476e4SDavid E. O'Brien     bool    ignore;
281c80476e4SDavid E. O'Brien {
282c80476e4SDavid E. O'Brien     register int p1 = exp2b(vp, ignore);
283c80476e4SDavid E. O'Brien 
284c80476e4SDavid E. O'Brien #ifdef EDEBUG
285c80476e4SDavid E. O'Brien     etraci("exp2a p1", p1, vp);
286c80476e4SDavid E. O'Brien #endif /* EDEBUG */
287c80476e4SDavid E. O'Brien     if (**vp && eq(**vp, STRcaret)) {
288c80476e4SDavid E. O'Brien 	register int p2;
289c80476e4SDavid E. O'Brien 
290c80476e4SDavid E. O'Brien 	(*vp)++;
291c80476e4SDavid E. O'Brien 	p2 = exp2a(vp, ignore);
292c80476e4SDavid E. O'Brien #ifdef EDEBUG
293c80476e4SDavid E. O'Brien 	etraci("exp2a p2", p2, vp);
294c80476e4SDavid E. O'Brien #endif /* EDEBUG */
295c80476e4SDavid E. O'Brien 	return (p1 ^ p2);
296c80476e4SDavid E. O'Brien     }
297c80476e4SDavid E. O'Brien     return (p1);
298c80476e4SDavid E. O'Brien }
299c80476e4SDavid E. O'Brien 
300c80476e4SDavid E. O'Brien static int
301c80476e4SDavid E. O'Brien exp2b(vp, ignore)
302c80476e4SDavid E. O'Brien     register Char ***vp;
303c80476e4SDavid E. O'Brien     bool    ignore;
304c80476e4SDavid E. O'Brien {
305c80476e4SDavid E. O'Brien     register int p1 = exp2c(vp, ignore);
306c80476e4SDavid E. O'Brien 
307c80476e4SDavid E. O'Brien #ifdef EDEBUG
308c80476e4SDavid E. O'Brien     etraci("exp2b p1", p1, vp);
309c80476e4SDavid E. O'Brien #endif /* EDEBUG */
310c80476e4SDavid E. O'Brien     if (**vp && eq(**vp, STRand)) {
311c80476e4SDavid E. O'Brien 	register int p2;
312c80476e4SDavid E. O'Brien 
313c80476e4SDavid E. O'Brien 	(*vp)++;
314c80476e4SDavid E. O'Brien 	p2 = exp2b(vp, ignore);
315c80476e4SDavid E. O'Brien #ifdef EDEBUG
316c80476e4SDavid E. O'Brien 	etraci("exp2b p2", p2, vp);
317c80476e4SDavid E. O'Brien #endif /* EDEBUG */
318c80476e4SDavid E. O'Brien 	return (p1 & p2);
319c80476e4SDavid E. O'Brien     }
320c80476e4SDavid E. O'Brien     return (p1);
321c80476e4SDavid E. O'Brien }
322c80476e4SDavid E. O'Brien 
323c80476e4SDavid E. O'Brien static int
324c80476e4SDavid E. O'Brien exp2c(vp, ignore)
325c80476e4SDavid E. O'Brien     register Char ***vp;
326c80476e4SDavid E. O'Brien     bool    ignore;
327c80476e4SDavid E. O'Brien {
328c80476e4SDavid E. O'Brien     register Char *p1 = exp3(vp, ignore);
329c80476e4SDavid E. O'Brien     register Char *p2;
330c80476e4SDavid E. O'Brien     register int i;
331c80476e4SDavid E. O'Brien 
332c80476e4SDavid E. O'Brien #ifdef EDEBUG
333c80476e4SDavid E. O'Brien     etracc("exp2c p1", p1, vp);
334c80476e4SDavid E. O'Brien #endif /* EDEBUG */
335c80476e4SDavid E. O'Brien     if ((i = isa(**vp, EQOP)) != 0) {
336c80476e4SDavid E. O'Brien 	(*vp)++;
337c80476e4SDavid E. O'Brien 	if (i == EQMATCH || i == NOTEQMATCH)
338c80476e4SDavid E. O'Brien 	    ignore |= TEXP_NOGLOB;
339c80476e4SDavid E. O'Brien 	p2 = exp3(vp, ignore);
340c80476e4SDavid E. O'Brien #ifdef EDEBUG
341c80476e4SDavid E. O'Brien 	etracc("exp2c p2", p2, vp);
342c80476e4SDavid E. O'Brien #endif /* EDEBUG */
343c80476e4SDavid E. O'Brien 	if (!(ignore & TEXP_IGNORE))
344c80476e4SDavid E. O'Brien 	    switch (i) {
345c80476e4SDavid E. O'Brien 
346c80476e4SDavid E. O'Brien 	    case EQEQ:
347c80476e4SDavid E. O'Brien 		i = eq(p1, p2);
348c80476e4SDavid E. O'Brien 		break;
349c80476e4SDavid E. O'Brien 
350c80476e4SDavid E. O'Brien 	    case NOTEQ:
351c80476e4SDavid E. O'Brien 		i = !eq(p1, p2);
352c80476e4SDavid E. O'Brien 		break;
353c80476e4SDavid E. O'Brien 
354c80476e4SDavid E. O'Brien 	    case EQMATCH:
355c80476e4SDavid E. O'Brien 		i = Gmatch(p1, p2);
356c80476e4SDavid E. O'Brien 		break;
357c80476e4SDavid E. O'Brien 
358c80476e4SDavid E. O'Brien 	    case NOTEQMATCH:
359c80476e4SDavid E. O'Brien 		i = !Gmatch(p1, p2);
360c80476e4SDavid E. O'Brien 		break;
361c80476e4SDavid E. O'Brien 	    }
362c80476e4SDavid E. O'Brien 	xfree((ptr_t) p1);
363c80476e4SDavid E. O'Brien 	xfree((ptr_t) p2);
364c80476e4SDavid E. O'Brien 	return (i);
365c80476e4SDavid E. O'Brien     }
366c80476e4SDavid E. O'Brien     i = egetn(p1);
367c80476e4SDavid E. O'Brien     xfree((ptr_t) p1);
368c80476e4SDavid E. O'Brien     return (i);
369c80476e4SDavid E. O'Brien }
370c80476e4SDavid E. O'Brien 
371c80476e4SDavid E. O'Brien static Char *
372c80476e4SDavid E. O'Brien exp3(vp, ignore)
373c80476e4SDavid E. O'Brien     register Char ***vp;
374c80476e4SDavid E. O'Brien     bool    ignore;
375c80476e4SDavid E. O'Brien {
376c80476e4SDavid E. O'Brien     register Char *p1, *p2;
377c80476e4SDavid E. O'Brien     register int i;
378c80476e4SDavid E. O'Brien 
379c80476e4SDavid E. O'Brien     p1 = exp3a(vp, ignore);
380c80476e4SDavid E. O'Brien #ifdef EDEBUG
381c80476e4SDavid E. O'Brien     etracc("exp3 p1", p1, vp);
382c80476e4SDavid E. O'Brien #endif /* EDEBUG */
383c80476e4SDavid E. O'Brien     if ((i = isa(**vp, RELOP)) != 0) {
384c80476e4SDavid E. O'Brien 	(*vp)++;
385c80476e4SDavid E. O'Brien 	if (**vp && eq(**vp, STRequal))
386c80476e4SDavid E. O'Brien 	    i |= 1, (*vp)++;
387c80476e4SDavid E. O'Brien 	p2 = exp3(vp, ignore);
388c80476e4SDavid E. O'Brien #ifdef EDEBUG
389c80476e4SDavid E. O'Brien 	etracc("exp3 p2", p2, vp);
390c80476e4SDavid E. O'Brien #endif /* EDEBUG */
391c80476e4SDavid E. O'Brien 	if (!(ignore & TEXP_IGNORE))
392c80476e4SDavid E. O'Brien 	    switch (i) {
393c80476e4SDavid E. O'Brien 
394c80476e4SDavid E. O'Brien 	    case GTR:
395c80476e4SDavid E. O'Brien 		i = egetn(p1) > egetn(p2);
396c80476e4SDavid E. O'Brien 		break;
397c80476e4SDavid E. O'Brien 
398c80476e4SDavid E. O'Brien 	    case GTR | 1:
399c80476e4SDavid E. O'Brien 		i = egetn(p1) >= egetn(p2);
400c80476e4SDavid E. O'Brien 		break;
401c80476e4SDavid E. O'Brien 
402c80476e4SDavid E. O'Brien 	    case LSS:
403c80476e4SDavid E. O'Brien 		i = egetn(p1) < egetn(p2);
404c80476e4SDavid E. O'Brien 		break;
405c80476e4SDavid E. O'Brien 
406c80476e4SDavid E. O'Brien 	    case LSS | 1:
407c80476e4SDavid E. O'Brien 		i = egetn(p1) <= egetn(p2);
408c80476e4SDavid E. O'Brien 		break;
409c80476e4SDavid E. O'Brien 	    }
410c80476e4SDavid E. O'Brien 	xfree((ptr_t) p1);
411c80476e4SDavid E. O'Brien 	xfree((ptr_t) p2);
412c80476e4SDavid E. O'Brien 	return (putn(i));
413c80476e4SDavid E. O'Brien     }
414c80476e4SDavid E. O'Brien     return (p1);
415c80476e4SDavid E. O'Brien }
416c80476e4SDavid E. O'Brien 
417c80476e4SDavid E. O'Brien static Char *
418c80476e4SDavid E. O'Brien exp3a(vp, ignore)
419c80476e4SDavid E. O'Brien     register Char ***vp;
420c80476e4SDavid E. O'Brien     bool    ignore;
421c80476e4SDavid E. O'Brien {
422c80476e4SDavid E. O'Brien     register Char *p1, *p2, *op;
423c80476e4SDavid E. O'Brien     register int i;
424c80476e4SDavid E. O'Brien 
425c80476e4SDavid E. O'Brien     p1 = exp4(vp, ignore);
426c80476e4SDavid E. O'Brien #ifdef EDEBUG
427c80476e4SDavid E. O'Brien     etracc("exp3a p1", p1, vp);
428c80476e4SDavid E. O'Brien #endif /* EDEBUG */
429c80476e4SDavid E. O'Brien     op = **vp;
430c80476e4SDavid E. O'Brien     if (op && any("<>", op[0]) && op[0] == op[1]) {
431c80476e4SDavid E. O'Brien 	(*vp)++;
432c80476e4SDavid E. O'Brien 	p2 = exp3a(vp, ignore);
433c80476e4SDavid E. O'Brien #ifdef EDEBUG
434c80476e4SDavid E. O'Brien 	etracc("exp3a p2", p2, vp);
435c80476e4SDavid E. O'Brien #endif /* EDEBUG */
436c80476e4SDavid E. O'Brien 	if (op[0] == '<')
437c80476e4SDavid E. O'Brien 	    i = egetn(p1) << egetn(p2);
438c80476e4SDavid E. O'Brien 	else
439c80476e4SDavid E. O'Brien 	    i = egetn(p1) >> egetn(p2);
440c80476e4SDavid E. O'Brien 	xfree((ptr_t) p1);
441c80476e4SDavid E. O'Brien 	xfree((ptr_t) p2);
442c80476e4SDavid E. O'Brien 	return (putn(i));
443c80476e4SDavid E. O'Brien     }
444c80476e4SDavid E. O'Brien     return (p1);
445c80476e4SDavid E. O'Brien }
446c80476e4SDavid E. O'Brien 
447c80476e4SDavid E. O'Brien static Char *
448c80476e4SDavid E. O'Brien exp4(vp, ignore)
449c80476e4SDavid E. O'Brien     register Char ***vp;
450c80476e4SDavid E. O'Brien     bool    ignore;
451c80476e4SDavid E. O'Brien {
452c80476e4SDavid E. O'Brien     register Char *p1, *p2;
453c80476e4SDavid E. O'Brien     register int i = 0;
454c80476e4SDavid E. O'Brien 
455c80476e4SDavid E. O'Brien     p1 = exp5(vp, ignore);
456c80476e4SDavid E. O'Brien #ifdef EDEBUG
457c80476e4SDavid E. O'Brien     etracc("exp4 p1", p1, vp);
458c80476e4SDavid E. O'Brien #endif /* EDEBUG */
459c80476e4SDavid E. O'Brien     if (isa(**vp, ADDOP)) {
460c80476e4SDavid E. O'Brien 	register Char *op = *(*vp)++;
461c80476e4SDavid E. O'Brien 
462c80476e4SDavid E. O'Brien 	p2 = exp4(vp, ignore);
463c80476e4SDavid E. O'Brien #ifdef EDEBUG
464c80476e4SDavid E. O'Brien 	etracc("exp4 p2", p2, vp);
465c80476e4SDavid E. O'Brien #endif /* EDEBUG */
466c80476e4SDavid E. O'Brien 	if (!(ignore & TEXP_IGNORE))
467c80476e4SDavid E. O'Brien 	    switch (op[0]) {
468c80476e4SDavid E. O'Brien 
469c80476e4SDavid E. O'Brien 	    case '+':
470c80476e4SDavid E. O'Brien 		i = egetn(p1) + egetn(p2);
471c80476e4SDavid E. O'Brien 		break;
472c80476e4SDavid E. O'Brien 
473c80476e4SDavid E. O'Brien 	    case '-':
474c80476e4SDavid E. O'Brien 		i = egetn(p1) - egetn(p2);
475c80476e4SDavid E. O'Brien 		break;
476c80476e4SDavid E. O'Brien 	    }
477c80476e4SDavid E. O'Brien 	xfree((ptr_t) p1);
478c80476e4SDavid E. O'Brien 	xfree((ptr_t) p2);
479c80476e4SDavid E. O'Brien 	return (putn(i));
480c80476e4SDavid E. O'Brien     }
481c80476e4SDavid E. O'Brien     return (p1);
482c80476e4SDavid E. O'Brien }
483c80476e4SDavid E. O'Brien 
484c80476e4SDavid E. O'Brien static Char *
485c80476e4SDavid E. O'Brien exp5(vp, ignore)
486c80476e4SDavid E. O'Brien     register Char ***vp;
487c80476e4SDavid E. O'Brien     bool    ignore;
488c80476e4SDavid E. O'Brien {
489c80476e4SDavid E. O'Brien     register Char *p1, *p2;
490c80476e4SDavid E. O'Brien     register int i = 0;
491c80476e4SDavid E. O'Brien 
492c80476e4SDavid E. O'Brien     p1 = exp6(vp, ignore);
493c80476e4SDavid E. O'Brien #ifdef EDEBUG
494c80476e4SDavid E. O'Brien     etracc("exp5 p1", p1, vp);
495c80476e4SDavid E. O'Brien #endif /* EDEBUG */
496c80476e4SDavid E. O'Brien 
497c80476e4SDavid E. O'Brien     if (isa(**vp, MULOP)) {
498c80476e4SDavid E. O'Brien 	register Char *op = *(*vp)++;
499c80476e4SDavid E. O'Brien 	if ((ignore & TEXP_NOGLOB) != 0)
500c80476e4SDavid E. O'Brien 	    /*
501c80476e4SDavid E. O'Brien 	     * We are just trying to get the right side of
502c80476e4SDavid E. O'Brien 	     * a =~ or !~ operator
503c80476e4SDavid E. O'Brien 	     */
504c80476e4SDavid E. O'Brien 	    return Strsave(op);
505c80476e4SDavid E. O'Brien 
506c80476e4SDavid E. O'Brien 	p2 = exp5(vp, ignore);
507c80476e4SDavid E. O'Brien #ifdef EDEBUG
508c80476e4SDavid E. O'Brien 	etracc("exp5 p2", p2, vp);
509c80476e4SDavid E. O'Brien #endif /* EDEBUG */
510c80476e4SDavid E. O'Brien 	if (!(ignore & TEXP_IGNORE))
511c80476e4SDavid E. O'Brien 	    switch (op[0]) {
512c80476e4SDavid E. O'Brien 
513c80476e4SDavid E. O'Brien 	    case '*':
514c80476e4SDavid E. O'Brien 		i = egetn(p1) * egetn(p2);
515c80476e4SDavid E. O'Brien 		break;
516c80476e4SDavid E. O'Brien 
517c80476e4SDavid E. O'Brien 	    case '/':
518c80476e4SDavid E. O'Brien 		i = egetn(p2);
519c80476e4SDavid E. O'Brien 		if (i == 0)
520c80476e4SDavid E. O'Brien 		    stderror(ERR_DIV0);
521c80476e4SDavid E. O'Brien 		i = egetn(p1) / i;
522c80476e4SDavid E. O'Brien 		break;
523c80476e4SDavid E. O'Brien 
524c80476e4SDavid E. O'Brien 	    case '%':
525c80476e4SDavid E. O'Brien 		i = egetn(p2);
526c80476e4SDavid E. O'Brien 		if (i == 0)
527c80476e4SDavid E. O'Brien 		    stderror(ERR_MOD0);
528c80476e4SDavid E. O'Brien 		i = egetn(p1) % i;
529c80476e4SDavid E. O'Brien 		break;
530c80476e4SDavid E. O'Brien 	    }
531c80476e4SDavid E. O'Brien 	xfree((ptr_t) p1);
532c80476e4SDavid E. O'Brien 	xfree((ptr_t) p2);
533c80476e4SDavid E. O'Brien 	return (putn(i));
534c80476e4SDavid E. O'Brien     }
535c80476e4SDavid E. O'Brien     return (p1);
536c80476e4SDavid E. O'Brien }
537c80476e4SDavid E. O'Brien 
538c80476e4SDavid E. O'Brien static Char *
539c80476e4SDavid E. O'Brien exp6(vp, ignore)
540c80476e4SDavid E. O'Brien     register Char ***vp;
541c80476e4SDavid E. O'Brien     bool    ignore;
542c80476e4SDavid E. O'Brien {
543c80476e4SDavid E. O'Brien     int     ccode, i = 0;
544c80476e4SDavid E. O'Brien     register Char *cp;
545c80476e4SDavid E. O'Brien 
546c80476e4SDavid E. O'Brien     if (**vp == 0)
547c80476e4SDavid E. O'Brien 	stderror(ERR_NAME | ERR_EXPRESSION);
548c80476e4SDavid E. O'Brien     if (eq(**vp, STRbang)) {
549c80476e4SDavid E. O'Brien 	(*vp)++;
550c80476e4SDavid E. O'Brien 	cp = exp6(vp, ignore);
551c80476e4SDavid E. O'Brien #ifdef EDEBUG
552c80476e4SDavid E. O'Brien 	etracc("exp6 ! cp", cp, vp);
553c80476e4SDavid E. O'Brien #endif /* EDEBUG */
554c80476e4SDavid E. O'Brien 	i = egetn(cp);
555c80476e4SDavid E. O'Brien 	xfree((ptr_t) cp);
556c80476e4SDavid E. O'Brien 	return (putn(!i));
557c80476e4SDavid E. O'Brien     }
558c80476e4SDavid E. O'Brien     if (eq(**vp, STRtilde)) {
559c80476e4SDavid E. O'Brien 	(*vp)++;
560c80476e4SDavid E. O'Brien 	cp = exp6(vp, ignore);
561c80476e4SDavid E. O'Brien #ifdef EDEBUG
562c80476e4SDavid E. O'Brien 	etracc("exp6 ~ cp", cp, vp);
563c80476e4SDavid E. O'Brien #endif /* EDEBUG */
564c80476e4SDavid E. O'Brien 	i = egetn(cp);
565c80476e4SDavid E. O'Brien 	xfree((ptr_t) cp);
566c80476e4SDavid E. O'Brien 	return (putn(~i));
567c80476e4SDavid E. O'Brien     }
568c80476e4SDavid E. O'Brien     if (eq(**vp, STRLparen)) {
569c80476e4SDavid E. O'Brien 	(*vp)++;
570c80476e4SDavid E. O'Brien 	ccode = exp0(vp, ignore);
571c80476e4SDavid E. O'Brien #ifdef EDEBUG
572c80476e4SDavid E. O'Brien 	etraci("exp6 () ccode", ccode, vp);
573c80476e4SDavid E. O'Brien #endif /* EDEBUG */
574c80476e4SDavid E. O'Brien 	if (*vp == 0 || **vp == 0 || ***vp != ')')
575c80476e4SDavid E. O'Brien 	    stderror(ERR_NAME | ERR_EXPRESSION);
576c80476e4SDavid E. O'Brien 	(*vp)++;
577c80476e4SDavid E. O'Brien 	return (putn(ccode));
578c80476e4SDavid E. O'Brien     }
579c80476e4SDavid E. O'Brien     if (eq(**vp, STRLbrace)) {
580c80476e4SDavid E. O'Brien 	register Char **v;
581c80476e4SDavid E. O'Brien 	struct command faket;
582c80476e4SDavid E. O'Brien 	Char   *fakecom[2];
583c80476e4SDavid E. O'Brien 
584c80476e4SDavid E. O'Brien 	faket.t_dtyp = NODE_COMMAND;
585c80476e4SDavid E. O'Brien 	faket.t_dflg = F_BACKQ;
586c80476e4SDavid E. O'Brien 	faket.t_dcar = faket.t_dcdr = faket.t_dspr = NULL;
587c80476e4SDavid E. O'Brien 	faket.t_dcom = fakecom;
588c80476e4SDavid E. O'Brien 	fakecom[0] = STRfakecom;
589c80476e4SDavid E. O'Brien 	fakecom[1] = NULL;
590c80476e4SDavid E. O'Brien 	(*vp)++;
591c80476e4SDavid E. O'Brien 	v = *vp;
592c80476e4SDavid E. O'Brien 	for (;;) {
593c80476e4SDavid E. O'Brien 	    if (!**vp)
594c80476e4SDavid E. O'Brien 		stderror(ERR_NAME | ERR_MISSING, '}');
595c80476e4SDavid E. O'Brien 	    if (eq(*(*vp)++, STRRbrace))
596c80476e4SDavid E. O'Brien 		break;
597c80476e4SDavid E. O'Brien 	}
598c80476e4SDavid E. O'Brien 	if (ignore & TEXP_IGNORE)
599c80476e4SDavid E. O'Brien 	    return (Strsave(STRNULL));
600c80476e4SDavid E. O'Brien 	psavejob();
601c80476e4SDavid E. O'Brien 	if (pfork(&faket, -1) == 0) {
602c80476e4SDavid E. O'Brien 	    *--(*vp) = 0;
603c80476e4SDavid E. O'Brien 	    evalav(v);
604c80476e4SDavid E. O'Brien 	    exitstat();
605c80476e4SDavid E. O'Brien 	}
606c80476e4SDavid E. O'Brien 	pwait();
607c80476e4SDavid E. O'Brien 	prestjob();
608c80476e4SDavid E. O'Brien #ifdef EDEBUG
609c80476e4SDavid E. O'Brien 	etraci("exp6 {} status", egetn(varval(STRstatus)), vp);
610c80476e4SDavid E. O'Brien #endif /* EDEBUG */
611c80476e4SDavid E. O'Brien 	return (putn(egetn(varval(STRstatus)) == 0));
612c80476e4SDavid E. O'Brien     }
613c80476e4SDavid E. O'Brien     if (isa(**vp, ANYOP))
614c80476e4SDavid E. O'Brien 	return (Strsave(STRNULL));
615c80476e4SDavid E. O'Brien     cp = *(*vp)++;
616c80476e4SDavid E. O'Brien #ifdef convex
617c80476e4SDavid E. O'Brien # define FILETESTS "erwxfdzoplstSXLbcugkmKR"
618c80476e4SDavid E. O'Brien #else
619c80476e4SDavid E. O'Brien # define FILETESTS "erwxfdzoplstSXLbcugkmK"
620c80476e4SDavid E. O'Brien #endif /* convex */
621c80476e4SDavid E. O'Brien #define FILEVALS  "ZAMCDIUGNFPL"
622c80476e4SDavid E. O'Brien     if (*cp == '-' && (any(FILETESTS, cp[1]) || any(FILEVALS, cp[1])))
623c80476e4SDavid E. O'Brien         return(filetest(cp, vp, ignore));
624c80476e4SDavid E. O'Brien #ifdef EDEBUG
625c80476e4SDavid E. O'Brien     etracc("exp6 default", cp, vp);
626c80476e4SDavid E. O'Brien #endif /* EDEBUG */
627c80476e4SDavid E. O'Brien     return (ignore & TEXP_NOGLOB ? Strsave(cp) : globone(cp, G_APPEND));
628c80476e4SDavid E. O'Brien }
629c80476e4SDavid E. O'Brien 
630c80476e4SDavid E. O'Brien 
631c80476e4SDavid E. O'Brien /*
632c80476e4SDavid E. O'Brien  * Extended file tests
633c80476e4SDavid E. O'Brien  * From: John Rowe <rowe@excc.exeter.ac.uk>
634c80476e4SDavid E. O'Brien  */
635c80476e4SDavid E. O'Brien Char *
636c80476e4SDavid E. O'Brien filetest(cp, vp, ignore)
637c80476e4SDavid E. O'Brien     Char *cp, ***vp;
638c80476e4SDavid E. O'Brien     bool ignore;
639c80476e4SDavid E. O'Brien {
640c80476e4SDavid E. O'Brien #ifdef convex
641c80476e4SDavid E. O'Brien     struct cvxstat stb, *st = NULL;
642c80476e4SDavid E. O'Brien # define TCSH_STAT	stat64
643c80476e4SDavid E. O'Brien #else
644c80476e4SDavid E. O'Brien # define TCSH_STAT	stat
645c80476e4SDavid E. O'Brien     struct stat stb, *st = NULL;
646c80476e4SDavid E. O'Brien #endif /* convex */
647c80476e4SDavid E. O'Brien 
648c80476e4SDavid E. O'Brien #ifdef S_IFLNK
649c80476e4SDavid E. O'Brien # ifdef convex
650c80476e4SDavid E. O'Brien     struct cvxstat lstb, *lst = NULL;
651c80476e4SDavid E. O'Brien #  define TCSH_LSTAT lstat64
652c80476e4SDavid E. O'Brien # else
653c80476e4SDavid E. O'Brien #  define TCSH_LSTAT lstat
654c80476e4SDavid E. O'Brien     struct stat lstb, *lst = NULL;
655c80476e4SDavid E. O'Brien # endif /* convex */
656c80476e4SDavid E. O'Brien     char *filnam;
657c80476e4SDavid E. O'Brien #endif /* S_IFLNK */
658c80476e4SDavid E. O'Brien 
659c80476e4SDavid E. O'Brien     int i = 0;
660c80476e4SDavid E. O'Brien     unsigned pmask = 0xffff;
661c80476e4SDavid E. O'Brien     bool altout = 0;
662c80476e4SDavid E. O'Brien     Char *ft = cp, *dp, *ep, *strdev, *strino, *strF, *str, valtest = '\0',
663c80476e4SDavid E. O'Brien     *errval = STR0;
664c80476e4SDavid E. O'Brien     char *string, string0[8];
665c80476e4SDavid E. O'Brien     time_t footime;
666c80476e4SDavid E. O'Brien     struct passwd *pw;
667c80476e4SDavid E. O'Brien     struct group *gr;
668c80476e4SDavid E. O'Brien 
669c80476e4SDavid E. O'Brien     while(any(FILETESTS, *++ft))
670c80476e4SDavid E. O'Brien 	continue;
671c80476e4SDavid E. O'Brien 
672c80476e4SDavid E. O'Brien     if (!*ft && *(ft - 1) == 'L')
673c80476e4SDavid E. O'Brien 	--ft;
674c80476e4SDavid E. O'Brien 
675c80476e4SDavid E. O'Brien     if (any(FILEVALS, *ft)) {
676c80476e4SDavid E. O'Brien 	valtest = *ft++;
677c80476e4SDavid E. O'Brien 	/*
678c80476e4SDavid E. O'Brien 	 * Value tests return '-1' on failure as 0 is
679c80476e4SDavid E. O'Brien 	 * a legitimate value for many of them.
680c80476e4SDavid E. O'Brien 	 * 'F' returns ':' for compatibility.
681c80476e4SDavid E. O'Brien 	 */
682c80476e4SDavid E. O'Brien 	errval = valtest == 'F' ? STRcolon : STRminus1;
683c80476e4SDavid E. O'Brien 
684c80476e4SDavid E. O'Brien 	if (valtest == 'P' && *ft >= '0' && *ft <= '7') {
685c80476e4SDavid E. O'Brien 	    pmask = (char) *ft - '0';
686c80476e4SDavid E. O'Brien 	    while ( *++ft >= '0' && *ft <= '7' )
687c80476e4SDavid E. O'Brien 		pmask = 8 * pmask + ((char) *ft - '0');
688c80476e4SDavid E. O'Brien 	}
689c80476e4SDavid E. O'Brien 	if (Strcmp(ft, STRcolon) == 0 && any("AMCUGP", valtest)) {
690c80476e4SDavid E. O'Brien 	    altout = 1;
691c80476e4SDavid E. O'Brien 	    ++ft;
692c80476e4SDavid E. O'Brien 	}
693c80476e4SDavid E. O'Brien     }
694c80476e4SDavid E. O'Brien 
695c80476e4SDavid E. O'Brien     if (*ft || ft == cp + 1)
696c80476e4SDavid E. O'Brien 	stderror(ERR_NAME | ERR_FILEINQ);
697c80476e4SDavid E. O'Brien 
698c80476e4SDavid E. O'Brien     /*
699c80476e4SDavid E. O'Brien      * Detect missing file names by checking for operator in the file name
700c80476e4SDavid E. O'Brien      * position.  However, if an operator name appears there, we must make
701c80476e4SDavid E. O'Brien      * sure that there's no file by that name (e.g., "/") before announcing
702c80476e4SDavid E. O'Brien      * an error.  Even this check isn't quite right, since it doesn't take
703c80476e4SDavid E. O'Brien      * globbing into account.
704c80476e4SDavid E. O'Brien      */
705c80476e4SDavid E. O'Brien 
706c80476e4SDavid E. O'Brien     if (isa(**vp, ANYOP) && TCSH_STAT(short2str(**vp), &stb))
707c80476e4SDavid E. O'Brien 	stderror(ERR_NAME | ERR_FILENAME);
708c80476e4SDavid E. O'Brien 
709c80476e4SDavid E. O'Brien     dp = *(*vp)++;
710c80476e4SDavid E. O'Brien     if (ignore & TEXP_IGNORE)
711c80476e4SDavid E. O'Brien 	return (Strsave(STRNULL));
712c80476e4SDavid E. O'Brien     ep = globone(dp, G_APPEND);
713c80476e4SDavid E. O'Brien     ft = &cp[1];
714c80476e4SDavid E. O'Brien     do
715c80476e4SDavid E. O'Brien 	switch (*ft) {
716c80476e4SDavid E. O'Brien 
717c80476e4SDavid E. O'Brien 	case 'r':
718c80476e4SDavid E. O'Brien 	    i = !sh_access(ep, R_OK);
719c80476e4SDavid E. O'Brien 	    break;
720c80476e4SDavid E. O'Brien 
721c80476e4SDavid E. O'Brien 	case 'w':
722c80476e4SDavid E. O'Brien 	    i = !sh_access(ep, W_OK);
723c80476e4SDavid E. O'Brien 	    break;
724c80476e4SDavid E. O'Brien 
725c80476e4SDavid E. O'Brien 	case 'x':
726c80476e4SDavid E. O'Brien 	    i = !sh_access(ep, X_OK);
727c80476e4SDavid E. O'Brien 	    break;
728c80476e4SDavid E. O'Brien 
729c80476e4SDavid E. O'Brien 	case 'X':	/* tcsh extension, name is an executable in the path
730c80476e4SDavid E. O'Brien 			 * or a tcsh builtin command
731c80476e4SDavid E. O'Brien 			 */
732c80476e4SDavid E. O'Brien 	    i = find_cmd(ep, 0);
733c80476e4SDavid E. O'Brien 	    break;
734c80476e4SDavid E. O'Brien 
735c80476e4SDavid E. O'Brien 	case 't':	/* SGI extension, true when file is a tty */
736c80476e4SDavid E. O'Brien 	    i = isatty(atoi(short2str(ep)));
737c80476e4SDavid E. O'Brien 	    break;
738c80476e4SDavid E. O'Brien 
739c80476e4SDavid E. O'Brien 	default:
740c80476e4SDavid E. O'Brien 
741c80476e4SDavid E. O'Brien #ifdef S_IFLNK
742c80476e4SDavid E. O'Brien 	    if (tolower(*ft) == 'l') {
743c80476e4SDavid E. O'Brien 		/*
744c80476e4SDavid E. O'Brien 		 * avoid convex compiler bug.
745c80476e4SDavid E. O'Brien 		 */
746c80476e4SDavid E. O'Brien 		if (!lst) {
747c80476e4SDavid E. O'Brien 		    lst = &lstb;
748c80476e4SDavid E. O'Brien 		    if (TCSH_LSTAT(short2str(ep), lst) == -1) {
749c80476e4SDavid E. O'Brien 			xfree((ptr_t) ep);
750c80476e4SDavid E. O'Brien 			return (Strsave(errval));
751c80476e4SDavid E. O'Brien 		    }
752c80476e4SDavid E. O'Brien 		}
753c80476e4SDavid E. O'Brien 		if (*ft == 'L')
754c80476e4SDavid E. O'Brien 		    st = lst;
755c80476e4SDavid E. O'Brien 	    }
756c80476e4SDavid E. O'Brien 	    else
757c80476e4SDavid E. O'Brien #endif /* S_IFLNK */
758c80476e4SDavid E. O'Brien 		/*
759c80476e4SDavid E. O'Brien 		 * avoid convex compiler bug.
760c80476e4SDavid E. O'Brien 		 */
761c80476e4SDavid E. O'Brien 		if (!st) {
762c80476e4SDavid E. O'Brien 		    st = &stb;
763c80476e4SDavid E. O'Brien 		    if (TCSH_STAT(short2str(ep), st) == -1) {
764c80476e4SDavid E. O'Brien 			xfree((ptr_t) ep);
765c80476e4SDavid E. O'Brien 			return (Strsave(errval));
766c80476e4SDavid E. O'Brien 		    }
767c80476e4SDavid E. O'Brien 		}
768c80476e4SDavid E. O'Brien 
769c80476e4SDavid E. O'Brien 	    switch (*ft) {
770c80476e4SDavid E. O'Brien 
771c80476e4SDavid E. O'Brien 	    case 'f':
772c80476e4SDavid E. O'Brien #ifdef S_ISREG
773c80476e4SDavid E. O'Brien 		i = S_ISREG(st->st_mode);
774c80476e4SDavid E. O'Brien #else /* !S_ISREG */
775c80476e4SDavid E. O'Brien 		i = 0;
776c80476e4SDavid E. O'Brien #endif /* S_ISREG */
777c80476e4SDavid E. O'Brien 		break;
778c80476e4SDavid E. O'Brien 
779c80476e4SDavid E. O'Brien 	    case 'd':
780c80476e4SDavid E. O'Brien #ifdef S_ISDIR
781c80476e4SDavid E. O'Brien 		i = S_ISDIR(st->st_mode);
782c80476e4SDavid E. O'Brien #else /* !S_ISDIR */
783c80476e4SDavid E. O'Brien 		i = 0;
784c80476e4SDavid E. O'Brien #endif /* S_ISDIR */
785c80476e4SDavid E. O'Brien 		break;
786c80476e4SDavid E. O'Brien 
787c80476e4SDavid E. O'Brien 	    case 'p':
788c80476e4SDavid E. O'Brien #ifdef S_ISFIFO
789c80476e4SDavid E. O'Brien 		i = S_ISFIFO(st->st_mode);
790c80476e4SDavid E. O'Brien #else /* !S_ISFIFO */
791c80476e4SDavid E. O'Brien 		i = 0;
792c80476e4SDavid E. O'Brien #endif /* S_ISFIFO */
793c80476e4SDavid E. O'Brien 		break;
794c80476e4SDavid E. O'Brien 
795c80476e4SDavid E. O'Brien 	    case 'm' :
796c80476e4SDavid E. O'Brien #ifdef S_ISOFL
797c80476e4SDavid E. O'Brien 	      i = S_ISOFL(st->st_dm_mode);
798c80476e4SDavid E. O'Brien #else /* !S_ISOFL */
799c80476e4SDavid E. O'Brien 	      i = 0;
800c80476e4SDavid E. O'Brien #endif /* S_ISOFL */
801c80476e4SDavid E. O'Brien 	      break ;
802c80476e4SDavid E. O'Brien 
803c80476e4SDavid E. O'Brien 	    case 'K' :
804c80476e4SDavid E. O'Brien #ifdef S_ISOFL
805c80476e4SDavid E. O'Brien 	      i = stb.st_dm_key;
806c80476e4SDavid E. O'Brien #else /* !S_ISOFL */
807c80476e4SDavid E. O'Brien 	      i = 0;
808c80476e4SDavid E. O'Brien #endif /* S_ISOFL */
809c80476e4SDavid E. O'Brien 	      break ;
810c80476e4SDavid E. O'Brien 
811c80476e4SDavid E. O'Brien 
812c80476e4SDavid E. O'Brien 	    case 'l':
813c80476e4SDavid E. O'Brien #ifdef S_ISLNK
814c80476e4SDavid E. O'Brien 		i = S_ISLNK(lst->st_mode);
815c80476e4SDavid E. O'Brien #else /* !S_ISLNK */
816c80476e4SDavid E. O'Brien 		i = 0;
817c80476e4SDavid E. O'Brien #endif /* S_ISLNK */
818c80476e4SDavid E. O'Brien 		break;
819c80476e4SDavid E. O'Brien 
820c80476e4SDavid E. O'Brien 	    case 'S':
821c80476e4SDavid E. O'Brien # ifdef S_ISSOCK
822c80476e4SDavid E. O'Brien 		i = S_ISSOCK(st->st_mode);
823c80476e4SDavid E. O'Brien # else /* !S_ISSOCK */
824c80476e4SDavid E. O'Brien 		i = 0;
825c80476e4SDavid E. O'Brien # endif /* S_ISSOCK */
826c80476e4SDavid E. O'Brien 		break;
827c80476e4SDavid E. O'Brien 
828c80476e4SDavid E. O'Brien 	    case 'b':
829c80476e4SDavid E. O'Brien #ifdef S_ISBLK
830c80476e4SDavid E. O'Brien 		i = S_ISBLK(st->st_mode);
831c80476e4SDavid E. O'Brien #else /* !S_ISBLK */
832c80476e4SDavid E. O'Brien 		i = 0;
833c80476e4SDavid E. O'Brien #endif /* S_ISBLK */
834c80476e4SDavid E. O'Brien 		break;
835c80476e4SDavid E. O'Brien 
836c80476e4SDavid E. O'Brien 	    case 'c':
837c80476e4SDavid E. O'Brien #ifdef S_ISCHR
838c80476e4SDavid E. O'Brien 		i = S_ISCHR(st->st_mode);
839c80476e4SDavid E. O'Brien #else /* !S_ISCHR */
840c80476e4SDavid E. O'Brien 		i = 0;
841c80476e4SDavid E. O'Brien #endif /* S_ISCHR */
842c80476e4SDavid E. O'Brien 		break;
843c80476e4SDavid E. O'Brien 
844c80476e4SDavid E. O'Brien 	    case 'u':
845c80476e4SDavid E. O'Brien 		i = (S_ISUID & st->st_mode) != 0;
846c80476e4SDavid E. O'Brien 		break;
847c80476e4SDavid E. O'Brien 
848c80476e4SDavid E. O'Brien 	    case 'g':
849c80476e4SDavid E. O'Brien 		i = (S_ISGID & st->st_mode) != 0;
850c80476e4SDavid E. O'Brien 		break;
851c80476e4SDavid E. O'Brien 
852c80476e4SDavid E. O'Brien 	    case 'k':
853c80476e4SDavid E. O'Brien 		i = (S_ISVTX & st->st_mode) != 0;
854c80476e4SDavid E. O'Brien 		break;
855c80476e4SDavid E. O'Brien 
856c80476e4SDavid E. O'Brien 	    case 'z':
857c80476e4SDavid E. O'Brien 		i = st->st_size == 0;
858c80476e4SDavid E. O'Brien 		break;
859c80476e4SDavid E. O'Brien 
860c80476e4SDavid E. O'Brien #ifdef convex
861c80476e4SDavid E. O'Brien 	    case 'R':
862c80476e4SDavid E. O'Brien 		i = (stb.st_dmonflags & IMIGRATED) == IMIGRATED;
863c80476e4SDavid E. O'Brien 		break;
864c80476e4SDavid E. O'Brien #endif /* convex */
865c80476e4SDavid E. O'Brien 
866c80476e4SDavid E. O'Brien 	    case 's':
867c80476e4SDavid E. O'Brien 		i = stb.st_size != 0;
868c80476e4SDavid E. O'Brien 		break;
869c80476e4SDavid E. O'Brien 
870c80476e4SDavid E. O'Brien 	    case 'e':
871c80476e4SDavid E. O'Brien 		i = 1;
872c80476e4SDavid E. O'Brien 		break;
873c80476e4SDavid E. O'Brien 
874c80476e4SDavid E. O'Brien 	    case 'o':
875c80476e4SDavid E. O'Brien 		i = st->st_uid == uid;
876c80476e4SDavid E. O'Brien 		break;
877c80476e4SDavid E. O'Brien 
878c80476e4SDavid E. O'Brien 		/*
879c80476e4SDavid E. O'Brien 		 * Value operators are a tcsh extension.
880c80476e4SDavid E. O'Brien 		 */
881c80476e4SDavid E. O'Brien 
882c80476e4SDavid E. O'Brien 	    case 'D':
883c80476e4SDavid E. O'Brien 		i = (int) st->st_dev;
884c80476e4SDavid E. O'Brien 		break;
885c80476e4SDavid E. O'Brien 
886c80476e4SDavid E. O'Brien 	    case 'I':
887c80476e4SDavid E. O'Brien 		i = (int) st->st_ino;
888c80476e4SDavid E. O'Brien 		break;
889c80476e4SDavid E. O'Brien 
890c80476e4SDavid E. O'Brien 	    case 'F':
891c80476e4SDavid E. O'Brien 		strdev = putn( (int) st->st_dev);
892c80476e4SDavid E. O'Brien 		strino = putn( (int) st->st_ino);
893c80476e4SDavid E. O'Brien 		strF = (Char *) xmalloc((size_t) (2 + Strlen(strdev) +
894c80476e4SDavid E. O'Brien 					 Strlen(strino)) * sizeof(Char));
895c80476e4SDavid E. O'Brien 		(void) Strcat(Strcat(Strcpy(strF, strdev), STRcolon), strino);
896c80476e4SDavid E. O'Brien 		xfree((ptr_t) strdev);
897c80476e4SDavid E. O'Brien 		xfree((ptr_t) strino);
898c80476e4SDavid E. O'Brien 		xfree((ptr_t) ep);
899c80476e4SDavid E. O'Brien 		return(strF);
900c80476e4SDavid E. O'Brien 
901c80476e4SDavid E. O'Brien 	    case 'L':
902c80476e4SDavid E. O'Brien 		if ( *(ft + 1) ) {
903c80476e4SDavid E. O'Brien 		    i = 1;
904c80476e4SDavid E. O'Brien 		    break;
905c80476e4SDavid E. O'Brien 		}
906c80476e4SDavid E. O'Brien #ifdef S_ISLNK
907c80476e4SDavid E. O'Brien 		filnam = short2str(ep);
908c80476e4SDavid E. O'Brien #ifdef PATH_MAX
909c80476e4SDavid E. O'Brien # define MY_PATH_MAX PATH_MAX
910c80476e4SDavid E. O'Brien #else /* !PATH_MAX */
911c80476e4SDavid E. O'Brien /*
912c80476e4SDavid E. O'Brien  * I can't think of any more sensible alterative; readlink doesn't give
913c80476e4SDavid E. O'Brien  * us an errno if the buffer isn't large enough :-(
914c80476e4SDavid E. O'Brien  */
915c80476e4SDavid E. O'Brien # define MY_PATH_MAX  2048
916c80476e4SDavid E. O'Brien #endif /* PATH_MAX */
917c80476e4SDavid E. O'Brien 		i = readlink(filnam, string = (char *)
918c80476e4SDavid E. O'Brien 		      xmalloc((size_t) (1 + MY_PATH_MAX) * sizeof(char)),
919c80476e4SDavid E. O'Brien 			MY_PATH_MAX);
920c80476e4SDavid E. O'Brien 		if (i >= 0 && i <= MY_PATH_MAX)
921c80476e4SDavid E. O'Brien 		    string[i] = '\0'; /* readlink does not null terminate */
922c80476e4SDavid E. O'Brien 		strF = (i < 0) ? errval : str2short(string);
923c80476e4SDavid E. O'Brien 		xfree((ptr_t) string);
924c80476e4SDavid E. O'Brien 		xfree((ptr_t) ep);
925c80476e4SDavid E. O'Brien 		return(Strsave(strF));
926c80476e4SDavid E. O'Brien 
927c80476e4SDavid E. O'Brien #else /* !S_ISLNK */
928c80476e4SDavid E. O'Brien 		i = 0;
929c80476e4SDavid E. O'Brien 		break;
930c80476e4SDavid E. O'Brien #endif /* S_ISLNK */
931c80476e4SDavid E. O'Brien 
932c80476e4SDavid E. O'Brien 
933c80476e4SDavid E. O'Brien 	    case 'N':
934c80476e4SDavid E. O'Brien 		i = (int) st->st_nlink;
935c80476e4SDavid E. O'Brien 		break;
936c80476e4SDavid E. O'Brien 
937c80476e4SDavid E. O'Brien 	    case 'P':
938c80476e4SDavid E. O'Brien 		string = string0 + 1;
939c80476e4SDavid E. O'Brien 		(void) xsnprintf(string, sizeof(string0) - 1, "%o",
940c80476e4SDavid E. O'Brien 		    pmask & (unsigned int)
941c80476e4SDavid E. O'Brien 		    ((S_IRWXU|S_IRWXG|S_IRWXO|S_ISUID|S_ISGID) & st->st_mode));
942c80476e4SDavid E. O'Brien 		if (altout && *string != '0')
943c80476e4SDavid E. O'Brien 		    *--string = '0';
944c80476e4SDavid E. O'Brien 		xfree((ptr_t) ep);
945c80476e4SDavid E. O'Brien 		return(Strsave(str2short(string)));
946c80476e4SDavid E. O'Brien 
947c80476e4SDavid E. O'Brien 	    case 'U':
948c80476e4SDavid E. O'Brien 		if (altout && (pw = getpwuid(st->st_uid))) {
949c80476e4SDavid E. O'Brien 		    xfree((ptr_t) ep);
950c80476e4SDavid E. O'Brien 		    return(Strsave(str2short(pw->pw_name)));
951c80476e4SDavid E. O'Brien 		}
952c80476e4SDavid E. O'Brien 		i = (int) st->st_uid;
953c80476e4SDavid E. O'Brien 		break;
954c80476e4SDavid E. O'Brien 
955c80476e4SDavid E. O'Brien 	    case 'G':
956c80476e4SDavid E. O'Brien 		if ( altout && (gr = getgrgid(st->st_gid))) {
957c80476e4SDavid E. O'Brien 		    xfree((ptr_t) ep);
958c80476e4SDavid E. O'Brien 		    return(Strsave(str2short(gr->gr_name)));
959c80476e4SDavid E. O'Brien 		}
960c80476e4SDavid E. O'Brien 		i = (int) st->st_gid;
961c80476e4SDavid E. O'Brien 		break;
962c80476e4SDavid E. O'Brien 
963c80476e4SDavid E. O'Brien 	    case 'Z':
964c80476e4SDavid E. O'Brien 		i = (int) st->st_size;
965c80476e4SDavid E. O'Brien 		break;
966c80476e4SDavid E. O'Brien 
967c80476e4SDavid E. O'Brien 	    case 'A': case 'M': case 'C':
968c80476e4SDavid E. O'Brien 		footime = *ft == 'A' ? st->st_atime :
969c80476e4SDavid E. O'Brien 		    *ft == 'M' ? st->st_mtime : st->st_ctime;
970c80476e4SDavid E. O'Brien 		if (altout) {
971c80476e4SDavid E. O'Brien 		    strF = str2short(ctime(&footime));
972c80476e4SDavid E. O'Brien 		    if ((str = Strchr(strF, '\n')) != NULL)
973c80476e4SDavid E. O'Brien 			*str = (Char) '\0';
974c80476e4SDavid E. O'Brien 		    xfree((ptr_t) ep);
975c80476e4SDavid E. O'Brien 		    return(Strsave(strF));
976c80476e4SDavid E. O'Brien 		}
977c80476e4SDavid E. O'Brien 		i = (int) footime;
978c80476e4SDavid E. O'Brien 		break;
979c80476e4SDavid E. O'Brien 
980c80476e4SDavid E. O'Brien 	    }
981c80476e4SDavid E. O'Brien 	}
982c80476e4SDavid E. O'Brien     while (*++ft && i);
983c80476e4SDavid E. O'Brien #ifdef EDEBUG
984c80476e4SDavid E. O'Brien     etraci("exp6 -? i", i, vp);
985c80476e4SDavid E. O'Brien #endif /* EDEBUG */
986c80476e4SDavid E. O'Brien     xfree((ptr_t) ep);
987c80476e4SDavid E. O'Brien     return (putn(i));
988c80476e4SDavid E. O'Brien }
989c80476e4SDavid E. O'Brien 
990c80476e4SDavid E. O'Brien 
991c80476e4SDavid E. O'Brien static void
992c80476e4SDavid E. O'Brien evalav(v)
993c80476e4SDavid E. O'Brien     register Char **v;
994c80476e4SDavid E. O'Brien {
995c80476e4SDavid E. O'Brien     struct wordent paraml1;
996c80476e4SDavid E. O'Brien     register struct wordent *hp = &paraml1;
997c80476e4SDavid E. O'Brien     struct command *t;
998c80476e4SDavid E. O'Brien     register struct wordent *wdp = hp;
999c80476e4SDavid E. O'Brien 
1000c80476e4SDavid E. O'Brien     set(STRstatus, Strsave(STR0), VAR_READWRITE);
1001c80476e4SDavid E. O'Brien     hp->prev = hp->next = hp;
1002c80476e4SDavid E. O'Brien     hp->word = STRNULL;
1003c80476e4SDavid E. O'Brien     while (*v) {
1004c80476e4SDavid E. O'Brien 	register struct wordent *new =
1005c80476e4SDavid E. O'Brien 	(struct wordent *) xcalloc(1, sizeof *wdp);
1006c80476e4SDavid E. O'Brien 
1007c80476e4SDavid E. O'Brien 	new->prev = wdp;
1008c80476e4SDavid E. O'Brien 	new->next = hp;
1009c80476e4SDavid E. O'Brien 	wdp->next = new;
1010c80476e4SDavid E. O'Brien 	wdp = new;
1011c80476e4SDavid E. O'Brien 	wdp->word = Strsave(*v++);
1012c80476e4SDavid E. O'Brien     }
1013c80476e4SDavid E. O'Brien     hp->prev = wdp;
1014c80476e4SDavid E. O'Brien     alias(&paraml1);
1015c80476e4SDavid E. O'Brien     t = syntax(paraml1.next, &paraml1, 0);
1016c80476e4SDavid E. O'Brien     if (seterr)
1017c80476e4SDavid E. O'Brien 	stderror(ERR_OLD);
101829301572SMark Peek     execute(t, -1, NULL, NULL, TRUE);
1019c80476e4SDavid E. O'Brien     freelex(&paraml1), freesyn(t);
1020c80476e4SDavid E. O'Brien }
1021c80476e4SDavid E. O'Brien 
1022c80476e4SDavid E. O'Brien static int
1023c80476e4SDavid E. O'Brien isa(cp, what)
1024c80476e4SDavid E. O'Brien     register Char *cp;
1025c80476e4SDavid E. O'Brien     register int what;
1026c80476e4SDavid E. O'Brien {
1027c80476e4SDavid E. O'Brien     if (cp == 0)
1028c80476e4SDavid E. O'Brien 	return ((what & RESTOP) != 0);
1029c80476e4SDavid E. O'Brien     if (*cp == '\0')
1030c80476e4SDavid E. O'Brien     	return 0;
1031c80476e4SDavid E. O'Brien     if (cp[1] == 0) {
1032c80476e4SDavid E. O'Brien 	if (what & ADDOP && (*cp == '+' || *cp == '-'))
1033c80476e4SDavid E. O'Brien 	    return (1);
1034c80476e4SDavid E. O'Brien 	if (what & MULOP && (*cp == '*' || *cp == '/' || *cp == '%'))
1035c80476e4SDavid E. O'Brien 	    return (1);
1036c80476e4SDavid E. O'Brien 	if (what & RESTOP && (*cp == '(' || *cp == ')' || *cp == '!' ||
1037c80476e4SDavid E. O'Brien 			      *cp == '~' || *cp == '^' || *cp == '"'))
1038c80476e4SDavid E. O'Brien 	    return (1);
1039c80476e4SDavid E. O'Brien     }
1040c80476e4SDavid E. O'Brien     else if (cp[2] == 0) {
1041c80476e4SDavid E. O'Brien 	if (what & RESTOP) {
1042c80476e4SDavid E. O'Brien 	    if (cp[0] == '|' && cp[1] == '&')
1043c80476e4SDavid E. O'Brien 		return (1);
1044c80476e4SDavid E. O'Brien 	    if (cp[0] == '<' && cp[1] == '<')
1045c80476e4SDavid E. O'Brien 		return (1);
1046c80476e4SDavid E. O'Brien 	    if (cp[0] == '>' && cp[1] == '>')
1047c80476e4SDavid E. O'Brien 		return (1);
1048c80476e4SDavid E. O'Brien 	}
1049c80476e4SDavid E. O'Brien 	if (what & EQOP) {
1050c80476e4SDavid E. O'Brien 	    if (cp[0] == '=') {
1051c80476e4SDavid E. O'Brien 		if (cp[1] == '=')
1052c80476e4SDavid E. O'Brien 		    return (EQEQ);
1053c80476e4SDavid E. O'Brien 		if (cp[1] == '~')
1054c80476e4SDavid E. O'Brien 		    return (EQMATCH);
1055c80476e4SDavid E. O'Brien 	    }
1056c80476e4SDavid E. O'Brien 	    else if (cp[0] == '!') {
1057c80476e4SDavid E. O'Brien 		if (cp[1] == '=')
1058c80476e4SDavid E. O'Brien 		    return (NOTEQ);
1059c80476e4SDavid E. O'Brien 		if (cp[1] == '~')
1060c80476e4SDavid E. O'Brien 		    return (NOTEQMATCH);
1061c80476e4SDavid E. O'Brien 	    }
1062c80476e4SDavid E. O'Brien 	}
1063c80476e4SDavid E. O'Brien     }
1064c80476e4SDavid E. O'Brien     if (what & RELOP) {
1065c80476e4SDavid E. O'Brien 	if (*cp == '<')
1066c80476e4SDavid E. O'Brien 	    return (LSS);
1067c80476e4SDavid E. O'Brien 	if (*cp == '>')
1068c80476e4SDavid E. O'Brien 	    return (GTR);
1069c80476e4SDavid E. O'Brien     }
1070c80476e4SDavid E. O'Brien     return (0);
1071c80476e4SDavid E. O'Brien }
1072c80476e4SDavid E. O'Brien 
1073c80476e4SDavid E. O'Brien static int
1074c80476e4SDavid E. O'Brien egetn(cp)
1075c80476e4SDavid E. O'Brien     register Char *cp;
1076c80476e4SDavid E. O'Brien {
1077c80476e4SDavid E. O'Brien     if (*cp && *cp != '-' && !Isdigit(*cp))
1078c80476e4SDavid E. O'Brien 	stderror(ERR_NAME | ERR_EXPRESSION);
1079c80476e4SDavid E. O'Brien     return (getn(cp));
1080c80476e4SDavid E. O'Brien }
1081c80476e4SDavid E. O'Brien 
1082c80476e4SDavid E. O'Brien /* Phew! */
1083c80476e4SDavid E. O'Brien 
1084c80476e4SDavid E. O'Brien #ifdef EDEBUG
1085c80476e4SDavid E. O'Brien static void
1086c80476e4SDavid E. O'Brien etraci(str, i, vp)
1087c80476e4SDavid E. O'Brien     char   *str;
1088c80476e4SDavid E. O'Brien     int     i;
1089c80476e4SDavid E. O'Brien     Char ***vp;
1090c80476e4SDavid E. O'Brien {
1091c80476e4SDavid E. O'Brien     xprintf("%s=%d\t", str, i);
1092c80476e4SDavid E. O'Brien     blkpr(*vp);
1093c80476e4SDavid E. O'Brien     xputchar('\n');
1094c80476e4SDavid E. O'Brien }
1095c80476e4SDavid E. O'Brien static void
1096c80476e4SDavid E. O'Brien etracc(str, cp, vp)
1097c80476e4SDavid E. O'Brien     char   *str;
1098c80476e4SDavid E. O'Brien     Char   *cp;
1099c80476e4SDavid E. O'Brien     Char ***vp;
1100c80476e4SDavid E. O'Brien {
1101c80476e4SDavid E. O'Brien     xprintf("%s=%s\t", str, cp);
1102c80476e4SDavid E. O'Brien     blkpr(*vp);
1103c80476e4SDavid E. O'Brien     xputchar('\n');
1104c80476e4SDavid E. O'Brien }
1105c80476e4SDavid E. O'Brien #endif /* EDEBUG */
1106