(eval4): Detect overflow properly when multiplying INTMAX_MIN * -1.
[platform/upstream/coreutils.git] / src / expr.c
1 /* expr -- evaluate expressions.
2    Copyright (C) 86, 1991-1997, 1999-2006 Free Software Foundation, Inc.
3
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.
8
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.
13
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
17
18 /* Author: Mike Parker.
19
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.
24
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).
28
29    Define EVAL_TRACE to print an evaluation trace.  */
30
31 #include <config.h>
32 #include <stdio.h>
33 #include <sys/types.h>
34 #include "system.h"
35
36 #include <regex.h>
37 #include "long-options.h"
38 #include "error.h"
39 #include "inttostr.h"
40 #include "quote.h"
41 #include "quotearg.h"
42 #include "strnumcmp.h"
43 #include "xstrtol.h"
44
45 /* The official name of this program (e.g., no `g' prefix).  */
46 #define PROGRAM_NAME "expr"
47
48 #define AUTHORS "Mike Parker"
49
50 /* Exit statuses.  */
51 enum
52   {
53     /* Invalid expression: e.g., its form does not conform to the
54        grammar for expressions.  Our grammar is an extension of the
55        POSIX grammar.  */
56     EXPR_INVALID = 2,
57
58     /* An internal error occurred, e.g., arithmetic overflow, storage
59        exhaustion.  */
60     EXPR_FAILURE
61   };
62
63 /* The kinds of value we can have.  */
64 enum valtype
65 {
66   integer,
67   string
68 };
69 typedef enum valtype TYPE;
70
71 /* A value is.... */
72 struct valinfo
73 {
74   TYPE type;                    /* Which kind. */
75   union
76   {                             /* The value itself. */
77     intmax_t i;
78     char *s;
79   } u;
80 };
81 typedef struct valinfo VALUE;
82
83 /* The arguments given to the program, minus the program name.  */
84 static char **args;
85
86 /* The name this program was run with. */
87 char *program_name;
88
89 static VALUE *eval (bool);
90 static bool nomoreargs (void);
91 static bool null (VALUE *v);
92 static void printv (VALUE *v);
93
94 void
95 usage (int status)
96 {
97   if (status != EXIT_SUCCESS)
98     fprintf (stderr, _("Try `%s --help' for more information.\n"),
99              program_name);
100   else
101     {
102       printf (_("\
103 Usage: %s EXPRESSION\n\
104   or:  %s OPTION\n\
105 "),
106               program_name, program_name);
107       putchar ('\n');
108       fputs (HELP_OPTION_DESCRIPTION, stdout);
109       fputs (VERSION_OPTION_DESCRIPTION, stdout);
110       fputs (_("\
111 \n\
112 Print the value of EXPRESSION to standard output.  A blank line below\n\
113 separates increasing precedence groups.  EXPRESSION may be:\n\
114 \n\
115   ARG1 | ARG2       ARG1 if it is neither null nor 0, otherwise ARG2\n\
116 \n\
117   ARG1 & ARG2       ARG1 if neither argument is null or 0, otherwise 0\n\
118 "), stdout);
119       fputs (_("\
120 \n\
121   ARG1 < ARG2       ARG1 is less than ARG2\n\
122   ARG1 <= ARG2      ARG1 is less than or equal to ARG2\n\
123   ARG1 = ARG2       ARG1 is equal to ARG2\n\
124   ARG1 != ARG2      ARG1 is unequal to ARG2\n\
125   ARG1 >= ARG2      ARG1 is greater than or equal to ARG2\n\
126   ARG1 > ARG2       ARG1 is greater than ARG2\n\
127 "), stdout);
128       fputs (_("\
129 \n\
130   ARG1 + ARG2       arithmetic sum of ARG1 and ARG2\n\
131   ARG1 - ARG2       arithmetic difference of ARG1 and ARG2\n\
132 "), stdout);
133       fputs (_("\
134 \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\
138 "), stdout);
139       fputs (_("\
140 \n\
141   STRING : REGEXP   anchored pattern match of REGEXP in STRING\n\
142 \n\
143   match STRING REGEXP        same as STRING : REGEXP\n\
144   substr STRING POS LENGTH   substring of STRING, POS counted from 1\n\
145   index STRING CHARS         index in STRING where any CHARS is found, or 0\n\
146   length STRING              length of STRING\n\
147 "), stdout);
148       fputs (_("\
149   + TOKEN                    interpret TOKEN as a string, even if it is a\n\
150                                keyword like `match' or an operator like `/'\n\
151 \n\
152   ( EXPRESSION )             value of EXPRESSION\n\
153 "), stdout);
154       fputs (_("\
155 \n\
156 Beware that many operators need to be escaped or quoted for shells.\n\
157 Comparisons are arithmetic if both ARGs are numbers, else lexicographical.\n\
158 Pattern matches return the string matched between \\( and \\) or null; if\n\
159 \\( and \\) are not used, they return the number of characters matched or 0.\n\
160 "), stdout);
161       fputs (_("\
162 \n\
163 Exit status is 0 if EXPRESSION is neither null nor 0, 1 if EXPRESSION is null\n\
164 or 0, 2 if EXPRESSION is syntactically invalid, and 3 if an error occurred.\n\
165 "), stdout);
166       printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
167     }
168   exit (status);
169 }
170
171 /* Report a syntax error and exit.  */
172 static void
173 syntax_error (void)
174 {
175   error (EXPR_INVALID, 0, _("syntax error"));
176 }
177
178 /* Report an integer overflow for operation OP and exit.  */
179 static void
180 integer_overflow (char op)
181 {
182   error (EXPR_FAILURE, ERANGE, "%c", op);
183 }
184
185 int
186 main (int argc, char **argv)
187 {
188   VALUE *v;
189
190   initialize_main (&argc, &argv);
191   program_name = argv[0];
192   setlocale (LC_ALL, "");
193   bindtextdomain (PACKAGE, LOCALEDIR);
194   textdomain (PACKAGE);
195
196   initialize_exit_failure (EXPR_FAILURE);
197   atexit (close_stdout);
198
199   parse_long_options (argc, argv, PROGRAM_NAME, GNU_PACKAGE, VERSION,
200                       usage, AUTHORS, (char const *) NULL);
201   /* The above handles --help and --version.
202      Since there is no other invocation of getopt, handle `--' here.  */
203   if (argc > 1 && STREQ (argv[1], "--"))
204     {
205       --argc;
206       ++argv;
207     }
208
209   if (argc <= 1)
210     {
211       error (0, 0, _("missing operand"));
212       usage (EXPR_INVALID);
213     }
214
215   args = argv + 1;
216
217   v = eval (true);
218   if (!nomoreargs ())
219     syntax_error ();
220   printv (v);
221
222   exit (null (v));
223 }
224
225 /* Return a VALUE for I.  */
226
227 static VALUE *
228 int_value (intmax_t i)
229 {
230   VALUE *v = xmalloc (sizeof *v);
231   v->type = integer;
232   v->u.i = i;
233   return v;
234 }
235
236 /* Return a VALUE for S.  */
237
238 static VALUE *
239 str_value (char *s)
240 {
241   VALUE *v = xmalloc (sizeof *v);
242   v->type = string;
243   v->u.s = xstrdup (s);
244   return v;
245 }
246
247 /* Free VALUE V, including structure components.  */
248
249 static void
250 freev (VALUE *v)
251 {
252   if (v->type == string)
253     free (v->u.s);
254   free (v);
255 }
256
257 /* Print VALUE V.  */
258
259 static void
260 printv (VALUE *v)
261 {
262   char *p;
263   char buf[INT_BUFSIZE_BOUND (intmax_t)];
264
265   switch (v->type)
266     {
267     case integer:
268       p = imaxtostr (v->u.i, buf);
269       break;
270     case string:
271       p = v->u.s;
272       break;
273     default:
274       abort ();
275     }
276
277   puts (p);
278 }
279
280 /* Return true if V is a null-string or zero-number.  */
281
282 static bool
283 null (VALUE *v)
284 {
285   switch (v->type)
286     {
287     case integer:
288       return v->u.i == 0;
289     case string:
290       {
291         char const *cp = v->u.s;
292         if (*cp == '\0')
293           return true;
294
295         cp += (*cp == '-');
296
297         do
298           {
299             if (*cp != '0')
300               return false;
301           }
302         while (*++cp);
303
304         return true;
305       }
306     default:
307       abort ();
308     }
309 }
310
311 /* Return true if CP takes the form of an integer.  */
312
313 static bool
314 looks_like_integer (char const *cp)
315 {
316   cp += (*cp == '-');
317
318   do
319     if (! ISDIGIT (*cp))
320       return false;
321   while (*++cp);
322
323   return true;
324 }
325
326 /* Coerce V to a string value (can't fail).  */
327
328 static void
329 tostring (VALUE *v)
330 {
331   char buf[INT_BUFSIZE_BOUND (intmax_t)];
332
333   switch (v->type)
334     {
335     case integer:
336       v->u.s = xstrdup (imaxtostr (v->u.i, buf));
337       v->type = string;
338       break;
339     case string:
340       break;
341     default:
342       abort ();
343     }
344 }
345
346 /* Coerce V to an integer value.  Return true on success, false on failure.  */
347
348 static bool
349 toarith (VALUE *v)
350 {
351   switch (v->type)
352     {
353     case integer:
354       return true;
355     case string:
356       {
357         intmax_t value;
358
359         if (! looks_like_integer (v->u.s))
360           return false;
361         if (xstrtoimax (v->u.s, NULL, 10, &value, NULL) != LONGINT_OK)
362           error (EXPR_FAILURE, ERANGE, "%s", v->u.s);
363         free (v->u.s);
364         v->u.i = value;
365         v->type = integer;
366         return true;
367       }
368     default:
369       abort ();
370     }
371 }
372
373 /* Return true and advance if the next token matches STR exactly.
374    STR must not be NULL.  */
375
376 static bool
377 nextarg (char const *str)
378 {
379   if (*args == NULL)
380     return false;
381   else
382     {
383       bool r = STREQ (*args, str);
384       args += r;
385       return r;
386     }
387 }
388
389 /* Return true if there no more tokens.  */
390
391 static bool
392 nomoreargs (void)
393 {
394   return *args == 0;
395 }
396
397 #ifdef EVAL_TRACE
398 /* Print evaluation trace and args remaining.  */
399
400 static void
401 trace (fxn)
402      char *fxn;
403 {
404   char **a;
405
406   printf ("%s:", fxn);
407   for (a = args; *a; a++)
408     printf (" %s", *a);
409   putchar ('\n');
410 }
411 #endif
412
413 /* Do the : operator.
414    SV is the VALUE for the lhs (the string),
415    PV is the VALUE for the rhs (the pattern).  */
416
417 static VALUE *
418 docolon (VALUE *sv, VALUE *pv)
419 {
420   VALUE *v IF_LINT (= NULL);
421   const char *errmsg;
422   struct re_pattern_buffer re_buffer;
423   char fastmap[UCHAR_MAX + 1];
424   struct re_registers re_regs;
425   regoff_t matchlen;
426
427   tostring (sv);
428   tostring (pv);
429
430   re_buffer.buffer = NULL;
431   re_buffer.allocated = 0;
432   re_buffer.fastmap = fastmap;
433   re_buffer.translate = NULL;
434   re_syntax_options =
435     RE_SYNTAX_POSIX_BASIC & ~RE_CONTEXT_INVALID_DUP & ~RE_NO_EMPTY_RANGES;
436   errmsg = re_compile_pattern (pv->u.s, strlen (pv->u.s), &re_buffer);
437   if (errmsg)
438     error (EXPR_INVALID, 0, "%s", errmsg);
439   re_buffer.newline_anchor = 0;
440
441   matchlen = re_match (&re_buffer, sv->u.s, strlen (sv->u.s), 0, &re_regs);
442   if (0 <= matchlen)
443     {
444       /* Were \(...\) used? */
445       if (re_buffer.re_nsub > 0)
446         {
447           sv->u.s[re_regs.end[1]] = '\0';
448           v = str_value (sv->u.s + re_regs.start[1]);
449         }
450       else
451         v = int_value (matchlen);
452     }
453   else if (matchlen == -1)
454     {
455       /* Match failed -- return the right kind of null.  */
456       if (re_buffer.re_nsub > 0)
457         v = str_value ("");
458       else
459         v = int_value (0);
460     }
461   else
462     error (EXPR_FAILURE,
463            (matchlen == -2 ? errno : EOVERFLOW),
464            _("error in regular expression matcher"));
465
466   free (re_buffer.buffer);
467   return v;
468 }
469
470 /* Handle bare operands and ( expr ) syntax.  */
471
472 static VALUE *
473 eval7 (bool evaluate)
474 {
475   VALUE *v;
476
477 #ifdef EVAL_TRACE
478   trace ("eval7");
479 #endif
480   if (nomoreargs ())
481     syntax_error ();
482
483   if (nextarg ("("))
484     {
485       v = eval (evaluate);
486       if (!nextarg (")"))
487         syntax_error ();
488       return v;
489     }
490
491   if (nextarg (")"))
492     syntax_error ();
493
494   return str_value (*args++);
495 }
496
497 /* Handle match, substr, index, and length keywords, and quoting "+".  */
498
499 static VALUE *
500 eval6 (bool evaluate)
501 {
502   VALUE *l;
503   VALUE *r;
504   VALUE *v;
505   VALUE *i1;
506   VALUE *i2;
507
508 #ifdef EVAL_TRACE
509   trace ("eval6");
510 #endif
511   if (nextarg ("+"))
512     {
513       if (nomoreargs ())
514         syntax_error ();
515       return str_value (*args++);
516     }
517   else if (nextarg ("length"))
518     {
519       r = eval6 (evaluate);
520       tostring (r);
521       v = int_value (strlen (r->u.s));
522       freev (r);
523       return v;
524     }
525   else if (nextarg ("match"))
526     {
527       l = eval6 (evaluate);
528       r = eval6 (evaluate);
529       if (evaluate)
530         {
531           v = docolon (l, r);
532           freev (l);
533         }
534       else
535         v = l;
536       freev (r);
537       return v;
538     }
539   else if (nextarg ("index"))
540     {
541       l = eval6 (evaluate);
542       r = eval6 (evaluate);
543       tostring (l);
544       tostring (r);
545       v = int_value (strcspn (l->u.s, r->u.s) + 1);
546       if (v->u.i == strlen (l->u.s) + 1)
547         v->u.i = 0;
548       freev (l);
549       freev (r);
550       return v;
551     }
552   else if (nextarg ("substr"))
553     {
554       l = eval6 (evaluate);
555       i1 = eval6 (evaluate);
556       i2 = eval6 (evaluate);
557       tostring (l);
558       if (!toarith (i1) || !toarith (i2)
559           || strlen (l->u.s) < i1->u.i
560           || i1->u.i <= 0 || i2->u.i <= 0)
561         v = str_value ("");
562       else
563         {
564           v = xmalloc (sizeof *v);
565           v->type = string;
566           v->u.s = strncpy (xmalloc (i2->u.i + 1),
567                             l->u.s + i1->u.i - 1, i2->u.i);
568           v->u.s[i2->u.i] = 0;
569         }
570       freev (l);
571       freev (i1);
572       freev (i2);
573       return v;
574     }
575   else
576     return eval7 (evaluate);
577 }
578
579 /* Handle : operator (pattern matching).
580    Calls docolon to do the real work.  */
581
582 static VALUE *
583 eval5 (bool evaluate)
584 {
585   VALUE *l;
586   VALUE *r;
587   VALUE *v;
588
589 #ifdef EVAL_TRACE
590   trace ("eval5");
591 #endif
592   l = eval6 (evaluate);
593   while (1)
594     {
595       if (nextarg (":"))
596         {
597           r = eval6 (evaluate);
598           if (evaluate)
599             {
600               v = docolon (l, r);
601               freev (l);
602               l = v;
603             }
604           freev (r);
605         }
606       else
607         return l;
608     }
609 }
610
611 /* Handle *, /, % operators.  */
612
613 static VALUE *
614 eval4 (bool evaluate)
615 {
616   VALUE *l;
617   VALUE *r;
618   enum { multiply, divide, mod } fxn;
619   intmax_t val = 0;
620
621 #ifdef EVAL_TRACE
622   trace ("eval4");
623 #endif
624   l = eval5 (evaluate);
625   while (1)
626     {
627       if (nextarg ("*"))
628         fxn = multiply;
629       else if (nextarg ("/"))
630         fxn = divide;
631       else if (nextarg ("%"))
632         fxn = mod;
633       else
634         return l;
635       r = eval5 (evaluate);
636       if (evaluate)
637         {
638           if (!toarith (l) || !toarith (r))
639             error (EXPR_INVALID, 0, _("non-numeric argument"));
640           if (fxn == multiply)
641             {
642               val = l->u.i * r->u.i;
643               if (! (l->u.i == 0 || r->u.i == 0
644                      || ((val < 0) == ((l->u.i < 0) ^ (r->u.i < 0))
645                          && val / l->u.i == r->u.i)))
646                 integer_overflow ('*');
647             }
648           else
649             {
650               if (r->u.i == 0)
651                 error (EXPR_INVALID, 0, _("division by zero"));
652               if (l->u.i < - INTMAX_MAX && r->u.i == -1)
653                 {
654                   /* Some x86-style hosts raise an exception for
655                      INT_MIN / -1 and INT_MIN % -1, so handle these
656                      problematic cases specially.  */
657                   if (fxn == divide)
658                     integer_overflow ('/');
659                   val = 0;
660                 }
661               else
662                 val = fxn == divide ? l->u.i / r->u.i : l->u.i % r->u.i;
663             }
664         }
665       freev (l);
666       freev (r);
667       l = int_value (val);
668     }
669 }
670
671 /* Handle +, - operators.  */
672
673 static VALUE *
674 eval3 (bool evaluate)
675 {
676   VALUE *l;
677   VALUE *r;
678   enum { plus, minus } fxn;
679   intmax_t val = 0;
680
681 #ifdef EVAL_TRACE
682   trace ("eval3");
683 #endif
684   l = eval4 (evaluate);
685   while (1)
686     {
687       if (nextarg ("+"))
688         fxn = plus;
689       else if (nextarg ("-"))
690         fxn = minus;
691       else
692         return l;
693       r = eval4 (evaluate);
694       if (evaluate)
695         {
696           if (!toarith (l) || !toarith (r))
697             error (EXPR_INVALID, 0, _("non-numeric argument"));
698           if (fxn == plus)
699             {
700               val = l->u.i + r->u.i;
701               if ((val < l->u.i) != (r->u.i < 0))
702                 integer_overflow ('+');
703             }
704           else
705             {
706               val = l->u.i - r->u.i;
707               if ((l->u.i < val) != (r->u.i < 0))
708                 integer_overflow ('-');
709             }
710         }
711       freev (l);
712       freev (r);
713       l = int_value (val);
714     }
715 }
716
717 /* Handle comparisons.  */
718
719 static VALUE *
720 eval2 (bool evaluate)
721 {
722   VALUE *l;
723
724 #ifdef EVAL_TRACE
725   trace ("eval2");
726 #endif
727   l = eval3 (evaluate);
728   while (1)
729     {
730       VALUE *r;
731       enum
732         {
733           less_than, less_equal, equal, not_equal, greater_equal, greater_than
734         } fxn;
735       bool val = false;
736
737       if (nextarg ("<"))
738         fxn = less_than;
739       else if (nextarg ("<="))
740         fxn = less_equal;
741       else if (nextarg ("=") || nextarg ("=="))
742         fxn = equal;
743       else if (nextarg ("!="))
744         fxn = not_equal;
745       else if (nextarg (">="))
746         fxn = greater_equal;
747       else if (nextarg (">"))
748         fxn = greater_than;
749       else
750         return l;
751       r = eval3 (evaluate);
752
753       if (evaluate)
754         {
755           int cmp;
756           tostring (l);
757           tostring (r);
758
759           if (looks_like_integer (l->u.s) && looks_like_integer (r->u.s))
760             cmp = strintcmp (l->u.s, r->u.s);
761           else
762             {
763               errno = 0;
764               cmp = strcoll (l->u.s, r->u.s);
765
766               if (errno)
767                 {
768                   error (0, errno, _("string comparison failed"));
769                   error (0, 0, _("Set LC_ALL='C' to work around the problem."));
770                   error (EXPR_INVALID, 0,
771                          _("The strings compared were %s and %s."),
772                          quotearg_n_style (0, locale_quoting_style, l->u.s),
773                          quotearg_n_style (1, locale_quoting_style, r->u.s));
774                 }
775             }
776
777           switch (fxn)
778             {
779             case less_than:     val = (cmp <  0); break;
780             case less_equal:    val = (cmp <= 0); break;
781             case equal:         val = (cmp == 0); break;
782             case not_equal:     val = (cmp != 0); break;
783             case greater_equal: val = (cmp >= 0); break;
784             case greater_than:  val = (cmp >  0); break;
785             default: abort ();
786             }
787         }
788
789       freev (l);
790       freev (r);
791       l = int_value (val);
792     }
793 }
794
795 /* Handle &.  */
796
797 static VALUE *
798 eval1 (bool evaluate)
799 {
800   VALUE *l;
801   VALUE *r;
802
803 #ifdef EVAL_TRACE
804   trace ("eval1");
805 #endif
806   l = eval2 (evaluate);
807   while (1)
808     {
809       if (nextarg ("&"))
810         {
811           r = eval2 (evaluate & ~ null (l));
812           if (null (l) || null (r))
813             {
814               freev (l);
815               freev (r);
816               l = int_value (0);
817             }
818           else
819             freev (r);
820         }
821       else
822         return l;
823     }
824 }
825
826 /* Handle |.  */
827
828 static VALUE *
829 eval (bool evaluate)
830 {
831   VALUE *l;
832   VALUE *r;
833
834 #ifdef EVAL_TRACE
835   trace ("eval");
836 #endif
837   l = eval1 (evaluate);
838   while (1)
839     {
840       if (nextarg ("|"))
841         {
842           r = eval1 (evaluate & null (l));
843           if (null (l))
844             {
845               freev (l);
846               l = r;
847               if (null (l))
848                 {
849                   freev (l);
850                   l = int_value (0);
851                 }
852             }
853           else
854             freev (r);
855         }
856       else
857         return l;
858     }
859 }