Tcl Source Code

Check-in [63de804c96]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:
* generic/tclVar.c: simplify tclLocalVarNameType, removing the reference to the corresponding proc. The reference is now seen as unnecessary, and it may cause leaking circular references under some circumstances (see for example [Bug 994838]).
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 63de804c9648dfa8ecc709d7bbf296ba4b347782
User & Date: msofer 2004-07-23 18:32:00
Context
2004-07-25
22:06
* tests/io.test: Make io-61.1 create file as binary to pass on Win32 check-in: fc89b74eed user: patthoyts tags: trunk
2004-07-23
18:32
* generic/tclVar.c: simplify tclLocalVarNameType, removing the reference to the corresponding proc...
check-in: 63de804c96 user: msofer tags: trunk
16:27
formatting check-in: de6666f396 user: dgp tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ChangeLog.








1
2
3
4
5
6
7







2004-07-22  Don Porter  <[email protected]>

        * tests/eofchar.data (removed): Test io-61.1 now generates its own
        * tests/io.test:        file of test data as needed.

2004-07-20  Jeff Hobbs  <[email protected]>

>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
2004-07-23  Miguel Sofer <[email protected]>

	* generic/tclVar.c: simplify tclLocalVarNameType, removing the
	reference to the corresponding proc. The reference is now seen as
	unnecessary, and it may cause leaking circular references under
	some circumstances (see for example [Bug 994838]).

2004-07-22  Don Porter  <[email protected]>

        * tests/eofchar.data (removed): Test io-61.1 now generates its own
        * tests/io.test:        file of test data as needed.

2004-07-20  Jeff Hobbs  <[email protected]>

Changes to generic/tclVar.c.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclVar.c,v 1.86 2004/05/27 20:44:37 msofer Exp $
 */

#ifdef STDC_HEADERS
#include <stddef.h>
#else
typedef int ptrdiff_t;
#endif







|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998-1999 by Scriptics Corporation.
 * Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: tclVar.c,v 1.87 2004/07/23 18:32:06 msofer Exp $
 */

#ifdef STDC_HEADERS
#include <stddef.h>
#else
typedef int ptrdiff_t;
#endif
68
69
70
71
72
73
74
75
76
77
78
79
80



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136

Var *		TclLookupSimpleVar _ANSI_ARGS_((Tcl_Interp *interp,
		    CONST char *varName, int flags, CONST int create,
		    CONST char **errMsgPtr, int *indexPtr));
int		TclObjUnsetVar2 _ANSI_ARGS_((Tcl_Interp *interp,
		    Tcl_Obj *part1Ptr, CONST char *part2, int flags));

static Tcl_FreeInternalRepProc FreeLocalVarName;
static Tcl_DupInternalRepProc DupLocalVarName;
static Tcl_UpdateStringProc UpdateLocalVarName;
static Tcl_FreeInternalRepProc FreeParsedVarName;
static Tcl_DupInternalRepProc DupParsedVarName;
static Tcl_UpdateStringProc UpdateParsedVarName;




/*
 * Types of Tcl_Objs used to cache variable lookups.
 *
 * 
 * localVarName - INTERNALREP DEFINITION:
 *   twoPtrValue.ptr1 = pointer to the corresponding Proc 
 *   twoPtrValue.ptr2 = index into locals table
 *
 * nsVarName - INTERNALREP DEFINITION:
 *   twoPtrValue.ptr1: pointer to the namespace containing the 
 *                     reference
 *   twoPtrValue.ptr2: pointer to the corresponding Var 
 *
 * parsedVarName - INTERNALREP DEFINITION:
 *   twoPtrValue.ptr1 = pointer to the array name Tcl_Obj, 
 *                      or NULL if it is a scalar variable
 *   twoPtrValue.ptr2 = pointer to the element name string
 *                      (owned by this Tcl_Obj), or NULL if 
 *                      it is a scalar variable
 */

