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