Added range checking for addition, subtraction, negation and division in the occam support headers
This commit is contained in:
parent
1b51eb5d63
commit
fdeab43b3c
|
@ -83,7 +83,7 @@ static inline int occam_check_index (int i, int limit, const char *pos) {
|
||||||
static inline int occam_check_index_lower (int, const char *) occam_unused;
|
static inline int occam_check_index_lower (int, const char *) occam_unused;
|
||||||
static inline int occam_check_index_lower (int i, const char *pos) {
|
static inline int occam_check_index_lower (int i, const char *pos) {
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
occam_stop (pos, 3, "invalid array index %d (should be 0 <= i)", i);
|
occam_stop (pos, 2, "invalid array index %d (should be 0 <= i)", i);
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -112,21 +112,38 @@ static inline int occam_check_retype (int src, int dest, const char *pos) {
|
||||||
} \
|
} \
|
||||||
return n; \
|
return n; \
|
||||||
}
|
}
|
||||||
|
// Some things taken from http://www.fefe.de/intof.html
|
||||||
|
|
||||||
|
#define __HALF_MAX_SIGNED(type) ((type)1 << (sizeof(type)*8-2))
|
||||||
|
#define __MAX_SIGNED(type) (__HALF_MAX_SIGNED(type) - 1 + __HALF_MAX_SIGNED(type))
|
||||||
|
#define __MIN_SIGNED(type) (-1 - __MAX_SIGNED(type))
|
||||||
|
|
||||||
|
#define __MIN(type) ((type)-1 < 1?__MIN_SIGNED(type):(type)0)
|
||||||
|
#define __MAX(type) ((type)~__MIN(type))
|
||||||
|
|
||||||
// FIXME All of these need to check for overflow and report errors appropriately.
|
// FIXME All of these need to check for overflow and report errors appropriately.
|
||||||
#define MAKE_ADD(type) \
|
#define MAKE_ADD(type) \
|
||||||
static inline type occam_add_##type (type, type, const char *) occam_unused; \
|
static inline type occam_add_##type (type, type, const char *) occam_unused; \
|
||||||
static inline type occam_add_##type (type a, type b, const char *pos) { \
|
static inline type occam_add_##type (type a, type b, const char *pos) { \
|
||||||
return a + b; \
|
if (((b<1)&&(__MIN(type)-b<=a)) || ((b>=1)&&(__MAX(type)-b>=a))) {return a + b;} \
|
||||||
|
else { occam_stop(pos, 3, "integer overflow when doing %d + %d", a, b); return 0; } \
|
||||||
}
|
}
|
||||||
|
#define MAKE_ADDF(type) \
|
||||||
|
static inline type occam_add_##type (type, type, const char *) occam_unused; \
|
||||||
|
static inline type occam_add_##type (type a, type b, const char *pos) { return a + b;}
|
||||||
#define MAKE_SUBTR(type) \
|
#define MAKE_SUBTR(type) \
|
||||||
static inline type occam_subtr_##type (type, type, const char *) occam_unused; \
|
static inline type occam_subtr_##type (type, type, const char *) occam_unused; \
|
||||||
static inline type occam_subtr_##type (type a, type b, const char *pos) { \
|
static inline type occam_subtr_##type (type a, type b, const char *pos) { \
|
||||||
return a - b; \
|
if (((b<1)&&(__MAX(type)+b>=a)) || ((b>=1)&&(__MIN(type)+b<=a))) {return a - b;} \
|
||||||
|
else { occam_stop(pos, 3, "integer overflow when doing %d - %d", a, b); } \
|
||||||
}
|
}
|
||||||
|
#define MAKE_SUBTRF(type) \
|
||||||
|
static inline type occam_subtr_##type (type, type, const char *) occam_unused; \
|
||||||
|
static inline type occam_subtr_##type (type a, type b, const char *pos) { return a - b;}
|
||||||
#define MAKE_MUL(type) \
|
#define MAKE_MUL(type) \
|
||||||
static inline type occam_mul_##type (type, type, const char *) occam_unused; \
|
static inline type occam_mul_##type (type, type, const char *) occam_unused; \
|
||||||
static inline type occam_mul_##type (type a, type b, const char *pos) { \
|
static inline type occam_mul_##type (type a, type b, const char *pos) { \
|
||||||
return a * b; \
|
return a * b; /*TODO*/ \
|
||||||
}
|
}
|
||||||
#define MAKE_DIV(type) \
|
#define MAKE_DIV(type) \
|
||||||
static inline type occam_div_##type (type, type, const char *) occam_unused; \
|
static inline type occam_div_##type (type, type, const char *) occam_unused; \
|
||||||
|
@ -134,13 +151,24 @@ static inline int occam_check_retype (int src, int dest, const char *pos) {
|
||||||
if (b == 0) { \
|
if (b == 0) { \
|
||||||
occam_stop (pos, 1, "divide by zero"); \
|
occam_stop (pos, 1, "divide by zero"); \
|
||||||
} \
|
} \
|
||||||
return a / b; \
|
else if (b == -1 && a == __MIN(type)) /* only overflow I can think of */ { \
|
||||||
|
occam_stop (pos, 1, "overflow in division"); \
|
||||||
|
} else { return a / b; } \
|
||||||
}
|
}
|
||||||
|
#define MAKE_DIVF(type) \
|
||||||
|
static inline type occam_div_##type (type, type, const char *) occam_unused; \
|
||||||
|
static inline type occam_div_##type (type a, type b, const char *pos) { return a / b;}
|
||||||
#define MAKE_NEGATE(type) \
|
#define MAKE_NEGATE(type) \
|
||||||
static inline type occam_negate_##type (type, const char *) occam_unused; \
|
static inline type occam_negate_##type (type, const char *) occam_unused; \
|
||||||
static inline type occam_negate_##type (type a, const char *pos) { \
|
static inline type occam_negate_##type (type a, const char *pos) { \
|
||||||
return - a; \
|
if (a == __MIN(type)) { \
|
||||||
|
occam_stop (pos, 1, "overflow in negation"); \
|
||||||
|
} else {return - a;} \
|
||||||
}
|
}
|
||||||
|
#define MAKE_NEGATEF(type) \
|
||||||
|
static inline type occam_negate_##type (type, const char *) occam_unused; \
|
||||||
|
static inline type occam_negate_##type (type a, const char *pos) { return - a; }
|
||||||
|
|
||||||
// occam's \ doesn't behave like C's %; it handles negative arguments.
|
// occam's \ doesn't behave like C's %; it handles negative arguments.
|
||||||
// (Effectively it ignores signs coming in, and the output sign is the sign of
|
// (Effectively it ignores signs coming in, and the output sign is the sign of
|
||||||
// the first argument.)
|
// the first argument.)
|
||||||
|
@ -264,20 +292,20 @@ MAKE_ALL_SIGNED(int64_t, "%lld", uint64_t)
|
||||||
// FIXME range checks for float and double shouldn't work this way
|
// FIXME range checks for float and double shouldn't work this way
|
||||||
//{{{ float
|
//{{{ float
|
||||||
MAKE_RANGE_CHECK(float, "%f")
|
MAKE_RANGE_CHECK(float, "%f")
|
||||||
MAKE_ADD(float)
|
MAKE_ADDF(float)
|
||||||
MAKE_SUBTR(float)
|
MAKE_SUBTRF(float)
|
||||||
MAKE_MUL(float)
|
MAKE_MUL(float)
|
||||||
MAKE_DIV(float)
|
MAKE_DIVF(float)
|
||||||
MAKE_NEGATE(float)
|
MAKE_NEGATEF(float)
|
||||||
MAKE_DUMB_REM(float)
|
MAKE_DUMB_REM(float)
|
||||||
//}}}
|
//}}}
|
||||||
//{{{ double
|
//{{{ double
|
||||||
MAKE_RANGE_CHECK(double, "%f")
|
MAKE_RANGE_CHECK(double, "%f")
|
||||||
MAKE_ADD(double)
|
MAKE_ADDF(double)
|
||||||
MAKE_SUBTR(double)
|
MAKE_SUBTRF(double)
|
||||||
MAKE_MUL(double)
|
MAKE_MUL(double)
|
||||||
MAKE_DIV(double)
|
MAKE_DIVF(double)
|
||||||
MAKE_NEGATE(double)
|
MAKE_NEGATEF(double)
|
||||||
MAKE_DUMB_REM(double)
|
MAKE_DUMB_REM(double)
|
||||||
//}}}
|
//}}}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user