Tcl_ObjType tclLocalVarNameType = {
    "localVarName",
    FreeLocalVarName, DupLocalVarName, UpdateLocalVarName, NULL
};

/*
 * Caching of namespace variables disabled: no simple way was found to
 * avoid interfering with the resolver's idea of variable existence.
 * A cached varName may keep a variable's name in the namespace's hash
 * table, which is the resolver's criterion for existence (see test
 * namespace-17.10).
 */	
#define ENABLE_NS_VARNAME_CACHING 0

#if ENABLE_NS_VARNAME_CACHING
static Tcl_FreeInternalRepProc FreeNsVarName;
static Tcl_DupInternalRepProc DupNsVarName;

Tcl_ObjType tclNsVarNameType = {
    "namespaceVarName",
    FreeNsVarName, DupNsVarName, NULL, NULL
};
#endif

Tcl_ObjType tclParsedVarNameType = {
    "parsedVarName",
    FreeParsedVarName, DupParsedVarName, UpdateParsedVarName, NULL
};

/*
 * Type of Tcl_Objs used to speed up array searches.
 *
 * INTERNALREP DEFINITION:
 *   twoPtrValue.ptr1 = searchIdNumber as offset from (char*)NULL







<

<



>
>
>






<
|
















|

















|





|







68
69
70
71
72
73
74

75

76
77
78
79
80
81
82
83
84
85
86
87

88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136

Var *		TclLookupSimpleVar _ANSI_ARGS_((Tcl_Interp *interp,
		    CONST char *varName, int flags, CONST int create,
		    CONST char **errMsgPtr, int *indexPtr));
int		TclObjUnsetVar2 _ANSI_ARGS_((Tcl_Interp *interp,
		    Tcl_Obj *part1Ptr, CONST char *part2, int flags));


static Tcl_DupInternalRepProc DupLocalVarName;

static Tcl_FreeInternalRepProc FreeParsedVarName;
static Tcl_DupInternalRepProc DupParsedVarName;
static Tcl_UpdateStringProc UpdateParsedVarName;

static Tcl_UpdateStringProc PanicOnUpdateVarName;
static Tcl_SetFromAnyProc PanicOnSetVarName;

/*
 * Types of Tcl_Objs used to cache variable lookups.
 *
 * 
 * localVarName - INTERNALREP DEFINITION:

 *   longValue = index into locals table
 *
 * nsVarName - INTERNALREP DEFINITION:
 *   twoPtrValue.ptr1: pointer to the namespace containing the 
 *                     reference
 *   twoPtrValue.ptr2: pointer to the corresponding Var 
 *
 * parsedVarName - INTERNALREP DEFINITION:
 *   twoPtrValue.ptr1 = pointer to the array name Tcl_Obj, 
 *                      or NULL if it is a scalar variable
 *   twoPtrValue.ptr2 = pointer to the element name string
 *                      (owned by this Tcl_Obj), or NULL if 
 *                      it is a scalar variable
 */

Tcl_ObjType tclLocalVarNameType = {
    "localVarName",
    NULL, DupLocalVarName, PanicOnUpdateVarName, PanicOnSetVarName
};

/*
 * Caching of namespace variables disabled: no simple way was found to
 * avoid interfering with the resolver's idea of variable existence.
 * A cached varName may keep a variable's name in the namespace's hash
 * table, which is the resolver's criterion for existence (see test
 * namespace-17.10).
 */	
#define ENABLE_NS_VARNAME_CACHING 0

#if ENABLE_NS_VARNAME_CACHING
static Tcl_FreeInternalRepProc FreeNsVarName;
static Tcl_DupInternalRepProc DupNsVarName;

Tcl_ObjType tclNsVarNameType = {
    "namespaceVarName",
    FreeNsVarName, DupNsVarName, PanicOnUpdateVarName, PanicOnSetVarName
};
#endif

Tcl_ObjType tclParsedVarNameType = {
    "parsedVarName",
    FreeParsedVarName, DupParsedVarName, UpdateParsedVarName, PanicOnSetVarName
};

