tests: remove a non portable localtime test
[coreutils.git] / src / expr.c
blob86eb1361fbf82111900742cd9c4dcebff7bdb313
1 /* expr -- evaluate expressions.
2 Copyright (C) 1986-2016 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 3 of the License, or
7 (at your option) 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, see <http://www.gnu.org/licenses/>. */
17 /* Author: Mike Parker.
18 Modified for arbitrary-precision calculation by James Youngman.
20 This program evaluates expressions. Each token (operator, operand,
21 parenthesis) of the expression must be a separate 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 "error.h"
38 #include "long-options.h"
39 #include "strnumcmp.h"
40 #include "xstrtol.h"
42 /* Various parts of this code assume size_t fits into unsigned long
43 int, the widest unsigned type that GMP supports. */
44 verify (SIZE_MAX <= ULONG_MAX);
46 #ifndef HAVE_GMP
47 # define HAVE_GMP 0
48 #endif
50 #if HAVE_GMP
51 # include <gmp.h>
52 #else
53 static void integer_overflow (char) ATTRIBUTE_NORETURN;
54 /* Approximate gmp.h well enough for expr.c's purposes. */
55 typedef intmax_t mpz_t[1];
56 static void mpz_clear (mpz_t z) { (void) z; }
57 static void mpz_init_set_ui (mpz_t z, unsigned long int i) { z[0] = i; }
58 static int
59 mpz_init_set_str (mpz_t z, char *s, int base)
61 return xstrtoimax (s, NULL, base, z, NULL) == LONGINT_OK ? 0 : -1;
63 static void
64 mpz_add (mpz_t r, mpz_t a0, mpz_t b0)
66 intmax_t a = a0[0];
67 intmax_t b = b0[0];
68 intmax_t val = a + b;
69 if ((val < a) != (b < 0))
70 integer_overflow ('+');
71 r[0] = val;
73 static void
74 mpz_sub (mpz_t r, mpz_t a0, mpz_t b0)
76 intmax_t a = a0[0];
77 intmax_t b = b0[0];
78 intmax_t val = a - b;
79 if ((a < val) != (b < 0))
80 integer_overflow ('-');
81 r[0] = val;
83 static void
84 mpz_mul (mpz_t r, mpz_t a0, mpz_t b0)
86 intmax_t a = a0[0];
87 intmax_t b = b0[0];
88 intmax_t val = a * b;
89 if (! (a == 0 || b == 0
90 || ((val < 0) == ((a < 0) ^ (b < 0)) && val / a == b)))
91 integer_overflow ('*');
92 r[0] = val;
94 static void
95 mpz_tdiv_q (mpz_t r, mpz_t a0, mpz_t b0)
97 intmax_t a = a0[0];
98 intmax_t b = b0[0];
100 /* Some x86-style hosts raise an exception for INT_MIN / -1. */
101 if (a < - INTMAX_MAX && b == -1)
102 integer_overflow ('/');
103 r[0] = a / b;
105 static void
106 mpz_tdiv_r (mpz_t r, mpz_t a0, mpz_t b0)
108 intmax_t a = a0[0];
109 intmax_t b = b0[0];
111 /* Some x86-style hosts raise an exception for INT_MIN % -1. */
112 r[0] = a < - INTMAX_MAX && b == -1 ? 0 : a % b;
114 static char *
115 mpz_get_str (char const *str, int base, mpz_t z)
117 (void) str; (void) base;
118 char buf[INT_BUFSIZE_BOUND (intmax_t)];
119 return xstrdup (imaxtostr (z[0], buf));
121 static int
122 mpz_sgn (mpz_t z)
124 return z[0] < 0 ? -1 : 0 < z[0];
126 static int
127 mpz_fits_ulong_p (mpz_t z)
129 return 0 <= z[0] && z[0] <= ULONG_MAX;
131 static unsigned long int
132 mpz_get_ui (mpz_t z)
134 return z[0];
136 static int
137 mpz_out_str (FILE *stream, int base, mpz_t z)
139 (void) base;
140 char buf[INT_BUFSIZE_BOUND (intmax_t)];
141 return fputs (imaxtostr (z[0], buf), stream) != EOF;
143 #endif
145 /* The official name of this program (e.g., no 'g' prefix). */
146 #define PROGRAM_NAME "expr"
148 #define AUTHORS \
149 proper_name ("Mike Parker"), \
150 proper_name ("James Youngman"), \
151 proper_name ("Paul Eggert")
153 /* Exit statuses. */
154 enum
156 /* Invalid expression: e.g., its form does not conform to the
157 grammar for expressions. Our grammar is an extension of the
158 POSIX grammar. */
159 EXPR_INVALID = 2,
161 /* An internal error occurred, e.g., arithmetic overflow, storage
162 exhaustion. */
163 EXPR_FAILURE
166 /* The kinds of value we can have. */
167 enum valtype
169 integer,
170 string
172 typedef enum valtype TYPE;
174 /* A value is.... */
175 struct valinfo
177 TYPE type; /* Which kind. */
178 union
179 { /* The value itself. */
180 mpz_t i;
181 char *s;
182 } u;
184 typedef struct valinfo VALUE;
186 /* The arguments given to the program, minus the program name. */
187 static char **args;
189 static VALUE *eval (bool);
190 static bool nomoreargs (void);
191 static bool null (VALUE *v);
192 static void printv (VALUE *v);
194 void
195 usage (int status)
197 if (status != EXIT_SUCCESS)
198 emit_try_help ();
199 else
201 printf (_("\
202 Usage: %s EXPRESSION\n\
203 or: %s OPTION\n\
205 program_name, program_name);
206 putchar ('\n');
207 fputs (HELP_OPTION_DESCRIPTION, stdout);
208 fputs (VERSION_OPTION_DESCRIPTION, stdout);
209 fputs (_("\
211 Print the value of EXPRESSION to standard output. A blank line below\n\
212 separates increasing precedence groups. EXPRESSION may be:\n\
214 ARG1 | ARG2 ARG1 if it is neither null nor 0, otherwise ARG2\n\
216 ARG1 & ARG2 ARG1 if neither argument is null or 0, otherwise 0\n\
217 "), stdout);
218 fputs (_("\
220 ARG1 < ARG2 ARG1 is less than ARG2\n\
221 ARG1 <= ARG2 ARG1 is less than or equal to ARG2\n\
222 ARG1 = ARG2 ARG1 is equal to ARG2\n\
223 ARG1 != ARG2 ARG1 is unequal to ARG2\n\
224 ARG1 >= ARG2 ARG1 is greater than or equal to ARG2\n\
225 ARG1 > ARG2 ARG1 is greater than ARG2\n\
226 "), stdout);
227 fputs (_("\
229 ARG1 + ARG2 arithmetic sum of ARG1 and ARG2\n\
230 ARG1 - ARG2 arithmetic difference of ARG1 and ARG2\n\
231 "), stdout);
232 /* Tell xgettext that the "% A" below is not a printf-style
233 format string: xgettext:no-c-format */
234 fputs (_("\
236 ARG1 * ARG2 arithmetic product of ARG1 and ARG2\n\
237 ARG1 / ARG2 arithmetic quotient of ARG1 divided by ARG2\n\
238 ARG1 % ARG2 arithmetic remainder of ARG1 divided by ARG2\n\
239 "), stdout);
240 fputs (_("\
242 STRING : REGEXP anchored pattern match of REGEXP in STRING\n\
244 match STRING REGEXP same as STRING : REGEXP\n\
245 substr STRING POS LENGTH substring of STRING, POS counted from 1\n\
246 index STRING CHARS index in STRING where any CHARS is found, or 0\n\
247 length STRING length of STRING\n\
248 "), stdout);
249 fputs (_("\
250 + TOKEN interpret TOKEN as a string, even if it is a\n\
251 keyword like 'match' or an operator like '/'\n\
253 ( EXPRESSION ) value of EXPRESSION\n\
254 "), stdout);
255 fputs (_("\
257 Beware that many operators need to be escaped or quoted for shells.\n\
258 Comparisons are arithmetic if both ARGs are numbers, else lexicographical.\n\
259 Pattern matches return the string matched between \\( and \\) or null; if\n\
260 \\( and \\) are not used, they return the number of characters matched or 0.\n\
261 "), stdout);
262 fputs (_("\
264 Exit status is 0 if EXPRESSION is neither null nor 0, 1 if EXPRESSION is null\n\
265 or 0, 2 if EXPRESSION is syntactically invalid, and 3 if an error occurred.\n\
266 "), stdout);
267 emit_ancillary_info (PROGRAM_NAME);
269 exit (status);
272 /* Report a syntax error and exit. */
273 static void
274 syntax_error (void)
276 error (EXPR_INVALID, 0, _("syntax error"));
279 #if ! HAVE_GMP
280 /* Report an integer overflow for operation OP and exit. */
281 static void
282 integer_overflow (char op)
284 error (EXPR_FAILURE, ERANGE, "%c", op);
285 abort (); /* notreached */
287 #endif
290 main (int argc, char **argv)
292 VALUE *v;
294 initialize_main (&argc, &argv);
295 set_program_name (argv[0]);
296 setlocale (LC_ALL, "");
297 bindtextdomain (PACKAGE, LOCALEDIR);
298 textdomain (PACKAGE);
300 initialize_exit_failure (EXPR_FAILURE);
301 atexit (close_stdout);
303 parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, VERSION,
304 usage, AUTHORS, (char const *) NULL);
306 /* The above handles --help and --version.
307 Since there is no other invocation of getopt, handle '--' here. */
308 unsigned int u_argc = argc;
309 if (1 < u_argc && STREQ (argv[1], "--"))
311 --u_argc;
312 ++argv;
315 if (u_argc <= 1)
317 error (0, 0, _("missing operand"));
318 usage (EXPR_INVALID);
321 args = argv + 1;
323 v = eval (true);
324 if (!nomoreargs ())
325 syntax_error ();
326 printv (v);
328 return null (v);
331 /* Return a VALUE for I. */
333 static VALUE *
334 int_value (unsigned long int i)
336 VALUE *v = xmalloc (sizeof *v);
337 v->type = integer;
338 mpz_init_set_ui (v->u.i, i);
339 return v;
342 /* Return a VALUE for S. */
344 static VALUE *
345 str_value (char const *s)
347 VALUE *v = xmalloc (sizeof *v);
348 v->type = string;
349 v->u.s = xstrdup (s);
350 return v;
353 /* Free VALUE V, including structure components. */
355 static void
356 freev (VALUE *v)
358 if (v->type == string)
359 free (v->u.s);
360 else
361 mpz_clear (v->u.i);
362 free (v);
365 /* Print VALUE V. */
367 static void
368 printv (VALUE *v)
370 switch (v->type)
372 case integer:
373 mpz_out_str (stdout, 10, v->u.i);
374 putchar ('\n');
375 break;
376 case string:
377 puts (v->u.s);
378 break;
379 default:
380 abort ();
384 /* Return true if V is a null-string or zero-number. */
386 static bool _GL_ATTRIBUTE_PURE
387 null (VALUE *v)
389 switch (v->type)
391 case integer:
392 return mpz_sgn (v->u.i) == 0;
393 case string:
395 char const *cp = v->u.s;
396 if (*cp == '\0')
397 return true;
399 cp += (*cp == '-');
403 if (*cp != '0')
404 return false;
406 while (*++cp);
408 return true;
410 default:
411 abort ();
415 /* Return true if CP takes the form of an integer. */
417 static bool _GL_ATTRIBUTE_PURE
418 looks_like_integer (char const *cp)
420 cp += (*cp == '-');
423 if (! ISDIGIT (*cp))
424 return false;
425 while (*++cp);
427 return true;
430 /* Coerce V to a string value (can't fail). */
432 static void
433 tostring (VALUE *v)
435 switch (v->type)
437 case integer:
439 char *s = mpz_get_str (NULL, 10, v->u.i);
440 mpz_clear (v->u.i);
441 v->u.s = s;
442 v->type = string;
444 break;
445 case string:
446 break;
447 default:
448 abort ();
452 /* Coerce V to an integer value. Return true on success, false on failure. */
454 static bool
455 toarith (VALUE *v)
457 switch (v->type)
459 case integer:
460 return true;
461 case string:
463 char *s = v->u.s;
465 if (! looks_like_integer (s))
466 return false;
467 if (mpz_init_set_str (v->u.i, s, 10) != 0 && !HAVE_GMP)
468 error (EXPR_FAILURE, ERANGE, "%s", (s));
469 free (s);
470 v->type = integer;
471 return true;
473 default:
474 abort ();
478 /* Extract a size_t value from an integer value I.
479 If the value is negative, return SIZE_MAX.
480 If the value is too large, return SIZE_MAX - 1. */
481 static size_t
482 getsize (mpz_t i)
484 if (mpz_sgn (i) < 0)
485 return SIZE_MAX;
486 if (mpz_fits_ulong_p (i))
488 unsigned long int ul = mpz_get_ui (i);
489 if (ul < SIZE_MAX)
490 return ul;
492 return SIZE_MAX - 1;
495 /* Return true and advance if the next token matches STR exactly.
496 STR must not be NULL. */
498 static bool
499 nextarg (char const *str)
501 if (*args == NULL)
502 return false;
503 else
505 bool r = STREQ (*args, str);
506 args += r;
507 return r;
511 /* Return true if there no more tokens. */
513 static bool
514 nomoreargs (void)
516 return *args == 0;
519 #ifdef EVAL_TRACE
520 /* Print evaluation trace and args remaining. */
522 static void
523 trace (fxn)
524 char *fxn;
526 char **a;
528 printf ("%s:", fxn);
529 for (a = args; *a; a++)
530 printf (" %s", *a);
531 putchar ('\n');
533 #endif
535 /* Do the : operator.
536 SV is the VALUE for the lhs (the string),
537 PV is the VALUE for the rhs (the pattern). */
539 static VALUE *
540 docolon (VALUE *sv, VALUE *pv)
542 VALUE *v IF_LINT ( = NULL);
543 const char *errmsg;
544 struct re_pattern_buffer re_buffer;
545 char fastmap[UCHAR_MAX + 1];
546 struct re_registers re_regs;
547 regoff_t matchlen;
549 tostring (sv);
550 tostring (pv);
552 re_regs.num_regs = 0;
553 re_regs.start = NULL;
554 re_regs.end = NULL;
556 re_buffer.buffer = NULL;
557 re_buffer.allocated = 0;
558 re_buffer.fastmap = fastmap;
559 re_buffer.translate = NULL;
560 re_syntax_options =
561 RE_SYNTAX_POSIX_BASIC & ~RE_CONTEXT_INVALID_DUP & ~RE_NO_EMPTY_RANGES;
562 errmsg = re_compile_pattern (pv->u.s, strlen (pv->u.s), &re_buffer);
563 if (errmsg)
564 error (EXPR_INVALID, 0, "%s", (errmsg));
565 re_buffer.newline_anchor = 0;
567 matchlen = re_match (&re_buffer, sv->u.s, strlen (sv->u.s), 0, &re_regs);
568 if (0 <= matchlen)
570 /* Were \(...\) used? */
571 if (re_buffer.re_nsub > 0)
573 sv->u.s[re_regs.end[1]] = '\0';
574 v = str_value (sv->u.s + re_regs.start[1]);
576 else
577 v = int_value (matchlen);
579 else if (matchlen == -1)
581 /* Match failed -- return the right kind of null. */
582 if (re_buffer.re_nsub > 0)
583 v = str_value ("");
584 else
585 v = int_value (0);
587 else
588 error (EXPR_FAILURE,
589 (matchlen == -2 ? errno : EOVERFLOW),
590 _("error in regular expression matcher"));
592 if (0 < re_regs.num_regs)
594 free (re_regs.start);
595 free (re_regs.end);
597 re_buffer.fastmap = NULL;
598 regfree (&re_buffer);
599 return v;
602 /* Handle bare operands and ( expr ) syntax. */
604 static VALUE *
605 eval7 (bool evaluate)
607 VALUE *v;
609 #ifdef EVAL_TRACE
610 trace ("eval7");
611 #endif
612 if (nomoreargs ())
613 syntax_error ();
615 if (nextarg ("("))
617 v = eval (evaluate);
618 if (!nextarg (")"))
619 syntax_error ();
620 return v;
623 if (nextarg (")"))
624 syntax_error ();
626 return str_value (*args++);
629 /* Handle match, substr, index, and length keywords, and quoting "+". */
631 static VALUE *
632 eval6 (bool evaluate)
634 VALUE *l;
635 VALUE *r;
636 VALUE *v;
637 VALUE *i1;
638 VALUE *i2;
640 #ifdef EVAL_TRACE
641 trace ("eval6");
642 #endif
643 if (nextarg ("+"))
645 if (nomoreargs ())
646 syntax_error ();
647 return str_value (*args++);
649 else if (nextarg ("length"))
651 r = eval6 (evaluate);
652 tostring (r);
653 v = int_value (strlen (r->u.s));
654 freev (r);
655 return v;
657 else if (nextarg ("match"))
659 l = eval6 (evaluate);
660 r = eval6 (evaluate);
661 if (evaluate)
663 v = docolon (l, r);
664 freev (l);
666 else
667 v = l;
668 freev (r);
669 return v;
671 else if (nextarg ("index"))
673 size_t pos;
675 l = eval6 (evaluate);
676 r = eval6 (evaluate);
677 tostring (l);
678 tostring (r);
679 pos = strcspn (l->u.s, r->u.s);
680 v = int_value (l->u.s[pos] ? pos + 1 : 0);
681 freev (l);
682 freev (r);
683 return v;
685 else if (nextarg ("substr"))
687 size_t llen;
688 l = eval6 (evaluate);
689 i1 = eval6 (evaluate);
690 i2 = eval6 (evaluate);
691 tostring (l);
692 llen = strlen (l->u.s);
694 if (!toarith (i1) || !toarith (i2))
695 v = str_value ("");
696 else
698 size_t pos = getsize (i1->u.i);
699 size_t len = getsize (i2->u.i);
701 if (llen < pos || pos == 0 || len == 0 || len == SIZE_MAX)
702 v = str_value ("");
703 else
705 size_t vlen = MIN (len, llen - pos + 1);
706 char *vlim;
707 v = xmalloc (sizeof *v);
708 v->type = string;
709 v->u.s = xmalloc (vlen + 1);
710 vlim = mempcpy (v->u.s, l->u.s + pos - 1, vlen);
711 *vlim = '\0';
714 freev (l);
715 freev (i1);
716 freev (i2);
717 return v;
719 else
720 return eval7 (evaluate);
723 /* Handle : operator (pattern matching).
724 Calls docolon to do the real work. */
726 static VALUE *
727 eval5 (bool evaluate)
729 VALUE *l;
730 VALUE *r;
731 VALUE *v;
733 #ifdef EVAL_TRACE
734 trace ("eval5");
735 #endif
736 l = eval6 (evaluate);
737 while (1)
739 if (nextarg (":"))
741 r = eval6 (evaluate);
742 if (evaluate)
744 v = docolon (l, r);
745 freev (l);
746 l = v;
748 freev (r);
750 else
751 return l;
755 /* Handle *, /, % operators. */
757 static VALUE *
758 eval4 (bool evaluate)
760 VALUE *l;
761 VALUE *r;
762 enum { multiply, divide, mod } fxn;
764 #ifdef EVAL_TRACE
765 trace ("eval4");
766 #endif
767 l = eval5 (evaluate);
768 while (1)
770 if (nextarg ("*"))
771 fxn = multiply;
772 else if (nextarg ("/"))
773 fxn = divide;
774 else if (nextarg ("%"))
775 fxn = mod;
776 else
777 return l;
778 r = eval5 (evaluate);
779 if (evaluate)
781 if (!toarith (l) || !toarith (r))
782 error (EXPR_INVALID, 0, _("non-integer argument"));
783 if (fxn != multiply && mpz_sgn (r->u.i) == 0)
784 error (EXPR_INVALID, 0, _("division by zero"));
785 ((fxn == multiply ? mpz_mul
786 : fxn == divide ? mpz_tdiv_q
787 : mpz_tdiv_r)
788 (l->u.i, l->u.i, r->u.i));
790 freev (r);
794 /* Handle +, - operators. */
796 static VALUE *
797 eval3 (bool evaluate)
799 VALUE *l;
800 VALUE *r;
801 enum { plus, minus } fxn;
803 #ifdef EVAL_TRACE
804 trace ("eval3");
805 #endif
806 l = eval4 (evaluate);
807 while (1)
809 if (nextarg ("+"))
810 fxn = plus;
811 else if (nextarg ("-"))
812 fxn = minus;
813 else
814 return l;
815 r = eval4 (evaluate);
816 if (evaluate)
818 if (!toarith (l) || !toarith (r))
819 error (EXPR_INVALID, 0, _("non-integer argument"));
820 (fxn == plus ? mpz_add : mpz_sub) (l->u.i, l->u.i, r->u.i);
822 freev (r);
826 /* Handle comparisons. */
828 static VALUE *
829 eval2 (bool evaluate)
831 VALUE *l;
833 #ifdef EVAL_TRACE
834 trace ("eval2");
835 #endif
836 l = eval3 (evaluate);
837 while (1)
839 VALUE *r;
840 enum
842 less_than, less_equal, equal, not_equal, greater_equal, greater_than
843 } fxn;
844 bool val = false;
846 if (nextarg ("<"))
847 fxn = less_than;
848 else if (nextarg ("<="))
849 fxn = less_equal;
850 else if (nextarg ("=") || nextarg ("=="))
851 fxn = equal;
852 else if (nextarg ("!="))
853 fxn = not_equal;
854 else if (nextarg (">="))
855 fxn = greater_equal;
856 else if (nextarg (">"))
857 fxn = greater_than;
858 else
859 return l;
860 r = eval3 (evaluate);
862 if (evaluate)
864 int cmp;
865 tostring (l);
866 tostring (r);
868 if (looks_like_integer (l->u.s) && looks_like_integer (r->u.s))
869 cmp = strintcmp (l->u.s, r->u.s);
870 else
872 errno = 0;
873 cmp = strcoll (l->u.s, r->u.s);
875 if (errno)
877 error (0, errno, _("string comparison failed"));
878 error (0, 0, _("set LC_ALL='C' to work around the problem"));
879 error (EXPR_INVALID, 0,
880 _("the strings compared were %s and %s"),
881 quotearg_n_style (0, locale_quoting_style, l->u.s),
882 quotearg_n_style (1, locale_quoting_style, r->u.s));
886 switch (fxn)
888 case less_than: val = (cmp < 0); break;
889 case less_equal: val = (cmp <= 0); break;
890 case equal: val = (cmp == 0); break;
891 case not_equal: val = (cmp != 0); break;
892 case greater_equal: val = (cmp >= 0); break;
893 case greater_than: val = (cmp > 0); break;
894 default: abort ();
898 freev (l);
899 freev (r);
900 l = int_value (val);
904 /* Handle &. */
906 static VALUE *
907 eval1 (bool evaluate)
909 VALUE *l;
910 VALUE *r;
912 #ifdef EVAL_TRACE
913 trace ("eval1");
914 #endif
915 l = eval2 (evaluate);
916 while (1)
918 if (nextarg ("&"))
920 r = eval2 (evaluate && !null (l));
921 if (null (l) || null (r))
923 freev (l);
924 freev (r);
925 l = int_value (0);
927 else
928 freev (r);
930 else
931 return l;
935 /* Handle |. */
937 static VALUE *
938 eval (bool evaluate)
940 VALUE *l;
941 VALUE *r;
943 #ifdef EVAL_TRACE
944 trace ("eval");
945 #endif
946 l = eval1 (evaluate);
947 while (1)
949 if (nextarg ("|"))
951 r = eval1 (evaluate && null (l));
952 if (null (l))
954 freev (l);
955 l = r;
956 if (null (l))
958 freev (l);
959 l = int_value (0);
962 else
963 freev (r);
965 else
966 return l;