Imported Upstream version 0.19.7
[platform/upstream/gettext.git] / gettext-runtime / intl / eval-plural.h
1 /* Plural expression evaluation.
2    Copyright (C) 2000-2003, 2007, 2015 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
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 }