From bcd9ec5103a2be29face2bacfe44187ba8b1bd30 Mon Sep 17 00:00:00 2001 From: sebres Date: Mon, 4 Feb 2019 09:21:25 +0000 Subject: partial cherry pick of [c5c83014d6]: Many simplifications in tclExecute.c, now that libtommath provides new functions mp_tc_and, mp_tc_or and mp_tc_xor --- generic/tclExecute.c | 126 ++-------------------------------------------- generic/tclStubInit.c | 3 ++ generic/tclTomMath.decls | 11 ++++ generic/tclTomMathDecls.h | 21 ++++++++ unix/Makefile.in | 15 +++++- win/Makefile.in | 3 ++ win/makefile.vc | 3 ++ 7 files changed, 60 insertions(+), 122 deletions(-) diff --git a/generic/tclExecute.c b/generic/tclExecute.c index fafd511..89e61b8 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -8292,7 +8292,7 @@ ExecuteExtendedBinaryMathOp( Tcl_WideInt w1, w2, wResult; mp_int big1, big2, bigResult, bigRemainder; Tcl_Obj *objResultPtr; - int invalid, numPos, zero; + int invalid, zero; long shift; (void) GetNumberFromObj(NULL, valuePtr, &ptr1, &type1); @@ -8321,7 +8321,7 @@ ExecuteExtendedBinaryMathOp( w1 = *((const Tcl_WideInt *)ptr1); if (type2 != TCL_NUMBER_BIG) { Tcl_WideInt wQuotient, wRemainder; - Tcl_GetWideIntFromObj(NULL, value2Ptr, &w2); + TclGetWideIntFromObj(NULL, value2Ptr, &w2); wQuotient = w1 / w2; /* @@ -8539,138 +8539,22 @@ ExecuteExtendedBinaryMathOp( case INST_BITXOR: case INST_BITAND: if ((type1 == TCL_NUMBER_BIG) || (type2 == TCL_NUMBER_BIG)) { - mp_int *First, *Second; - Tcl_TakeBignumFromObj(NULL, valuePtr, &big1); Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); - /* - * Count how many positive arguments we have. If only one of the - * arguments is negative, store it in 'Second'. - */ - - if (mp_cmp_d(&big1, 0) != MP_LT) { - numPos = 1 + (mp_cmp_d(&big2, 0) != MP_LT); - First = &big1; - Second = &big2; - } else { - First = &big2; - Second = &big1; - numPos = (mp_cmp_d(First, 0) != MP_LT); - } mp_init(&bigResult); switch (opcode) { case INST_BITAND: - switch (numPos) { - case 2: - /* - * Both arguments positive, base case. - */ - - mp_and(First, Second, &bigResult); - break; - case 1: - /* - * First is positive; second negative: - * P & N = P & ~~N = P&~(-N-1) = P & (P ^ (-N-1)) - */ - - mp_neg(Second, Second); - mp_sub_d(Second, 1, Second); - mp_xor(First, Second, &bigResult); - mp_and(First, &bigResult, &bigResult); - break; - case 0: - /* - * Both arguments negative: - * a & b = ~ (~a | ~b) = -(-a-1|-b-1)-1 - */ - - mp_neg(First, First); - mp_sub_d(First, 1, First); - mp_neg(Second, Second); - mp_sub_d(Second, 1, Second); - mp_or(First, Second, &bigResult); - mp_neg(&bigResult, &bigResult); - mp_sub_d(&bigResult, 1, &bigResult); - break; - } + mp_tc_and(&big1, &big2, &bigResult); break; case INST_BITOR: - switch (numPos) { - case 2: - /* - * Both arguments positive, base case. - */ - - mp_or(First, Second, &bigResult); - break; - case 1: - /* - * First is positive; second negative: - * N|P = ~(~N&~P) = ~((-N-1)&~P) = -((-N-1)&((-N-1)^P))-1 - */ - - mp_neg(Second, Second); - mp_sub_d(Second, 1, Second); - mp_xor(First, Second, &bigResult); - mp_and(Second, &bigResult, &bigResult); - mp_neg(&bigResult, &bigResult); - mp_sub_d(&bigResult, 1, &bigResult); - break; - case 0: - /* - * Both arguments negative: - * a | b = ~ (~a & ~b) = -(-a-1&-b-1)-1 - */ - - mp_neg(First, First); - mp_sub_d(First, 1, First); - mp_neg(Second, Second); - mp_sub_d(Second, 1, Second); - mp_and(First, Second, &bigResult); - mp_neg(&bigResult, &bigResult); - mp_sub_d(&bigResult, 1, &bigResult); - break; - } + mp_tc_or(&big1, &big2, &bigResult); break; case INST_BITXOR: - switch (numPos) { - case 2: - /* - * Both arguments positive, base case. - */ - - mp_xor(First, Second, &bigResult); - break; - case 1: - /* - * First is positive; second negative: - * P^N = ~(P^~N) = -(P^(-N-1))-1 - */ - - mp_neg(Second, Second); - mp_sub_d(Second, 1, Second); - mp_xor(First, Second, &bigResult); - mp_neg(&bigResult, &bigResult); - mp_sub_d(&bigResult, 1, &bigResult); - break; - case 0: - /* - * Both arguments negative: - * a ^ b = (~a ^ ~b) = (-a-1^-b-1) - */ - - mp_neg(First, First); - mp_sub_d(First, 1, First); - mp_neg(Second, Second); - mp_sub_d(Second, 1, Second); - mp_xor(First, Second, &bigResult); - break; - } + mp_tc_xor(&big1, &big2, &bigResult); break; } diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index 3de8de1..ced89c0 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -850,6 +850,9 @@ const TclTomMathStubs tclTomMathStubs = { TclBNInitBignumFromWideInt, /* 65 */ TclBNInitBignumFromWideUInt, /* 66 */ TclBN_mp_expt_d_ex, /* 67 */ + TclBN_mp_tc_and, /* 73 */ + TclBN_mp_tc_or, /* 74 */ + TclBN_mp_tc_xor, /* 75 */ }; static const TclStubHooks tclStubHooks = { diff --git a/generic/tclTomMath.decls b/generic/tclTomMath.decls index 065fe09..6650067 100644 --- a/generic/tclTomMath.decls +++ b/generic/tclTomMath.decls @@ -238,6 +238,17 @@ declare 67 { int TclBN_mp_expt_d_ex(const mp_int *a, mp_digit b, mp_int *c, int fast) } +# Added in libtommath 1.1.0 +declare 73 { + int TclBN_mp_tc_and(const mp_int *a, const mp_int *b, mp_int *c) +} +declare 74 { + int TclBN_mp_tc_or(const mp_int *a, const mp_int *b, mp_int *c) +} +declare 75 { + int TclBN_mp_tc_xor(const mp_int *a, const mp_int *b, mp_int *c) +} + # Local Variables: # mode: tcl # End: diff --git a/generic/tclTomMathDecls.h b/generic/tclTomMathDecls.h index 81cd7c9..18739cd 100644 --- a/generic/tclTomMathDecls.h +++ b/generic/tclTomMathDecls.h @@ -102,6 +102,9 @@ #define mp_sqrt TclBN_mp_sqrt #define mp_sub TclBN_mp_sub #define mp_sub_d TclBN_mp_sub_d +#define mp_tc_and TclBN_mp_tc_and +#define mp_tc_or TclBN_mp_tc_or +#define mp_tc_xor TclBN_mp_tc_xor #define mp_to_unsigned_bin TclBN_mp_to_unsigned_bin #define mp_to_unsigned_bin_n TclBN_mp_to_unsigned_bin_n #define mp_toom_mul TclBN_mp_toom_mul @@ -307,6 +310,15 @@ EXTERN void TclBNInitBignumFromWideUInt(mp_int *bignum, /* 67 */ EXTERN int TclBN_mp_expt_d_ex(const mp_int *a, mp_digit b, mp_int *c, int fast); +/* 73 */ +EXTERN int TclBN_mp_tc_and(const mp_int *a, const mp_int *b, + mp_int *c); +/* 74 */ +EXTERN int TclBN_mp_tc_or(const mp_int *a, const mp_int *b, + mp_int *c); +/* 75 */ +EXTERN int TclBN_mp_tc_xor(const mp_int *a, const mp_int *b, + mp_int *c); typedef struct TclTomMathStubs { int magic; @@ -380,6 +392,9 @@ typedef struct TclTomMathStubs { void (*tclBNInitBignumFromWideInt) (mp_int *bignum, Tcl_WideInt initVal); /* 65 */ void (*tclBNInitBignumFromWideUInt) (mp_int *bignum, Tcl_WideUInt initVal); /* 66 */ int (*tclBN_mp_expt_d_ex) (const mp_int *a, mp_digit b, mp_int *c, int fast); /* 67 */ + int (*tclBN_mp_tc_and) (const mp_int *a, const mp_int *b, mp_int *c); /* 73 */ + int (*tclBN_mp_tc_or) (const mp_int *a, const mp_int *b, mp_int *c); /* 74 */ + int (*tclBN_mp_tc_xor) (const mp_int *a, const mp_int *b, mp_int *c); /* 75 */ } TclTomMathStubs; extern const TclTomMathStubs *tclTomMathStubsPtr; @@ -530,6 +545,12 @@ extern const TclTomMathStubs *tclTomMathStubsPtr; (tclTomMathStubsPtr->tclBNInitBignumFromWideUInt) /* 66 */ #define TclBN_mp_expt_d_ex \ (tclTomMathStubsPtr->tclBN_mp_expt_d_ex) /* 67 */ +#define TclBN_mp_tc_and \ + (tclTomMathStubsPtr->tclBN_mp_tc_and) /* 73 */ +#define TclBN_mp_tc_or \ + (tclTomMathStubsPtr->tclBN_mp_tc_or) /* 74 */ +#define TclBN_mp_tc_xor \ + (tclTomMathStubsPtr->tclBN_mp_tc_xor) /* 75 */ #endif /* defined(USE_TCL_STUBS) */ diff --git a/unix/Makefile.in b/unix/Makefile.in index d13c490..a5f942c 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -332,7 +332,8 @@ TOMMATH_OBJS = bncore.o bn_reverse.o bn_fast_s_mp_mul_digs.o \ bn_mp_read_radix.o bn_mp_rshd.o bn_mp_set.o bn_mp_set_int.o \ bn_mp_shrink.o \ bn_mp_sqr.o bn_mp_sqrt.o bn_mp_sub.o bn_mp_sub_d.o \ - bn_mp_to_unsigned_bin.o bn_mp_to_unsigned_bin_n.o \ + bn_mp_tc_and.o bn_mp_tc_or.o bn_mp_tc_xor.o \ + bn_mp_to_unsigned_bin.o bn_mp_to_unsigned_bin_n.o \ bn_mp_toom_mul.o bn_mp_toom_sqr.o bn_mp_toradix_n.o \ bn_mp_unsigned_bin_size.o bn_mp_xor.o bn_mp_zero.o bn_s_mp_add.o \ bn_s_mp_mul_digs.o bn_s_mp_sqr.o bn_s_mp_sub.o @@ -535,6 +536,9 @@ TOMMATH_SRCS = \ $(TOMMATH_DIR)/bn_mp_sqrt.c \ $(TOMMATH_DIR)/bn_mp_sub.c \ $(TOMMATH_DIR)/bn_mp_sub_d.c \ + $(TOMMATH_DIR)/bn_mp_tc_and.c \ + $(TOMMATH_DIR)/bn_mp_tc_or.c \ + $(TOMMATH_DIR)/bn_mp_tc_xor.c \ $(TOMMATH_DIR)/bn_mp_to_unsigned_bin.c \ $(TOMMATH_DIR)/bn_mp_to_unsigned_bin_n.c \ $(TOMMATH_DIR)/bn_mp_toom_mul.c \ @@ -1513,6 +1517,15 @@ bn_mp_sub.o: $(TOMMATH_DIR)/bn_mp_sub.c $(MATHHDRS) bn_mp_sub_d.o: $(TOMMATH_DIR)/bn_mp_sub_d.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_sub_d.c +bn_mp_tc_and.o: $(TOMMATH_DIR)/bn_mp_tc_and.c $(MATHHDRS) + $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_tc_and.c + +bn_mp_tc_or.o: $(TOMMATH_DIR)/bn_mp_tc_or.c $(MATHHDRS) + $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_tc_or.c + +bn_mp_tc_xor.o: $(TOMMATH_DIR)/bn_mp_tc_xor.c $(MATHHDRS) + $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_tc_xor.c + bn_mp_to_unsigned_bin.o: $(TOMMATH_DIR)/bn_mp_to_unsigned_bin.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_to_unsigned_bin.c diff --git a/win/Makefile.in b/win/Makefile.in index e6b9801..4d6011b 100644 --- a/win/Makefile.in +++ b/win/Makefile.in @@ -364,6 +364,9 @@ TOMMATH_OBJS = \ bn_mp_sqrt.${OBJEXT} \ bn_mp_sub.${OBJEXT} \ bn_mp_sub_d.${OBJEXT} \ + bn_mp_tc_and.${OBJEXT} \ + bn_mp_tc_or.${OBJEXT} \ + bn_mp_tc_xor.${OBJEXT} \ bn_mp_to_unsigned_bin.${OBJEXT} \ bn_mp_to_unsigned_bin_n.${OBJEXT} \ bn_mp_toom_mul.${OBJEXT} \ diff --git a/win/makefile.vc b/win/makefile.vc index a6709d1..a607aaf 100644 --- a/win/makefile.vc +++ b/win/makefile.vc @@ -304,6 +304,9 @@ TOMMATHOBJS = \ $(TMP_DIR)\bn_mp_sqrt.obj \ $(TMP_DIR)\bn_mp_sub.obj \ $(TMP_DIR)\bn_mp_sub_d.obj \ + $(TMP_DIR)\bn_mp_tc_and.obj \ + $(TMP_DIR)\bn_mp_tc_or.obj \ + $(TMP_DIR)\bn_mp_tc_xor.obj \ $(TMP_DIR)\bn_mp_to_unsigned_bin.obj \ $(TMP_DIR)\bn_mp_to_unsigned_bin_n.obj \ $(TMP_DIR)\bn_mp_toom_mul.obj \ -- cgit v0.12 From 08d4e75deb21fca30944b087b1fffd7ae542aab3 Mon Sep 17 00:00:00 2001 From: sebres Date: Mon, 4 Feb 2019 09:40:27 +0000 Subject: partial cherry pick of [e8e92eb381d689ab]: One more libtommath function, mp_tc_div_2d, which simplifies code. --- generic/tclExecute.c | 11 +---------- generic/tclStubInit.c | 1 + generic/tclTomMath.decls | 4 ++++ generic/tclTomMathDecls.h | 6 ++++++ unix/Makefile.in | 6 +++++- win/Makefile.in | 1 + win/makefile.vc | 1 + 7 files changed, 19 insertions(+), 11 deletions(-) diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 89e61b8..d1d729a 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -8520,16 +8520,7 @@ ExecuteExtendedBinaryMathOp( if (opcode == INST_LSHIFT) { mp_mul_2d(&big1, shift, &bigResult); } else { - mp_init(&bigRemainder); - mp_div_2d(&big1, shift, &bigResult, &bigRemainder); - if (mp_cmp_d(&bigRemainder, 0) == MP_LT) { - /* - * Convert to Tcl's integer division rules. - */ - - mp_sub_d(&bigResult, 1, &bigResult); - } - mp_clear(&bigRemainder); + mp_tc_div_2d(&big1, shift, &bigResult); } mp_clear(&big1); BIG_RESULT(&bigResult); diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index ced89c0..1a9a8d5 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -853,6 +853,7 @@ const TclTomMathStubs tclTomMathStubs = { TclBN_mp_tc_and, /* 73 */ TclBN_mp_tc_or, /* 74 */ TclBN_mp_tc_xor, /* 75 */ + TclBN_mp_tc_div_2d, /* 76 */ }; static const TclStubHooks tclStubHooks = { diff --git a/generic/tclTomMath.decls b/generic/tclTomMath.decls index 6650067..65178c3 100644 --- a/generic/tclTomMath.decls +++ b/generic/tclTomMath.decls @@ -248,6 +248,10 @@ declare 74 { declare 75 { int TclBN_mp_tc_xor(const mp_int *a, const mp_int *b, mp_int *c) } +declare 76 { + int TclBN_mp_tc_div_2d(const mp_int *a, int b, mp_int *c) +} + # Local Variables: # mode: tcl diff --git a/generic/tclTomMathDecls.h b/generic/tclTomMathDecls.h index 18739cd..d19df64 100644 --- a/generic/tclTomMathDecls.h +++ b/generic/tclTomMathDecls.h @@ -103,6 +103,7 @@ #define mp_sub TclBN_mp_sub #define mp_sub_d TclBN_mp_sub_d #define mp_tc_and TclBN_mp_tc_and +#define mp_tc_div_2d TclBN_mp_tc_div_2d #define mp_tc_or TclBN_mp_tc_or #define mp_tc_xor TclBN_mp_tc_xor #define mp_to_unsigned_bin TclBN_mp_to_unsigned_bin @@ -319,6 +320,8 @@ EXTERN int TclBN_mp_tc_or(const mp_int *a, const mp_int *b, /* 75 */ EXTERN int TclBN_mp_tc_xor(const mp_int *a, const mp_int *b, mp_int *c); +/* 76 */ +EXTERN int TclBN_mp_tc_div_2d(const mp_int *a, int b, mp_int *c); typedef struct TclTomMathStubs { int magic; @@ -395,6 +398,7 @@ typedef struct TclTomMathStubs { int (*tclBN_mp_tc_and) (const mp_int *a, const mp_int *b, mp_int *c); /* 73 */ int (*tclBN_mp_tc_or) (const mp_int *a, const mp_int *b, mp_int *c); /* 74 */ int (*tclBN_mp_tc_xor) (const mp_int *a, const mp_int *b, mp_int *c); /* 75 */ + int (*tclBN_mp_tc_div_2d) (const mp_int *a, int b, mp_int *c); /* 76 */ } TclTomMathStubs; extern const TclTomMathStubs *tclTomMathStubsPtr; @@ -551,6 +555,8 @@ extern const TclTomMathStubs *tclTomMathStubsPtr; (tclTomMathStubsPtr->tclBN_mp_tc_or) /* 74 */ #define TclBN_mp_tc_xor \ (tclTomMathStubsPtr->tclBN_mp_tc_xor) /* 75 */ +#define TclBN_mp_tc_div_2d \ + (tclTomMathStubsPtr->tclBN_mp_tc_div_2d) /* 76 */ #endif /* defined(USE_TCL_STUBS) */ diff --git a/unix/Makefile.in b/unix/Makefile.in index a5f942c..71f7ec8 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -332,7 +332,7 @@ TOMMATH_OBJS = bncore.o bn_reverse.o bn_fast_s_mp_mul_digs.o \ bn_mp_read_radix.o bn_mp_rshd.o bn_mp_set.o bn_mp_set_int.o \ bn_mp_shrink.o \ bn_mp_sqr.o bn_mp_sqrt.o bn_mp_sub.o bn_mp_sub_d.o \ - bn_mp_tc_and.o bn_mp_tc_or.o bn_mp_tc_xor.o \ + bn_mp_tc_and.o bn_mp_tc_div_2d.o bn_mp_tc_or.o bn_mp_tc_xor.o \ bn_mp_to_unsigned_bin.o bn_mp_to_unsigned_bin_n.o \ bn_mp_toom_mul.o bn_mp_toom_sqr.o bn_mp_toradix_n.o \ bn_mp_unsigned_bin_size.o bn_mp_xor.o bn_mp_zero.o bn_s_mp_add.o \ @@ -537,6 +537,7 @@ TOMMATH_SRCS = \ $(TOMMATH_DIR)/bn_mp_sub.c \ $(TOMMATH_DIR)/bn_mp_sub_d.c \ $(TOMMATH_DIR)/bn_mp_tc_and.c \ + $(TOMMATH_DIR)/bn_mp_tc_div_2d.c \ $(TOMMATH_DIR)/bn_mp_tc_or.c \ $(TOMMATH_DIR)/bn_mp_tc_xor.c \ $(TOMMATH_DIR)/bn_mp_to_unsigned_bin.c \ @@ -1520,6 +1521,9 @@ bn_mp_sub_d.o: $(TOMMATH_DIR)/bn_mp_sub_d.c $(MATHHDRS) bn_mp_tc_and.o: $(TOMMATH_DIR)/bn_mp_tc_and.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_tc_and.c +bn_mp_tc_div_2d.o: $(TOMMATH_DIR)/bn_mp_tc_div_2d.c $(MATHHDRS) + $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_tc_div_2d.c + bn_mp_tc_or.o: $(TOMMATH_DIR)/bn_mp_tc_or.c $(MATHHDRS) $(CC) -c $(CC_SWITCHES) $(TOMMATH_DIR)/bn_mp_tc_or.c diff --git a/win/Makefile.in b/win/Makefile.in index 4d6011b..ab19070 100644 --- a/win/Makefile.in +++ b/win/Makefile.in @@ -365,6 +365,7 @@ TOMMATH_OBJS = \ bn_mp_sub.${OBJEXT} \ bn_mp_sub_d.${OBJEXT} \ bn_mp_tc_and.${OBJEXT} \ + bn_mp_tc_div_2d.${OBJEXT} \ bn_mp_tc_or.${OBJEXT} \ bn_mp_tc_xor.${OBJEXT} \ bn_mp_to_unsigned_bin.${OBJEXT} \ diff --git a/win/makefile.vc b/win/makefile.vc index a607aaf..ae690fe 100644 --- a/win/makefile.vc +++ b/win/makefile.vc @@ -305,6 +305,7 @@ TOMMATHOBJS = \ $(TMP_DIR)\bn_mp_sub.obj \ $(TMP_DIR)\bn_mp_sub_d.obj \ $(TMP_DIR)\bn_mp_tc_and.obj \ + $(TMP_DIR)\bn_mp_tc_div_2d.obj \ $(TMP_DIR)\bn_mp_tc_or.obj \ $(TMP_DIR)\bn_mp_tc_xor.obj \ $(TMP_DIR)\bn_mp_to_unsigned_bin.obj \ -- cgit v0.12 From cf1edde4f6ffcfc364e93eb473458915c595b14b Mon Sep 17 00:00:00 2001 From: sebres Date: Mon, 4 Feb 2019 12:24:58 +0000 Subject: cherry pick of [238bd4d2c053540c]..[31dd092df4b57fdb]: More simplifications in tclExecute.c (INST_EXPON), much more and well-arranged branching of long/wide/bignum base and exponent cases, test-cases extended to cover all this branches and edge cases. --- generic/tclExecute.c | 328 ++++++++++++++++++++++++++++----------------------- tests/mathop.test | 30 ++++- 2 files changed, 206 insertions(+), 152 deletions(-) diff --git a/generic/tclExecute.c b/generic/tclExecute.c index d1d729a..4a1dbfa 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -8222,6 +8222,126 @@ FinalizeOONextFilter( } /* + * LongPwrSmallExpon -- , WidePwrSmallExpon -- + * + * Helpers to calculate small powers of integers whose result is long or wide. + */ +static inline long +LongPwrSmallExpon(long l1, long exponent) { + + long lResult; + + lResult = l1 * l1; /* b**2 */ + switch (exponent) { + case 2: + break; + case 3: + lResult *= l1; /* b**3 */ + break; + case 4: + lResult *= lResult; /* b**4 */ + break; + case 5: + lResult *= lResult; /* b**4 */ + lResult *= l1; /* b**5 */ + break; + case 6: + lResult *= l1; /* b**3 */ + lResult *= lResult; /* b**6 */ + break; + case 7: + lResult *= l1; /* b**3 */ + lResult *= lResult; /* b**6 */ + lResult *= l1; /* b**7 */ + break; + case 8: + lResult *= lResult; /* b**4 */ + lResult *= lResult; /* b**8 */ + break; + } + return lResult; +} +static inline Tcl_WideInt +WidePwrSmallExpon(Tcl_WideInt w1, long exponent) { + + Tcl_WideInt wResult; + + wResult = w1 * w1; /* b**2 */ + switch (exponent) { + case 2: + break; + case 3: + wResult *= w1; /* b**3 */ + break; + case 4: + wResult *= wResult; /* b**4 */ + break; + case 5: + wResult *= wResult; /* b**4 */ + wResult *= w1; /* b**5 */ + break; + case 6: + wResult *= w1; /* b**3 */ + wResult *= wResult; /* b**6 */ + break; + case 7: + wResult *= w1; /* b**3 */ + wResult *= wResult; /* b**6 */ + wResult *= w1; /* b**7 */ + break; + case 8: + wResult *= wResult; /* b**4 */ + wResult *= wResult; /* b**8 */ + break; + case 9: + wResult *= wResult; /* b**4 */ + wResult *= wResult; /* b**8 */ + wResult *= w1; /* b**9 */ + break; + case 10: + wResult *= wResult; /* b**4 */ + wResult *= w1; /* b**5 */ + wResult *= wResult; /* b**10 */ + break; + case 11: + wResult *= wResult; /* b**4 */ + wResult *= w1; /* b**5 */ + wResult *= wResult; /* b**10 */ + wResult *= w1; /* b**11 */ + break; + case 12: + wResult *= w1; /* b**3 */ + wResult *= wResult; /* b**6 */ + wResult *= wResult; /* b**12 */ + break; + case 13: + wResult *= w1; /* b**3 */ + wResult *= wResult; /* b**6 */ + wResult *= wResult; /* b**12 */ + wResult *= w1; /* b**13 */ + break; + case 14: + wResult *= w1; /* b**3 */ + wResult *= wResult; /* b**6 */ + wResult *= w1; /* b**7 */ + wResult *= wResult; /* b**14 */ + break; + case 15: + wResult *= w1; /* b**3 */ + wResult *= wResult; /* b**6 */ + wResult *= w1; /* b**7 */ + wResult *= wResult; /* b**14 */ + wResult *= w1; /* b**15 */ + break; + case 16: + wResult *= wResult; /* b**4 */ + wResult *= wResult; /* b**8 */ + wResult *= wResult; /* b**16 */ + break; + } + return wResult; +} +/* *---------------------------------------------------------------------- * * ExecuteExtendedBinaryMathOp, ExecuteExtendedUnaryMathOp -- @@ -8610,8 +8730,11 @@ ExecuteExtendedBinaryMathOp( goto doubleResult; } l1 = l2 = 0; - if (type2 == TCL_NUMBER_LONG) { + w1 = w2 = 0; /* to silence compiler warning (maybe-uninitialized) */ + switch (type2) { + case TCL_NUMBER_LONG: l2 = *((const long *) ptr2); + pwrLongExpon: if (l2 == 0) { /* * Anything to the zero power is 1. @@ -8625,16 +8748,17 @@ ExecuteExtendedBinaryMathOp( return NULL; } - } - - switch (type2) { - case TCL_NUMBER_LONG: negativeExponent = (l2 < 0); oddExponent = (int) (l2 & 1); break; #ifndef TCL_WIDE_INT_IS_LONG case TCL_NUMBER_WIDE: w2 = *((const Tcl_WideInt *)ptr2); + l2 = (long)w2; + if (w2 == l2) { + type2 = TCL_NUMBER_LONG; + goto pwrLongExpon; + } negativeExponent = (w2 < 0); oddExponent = (int) (w2 & (Tcl_WideInt)1); break; @@ -8648,48 +8772,18 @@ ExecuteExtendedBinaryMathOp( break; } - if (type1 == TCL_NUMBER_LONG) { + switch (type1) { + case TCL_NUMBER_LONG: l1 = *((const long *)ptr1); - } - if (negativeExponent) { - if (type1 == TCL_NUMBER_LONG) { - switch (l1) { - case 0: - /* - * Zero to a negative power is div by zero error. - */ - - return EXPONENT_OF_ZERO; - case -1: - if (oddExponent) { - LONG_RESULT(-1); - } - /* fallthrough */ - case 1: - /* - * 1 to any power is 1. - */ - - return constants[1]; - } - } - - /* - * Integers with magnitude greater than 1 raise to a negative - * power yield the answer zero (see TIP 123). - */ - - return constants[0]; - } - - if (type1 == TCL_NUMBER_LONG) { + pwrLongBase: switch (l1) { case 0: /* * Zero to a positive power is zero. + * Zero to a negative power is div by zero error. */ - return constants[0]; + return (!negativeExponent) ? constants[0] : EXPONENT_OF_ZERO; case 1: /* * 1 to any power is 1. @@ -8697,11 +8791,44 @@ ExecuteExtendedBinaryMathOp( return constants[1]; case -1: - if (!oddExponent) { - return constants[1]; + if (!negativeExponent) { + if (!oddExponent) { + return constants[1]; + } + LONG_RESULT(-1); } - LONG_RESULT(-1); + /* negativeExponent */ + if (oddExponent) { + LONG_RESULT(-1); + } + return constants[1]; + } + break; +#ifndef TCL_WIDE_INT_IS_LONG + case TCL_NUMBER_WIDE: + w1 = *((const Tcl_WideInt *) ptr1); + /* check it fits in long */ + l1 = (long)w1; + if (w1 == l1) { + type1 = TCL_NUMBER_LONG; + goto pwrLongBase; } + break; +#endif + } + if (negativeExponent) { + + /* + * Integers with magnitude greater than 1 raise to a negative + * power yield the answer zero (see TIP 123). + */ + + return constants[0]; + } + + + if (type1 == TCL_NUMBER_BIG) { + goto overflowExpon; } /* @@ -8719,6 +8846,8 @@ ExecuteExtendedBinaryMathOp( return GENERAL_ARITHMETIC_ERROR; } + /* From here (up to overflowExpon) exponent is long. */ + if (type1 == TCL_NUMBER_LONG) { if (l1 == 2) { /* @@ -8759,35 +8888,8 @@ ExecuteExtendedBinaryMathOp( /* * Small powers of 32-bit integers. */ + lResult = LongPwrSmallExpon(l1, l2); - lResult = l1 * l1; /* b**2 */ - switch (l2) { - case 2: - break; - case 3: - lResult *= l1; /* b**3 */ - break; - case 4: - lResult *= lResult; /* b**4 */ - break; - case 5: - lResult *= lResult; /* b**4 */ - lResult *= l1; /* b**5 */ - break; - case 6: - lResult *= l1; /* b**3 */ - lResult *= lResult; /* b**6 */ - break; - case 7: - lResult *= l1; /* b**3 */ - lResult *= lResult; /* b**6 */ - lResult *= l1; /* b**7 */ - break; - case 8: - lResult *= lResult; /* b**4 */ - lResult *= lResult; /* b**8 */ - break; - } LONG_RESULT(lResult); } @@ -8821,96 +8923,22 @@ ExecuteExtendedBinaryMathOp( } #endif } + #if (LONG_MAX > 0x7fffffff) || !defined(TCL_WIDE_INT_IS_LONG) if (type1 == TCL_NUMBER_LONG) { w1 = l1; -#ifndef TCL_WIDE_INT_IS_LONG - } else if (type1 == TCL_NUMBER_WIDE) { - w1 = *((const Tcl_WideInt *) ptr1); -#endif - } else { - goto overflowExpon; } + + /* From here (up to overflowExpon) base is wide-int (w1). */ + if (l2 - 2 < (long)MaxBase64Size && w1 <= MaxBase64[l2 - 2] && w1 >= -MaxBase64[l2 - 2]) { /* * Small powers of integers whose result is wide. */ + wResult = WidePwrSmallExpon(w1, l2); - wResult = w1 * w1; /* b**2 */ - switch (l2) { - case 2: - break; - case 3: - wResult *= l1; /* b**3 */ - break; - case 4: - wResult *= wResult; /* b**4 */ - break; - case 5: - wResult *= wResult; /* b**4 */ - wResult *= w1; /* b**5 */ - break; - case 6: - wResult *= w1; /* b**3 */ - wResult *= wResult; /* b**6 */ - break; - case 7: - wResult *= w1; /* b**3 */ - wResult *= wResult; /* b**6 */ - wResult *= w1; /* b**7 */ - break; - case 8: - wResult *= wResult; /* b**4 */ - wResult *= wResult; /* b**8 */ - break; - case 9: - wResult *= wResult; /* b**4 */ - wResult *= wResult; /* b**8 */ - wResult *= w1; /* b**9 */ - break; - case 10: - wResult *= wResult; /* b**4 */ - wResult *= w1; /* b**5 */ - wResult *= wResult; /* b**10 */ - break; - case 11: - wResult *= wResult; /* b**4 */ - wResult *= w1; /* b**5 */ - wResult *= wResult; /* b**10 */ - wResult *= w1; /* b**11 */ - break; - case 12: - wResult *= w1; /* b**3 */ - wResult *= wResult; /* b**6 */ - wResult *= wResult; /* b**12 */ - break; - case 13: - wResult *= w1; /* b**3 */ - wResult *= wResult; /* b**6 */ - wResult *= wResult; /* b**12 */ - wResult *= w1; /* b**13 */ - break; - case 14: - wResult *= w1; /* b**3 */ - wResult *= wResult; /* b**6 */ - wResult *= w1; /* b**7 */ - wResult *= wResult; /* b**14 */ - break; - case 15: - wResult *= w1; /* b**3 */ - wResult *= wResult; /* b**6 */ - wResult *= w1; /* b**7 */ - wResult *= wResult; /* b**14 */ - wResult *= w1; /* b**15 */ - break; - case 16: - wResult *= wResult; /* b**4 */ - wResult *= wResult; /* b**8 */ - wResult *= wResult; /* b**16 */ - break; - } WIDE_RESULT(wResult); } diff --git a/tests/mathop.test b/tests/mathop.test index f122b7b..a1a3f80 100644 --- a/tests/mathop.test +++ b/tests/mathop.test @@ -1206,6 +1206,8 @@ test mathop-25.5 { exp operator } {TestOp ** 1 5} 1 test mathop-25.6 { exp operator } {TestOp ** 5 1} 5 test mathop-25.7 { exp operator } {TestOp ** 4 3 2 1} 262144 test mathop-25.8 { exp operator } {TestOp ** 5.5 4} 915.0625 +test mathop-25.8a { exp operator } {TestOp ** 4.0 -1} 0.25 +test mathop-25.8b { exp operator } {TestOp ** 2.0 -2} 0.25 test mathop-25.9 { exp operator } {TestOp ** 16 3.5} 16384.0 test mathop-25.10 { exp operator } {TestOp ** 3.5 0} 1.0 test mathop-25.11 { exp operator } {TestOp ** 378 0} 1 @@ -1219,8 +1221,32 @@ test mathop-25.18 { exp operator } {TestOp ** -1 -2} 1 test mathop-25.19 { exp operator } {TestOp ** -1 3} -1 test mathop-25.20 { exp operator } {TestOp ** -1 4} 1 test mathop-25.21 { exp operator } {TestOp ** 2 63} 9223372036854775808 -test mathop-25.22 { exp operator } {TestOp ** 83756485763458746358734658473567847567473 2} 7015148907444467657897585474493757781161998914521537835809623408157343003287605729 -test mathop-25.23 { exp operator errors } { +test mathop-25.22 { exp operator } {TestOp ** 2 256} 115792089237316195423570985008687907853269984665640564039457584007913129639936 +set big 83756485763458746358734658473567847567473 +test mathop-25.23 { exp operator } {TestOp ** $big 2} 7015148907444467657897585474493757781161998914521537835809623408157343003287605729 +test mathop-25.24 { exp operator } {TestOp ** $big 0} 1 +test mathop-25.25 { exp operator } {TestOp ** $big 1} $big +test mathop-25.26 { exp operator } {TestOp ** $big -1} 0 +test mathop-25.27 { exp operator } {TestOp ** $big -2} 0 +test mathop-25.28 { exp operator } {TestOp ** $big -$big} 0 +test mathop-25.29 { exp operator } {expr {[set res [TestOp ** $big -1.0]] > 0 && $res < 1.2e-41}} 1 +test mathop-25.30 { exp operator } {expr {[set res [TestOp ** $big -1e-18]] > 0 && $res < 1}} 1 +test mathop-25.31 { exp operator } {expr {[set res [TestOp ** -$big -1.0]] > -1 && $res < 0}} 1 +test mathop-25.32 { exp operator } {expr {[set res [TestOp ** -$big -2.0]] > 0 && $res < 1}} 1 +test mathop-25.33 { exp operator } {expr {[set res [TestOp ** -$big -3.0]] > -1 && $res < 0}} 1 +test mathop-25.34 { exp operator } {TestOp ** $big -1e-30} 1.0 +test mathop-25.35 { exp operator } {TestOp ** $big -1e+30} 0.0 +test mathop-25.36 { exp operator } {TestOp ** 0 $big} 0 +test mathop-25.37 { exp operator } {TestOp ** 1 $big} 1 +test mathop-25.38 { exp operator } {TestOp ** -1 $big} -1 +test mathop-25.39 { exp operator } {TestOp ** -1 [expr {$big+1}]} 1 +test mathop-25.40 { exp operator (small exponent power helper and its boundaries) } { + set pwr 0 + set res 1 + while {[incr pwr] <= 17 && [set i [TestOp ** 15 $pwr]] == [set res [expr {$res * 15}]]} {} + list [incr pwr -1] $res +} {17 98526125335693359375} +test mathop-25.41 { exp operator errors } { set res {} set exp {} -- cgit v0.12 From 0fcfbd81dff3bfe93a0695f0270dd3e9322fbc62 Mon Sep 17 00:00:00 2001 From: sebres Date: Mon, 4 Feb 2019 14:40:04 +0000 Subject: code review --- generic/tclExecute.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 4a1dbfa..1a932a1 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -8754,6 +8754,7 @@ ExecuteExtendedBinaryMathOp( #ifndef TCL_WIDE_INT_IS_LONG case TCL_NUMBER_WIDE: w2 = *((const Tcl_WideInt *)ptr2); + /* check it fits in long */ l2 = (long)w2; if (w2 == l2) { type2 = TCL_NUMBER_LONG; @@ -8846,7 +8847,7 @@ ExecuteExtendedBinaryMathOp( return GENERAL_ARITHMETIC_ERROR; } - /* From here (up to overflowExpon) exponent is long. */ + /* From here (up to overflowExpon) exponent is long (l2). */ if (type1 == TCL_NUMBER_LONG) { if (l1 == 2) { @@ -8922,13 +8923,14 @@ ExecuteExtendedBinaryMathOp( } } #endif - } - #if (LONG_MAX > 0x7fffffff) || !defined(TCL_WIDE_INT_IS_LONG) - if (type1 == TCL_NUMBER_LONG) { + /* Code below (up to overflowExpon) works with wide-int base */ w1 = l1; +#endif } +#if (LONG_MAX > 0x7fffffff) || !defined(TCL_WIDE_INT_IS_LONG) + /* From here (up to overflowExpon) base is wide-int (w1). */ if (l2 - 2 < (long)MaxBase64Size -- cgit v0.12 From 89fee2234176e8ba700279249fdbe5027e499e27 Mon Sep 17 00:00:00 2001 From: sebres Date: Mon, 1 Apr 2019 13:51:46 +0000 Subject: timerate: avoid divide by zero by no iterations in measurement cycle (e. g. count is 0) --- generic/tclCmdMZ.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index ba86203..0cad34f 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -4253,6 +4253,11 @@ usage: middle *= TclpWideClickInMicrosec(); #endif + if (!count) { /* no iterations - avoid divide by zero */ + objs[0] = objs[2] = objs[4] = Tcl_NewWideIntObj(0); + goto retRes; + } + /* if not calibrate */ if (!calibrate) { /* minimize influence of measurement overhead */ @@ -4305,9 +4310,14 @@ usage: objs[4] = Tcl_NewWideIntObj((count / middle) * 1000000); } + retRes: /* estimated net execution time (in millisecs) */ if (!calibrate) { - objs[6] = Tcl_ObjPrintf("%.3f", (double)middle / 1000); + if (middle >= 1) { + objs[6] = Tcl_ObjPrintf("%.3f", (double)middle / 1000); + } else { + objs[6] = Tcl_NewWideIntObj(0); + } TclNewLiteralStringObj(objs[7], "nett-ms"); } -- cgit v0.12 From 01dccf28f9a4c2280c11b24bef6cac2313a7ead3 Mon Sep 17 00:00:00 2001 From: sebres Date: Mon, 1 Apr 2019 13:53:54 +0000 Subject: closes [1a3fa1232e306a44], test case cmdMZ-6.5 fixed to cover float value by iteration per second --- tests/cmdMZ.test | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/cmdMZ.test b/tests/cmdMZ.test index 60f6236..d1f0a44 100644 --- a/tests/cmdMZ.test +++ b/tests/cmdMZ.test @@ -365,8 +365,11 @@ test cmdMZ-6.3 {Tcl_TimeRateObjCmd: basic format of command} { test cmdMZ-6.4 {Tcl_TimeRateObjCmd: compile of script happens even with negative iteration counts} { list [catch {timerate "foreach a {c d e} \{" -12456} msg] $msg } {1 {missing close-brace}} -test cmdMZ-6.5 {Tcl_TimeRateObjCmd: result format and one iteration} { - regexp {^\d+.\d+ \ws/# 1 # \d+ #/sec \d+.\d+ nett-ms$} [timerate {} 0] +test cmdMZ-6.5a {Tcl_TimeRateObjCmd: result format and one iteration} { + regexp {^\d+(?:\.\d+)? \ws/# 1 # \d+(?:\.\d+)? #/sec \d+(?:\.\d+)? nett-ms$} [timerate {} 0] +} 1 +test cmdMZ-6.5b {Tcl_TimeRateObjCmd: result format without iterations} { + regexp {^0 \ws/# 0 # 0 #/sec 0 nett-ms$} [timerate {} 0 0] } 1 test cmdMZ-6.6 {Tcl_TimeRateObjCmd: slower commands take longer, but it remains almost the same time of measument} { set m1 [timerate {after 0} 20] -- cgit v0.12 From 384b9de6bb83732c6055c5d1a880898399579ecf Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 1 Apr 2019 19:36:20 +0000 Subject: Modify testbytestring such that is only produces pure byte-arrays, if not it errors out. Modify Tcl_NewIntObj/Tcl_NewBooleanObj -> Tcl_NewWideIntObj. Less references to "long" datatype. --- doc/info.n | 4 ++-- generic/tclCmdAH.c | 6 +++--- generic/tclProcess.c | 4 ++-- generic/tclTest.c | 21 +++++++++++++++------ generic/tclTestObj.c | 26 +++++++++++++------------- generic/tclTestProcBodyObj.c | 2 +- generic/tclUtil.c | 6 +++--- generic/tclZlib.c | 6 ++++-- macosx/tclMacOSXFCmd.c | 10 +++++----- tests/obj.test | 28 ++++++++++++++-------------- tests/utf.test | 4 ++-- unix/tclUnixFCmd.c | 20 ++++++++++---------- win/tclWinFCmd.c | 2 +- 13 files changed, 75 insertions(+), 64 deletions(-) diff --git a/doc/info.n b/doc/info.n index ac89bdb..dc21ac1 100644 --- a/doc/info.n +++ b/doc/info.n @@ -212,7 +212,7 @@ procedures nested in statically defined procedures, and literal eval scripts in files or statically defined procedures, its type is \fBsource\fR and its location is the absolute line number in the script. Otherwise, its type is \fBproc\fR and its location is its line number within the body of the -procedure. +procedure. .PP In contrast, procedure definitions and \fBeval\fR within a dynamically \fBeval\fRuated environment count line numbers relative to the start of @@ -300,7 +300,7 @@ described \fBOBJECT INTROSPECTION\fR below. .TP \fBinfo patchlevel\fR . -Returns the value of the global variable \fBtcl_patchLevel\fR, in which the +Returns the value of the global variable \fBtcl_patchLevel\fR, in which the exact version of the Tcl library initially stored. .TP \fBinfo procs \fR?\fIpattern\fR? diff --git a/generic/tclCmdAH.c b/generic/tclCmdAH.c index 331f791..1811c5c 100644 --- a/generic/tclCmdAH.c +++ b/generic/tclCmdAH.c @@ -932,7 +932,7 @@ Tcl_ExitObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int value; + Tcl_WideInt value; if ((objc != 1) && (objc != 2)) { Tcl_WrongNumArgs(interp, 1, objv, "?returnCode?"); @@ -941,10 +941,10 @@ Tcl_ExitObjCmd( if (objc == 1) { value = 0; - } else if (Tcl_GetIntFromObj(interp, objv[1], &value) != TCL_OK) { + } else if (TclGetWideBitsFromObj(interp, objv[1], &value) != TCL_OK) { return TCL_ERROR; } - Tcl_Exit(value); + Tcl_Exit((int)value); /*NOTREACHED*/ return TCL_OK; /* Better not ever reach this! */ } diff --git a/generic/tclProcess.c b/generic/tclProcess.c index a781386..2f3f4ba 100644 --- a/generic/tclProcess.c +++ b/generic/tclProcess.c @@ -540,7 +540,7 @@ ProcessStatusObjCmd( dict = Tcl_NewDictObj(); Tcl_MutexLock(&infoTablesMutex); for (i = 0; i < numPids; i++) { - result = Tcl_GetIntFromObj(interp, pidObjs[i], (int *) &pid); + result = Tcl_GetIntFromObj(interp, pidObjs[i], &pid); if (result != TCL_OK) { Tcl_MutexUnlock(&infoTablesMutex); Tcl_DecrRefCount(dict); @@ -654,7 +654,7 @@ ProcessPurgeObjCmd( } Tcl_MutexLock(&infoTablesMutex); for (i = 0; i < numPids; i++) { - result = Tcl_GetIntFromObj(interp, pidObjs[i], (int *) &pid); + result = Tcl_GetIntFromObj(interp, pidObjs[i], &pid); if (result != TCL_OK) { Tcl_MutexUnlock(&infoTablesMutex); return result; diff --git a/generic/tclTest.c b/generic/tclTest.c index 172b56e..349d935 100644 --- a/generic/tclTest.c +++ b/generic/tclTest.c @@ -52,6 +52,7 @@ DLLEXPORT int Tcltest_SafeInit(Tcl_Interp *interp); static Tcl_DString delString; static Tcl_Interp *delInterp; +static const Tcl_ObjType *properByteArrayType; /* * One of the following structures exists for each asynchronous handler @@ -552,8 +553,7 @@ int Tcltest_Init( Tcl_Interp *interp) /* Interpreter for application. */ { - Tcl_Obj *listPtr; - Tcl_Obj **objv; + Tcl_Obj **objv, *objPtr; int objc, index; static const char *const specialOptions[] = { "-appinitprocerror", "-appinitprocdeleteinterp", @@ -575,6 +575,11 @@ Tcltest_Init( return TCL_ERROR; } + objPtr = Tcl_NewStringObj("abc", 3); + (void)Tcl_GetByteArrayFromObj(objPtr, &index); + properByteArrayType = objPtr->typePtr; + Tcl_DecrRefCount(objPtr); + /* * Create additional commands and math functions for testing Tcl. */ @@ -740,9 +745,9 @@ Tcltest_Init( * Check for special options used in ../tests/main.test */ - listPtr = Tcl_GetVar2Ex(interp, "argv", NULL, TCL_GLOBAL_ONLY); - if (listPtr != NULL) { - if (Tcl_ListObjGetElements(interp, listPtr, &objc, &objv) != TCL_OK) { + objPtr = Tcl_GetVar2Ex(interp, "argv", NULL, TCL_GLOBAL_ONLY); + if (objPtr != NULL) { + if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) { return TCL_ERROR; } if (objc && (Tcl_GetIndexFromObj(NULL, objv[0], specialOptions, NULL, @@ -5011,7 +5016,7 @@ TestbytestringObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { - int n; + int n = 0; const char *p; if (objc != 2) { @@ -5019,6 +5024,10 @@ TestbytestringObjCmd( return TCL_ERROR; } p = (const char *)Tcl_GetByteArrayFromObj(objv[1], &n); + if ((p == NULL) || !Tcl_FetchIntRep(objv[1], properByteArrayType)) { + Tcl_AppendResult(interp, "testbytestring expects bytes", NULL); + return TCL_ERROR; + } Tcl_SetObjResult(interp, Tcl_NewStringObj(p, n)); return TCL_OK; } diff --git a/generic/tclTestObj.c b/generic/tclTestObj.c index 8f12fd6..a289e32 100644 --- a/generic/tclTestObj.c +++ b/generic/tclTestObj.c @@ -385,9 +385,9 @@ TestbooleanobjCmd( */ if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetBooleanObj(varPtr[varIndex], boolValue); + Tcl_SetWideIntObj(varPtr[varIndex], boolValue != 0); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewBooleanObj(boolValue)); + SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(boolValue != 0)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else if (strcmp(subCmd, "get") == 0) { @@ -410,9 +410,9 @@ TestbooleanobjCmd( return TCL_ERROR; } if (!Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetBooleanObj(varPtr[varIndex], !boolValue); + Tcl_SetWideIntObj(varPtr[varIndex], boolValue == 0); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewBooleanObj(!boolValue)); + SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(boolValue == 0)); } Tcl_SetObjResult(interp, varPtr[varIndex]); } else { @@ -658,7 +658,7 @@ TestintobjCmd( Tcl_Obj *const objv[]) /* Argument objects. */ { int intValue, varIndex, i; - long longValue; + Tcl_WideInt wideValue; const char *index, *subCmd, *string; Tcl_Obj **varPtr; @@ -713,7 +713,7 @@ TestintobjCmd( } else { SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(intValue)); } - } else if (strcmp(subCmd, "setlong") == 0) { + } else if (strcmp(subCmd, "setint") == 0) { if (objc != 4) { goto wrongNumArgs; } @@ -728,28 +728,28 @@ TestintobjCmd( SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(intValue)); } Tcl_SetObjResult(interp, varPtr[varIndex]); - } else if (strcmp(subCmd, "setmaxlong") == 0) { - long maxLong = LONG_MAX; + } else if (strcmp(subCmd, "setmax") == 0) { + Tcl_WideInt maxWide = WIDE_MAX; if (objc != 3) { goto wrongNumArgs; } if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { - Tcl_SetWideIntObj(varPtr[varIndex], maxLong); + Tcl_SetWideIntObj(varPtr[varIndex], maxWide); } else { - SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(maxLong)); + SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(maxWide)); } - } else if (strcmp(subCmd, "ismaxlong") == 0) { + } else if (strcmp(subCmd, "ismax") == 0) { if (objc != 3) { goto wrongNumArgs; } if (CheckIfVarUnset(interp, varPtr,varIndex)) { return TCL_ERROR; } - if (Tcl_GetLongFromObj(interp, varPtr[varIndex], &longValue) != TCL_OK) { + if (Tcl_GetWideIntFromObj(interp, varPtr[varIndex], &wideValue) != TCL_OK) { return TCL_ERROR; } Tcl_AppendToObj(Tcl_GetObjResult(interp), - ((longValue == LONG_MAX)? "1" : "0"), -1); + ((wideValue == WIDE_MAX)? "1" : "0"), -1); } else if (strcmp(subCmd, "get") == 0) { if (objc != 3) { goto wrongNumArgs; diff --git a/generic/tclTestProcBodyObj.c b/generic/tclTestProcBodyObj.c index fba2844..913b253 100644 --- a/generic/tclTestProcBodyObj.c +++ b/generic/tclTestProcBodyObj.c @@ -340,7 +340,7 @@ ProcBodyTestCheckObjCmd( } version = Tcl_PkgPresent(interp, packageName, packageVersion, 1); - Tcl_SetObjResult(interp, Tcl_NewBooleanObj( + Tcl_SetObjResult(interp, Tcl_NewWideIntObj( strcmp(version, packageVersion) == 0)); return TCL_OK; } diff --git a/generic/tclUtil.c b/generic/tclUtil.c index 250a393..2889852 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -3448,7 +3448,7 @@ TclPrecTraceProc( int flags) /* Information about what happened. */ { Tcl_Obj *value; - int prec; + Tcl_WideInt prec; int *precisionPtr = Tcl_GetThreadData(&precisionKey, sizeof(int)); /* @@ -3488,11 +3488,11 @@ TclPrecTraceProc( } value = Tcl_GetVar2Ex(interp, name1, name2, flags & TCL_GLOBAL_ONLY); if (value == NULL - || Tcl_GetIntFromObj(NULL, value, &prec) != TCL_OK + || Tcl_GetWideIntFromObj(NULL, value, &prec) != TCL_OK || prec < 0 || prec > TCL_MAX_PREC) { return (char *) "improper value for precision"; } - *precisionPtr = prec; + *precisionPtr = (int)prec; return NULL; } #endif /* !TCL_NO_DEPRECATED)*/ diff --git a/generic/tclZlib.c b/generic/tclZlib.c index 32268af..5a7abec 100644 --- a/generic/tclZlib.c +++ b/generic/tclZlib.c @@ -422,6 +422,7 @@ GenerateHeader( { Tcl_Obj *value; int len, result = TCL_ERROR; + Tcl_WideInt wideValue; const char *valueStr; Tcl_Encoding latin1enc; static const char *const types[] = { @@ -485,10 +486,11 @@ GenerateHeader( if (GetValue(interp, dictObj, "time", &value) != TCL_OK) { goto error; - } else if (value != NULL && Tcl_GetLongFromObj(interp, value, - (long *) &headerPtr->header.time) != TCL_OK) { + } else if (value != NULL && Tcl_GetWideIntFromObj(interp, value, + &wideValue) != TCL_OK) { goto error; } + headerPtr->header.time = wideValue; if (GetValue(interp, dictObj, "type", &value) != TCL_OK) { goto error; diff --git a/macosx/tclMacOSXFCmd.c b/macosx/tclMacOSXFCmd.c index 1f7dcd8..7c65088 100644 --- a/macosx/tclMacOSXFCmd.c +++ b/macosx/tclMacOSXFCmd.c @@ -192,7 +192,7 @@ TclMacOSXGetFileAttribute( OSSwapBigToHostInt32(finder->type)); break; case MACOSX_HIDDEN_ATTRIBUTE: - *attributePtrPtr = Tcl_NewBooleanObj( + *attributePtrPtr = Tcl_NewWideIntObj( (finder->fdFlags & kFinfoIsInvisible) != 0); break; case MACOSX_RSRCLENGTH_ATTRIBUTE: @@ -580,7 +580,7 @@ GetOSTypeFromObj( if (!TclHasIntRep(objPtr, &tclOSTypeType)) { result = SetOSTypeFromAny(interp, objPtr); } - *osTypePtr = (OSType) objPtr->internalRep.longValue; + *osTypePtr = (OSType) objPtr->internalRep.wideValue; return result; } @@ -609,7 +609,7 @@ NewOSTypeObj( TclNewObj(objPtr); TclInvalidateStringRep(objPtr); - objPtr->internalRep.longValue = (long) osType; + objPtr->internalRep.wideValue = (Tcl_WideInt) osType; objPtr->typePtr = &tclOSTypeType; return objPtr; } @@ -660,7 +660,7 @@ SetOSTypeFromAny( (OSType) bytes[2] << 8 | (OSType) bytes[3]; TclFreeIntRep(objPtr); - objPtr->internalRep.longValue = (long) osType; + objPtr->internalRep.wideValue = (Tcl_WideInt) osType; objPtr->typePtr = &tclOSTypeType; } Tcl_DStringFree(&ds); @@ -694,7 +694,7 @@ UpdateStringOfOSType( { const int size = TCL_UTF_MAX * 4; char *dst = Tcl_InitStringRep(objPtr, NULL, size); - OSType osType = (OSType) objPtr->internalRep.longValue; + OSType osType = (OSType) objPtr->internalRep.wideValue; int written = 0; Tcl_Encoding encoding; char src[5]; diff --git a/tests/obj.test b/tests/obj.test index 87c8d08..5bcffa3 100644 --- a/tests/obj.test +++ b/tests/obj.test @@ -476,11 +476,11 @@ test obj-26.1 {UpdateStringOfInt} testobj { lappend result [testintobj get 1] ;# must update string rep } {512 5120 5120} -test obj-27.1 {Tcl_NewLongObj} testobj { +test obj-27.1 {Tcl_NewWideObj} testobj { set result "" lappend result [testobj freeallvars] - testintobj setmaxlong 1 - lappend result [testintobj ismaxlong 1] + testintobj setmax 1 + lappend result [testintobj ismax 1] lappend result [testobj type 1] lappend result [testobj refcount 1] } {{} 1 int 1} @@ -489,7 +489,7 @@ test obj-28.1 {Tcl_SetLongObj, existing "empty string" object} testobj { set result "" lappend result [testobj freeallvars] lappend result [testobj newobj 1] - lappend result [testintobj setlong 1 77] ;# makes existing obj long int + lappend result [testintobj setint 1 77] ;# makes existing obj int lappend result [testobj type 1] lappend result [testobj refcount 1] } {{} {} 77 int 2} @@ -497,32 +497,32 @@ test obj-28.2 {Tcl_SetLongObj, existing non-"empty string" object} testobj { set result "" lappend result [testobj freeallvars] lappend result [testdoubleobj set 1 12.34] - lappend result [testintobj setlong 1 77] ;# makes existing obj long int + lappend result [testintobj setint 1 77] ;# makes existing obj int lappend result [testobj type 1] lappend result [testobj refcount 1] } {{} 12.34 77 int 2} -test obj-29.1 {Tcl_GetLongFromObj, existing long integer object} testobj { +test obj-29.1 {Tcl_GetWideIntFromObj, existing int object} testobj { set result "" - lappend result [testintobj setlong 1 22] - lappend result [testintobj mult10 1] ;# gets existing long int rep + lappend result [testintobj setint 1 22] + lappend result [testintobj mult10 1] ;# gets existingint rep } {22 220} -test obj-29.2 {Tcl_GetLongFromObj, convert to long} testobj { +test obj-29.2 {Tcl_GetWideIntFromObj, convert to int} testobj { set result "" - lappend result [testintobj setlong 1 477] + lappend result [testintobj setint 1 477] lappend result [testintobj div10 1] ;# must convert to bool lappend result [testobj type 1] } {477 47 int} -test obj-29.3 {Tcl_GetLongFromObj, error converting to long integer} testobj { +test obj-29.3 {Tcl_GetWideIntFromObj, error converting to int} testobj { set result "" lappend result [teststringobj set 1 abc] - lappend result [catch {testintobj ismaxlong 1} msg] ;# cvts to long int + lappend result [catch {testintobj ismax 1} msg] ;# cvts to long int lappend result $msg } {abc 1 {expected integer but got "abc"}} -test obj-29.4 {Tcl_GetLongFromObj, error converting from "empty string"} testobj { +test obj-29.4 {Tcl_GetWideIntFromObj, error converting from "empty string"} testobj { set result "" lappend result [testobj newobj 1] - lappend result [catch {testintobj ismaxlong 1} msg] ;# cvts to long int + lappend result [catch {testintobj ismax 1} msg] ;# cvts to long int lappend result $msg } {{} 1 {expected integer but got ""}} diff --git a/tests/utf.test b/tests/utf.test index f4926af..72b8d97 100644 --- a/tests/utf.test +++ b/tests/utf.test @@ -108,7 +108,7 @@ test utf-4.2 {Tcl_NumUtfChars: length 1} {testnumutfchars testbytestring} { testnumutfchars [testbytestring "\xC2\xA2"] } {1} test utf-4.3 {Tcl_NumUtfChars: long string} {testnumutfchars testbytestring} { - testnumutfchars [testbytestring "abc\xC2\xA2\xe4\xb9\x8e\uA2\u4e4e"] + testnumutfchars [testbytestring "abc\xC2\xA2\xE4\xB9\x8E\uA2\x4E"] } {7} test utf-4.4 {Tcl_NumUtfChars: #u0000} {testnumutfchars testbytestring} { testnumutfchars [testbytestring "\xC0\x80"] @@ -120,7 +120,7 @@ test utf-4.6 {Tcl_NumUtfChars: length 1, calc len} {testnumutfchars testbytestri testnumutfchars [testbytestring "\xC2\xA2"] 2 } {1} test utf-4.7 {Tcl_NumUtfChars: long string, calc len} {testnumutfchars testbytestring} { - testnumutfchars [testbytestring "abc\xC2\xA2\xe4\xb9\x8e\uA2\u4e4e"] 10 + testnumutfchars [testbytestring "abc\xC2\xA2\xE4\xB9\x8E\uA2\x4E"] 10 } {7} test utf-4.8 {Tcl_NumUtfChars: #u0000, calc len} {testnumutfchars testbytestring} { testnumutfchars [testbytestring "\xC0\x80"] 2 diff --git a/unix/tclUnixFCmd.c b/unix/tclUnixFCmd.c index 7205085..e963589 100644 --- a/unix/tclUnixFCmd.c +++ b/unix/tclUnixFCmd.c @@ -1499,11 +1499,11 @@ SetGroupAttribute( Tcl_Obj *fileName, /* The name of the file (UTF-8). */ Tcl_Obj *attributePtr) /* New group for file. */ { - long gid; + Tcl_WideInt gid; int result; const char *native; - if (Tcl_GetLongFromObj(NULL, attributePtr, &gid) != TCL_OK) { + if (Tcl_GetWideIntFromObj(NULL, attributePtr, &gid) != TCL_OK) { Tcl_DString ds; struct group *groupPtr = NULL; const char *string; @@ -1565,11 +1565,11 @@ SetOwnerAttribute( Tcl_Obj *fileName, /* The name of the file (UTF-8). */ Tcl_Obj *attributePtr) /* New owner for file. */ { - long uid; + Tcl_WideInt uid; int result; const char *native; - if (Tcl_GetLongFromObj(NULL, attributePtr, &uid) != TCL_OK) { + if (Tcl_GetWideIntFromObj(NULL, attributePtr, &uid) != TCL_OK) { Tcl_DString ds; struct passwd *pwPtr = NULL; const char *string; @@ -1631,7 +1631,7 @@ SetPermissionsAttribute( Tcl_Obj *fileName, /* The name of the file (UTF-8). */ Tcl_Obj *attributePtr) /* The attribute to set. */ { - long mode; + Tcl_WideInt mode; mode_t newMode; int result = TCL_ERROR; const char *native; @@ -1650,11 +1650,11 @@ SetPermissionsAttribute( TclNewLiteralStringObj(modeObj, "0o"); Tcl_AppendToObj(modeObj, modeStringPtr+scanned+1, -1); - result = Tcl_GetLongFromObj(NULL, modeObj, &mode); + result = Tcl_GetWideIntFromObj(NULL, modeObj, &mode); Tcl_DecrRefCount(modeObj); } if (result == TCL_OK - || Tcl_GetLongFromObj(NULL, attributePtr, &mode) == TCL_OK) { + || Tcl_GetWideIntFromObj(NULL, attributePtr, &mode) == TCL_OK) { newMode = (mode_t) (mode & 0x00007FFF); } else { Tcl_StatBuf buf; @@ -2340,8 +2340,8 @@ GetUnixFileAttributes( return TCL_ERROR; } - *attributePtrPtr = Tcl_NewBooleanObj( - fileAttributes & attributeArray[objIndex]); + *attributePtrPtr = Tcl_NewWideIntObj( + (fileAttributes & attributeArray[objIndex]) != 0); return TCL_OK; } @@ -2440,7 +2440,7 @@ GetUnixFileAttributes( return TCL_ERROR; } - *attributePtrPtr = Tcl_NewBooleanObj(statBuf.st_flags & UF_IMMUTABLE); + *attributePtrPtr = Tcl_NewWideIntObj((statBuf.st_flags & UF_IMMUTABLE) != 0); return TCL_OK; } diff --git a/win/tclWinFCmd.c b/win/tclWinFCmd.c index a950714..14bb252 100644 --- a/win/tclWinFCmd.c +++ b/win/tclWinFCmd.c @@ -1549,7 +1549,7 @@ GetWinFileAttributes( } } - *attributePtrPtr = Tcl_NewBooleanObj(attr); + *attributePtrPtr = Tcl_NewWideIntObj(attr != 0); return TCL_OK; } -- cgit v0.12