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