/*
 * Type of Tcl_Objs used to speed up array searches.
 *
 * INTERNALREP DEFINITION:
 *   twoPtrValue.ptr1 = searchIdNumber as offset from (char*)NULL
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427

    nsPtr = ((varFramePtr == NULL)? iPtr->globalNsPtr : varFramePtr->nsPtr);
    if (nsPtr->varResProc != NULL || iPtr->resolverPtr != NULL) {
	goto doParse;
    }
    
    if (typePtr == &tclLocalVarNameType) {
	Proc *procPtr = (Proc *) part1Ptr->internalRep.twoPtrValue.ptr1;
	ptrdiff_t localIndex = (ptrdiff_t) part1Ptr->internalRep.twoPtrValue.ptr2;
	int useLocal;

	useLocal = ((varFramePtr != NULL) && varFramePtr->isProcCallFrame
	        && !(flags & (TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY)));
	if (useLocal && (procPtr == varFramePtr->procPtr)) {
	    /*
	     * part1Ptr points to an indexed local variable of the
	     * correct procedure: use the cached value if the names
	     * coincide.
	     */
	    
	    varPtr = &(varFramePtr->compiledLocals[localIndex]);
	    if ((varPtr->name != NULL)
		    && (strcmp(part1, varPtr->name) == 0)) {
		goto donePart1;
	    }







|
<
<

|
|
|

<
|
<







403
404
405
406
407
408
409
410


411
412
413
414
415

416

