Cast NULL to `(char *)' in call to variadic function,
[platform/upstream/coreutils.git] / src / expr.c
1 /* expr -- evaluate expressions.
2    Copyright (C) 86, 1991-1997, 1999-2003 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 "system.h"
35
36 #include <regex.h>
37 #include "long-options.h"
38 #include "error.h"
39 #include "exitfail.h"
40 #include "inttostr.h"
41 #include "quotearg.h"
42
43 /* The official name of this program (e.g., no `g' prefix).  */
44 #define PROGRAM_NAME "expr"
45
46 #define AUTHORS "Mike Parker"
47
48 #undef NEW
49 #define NEW(Type) XMALLOC (Type, 1)
50 #define OLD(x) free (x)
51
52 /* Exit statuses.  */
53 enum
54   {
55     /* Invalid expression: i.e., its form does not conform to the
56        grammar for expressions.  Our grammar is an extension of the
57        POSIX grammar.  */
58     EXPR_INVALID = 2,
59
60     /* Some other error occurred.  */
61     EXPR_ERROR
62   };
63
64 /* The kinds of value we can have.  */
65 enum valtype
66 {
67   integer,
68   string
69 };
70 typedef enum valtype TYPE;
71
72 /* A value is.... */
73 struct valinfo
74 {
75   TYPE type;                    /* Which kind. */
76   union
77   {                             /* The value itself. */
78     intmax_t i;
79     char *s;
80   } u;
81 };
82 typedef struct valinfo VALUE;
83
84 /* The arguments given to the program, minus the program name.  */
85 static char **args;
86
87 /* The name this program was run with. */
88 char *program_name;
89
90 static VALUE *eval (void);
91 static bool nomoreargs (void);
92 static bool null (VALUE *v);
93 static void printv (VALUE *v);
94
95 void
96 usage (int status)
97 {
98   if (status != 0)
99     fprintf (stderr, _("Try `%s --help' for more information.\n"),
100              program_name);
101   else
102     {
103       printf (_("\
104 Usage: %s EXPRESSION\n\
105   or:  %s OPTION\n\
106 "),
107               program_name, program_name);
108       putchar ('\n');
109       fputs (HELP_OPTION_DESCRIPTION, stdout);
110       fputs (VERSION_OPTION_DESCRIPTION, stdout);
111       fputs (_("\
112 \n\
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 "), stdout);
120       fputs (_("\
121 \n\
122   ARG1 < ARG2       ARG1 is less than ARG2\n\
123   ARG1 <= ARG2      ARG1 is less than or equal to ARG2\n\
124   ARG1 = ARG2       ARG1 is equal to ARG2\n\
125   ARG1 != ARG2      ARG1 is unequal to ARG2\n\
126   ARG1 >= ARG2      ARG1 is greater than or equal to ARG2\n\
127   ARG1 > ARG2       ARG1 is greater than ARG2\n\
128 "), stdout);
129       fputs (_("\
130 \n\
131   ARG1 + ARG2       arithmetic sum of ARG1 and ARG2\n\
132   ARG1 - ARG2       arithmetic difference of ARG1 and ARG2\n\
133 "), stdout);
134       fputs (_("\
135 \n\
136   ARG1 * ARG2       arithmetic product of ARG1 and ARG2\n\
137   ARG1 / ARG2       arithmetic quotient of ARG1 divided by ARG2\n\
138   ARG1 % ARG2       arithmetic remainder of ARG1 divided by ARG2\n\
139 "), stdout);
140       fputs (_("\
141 \n\
142   STRING : REGEXP   anchored pattern match of REGEXP in STRING\n\
143 \n\
144   match STRING REGEXP        same as STRING : REGEXP\n\
145   substr STRING POS LENGTH   substring of STRING, POS counted from 1\n\
146   index STRING CHARS         index in STRING where any CHARS is found, or 0\n\
147   length STRING              length of STRING\n\
148 "), stdout);
149       fputs (_("\
150   + TOKEN                    interpret TOKEN as a string, even if it is a\n\
151                                keyword like `match' or an operator like `/'\n\
152 \n\
153   ( EXPRESSION )             value of EXPRESSION\n\
154 "), stdout);
155       fputs (_("\
156 \n\
157 Beware that many operators need to be escaped or quoted for shells.\n\
158 Comparisons are arithmetic if both ARGs are numbers, else lexicographical.\n\
159 Pattern matches return the string matched between \\( and \\) or null; if\n\
160 \\( and \\) are not used, they return the number of characters matched or 0.\n\
161 "), stdout);
162       printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
163     }
164   exit (status);
165 }
166
167 /* Report a syntax error and exit.  */
168 static void
169 syntax_error (void)
170 {
171   error (EXPR_INVALID, 0, _("syntax error"));
172 }
173
174 int
175 main (int argc, char **argv)
176 {
177   VALUE *v;
178
179   initialize_main (&argc, &argv);
180   program_name = argv[0];
181   setlocale (LC_ALL, "");
182   bindtextdomain (PACKAGE, LOCALEDIR);
183   textdomain (PACKAGE);
184
185   /* Change the way library functions fail.  */
186   exit_failure = EXPR_ERROR;
187
188   atexit (close_stdout);
189
190   parse_long_options (argc, argv, PROGRAM_NAME, GNU_PACKAGE, VERSION,
191                       usage, AUTHORS, (char const *) NULL);
192   /* The above handles --help and --version.
193      Since there is no other invocation of getopt, handle `--' here.  */
194   if (argc > 1 && STREQ (argv[1], "--"))
195     {
196       --argc;
197       ++argv;
198     }
199
200   if (argc <= 1)
201     {
202       error (0, 0, _("too few arguments"));
203       usage (EXPR_INVALID);
204     }
205
206   args = argv + 1;
207
208   v = eval ();
209   if (!nomoreargs ())
210     syntax_error ();
211   printv (v);
212
213   exit (null (v));
214 }
215
216 /* Return a VALUE for I.  */
217
218 static VALUE *
219 int_value (intmax_t i)
220 {
221   VALUE *v;
222
223   v = NEW (VALUE);
224   v->type = integer;
225   v->u.i = i;
226   return v;
227 }
228
229 /* Return a VALUE for S.  */
230
231 static VALUE *
232 str_value (char *s)
233 {
234   VALUE *v;
235
236   v = NEW (VALUE);
237   v->type = string;
238   v->u.s = xstrdup (s);
239   return v;
240 }
241
242 /* Free VALUE V, including structure components.  */
243
244 static void
245 freev (VALUE *v)
246 {
247   if (v->type == string)
248     free (v->u.s);
249   OLD (v);
250 }
251
252 /* Print VALUE V.  */
253
254 static void
255 printv (VALUE *v)
256 {
257   char *p;
258   char buf[INT_STRLEN_BOUND (intmax_t) + 1];
259
260   switch (v->type)
261     {
262     case integer:
263       p = imaxtostr (v->u.i, buf);
264       break;
265     case string:
266       p = v->u.s;
267       break;
268     default:
269       abort ();
270     }
271
272   puts (p);
273 }
274
275 /* Return true if V is a null-string or zero-number.  */
276
277 static bool
278 null (VALUE *v)
279 {
280   switch (v->type)
281     {
282     case integer:
283       return v->u.i == 0;
284     case string:
285       return v->u.s[0] == '\0' || strcmp (v->u.s, "0") == 0;
286     default:
287       abort ();
288     }
289 }
290
291 /* Coerce V to a string value (can't fail).  */
292
293 static void
294 tostring (VALUE *v)
295 {
296   char buf[INT_STRLEN_BOUND (intmax_t) + 1];
297
298   switch (v->type)
299     {
300     case integer:
301       v->u.s = xstrdup (imaxtostr (v->u.i, buf));
302       v->type = string;
303       break;
304     case string:
305       break;
306     default:
307       abort ();
308     }
309 }
310
311 /* Coerce V to an integer value.  Return true on success, false on failure.  */
312
313 static bool
314 toarith (VALUE *v)
315 {
316   intmax_t i;
317   bool neg;
318   char *cp;
319
320   switch (v->type)
321     {
322     case integer:
323       return true;
324     case string:
325       i = 0;
326       cp = v->u.s;
327       neg = (*cp == '-');
328       if (neg)
329         cp++;
330
331       do
332         {
333           if (ISDIGIT (*cp))
334             i = i * 10 + *cp - '0';
335           else
336             return false;
337         }
338       while (*++cp);
339
340       free (v->u.s);
341       v->u.i = i * (neg ? -1 : 1);
342       v->type = integer;
343       return true;
344     default:
345       abort ();
346     }
347 }
348
349 /* Return nonzero and advance if the next token matches STR exactly.
350    STR must not be NULL.  */
351
352 static bool
353 nextarg (char const *str)
354 {
355   if (*args == NULL)
356     return 0;
357   else
358     {
359       bool r = strcmp (*args, str) == 0;
360       args += r;
361       return r;
362     }
363 }
364
365 /* Return true if there no more tokens.  */
366
367 static bool
368 nomoreargs (void)
369 {
370   return *args == 0;
371 }
372
373 #ifdef EVAL_TRACE
374 /* Print evaluation trace and args remaining.  */
375
376 static void
377 trace (fxn)
378      char *fxn;
379 {
380   char **a;
381
382   printf ("%s:", fxn);
383   for (a = args; *a; a++)
384     printf (" %s", *a);
385   putchar ('\n');
386 }
387 #endif
388
389 /* Do the : operator.
390    SV is the VALUE for the lhs (the string),
391    PV is the VALUE for the rhs (the pattern).  */
392
393 static VALUE *
394 docolon (VALUE *sv, VALUE *pv)
395 {
396   VALUE *v;
397   const char *errmsg;
398   struct re_pattern_buffer re_buffer;
399   struct re_registers re_regs;
400   size_t len;
401   int matchlen;
402
403   tostring (sv);
404   tostring (pv);
405
406   if (pv->u.s[0] == '^')
407     {
408       error (0, 0, _("\
409 warning: unportable BRE: `%s': using `^' as the first character\n\
410 of the basic regular expression is not portable; it is being ignored"),
411              pv->u.s);
412     }
413
414   len = strlen (pv->u.s);
415   memset (&re_buffer, 0, sizeof (re_buffer));
416   memset (&re_regs, 0, sizeof (re_regs));
417   re_buffer.allocated = 2 * len;
418   if (re_buffer.allocated < len)
419     xalloc_die ();
420   re_buffer.buffer = xmalloc (re_buffer.allocated);
421   re_buffer.translate = 0;
422   re_syntax_options = RE_SYNTAX_POSIX_BASIC;
423   errmsg = re_compile_pattern (pv->u.s, len, &re_buffer);
424   if (errmsg)
425     error (EXPR_ERROR, 0, "%s", errmsg);
426
427   matchlen = re_match (&re_buffer, sv->u.s, strlen (sv->u.s), 0, &re_regs);
428   if (0 <= matchlen)
429     {
430       /* Were \(...\) used? */
431       if (re_buffer.re_nsub > 0)/* was (re_regs.start[1] >= 0) */
432         {
433           sv->u.s[re_regs.end[1]] = '\0';
434           v = str_value (sv->u.s + re_regs.start[1]);
435         }
436       else
437         v = int_value (matchlen);
438     }
439   else
440     {
441       /* Match failed -- return the right kind of null.  */
442       if (re_buffer.re_nsub > 0)
443         v = str_value ("");
444       else
445         v = int_value (0);
446     }
447   free (re_buffer.buffer);
448   return v;
449 }
450
451 /* Handle bare operands and ( expr ) syntax.  */
452
453 static VALUE *
454 eval7 (void)
455 {
456   VALUE *v;
457
458 #ifdef EVAL_TRACE
459   trace ("eval7");
460 #endif
461   if (nomoreargs ())
462     syntax_error ();
463
464   if (nextarg ("("))
465     {
466       v = eval ();
467       if (!nextarg (")"))
468         syntax_error ();
469       return v;
470     }
471
472   if (nextarg (")"))
473     syntax_error ();
474
475   return str_value (*args++);
476 }
477
478 /* Handle match, substr, index, and length keywords, and quoting "+".  */
479
480 static VALUE *
481 eval6 (void)
482 {
483   VALUE *l;
484   VALUE *r;
485   VALUE *v;
486   VALUE *i1;
487   VALUE *i2;
488
489 #ifdef EVAL_TRACE
490   trace ("eval6");
491 #endif
492   if (nextarg ("+"))
493     {
494       if (nomoreargs ())
495         syntax_error ();
496       return str_value (*args++);
497     }
498   else if (nextarg ("length"))
499     {
500       r = eval6 ();
501       tostring (r);
502       v = int_value (strlen (r->u.s));
503       freev (r);
504       return v;
505     }
506   else if (nextarg ("match"))
507     {
508       l = eval6 ();
509       r = eval6 ();
510       v = docolon (l, r);
511       freev (l);
512       freev (r);
513       return v;
514     }
515   else if (nextarg ("index"))
516     {
517       l = eval6 ();
518       r = eval6 ();
519       tostring (l);
520       tostring (r);
521       v = int_value (strcspn (l->u.s, r->u.s) + 1);
522       if (v->u.i == strlen (l->u.s) + 1)
523         v->u.i = 0;
524       freev (l);
525       freev (r);
526       return v;
527     }
528   else if (nextarg ("substr"))
529     {
530       l = eval6 ();
531       i1 = eval6 ();
532       i2 = eval6 ();
533       tostring (l);
534       if (!toarith (i1) || !toarith (i2)
535           || strlen (l->u.s) < i1->u.i
536           || i1->u.i <= 0 || i2->u.i <= 0)
537         v = str_value ("");
538       else
539         {
540           v = NEW (VALUE);
541           v->type = string;
542           v->u.s = strncpy (xmalloc (i2->u.i + 1),
543                             l->u.s + i1->u.i - 1, i2->u.i);
544           v->u.s[i2->u.i] = 0;
545         }
546       freev (l);
547       freev (i1);
548       freev (i2);
549       return v;
550     }
551   else
552     return eval7 ();
553 }
554
555 /* Handle : operator (pattern matching).
556    Calls docolon to do the real work.  */
557
558 static VALUE *
559 eval5 (void)
560 {
561   VALUE *l;
562   VALUE *r;
563   VALUE *v;
564
565 #ifdef EVAL_TRACE
566   trace ("eval5");
567 #endif
568   l = eval6 ();
569   while (1)
570     {
571       if (nextarg (":"))
572         {
573           r = eval6 ();
574           v = docolon (l, r);
575           freev (l);
576           freev (r);
577           l = v;
578         }
579       else
580         return l;
581     }
582 }
583
584 /* Handle *, /, % operators.  */
585
586 static VALUE *
587 eval4 (void)
588 {
589   VALUE *l;
590   VALUE *r;
591   enum { multiply, divide, mod } fxn;
592   intmax_t val;
593
594 #ifdef EVAL_TRACE
595   trace ("eval4");
596 #endif
597   l = eval5 ();
598   while (1)
599     {
600       if (nextarg ("*"))
601         fxn = multiply;
602       else if (nextarg ("/"))
603         fxn = divide;
604       else if (nextarg ("%"))
605         fxn = mod;
606       else
607         return l;
608       r = eval5 ();
609       if (!toarith (l) || !toarith (r))
610         error (EXPR_ERROR, 0, _("non-numeric argument"));
611       if (fxn == multiply)
612         val = l->u.i * r->u.i;
613       else
614         {
615           if (r->u.i == 0)
616             error (EXPR_ERROR, 0, _("division by zero"));
617           val = fxn == divide ? l->u.i / r->u.i : l->u.i % r->u.i;
618         }
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   enum { plus, minus } fxn;
633   intmax_t 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       r = eval4 ();
648       if (!toarith (l) || !toarith (r))
649         error (EXPR_ERROR, 0, _("non-numeric argument"));
650       val = fxn == plus ? l->u.i + r->u.i : l->u.i - r->u.i;
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   enum
665   {
666     less_than, less_equal, equal, not_equal, greater_equal, greater_than
667   } fxn;
668   bool val;
669   intmax_t lval;
670   intmax_t rval;
671   int collation_errno;
672   char *collation_arg1;
673
674 #ifdef EVAL_TRACE
675   trace ("eval2");
676 #endif
677   l = eval3 ();
678   while (1)
679     {
680       if (nextarg ("<"))
681         fxn = less_than;
682       else if (nextarg ("<="))
683         fxn = less_equal;
684       else if (nextarg ("=") || nextarg ("=="))
685         fxn = equal;
686       else if (nextarg ("!="))
687         fxn = not_equal;
688       else if (nextarg (">="))
689         fxn = greater_equal;
690       else if (nextarg (">"))
691         fxn = greater_than;
692       else
693         return l;
694       r = eval3 ();
695       tostring (l);
696       tostring (r);
697
698       /* Save the first arg to strcoll, in case we need its value for
699          a diagnostic later.  This is needed because 'toarith' might
700          free the first arg.  */
701       collation_arg1 = xstrdup (l->u.s);
702
703       errno = 0;
704       lval = strcoll (collation_arg1, r->u.s);
705       collation_errno = errno;
706       rval = 0;
707       if (toarith (l) && toarith (r))
708         {
709           lval = l->u.i;
710           rval = r->u.i;
711         }
712       else if (collation_errno)
713         {
714           error (0, collation_errno, _("string comparison failed"));
715           error (0, 0, _("Set LC_ALL='C' to work around the problem."));
716           error (EXPR_ERROR, 0,
717                  _("The strings compared were %s and %s."),
718                  quotearg_n_style (0, locale_quoting_style, collation_arg1),
719                  quotearg_n_style (1, locale_quoting_style, r->u.s));
720         }
721
722       switch (fxn)
723         {
724         case less_than:     val = (lval <  rval); break;
725         case less_equal:    val = (lval <= rval); break;
726         case equal:         val = (lval == rval); break;
727         case not_equal:     val = (lval != rval); break;
728         case greater_equal: val = (lval >= rval); break;
729         case greater_than:  val = (lval >  rval); break;
730         default: abort ();
731         }
732       freev (l);
733       freev (r);
734       free (collation_arg1);
735       l = int_value (val);
736     }
737 }
738
739 /* Handle &.  */
740
741 static VALUE *
742 eval1 (void)
743 {
744   VALUE *l;
745   VALUE *r;
746
747 #ifdef EVAL_TRACE
748   trace ("eval1");
749 #endif
750   l = eval2 ();
751   while (1)
752     {
753       if (nextarg ("&"))
754         {
755           r = eval2 ();
756           if (null (l) || null (r))
757             {
758               freev (l);
759               freev (r);
760               l = int_value (0);
761             }
762           else
763             freev (r);
764         }
765       else
766         return l;
767     }
768 }
769
770 /* Handle |.  */
771
772 static VALUE *
773 eval (void)
774 {
775   VALUE *l;
776   VALUE *r;
777
778 #ifdef EVAL_TRACE
779   trace ("eval");
780 #endif
781   l = eval1 ();
782   while (1)
783     {
784       if (nextarg ("|"))
785         {
786           r = eval1 ();
787           if (null (l))
788             {
789               freev (l);
790               l = r;
791             }
792           else
793             freev (r);
794         }
795       else
796         return l;
797     }
798 }