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