*** empty log message ***
[coreutils.git] / src / expr.c
blob7dea02b75a28145ac675e49d2d2fd490873f6704
1 /* expr -- evaluate expressions.
2 Copyright (C) 86, 1991-1997, 1999, 2000 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"
39 #include "xalloc.h"
40 #include "closeout.h"
42 /* The official name of this program (e.g., no `g' prefix). */
43 #define PROGRAM_NAME "expr"
45 #define AUTHORS "Mike Parker"
47 #undef NEW
48 #define NEW(Type) XMALLOC (Type, 1)
49 #define OLD(x) free ((char *) x)
51 /* The kinds of value we can have. */
52 enum valtype
54 integer,
55 string
57 typedef enum valtype TYPE;
59 /* A value is.... */
60 struct valinfo
62 TYPE type; /* Which kind. */
63 union
64 { /* The value itself. */
65 int i;
66 char *s;
67 } u;
69 typedef struct valinfo VALUE;
71 /* Non-zero if the POSIXLY_CORRECT environment variable is set.
72 The unary operator `quote' is disabled when this variable is zero. */
73 static int posixly_correct;
75 /* The arguments given to the program, minus the program name. */
76 static char **args;
78 /* The name this program was run with. */
79 char *program_name;
81 static VALUE *docolon PARAMS ((VALUE *sv, VALUE *pv));
82 static VALUE *eval PARAMS ((void));
83 static VALUE *int_value PARAMS ((int i));
84 static VALUE *str_value PARAMS ((char *s));
85 static int isstring PARAMS ((VALUE *v));
86 static int nextarg PARAMS ((char *str));
87 static int nomoreargs PARAMS ((void));
88 static int null PARAMS ((VALUE *v));
89 static int toarith PARAMS ((VALUE *v));
90 static void freev PARAMS ((VALUE *v));
91 static void printv PARAMS ((VALUE *v));
92 static void tostring PARAMS ((VALUE *v));
94 #ifdef EVAL_TRACE
95 static void trace ();
96 #endif
98 void
99 usage (int status)
101 if (status != 0)
102 fprintf (stderr, _("Try `%s --help' for more information.\n"),
103 program_name);
104 else
106 printf (_("\
107 Usage: %s EXPRESSION\n\
108 or: %s OPTION\n\
110 program_name, program_name);
111 printf (_("\
113 --help display this help and exit\n\
114 --version output version information and exit\n\
116 "));
117 printf (_("\
118 Print the value of EXPRESSION to standard output. A blank line below\n\
119 separates increasing precedence groups. EXPRESSION may be:\n\
121 ARG1 | ARG2 ARG1 if it is neither null nor 0, otherwise ARG2\n\
123 ARG1 & ARG2 ARG1 if neither argument is null or 0, otherwise 0\n\
125 ARG1 < ARG2 ARG1 is less than ARG2\n\
126 ARG1 <= ARG2 ARG1 is less than or equal to ARG2\n\
127 ARG1 = ARG2 ARG1 is equal to ARG2\n\
128 ARG1 != ARG2 ARG1 is unequal to ARG2\n\
129 ARG1 >= ARG2 ARG1 is greater than or equal to ARG2\n\
130 ARG1 > ARG2 ARG1 is greater than ARG2\n\
132 ARG1 + ARG2 arithmetic sum of ARG1 and ARG2\n\
133 ARG1 - ARG2 arithmetic difference of ARG1 and ARG2\n\
135 ARG1 * ARG2 arithmetic product of ARG1 and ARG2\n\
136 ARG1 / ARG2 arithmetic quotient of ARG1 divided by ARG2\n\
137 ARG1 %% ARG2 arithmetic remainder of ARG1 divided by ARG2\n\
139 STRING : REGEXP anchored pattern match of REGEXP in STRING\n\
141 match STRING REGEXP same as STRING : REGEXP\n\
142 substr STRING POS LENGTH substring of STRING, POS counted from 1\n\
143 index STRING CHARS index in STRING where any CHARS is found, or 0\n\
144 length STRING length of STRING\n\
145 quote TOKEN interpret TOKEN as a string, even if it is a\n\
146 keyword like `match' or an operator like `/'\n\
148 ( EXPRESSION ) value of EXPRESSION\n\
149 "));
150 printf (_("\
152 Beware that many operators need to be escaped or quoted for shells.\n\
153 Comparisons are arithmetic if both ARGs are numbers, else lexicographical.\n\
154 Pattern matches return the string matched between \\( and \\) or null; if\n\
155 \\( and \\) are not used, they return the number of characters matched or 0.\n\
156 "));
157 puts (_("\nReport bugs to <bug-sh-utils@gnu.org>."));
159 exit (status);
163 main (int argc, char **argv)
165 VALUE *v;
167 program_name = argv[0];
168 setlocale (LC_ALL, "");
169 bindtextdomain (PACKAGE, LOCALEDIR);
170 textdomain (PACKAGE);
172 atexit (close_stdout);
174 posixly_correct = (getenv ("POSIXLY_CORRECT") != NULL);
176 /* Recognize --help or --version only if POSIXLY_CORRECT is not set. */
177 if (!posixly_correct)
178 parse_long_options (argc, argv, PROGRAM_NAME, GNU_PACKAGE, VERSION,
179 AUTHORS, usage);
181 if (argc == 1)
183 error (0, 0, _("too few arguments"));
184 usage (1);
187 args = argv + 1;
189 v = eval ();
190 if (!nomoreargs ())
191 error (2, 0, _("syntax error"));
192 printv (v);
194 exit (null (v));
197 /* Return a VALUE for I. */
199 static VALUE *
200 int_value (int i)
202 VALUE *v;
204 v = NEW (VALUE);
205 v->type = integer;
206 v->u.i = i;
207 return v;
210 /* Return a VALUE for S. */
212 static VALUE *
213 str_value (char *s)
215 VALUE *v;
217 v = NEW (VALUE);
218 v->type = string;
219 v->u.s = xstrdup (s);
220 return v;
223 /* Free VALUE V, including structure components. */
225 static void
226 freev (VALUE *v)
228 if (v->type == string)
229 free (v->u.s);
230 OLD (v);
233 /* Print VALUE V. */
235 static void
236 printv (VALUE *v)
238 switch (v->type)
240 case integer:
241 printf ("%d\n", v->u.i);
242 break;
243 case string:
244 printf ("%s\n", v->u.s);
245 break;
246 default:
247 abort ();
251 /* Return nonzero if V is a null-string or zero-number. */
253 static int
254 null (VALUE *v)
256 switch (v->type)
258 case integer:
259 return v->u.i == 0;
260 case string:
261 return v->u.s[0] == '\0' || strcmp (v->u.s, "0") == 0;
262 default:
263 abort ();
267 /* Return nonzero if V is a string value. */
269 static int
270 isstring (VALUE *v)
272 return v->type == string;
275 /* Coerce V to a string value (can't fail). */
277 static void
278 tostring (VALUE *v)
280 char *temp;
282 switch (v->type)
284 case integer:
285 temp = xmalloc (4 * (sizeof (int) / sizeof (char)));
286 sprintf (temp, "%d", v->u.i);
287 v->u.s = temp;
288 v->type = string;
289 break;
290 case string:
291 break;
292 default:
293 abort ();
297 /* Coerce V to an integer value. Return 1 on success, 0 on failure. */
299 static int
300 toarith (VALUE *v)
302 int i;
303 int neg;
304 char *cp;
306 switch (v->type)
308 case integer:
309 return 1;
310 case string:
311 i = 0;
312 cp = v->u.s;
313 /* Don't interpret the empty string as an integer. */
314 if (*cp == 0)
315 return 0;
316 neg = (*cp == '-');
317 if (neg)
318 cp++;
319 for (; *cp; cp++)
321 if (ISDIGIT (*cp))
322 i = i * 10 + *cp - '0';
323 else
324 return 0;
326 free (v->u.s);
327 v->u.i = i * (neg ? -1 : 1);
328 v->type = integer;
329 return 1;
330 default:
331 abort ();
335 /* Return nonzero if the next token matches STR exactly.
336 STR must not be NULL. */
338 static int
339 nextarg (char *str)
341 if (*args == NULL)
342 return 0;
343 return strcmp (*args, str) == 0;
346 /* Return nonzero if there no more tokens. */
348 static int
349 nomoreargs (void)
351 return *args == 0;
354 /* The comparison operator handling functions. */
356 #define cmpf(name, rel) \
357 static \
358 int name (l, r) VALUE *l; VALUE *r; \
360 if (isstring (l) || isstring (r)) \
362 tostring (l); \
363 tostring (r); \
364 return strcmp (l->u.s, r->u.s) rel 0; \
366 else \
367 return l->u.i rel r->u.i; \
369 cmpf (less_than, <)
370 cmpf (less_equal, <=)
371 cmpf (equal, ==)
372 cmpf (not_equal, !=)
373 cmpf (greater_equal, >=)
374 cmpf (greater_than, >)
376 #undef cmpf
378 /* The arithmetic operator handling functions. */
380 #define arithf(name, op) \
381 static \
382 int name (l, r) VALUE *l; VALUE *r; \
384 if (!toarith (l) || !toarith (r)) \
385 error (2, 0, _("non-numeric argument")); \
386 return l->u.i op r->u.i; \
389 #define arithdivf(name, op) \
390 int name (l, r) VALUE *l; VALUE *r; \
392 if (!toarith (l) || !toarith (r)) \
393 error (2, 0, _("non-numeric argument")); \
394 if (r->u.i == 0) \
395 error (2, 0, _("division by zero")); \
396 return l->u.i op r->u.i; \
399 arithf (plus, +)
400 arithf (minus, -)
401 arithf (multiply, *)
402 arithdivf (divide, /)
403 arithdivf (mod, %)
405 #undef arithf
406 #undef arithdivf
408 #ifdef EVAL_TRACE
409 /* Print evaluation trace and args remaining. */
411 static void
412 trace (fxn)
413 char *fxn;
415 char **a;
417 printf ("%s:", fxn);
418 for (a = args; *a; a++)
419 printf (" %s", *a);
420 putchar ('\n');
422 #endif
424 /* Do the : operator.
425 SV is the VALUE for the lhs (the string),
426 PV is the VALUE for the rhs (the pattern). */
428 static VALUE *
429 docolon (VALUE *sv, VALUE *pv)
431 VALUE *v;
432 const char *errmsg;
433 struct re_pattern_buffer re_buffer;
434 struct re_registers re_regs;
435 int len;
437 tostring (sv);
438 tostring (pv);
440 if (pv->u.s[0] == '^')
442 error (0, 0, _("\
443 warning: unportable BRE: `%s': using `^' as the first character\n\
444 of the basic regular expression is not portable; it is being ignored"),
445 pv->u.s);
448 len = strlen (pv->u.s);
449 memset (&re_buffer, 0, sizeof (re_buffer));
450 memset (&re_regs, 0, sizeof (re_regs));
451 re_buffer.allocated = 2 * len;
452 re_buffer.buffer = (unsigned char *) xmalloc (re_buffer.allocated);
453 re_buffer.translate = 0;
454 re_syntax_options = RE_SYNTAX_POSIX_BASIC;
455 errmsg = re_compile_pattern (pv->u.s, len, &re_buffer);
456 if (errmsg)
457 error (2, 0, "%s", errmsg);
459 len = re_match (&re_buffer, sv->u.s, strlen (sv->u.s), 0, &re_regs);
460 if (len >= 0)
462 /* Were \(...\) used? */
463 if (re_buffer.re_nsub > 0)/* was (re_regs.start[1] >= 0) */
465 sv->u.s[re_regs.end[1]] = '\0';
466 v = str_value (sv->u.s + re_regs.start[1]);
468 else
469 v = int_value (len);
471 else
473 /* Match failed -- return the right kind of null. */
474 if (re_buffer.re_nsub > 0)
475 v = str_value ("");
476 else
477 v = int_value (0);
479 free (re_buffer.buffer);
480 return v;
483 /* Handle bare operands and ( expr ) syntax. */
485 static VALUE *
486 eval7 (void)
488 VALUE *v;
490 #ifdef EVAL_TRACE
491 trace ("eval7");
492 #endif
493 if (nomoreargs ())
494 error (2, 0, _("syntax error"));
496 if (nextarg ("("))
498 args++;
499 v = eval ();
500 if (!nextarg (")"))
501 error (2, 0, _("syntax error"));
502 args++;
503 return v;
506 if (nextarg (")"))
507 error (2, 0, _("syntax error"));
509 return str_value (*args++);
512 /* Handle match, substr, index, length, and quote keywords. */
514 static VALUE *
515 eval6 (void)
517 VALUE *l;
518 VALUE *r;
519 VALUE *v;
520 VALUE *i1;
521 VALUE *i2;
523 #ifdef EVAL_TRACE
524 trace ("eval6");
525 #endif
526 if (!posixly_correct && nextarg ("quote"))
528 args++;
529 if (nomoreargs ())
530 error (2, 0, _("syntax error"));
531 return str_value (*args++);
533 else if (nextarg ("length"))
535 args++;
536 r = eval6 ();
537 tostring (r);
538 v = int_value (strlen (r->u.s));
539 freev (r);
540 return v;
542 else if (nextarg ("match"))
544 args++;
545 l = eval6 ();
546 r = eval6 ();
547 v = docolon (l, r);
548 freev (l);
549 freev (r);
550 return v;
552 else if (nextarg ("index"))
554 args++;
555 l = eval6 ();
556 r = eval6 ();
557 tostring (l);
558 tostring (r);
559 v = int_value (strcspn (l->u.s, r->u.s) + 1);
560 if (v->u.i == (int) strlen (l->u.s) + 1)
561 v->u.i = 0;
562 freev (l);
563 freev (r);
564 return v;
566 else if (nextarg ("substr"))
568 args++;
569 l = eval6 ();
570 i1 = eval6 ();
571 i2 = eval6 ();
572 tostring (l);
573 if (!toarith (i1) || !toarith (i2)
574 || i1->u.i > (int) strlen (l->u.s)
575 || i1->u.i <= 0 || i2->u.i <= 0)
576 v = str_value ("");
577 else
579 v = NEW (VALUE);
580 v->type = string;
581 v->u.s = strncpy ((char *) xmalloc (i2->u.i + 1),
582 l->u.s + i1->u.i - 1, i2->u.i);
583 v->u.s[i2->u.i] = 0;
585 freev (l);
586 freev (i1);
587 freev (i2);
588 return v;
590 else
591 return eval7 ();
594 /* Handle : operator (pattern matching).
595 Calls docolon to do the real work. */
597 static VALUE *
598 eval5 (void)
600 VALUE *l;
601 VALUE *r;
602 VALUE *v;
604 #ifdef EVAL_TRACE
605 trace ("eval5");
606 #endif
607 l = eval6 ();
608 while (1)
610 if (nextarg (":"))
612 args++;
613 r = eval6 ();
614 v = docolon (l, r);
615 freev (l);
616 freev (r);
617 l = v;
619 else
620 return l;
624 /* Handle *, /, % operators. */
626 static VALUE *
627 eval4 (void)
629 VALUE *l;
630 VALUE *r;
631 int (*fxn) ();
632 int val;
634 #ifdef EVAL_TRACE
635 trace ("eval4");
636 #endif
637 l = eval5 ();
638 while (1)
640 if (nextarg ("*"))
641 fxn = multiply;
642 else if (nextarg ("/"))
643 fxn = divide;
644 else if (nextarg ("%"))
645 fxn = mod;
646 else
647 return l;
648 args++;
649 r = eval5 ();
650 val = (*fxn) (l, r);
651 freev (l);
652 freev (r);
653 l = int_value (val);
657 /* Handle +, - operators. */
659 static VALUE *
660 eval3 (void)
662 VALUE *l;
663 VALUE *r;
664 int (*fxn) ();
665 int val;
667 #ifdef EVAL_TRACE
668 trace ("eval3");
669 #endif
670 l = eval4 ();
671 while (1)
673 if (nextarg ("+"))
674 fxn = plus;
675 else if (nextarg ("-"))
676 fxn = minus;
677 else
678 return l;
679 args++;
680 r = eval4 ();
681 val = (*fxn) (l, r);
682 freev (l);
683 freev (r);
684 l = int_value (val);
688 /* Handle comparisons. */
690 static VALUE *
691 eval2 (void)
693 VALUE *l;
694 VALUE *r;
695 int (*fxn) ();
696 int val;
698 #ifdef EVAL_TRACE
699 trace ("eval2");
700 #endif
701 l = eval3 ();
702 while (1)
704 if (nextarg ("<"))
705 fxn = less_than;
706 else if (nextarg ("<="))
707 fxn = less_equal;
708 else if (nextarg ("=") || nextarg ("=="))
709 fxn = equal;
710 else if (nextarg ("!="))
711 fxn = not_equal;
712 else if (nextarg (">="))
713 fxn = greater_equal;
714 else if (nextarg (">"))
715 fxn = greater_than;
716 else
717 return l;
718 args++;
719 r = eval3 ();
720 toarith (l);
721 toarith (r);
722 val = (*fxn) (l, r);
723 freev (l);
724 freev (r);
725 l = int_value (val);
729 /* Handle &. */
731 static VALUE *
732 eval1 (void)
734 VALUE *l;
735 VALUE *r;
737 #ifdef EVAL_TRACE
738 trace ("eval1");
739 #endif
740 l = eval2 ();
741 while (1)
743 if (nextarg ("&"))
745 args++;
746 r = eval2 ();
747 if (null (l) || null (r))
749 freev (l);
750 freev (r);
751 l = int_value (0);
753 else
754 freev (r);
756 else
757 return l;
761 /* Handle |. */
763 static VALUE *
764 eval (void)
766 VALUE *l;
767 VALUE *r;
769 #ifdef EVAL_TRACE
770 trace ("eval");
771 #endif
772 l = eval1 ();
773 while (1)
775 if (nextarg ("|"))
777 args++;
778 r = eval1 ();
779 if (null (l))
781 freev (l);
782 l = r;
784 else
785 freev (r);
787 else
788 return l;