ADDED doc/Number.3 Index: doc/Number.3 ================================================================== --- /dev/null +++ doc/Number.3 @@ -0,0 +1,123 @@ +'\" +'\" Contribution from Don Porter, NIST, 2022. (not subject to US copyright) +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +.TH Tcl_GetNumber 3 8.7 Tcl "Tcl Library Procedures" +.so man.macros +.BS +.SH NAME +Tcl_GetNumber, Tcl_GetNumberFromObj \- get numeric value from Tcl value +.SH SYNOPSIS +.nf +\fB#include \fR +.sp +\fB#include \fR +.sp +int +\fBTcl_GetNumber\fR(\fIinterp, bytes, numBytes, clientDataPtr, typePtr\fR) +.sp +int +\fBTcl_GetNumberFromObj\fR(\fIinterp, objPtr, clientDataPtr, typePtr\fR) +.SH ARGUMENTS +.AS Tcl_Interp clientDataPtr out +.AP Tcl_Interp *interp out +When non-NULL, error information is recorded here when the value is not +in any of the numeric formats recognized by Tcl. +.AP "const char" *bytes in +Points to first byte of the string value to be examined. +.AP size_t numBytes in +The number of bytes, starting at \fIbytes\fR, that should be examined. +If the value \fBTCL_INDEX_NONE\fR is provided, then all bytes should +be examined until the first \fBNUL\fR byte terminates examination. +.AP "void *" *clientDataPtr out +Points to space where a pointer value may be written through which a numeric +value is available to read. +.AP int *typePtr out +Points to space where a value may be written reporting what type of +numeric storage is available to read. +.AP Tcl_Obj *objPtr in +A Tcl value to be examined. +.BE +.SH DESCRIPTION +.PP +These procedures enable callers to retrieve a numeric value from a +Tcl value in a numeric format recognized by Tcl. +.PP +Tcl recognizes many values as numbers. Several examples include: +\fB"0"\fR, \fB" +1"\fR, \fB"-2 "\fR, \fB" 3 "\fR, \fB"0xdad1"\fR, \fB"0d09"\fR, +\fB"1_000_000"\fR, \fB"4.0"\fR, \fB"1e-7"\fR, \fB"NaN"\fR, or \fB"Inf"\fR. +When built-in Tcl commands act on these values as numbers, they are converted +to a numeric representation for efficient handling in C code. Tcl makes +use of three C types to store these representations: \fBdouble\fR, +\fBTcl_WideInt\fR, and \fBmp_int\fR. The \fBdouble\fR type is provided by the +C language standard. The \fBTcl_WideInt\fR type is declared in the Tcl +header file, \fBtcl.h\fR, and is equivalent to the C standard type +\fBlong long\fR on most platforms. The \fBmp_int\fR type is declared in the +header file \fBtclTomMath.h\fR, and implemented by the LibTomMath +multiple-precision integer library, included with Tcl. +.PP +The routines \fBTcl_GetNumber\fR and \fBTcl_GetNumberFromObj\fR perform +the same function. They differ only in how the arguments present the Tcl +value to be examined. \fBTcl_GetNumber\fR accepts a counted string +value in the arguments \fIbytes\fR and \fInumBytes\fR (or a +\fBNUL\fR-terminated string value when \fInumBytes\fR is +\fBTCL_INDEX_NONE\fR). \fBTcl_GetNumberFromObj\fR accepts the Tcl value +in \fIobjPtr\fR. +.PP +Both routines examine the Tcl value and determine whether Tcl recognizes +it as a number. If not, both routines return \fBTCL_ERROR\fR and (when +\fIinterp\fR is not NULL) record an error message and error code +in \fIinterp\fR. +.PP +If Tcl does recognize the examined value as a number, both routines return +\fBTCL_OK\fR, and use the pointer arguments \fIclientDataPtr\fR +and \fItypePtr\fR (which may not be NULL) to report information the +caller can use to retrieve the numeric representation. Both routines +write to *\fIclientDataPtr\fR a pointer to the internal storage location +where Tcl holds the converted numeric value. +.PP +When the converted numeric value is stored as a \fBdouble\fR, +a call to math library routine \fBisnan\fR determines whether that +value is not a number (NaN). If so, both \fBTcl_GetNumber\fR and +\fBTcl_GetNumberFromObj\fR write the value \fBTCL_NUMBER_NAN\fR +to *\fItypePtr\fR. If not, both routines write the value +\fBTCL_NUMBER_DOUBLE\fR to *\fItypePtr\fR. These routines report +different type values in these cases because \fBTcl_GetDoubleFromObj\fR +raises an error on NaN values. For both reported type values, +the storage pointer may be cast to type \fBconst double *\fR and +the \fBdouble\fR numeric value may be read through it. +.PP +When the converted numeric value is stored as a \fBTcl_WideInt\fR, +both \fBTcl_GetNumber\fR and \fBTcl_GetNumberFromObj\fR write the +value \fBTCL_NUMBER_INT\fR to *\fItypePtr\fR. +The storage pointer may be cast to type \fBconst Tcl_WideInt *\fR and +the \fBTcl_WideInt\fR numeric value may be read through it. +.PP +When the converted numeric value is stored as an \fBmp_int\fR, +both \fBTcl_GetNumber\fR and \fBTcl_GetNumberFromObj\fR write the +value \fBTCL_NUMBER_BIG\fR to *\fItypePtr\fR. +The storage pointer may be cast to type \fBconst mp_int *\fR and +the \fBmp_int\fR numeric value may be read through it. +.PP +Future releases of Tcl might expand or revise the recognition of +values as numbers. If additional storage representations are +adopted, these routines will add new values to be written to +*\fItypePtr\fR to identify them. Callers should consider how +they should react to unknown values written to *\fItypePtr\fR. +.PP +When callers of these routines read numeric values through the +reported storage pointer, they are accessing memory that belongs +to the Tcl library. The Tcl library has the power to overwrite +or free this memory. The storage pointer reported by a call to +\fBTcl_GetNumber\fR or \fBTcl_GetNumberFromObj\fR should not be +used after the same thread has possibly returned control to the +Tcl library. If longer term access to the numeric value is needed, +it should be copied into memory controlled by the caller. Callers +must not attempt to write through or free the storage pointer. +.SH "SEE ALSO" +Tcl_GetDouble, Tcl_GetDoubleFromObj, Tcl_GetWideIntFromObj +.SH KEYWORDS +double, double value, double type, integer, integer value, integer type, +internal representation, value, value type, string representation Index: generic/tcl.decls ================================================================== --- generic/tcl.decls +++ generic/tcl.decls @@ -2530,11 +2530,19 @@ declare 679 { int Tcl_NRCallObjProc2(Tcl_Interp *interp, Tcl_ObjCmdProc2 *objProc2, void *clientData, size_t objc, Tcl_Obj *const objv[]) } -# slot 680 and 681 are reserved for TIP #638 +# TIP #638. +declare 680 { + int Tcl_GetNumberFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, + void **clientDataPtr, int *typePtr) +} +declare 681 { + int Tcl_GetNumber(Tcl_Interp *interp, const char *bytes, size_t numBytes, + void **clientDataPtr, int *typePtr) +} # TIP #220. declare 682 { int Tcl_RemoveChannelMode(Tcl_Interp *interp, Tcl_Channel chan, int mode) } Index: generic/tcl.h ================================================================== --- generic/tcl.h +++ generic/tcl.h @@ -973,10 +973,24 @@ * 64-bit integers). */ #define TCL_INTEGER_SPACE (3*(int)sizeof(Tcl_WideInt)) +/* + *---------------------------------------------------------------------------- + * Type values returned by Tcl_GetNumberFromObj + * TCL_NUMBER_INT Representation is a Tcl_WideInt + * TCL_NUMBER_BIG Representation is an mp_int + * TCL_NUMBER_DOUBLE Representation is a double + * TCL_NUMBER_NAN Value is NaN. + */ + +#define TCL_NUMBER_INT 2 +#define TCL_NUMBER_BIG 3 +#define TCL_NUMBER_DOUBLE 4 +#define TCL_NUMBER_NAN 5 + /* * Flag values passed to Tcl_ConvertElement. * TCL_DONT_USE_BRACES forces it not to enclose the element in braces, but to * use backslash quoting instead. * TCL_DONT_QUOTE_HASH disables the default quoting of the '#' character. It Index: generic/tclArithSeries.c ================================================================== --- generic/tclArithSeries.c +++ generic/tclArithSeries.c @@ -230,11 +230,11 @@ assignNumber(int useDoubles, Tcl_WideInt *intNumberPtr, double *dblNumberPtr, Tcl_Obj *numberObj) { void *clientData; int tcl_number_type; - if (TclGetNumberFromObj(NULL, numberObj, &clientData, &tcl_number_type) != TCL_OK + if (Tcl_GetNumberFromObj(NULL, numberObj, &clientData, &tcl_number_type) != TCL_OK || tcl_number_type == TCL_NUMBER_BIG) { return; } if (useDoubles) { if (tcl_number_type != TCL_NUMBER_INT) { Index: generic/tclBasic.c ================================================================== --- generic/tclBasic.c +++ generic/tclBasic.c @@ -4133,11 +4133,11 @@ * Convert arguments from Tcl_Obj's to Tcl_Value's. */ args = (Tcl_Value *)ckalloc(dataPtr->numArgs * sizeof(Tcl_Value)); for (j = 1, k = 0; j < objc; ++j, ++k) { - /* TODO: Convert to TclGetNumberFromObj? */ + /* TODO: Convert to Tcl_GetNumberFromObj? */ valuePtr = objv[j]; result = Tcl_GetDoubleFromObj(NULL, valuePtr, &d); #ifdef ACCEPT_NAN if (result != TCL_OK) { const Tcl_ObjInternalRep *irPtr @@ -7041,11 +7041,11 @@ result = Tcl_ExprObj(interp, objPtr, &resultPtr); if (result != TCL_OK) { return TCL_ERROR; } - if (TclGetNumberFromObj(interp, resultPtr, &internalPtr, &type)!=TCL_OK) { + if (Tcl_GetNumberFromObj(interp, resultPtr, &internalPtr, &type)!=TCL_OK) { return TCL_ERROR; } switch (type) { case TCL_NUMBER_DOUBLE: { @@ -7087,11 +7087,11 @@ result = Tcl_ExprObj(interp, objPtr, &resultPtr); if (result != TCL_OK) { return TCL_ERROR; } - result = TclGetNumberFromObj(interp, resultPtr, &internalPtr, &type); + result = Tcl_GetNumberFromObj(interp, resultPtr, &internalPtr, &type); if (result == TCL_OK) { switch (type) { case TCL_NUMBER_NAN: #ifndef ACCEPT_NAN result = Tcl_GetDoubleFromObj(interp, resultPtr, ptr); @@ -7808,11 +7808,11 @@ /* * Make sure that the arg is a number. */ - if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } switch (type) { case TCL_NUMBER_NAN: @@ -8071,11 +8071,11 @@ if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } - if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_INT) { Tcl_WideInt l = *((const Tcl_WideInt *) ptr); @@ -8226,11 +8226,11 @@ if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } - if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_DOUBLE) { d = *((const double *) ptr); @@ -8307,11 +8307,11 @@ MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } res = objv[1]; for (i = 1; i < objc; i++) { - if (TclGetNumberFromObj(interp, objv[i], &ptr, &type) != TCL_OK) { + if (Tcl_GetNumberFromObj(interp, objv[i], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_NAN) { /* * Get the error message for NaN. @@ -8459,11 +8459,11 @@ if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } - if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_DOUBLE) { double fractPart, intPart; @@ -8727,11 +8727,11 @@ if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } - if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type != TCL_NUMBER_NAN) { if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { return TCL_ERROR; @@ -8758,11 +8758,11 @@ if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } - if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type != TCL_NUMBER_NAN) { if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { return TCL_ERROR; @@ -8788,11 +8788,11 @@ if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } - if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type != TCL_NUMBER_NAN) { if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { return TCL_ERROR; @@ -8818,11 +8818,11 @@ if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } - if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type != TCL_NUMBER_NAN) { if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { return TCL_ERROR; @@ -8848,11 +8848,11 @@ if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } - if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type != TCL_NUMBER_NAN) { if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { return TCL_ERROR; @@ -8878,21 +8878,21 @@ if (objc != 3) { MathFuncWrongNumArgs(interp, 3, objc, objv); return TCL_ERROR; } - if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_NAN) { result = 1; } else { d = *((const double *) ptr); result = (ClassifyDouble(d) == FP_NAN); } - if (TclGetNumberFromObj(interp, objv[2], &ptr, &type) != TCL_OK) { + if (Tcl_GetNumberFromObj(interp, objv[2], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_NAN) { result |= 1; } else { @@ -8920,11 +8920,11 @@ if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "floatValue"); return TCL_ERROR; } - if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { + if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_NAN) { goto gotNaN; } else if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { Index: generic/tclCmdIL.c ================================================================== --- generic/tclCmdIL.c +++ generic/tclCmdIL.c @@ -4077,11 +4077,11 @@ int status; SequenceOperators opmode; SequenceByMode bymode; void *clientData; - status = TclGetNumberFromObj(NULL, argPtr, &clientData, keywordIndexPtr); + status = Tcl_GetNumberFromObj(NULL, argPtr, &clientData, keywordIndexPtr); if (status == TCL_OK) { if (numValuePtr) { *numValuePtr = argPtr; } return NumericArg; Index: generic/tclDecls.h ================================================================== --- generic/tclDecls.h +++ generic/tclDecls.h @@ -2006,12 +2006,18 @@ Tcl_CmdDeleteProc *deleteProc); /* 679 */ EXTERN int Tcl_NRCallObjProc2(Tcl_Interp *interp, Tcl_ObjCmdProc2 *objProc2, void *clientData, size_t objc, Tcl_Obj *const objv[]); -/* Slot 680 is reserved */ -/* Slot 681 is reserved */ +/* 680 */ +EXTERN int Tcl_GetNumberFromObj(Tcl_Interp *interp, + Tcl_Obj *objPtr, void **clientDataPtr, + int *typePtr); +/* 681 */ +EXTERN int Tcl_GetNumber(Tcl_Interp *interp, const char *bytes, + size_t numBytes, void **clientDataPtr, + int *typePtr); /* 682 */ EXTERN int Tcl_RemoveChannelMode(Tcl_Interp *interp, Tcl_Channel chan, int mode); typedef struct { @@ -2726,12 +2732,12 @@ int (*tcl_GetBoolFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags, char *charPtr); /* 675 */ Tcl_Command (*tcl_CreateObjCommand2) (Tcl_Interp *interp, const char *cmdName, Tcl_ObjCmdProc2 *proc2, void *clientData, Tcl_CmdDeleteProc *deleteProc); /* 676 */ Tcl_Trace (*tcl_CreateObjTrace2) (Tcl_Interp *interp, int level, int flags, Tcl_CmdObjTraceProc2 *objProc2, void *clientData, Tcl_CmdObjTraceDeleteProc *delProc); /* 677 */ Tcl_Command (*tcl_NRCreateCommand2) (Tcl_Interp *interp, const char *cmdName, Tcl_ObjCmdProc2 *proc, Tcl_ObjCmdProc2 *nreProc2, void *clientData, Tcl_CmdDeleteProc *deleteProc); /* 678 */ int (*tcl_NRCallObjProc2) (Tcl_Interp *interp, Tcl_ObjCmdProc2 *objProc2, void *clientData, size_t objc, Tcl_Obj *const objv[]); /* 679 */ - void (*reserved680)(void); - void (*reserved681)(void); + int (*tcl_GetNumberFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, void **clientDataPtr, int *typePtr); /* 680 */ + int (*tcl_GetNumber) (Tcl_Interp *interp, const char *bytes, size_t numBytes, void **clientDataPtr, int *typePtr); /* 681 */ int (*tcl_RemoveChannelMode) (Tcl_Interp *interp, Tcl_Channel chan, int mode); /* 682 */ } TclStubs; extern const TclStubs *tclStubsPtr; @@ -4119,12 +4125,14 @@ (tclStubsPtr->tcl_CreateObjTrace2) /* 677 */ #define Tcl_NRCreateCommand2 \ (tclStubsPtr->tcl_NRCreateCommand2) /* 678 */ #define Tcl_NRCallObjProc2 \ (tclStubsPtr->tcl_NRCallObjProc2) /* 679 */ -/* Slot 680 is reserved */ -/* Slot 681 is reserved */ +#define Tcl_GetNumberFromObj \ + (tclStubsPtr->tcl_GetNumberFromObj) /* 680 */ +#define Tcl_GetNumber \ + (tclStubsPtr->tcl_GetNumber) /* 681 */ #define Tcl_RemoveChannelMode \ (tclStubsPtr->tcl_RemoveChannelMode) /* 682 */ #endif /* defined(USE_TCL_STUBS) */ Index: generic/tclExecute.c ================================================================== --- generic/tclExecute.c +++ generic/tclExecute.c @@ -501,11 +501,11 @@ } \ } while (0) /* * Macro used in this file to save a function call for common uses of - * TclGetNumberFromObj(). The ANSI C "prototype" is: + * Tcl_GetNumberFromObj(). The ANSI C "prototype" is: * * MODULE_SCOPE int GetNumberFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, * void **ptrPtr, int *tPtr); */ @@ -520,11 +520,11 @@ : (*(tPtr) = TCL_NUMBER_DOUBLE)), \ *(ptrPtr) = (void *) \ (&((objPtr)->internalRep.doubleValue)), TCL_OK) : \ (((objPtr)->bytes != NULL) && ((objPtr)->length == 0)) \ ? TCL_ERROR : \ - TclGetNumberFromObj((interp), (objPtr), (ptrPtr), (tPtr))) + Tcl_GetNumberFromObj((interp), (objPtr), (ptrPtr), (tPtr))) /* * Macro used to make the check for type overflow more mnemonic. This works by * comparing sign bits; the rest of the word is irrelevant. The ANSI C * "prototype" (where inttype_t is any integer type) is: Index: generic/tclInt.h ================================================================== --- generic/tclInt.h +++ generic/tclInt.h @@ -2874,25 +2874,10 @@ #define TCL_PARSE_BINARY_ONLY 64 /* Parse binary even without prefix. */ #define TCL_PARSE_NO_UNDERSCORE 128 /* Reject underscore digit separator */ -/* - *---------------------------------------------------------------------- - * Type values TclGetNumberFromObj - *---------------------------------------------------------------------- - */ - -#define TCL_NUMBER_INT 2 -#if !defined(TCL_NO_DEPRECATED) -# define TCL_NUMBER_LONG 1 /* deprecated, not used any more */ -# define TCL_NUMBER_WIDE TCL_NUMBER_INT /* deprecated */ -#endif -#define TCL_NUMBER_BIG 3 -#define TCL_NUMBER_DOUBLE 4 -#define TCL_NUMBER_NAN 5 - /* *---------------------------------------------------------------- * Variables shared among Tcl modules but not used by the outside world. *---------------------------------------------------------------- */ @@ -3200,13 +3185,10 @@ MODULE_SCOPE CmdFrame * TclGetCmdFrameForProcedure(Proc *procPtr); MODULE_SCOPE int TclGetCompletionCodeFromObj(Tcl_Interp *interp, Tcl_Obj *value, int *code); MODULE_SCOPE Proc * TclGetLambdaFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Obj **nsObjPtrPtr); -MODULE_SCOPE int TclGetNumberFromObj(Tcl_Interp *interp, - Tcl_Obj *objPtr, void **clientDataPtr, - int *typePtr); MODULE_SCOPE int TclGetOpenModeEx(Tcl_Interp *interp, const char *modeString, int *seekFlagPtr, int *binaryPtr); MODULE_SCOPE Tcl_Obj * TclGetProcessGlobalValue(ProcessGlobalValue *pgvPtr); MODULE_SCOPE Tcl_Obj * TclGetSourceFromFrame(CmdFrame *cfPtr, int objc, Index: generic/tclLink.c ================================================================== --- generic/tclLink.c +++ generic/tclLink.c @@ -528,11 +528,11 @@ { Tcl_WideInt *widePtr = (Tcl_WideInt *) uwidePtr; void *clientData; int type, intValue; - if (TclGetNumberFromObj(NULL, objPtr, &clientData, &type) == TCL_OK) { + if (Tcl_GetNumberFromObj(NULL, objPtr, &clientData, &type) == TCL_OK) { if (type == TCL_NUMBER_INT) { *widePtr = *((const Tcl_WideInt *) clientData); return (*widePtr < 0); } else if (type == TCL_NUMBER_BIG) { mp_int *numPtr = (mp_int *)clientData; Index: generic/tclObj.c ================================================================== --- generic/tclObj.c +++ generic/tclObj.c @@ -3895,11 +3895,11 @@ } /* *---------------------------------------------------------------------- * - * TclGetNumberFromObj -- + * Tcl_GetNumberFromObj -- * * Extracts a number (of any possible numeric type) from an object. * * Results: * Whether the extraction worked. The type is stored in the variable @@ -3913,11 +3913,11 @@ * *---------------------------------------------------------------------- */ int -TclGetNumberFromObj( +Tcl_GetNumberFromObj( Tcl_Interp *interp, Tcl_Obj *objPtr, void **clientDataPtr, int *typePtr) { @@ -3948,10 +3948,46 @@ } } while (TCL_OK == TclParseNumber(interp, objPtr, "number", NULL, -1, NULL, 0)); return TCL_ERROR; } + +int +Tcl_GetNumber( + Tcl_Interp *interp, + const char *bytes, + size_t numBytes, + ClientData *clientDataPtr, + int *typePtr) +{ + static Tcl_ThreadDataKey numberCacheKey; + Tcl_Obj *objPtr = (Tcl_Obj *)Tcl_GetThreadData(&numberCacheKey, + sizeof(Tcl_Obj)); + + Tcl_FreeInternalRep(objPtr); + + if (bytes == NULL) { + bytes = &tclEmptyString; + numBytes = 0; + } + if (numBytes == (size_t)TCL_INDEX_NONE) { + numBytes = strlen(bytes); + } + if (numBytes > INT_MAX) { + if (interp) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "max size for a Tcl value (%d bytes) exceeded", INT_MAX)); + Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); + } + return TCL_ERROR; + } + + objPtr->bytes = (char *) bytes; + objPtr->length = numBytes; + + return Tcl_GetNumberFromObj(interp, objPtr, clientDataPtr, typePtr); +} /* *---------------------------------------------------------------------- * * Tcl_IncrRefCount -- Index: generic/tclStubInit.c ================================================================== --- generic/tclStubInit.c +++ generic/tclStubInit.c @@ -2043,11 +2043,11 @@ Tcl_GetBoolFromObj, /* 675 */ Tcl_CreateObjCommand2, /* 676 */ Tcl_CreateObjTrace2, /* 677 */ Tcl_NRCreateCommand2, /* 678 */ Tcl_NRCallObjProc2, /* 679 */ - 0, /* 680 */ - 0, /* 681 */ + Tcl_GetNumberFromObj, /* 680 */ + Tcl_GetNumber, /* 681 */ Tcl_RemoveChannelMode, /* 682 */ }; /* !END!: Do not edit above this line. */ Index: generic/tclUtil.c ================================================================== --- generic/tclUtil.c +++ generic/tclUtil.c @@ -3646,11 +3646,11 @@ Tcl_WideInt *widePtr) /* Location filled in with a wide integer * representing an index. */ { int numType; void *cd; - int code = TclGetNumberFromObj(NULL, objPtr, &cd, &numType); + int code = Tcl_GetNumberFromObj(NULL, objPtr, &cd, &numType); if (code == TCL_OK) { if (numType == TCL_NUMBER_INT) { /* objPtr holds an integer in the signed wide range */ *widePtr = *(Tcl_WideInt *)cd; @@ -3810,21 +3810,21 @@ if ((*opPtr == '-') || (*opPtr == '+')) { /* ... value continues with [-+] ... */ /* Save first integer as wide if possible */ - TclGetNumberFromObj(NULL, objPtr, &cd, &t1); + Tcl_GetNumberFromObj(NULL, objPtr, &cd, &t1); if (t1 == TCL_NUMBER_INT) { w1 = (*(Tcl_WideInt *)cd); } if (TCL_OK == TclParseNumber(NULL, objPtr, NULL, opPtr + 1, TCL_INDEX_NONE, NULL, TCL_PARSE_INTEGER_ONLY)) { /* ... value concludes with second valid integer */ /* Save second integer as wide if possible */ - TclGetNumberFromObj(NULL, objPtr, &cd, &t2); + Tcl_GetNumberFromObj(NULL, objPtr, &cd, &t2); if (t2 == TCL_NUMBER_INT) { w2 = (*(Tcl_WideInt *)cd); } } } @@ -3873,11 +3873,11 @@ } else { Tcl_Interp *compute = Tcl_CreateInterp(); Tcl_ExprObj(compute, objPtr, &sum); Tcl_DeleteInterp(compute); } - TclGetNumberFromObj(NULL, sum, &cd, &numType); + Tcl_GetNumberFromObj(NULL, sum, &cd, &numType); if (numType == TCL_NUMBER_INT) { /* sum holds an integer in the signed wide range */ offset = *(Tcl_WideInt *)cd; } else { @@ -3924,11 +3924,11 @@ /* Not a recognized integer format */ goto parseError; } /* Got an integer offset; pull it from where parser left it. */ - TclGetNumberFromObj(NULL, objPtr, &cd, &t); + Tcl_GetNumberFromObj(NULL, objPtr, &cd, &t); if (t == TCL_NUMBER_BIG) { /* Truncate to the signed wide range. */ if (mp_isneg((mp_int *)cd)) { offset = (bytes[3] == '-') ? WIDE_MAX : WIDE_MIN;