ch3bin.c 3.5 KB

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