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