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