/Tests/Module/WriteCompilerDetectionHeader/

option> Tcl is a high-level, general-purpose, interpreted, dynamic programming language. It was designed with the goal of being very simple but powerful.
summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authorKevin B Kenny <kennykb@acm.org>2005-05-10 18:33:37 (GMT)
committerKevin B Kenny <kennykb@acm.org>2005-05-10 18:33:37 (GMT)
commit76e3b5eed61a674bce7f9c1e18380842dcff3fbf (patch)
tree2f108341f2c542f48532e6057d79bfa551a4245f /generic
parent5b510b75ec4a1d6fb55691bcf55dbf4b0b936624 (diff)
downloadtcl-76e3b5eed61a674bce7f9c1e18380842dcff3fbf.zip
tcl-76e3b5eed61a674bce7f9c1e18380842dcff3fbf.tar.gz
tcl-76e3b5eed61a674bce7f9c1e18380842dcff3fbf.tar.bz2
Merged kennykb-numerics-branch back to the head; TIPs 132 and 232
Diffstat (limited to 'generic')
-rw-r--r--generic/tcl.decls17
-rw-r--r--generic/tcl.h19
-rw-r--r--generic/tclBasic.c1195
-rw-r--r--generic/tclBinary.c15
-rw-r--r--generic/tclCmdAH.c2
-rw-r--r--generic/tclCmdIL.c2
-rw-r--r--generic/tclCmdMZ.c15
-rw-r--r--generic/tclCompCmds.c2
-rw-r--r--generic/tclCompExpr.c103
-rw-r--r--generic/tclCompile.c2
-rw-r--r--generic/tclCompile.h60
-rw-r--r--generic/tclConfig.c2
-rw-r--r--generic/tclDecls.h45
-rw-r--r--generic/tclDictObj.c2
-rw-r--r--generic/tclEncoding.c2
-rw-r--r--generic/tclEnv.c2
-rw-r--r--generic/tclEvent.c8
-rw-r--r--generic/tclExecute.c897
-rw-r--r--generic/tclFCmd.c2
-rw-r--r--generic/tclFileName.c2
-rw-r--r--generic/tclGet.c2
-rw-r--r--generic/tclGetDate.y2
-rw-r--r--generic/tclIO.c2
-rw-r--r--generic/tclIOCmd.c2
-rw-r--r--generic/tclIOUtil.c2
-rw-r--r--generic/tclInt.decls19
-rw-r--r--generic/tclInt.h25
-rw-r--r--generic/tclIntDecls.h55
-rw-r--r--generic/tclInterp.c2
-rw-r--r--generic/tclListObj.c2
-rw-r--r--generic/tclLiteral.c2
-rw-r--r--generic/tclNamesp.c2
-rw-r--r--generic/tclNotify.c2
-rw-r--r--generic/tclObj.c468
-rw-r--r--generic/tclParse.c2
-rw-r--r--generic/tclParseExpr.c69
-rw-r--r--generic/tclPathObj.c2
-rw-r--r--generic/tclPort.h2
-rw-r--r--generic/tclProc.c2
-rw-r--r--generic/tclRegexp.c2
-rw-r--r--generic/tclResult.c2
-rw-r--r--generic/tclScan.c4
-rwxr-xr-xgeneric/tclStrToD.c1361
-rw-r--r--generic/tclStringObj.c2
-rw-r--r--generic/tclStubInit.c11
-rw-r--r--generic/tclTest.c2
-rw-r--r--generic/tclTestObj.c172
-rw-r--r--generic/tclThread.c2
-rwxr-xr-xgeneric/tclThreadAlloc.c2
-rw-r--r--generic/tclThreadTest.c2
-rw-r--r--generic/tclTimer.c2
-rw-r--r--generic/tclTomMath.h109
-rw-r--r--generic/tclTomMathInterface.c143
-rw-r--r--generic/tclTrace.c2
-rw-r--r--generic/tclUtf.c2
-rw-r--r--generic/tclUtil.c188
-rw-r--r--generic/tclVar.c2
-rw-r--r--generic/tommath.h591
58 files changed, 4381 insertions, 1278 deletions
diff --git a/generic/tcl.decls b/generic/tcl.decls
index 4ad45ab..82219aa 100644
--- a/generic/tcl.decls
+++ b/generic/tcl.decls
@@ -11,7 +11,7 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
-# RCS: @(#) $Id: tcl.decls,v 1.110 2005/05/03 18:07:44 dgp Exp $
+# RCS: @(#) $Id: tcl.decls,v 1.111 2005/05/10 18:34:04 kennykb Exp $
library tcl
@@ -1989,6 +1989,21 @@ declare 554 generic {
Tcl_DriverThreadActionProc *Tcl_ChannelThreadActionProc(Tcl_ChannelType *chanTypePtr)
}
+# TIP #237:
+
+declare 555 generic {
+ Tcl_Obj* Tcl_NewBignumObj( mp_int* value )
+}
+declare 556 generic {
+ Tcl_Obj* Tcl_DbNewBignumObj( mp_int* value, CONST char* file, int line )
+}
+declare 557 generic {
+ void Tcl_SetBignumObj( Tcl_Obj* obj, mp_int* value )
+}
+declare 558 generic {
+ int Tcl_GetBignumFromObj( Tcl_Interp* interp, Tcl_Obj* obj, mp_int* value )
+}
+
##############################################################################
# Define the platform specific public Tcl interface. These functions are
diff --git a/generic/tcl.h b/generic/tcl.h
index 97e6d25..bdb8e10 100644
--- a/generic/tcl.h
+++ b/generic/tcl.h
@@ -13,7 +13,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tcl.h,v 1.197 2005/03/10 22:10:38 dgp Exp $
+ * RCS: @(#) $Id: tcl.h,v 1.198 2005/05/10 18:34:05 kennykb Exp $
*/
#ifndef _TCL
@@ -768,6 +768,12 @@ typedef struct Tcl_Obj {
VOID *ptr1;
VOID *ptr2;
} twoPtrValue;
+ struct { /* - internal rep as a wide int,
+ * tightly packed fields */
+ VOID *digits; /* Pointer to digits */
+ unsigned long misc; /* Alloc, used, and signum packed
+ * into a single word */
+ } bignumValue;
} internalRep;
} Tcl_Obj;
@@ -809,6 +815,8 @@ int Tcl_IsShared _ANSI_ARGS_((Tcl_Obj *objPtr));
*/
#ifdef TCL_MEM_DEBUG
+# define Tcl_NewBignumObj(val) \
+ Tcl_DbNewBignumObj(val, __FILE__, __LINE__)
# define Tcl_NewBooleanObj(val) \
Tcl_DbNewBooleanObj(val, __FILE__, __LINE__)
# define Tcl_NewByteArrayObj(bytes, len) \
@@ -2292,6 +2300,15 @@ typedef void (Tcl_LimitHandlerProc) _ANSI_ARGS_((ClientData clientData,
typedef void (Tcl_LimitHandlerDeleteProc) _ANSI_ARGS_((ClientData clientData));
+#ifndef MP_INT_DECLARED
+typedef struct mp_int mp_int;
+#define MP_INT_DECLARED
+#endif
+#ifndef MP_DIGIT_DECLARED
+typedef unsigned long mp_digit;
+#define MP_DIGIT_DECLARED
+#endif
+
#ifndef TCL_NO_DEPRECATED
/*
diff --git a/generic/tclBasic.c b/generic/tclBasic.c
index 9783367..2ec1776 100644
--- a/generic/tclBasic.c
+++ b/generic/tclBasic.c
@@ -13,11 +13,27 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclBasic.c,v 1.150 2005/05/05 18:37:55 dgp Exp $
+ * RCS: @(#) $Id: tclBasic.c,v 1.151 2005/05/10 18:34:06 kennykb Exp $
*/
#include "tclInt.h"
#include "tclCompile.h"
+#include <float.h>
+#ifndef TCL_NO_MATH
+#include <math.h>
+#endif
+
+/*
+ * The following structure defines the client data for a math function
+ * registered with Tcl_CreateMathFunc
+ */
+
+typedef struct OldMathFuncData {
+ Tcl_MathProc* proc; /* Handler procedure */
+ int numArgs; /* Number of args expected */
+ Tcl_ValueType* argTypes; /* Types of the args */
+ ClientData clientData; /* Client data for the handler function */
+} OldMathFuncData;
/*
* Static procedures in this file:
@@ -30,6 +46,106 @@ static void DeleteInterpProc _ANSI_ARGS_((Tcl_Interp *interp));
static void ProcessUnexpectedResult _ANSI_ARGS_((
Tcl_Interp *interp, int returnCode));
+static int OldMathFuncProc _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp* interp,
+ int argc,
+ Tcl_Obj *CONST *objv ));
+
+static void OldMathFuncDeleteProc _ANSI_ARGS_((ClientData));
+
+static int ExprAbsFunc _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp,
+ int argc,
+ Tcl_Obj *CONST *objv));
+static int ExprBinaryFunc _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp,
+ int argc,
+ Tcl_Obj *CONST *objv));
+static int ExprDoubleFunc _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp,
+ int argc,
+ Tcl_Obj *CONST *objv));
+static int ExprIntFunc _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp,
+ int argc,
+ Tcl_Obj *CONST *objv));
+static int ExprRandFunc _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp,
+ int argc,
+ Tcl_Obj *CONST *objv));
+static int ExprRoundFunc _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp,
+ int argc,
+ Tcl_Obj *CONST *objv));
+static int ExprSrandFunc _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp,
+ int argc,
+ Tcl_Obj *CONST *objv));
+static int ExprUnaryFunc _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp,
+ int argc,
+ Tcl_Obj *CONST *objv));
+static int ExprWideFunc _ANSI_ARGS_((ClientData clientData,
+ Tcl_Interp *interp,
+ int argc,
+ Tcl_Obj *CONST *objv));
+static int VerifyExprObjType _ANSI_ARGS_((Tcl_Interp *interp,
+ Tcl_Obj *objPtr));
+
+static void MathFuncWrongNumArgs
+ _ANSI_ARGS_((Tcl_Interp* interp,
+ int expected,
+ int actual,
+ Tcl_Obj *CONST *objv ));
+
+#ifndef TCL_WIDE_INT_IS_LONG
+/*
+ * Extract a double value from a general numeric object.
+ */
+#define GET_DOUBLE_VALUE(doubleVar, objPtr, typePtr) \
+ if ((typePtr) == &tclIntType) { \
+ (doubleVar) = (double) (objPtr)->internalRep.longValue; \
+ } else if ((typePtr) == &tclWideIntType) { \
+ (doubleVar) = Tcl_WideAsDouble((objPtr)->internalRep.wideValue);\
+ } else { \
+ (doubleVar) = (objPtr)->internalRep.doubleValue; \
+ }
+#else /* TCL_WIDE_INT_IS_LONG */
+#define GET_DOUBLE_VALUE(doubleVar, objPtr, typePtr) \
+ if (((typePtr) == &tclIntType) || ((typePtr) == &tclWideIntType)) { \
+ (doubleVar) = (double) (objPtr)->internalRep.longValue; \
+ } else { \
+ (doubleVar) = (objPtr)->internalRep.doubleValue; \
+ }
+#endif /* TCL_WIDE_INT_IS_LONG */
+#define GET_WIDE_OR_INT(resultVar, objPtr, longVar, wideVar) \
+ (resultVar) = Tcl_GetWideIntFromObj((Tcl_Interp *) NULL, (objPtr), \
+ &(wideVar)); \
+ if ((resultVar) == TCL_OK && (wideVar) >= Tcl_LongAsWide(LONG_MIN) \
+ && (wideVar) <= Tcl_LongAsWide(LONG_MAX)) { \
+ (objPtr)->typePtr = &tclIntType; \
+ (objPtr)->internalRep.longValue = (longVar) \
+ = Tcl_WideAsLong(wideVar); \
+ }
+#define IS_INTEGER_TYPE(typePtr) \
+ ((typePtr) == &tclIntType || (typePtr) == &tclWideIntType)
+#define IS_NUMERIC_TYPE(typePtr) \
+ (IS_INTEGER_TYPE(typePtr) || (typePtr) == &tclDoubleType)
+
+/*
+ * Macros for testing floating-point values for certain special cases. Test
+ * for not-a-number by comparing a value against itself; test for infinity
+ * by comparing against the largest floating-point value.
+ */
+
+#ifdef _MSC_VER
+#define IS_NAN(f) (_isnan((f)))
+#define IS_INF(f) ( ! (_finite((f))))
+#else
+#define IS_NAN(f) ((f) != (f))
+#define IS_INF(f) ( (f) > DBL_MAX || (f) < -DBL_MAX )
+#endif
+
extern TclStubs tclStubs;
/*
@@ -144,6 +260,55 @@ static CmdInfo builtInCmds[] = {
{NULL, (Tcl_ObjCmdProc *) NULL, (CompileProc *) NULL, 0}
};
+/*
+ * Math functions
+ */
+
+typedef struct {
+ CONST char* name; /* Name of the function */
+ Tcl_ObjCmdProc* objCmdProc; /* Procedure that evaluates the function */
+ ClientData clientData; /* Client data for the procedure */
+} BuiltinFuncDef;
+BuiltinFuncDef BuiltinFuncTable[] = {
+ { "::tcl::mathfunc::abs", ExprAbsFunc, NULL },
+#ifndef TCL_NO_MATH
+ { "::tcl::mathfunc::acos", ExprUnaryFunc, (ClientData) acos },
+ { "::tcl::mathfunc::asin", ExprUnaryFunc, (ClientData) asin },
+ { "::tcl::mathfunc::atan", ExprUnaryFunc, (ClientData) atan },
+ { "::tcl::mathfunc::atan2", ExprBinaryFunc, (ClientData) atan2 },
+ { "::tcl::mathfunc::ceil", ExprUnaryFunc, (ClientData) ceil },
+ { "::tcl::mathfunc::cos", ExprUnaryFunc, (ClientData) cos },
+ { "::tcl::mathfunc::cosh", ExprUnaryFunc, (ClientData) cosh },
+#endif
+ { "::tcl::mathfunc::double",ExprDoubleFunc, NULL },
+#ifndef TCL_NO_MATH
+ { "::tcl::mathfunc::exp", ExprUnaryFunc, (ClientData) exp },
+ { "::tcl::mathfunc::floor", ExprUnaryFunc, (ClientData) floor },
+ { "::tcl::mathfunc::fmod", ExprBinaryFunc, (ClientData) fmod },
+ { "::tcl::mathfunc::hypot", ExprBinaryFunc, (ClientData) hypot },
+#endif
+ { "::tcl::mathfunc::int", ExprIntFunc, NULL },
+#ifndef TCL_NO_MATH
+ { "::tcl::mathfunc::log", ExprUnaryFunc, (ClientData) log },
+ { "::tcl::mathfunc::log10", ExprUnaryFunc, (ClientData) log10 },
+ { "::tcl::mathfunc::pow", ExprBinaryFunc, (ClientData) pow },
+#endif
+ { "::tcl::mathfunc::rand", ExprRandFunc, NULL },
+ { "::tcl::mathfunc::round", ExprRoundFunc, NULL },
+#ifndef TCL_NO_MATH
+ { "::tcl::mathfunc::sin", ExprUnaryFunc, (ClientData) sin },
+ { "::tcl::mathfunc::sinh", ExprUnaryFunc, (ClientData) sinh },
+ { "::tcl::mathfunc::sqrt", ExprUnaryFunc, (ClientData) sqrt },
+#endif
+ { "::tcl::mathfunc::srand", ExprSrandFunc, NULL },
+#ifndef TCL_NO_MATH
+ { "::tcl::mathfunc::tan", ExprUnaryFunc, (ClientData) tan },
+ { "::tcl::mathfunc::tanh", ExprUnaryFunc, (ClientData) tanh },
+#endif
+ { "::tcl::mathfunc::wide", ExprWideFunc, NULL },
+ { NULL, NULL, NULL }
+};
+
/*
*----------------------------------------------------------------------
@@ -170,10 +335,9 @@ Tcl_CreateInterp()
Interp *iPtr;
Tcl_Interp *interp;
Command *cmdPtr;
- BuiltinFunc *builtinFuncPtr;
- MathFunc *mathFuncPtr;
- Tcl_HashEntry *hPtr;
+ BuiltinFuncDef *builtinFuncPtr;
const CmdInfo *cmdInfoPtr;
+ Tcl_Namespace* mathfuncNSPtr;
int i;
union {
char c[sizeof(short)];
@@ -213,7 +377,6 @@ Tcl_CreateInterp()
iPtr->globalNsPtr = NULL;
iPtr->hiddenCmdTablePtr = NULL;
iPtr->interpInfo = NULL;
- Tcl_InitHashTable(&iPtr->mathFuncTable, TCL_STRING_KEYS);
iPtr->numLevels = 0;
iPtr->maxNestingDepth = MAX_NESTING_DEPTH;
@@ -223,10 +386,10 @@ Tcl_CreateInterp()
iPtr->returnOpts = NULL;
iPtr->errorInfo = NULL;
- iPtr->eiVar = Tcl_NewStringObj("errorInfo", -1);
+ iPtr->eiVar = Tcl_NewStringObj( "errorInfo", -1 );
Tcl_IncrRefCount(iPtr->eiVar);
iPtr->errorCode = NULL;
- iPtr->ecVar = Tcl_NewStringObj("errorCode", -1);
+ iPtr->ecVar = Tcl_NewStringObj( "errorCode", -1 );
Tcl_IncrRefCount(iPtr->ecVar);
iPtr->returnLevel = 0;
iPtr->returnCode = TCL_OK;
@@ -399,6 +562,11 @@ Tcl_CreateInterp()
TclClockOldscanObjCmd, (ClientData) NULL,
(Tcl_CmdDeleteProc*) NULL );
+ /*
+ * Register the built-in functions
+ */
+
+
/* Register the default [interp bgerror] handler. */
Tcl_CreateObjCommand( interp, "::tcl::Bgerror",
@@ -413,21 +581,25 @@ Tcl_CreateInterp()
* Register the builtin math functions.
*/
+ mathfuncNSPtr = Tcl_CreateNamespace( interp, "::tcl::mathfunc",
+ (ClientData) NULL,
+ (Tcl_NamespaceDeleteProc*) NULL );
+ if ( mathfuncNSPtr == NULL ) {
+ Tcl_Panic( "Can't create math function namespace" );
+ }
i = 0;
- for (builtinFuncPtr = tclBuiltinFuncTable; builtinFuncPtr->name != NULL;
- builtinFuncPtr++) {
- Tcl_CreateMathFunc((Tcl_Interp *) iPtr, builtinFuncPtr->name,
- builtinFuncPtr->numArgs, builtinFuncPtr->argTypes,
- (Tcl_MathProc *) NULL, (ClientData) 0);
- hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable,
- builtinFuncPtr->name);
- if (hPtr == NULL) {
- Tcl_Panic("Tcl_CreateInterp: Tcl_CreateMathFunc incorrectly registered '%s'", builtinFuncPtr->name);
- return NULL;
+ for ( ; ; ) {
+ CONST char* tail;
+ builtinFuncPtr = &(BuiltinFuncTable[ i++ ]);
+ if ( builtinFuncPtr->name == NULL ) {
+ break;
}
- mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
- mathFuncPtr->builtinFuncIndex = i;
- i++;
+ Tcl_CreateObjCommand( interp, builtinFuncPtr->name,
+ builtinFuncPtr->objCmdProc,
+ builtinFuncPtr->clientData,
+ (Tcl_CmdDeleteProc*) NULL );
+ tail = builtinFuncPtr->name + strlen( "::tcl::mathfunc::" );
+ Tcl_Export( interp, mathfuncNSPtr, tail, 0 );
}
/*
@@ -936,16 +1108,6 @@ DeleteInterpProc(interp)
Tcl_DeleteHashTable(hTablePtr);
ckfree((char *) hTablePtr);
}
- /*
- * Tear down the math function table.
- */
-
- for (hPtr = Tcl_FirstHashEntry(&iPtr->mathFuncTable, &search);
- hPtr != NULL;
- hPtr = Tcl_NextHashEntry(&search)) {
- ckfree((char *) Tcl_GetHashValue(hPtr));
- }
- Tcl_DeleteHashTable(&iPtr->mathFuncTable);
/*
* Invoke deletion callbacks; note that a callback can create new
@@ -2675,52 +2837,176 @@ Tcl_CreateMathFunc(interp, name, numArgs, argTypes, proc, clientData)
ClientData clientData; /* Additional value to pass to the
* function. */
{
- Interp *iPtr = (Interp *) interp;
- Tcl_HashEntry *hPtr;
- MathFunc *mathFuncPtr;
- int new, i;
- hPtr = Tcl_CreateHashEntry(&iPtr->mathFuncTable, name, &new);
- if (new) {
- Tcl_SetHashValue(hPtr, ckalloc(sizeof(MathFunc)));
+ Tcl_DString bigName;
+
+ OldMathFuncData* data
+ = (OldMathFuncData*) Tcl_Alloc( sizeof ( OldMathFuncData ) );
+
+ if ( numArgs > MAX_MATH_ARGS ) {
+ Tcl_Panic( "attempt to create a math function with too many args" );
}
- mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
- if (!new) {
- if (mathFuncPtr->builtinFuncIndex >= 0) {
- /*
- * We are redefining a builtin math function. Invalidate the
- * interpreter's existing code by incrementing its
- * compileEpoch member. This field is checked in Tcl_EvalObj
- * and ObjInterpProc, and code whose compilation epoch doesn't
- * match is recompiled. Newly compiled code will no longer
- * treat the function as builtin.
- */
+ data->proc = proc;
+ data->numArgs = numArgs;
+ data->argTypes
+ = (Tcl_ValueType*) Tcl_Alloc( numArgs * sizeof( Tcl_ValueType ) );
+ memcpy( data->argTypes, argTypes, numArgs * sizeof( Tcl_ValueType ) );
+ data->clientData = clientData;
- iPtr->compileEpoch++;
- } else {
- /*
- * A non-builtin function is being redefined. We must invalidate
- * existing code if the number of arguments has changed. This
- * is because existing code was compiled assuming that number.
- */
+ Tcl_DStringInit( &bigName );
+ Tcl_DStringAppend( &bigName, "::tcl::mathfunc::", -1 );
+ Tcl_DStringAppend( &bigName, name, -1 );
- if (numArgs != mathFuncPtr->numArgs) {
- iPtr->compileEpoch++;
+ Tcl_CreateObjCommand( interp, Tcl_DStringValue( &bigName ),
+ OldMathFuncProc, (ClientData) data,
+ OldMathFuncDeleteProc );
+ Tcl_DStringFree( &bigName );
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * OldMathFuncProc --
+ *
+ * Dispatch to a math function created with Tcl_CreateMathFunc
+ *
+ * Results:
+ * Returns a standard Tcl result.
+ *
+ * Side effects:
+ * Whatever the math function does.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+OldMathFuncProc( clientData, interp, objc, objv )
+ ClientData clientData; /* Ponter to OldMathFuncData describing
+ * the function being called */
+ Tcl_Interp* interp; /* Tcl interpreter */
+ int objc; /* Actual parameter count */
+ Tcl_Obj *CONST *objv; /* Parameter vector */
+{
+ Tcl_Obj* valuePtr;
+ OldMathFuncData* dataPtr = (OldMathFuncData*) clientData;
+ Tcl_Value args[MAX_MATH_ARGS];
+ Tcl_Value funcResult;
+ int result;
+ int i, j, k;
+ double d;
+
+ /* Check argument count */
+
+ if ( objc != dataPtr->numArgs + 1 ) {
+ MathFuncWrongNumArgs( interp, dataPtr->numArgs+1, objc, objv );
+ return TCL_ERROR;
+ }
+
+ /* Convert arguments from Tcl_Obj's to Tcl_Value's */
+
+ for ( j = 1, k = 0; j < objc; ++j, ++k ) {
+ valuePtr = objv[j];
+ if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Copy the object's numeric value to the argument record,
+ * converting it if necessary.
+ */
+
+ if (valuePtr->typePtr == &tclIntType) {
+ i = valuePtr->internalRep.longValue;
+ if (dataPtr->argTypes[k] == TCL_DOUBLE) {
+ args[k].type = TCL_DOUBLE;
+ args[k].doubleValue = i;
+ } else if (dataPtr->argTypes[k] == TCL_WIDE_INT) {
+ args[k].type = TCL_WIDE_INT;
+ args[k].wideValue = Tcl_LongAsWide(i);
+ } else {
+ args[k].type = TCL_INT;
+ args[k].intValue = i;
+ }
+ } else if (valuePtr->typePtr == &tclWideIntType) {
+ Tcl_WideInt w;
+ TclGetWide(w,valuePtr);
+ if (dataPtr->argTypes[k] == TCL_DOUBLE) {
+ args[k].type = TCL_DOUBLE;
+ args[k].doubleValue = Tcl_WideAsDouble(w);
+ } else if (dataPtr->argTypes[k] == TCL_INT) {
+ args[k].type = TCL_INT;
+ args[k].intValue = Tcl_WideAsLong(w);
+ } else {
+ args[k].type = TCL_WIDE_INT;
+ args[k].wideValue = w;
+ }
+ } else {
+ d = valuePtr->internalRep.doubleValue;
+ if (dataPtr->argTypes[k] == TCL_INT) {
+ args[k].type = TCL_INT;
+ args[k].intValue = (long) d;
+ } else if (dataPtr->argTypes[k] == TCL_WIDE_INT) {
+ args[k].type = TCL_WIDE_INT;
+ args[k].wideValue = Tcl_DoubleAsWide(d);
+ } else {
+ args[k].type = TCL_DOUBLE;
+ args[k].doubleValue = d;
}
}
}
-
- mathFuncPtr->builtinFuncIndex = -1; /* can't be a builtin function */
- if (numArgs > MAX_MATH_ARGS) {
- numArgs = MAX_MATH_ARGS;
+
+ /* Call the function */
+
+ result = (*dataPtr->proc)(dataPtr->clientData, interp, args,
+ &funcResult);
+ if (result != TCL_OK) {
+ return result;
}
- mathFuncPtr->numArgs = numArgs;
- for (i = 0; i < numArgs; i++) {
- mathFuncPtr->argTypes[i] = argTypes[i];
+
+ /* Return the result of the call */
+
+ if (funcResult.type == TCL_INT) {
+ TclNewLongObj(valuePtr, funcResult.intValue);
+ } else if (funcResult.type == TCL_WIDE_INT) {
+ TclNewWideIntObj(valuePtr, funcResult.wideValue);
+ } else {
+ d = funcResult.doubleValue;
+ if (IS_NAN(d) || IS_INF(d)) {
+ TclExprFloatError(interp, d);
+ return TCL_ERROR;
+ }
+ TclNewDoubleObj(valuePtr, d);
}
- mathFuncPtr->proc = proc;
- mathFuncPtr->clientData = clientData;
+ Tcl_SetObjResult( interp, valuePtr );
+ return TCL_OK;
+
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * OldMathFuncDeleteProc --
+ *
+ * Cleans up after deleting a math function registered with
+ * Tcl_CreateMathFunc
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Frees allocated memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+OldMathFuncDeleteProc( clientData )
+ ClientData clientData;
+{
+ OldMathFuncData* dataPtr = (OldMathFuncData*) clientData;
+ Tcl_Free( (VOID*) dataPtr->argTypes );
+ Tcl_Free( (VOID*) dataPtr );
}
/*
@@ -2757,39 +3043,51 @@ Tcl_GetMathFuncInfo(interp, name, numArgsPtr, argTypesPtr, procPtr,
Tcl_MathProc **procPtr;
ClientData *clientDataPtr;
{
- Interp *iPtr = (Interp *) interp;
- Tcl_HashEntry *hPtr;
- MathFunc *mathFuncPtr;
- Tcl_ValueType *argTypes;
- int i,numArgs;
- hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, name);
- if (hPtr == NULL) {
- Tcl_AppendResult(interp, "math function \"", name,
- "\" not known in this interpreter", (char *) NULL);
- return TCL_ERROR;
- }
- mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
+ Tcl_Obj* cmdNameObj;
+ Command* cmdPtr;
- *numArgsPtr = numArgs = mathFuncPtr->numArgs;
- if (numArgs == 0) {
- /* Avoid doing zero-sized allocs... */
- numArgs = 1;
- }
- *argTypesPtr = argTypes =
- (Tcl_ValueType *)ckalloc(numArgs * sizeof(Tcl_ValueType));
- for (i = 0; i < mathFuncPtr->numArgs; i++) {
- argTypes[i] = mathFuncPtr->argTypes[i];
+ /* Get the command that implements the math function */
+
+ cmdNameObj = Tcl_NewStringObj( "tcl::mathfunc::", -1 );
+ Tcl_AppendToObj( cmdNameObj, name, -1 );
+ Tcl_IncrRefCount( cmdNameObj );
+ cmdPtr = (Command*) Tcl_GetCommandFromObj( interp, cmdNameObj );
+ Tcl_DecrRefCount( cmdNameObj );
+
+ /* Report unknown functions */
+
+ if ( cmdPtr == NULL ) {
+ Tcl_Obj* message;
+ message = Tcl_NewStringObj( "unknown math function \"", -1 );
+ Tcl_AppendToObj( message, name, -1 );
+ Tcl_AppendToObj( message, "\"", 1 );
+ *numArgsPtr = -1; *argTypesPtr = NULL;
+ *procPtr = NULL;
+ *clientDataPtr = NULL;
+ return TCL_ERROR;
}
+
+ /*
+ * Retrieve function info for user defined functions; return
+ * dummy information for builtins.
+ */
- if (mathFuncPtr->builtinFuncIndex == -1) {
- *procPtr = (Tcl_MathProc *) NULL;
+ if ( cmdPtr->objProc == &OldMathFuncProc ) {
+ OldMathFuncData* dataPtr = (OldMathFuncData*) cmdPtr->clientData;
+ *procPtr = dataPtr->proc;
+ *numArgsPtr = dataPtr->numArgs;
+ *argTypesPtr = dataPtr->argTypes;
+ *clientDataPtr = dataPtr->clientData;
} else {
- *procPtr = mathFuncPtr->proc;
- *clientDataPtr = mathFuncPtr->clientData;
+ *procPtr = NULL;
+ *numArgsPtr = -1;
+ *argTypesPtr = NULL;
+ *procPtr = NULL;
+ *clientDataPtr = NULL;
}
-
return TCL_OK;
+
}
/*
@@ -2816,33 +3114,42 @@ Tcl_ListMathFuncs(interp, pattern)
Tcl_Interp *interp;
CONST char *pattern;
{
- Interp *iPtr = (Interp *) interp;
- Tcl_Obj *resultList = Tcl_NewObj();
- register Tcl_HashEntry *hPtr;
- Tcl_HashSearch hSearch;
- CONST char *name;
-
- if ((pattern != NULL) && TclMatchIsTrivial(pattern)) {
- if ((Tcl_FindHashEntry(&iPtr->mathFuncTable, pattern) != NULL)
- && (Tcl_ListObjAppendElement(interp, resultList,
- Tcl_NewStringObj(pattern,-1)) != TCL_OK)) {
- goto error;
- }
- return resultList;
- }
- for (hPtr = Tcl_FirstHashEntry(&iPtr->mathFuncTable, &hSearch);
- hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) {
- name = Tcl_GetHashKey(&iPtr->mathFuncTable, hPtr);
- if ((pattern == NULL || Tcl_StringMatch(name, pattern)) &&
- /* I don't expect this to fail, but... */
- Tcl_ListObjAppendElement(interp, resultList,
- Tcl_NewStringObj(name,-1)) != TCL_OK) {
-error:
- Tcl_DecrRefCount(resultList);
- return NULL;
+ Namespace* globalNsPtr = (Namespace*) Tcl_GetGlobalNamespace( interp );
+ Namespace* nsPtr;
+ Namespace* dummy1NsPtr;
+ Namespace* dummy2NsPtr;
+ CONST char* dummyNamePtr;
+ Tcl_Obj* result = Tcl_NewObj();
+ Tcl_HashEntry* cmdHashEntry;
+ Tcl_HashSearch cmdHashSearch;
+ CONST char* cmdNamePtr;
+
+ TclGetNamespaceForQualName( interp, "::tcl::mathfunc",
+ globalNsPtr,
+ TCL_FIND_ONLY_NS | TCL_GLOBAL_ONLY,
+ &nsPtr, &dummy1NsPtr, &dummy2NsPtr,
+ &dummyNamePtr );
+
+ if ( nsPtr != NULL ) {
+ if ((pattern != NULL) && TclMatchIsTrivial(pattern)) {
+ if (Tcl_FindHashEntry(&nsPtr->cmdTable, pattern) != NULL) {
+ Tcl_ListObjAppendElement(NULL, result,
+ Tcl_NewStringObj(pattern,-1));
+ }
+ } else {
+ for ( cmdHashEntry =
+ Tcl_FirstHashEntry( &nsPtr->cmdTable, &cmdHashSearch );
+ cmdHashEntry != NULL;
+ cmdHashEntry = Tcl_NextHashEntry( &cmdHashSearch ) ) {
+ cmdNamePtr = Tcl_GetHashKey( &nsPtr->cmdTable, cmdHashEntry );
+ if (pattern == NULL || Tcl_StringMatch(cmdNamePtr, pattern)) {
+ Tcl_ListObjAppendElement( NULL, result,
+ Tcl_NewStringObj( cmdNamePtr, -1 ) );
+ }
+ }
}
}
- return resultList;
+ return result;
}
/*
@@ -3000,7 +3307,7 @@ TclEvalObjvInternal(interp, objc, objv, command, length, flags)
for (i = objc-1; i >= 0; i--) {
newObjv[i+1] = objv[i];
}
- newObjv[0] = Tcl_NewStringObj("::unknown", -1);
+ newObjv[0] = Tcl_NewStringObj( "::unknown", -1);
Tcl_IncrRefCount(newObjv[0]);
cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, newObjv[0]);
if (cmdPtr == NULL) {
@@ -3483,9 +3790,10 @@ Tcl_EvalEx(interp, script, numBytes, flags)
objv[objectsUsed], &numElements);
if (code == TCL_ERROR) {
/* Attempt to expand a non-list */
- Tcl_Obj *msg =
- Tcl_NewStringObj("\n (expanding word ", -1);
- Tcl_Obj *wordNum = Tcl_NewIntObj(objectsUsed);
+ Tcl_Obj *msg;
+ Tcl_Obj *wordNum;
+ msg = Tcl_NewStringObj("\n (expanding word ", -1);
+ TclNewIntObj( wordNum, objectsUsed );
Tcl_IncrRefCount(wordNum);
Tcl_IncrRefCount(msg);
Tcl_AppendObjToObj(msg, wordNum);
@@ -4299,8 +4607,9 @@ TclObjInvoke(interp, objc, objv, flags)
&& ((iPtr->flags & ERR_ALREADY_LOGGED) == 0)) {
int length;
Tcl_Obj *command = Tcl_NewListObj(objc, objv);
- CONST char* cmdString = Tcl_GetStringFromObj(command, &length);
-
+ CONST char* cmdString;
+ Tcl_IncrRefCount( command );
+ cmdString = Tcl_GetStringFromObj(command, &length);
Tcl_LogCommandInfo(interp, cmdString, cmdString, length);
Tcl_DecrRefCount(command);
iPtr->flags &= ~ERR_ALREADY_LOGGED;
@@ -4701,4 +5010,642 @@ Tcl_GetVersion(majorV, minorV, patchLevelV, type)
*type = TCL_RELEASE_LEVEL;
}
}
-
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Math Functions --
+ *
+ * This page contains the procedures that implement all of the
+ * built-in math functions for expressions.
+ *
+ * Results:
+ * Each procedure returns TCL_OK if it succeeds and pushes an
+ * Tcl object holding the result. If it fails it returns TCL_ERROR
+ * and leaves an error message in the interpreter's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+ExprUnaryFunc(clientData, interp, objc, objv)
+ ClientData clientData; /* Contains the address of a procedure that
+ * takes one double argument and returns a
+ * double result. */
+ Tcl_Interp *interp; /* The interpreter in which to execute the
+ * function. */
+ int objc; /* Actual parameter count */
+ Tcl_Obj *CONST *objv; /* Actual parameter list */
+{
+ double d, dResult;
+ Tcl_Obj* oResult;
+
+ double (*func) _ANSI_ARGS_((double)) =
+ (double (*)_ANSI_ARGS_((double))) clientData;
+
+ /*
+ * Convert the function's argument to a double if necessary.
+ */
+
+ if ( objc != 2 ) {
+ MathFuncWrongNumArgs( interp, 2, objc, objv );
+ } else if ( Tcl_GetDoubleFromObj( interp, objv[1], &d ) == TCL_OK ) {
+
+ /* Evaluate the function */
+
+ dResult = (*func)(d);
+ if ((errno != 0 ) || IS_NAN(dResult)) {
+ if ( errno != ERANGE || ( dResult != 0.0 && !IS_INF(dResult) )) {
+ TclExprFloatError(interp, dResult);
+ return TCL_ERROR;
+ }
+ }
+ TclNewDoubleObj( oResult, dResult );
+ Tcl_SetObjResult( interp, oResult );
+ return TCL_OK;
+ }
+
+ return TCL_ERROR;
+}
+
+static int
+ExprBinaryFunc( clientData, interp, objc, objv )
+ ClientData clientData; /* Contains the address of a procedure that
+ * takes two double arguments and
+ * returns a double result. */
+ Tcl_Interp *interp; /* The interpreter in which to execute the
+ * function. */
+ int objc; /* Actual parameter count */
+ Tcl_Obj *CONST *objv; /* Parameter vector */
+{
+ double d1, d2, dResult;
+ Tcl_Obj* oResult;
+
+ double (*func) _ANSI_ARGS_((double, double))
+ = (double (*)_ANSI_ARGS_((double, double))) clientData;
+
+ /*
+ * Convert the function's two arguments to doubles if necessary.
+ */
+
+ if ( objc != 3 ) {
+ MathFuncWrongNumArgs( interp, 3, objc, objv );
+ } else if ( Tcl_GetDoubleFromObj( interp, objv[1], &d1 ) == TCL_OK
+ && Tcl_GetDoubleFromObj( interp, objv[2], &d2 ) == TCL_OK ) {
+
+ /* Evaluate the function */
+
+ errno = 0;
+ dResult = (*func)(d1, d2);
+ if ((errno != 0) || IS_NAN(dResult)) {
+ if ( errno != ERANGE || ( dResult != 0.0 && !IS_INF( dResult ) ) ) {
+ TclExprFloatError(interp, dResult);
+ return TCL_ERROR;
+ }
+ }
+ TclNewDoubleObj( oResult, dResult );
+ Tcl_SetObjResult( interp, oResult );
+ return TCL_OK;
+ }
+
+ return TCL_ERROR;
+
+}
+
+static int
+ExprAbsFunc( clientData, interp, objc, objv )
+ ClientData clientData; /* Ignored. */
+ Tcl_Interp *interp; /* The interpreter in which to execute the
+ * function. */
+ int objc; /* Actual parameter count */
+ Tcl_Obj *CONST *objv; /* Parameter vector */
+{
+ register Tcl_Obj *valuePtr;
+ long i, iResult;
+ double d, dResult;
+ Tcl_Obj* oResult;
+
+ if ( objc != 2 ) {
+ MathFuncWrongNumArgs( interp, 2, objc, objv );
+ return TCL_ERROR;
+ }
+ valuePtr = objv[1];
+
+ if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Derive the absolute value according to the arg type.
+ */
+ if (valuePtr->typePtr == &tclIntType) {
+ i = valuePtr->internalRep.longValue;
+ if (i < 0) {
+ iResult = -i;
+ if (iResult < 0) {
+ /* FIXME: This should promote to wide! */
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "integer value too large to represent", -1));
+ Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
+ "integer value too large to represent", (char *) NULL);
+ return TCL_ERROR;
+ }
+ } else {
+ iResult = i;
+ }
+ TclNewLongObj( oResult, iResult );
+ Tcl_SetObjResult( interp, oResult );
+ } else if (valuePtr->typePtr == &tclWideIntType) {
+ Tcl_WideInt wResult, w;
+ TclGetWide(w,valuePtr);
+ if (w < (Tcl_WideInt)0) {
+ wResult = -w;
+ if (wResult < 0) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "integer value too large to represent", -1));
+ Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
+ "integer value too large to represent", (char *) NULL);
+ return TCL_ERROR;
+ }
+ } else {
+ wResult = w;
+ }
+ TclNewWideIntObj( oResult, wResult );
+ Tcl_SetObjResult( interp, oResult );
+ } else {
+ d = valuePtr->internalRep.doubleValue;
+ if (d < 0.0) {
+ dResult = -d;
+ } else {
+ dResult = d;
+ }
+ if (IS_NAN(dResult)) {
+ TclExprFloatError(interp, dResult);
+ return TCL_ERROR;
+ }
+ TclNewDoubleObj( oResult, dResult );
+ Tcl_SetObjResult( interp, oResult );
+ }
+
+ return TCL_OK;
+}
+
+static int
+ExprDoubleFunc(clientData, interp, objc, objv )
+ ClientData clientData; /* Ignored. */
+ Tcl_Interp *interp; /* The interpreter in which to execute the
+ * function. */
+ int objc; /* Actual parameter count */
+ Tcl_Obj *CONST *objv; /* Actual parameter vector */
+{
+ Tcl_Obj* valuePtr;
+ double dResult;
+ Tcl_Obj* oResult;
+
+ /*
+ * Check parameter type
+ */
+
+ if ( objc != 2 ) {
+ MathFuncWrongNumArgs( interp, 2, objc, objv );
+ } else {
+ valuePtr = objv[1];
+ if ( VerifyExprObjType( interp, valuePtr ) == TCL_OK ) {
+ GET_DOUBLE_VALUE( dResult, valuePtr, valuePtr->typePtr );
+ TclNewDoubleObj( oResult, dResult );
+ Tcl_SetObjResult( interp, oResult );
+ return TCL_OK;
+ }
+ }
+
+ return TCL_ERROR;
+}
+
+static int
+ExprIntFunc(clientData, interp, objc, objv)
+ ClientData clientData; /* Ignored. */
+ Tcl_Interp *interp; /* The interpreter in which to execute the
+ * function. */
+ int objc; /* Actual parameter count */
+ Tcl_Obj *CONST *objv; /* Actual parameter vector */
+{
+
+ register Tcl_Obj *valuePtr;
+ long iResult;
+ double d;
+ Tcl_Obj* oResult;
+
+ if ( objc != 2 ) {
+ MathFuncWrongNumArgs( interp, 2, objc, objv );
+ } else {
+ valuePtr = objv[1];
+ if (VerifyExprObjType(interp, valuePtr) == TCL_OK) {
+ if (valuePtr->typePtr == &tclIntType) {
+ iResult = valuePtr->internalRep.longValue;
+ } else if (valuePtr->typePtr == &tclWideIntType) {
+ TclGetLongFromWide(iResult,valuePtr);
+ } else {
+ d = valuePtr->internalRep.doubleValue;
+ if (d < 0.0) {
+ if (d < (double) (long) LONG_MIN) {
+ tooLarge:
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "integer value too large to represent", -1));
+ Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
+ "integer value too large to represent",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ } else {
+ if (d > (double) LONG_MAX) {
+ goto tooLarge;
+ }
+ }
+ if (IS_NAN(d) || IS_INF(d)) {
+ TclExprFloatError(interp, d);
+ return TCL_ERROR;
+ }
+ iResult = (long) d;
+ }
+ TclNewIntObj( oResult, iResult );
+ Tcl_SetObjResult( interp, oResult );
+ return TCL_OK;
+ }
+ }
+ return TCL_ERROR;
+}
+
+static int
+ExprWideFunc(clientData, interp, objc, objv)
+ ClientData clientData; /* Ignored. */
+ Tcl_Interp *interp; /* The interpreter in which to execute the
+ * function. */
+ int objc; /* Actual parameter count */
+ Tcl_Obj *CONST *objv; /* Actual parameter vector */
+{
+
+ register Tcl_Obj *valuePtr;
+ Tcl_WideInt wResult;
+ double d;
+ Tcl_Obj* oResult;
+
+ if ( objc != 2 ) {
+ MathFuncWrongNumArgs( interp, 2, objc, objv );
+ } else {
+ valuePtr = objv[1];
+ if (VerifyExprObjType(interp, valuePtr) == TCL_OK) {
+ if (valuePtr->typePtr == &tclIntType) {
+ wResult = valuePtr->internalRep.longValue;
+ } else if (valuePtr->typePtr == &tclWideIntType) {
+ wResult = valuePtr->internalRep.wideValue;
+ } else {
+ d = valuePtr->internalRep.doubleValue;
+ if (d < 0.0) {
+ if (d < Tcl_WideAsDouble( LLONG_MIN ) ) {
+ tooLarge:
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "integer value too large to represent", -1));
+ Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
+ "integer value too large to represent",
+ (char *) NULL);
+ return TCL_ERROR;
+ }
+ } else {
+ if (d > Tcl_WideAsDouble( LLONG_MAX ) ) {
+ goto tooLarge;
+ }
+ }
+ if (IS_NAN(d) || IS_INF(d)) {
+ TclExprFloatError(interp, d);
+ return TCL_ERROR;
+ }
+ wResult = (Tcl_WideInt) d;
+ }
+ TclNewWideIntObj( oResult, wResult );
+ Tcl_SetObjResult( interp, oResult );
+ return TCL_OK;
+ }
+ }
+ return TCL_ERROR;
+}
+
+static int
+ExprRandFunc(clientData, interp, objc, objv)
+ ClientData clientData; /* Ignored. */
+ Tcl_Interp *interp; /* The interpreter in which to execute the
+ * function. */
+ int objc; /* Actual parameter count */
+ Tcl_Obj *CONST *objv; /* Actual parameter vector */
+{
+ Interp *iPtr = (Interp *) interp;
+ double dResult;
+ long tmp; /* Algorithm assumes at least 32 bits.
+ * Only long guarantees that. See below. */
+ Tcl_Obj* oResult;
+
+ if ( objc != 1 ) {
+ MathFuncWrongNumArgs( interp, 1, objc, objv );
+ return TCL_ERROR;
+ }
+
+ if (!(iPtr->flags & RAND_SEED_INITIALIZED)) {
+ iPtr->flags |= RAND_SEED_INITIALIZED;
+
+ /*
+ * Take into consideration the thread this interp is running in order
+ * to insure different seeds in different threads (bug #416643)
+ */
+
+ iPtr->randSeed = TclpGetClicks() + ((long)Tcl_GetCurrentThread()<<12);
+
+ /*
+ * Make sure 1 <= randSeed <= (2^31) - 2. See below.
+ */
+
+ iPtr->randSeed &= (unsigned long) 0x7fffffff;
+ if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7fffffff)) {
+ iPtr->randSeed ^= 123459876;
+ }
+ }
+
+ /*
+ * Generate the random number using the linear congruential
+ * generator defined by the following recurrence:
+ * seed = ( IA * seed ) mod IM
+ * where IA is 16807 and IM is (2^31) - 1. The recurrence maps
+ * a seed in the range [1, IM - 1] to a new seed in that same range.
+ * The recurrence maps IM to 0, and maps 0 back to 0, so those two
+ * values must not be allowed as initial values of seed.
+ *
+ * In order to avoid potential problems with integer overflow, the
+ * recurrence is implemented in terms of additional constants
+ * IQ and IR such that
+ * IM = IA*IQ + IR
+ * None of the operations in the implementation overflows a 32-bit
+ * signed integer, and the C type long is guaranteed to be at least
+ * 32 bits wide.
+ *
+ * For more details on how this algorithm works, refer to the following
+ * papers:
+ *
+ * S.K. Park & K.W. Miller, "Random number generators: good ones
+ * are hard to find," Comm ACM 31(10):1192-1201, Oct 1988
+ *
+ * W.H. Press & S.A. Teukolsky, "Portable random number
+ * generators," Computers in Physics 6(5):522-524, Sep/Oct 1992.
+ */
+
+#define RAND_IA 16807
+#define RAND_IM 2147483647
+#define RAND_IQ 127773
+#define RAND_IR 2836
+#define RAND_MASK 123459876
+
+ tmp = iPtr->randSeed/RAND_IQ;
+ iPtr->randSeed = RAND_IA*(iPtr->randSeed - tmp*RAND_IQ) - RAND_IR*tmp;
+ if (iPtr->randSeed < 0) {
+ iPtr->randSeed += RAND_IM;
+ }
+
+ /*
+ * Since the recurrence keeps seed values in the range [1, RAND_IM - 1],
+ * dividing by RAND_IM yields a double in the range (0, 1).
+ */
+
+ dResult = iPtr->randSeed * (1.0/RAND_IM);
+
+ /*
+ * Push a Tcl object with the result.
+ */
+
+ TclNewDoubleObj( oResult, dResult );
+ Tcl_SetObjResult( interp, oResult );
+ return TCL_OK;
+}
+
+static int
+ExprRoundFunc(clientData, interp, objc, objv)
+ ClientData clientData; /* Ignored. */
+ Tcl_Interp *interp; /* The interpreter in which to execute the
+ * function. */
+ int objc; /* Actual parameter count */
+ Tcl_Obj *CONST *objv; /* Parameter vector */
+{
+ Tcl_Obj *valuePtr, *resPtr;
+ double d, a, f;
+
+ /* Check the argument count. */
+
+ if ( objc != 2 ) {
+ MathFuncWrongNumArgs( interp, 1, objc, objv );
+ return TCL_ERROR;
+ }
+ valuePtr = objv[1];
+
+ /* Coerce the argument to a number. Integers are already rounded. */
+
+ if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((valuePtr->typePtr == &tclIntType) ||
+ (valuePtr->typePtr == &tclWideIntType)) {
+ return TCL_OK;
+ }
+ GET_DOUBLE_VALUE( d, valuePtr, valuePtr->typePtr );
+
+ /*
+ * Round the number to the nearest integer. I'd like to use rint()
+ * or nearbyint(), but they are far from universal.
+ */
+
+ a = fabs( d );
+ if ( a < Tcl_WideAsDouble( LLONG_MAX ) + 0.5 ) {
+ d = valuePtr->internalRep.doubleValue;
+ f = floor( d );
+ d -= f;
+ if ( d > 0.5 || ( d == 0.5 && fmod( f, 2.0 ) != 0.0 ) ) {
+ f = f + 1.0;
+ }
+ if ( f >= (double) LONG_MIN && f <= (double) LONG_MAX ) {
+ TclNewLongObj( resPtr, (long) f );
+ } else {
+ TclNewWideIntObj( resPtr, Tcl_DoubleAsWide( f ) );
+ }
+ Tcl_SetObjResult( interp, resPtr );
+ return TCL_OK;
+ }
+
+ /*
+ * Error return: result cannot be represented as an integer.
+ */
+
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "integer value too large to represent", -1));
+ Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
+ "integer value too large to represent",
+ (char *) NULL);
+
+ return TCL_ERROR;
+
+}
+
+static int
+ExprSrandFunc(clientData, interp, objc, objv)
+ ClientData clientData; /* Ignored. */
+ Tcl_Interp *interp; /* The interpreter in which to execute the
+ * function. */
+ int objc; /* Actual parameter count */
+ Tcl_Obj *CONST *objv; /* Parameter vector */
+{
+ Interp *iPtr = (Interp *) interp;
+ Tcl_Obj *valuePtr;
+ long i = 0; /* Initialized to avoid compiler warning. */
+
+ /*
+ * Convert argument and use it to reset the seed.
+ */
+
+ if (objc != 2 ) {
+ MathFuncWrongNumArgs( interp, 2, objc, objv );
+ return TCL_ERROR;
+ }
+ valuePtr = objv[1];
+
+ if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if ( Tcl_GetLongFromObj( NULL, valuePtr, &i ) != TCL_OK ) {
+ /*
+ * At this point, the only other possible type is double
+ */
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "can't use floating-point value as argument to srand", -1));
+ return TCL_ERROR;
+ }
+
+ /*
+ * Reset the seed. Make sure 1 <= randSeed <= 2^31 - 2.
+ * See comments in ExprRandFunc() for more details.
+ */
+
+ iPtr->flags |= RAND_SEED_INITIALIZED;
+ iPtr->randSeed = i;
+ iPtr->randSeed &= (unsigned long) 0x7fffffff;
+ if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7fffffff)) {
+ iPtr->randSeed ^= 123459876;
+ }
+
+ /*
+ * To avoid duplicating the random number generation code we simply
+ * clean up our state and call the real random number function. That
+ * function will always succeed.
+ */
+
+ return ExprRandFunc(clientData, interp, 1, objv);
+
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * VerifyExprObjType --
+ *
+ * This procedure is called by the math functions to verify that
+ * the object is either an int or double, coercing it if necessary.
+ * If an error occurs during conversion, an error message is left
+ * in the interpreter's result unless "interp" is NULL.
+ *
+ * Results:
+ * TCL_OK if it was int or double, TCL_ERROR otherwise
+ *
+ * Side effects:
+ * objPtr is ensured to be of tclIntType, tclWideIntType or
+ * tclDoubleType.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+VerifyExprObjType(interp, objPtr)
+ Tcl_Interp *interp; /* The interpreter in which to execute the
+ * function. */
+ Tcl_Obj *objPtr; /* Points to the object to type check. */
+{
+ if (IS_NUMERIC_TYPE(objPtr->typePtr)) {
+ return TCL_OK;
+ } else {
+ int length, result = TCL_OK;
+ char *s = Tcl_GetStringFromObj(objPtr, &length);
+
+ if (TclLooksLikeInt(s, length)) {
+ long i; /* Set but never used, needed in GET_WIDE_OR_INT */
+ Tcl_WideInt w;
+ GET_WIDE_OR_INT(result, objPtr, i, w);
+ } else {
+ double d;
+ result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, objPtr, &d);
+ }
+ if ((result != TCL_OK) && (interp != NULL)) {
+ if (TclCheckBadOctal((Tcl_Interp *) NULL, s)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "argument to math function was an invalid octal number",
+ -1));
+ } else {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "argument to math function didn't have numeric value",
+ -1));
+ }
+ }
+ return result;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * MathFuncWrongNumArgs --
+ *
+ * Generate an error message when a math function presents the
+ * wrong number of arguments
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * An error message is stored in the interpreter result
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+MathFuncWrongNumArgs( interp, expected, found, objv )
+ Tcl_Interp* interp; /* Tcl interpreter */
+ int expected; /* Formal parameter count */
+ int found; /* Actual parameter count */
+ Tcl_Obj *CONST *objv; /* Actual parameter vector */
+{
+ Tcl_Obj* errorMessage;
+ CONST char* name = Tcl_GetString( objv[0] );
+ CONST char* tail = name + strlen( name );
+ while ( tail > name+1 ) {
+ --tail;
+ if ( *tail == ':' && tail[-1] == ':' ) {
+ name = tail+1;
+ break;
+ }
+ }
+ errorMessage = Tcl_NewStringObj( "too ", -1 );
+ if ( found < expected ) {
+ Tcl_AppendToObj( errorMessage, "few", -1 );
+ } else {
+ Tcl_AppendToObj( errorMessage, "many", -1 );
+ }
+ Tcl_AppendToObj( errorMessage, " arguments for math function \"", -1 );
+ Tcl_AppendToObj( errorMessage, name, -1 );
+ Tcl_AppendToObj( errorMessage, "\"", -1 );
+ Tcl_SetObjResult( interp, errorMessage );
+}
diff --git a/generic/tclBinary.c b/generic/tclBinary.c
index 1b613d8..706d1f0 100644
--- a/generic/tclBinary.c
+++ b/generic/tclBinary.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclBinary.c,v 1.21 2004/10/06 05:52:21 dgp Exp $
+ * RCS: @(#) $Id: tclBinary.c,v 1.22 2005/05/10 18:34:07 kennykb Exp $
*/
#include "tclInt.h"
@@ -1605,10 +1605,15 @@ FormatNumber(interp, type, src, cursorPtr)
case 'Q':
/*
* Double-precision floating point values.
+ * Tcl_GetDoubleFromObj returns TCL_ERROR for NaN, but
+ * we can check by comparing the object's type pointer.
*/
if (Tcl_GetDoubleFromObj(interp, src, &dvalue) != TCL_OK) {
- return TCL_ERROR;
+ if ( src->typePtr != &tclDoubleType ) {
+ return TCL_ERROR;
+ }
+ dvalue = src->internalRep.doubleValue;
}
CopyNumber(&dvalue, *cursorPtr, sizeof(double), type);
*cursorPtr += sizeof(double);
@@ -1619,10 +1624,14 @@ FormatNumber(interp, type, src, cursorPtr)
case 'R':
/*
* Single-precision floating point values.
+ * Tcl_GetDoubleFromObj returns TCL_ERROR for NaN, but
+ * we can check by comparing the object's type pointer.
*/
if (Tcl_GetDoubleFromObj(interp, src, &dvalue) != TCL_OK) {
- return TCL_ERROR;
+ if ( src->typePtr != &tclDoubleType ) {
+ return TCL_ERROR;
+ }
}
/*
diff --git a/generic/tclCmdAH.c b/generic/tclCmdAH.c
index eb57690..c3037bc 100644
--- a/generic/tclCmdAH.c
+++ b/generic/tclCmdAH.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclCmdAH.c,v 1.60 2005/04/19 16:32:55 dgp Exp $
+ * RCS: @(#) $Id: tclCmdAH.c,v 1.61 2005/05/10 18:34:08 kennykb Exp $
*/
#include "tclInt.h"
diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c
index 3b61959..7f67180 100644
--- a/generic/tclCmdIL.c
+++ b/generic/tclCmdIL.c
@@ -15,7 +15,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclCmdIL.c,v 1.73 2005/05/05 18:37:56 dgp Exp $
+ * RCS: @(#) $Id: tclCmdIL.c,v 1.74 2005/05/10 18:34:08 kennykb Exp $
*/
#include "tclInt.h"
diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c
index 18da3f4..aee76d3 100644
--- a/generic/tclCmdMZ.c
+++ b/generic/tclCmdMZ.c
@@ -15,7 +15,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclCmdMZ.c,v 1.117 2005/04/29 20:49:43 dgp Exp $
+ * RCS: @(#) $Id: tclCmdMZ.c,v 1.118 2005/05/10 18:34:08 kennykb Exp $
*/
#include "tclInt.h"
@@ -1536,17 +1536,8 @@ Tcl_StringObjCmd(dummy, interp, objc, objv)
}
}
errno = 0;
- strtod(string1, &stop); /* INTL: Tcl source. */
- if (errno == ERANGE) {
- /*
- * if (errno == ERANGE), then it was an over/underflow
- * problem, but in this method, we only want to know
- * yes or no, so bad flow returns 0 (false) and sets
- * the failVarObj to the string length.
- */
- result = 0;
- failat = -1;
- } else if (stop == string1) {
+ TclStrToD(string1, (CONST char **) &stop); /* INTL: Tcl source. */
+ if (stop == string1) {
/*
* In this case, nothing like a number was found
*/
diff --git a/generic/tclCompCmds.c b/generic/tclCompCmds.c
index bd0c4b7..da77439 100644
--- a/generic/tclCompCmds.c
+++ b/generic/tclCompCmds.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclCompCmds.c,v 1.67 2005/05/05 18:37:57 dgp Exp $
+ * RCS: @(#) $Id: tclCompCmds.c,v 1.68 2005/05/10 18:34:09 kennykb Exp $
*/
#include "tclInt.h"
diff --git a/generic/tclCompExpr.c b/generic/tclCompExpr.c
index e25160d..e378ef6 100644
--- a/generic/tclCompExpr.c
+++ b/generic/tclCompExpr.c
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclCompExpr.c,v 1.25 2004/10/08 15:39:52 dkf Exp $
+ * RCS: @(#) $Id: tclCompExpr.c,v 1.26 2005/05/10 18:34:11 kennykb Exp $
*/
#include "tclInt.h"
@@ -828,95 +828,54 @@ CompileMathFuncCall(exprTokenPtr, funcName, infoPtr, envPtr, endPtrPtr)
* just after the last token in the
* subexpression is stored here. */
{
- Tcl_Interp *interp = infoPtr->interp;
- Interp *iPtr = (Interp *) interp;
- MathFunc *mathFuncPtr;
- Tcl_HashEntry *hPtr;
+ Tcl_DString cmdName;
+ int objIndex;
Tcl_Token *tokenPtr, *afterSubexprPtr;
- int code, i;
-
- /*
- * Look up the MathFunc record for the function.
- */
-
- code = TCL_OK;
- hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, funcName);
- if (hPtr == NULL) {
- Tcl_AppendResult(interp, "unknown math function \"", funcName,
- "\"", (char *) NULL);
- code = TCL_ERROR;
- goto done;
- }
- mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
-
+ int argCount;
+ int code = TCL_OK;
+
/*
- * If not a builtin function, push an object with the function's name.
+ * Prepend "tcl::mathfunc::" to the function name, to produce the
+ * name of a command that evaluates the function. Push that
+ * command name on the stack, in a literal registered to the
+ * namespace so that resolution can be cached.
*/
- if (mathFuncPtr->builtinFuncIndex < 0) {
- TclEmitPush(TclRegisterNewLiteral(envPtr, funcName, -1), envPtr);
- }
+ Tcl_DStringInit( &cmdName );
+ Tcl_DStringAppend( &cmdName, "tcl::mathfunc::", -1 );
+ Tcl_DStringAppend( &cmdName, funcName, -1 );
+ objIndex = TclRegisterNewNSLiteral( envPtr,
+ Tcl_DStringValue( &cmdName ),
+ Tcl_DStringLength( &cmdName ) );
+ TclEmitPush( objIndex, envPtr );
+ Tcl_DStringFree( &cmdName );
/*
* Compile any arguments for the function.
*/
+ argCount = 1;
tokenPtr = exprTokenPtr+2;
afterSubexprPtr = exprTokenPtr + (exprTokenPtr->numComponents + 1);
- if (mathFuncPtr->numArgs > 0) {
- for (i = 0; i < mathFuncPtr->numArgs; i++) {
- if (tokenPtr == afterSubexprPtr) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "too few arguments for math function", -1));
- code = TCL_ERROR;
- goto done;
- }
- code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
- if (code != TCL_OK) {
- goto done;
- }
- tokenPtr += (tokenPtr->numComponents + 1);
+ while (tokenPtr != afterSubexprPtr) {
+ ++argCount;
+ code = CompileSubExpr(tokenPtr, infoPtr, envPtr);
+ if (code != TCL_OK) {
+ return code;
}
- if (tokenPtr != afterSubexprPtr) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "too many arguments for math function", -1));
- code = TCL_ERROR;
- goto done;
- }
- } else if (tokenPtr != afterSubexprPtr) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "too many arguments for math function", -1));
- code = TCL_ERROR;
- goto done;
+ tokenPtr += (tokenPtr->numComponents + 1);
}
- /*
- * Compile the call on the math function. Note that the "objc" argument
- * count for non-builtin functions is incremented by 1 to include the
- * function name itself.
- */
+ /* Invoke the function */
- if (mathFuncPtr->builtinFuncIndex >= 0) { /* a builtin function */
- /*
- * Adjust the current stack depth by the number of arguments
- * of the builtin function. This cannot be handled by the
- * TclEmitInstInt1 macro as the number of arguments is not
- * passed as an operand.
- */
-
- if (envPtr->maxStackDepth < envPtr->currStackDepth) {
- envPtr->maxStackDepth = envPtr->currStackDepth;
- }
- TclEmitInstInt1(INST_CALL_BUILTIN_FUNC1,
- mathFuncPtr->builtinFuncIndex, envPtr);
- envPtr->currStackDepth -= mathFuncPtr->numArgs;
+ if ( argCount < 255 ) {
+ TclEmitInstInt1( INST_INVOKE_STK1, argCount, envPtr );
} else {
- TclEmitInstInt1(INST_CALL_FUNC1, (mathFuncPtr->numArgs+1), envPtr);
+ TclEmitInstInt4( INST_INVOKE_STK4, argCount, envPtr );
}
- *endPtrPtr = afterSubexprPtr;
- done:
- return code;
+ *endPtrPtr = afterSubexprPtr;
+ return TCL_OK;
}
/*
diff --git a/generic/tclCompile.c b/generic/tclCompile.c
index 47b6831..f67fea6 100644
--- a/generic/tclCompile.c
+++ b/generic/tclCompile.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclCompile.c,v 1.84 2005/05/05 15:32:20 dgp Exp $
+ * RCS: @(#) $Id: tclCompile.c,v 1.85 2005/05/10 18:34:11 kennykb Exp $
*/
#include "tclInt.h"
diff --git a/generic/tclCompile.h b/generic/tclCompile.h
index 896b385..ab34f81 100644
--- a/generic/tclCompile.h
+++ b/generic/tclCompile.h
@@ -8,7 +8,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclCompile.h,v 1.54 2005/03/25 00:35:03 dgp Exp $
+ * RCS: @(#) $Id: tclCompile.h,v 1.55 2005/05/10 18:34:27 kennykb Exp $
*/
#ifndef _TCLCOMPILATION
@@ -591,64 +591,6 @@ typedef struct InstructionDesc {
MODULE_SCOPE InstructionDesc tclInstructionTable[];
/*
- * Definitions of the values of the INST_CALL_BUILTIN_FUNC instruction's
- * operand byte. Each value denotes a builtin Tcl math function. These
- * values must correspond to the entries in the tclBuiltinFuncTable array
- * below and to the values stored in the tclInt.h MathFunc structure's
- * builtinFuncIndex field.
- */
-
-#define BUILTIN_FUNC_ACOS 0
-#define BUILTIN_FUNC_ASIN 1
-#define BUILTIN_FUNC_ATAN 2
-#define BUILTIN_FUNC_ATAN2 3
-#define BUILTIN_FUNC_CEIL 4
-#define BUILTIN_FUNC_COS 5
-#define BUILTIN_FUNC_COSH 6
-#define BUILTIN_FUNC_EXP 7
-#define BUILTIN_FUNC_FLOOR 8
-#define BUILTIN_FUNC_FMOD 9
-#define BUILTIN_FUNC_HYPOT 10
-#define BUILTIN_FUNC_LOG 11
-#define BUILTIN_FUNC_LOG10 12
-#define BUILTIN_FUNC_POW 13
-#define BUILTIN_FUNC_SIN 14
-#define BUILTIN_FUNC_SINH 15
-#define BUILTIN_FUNC_SQRT 16
-#define BUILTIN_FUNC_TAN 17
-#define BUILTIN_FUNC_TANH 18
-#define BUILTIN_FUNC_ABS 19
-#define BUILTIN_FUNC_DOUBLE 20
-#define BUILTIN_FUNC_INT 21
-#define BUILTIN_FUNC_RAND 22
-#define BUILTIN_FUNC_ROUND 23
-#define BUILTIN_FUNC_SRAND 24
-#define BUILTIN_FUNC_WIDE 25
-
-#define LAST_BUILTIN_FUNC 25
-
-/*
- * Table describing the built-in math functions. Entries in this table are
- * indexed by the values of the INST_CALL_BUILTIN_FUNC instruction's
- * operand byte.
- */
-
-typedef int (CallBuiltinFuncProc) _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj **tosPtr, ClientData clientData));
-
-typedef struct {
- char *name; /* Name of function. */
- int numArgs; /* Number of arguments for function. */
- Tcl_ValueType argTypes[MAX_MATH_ARGS];
- /* Acceptable types for each argument. */
- CallBuiltinFuncProc *proc; /* Procedure implementing this function. */
- ClientData clientData; /* Additional argument to pass to the
- * function when invoking it. */
-} BuiltinFunc;
-
-MODULE_SCOPE BuiltinFunc tclBuiltinFuncTable[];
-
-/*
* Compilation of some Tcl constructs such as if commands and the logical or
* (||) and logical and (&&) operators in expressions requires the
* generation of forward jumps. Since the PC target of these jumps isn't
diff --git a/generic/tclConfig.c b/generic/tclConfig.c
index 4172fdb..f9c6dda 100644
--- a/generic/tclConfig.c
+++ b/generic/tclConfig.c
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclConfig.c,v 1.7 2005/04/02 02:08:32 msofer Exp $
+ * RCS: @(#) $Id: tclConfig.c,v 1.8 2005/05/10 18:34:28 kennykb Exp $
*/
#include "tclInt.h"
diff --git a/generic/tclDecls.h b/generic/tclDecls.h
index 0ec588f..7ab10d3 100644
--- a/generic/tclDecls.h
+++ b/generic/tclDecls.h
@@ -8,7 +8,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclDecls.h,v 1.112 2005/05/03 18:07:47 dgp Exp $
+ * RCS: @(#) $Id: tclDecls.h,v 1.113 2005/05/10 18:34:28 kennykb Exp $
*/
#ifndef _TCLDECLS
@@ -3461,6 +3461,29 @@ EXTERN void Tcl_QueryTimeProc _ANSI_ARGS_((
EXTERN Tcl_DriverThreadActionProc * Tcl_ChannelThreadActionProc _ANSI_ARGS_((
Tcl_ChannelType * chanTypePtr));
#endif
+#ifndef Tcl_NewBignumObj_TCL_DECLARED
+#define Tcl_NewBignumObj_TCL_DECLARED
+/* 555 */
+EXTERN Tcl_Obj* Tcl_NewBignumObj _ANSI_ARGS_((mp_int* value));
+#endif
+#ifndef Tcl_DbNewBignumObj_TCL_DECLARED
+#define Tcl_DbNewBignumObj_TCL_DECLARED
+/* 556 */
+EXTERN Tcl_Obj* Tcl_DbNewBignumObj _ANSI_ARGS_((mp_int* value,
+ CONST char* file, int line));
+#endif
+#ifndef Tcl_SetBignumObj_TCL_DECLARED
+#define Tcl_SetBignumObj_TCL_DECLARED
+/* 557 */
+EXTERN void Tcl_SetBignumObj _ANSI_ARGS_((Tcl_Obj* obj,
+ mp_int* value));
+#endif
+#ifndef Tcl_GetBignumFromObj_TCL_DECLARED
+#define Tcl_GetBignumFromObj_TCL_DECLARED
+/* 558 */
+EXTERN int Tcl_GetBignumFromObj _ANSI_ARGS_((Tcl_Interp* interp,
+ Tcl_Obj* obj, mp_int* value));
+#endif
typedef struct TclStubHooks {
struct TclPlatStubs *tclPlatStubs;
@@ -4057,6 +4080,10 @@ typedef struct TclStubs {
void (*tcl_SetTimeProc) _ANSI_ARGS_((Tcl_GetTimeProc* getProc, Tcl_ScaleTimeProc* scaleProc, ClientData clientData)); /* 552 */
void (*tcl_QueryTimeProc) _ANSI_ARGS_((Tcl_GetTimeProc** getProc, Tcl_ScaleTimeProc** scaleProc, ClientData* clientData)); /* 553 */
Tcl_DriverThreadActionProc * (*tcl_ChannelThreadActionProc) _ANSI_ARGS_((Tcl_ChannelType * chanTypePtr)); /* 554 */
+ Tcl_Obj* (*tcl_NewBignumObj) _ANSI_ARGS_((mp_int* value)); /* 555 */
+ Tcl_Obj* (*tcl_DbNewBignumObj) _ANSI_ARGS_((mp_int* value, CONST char* file, int line)); /* 556 */
+ void (*tcl_SetBignumObj) _ANSI_ARGS_((Tcl_Obj* obj, mp_int* value)); /* 557 */
+ int (*tcl_GetBignumFromObj) _ANSI_ARGS_((Tcl_Interp* interp, Tcl_Obj* obj, mp_int* value)); /* 558 */
} TclStubs;
#ifdef __cplusplus
@@ -6317,6 +6344,22 @@ extern TclStubs *tclStubsPtr;
#define Tcl_ChannelThreadActionProc \
(tclStubsPtr->tcl_ChannelThreadActionProc) /* 554 */
#endif
+#ifndef Tcl_NewBignumObj
+#define Tcl_NewBignumObj \
+ (tclStubsPtr->tcl_NewBignumObj) /* 555 */
+#endif
+#ifndef Tcl_DbNewBignumObj
+#define Tcl_DbNewBignumObj \
+ (tclStubsPtr->tcl_DbNewBignumObj) /* 556 */
+#endif
+#ifndef Tcl_SetBignumObj
+#define Tcl_SetBignumObj \
+ (tclStubsPtr->tcl_SetBignumObj) /* 557 */
+#endif
+#ifndef Tcl_GetBignumFromObj
+#define Tcl_GetBignumFromObj \
+ (tclStubsPtr->tcl_GetBignumFromObj) /* 558 */
+#endif
#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */
diff --git a/generic/tclDictObj.c b/generic/tclDictObj.c
index 1dc87d4..5c40825 100644
--- a/generic/tclDictObj.c
+++ b/generic/tclDictObj.c
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclDictObj.c,v 1.30 2005/05/05 18:37:58 dgp Exp $
+ * RCS: @(#) $Id: tclDictObj.c,v 1.31 2005/05/10 18:34:34 kennykb Exp $
*/
#include "tclInt.h"
diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c
index 13c517b..646713d 100644
--- a/generic/tclEncoding.c
+++ b/generic/tclEncoding.c
@@ -8,7 +8,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclEncoding.c,v 1.34 2005/04/12 20:28:46 dgp Exp $
+ * RCS: @(#) $Id: tclEncoding.c,v 1.35 2005/05/10 18:34:34 kennykb Exp $
*/
#include "tclInt.h"
diff --git a/generic/tclEnv.c b/generic/tclEnv.c
index e4d7b23..4ceb4fb 100644
--- a/generic/tclEnv.c
+++ b/generic/tclEnv.c
@@ -12,7 +12,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclEnv.c,v 1.23 2005/05/03 18:08:17 dgp Exp $
+ * RCS: @(#) $Id: tclEnv.c,v 1.24 2005/05/10 18:34:34 kennykb Exp $
*/
#include "tclInt.h"
diff --git a/generic/tclEvent.c b/generic/tclEvent.c
index 8d4533ec..6e2a4df 100644
--- a/generic/tclEvent.c
+++ b/generic/tclEvent.c
@@ -12,7 +12,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclEvent.c,v 1.56 2004/12/16 19:36:17 dkf Exp $
+ * RCS: @(#) $Id: tclEvent.c,v 1.57 2005/05/10 18:34:35 kennykb Exp $
*/
#include "tclInt.h"
@@ -798,6 +798,8 @@ TclInitSubsystems()
#endif
TclpInitPlatform(); /* creates signal handler(s) */
+ TclInitDoubleConversion(); /* initializes constants for
+ * converting to/from double */
TclInitObjSubsystem(); /* register obj types, create mutexes */
TclInitIOSubsystem(); /* inits a tsd key (noop) */
TclInitEncodingSubsystem(); /* process wide encoding init */
@@ -938,6 +940,10 @@ Tcl_Finalize()
TclFinalizeLoad();
TclResetFilesystem();
+
+ /* Now we can free constants for conversions to/from double */
+
+ TclFinalizeDoubleConversion();
/*
* There shouldn't be any malloc'ed memory after this.
diff --git a/generic/tclExecute.c b/generic/tclExecute.c
index ad91579..3333c79 100644
--- a/generic/tclExecute.c
+++ b/generic/tclExecute.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclExecute.c,v 1.187 2005/05/10 10:02:16 msofer Exp $
+ * RCS: @(#) $Id: tclExecute.c,v 1.188 2005/05/10 18:34:35 kennykb Exp $
*/
#include "tclInt.h"
@@ -20,6 +20,18 @@
#ifndef TCL_NO_MATH
# include <math.h>
#endif
+#include <float.h>
+
+/*
+ * Hack to determine whether we may expect IEEE floating point.
+ * The hack is formally incorrect in that non-IEEE platforms might
+ * have the same precision and range, but VAX, IBM, and Cray do not;
+ * are there any other floating point units that we might care about?
+ */
+
+#if ( FLT_RADIX == 2 ) && ( DBL_MANT_DIG == 53 ) && ( DBL_MAX_EXP == 1024 )
+#define IEEE_FLOATING_POINT
+#endif
/*
* The stuff below is a bit of a hack so that this file can be used
@@ -136,8 +148,13 @@ long tclObjsShared[TCL_MAX_SHARED_OBJ_STATS] = { 0, 0, 0, 0, 0 };
* by comparing against the largest floating-point value.
*/
-#define IS_NAN(v) ((v) != (v))
-#define IS_INF(v) (((v) > DBL_MAX) || ((v) < -DBL_MAX))
+#ifdef _MSC_VER
+#define IS_NAN(f) (_isnan((f)))
+#define IS_INF(f) ( ! (_finite((f))))
+#else
+#define IS_NAN(f) ((f) != (f))
+#define IS_INF(f) ( (f) > DBL_MAX || (f) < -DBL_MAX )
+#endif
/*
* The new macro for ending an instruction; note that a
@@ -345,26 +362,6 @@ long tclObjsShared[TCL_MAX_SHARED_OBJ_STATS] = { 0, 0, 0, 0, 0 };
static int TclExecuteByteCode _ANSI_ARGS_((Tcl_Interp *interp,
ByteCode *codePtr));
-static int ExprAbsFunc _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj **tosPtr, ClientData clientData));
-static int ExprBinaryFunc _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj **tosPtr, ClientData clientData));
-static int ExprCallMathFunc _ANSI_ARGS_((Tcl_Interp *interp,
- int objc, Tcl_Obj **objv));
-static int ExprDoubleFunc _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj **tosPtr, ClientData clientData));
-static int ExprIntFunc _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj **tosPtr, ClientData clientData));
-static int ExprRandFunc _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj **tosPtr, ClientData clientData));
-static int ExprRoundFunc _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj **tosPtr, ClientData clientData));
-static int ExprSrandFunc _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj **tosPtr, ClientData clientData));
-static int ExprUnaryFunc _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj **tosPtr, ClientData clientData));
-static int ExprWideFunc _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj **tosPtr, ClientData clientData));
#ifdef TCL_COMPILE_STATS
static int EvalStatsCmd _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int objc,
@@ -391,50 +388,11 @@ static void ValidatePcAndStackTop _ANSI_ARGS_((
int stackTop, int stackLowerBound,
int checkStack));
#endif /* TCL_COMPILE_DEBUG */
-static int VerifyExprObjType _ANSI_ARGS_((Tcl_Interp *interp,
- Tcl_Obj *objPtr));
static Tcl_WideInt ExponWide _ANSI_ARGS_((Tcl_WideInt w, Tcl_WideInt w2,
int *errExpon));
static long ExponLong _ANSI_ARGS_((long i, long i2,
int *errExpon));
-/*
- * Table describing the built-in math functions. Entries in this table are
- * indexed by the values of the INST_CALL_BUILTIN_FUNC instruction's
- * operand byte.
- */
-
-BuiltinFunc tclBuiltinFuncTable[] = {
-#ifndef TCL_NO_MATH
- {"acos", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) acos},
- {"asin", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) asin},
- {"atan", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) atan},
- {"atan2", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) atan2},
- {"ceil", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) ceil},
- {"cos", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) cos},
- {"cosh", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) cosh},
- {"exp", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) exp},
- {"floor", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) floor},
- {"fmod", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) fmod},
- {"hypot", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) hypot},
- {"log", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) log},
- {"log10", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) log10},
- {"pow", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) pow},
- {"sin", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) sin},
- {"sinh", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) sinh},
- {"sqrt", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) sqrt},
- {"tan", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) tan},
- {"tanh", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) tanh},
-#endif
- {"abs", 1, {TCL_EITHER}, ExprAbsFunc, 0},
- {"double", 1, {TCL_EITHER}, ExprDoubleFunc, 0},
- {"int", 1, {TCL_EITHER}, ExprIntFunc, 0},
- {"rand", 0, {TCL_EITHER}, ExprRandFunc, 0}, /* NOTE: rand takes no args. */
- {"round", 1, {TCL_EITHER}, ExprRoundFunc, 0},
- {"srand", 1, {TCL_INT}, ExprSrandFunc, 0},
- {"wide", 1, {TCL_EITHER}, ExprWideFunc, 0},
- {0},
-};
/*
*----------------------------------------------------------------------
@@ -4023,10 +3981,18 @@ TclExecuteByteCode(interp, codePtr)
dResult = d1 * d2;
break;
case INST_DIV:
+#ifndef IEEE_FLOATING_POINT
if (d2 == 0.0) {
TRACE(("%.6g %.6g => DIVIDE BY ZERO\n", d1, d2));
goto divideByZero;
}
+#endif
+ /*
+ * We presume that we are running with zero-divide
+ * unmasked if we're on an IEEE box. Otherwise,
+ * this statement might cause demons to fly out
+ * our noses.
+ */
dResult = d1 / d2;
break;
case INST_EXPON:
@@ -4042,7 +4008,7 @@ TclExecuteByteCode(interp, codePtr)
* Check now for IEEE floating-point error.
*/
- if (IS_NAN(dResult) || IS_INF(dResult)) {
+ if (IS_NAN(dResult)) {
TRACE(("%.20s %.20s => IEEE FLOATING PT ERROR\n",
O2S(valuePtr), O2S(value2Ptr)));
TclExprFloatError(interp, dResult);
@@ -4430,53 +4396,13 @@ TclExecuteByteCode(interp, codePtr)
case INST_CALL_BUILTIN_FUNC1:
{
- int opnd;
- BuiltinFunc *mathFuncPtr;
-
- /*
- * Call one of the built-in Tcl math functions.
- */
-
- opnd = TclGetUInt1AtPtr(pc+1);
- if ((opnd < 0) || (opnd > LAST_BUILTIN_FUNC)) {
- TRACE(("UNRECOGNIZED BUILTIN FUNC CODE %d\n", opnd));
- Tcl_Panic("TclExecuteByteCode: unrecognized builtin function code %d", opnd);
- }
- mathFuncPtr = &(tclBuiltinFuncTable[opnd]);
- result = (*mathFuncPtr->proc)(interp, tosPtr,
- mathFuncPtr->clientData);
- if (result != TCL_OK) {
- goto checkForCatch;
- }
- tosPtr -= (mathFuncPtr->numArgs - 1);
- TRACE_WITH_OBJ(("%d => ", opnd), *tosPtr);
+ Tcl_Panic("TclExecuteByteCode: obsolete INST_CALL_BUILTIN_FUNC1 found");
}
- NEXT_INST_F(2, 0, 0);
case INST_CALL_FUNC1:
{
- /*
- * Call a non-builtin Tcl math function previously
- * registered by a call to Tcl_CreateMathFunc.
- */
-
- int objc; /* Number of arguments. The function name
- * is the 0-th argument. */
- Tcl_Obj **objv; /* The array of arguments. The function
- * name is objv[0]. */
-
- objc = TclGetUInt1AtPtr(pc+1);
- objv = (tosPtr - (objc-1)); /* "objv[0]" */
- DECACHE_STACK_INFO();
- result = ExprCallMathFunc(interp, objc, objv);
- CACHE_STACK_INFO();
- if (result != TCL_OK) {
- goto checkForCatch;
- }
- tosPtr = objv;
- TRACE_WITH_OBJ(("%d => ", objc), *tosPtr);
+ Tcl_Panic("TclExecuteByteCode: obsolete INST_CALL_FUNC1 found");
}
- NEXT_INST_F(2, 0, 0);
case INST_TRY_CVT_TO_NUMERIC:
{
@@ -4569,7 +4495,7 @@ TclExecuteByteCode(interp, codePtr)
if (tPtr == &tclDoubleType) {
d = objResultPtr->internalRep.doubleValue;
- if (IS_NAN(d) || IS_INF(d)) {
+ if (IS_NAN(d)) {
TRACE(("\"%.20s\" => IEEE FLOATING PT ERROR\n",
O2S(objResultPtr)));
TclExprFloatError(interp, d);
@@ -5594,765 +5520,6 @@ GetOpcodeName(pc)
/*
*----------------------------------------------------------------------
*
- * VerifyExprObjType --
- *
- * This procedure is called by the math functions to verify that
- * the object is either an int or double, coercing it if necessary.
- * If an error occurs during conversion, an error message is left
- * in the interpreter's result unless "interp" is NULL.
- *
- * Results:
- * TCL_OK if it was int or double, TCL_ERROR otherwise
- *
- * Side effects:
- * objPtr is ensured to be of tclIntType, tclWideIntType or
- * tclDoubleType.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-VerifyExprObjType(interp, objPtr)
- Tcl_Interp *interp; /* The interpreter in which to execute the
- * function. */
- Tcl_Obj *objPtr; /* Points to the object to type check. */
-{
- if (IS_NUMERIC_TYPE(objPtr->typePtr)) {
- return TCL_OK;
- } else {
- int length, result = TCL_OK;
- char *s = Tcl_GetStringFromObj(objPtr, &length);
-
- if (TclLooksLikeInt(s, length)) {
- long i; /* Set but never used, needed in GET_WIDE_OR_INT */
- Tcl_WideInt w;
- GET_WIDE_OR_INT(result, objPtr, i, w);
- } else {
- double d;
- result = Tcl_GetDoubleFromObj((Tcl_Interp *) NULL, objPtr, &d);
- }
- if ((result != TCL_OK) && (interp != NULL)) {
- if (TclCheckBadOctal((Tcl_Interp *) NULL, s)) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "argument to math function was an invalid octal number",
- -1));
- } else {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "argument to math function didn't have numeric value",
- -1));
- }
- }
- return result;
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Math Functions --
- *
- * This page contains the procedures that implement all of the
- * built-in math functions for expressions.
- *
- * Results:
- * Each procedure returns TCL_OK if it succeeds and pushes an
- * Tcl object holding the result. If it fails it returns TCL_ERROR
- * and leaves an error message in the interpreter's result.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-ExprUnaryFunc(interp, tosPtr, clientData)
- Tcl_Interp *interp; /* The interpreter in which to execute the
- * function. */
- Tcl_Obj **tosPtr; /* Points to top of evaluation stack. */
- ClientData clientData; /* Contains the address of a procedure that
- * takes one double argument and returns a
- * double result. */
-{
- register Tcl_Obj *valuePtr, *resPtr;
- double d, dResult;
-
- double (*func) _ANSI_ARGS_((double)) =
- (double (*)_ANSI_ARGS_((double))) clientData;
-
- /*
- * Pop the function's argument from the evaluation stack. Convert it
- * to a double if necessary.
- */
-
- valuePtr = POP_OBJECT();
-
- if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
- return TCL_ERROR;
- }
-
- GET_DOUBLE_VALUE(d, valuePtr, valuePtr->typePtr);
-
- errno = 0;
- dResult = (*func)(d);
- if ((errno != 0) || IS_NAN(dResult) || IS_INF(dResult)) {
- TclExprFloatError(interp, dResult);
- return TCL_ERROR;
- }
-
- /*
- * Push a Tcl object holding the result.
- */
-
- TclNewDoubleObj(resPtr, dResult);
- PUSH_OBJECT(resPtr);
- TclDecrRefCount(valuePtr);
- return TCL_OK;
-}
-
-static int
-ExprBinaryFunc(interp, tosPtr, clientData)
- Tcl_Interp *interp; /* The interpreter in which to execute the
- * function. */
- Tcl_Obj **tosPtr; /* Points to top of evaluation stack. */
- ClientData clientData; /* Contains the address of a procedure that
- * takes two double arguments and
- * returns a double result. */
-{
- register Tcl_Obj *valuePtr, *value2Ptr, *resPtr;
- double d1, d2, dResult;
-
- double (*func) _ANSI_ARGS_((double, double))
- = (double (*)_ANSI_ARGS_((double, double))) clientData;
-
- /*
- * Pop the function's two arguments from the evaluation stack. Convert
- * them to doubles if necessary.
- */
-
- value2Ptr = POP_OBJECT();
- valuePtr = POP_OBJECT();
-
- if ((VerifyExprObjType(interp, valuePtr) != TCL_OK) ||
- (VerifyExprObjType(interp, value2Ptr) != TCL_OK)) {
- return TCL_ERROR;
- }
-
- GET_DOUBLE_VALUE(d1, valuePtr, valuePtr->typePtr);
- GET_DOUBLE_VALUE(d2, value2Ptr, value2Ptr->typePtr);
-
- errno = 0;
- dResult = (*func)(d1, d2);
- if ((errno != 0) || IS_NAN(dResult) || IS_INF(dResult)) {
- TclExprFloatError(interp, dResult);
- return TCL_ERROR;
- }
-
- /*
- * Push a Tcl object holding the result.
- */
-
- TclNewDoubleObj(resPtr, dResult);
- PUSH_OBJECT(resPtr);
- TclDecrRefCount(valuePtr);
- TclDecrRefCount(value2Ptr);
- return TCL_OK;
-}
-
-static int
-ExprAbsFunc(interp, tosPtr, clientData)
- Tcl_Interp *interp; /* The interpreter in which to execute the
- * function. */
- Tcl_Obj **tosPtr; /* Points to top of evaluation stack. */
- ClientData clientData; /* Ignored. */
-{
- register Tcl_Obj *valuePtr, *resPtr;
- long i, iResult;
- double d, dResult;
-
- /*
- * Pop the argument from the evaluation stack.
- */
-
- valuePtr = POP_OBJECT();
-
- if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
- return TCL_ERROR;
- }
-
- /*
- * Push a Tcl object with the result.
- */
- if (valuePtr->typePtr == &tclIntType) {
- i = valuePtr->internalRep.longValue;
- if (i < 0) {
- iResult = -i;
- if (iResult < 0) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "integer value too large to represent", -1));
- Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
- "integer value too large to represent", (char *) NULL);
- return TCL_ERROR;
- }
- } else {
- iResult = i;
- }
- TclNewLongObj(resPtr, iResult);
- PUSH_OBJECT(resPtr);
- } else if (valuePtr->typePtr == &tclWideIntType) {
- Tcl_WideInt wResult, w;
- TclGetWide(w,valuePtr);
- if (w < W0) {
- wResult = -w;
- if (wResult < 0) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "integer value too large to represent", -1));
- Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
- "integer value too large to represent", (char *) NULL);
- return TCL_ERROR;
- }
- } else {
- wResult = w;
- }
- TclNewWideIntObj(resPtr, wResult);
- PUSH_OBJECT(resPtr);
- } else {
- d = valuePtr->internalRep.doubleValue;
- if (d < 0.0) {
- dResult = -d;
- } else {
- dResult = d;
- }
- if (IS_NAN(dResult) || IS_INF(dResult)) {
- TclExprFloatError(interp, dResult);
- return TCL_ERROR;
- }
- TclNewDoubleObj(resPtr, dResult);
- PUSH_OBJECT(resPtr);
- }
-
- TclDecrRefCount(valuePtr);
- return TCL_OK;
-}
-
-static int
-ExprDoubleFunc(interp, tosPtr, clientData)
- Tcl_Interp *interp; /* The interpreter in which to execute the
- * function. */
- Tcl_Obj **tosPtr; /* Points to top of evaluation stack. */
- ClientData clientData; /* Ignored. */
-{
- register Tcl_Obj *valuePtr, *resPtr;
- double dResult;
-
- /*
- * Pop the argument from the evaluation stack.
- */
-
- valuePtr = POP_OBJECT();
-
- if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
- return TCL_ERROR;
- }
-
- GET_DOUBLE_VALUE(dResult, valuePtr, valuePtr->typePtr);
-
- /*
- * Push a Tcl object with the result.
- */
-
- TclNewDoubleObj(resPtr, dResult);
- PUSH_OBJECT(resPtr);
-
- TclDecrRefCount(valuePtr);
- return TCL_OK;
-}
-
-static int
-ExprIntFunc(interp, tosPtr, clientData)
- Tcl_Interp *interp; /* The interpreter in which to execute the
- * function. */
- Tcl_Obj **tosPtr; /* Points to top of evaluation stack. */
- ClientData clientData; /* Ignored. */
-{
- register Tcl_Obj *valuePtr, *resPtr;
- long iResult;
- double d;
-
- /*
- * Pop the argument from the evaluation stack.
- */
-
- valuePtr = POP_OBJECT();
-
- if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
- return TCL_ERROR;
- }
-
- if (valuePtr->typePtr == &tclIntType) {
- iResult = valuePtr->internalRep.longValue;
- } else if (valuePtr->typePtr == &tclWideIntType) {
- TclGetLongFromWide(iResult,valuePtr);
- } else {
- d = valuePtr->internalRep.doubleValue;
- if (d < 0.0) {
- if (d < (double) (long) LONG_MIN) {
- tooLarge:
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "integer value too large to represent", -1));
- Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
- "integer value too large to represent", (char *) NULL);
- return TCL_ERROR;
- }
- } else {
- if (d > (double) LONG_MAX) {
- goto tooLarge;
- }
- }
- if (IS_NAN(d) || IS_INF(d)) {
- TclExprFloatError(interp, d);
- return TCL_ERROR;
- }
- iResult = (long) d;
- }
-
- /*
- * Push a Tcl object with the result.
- */
-
- TclNewLongObj(resPtr, iResult);
- PUSH_OBJECT(resPtr);
- TclDecrRefCount(valuePtr);
- return TCL_OK;
-}
-
-static int
-ExprWideFunc(interp, tosPtr, clientData)
- Tcl_Interp *interp; /* The interpreter in which to execute the
- * function. */
- Tcl_Obj **tosPtr; /* Points to top of evaluation stack. */
- ClientData clientData; /* Ignored. */
-{
- register Tcl_Obj *valuePtr, *resPtr;
- Tcl_WideInt wResult;
- double d;
-
- /*
- * Pop the argument from the evaluation stack.
- */
-
- valuePtr = POP_OBJECT();
-
- if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
- return TCL_ERROR;
- }
-
- if (valuePtr->typePtr == &tclWideIntType) {
- TclGetWide(wResult,valuePtr);
- } else if (valuePtr->typePtr == &tclIntType) {
- wResult = Tcl_LongAsWide(valuePtr->internalRep.longValue);
- } else {
- d = valuePtr->internalRep.doubleValue;
- if (d < 0.0) {
- if (d < Tcl_WideAsDouble(LLONG_MIN)) {
- tooLarge:
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "integer value too large to represent", -1));
- Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
- "integer value too large to represent", (char *) NULL);
- return TCL_ERROR;
- }
- } else {
- if (d > Tcl_WideAsDouble(LLONG_MAX)) {
- goto tooLarge;
- }
- }
- if (IS_NAN(d) || IS_INF(d)) {
- TclExprFloatError(interp, d);
- return TCL_ERROR;
- }
- wResult = Tcl_DoubleAsWide(d);
- }
-
- /*
- * Push a Tcl object with the result.
- */
-
- TclNewWideIntObj(resPtr, wResult);
- PUSH_OBJECT(resPtr);
- TclDecrRefCount(valuePtr);
- return TCL_OK;
-}
-
-static int
-ExprRandFunc(interp, tosPtr, clientData)
- Tcl_Interp *interp; /* The interpreter in which to execute the
- * function. */
- Tcl_Obj **tosPtr; /* Points to top of evaluation stack. */
- ClientData clientData; /* Ignored. */
-{
- Interp *iPtr = (Interp *) interp;
- double dResult;
- long tmp; /* Algorithm assumes at least 32 bits.
- * Only long guarantees that. See below. */
- Tcl_Obj *resPtr;
-
- if (!(iPtr->flags & RAND_SEED_INITIALIZED)) {
- iPtr->flags |= RAND_SEED_INITIALIZED;
-
- /*
- * Take into consideration the thread this interp is running in order
- * to insure different seeds in different threads (bug #416643)
- */
-
- iPtr->randSeed = TclpGetClicks() + ((long)Tcl_GetCurrentThread()<<12);
-
- /*
- * Make sure 1 <= randSeed <= (2^31) - 2. See below.
- */
-
- iPtr->randSeed &= (unsigned long) 0x7fffffff;
- if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7fffffff)) {
- iPtr->randSeed ^= 123459876;
- }
- }
-
- /*
- * Generate the random number using the linear congruential
- * generator defined by the following recurrence:
- * seed = ( IA * seed ) mod IM
- * where IA is 16807 and IM is (2^31) - 1. The recurrence maps
- * a seed in the range [1, IM - 1] to a new seed in that same range.
- * The recurrence maps IM to 0, and maps 0 back to 0, so those two
- * values must not be allowed as initial values of seed.
- *
- * In order to avoid potential problems with integer overflow, the
- * recurrence is implemented in terms of additional constants
- * IQ and IR such that
- * IM = IA*IQ + IR
- * None of the operations in the implementation overflows a 32-bit
- * signed integer, and the C type long is guaranteed to be at least
- * 32 bits wide.
- *
- * For more details on how this algorithm works, refer to the following
- * papers:
- *
- * S.K. Park & K.W. Miller, "Random number generators: good ones
- * are hard to find," Comm ACM 31(10):1192-1201, Oct 1988
- *
- * W.H. Press & S.A. Teukolsky, "Portable random number
- * generators," Computers in Physics 6(5):522-524, Sep/Oct 1992.
- */
-
-#define RAND_IA 16807
-#define RAND_IM 2147483647
-#define RAND_IQ 127773
-#define RAND_IR 2836
-#define RAND_MASK 123459876
-
- tmp = iPtr->randSeed/RAND_IQ;
- iPtr->randSeed = RAND_IA*(iPtr->randSeed - tmp*RAND_IQ) - RAND_IR*tmp;
- if (iPtr->randSeed < 0) {
- iPtr->randSeed += RAND_IM;
- }
-
- /*
- * Since the recurrence keeps seed values in the range [1, RAND_IM - 1],
- * dividing by RAND_IM yields a double in the range (0, 1).
- */
-
- dResult = iPtr->randSeed * (1.0/RAND_IM);
-
- /*
- * Push a Tcl object with the result.
- */
-
- TclNewDoubleObj(resPtr, dResult);
- PUSH_OBJECT(resPtr);
- return TCL_OK;
-}
-
-static int
-ExprRoundFunc(interp, tosPtr, clientData)
- Tcl_Interp *interp; /* The interpreter in which to execute the
- * function. */
- Tcl_Obj **tosPtr; /* Points to top of evaluation stack. */
- ClientData clientData; /* Ignored. */
-{
- Tcl_Obj *valuePtr, *resPtr;
- double d;
-
- /*
- * Pop the argument from the evaluation stack.
- */
-
- valuePtr = POP_OBJECT();
-
- if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
- return TCL_ERROR;
- }
-
- if ((valuePtr->typePtr == &tclIntType) ||
- (valuePtr->typePtr == &tclWideIntType)) {
- return TCL_OK;
- }
-
- d = valuePtr->internalRep.doubleValue;
- if (d < 0.0) {
- if (d <= Tcl_WideAsDouble(LLONG_MIN)-0.5) {
- goto tooLarge;
- } else if (d <= (((double) (long) LONG_MIN) - 0.5)) {
- TclNewWideIntObj(resPtr, Tcl_DoubleAsWide(d - 0.5));
- } else {
- TclNewLongObj(resPtr, (long) (d - 0.5));
- }
- } else {
- if (d >= Tcl_WideAsDouble(LLONG_MAX)+0.5) {
- goto tooLarge;
- } else if (d >= (((double) LONG_MAX + 0.5))) {
- TclNewWideIntObj(resPtr, Tcl_DoubleAsWide(d + 0.5));
- } else {
- TclNewLongObj(resPtr, (long) (d + 0.5));
- }
- }
-
- /*
- * Free the argument Tcl_Obj and push the result object.
- */
-
- TclDecrRefCount(valuePtr);
- PUSH_OBJECT(resPtr);
- return TCL_OK;
-
- /*
- * Error return: result cannot be represented as an integer.
- */
-
- tooLarge:
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "integer value too large to represent", -1));
- Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW",
- "integer value too large to represent",
- (char *) NULL);
- return TCL_ERROR;
-}
-
-static int
-ExprSrandFunc(interp, tosPtr, clientData)
- Tcl_Interp *interp; /* The interpreter in which to execute the
- * function. */
- Tcl_Obj **tosPtr; /* Points to top of evaluation stack. */
- ClientData clientData; /* Ignored. */
-{
- Interp *iPtr = (Interp *) interp;
- Tcl_Obj *valuePtr;
- long i = 0; /* Initialized to avoid compiler warning. */
-
- /*
- * Pop the argument from the evaluation stack. Use the value
- * to reset the random number seed.
- */
-
- valuePtr = POP_OBJECT();
-
- if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
- return TCL_ERROR;
- }
-
- if (Tcl_GetLongFromObj(NULL, valuePtr, &i) != TCL_OK) {
- /*
- * At this point, the only other possible type is double
- */
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "can't use floating-point value as argument to srand", -1));
- return TCL_ERROR;
- }
-
- /*
- * Reset the seed. Make sure 1 <= randSeed <= 2^31 - 2.
- * See comments in ExprRandFunc() for more details.
- */
-
- iPtr->flags |= RAND_SEED_INITIALIZED;
- iPtr->randSeed = i;
- iPtr->randSeed &= (unsigned long) 0x7fffffff;
- if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7fffffff)) {
- iPtr->randSeed ^= 123459876;
- }
-
- /*
- * To avoid duplicating the random number generation code we simply
- * clean up our state and call the real random number function. That
- * function will always succeed.
- */
-
- TclDecrRefCount(valuePtr);
- ExprRandFunc(interp, tosPtr, clientData);
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * ExprCallMathFunc --
- *
- * This procedure is invoked to call a non-builtin math function
- * during the execution of an expression.
- *
- * Results:
- * TCL_OK is returned if all went well and the function's value
- * was computed successfully. If an error occurred, TCL_ERROR
- * is returned and an error message is left in the interpreter's
- * result. After a successful return this procedure pops its
- * objc arguments and pushes a Tcl object holding the result.
- *
- * Side effects:
- * None, unless the called math function has side effects.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-ExprCallMathFunc(interp, objc, objv)
- Tcl_Interp *interp; /* The interpreter in which to execute the
- * function. */
- int objc; /* Number of arguments. The function name is
- * the 0-th argument. */
- Tcl_Obj **objv; /* The array of arguments. The function name
- * is objv[0]. */
-{
- Interp *iPtr = (Interp *) interp;
- char *funcName;
- Tcl_HashEntry *hPtr;
- MathFunc *mathFuncPtr; /* Information about math function. */
- Tcl_Value args[MAX_MATH_ARGS]; /* Arguments for function call. */
- Tcl_Value funcResult; /* Result of function call as Tcl_Value. */
- register Tcl_Obj *valuePtr;
- long i;
- double d;
- int j, k, result;
-
- Tcl_ResetResult(interp);
-
- /*
- * Look up the MathFunc record for the function.
- */
-
- funcName = TclGetString(objv[0]);
- hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, funcName);
- if (hPtr == NULL) {
- Tcl_AppendResult(interp, "unknown math function \"", funcName,
- "\"", (char *) NULL);
- return TCL_ERROR;
- }
- mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);
- if (mathFuncPtr->numArgs != (objc-1)) {
- Tcl_Panic("ExprCallMathFunc: expected number of args %d != actual number %d",
- mathFuncPtr->numArgs, objc);
- return TCL_ERROR;
- }
-
- /*
- * Collect the arguments for the function, if there are any, into the
- * array "args". Note that args[0] will have the Tcl_Value that
- * corresponds to objv[1].
- */
-
- for (j = 1, k = 0; j < objc; j++, k++) {
- valuePtr = objv[j];
-
- if (VerifyExprObjType(interp, valuePtr) != TCL_OK) {
- return TCL_ERROR;
- }
-
- /*
- * Copy the object's numeric value to the argument record,
- * converting it if necessary.
- */
-
- if (valuePtr->typePtr == &tclIntType) {
- i = valuePtr->internalRep.longValue;
- if (mathFuncPtr->argTypes[k] == TCL_DOUBLE) {
- args[k].type = TCL_DOUBLE;
- args[k].doubleValue = i;
- } else if (mathFuncPtr->argTypes[k] == TCL_WIDE_INT) {
- args[k].type = TCL_WIDE_INT;
- args[k].wideValue = Tcl_LongAsWide(i);
- } else {
- args[k].type = TCL_INT;
- args[k].intValue = i;
- }
- } else if (valuePtr->typePtr == &tclWideIntType) {
- Tcl_WideInt w;
- TclGetWide(w,valuePtr);
- if (mathFuncPtr->argTypes[k] == TCL_DOUBLE) {
- args[k].type = TCL_DOUBLE;
- args[k].doubleValue = Tcl_WideAsDouble(w);
- } else if (mathFuncPtr->argTypes[k] == TCL_INT) {
- args[k].type = TCL_INT;
- args[k].intValue = Tcl_WideAsLong(w);
- } else {
- args[k].type = TCL_WIDE_INT;
- args[k].wideValue = w;
- }
- } else {
- d = valuePtr->internalRep.doubleValue;
- if (mathFuncPtr->argTypes[k] == TCL_INT) {
- args[k].type = TCL_INT;
- args[k].intValue = (long) d;
- } else if (mathFuncPtr->argTypes[k] == TCL_WIDE_INT) {
- args[k].type = TCL_WIDE_INT;
- args[k].wideValue = Tcl_DoubleAsWide(d);
- } else {
- args[k].type = TCL_DOUBLE;
- args[k].doubleValue = d;
- }
- }
- }
-
- /*
- * Invoke the function and copy its result back into valuePtr.
- */
-
- result = (*mathFuncPtr->proc)(mathFuncPtr->clientData, interp, args,
- &funcResult);
- if (result != TCL_OK) {
- return result;
- }
-
- /*
- * Pop the objc top stack elements and decrement their ref counts.
- */
-
- for (k = 0; k < objc; k++) {
- valuePtr = objv[k];
- TclDecrRefCount(valuePtr);
- }
-
- /*
- * Push the call's object result.
- */
-
- if (funcResult.type == TCL_INT) {
- TclNewLongObj(objv[0], funcResult.intValue);
- } else if (funcResult.type == TCL_WIDE_INT) {
- TclNewWideIntObj(objv[0], funcResult.wideValue);
- } else {
- d = funcResult.doubleValue;
- if (IS_NAN(d) || IS_INF(d)) {
- TclExprFloatError(interp, d);
- return TCL_ERROR;
- }
- TclNewDoubleObj(objv[0], d);
- }
- Tcl_IncrRefCount(objv[0]);
-
- return result;
-}
-
-/*
- *----------------------------------------------------------------------
- *
* TclExprFloatError --
*
* This procedure is called when an error occurs during a
diff --git a/generic/tclFCmd.c b/generic/tclFCmd.c
index 024526e..f8606e5 100644
--- a/generic/tclFCmd.c
+++ b/generic/tclFCmd.c
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclFCmd.c,v 1.31 2005/01/14 18:56:32 vincentdarley Exp $
+ * RCS: @(#) $Id: tclFCmd.c,v 1.32 2005/05/10 18:34:37 kennykb Exp $
*/
#include "tclInt.h"
diff --git a/generic/tclFileName.c b/generic/tclFileName.c
index bde0071..5bfad99 100644
--- a/generic/tclFileName.c
+++ b/generic/tclFileName.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclFileName.c,v 1.68 2005/04/20 15:13:39 kennykb Exp $
+ * RCS: @(#) $Id: tclFileName.c,v 1.69 2005/05/10 18:34:38 kennykb Exp $
*/
#include "tclInt.h"
diff --git a/generic/tclGet.c b/generic/tclGet.c
index 1804088..be3d942 100644
--- a/generic/tclGet.c
+++ b/generic/tclGet.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclGet.c,v 1.14 2005/05/03 18:08:18 dgp Exp $
+ * RCS: @(#) $Id: tclGet.c,v 1.15 2005/05/10 18:34:38 kennykb Exp $
*/
#include "tclInt.h"
diff --git a/generic/tclGetDate.y b/generic/tclGetDate.y
index 0be34be..800c04b 100644
--- a/generic/tclGetDate.y
+++ b/generic/tclGetDate.y
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclGetDate.y,v 1.26 2004/12/29 20:57:27 kennykb Exp $
+ * RCS: @(#) $Id: tclGetDate.y,v 1.27 2005/05/10 18:34:38 kennykb Exp $
*/
%{
diff --git a/generic/tclIO.c b/generic/tclIO.c
index e94264a..ee37035 100644
--- a/generic/tclIO.c
+++ b/generic/tclIO.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclIO.c,v 1.85 2005/05/05 18:37:58 dgp Exp $
+ * RCS: @(#) $Id: tclIO.c,v 1.86 2005/05/10 18:34:38 kennykb Exp $
*/
#include "tclInt.h"
diff --git a/generic/tclIOCmd.c b/generic/tclIOCmd.c
index fc14619..abd789c 100644
--- a/generic/tclIOCmd.c
+++ b/generic/tclIOCmd.c
@@ -8,7 +8,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclIOCmd.c,v 1.23 2005/04/27 18:48:25 dgp Exp $
+ * RCS: @(#) $Id: tclIOCmd.c,v 1.24 2005/05/10 18:34:40 kennykb Exp $
*/
#include "tclInt.h"
diff --git a/generic/tclIOUtil.c b/generic/tclIOUtil.c
index 17d6efa..f94a3c8 100644
--- a/generic/tclIOUtil.c
+++ b/generic/tclIOUtil.c
@@ -17,7 +17,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclIOUtil.c,v 1.117 2005/04/27 18:48:25 dgp Exp $
+ * RCS: @(#) $Id: tclIOUtil.c,v 1.118 2005/05/10 18:34:40 kennykb Exp $
*/
#include "tclInt.h"
diff --git a/generic/tclInt.decls b/generic/tclInt.decls
index a997c25..c457741 100644
--- a/generic/tclInt.decls
+++ b/generic/tclInt.decls
@@ -12,7 +12,7 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
-# RCS: @(#) $Id: tclInt.decls,v 1.87 2005/05/05 18:38:00 dgp Exp $
+# RCS: @(#) $Id: tclInt.decls,v 1.88 2005/05/10 18:34:41 kennykb Exp $
library tcl
@@ -874,6 +874,23 @@ declare 218 generic {
void TclPopStackFrame(Tcl_Interp *interp)
}
+# Entries in tommath needed only by tcltest
+
+declare 219 generic {
+ int TclBN_mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d)
+}
+declare 220 generic {
+ int TclBN_mp_mul_d(mp_int *a, mp_digit b, mp_int *c)
+}
+declare 221 generic {
+ void TclBN_mp_clear(mp_int *a)
+}
+declare 222 generic {
+ int TclBN_mp_init(mp_int *a)
+}
+declare 223 generic {
+ int TclBN_mp_read_radix(mp_int *a, const char *str, int radix)
+}
##############################################################################
diff --git a/generic/tclInt.h b/generic/tclInt.h
index 6af07ff..0a05edb 100644
--- a/generic/tclInt.h
+++ b/generic/tclInt.h
@@ -12,7 +12,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclInt.h,v 1.228 2005/05/05 18:38:01 dgp Exp $
+ * RCS: @(#) $Id: tclInt.h,v 1.229 2005/05/10 18:34:42 kennykb Exp $
*/
#ifndef _TCLINT
@@ -1852,10 +1852,14 @@ MODULE_SCOPE void TclAppendObjToErrorInfo _ANSI_ARGS_((
Tcl_Interp *interp, Tcl_Obj *objPtr));
MODULE_SCOPE int TclArraySet _ANSI_ARGS_((Tcl_Interp *interp,
Tcl_Obj *arrayNameObj, Tcl_Obj *arrayElemObj));
+MODULE_SCOPE double TclBignumToDouble _ANSI_ARGS_((mp_int* bignum));
MODULE_SCOPE int TclCheckBadOctal _ANSI_ARGS_((Tcl_Interp *interp,
CONST char *value));
MODULE_SCOPE void TclCleanupLiteralTable _ANSI_ARGS_((
Tcl_Interp* interp, LiteralTable* tablePtr));
+MODULE_SCOPE int TclDoubleDigits _ANSI_ARGS_((char* buf,
+ double value,
+ int* signum));
MODULE_SCOPE void TclExpandTokenArray _ANSI_ARGS_((
Tcl_Parse *parsePtr));
MODULE_SCOPE int TclFileAttrsCmd _ANSI_ARGS_((Tcl_Interp *interp,
@@ -1871,6 +1875,7 @@ MODULE_SCOPE int TclFileRenameCmd _ANSI_ARGS_((Tcl_Interp *interp,
MODULE_SCOPE void TclFinalizeAllocSubsystem _ANSI_ARGS_((void));
MODULE_SCOPE void TclFinalizeCompExecEnv _ANSI_ARGS_((void));
MODULE_SCOPE void TclFinalizeCompilation _ANSI_ARGS_((void));
+MODULE_SCOPE void TclFinalizeDoubleConversion _ANSI_ARGS_((void));
MODULE_SCOPE void TclFinalizeEncodingSubsystem _ANSI_ARGS_((void));
MODULE_SCOPE void TclFinalizeEnvironment _ANSI_ARGS_((void));
MODULE_SCOPE void TclFinalizeExecution _ANSI_ARGS_((void));
@@ -1884,6 +1889,7 @@ MODULE_SCOPE void TclFinalizeAsync _ANSI_ARGS_((void));
MODULE_SCOPE void TclFinalizeSynchronization _ANSI_ARGS_((void));
MODULE_SCOPE void TclFinalizeLock _ANSI_ARGS_((void));
MODULE_SCOPE void TclFinalizeThreadData _ANSI_ARGS_((void));
+MODULE_SCOPE void TclFormatNaN _ANSI_ARGS_((double value, char* buffer));
MODULE_SCOPE int TclFSFileAttrIndex _ANSI_ARGS_((Tcl_Obj *pathPtr,
CONST char *attributeName, int *indexPtr));
MODULE_SCOPE Tcl_Obj * TclGetBgErrorHandler _ANSI_ARGS_((Tcl_Interp *interp));
@@ -1902,6 +1908,7 @@ MODULE_SCOPE int TclGlob _ANSI_ARGS_((Tcl_Interp *interp,
int globFlags, Tcl_GlobTypeData* types));
MODULE_SCOPE void TclInitAlloc _ANSI_ARGS_((void));
MODULE_SCOPE void TclInitDbCkalloc _ANSI_ARGS_((void));
+MODULE_SCOPE void TclInitDoubleConversion _ANSI_ARGS_((void));
MODULE_SCOPE void TclInitEmbeddedConfigurationInformation
_ANSI_ARGS_((Tcl_Interp *interp));
MODULE_SCOPE void TclInitEncodingSubsystem _ANSI_ARGS_((void));
@@ -2048,6 +2055,8 @@ MODULE_SCOPE void TclSetProcessGlobalValue _ANSI_ARGS_ ((
Tcl_Encoding encoding));
MODULE_SCOPE VOID TclSignalExitThread _ANSI_ARGS_((Tcl_ThreadId id,
int result));
+MODULE_SCOPE double TclStrToD _ANSI_ARGS_((CONST char* string,
+ CONST char** endPtr));
MODULE_SCOPE int TclSubstTokens _ANSI_ARGS_((Tcl_Interp *interp,
Tcl_Token *tokenPtr, int count,
int *tokensLeftPtr));
@@ -2717,6 +2726,20 @@ MODULE_SCOPE void TclDbInitNewObj _ANSI_ARGS_((Tcl_Obj *objPtr));
}
/*
+ *----------------------------------------------------------------------
+ *
+ * Core procedures added to libtommath for bignum manipulation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+MODULE_SCOPE void* TclBNAlloc( size_t nBytes );
+MODULE_SCOPE void* TclBNRealloc( void* oldBlock, size_t newNBytes );
+MODULE_SCOPE void TclBNFree( void* block );
+MODULE_SCOPE void TclBNInitBignumFromLong( mp_int* bignum, long initVal );
+
+
+/*
*----------------------------------------------------------------
* Macro used by the Tcl core to check whether a pattern has
* any characters special to [string match].
diff --git a/generic/tclIntDecls.h b/generic/tclIntDecls.h
index 6972a28..7364d0f 100644
--- a/generic/tclIntDecls.h
+++ b/generic/tclIntDecls.h
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclIntDecls.h,v 1.78 2005/05/05 18:38:02 dgp Exp $
+ * RCS: @(#) $Id: tclIntDecls.h,v 1.79 2005/05/10 18:34:42 kennykb Exp $
*/
#ifndef _TCLINTDECLS
@@ -1128,6 +1128,34 @@ EXTERN int TclPushStackFrame _ANSI_ARGS_((Tcl_Interp * interp,
/* 218 */
EXTERN void TclPopStackFrame _ANSI_ARGS_((Tcl_Interp * interp));
#endif
+#ifndef TclBN_mp_div_d_TCL_DECLARED
+#define TclBN_mp_div_d_TCL_DECLARED
+/* 219 */
+EXTERN int TclBN_mp_div_d _ANSI_ARGS_((mp_int * a, mp_digit b,
+ mp_int * c, mp_digit * d));
+#endif
+#ifndef TclBN_mp_mul_d_TCL_DECLARED
+#define TclBN_mp_mul_d_TCL_DECLARED
+/* 220 */
+EXTERN int TclBN_mp_mul_d _ANSI_ARGS_((mp_int * a, mp_digit b,
+ mp_int * c));
+#endif
+#ifndef TclBN_mp_clear_TCL_DECLARED
+#define TclBN_mp_clear_TCL_DECLARED
+/* 221 */
+EXTERN void TclBN_mp_clear _ANSI_ARGS_((mp_int * a));
+#endif
+#ifndef TclBN_mp_init_TCL_DECLARED
+#define TclBN_mp_init_TCL_DECLARED
+/* 222 */
+EXTERN int TclBN_mp_init _ANSI_ARGS_((mp_int * a));
+#endif
+#ifndef TclBN_mp_read_radix_TCL_DECLARED
+#define TclBN_mp_read_radix_TCL_DECLARED
+/* 223 */
+EXTERN int TclBN_mp_read_radix _ANSI_ARGS_((mp_int * a,
+ const char * str, int radix));
+#endif
typedef struct TclIntStubs {
int magic;
@@ -1367,6 +1395,11 @@ typedef struct TclIntStubs {
void (*tclStackFree) _ANSI_ARGS_((Tcl_Interp * interp)); /* 216 */
int (*tclPushStackFrame) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_CallFrame ** framePtrPtr, Tcl_Namespace * namespacePtr, int isProcCallFrame)); /* 217 */
void (*tclPopStackFrame) _ANSI_ARGS_((Tcl_Interp * interp)); /* 218 */
+ int (*tclBN_mp_div_d) _ANSI_ARGS_((mp_int * a, mp_digit b, mp_int * c, mp_digit * d)); /* 219 */
+ int (*tclBN_mp_mul_d) _ANSI_ARGS_((mp_int * a, mp_digit b, mp_int * c)); /* 220 */
+ void (*tclBN_mp_clear) _ANSI_ARGS_((mp_int * a)); /* 221 */
+ int (*tclBN_mp_init) _ANSI_ARGS_((mp_int * a)); /* 222 */
+ int (*tclBN_mp_read_radix) _ANSI_ARGS_((mp_int * a, const char * str, int radix)); /* 223 */
} TclIntStubs;
#ifdef __cplusplus
@@ -2121,6 +2154,26 @@ extern TclIntStubs *tclIntStubsPtr;
#define TclPopStackFrame \
(tclIntStubsPtr->tclPopStackFrame) /* 218 */
#endif
+#ifndef TclBN_mp_div_d
+#define TclBN_mp_div_d \
+ (tclIntStubsPtr->tclBN_mp_div_d) /* 219 */
+#endif
+#ifndef TclBN_mp_mul_d
+#define TclBN_mp_mul_d \
+ (tclIntStubsPtr->tclBN_mp_mul_d) /* 220 */
+#endif
+#ifndef TclBN_mp_clear
+#define TclBN_mp_clear \
+ (tclIntStubsPtr->tclBN_mp_clear) /* 221 */
+#endif
+#ifndef TclBN_mp_init
+#define TclBN_mp_init \
+ (tclIntStubsPtr->tclBN_mp_init) /* 222 */
+#endif
+#ifndef TclBN_mp_read_radix
+#define TclBN_mp_read_radix \
+ (tclIntStubsPtr->tclBN_mp_read_radix) /* 223 */
+#endif
#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */
diff --git a/generic/tclInterp.c b/generic/tclInterp.c