1 /* Plural expression evaluation.
2    Copyright (C) 2000-2003, 2007 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 Lesser General Public License as published by
6    the Free Software Foundation; either version 2.1 of the License, or
7    (at your option) 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 Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
16 
17 #ifndef STATIC
18 #define STATIC static
19 #endif
20 
21 /* Evaluate the plural expression and return an index value.  */
22 STATIC
23 unsigned long int
24 internal_function
plural_eval(const struct expression * pexp,unsigned long int n)25 plural_eval (const struct expression *pexp, unsigned long int n)
26 {
27   switch (pexp->nargs)
28     {
29     case 0:
30       switch (pexp->operation)
31 	{
32 	case var:
33 	  return n;
34 	case num:
35 	  return pexp->val.num;
36 	default:
37 	  break;
38 	}
39       /* NOTREACHED */
40       break;
41     case 1:
42       {
43 	/* pexp->operation must be lnot.  */
44 	unsigned long int arg = plural_eval (pexp->val.args[0], n);
45 	return ! arg;
46       }
47     case 2:
48       {
49 	unsigned long int leftarg = plural_eval (pexp->val.args[0], n);
50 	if (pexp->operation == lor)
51 	  return leftarg || plural_eval (pexp->val.args[1], n);
52 	else if (pexp->operation == land)
53 	  return leftarg && plural_eval (pexp->val.args[1], n);
54 	else
55 	  {
56 	    unsigned long int rightarg = plural_eval (pexp->val.args[1], n);
57 
58 	    switch (pexp->operation)
59 	      {
60 	      case mult:
61 		return leftarg * rightarg;
62 	      case divide:
63 #if !INTDIV0_RAISES_SIGFPE
64 		if (rightarg == 0)
65 		  raise (SIGFPE);
66 #endif
67 		return leftarg / rightarg;
68 	      case module:
69 #if !INTDIV0_RAISES_SIGFPE
70 		if (rightarg == 0)
71 		  raise (SIGFPE);
72 #endif
73 		return leftarg % rightarg;
74 	      case plus:
75 		return leftarg + rightarg;
76 	      case minus:
77 		return leftarg - rightarg;
78 	      case less_than:
79 		return leftarg < rightarg;
80 	      case greater_than:
81 		return leftarg > rightarg;
82 	      case less_or_equal:
83 		return leftarg <= rightarg;
84 	      case greater_or_equal:
85 		return leftarg >= rightarg;
86 	      case equal:
87 		return leftarg == rightarg;
88 	      case not_equal:
89 		return leftarg != rightarg;
90 	      default:
91 		break;
92 	      }
93 	  }
94 	/* NOTREACHED */
95 	break;
96       }
97     case 3:
98       {
99 	/* pexp->operation must be qmop.  */
100 	unsigned long int boolarg = plural_eval (pexp->val.args[0], n);
101 	return plural_eval (pexp->val.args[boolarg ? 1 : 2], n);
102       }
103     }
104   /* NOTREACHED */
105   return 0;
106 }
107