Import Tcl-code 8.6.8
This commit is contained in:
@@ -67,6 +67,9 @@ typedef struct Link {
|
||||
static char * LinkTraceProc(ClientData clientData,Tcl_Interp *interp,
|
||||
const char *name1, const char *name2, int flags);
|
||||
static Tcl_Obj * ObjValue(Link *linkPtr);
|
||||
static int GetInvalidIntFromObj(Tcl_Obj *objPtr, int *intPtr);
|
||||
static int GetInvalidWideFromObj(Tcl_Obj *objPtr, Tcl_WideInt *widePtr);
|
||||
static int GetInvalidDoubleFromObj(Tcl_Obj *objPtr, double *doublePtr);
|
||||
|
||||
/*
|
||||
* Convenience macro for accessing the value of the C variable pointed to by a
|
||||
@@ -259,7 +262,8 @@ LinkTraceProc(
|
||||
int flags) /* Miscellaneous additional information. */
|
||||
{
|
||||
Link *linkPtr = clientData;
|
||||
int changed, valueLength;
|
||||
int changed;
|
||||
size_t valueLength;
|
||||
const char *value;
|
||||
char **pp;
|
||||
Tcl_Obj *valueObj;
|
||||
@@ -378,8 +382,8 @@ LinkTraceProc(
|
||||
|
||||
switch (linkPtr->type) {
|
||||
case TCL_LINK_INT:
|
||||
if (Tcl_GetIntFromObj(NULL, valueObj, &linkPtr->lastValue.i)
|
||||
!= TCL_OK) {
|
||||
if (Tcl_GetIntFromObj(NULL, valueObj, &linkPtr->lastValue.i) != TCL_OK
|
||||
&& GetInvalidIntFromObj(valueObj, &linkPtr->lastValue.i) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have integer value";
|
||||
@@ -388,8 +392,8 @@ LinkTraceProc(
|
||||
break;
|
||||
|
||||
case TCL_LINK_WIDE_INT:
|
||||
if (Tcl_GetWideIntFromObj(NULL, valueObj, &linkPtr->lastValue.w)
|
||||
!= TCL_OK) {
|
||||
if (Tcl_GetWideIntFromObj(NULL, valueObj, &linkPtr->lastValue.w) != TCL_OK
|
||||
&& GetInvalidWideFromObj(valueObj, &linkPtr->lastValue.w) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have integer value";
|
||||
@@ -398,14 +402,15 @@ LinkTraceProc(
|
||||
break;
|
||||
|
||||
case TCL_LINK_DOUBLE:
|
||||
if (Tcl_GetDoubleFromObj(NULL, valueObj, &linkPtr->lastValue.d)
|
||||
!= TCL_OK) {
|
||||
if (Tcl_GetDoubleFromObj(NULL, valueObj, &linkPtr->lastValue.d) != TCL_OK) {
|
||||
#ifdef ACCEPT_NAN
|
||||
if (valueObj->typePtr != &tclDoubleType) {
|
||||
#endif
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
|
||||
ObjValue(linkPtr), TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have real value";
|
||||
if (GetInvalidDoubleFromObj(valueObj, &linkPtr->lastValue.d) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have real value";
|
||||
}
|
||||
#ifdef ACCEPT_NAN
|
||||
}
|
||||
linkPtr->lastValue.d = valueObj->internalRep.doubleValue;
|
||||
@@ -415,8 +420,7 @@ LinkTraceProc(
|
||||
break;
|
||||
|
||||
case TCL_LINK_BOOLEAN:
|
||||
if (Tcl_GetBooleanFromObj(NULL, valueObj, &linkPtr->lastValue.i)
|
||||
!= TCL_OK) {
|
||||
if (Tcl_GetBooleanFromObj(NULL, valueObj, &linkPtr->lastValue.i) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have boolean value";
|
||||
@@ -425,113 +429,113 @@ LinkTraceProc(
|
||||
break;
|
||||
|
||||
case TCL_LINK_CHAR:
|
||||
if (Tcl_GetIntFromObj(interp, valueObj, &valueInt) != TCL_OK
|
||||
if ((Tcl_GetIntFromObj(NULL, valueObj, &valueInt) != TCL_OK
|
||||
&& GetInvalidIntFromObj(valueObj, &valueInt) != TCL_OK)
|
||||
|| valueInt < SCHAR_MIN || valueInt > SCHAR_MAX) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have char value";
|
||||
}
|
||||
linkPtr->lastValue.c = (char)valueInt;
|
||||
LinkedVar(char) = linkPtr->lastValue.c;
|
||||
LinkedVar(char) = linkPtr->lastValue.c = (char)valueInt;
|
||||
break;
|
||||
|
||||
case TCL_LINK_UCHAR:
|
||||
if (Tcl_GetIntFromObj(interp, valueObj, &valueInt) != TCL_OK
|
||||
if ((Tcl_GetIntFromObj(NULL, valueObj, &valueInt) != TCL_OK
|
||||
&& GetInvalidIntFromObj(valueObj, &valueInt) != TCL_OK)
|
||||
|| valueInt < 0 || valueInt > UCHAR_MAX) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned char value";
|
||||
}
|
||||
linkPtr->lastValue.uc = (unsigned char) valueInt;
|
||||
LinkedVar(unsigned char) = linkPtr->lastValue.uc;
|
||||
LinkedVar(unsigned char) = linkPtr->lastValue.uc = (unsigned char) valueInt;
|
||||
break;
|
||||
|
||||
case TCL_LINK_SHORT:
|
||||
if (Tcl_GetIntFromObj(interp, valueObj, &valueInt) != TCL_OK
|
||||
if ((Tcl_GetIntFromObj(NULL, valueObj, &valueInt) != TCL_OK
|
||||
&& GetInvalidIntFromObj(valueObj, &valueInt) != TCL_OK)
|
||||
|| valueInt < SHRT_MIN || valueInt > SHRT_MAX) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have short value";
|
||||
}
|
||||
linkPtr->lastValue.s = (short)valueInt;
|
||||
LinkedVar(short) = linkPtr->lastValue.s;
|
||||
LinkedVar(short) = linkPtr->lastValue.s = (short)valueInt;
|
||||
break;
|
||||
|
||||
case TCL_LINK_USHORT:
|
||||
if (Tcl_GetIntFromObj(interp, valueObj, &valueInt) != TCL_OK
|
||||
if ((Tcl_GetIntFromObj(NULL, valueObj, &valueInt) != TCL_OK
|
||||
&& GetInvalidIntFromObj(valueObj, &valueInt) != TCL_OK)
|
||||
|| valueInt < 0 || valueInt > USHRT_MAX) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned short value";
|
||||
}
|
||||
linkPtr->lastValue.us = (unsigned short)valueInt;
|
||||
LinkedVar(unsigned short) = linkPtr->lastValue.us;
|
||||
LinkedVar(unsigned short) = linkPtr->lastValue.us = (unsigned short)valueInt;
|
||||
break;
|
||||
|
||||
case TCL_LINK_UINT:
|
||||
if (Tcl_GetWideIntFromObj(interp, valueObj, &valueWide) != TCL_OK
|
||||
if ((Tcl_GetWideIntFromObj(NULL, valueObj, &valueWide) != TCL_OK
|
||||
&& GetInvalidWideFromObj(valueObj, &valueWide) != TCL_OK)
|
||||
|| valueWide < 0 || valueWide > UINT_MAX) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned int value";
|
||||
}
|
||||
linkPtr->lastValue.ui = (unsigned int)valueWide;
|
||||
LinkedVar(unsigned int) = linkPtr->lastValue.ui;
|
||||
LinkedVar(unsigned int) = linkPtr->lastValue.ui = (unsigned int)valueWide;
|
||||
break;
|
||||
|
||||
case TCL_LINK_LONG:
|
||||
if (Tcl_GetWideIntFromObj(interp, valueObj, &valueWide) != TCL_OK
|
||||
if ((Tcl_GetWideIntFromObj(NULL, valueObj, &valueWide) != TCL_OK
|
||||
&& GetInvalidWideFromObj(valueObj, &valueWide) != TCL_OK)
|
||||
|| valueWide < LONG_MIN || valueWide > LONG_MAX) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have long value";
|
||||
}
|
||||
linkPtr->lastValue.l = (long)valueWide;
|
||||
LinkedVar(long) = linkPtr->lastValue.l;
|
||||
LinkedVar(long) = linkPtr->lastValue.l = (long)valueWide;
|
||||
break;
|
||||
|
||||
case TCL_LINK_ULONG:
|
||||
if (Tcl_GetWideIntFromObj(interp, valueObj, &valueWide) != TCL_OK
|
||||
if ((Tcl_GetWideIntFromObj(NULL, valueObj, &valueWide) != TCL_OK
|
||||
&& GetInvalidWideFromObj(valueObj, &valueWide) != TCL_OK)
|
||||
|| valueWide < 0 || (Tcl_WideUInt) valueWide > ULONG_MAX) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned long value";
|
||||
}
|
||||
linkPtr->lastValue.ul = (unsigned long)valueWide;
|
||||
LinkedVar(unsigned long) = linkPtr->lastValue.ul;
|
||||
LinkedVar(unsigned long) = linkPtr->lastValue.ul = (unsigned long)valueWide;
|
||||
break;
|
||||
|
||||
case TCL_LINK_WIDE_UINT:
|
||||
/*
|
||||
* FIXME: represent as a bignum.
|
||||
*/
|
||||
if (Tcl_GetWideIntFromObj(interp, valueObj, &valueWide) != TCL_OK) {
|
||||
if (Tcl_GetWideIntFromObj(NULL, valueObj, &valueWide) != TCL_OK
|
||||
&& GetInvalidWideFromObj(valueObj, &valueWide) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned wide int value";
|
||||
}
|
||||
linkPtr->lastValue.uw = (Tcl_WideUInt)valueWide;
|
||||
LinkedVar(Tcl_WideUInt) = linkPtr->lastValue.uw;
|
||||
LinkedVar(Tcl_WideUInt) = linkPtr->lastValue.uw = (Tcl_WideUInt)valueWide;
|
||||
break;
|
||||
|
||||
case TCL_LINK_FLOAT:
|
||||
if (Tcl_GetDoubleFromObj(interp, valueObj, &valueDouble) != TCL_OK
|
||||
if ((Tcl_GetDoubleFromObj(NULL, valueObj, &valueDouble) != TCL_OK
|
||||
&& GetInvalidDoubleFromObj(valueObj, &valueDouble) != TCL_OK)
|
||||
|| valueDouble < -FLT_MAX || valueDouble > FLT_MAX) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have float value";
|
||||
}
|
||||
linkPtr->lastValue.f = (float)valueDouble;
|
||||
LinkedVar(float) = linkPtr->lastValue.f;
|
||||
LinkedVar(float) = linkPtr->lastValue.f = (float)valueDouble;
|
||||
break;
|
||||
|
||||
case TCL_LINK_STRING:
|
||||
value = Tcl_GetStringFromObj(valueObj, &valueLength);
|
||||
valueLength++;
|
||||
value = TclGetString(valueObj);
|
||||
valueLength = valueObj->length + 1;
|
||||
pp = (char **) linkPtr->addr;
|
||||
|
||||
*pp = ckrealloc(*pp, valueLength);
|
||||
memcpy(*pp, value, (unsigned) valueLength);
|
||||
memcpy(*pp, value, valueLength);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -626,6 +630,111 @@ ObjValue(
|
||||
return resultObj;
|
||||
}
|
||||
}
|
||||
|
||||
static int SetInvalidRealFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
|
||||
|
||||
static Tcl_ObjType invalidRealType = {
|
||||
"invalidReal", /* name */
|
||||
NULL, /* freeIntRepProc */
|
||||
NULL, /* dupIntRepProc */
|
||||
NULL, /* updateStringProc */
|
||||
NULL /* setFromAnyProc */
|
||||
};
|
||||
|
||||
static int
|
||||
SetInvalidRealFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr) {
|
||||
int length;
|
||||
const char *str;
|
||||
const char *endPtr;
|
||||
|
||||
str = TclGetStringFromObj(objPtr, &length);
|
||||
if ((length == 1) && (str[0] == '.')){
|
||||
objPtr->typePtr = &invalidRealType;
|
||||
objPtr->internalRep.doubleValue = 0.0;
|
||||
return TCL_OK;
|
||||
}
|
||||
if (TclParseNumber(NULL, objPtr, NULL, str, length, &endPtr,
|
||||
TCL_PARSE_DECIMAL_ONLY) == TCL_OK) {
|
||||
/* If number is followed by [eE][+-]?, then it is an invalid
|
||||
* double, but it could be the start of a valid double. */
|
||||
if (*endPtr == 'e' || *endPtr == 'E') {
|
||||
++endPtr;
|
||||
if (*endPtr == '+' || *endPtr == '-') ++endPtr;
|
||||
if (*endPtr == 0) {
|
||||
double doubleValue = 0.0;
|
||||
Tcl_GetDoubleFromObj(NULL, objPtr, &doubleValue);
|
||||
if (objPtr->typePtr->freeIntRepProc) objPtr->typePtr->freeIntRepProc(objPtr);
|
||||
objPtr->typePtr = &invalidRealType;
|
||||
objPtr->internalRep.doubleValue = doubleValue;
|
||||
return TCL_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function checks for integer representations, which are valid
|
||||
* when linking with C variables, but which are invalid in other
|
||||
* contexts in Tcl. Handled are "+", "-", "", "0x", "0b" and "0o"
|
||||
* (upperand lowercase). See bug [39f6304c2e].
|
||||
*/
|
||||
int
|
||||
GetInvalidIntFromObj(Tcl_Obj *objPtr,
|
||||
int *intPtr)
|
||||
{
|
||||
const char *str = TclGetString(objPtr);
|
||||
|
||||
if ((objPtr->length == 0) ||
|
||||
((objPtr->length == 2) && (str[0] == '0') && strchr("xXbBoO", str[1]))) {
|
||||
*intPtr = 0;
|
||||
return TCL_OK;
|
||||
} else if ((objPtr->length == 1) && strchr("+-", str[0])) {
|
||||
*intPtr = (str[0] == '+');
|
||||
return TCL_OK;
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
int
|
||||
GetInvalidWideFromObj(Tcl_Obj *objPtr, Tcl_WideInt *widePtr)
|
||||
{
|
||||
int intValue;
|
||||
|
||||
if (GetInvalidIntFromObj(objPtr, &intValue) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
*widePtr = intValue;
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function checks for double representations, which are valid
|
||||
* when linking with C variables, but which are invalid in other
|
||||
* contexts in Tcl. Handled are "+", "-", "", ".", "0x", "0b" and "0o"
|
||||
* (upper- and lowercase) and sequences like "1e-". See bug [39f6304c2e].
|
||||
*/
|
||||
int
|
||||
GetInvalidDoubleFromObj(Tcl_Obj *objPtr,
|
||||
double *doublePtr)
|
||||
{
|
||||
int intValue;
|
||||
|
||||
if (objPtr->typePtr == &invalidRealType) {
|
||||
goto gotdouble;
|
||||
}
|
||||
if (GetInvalidIntFromObj(objPtr, &intValue) == TCL_OK) {
|
||||
*doublePtr = (double) intValue;
|
||||
return TCL_OK;
|
||||
}
|
||||
if (SetInvalidRealFromAny(NULL, objPtr) == TCL_OK) {
|
||||
gotdouble:
|
||||
*doublePtr = objPtr->internalRep.doubleValue;
|
||||
return TCL_OK;
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
|
||||
Reference in New Issue
Block a user