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