.
[coreutils.git] / src / expr.c
blob567633b58ade0c5ed572c59eb52e6c39be759f0d
1 /* expr -- evaluate expressions.
2 Copyright (C) 86, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
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.
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.
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. */
18 /* Author: Mike Parker.
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.
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).
29 Define EVAL_TRACE to print an evaluation trace. */
31 #include <config.h>
32 #include <stdio.h>
33 #include <sys/types.h>
34 #include <regex.h>
36 #include "system.h"
37 #include "long-options.h"
38 #include "error.h"
40 #define NEW(type) ((type *) xmalloc (sizeof (type)))
41 #define OLD(x) free ((char *) x)
43 /* The kinds of value we can have. */
44 enum valtype
46 integer,
47 string
49 typedef enum valtype TYPE;
51 /* A value is.... */
52 struct valinfo
54 TYPE type; /* Which kind. */
55 union
56 { /* The value itself. */
57 int i;
58 char *s;
59 } u;
61 typedef struct valinfo VALUE;
63 /* The arguments given to the program, minus the program name. */
64 static char **args;
66 /* The name this program was run with. */
67 char *program_name;
69 char *xstrdup ();
70 char *strstr ();
71 char *xmalloc ();
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));
86 #ifdef EVAL_TRACE
87 static void trace ();
88 #endif
90 static void
91 usage (int status)
93 if (status != 0)
94 fprintf (stderr, _("Try `%s --help' for more information.\n"),
95 program_name);
96 else
98 printf (_("\
99 Usage: %s EXPRESSION\n\
100 or: %s OPTION\n\
102 program_name, program_name);
103 printf (_("\
105 --help display this help and exit\n\
106 --version output version information and exit\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\
113 ARG1 | ARG2 ARG1 if it is neither null nor 0, otherwise ARG2\n\
115 ARG1 & ARG2 ARG1 if neither argument is null or 0, otherwise 0\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\
124 ARG1 + ARG2 arithmetic sum of ARG1 and ARG2\n\
125 ARG1 - ARG2 arithmetic difference of ARG1 and ARG2\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\
131 STRING : REGEXP anchored pattern match of REGEXP in STRING\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\
138 ( EXPRESSION ) value of EXPRESSION\n\
139 "));
140 printf (_("\
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 "));
148 exit (status);
152 main (int argc, char **argv)
154 VALUE *v;
156 program_name = argv[0];
157 setlocale (LC_ALL, "");
158 bindtextdomain (PACKAGE, LOCALEDIR);
159 textdomain (PACKAGE);
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);
165 if (argc == 1)
167 error (0, 0, _("too few arguments"));
168 usage (1);
171 args = argv + 1;
173 v = eval ();
174 if (!nomoreargs ())
175 error (2, 0, _("syntax error"));
176 printv (v);
178 exit (null (v));
181 /* Return a VALUE for I. */
183 static VALUE *
184 int_value (int i)
186 VALUE *v;
188 v = NEW (VALUE);
189 v->type = integer;
190 v->u.i = i;
191 return v;
194 /* Return a VALUE for S. */
196 static VALUE *
197 str_value (char *s)
199 VALUE *v;
201 v = NEW (VALUE);
202 v->type = string;
203 v->u.s = xstrdup (s);
204 return v;
207 /* Free VALUE V, including structure components. */
209 static void
210 freev (VALUE *v)
212 if (v->type == string)
213 free (v->u.s);
214 OLD (v);
217 /* Print VALUE V. */
219 static void
220 printv (VALUE *v)
222 switch (v->type)
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 ();
235 /* Return nonzero if V is a null-string or zero-number. */
237 static int
238 null (VALUE *v)
240 switch (v->type)
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 ();
251 /* Return nonzero if V is a string value. */
253 static int
254 isstring (VALUE *v)
256 return v->type == string;
259 /* Coerce V to a string value (can't fail). */
261 static void
262 tostring (VALUE *v)
264 char *temp;
266 switch (v->type)
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 ();
281 /* Coerce V to an integer value. Return 1 on success, 0 on failure. */
283 static int
284 toarith (VALUE *v)
286 int i;
287 int neg;
288 char *cp;
290 switch (v->type)
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++)
305 if (ISDIGIT (*cp))
306 i = i * 10 + *cp - '0';
307 else
308 return 0;
310 free (v->u.s);
311 v->u.i = i * (neg ? -1 : 1);
312 v->type = integer;
313 return 1;
314 default:
315 abort ();
319 /* Return nonzero if the next token matches STR exactly.
320 STR must not be NULL. */
322 static int
323 nextarg (char *str)
325 if (*args == NULL)
326 return 0;
327 return strcmp (*args, str) == 0;
330 /* Return nonzero if there no more tokens. */
332 static int
333 nomoreargs (void)
335 return *args == 0;
338 /* The comparison operator handling functions. */
340 #define cmpf(name, rel) \
341 static \
342 int name (l, r) VALUE *l; VALUE *r; \
344 if (isstring (l) || isstring (r)) \
346 tostring (l); \
347 tostring (r); \
348 return strcmp (l->u.s, r->u.s) rel 0; \
350 else \
351 return l->u.i rel r->u.i; \
353 cmpf (less_than, <)
354 cmpf (less_equal, <=)
355 cmpf (equal, ==)
356 cmpf (not_equal, !=)
357 cmpf (greater_equal, >=)
358 cmpf (greater_than, >)
360 #undef cmpf
362 /* The arithmetic operator handling functions. */
364 #define arithf(name, op) \
365 static \
366 int name (l, r) VALUE *l; VALUE *r; \
368 if (!toarith (l) || !toarith (r)) \
369 error (2, 0, _("non-numeric argument")); \
370 return l->u.i op r->u.i; \
373 #define arithdivf(name, op) \
374 int name (l, r) VALUE *l; VALUE *r; \
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; \
383 arithf (plus, +)
384 arithf (minus, -)
385 arithf (multiply, *)
386 arithdivf (divide, /)
387 arithdivf (mod, %)
389 #undef arithf
390 #undef arithdivf
392 #ifdef EVAL_TRACE
393 /* Print evaluation trace and args remaining. */
395 static void
396 trace (fxn)
397 char *fxn;
399 char **a;
401 printf ("%s:", fxn);
402 for (a = args; *a; a++)
403 printf (" %s", *a);
404 putchar ('\n');
406 #endif
408 /* Do the : operator.
409 SV is the VALUE for the lhs (the string),
410 PV is the VALUE for the rhs (the pattern). */
412 static VALUE *
413 docolon (VALUE *sv, VALUE *pv)
415 VALUE *v;
416 const char *errmsg;
417 struct re_pattern_buffer re_buffer;
418 struct re_registers re_regs;
419 int len;
421 tostring (sv);
422 tostring (pv);
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);
435 len = re_match (&re_buffer, sv->u.s, strlen (sv->u.s), 0, &re_regs);
436 if (len >= 0)
438 /* Were \(...\) used? */
439 if (re_buffer.re_nsub > 0)/* was (re_regs.start[1] >= 0) */
441 sv->u.s[re_regs.end[1]] = '\0';
442 v = str_value (sv->u.s + re_regs.start[1]);
444 else
445 v = int_value (len);
447 else
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);
455 free (re_buffer.buffer);
456 return v;
459 /* Handle bare operands and ( expr ) syntax. */
461 static VALUE *
462 eval7 (void)
464 VALUE *v;
466 #ifdef EVAL_TRACE
467 trace ("eval7");
468 #endif
469 if (nomoreargs ())
470 error (2, 0, _("syntax error"));
472 if (nextarg ("("))
474 args++;
475 v = eval ();
476 if (!nextarg (")"))
477 error (2, 0, _("syntax error"));
478 args++;
479 return v;
482 if (nextarg (")"))
483 error (2, 0, _("syntax error"));
485 return str_value (*args++);
488 /* Handle match, substr, index, and length keywords. */
490 static VALUE *
491 eval6 (void)
493 VALUE *l;
494 VALUE *r;
495 VALUE *v;
496 VALUE *i1;
497 VALUE *i2;
499 #ifdef EVAL_TRACE
500 trace ("eval6");
501 #endif
502 if (nextarg ("length"))
504 args++;
505 r = eval6 ();
506 tostring (r);
507 v = int_value (strlen (r->u.s));
508 freev (r);
509 return v;
511 else if (nextarg ("match"))
513 args++;
514 l = eval6 ();
515 r = eval6 ();
516 v = docolon (l, r);
517 freev (l);
518 freev (r);
519 return v;
521 else if (nextarg ("index"))
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;
535 else if (nextarg ("substr"))
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
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;
554 freev (l);
555 freev (i1);
556 freev (i2);
557 return v;
559 else
560 return eval7 ();
563 /* Handle : operator (pattern matching).
564 Calls docolon to do the real work. */
566 static VALUE *
567 eval5 (void)
569 VALUE *l;
570 VALUE *r;
571 VALUE *v;
573 #ifdef EVAL_TRACE
574 trace ("eval5");
575 #endif
576 l = eval6 ();
577 while (1)
579 if (nextarg (":"))
581 args++;
582 r = eval6 ();
583 v = docolon (l, r);
584 freev (l);
585 freev (r);
586 l = v;
588 else
589 return l;
593 /* Handle *, /, % operators. */
595 static VALUE *
596 eval4 (void)
598 VALUE *l;
599 VALUE *r;
600 int (*fxn) ();
601 int val;
603 #ifdef EVAL_TRACE
604 trace ("eval4");
605 #endif
606 l = eval5 ();
607 while (1)
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);
626 /* Handle +, - operators. */
628 static VALUE *
629 eval3 (void)
631 VALUE *l;
632 VALUE *r;
633 int (*fxn) ();
634 int val;
636 #ifdef EVAL_TRACE
637 trace ("eval3");
638 #endif
639 l = eval4 ();
640 while (1)
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);
657 /* Handle comparisons. */
659 static VALUE *
660 eval2 (void)
662 VALUE *l;
663 VALUE *r;
664 int (*fxn) ();
665 int val;
667 #ifdef EVAL_TRACE
668 trace ("eval2");
669 #endif
670 l = eval3 ();
671 while (1)
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);
698 /* Handle &. */
700 static VALUE *
701 eval1 (void)
703 VALUE *l;
704 VALUE *r;
706 #ifdef EVAL_TRACE
707 trace ("eval1");
708 #endif
709 l = eval2 ();
710 while (1)
712 if (nextarg ("&"))
714 args++;
715 r = eval2 ();
716 if (null (l) || null (r))
718 freev (l);
719 freev (r);
720 l = int_value (0);
722 else
723 freev (r);
725 else
726 return l;
730 /* Handle |. */
732 static VALUE *
733 eval (void)
735 VALUE *l;
736 VALUE *r;
738 #ifdef EVAL_TRACE
739 trace ("eval");
740 #endif
741 l = eval1 ();
742 while (1)
744 if (nextarg ("|"))
746 args++;
747 r = eval1 ();
748 if (null (l))
750 freev (l);
751 l = r;
753 else
754 freev (r);
756 else
757 return l;