1
0
mirror of https://github.com/janet-lang/janet synced 2024-11-25 01:37:19 +00:00

Fix dst_arg_bytes macro to correctly catch bad input.

This commit is contained in:
Calvin Rose 2018-05-09 23:43:56 -04:00
parent dcb903ffa6
commit ac4b46bdb1
2 changed files with 48 additions and 94 deletions

View File

@ -25,21 +25,23 @@
/* Get a random number */ /* Get a random number */
int dst_rand(DstArgs args) { int dst_rand(DstArgs args) {
dst_fixarity(args, 0);
double r = (rand() % RAND_MAX) / ((double) RAND_MAX); double r = (rand() % RAND_MAX) / ((double) RAND_MAX);
return dst_return(args, dst_wrap_real(r)); return dst_return(args, dst_wrap_real(r));
} }
/* Seed the random number generator */ /* Seed the random number generator */
int dst_srand(DstArgs args) { int dst_srand(DstArgs args) {
if (args.n != 1 || !dst_checktype(args.v[0], DST_INTEGER)) int32_t x = 0;
return dst_throw(args, "expected integer"); dst_fixarity(args, 0);
srand((unsigned) dst_unwrap_integer(args.v[0])); dst_arg_integer(x, args, 0);
return 0; srand((unsigned) x);
return 0;
} }
/* Convert a number to an integer */ /* Convert a number to an integer */
int dst_int(DstArgs args) { int dst_int(DstArgs args) {
if (args.n != 1) return dst_throw(args, "expected one argument"); dst_fixarity(args, 1);
switch (dst_type(args.v[0])) { switch (dst_type(args.v[0])) {
default: default:
return dst_throw(args, "could not convert to integer"); return dst_throw(args, "could not convert to integer");
@ -55,7 +57,7 @@ int dst_int(DstArgs args) {
/* Convert a number to a real number */ /* Convert a number to a real number */
int dst_real(DstArgs args) { int dst_real(DstArgs args) {
if (args.n != 1) return dst_throw(args, "expected one argument"); dst_fixarity(args, 1);
switch (dst_type(args.v[0])) { switch (dst_type(args.v[0])) {
default: default:
return dst_throw(args, "could not convert to real"); return dst_throw(args, "could not convert to real");
@ -197,47 +199,35 @@ DST_DEFINE_BITOP(bor, |=, 0)
DST_DEFINE_BITOP(bxor, ^=, 0) DST_DEFINE_BITOP(bxor, ^=, 0)
int dst_lshift(DstArgs args) { int dst_lshift(DstArgs args) {
if (args.n != 2 || !dst_checktype(args.v[0], DST_INTEGER) || !dst_checktype(args.v[1], DST_INTEGER)) { int32_t lhs, rhs;
*args.ret = dst_cstringv("expected 2 integers"); dst_fixarity(args, 2);
return 1; dst_arg_integer(lhs, args, 0);
} dst_arg_integer(rhs, args, 1);
*args.ret = dst_wrap_integer(dst_unwrap_integer(args.v[0]) >> dst_unwrap_integer(args.v[1])); return dst_return(args, dst_wrap_integer(lhs >> rhs));
return 0;
} }
int dst_rshift(DstArgs args) { int dst_rshift(DstArgs args) {
if (args.n != 2 || !dst_checktype(args.v[0], DST_INTEGER) || !dst_checktype(args.v[1], DST_INTEGER)) { int32_t lhs, rhs;
*args.ret = dst_cstringv("expected 2 integers"); dst_fixarity(args, 2);
return 1; dst_arg_integer(lhs, args, 0);
} dst_arg_integer(rhs, args, 1);
*args.ret = dst_wrap_integer(dst_unwrap_integer(args.v[0]) << dst_unwrap_integer(args.v[1])); return dst_return(args, dst_wrap_integer(lhs << rhs));
return 0;
} }
int dst_lshiftu(DstArgs args) { int dst_lshiftu(DstArgs args) {
if (args.n != 2 || !dst_checktype(args.v[0], DST_INTEGER) || !dst_checktype(args.v[1], DST_INTEGER)) { int32_t lhs, rhs;
*args.ret = dst_cstringv("expected 2 integers"); dst_fixarity(args, 2);
return 1; dst_arg_integer(lhs, args, 0);
} dst_arg_integer(rhs, args, 1);
*args.ret = dst_wrap_integer((int32_t)((uint32_t)dst_unwrap_integer(args.v[0]) >> dst_unwrap_integer(args.v[1]))); return dst_return(args, dst_wrap_integer((int32_t)((uint32_t)lhs << rhs)));
return 0;
} }
#define DST_DEFINE_MATHOP(name, fop)\ #define DST_DEFINE_MATHOP(name, fop)\
int dst_##name(DstArgs args) {\ int dst_##name(DstArgs args) {\
if (args.n != 1) {\ double x;\
*args.ret = dst_cstringv("expected 1 argument");\ dst_fixarity(args, 1);\
return 1;\ dst_arg_number(x, args, 0);\
}\ return dst_return(args, dst_wrap_real(fop(x)));\
if (dst_checktype(args.v[0], DST_INTEGER)) {\
args.v[0] = dst_wrap_real(dst_unwrap_integer(args.v[0]));\
}\
if (!dst_checktype(args.v[0], DST_REAL)) {\
*args.ret = dst_cstringv("expected number");\
return 1;\
}\
*args.ret = dst_wrap_real(fop(dst_unwrap_real(args.v[0])));\
return 0;\
} }
DST_DEFINE_MATHOP(acos, acos) DST_DEFINE_MATHOP(acos, acos)
@ -259,21 +249,11 @@ DST_DEFINE_MATHOP(floor, floor)
#define DST_DEFINE_MATH2OP(name, fop)\ #define DST_DEFINE_MATH2OP(name, fop)\
int dst_##name(DstArgs args) {\ int dst_##name(DstArgs args) {\
if (args.n != 2) {\ double lhs, rhs;\
*args.ret = dst_cstringv("expected 2 arguments");\ dst_fixarity(args, 2);\
return 1;\ dst_arg_number(lhs, args, 0);\
}\ dst_arg_number(rhs, args, 1);\
if (dst_checktype(args.v[0], DST_INTEGER))\ return dst_return(args, dst_wrap_real(fop(lhs, rhs)));\
args.v[0] = dst_wrap_real(dst_unwrap_integer(args.v[0]));\
if (dst_checktype(args.v[1], DST_INTEGER))\
args.v[1] = dst_wrap_real(dst_unwrap_integer(args.v[1]));\
if (!dst_checktype(args.v[0], DST_REAL) || !dst_checktype(args.v[1], DST_REAL)) {\
*args.ret = dst_cstringv("expected real");\
return 1;\
}\
*args.ret =\
dst_wrap_real(fop(dst_unwrap_real(args.v[0]), dst_unwrap_real(args.v[1])));\
return 0;\
}\ }\
DST_DEFINE_MATH2OP(atan2, atan2) DST_DEFINE_MATH2OP(atan2, atan2)
@ -281,20 +261,12 @@ DST_DEFINE_MATH2OP(pow, pow)
DST_DEFINE_MATH2OP(fmod, fmod) DST_DEFINE_MATH2OP(fmod, fmod)
int dst_modf(DstArgs args) { int dst_modf(DstArgs args) {
double intpart; double x, intpart;
Dst *tup; Dst *tup;
if (args.n != 1) { dst_fixarity(args, 1);
*args.ret = dst_cstringv("expected 1 argument"); dst_arg_number(x, args, 0);
return 1;
}
if (dst_checktype(args.v[0], DST_INTEGER))
args.v[0] = dst_wrap_real(dst_unwrap_integer(args.v[0]));
if (!dst_checktype(args.v[0], DST_REAL)) {
*args.ret = dst_cstringv("expected real");
return 1;
}
tup = dst_tuple_begin(2); tup = dst_tuple_begin(2);
tup[0] = dst_wrap_real(modf(dst_unwrap_real(args.v[0]), &intpart)); tup[0] = dst_wrap_real(modf(x, &intpart));
tup[1] = dst_wrap_real(intpart); tup[1] = dst_wrap_real(intpart);
*args.ret = dst_wrap_tuple(dst_tuple_end(tup)); *args.ret = dst_wrap_tuple(dst_tuple_end(tup));
return 0; return 0;
@ -324,52 +296,34 @@ static int dst_strict_equal(DstArgs args) {
int32_t i; int32_t i;
for (i = 0; i < args.n - 1; i++) { for (i = 0; i < args.n - 1; i++) {
if (!dst_equals(args.v[i], args.v[i+1])) { if (!dst_equals(args.v[i], args.v[i+1])) {
*args.ret = dst_wrap_false(); return dst_return(args, dst_wrap_false());
return 0;
} }
} }
*args.ret = dst_wrap_true(); return dst_return(args, dst_wrap_true());
return 0;
} }
static int dst_strict_notequal(DstArgs args) { static int dst_strict_notequal(DstArgs args) {
int32_t i; int32_t i;
for (i = 0; i < args.n - 1; i++) { for (i = 0; i < args.n - 1; i++) {
if (dst_equals(args.v[i], args.v[i+1])) { if (dst_equals(args.v[i], args.v[i+1])) {
*args.ret = dst_wrap_false(); return dst_return(args, dst_wrap_false());
return 0;
} }
} }
*args.ret = dst_wrap_true(); return dst_return(args, dst_wrap_true());
return 0;
} }
static int dst_not(DstArgs args) { static int dst_not(DstArgs args) {
*args.ret = dst_wrap_boolean(args.n == 0 || !dst_truthy(args.v[0])); dst_fixarity(args, 1);
return 0; return dst_return(args, dst_wrap_boolean(!dst_truthy(args.v[0])));
}
static int toreal(Dst x, double *out) {
if (dst_checktype(x, DST_REAL)) {
*out = dst_unwrap_real(x);
return 0;
} else if (dst_checktype(x, DST_INTEGER)) {
*out = (double)dst_unwrap_integer(x);
return 0;
} else {
return -1;
}
} }
#define DEF_NUMERIC_COMP(name, op) \ #define DEF_NUMERIC_COMP(name, op) \
int dst_numeric_##name(DstArgs args) { \ int dst_numeric_##name(DstArgs args) { \
int32_t i; \ int32_t i; \
for (i = 1; i < args.n; i++) { \ for (i = 1; i < args.n; i++) { \
int xbad, ybad; \ double x = 0, y = 0; \
double x, y; \ dst_arg_number(x, args, i-1);\
xbad = toreal(args.v[0], &x); \ dst_arg_number(y, args, i);\
ybad = toreal(args.v[1], &y); \
if (xbad | ybad) return dst_throw(args, "expected number"); \
if (!(x op y)) { \ if (!(x op y)) { \
return dst_return(args, dst_wrap_false()); \ return dst_return(args, dst_wrap_false()); \
} \ } \

View File

@ -245,7 +245,7 @@ int dst_typeabstract_err(DstArgs args, int32_t n, const DstAbstractType *at);
Dst val = (A).v[(N)];\ Dst val = (A).v[(N)];\
if (dst_checktype(val, DST_REAL)) { DEST = dst_unwrap_real(val); }\ if (dst_checktype(val, DST_REAL)) { DEST = dst_unwrap_real(val); }\
else if (dst_checktype(val, DST_INTEGER)) { DEST = (double) dst_unwrap_integer(val); }\ else if (dst_checktype(val, DST_INTEGER)) { DEST = (double) dst_unwrap_integer(val); }\
else dst_typemany_err(A, N, DST_TFLAG_NUMBER); } while (0) else return dst_typemany_err(A, N, DST_TFLAG_NUMBER); } while (0)
#define dst_arg_boolean(DEST, A, N) do { \ #define dst_arg_boolean(DEST, A, N) do { \
dst_checkmany(A, N, DST_TFLAG_TRUE | DST_TFLAG_FALSE);\ dst_checkmany(A, N, DST_TFLAG_TRUE | DST_TFLAG_FALSE);\
@ -257,8 +257,8 @@ int dst_typeabstract_err(DstArgs args, int32_t n, const DstAbstractType *at);
#define dst_arg_bytes(DESTBYTES, DESTLEN, A, N) do {\ #define dst_arg_bytes(DESTBYTES, DESTLEN, A, N) do {\
if ((A).n <= (N)) return dst_typemany_err(A, N, DST_TFLAG_BYTES);\ if ((A).n <= (N)) return dst_typemany_err(A, N, DST_TFLAG_BYTES);\
if (dst_chararray_view((A).v[(N)], &(DESTBYTES), &(DESTLEN))) {\ if (!dst_chararray_view((A).v[(N)], &(DESTBYTES), &(DESTLEN))) {\
dst_typemany_err(A, N, DST_TFLAG_BYTES);\ return dst_typemany_err(A, N, DST_TFLAG_BYTES);\
}\ }\
} while (0) } while (0)