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