tests: pwd-long: diagnose failure earlier
[coreutils/ericb.git] / src / expr.c
blob1f535070bdbe625bc8dd24a4b46c116db108c859
1 /* expr -- evaluate expressions.
2 Copyright (C) 1986, 1991-1997, 1999-2011 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 3 of the License, or
7 (at your option) 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, see <http://www.gnu.org/licenses/>. */
17 /* Author: Mike Parker.
18 Modified for arbitrary-precision calculation by James Youngman.
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 "system.h"
36 #include <regex.h>
37 #include "error.h"
38 #include "long-options.h"
39 #include "quotearg.h"
40 #include "strnumcmp.h"
41 #include "xstrtol.h"
43 /* Various parts of this code assume size_t fits into unsigned long
44 int, the widest unsigned type that GMP supports. */
45 verify (SIZE_MAX <= ULONG_MAX);
47 static void integer_overflow (char) ATTRIBUTE_NORETURN;
49 #ifndef HAVE_GMP
50 # define HAVE_GMP 0
51 #endif
53 #if HAVE_GMP
54 # include <gmp.h>
55 #else
56 /* Approximate gmp.h well enough for expr.c's purposes. */
57 typedef intmax_t mpz_t[1];
58 static void mpz_clear (mpz_t z) { (void) z; }
59 static void mpz_init_set_ui (mpz_t z, unsigned long int i) { z[0] = i; }
60 static int
61 mpz_init_set_str (mpz_t z, char *s, int base)
63 return xstrtoimax (s, NULL, base, z, NULL) == LONGINT_OK ? 0 : -1;
65 static void
66 mpz_add (mpz_t r, mpz_t a0, mpz_t b0)
68 intmax_t a = a0[0];
69 intmax_t b = b0[0];
70 intmax_t val = a + b;
71 if ((val < a) != (b < 0))
72 integer_overflow ('+');
73 r[0] = val;
75 static void
76 mpz_sub (mpz_t r, mpz_t a0, mpz_t b0)
78 intmax_t a = a0[0];
79 intmax_t b = b0[0];
80 intmax_t val = a - b;
81 if ((a < val) != (b < 0))
82 integer_overflow ('-');
83 r[0] = val;
85 static void
86 mpz_mul (mpz_t r, mpz_t a0, mpz_t b0)
88 intmax_t a = a0[0];
89 intmax_t b = b0[0];
90 intmax_t val = a * b;
91 if (! (a == 0 || b == 0
92 || ((val < 0) == ((a < 0) ^ (b < 0)) && val / a == b)))
93 integer_overflow ('*');
94 r[0] = val;
96 static void
97 mpz_tdiv_q (mpz_t r, mpz_t a0, mpz_t b0)
99 intmax_t a = a0[0];
100 intmax_t b = b0[0];
102 /* Some x86-style hosts raise an exception for INT_MIN / -1. */
103 if (a < - INTMAX_MAX && b == -1)
104 integer_overflow ('/');
105 r[0] = a / b;
107 static void
108 mpz_tdiv_r (mpz_t r, mpz_t a0, mpz_t b0)
110 intmax_t a = a0[0];
111 intmax_t b = b0[0];
113 /* Some x86-style hosts raise an exception for INT_MIN % -1. */
114 r[0] = a < - INTMAX_MAX && b == -1 ? 0 : a % b;
116 static char *
117 mpz_get_str (char const *str, int base, mpz_t z)
119 (void) str; (void) base;
120 char buf[INT_BUFSIZE_BOUND (intmax_t)];
121 return xstrdup (imaxtostr (z[0], buf));
123 static int
124 mpz_sgn (mpz_t z)
126 return z[0] < 0 ? -1 : 0 < z[0];
128 static int
129 mpz_fits_ulong_p (mpz_t z)
131 return 0 <= z[0] && z[0] <= ULONG_MAX;
133 static unsigned long int
134 mpz_get_ui (mpz_t z)
136 return z[0];
138 static int
139 mpz_out_str (FILE *stream, int base, mpz_t z)
141 (void) base;
142 char buf[INT_BUFSIZE_BOUND (intmax_t)];
143 return fputs (imaxtostr (z[0], buf), stream) != EOF;
145 #endif
147 /* The official name of this program (e.g., no `g' prefix). */
148 #define PROGRAM_NAME "expr"
150 #define AUTHORS \
151 proper_name ("Mike Parker"), \
152 proper_name ("James Youngman"), \
153 proper_name ("Paul Eggert")
155 /* Exit statuses. */
156 enum
158 /* Invalid expression: e.g., its form does not conform to the
159 grammar for expressions. Our grammar is an extension of the
160 POSIX grammar. */
161 EXPR_INVALID = 2,
163 /* An internal error occurred, e.g., arithmetic overflow, storage
164 exhaustion. */
165 EXPR_FAILURE
168 /* The kinds of value we can have. */
169 enum valtype
171 integer,
172 string
174 typedef enum valtype TYPE;
176 /* A value is.... */
177 struct valinfo
179 TYPE type; /* Which kind. */
180 union
181 { /* The value itself. */
182 mpz_t i;
183 char *s;
184 } u;
186 typedef struct valinfo VALUE;
188 /* The arguments given to the program, minus the program name. */
189 static char **args;
191 static VALUE *eval (bool);
192 static bool nomoreargs (void);
193 static bool null (VALUE *v);
194 static void printv (VALUE *v);
196 void
197 usage (int status)
199 if (status != EXIT_SUCCESS)
200 fprintf (stderr, _("Try `%s --help' for more information.\n"),
201 program_name);
202 else
204 printf (_("\
205 Usage: %s EXPRESSION\n\
206 or: %s OPTION\n\
208 program_name, program_name);
209 putchar ('\n');
210 fputs (HELP_OPTION_DESCRIPTION, stdout);
211 fputs (VERSION_OPTION_DESCRIPTION, stdout);
212 fputs (_("\
214 Print the value of EXPRESSION to standard output. A blank line below\n\
215 separates increasing precedence groups. EXPRESSION may be:\n\
217 ARG1 | ARG2 ARG1 if it is neither null nor 0, otherwise ARG2\n\
219 ARG1 & ARG2 ARG1 if neither argument is null or 0, otherwise 0\n\
220 "), stdout);
221 fputs (_("\
223 ARG1 < ARG2 ARG1 is less than ARG2\n\
224 ARG1 <= ARG2 ARG1 is less than or equal to ARG2\n\
225 ARG1 = ARG2 ARG1 is equal to ARG2\n\
226 ARG1 != ARG2 ARG1 is unequal to ARG2\n\
227 ARG1 >= ARG2 ARG1 is greater than or equal to ARG2\n\
228 ARG1 > ARG2 ARG1 is greater than ARG2\n\
229 "), stdout);
230 fputs (_("\
232 ARG1 + ARG2 arithmetic sum of ARG1 and ARG2\n\
233 ARG1 - ARG2 arithmetic difference of ARG1 and ARG2\n\
234 "), stdout);
235 /* Tell xgettext that the "% A" below is not a printf-style
236 format string: xgettext:no-c-format */
237 fputs (_("\
239 ARG1 * ARG2 arithmetic product of ARG1 and ARG2\n\
240 ARG1 / ARG2 arithmetic quotient of ARG1 divided by ARG2\n\
241 ARG1 % ARG2 arithmetic remainder of ARG1 divided by ARG2\n\
242 "), stdout);
243 fputs (_("\
245 STRING : REGEXP anchored pattern match of REGEXP in STRING\n\
247 match STRING REGEXP same as STRING : REGEXP\n\
248 substr STRING POS LENGTH substring of STRING, POS counted from 1\n\
249 index STRING CHARS index in STRING where any CHARS is found, or 0\n\
250 length STRING length of STRING\n\
251 "), stdout);
252 fputs (_("\
253 + TOKEN interpret TOKEN as a string, even if it is a\n\
254 keyword like `match' or an operator like `/'\n\
256 ( EXPRESSION ) value of EXPRESSION\n\
257 "), stdout);
258 fputs (_("\
260 Beware that many operators need to be escaped or quoted for shells.\n\
261 Comparisons are arithmetic if both ARGs are numbers, else lexicographical.\n\
262 Pattern matches return the string matched between \\( and \\) or null; if\n\
263 \\( and \\) are not used, they return the number of characters matched or 0.\n\
264 "), stdout);
265 fputs (_("\
267 Exit status is 0 if EXPRESSION is neither null nor 0, 1 if EXPRESSION is null\n\
268 or 0, 2 if EXPRESSION is syntactically invalid, and 3 if an error occurred.\n\
269 "), stdout);
270 emit_ancillary_info ();
272 exit (status);
275 /* Report a syntax error and exit. */
276 static void
277 syntax_error (void)
279 error (EXPR_INVALID, 0, _("syntax error"));
282 /* Report an integer overflow for operation OP and exit. */
283 static void
284 integer_overflow (char op)
286 error (EXPR_FAILURE, ERANGE, "%c", op);
287 abort (); /* notreached */
290 static void die (int errno_val, char const *msg)
291 ATTRIBUTE_NORETURN;
292 static void
293 die (int errno_val, char const *msg)
295 error (EXPR_FAILURE, errno_val, "%s", msg);
296 abort (); /* notreached */
300 main (int argc, char **argv)
302 VALUE *v;
304 initialize_main (&argc, &argv);
305 set_program_name (argv[0]);
306 setlocale (LC_ALL, "");
307 bindtextdomain (PACKAGE, LOCALEDIR);
308 textdomain (PACKAGE);
310 initialize_exit_failure (EXPR_FAILURE);
311 atexit (close_stdout);
313 parse_long_options (argc, argv, PROGRAM_NAME, PACKAGE_NAME, VERSION,
314 usage, AUTHORS, (char const *) NULL);
316 /* The above handles --help and --version.
317 Since there is no other invocation of getopt, handle `--' here. */
318 unsigned int u_argc = argc;
319 if (1 < u_argc && STREQ (argv[1], "--"))
321 --u_argc;
322 ++argv;
325 if (u_argc <= 1)
327 error (0, 0, _("missing operand"));
328 usage (EXPR_INVALID);
331 args = argv + 1;
333 v = eval (true);
334 if (!nomoreargs ())
335 syntax_error ();
336 printv (v);
338 exit (null (v));
341 /* Return a VALUE for I. */
343 static VALUE *
344 int_value (unsigned long int i)
346 VALUE *v = xmalloc (sizeof *v);
347 v->type = integer;
348 mpz_init_set_ui (v->u.i, i);
349 return v;
352 /* Return a VALUE for S. */
354 static VALUE *
355 str_value (char const *s)
357 VALUE *v = xmalloc (sizeof *v);
358 v->type = string;
359 v->u.s = xstrdup (s);
360 return v;
363 /* Free VALUE V, including structure components. */
365 static void
366 freev (VALUE *v)
368 if (v->type == string)
369 free (v->u.s);
370 else
371 mpz_clear (v->u.i);
372 free (v);
375 /* Print VALUE V. */
377 static void
378 printv (VALUE *v)
380 switch (v->type)
382 case integer:
383 mpz_out_str (stdout, 10, v->u.i);
384 putchar ('\n');
385 break;
386 case string:
387 puts (v->u.s);
388 break;
389 default:
390 abort ();
394 /* Return true if V is a null-string or zero-number. */
396 static bool _GL_ATTRIBUTE_PURE
397 null (VALUE *v)
399 switch (v->type)
401 case integer:
402 return mpz_sgn (v->u.i) == 0;
403 case string:
405 char const *cp = v->u.s;
406 if (*cp == '\0')
407 return true;
409 cp += (*cp == '-');
413 if (*cp != '0')
414 return false;
416 while (*++cp);
418 return true;
420 default:
421 abort ();
425 /* Return true if CP takes the form of an integer. */
427 static bool _GL_ATTRIBUTE_PURE
428 looks_like_integer (char const *cp)
430 cp += (*cp == '-');
433 if (! ISDIGIT (*cp))
434 return false;
435 while (*++cp);
437 return true;
440 /* Coerce V to a string value (can't fail). */
442 static void
443 tostring (VALUE *v)
445 switch (v->type)
447 case integer:
449 char *s = mpz_get_str (NULL, 10, v->u.i);
450 mpz_clear (v->u.i);
451 v->u.s = s;
452 v->type = string;
454 break;
455 case string:
456 break;
457 default:
458 abort ();
462 /* Coerce V to an integer value. Return true on success, false on failure. */
464 static bool
465 toarith (VALUE *v)
467 switch (v->type)
469 case integer:
470 return true;
471 case string:
473 char *s = v->u.s;
475 if (! looks_like_integer (s))
476 return false;
477 if (mpz_init_set_str (v->u.i, s, 10) != 0 && !HAVE_GMP)
478 error (EXPR_FAILURE, ERANGE, "%s", s);
479 free (s);
480 v->type = integer;
481 return true;
483 default:
484 abort ();
488 /* Extract a size_t value from an integer value I.
489 If the value is negative, return SIZE_MAX.
490 If the value is too large, return SIZE_MAX - 1. */
491 static size_t
492 getsize (mpz_t i)
494 if (mpz_sgn (i) < 0)
495 return SIZE_MAX;
496 if (mpz_fits_ulong_p (i))
498 unsigned long int ul = mpz_get_ui (i);
499 if (ul < SIZE_MAX)
500 return ul;
502 return SIZE_MAX - 1;
505 /* Return true and advance if the next token matches STR exactly.
506 STR must not be NULL. */
508 static bool
509 nextarg (char const *str)
511 if (*args == NULL)
512 return false;
513 else
515 bool r = STREQ (*args, str);
516 args += r;
517 return r;
521 /* Return true if there no more tokens. */
523 static bool
524 nomoreargs (void)
526 return *args == 0;
529 #ifdef EVAL_TRACE
530 /* Print evaluation trace and args remaining. */
532 static void
533 trace (fxn)
534 char *fxn;
536 char **a;
538 printf ("%s:", fxn);
539 for (a = args; *a; a++)
540 printf (" %s", *a);
541 putchar ('\n');
543 #endif
545 /* Do the : operator.
546 SV is the VALUE for the lhs (the string),
547 PV is the VALUE for the rhs (the pattern). */
549 static VALUE *
550 docolon (VALUE *sv, VALUE *pv)
552 VALUE *v IF_LINT ( = NULL);
553 const char *errmsg;
554 struct re_pattern_buffer re_buffer;
555 char fastmap[UCHAR_MAX + 1];
556 struct re_registers re_regs;
557 regoff_t matchlen;
559 tostring (sv);
560 tostring (pv);
562 re_regs.num_regs = 0;
563 re_regs.start = NULL;
564 re_regs.end = NULL;
566 re_buffer.buffer = NULL;
567 re_buffer.allocated = 0;
568 re_buffer.fastmap = fastmap;
569 re_buffer.translate = NULL;
570 re_syntax_options =
571 RE_SYNTAX_POSIX_BASIC & ~RE_CONTEXT_INVALID_DUP & ~RE_NO_EMPTY_RANGES;
572 errmsg = re_compile_pattern (pv->u.s, strlen (pv->u.s), &re_buffer);
573 if (errmsg)
574 error (EXPR_INVALID, 0, "%s", errmsg);
575 re_buffer.newline_anchor = 0;
577 matchlen = re_match (&re_buffer, sv->u.s, strlen (sv->u.s), 0, &re_regs);
578 if (0 <= matchlen)
580 /* Were \(...\) used? */
581 if (re_buffer.re_nsub > 0)
583 sv->u.s[re_regs.end[1]] = '\0';
584 v = str_value (sv->u.s + re_regs.start[1]);
586 else
587 v = int_value (matchlen);
589 else if (matchlen == -1)
591 /* Match failed -- return the right kind of null. */
592 if (re_buffer.re_nsub > 0)
593 v = str_value ("");
594 else
595 v = int_value (0);
597 else
598 error (EXPR_FAILURE,
599 (matchlen == -2 ? errno : EOVERFLOW),
600 _("error in regular expression matcher"));
602 if (0 < re_regs.num_regs)
604 free (re_regs.start);
605 free (re_regs.end);
607 re_buffer.fastmap = NULL;
608 regfree (&re_buffer);
609 return v;
612 /* Handle bare operands and ( expr ) syntax. */
614 static VALUE *
615 eval7 (bool evaluate)
617 VALUE *v;
619 #ifdef EVAL_TRACE
620 trace ("eval7");
621 #endif
622 if (nomoreargs ())
623 syntax_error ();
625 if (nextarg ("("))
627 v = eval (evaluate);
628 if (!nextarg (")"))
629 syntax_error ();
630 return v;
633 if (nextarg (")"))
634 syntax_error ();
636 return str_value (*args++);
639 /* Handle match, substr, index, and length keywords, and quoting "+". */
641 static VALUE *
642 eval6 (bool evaluate)
644 VALUE *l;
645 VALUE *r;
646 VALUE *v;
647 VALUE *i1;
648 VALUE *i2;
650 #ifdef EVAL_TRACE
651 trace ("eval6");
652 #endif
653 if (nextarg ("+"))
655 if (nomoreargs ())
656 syntax_error ();
657 return str_value (*args++);
659 else if (nextarg ("length"))
661 r = eval6 (evaluate);
662 tostring (r);
663 v = int_value (strlen (r->u.s));
664 freev (r);
665 return v;
667 else if (nextarg ("match"))
669 l = eval6 (evaluate);
670 r = eval6 (evaluate);
671 if (evaluate)
673 v = docolon (l, r);
674 freev (l);
676 else
677 v = l;
678 freev (r);
679 return v;
681 else if (nextarg ("index"))
683 size_t pos;
685 l = eval6 (evaluate);
686 r = eval6 (evaluate);
687 tostring (l);
688 tostring (r);
689 pos = strcspn (l->u.s, r->u.s);
690 v = int_value (l->u.s[pos] ? pos + 1 : 0);
691 freev (l);
692 freev (r);
693 return v;
695 else if (nextarg ("substr"))
697 size_t llen;
698 l = eval6 (evaluate);
699 i1 = eval6 (evaluate);
700 i2 = eval6 (evaluate);
701 tostring (l);
702 llen = strlen (l->u.s);
704 if (!toarith (i1) || !toarith (i2))
705 v = str_value ("");
706 else
708 size_t pos = getsize (i1->u.i);
709 size_t len = getsize (i2->u.i);
711 if (llen < pos || pos == 0 || len == 0 || len == SIZE_MAX)
712 v = str_value ("");
713 else
715 size_t vlen = MIN (len, llen - pos + 1);
716 char *vlim;
717 v = xmalloc (sizeof *v);
718 v->type = string;
719 v->u.s = xmalloc (vlen + 1);
720 vlim = mempcpy (v->u.s, l->u.s + pos - 1, vlen);
721 *vlim = '\0';
724 freev (l);
725 freev (i1);
726 freev (i2);
727 return v;
729 else
730 return eval7 (evaluate);
733 /* Handle : operator (pattern matching).
734 Calls docolon to do the real work. */
736 static VALUE *
737 eval5 (bool evaluate)
739 VALUE *l;
740 VALUE *r;
741 VALUE *v;
743 #ifdef EVAL_TRACE
744 trace ("eval5");
745 #endif
746 l = eval6 (evaluate);
747 while (1)
749 if (nextarg (":"))
751 r = eval6 (evaluate);
752 if (evaluate)
754 v = docolon (l, r);
755 freev (l);
756 l = v;
758 freev (r);
760 else
761 return l;
765 /* Handle *, /, % operators. */
767 static VALUE *
768 eval4 (bool evaluate)
770 VALUE *l;
771 VALUE *r;
772 enum { multiply, divide, mod } fxn;
774 #ifdef EVAL_TRACE
775 trace ("eval4");
776 #endif
777 l = eval5 (evaluate);
778 while (1)
780 if (nextarg ("*"))
781 fxn = multiply;
782 else if (nextarg ("/"))
783 fxn = divide;
784 else if (nextarg ("%"))
785 fxn = mod;
786 else
787 return l;
788 r = eval5 (evaluate);
789 if (evaluate)
791 if (!toarith (l) || !toarith (r))
792 error (EXPR_INVALID, 0, _("non-integer argument"));
793 if (fxn != multiply && mpz_sgn (r->u.i) == 0)
794 error (EXPR_INVALID, 0, _("division by zero"));
795 ((fxn == multiply ? mpz_mul
796 : fxn == divide ? mpz_tdiv_q
797 : mpz_tdiv_r)
798 (l->u.i, l->u.i, r->u.i));
800 freev (r);
804 /* Handle +, - operators. */
806 static VALUE *
807 eval3 (bool evaluate)
809 VALUE *l;
810 VALUE *r;
811 enum { plus, minus } fxn;
813 #ifdef EVAL_TRACE
814 trace ("eval3");
815 #endif
816 l = eval4 (evaluate);
817 while (1)
819 if (nextarg ("+"))
820 fxn = plus;
821 else if (nextarg ("-"))
822 fxn = minus;
823 else
824 return l;
825 r = eval4 (evaluate);
826 if (evaluate)
828 if (!toarith (l) || !toarith (r))
829 error (EXPR_INVALID, 0, _("non-integer argument"));
830 (fxn == plus ? mpz_add : mpz_sub) (l->u.i, l->u.i, r->u.i);
832 freev (r);
836 /* Handle comparisons. */
838 static VALUE *
839 eval2 (bool evaluate)
841 VALUE *l;
843 #ifdef EVAL_TRACE
844 trace ("eval2");
845 #endif
846 l = eval3 (evaluate);
847 while (1)
849 VALUE *r;
850 enum
852 less_than, less_equal, equal, not_equal, greater_equal, greater_than
853 } fxn;
854 bool val = false;
856 if (nextarg ("<"))
857 fxn = less_than;
858 else if (nextarg ("<="))
859 fxn = less_equal;
860 else if (nextarg ("=") || nextarg ("=="))
861 fxn = equal;
862 else if (nextarg ("!="))
863 fxn = not_equal;
864 else if (nextarg (">="))
865 fxn = greater_equal;
866 else if (nextarg (">"))
867 fxn = greater_than;
868 else
869 return l;
870 r = eval3 (evaluate);
872 if (evaluate)
874 int cmp;
875 tostring (l);
876 tostring (r);
878 if (looks_like_integer (l->u.s) && looks_like_integer (r->u.s))
879 cmp = strintcmp (l->u.s, r->u.s);
880 else
882 errno = 0;
883 cmp = strcoll (l->u.s, r->u.s);
885 if (errno)
887 error (0, errno, _("string comparison failed"));
888 error (0, 0, _("set LC_ALL='C' to work around the problem"));
889 error (EXPR_INVALID, 0,
890 _("the strings compared were %s and %s"),
891 quotearg_n_style (0, locale_quoting_style, l->u.s),
892 quotearg_n_style (1, locale_quoting_style, r->u.s));
896 switch (fxn)
898 case less_than: val = (cmp < 0); break;
899 case less_equal: val = (cmp <= 0); break;
900 case equal: val = (cmp == 0); break;
901 case not_equal: val = (cmp != 0); break;
902 case greater_equal: val = (cmp >= 0); break;
903 case greater_than: val = (cmp > 0); break;
904 default: abort ();
908 freev (l);
909 freev (r);
910 l = int_value (val);
914 /* Handle &. */
916 static VALUE *
917 eval1 (bool evaluate)
919 VALUE *l;
920 VALUE *r;
922 #ifdef EVAL_TRACE
923 trace ("eval1");
924 #endif
925 l = eval2 (evaluate);
926 while (1)
928 if (nextarg ("&"))
930 r = eval2 (evaluate && !null (l));
931 if (null (l) || null (r))
933 freev (l);
934 freev (r);
935 l = int_value (0);
937 else
938 freev (r);
940 else
941 return l;
945 /* Handle |. */
947 static VALUE *
948 eval (bool evaluate)
950 VALUE *l;
951 VALUE *r;
953 #ifdef EVAL_TRACE
954 trace ("eval");
955 #endif
956 l = eval1 (evaluate);
957 while (1)
959 if (nextarg ("|"))
961 r = eval1 (evaluate && null (l));
962 if (null (l))
964 freev (l);
965 l = r;
966 if (null (l))
968 freev (l);
969 l = int_value (0);
972 else
973 freev (r);
975 else
976 return l;