123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- /*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
- * See the copyright notice in the ACK home directory, in the file "Copyright".
- */
- /* $Id$ */
- /* EVALUATION OF BINARY OPERATORS */
- #include "Lpars.h"
- #include "arith.h"
- #define arith_sign (1L << (sizeof(arith)*8-1))
- void ch3bin(arith *pval, int *pis_uns, int oper, arith val, int is_uns)
- {
- if (is_uns) *pis_uns = 1;
- switch (oper) {
- case '/':
- if (val == 0) {
- error("/ by 0");
- break;
- }
- if (*pis_uns) {
- #ifdef UNSIGNED_ARITH
- *pval /= (UNSIGNED_ARITH) val;
- #else
- /* this is more of a problem than you might
- think on C compilers which do not have
- unsigned arith (== long (probably)).
- */
- if (val & arith_sign) {/* val > max_arith */
- *pval = ! (*pval >= 0 || *pval < val);
- /* this is the unsigned test
- *pval < val for val > max_arith
- */
- }
- else { /* val <= max_arith */
- arith half, bit, hdiv, hrem, rem;
- half = (*pval >> 1) & ~arith_sign;
- bit = *pval & 01;
- /* now *pval == 2 * half + bit
- and half <= max_arith
- and bit <= max_arith
- */
- hdiv = half / val;
- hrem = half % val;
- rem = 2 * hrem + bit;
- *pval = 2 * hdiv + (rem < 0 || rem >= val);
- /* that is the unsigned compare
- rem >= val for val <= max_arith
- */
- }
- #endif
- }
- else {
- *pval = *pval / val;
- }
- break;
- case '%':
- if (val == 0) {
- error("%% by 0");
- break;
- }
- if (*pis_uns) {
- #ifdef UNSIGNED_ARITH
- *pval %= (UNSIGNED_ARITH) val;
- #else
- if (val & arith_sign) {/* val > max_arith */
- *pval = (*pval >= 0 || *pval < val) ? *pval : *pval - val;
- /* this is the unsigned test
- *pval < val for val > max_arith
- */
- }
- else { /* val <= max_arith */
- arith half, bit, hrem, rem;
- half = (*pval >> 1) & ~arith_sign;
- bit = *pval & 01;
- /* now *pval == 2 * half + bit
- and half <= max_arith
- and bit <= max_arith
- */
- hrem = half % val;
- rem = 2 * hrem + bit;
- *pval = (rem < 0 || rem >= val) ? rem - val : rem;
- }
- #endif
- }
- else {
- *pval = *pval % val;
- }
- break;
- case '*':
- *pval = *pval * val;
- break;
- case '+':
- *pval = *pval + val;
- break;
- case '-':
- *pval = *pval - val;
- break;
- case LEFT:
- *pval = *pval << val;
- break;
- case RIGHT:
- if (val == 0) break;
- if (*pis_uns) {
- *pval = (*pval >> 1) & ~arith_sign;
- *pval = *pval >> (val - 1);
- }
- else *pval = *pval >> val;
- break;
- case '<':
- { arith tmp = *pval; *pval = val; val = tmp; }
- /* fall through */
- case '>':
- if (*pis_uns) {
- #ifdef UNSIGNED_ARITH
- *pval = (UNSIGNED_ARITH) *pval > (UNSIGNED_ARITH) val;
- #else
- *pval = (*pval & arith_sign ?
- (val & arith_sign ? *pval > val : 1) :
- (val & arith_sign ? 0 : *pval > val)
- );
- #endif
- }
- else *pval = (*pval > val);
- break;
- case LESSEQ:
- { arith tmp = *pval; *pval = val; val = tmp; }
- /* fall through */
- case GREATEREQ:
- if (*pis_uns) {
- #ifdef UNSIGNED_ARITH
- *pval = (UNSIGNED_ARITH) *pval >= (UNSIGNED_ARITH) val;
- #else
- *pval = (*pval & arith_sign ?
- (val & arith_sign ? *pval >= val : 1) :
- (val & arith_sign ? 0 : *pval >= val)
- );
- #endif
- }
- else *pval = (*pval >= val);
- break;
- case EQUAL:
- *pval = (*pval == val);
- break;
- case NOTEQUAL:
- *pval = (*pval != val);
- break;
- case '&':
- *pval = *pval & val;
- break;
- case '^':
- *pval = *pval ^ val;
- break;
- case '|':
- *pval = *pval | val;
- break;
- case AND:
- *pval = (*pval && val);
- break;
- case OR:
- *pval = (*pval || val);
- break;
- case ',':
- *pis_uns = is_uns;
- *pval = val;
- break;
- }
- }
|