.
[coreutils.git] / src / expr.c
blobabeae7e3e899427f625e690c033702b07fb4a45c
1 /* expr -- evaluate expressions.
2 Copyright (C) 86,91,92,93,94,95,96,1997 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)
7 any later version.
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 Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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. */
31 #include <config.h>
32 #include <stdio.h>
33 #include <sys/types.h>
34 #include "system.h"
36 #include <regex.h>
37 #include "long-options.h"
38 #include "error.h"
40 #define NEW(type) ((type *) xmalloc (sizeof (type)))
41 #define OLD(x) free ((char *) x)
43 /* The kinds of value we can have. */
44 enum valtype
46 integer,
47 string
49 typedef enum valtype TYPE;
51 /* A value is.... */
52 struct valinfo
54 TYPE type; /* Which kind. */
55 union
56 { /* The value itself. */
57 int i;
58 char *s;
59 } u;
61 typedef struct valinfo VALUE;
63 /* Non-zero if the POSIXLY_CORRECT environment variable is set.
64 The unary operator `quote' is disabled when this variable is zero. */
65 static int posixly_correct;
67 /* The arguments given to the program, minus the program name. */
68 static char **args;
70 /* The name this program was run with. */
71 char *program_name;
73 char *xstrdup ();
75 static VALUE *docolon PARAMS ((VALUE *sv, VALUE *pv));
76 static VALUE *eval PARAMS ((void));
77 static VALUE *int_value PARAMS ((int i));
78 static VALUE *str_value PARAMS ((char *s));
79 static int isstring PARAMS ((VALUE *v));
80 static int nextarg PARAMS ((char *str));
81 static int nomoreargs PARAMS ((void));
82 static int null PARAMS ((VALUE *v));
83 static int toarith PARAMS ((VALUE *v));
84 static void freev PARAMS ((VALUE *v));
85 static void printv PARAMS ((VALUE *v));
86 static void tostring PARAMS ((VALUE *v));
88 #ifdef EVAL_TRACE
89 static void trace ();
90 #endif
92 static void
93 usage (int status)
95 if (status != 0)
96 fprintf (stderr, _("Try `%s --help' for more information.\n"),
97 program_name);
98 else
100 printf (_("\
101 Usage: %s EXPRESSION\n\
102 or: %s OPTION\n\
104 program_name, program_name);
105 printf (_("\
107 --help display this help and exit\n\
108 --version output version information and exit\n\
110 "));
111 printf (_("\
112 Print the value of EXPRESSION to standard output. A blank line below\n\
113 separates increasing precedence groups. EXPRESSION may be:\n\
115 ARG1 | ARG2 ARG1 if it is neither null nor 0, otherwise ARG2\n\
117 ARG1 & ARG2 ARG1 if neither argument is null or 0, otherwise 0\n\
119 ARG1 < ARG2 ARG1 is less than ARG2\n\
120 ARG1 <= ARG2 ARG1 is less than or equal to ARG2\n\
121 ARG1 = ARG2 ARG1 is equal to ARG2\n\
122 ARG1 != ARG2 ARG1 is unequal to ARG2\n\
123 ARG1 >= ARG2 ARG1 is greater than or equal to ARG2\n\
124 ARG1 > ARG2 ARG1 is greater than ARG2\n\
126 ARG1 + ARG2 arithmetic sum of ARG1 and ARG2\n\
127 ARG1 - ARG2 arithmetic difference of ARG1 and ARG2\n\
129 ARG1 * ARG2 arithmetic product of ARG1 and ARG2\n\
130 ARG1 / ARG2 arithmetic quotient of ARG1 divided by ARG2\n\
131 ARG1 %% ARG2 arithmetic remainder of ARG1 divided by ARG2\n\
133 STRING : REGEXP anchored pattern match of REGEXP in STRING\n\
135 match STRING REGEXP same as STRING : REGEXP\n\
136 substr STRING POS LENGTH substring of STRING, POS counted from 1\n\
137 index STRING CHARS index in STRING where any CHARS is found, or 0\n\
138 length STRING length of STRING\n\
139 quote TOKEN interpret TOKEN as a string, even if it is a\n\
140 keyword like `match' or an operator like `/'\n\
142 ( EXPRESSION ) value of EXPRESSION\n\
143 "));
144 printf (_("\
146 Beware that many operators need to be escaped or quoted for shells.\n\
147 Comparisons are arithmetic if both ARGs are numbers, else lexicographical.\n\
148 Pattern matches return the string matched between \\( and \\) or null; if\n\
149 \\( and \\) are not used, they return the number of characters matched or 0.\n\
150 "));
151 puts (_("\nReport bugs to <sh-utils-bugs@gnu.org>."));
153 exit (status);
157 main (int argc, char **argv)
159 VALUE *v;
161 program_name = argv[0];
162 setlocale (LC_ALL, "");
163 bindtextdomain (PACKAGE, LOCALEDIR);
164 textdomain (PACKAGE);
166 posixly_correct = (getenv ("POSIXLY_CORRECT") != NULL);
168 /* Recognize --help or --version only if POSIXLY_CORRECT is not set. */
169 if (!posixly_correct)
170 parse_long_options (argc, argv, "expr", GNU_PACKAGE, VERSION, usage);
172 if (argc == 1)
174 error (0, 0, _("too few arguments"));
175 usage (1);
178 args = argv + 1;
180 v = eval ();
181 if (!nomoreargs ())
182 error (2, 0, _("syntax error"));
183 printv (v);
185 exit (null (v));
188 /* Return a VALUE for I. */
190 static VALUE *
191 int_value (int i)
193 VALUE *v;
195 v = NEW (VALUE);
196 v->type = integer;
197 v->u.i = i;
198 return v;
201 /* Return a VALUE for S. */
203 static VALUE *
204 str_value (char *s)
206 VALUE *v;
208 v = NEW (VALUE);
209 v->type = string;
210 v->u.s = xstrdup (s);
211 return v;
214 /* Free VALUE V, including structure components. */
216 static void
217 freev (VALUE *v)
219 if (v->type == string)
220 free (v->u.s);
221 OLD (v);
224 /* Print VALUE V. */
226 static void
227 printv (VALUE *v)
229 switch (v->type)
231 case integer:
232 printf ("%d\n", v->u.i);
233 break;
234 case string:
235 printf ("%s\n", v->u.s);
236 break;
237 default:
238 abort ();
242 /* Return nonzero if V is a null-string or zero-number. */
244 static int
245 null (VALUE *v)
247 switch (v->type)
249 case integer:
250 return v->u.i == 0;
251 case string:
252 return v->u.s[0] == '\0' || strcmp (v->u.s, "0") == 0;
253 default:
254 abort ();
258 /* Return nonzero if V is a string value. */
260 static int
261 isstring (VALUE *v)
263 return v->type == string;
266 /* Coerce V to a string value (can't fail). */
268 static void
269 tostring (VALUE *v)
271 char *temp;
273 switch (v->type)
275 case integer:
276 temp = xmalloc (4 * (sizeof (int) / sizeof (char)));
277 sprintf (temp, "%d", v->u.i);
278 v->u.s = temp;
279 v->type = string;
280 break;
281 case string:
282 break;
283 default:
284 abort ();
288 /* Coerce V to an integer value. Return 1 on success, 0 on failure. */
290 static int
291 toarith (VALUE *v)
293 int i;
294 int neg;
295 char *cp;
297 switch (v->type)
299 case integer:
300 return 1;
301 case string:
302 i = 0;
303 cp = v->u.s;
304 /* Don't interpret the empty string as an integer. */
305 if (*cp == 0)
306 return 0;
307 neg = (*cp == '-');
308 if (neg)
309 cp++;
310 for (; *cp; cp++)
312 if (ISDIGIT (*cp))
313 i = i * 10 + *cp - '0';
314 else
315 return 0;
317 free (v->u.s);
318 v->u.i = i * (neg ? -1 : 1);
319 v->type = integer;
320 return 1;
321 default:
322 abort ();
326 /* Return nonzero if the next token matches STR exactly.
327 STR must not be NULL. */
329 static int
330 nextarg (char *str)
332 if (*args == NULL)
333 return 0;
334 return strcmp (*args, str) == 0;
337 /* Return nonzero if there no more tokens. */
339 static int
340 nomoreargs (void)
342 return *args == 0;
345 /* The comparison operator handling functions. */
347 #define cmpf(name, rel) \
348 static \
349 int name (l, r) VALUE *l; VALUE *r; \
351 if (isstring (l) || isstring (r)) \
353 tostring (l); \
354 tostring (r); \
355 return strcmp (l->u.s, r->u.s) rel 0; \
357 else \
358 return l->u.i rel r->u.i; \
360 cmpf (less_than, <)
361 cmpf (less_equal, <=)
362 cmpf (equal, ==)
363 cmpf (not_equal, !=)
364 cmpf (greater_equal, >=)
365 cmpf (greater_than, >)
367 #undef cmpf
369 /* The arithmetic operator handling functions. */
371 #define arithf(name, op) \
372 static \
373 int name (l, r) VALUE *l; VALUE *r; \
375 if (!toarith (l) || !toarith (r)) \
376 error (2, 0, _("non-numeric argument")); \
377 return l->u.i op r->u.i; \
380 #define arithdivf(name, op) \
381 int name (l, r) VALUE *l; VALUE *r; \
383 if (!toarith (l) || !toarith (r)) \
384 error (2, 0, _("non-numeric argument")); \
385 if (r->u.i == 0) \
386 error (2, 0, _("division by zero")); \
387 return l->u.i op r->u.i; \
390 arithf (plus, +)
391 arithf (minus, -)
392 arithf (multiply, *)
393 arithdivf (divide, /)
394 arithdivf (mod, %)
396 #undef arithf
397 #undef arithdivf
399 #ifdef EVAL_TRACE
400 /* Print evaluation trace and args remaining. */
402 static void
403 trace (fxn)
404 char *fxn;
406 char **a;
408 printf ("%s:", fxn);
409 for (a = args; *a; a++)
410 printf (" %s", *a);
411 putchar ('\n');
413 #endif
415 /* Do the : operator.
416 SV is the VALUE for the lhs (the string),
417 PV is the VALUE for the rhs (the pattern). */
419 static VALUE *
420 docolon (VALUE *sv, VALUE *pv)
422 VALUE *v;
423 const char *errmsg;
424 struct re_pattern_buffer re_buffer;
425 struct re_registers re_regs;
426 int len;
428 tostring (sv);
429 tostring (pv);
431 if (pv->u.s[0] == '^')
433 error (0, 0, _("\
434 warning: unportable BRE: `%s': using `^' as the first character\n\
435 of the basic regular expression is not portable; it is being ignored"),
436 pv->u.s);
439 len = strlen (pv->u.s);
440 memset (&re_buffer, 0, sizeof (re_buffer));
441 memset (&re_regs, 0, sizeof (re_regs));
442 re_buffer.allocated = 2 * len;
443 re_buffer.buffer = (unsigned char *) xmalloc (re_buffer.allocated);
444 re_buffer.translate = 0;
445 re_syntax_options = RE_SYNTAX_POSIX_BASIC;
446 errmsg = re_compile_pattern (pv->u.s, len, &re_buffer);
447 if (errmsg)
448 error (2, 0, "%s", errmsg);
450 len = re_match (&re_buffer, sv->u.s, strlen (sv->u.s), 0, &re_regs);
451 if (len >= 0)
453 /* Were \(...\) used? */
454 if (re_buffer.re_nsub > 0)/* was (re_regs.start[1] >= 0) */
456 sv->u.s[re_regs.end[1]] = '\0';
457 v = str_value (sv->u.s + re_regs.start[1]);
459 else
460 v = int_value (len);
462 else
464 /* Match failed -- return the right kind of null. */
465 if (re_buffer.re_nsub > 0)
466 v = str_value ("");
467 else
468 v = int_value (0);
470 free (re_buffer.buffer);
471 return v;
474 /* Handle bare operands and ( expr ) syntax. */
476 static VALUE *
477 eval7 (void)
479 VALUE *v;
481 #ifdef EVAL_TRACE
482 trace ("eval7");
483 #endif
484 if (nomoreargs ())
485 error (2, 0, _("syntax error"));
487 if (nextarg ("("))
489 args++;
490 v = eval ();
491 if (!nextarg (")"))
492 error (2, 0, _("syntax error"));
493 args++;
494 return v;
497 if (nextarg (")"))
498 error (2, 0, _("syntax error"));
500 return str_value (*args++);
503 /* Handle match, substr, index, length, and quote keywords. */
505 static VALUE *
506 eval6 (void)
508 VALUE *l;
509 VALUE *r;
510 VALUE *v;
511 VALUE *i1;
512 VALUE *i2;
514 #ifdef EVAL_TRACE
515 trace ("eval6");
516 #endif
517 if (!posixly_correct && nextarg ("quote"))
519 args++;
520 if (nomoreargs ())
521 error (2, 0, _("syntax error"));
522 return str_value (*args++);
524 else if (nextarg ("length"))
526 args++;
527 r = eval6 ();
528 tostring (r);
529 v = int_value (strlen (r->u.s));
530 freev (r);
531 return v;
533 else if (nextarg ("match"))
535 args++;
536 l = eval6 ();
537 r = eval6 ();
538 v = docolon (l, r);
539 freev (l);
540 freev (r);
541 return v;
543 else if (nextarg ("index"))
545 args++;
546 l = eval6 ();
547 r = eval6 ();
548 tostring (l);
549 tostring (r);
550 v = int_value (strcspn (l->u.s, r->u.s) + 1);
551 if (v->u.i == (int) strlen (l->u.s) + 1)
552 v->u.i = 0;
553 freev (l);
554 freev (r);
555 return v;
557 else if (nextarg ("substr"))
559 args++;
560 l = eval6 ();
561 i1 = eval6 ();
562 i2 = eval6 ();
563 tostring (l);
564 if (!toarith (i1) || !toarith (i2)
565 || i1->u.i > (int) strlen (l->u.s)
566 || i1->u.i <= 0 || i2->u.i <= 0)
567 v = str_value ("");
568 else
570 v = NEW (VALUE);
571 v->type = string;
572 v->u.s = strncpy ((char *) xmalloc (i2->u.i + 1),
573 l->u.s + i1->u.i - 1, i2->u.i);
574 v->u.s[i2->u.i] = 0;
576 freev (l);
577 freev (i1);
578 freev (i2);
579 return v;
581 else
582 return eval7 ();
585 /* Handle : operator (pattern matching).
586 Calls docolon to do the real work. */
588 static VALUE *
589 eval5 (void)
591 VALUE *l;
592 VALUE *r;
593 VALUE *v;
595 #ifdef EVAL_TRACE
596 trace ("eval5");
597 #endif
598 l = eval6 ();
599 while (1)
601 if (nextarg (":"))
603 args++;
604 r = eval6 ();
605 v = docolon (l, r);
606 freev (l);
607 freev (r);
608 l = v;
610 else
611 return l;
615 /* Handle *, /, % operators. */
617 static VALUE *
618 eval4 (void)
620 VALUE *l;
621 VALUE *r;
622 int (*fxn) ();
623 int val;
625 #ifdef EVAL_TRACE
626 trace ("eval4");
627 #endif
628 l = eval5 ();
629 while (1)
631 if (nextarg ("*"))
632 fxn = multiply;
633 else if (nextarg ("/"))
634 fxn = divide;
635 else if (nextarg ("%"))
636 fxn = mod;
637 else
638 return l;
639 args++;
640 r = eval5 ();
641 val = (*fxn) (l, r);
642 freev (l);
643 freev (r);
644 l = int_value (val);
648 /* Handle +, - operators. */
650 static VALUE *
651 eval3 (void)
653 VALUE *l;
654 VALUE *r;
655 int (*fxn) ();
656 int val;
658 #ifdef EVAL_TRACE
659 trace ("eval3");
660 #endif
661 l = eval4 ();
662 while (1)
664 if (nextarg ("+"))
665 fxn = plus;
666 else if (nextarg ("-"))
667 fxn = minus;
668 else
669 return l;
670 args++;
671 r = eval4 ();
672 val = (*fxn) (l, r);
673 freev (l);
674 freev (r);
675 l = int_value (val);
679 /* Handle comparisons. */
681 static VALUE *
682 eval2 (void)
684 VALUE *l;
685 VALUE *r;
686 int (*fxn) ();
687 int val;
689 #ifdef EVAL_TRACE
690 trace ("eval2");
691 #endif
692 l = eval3 ();
693 while (1)
695 if (nextarg ("<"))
696 fxn = less_than;
697 else if (nextarg ("<="))
698 fxn = less_equal;
699 else if (nextarg ("=") || nextarg ("=="))
700 fxn = equal;
701 else if (nextarg ("!="))
702 fxn = not_equal;
703 else if (nextarg (">="))
704 fxn = greater_equal;
705 else if (nextarg (">"))
706 fxn = greater_than;
707 else
708 return l;
709 args++;
710 r = eval3 ();
711 toarith (l);
712 toarith (r);
713 val = (*fxn) (l, r);
714 freev (l);
715 freev (r);
716 l = int_value (val);
720 /* Handle &. */
722 static VALUE *
723 eval1 (void)
725 VALUE *l;
726 VALUE *r;
728 #ifdef EVAL_TRACE
729 trace ("eval1");
730 #endif
731 l = eval2 ();
732 while (1)
734 if (nextarg ("&"))
736 args++;
737 r = eval2 ();
738 if (null (l) || null (r))
740 freev (l);
741 freev (r);
742 l = int_value (0);
744 else
745 freev (r);
747 else
748 return l;
752 /* Handle |. */
754 static VALUE *
755 eval (void)
757 VALUE *l;
758 VALUE *r;
760 #ifdef EVAL_TRACE
761 trace ("eval");
762 #endif
763 l = eval1 ();
764 while (1)
766 if (nextarg ("|"))
768 args++;
769 r = eval1 ();
770 if (null (l))
772 freev (l);
773 l = r;
775 else
776 freev (r);
778 else
779 return l;