Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / cpp.ansi / ch3bin.c
1 /*
2  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3  * See the copyright notice in the ACK home directory, in the file "Copyright".
4  */
5 /* $Id: ch3bin.c,v 1.7 1995/03/28 09:10:31 ceriel Exp $ */
6 /* EVALUATION OF BINARY OPERATORS */
7
8 #include        "Lpars.h"
9 #include        "arith.h"
10
11 #define arith_sign (1L << (sizeof(arith)*8-1))
12
13 ch3bin(pval, pis_uns, oper, val, is_uns)
14         register arith *pval, val;
15         int oper, is_uns, *pis_uns;
16 {
17         if (is_uns) *pis_uns = 1;
18         switch (oper)   {
19         case '/':
20                 if (val == 0) {
21                         error("/ by 0");
22                         break;
23                 }
24                 if (*pis_uns) {
25 #ifdef UNSIGNED_ARITH
26                         *pval /= (UNSIGNED_ARITH) val;
27 #else
28                         /*      this is more of a problem than you might
29                                 think on C compilers which do not have
30                                 unsigned arith (== long (probably)).
31                         */
32                         if (val & arith_sign)   {/* val > max_arith */
33                                 *pval = ! (*pval >= 0 || *pval < val);
34                                 /*      this is the unsigned test
35                                         *pval < val for val > max_arith
36                                 */
37                         }
38                         else    {               /* val <= max_arith */
39                                 arith half, bit, hdiv, hrem, rem;
40
41                                 half = (*pval >> 1) & ~arith_sign;
42                                 bit = *pval & 01;
43                                 /*      now *pval == 2 * half + bit
44                                         and half <= max_arith
45                                         and bit <= max_arith
46                                 */
47                                 hdiv = half / val;
48                                 hrem = half % val;
49                                 rem = 2 * hrem + bit;
50                                 *pval = 2 * hdiv + (rem < 0 || rem >= val);
51                                 /*      that is the unsigned compare
52                                         rem >= val for val <= max_arith
53                                 */
54                         }
55 #endif
56                 }
57                 else {
58                         *pval = *pval / val;
59                 }
60                 break;
61         case '%':
62                 if (val == 0) {
63                         error("%% by 0");
64                         break;
65                 }
66                 if (*pis_uns) {
67 #ifdef UNSIGNED_ARITH
68                         *pval %= (UNSIGNED_ARITH) val;
69 #else
70                         if (val & arith_sign)   {/* val > max_arith */
71                                 *pval = (*pval >= 0 || *pval < val) ? *pval : *pval - val;
72                                 /*      this is the unsigned test
73                                         *pval < val for val > max_arith
74                                 */
75                         }
76                         else    {               /* val <= max_arith */
77                                 arith half, bit, hrem, rem;
78
79                                 half = (*pval >> 1) & ~arith_sign;
80                                 bit = *pval & 01;
81                                 /*      now *pval == 2 * half + bit
82                                         and half <= max_arith
83                                         and bit <= max_arith
84                                 */
85                                 hrem = half % val;
86                                 rem = 2 * hrem + bit;
87                                 *pval = (rem < 0 || rem >= val) ? rem - val : rem;
88                         }
89 #endif
90                 }
91                 else {
92                         *pval = *pval % val;
93                 }
94                 break;
95         case '*':
96                 *pval = *pval * val;
97                 break;
98         case '+':
99                 *pval = *pval + val;
100                 break;
101         case '-':
102                 *pval = *pval - val;
103                 break;
104         case LEFT:
105                 *pval = *pval << val;
106                 break;
107         case RIGHT:
108                 if (val == 0) break;
109                 if (*pis_uns) {
110                         *pval = (*pval >> 1) & ~arith_sign;
111                         *pval = *pval >> (val - 1);
112                 }
113                 else *pval = *pval >> val;
114                 break;
115         case '<':
116                 {       arith tmp = *pval; *pval = val; val = tmp; }
117                 /* fall through */
118         case '>':
119                 if (*pis_uns) {
120 #ifdef UNSIGNED_ARITH
121                         *pval = (UNSIGNED_ARITH) *pval > (UNSIGNED_ARITH) val;
122 #else
123                         *pval = (*pval & arith_sign ?
124                                 (val & arith_sign ? *pval > val : 1) :
125                                 (val & arith_sign ? 0 : *pval > val)
126                         );
127 #endif
128                 }
129                 else    *pval = (*pval > val);
130                 break;
131         case LESSEQ:
132                 {       arith tmp = *pval; *pval = val; val = tmp; }
133                 /* fall through */
134         case GREATEREQ:
135                 if (*pis_uns) {
136 #ifdef UNSIGNED_ARITH
137                         *pval = (UNSIGNED_ARITH) *pval >= (UNSIGNED_ARITH) val;
138 #else
139                         *pval = (*pval & arith_sign ?
140                                 (val & arith_sign ? *pval >= val : 1) :
141                                 (val & arith_sign ? 0 : *pval >= val)
142                         );
143 #endif
144                 }
145                 else    *pval = (*pval >= val);
146                 break;
147         case EQUAL:
148                 *pval = (*pval == val);
149                 break;
150         case NOTEQUAL:
151                 *pval = (*pval != val);
152                 break;
153         case '&':
154                 *pval = *pval & val;
155                 break;
156         case '^':
157                 *pval = *pval ^ val;
158                 break;
159         case '|':
160                 *pval = *pval | val;
161                 break;
162         case AND:
163                 *pval = (*pval && val);
164                 break;
165         case OR:
166                 *pval = (*pval || val);
167                 break;
168         case ',':
169                 *pis_uns = is_uns;
170                 *pval = val;
171                 break;
172         }
173 }