1/* eval-plural.c - Plural expression evaluation. */
2
3/* Copyright (C) 2000-2002, 2006-2009 Free Software Foundation, Inc.
4
5   This file is part of GNU Bash.
6
7   Bash is free software: you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation, either version 3 of the License, or
10   (at your option) any later version.
11
12   Bash is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with Bash.  If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#ifndef STATIC
22#define STATIC static
23#endif
24
25/* Evaluate the plural expression and return an index value.  */
26STATIC unsigned long int plural_eval PARAMS ((struct expression *pexp,
27					      unsigned long int n))
28     internal_function;
29
30STATIC
31unsigned long int
32internal_function
33plural_eval (pexp, n)
34     struct expression *pexp;
35     unsigned long int n;
36{
37  switch (pexp->nargs)
38    {
39    case 0:
40      switch (pexp->operation)
41	{
42	case var:
43	  return n;
44	case num:
45	  return pexp->val.num;
46	default:
47	  break;
48	}
49      /* NOTREACHED */
50      break;
51    case 1:
52      {
53	/* pexp->operation must be lnot.  */
54	unsigned long int arg = plural_eval (pexp->val.args[0], n);
55	return ! arg;
56      }
57    case 2:
58      {
59	unsigned long int leftarg = plural_eval (pexp->val.args[0], n);
60	if (pexp->operation == lor)
61	  return leftarg || plural_eval (pexp->val.args[1], n);
62	else if (pexp->operation == land)
63	  return leftarg && plural_eval (pexp->val.args[1], n);
64	else
65	  {
66	    unsigned long int rightarg = plural_eval (pexp->val.args[1], n);
67
68	    switch (pexp->operation)
69	      {
70	      case mult:
71		return leftarg * rightarg;
72	      case divide:
73#if !INTDIV0_RAISES_SIGFPE
74		if (rightarg == 0)
75		  raise (SIGFPE);
76#endif
77		return leftarg / rightarg;
78	      case module:
79#if !INTDIV0_RAISES_SIGFPE
80		if (rightarg == 0)
81		  raise (SIGFPE);
82#endif
83		return leftarg % rightarg;
84	      case plus:
85		return leftarg + rightarg;
86	      case minus:
87		return leftarg - rightarg;
88	      case less_than:
89		return leftarg < rightarg;
90	      case greater_than:
91		return leftarg > rightarg;
92	      case less_or_equal:
93		return leftarg <= rightarg;
94	      case greater_or_equal:
95		return leftarg >= rightarg;
96	      case equal:
97		return leftarg == rightarg;
98	      case not_equal:
99		return leftarg != rightarg;
100	      default:
101		break;
102	      }
103	  }
104	/* NOTREACHED */
105	break;
106      }
107    case 3:
108      {
109	/* pexp->operation must be qmop.  */
110	unsigned long int boolarg = plural_eval (pexp->val.args[0], n);
111	return plural_eval (pexp->val.args[boolarg ? 1 : 2], n);
112      }
113    }
114  /* NOTREACHED */
115  return 0;
116}
117