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