]>
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((int));
39 struct val
*make_str
__P((char *));
40 void free_value
__P((struct val
*));
41 int is_integer
__P((struct val
*, int *));
42 int to_integer
__P((struct val
*));
43 void to_string
__P((struct val
*));
44 int is_zero_or_null
__P((struct val
*));
45 void nexttoken
__P((void));
46 void error
__P((void)) __attribute__((__noreturn__
));
47 struct val
*eval6
__P((void));
48 struct val
*eval5
__P((void));
49 struct val
*eval4
__P((void));
50 struct val
*eval3
__P((void));
51 struct val
*eval2
__P((void));
52 struct val
*eval1
__P((void));
53 struct val
*eval0
__P((void));
54 int main
__P((int, char **));
63 vp
= (struct val
*) malloc(sizeof(*vp
));
79 vp
= (struct val
*) malloc(sizeof(*vp
));
80 if (vp
== NULL
|| ((vp
->u
.s
= strdup(s
)) == NULL
)) {
92 if (vp
->type
== string
)
98 /* determine if vp is an integer; if so, return it's value in *r */
108 if (vp
->type
== integer
) {
114 * POSIX.2 defines an "integer" as an optional unary minus
115 * followed by digits.
142 /* coerce to vp to an integer */
149 if (vp
->type
== integer
)
152 if (is_integer(vp
, &r
)) {
163 /* coerce to vp to an string */
170 if (vp
->type
== string
)
177 (void)snprintf(tmp
, 25, "%d", vp
->u
.i
);
186 if (vp
->type
== integer
)
187 return (vp
->u
.i
== 0);
189 return (*vp
->u
.s
== 0 || (to_integer(vp
) && vp
->u
.i
== 0));
198 if ((p
= *av
) == NULL
) {
206 const char *x
= "|&=<>+-*/%:()";
209 if ((i
= strchr(x
, *p
)) != NULL
) {
213 } else if (p
[1] == '=' && p
[2] == '\0') {
227 tokval
= make_str(p
);
235 errx(2, "syntax error");
244 if (token
== OPERAND
) {
248 } else if (token
== RP
) {
262 /* Parse and evaluate match (regex) expressions */
274 while (token
== MATCH
) {
278 /* coerce to both arguments to strings */
282 /* compile regular expression */
283 if ((eval
= regcomp(&rp
, r
->u
.s
, 0)) != 0) {
284 (void)regerror(eval
, &rp
, errbuf
, sizeof(errbuf
));
285 errx(2, "%s", errbuf
);
288 /* compare string against pattern -- remember that patterns
289 are anchored to the beginning of the line */
290 if (regexec(&rp
, l
->u
.s
, 2, rm
, 0) == 0 && rm
[0].rm_so
== 0) {
291 if (rm
[1].rm_so
>= 0) {
292 *(l
->u
.s
+ rm
[1].rm_eo
) = '\0';
293 v
= make_str(l
->u
.s
+ rm
[1].rm_so
);
296 v
= make_int((int)(rm
[0].rm_eo
- rm
[0].rm_so
));
299 if (rp
.re_nsub
== 0) {
306 /* free arguments and pattern buffer */
317 /* Parse and evaluate multiplication and division expressions */
325 while ((op
= token
) == MUL
|| op
== DIV
|| op
== MOD
) {
329 if (!to_integer(l
) || !to_integer(r
)) {
330 errx(2, "non-numeric argument");
337 errx(2, "division by zero");
352 /* Parse and evaluate addition and subtraction expressions */
360 while ((op
= token
) == ADD
|| op
== SUB
) {
364 if (!to_integer(l
) || !to_integer(r
)) {
365 errx(2, "non-numeric argument");
380 /* Parse and evaluate comparison expressions */
386 int v
= 0; /* pacify gcc */
390 while ((op
= token
) == EQ
|| op
== NE
|| op
== LT
|| op
== GT
|| op
== LE
|| op
== GE
) {
394 if (is_integer(l
, &li
) && is_integer(r
, &ri
)) {
436 v
= (strcoll(l
->u
.s
, r
->u
.s
) > 0);
439 v
= (strcoll(l
->u
.s
, r
->u
.s
) >= 0);
442 v
= (strcoll(l
->u
.s
, r
->u
.s
) < 0);
445 v
= (strcoll(l
->u
.s
, r
->u
.s
) <= 0);
448 v
= (strcoll(l
->u
.s
, r
->u
.s
) == 0);
451 v
= (strcoll(l
->u
.s
, r
->u
.s
) != 0);
479 /* Parse and evaluate & expressions */
486 while (token
== AND
) {
490 if (is_zero_or_null(l
) || is_zero_or_null(r
)) {
502 /* Parse and evaluate | expressions */
509 while (token
== OR
) {
513 if (is_zero_or_null(l
)) {
532 (void) setlocale(LC_ALL
, "");
541 if (vp
->type
== integer
)
542 (void)printf("%d\n", vp
->u
.i
);
544 (void)printf("%s\n", vp
->u
.s
);
546 exit(is_zero_or_null(vp
));