]>
git.saurik.com Git - apple/shell_cmds.git/blob - expr/expr.c
1 /* $NetBSD: expr.c,v 1.9 1998/07/28 11:41:48 mycroft Exp $ */
4 * Written by J.T. Conklin <jtc@netbsd.org>.
18 OR
, AND
, EQ
, LT
, GT
, ADD
, SUB
, MUL
, DIV
, MOD
, MATCH
, RP
, LP
,
19 NE
, LE
, GE
, OPERAND
, EOI
38 struct val
*make_int
__P((int64_t));
39 struct val
*make_str
__P((char *));
40 void free_value
__P((struct val
*));
41 int is_integer
__P((struct val
*, int64_t *));
42 int to_integer
__P((struct val
*));
43 void to_string
__P((struct val
*));
44 int is_null
__P((struct val
*));
45 int is_zero_or_null
__P((struct val
*));
46 void nexttoken
__P((void));
47 void error
__P((void)) __attribute__((__noreturn__
));
48 struct val
*eval6
__P((void));
49 struct val
*eval5
__P((void));
50 struct val
*eval4
__P((void));
51 struct val
*eval3
__P((void));
52 struct val
*eval2
__P((void));
53 struct val
*eval1
__P((void));
54 struct val
*eval0
__P((void));
55 int main
__P((int, char **));
64 vp
= (struct val
*) malloc(sizeof(*vp
));
80 vp
= (struct val
*) malloc(sizeof(*vp
));
81 if (vp
== NULL
|| ((vp
->u
.s
= strdup(s
)) == NULL
)) {
93 if (vp
->type
== string
)
99 /* determine if vp is an integer; if so, return it's value in *r */
109 if (vp
->type
== integer
) {
115 * POSIX.2 defines an "integer" as an optional unary minus
116 * followed by digits.
124 /* the optional unary minus *must* be followed by digits to
125 * be considered an integer. A '-' alone is not an integer.
149 /* coerce to vp to an integer */
156 if (vp
->type
== integer
)
159 if (is_integer(vp
, &r
)) {
170 /* coerce to vp to an string */
177 if (vp
->type
== string
)
184 (void)snprintf(tmp
, 100, "%lld", vp
->u
.i
);
192 if ((vp
->type
!= integer
) && (*vp
->u
.s
== 0))
201 if (vp
->type
== integer
)
202 return (vp
->u
.i
== 0);
204 return (*vp
->u
.s
== 0 || (to_integer(vp
) && vp
->u
.i
== 0));
213 if ((p
= *av
) == NULL
) {
221 const char *x
= "|&=<>+-*/%:()";
224 if ((i
= strchr(x
, *p
)) != NULL
) {
228 } else if (p
[1] == '=' && p
[2] == '\0') {
242 tokval
= make_str(p
);
250 errx(2, "syntax error");
259 if (token
== OPERAND
) {
263 } else if (token
== RP
) {
277 tokval
= make_str("/");
281 tokval
= make_str("*");
285 tokval
= make_str("|");
289 tokval
= make_str("&");
293 tokval
= make_str("=");
297 tokval
= make_str("<");
301 tokval
= make_str(">");
305 tokval
= make_str("+");
309 tokval
= make_str("-");
313 tokval
= make_str("%");
317 tokval
= make_str("!=");
321 tokval
= make_str("<=");
325 tokval
= make_str(":");
329 tokval
= make_str(">=");
339 /* Parse and evaluate match (regex) expressions */
351 while (token
== MATCH
) {
355 /* coerce to both arguments to strings */
359 /* compile regular expression */
360 if ((eval
= regcomp(&rp
, r
->u
.s
, 0)) != 0) {
361 (void)regerror(eval
, &rp
, errbuf
, sizeof(errbuf
));
362 errx(2, "%s", errbuf
);
365 /* compare string against pattern -- remember that patterns
366 are anchored to the beginning of the line */
367 if (regexec(&rp
, l
->u
.s
, 2, rm
, 0) == 0 && rm
[0].rm_so
== 0) {
368 if (rm
[1].rm_so
>= 0) {
369 *(l
->u
.s
+ rm
[1].rm_eo
) = '\0';
370 v
= make_str(l
->u
.s
+ rm
[1].rm_so
);
373 v
= make_int((int)(rm
[0].rm_eo
- rm
[0].rm_so
));
376 if (rp
.re_nsub
== 0) {
383 /* free arguments and pattern buffer */
394 /* Parse and evaluate multiplication and division expressions */
402 while ((op
= token
) == MUL
|| op
== DIV
|| op
== MOD
) {
406 if (!to_integer(l
) || !to_integer(r
)) {
407 errx(2, "non-numeric argument");
414 errx(2, "division by zero");
429 /* Parse and evaluate addition and subtraction expressions */
437 while ((op
= token
) == ADD
|| op
== SUB
) {
441 if (!to_integer(l
) || !to_integer(r
)) {
442 errx(2, "non-numeric argument");
457 /* Parse and evaluate comparison expressions */
463 int v
= 0; /* pacify gcc */
467 while ((op
= token
) == EQ
|| op
== NE
|| op
== LT
|| op
== GT
|| op
== LE
|| op
== GE
) {
471 if (is_integer(l
, &li
) && is_integer(r
, &ri
)) {
513 v
= (strcoll(l
->u
.s
, r
->u
.s
) > 0);
516 v
= (strcoll(l
->u
.s
, r
->u
.s
) >= 0);
519 v
= (strcoll(l
->u
.s
, r
->u
.s
) < 0);
522 v
= (strcoll(l
->u
.s
, r
->u
.s
) <= 0);
525 v
= (strcoll(l
->u
.s
, r
->u
.s
) == 0);
528 v
= (strcoll(l
->u
.s
, r
->u
.s
) != 0);
556 /* Parse and evaluate & expressions */
563 while (token
== AND
) {
567 if (is_zero_or_null(l
) || is_zero_or_null(r
)) {
579 /* Parse and evaluate | expressions */
586 while (token
== OR
) {
590 if (is_zero_or_null(l
)) {
613 (void) setlocale(LC_ALL
, "");
615 if (*av
&& !strcmp(*av
, "--"))
622 if (vp
->type
== string
&& vp
->u
.s
[0])
623 to_integer(vp
); /* -0 is not a string */
624 if (vp
->type
== integer
)
625 (void)printf("%lld\n", vp
->u
.i
);
627 (void)printf("%s\n", vp
->u
.s
);
629 exit(is_zero_or_null(vp
));