diff options
Diffstat (limited to 'generic/tclLink.c')
| -rw-r--r-- | generic/tclLink.c | 236 | 
1 files changed, 128 insertions, 108 deletions
| diff --git a/generic/tclLink.c b/generic/tclLink.c index 7bf4fd5..2735256 100644 --- a/generic/tclLink.c +++ b/generic/tclLink.c @@ -11,8 +11,6 @@   *   * See the file "license.terms" for information on usage and redistribution of   * this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - * RCS: @(#) $Id: tclLink.c,v 1.17 2006/08/18 07:45:31 das Exp $   */  #include "tclInt.h" @@ -67,8 +65,19 @@ typedef struct Link {   */  static char *		LinkTraceProc(ClientData clientData,Tcl_Interp *interp, -			    CONST char *name1, CONST char *name2, int flags); +			    const char *name1, const char *name2, int flags);  static Tcl_Obj *	ObjValue(Link *linkPtr); + +/* + * Convenience macro for accessing the value of the C variable pointed to by a + * link. Note that this macro produces something that may be regarded as an + * lvalue or rvalue; it may be assigned to as well as read. Also note that + * this macro assumes the name of the variable being accessed (linkPtr); this + * is not strictly a good thing, but it keeps the code much shorter and + * cleaner. + */ + +#define LinkedVar(type) (*(type *) linkPtr->addr)  /*   *---------------------------------------------------------------------- @@ -93,7 +102,7 @@ static Tcl_Obj *	ObjValue(Link *linkPtr);  int  Tcl_LinkVar(      Tcl_Interp *interp,		/* Interpreter in which varName exists. */ -    CONST char *varName,	/* Name of a global variable in interp. */ +    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 @@ -103,7 +112,15 @@ Tcl_LinkVar(      Link *linkPtr;      int code; -    linkPtr = (Link *) ckalloc(sizeof(Link)); +    linkPtr = (Link *) Tcl_VarTraceInfo2(interp, varName, NULL, +	    TCL_GLOBAL_ONLY, LinkTraceProc, (ClientData) NULL); +    if (linkPtr != NULL) { +	Tcl_SetObjResult(interp, Tcl_ObjPrintf( +		"variable '%s' is already linked", varName)); +	return TCL_ERROR; +    } + +    linkPtr = ckalloc(sizeof(Link));      linkPtr->interp = interp;      linkPtr->varName = Tcl_NewStringObj(varName, -1);      Tcl_IncrRefCount(linkPtr->varName); @@ -118,15 +135,15 @@ Tcl_LinkVar(      if (Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, objPtr,  	    TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {  	Tcl_DecrRefCount(linkPtr->varName); -	ckfree((char *) linkPtr); +	ckfree(linkPtr);  	return TCL_ERROR;      } -    code = Tcl_TraceVar(interp, varName, TCL_GLOBAL_ONLY|TCL_TRACE_READS -	    |TCL_TRACE_WRITES|TCL_TRACE_UNSETS, LinkTraceProc, -	    (ClientData) linkPtr); +    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); -	ckfree((char *) linkPtr); +	ckfree(linkPtr);      }      return code;  } @@ -152,20 +169,19 @@ Tcl_LinkVar(  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 *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) {  	return;      } -    Tcl_UntraceVar(interp, varName, +    Tcl_UntraceVar2(interp, varName, NULL,  	    TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS, -	    LinkTraceProc, (ClientData) linkPtr); +	    LinkTraceProc, linkPtr);      Tcl_DecrRefCount(linkPtr->varName); -    ckfree((char *) linkPtr); +    ckfree(linkPtr);  }  /* @@ -190,13 +206,12 @@ 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 *linkPtr = (Link *) Tcl_VarTraceInfo2(interp, varName, NULL, +	    TCL_GLOBAL_ONLY, LinkTraceProc, NULL);      int savedFlag; -    linkPtr = (Link *) Tcl_VarTraceInfo(interp, varName, TCL_GLOBAL_ONLY, -	    LinkTraceProc, (ClientData) NULL);      if (linkPtr == NULL) {  	return;      } @@ -204,7 +219,14 @@ Tcl_UpdateLinkedVar(      linkPtr->flags |= LINK_BEING_UPDATED;      Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),  	    TCL_GLOBAL_ONLY); -    linkPtr->flags = (linkPtr->flags & ~LINK_BEING_UPDATED) | savedFlag; +    /* +     * Callback may have unlinked the variable. [Bug 1740631] +     */ +    linkPtr = (Link *) Tcl_VarTraceInfo2(interp, varName, NULL, +	    TCL_GLOBAL_ONLY, LinkTraceProc, NULL); +    if (linkPtr != NULL) { +	linkPtr->flags = (linkPtr->flags & ~LINK_BEING_UPDATED) | savedFlag; +    }  }  /* @@ -232,13 +254,13 @@ static char *  LinkTraceProc(      ClientData clientData,	/* Contains information about the link. */      Tcl_Interp *interp,		/* Interpreter containing Tcl variable. */ -    CONST char *name1,		/* First part of variable name. */ -    CONST char *name2,		/* Second part of variable name. */ +    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; +    Link *linkPtr = clientData;      int changed, valueLength; -    CONST char *value; +    const char *value;      char **pp;      Tcl_Obj *valueObj;      int valueInt; @@ -251,15 +273,15 @@ LinkTraceProc(       */      if (flags & TCL_TRACE_UNSETS) { -	if (flags & TCL_INTERP_DESTROYED) { +	if (Tcl_InterpDeleted(interp)) {  	    Tcl_DecrRefCount(linkPtr->varName); -	    ckfree((char *) linkPtr); +	    ckfree(linkPtr);  	} else if (flags & TCL_TRACE_DESTROYED) {  	    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),  		    TCL_GLOBAL_ONLY); -	    Tcl_TraceVar(interp, Tcl_GetString(linkPtr->varName), +	    Tcl_TraceVar2(interp, Tcl_GetString(linkPtr->varName), NULL,  		    TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES -		    |TCL_TRACE_UNSETS, LinkTraceProc, (ClientData) linkPtr); +		    |TCL_TRACE_UNSETS, LinkTraceProc, linkPtr);  	}  	return NULL;      } @@ -283,51 +305,46 @@ LinkTraceProc(  	switch (linkPtr->type) {  	case TCL_LINK_INT:  	case TCL_LINK_BOOLEAN: -	    changed = *(int *)(linkPtr->addr) != linkPtr->lastValue.i; +	    changed = (LinkedVar(int) != linkPtr->lastValue.i);  	    break;  	case TCL_LINK_DOUBLE: -	    changed = *(double *)(linkPtr->addr) != linkPtr->lastValue.d; +	    changed = (LinkedVar(double) != linkPtr->lastValue.d);  	    break;  	case TCL_LINK_WIDE_INT: -	    changed = *(Tcl_WideInt *)(linkPtr->addr) != linkPtr->lastValue.w; +	    changed = (LinkedVar(Tcl_WideInt) != linkPtr->lastValue.w);  	    break;  	case TCL_LINK_WIDE_UINT: -	    changed = *(Tcl_WideUInt *)(linkPtr->addr) != -		    linkPtr->lastValue.uw; +	    changed = (LinkedVar(Tcl_WideUInt) != linkPtr->lastValue.uw);  	    break;  	case TCL_LINK_CHAR: -	    changed = *(char *)(linkPtr->addr) != linkPtr->lastValue.c; +	    changed = (LinkedVar(char) != linkPtr->lastValue.c);  	    break;  	case TCL_LINK_UCHAR: -	    changed = *(unsigned char *)(linkPtr->addr) != -		    linkPtr->lastValue.uc; +	    changed = (LinkedVar(unsigned char) != linkPtr->lastValue.uc);  	    break;  	case TCL_LINK_SHORT: -	    changed = *(short *)(linkPtr->addr) != linkPtr->lastValue.s; +	    changed = (LinkedVar(short) != linkPtr->lastValue.s);  	    break;  	case TCL_LINK_USHORT: -	    changed = *(unsigned short *)(linkPtr->addr) != -		    linkPtr->lastValue.us; +	    changed = (LinkedVar(unsigned short) != linkPtr->lastValue.us);  	    break;  	case TCL_LINK_UINT: -	    changed = *(unsigned int *)(linkPtr->addr) != -		    linkPtr->lastValue.ui; +	    changed = (LinkedVar(unsigned int) != linkPtr->lastValue.ui);  	    break;  	case TCL_LINK_LONG: -	    changed = *(long *)(linkPtr->addr) != linkPtr->lastValue.l; +	    changed = (LinkedVar(long) != linkPtr->lastValue.l);  	    break;  	case TCL_LINK_ULONG: -	    changed = *(unsigned long *)(linkPtr->addr) != -		    linkPtr->lastValue.ul; +	    changed = (LinkedVar(unsigned long) != linkPtr->lastValue.ul);  	    break;  	case TCL_LINK_FLOAT: -	    changed = *(float *)(linkPtr->addr) != linkPtr->lastValue.f; +	    changed = (LinkedVar(float) != linkPtr->lastValue.f);  	    break;  	case TCL_LINK_STRING:  	    changed = 1;  	    break;  	default: -	    return "internal error: bad linked variable type"; +	    return (char *) "internal error: bad linked variable type";  	}  	if (changed) {  	    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), @@ -348,14 +365,15 @@ LinkTraceProc(      if (linkPtr->flags & LINK_READ_ONLY) {  	Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),  		TCL_GLOBAL_ONLY); -	return "linked variable is read-only"; +	return (char *) "linked variable is read-only";      }      valueObj = Tcl_ObjGetVar2(interp, linkPtr->varName,NULL, TCL_GLOBAL_ONLY);      if (valueObj == NULL) {  	/*  	 * This shouldn't ever happen.  	 */ -	return "internal error: linked variable couldn't be read"; + +	return (char *) "internal error: linked variable couldn't be read";      }      switch (linkPtr->type) { @@ -364,9 +382,9 @@ LinkTraceProc(  		!= TCL_OK) {  	    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),  		    TCL_GLOBAL_ONLY); -	    return "variable must have integer value"; +	    return (char *) "variable must have integer value";  	} -	*(int *)(linkPtr->addr) = linkPtr->lastValue.i; +	LinkedVar(int) = linkPtr->lastValue.i;  	break;      case TCL_LINK_WIDE_INT: @@ -374,36 +392,36 @@ LinkTraceProc(  		!= TCL_OK) {  	    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),  		    TCL_GLOBAL_ONLY); -	    return "variable must have integer value"; +	    return (char *) "variable must have integer value";  	} -	*(Tcl_WideInt *)(linkPtr->addr) = linkPtr->lastValue.w; +	LinkedVar(Tcl_WideInt) = linkPtr->lastValue.w;  	break;      case TCL_LINK_DOUBLE:  	if (Tcl_GetDoubleFromObj(NULL, valueObj, &linkPtr->lastValue.d)  		!= TCL_OK) {  #ifdef ACCEPT_NAN -	  if (valueObj->typePtr != &tclDoubleType) { +	    if (valueObj->typePtr != &tclDoubleType) {  #endif -	    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr), -		    TCL_GLOBAL_ONLY); -	    return "variable must have real value"; +		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; +	    } +	    linkPtr->lastValue.d = valueObj->internalRep.doubleValue;  #endif  	} -	*(double *)(linkPtr->addr) = linkPtr->lastValue.d; +	LinkedVar(double) = linkPtr->lastValue.d;  	break;      case TCL_LINK_BOOLEAN:  	if (Tcl_GetBooleanFromObj(NULL, valueObj, &linkPtr->lastValue.i) -	    != TCL_OK) { +		!= TCL_OK) {  	    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),  		    TCL_GLOBAL_ONLY); -	    return "variable must have boolean value"; +	    return (char *) "variable must have boolean value";  	} -	*(int *)(linkPtr->addr) = linkPtr->lastValue.i; +	LinkedVar(int) = linkPtr->lastValue.i;  	break;      case TCL_LINK_CHAR: @@ -411,10 +429,10 @@ LinkTraceProc(  		|| valueInt < SCHAR_MIN || valueInt > SCHAR_MAX) {  	    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),  		    TCL_GLOBAL_ONLY); -	    return "variable must have char value"; +	    return (char *) "variable must have char value";  	}  	linkPtr->lastValue.c = (char)valueInt; -	*(char *)(linkPtr->addr) = linkPtr->lastValue.c; +	LinkedVar(char) = linkPtr->lastValue.c;  	break;      case TCL_LINK_UCHAR: @@ -422,10 +440,10 @@ LinkTraceProc(  		|| valueInt < 0 || valueInt > UCHAR_MAX) {  	    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),  		    TCL_GLOBAL_ONLY); -	    return "variable must have unsigned char value"; +	    return (char *) "variable must have unsigned char value";  	}  	linkPtr->lastValue.uc = (unsigned char) valueInt; -	*(unsigned char *)(linkPtr->addr) = linkPtr->lastValue.uc; +	LinkedVar(unsigned char) = linkPtr->lastValue.uc;  	break;      case TCL_LINK_SHORT: @@ -433,10 +451,10 @@ LinkTraceProc(  		|| valueInt < SHRT_MIN || valueInt > SHRT_MAX) {  	    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),  		    TCL_GLOBAL_ONLY); -	    return "variable must have short value"; +	    return (char *) "variable must have short value";  	}  	linkPtr->lastValue.s = (short)valueInt; -	*(short *)(linkPtr->addr) = linkPtr->lastValue.s; +	LinkedVar(short) = linkPtr->lastValue.s;  	break;      case TCL_LINK_USHORT: @@ -444,10 +462,10 @@ LinkTraceProc(  		|| valueInt < 0 || valueInt > USHRT_MAX) {  	    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),  		    TCL_GLOBAL_ONLY); -	    return "variable must have unsigned short value"; +	    return (char *) "variable must have unsigned short value";  	}  	linkPtr->lastValue.us = (unsigned short)valueInt; -	*(unsigned short *)(linkPtr->addr) = linkPtr->lastValue.us; +	LinkedVar(unsigned short) = linkPtr->lastValue.us;  	break;      case TCL_LINK_UINT: @@ -455,10 +473,10 @@ LinkTraceProc(  		|| valueWide < 0 || valueWide > UINT_MAX) {  	    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),  		    TCL_GLOBAL_ONLY); -	    return "variable must have unsigned int value"; +	    return (char *) "variable must have unsigned int value";  	}  	linkPtr->lastValue.ui = (unsigned int)valueWide; -	*(unsigned int *)(linkPtr->addr) = linkPtr->lastValue.ui; +	LinkedVar(unsigned int) = linkPtr->lastValue.ui;  	break;      case TCL_LINK_LONG: @@ -466,10 +484,10 @@ LinkTraceProc(  		|| valueWide < LONG_MIN || valueWide > LONG_MAX) {  	    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),  		    TCL_GLOBAL_ONLY); -	    return "variable must have long value"; +	    return (char *) "variable must have long value";  	}  	linkPtr->lastValue.l = (long)valueWide; -	*(long *)(linkPtr->addr) = linkPtr->lastValue.l; +	LinkedVar(long) = linkPtr->lastValue.l;  	break;      case TCL_LINK_ULONG: @@ -477,10 +495,10 @@ LinkTraceProc(  		|| 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"; +	    return (char *) "variable must have unsigned long value";  	}  	linkPtr->lastValue.ul = (unsigned long)valueWide; -	*(unsigned long *)(linkPtr->addr) = linkPtr->lastValue.ul; +	LinkedVar(unsigned long) = linkPtr->lastValue.ul;  	break;      case TCL_LINK_WIDE_UINT: @@ -490,36 +508,34 @@ LinkTraceProc(  	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"; +	    return (char *) "variable must have unsigned wide int value";  	}  	linkPtr->lastValue.uw = (Tcl_WideUInt)valueWide; -	*(Tcl_WideUInt *)(linkPtr->addr) = linkPtr->lastValue.uw; +	LinkedVar(Tcl_WideUInt) = linkPtr->lastValue.uw;  	break;      case TCL_LINK_FLOAT:  	if (Tcl_GetDoubleFromObj(interp, valueObj, &valueDouble) != TCL_OK -		|| valueDouble < FLT_MIN || valueDouble > FLT_MAX) { +		|| valueDouble < -FLT_MAX || valueDouble > FLT_MAX) {  	    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),  		    TCL_GLOBAL_ONLY); -	    return "variable must have float value"; +	    return (char *) "variable must have float value";  	}  	linkPtr->lastValue.f = (float)valueDouble; -	*(float *)(linkPtr->addr) = linkPtr->lastValue.f; +	LinkedVar(float) = linkPtr->lastValue.f;  	break;      case TCL_LINK_STRING:  	value = Tcl_GetStringFromObj(valueObj, &valueLength);  	valueLength++; -	pp = (char **)(linkPtr->addr); -	if (*pp != NULL) { -	    ckfree(*pp); -	} -	*pp = (char *) ckalloc((unsigned) valueLength); +	pp = (char **) linkPtr->addr; + +	*pp = ckrealloc(*pp, valueLength);  	memcpy(*pp, value, (unsigned) valueLength);  	break;      default: -	return "internal error: bad linked variable type"; +	return (char *) "internal error: bad linked variable type";      }      return NULL;  } @@ -547,54 +563,56 @@ ObjValue(      Link *linkPtr)		/* Structure describing linked variable. */  {      char *p; +    Tcl_Obj *resultObj;      switch (linkPtr->type) {      case TCL_LINK_INT: -	linkPtr->lastValue.i = *(int *)(linkPtr->addr); +	linkPtr->lastValue.i = LinkedVar(int);  	return Tcl_NewIntObj(linkPtr->lastValue.i);      case TCL_LINK_WIDE_INT: -	linkPtr->lastValue.w = *(Tcl_WideInt *)(linkPtr->addr); +	linkPtr->lastValue.w = LinkedVar(Tcl_WideInt);  	return Tcl_NewWideIntObj(linkPtr->lastValue.w);      case TCL_LINK_DOUBLE: -	linkPtr->lastValue.d = *(double *)(linkPtr->addr); +	linkPtr->lastValue.d = LinkedVar(double);  	return Tcl_NewDoubleObj(linkPtr->lastValue.d);      case TCL_LINK_BOOLEAN: -	linkPtr->lastValue.i = *(int *)(linkPtr->addr); +	linkPtr->lastValue.i = LinkedVar(int);  	return Tcl_NewBooleanObj(linkPtr->lastValue.i != 0);      case TCL_LINK_CHAR: -	linkPtr->lastValue.c = *(char *)(linkPtr->addr); +	linkPtr->lastValue.c = LinkedVar(char);  	return Tcl_NewIntObj(linkPtr->lastValue.c);      case TCL_LINK_UCHAR: -	linkPtr->lastValue.uc = *(unsigned char *)(linkPtr->addr); +	linkPtr->lastValue.uc = LinkedVar(unsigned char);  	return Tcl_NewIntObj(linkPtr->lastValue.uc);      case TCL_LINK_SHORT: -	linkPtr->lastValue.s = *(short *)(linkPtr->addr); +	linkPtr->lastValue.s = LinkedVar(short);  	return Tcl_NewIntObj(linkPtr->lastValue.s);      case TCL_LINK_USHORT: -	linkPtr->lastValue.us = *(unsigned short *)(linkPtr->addr); +	linkPtr->lastValue.us = LinkedVar(unsigned short);  	return Tcl_NewIntObj(linkPtr->lastValue.us);      case TCL_LINK_UINT: -	linkPtr->lastValue.ui = *(unsigned int *)(linkPtr->addr); -	return Tcl_NewWideIntObj((Tcl_WideInt)(linkPtr->lastValue.ui)); +	linkPtr->lastValue.ui = LinkedVar(unsigned int); +	return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.ui);      case TCL_LINK_LONG: -	linkPtr->lastValue.l = *(long *)(linkPtr->addr); -	return Tcl_NewWideIntObj(linkPtr->lastValue.l); +	linkPtr->lastValue.l = LinkedVar(long); +	return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.l);      case TCL_LINK_ULONG: -	linkPtr->lastValue.ul = *(unsigned long *)(linkPtr->addr); -	return Tcl_NewWideIntObj((Tcl_WideInt)(linkPtr->lastValue.ul)); +	linkPtr->lastValue.ul = LinkedVar(unsigned long); +	return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.ul);      case TCL_LINK_FLOAT: -	linkPtr->lastValue.f = *(float *)(linkPtr->addr); +	linkPtr->lastValue.f = LinkedVar(float);  	return Tcl_NewDoubleObj(linkPtr->lastValue.f);      case TCL_LINK_WIDE_UINT: -	linkPtr->lastValue.uw = *(Tcl_WideUInt *)(linkPtr->addr); +	linkPtr->lastValue.uw = LinkedVar(Tcl_WideUInt);  	/*  	 * FIXME: represent as a bignum.  	 */  	return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.uw);      case TCL_LINK_STRING: -	p = *(char **)(linkPtr->addr); +	p = LinkedVar(char *);  	if (p == NULL) { -	    return Tcl_NewStringObj("NULL", 4); +	    TclNewLiteralStringObj(resultObj, "NULL"); +	    return resultObj;  	}  	return Tcl_NewStringObj(p, -1); @@ -602,8 +620,10 @@ ObjValue(       * This code only gets executed if the link type is unknown (shouldn't       * ever happen).       */ +      default: -	return Tcl_NewStringObj("??", 2); +	TclNewLiteralStringObj(resultObj, "??"); +	return resultObj;      }  } | 
