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