1 /* Native functions for integer operations. 2 3 Copyright (C) 2016, 2017 Paul Boddie <paul@boddie.org.uk> 4 5 This program is free software; you can redistribute it and/or modify it under 6 the terms of the GNU General Public License as published by the Free Software 7 Foundation; either version 3 of the License, or (at your option) any later 8 version. 9 10 This program is distributed in the hope that it will be useful, but WITHOUT 11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 details. 14 15 You should have received a copy of the GNU General Public License along with 16 this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include <limits.h> /* INT_MAX, INT_MIN */ 20 #include <math.h> /* ceil, log10, pow */ 21 #include <stdio.h> /* fdopen, snprintf, strlen */ 22 #include <errno.h> /* errno */ 23 #include "native/common.h" 24 #include "types.h" 25 #include "exceptions.h" 26 #include "ops.h" 27 #include "progconsts.h" 28 #include "progops.h" 29 #include "progtypes.h" 30 #include "main.h" 31 32 /* Integer operations. */ 33 34 __attr __fn_native_int_int_add(__attr __args[]) 35 { 36 __attr * const _data = &__args[1]; 37 __attr * const other = &__args[2]; 38 /* _data and other interpreted as int */ 39 int i = _data->intvalue; 40 int j = other->intvalue; 41 42 /* Test for overflow. */ 43 if (((i > 0) && (j > 0) && (i > INT_MAX - j)) || 44 ((i < 0) && (j < 0) && (i < INT_MIN - j))) 45 46 __raise_overflow_error(); 47 48 /* Return the new integer. */ 49 return __new_int(i + j); 50 } 51 52 __attr __fn_native_int_int_sub(__attr __args[]) 53 { 54 __attr * const _data = &__args[1]; 55 __attr * const other = &__args[2]; 56 /* _data and other interpreted as int */ 57 int i = _data->intvalue; 58 int j = other->intvalue; 59 60 /* Test for overflow. */ 61 if (((i < 0) && (j > 0) && (i < INT_MIN + j)) || 62 ((i > 0) && (j < 0) && (i > INT_MAX + j))) 63 64 __raise_overflow_error(); 65 66 /* Return the new integer. */ 67 return __new_int(i - j); 68 } 69 70 __attr __fn_native_int_int_mul(__attr __args[]) 71 { 72 __attr * const _data = &__args[1]; 73 __attr * const other = &__args[2]; 74 /* _data and other interpreted as int */ 75 int i = _data->intvalue; 76 int j = other->intvalue; 77 78 /* Test for overflow. */ 79 if (((i > 0) && (j > 0) && (i > INT_MAX / j)) || 80 ((i < 0) && (j < 0) && (i > INT_MAX / j)) || 81 ((i < 0) && (j > 0) && (i < INT_MIN / j)) || 82 ((i > 0) && (j < 0) && (j < INT_MIN / i))) 83 84 __raise_overflow_error(); 85 86 /* Return the new integer. */ 87 return __new_int(i * j); 88 } 89 90 __attr __fn_native_int_int_div(__attr __args[]) 91 { 92 __attr * const _data = &__args[1]; 93 __attr * const other = &__args[2]; 94 /* _data and other interpreted as int */ 95 int i = _data->intvalue; 96 int j = other->intvalue; 97 98 /* Test for division by zero or overflow. */ 99 if (j == 0) 100 __raise_zero_division_error(); 101 else if ((j == -1) && (i == INT_MIN)) 102 __raise_overflow_error(); 103 104 /* Return the new integer. */ 105 return __new_int(i / j); 106 } 107 108 __attr __fn_native_int_int_mod(__attr __args[]) 109 { 110 __attr * const _data = &__args[1]; 111 __attr * const other = &__args[2]; 112 /* _data and other interpreted as int */ 113 int i = _data->intvalue; 114 int j = other->intvalue; 115 116 /* Test for division by zero or overflow. */ 117 if (j == 0) 118 __raise_zero_division_error(); 119 else if ((j == -1) && (i == INT_MIN)) 120 __raise_overflow_error(); 121 122 /* Return the new integer. */ 123 return __new_int(i % j); 124 } 125 126 __attr __fn_native_int_int_neg(__attr __args[]) 127 { 128 __attr * const _data = &__args[1]; 129 /* _data interpreted as int */ 130 int i = _data->intvalue; 131 132 /* Test for overflow. */ 133 if (i == INT_MIN) 134 __raise_overflow_error(); 135 136 /* Return the new integer. */ 137 return __new_int(-i); 138 } 139 140 __attr __fn_native_int_int_pow(__attr __args[]) 141 { 142 __attr * const _data = &__args[1]; 143 __attr * const other = &__args[2]; 144 /* _data and other interpreted as int */ 145 int i = _data->intvalue; 146 int j = other->intvalue; 147 int k; 148 149 errno = 0; 150 k = (int) pow(i, j); 151 152 /* Test for overflow. */ 153 154 if (errno == ERANGE) 155 __raise_overflow_error(); 156 157 /* Return the new integer. */ 158 return __new_int(k); 159 } 160 161 __attr __fn_native_int_int_and(__attr __args[]) 162 { 163 __attr * const _data = &__args[1]; 164 __attr * const other = &__args[2]; 165 /* _data and other interpreted as int */ 166 int i = _data->intvalue; 167 int j = other->intvalue; 168 169 /* Return the new integer. */ 170 /* NOTE: No overflow test applied. */ 171 return __new_int(i & j); 172 } 173 174 __attr __fn_native_int_int_not(__attr __args[]) 175 { 176 __attr * const _data = &__args[1]; 177 /* _data interpreted as int */ 178 int i = _data->intvalue; 179 180 /* Return the new integer. */ 181 return __new_int(~i); 182 } 183 184 __attr __fn_native_int_int_or(__attr __args[]) 185 { 186 __attr * const _data = &__args[1]; 187 __attr * const other = &__args[2]; 188 /* _data and other interpreted as int */ 189 int i = _data->intvalue; 190 int j = other->intvalue; 191 192 /* Return the new integer. */ 193 /* NOTE: No overflow test applied. */ 194 return __new_int(i | j); 195 } 196 197 __attr __fn_native_int_int_xor(__attr __args[]) 198 { 199 __attr * const _data = &__args[1]; 200 __attr * const other = &__args[2]; 201 /* _data and other interpreted as int */ 202 int i = _data->intvalue; 203 int j = other->intvalue; 204 205 /* Return the new integer. */ 206 /* NOTE: No overflow test applied. */ 207 return __new_int(i ^ j); 208 } 209 210 __attr __fn_native_int_int_lt(__attr __args[]) 211 { 212 __attr * const _data = &__args[1]; 213 __attr * const other = &__args[2]; 214 /* _data and other interpreted as int */ 215 int i = _data->intvalue; 216 int j = other->intvalue; 217 218 /* Return a boolean result. */ 219 return i < j ? __builtins___boolean_True : __builtins___boolean_False; 220 } 221 222 __attr __fn_native_int_int_gt(__attr __args[]) 223 { 224 __attr * const _data = &__args[1]; 225 __attr * const other = &__args[2]; 226 /* _data and other interpreted as int */ 227 int i = _data->intvalue; 228 int j = other->intvalue; 229 230 /* Return a boolean result. */ 231 return i > j ? __builtins___boolean_True : __builtins___boolean_False; 232 } 233 234 __attr __fn_native_int_int_eq(__attr __args[]) 235 { 236 __attr * const _data = &__args[1]; 237 __attr * const other = &__args[2]; 238 /* _data and other interpreted as int */ 239 int i = _data->intvalue; 240 int j = other->intvalue; 241 242 /* Return a boolean result. */ 243 return i == j ? __builtins___boolean_True : __builtins___boolean_False; 244 } 245 246 __attr __fn_native_int_int_ne(__attr __args[]) 247 { 248 __attr * const _data = &__args[1]; 249 __attr * const other = &__args[2]; 250 /* _data and other interpreted as int */ 251 int i = _data->intvalue; 252 int j = other->intvalue; 253 254 /* Return a boolean result. */ 255 return i != j ? __builtins___boolean_True : __builtins___boolean_False; 256 } 257 258 __attr __fn_native_int_int_str(__attr __args[]) 259 { 260 __attr * const _data = &__args[1]; 261 /* _data interpreted as int */ 262 int i = _data->intvalue; 263 /* Employ a buffer big enough to fit the largest integer plus an extra 264 character, a minus sign, and the null terminator. */ 265 unsigned int n = (int) log10(INT_MAX) + 3; 266 char *s = (char *) __ALLOCATE(n, sizeof(char)); 267 268 snprintf(s, n, "%d", i); 269 270 /* Return a new string. */ 271 return __new_str(s); 272 } 273 274 /* Module initialisation. */ 275 276 void __main_native_int() 277 { 278 }