Modify 'expr' so that it uses intmax_t, not int, to calculate
[platform/upstream/coreutils.git] / src / expr.c
1 /* expr -- evaluate expressions.
2    Copyright (C) 86, 1991-1997, 1999, 2000 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
169   if (argc == 1)
170     {
171       error (0, 0, _("too few arguments"));
172       usage (1);
173     }
174
175   args = argv + 1;
176
177   v = eval ();
178   if (!nomoreargs ())
179     error (2, 0, _("syntax error"));
180   printv (v);
181
182   exit (null (v));
183 }
184
185 /* Return a VALUE for I.  */
186
187 static VALUE *
188 int_value (intmax_t i)
189 {
190   VALUE *v;
191
192   v = NEW (VALUE);
193   v->type = integer;
194   v->u.i = i;
195   return v;
196 }
197
198 /* Return a VALUE for S.  */
199
200 static VALUE *
201 str_value (char *s)
202 {
203   VALUE *v;
204
205   v = NEW (VALUE);
206   v->type = string;
207   v->u.s = xstrdup (s);
208   return v;
209 }
210
211 /* Free VALUE V, including structure components.  */
212
213 static void
214 freev (VALUE *v)
215 {
216   if (v->type == string)
217     free (v->u.s);
218   OLD (v);
219 }
220
221 /* Store a printable representation of I somewhere into BUF, and
222    return a pointer to the stored representation.  */
223
224 static char *
225 inttostr (intmax_t i, char buf[INT_STRLEN_BOUND (intmax_t) + 1])
226 {
227   uintmax_t ui = i;
228   char *p = buf + INT_STRLEN_BOUND (intmax_t);
229   *p = '\0';
230   if (i < 0)
231     ui = -ui;
232   do
233     *--p = '0' + ui % 10;
234   while ((ui /= 10) != 0);
235   if (i < 0)
236     *--p = '-';
237   return p;
238 }
239
240 /* Print VALUE V.  */
241
242 static void
243 printv (VALUE *v)
244 {
245   char *p;
246   char buf[INT_STRLEN_BOUND (intmax_t) + 1];
247
248   switch (v->type)
249     {
250     case integer:
251       p = inttostr (v->u.i, buf);
252       break;
253     case string:
254       p = v->u.s;
255       break;
256     default:
257       abort ();
258     }
259
260   puts (p);
261 }
262
263 /* Return nonzero if V is a null-string or zero-number.  */
264
265 static int
266 null (VALUE *v)
267 {
268   switch (v->type)
269     {
270     case integer:
271       return v->u.i == 0;
272     case string:
273       return v->u.s[0] == '\0' || strcmp (v->u.s, "0") == 0;
274     default:
275       abort ();
276     }
277 }
278
279 /* Return nonzero if V is a string value.  */
280
281 static int
282 isstring (VALUE *v)
283 {
284   return v->type == string;
285 }
286
287 /* Coerce V to a string value (can't fail).  */
288
289 static void
290 tostring (VALUE *v)
291 {
292   char buf[INT_STRLEN_BOUND (intmax_t) + 1];
293
294   switch (v->type)
295     {
296     case integer:
297       v->u.s = xstrdup (inttostr (v->u.i, buf));
298       v->type = string;
299       break;
300     case string:
301       break;
302     default:
303       abort ();
304     }
305 }
306
307 /* Coerce V to an integer value.  Return 1 on success, 0 on failure.  */
308
309 static int
310 toarith (VALUE *v)
311 {
312   intmax_t i;
313   int neg;
314   char *cp;
315
316   switch (v->type)
317     {
318     case integer:
319       return 1;
320     case string:
321       i = 0;
322       cp = v->u.s;
323       /* Don't interpret the empty string as an integer.  */
324       if (*cp == 0)
325         return 0;
326       neg = (*cp == '-');
327       if (neg)
328         cp++;
329       for (; *cp; cp++)
330         {
331           if (ISDIGIT (*cp))
332             i = i * 10 + *cp - '0';
333           else
334             return 0;
335         }
336       free (v->u.s);
337       v->u.i = i * (neg ? -1 : 1);
338       v->type = integer;
339       return 1;
340     default:
341       abort ();
342     }
343 }
344
345 /* Return nonzero if the next token matches STR exactly.
346    STR must not be NULL.  */
347
348 static int
349 nextarg (char *str)
350 {
351   if (*args == NULL)
352     return 0;
353   return strcmp (*args, str) == 0;
354 }
355
356 /* Return nonzero if there no more tokens.  */
357
358 static int
359 nomoreargs (void)
360 {
361   return *args == 0;
362 }
363
364 /* The comparison operator handling functions.  */
365
366 #define cmpf(name, rel)                         \
367 static                                          \
368 int name (l, r) VALUE *l; VALUE *r;             \
369 {                                               \
370   if (isstring (l) || isstring (r))             \
371     {                                           \
372        tostring (l);                            \
373        tostring (r);                            \
374        return strcmp (l->u.s, r->u.s) rel 0;    \
375     }                                           \
376  else                                           \
377    return l->u.i rel r->u.i;                    \
378 }
379  cmpf (less_than, <)
380  cmpf (less_equal, <=)
381  cmpf (equal, ==)
382  cmpf (not_equal, !=)
383  cmpf (greater_equal, >=)
384  cmpf (greater_than, >)
385
386 #undef cmpf
387
388 /* The arithmetic operator handling functions.  */
389
390 #define arithf(name, op)                        \
391 static intmax_t                                 \
392 name (l, r) VALUE *l; VALUE *r;                 \
393 {                                               \
394   if (!toarith (l) || !toarith (r))             \
395     error (2, 0, _("non-numeric argument"));    \
396   return l->u.i op r->u.i;                      \
397 }
398
399 #define arithdivf(name, op)                     \
400 static intmax_t                                 \
401 name (l, r) VALUE *l; VALUE *r;                 \
402 {                                               \
403   if (!toarith (l) || !toarith (r))             \
404     error (2, 0, _("non-numeric argument"));    \
405   if (r->u.i == 0)                              \
406     error (2, 0, _("division by zero"));        \
407   return l->u.i op r->u.i;                      \
408 }
409
410  arithf (plus, +)
411  arithf (minus, -)
412  arithf (multiply, *)
413  arithdivf (divide, /)
414  arithdivf (mod, %)
415
416 #undef arithf
417 #undef arithdivf
418
419 #ifdef EVAL_TRACE
420 /* Print evaluation trace and args remaining.  */
421
422 static void
423 trace (fxn)
424      char *fxn;
425 {
426   char **a;
427
428   printf ("%s:", fxn);
429   for (a = args; *a; a++)
430     printf (" %s", *a);
431   putchar ('\n');
432 }
433 #endif
434
435 /* Do the : operator.
436    SV is the VALUE for the lhs (the string),
437    PV is the VALUE for the rhs (the pattern).  */
438
439 static VALUE *
440 docolon (VALUE *sv, VALUE *pv)
441 {
442   VALUE *v;
443   const char *errmsg;
444   struct re_pattern_buffer re_buffer;
445   struct re_registers re_regs;
446   size_t len;
447   int matchlen;
448
449   tostring (sv);
450   tostring (pv);
451
452   if (pv->u.s[0] == '^')
453     {
454       error (0, 0, _("\
455 warning: unportable BRE: `%s': using `^' as the first character\n\
456 of the basic regular expression is not portable; it is being ignored"),
457              pv->u.s);
458     }
459
460   len = strlen (pv->u.s);
461   memset (&re_buffer, 0, sizeof (re_buffer));
462   memset (&re_regs, 0, sizeof (re_regs));
463   re_buffer.allocated = 2 * len;
464   if (re_buffer.allocated < len)
465     xalloc_die ();
466   re_buffer.buffer = (unsigned char *) xmalloc (re_buffer.allocated);
467   re_buffer.translate = 0;
468   re_syntax_options = RE_SYNTAX_POSIX_BASIC;
469   errmsg = re_compile_pattern (pv->u.s, len, &re_buffer);
470   if (errmsg)
471     error (2, 0, "%s", errmsg);
472
473   matchlen = re_match (&re_buffer, sv->u.s, strlen (sv->u.s), 0, &re_regs);
474   if (0 <= matchlen)
475     {
476       /* Were \(...\) used? */
477       if (re_buffer.re_nsub > 0)/* was (re_regs.start[1] >= 0) */
478         {
479           sv->u.s[re_regs.end[1]] = '\0';
480           v = str_value (sv->u.s + re_regs.start[1]);
481         }
482       else
483         v = int_value (matchlen);
484     }
485   else
486     {
487       /* Match failed -- return the right kind of null.  */
488       if (re_buffer.re_nsub > 0)
489         v = str_value ("");
490       else
491         v = int_value (0);
492     }
493   free (re_buffer.buffer);
494   return v;
495 }
496
497 /* Handle bare operands and ( expr ) syntax.  */
498
499 static VALUE *
500 eval7 (void)
501 {
502   VALUE *v;
503
504 #ifdef EVAL_TRACE
505   trace ("eval7");
506 #endif
507   if (nomoreargs ())
508     error (2, 0, _("syntax error"));
509
510   if (nextarg ("("))
511     {
512       args++;
513       v = eval ();
514       if (!nextarg (")"))
515         error (2, 0, _("syntax error"));
516       args++;
517       return v;
518     }
519
520   if (nextarg (")"))
521     error (2, 0, _("syntax error"));
522
523   return str_value (*args++);
524 }
525
526 /* Handle match, substr, index, length, and quote keywords.  */
527
528 static VALUE *
529 eval6 (void)
530 {
531   VALUE *l;
532   VALUE *r;
533   VALUE *v;
534   VALUE *i1;
535   VALUE *i2;
536
537 #ifdef EVAL_TRACE
538   trace ("eval6");
539 #endif
540   if (!posixly_correct && nextarg ("quote"))
541     {
542       args++;
543       if (nomoreargs ())
544         error (2, 0, _("syntax error"));
545       return str_value (*args++);
546     }
547   else if (nextarg ("length"))
548     {
549       args++;
550       r = eval6 ();
551       tostring (r);
552       v = int_value (strlen (r->u.s));
553       freev (r);
554       return v;
555     }
556   else if (nextarg ("match"))
557     {
558       args++;
559       l = eval6 ();
560       r = eval6 ();
561       v = docolon (l, r);
562       freev (l);
563       freev (r);
564       return v;
565     }
566   else if (nextarg ("index"))
567     {
568       args++;
569       l = eval6 ();
570       r = eval6 ();
571       tostring (l);
572       tostring (r);
573       v = int_value (strcspn (l->u.s, r->u.s) + 1);
574       if (v->u.i == strlen (l->u.s) + 1)
575         v->u.i = 0;
576       freev (l);
577       freev (r);
578       return v;
579     }
580   else if (nextarg ("substr"))
581     {
582       args++;
583       l = eval6 ();
584       i1 = eval6 ();
585       i2 = eval6 ();
586       tostring (l);
587       if (!toarith (i1) || !toarith (i2)
588           || strlen (l->u.s) < i1->u.i
589           || i1->u.i <= 0 || i2->u.i <= 0)
590         v = str_value ("");
591       else
592         {
593           v = NEW (VALUE);
594           v->type = string;
595           v->u.s = strncpy ((char *) xmalloc (i2->u.i + 1),
596                             l->u.s + i1->u.i - 1, i2->u.i);
597           v->u.s[i2->u.i] = 0;
598         }
599       freev (l);
600       freev (i1);
601       freev (i2);
602       return v;
603     }
604   else
605     return eval7 ();
606 }
607
608 /* Handle : operator (pattern matching).
609    Calls docolon to do the real work.  */
610
611 static VALUE *
612 eval5 (void)
613 {
614   VALUE *l;
615   VALUE *r;
616   VALUE *v;
617
618 #ifdef EVAL_TRACE
619   trace ("eval5");
620 #endif
621   l = eval6 ();
622   while (1)
623     {
624       if (nextarg (":"))
625         {
626           args++;
627           r = eval6 ();
628           v = docolon (l, r);
629           freev (l);
630           freev (r);
631           l = v;
632         }
633       else
634         return l;
635     }
636 }
637
638 /* Handle *, /, % operators.  */
639
640 static VALUE *
641 eval4 (void)
642 {
643   VALUE *l;
644   VALUE *r;
645   intmax_t (*fxn) ();
646   intmax_t val;
647
648 #ifdef EVAL_TRACE
649   trace ("eval4");
650 #endif
651   l = eval5 ();
652   while (1)
653     {
654       if (nextarg ("*"))
655         fxn = multiply;
656       else if (nextarg ("/"))
657         fxn = divide;
658       else if (nextarg ("%"))
659         fxn = mod;
660       else
661         return l;
662       args++;
663       r = eval5 ();
664       val = (*fxn) (l, r);
665       freev (l);
666       freev (r);
667       l = int_value (val);
668     }
669 }
670
671 /* Handle +, - operators.  */
672
673 static VALUE *
674 eval3 (void)
675 {
676   VALUE *l;
677   VALUE *r;
678   intmax_t (*fxn) ();
679   intmax_t val;
680
681 #ifdef EVAL_TRACE
682   trace ("eval3");
683 #endif
684   l = eval4 ();
685   while (1)
686     {
687       if (nextarg ("+"))
688         fxn = plus;
689       else if (nextarg ("-"))
690         fxn = minus;
691       else
692         return l;
693       args++;
694       r = eval4 ();
695       val = (*fxn) (l, r);
696       freev (l);
697       freev (r);
698       l = int_value (val);
699     }
700 }
701
702 /* Handle comparisons.  */
703
704 static VALUE *
705 eval2 (void)
706 {
707   VALUE *l;
708   VALUE *r;
709   int (*fxn) ();
710   int val;
711
712 #ifdef EVAL_TRACE
713   trace ("eval2");
714 #endif
715   l = eval3 ();
716   while (1)
717     {
718       if (nextarg ("<"))
719         fxn = less_than;
720       else if (nextarg ("<="))
721         fxn = less_equal;
722       else if (nextarg ("=") || nextarg ("=="))
723         fxn = equal;
724       else if (nextarg ("!="))
725         fxn = not_equal;
726       else if (nextarg (">="))
727         fxn = greater_equal;
728       else if (nextarg (">"))
729         fxn = greater_than;
730       else
731         return l;
732       args++;
733       r = eval3 ();
734       toarith (l);
735       toarith (r);
736       val = (*fxn) (l, r);
737       freev (l);
738       freev (r);
739       l = int_value (val);
740     }
741 }
742
743 /* Handle &.  */
744
745 static VALUE *
746 eval1 (void)
747 {
748   VALUE *l;
749   VALUE *r;
750
751 #ifdef EVAL_TRACE
752   trace ("eval1");
753 #endif
754   l = eval2 ();
755   while (1)
756     {
757       if (nextarg ("&"))
758         {
759           args++;
760           r = eval2 ();
761           if (null (l) || null (r))
762             {
763               freev (l);
764               freev (r);
765               l = int_value (0);
766             }
767           else
768             freev (r);
769         }
770       else
771         return l;
772     }
773 }
774
775 /* Handle |.  */
776
777 static VALUE *
778 eval (void)
779 {
780   VALUE *l;
781   VALUE *r;
782
783 #ifdef EVAL_TRACE
784   trace ("eval");
785 #endif
786   l = eval1 ();
787   while (1)
788     {
789       if (nextarg ("|"))
790         {
791           args++;
792           r = eval1 ();
793           if (null (l))
794             {
795               freev (l);
796               l = r;
797             }
798           else
799             freev (r);
800         }
801       else
802         return l;
803     }
804 }