1 /* $NetBSD: exp.c,v 1.19 2007/07/16 18:26:10 christos Exp $ */
4 * Copyright (c) 1980, 1991, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "@(#)exp.c 8.1 (Berkeley) 5/31/93";
37 __RCSID("$NetBSD: exp.c,v 1.19 2007/07/16 18:26:10 christos Exp $");
41 #include <sys/types.h>
50 #endif /* SHORT_STRINGS */
55 #define IGNORE 1 /* in ignore, it means to ignore value, just parse */
56 #define NOGLOB 2 /* in ignore, it means not to globone */
72 static int exp1(Char
***, int);
73 static int csh_exp2(Char
***, int);
74 static int exp2a(Char
***, int);
75 static int exp2b(Char
***, int);
76 static int exp2c(Char
***, int);
77 static Char
*exp3(Char
***, int);
78 static Char
*exp3a(Char
***, int);
79 static Char
*exp4(Char
***, int);
80 static Char
*exp5(Char
***, int);
81 static Char
*exp6(Char
***, int);
82 static void evalav(Char
**);
83 static int isa(Char
*, int);
84 static int egetn(Char
*);
87 static void etracc(char *, Char
*, Char
***);
88 static void etraci(char *, int, Char
***);
98 exp0(Char
***vp
, int ignore
)
102 p1
= exp1(vp
, ignore
);
104 etraci("exp0 p1", p1
, vp
);
106 if (**vp
&& eq(**vp
, STRor2
)) {
110 p2
= exp0(vp
, (ignore
& IGNORE
) || p1
);
112 etraci("exp0 p2", p2
, vp
);
120 exp1(Char
***vp
, int ignore
)
124 p1
= csh_exp2(vp
, ignore
);
126 etraci("exp1 p1", p1
, vp
);
128 if (**vp
&& eq(**vp
, STRand2
)) {
132 p2
= exp1(vp
, (ignore
& IGNORE
) || !p1
);
134 etraci("exp1 p2", p2
, vp
);
142 csh_exp2(Char
***vp
, int ignore
)
146 p1
= exp2a(vp
, ignore
);
148 etraci("exp3 p1", p1
, vp
);
150 if (**vp
&& eq(**vp
, STRor
)) {
154 p2
= csh_exp2(vp
, ignore
);
156 etraci("exp3 p2", p2
, vp
);
164 exp2a(Char
***vp
, int ignore
)
168 p1
= exp2b(vp
, ignore
);
170 etraci("exp2a p1", p1
, vp
);
172 if (**vp
&& eq(**vp
, STRcaret
)) {
176 p2
= exp2a(vp
, ignore
);
178 etraci("exp2a p2", p2
, vp
);
186 exp2b(Char
***vp
, int ignore
)
190 p1
= exp2c(vp
, ignore
);
192 etraci("exp2b p1", p1
, vp
);
194 if (**vp
&& eq(**vp
, STRand
)) {
198 p2
= exp2b(vp
, ignore
);
200 etraci("exp2b p2", p2
, vp
);
208 exp2c(Char
***vp
, int ignore
)
213 p1
= exp3(vp
, ignore
);
215 etracc("exp2c p1", p1
, vp
);
217 if ((i
= isa(**vp
, EQOP
)) != 0) {
219 if (i
== EQMATCH
|| i
== NOTEQMATCH
)
221 p2
= exp3(vp
, ignore
);
223 etracc("exp2c p2", p2
, vp
);
225 if (!(ignore
& IGNORE
))
250 exp3(Char
***vp
, int ignore
)
255 p1
= exp3a(vp
, ignore
);
257 etracc("exp3 p1", p1
, vp
);
259 if ((i
= isa(**vp
, RELOP
)) != 0) {
261 if (**vp
&& eq(**vp
, STRequal
))
263 p2
= exp3(vp
, ignore
);
265 etracc("exp3 p2", p2
, vp
);
267 if (!(ignore
& IGNORE
))
270 i
= egetn(p1
) > egetn(p2
);
273 i
= egetn(p1
) >= egetn(p2
);
276 i
= egetn(p1
) < egetn(p2
);
279 i
= egetn(p1
) <= egetn(p2
);
290 exp3a(Char
***vp
, int ignore
)
295 p1
= exp4(vp
, ignore
);
297 etracc("exp3a p1", p1
, vp
);
300 if (op
&& any("<>", op
[0]) && op
[0] == op
[1]) {
302 p2
= exp3a(vp
, ignore
);
304 etracc("exp3a p2", p2
, vp
);
307 i
= egetn(p1
) << egetn(p2
);
309 i
= egetn(p1
) >> egetn(p2
);
318 exp4(Char
***vp
, int ignore
)
324 p1
= exp5(vp
, ignore
);
326 etracc("exp4 p1", p1
, vp
);
328 if (isa(**vp
, ADDOP
)) {
332 p2
= exp4(vp
, ignore
);
334 etracc("exp4 p2", p2
, vp
);
336 if (!(ignore
& IGNORE
))
339 i
= egetn(p1
) + egetn(p2
);
342 i
= egetn(p1
) - egetn(p2
);
353 exp5(Char
***vp
, int ignore
)
359 p1
= exp6(vp
, ignore
);
361 etracc("exp5 p1", p1
, vp
);
363 if (isa(**vp
, MULOP
)) {
367 p2
= exp5(vp
, ignore
);
369 etracc("exp5 p2", p2
, vp
);
371 if (!(ignore
& IGNORE
))
374 i
= egetn(p1
) * egetn(p2
);
397 exp6(Char
***vp
, int ignore
)
404 stderror(ERR_NAME
| ERR_EXPRESSION
);
405 if (eq(**vp
, STRbang
)) {
407 cp
= exp6(vp
, ignore
);
409 etracc("exp6 ! cp", cp
, vp
);
415 if (eq(**vp
, STRtilde
)) {
417 cp
= exp6(vp
, ignore
);
419 etracc("exp6 ~ cp", cp
, vp
);
425 if (eq(**vp
, STRLparen
)) {
427 ccode
= exp0(vp
, ignore
);
429 etraci("exp6 () ccode", ccode
, vp
);
431 if (**vp
== 0 || ***vp
!= ')')
432 stderror(ERR_NAME
| ERR_EXPRESSION
);
434 return (putn(ccode
));
436 if (eq(**vp
, STRLbrace
)) {
437 struct command faket
;
441 faket
.t_dtyp
= NODE_COMMAND
;
443 faket
.t_dcar
= faket
.t_dcdr
= faket
.t_dspr
= NULL
;
444 faket
.t_dcom
= fakecom
;
445 fakecom
[0] = STRfakecom
;
451 stderror(ERR_NAME
| ERR_MISSING
, '}');
452 if (eq(*(*vp
)++, STRRbrace
))
456 return (Strsave(STRNULL
));
458 if (pfork(&faket
, -1) == 0) {
466 etraci("exp6 {} status", egetn(value(STRstatus
)), vp
);
468 return (putn(egetn(value(STRstatus
)) == 0));
470 if (isa(**vp
, ANYOP
))
471 return (Strsave(STRNULL
));
473 if (*cp
== '-' && any("erwxfdzopls", cp
[1])) {
477 stderror(ERR_NAME
| ERR_FILEINQ
);
479 * Detect missing file names by checking for operator in the file name
480 * position. However, if an operator name appears there, we must make
481 * sure that there's no file by that name (e.g., "/") before announcing
482 * an error. Even this check isn't quite right, since it doesn't take
483 * globbing into account.
485 if (isa(**vp
, ANYOP
) && stat(short2str(**vp
), &stb
))
486 stderror(ERR_NAME
| ERR_FILENAME
);
490 return (Strsave(STRNULL
));
491 ep
= globone(dp
, G_ERROR
);
494 i
= !access(short2str(ep
), R_OK
);
497 i
= !access(short2str(ep
), W_OK
);
500 i
= !access(short2str(ep
), X_OK
);
504 lstat(short2str(ep
), &stb
) : stat(short2str(ep
), &stb
)) {
506 return (Strsave(STR0
));
510 i
= S_ISDIR(stb
.st_mode
);
516 i
= S_ISREG(stb
.st_mode
);
520 i
= S_ISLNK(stb
.st_mode
);
526 i
= stb
.st_uid
== (uid_t
)uid
;
530 i
= S_ISFIFO(stb
.st_mode
);
537 i
= S_ISSOCK(stb
.st_mode
);
543 i
= stb
.st_size
== 0;
548 etraci("exp6 -? i", i
, vp
);
554 etracc("exp6 default", cp
, vp
);
556 return (ignore
& NOGLOB
? Strsave(cp
) : globone(cp
, G_ERROR
));
562 struct wordent
*hp
, paraml1
, *wdp
;
567 set(STRstatus
, Strsave(STR0
));
568 hp
->prev
= hp
->next
= hp
;
573 new = (struct wordent
*)xcalloc(1, sizeof *wdp
);
578 wdp
->word
= Strsave(*v
++);
582 t
= syntax(paraml1
.next
, ¶ml1
, 0);
585 execute(t
, -1, NULL
, NULL
);
586 freelex(¶ml1
), freesyn(t
);
590 isa(Char
*cp
, int what
)
593 return ((what
& RESTOP
) != 0);
595 if (what
& ADDOP
&& (*cp
== '+' || *cp
== '-'))
597 if (what
& MULOP
&& (*cp
== '*' || *cp
== '/' || *cp
== '%'))
599 if (what
& RESTOP
&& (*cp
== '(' || *cp
== ')' || *cp
== '!' ||
600 *cp
== '~' || *cp
== '^' || *cp
== '"'))
603 else if (cp
[2] == 0) {
605 if (cp
[0] == '|' && cp
[1] == '&')
607 if (cp
[0] == '<' && cp
[1] == '<')
609 if (cp
[0] == '>' && cp
[1] == '>')
619 else if (cp
[0] == '!') {
639 if (*cp
&& *cp
!= '-' && !Isdigit(*cp
))
640 stderror(ERR_NAME
| ERR_EXPRESSION
);
648 etraci(char *str
, int i
, Char
***vp
)
650 (void)fprintf(csherr
, "%s=%d\t", str
, i
);
652 (void)fprintf(csherr
, "\n");
655 etracc(char *str
, Char
*cp
, Char
***vp
)
657 (void)fprintf(csherr
, "%s=%s\t", str
, vis_str(cp
));
659 (void)fprintf(csherr
, "\n");