421f00799f9a7f4442e170324b3b8e2acdef8986
[platform/upstream/glibc.git] / intl / eval-plural.h
1 /* Plural expression evaluation.
2    Copyright (C) 2000-2019 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 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 }