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 */ 22 #include <errno.h> /* errno */ 23 #include <string.h> /* strlen */ 24 #include "native/common.h" 25 #include "types.h" 26 #include "exceptions.h" 27 #include "ops.h" 28 #include "progconsts.h" 29 #include "progops.h" 30 #include "progtypes.h" 31 #include "main.h" 32 33 /* Integer operations. */ 34 35 __attr __fn_native_int_int_new(__attr __args[]) 36 { 37 __attr * const _data = &__args[1]; 38 39 return __new_int(_data->intvalue); 40 } 41 42 __attr __fn_native_int_int_add(__attr __args[]) 43 { 44 __attr * const _data = &__args[1]; 45 __attr * const other = &__args[2]; 46 /* _data and other interpreted as int */ 47 int i = _data->intvalue; 48 int j = other->intvalue; 49 50 /* Test for overflow. */ 51 if (((i > 0) && (j > 0) && (i > INT_MAX - j)) || 52 ((i < 0) && (j < 0) && (i < INT_MIN - j))) 53 54 __raise_overflow_error(); 55 56 /* Return the new integer. */ 57 return __new_int(i + j); 58 } 59 60 __attr __fn_native_int_int_sub(__attr __args[]) 61 { 62 __attr * const _data = &__args[1]; 63 __attr * const other = &__args[2]; 64 /* _data and other interpreted as int */ 65 int i = _data->intvalue; 66 int j = other->intvalue; 67 68 /* Test for overflow. */ 69 if (((i < 0) && (j > 0) && (i < INT_MIN + j)) || 70 ((i > 0) && (j < 0) && (i > INT_MAX + j))) 71 72 __raise_overflow_error(); 73 74 /* Return the new integer. */ 75 return __new_int(i - j); 76 } 77 78 __attr __fn_native_int_int_mul(__attr __args[]) 79 { 80 __attr * const _data = &__args[1]; 81 __attr * const other = &__args[2]; 82 /* _data and other interpreted as int */ 83 int i = _data->intvalue; 84 int j = other->intvalue; 85 86 /* Test for overflow. */ 87 if (((i > 0) && (j > 0) && (i > INT_MAX / j)) || 88 ((i < 0) && (j < 0) && (i > INT_MAX / j)) || 89 ((i < 0) && (j > 0) && (i < INT_MIN / j)) || 90 ((i > 0) && (j < 0) && (j < INT_MIN / i))) 91 92 __raise_overflow_error(); 93 94 /* Return the new integer. */ 95 return __new_int(i * j); 96 } 97 98 __attr __fn_native_int_int_div(__attr __args[]) 99 { 100 __attr * const _data = &__args[1]; 101 __attr * const other = &__args[2]; 102 /* _data and other interpreted as int */ 103 int i = _data->intvalue; 104 int j = other->intvalue; 105 106 /* Test for division by zero or overflow. */ 107 if (j == 0) 108 __raise_zero_division_error(); 109 else if ((j == -1) && (i == INT_MIN)) 110 __raise_overflow_error(); 111 112 /* Return the new integer. */ 113 return __new_int(i / j); 114 } 115 116 __attr __fn_native_int_int_mod(__attr __args[]) 117 { 118 __attr * const _data = &__args[1]; 119 __attr * const other = &__args[2]; 120 /* _data and other interpreted as int */ 121 int i = _data->intvalue; 122 int j = other->intvalue; 123 124 /* Test for division by zero or overflow. */ 125 if (j == 0) 126 __raise_zero_division_error(); 127 else if ((j == -1) && (i == INT_MIN)) 128 __raise_overflow_error(); 129 130 /* Return the new integer. */ 131 return __new_int(i % j); 132 } 133 134 __attr __fn_native_int_int_neg(__attr __args[]) 135 { 136 __attr * const _data = &__args[1]; 137 /* _data interpreted as int */ 138 int i = _data->intvalue; 139 140 /* Test for overflow. */ 141 if (i == INT_MIN) 142 __raise_overflow_error(); 143 144 /* Return the new integer. */ 145 return __new_int(-i); 146 } 147 148 __attr __fn_native_int_int_pow(__attr __args[]) 149 { 150 __attr * const _data = &__args[1]; 151 __attr * const other = &__args[2]; 152 /* _data and other interpreted as int */ 153 int i = _data->intvalue; 154 int j = other->intvalue; 155 int k; 156 157 errno = 0; 158 k = (int) pow(i, j); 159 160 /* Test for overflow. */ 161 162 if (errno == ERANGE) 163 __raise_overflow_error(); 164 165 /* Return the new integer. */ 166 return __new_int(k); 167 } 168 169 __attr __fn_native_int_int_and(__attr __args[]) 170 { 171 __attr * const _data = &__args[1]; 172 __attr * const other = &__args[2]; 173 /* _data and other interpreted as int */ 174 int i = _data->intvalue; 175 int j = other->intvalue; 176 177 /* Return the new integer. */ 178 /* NOTE: No overflow test applied. */ 179 return __new_int(i & j); 180 } 181 182 __attr __fn_native_int_int_not(__attr __args[]) 183 { 184 __attr * const _data = &__args[1]; 185 /* _data interpreted as int */ 186 int i = _data->intvalue; 187 188 /* Return the new integer. */ 189 return __new_int(~i); 190 } 191 192 __attr __fn_native_int_int_or(__attr __args[]) 193 { 194 __attr * const _data = &__args[1]; 195 __attr * const other = &__args[2]; 196 /* _data and other interpreted as int */ 197 int i = _data->intvalue; 198 int j = other->intvalue; 199 200 /* Return the new integer. */ 201 /* NOTE: No overflow test applied. */ 202 return __new_int(i | j); 203 } 204 205 __attr __fn_native_int_int_xor(__attr __args[]) 206 { 207 __attr * const _data = &__args[1]; 208 __attr * const other = &__args[2]; 209 /* _data and other interpreted as int */ 210 int i = _data->intvalue; 211 int j = other->intvalue; 212 213 /* Return the new integer. */ 214 /* NOTE: No overflow test applied. */ 215 return __new_int(i ^ j); 216 } 217 218 __attr __fn_native_int_int_lt(__attr __args[]) 219 { 220 __attr * const _data = &__args[1]; 221 __attr * const other = &__args[2]; 222 /* _data and other interpreted as int */ 223 int i = _data->intvalue; 224 int j = other->intvalue; 225 226 /* Return a boolean result. */ 227 return i < j ? __builtins___boolean_True : __builtins___boolean_False; 228 } 229 230 __attr __fn_native_int_int_gt(__attr __args[]) 231 { 232 __attr * const _data = &__args[1]; 233 __attr * const other = &__args[2]; 234 /* _data and other interpreted as int */ 235 int i = _data->intvalue; 236 int j = other->intvalue; 237 238 /* Return a boolean result. */ 239 return i > j ? __builtins___boolean_True : __builtins___boolean_False; 240 } 241 242 __attr __fn_native_int_int_eq(__attr __args[]) 243 { 244 __attr * const _data = &__args[1]; 245 __attr * const other = &__args[2]; 246 /* _data and other interpreted as int */ 247 int i = _data->intvalue; 248 int j = other->intvalue; 249 250 /* Return a boolean result. */ 251 return i == j ? __builtins___boolean_True : __builtins___boolean_False; 252 } 253 254 __attr __fn_native_int_int_ne(__attr __args[]) 255 { 256 __attr * const _data = &__args[1]; 257 __attr * const other = &__args[2]; 258 /* _data and other interpreted as int */ 259 int i = _data->intvalue; 260 int j = other->intvalue; 261 262 /* Return a boolean result. */ 263 return i != j ? __builtins___boolean_True : __builtins___boolean_False; 264 } 265 266 __attr __fn_native_int_int_str(__attr __args[]) 267 { 268 __attr * const _data = &__args[1]; 269 /* _data interpreted as int */ 270 int i = _data->intvalue; 271 /* Employ a buffer big enough to fit the largest integer plus an extra 272 character, a minus sign, and the null terminator. */ 273 unsigned int n = (int) log10(INT_MAX) + 3; 274 char *s = (char *) __ALLOCATE(n, sizeof(char)); 275 276 snprintf(s, n, "%d", i); 277 278 /* Return a new string. */ 279 return __new_str(s, strlen(s)); 280 } 281 282 /* Module initialisation. */ 283 284 void __main_native_int() 285 { 286 }