*** empty log message ***
[coreutils.git] / src / expr.c
blob18000705d2ee38afaafa64c247482b017247ec75
1 /* expr -- evaluate expressions.
2 Copyright (C) 86, 1991-1997, 1999-2002 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 "closeout.h"
41 /* The official name of this program (e.g., no `g' prefix). */
42 #define PROGRAM_NAME "expr"
44 #define AUTHORS "Mike Parker"
46 #undef NEW
47 #define NEW(Type) XMALLOC (Type, 1)
48 #define OLD(x) free ((char *) x)
50 /* The kinds of value we can have. */
51 enum valtype
53 integer,
54 string
56 typedef enum valtype TYPE;
58 /* A value is.... */
59 struct valinfo
61 TYPE type; /* Which kind. */
62 union
63 { /* The value itself. */
64 intmax_t i;
65 char *s;
66 } u;
68 typedef struct valinfo VALUE;
70 /* The arguments given to the program, minus the program name. */
71 static char **args;
73 /* The name this program was run with. */
74 char *program_name;
76 static VALUE *eval PARAMS ((void));
77 static int nomoreargs PARAMS ((void));
78 static int null PARAMS ((VALUE *v));
79 static void printv PARAMS ((VALUE *v));
81 void
82 usage (int status)
84 if (status != 0)
85 fprintf (stderr, _("Try `%s --help' for more information.\n"),
86 program_name);
87 else
89 printf (_("\
90 Usage: %s EXPRESSION\n\
91 or: %s OPTION\n\
92 "),
93 program_name, program_name);
94 fputs ("\n", stdout);
95 fputs (HELP_OPTION_DESCRIPTION, stdout);
96 fputs (VERSION_OPTION_DESCRIPTION, stdout);
97 fputs (_("\
98 \n\
99 Print the value of EXPRESSION to standard output. A blank line below\n\
100 separates increasing precedence groups. EXPRESSION may be:\n\
102 ARG1 | ARG2 ARG1 if it is neither null nor 0, otherwise ARG2\n\
104 ARG1 & ARG2 ARG1 if neither argument is null or 0, otherwise 0\n\
105 "), stdout);
106 fputs (_("\
108 ARG1 < ARG2 ARG1 is less than ARG2\n\
109 ARG1 <= ARG2 ARG1 is less than or equal to ARG2\n\
110 ARG1 = ARG2 ARG1 is equal to ARG2\n\
111 ARG1 != ARG2 ARG1 is unequal to ARG2\n\
112 ARG1 >= ARG2 ARG1 is greater than or equal to ARG2\n\
113 ARG1 > ARG2 ARG1 is greater than ARG2\n\
114 "), stdout);
115 fputs (_("\
117 ARG1 + ARG2 arithmetic sum of ARG1 and ARG2\n\
118 ARG1 - ARG2 arithmetic difference of ARG1 and ARG2\n\
119 "), stdout);
120 fputs (_("\
122 ARG1 * ARG2 arithmetic product of ARG1 and ARG2\n\
123 ARG1 / ARG2 arithmetic quotient of ARG1 divided by ARG2\n\
124 ARG1 % ARG2 arithmetic remainder of ARG1 divided by ARG2\n\
125 "), stdout);
126 fputs (_("\
128 STRING : REGEXP anchored pattern match of REGEXP in STRING\n\
130 match STRING REGEXP same as STRING : REGEXP\n\
131 substr STRING POS LENGTH substring of STRING, POS counted from 1\n\
132 index STRING CHARS index in STRING where any CHARS is found, or 0\n\
133 length STRING length of STRING\n\
134 "), stdout);
135 fputs (_("\
136 + TOKEN interpret TOKEN as a string, even if it is a\n\
137 keyword like `match' or an operator like `/'\n\
139 ( EXPRESSION ) value of EXPRESSION\n\
140 "), stdout);
141 fputs (_("\
143 Beware that many operators need to be escaped or quoted for shells.\n\
144 Comparisons are arithmetic if both ARGs are numbers, else lexicographical.\n\
145 Pattern matches return the string matched between \\( and \\) or null; if\n\
146 \\( and \\) are not used, they return the number of characters matched or 0.\n\
147 "), stdout);
148 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
150 exit (status);
154 main (int argc, char **argv)
156 VALUE *v;
158 program_name = argv[0];
159 setlocale (LC_ALL, "");
160 bindtextdomain (PACKAGE, LOCALEDIR);
161 textdomain (PACKAGE);
163 atexit (close_stdout);
165 parse_long_options (argc, argv, PROGRAM_NAME, GNU_PACKAGE, VERSION,
166 AUTHORS, usage);
167 /* The above handles --help and --version.
168 Since there is no other invocation of getopt, handle `--' here. */
169 if (argc > 1 && STREQ (argv[1], "--"))
171 --argc;
172 ++argv;
175 if (argc == 1)
177 error (0, 0, _("too few arguments"));
178 usage (1);
181 args = argv + 1;
183 v = eval ();
184 if (!nomoreargs ())
185 error (2, 0, _("syntax error"));
186 printv (v);
188 exit (null (v));
191 /* Return a VALUE for I. */
193 static VALUE *
194 int_value (intmax_t i)
196 VALUE *v;
198 v = NEW (VALUE);
199 v->type = integer;
200 v->u.i = i;
201 return v;
204 /* Return a VALUE for S. */
206 static VALUE *
207 str_value (char *s)
209 VALUE *v;
211 v = NEW (VALUE);
212 v->type = string;
213 v->u.s = xstrdup (s);
214 return v;
217 /* Free VALUE V, including structure components. */
219 static void
220 freev (VALUE *v)
222 if (v->type == string)
223 free (v->u.s);
224 OLD (v);
227 /* Store a printable representation of I somewhere into BUF, and
228 return a pointer to the stored representation. */
230 static char *
231 inttostr (intmax_t i, char buf[INT_STRLEN_BOUND (intmax_t) + 1])
233 uintmax_t ui = i;
234 char *p = buf + INT_STRLEN_BOUND (intmax_t);
235 *p = '\0';
236 if (i < 0)
237 ui = -ui;
239 *--p = '0' + ui % 10;
240 while ((ui /= 10) != 0);
241 if (i < 0)
242 *--p = '-';
243 return p;
246 /* Print VALUE V. */
248 static void
249 printv (VALUE *v)
251 char *p;
252 char buf[INT_STRLEN_BOUND (intmax_t) + 1];
254 switch (v->type)
256 case integer:
257 p = inttostr (v->u.i, buf);
258 break;
259 case string:
260 p = v->u.s;
261 break;
262 default:
263 abort ();
266 puts (p);
269 /* Return nonzero if V is a null-string or zero-number. */
271 static int
272 null (VALUE *v)
274 switch (v->type)
276 case integer:
277 return v->u.i == 0;
278 case string:
279 return v->u.s[0] == '\0' || strcmp (v->u.s, "0") == 0;
280 default:
281 abort ();
285 /* Coerce V to a string value (can't fail). */
287 static void
288 tostring (VALUE *v)
290 char buf[INT_STRLEN_BOUND (intmax_t) + 1];
292 switch (v->type)
294 case integer:
295 v->u.s = xstrdup (inttostr (v->u.i, buf));
296 v->type = string;
297 break;
298 case string:
299 break;
300 default:
301 abort ();
305 /* Coerce V to an integer value. Return 1 on success, 0 on failure. */
307 static int
308 toarith (VALUE *v)
310 intmax_t i;
311 int neg;
312 char *cp;
314 switch (v->type)
316 case integer:
317 return 1;
318 case string:
319 i = 0;
320 cp = v->u.s;
321 neg = (*cp == '-');
322 if (neg)
323 cp++;
327 if (ISDIGIT (*cp))
328 i = i * 10 + *cp - '0';
329 else
330 return 0;
332 while (*++cp);
334 free (v->u.s);
335 v->u.i = i * (neg ? -1 : 1);
336 v->type = integer;
337 return 1;
338 default:
339 abort ();
343 /* Return nonzero and advance if the next token matches STR exactly.
344 STR must not be NULL. */
346 static int
347 nextarg (char *str)
349 if (*args == NULL)
350 return 0;
351 else
353 int r = strcoll (*args, str) == 0;
354 args += r;
355 return r;
359 /* Return nonzero if there no more tokens. */
361 static int
362 nomoreargs (void)
364 return *args == 0;
367 #ifdef EVAL_TRACE
368 /* Print evaluation trace and args remaining. */
370 static void
371 trace (fxn)
372 char *fxn;
374 char **a;
376 printf ("%s:", fxn);
377 for (a = args; *a; a++)
378 printf (" %s", *a);
379 putchar ('\n');
381 #endif
383 /* Do the : operator.
384 SV is the VALUE for the lhs (the string),
385 PV is the VALUE for the rhs (the pattern). */
387 static VALUE *
388 docolon (VALUE *sv, VALUE *pv)
390 VALUE *v;
391 const char *errmsg;
392 struct re_pattern_buffer re_buffer;
393 struct re_registers re_regs;
394 size_t len;
395 int matchlen;
397 tostring (sv);
398 tostring (pv);
400 if (pv->u.s[0] == '^')
402 error (0, 0, _("\
403 warning: unportable BRE: `%s': using `^' as the first character\n\
404 of the basic regular expression is not portable; it is being ignored"),
405 pv->u.s);
408 len = strlen (pv->u.s);
409 memset (&re_buffer, 0, sizeof (re_buffer));
410 memset (&re_regs, 0, sizeof (re_regs));
411 re_buffer.allocated = 2 * len;
412 if (re_buffer.allocated < len)
413 xalloc_die ();
414 re_buffer.buffer = (unsigned char *) xmalloc (re_buffer.allocated);
415 re_buffer.translate = 0;
416 re_syntax_options = RE_SYNTAX_POSIX_BASIC;
417 errmsg = re_compile_pattern (pv->u.s, len, &re_buffer);
418 if (errmsg)
419 error (2, 0, "%s", errmsg);
421 matchlen = re_match (&re_buffer, sv->u.s, strlen (sv->u.s), 0, &re_regs);
422 if (0 <= matchlen)
424 /* Were \(...\) used? */
425 if (re_buffer.re_nsub > 0)/* was (re_regs.start[1] >= 0) */
427 sv->u.s[re_regs.end[1]] = '\0';
428 v = str_value (sv->u.s + re_regs.start[1]);
430 else
431 v = int_value (matchlen);
433 else
435 /* Match failed -- return the right kind of null. */
436 if (re_buffer.re_nsub > 0)
437 v = str_value ("");
438 else
439 v = int_value (0);
441 free (re_buffer.buffer);
442 return v;
445 /* Handle bare operands and ( expr ) syntax. */
447 static VALUE *
448 eval7 (void)
450 VALUE *v;
452 #ifdef EVAL_TRACE
453 trace ("eval7");
454 #endif
455 if (nomoreargs ())
456 error (2, 0, _("syntax error"));
458 if (nextarg ("("))
460 v = eval ();
461 if (!nextarg (")"))
462 error (2, 0, _("syntax error"));
463 return v;
466 if (nextarg (")"))
467 error (2, 0, _("syntax error"));
469 return str_value (*args++);
472 /* Handle match, substr, index, and length keywords, and quoting "+". */
474 static VALUE *
475 eval6 (void)
477 VALUE *l;
478 VALUE *r;
479 VALUE *v;
480 VALUE *i1;
481 VALUE *i2;
483 #ifdef EVAL_TRACE
484 trace ("eval6");
485 #endif
486 if (nextarg ("+"))
488 if (nomoreargs ())
489 error (2, 0, _("syntax error"));
490 return str_value (*args++);
492 else if (nextarg ("length"))
494 r = eval6 ();
495 tostring (r);
496 v = int_value (strlen (r->u.s));
497 freev (r);
498 return v;
500 else if (nextarg ("match"))
502 l = eval6 ();
503 r = eval6 ();
504 v = docolon (l, r);
505 freev (l);
506 freev (r);
507 return v;
509 else if (nextarg ("index"))
511 l = eval6 ();
512 r = eval6 ();
513 tostring (l);
514 tostring (r);
515 v = int_value (strcspn (l->u.s, r->u.s) + 1);
516 if (v->u.i == strlen (l->u.s) + 1)
517 v->u.i = 0;
518 freev (l);
519 freev (r);
520 return v;
522 else if (nextarg ("substr"))
524 l = eval6 ();
525 i1 = eval6 ();
526 i2 = eval6 ();
527 tostring (l);
528 if (!toarith (i1) || !toarith (i2)
529 || strlen (l->u.s) < i1->u.i
530 || i1->u.i <= 0 || i2->u.i <= 0)
531 v = str_value ("");
532 else
534 v = NEW (VALUE);
535 v->type = string;
536 v->u.s = strncpy ((char *) xmalloc (i2->u.i + 1),
537 l->u.s + i1->u.i - 1, i2->u.i);
538 v->u.s[i2->u.i] = 0;
540 freev (l);
541 freev (i1);
542 freev (i2);
543 return v;
545 else
546 return eval7 ();
549 /* Handle : operator (pattern matching).
550 Calls docolon to do the real work. */
552 static VALUE *
553 eval5 (void)
555 VALUE *l;
556 VALUE *r;
557 VALUE *v;
559 #ifdef EVAL_TRACE
560 trace ("eval5");
561 #endif
562 l = eval6 ();
563 while (1)
565 if (nextarg (":"))
567 r = eval6 ();
568 v = docolon (l, r);
569 freev (l);
570 freev (r);
571 l = v;
573 else
574 return l;
578 /* Handle *, /, % operators. */
580 static VALUE *
581 eval4 (void)
583 VALUE *l;
584 VALUE *r;
585 enum { multiply, divide, mod } fxn;
586 intmax_t val;
588 #ifdef EVAL_TRACE
589 trace ("eval4");
590 #endif
591 l = eval5 ();
592 while (1)
594 if (nextarg ("*"))
595 fxn = multiply;
596 else if (nextarg ("/"))
597 fxn = divide;
598 else if (nextarg ("%"))
599 fxn = mod;
600 else
601 return l;
602 r = eval5 ();
603 if (!toarith (l) || !toarith (r))
604 error (2, 0, _("non-numeric argument"));
605 if (fxn == multiply)
606 val = l->u.i * r->u.i;
607 else
609 if (r->u.i == 0)
610 error (2, 0, _("division by zero"));
611 val = fxn == divide ? l->u.i / r->u.i : l->u.i % r->u.i;
613 freev (l);
614 freev (r);
615 l = int_value (val);
619 /* Handle +, - operators. */
621 static VALUE *
622 eval3 (void)
624 VALUE *l;
625 VALUE *r;
626 enum { plus, minus } fxn;
627 intmax_t val;
629 #ifdef EVAL_TRACE
630 trace ("eval3");
631 #endif
632 l = eval4 ();
633 while (1)
635 if (nextarg ("+"))
636 fxn = plus;
637 else if (nextarg ("-"))
638 fxn = minus;
639 else
640 return l;
641 r = eval4 ();
642 if (!toarith (l) || !toarith (r))
643 error (2, 0, _("non-numeric argument"));
644 val = fxn == plus ? l->u.i + r->u.i : l->u.i - r->u.i;
645 freev (l);
646 freev (r);
647 l = int_value (val);
651 /* Handle comparisons. */
653 static VALUE *
654 eval2 (void)
656 VALUE *l;
657 VALUE *r;
658 enum
660 less_than, less_equal, equal, not_equal, greater_equal, greater_than
661 } fxn;
662 int val;
663 intmax_t lval;
664 intmax_t rval;
666 #ifdef EVAL_TRACE
667 trace ("eval2");
668 #endif
669 l = eval3 ();
670 while (1)
672 if (nextarg ("<"))
673 fxn = less_than;
674 else if (nextarg ("<="))
675 fxn = less_equal;
676 else if (nextarg ("=") || nextarg ("=="))
677 fxn = equal;
678 else if (nextarg ("!="))
679 fxn = not_equal;
680 else if (nextarg (">="))
681 fxn = greater_equal;
682 else if (nextarg (">"))
683 fxn = greater_than;
684 else
685 return l;
686 r = eval3 ();
687 tostring (l);
688 tostring (r);
689 lval = strcoll (l->u.s, r->u.s);
690 rval = 0;
691 if (toarith (l) && toarith (r))
693 lval = l->u.i;
694 rval = r->u.i;
696 switch (fxn)
698 case less_than: val = (lval < rval); break;
699 case less_equal: val = (lval <= rval); break;
700 case equal: val = (lval == rval); break;
701 case not_equal: val = (lval != rval); break;
702 case greater_equal: val = (lval >= rval); break;
703 case greater_than: val = (lval > rval); break;
704 default: abort ();
706 freev (l);
707 freev (r);
708 l = int_value (val);
712 /* Handle &. */
714 static VALUE *
715 eval1 (void)
717 VALUE *l;
718 VALUE *r;
720 #ifdef EVAL_TRACE
721 trace ("eval1");
722 #endif
723 l = eval2 ();
724 while (1)
726 if (nextarg ("&"))
728 r = eval2 ();
729 if (null (l) || null (r))
731 freev (l);
732 freev (r);
733 l = int_value (0);
735 else
736 freev (r);
738 else
739 return l;
743 /* Handle |. */
745 static VALUE *
746 eval (void)
748 VALUE *l;
749 VALUE *r;
751 #ifdef EVAL_TRACE
752 trace ("eval");
753 #endif
754 l = eval1 ();
755 while (1)
757 if (nextarg ("|"))
759 r = eval1 ();
760 if (null (l))
762 freev (l);
763 l = r;
765 else
766 freev (r);
768 else
769 return l;