(docolon): Give a warning when the first character
[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   if (pv->u.s[0] == '^')
425     {
426       error (0, 0, _("\
427 warning: unportable BRE: `%s': using `^' as the first character \n\
428 of the basic regular expression is not portable; it is being ignored"),
429              pv->u.s);
430     }
431
432   len = strlen (pv->u.s);
433   memset (&re_buffer, 0, sizeof (re_buffer));
434   memset (&re_regs, 0, sizeof (re_regs));
435   re_buffer.allocated = 2 * len;
436   re_buffer.buffer = (unsigned char *) xmalloc (re_buffer.allocated);
437   re_buffer.translate = 0;
438   re_syntax_options = RE_SYNTAX_POSIX_BASIC;
439   errmsg = re_compile_pattern (pv->u.s, len, &re_buffer);
440   if (errmsg)
441     error (2, 0, "%s", errmsg);
442
443   len = re_match (&re_buffer, sv->u.s, strlen (sv->u.s), 0, &re_regs);
444   if (len >= 0)
445     {
446       /* Were \(...\) used? */
447       if (re_buffer.re_nsub > 0)/* was (re_regs.start[1] >= 0) */
448         {
449           sv->u.s[re_regs.end[1]] = '\0';
450           v = str_value (sv->u.s + re_regs.start[1]);
451         }
452       else
453         v = int_value (len);
454     }
455   else
456     {
457       /* Match failed -- return the right kind of null.  */
458       if (strstr (pv->u.s, "\\("))
459         v = str_value ("");
460       else
461         v = int_value (0);
462     }
463   free (re_buffer.buffer);
464   return v;
465 }
466
467 /* Handle bare operands and ( expr ) syntax.  */
468
469 static VALUE *
470 eval7 (void)
471 {
472   VALUE *v;
473
474 #ifdef EVAL_TRACE
475   trace ("eval7");
476 #endif
477   if (nomoreargs ())
478     error (2, 0, _("syntax error"));
479
480   if (nextarg ("("))
481     {
482       args++;
483       v = eval ();
484       if (!nextarg (")"))
485         error (2, 0, _("syntax error"));
486       args++;
487       return v;
488     }
489
490   if (nextarg (")"))
491     error (2, 0, _("syntax error"));
492
493   return str_value (*args++);
494 }
495
496 /* Handle match, substr, index, and length keywords.  */
497
498 static VALUE *
499 eval6 (void)
500 {
501   VALUE *l;
502   VALUE *r;
503   VALUE *v;
504   VALUE *i1;
505   VALUE *i2;
506
507 #ifdef EVAL_TRACE
508   trace ("eval6");
509 #endif
510   if (nextarg ("length"))
511     {
512       args++;
513       r = eval6 ();
514       tostring (r);
515       v = int_value (strlen (r->u.s));
516       freev (r);
517       return v;
518     }
519   else if (nextarg ("match"))
520     {
521       args++;
522       l = eval6 ();
523       r = eval6 ();
524       v = docolon (l, r);
525       freev (l);
526       freev (r);
527       return v;
528     }
529   else if (nextarg ("index"))
530     {
531       args++;
532       l = eval6 ();
533       r = eval6 ();
534       tostring (l);
535       tostring (r);
536       v = int_value (strcspn (l->u.s, r->u.s) + 1);
537       if (v->u.i == (int) strlen (l->u.s) + 1)
538         v->u.i = 0;
539       freev (l);
540       freev (r);
541       return v;
542     }
543   else if (nextarg ("substr"))
544     {
545       args++;
546       l = eval6 ();
547       i1 = eval6 ();
548       i2 = eval6 ();
549       tostring (l);
550       if (!toarith (i1) || !toarith (i2)
551           || i1->u.i > (int) strlen (l->u.s)
552           || i1->u.i <= 0 || i2->u.i <= 0)
553         v = str_value ("");
554       else
555         {
556           v = NEW (VALUE);
557           v->type = string;
558           v->u.s = strncpy ((char *) xmalloc (i2->u.i + 1),
559                             l->u.s + i1->u.i - 1, i2->u.i);
560           v->u.s[i2->u.i] = 0;
561         }
562       freev (l);
563       freev (i1);
564       freev (i2);
565       return v;
566     }
567   else
568     return eval7 ();
569 }
570
571 /* Handle : operator (pattern matching).
572    Calls docolon to do the real work.  */
573
574 static VALUE *
575 eval5 (void)
576 {
577   VALUE *l;
578   VALUE *r;
579   VALUE *v;
580
581 #ifdef EVAL_TRACE
582   trace ("eval5");
583 #endif
584   l = eval6 ();
585   while (1)
586     {
587       if (nextarg (":"))
588         {
589           args++;
590           r = eval6 ();
591           v = docolon (l, r);
592           freev (l);
593           freev (r);
594           l = v;
595         }
596       else
597         return l;
598     }
599 }
600
601 /* Handle *, /, % operators.  */
602
603 static VALUE *
604 eval4 (void)
605 {
606   VALUE *l;
607   VALUE *r;
608   int (*fxn) ();
609   int val;
610
611 #ifdef EVAL_TRACE
612   trace ("eval4");
613 #endif
614   l = eval5 ();
615   while (1)
616     {
617       if (nextarg ("*"))
618         fxn = multiply;
619       else if (nextarg ("/"))
620         fxn = divide;
621       else if (nextarg ("%"))
622         fxn = mod;
623       else
624         return l;
625       args++;
626       r = eval5 ();
627       val = (*fxn) (l, r);
628       freev (l);
629       freev (r);
630       l = int_value (val);
631     }
632 }
633
634 /* Handle +, - operators.  */
635
636 static VALUE *
637 eval3 (void)
638 {
639   VALUE *l;
640   VALUE *r;
641   int (*fxn) ();
642   int val;
643
644 #ifdef EVAL_TRACE
645   trace ("eval3");
646 #endif
647   l = eval4 ();
648   while (1)
649     {
650       if (nextarg ("+"))
651         fxn = plus;
652       else if (nextarg ("-"))
653         fxn = minus;
654       else
655         return l;
656       args++;
657       r = eval4 ();
658       val = (*fxn) (l, r);
659       freev (l);
660       freev (r);
661       l = int_value (val);
662     }
663 }
664
665 /* Handle comparisons.  */
666
667 static VALUE *
668 eval2 (void)
669 {
670   VALUE *l;
671   VALUE *r;
672   int (*fxn) ();
673   int val;
674
675 #ifdef EVAL_TRACE
676   trace ("eval2");
677 #endif
678   l = eval3 ();
679   while (1)
680     {
681       if (nextarg ("<"))
682         fxn = less_than;
683       else if (nextarg ("<="))
684         fxn = less_equal;
685       else if (nextarg ("=") || nextarg ("=="))
686         fxn = equal;
687       else if (nextarg ("!="))
688         fxn = not_equal;
689       else if (nextarg (">="))
690         fxn = greater_equal;
691       else if (nextarg (">"))
692         fxn = greater_than;
693       else
694         return l;
695       args++;
696       r = eval3 ();
697       toarith (l);
698       toarith (r);
699       val = (*fxn) (l, r);
700       freev (l);
701       freev (r);
702       l = int_value (val);
703     }
704 }
705
706 /* Handle &.  */
707
708 static VALUE *
709 eval1 (void)
710 {
711   VALUE *l;
712   VALUE *r;
713
714 #ifdef EVAL_TRACE
715   trace ("eval1");
716 #endif
717   l = eval2 ();
718   while (1)
719     {
720       if (nextarg ("&"))
721         {
722           args++;
723           r = eval2 ();
724           if (null (l) || null (r))
725             {
726               freev (l);
727               freev (r);
728               l = int_value (0);
729             }
730           else
731             freev (r);
732         }
733       else
734         return l;
735     }
736 }
737
738 /* Handle |.  */
739
740 static VALUE *
741 eval (void)
742 {
743   VALUE *l;
744   VALUE *r;
745
746 #ifdef EVAL_TRACE
747   trace ("eval");
748 #endif
749   l = eval1 ();
750   while (1)
751     {
752       if (nextarg ("|"))
753         {
754           args++;
755           r = eval1 ();
756           if (null (l))
757             {
758               freev (l);
759               l = r;
760             }
761           else
762             freev (r);
763         }
764       else
765         return l;
766     }
767 }