417
418
419
420
421
422
423

    nsPtr = ((varFramePtr == NULL)? iPtr->globalNsPtr : varFramePtr->nsPtr);
    if (nsPtr->varResProc != NULL || iPtr->resolverPtr != NULL) {
	goto doParse;
    }
    
    if (typePtr == &tclLocalVarNameType) {
	int localIndex = (int) part1Ptr->internalRep.longValue;



	if ((varFramePtr != NULL) && varFramePtr->isProcCallFrame
	        && !(flags & (TCL_GLOBAL_ONLY | TCL_NAMESPACE_ONLY))
		&& (localIndex < varFramePtr->numCompiledLocals)) {
	    /*

	     * use the cached index if the names coincide.

	     */
	    
	    varPtr = &(varFramePtr->compiledLocals[localIndex]);
	    if ((varPtr->name != NULL)
		    && (strcmp(part1, varPtr->name) == 0)) {
		goto donePart1;
	    }
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
	 * An indexed local variable.
	 */

	Proc *procPtr = ((Interp *) interp)->varFramePtr->procPtr;

	part1Ptr->typePtr = &tclLocalVarNameType;
	procPtr->refCount++;
	part1Ptr->internalRep.twoPtrValue.ptr1 = (VOID *) procPtr;
	part1Ptr->internalRep.twoPtrValue.ptr2 = (VOID *)(ptrdiff_t) index;
#if ENABLE_NS_VARNAME_CACHING
    } else if (index > -3) {
	/*
	 * A cacheable namespace or global variable.
	 */
	Namespace *nsPtr;
    







|
<







552
553
554
555
556
557
558
559

560
561
562
563
564
565
566
	 * An indexed local variable.
	 */

	Proc *procPtr = ((Interp *) interp)->varFramePtr->procPtr;

	part1Ptr->typePtr = &tclLocalVarNameType;
	procPtr->refCount++;
	part1Ptr->internalRep.longValue = (long) index;

#if ENABLE_NS_VARNAME_CACHING
    } else if (index > -3) {
	/*
	 * A cacheable namespace or global variable.
	 */
	Namespace *nsPtr;
    
4575
4576
4577
4578
4579
4580
4581























4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
/*
 *----------------------------------------------------------------------
 *
 * Internal functions for variable name object types --
 *
 *----------------------------------------------------------------------
 */
























/* 
 * localVarName -
 *
 * INTERNALREP DEFINITION:
 *   twoPtrValue.ptr1 = pointer to the corresponding Proc 
 *   twoPtrValue.ptr2 = index into locals table
 */

static void 
FreeLocalVarName(objPtr)
    Tcl_Obj *objPtr;
{
    register Proc *procPtr = (Proc *) objPtr->internalRep.twoPtrValue.ptr1;
    procPtr->refCount--;
    if (procPtr->refCount <= 0) {
	TclProcCleanupProc(procPtr);
    }
}

static void
DupLocalVarName(srcPtr, dupPtr)
    Tcl_Obj *srcPtr;
    Tcl_Obj *dupPtr;
{
    register Proc *procPtr = (Proc *) srcPtr->internalRep.twoPtrValue.ptr1;

    dupPtr->internalRep.twoPtrValue.ptr1 = (VOID *) procPtr;
    dupPtr->internalRep.twoPtrValue.ptr2 = srcPtr->internalRep.twoPtrValue.ptr2;
    procPtr->refCount++;
    dupPtr->typePtr = &tclLocalVarNameType;
}

static void
UpdateLocalVarName(objPtr)
    Tcl_Obj *objPtr;
{
    Proc *procPtr = (Proc *) objPtr->internalRep.twoPtrValue.ptr1;
    ptrdiff_t index = (ptrdiff_t) objPtr->internalRep.twoPtrValue.ptr2;
    CompiledLocal *localPtr = procPtr->firstLocalPtr;
    unsigned int nameLen;

    if (localPtr == NULL) {
	goto emptyName;
    }
    while (index--) {
	localPtr = localPtr->nextPtr;
	if (localPtr == NULL) {
	    goto emptyName;
	}
    }

    nameLen = (unsigned int) localPtr->nameLength;
    objPtr->bytes = ckalloc(nameLen + 1);
    memcpy(objPtr->bytes, localPtr->name, nameLen + 1);
    objPtr->length = nameLen;
    return;

    emptyName:
    objPtr->bytes = ckalloc(1);
    *(objPtr->bytes) = '\0';
    objPtr->length = 0;
}

#if ENABLE_NS_VARNAME_CACHING
/* 
 * nsVarName -
 *
 * INTERNALREP DEFINITION:
 *   twoPtrValue.ptr1: pointer to the namespace containing the 
 *                     reference.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





<
|


<
<
<
<
<
<
<
<
<
<
<





<
<
|
<
<



<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604

4605
4606
4607











4608
4609
4610
4611
4612


4613


4614
4615
4616































4617
4618
4619
4620
4621
4622
4623
/*
 *----------------------------------------------------------------------
 *
 * Internal functions for variable name object types --
 *
 *----------------------------------------------------------------------
 */

/*
 * Panic functions that should never be called in normal
 * operation.
 */

static void
PanicOnUpdateVarName(objPtr)
    Tcl_Obj *objPtr;
{
    Tcl_Panic("ERROR: updateStringProc of type %s should not be called.",
	    objPtr->typePtr->name);
}

static int
PanicOnSetVarName(interp, objPtr)
    Tcl_Interp *interp;
    Tcl_Obj *objPtr;
{
    Tcl_Panic("ERROR: setFromAnyProc of type %s should not be called.",
	    objPtr->typePtr->name);
    return TCL_ERROR;
}

/* 
 * localVarName -
 *
 * INTERNALREP DEFINITION:

 *   longValue = index into locals table
 */












static void
DupLocalVarName(srcPtr, dupPtr)
    Tcl_Obj *srcPtr;
    Tcl_Obj *dupPtr;
{


    dupPtr->internalRep.longValue = srcPtr->internalRep.longValue;


    dupPtr->typePtr = &tclLocalVarNameType;
}
































#if ENABLE_NS_VARNAME_CACHING
/* 
 * nsVarName -
 *
 * INTERNALREP DEFINITION:
 *   twoPtrValue.ptr1: pointer to the namespace containing the 
 *                     reference.