1 /* expr -- evaluate expressions.
2 Copyright (C) 1986, 1991 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
18 /* Author: Mike Parker.
20 This program evaluates expressions. Each token (operator, operand,
21 parenthesis) of the expression must be a seperate argument. The
22 parser used is a reasonably general one, though any incarnation of
23 it is language-specific. It is especially nice for expressions.
25 No parse tree is needed; a new node is evaluated immediately.
26 One function can handle multiple operators all of equal precedence,
27 provided they all associate ((x op x) op x).
29 Define EVAL_TRACE to print an evaluation trace. */
32 #if defined (CONFIG_BROKETS)
33 /* We use <config.h> instead of "config.h" so that a compilation
34 using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
35 (which it would do because it found this file in $srcdir). */
44 #include <sys/types.h>
50 #if !defined (isascii) || defined (STDC_HEADERS)
55 #define ISDIGIT(c) (isascii (c) && isdigit (c))
61 #define NEW(type) ((type *) xmalloc (sizeof (type)))
62 #define OLD(x) free ((char *) x)
64 /* The kinds of value we can have. */
70 typedef enum valtype TYPE
;
75 TYPE type
; /* Which kind. */
77 { /* The value itself. */
82 typedef struct valinfo VALUE
;
84 /* The arguments given to the program, minus the program name. */
87 /* The name this program was run with. */
94 void parse_long_options ();
96 static VALUE
*docolon ();
97 static VALUE
*eval ();
98 static VALUE
*int_value ();
99 static VALUE
*str_value ();
100 static int isstring ();
101 static int nextarg ();
102 static int nomoreargs ();
104 static int toarith ();
105 static void freev ();
106 static void printv ();
107 static void tostring ();
110 static void trace ();
116 fprintf (stderr
, "Usage: %s [{--help,--version}] expression...\n",
128 program_name
= argv
[0];
130 parse_long_options (argc
, argv
, usage
);
138 error (2, 0, "syntax error");
144 /* Return a VALUE for I. */
158 /* Return a VALUE for S. */
168 v
->u
.s
= xstrdup (s
);
172 /* Free VALUE V, including structure components. */
178 if (v
->type
== string
)
192 printf ("%d\n", v
->u
.i
);
195 printf ("%s\n", v
->u
.s
);
202 /* Return nonzero if V is a null-string or zero-number. */
213 return v
->u
.s
[0] == '\0' || strcmp(v
->u
.s
, "0") == 0;
219 /* Return nonzero if V is a string value. */
225 return v
->type
== string
;
228 /* Coerce V to a string value (can't fail). */
239 temp
= xmalloc (4 * (sizeof (int) / sizeof (char)));
240 sprintf (temp
, "%d", v
->u
.i
);
251 /* Coerce V to an integer value. Return 1 on success, 0 on failure. */
274 i
= i
* 10 + *cp
- '0';
279 v
->u
.i
= i
* (neg
? -1 : 1);
287 /* Return nonzero if the next token matches STR exactly.
288 STR must not be NULL. */
296 return strcmp (*args
, str
) == 0;
299 /* Return nonzero if there no more tokens. */
307 /* The comparison operator handling functions. */
309 #define cmpf(name, rel) \
311 int name (l, r) VALUE *l; VALUE *r; \
313 if (isstring (l) || isstring (r)) \
317 return strcmp (l->u.s, r->u.s) rel 0; \
320 return l->u.i rel r->u.i; \
323 cmpf (less_equal
, <=)
326 cmpf (greater_equal
, >=)
327 cmpf (greater_than
, >)
331 /* The arithmetic operator handling functions. */
333 #define arithf(name, op) \
335 int name (l, r) VALUE *l; VALUE *r; \
337 if (!toarith (l) || !toarith (r)) \
338 error (2, 0, "non-numeric argument"); \
339 return l->u.i op r->u.i; \
342 #define arithdivf(name, op) \
343 int name (l, r) VALUE *l; VALUE *r; \
345 if (!toarith (l) || !toarith (r)) \
346 error (2, 0, "non-numeric argument"); \
348 error (2, 0, "division by zero"); \
349 return l->u.i op r->u.i; \
355 arithdivf (divide
, /)
362 /* Print evaluation trace and args remaining. */
371 for (a
= args
; *a
; a
++)
377 /* Do the : operator.
378 SV is the VALUE for the lhs (the string),
379 PV is the VALUE for the rhs (the pattern). */
388 struct re_pattern_buffer re_buffer
;
389 struct re_registers re_regs
;
395 len
= strlen (pv
->u
.s
);
396 re_buffer
.allocated
= 2 * len
;
397 re_buffer
.buffer
= (unsigned char *) xmalloc (re_buffer
.allocated
);
398 re_buffer
.translate
= 0;
399 errmsg
= re_compile_pattern (pv
->u
.s
, len
, &re_buffer
);
401 error (2, 0, "%s", errmsg
);
403 len
= re_match (&re_buffer
, sv
->u
.s
, strlen (sv
->u
.s
), 0, &re_regs
);
406 /* Were \(...\) used? */
407 if (re_buffer
.re_nsub
> 0)/* was (re_regs.start[1] >= 0) */
409 sv
->u
.s
[re_regs
.end
[1]] = '\0';
410 v
= str_value (sv
->u
.s
+ re_regs
.start
[1]);
417 /* Match failed -- return the right kind of null. */
418 if (strstr (pv
->u
.s
, "\\("))
423 free (re_buffer
.buffer
);
427 /* Handle bare operands and ( expr ) syntax. */
438 error (2, 0, "syntax error");
445 error (2, 0, "syntax error");
451 error (2, 0, "syntax error");
453 return str_value (*args
++);
456 /* Handle match, substr, index, and length keywords. */
470 if (nextarg ("length"))
475 v
= int_value (strlen (r
->u
.s
));
479 else if (nextarg ("match"))
489 else if (nextarg ("index"))
496 v
= int_value (strcspn (l
->u
.s
, r
->u
.s
) + 1);
497 if (v
->u
.i
== strlen (l
->u
.s
) + 1)
503 else if (nextarg ("substr"))
510 if (!toarith (i1
) || !toarith (i2
)
511 || i1
->u
.i
> strlen (l
->u
.s
)
512 || i1
->u
.i
<= 0 || i2
->u
.i
<= 0)
518 v
->u
.s
= strncpy ((char *) xmalloc (i2
->u
.i
+ 1),
519 l
->u
.s
+ i1
->u
.i
- 1, i2
->u
.i
);
531 /* Handle : operator (pattern matching).
532 Calls docolon to do the real work. */
561 /* Handle *, /, % operators. */
579 else if (nextarg ("/"))
581 else if (nextarg ("%"))
594 /* Handle +, - operators. */
612 else if (nextarg ("-"))
625 /* Handle comparisons. */
643 else if (nextarg ("<="))
645 else if (nextarg ("=") || nextarg ("=="))
647 else if (nextarg ("!="))
649 else if (nextarg (">="))
651 else if (nextarg (">"))
684 if (null (l
) || null (r
))