*** empty log message ***
[coreutils.git] / src / expr.c
bloba61bc34c97edc2dc0a80cb6065f988c2d3fb2571
1 /* expr -- evaluate expressions.
2 Copyright (C) 86, 1991-1997, 1999 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 /* The official name of this program (e.g., no `g' prefix). */
41 #define PROGRAM_NAME "expr"
43 #define AUTHORS "Mike Parker"
45 #define NEW(type) ((type *) xmalloc (sizeof (type)))
46 #define OLD(x) free ((char *) x)
48 /* The kinds of value we can have. */
49 enum valtype
51 integer,
52 string
54 typedef enum valtype TYPE;
56 /* A value is.... */
57 struct valinfo
59 TYPE type; /* Which kind. */
60 union
61 { /* The value itself. */
62 int i;
63 char *s;
64 } u;
66 typedef struct valinfo VALUE;
68 /* Non-zero if the POSIXLY_CORRECT environment variable is set.
69 The unary operator `quote' is disabled when this variable is zero. */
70 static int posixly_correct;
72 /* The arguments given to the program, minus the program name. */
73 static char **args;
75 /* The name this program was run with. */
76 char *program_name;
78 char *xstrdup ();
80 static VALUE *docolon PARAMS ((VALUE *sv, VALUE *pv));
81 static VALUE *eval PARAMS ((void));
82 static VALUE *int_value PARAMS ((int i));
83 static VALUE *str_value PARAMS ((char *s));
84 static int isstring PARAMS ((VALUE *v));
85 static int nextarg PARAMS ((char *str));
86 static int nomoreargs PARAMS ((void));
87 static int null PARAMS ((VALUE *v));
88 static int toarith PARAMS ((VALUE *v));
89 static void freev PARAMS ((VALUE *v));
90 static void printv PARAMS ((VALUE *v));
91 static void tostring PARAMS ((VALUE *v));
93 #ifdef EVAL_TRACE
94 static void trace ();
95 #endif
97 void
98 usage (int status)
100 if (status != 0)
101 fprintf (stderr, _("Try `%s --help' for more information.\n"),
102 program_name);
103 else
105 printf (_("\
106 Usage: %s EXPRESSION\n\
107 or: %s OPTION\n\
109 program_name, program_name);
110 printf (_("\
112 --help display this help and exit\n\
113 --version output version information and exit\n\
115 "));
116 printf (_("\
117 Print the value of EXPRESSION to standard output. A blank line below\n\
118 separates increasing precedence groups. EXPRESSION may be:\n\
120 ARG1 | ARG2 ARG1 if it is neither null nor 0, otherwise ARG2\n\
122 ARG1 & ARG2 ARG1 if neither argument is null or 0, otherwise 0\n\
124 ARG1 < ARG2 ARG1 is less than ARG2\n\
125 ARG1 <= ARG2 ARG1 is less than or equal to ARG2\n\
126 ARG1 = ARG2 ARG1 is equal to ARG2\n\
127 ARG1 != ARG2 ARG1 is unequal to ARG2\n\
128 ARG1 >= ARG2 ARG1 is greater than or equal to ARG2\n\
129 ARG1 > ARG2 ARG1 is greater than ARG2\n\
131 ARG1 + ARG2 arithmetic sum of ARG1 and ARG2\n\
132 ARG1 - ARG2 arithmetic difference of ARG1 and ARG2\n\
134 ARG1 * ARG2 arithmetic product of ARG1 and ARG2\n\
135 ARG1 / ARG2 arithmetic quotient of ARG1 divided by ARG2\n\
136 ARG1 %% ARG2 arithmetic remainder of ARG1 divided by ARG2\n\
138 STRING : REGEXP anchored pattern match of REGEXP in STRING\n\
140 match STRING REGEXP same as STRING : REGEXP\n\
141 substr STRING POS LENGTH substring of STRING, POS counted from 1\n\
142 index STRING CHARS index in STRING where any CHARS is found, or 0\n\
143 length STRING length of STRING\n\
144 quote TOKEN interpret TOKEN as a string, even if it is a\n\
145 keyword like `match' or an operator like `/'\n\
147 ( EXPRESSION ) value of EXPRESSION\n\
148 "));
149 printf (_("\
151 Beware that many operators need to be escaped or quoted for shells.\n\
152 Comparisons are arithmetic if both ARGs are numbers, else lexicographical.\n\
153 Pattern matches return the string matched between \\( and \\) or null; if\n\
154 \\( and \\) are not used, they return the number of characters matched or 0.\n\
155 "));
156 puts (_("\nReport bugs to <bug-sh-utils@gnu.org>."));
158 exit (status);
162 main (int argc, char **argv)
164 VALUE *v;
166 program_name = argv[0];
167 setlocale (LC_ALL, "");
168 bindtextdomain (PACKAGE, LOCALEDIR);
169 textdomain (PACKAGE);
171 posixly_correct = (getenv ("POSIXLY_CORRECT") != NULL);
173 /* Recognize --help or --version only if POSIXLY_CORRECT is not set. */
174 if (!posixly_correct)
175 parse_long_options (argc, argv, PROGRAM_NAME, GNU_PACKAGE, VERSION,
176 AUTHORS, usage);
178 if (argc == 1)
180 error (0, 0, _("too few arguments"));
181 usage (1);
184 args = argv + 1;
186 v = eval ();
187 if (!nomoreargs ())
188 error (2, 0, _("syntax error"));
189 printv (v);
191 exit (null (v));
194 /* Return a VALUE for I. */
196 static VALUE *
197 int_value (int i)
199 VALUE *v;
201 v = NEW (VALUE);
202 v->type = integer;
203 v->u.i = i;
204 return v;
207 /* Return a VALUE for S. */
209 static VALUE *
210 str_value (char *s)
212 VALUE *v;
214 v = NEW (VALUE);
215 v->type = string;
216 v->u.s = xstrdup (s);
217 return v;
220 /* Free VALUE V, including structure components. */
222 static void
223 freev (VALUE *v)
225 if (v->type == string)
226 free (v->u.s);
227 OLD (v);
230 /* Print VALUE V. */
232 static void
233 printv (VALUE *v)
235 switch (v->type)
237 case integer:
238 printf ("%d\n", v->u.i);
239 break;
240 case string:
241 printf ("%s\n", v->u.s);
242 break;
243 default:
244 abort ();
248 /* Return nonzero if V is a null-string or zero-number. */
250 static int
251 null (VALUE *v)
253 switch (v->type)
255 case integer:
256 return v->u.i == 0;
257 case string:
258 return v->u.s[0] == '\0' || strcmp (v->u.s, "0") == 0;
259 default:
260 abort ();
264 /* Return nonzero if V is a string value. */
266 static int
267 isstring (VALUE *v)
269 return v->type == string;
272 /* Coerce V to a string value (can't fail). */
274 static void
275 tostring (VALUE *v)
277 char *temp;
279 switch (v->type)
281 case integer:
282 temp = xmalloc (4 * (sizeof (int) / sizeof (char)));
283 sprintf (temp, "%d", v->u.i);
284 v->u.s = temp;
285 v->type = string;
286 break;
287 case string:
288 break;
289 default:
290 abort ();
294 /* Coerce V to an integer value. Return 1 on success, 0 on failure. */
296 static int
297 toarith (VALUE *v)
299 int i;
300 int neg;
301 char *cp;
303 switch (v->type)
305 case integer:
306 return 1;
307 case string:
308 i = 0;
309 cp = v->u.s;
310 /* Don't interpret the empty string as an integer. */
311 if (*cp == 0)
312 return 0;
313 neg = (*cp == '-');
314 if (neg)
315 cp++;
316 for (; *cp; cp++)
318 if (ISDIGIT (*cp))
319 i = i * 10 + *cp - '0';
320 else
321 return 0;
323 free (v->u.s);
324 v->u.i = i * (neg ? -1 : 1);
325 v->type = integer;
326 return 1;
327 default:
328 abort ();
332 /* Return nonzero if the next token matches STR exactly.
333 STR must not be NULL. */
335 static int
336 nextarg (char *str)
338 if (*args == NULL)
339 return 0;
340 return strcmp (*args, str) == 0;
343 /* Return nonzero if there no more tokens. */
345 static int
346 nomoreargs (void)
348 return *args == 0;
351 /* The comparison operator handling functions. */
353 #define cmpf(name, rel) \
354 static \
355 int name (l, r) VALUE *l; VALUE *r; \
357 if (isstring (l) || isstring (r)) \
359 tostring (l); \
360 tostring (r); \
361 return strcmp (l->u.s, r->u.s) rel 0; \
363 else \
364 return l->u.i rel r->u.i; \
366 cmpf (less_than, <)
367 cmpf (less_equal, <=)
368 cmpf (equal, ==)
369 cmpf (not_equal, !=)
370 cmpf (greater_equal, >=)
371 cmpf (greater_than, >)
373 #undef cmpf
375 /* The arithmetic operator handling functions. */
377 #define arithf(name, op) \
378 static \
379 int name (l, r) VALUE *l; VALUE *r; \
381 if (!toarith (l) || !toarith (r)) \
382 error (2, 0, _("non-numeric argument")); \
383 return l->u.i op r->u.i; \
386 #define arithdivf(name, op) \
387 int name (l, r) VALUE *l; VALUE *r; \
389 if (!toarith (l) || !toarith (r)) \
390 error (2, 0, _("non-numeric argument")); \
391 if (r->u.i == 0) \
392 error (2, 0, _("division by zero")); \
393 return l->u.i op r->u.i; \
396 arithf (plus, +)
397 arithf (minus, -)
398 arithf (multiply, *)
399 arithdivf (divide, /)
400 arithdivf (mod, %)
402 #undef arithf
403 #undef arithdivf
405 #ifdef EVAL_TRACE
406 /* Print evaluation trace and args remaining. */
408 static void
409 trace (fxn)
410 char *fxn;
412 char **a;
414 printf ("%s:", fxn);
415 for (a = args; *a; a++)
416 printf (" %s", *a);
417 putchar ('\n');
419 #endif
421 /* Do the : operator.
422 SV is the VALUE for the lhs (the string),
423 PV is the VALUE for the rhs (the pattern). */
425 static VALUE *
426 docolon (VALUE *sv, VALUE *pv)
428 VALUE *v;
429 const char *errmsg;
430 struct re_pattern_buffer re_buffer;
431 struct re_registers re_regs;
432 int len;
434 tostring (sv);
435 tostring (pv);
437 if (pv->u.s[0] == '^')
439 error (0, 0, _("\
440 warning: unportable BRE: `%s': using `^' as the first character\n\
441 of the basic regular expression is not portable; it is being ignored"),
442 pv->u.s);
445 len = strlen (pv->u.s);
446 memset (&re_buffer, 0, sizeof (re_buffer));
447 memset (&re_regs, 0, sizeof (re_regs));
448 re_buffer.allocated = 2 * len;
449 re_buffer.buffer = (unsigned char *) xmalloc (re_buffer.allocated);
450 re_buffer.translate = 0;
451 re_syntax_options = RE_SYNTAX_POSIX_BASIC;
452 errmsg = re_compile_pattern (pv->u.s, len, &re_buffer);
453 if (errmsg)
454 error (2, 0, "%s", errmsg);
456 len = re_match (&re_buffer, sv->u.s, strlen (sv->u.s), 0, &re_regs);
457 if (len >= 0)
459 /* Were \(...\) used? */
460 if (re_buffer.re_nsub > 0)/* was (re_regs.start[1] >= 0) */
462 sv->u.s[re_regs.end[1]] = '\0';
463 v = str_value (sv->u.s + re_regs.start[1]);
465 else
466 v = int_value (len);
468 else
470 /* Match failed -- return the right kind of null. */
471 if (re_buffer.re_nsub > 0)
472 v = str_value ("");
473 else
474 v = int_value (0);
476 free (re_buffer.buffer);
477 return v;
480 /* Handle bare operands and ( expr ) syntax. */
482 static VALUE *
483 eval7 (void)
485 VALUE *v;
487 #ifdef EVAL_TRACE
488 trace ("eval7");
489 #endif
490 if (nomoreargs ())
491 error (2, 0, _("syntax error"));
493 if (nextarg ("("))
495 args++;
496 v = eval ();
497 if (!nextarg (")"))
498 error (2, 0, _("syntax error"));
499 args++;
500 return v;
503 if (nextarg (")"))
504 error (2, 0, _("syntax error"));
506 return str_value (*args++);
509 /* Handle match, substr, index, length, and quote keywords. */
511 static VALUE *
512 eval6 (void)
514 VALUE *l;
515 VALUE *r;
516 VALUE *v;
517 VALUE *i1;
518 VALUE *i2;
520 #ifdef EVAL_TRACE
521 trace ("eval6");
522 #endif
523 if (!posixly_correct && nextarg ("quote"))
525 args++;
526 if (nomoreargs ())
527 error (2, 0, _("syntax error"));
528 return str_value (*args++);
530 else if (nextarg ("length"))
532 args++;
533 r = eval6 ();
534 tostring (r);
535 v = int_value (strlen (r->u.s));
536 freev (r);
537 return v;
539 else if (nextarg ("match"))
541 args++;
542 l = eval6 ();
543 r = eval6 ();
544 v = docolon (l, r);
545 freev (l);
546 freev (r);
547 return v;
549 else if (nextarg ("index"))
551 args++;
552 l = eval6 ();
553 r = eval6 ();
554 tostring (l);
555 tostring (r);
556 v = int_value (strcspn (l->u.s, r->u.s) + 1);
557 if (v->u.i == (int) strlen (l->u.s) + 1)
558 v->u.i = 0;
559 freev (l);
560 freev (r);
561 return v;
563 else if (nextarg ("substr"))
565 args++;
566 l = eval6 ();
567 i1 = eval6 ();
568 i2 = eval6 ();
569 tostring (l);
570 if (!toarith (i1) || !toarith (i2)
571 || i1->u.i > (int) strlen (l->u.s)
572 || i1->u.i <= 0 || i2->u.i <= 0)
573 v = str_value ("");
574 else
576 v = NEW (VALUE);
577 v->type = string;
578 v->u.s = strncpy ((char *) xmalloc (i2->u.i + 1),
579 l->u.s + i1->u.i - 1, i2->u.i);
580 v->u.s[i2->u.i] = 0;
582 freev (l);
583 freev (i1);
584 freev (i2);
585 return v;
587 else
588 return eval7 ();
591 /* Handle : operator (pattern matching).
592 Calls docolon to do the real work. */
594 static VALUE *
595 eval5 (void)
597 VALUE *l;
598 VALUE *r;
599 VALUE *v;
601 #ifdef EVAL_TRACE
602 trace ("eval5");
603 #endif
604 l = eval6 ();
605 while (1)
607 if (nextarg (":"))
609 args++;
610 r = eval6 ();
611 v = docolon (l, r);
612 freev (l);
613 freev (r);
614 l = v;
616 else
617 return l;
621 /* Handle *, /, % operators. */
623 static VALUE *
624 eval4 (void)
626 VALUE *l;
627 VALUE *r;
628 int (*fxn) ();
629 int val;
631 #ifdef EVAL_TRACE
632 trace ("eval4");
633 #endif
634 l = eval5 ();
635 while (1)
637 if (nextarg ("*"))
638 fxn = multiply;
639 else if (nextarg ("/"))
640 fxn = divide;
641 else if (nextarg ("%"))
642 fxn = mod;
643 else
644 return l;
645 args++;
646 r = eval5 ();
647 val = (*fxn) (l, r);
648 freev (l);
649 freev (r);
650 l = int_value (val);
654 /* Handle +, - operators. */
656 static VALUE *
657 eval3 (void)
659 VALUE *l;
660 VALUE *r;
661 int (*fxn) ();
662 int val;
664 #ifdef EVAL_TRACE
665 trace ("eval3");
666 #endif
667 l = eval4 ();
668 while (1)
670 if (nextarg ("+"))
671 fxn = plus;
672 else if (nextarg ("-"))
673 fxn = minus;
674 else
675 return l;
676 args++;
677 r = eval4 ();
678 val = (*fxn) (l, r);
679 freev (l);
680 freev (r);
681 l = int_value (val);
685 /* Handle comparisons. */
687 static VALUE *
688 eval2 (void)
690 VALUE *l;
691 VALUE *r;
692 int (*fxn) ();
693 int val;
695 #ifdef EVAL_TRACE
696 trace ("eval2");
697 #endif
698 l = eval3 ();
699 while (1)
701 if (nextarg ("<"))
702 fxn = less_than;
703 else if (nextarg ("<="))
704 fxn = less_equal;
705 else if (nextarg ("=") || nextarg ("=="))
706 fxn = equal;
707 else if (nextarg ("!="))
708 fxn = not_equal;
709 else if (nextarg (">="))
710 fxn = greater_equal;
711 else if (nextarg (">"))
712 fxn = greater_than;
713 else
714 return l;
715 args++;
716 r = eval3 ();
717 toarith (l);
718 toarith (r);
719 val = (*fxn) (l, r);
720 freev (l);
721 freev (r);
722 l = int_value (val);
726 /* Handle &. */
728 static VALUE *
729 eval1 (void)
731 VALUE *l;
732 VALUE *r;
734 #ifdef EVAL_TRACE
735 trace ("eval1");
736 #endif
737 l = eval2 ();
738 while (1)
740 if (nextarg ("&"))
742 args++;
743 r = eval2 ();
744 if (null (l) || null (r))
746 freev (l);
747 freev (r);
748 l = int_value (0);
750 else
751 freev (r);
753 else
754 return l;
758 /* Handle |. */
760 static VALUE *
761 eval (void)
763 VALUE *l;
764 VALUE *r;
766 #ifdef EVAL_TRACE
767 trace ("eval");
768 #endif
769 l = eval1 ();
770 while (1)
772 if (nextarg ("|"))
774 args++;
775 r = eval1 ();
776 if (null (l))
778 freev (l);
779 l = r;
781 else
782 freev (r);
784 else
785 return l;