(isstring): Remove.
[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 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   return strcmp (*args, str) == 0;
353 }
354
355 /* Return nonzero if there no more tokens.  */
356
357 static int
358 nomoreargs (void)
359 {
360   return *args == 0;
361 }
362
363 #ifdef EVAL_TRACE
364 /* Print evaluation trace and args remaining.  */
365
366 static void
367 trace (fxn)
368      char *fxn;
369 {
370   char **a;
371
372   printf ("%s:", fxn);
373   for (a = args; *a; a++)
374     printf (" %s", *a);
375   putchar ('\n');
376 }
377 #endif
378
379 /* Do the : operator.
380    SV is the VALUE for the lhs (the string),
381    PV is the VALUE for the rhs (the pattern).  */
382
383 static VALUE *
384 docolon (VALUE *sv, VALUE *pv)
385 {
386   VALUE *v;
387   const char *errmsg;
388   struct re_pattern_buffer re_buffer;
389   struct re_registers re_regs;
390   size_t len;
391   int matchlen;
392
393   tostring (sv);
394   tostring (pv);
395
396   if (pv->u.s[0] == '^')
397     {
398       error (0, 0, _("\
399 warning: unportable BRE: `%s': using `^' as the first character\n\
400 of the basic regular expression is not portable; it is being ignored"),
401              pv->u.s);
402     }
403
404   len = strlen (pv->u.s);
405   memset (&re_buffer, 0, sizeof (re_buffer));
406   memset (&re_regs, 0, sizeof (re_regs));
407   re_buffer.allocated = 2 * len;
408   if (re_buffer.allocated < len)
409     xalloc_die ();
410   re_buffer.buffer = (unsigned char *) xmalloc (re_buffer.allocated);
411   re_buffer.translate = 0;
412   re_syntax_options = RE_SYNTAX_POSIX_BASIC;
413   errmsg = re_compile_pattern (pv->u.s, len, &re_buffer);
414   if (errmsg)
415     error (2, 0, "%s", errmsg);
416
417   matchlen = re_match (&re_buffer, sv->u.s, strlen (sv->u.s), 0, &re_regs);
418   if (0 <= matchlen)
419     {
420       /* Were \(...\) used? */
421       if (re_buffer.re_nsub > 0)/* was (re_regs.start[1] >= 0) */
422         {
423           sv->u.s[re_regs.end[1]] = '\0';
424           v = str_value (sv->u.s + re_regs.start[1]);
425         }
426       else
427         v = int_value (matchlen);
428     }
429   else
430     {
431       /* Match failed -- return the right kind of null.  */
432       if (re_buffer.re_nsub > 0)
433         v = str_value ("");
434       else
435         v = int_value (0);
436     }
437   free (re_buffer.buffer);
438   return v;
439 }
440
441 /* Handle bare operands and ( expr ) syntax.  */
442
443 static VALUE *
444 eval7 (void)
445 {
446   VALUE *v;
447
448 #ifdef EVAL_TRACE
449   trace ("eval7");
450 #endif
451   if (nomoreargs ())
452     error (2, 0, _("syntax error"));
453
454   if (nextarg ("("))
455     {
456       args++;
457       v = eval ();
458       if (!nextarg (")"))
459         error (2, 0, _("syntax error"));
460       args++;
461       return v;
462     }
463
464   if (nextarg (")"))
465     error (2, 0, _("syntax error"));
466
467   return str_value (*args++);
468 }
469
470 /* Handle match, substr, index, length, and quote keywords.  */
471
472 static VALUE *
473 eval6 (void)
474 {
475   VALUE *l;
476   VALUE *r;
477   VALUE *v;
478   VALUE *i1;
479   VALUE *i2;
480
481 #ifdef EVAL_TRACE
482   trace ("eval6");
483 #endif
484   if (!posixly_correct && nextarg ("quote"))
485     {
486       args++;
487       if (nomoreargs ())
488         error (2, 0, _("syntax error"));
489       return str_value (*args++);
490     }
491   else if (nextarg ("length"))
492     {
493       args++;
494       r = eval6 ();
495       tostring (r);
496       v = int_value (strlen (r->u.s));
497       freev (r);
498       return v;
499     }
500   else if (nextarg ("match"))
501     {
502       args++;
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       args++;
513       l = eval6 ();
514       r = eval6 ();
515       tostring (l);
516       tostring (r);
517       v = int_value (strcspn (l->u.s, r->u.s) + 1);
518       if (v->u.i == strlen (l->u.s) + 1)
519         v->u.i = 0;
520       freev (l);
521       freev (r);
522       return v;
523     }
524   else if (nextarg ("substr"))
525     {
526       args++;
527       l = eval6 ();
528       i1 = eval6 ();
529       i2 = eval6 ();
530       tostring (l);
531       if (!toarith (i1) || !toarith (i2)
532           || strlen (l->u.s) < i1->u.i
533           || i1->u.i <= 0 || i2->u.i <= 0)
534         v = str_value ("");
535       else
536         {
537           v = NEW (VALUE);
538           v->type = string;
539           v->u.s = strncpy ((char *) xmalloc (i2->u.i + 1),
540                             l->u.s + i1->u.i - 1, i2->u.i);
541           v->u.s[i2->u.i] = 0;
542         }
543       freev (l);
544       freev (i1);
545       freev (i2);
546       return v;
547     }
548   else
549     return eval7 ();
550 }
551
552 /* Handle : operator (pattern matching).
553    Calls docolon to do the real work.  */
554
555 static VALUE *
556 eval5 (void)
557 {
558   VALUE *l;
559   VALUE *r;
560   VALUE *v;
561
562 #ifdef EVAL_TRACE
563   trace ("eval5");
564 #endif
565   l = eval6 ();
566   while (1)
567     {
568       if (nextarg (":"))
569         {
570           args++;
571           r = eval6 ();
572           v = docolon (l, r);
573           freev (l);
574           freev (r);
575           l = v;
576         }
577       else
578         return l;
579     }
580 }
581
582 /* Handle *, /, % operators.  */
583
584 static VALUE *
585 eval4 (void)
586 {
587   VALUE *l;
588   VALUE *r;
589   enum { multiply, divide, mod } fxn;
590   intmax_t val;
591
592 #ifdef EVAL_TRACE
593   trace ("eval4");
594 #endif
595   l = eval5 ();
596   while (1)
597     {
598       if (nextarg ("*"))
599         fxn = multiply;
600       else if (nextarg ("/"))
601         fxn = divide;
602       else if (nextarg ("%"))
603         fxn = mod;
604       else
605         return l;
606       args++;
607       r = eval5 ();
608       if (!toarith (l) || !toarith (r))
609         error (2, 0, _("non-numeric argument"));
610       if (fxn == multiply)
611         val = l->u.i * r->u.i;
612       else
613         {
614           if (r->u.i == 0)
615             error (2, 0, _("division by zero"));
616           val = fxn == divide ? l->u.i / r->u.i : l->u.i % r->u.i;
617         }
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   enum { plus, minus } fxn;
632   intmax_t 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       if (!toarith (l) || !toarith (r))
649         error (2, 0, _("non-numeric argument"));
650       val = fxn == plus ? l->u.i + r->u.i : l->u.i - r->u.i;
651       freev (l);
652       freev (r);
653       l = int_value (val);
654     }
655 }
656
657 /* Handle comparisons.  */
658
659 static VALUE *
660 eval2 (void)
661 {
662   VALUE *l;
663   VALUE *r;
664   enum
665   {
666     less_than, less_equal, equal, not_equal, greater_equal, greater_than
667   } fxn;
668   int val;
669   intmax_t lval;
670   intmax_t rval;
671
672 #ifdef EVAL_TRACE
673   trace ("eval2");
674 #endif
675   l = eval3 ();
676   while (1)
677     {
678       if (nextarg ("<"))
679         fxn = less_than;
680       else if (nextarg ("<="))
681         fxn = less_equal;
682       else if (nextarg ("=") || nextarg ("=="))
683         fxn = equal;
684       else if (nextarg ("!="))
685         fxn = not_equal;
686       else if (nextarg (">="))
687         fxn = greater_equal;
688       else if (nextarg (">"))
689         fxn = greater_than;
690       else
691         return l;
692       args++;
693       r = eval3 ();
694       tostring (l);
695       tostring (r);
696       lval = strcoll (l->u.s, r->u.s);
697       rval = 0;
698       if (toarith (l) && toarith (r))
699         {
700           lval = l->u.i;
701           rval = r->u.i;
702         }
703       switch (fxn)
704         {
705         case less_than:     val = (lval <  rval); break;
706         case less_equal:    val = (lval <= rval); break;
707         case equal:         val = (lval == rval); break;
708         case not_equal:     val = (lval != rval); break;
709         case greater_equal: val = (lval >= rval); break;
710         case greater_than:  val = (lval >  rval); break;
711         default: abort ();
712         }
713       freev (l);
714       freev (r);
715       l = int_value (val);
716     }
717 }
718
719 /* Handle &.  */
720
721 static VALUE *
722 eval1 (void)
723 {
724   VALUE *l;
725   VALUE *r;
726
727 #ifdef EVAL_TRACE
728   trace ("eval1");
729 #endif
730   l = eval2 ();
731   while (1)
732     {
733       if (nextarg ("&"))
734         {
735           args++;
736           r = eval2 ();
737           if (null (l) || null (r))
738             {
739               freev (l);
740               freev (r);
741               l = int_value (0);
742             }
743           else
744             freev (r);
745         }
746       else
747         return l;
748     }
749 }
750
751 /* Handle |.  */
752
753 static VALUE *
754 eval (void)
755 {
756   VALUE *l;
757   VALUE *r;
758
759 #ifdef EVAL_TRACE
760   trace ("eval");
761 #endif
762   l = eval1 ();
763   while (1)
764     {
765       if (nextarg ("|"))
766         {
767           args++;
768           r = eval1 ();
769           if (null (l))
770             {
771               freev (l);
772               l = r;
773             }
774           else
775             freev (r);
776         }
777       else
778         return l;
779     }
780 }