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