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