Improve the check for departures from C89, and fix the departures
[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 const *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       size_t llen;
555       l = eval6 (evaluate);
556       i1 = eval6 (evaluate);
557       i2 = eval6 (evaluate);
558       tostring (l);
559       llen = strlen (l->u.s);
560       if (!toarith (i1) || !toarith (i2)
561           || llen < i1->u.i
562           || i1->u.i <= 0 || i2->u.i <= 0)
563         v = str_value ("");
564       else
565         {
566           size_t vlen = MIN (i2->u.i, llen - i1->u.i + 1);
567           char *vlim;
568           v = xmalloc (sizeof *v);
569           v->type = string;
570           v->u.s = xmalloc (vlen + 1);
571           vlim = mempcpy (v->u.s, l->u.s + i1->u.i - 1, vlen);
572           *vlim = '\0';
573         }
574       freev (l);
575       freev (i1);
576       freev (i2);
577       return v;
578     }
579   else
580     return eval7 (evaluate);
581 }
582
583 /* Handle : operator (pattern matching).
584    Calls docolon to do the real work.  */
585
586 static VALUE *
587 eval5 (bool evaluate)
588 {
589   VALUE *l;
590   VALUE *r;
591   VALUE *v;
592
593 #ifdef EVAL_TRACE
594   trace ("eval5");
595 #endif
596   l = eval6 (evaluate);
597   while (1)
598     {
599       if (nextarg (":"))
600         {
601           r = eval6 (evaluate);
602           if (evaluate)
603             {
604               v = docolon (l, r);
605               freev (l);
606               l = v;
607             }
608           freev (r);
609         }
610       else
611         return l;
612     }
613 }
614
615 /* Handle *, /, % operators.  */
616
617 static VALUE *
618 eval4 (bool evaluate)
619 {
620   VALUE *l;
621   VALUE *r;
622   enum { multiply, divide, mod } fxn;
623   intmax_t val = 0;
624
625 #ifdef EVAL_TRACE
626   trace ("eval4");
627 #endif
628   l = eval5 (evaluate);
629   while (1)
630     {
631       if (nextarg ("*"))
632         fxn = multiply;
633       else if (nextarg ("/"))
634         fxn = divide;
635       else if (nextarg ("%"))
636         fxn = mod;
637       else
638         return l;
639       r = eval5 (evaluate);
640       if (evaluate)
641         {
642           if (!toarith (l) || !toarith (r))
643             error (EXPR_INVALID, 0, _("non-numeric argument"));
644           if (fxn == multiply)
645             {
646               val = l->u.i * r->u.i;
647               if (! (l->u.i == 0 || r->u.i == 0
648                      || ((val < 0) == ((l->u.i < 0) ^ (r->u.i < 0))
649                          && val / l->u.i == r->u.i)))
650                 integer_overflow ('*');
651             }
652           else
653             {
654               if (r->u.i == 0)
655                 error (EXPR_INVALID, 0, _("division by zero"));
656               if (l->u.i < - INTMAX_MAX && r->u.i == -1)
657                 {
658                   /* Some x86-style hosts raise an exception for
659                      INT_MIN / -1 and INT_MIN % -1, so handle these
660                      problematic cases specially.  */
661                   if (fxn == divide)
662                     integer_overflow ('/');
663                   val = 0;
664                 }
665               else
666                 val = fxn == divide ? l->u.i / r->u.i : l->u.i % r->u.i;
667             }
668         }
669       freev (l);
670       freev (r);
671       l = int_value (val);
672     }
673 }
674
675 /* Handle +, - operators.  */
676
677 static VALUE *
678 eval3 (bool evaluate)
679 {
680   VALUE *l;
681   VALUE *r;
682   enum { plus, minus } fxn;
683   intmax_t val = 0;
684
685 #ifdef EVAL_TRACE
686   trace ("eval3");
687 #endif
688   l = eval4 (evaluate);
689   while (1)
690     {
691       if (nextarg ("+"))
692         fxn = plus;
693       else if (nextarg ("-"))
694         fxn = minus;
695       else
696         return l;
697       r = eval4 (evaluate);
698       if (evaluate)
699         {
700           if (!toarith (l) || !toarith (r))
701             error (EXPR_INVALID, 0, _("non-numeric argument"));
702           if (fxn == plus)
703             {
704               val = l->u.i + r->u.i;
705               if ((val < l->u.i) != (r->u.i < 0))
706                 integer_overflow ('+');
707             }
708           else
709             {
710               val = l->u.i - r->u.i;
711               if ((l->u.i < val) != (r->u.i < 0))
712                 integer_overflow ('-');
713             }
714         }
715       freev (l);
716       freev (r);
717       l = int_value (val);
718     }
719 }
720
721 /* Handle comparisons.  */
722
723 static VALUE *
724 eval2 (bool evaluate)
725 {
726   VALUE *l;
727
728 #ifdef EVAL_TRACE
729   trace ("eval2");
730 #endif
731   l = eval3 (evaluate);
732   while (1)
733     {
734       VALUE *r;
735       enum
736         {
737           less_than, less_equal, equal, not_equal, greater_equal, greater_than
738         } fxn;
739       bool val = false;
740
741       if (nextarg ("<"))
742         fxn = less_than;
743       else if (nextarg ("<="))
744         fxn = less_equal;
745       else if (nextarg ("=") || nextarg ("=="))
746         fxn = equal;
747       else if (nextarg ("!="))
748         fxn = not_equal;
749       else if (nextarg (">="))
750         fxn = greater_equal;
751       else if (nextarg (">"))
752         fxn = greater_than;
753       else
754         return l;
755       r = eval3 (evaluate);
756
757       if (evaluate)
758         {
759           int cmp;
760           tostring (l);
761           tostring (r);
762
763           if (looks_like_integer (l->u.s) && looks_like_integer (r->u.s))
764             cmp = strintcmp (l->u.s, r->u.s);
765           else
766             {
767               errno = 0;
768               cmp = strcoll (l->u.s, r->u.s);
769
770               if (errno)
771                 {
772                   error (0, errno, _("string comparison failed"));
773                   error (0, 0, _("Set LC_ALL='C' to work around the problem."));
774                   error (EXPR_INVALID, 0,
775                          _("The strings compared were %s and %s."),
776                          quotearg_n_style (0, locale_quoting_style, l->u.s),
777                          quotearg_n_style (1, locale_quoting_style, r->u.s));
778                 }
779             }
780
781           switch (fxn)
782             {
783             case less_than:     val = (cmp <  0); break;
784             case less_equal:    val = (cmp <= 0); break;
785             case equal:         val = (cmp == 0); break;
786             case not_equal:     val = (cmp != 0); break;
787             case greater_equal: val = (cmp >= 0); break;
788             case greater_than:  val = (cmp >  0); break;
789             default: abort ();
790             }
791         }
792
793       freev (l);
794       freev (r);
795       l = int_value (val);
796     }
797 }
798
799 /* Handle &.  */
800
801 static VALUE *
802 eval1 (bool evaluate)
803 {
804   VALUE *l;
805   VALUE *r;
806
807 #ifdef EVAL_TRACE
808   trace ("eval1");
809 #endif
810   l = eval2 (evaluate);
811   while (1)
812     {
813       if (nextarg ("&"))
814         {
815           r = eval2 (evaluate & ~ null (l));
816           if (null (l) || null (r))
817             {
818               freev (l);
819               freev (r);
820               l = int_value (0);
821             }
822           else
823             freev (r);
824         }
825       else
826         return l;
827     }
828 }
829
830 /* Handle |.  */
831
832 static VALUE *
833 eval (bool evaluate)
834 {
835   VALUE *l;
836   VALUE *r;
837
838 #ifdef EVAL_TRACE
839   trace ("eval");
840 #endif
841   l = eval1 (evaluate);
842   while (1)
843     {
844       if (nextarg ("|"))
845         {
846           r = eval1 (evaluate & null (l));
847           if (null (l))
848             {
849               freev (l);
850               l = r;
851               if (null (l))
852                 {
853                   freev (l);
854                   l = int_value (0);
855                 }
856             }
857           else
858             freev (r);
859         }
860       else
861         return l;
862     }
863 }