| ︙ | | | ︙ | |
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
* Tcl_GetStringFromObj should panic
* instead. */
NULL /* SetFromAny function; Tcl_ConvertToType
* should panic instead. */
};
/*
* The [upvar]/[uplevel] level reference type. Uses the twoPtrValue field,
* encoding the type of level reference in ptr and the actual parsed out
* offset in ptr2.
*
* Uses the default behaviour throughout, and never disposes of the string
* rep; it's just a cache type.
*/
static const Tcl_ObjType levelReferenceType = {
"levelReference",
|
|
|
<
|
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
* Tcl_GetStringFromObj should panic
* instead. */
NULL /* SetFromAny function; Tcl_ConvertToType
* should panic instead. */
};
/*
* The [upvar]/[uplevel] level reference type. Uses the longValue field
* to remember the integer value of a parsed #<integer> format.
*
* Uses the default behaviour throughout, and never disposes of the string
* rep; it's just a cache type.
*/
static const Tcl_ObjType levelReferenceType = {
"levelReference",
|
| ︙ | | | ︙ | |
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
|
* Given a description of a procedure frame, such as the first argument
* to an "uplevel" or "upvar" command, locate the call frame for the
* appropriate level of procedure.
*
* Results:
* The return value is -1 if an error occurred in finding the frame (in
* this case an error message is left in the interp's result). 1 is
* returned if objPtr was either a number or a number preceded by "#" and
* it specified a valid frame. 0 is returned if objPtr isn't one of the
* two things above (in this case, the lookup acts as if objPtr were
* "1"). The variable pointed to by framePtrPtr is filled in with the
* address of the desired frame (unless an error occurs, in which case it
* isn't modified).
*
* Side effects:
|
|
|
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
|
* Given a description of a procedure frame, such as the first argument
* to an "uplevel" or "upvar" command, locate the call frame for the
* appropriate level of procedure.
*
* Results:
* The return value is -1 if an error occurred in finding the frame (in
* this case an error message is left in the interp's result). 1 is
* returned if objPtr was either an int or an int preceded by "#" and
* it specified a valid frame. 0 is returned if objPtr isn't one of the
* two things above (in this case, the lookup acts as if objPtr were
* "1"). The variable pointed to by framePtrPtr is filled in with the
* address of the desired frame (unless an error occurs, in which case it
* isn't modified).
*
* Side effects:
|
| ︙ | | | ︙ | |
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
|
Tcl_Interp *interp, /* Interpreter in which to find frame. */
Tcl_Obj *objPtr, /* Object describing frame. */
CallFrame **framePtrPtr) /* Store pointer to frame here (or NULL if
* global frame indicated). */
{
register Interp *iPtr = (Interp *) interp;
int curLevel, level, result;
CallFrame *framePtr;
const char *name = NULL;
/*
* Parse object to figure out which level number to go to.
*/
result = 0;
|
<
|
802
803
804
805
806
807
808
809
810
811
812
813
814
815
|
Tcl_Interp *interp, /* Interpreter in which to find frame. */
Tcl_Obj *objPtr, /* Object describing frame. */
CallFrame **framePtrPtr) /* Store pointer to frame here (or NULL if
* global frame indicated). */
{
register Interp *iPtr = (Interp *) interp;
int curLevel, level, result;
const char *name = NULL;
/*
* Parse object to figure out which level number to go to.
*/
result = 0;
|
| ︙ | | | ︙ | |
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
|
if (objPtr == NULL) {
/* Do nothing */
} else if (TCL_OK == Tcl_GetIntFromObj(NULL, objPtr, &level)
&& (level >= 0)) {
level = curLevel - level;
result = 1;
} else if (objPtr->typePtr == &levelReferenceType) {
level = PTR2INT(objPtr->internalRep.twoPtrValue.ptr1);
result = 1;
} else {
name = TclGetString(objPtr);
if (name[0] == '#') {
if (TCL_OK == Tcl_GetInt(NULL, name+1, &level) && level >= 0) {
TclFreeIntRep(objPtr);
objPtr->typePtr = &levelReferenceType;
objPtr->internalRep.twoPtrValue.ptr1 = INT2PTR(level);
result = 1;
} else {
result = -1;
}
} else if (isdigit(UCHAR(name[0]))) { /* INTL: digit */
/*
* If this were an integer, we'd have succeeded already.
* Docs say we have to treat this as a 'bad level' error.
*/
result = -1;
}
}
if (result == 0) {
level = curLevel - 1;
name = "1";
}
if (result != -1) {
if (level >= 0) {
for (framePtr = iPtr->varFramePtr; framePtr != NULL;
framePtr = framePtr->callerVarPtr) {
if (framePtr->level == level) {
*framePtrPtr = framePtr;
return result;
}
}
|
|
|
>
|
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
|
if (objPtr == NULL) {
/* Do nothing */
} else if (TCL_OK == Tcl_GetIntFromObj(NULL, objPtr, &level)
&& (level >= 0)) {
level = curLevel - level;
result = 1;
} else if (objPtr->typePtr == &levelReferenceType) {
level = (int) objPtr->internalRep.longValue;
result = 1;
} else {
name = TclGetString(objPtr);
if (name[0] == '#') {
if (TCL_OK == Tcl_GetInt(NULL, name+1, &level) && level >= 0) {
TclFreeIntRep(objPtr);
objPtr->typePtr = &levelReferenceType;
objPtr->internalRep.longValue = level;
result = 1;
} else {
result = -1;
}
} else if (isdigit(UCHAR(name[0]))) { /* INTL: digit */
/*
* If this were an integer, we'd have succeeded already.
* Docs say we have to treat this as a 'bad level' error.
*/
result = -1;
}
}
if (result == 0) {
level = curLevel - 1;
name = "1";
}
if (result != -1) {
if (level >= 0) {
CallFrame *framePtr;
for (framePtr = iPtr->varFramePtr; framePtr != NULL;
framePtr = framePtr->callerVarPtr) {
if (framePtr->level == level) {
*framePtrPtr = framePtr;
return result;
}
}
|
| ︙ | | | ︙ | |