diff options
author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2023-09-01 12:43:41 (GMT) |
---|---|---|
committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2023-09-01 12:43:41 (GMT) |
commit | 6596a897b03d3e5a8c192481e47251f124cf6a68 (patch) | |
tree | 7d642faf4e7a4c0aa94a572fe98b0f4475579175 /generic/tkObj.c | |
parent | 3d4865351a5e9ec4af6a58463a3d7b02ab9cdab7 (diff) | |
parent | 90b909515c2a6ff8b67618bca674856b7d23182f (diff) | |
download | tk-6596a897b03d3e5a8c192481e47251f124cf6a68.zip tk-6596a897b03d3e5a8c192481e47251f124cf6a68.tar.gz tk-6596a897b03d3e5a8c192481e47251f124cf6a68.tar.bz2 |
Fix [6cc8002951]: numeric parameter errors depending on whether string vs double/int rep
Diffstat (limited to 'generic/tkObj.c')
-rw-r--r-- | generic/tkObj.c | 150 |
1 files changed, 45 insertions, 105 deletions
diff --git a/generic/tkObj.c b/generic/tkObj.c index 0abf534..47a3201 100644 --- a/generic/tkObj.c +++ b/generic/tkObj.c @@ -40,20 +40,6 @@ typedef struct PixelRep { ((PixelRep *) (objPtr)->internalRep.twoPtrValue.ptr2) /* - * One of these structures is created per thread to store thread-specific - * data. In this case, it is used to contain references to selected - * Tcl_ObjTypes that we can use as screen distances without conversion. The - * "dataKey" below is used to locate the ThreadSpecificData for the current - * thread. - */ - -typedef struct { - const Tcl_ObjType *doubleTypePtr; - const Tcl_ObjType *intTypePtr; -} ThreadSpecificData; -static Tcl_ThreadDataKey dataKey; - -/* * The following structure is the internal representation for mm objects. */ @@ -87,7 +73,6 @@ static void DupWindowInternalRep(Tcl_Obj *srcPtr,Tcl_Obj*copyPtr); static void FreeMMInternalRep(Tcl_Obj *objPtr); static void FreePixelInternalRep(Tcl_Obj *objPtr); static void FreeWindowInternalRep(Tcl_Obj *objPtr); -static ThreadSpecificData *GetTypeCache(void); static void UpdateStringOfMM(Tcl_Obj *objPtr); static int SetMMFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static int SetPixelFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); @@ -137,42 +122,6 @@ static const Tcl_ObjType windowObjType = { /* *---------------------------------------------------------------------- * - * GetTypeCache -- - * - * Get (and build if necessary) the cache of useful Tcl object types for - * comparisons in the conversion functions. This allows optimized checks - * for standard cases. - * - *---------------------------------------------------------------------- - */ - -static ThreadSpecificData * -GetTypeCache(void) -{ - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - - if (tsdPtr->doubleTypePtr == NULL) { - /* Smart initialization of doubleTypePtr/intTypePtr without - * hash-table lookup or creating complete Tcl_Obj's */ - Tcl_Obj obj; - obj.length = 3; - obj.bytes = (char *)"0.0"; - obj.typePtr = NULL; - Tcl_GetDoubleFromObj(NULL, &obj, &obj.internalRep.doubleValue); - tsdPtr->doubleTypePtr = obj.typePtr; - obj.bytes += 2; - obj.length = 1; - obj.typePtr = NULL; - Tcl_GetLongFromObj(NULL, &obj, &obj.internalRep.longValue); - tsdPtr->intTypePtr = obj.typePtr; - } - return tsdPtr; -} - -/* - *---------------------------------------------------------------------- - * * GetPixelsFromObjEx -- * * Attempt to return a pixel value from the Tcl object "objPtr". If the @@ -207,29 +156,14 @@ GetPixelsFromObjEx( 1.0, 10.0, 25.4, 0.35278 /*25.4 / 72.0*/ }; - /* - * Special hacks where the type of the object is known to be something - * that is just numeric and cannot require distance conversion. This pokes - * holes in Tcl's abstractions, but they are just for optimization, not - * semantics. - */ - if (objPtr->typePtr != &pixelObjType) { - ThreadSpecificData *typeCache = GetTypeCache(); - if (objPtr->typePtr == typeCache->doubleTypePtr) { - (void) Tcl_GetDoubleFromObj(interp, objPtr, &d); + if (Tcl_GetDoubleFromObj(NULL, objPtr, &d) == TCL_OK) { if (dblPtr != NULL) { *dblPtr = d; } *intPtr = (int) (d<0 ? d-0.5 : d+0.5); return TCL_OK; - } else if (objPtr->typePtr == typeCache->intTypePtr) { - (void) Tcl_GetIntFromObj(interp, objPtr, intPtr); - if (dblPtr) { - *dblPtr = (double) (*intPtr); - } - return TCL_OK; } } @@ -458,36 +392,50 @@ SetPixelFromAny( double d; int i, units; - string = Tcl_GetString(objPtr); + if (Tcl_GetIntFromObj(NULL, objPtr, &units) == TCL_OK) { + d = (double) units; + units = -1; - d = strtod(string, &rest); - if (rest == string) { - goto error; - } - while ((*rest != '\0') && isspace(UCHAR(*rest))) { - rest++; - } + /* + * In the case of ints, we need to ensure that a valid string exists + * in order for int-but-not-string objects to be converted back to + * ints again from pixel obj types. + */ - switch (*rest) { - case '\0': + (void) Tcl_GetString(objPtr); + } else if (Tcl_GetDoubleFromObj(NULL, objPtr, &d) == TCL_OK) { units = -1; - break; - case 'm': - units = 0; - break; - case 'c': - units = 1; - break; - case 'i': - units = 2; - break; - case 'p': - units = 3; - break; - default: - goto error; - } + } else { + string = Tcl_GetString(objPtr); + d = strtod(string, &rest); + if (rest == string) { + goto error; + } + while ((*rest != '\0') && isspace(UCHAR(*rest))) { + rest++; + } + + switch (*rest) { + case '\0': + units = -1; + break; + case 'm': + units = 0; + break; + case 'c': + units = 1; + break; + case 'i': + units = 2; + break; + case 'p': + units = 3; + break; + default: + goto error; + } + } /* * Free the old internalRep before setting the new one. */ @@ -708,19 +656,14 @@ SetMMFromAny( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ Tcl_Obj *objPtr) /* The object to convert. */ { - ThreadSpecificData *typeCache = GetTypeCache(); const Tcl_ObjType *typePtr; - const char *string; + char *string; char *rest; double d; int units; MMRep *mmPtr; - if (objPtr->typePtr == typeCache->doubleTypePtr) { - Tcl_GetDoubleFromObj(interp, objPtr, &d); - units = -1; - } else if (objPtr->typePtr == typeCache->intTypePtr) { - Tcl_GetIntFromObj(interp, objPtr, &units); + if (Tcl_GetIntFromObj(NULL, objPtr, &units) == TCL_OK) { d = (double) units; units = -1; @@ -731,6 +674,8 @@ SetMMFromAny( */ (void) Tcl_GetString(objPtr); + } else if (Tcl_GetDoubleFromObj(NULL, objPtr, &d) == TCL_OK) { + units = -1; } else { /* * It wasn't a known int or double, so parse it. @@ -740,11 +685,6 @@ SetMMFromAny( d = strtod(string, &rest); if (rest == string) { - /* - * Must copy string before resetting the result in case a caller - * is trying to convert the interpreter's result to mms. - */ - error: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad screen distance \"%s\"", string)); |