summaryrefslogtreecommitdiffstats
path: root/generic/tclLink.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclLink.c')
-rw-r--r--generic/tclLink.c1265
1 files changed, 199 insertions, 1066 deletions
diff --git a/generic/tclLink.c b/generic/tclLink.c
index 6a5e73a..f7911a4 100644
--- a/generic/tclLink.c
+++ b/generic/tclLink.c
@@ -6,18 +6,14 @@
* Andreas Stolcke and this implementation is based heavily on a
* prototype implementation provided by him.
*
- * Copyright © 1993 The Regents of the University of California.
- * Copyright © 1994-1997 Sun Microsystems, Inc.
- * Copyright © 2008 Rene Zaumseil
- * Copyright © 2019 Donal K. Fellows
+ * Copyright (c) 1993 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclTomMath.h"
-#include <math.h>
/*
* For each linked variable there is a data structure of the following type,
@@ -27,17 +23,11 @@
typedef struct Link {
Tcl_Interp *interp; /* Interpreter containing Tcl variable. */
- Namespace *nsPtr; /* Namespace containing Tcl variable */
Tcl_Obj *varName; /* Name of variable (must be global). This is
* needed during trace callbacks, since the
* actual variable may be aliased at that time
* via upvar. */
- void *addr; /* Location of C variable. */
- int bytes; /* Size of C variable array. This is 0 when
- * single variables, and >0 used for array
- * variables. */
- int numElems; /* Number of elements in C variable array.
- * Zero for single variables. */
+ char *addr; /* Location of C variable. */
int type; /* Type of link (TCL_LINK_INT, etc.). */
union {
char c;
@@ -46,27 +36,12 @@ typedef struct Link {
unsigned int ui;
short s;
unsigned short us;
-#if !defined(TCL_WIDE_INT_IS_LONG) && !defined(_WIN32) && !defined(__CYGWIN__)
long l;
unsigned long ul;
-#endif
Tcl_WideInt w;
Tcl_WideUInt uw;
float f;
double d;
- void *aryPtr; /* Generic array. */
- char *cPtr; /* char array */
- unsigned char *ucPtr; /* unsigned char array */
- short *sPtr; /* short array */
- unsigned short *usPtr; /* unsigned short array */
- int *iPtr; /* int array */
- unsigned int *uiPtr; /* unsigned int array */
- long *lPtr; /* long array */
- unsigned long *ulPtr; /* unsigned long array */
- Tcl_WideInt *wPtr; /* wide (long long) array */
- Tcl_WideUInt *uwPtr; /* unsigned wide (long long) array */
- float *fPtr; /* float array */
- double *dPtr; /* double array */
} lastValue; /* Last known value of C variable; used to
* avoid string conversions. */
int flags; /* Miscellaneous one-bit values; see below for
@@ -80,42 +55,18 @@ typedef struct Link {
* LINK_BEING_UPDATED - 1 means that a call to Tcl_UpdateLinkedVar is
* in progress for this variable, so trace
* callbacks on the variable should be ignored.
- * LINK_ALLOC_ADDR - 1 means linkPtr->addr was allocated on the
- * heap.
- * LINK_ALLOC_LAST - 1 means linkPtr->valueLast.p was allocated on
- * the heap.
*/
#define LINK_READ_ONLY 1
#define LINK_BEING_UPDATED 2
-#define LINK_ALLOC_ADDR 4
-#define LINK_ALLOC_LAST 8
/*
* Forward references to functions defined later in this file:
*/
-static char * LinkTraceProc(void *clientData,Tcl_Interp *interp,
- const char *name1, const char *name2, int flags);
+static char * LinkTraceProc(ClientData clientData,Tcl_Interp *interp,
+ CONST char *name1, CONST char *name2, int flags);
static Tcl_Obj * ObjValue(Link *linkPtr);
-static void LinkFree(Link *linkPtr);
-static int GetInvalidIntFromObj(Tcl_Obj *objPtr, int *intPtr);
-static int GetInvalidDoubleFromObj(Tcl_Obj *objPtr,
- double *doublePtr);
-static int SetInvalidRealFromAny(Tcl_Interp *interp,
- Tcl_Obj *objPtr);
-
-/*
- * A marker type used to flag weirdnesses so we can pass them around right.
- */
-
-static Tcl_ObjType invalidRealType = {
- "invalidReal", /* name */
- NULL, /* freeIntRepProc */
- NULL, /* dupIntRepProc */
- NULL, /* updateStringProc */
- NULL /* setFromAnyProc */
-};
/*
* Convenience macro for accessing the value of the C variable pointed to by a
@@ -151,255 +102,48 @@ static Tcl_ObjType invalidRealType = {
int
Tcl_LinkVar(
Tcl_Interp *interp, /* Interpreter in which varName exists. */
- const char *varName, /* Name of a global variable in interp. */
- void *addr, /* Address of a C variable to be linked to
+ CONST char *varName, /* Name of a global variable in interp. */
+ char *addr, /* Address of a C variable to be linked to
* varName. */
int type) /* Type of C variable: TCL_LINK_INT, etc. Also
* may have TCL_LINK_READ_ONLY OR'ed in. */
{
Tcl_Obj *objPtr;
Link *linkPtr;
- Namespace *dummy;
- const char *name;
int code;
- linkPtr = (Link *) Tcl_VarTraceInfo2(interp, varName, NULL,
- TCL_GLOBAL_ONLY, LinkTraceProc, NULL);
+ linkPtr = (Link *) Tcl_VarTraceInfo(interp, varName, TCL_GLOBAL_ONLY,
+ LinkTraceProc, (ClientData) NULL);
if (linkPtr != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"variable '%s' is already linked", varName));
return TCL_ERROR;
}
- linkPtr = (Link *)ckalloc(sizeof(Link));
+ linkPtr = (Link *) ckalloc(sizeof(Link));
linkPtr->interp = interp;
- linkPtr->nsPtr = NULL;
linkPtr->varName = Tcl_NewStringObj(varName, -1);
Tcl_IncrRefCount(linkPtr->varName);
linkPtr->addr = addr;
linkPtr->type = type & ~TCL_LINK_READ_ONLY;
-#if !defined(TCL_NO_DEPRECATED) && (defined(TCL_WIDE_INT_IS_LONG) \
- || defined(_WIN32) || defined(__CYGWIN__))
- if (linkPtr->type == 11 /* legacy TCL_LINK_LONG */) {
- linkPtr->type = TCL_LINK_LONG;
- } else if (linkPtr->type == 12 /* legacy TCL_LINK_ULONG */) {
- linkPtr->type = TCL_LINK_ULONG;
- }
-#endif
- if (type & TCL_LINK_READ_ONLY) {
- linkPtr->flags = LINK_READ_ONLY;
- } else {
- linkPtr->flags = 0;
- }
- linkPtr->bytes = 0;
- linkPtr->numElems = 0;
- objPtr = ObjValue(linkPtr);
- if (Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, objPtr,
- TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
- Tcl_DecrRefCount(linkPtr->varName);
- LinkFree(linkPtr);
- return TCL_ERROR;
- }
-
- TclGetNamespaceForQualName(interp, varName, NULL, TCL_GLOBAL_ONLY,
- &(linkPtr->nsPtr), &dummy, &dummy, &name);
- linkPtr->nsPtr->refCount++;
-
- code = Tcl_TraceVar2(interp, varName, NULL,
- TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- LinkTraceProc, linkPtr);
- if (code != TCL_OK) {
- Tcl_DecrRefCount(linkPtr->varName);
- LinkFree(linkPtr);
- }
- return code;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_LinkArray --
- *
- * Link a C variable array to a Tcl variable so that changes to either
- * one causes the other to change.
- *
- * Results:
- * The return value is TCL_OK if everything went well or TCL_ERROR if an
- * error occurred (the interp's result is also set after errors).
- *
- * Side effects:
- * The value at *addr is linked to the Tcl variable "varName", using
- * "type" to convert between string values for Tcl and binary values for
- * *addr.
- *
- *----------------------------------------------------------------------
- */
-
-int
-Tcl_LinkArray(
- Tcl_Interp *interp, /* Interpreter in which varName exists. */
- const char *varName, /* Name of a global variable in interp. */
- void *addr, /* Address of a C variable to be linked to
- * varName. If NULL then the necessary space
- * will be allocated and returned as the
- * interpreter result. */
- int type, /* Type of C variable: TCL_LINK_INT, etc. Also
- * may have TCL_LINK_READ_ONLY OR'ed in. */
- int size) /* Size of C variable array, >1 if array */
-{
- Tcl_Obj *objPtr;
- Link *linkPtr;
- Namespace *dummy;
- const char *name;
- int code;
-
- if (size < 1) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "wrong array size given", -1));
- return TCL_ERROR;
- }
-
- linkPtr = (Link *)ckalloc(sizeof(Link));
- linkPtr->type = type & ~TCL_LINK_READ_ONLY;
-#if !defined(TCL_NO_DEPRECATED) && (defined(TCL_WIDE_INT_IS_LONG) \
- || defined(_WIN32) || defined(__CYGWIN__))
- if (linkPtr->type == 11 /* legacy TCL_LINK_LONG */) {
- linkPtr->type = TCL_LINK_LONG;
- } else if (linkPtr->type == 12 /* legacy TCL_LINK_ULONG */) {
- linkPtr->type = TCL_LINK_ULONG;
- }
-#endif
- linkPtr->numElems = size;
if (type & TCL_LINK_READ_ONLY) {
linkPtr->flags = LINK_READ_ONLY;
} else {
linkPtr->flags = 0;
}
-
- switch (linkPtr->type) {
- case TCL_LINK_INT:
- case TCL_LINK_BOOLEAN:
- linkPtr->bytes = size * sizeof(int);
- break;
- case TCL_LINK_DOUBLE:
- linkPtr->bytes = size * sizeof(double);
- break;
- case TCL_LINK_WIDE_INT:
- linkPtr->bytes = size * sizeof(Tcl_WideInt);
- break;
- case TCL_LINK_WIDE_UINT:
- linkPtr->bytes = size * sizeof(Tcl_WideUInt);
- break;
- case TCL_LINK_CHAR:
- linkPtr->bytes = size * sizeof(char);
- break;
- case TCL_LINK_UCHAR:
- linkPtr->bytes = size * sizeof(unsigned char);
- break;
- case TCL_LINK_SHORT:
- linkPtr->bytes = size * sizeof(short);
- break;
- case TCL_LINK_USHORT:
- linkPtr->bytes = size * sizeof(unsigned short);
- break;
- case TCL_LINK_UINT:
- linkPtr->bytes = size * sizeof(unsigned int);
- break;
-#if !defined(TCL_WIDE_INT_IS_LONG) && !defined(_WIN32) && !defined(__CYGWIN__)
- case TCL_LINK_LONG:
- linkPtr->bytes = size * sizeof(long);
- break;
- case TCL_LINK_ULONG:
- linkPtr->bytes = size * sizeof(unsigned long);
- break;
-#endif
- case TCL_LINK_FLOAT:
- linkPtr->bytes = size * sizeof(float);
- break;
- case TCL_LINK_STRING:
- linkPtr->bytes = size * sizeof(char);
- size = 1; /* This is a variable length string, no need
- * to check last value. */
-
- /*
- * If no address is given create one and use as address the
- * not needed linkPtr->lastValue
- */
-
- if (addr == NULL) {
- linkPtr->lastValue.aryPtr = ckalloc(linkPtr->bytes);
- linkPtr->flags |= LINK_ALLOC_LAST;
- addr = (char *) &linkPtr->lastValue.cPtr;
- }
- break;
- case TCL_LINK_CHARS:
- case TCL_LINK_BINARY:
- linkPtr->bytes = size * sizeof(char);
- break;
- default:
- LinkFree(linkPtr);
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "bad linked array variable type", -1));
- return TCL_ERROR;
- }
-
- /*
- * Allocate C variable space in case no address is given
- */
-
- if (addr == NULL) {
- linkPtr->addr = ckalloc(linkPtr->bytes);
- linkPtr->flags |= LINK_ALLOC_ADDR;
- } else {
- linkPtr->addr = addr;
- }
-
- /*
- * If necessary create space for last used value.
- */
-
- if (size > 1) {
- linkPtr->lastValue.aryPtr = ckalloc(linkPtr->bytes);
- linkPtr->flags |= LINK_ALLOC_LAST;
- }
-
- /*
- * Initialize allocated space.
- */
-
- if (linkPtr->flags & LINK_ALLOC_ADDR) {
- memset(linkPtr->addr, 0, linkPtr->bytes);
- }
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- memset(linkPtr->lastValue.aryPtr, 0, linkPtr->bytes);
- }
-
- /*
- * Set common structure values.
- */
-
- linkPtr->interp = interp;
- linkPtr->varName = Tcl_NewStringObj(varName, -1);
- Tcl_IncrRefCount(linkPtr->varName);
-
- TclGetNamespaceForQualName(interp, varName, NULL, TCL_GLOBAL_ONLY,
- &(linkPtr->nsPtr), &dummy, &dummy, &name);
- linkPtr->nsPtr->refCount++;
-
objPtr = ObjValue(linkPtr);
if (Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, objPtr,
TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
Tcl_DecrRefCount(linkPtr->varName);
- LinkFree(linkPtr);
+ ckfree((char *) linkPtr);
return TCL_ERROR;
}
-
- code = Tcl_TraceVar2(interp, varName, NULL,
- TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- LinkTraceProc, linkPtr);
+ code = Tcl_TraceVar(interp, varName, TCL_GLOBAL_ONLY|TCL_TRACE_READS
+ |TCL_TRACE_WRITES|TCL_TRACE_UNSETS, LinkTraceProc,
+ (ClientData) linkPtr);
if (code != TCL_OK) {
Tcl_DecrRefCount(linkPtr->varName);
- LinkFree(linkPtr);
+ ckfree((char *) linkPtr);
}
return code;
}
@@ -425,19 +169,20 @@ Tcl_LinkArray(
void
Tcl_UnlinkVar(
Tcl_Interp *interp, /* Interpreter containing variable to unlink */
- const char *varName) /* Global variable in interp to unlink. */
+ CONST char *varName) /* Global variable in interp to unlink. */
{
- Link *linkPtr = (Link *) Tcl_VarTraceInfo2(interp, varName, NULL,
- TCL_GLOBAL_ONLY, LinkTraceProc, NULL);
+ Link *linkPtr;
+ linkPtr = (Link *) Tcl_VarTraceInfo(interp, varName, TCL_GLOBAL_ONLY,
+ LinkTraceProc, (ClientData) NULL);
if (linkPtr == NULL) {
return;
}
- Tcl_UntraceVar2(interp, varName, NULL,
+ Tcl_UntraceVar(interp, varName,
TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- LinkTraceProc, linkPtr);
+ LinkTraceProc, (ClientData) linkPtr);
Tcl_DecrRefCount(linkPtr->varName);
- LinkFree(linkPtr);
+ ckfree((char *) linkPtr);
}
/*
@@ -462,12 +207,13 @@ Tcl_UnlinkVar(
void
Tcl_UpdateLinkedVar(
Tcl_Interp *interp, /* Interpreter containing variable. */
- const char *varName) /* Name of global variable that is linked. */
+ CONST char *varName) /* Name of global variable that is linked. */
{
- Link *linkPtr = (Link *) Tcl_VarTraceInfo2(interp, varName, NULL,
- TCL_GLOBAL_ONLY, LinkTraceProc, NULL);
+ Link *linkPtr;
int savedFlag;
+ linkPtr = (Link *) Tcl_VarTraceInfo(interp, varName, TCL_GLOBAL_ONLY,
+ LinkTraceProc, (ClientData) NULL);
if (linkPtr == NULL) {
return;
}
@@ -478,8 +224,8 @@ Tcl_UpdateLinkedVar(
/*
* Callback may have unlinked the variable. [Bug 1740631]
*/
- linkPtr = (Link *) Tcl_VarTraceInfo2(interp, varName, NULL,
- TCL_GLOBAL_ONLY, LinkTraceProc, NULL);
+ linkPtr = (Link *) Tcl_VarTraceInfo(interp, varName, TCL_GLOBAL_ONLY,
+ LinkTraceProc, (ClientData) NULL);
if (linkPtr != NULL) {
linkPtr->flags = (linkPtr->flags & ~LINK_BEING_UPDATED) | savedFlag;
}
@@ -488,201 +234,6 @@ Tcl_UpdateLinkedVar(
/*
*----------------------------------------------------------------------
*
- * GetInt, GetWide, GetUWide, GetDouble, EqualDouble, IsSpecial --
- *
- * Helper functions for LinkTraceProc and ObjValue. These are all
- * factored out here to make those functions simpler.
- *
- *----------------------------------------------------------------------
- */
-
-static inline int
-GetInt(
- Tcl_Obj *objPtr,
- int *intPtr)
-{
- return (Tcl_GetIntFromObj(NULL, objPtr, intPtr) != TCL_OK
- && GetInvalidIntFromObj(objPtr, intPtr) != TCL_OK);
-}
-
-static inline int
-GetWide(
- Tcl_Obj *objPtr,
- Tcl_WideInt *widePtr)
-{
- if (Tcl_GetWideIntFromObj(NULL, objPtr, widePtr) != TCL_OK) {
- int intValue;
-
- if (GetInvalidIntFromObj(objPtr, &intValue) != TCL_OK) {
- return 1;
- }
- *widePtr = intValue;
- }
- return 0;
-}
-
-static inline int
-GetUWide(
- Tcl_Obj *objPtr,
- Tcl_WideUInt *uwidePtr)
-{
- if (Tcl_GetWideUIntFromObj(NULL, objPtr, uwidePtr) != TCL_OK) {
- int intValue;
-
- if (GetInvalidIntFromObj(objPtr, &intValue) != TCL_OK) {
- return 1;
- }
- *uwidePtr = intValue;
- }
- return 0;
-}
-
-static inline int
-GetDouble(
- Tcl_Obj *objPtr,
- double *dblPtr)
-{
- if (Tcl_GetDoubleFromObj(NULL, objPtr, dblPtr) == TCL_OK) {
- return 0;
- } else {
-#ifdef ACCEPT_NAN
- Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objPtr, &tclDoubleType);
-
- if (irPtr != NULL) {
- *dblPtr = irPtr->doubleValue;
- return 0;
- }
-#endif /* ACCEPT_NAN */
- return GetInvalidDoubleFromObj(objPtr, dblPtr) != TCL_OK;
- }
-}
-
-static inline int
-EqualDouble(
- double a,
- double b)
-{
- return (a == b)
-#ifdef ACCEPT_NAN
- || (isnan(a) && isnan(b))
-#endif /* ACCEPT_NAN */
- ;
-}
-
-static inline int
-IsSpecial(
- double a)
-{
- return isinf(a)
-#ifdef ACCEPT_NAN
- || isnan(a)
-#endif /* ACCEPT_NAN */
- ;
-}
-
-/*
- * Mark an object as holding a weird double.
- */
-
-static int
-SetInvalidRealFromAny(
- TCL_UNUSED(Tcl_Interp *),
- Tcl_Obj *objPtr)
-{
- const char *str;
- const char *endPtr;
- int length;
-
- 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);
- TclFreeInternalRep(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", "0d" and "0o"
- * (upperand lowercase). See bug [39f6304c2e].
- */
-
-static int
-GetInvalidIntFromObj(
- Tcl_Obj *objPtr,
- int *intPtr)
-{
- int length;
- const char *str = TclGetStringFromObj(objPtr, &length);
-
- if ((length == 0) || ((length == 2) && (str[0] == '0')
- && strchr("xXbBoOdD", str[1]))) {
- *intPtr = 0;
- return TCL_OK;
- } else if ((length == 1) && strchr("+-", str[0])) {
- *intPtr = (str[0] == '+');
- return TCL_OK;
- }
- return TCL_ERROR;
-}
-
-/*
- * 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].
- */
-
-static int
-GetInvalidDoubleFromObj(
- Tcl_Obj *objPtr,
- double *doublePtr)
-{
- int intValue;
-
- if (TclHasInternalRep(objPtr, &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;
-}
-
-/*
- *----------------------------------------------------------------------
- *
* LinkTraceProc --
*
* This function is invoked when a linked Tcl variable is read, written,
@@ -703,28 +254,20 @@ GetInvalidDoubleFromObj(
static char *
LinkTraceProc(
- void *clientData, /* Contains information about the link. */
+ ClientData clientData, /* Contains information about the link. */
Tcl_Interp *interp, /* Interpreter containing Tcl variable. */
- TCL_UNUSED(const char *) /*name1*/,
- TCL_UNUSED(const char *) /*name2*/,
- /* Links can only be made to global variables,
- * so we can find them with need to resolve
- * caller-supplied name in caller context. */
+ CONST char *name1, /* First part of variable name. */
+ CONST char *name2, /* Second part of variable name. */
int flags) /* Miscellaneous additional information. */
{
- Link *linkPtr = (Link *)clientData;
- int changed;
- int valueLength;
- const char *value;
+ Link *linkPtr = (Link *) clientData;
+ int changed, valueLength;
+ CONST char *value;
char **pp;
Tcl_Obj *valueObj;
int valueInt;
Tcl_WideInt valueWide;
- Tcl_WideUInt valueUWide;
double valueDouble;
- int objc;
- Tcl_Obj **objv;
- int i;
/*
* If the variable is being unset, then just re-create it (with a trace)
@@ -732,15 +275,15 @@ LinkTraceProc(
*/
if (flags & TCL_TRACE_UNSETS) {
- if (Tcl_InterpDeleted(interp) || TclNamespaceDeleted(linkPtr->nsPtr)) {
+ if (Tcl_InterpDeleted(interp)) {
Tcl_DecrRefCount(linkPtr->varName);
- LinkFree(linkPtr);
+ ckfree((char *) linkPtr);
} else if (flags & TCL_TRACE_DESTROYED) {
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
TCL_GLOBAL_ONLY);
- Tcl_TraceVar2(interp, Tcl_GetString(linkPtr->varName), NULL,
+ Tcl_TraceVar(interp, Tcl_GetString(linkPtr->varName),
TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES
- |TCL_TRACE_UNSETS, LinkTraceProc, linkPtr);
+ |TCL_TRACE_UNSETS, LinkTraceProc, (ClientData) linkPtr);
}
return NULL;
}
@@ -761,64 +304,49 @@ LinkTraceProc(
*/
if (flags & TCL_TRACE_READS) {
- /*
- * Variable arrays
- */
-
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- changed = memcmp(linkPtr->addr, linkPtr->lastValue.aryPtr,
- linkPtr->bytes);
- } else {
- /* single variables */
- switch (linkPtr->type) {
- case TCL_LINK_INT:
- case TCL_LINK_BOOLEAN:
- changed = (LinkedVar(int) != linkPtr->lastValue.i);
- break;
- case TCL_LINK_DOUBLE:
- changed = !EqualDouble(LinkedVar(double), linkPtr->lastValue.d);
- break;
- case TCL_LINK_WIDE_INT:
- changed = (LinkedVar(Tcl_WideInt) != linkPtr->lastValue.w);
- break;
- case TCL_LINK_WIDE_UINT:
- changed = (LinkedVar(Tcl_WideUInt) != linkPtr->lastValue.uw);
- break;
- case TCL_LINK_CHAR:
- changed = (LinkedVar(char) != linkPtr->lastValue.c);
- break;
- case TCL_LINK_UCHAR:
- changed = (LinkedVar(unsigned char) != linkPtr->lastValue.uc);
- break;
- case TCL_LINK_SHORT:
- changed = (LinkedVar(short) != linkPtr->lastValue.s);
- break;
- case TCL_LINK_USHORT:
- changed = (LinkedVar(unsigned short) != linkPtr->lastValue.us);
- break;
- case TCL_LINK_UINT:
- changed = (LinkedVar(unsigned int) != linkPtr->lastValue.ui);
- break;
-#if !defined(TCL_WIDE_INT_IS_LONG) && !defined(_WIN32) && !defined(__CYGWIN__)
- case TCL_LINK_LONG:
- changed = (LinkedVar(long) != linkPtr->lastValue.l);
- break;
- case TCL_LINK_ULONG:
- changed = (LinkedVar(unsigned long) != linkPtr->lastValue.ul);
- break;
-#endif
- case TCL_LINK_FLOAT:
- changed = !EqualDouble(LinkedVar(float), linkPtr->lastValue.f);
- break;
- case TCL_LINK_STRING:
- case TCL_LINK_CHARS:
- case TCL_LINK_BINARY:
- changed = 1;
- break;
- default:
- changed = 0;
- /* return (char *) "internal error: bad linked variable type"; */
- }
+ switch (linkPtr->type) {
+ case TCL_LINK_INT:
+ case TCL_LINK_BOOLEAN:
+ changed = (LinkedVar(int) != linkPtr->lastValue.i);
+ break;
+ case TCL_LINK_DOUBLE:
+ changed = (LinkedVar(double) != linkPtr->lastValue.d);
+ break;
+ case TCL_LINK_WIDE_INT:
+ changed = (LinkedVar(Tcl_WideInt) != linkPtr->lastValue.w);
+ break;
+ case TCL_LINK_WIDE_UINT:
+ changed = (LinkedVar(Tcl_WideUInt) != linkPtr->lastValue.uw);
+ break;
+ case TCL_LINK_CHAR:
+ changed = (LinkedVar(char) != linkPtr->lastValue.c);
+ break;
+ case TCL_LINK_UCHAR:
+ changed = (LinkedVar(unsigned char) != linkPtr->lastValue.uc);
+ break;
+ case TCL_LINK_SHORT:
+ changed = (LinkedVar(short) != linkPtr->lastValue.s);
+ break;
+ case TCL_LINK_USHORT:
+ changed = (LinkedVar(unsigned short) != linkPtr->lastValue.us);
+ break;
+ case TCL_LINK_UINT:
+ changed = (LinkedVar(unsigned int) != linkPtr->lastValue.ui);
+ break;
+ case TCL_LINK_LONG:
+ changed = (LinkedVar(long) != linkPtr->lastValue.l);
+ break;
+ case TCL_LINK_ULONG:
+ changed = (LinkedVar(unsigned long) != linkPtr->lastValue.ul);
+ break;
+ case TCL_LINK_FLOAT:
+ changed = (LinkedVar(float) != linkPtr->lastValue.f);
+ break;
+ case TCL_LINK_STRING:
+ changed = 1;
+ break;
+ default:
+ return "internal error: bad linked variable type";
}
if (changed) {
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
@@ -830,7 +358,7 @@ LinkTraceProc(
/*
* For writes, first make sure that the variable is writable. Then convert
* the Tcl value to C if possible. If the variable isn't writable or can't
- * be converted, then restore the variable's old value and return an
+ * be converted, then restore the varaible's old value and return an
* error. Another tricky thing: we have to save and restore the interp's
* result, since the variable access could occur when the result has been
* partially set.
@@ -839,7 +367,7 @@ LinkTraceProc(
if (linkPtr->flags & LINK_READ_ONLY) {
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
TCL_GLOBAL_ONLY);
- return (char *) "linked variable is read-only";
+ return "linked variable is read-only";
}
valueObj = Tcl_ObjGetVar2(interp, linkPtr->varName,NULL, TCL_GLOBAL_ONLY);
if (valueObj == NULL) {
@@ -847,379 +375,169 @@ LinkTraceProc(
* This shouldn't ever happen.
*/
- return (char *) "internal error: linked variable couldn't be read";
- }
-
- /*
- * Special cases.
- */
-
- switch (linkPtr->type) {
- case TCL_LINK_STRING:
- value = TclGetStringFromObj(valueObj, &valueLength);
- valueLength++; /* include end of string char */
- pp = (char **) linkPtr->addr;
-
- *pp = (char *)ckrealloc(*pp, valueLength);
- memcpy(*pp, value, valueLength);
- return NULL;
-
- case TCL_LINK_CHARS:
- value = (char *) TclGetStringFromObj(valueObj, &valueLength);
- valueLength++; /* include end of string char */
- if (valueLength > linkPtr->bytes) {
- return (char *) "wrong size of char* value";
- }
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- memcpy(linkPtr->lastValue.aryPtr, value, valueLength);
- memcpy(linkPtr->addr, value, valueLength);
- } else {
- linkPtr->lastValue.c = '\0';
- LinkedVar(char) = linkPtr->lastValue.c;
- }
- return NULL;
-
- case TCL_LINK_BINARY:
- value = (char *) Tcl_GetByteArrayFromObj(valueObj, &valueLength);
- if (valueLength != linkPtr->bytes) {
- return (char *) "wrong size of binary value";
- }
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- memcpy(linkPtr->lastValue.aryPtr, value, valueLength);
- memcpy(linkPtr->addr, value, valueLength);
- } else {
- linkPtr->lastValue.uc = (unsigned char) *value;
- LinkedVar(unsigned char) = linkPtr->lastValue.uc;
- }
- return NULL;
- }
-
- /*
- * A helper macro. Writing this as a function is messy because of type
- * variance.
- */
-
-#define InRange(lowerLimit, value, upperLimit) \
- ((value) >= (lowerLimit) && (value) <= (upperLimit))
-
- /*
- * If we're working with an array of numbers, extract the Tcl list.
- */
-
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- if (TclListObjGetElements(NULL, (valueObj), &objc, &objv) == TCL_ERROR
- || objc != linkPtr->numElems) {
- return (char *) "wrong dimension";
- }
+ return "internal error: linked variable couldn't be read";
}
switch (linkPtr->type) {
case TCL_LINK_INT:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- for (i=0; i < objc; i++) {
- int *varPtr = &linkPtr->lastValue.iPtr[i];
-
- if (GetInt(objv[i], varPtr)) {
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
- ObjValue(linkPtr), TCL_GLOBAL_ONLY);
- return (char *) "variable array must have integer values";
- }
- }
- } else {
- int *varPtr = &linkPtr->lastValue.i;
-
- if (GetInt(valueObj, varPtr)) {
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
- ObjValue(linkPtr), TCL_GLOBAL_ONLY);
- return (char *) "variable must have integer value";
- }
- LinkedVar(int) = *varPtr;
+ if (Tcl_GetIntFromObj(NULL, valueObj, &linkPtr->lastValue.i)
+ != TCL_OK) {
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
+ TCL_GLOBAL_ONLY);
+ return "variable must have integer value";
}
+ LinkedVar(int) = linkPtr->lastValue.i;
break;
case TCL_LINK_WIDE_INT:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- for (i=0; i < objc; i++) {
- Tcl_WideInt *varPtr = &linkPtr->lastValue.wPtr[i];
-
- if (GetWide(objv[i], varPtr)) {
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
- ObjValue(linkPtr), TCL_GLOBAL_ONLY);
- return (char *)
- "variable array must have wide integer value";
- }
- }
- } else {
- Tcl_WideInt *varPtr = &linkPtr->lastValue.w;
-
- if (GetWide(valueObj, varPtr)) {
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
- ObjValue(linkPtr), TCL_GLOBAL_ONLY);
- return (char *) "variable must have wide integer value";
- }
- LinkedVar(Tcl_WideInt) = *varPtr;
+ if (Tcl_GetWideIntFromObj(NULL, valueObj, &linkPtr->lastValue.w)
+ != TCL_OK) {
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
+ TCL_GLOBAL_ONLY);
+ return "variable must have integer value";
}
+ LinkedVar(Tcl_WideInt) = linkPtr->lastValue.w;
break;
case TCL_LINK_DOUBLE:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- for (i=0; i < objc; i++) {
- if (GetDouble(objv[i], &linkPtr->lastValue.dPtr[i])) {
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
- ObjValue(linkPtr), TCL_GLOBAL_ONLY);
- return (char *) "variable array must have real value";
- }
- }
- } else {
- double *varPtr = &linkPtr->lastValue.d;
-
- if (GetDouble(valueObj, varPtr)) {
+ 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";
+ return "variable must have real value";
+#ifdef ACCEPT_NAN
}
- LinkedVar(double) = *varPtr;
+ linkPtr->lastValue.d = valueObj->internalRep.doubleValue;
+#endif
}
+ LinkedVar(double) = linkPtr->lastValue.d;
break;
case TCL_LINK_BOOLEAN:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- for (i=0; i < objc; i++) {
- int *varPtr = &linkPtr->lastValue.iPtr[i];
-
- if (Tcl_GetBooleanFromObj(NULL, objv[i], varPtr) != TCL_OK) {
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
- ObjValue(linkPtr), TCL_GLOBAL_ONLY);
- return (char *) "variable array must have boolean value";
- }
- }
- } else {
- int *varPtr = &linkPtr->lastValue.i;
-
- if (Tcl_GetBooleanFromObj(NULL, valueObj, varPtr) != TCL_OK) {
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
- ObjValue(linkPtr), TCL_GLOBAL_ONLY);
- return (char *) "variable must have boolean value";
- }
- LinkedVar(int) = *varPtr;
+ if (Tcl_GetBooleanFromObj(NULL, valueObj, &linkPtr->lastValue.i)
+ != TCL_OK) {
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
+ TCL_GLOBAL_ONLY);
+ return "variable must have boolean value";
}
+ LinkedVar(int) = linkPtr->lastValue.i;
break;
case TCL_LINK_CHAR:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- for (i=0; i < objc; i++) {
- if (GetInt(objv[i], &valueInt)
- || !InRange(SCHAR_MIN, valueInt, SCHAR_MAX)) {
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
- ObjValue(linkPtr), TCL_GLOBAL_ONLY);
- return (char *) "variable array must have char value";
- }
- linkPtr->lastValue.cPtr[i] = (char) valueInt;
- }
- } else {
- if (GetInt(valueObj, &valueInt)
- || !InRange(SCHAR_MIN, valueInt, SCHAR_MAX)) {
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
- ObjValue(linkPtr), TCL_GLOBAL_ONLY);
- return (char *) "variable must have char value";
- }
- LinkedVar(char) = linkPtr->lastValue.c = (char) valueInt;
+ if (Tcl_GetIntFromObj(interp, valueObj, &valueInt) != TCL_OK
+ || valueInt < SCHAR_MIN || valueInt > SCHAR_MAX) {
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
+ TCL_GLOBAL_ONLY);
+ return "variable must have char value";
}
+ linkPtr->lastValue.c = (char)valueInt;
+ LinkedVar(char) = linkPtr->lastValue.c;
break;
case TCL_LINK_UCHAR:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- for (i=0; i < objc; i++) {
- if (GetInt(objv[i], &valueInt)
- || !InRange(0, valueInt, (int)UCHAR_MAX)) {
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
- ObjValue(linkPtr), TCL_GLOBAL_ONLY);
- return (char *)
- "variable array must have unsigned char value";
- }
- linkPtr->lastValue.ucPtr[i] = (unsigned char) valueInt;
- }
- } else {
- if (GetInt(valueObj, &valueInt)
- || !InRange(0, valueInt, (int)UCHAR_MAX)) {
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
- ObjValue(linkPtr), TCL_GLOBAL_ONLY);
- return (char *) "variable must have unsigned char value";
- }
- LinkedVar(unsigned char) = linkPtr->lastValue.uc =
- (unsigned char) valueInt;
+ if (Tcl_GetIntFromObj(interp, valueObj, &valueInt) != TCL_OK
+ || valueInt < 0 || valueInt > UCHAR_MAX) {
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
+ TCL_GLOBAL_ONLY);
+ return "variable must have unsigned char value";
}
+ linkPtr->lastValue.uc = (unsigned char) valueInt;
+ LinkedVar(unsigned char) = linkPtr->lastValue.uc;
break;
case TCL_LINK_SHORT:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- for (i=0; i < objc; i++) {
- if (GetInt(objv[i], &valueInt)
- || !InRange(SHRT_MIN, valueInt, SHRT_MAX)) {
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
- ObjValue(linkPtr), TCL_GLOBAL_ONLY);
- return (char *) "variable array must have short value";
- }
- linkPtr->lastValue.sPtr[i] = (short) valueInt;
- }
- } else {
- if (GetInt(valueObj, &valueInt)
- || !InRange(SHRT_MIN, valueInt, SHRT_MAX)) {
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
- ObjValue(linkPtr), TCL_GLOBAL_ONLY);
- return (char *) "variable must have short value";
- }
- LinkedVar(short) = linkPtr->lastValue.s = (short) valueInt;
+ if (Tcl_GetIntFromObj(interp, valueObj, &valueInt) != TCL_OK
+ || valueInt < SHRT_MIN || valueInt > SHRT_MAX) {
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
+ TCL_GLOBAL_ONLY);
+ return "variable must have short value";
}
+ linkPtr->lastValue.s = (short)valueInt;
+ LinkedVar(short) = linkPtr->lastValue.s;
break;
case TCL_LINK_USHORT:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- for (i=0; i < objc; i++) {
- if (GetInt(objv[i], &valueInt)
- || !InRange(0, valueInt, (int)USHRT_MAX)) {
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
- ObjValue(linkPtr), TCL_GLOBAL_ONLY);
- return (char *)
- "variable array must have unsigned short value";
- }
- linkPtr->lastValue.usPtr[i] = (unsigned short) valueInt;
- }
- } else {
- if (GetInt(valueObj, &valueInt)
- || !InRange(0, valueInt, (int)USHRT_MAX)) {
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
- ObjValue(linkPtr), TCL_GLOBAL_ONLY);
- return (char *) "variable must have unsigned short value";
- }
- LinkedVar(unsigned short) = linkPtr->lastValue.us =
- (unsigned short) valueInt;
+ if (Tcl_GetIntFromObj(interp, valueObj, &valueInt) != TCL_OK
+ || valueInt < 0 || valueInt > USHRT_MAX) {
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
+ TCL_GLOBAL_ONLY);
+ return "variable must have unsigned short value";
}
+ linkPtr->lastValue.us = (unsigned short)valueInt;
+ LinkedVar(unsigned short) = linkPtr->lastValue.us;
break;
case TCL_LINK_UINT:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- for (i=0; i < objc; i++) {
- if (GetWide(objv[i], &valueWide)
- || !InRange(0, valueWide, (Tcl_WideInt)UINT_MAX)) {
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
- ObjValue(linkPtr), TCL_GLOBAL_ONLY);
- return (char *)
- "variable array must have unsigned int value";
- }
- linkPtr->lastValue.uiPtr[i] = (unsigned int) valueWide;
- }
- } else {
- if (GetWide(valueObj, &valueWide)
- || !InRange(0, valueWide, (Tcl_WideInt)UINT_MAX)) {
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
- ObjValue(linkPtr), TCL_GLOBAL_ONLY);
- return (char *) "variable must have unsigned int value";
- }
- LinkedVar(unsigned int) = linkPtr->lastValue.ui =
- (unsigned int) valueWide;
+ if (Tcl_GetWideIntFromObj(interp, valueObj, &valueWide) != TCL_OK
+ || valueWide < 0 || valueWide > UINT_MAX) {
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
+ TCL_GLOBAL_ONLY);
+ return "variable must have unsigned int value";
}
+ linkPtr->lastValue.ui = (unsigned int)valueWide;
+ LinkedVar(unsigned int) = linkPtr->lastValue.ui;
break;
-#if !defined(TCL_WIDE_INT_IS_LONG) && !defined(_WIN32) && !defined(__CYGWIN__)
case TCL_LINK_LONG:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- for (i=0; i < objc; i++) {
- if (GetWide(objv[i], &valueWide)
- || !InRange(LONG_MIN, valueWide, LONG_MAX)) {
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
- ObjValue(linkPtr), TCL_GLOBAL_ONLY);
- return (char *) "variable array must have long value";
- }
- linkPtr->lastValue.lPtr[i] = (long) valueWide;
- }
- } else {
- if (GetWide(valueObj, &valueWide)
- || !InRange(LONG_MIN, valueWide, LONG_MAX)) {
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
- ObjValue(linkPtr), TCL_GLOBAL_ONLY);
- return (char *) "variable must have long value";
- }
- LinkedVar(long) = linkPtr->lastValue.l = (long) valueWide;
+ if (Tcl_GetWideIntFromObj(interp, valueObj, &valueWide) != TCL_OK
+ || valueWide < LONG_MIN || valueWide > LONG_MAX) {
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
+ TCL_GLOBAL_ONLY);
+ return "variable must have long value";
}
+ linkPtr->lastValue.l = (long)valueWide;
+ LinkedVar(long) = linkPtr->lastValue.l;
break;
case TCL_LINK_ULONG:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- for (i=0; i < objc; i++) {
- if (GetUWide(objv[i], &valueUWide)
- || (valueUWide > ULONG_MAX)) {
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
- ObjValue(linkPtr), TCL_GLOBAL_ONLY);
- return (char *)
- "variable array must have unsigned long value";
- }
- linkPtr->lastValue.ulPtr[i] = (unsigned long) valueUWide;
- }
- } else {
- if (GetUWide(valueObj, &valueUWide)
- || (valueUWide > ULONG_MAX)) {
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
- ObjValue(linkPtr), TCL_GLOBAL_ONLY);
- return (char *) "variable must have unsigned long value";
- }
- LinkedVar(unsigned long) = linkPtr->lastValue.ul =
- (unsigned long) valueUWide;
+ if (Tcl_GetWideIntFromObj(interp, valueObj, &valueWide) != TCL_OK
+ || valueWide < 0 || (Tcl_WideUInt) valueWide > ULONG_MAX) {
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
+ TCL_GLOBAL_ONLY);
+ return "variable must have unsigned long value";
}
+ linkPtr->lastValue.ul = (unsigned long)valueWide;
+ LinkedVar(unsigned long) = linkPtr->lastValue.ul;
break;
-#endif
case TCL_LINK_WIDE_UINT:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- for (i=0; i < objc; i++) {
- if (GetUWide(objv[i], &valueUWide)) {
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
- ObjValue(linkPtr), TCL_GLOBAL_ONLY);
- return (char *)
- "variable array must have unsigned wide int value";
- }
- linkPtr->lastValue.uwPtr[i] = valueUWide;
- }
- } else {
- if (GetUWide(valueObj, &valueUWide)) {
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
- ObjValue(linkPtr), TCL_GLOBAL_ONLY);
- return (char *) "variable must have unsigned wide int value";
- }
- LinkedVar(Tcl_WideUInt) = linkPtr->lastValue.uw = valueUWide;
+ /*
+ * FIXME: represent as a bignum.
+ */
+ if (Tcl_GetWideIntFromObj(interp, valueObj, &valueWide) != TCL_OK) {
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
+ TCL_GLOBAL_ONLY);
+ return "variable must have unsigned wide int value";
}
+ linkPtr->lastValue.uw = (Tcl_WideUInt)valueWide;
+ LinkedVar(Tcl_WideUInt) = linkPtr->lastValue.uw;
break;
case TCL_LINK_FLOAT:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- for (i=0; i < objc; i++) {
- if (GetDouble(objv[i], &valueDouble)
- && !InRange(FLT_MIN, fabs(valueDouble), FLT_MAX)
- && !IsSpecial(valueDouble)) {
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
- ObjValue(linkPtr), TCL_GLOBAL_ONLY);
- return (char *) "variable array must have float value";
- }
- linkPtr->lastValue.fPtr[i] = (float) valueDouble;
- }
- } else {
- if (GetDouble(valueObj, &valueDouble)
- && !InRange(FLT_MIN, fabs(valueDouble), FLT_MAX)
- && !IsSpecial(valueDouble)) {
- Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
- ObjValue(linkPtr), TCL_GLOBAL_ONLY);
- return (char *) "variable must have float value";
- }
- LinkedVar(float) = linkPtr->lastValue.f = (float) valueDouble;
+ if (Tcl_GetDoubleFromObj(interp, valueObj, &valueDouble) != TCL_OK
+ || valueDouble < -FLT_MAX || valueDouble > FLT_MAX) {
+ Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
+ TCL_GLOBAL_ONLY);
+ return "variable must have float value";
}
+ linkPtr->lastValue.f = (float)valueDouble;
+ LinkedVar(float) = linkPtr->lastValue.f;
break;
- default:
- return (char *) "internal error: bad linked variable type";
- }
+ case TCL_LINK_STRING:
+ value = Tcl_GetStringFromObj(valueObj, &valueLength);
+ valueLength++;
+ pp = (char **) linkPtr->addr;
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- memcpy(linkPtr->addr, linkPtr->lastValue.aryPtr, linkPtr->bytes);
+ *pp = ckrealloc(*pp, valueLength);
+ memcpy(*pp, value, (unsigned) valueLength);
+ break;
+
+ default:
+ return "internal error: bad linked variable type";
}
return NULL;
}
@@ -1247,185 +565,51 @@ ObjValue(
Link *linkPtr) /* Structure describing linked variable. */
{
char *p;
- Tcl_Obj *resultObj, **objv;
- int i;
+ Tcl_Obj *resultObj;
switch (linkPtr->type) {
case TCL_LINK_INT:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes);
- objv = (Tcl_Obj **)ckalloc(linkPtr->numElems * sizeof(Tcl_Obj *));
- for (i=0; i < linkPtr->numElems; i++) {
- TclNewIntObj(objv[i], linkPtr->lastValue.iPtr[i]);
- }
- resultObj = Tcl_NewListObj(linkPtr->numElems, objv);
- ckfree(objv);
- return resultObj;
- }
linkPtr->lastValue.i = LinkedVar(int);
- return Tcl_NewWideIntObj(linkPtr->lastValue.i);
+ return Tcl_NewIntObj(linkPtr->lastValue.i);
case TCL_LINK_WIDE_INT:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes);
- objv = (Tcl_Obj **)ckalloc(linkPtr->numElems * sizeof(Tcl_Obj *));
- for (i=0; i < linkPtr->numElems; i++) {
- TclNewIntObj(objv[i], linkPtr->lastValue.wPtr[i]);
- }
- resultObj = Tcl_NewListObj(linkPtr->numElems, objv);
- ckfree(objv);
- return resultObj;
- }
linkPtr->lastValue.w = LinkedVar(Tcl_WideInt);
return Tcl_NewWideIntObj(linkPtr->lastValue.w);
case TCL_LINK_DOUBLE:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes);
- objv = (Tcl_Obj **)ckalloc(linkPtr->numElems * sizeof(Tcl_Obj *));
- for (i=0; i < linkPtr->numElems; i++) {
- TclNewDoubleObj(objv[i], linkPtr->lastValue.dPtr[i]);
- }
- resultObj = Tcl_NewListObj(linkPtr->numElems, objv);
- ckfree(objv);
- return resultObj;
- }
linkPtr->lastValue.d = LinkedVar(double);
return Tcl_NewDoubleObj(linkPtr->lastValue.d);
case TCL_LINK_BOOLEAN:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes);
- objv = (Tcl_Obj **)ckalloc(linkPtr->numElems * sizeof(Tcl_Obj *));
- for (i=0; i < linkPtr->numElems; i++) {
- objv[i] = Tcl_NewBooleanObj(linkPtr->lastValue.iPtr[i] != 0);
- }
- resultObj = Tcl_NewListObj(linkPtr->numElems, objv);
- ckfree(objv);
- return resultObj;
- }
linkPtr->lastValue.i = LinkedVar(int);
- return Tcl_NewBooleanObj(linkPtr->lastValue.i);
+ return Tcl_NewBooleanObj(linkPtr->lastValue.i != 0);
case TCL_LINK_CHAR:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes);
- objv = (Tcl_Obj **)ckalloc(linkPtr->numElems * sizeof(Tcl_Obj *));
- for (i=0; i < linkPtr->numElems; i++) {
- TclNewIntObj(objv[i], linkPtr->lastValue.cPtr[i]);
- }
- resultObj = Tcl_NewListObj(linkPtr->numElems, objv);
- ckfree(objv);
- return resultObj;
- }
linkPtr->lastValue.c = LinkedVar(char);
- return Tcl_NewWideIntObj(linkPtr->lastValue.c);
+ return Tcl_NewIntObj(linkPtr->lastValue.c);
case TCL_LINK_UCHAR:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes);
- objv = (Tcl_Obj **)ckalloc(linkPtr->numElems * sizeof(Tcl_Obj *));
- for (i=0; i < linkPtr->numElems; i++) {
- TclNewIntObj(objv[i], linkPtr->lastValue.ucPtr[i]);
- }
- resultObj = Tcl_NewListObj(linkPtr->numElems, objv);
- ckfree(objv);
- return resultObj;
- }
linkPtr->lastValue.uc = LinkedVar(unsigned char);
- return Tcl_NewWideIntObj(linkPtr->lastValue.uc);
+ return Tcl_NewIntObj(linkPtr->lastValue.uc);
case TCL_LINK_SHORT:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes);
- objv = (Tcl_Obj **)ckalloc(linkPtr->numElems * sizeof(Tcl_Obj *));
- for (i=0; i < linkPtr->numElems; i++) {
- TclNewIntObj(objv[i], linkPtr->lastValue.sPtr[i]);
- }
- resultObj = Tcl_NewListObj(linkPtr->numElems, objv);
- ckfree(objv);
- return resultObj;
- }
linkPtr->lastValue.s = LinkedVar(short);
- return Tcl_NewWideIntObj(linkPtr->lastValue.s);
+ return Tcl_NewIntObj(linkPtr->lastValue.s);
case TCL_LINK_USHORT:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes);
- objv = (Tcl_Obj **)ckalloc(linkPtr->numElems * sizeof(Tcl_Obj *));
- for (i=0; i < linkPtr->numElems; i++) {
- TclNewIntObj(objv[i], linkPtr->lastValue.usPtr[i]);
- }
- resultObj = Tcl_NewListObj(linkPtr->numElems, objv);
- ckfree(objv);
- return resultObj;
- }
linkPtr->lastValue.us = LinkedVar(unsigned short);
- return Tcl_NewWideIntObj(linkPtr->lastValue.us);
+ return Tcl_NewIntObj(linkPtr->lastValue.us);
case TCL_LINK_UINT:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes);
- objv = (Tcl_Obj **)ckalloc(linkPtr->numElems * sizeof(Tcl_Obj *));
- for (i=0; i < linkPtr->numElems; i++) {
- TclNewIntObj(objv[i], linkPtr->lastValue.uiPtr[i]);
- }
- resultObj = Tcl_NewListObj(linkPtr->numElems, objv);
- ckfree(objv);
- return resultObj;
- }
linkPtr->lastValue.ui = LinkedVar(unsigned int);
return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.ui);
-#if !defined(TCL_WIDE_INT_IS_LONG) && !defined(_WIN32) && !defined(__CYGWIN__)
case TCL_LINK_LONG:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes);
- objv = (Tcl_Obj **)ckalloc(linkPtr->numElems * sizeof(Tcl_Obj *));
- for (i=0; i < linkPtr->numElems; i++) {
- TclNewIntObj(objv[i], linkPtr->lastValue.lPtr[i]);
- }
- resultObj = Tcl_NewListObj(linkPtr->numElems, objv);
- ckfree(objv);
- return resultObj;
- }
linkPtr->lastValue.l = LinkedVar(long);
return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.l);
case TCL_LINK_ULONG:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes);
- objv = (Tcl_Obj **)ckalloc(linkPtr->numElems * sizeof(Tcl_Obj *));
- for (i=0; i < linkPtr->numElems; i++) {
- TclNewIntObj(objv[i], linkPtr->lastValue.ulPtr[i]);
- }
- resultObj = Tcl_NewListObj(linkPtr->numElems, objv);
- ckfree(objv);
- return resultObj;
- }
linkPtr->lastValue.ul = LinkedVar(unsigned long);
return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.ul);
-#endif
case TCL_LINK_FLOAT:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes);
- objv = (Tcl_Obj **)ckalloc(linkPtr->numElems * sizeof(Tcl_Obj *));
- for (i=0; i < linkPtr->numElems; i++) {
- TclNewDoubleObj(objv[i], linkPtr->lastValue.fPtr[i]);
- }
- resultObj = Tcl_NewListObj(linkPtr->numElems, objv);
- ckfree(objv);
- return resultObj;
- }
linkPtr->lastValue.f = LinkedVar(float);
return Tcl_NewDoubleObj(linkPtr->lastValue.f);
- case TCL_LINK_WIDE_UINT: {
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes);
- objv = (Tcl_Obj **)ckalloc(linkPtr->numElems * sizeof(Tcl_Obj *));
- for (i=0; i < linkPtr->numElems; i++) {
- TclNewUIntObj(objv[i], linkPtr->lastValue.uwPtr[i]);
- }
- resultObj = Tcl_NewListObj(linkPtr->numElems, objv);
- ckfree(objv);
- return resultObj;
- }
+ case TCL_LINK_WIDE_UINT:
linkPtr->lastValue.uw = LinkedVar(Tcl_WideUInt);
- Tcl_Obj *uwObj;
- TclNewUIntObj(uwObj, linkPtr->lastValue.uw);
- return uwObj;
- }
-
+ /*
+ * FIXME: represent as a bignum.
+ */
+ return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.uw);
case TCL_LINK_STRING:
p = LinkedVar(char *);
if (p == NULL) {
@@ -1434,25 +618,6 @@ ObjValue(
}
return Tcl_NewStringObj(p, -1);
- case TCL_LINK_CHARS:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes);
- linkPtr->lastValue.cPtr[linkPtr->bytes-1] = '\0';
- /* take care of proper string end */
- return Tcl_NewStringObj(linkPtr->lastValue.cPtr, linkPtr->bytes);
- }
- linkPtr->lastValue.c = '\0';
- return Tcl_NewStringObj(&linkPtr->lastValue.c, 1);
-
- case TCL_LINK_BINARY:
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- memcpy(linkPtr->lastValue.aryPtr, linkPtr->addr, linkPtr->bytes);
- return Tcl_NewByteArrayObj((unsigned char *) linkPtr->addr,
- linkPtr->bytes);
- }
- linkPtr->lastValue.uc = LinkedVar(unsigned char);
- return Tcl_NewByteArrayObj(&linkPtr->lastValue.uc, 1);
-
/*
* This code only gets executed if the link type is unknown (shouldn't
* ever happen).
@@ -1465,38 +630,6 @@ ObjValue(
}
/*
- *----------------------------------------------------------------------
- *
- * LinkFree --
- *
- * Free's allocated space of given link and link structure.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-LinkFree(
- Link *linkPtr) /* Structure describing linked variable. */
-{
- if (linkPtr->nsPtr) {
- TclNsDecrRefCount(linkPtr->nsPtr);
- }
- if (linkPtr->flags & LINK_ALLOC_ADDR) {
- ckfree(linkPtr->addr);
- }
- if (linkPtr->flags & LINK_ALLOC_LAST) {
- ckfree(linkPtr->lastValue.aryPtr);
- }
- ckfree((char *) linkPtr);
-}
-
-/*
* Local Variables:
* mode: c
* c-basic-offset: 4