1 /* Plural expression evaluation.
2    Copyright (C) 2000-2022 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 <https://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
plural_eval(const struct expression * pexp,unsigned long int n)24 plural_eval (const struct expression *pexp, unsigned long int n)
25 {
26   switch (pexp->nargs)
27     {
28     case 0:
29       switch (pexp->operation)
30 	{
31 	case var:
32 	  return n;
33 	case num:
34 	  return pexp->val.num;
35 	default:
36 	  break;
37 	}
38       /* NOTREACHED */
39       break;
40     case 1:
41       {
42 	/* pexp->operation must be lnot.  */
43 	unsigned long int arg = plural_eval (pexp->val.args[0], n);
44 	return ! arg;
45       }
46     case 2:
47       {
48 	unsigned long int leftarg = plural_eval (pexp->val.args[0], n);
49 	if (pexp->operation == lor)
50 	  return leftarg || plural_eval (pexp->val.args[1], n);
51 	else if (pexp->operation == land)
52 	  return leftarg && plural_eval (pexp->val.args[1], n);
53 	else
54 	  {
55 	    unsigned long int rightarg = plural_eval (pexp->val.args[1], n);
56 
57 	    switch (pexp->operation)
58 	      {
59 	      case mult:
60 		return leftarg * rightarg;
61 	      case divide:
62 #if !INTDIV0_RAISES_SIGFPE
63 		if (rightarg == 0)
64 		  raise (SIGFPE);
65 #endif
66 		return leftarg / rightarg;
67 	      case module:
68 #if !INTDIV0_RAISES_SIGFPE
69 		if (rightarg == 0)
70 		  raise (SIGFPE);
71 #endif
72 		return leftarg % rightarg;
73 	      case plus:
74 		return leftarg + rightarg;
75 	      case minus:
76 		return leftarg - rightarg;
77 	      case less_than:
78 		return leftarg < rightarg;
79 	      case greater_than:
80 		return leftarg > rightarg;
81 	      case less_or_equal:
82 		return leftarg <= rightarg;
83 	      case greater_or_equal:
84 		return leftarg >= rightarg;
85 	      case equal:
86 		return leftarg == rightarg;
87 	      case not_equal:
88 		return leftarg != rightarg;
89 	      default:
90 		break;
91 	      }
92 	  }
93 	/* NOTREACHED */
94 	break;
95       }
96     case 3:
97       {
98 	/* pexp->operation must be qmop.  */
99 	unsigned long int boolarg = plural_eval (pexp->val.args[0], n);
100 	return plural_eval (pexp->val.args[boolarg ? 1 : 2], n);
101       }
102     }
103   /* NOTREACHED */
104   return 0;
105 }
106