Itcl - the [incr Tcl] extension

Check-in [3f5de3c16d]
Login

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

Overview
Comment:
* itcl/generic/itclInt.h: * itcl/generic/itcl_class.c: * itcl/generic/itcl_cmds.c: * itcl/generic/itcl_methods.c: * itcl/generic/itcl_migrate.c: * itcl/generic/itcl_objects.c: * itcl/generic/itcl_parse.c: * itcl/generic/itcl_util.c: Adaptation to Tcl's VarReform. When compiled against 8.4 headers, itcl/itk will also run under 8.5. Patch from [Bug 1766617]
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 3f5de3c16d2e10431799fda4b642c82ee44a91c5
User & Date: msofer 2007-08-07 20:05:29
References
2015-01-28
03:47 Ticket [427ff95a38] namespace which crashes Itcl 3.4.2 (against Tcl 8.5+) status still Open with 3 other changes artifact: 6b4c718091 user: anonymous
Context
2007-09-06
21:37
Small change to how compiler flag are built-up. Stubs library doesn't have stuff it doesn't need and now take $(OPTDEFINES) from the top rules.vc check-in: b50561d555 user: davygrvy tags: trunk
2007-08-07
20:05
* itcl/generic/itclInt.h: * itcl/generic/itcl_class.c: * itcl/generic/itcl_cmds.c: * itcl/generic/itcl_methods.c: * itcl/generic/itcl_migrate.c: * itcl/generic/itcl_objects.c: * itcl/generic/itcl_parse.c: * itcl/generic/itcl_util.c: Adaptation to Tcl's VarReform. When compiled against 8.4 headers, itcl/itk will also run under 8.5. Patch from [Bug 1766617]
check-in: 3f5de3c16d user: msofer tags: trunk
2007-08-03
18:56
* itcl/generic/itcl_parse.c (Itcl_ClassCommonCmd): plug leak of pre-existing variables being declared as common
check-in: bfc09a1ebb user: msofer tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/itclInt.h.

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59





60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
 *  
 * ========================================================================
 *  AUTHOR:  Michael J. McLennan
 *           Bell Labs Innovations for Lucent Technologies
 *           [email protected]
 *           http://www.tcltk.com/itcl
 *
 *     RCS:  $Id: itclInt.h,v 1.16 2007/07/03 23:11:24 hobbs Exp $
 * ========================================================================
 *           Copyright (c) 1993-1998  Lucent Technologies, Inc.
 * ------------------------------------------------------------------------
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */
#ifndef ITCLINT_H
#define ITCLINT_H

#include "tclInt.h"
#include "itcl.h"

#ifdef BUILD_itcl
# undef TCL_STORAGE_CLASS
# define TCL_STORAGE_CLASS DLLEXPORT
#endif






/*
 * Fix Tcl bug #803489 the right way.  We need to always use the old Stub
 * slot positions, not the new broken ones part of TIP 127.  I do like
 * that these functions have moved to the public space (about time), but
 * the slot change is the killer and is the painful side affect.
 */

#if defined(USE_TCL_STUBS) && \
	(TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION >= 5)
#   undef Tcl_CreateNamespace
#   define Tcl_CreateNamespace \
	(tclIntStubsPtr->tcl_CreateNamespace)
#   undef Tcl_DeleteNamespace
#   define Tcl_DeleteNamespace \
	(tclIntStubsPtr->tcl_DeleteNamespace)
#   undef Tcl_AppendExportList







|

















>
>
>
>
>







<
<







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71


72
73
74
75
76
77
78
 *  
 * ========================================================================
 *  AUTHOR:  Michael J. McLennan
 *           Bell Labs Innovations for Lucent Technologies
 *           [email protected]
 *           http://www.tcltk.com/itcl
 *
 *     RCS:  $Id: itclInt.h,v 1.17 2007/08/07 20:05:29 msofer Exp $
 * ========================================================================
 *           Copyright (c) 1993-1998  Lucent Technologies, Inc.
 * ------------------------------------------------------------------------
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */
#ifndef ITCLINT_H
#define ITCLINT_H

#include "tclInt.h"
#include "itcl.h"

#ifdef BUILD_itcl
# undef TCL_STORAGE_CLASS
# define TCL_STORAGE_CLASS DLLEXPORT
#endif

#define ITCL_TCL_PRE_8_5 (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION < 5)

#if !ITCL_TCL_PRE_8_5
#if (USE_TCL_STUBS)

/*
 * Fix Tcl bug #803489 the right way.  We need to always use the old Stub
 * slot positions, not the new broken ones part of TIP 127.  I do like
 * that these functions have moved to the public space (about time), but
 * the slot change is the killer and is the painful side affect.
 */



#   undef Tcl_CreateNamespace
#   define Tcl_CreateNamespace \
	(tclIntStubsPtr->tcl_CreateNamespace)
#   undef Tcl_DeleteNamespace
#   define Tcl_DeleteNamespace \
	(tclIntStubsPtr->tcl_DeleteNamespace)
#   undef Tcl_AppendExportList
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
137
138
139
140
141
142
143
144
145

146
147























































































148










149
150
151
152
153
154
155
	(tclIntStubsPtr->tcl_FindCommand)
#   undef Tcl_GetCommandFromObj
#   define Tcl_GetCommandFromObj \
	(tclIntStubsPtr->tcl_GetCommandFromObj)
#   undef Tcl_GetCommandFullName
#   define Tcl_GetCommandFullName \
	(tclIntStubsPtr->tcl_GetCommandFullName)


/*
 * Use 8.5+ CallFrame
 */

#define ItclCallFrame CallFrame
#define Itcl_CallFrame Tcl_CallFrame



#else



















/*
 * Redefine CallFrame to account for extra ClientData in 8.5.
 * Make sure that standard CallFrame comes first.
 */

typedef struct ItclCallFrame {
    Namespace *nsPtr;
    int isProcCallFrame;
    int objc;
    Tcl_Obj *CONST *objv;
    struct CallFrame *callerPtr;
    struct CallFrame *callerVarPtr;
    int level;
    Proc *procPtr;
    Tcl_HashTable *varTablePtr;
    int numCompiledLocals;
    Var* compiledLocals;
    ClientData clientData;

} ItclCallFrame;

typedef struct Itcl_CallFrame {
    Tcl_Namespace *nsPtr;
    int dummy1;
    int dummy2;
    char *dummy3;
    char *dummy4;
    char *dummy5;
    int dummy6;
    char *dummy7;
    char *dummy8;
    int dummy9;
    char *dummy10;
    char *dummy11;

} Itcl_CallFrame;
























































































#endif











/*
 * Some backward compatability adjustments.
 */

#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0
#   define Tcl_GetString(obj)	Tcl_GetStringFromObj((obj), NULL)







>




>



>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





>













>















>


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

>
>
>
>
>
>
>
>
>
>







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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
	(tclIntStubsPtr->tcl_FindCommand)
#   undef Tcl_GetCommandFromObj
#   define Tcl_GetCommandFromObj \
	(tclIntStubsPtr->tcl_GetCommandFromObj)
#   undef Tcl_GetCommandFullName
#   define Tcl_GetCommandFullName \
	(tclIntStubsPtr->tcl_GetCommandFullName)
#endif /* use stubs */

/*
 * Use 8.5+ CallFrame
 */

#define ItclCallFrame CallFrame
#define Itcl_CallFrame Tcl_CallFrame

#define ItclInitVarFlags(varPtr) \
    (varPtr)->flags = 0

#define ItclInitVarArgument(varPtr) \
   (varPtr)->flags = VAR_ARGUMENT 

#define ItclVarHashCreateVar(tablePtr, key, newPtr) \
    TclVarHashCreateVar((tablePtr), (key), (newPtr))

#define ItclVarRefCount(varPtr) VarHashRefCount(varPtr)

#define ItclClearVarUndefined(varPtr)

#define ItclNextLocal(varPtr) ((varPtr)++)

#define ItclVarObjValue(varPtr) ((varPtr)->value.objPtr)

#define itclVarInHashSize sizeof(VarInHash)
#define itclVarLocalSize  sizeof(Var)

#else /* Compiling on Tcl8.x, x<5 */ 

/*
 * Redefine CallFrame to account for extra ClientData in 8.5.
 * Make sure that standard CallFrame comes first.
 */

typedef struct ItclCallFrame {
    Namespace *nsPtr;
    int isProcCallFrame;
    int objc;
    Tcl_Obj *CONST *objv;
    struct CallFrame *callerPtr;
    struct CallFrame *callerVarPtr;
    int level;
    Proc *procPtr;
    Tcl_HashTable *varTablePtr;
    int numCompiledLocals;
    Var* compiledLocals;
    ClientData clientData;
    struct localCache *localCachePtr;
} ItclCallFrame;

typedef struct Itcl_CallFrame {
    Tcl_Namespace *nsPtr;
    int dummy1;
    int dummy2;
    char *dummy3;
    char *dummy4;
    char *dummy5;
    int dummy6;
    char *dummy7;
    char *dummy8;
    int dummy9;
    char *dummy10;
    char *dummy11;
    char *dummy12;
} Itcl_CallFrame;

/*
 * Definition of runtime behaviour to be able to run irrespective of the Tcl
 * version.
 */

#define VarInHash Var

#define TclVarHashTable Tcl_HashTable

typedef struct ItclShortVar {
    int flags;
    union {
	Tcl_Obj *objPtr;
	TclVarHashTable *tablePtr;
	struct Var *linkPtr;
    } value;
} ItclShortVar;

typedef struct ItclVarInHash {
    ItclShortVar var;
    int refCount;
    Tcl_HashEntry entry;
} ItclVarInHash;

#define ItclOffset(type, field) ((int) ((char *) &((type *) 0)->field))

#define itclOldRuntime (itclVarFlagOffset!=0)

extern int itclVarFlagOffset; 
extern int itclVarRefCountOffset;
extern int itclVarInHashSize;
extern int itclVarLocalSize;
extern int itclVarValueOffset;

/*
 * VarReform related macros: provide access to the Var fields with offsets
 * determined at load time, so that the same code copes with the different
 * structs in Tcl8.5 and previous Tcl.
 */

#define ItclNextLocal(varPtr) \
    ((varPtr) = (Var *) (((char *)(varPtr))+itclVarLocalSize))

#define ItclVarObjValue(varPtr) \
    (*((Tcl_Obj **) (((char *)(varPtr))+itclVarValueOffset)))

#define ItclVarRefCount(varPtr) \
    (*((int *) (((char *)(varPtr))+itclVarRefCountOffset)))

#define ItclVarFlags(varPtr) \
    (*((int *)(((char *)(varPtr))+itclVarFlagOffset)))

/* Note that itclVarFlagOffset==0 exactly when we are running in Tcl8.5 */
#define ItclInitVarFlags(varPtr) \
    if (itclOldRuntime) { \
	(varPtr)->flags = (VAR_SCALAR | VAR_UNDEFINED | VAR_IN_HASHTABLE);\
    } else { \
        ((ItclShortVar *)(varPtr))->flags = 0;\
    }

/* This is used for CompiledLocal, not for Var & Co. That struct did not
 * change, but the correct flag init did! The flags bits themselves are
 * unchanged */

#define ItclInitVarArgument(varPtr) \
    if (itclOldRuntime) { \
	(varPtr)->flags = (VAR_SCALAR | VAR_ARGUMENT);\
    } else { \
	(varPtr)->flags = VAR_ARGUMENT;\
    }

#define TclIsVarNamespaceVar(varPtr) \
    (ItclVarFlags(varPtr) & VAR_NAMESPACE_VAR)

#define TclSetVarNamespaceVar(varPtr) \
    if (!TclIsVarNamespaceVar(varPtr)) {\
        ItclVarFlags(varPtr) |= VAR_NAMESPACE_VAR;\
        ItclVarRefCount(varPtr)++;\
    }

#define ItclClearVarUndefined(varPtr) \
    if (itclOldRuntime) { \
	ItclVarFlags(varPtr) &= ~VAR_UNDEFINED;\
    }

#ifndef MODULE_SCOPE
#define MODULE_SCOPE
#endif

MODULE_SCOPE Var * ItclVarHashCreateVar (TclVarHashTable * tablePtr, 
				const char * key, int * newPtr);

#endif /* Version dependent defs and macros */


#define ItclVarHashFindVar(tablePtr, key) \
    ItclVarHashCreateVar((tablePtr), (key), NULL)


/*
 * Some backward compatability adjustments.
 */

#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0
#   define Tcl_GetString(obj)	Tcl_GetStringFromObj((obj), NULL)
347
348
349
350
351
352
353



354
355
356
357
358
359
360
    Var localStorage[20];     /* default storage for compiled locals */
} ItclContext;

/*
 *  Compatibility flags.  Used to support small "hacks".  These are stored
 *  in the global variable named itclCompatFlags.
 */



#define ITCL_COMPAT_USECMDFLAGS 0x0001	/* Tcl8.4a1 introduced a different Command
					 * structure, and we need to adapt
					 * dynamically */
#define ITCL_COMPAT_USE_ISTATE_API 0x2  /* Tcl 8.5a2 added interp state APIs */

#include "itclIntDecls.h"








>
>
>







472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
    Var localStorage[20];     /* default storage for compiled locals */
} ItclContext;

/*
 *  Compatibility flags.  Used to support small "hacks".  These are stored
 *  in the global variable named itclCompatFlags.
 */

extern int itclCompatFlags;

#define ITCL_COMPAT_USECMDFLAGS 0x0001	/* Tcl8.4a1 introduced a different Command
					 * structure, and we need to adapt
					 * dynamically */
#define ITCL_COMPAT_USE_ISTATE_API 0x2  /* Tcl 8.5a2 added interp state APIs */

#include "itclIntDecls.h"

Changes to generic/itcl_class.c.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 *
 * ========================================================================
 *  AUTHOR:  Michael J. McLennan
 *           Bell Labs Innovations for Lucent Technologies
 *           [email protected]
 *           http://www.tcltk.com/itcl
 *
 *     RCS:  $Id: itcl_class.c,v 1.23 2007/07/03 20:46:44 hobbs Exp $
 * ========================================================================
 *           Copyright (c) 1993-1998  Lucent Technologies, Inc.
 * ------------------------------------------------------------------------
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */
#include "itclInt.h"







|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 *
 * ========================================================================
 *  AUTHOR:  Michael J. McLennan
 *           Bell Labs Innovations for Lucent Technologies
 *           [email protected]
 *           http://www.tcltk.com/itcl
 *
 *     RCS:  $Id: itcl_class.c,v 1.24 2007/08/07 20:05:29 msofer Exp $
 * ========================================================================
 *           Copyright (c) 1993-1998  Lucent Technologies, Inc.
 * ------------------------------------------------------------------------
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */
#include "itclInt.h"
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530




531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
 */
static void
ItclFreeClass(cdata)
    char *cdata;  /* class definition to be destroyed */
{
    ItclClass *cdefnPtr = (ItclClass*)cdata;

    int newEntry;
    Itcl_ListElem *elem;
    Tcl_HashSearch place;
    Tcl_HashEntry *entry, *hPtr;
    ItclVarDefn *vdefn;
    ItclVarLookup *vlookup;
    Var *varPtr;
    Tcl_HashTable varTable;

    /*
     *  Tear down the list of derived classes.  This list should
     *  really be empty if everything is working properly, but
     *  release it here just in case.
     */
    elem = Itcl_FirstListElem(&cdefnPtr->derived);
    while (elem) {
        Itcl_ReleaseData( Itcl_GetListValue(elem) );
        elem = Itcl_NextListElem(elem);
    }
    Itcl_DeleteList(&cdefnPtr->derived);

    /*
     *  Tear down the variable resolution table.  Some records
     *  appear multiple times in the table (for x, foo::x, etc.)
     *  so each one has a reference count.
     */
    Tcl_InitHashTable(&varTable, TCL_STRING_KEYS);

    entry = Tcl_FirstHashEntry(&cdefnPtr->resolveVars, &place);
    while (entry) {
        vlookup = (ItclVarLookup*)Tcl_GetHashValue(entry);
        if (--vlookup->usage == 0) {
            /*
             *  If this is a common variable owned by this class,
             *  then release the class's hold on it.  If it's no
             *  longer being used, move it into a variable table
             *  for destruction.
             */
            if ( (vlookup->vdefn->member->flags & ITCL_COMMON) != 0 &&
                 vlookup->vdefn->member->classDefn == cdefnPtr ) {
                varPtr = (Var*)vlookup->var.common;
                if (--varPtr->refCount == 0) {




                    hPtr = Tcl_CreateHashEntry(&varTable,
                        vlookup->vdefn->member->fullname, &newEntry);
                    Tcl_SetHashValue(hPtr, (ClientData) varPtr);
                }
            }
            ckfree((char*)vlookup);
        }
        entry = Tcl_NextHashEntry(&place);
    }

    TclDeleteVars((Interp*)cdefnPtr->interp, &varTable);
    Tcl_DeleteHashTable(&cdefnPtr->resolveVars);

    /*
     *  Tear down the virtual method table...
     */
    Tcl_DeleteHashTable(&cdefnPtr->resolveCmds);








<


|


|
<


















<













|
|
>
>
>
>
|
<
|






<
<







482
483
484
485
486
487
488

489
490
491
492
493
494

495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512

513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532

533
534
535
536
537
538
539


540
541
542
543
544
545
546
 */
static void
ItclFreeClass(cdata)
    char *cdata;  /* class definition to be destroyed */
{
    ItclClass *cdefnPtr = (ItclClass*)cdata;


    Itcl_ListElem *elem;
    Tcl_HashSearch place;
    Tcl_HashEntry *entry;
    ItclVarDefn *vdefn;
    ItclVarLookup *vlookup;
    VarInHash *varPtr;


    /*
     *  Tear down the list of derived classes.  This list should
     *  really be empty if everything is working properly, but
     *  release it here just in case.
     */
    elem = Itcl_FirstListElem(&cdefnPtr->derived);
    while (elem) {
        Itcl_ReleaseData( Itcl_GetListValue(elem) );
        elem = Itcl_NextListElem(elem);
    }
    Itcl_DeleteList(&cdefnPtr->derived);

    /*
     *  Tear down the variable resolution table.  Some records
     *  appear multiple times in the table (for x, foo::x, etc.)
     *  so each one has a reference count.
     */


    entry = Tcl_FirstHashEntry(&cdefnPtr->resolveVars, &place);
    while (entry) {
        vlookup = (ItclVarLookup*)Tcl_GetHashValue(entry);
        if (--vlookup->usage == 0) {
            /*
             *  If this is a common variable owned by this class,
             *  then release the class's hold on it.  If it's no
             *  longer being used, move it into a variable table
             *  for destruction.
             */
            if ( (vlookup->vdefn->member->flags & ITCL_COMMON) != 0 &&
                 vlookup->vdefn->member->classDefn == cdefnPtr ) {
                varPtr = (VarInHash*)vlookup->var.common;
                if (--ItclVarRefCount(varPtr) == 0) {
		    /*
		     * This is called after the namespace is already gone: the
		     * variable is already unset and ready to be freed.
		     */
		    

		    ckfree((char *)varPtr);
                }
            }
            ckfree((char*)vlookup);
        }
        entry = Tcl_NextHashEntry(&place);
    }


    Tcl_DeleteHashTable(&cdefnPtr->resolveVars);

    /*
     *  Tear down the virtual method table...
     */
    Tcl_DeleteHashTable(&cdefnPtr->resolveCmds);

1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
            CompiledLocal *localPtr = procPtr->firstLocalPtr;
            Var *localVarPtr = varFramePtr->compiledLocals;
            int nameLen = strlen(name);
            int i;

            for (i=0; i < localCt; i++) {
                if (!TclIsVarTemporary(localPtr)) {
                    register char *localName = localVarPtr->name;
                    if ((name[0] == localName[0])
                            && (nameLen == localPtr->nameLength)
                            && (strcmp(name, localName) == 0)) {
                        *rPtr = (Tcl_Var)localVarPtr;
                        return TCL_OK;
                    }
                }
                localVarPtr++;
                localPtr = localPtr->nextPtr;
            }
        }

        /*
         *  If it's not a compiled local, then look in the frame's
         *  var hash table next.  This variable may have been
         *  created on the fly.
         */
        if (varFramePtr->varTablePtr != NULL) {
            entry = Tcl_FindHashEntry(varFramePtr->varTablePtr, name);
            if (entry != NULL) {
                *rPtr = (Tcl_Var)Tcl_GetHashValue(entry);
                return TCL_OK;
            }
        }
    }

    /*
     *  See if the variable is a known data member and accessible.







|







|










|
|
<







1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118

1119
1120
1121
1122
1123
1124
1125
            CompiledLocal *localPtr = procPtr->firstLocalPtr;
            Var *localVarPtr = varFramePtr->compiledLocals;
            int nameLen = strlen(name);
            int i;

            for (i=0; i < localCt; i++) {
                if (!TclIsVarTemporary(localPtr)) {
                    register char *localName = localPtr->name;
                    if ((name[0] == localName[0])
                            && (nameLen == localPtr->nameLength)
                            && (strcmp(name, localName) == 0)) {
                        *rPtr = (Tcl_Var)localVarPtr;
                        return TCL_OK;
                    }
                }
                ItclNextLocal(localVarPtr);
                localPtr = localPtr->nextPtr;
            }
        }

        /*
         *  If it's not a compiled local, then look in the frame's
         *  var hash table next.  This variable may have been
         *  created on the fly.
         */
        if (varFramePtr->varTablePtr != NULL) {
	    *rPtr = (Tcl_Var) ItclVarHashFindVar(varFramePtr->varTablePtr, name);
	    if (*rPtr) {

                return TCL_OK;
            }
        }
    }

    /*
     *  See if the variable is a known data member and accessible.
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
 *  table will point to the most-specific member.
 * ------------------------------------------------------------------------
 */
void
Itcl_BuildVirtualTables(cdefnPtr)
    ItclClass* cdefnPtr;       /* class definition being updated */
{
    Tcl_HashEntry *entry, *hPtr;
    Tcl_HashSearch place;
    ItclVarLookup *vlookup;
    ItclVarDefn *vdefn;
    ItclMemberFunc *mfunc;
    ItclHierIter hier;
    ItclClass *cdPtr;
    Namespace* nsPtr;







|







1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
 *  table will point to the most-specific member.
 * ------------------------------------------------------------------------
 */
void
Itcl_BuildVirtualTables(cdefnPtr)
    ItclClass* cdefnPtr;       /* class definition being updated */
{
    Tcl_HashEntry *entry;
    Tcl_HashSearch place;
    ItclVarLookup *vlookup;
    ItclVarDefn *vdefn;
    ItclMemberFunc *mfunc;
    ItclHierIter hier;
    ItclClass *cdPtr;
    Namespace* nsPtr;
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
            /*
             *  If this is a common variable, then keep a reference to
             *  the variable directly.  Otherwise, keep an index into
             *  the object's variable table.
             */
            if ((vdefn->member->flags & ITCL_COMMON) != 0) {
                nsPtr = (Namespace*)cdPtr->namesp;
                hPtr = Tcl_FindHashEntry(&nsPtr->varTable, vdefn->member->name);
                assert(hPtr != NULL);

                vlookup->var.common = (Tcl_Var)Tcl_GetHashValue(hPtr);
            }
            else {
                /*
                 *  If this is a reference to the built-in "this"
                 *  variable, then its index is "0".  Otherwise,
                 *  add another slot to the end of the table.
                 */







|
<
<
|







1409
1410
1411
1412
1413
1414
1415
1416


1417
1418
1419
1420
1421
1422
1423
1424
            /*
             *  If this is a common variable, then keep a reference to
             *  the variable directly.  Otherwise, keep an index into
             *  the object's variable table.
             */
            if ((vdefn->member->flags & ITCL_COMMON) != 0) {
                nsPtr = (Namespace*)cdPtr->namesp;
                vlookup->var.common = (Tcl_Var) ItclVarHashFindVar(&nsPtr->varTable, vdefn->member->name);


                assert(vlookup->var.common  != NULL);
            }
            else {
                /*
                 *  If this is a reference to the built-in "this"
                 *  variable, then its index is "0".  Otherwise,
                 *  add another slot to the end of the table.
                 */

Changes to generic/itcl_cmds.c.

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 *
 * ========================================================================
 *  AUTHOR:  Michael J. McLennan
 *           Bell Labs Innovations for Lucent Technologies
 *           [email protected]
 *           http://www.tcltk.com/itcl
 *
 *     RCS:  $Id: itcl_cmds.c,v 1.30 2007/07/03 23:11:24 hobbs Exp $
 * ========================================================================
 *           Copyright (c) 1993-1998  Lucent Technologies, Inc.
 * ------------------------------------------------------------------------
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */
#include "itclInt.h"







|







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 *
 * ========================================================================
 *  AUTHOR:  Michael J. McLennan
 *           Bell Labs Innovations for Lucent Technologies
 *           [email protected]
 *           http://www.tcltk.com/itcl
 *
 *     RCS:  $Id: itcl_cmds.c,v 1.31 2007/08/07 20:05:30 msofer Exp $
 * ========================================================================
 *           Copyright (c) 1993-1998  Lucent Technologies, Inc.
 * ------------------------------------------------------------------------
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */
#include "itclInt.h"
106
107
108
109
110
111
112








113
114
115
116
117
118
119
    set cmd [uplevel namespace which -command $ptr]\n\
    uplevel [list trace variable itcl-local-$ptr u \"::itcl::delete object $cmd; list\"]\n\
    return $ptr\n\
}";

int itclCompatFlags = -1;










/*
 * ------------------------------------------------------------------------
 *  Initialize()
 *
 *  Invoked whenever a new interpeter is created to install the
 *  [incr Tcl] package.  Usually invoked within Tcl_AppInit() at







>
>
>
>
>
>
>
>







106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
    set cmd [uplevel namespace which -command $ptr]\n\
    uplevel [list trace variable itcl-local-$ptr u \"::itcl::delete object $cmd; list\"]\n\
    return $ptr\n\
}";

int itclCompatFlags = -1;

#if ITCL_TCL_PRE_8_5
int itclVarFlagOffset; 
int itclVarRefCountOffset;
int itclVarInHashSize;
int itclVarLocalSize;
int itclVarValueOffset;
#endif


/*
 * ------------------------------------------------------------------------
 *  Initialize()
 *
 *  Invoked whenever a new interpeter is created to install the
 *  [incr Tcl] package.  Usually invoked within Tcl_AppInit() at
172
173
174
175
176
177
178
179
180
181
182
183





















184
185
186
187
188
189
190
191

192
193
194
195
196
197
198
199
	    itclCompatFlags |= ITCL_COMPAT_USECMDFLAGS;
	}
#if USE_TCL_STUBS
	if ((maj == 8) && (min > 4) &&
		((type > TCL_ALPHA_RELEASE) || (ptch > 2))) {
	    itclCompatFlags |= ITCL_COMPAT_USE_ISTATE_API;
	}
#endif
    }
#else
    itclCompatFlags = 0;
#endif






















    /*
     *  Initialize the ensemble package first, since we need this
     *  for other parts of [incr Tcl].
     */
    if (Itcl_EnsembleInit(interp) != TCL_OK) {
        return TCL_ERROR;
    }


    /*
     *  Create the top-level data structure for tracking objects.
     *  Store this as "associated data" for easy access, but link
     *  it to the itcl namespace for ownership.
     */
    info = (ItclObjectInfo*)ckalloc(sizeof(ItclObjectInfo));
    info->interp = interp;







<
<



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








>
|







180
181
182
183
184
185
186


187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
	    itclCompatFlags |= ITCL_COMPAT_USECMDFLAGS;
	}
#if USE_TCL_STUBS
	if ((maj == 8) && (min > 4) &&
		((type > TCL_ALPHA_RELEASE) || (ptch > 2))) {
	    itclCompatFlags |= ITCL_COMPAT_USE_ISTATE_API;
	}


#else
    itclCompatFlags = 0;
#endif

#if ITCL_TCL_PRE_8_5
#if USE_TCL_STUBS
	if ((maj == 8) && (min < 5)) {
#endif
	    itclVarFlagOffset     = ItclOffset(Var, flags);
	    itclVarRefCountOffset = ItclOffset(Var, refCount);
	    itclVarValueOffset    = ItclOffset(Var, value);
	    itclVarInHashSize     = sizeof(Var);
	    itclVarLocalSize	  = sizeof(Var);
#if USE_TCL_STUBS
	} else {
	    itclVarFlagOffset     = ItclOffset(ItclShortVar, flags);
	    itclVarRefCountOffset = ItclOffset(ItclVarInHash, refCount);
	    itclVarValueOffset    = ItclOffset(ItclShortVar, value);
	    itclVarInHashSize     = sizeof(ItclVarInHash);
	    itclVarLocalSize	  = sizeof(ItclShortVar);  
	}
#endif
#endif
    }

    /*
     *  Initialize the ensemble package first, since we need this
     *  for other parts of [incr Tcl].
     */
    if (Itcl_EnsembleInit(interp) != TCL_OK) {
        return TCL_ERROR;
    }
#endif
    
    /*
     *  Create the top-level data structure for tracking objects.
     *  Store this as "associated data" for easy access, but link
     *  it to the itcl namespace for ownership.
     */
    info = (ItclObjectInfo*)ckalloc(sizeof(ItclObjectInfo));
    info->interp = interp;

Changes to generic/itcl_methods.c.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 *
 * ========================================================================
 *  AUTHOR:  Michael J. McLennan
 *           Bell Labs Innovations for Lucent Technologies
 *           [email protected]
 *           http://www.tcltk.com/itcl
 *
 *     RCS:  $Id: itcl_methods.c,v 1.20 2007/05/24 23:04:10 hobbs Exp $
 * ========================================================================
 *           Copyright (c) 1993-1998  Lucent Technologies, Inc.
 * ------------------------------------------------------------------------
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */
#include "itclInt.h"







|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 *
 * ========================================================================
 *  AUTHOR:  Michael J. McLennan
 *           Bell Labs Innovations for Lucent Technologies
 *           [email protected]
 *           http://www.tcltk.com/itcl
 *
 *     RCS:  $Id: itcl_methods.c,v 1.21 2007/08/07 20:05:30 msofer Exp $
 * ========================================================================
 *           Copyright (c) 1993-1998  Lucent Technologies, Inc.
 * ------------------------------------------------------------------------
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */
#include "itclInt.h"
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
     *  If the implementation has not yet been defined, try to
     *  autoload it now.
     */

    if (!Itcl_IsMemberCodeImplemented(mcode)) {
        result = Tcl_VarEval(interp, "::auto_load ", member->fullname,
            (char*)NULL);

        if (result != TCL_OK) {
            char msg[256];
            sprintf(msg, "\n    (while autoloading code for \"%.100s\")",
                member->fullname);
            Tcl_AddErrorInfo(interp, msg);
            return result;
        }







<







793
794
795
796
797
798
799

800
801
802
803
804
805
806
     *  If the implementation has not yet been defined, try to
     *  autoload it now.
     */

    if (!Itcl_IsMemberCodeImplemented(mcode)) {
        result = Tcl_VarEval(interp, "::auto_load ", member->fullname,
            (char*)NULL);

        if (result != TCL_OK) {
            char msg[256];
            sprintf(msg, "\n    (while autoloading code for \"%.100s\")",
                member->fullname);
            Tcl_AddErrorInfo(interp, msg);
            return result;
        }
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843

    /*
     *  If the member is a constructor and the class has an
     *  initialization command, compile it here.
     */
    if ((member->flags & ITCL_CONSTRUCTOR) != 0 &&
        (member->classDefn->initCode != NULL)) {

        result = TclProcCompileProc(interp, mcode->procPtr,
            member->classDefn->initCode, (Namespace*)member->classDefn->namesp,
            "initialization code for", member->fullname);

        if (result != TCL_OK) {
            return result;
        }







<







828
829
830
831
832
833
834

835
836
837
838
839
840
841

    /*
     *  If the member is a constructor and the class has an
     *  initialization command, compile it here.
     */
    if ((member->flags & ITCL_CONSTRUCTOR) != 0 &&
        (member->classDefn->initCode != NULL)) {

        result = TclProcCompileProc(interp, mcode->procPtr,
            member->classDefn->initCode, (Namespace*)member->classDefn->namesp,
            "initialization code for", member->fullname);

        if (result != TCL_OK) {
            return result;
        }
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
    localPtr = (CompiledLocal*)ckalloc(
        (unsigned)(sizeof(CompiledLocal)-sizeof(localPtr->name) + nameLen+1)
    );

    localPtr->nextPtr = NULL;
    localPtr->nameLength = nameLen;
    localPtr->frameIndex = 0;  /* set this later */
    localPtr->flags  = VAR_SCALAR | VAR_ARGUMENT;
    localPtr->resolveInfo = NULL;

    if (init != NULL) {
        localPtr->defValuePtr = Tcl_NewStringObj((CONST84 char *)init, -1);
        Tcl_IncrRefCount(localPtr->defValuePtr);
    } else {
        localPtr->defValuePtr = NULL;







|







1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
    localPtr = (CompiledLocal*)ckalloc(
        (unsigned)(sizeof(CompiledLocal)-sizeof(localPtr->name) + nameLen+1)
    );

    localPtr->nextPtr = NULL;
    localPtr->nameLength = nameLen;
    localPtr->frameIndex = 0;  /* set this later */
    ItclInitVarArgument(localPtr);
    localPtr->resolveInfo = NULL;

    if (init != NULL) {
        localPtr->defValuePtr = Tcl_NewStringObj((CONST84 char *)init, -1);
        Tcl_IncrRefCount(localPtr->defValuePtr);
    } else {
        localPtr->defValuePtr = NULL;
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688























1689
1690
1691
1692
1693
1694
1695
     *  Set up the compiled locals in the call frame and assign
     *  argument variables.
     */
    if (member) {
        mcode = member->code;
        procPtr = mcode->procPtr;

        /*
         *  If there are too many compiled locals to fit in the default
         *  storage space for the context, then allocate more space.
         */
        localCt = procPtr->numCompiledLocals;
        if (localCt > sizeof(contextPtr->localStorage)/sizeof(Var)) {
            contextPtr->compiledLocals = (Var*)ckalloc(
                (unsigned)(localCt * sizeof(Var))
            );
        }

        /*
         * Initialize and resolve compiled variable references.
         * Class variables will have special resolution rules.
         * In that case, we call their "resolver" procs to get our
         * hands on the variable, and we make the compiled local a
         * link to the real variable.
         */

        framePtr->procPtr = procPtr;
        framePtr->numCompiledLocals = localCt;
        framePtr->compiledLocals = contextPtr->compiledLocals;

        /*
         * Invoking TclInitCompiledLocals with a framePtr->procPtr->bodyPtr
         * that is not a compiled byte code type leads to a crash. So
         * make sure that the body is compiled here. This needs to
         * be done even if the body of the Itcl method is not implemented
         * as a Tcl proc or has no implementation. The empty string should
         * have been defined as the body if no implementation was defined.
         */
        assert(mcode->procPtr->bodyPtr != NULL);

        result = TclProcCompileProc(interp, mcode->procPtr,
            mcode->procPtr->bodyPtr, (Namespace*)member->classDefn->namesp,
            "body for", member->fullname);

        if (result != TCL_OK) {
            return result;
        }
























        TclInitCompiledLocals(interp, (CallFrame *) framePtr,
            (Namespace*)contextClass->namesp);
    }
    return result;
}









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


















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







1639
1640
1641
1642
1643
1644
1645























1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
     *  Set up the compiled locals in the call frame and assign
     *  argument variables.
     */
    if (member) {
        mcode = member->code;
        procPtr = mcode->procPtr;
























        /*
         * Invoking TclInitCompiledLocals with a framePtr->procPtr->bodyPtr
         * that is not a compiled byte code type leads to a crash. So
         * make sure that the body is compiled here. This needs to
         * be done even if the body of the Itcl method is not implemented
         * as a Tcl proc or has no implementation. The empty string should
         * have been defined as the body if no implementation was defined.
         */
        assert(mcode->procPtr->bodyPtr != NULL);

        result = TclProcCompileProc(interp, mcode->procPtr,
            mcode->procPtr->bodyPtr, (Namespace*)member->classDefn->namesp,
            "body for", member->fullname);

        if (result != TCL_OK) {
            return result;
        }

        /*
         *  If there are too many compiled locals to fit in the default
         *  storage space for the context, then allocate more space.
         */
        localCt = procPtr->numCompiledLocals;
        if (localCt > sizeof(contextPtr->localStorage)/itclVarLocalSize) {
            contextPtr->compiledLocals = (Var*)ckalloc(
                (unsigned)(localCt * itclVarLocalSize)
            );
        }

        /*
         * Initialize and resolve compiled variable references.
         * Class variables will have special resolution rules.
         * In that case, we call their "resolver" procs to get our
         * hands on the variable, and we make the compiled local a
         * link to the real variable.
         */

        framePtr->procPtr = procPtr;
        framePtr->numCompiledLocals = localCt;
        framePtr->compiledLocals = contextPtr->compiledLocals;

        TclInitCompiledLocals(interp, (CallFrame *) framePtr,
            (Namespace*)contextClass->namesp);
    }
    return result;
}


1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
     *  Match the actual arguments against the procedure's formal
     *  parameters to compute local variables.
     */
    varPtr = framePtr->compiledLocals;

    for (argsLeft=mcode->argcount, argPtr=mcode->arglist, objv++, objc--;
         argsLeft > 0;
         argPtr=argPtr->nextPtr, argsLeft--, varPtr++, objv++, objc--)
    {
        if (!TclIsVarArgument(argPtr)) {
            Tcl_Panic("local variable %s is not argument but should be",
                argPtr->name);
            return TCL_ERROR;
        }
        if (TclIsVarTemporary(argPtr)) {
            Tcl_Panic("local variable is temporary but should be an argument");
            return TCL_ERROR;
        }

        /*
         *  Handle the special case of the last formal being "args".
         *  When it occurs, assign it a list consisting of all the
         *  remaining actual arguments.
         */
        if ((argsLeft == 1) && (strcmp(argPtr->name, "args") == 0)) {
            if (objc < 0) objc = 0;

            listPtr = Tcl_NewListObj(objc, objv);
            varPtr->value.objPtr = listPtr;
            Tcl_IncrRefCount(listPtr); /* local var is a reference */
            varPtr->flags &= ~VAR_UNDEFINED;
            objc = 0;

            break;
        }

        /*
         *  Handle the special case of the last formal being "config".







|




















|

|







1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
     *  Match the actual arguments against the procedure's formal
     *  parameters to compute local variables.
     */
    varPtr = framePtr->compiledLocals;

    for (argsLeft=mcode->argcount, argPtr=mcode->arglist, objv++, objc--;
         argsLeft > 0;
         argPtr=argPtr->nextPtr, argsLeft--, ItclNextLocal(varPtr), objv++, objc--)
    {
        if (!TclIsVarArgument(argPtr)) {
            Tcl_Panic("local variable %s is not argument but should be",
                argPtr->name);
            return TCL_ERROR;
        }
        if (TclIsVarTemporary(argPtr)) {
            Tcl_Panic("local variable is temporary but should be an argument");
            return TCL_ERROR;
        }

        /*
         *  Handle the special case of the last formal being "args".
         *  When it occurs, assign it a list consisting of all the
         *  remaining actual arguments.
         */
        if ((argsLeft == 1) && (strcmp(argPtr->name, "args") == 0)) {
            if (objc < 0) objc = 0;

            listPtr = Tcl_NewListObj(objc, objv);
            ItclVarObjValue(varPtr) = listPtr;
            Tcl_IncrRefCount(listPtr); /* local var is a reference */
	    ItclClearVarUndefined(varPtr);
            objc = 0;

            break;
        }

        /*
         *  Handle the special case of the last formal being "config".
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
                        configVars[vi]->member->classDefn->name, -1);
                    Tcl_AppendToObj(objPtr, "::", -1);
                    Tcl_AppendToObj(objPtr, configVars[vi]->member->name, -1);

                    Tcl_ListObjAppendElement(interp, listPtr, objPtr);
                }

                varPtr->value.objPtr = listPtr;
                Tcl_IncrRefCount(listPtr); /* local var is a reference */
                varPtr->flags &= ~VAR_UNDEFINED;

                objc = 0;  /* all remaining args handled */
            }

            else if (argPtr->defValuePtr) {
                value = Tcl_GetStringFromObj(argPtr->defValuePtr, (int*)NULL);








|

|







1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
                        configVars[vi]->member->classDefn->name, -1);
                    Tcl_AppendToObj(objPtr, "::", -1);
                    Tcl_AppendToObj(objPtr, configVars[vi]->member->name, -1);

                    Tcl_ListObjAppendElement(interp, listPtr, objPtr);
                }

                ItclVarObjValue(varPtr) = listPtr;
                Tcl_IncrRefCount(listPtr); /* local var is a reference */
		ItclClearVarUndefined(varPtr);

                objc = 0;  /* all remaining args handled */
            }

            else if (argPtr->defValuePtr) {
                value = Tcl_GetStringFromObj(argPtr->defValuePtr, (int*)NULL);

1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
                        configVars[vi]->member->classDefn->name, -1);
                    Tcl_AppendToObj(objPtr, "::", -1);
                    Tcl_AppendToObj(objPtr, configVars[vi]->member->name, -1);

                    Tcl_ListObjAppendElement(interp, listPtr, objPtr);
                }

                varPtr->value.objPtr = listPtr;
                Tcl_IncrRefCount(listPtr); /* local var is a reference */
                varPtr->flags &= ~VAR_UNDEFINED;
            }
            else {
                objPtr = Tcl_NewStringObj("", 0);
                varPtr->value.objPtr = objPtr;
                Tcl_IncrRefCount(objPtr); /* local var is a reference */
                varPtr->flags &= ~VAR_UNDEFINED;
            }
        }

        /*
         *  Resume the usual processing of arguments...
         */
        else if (objc > 0) {          /* take next arg as value */
            objPtr = *objv;
            varPtr->value.objPtr = objPtr;
            varPtr->flags &= ~VAR_UNDEFINED;
            Tcl_IncrRefCount(objPtr);  /* local var is a reference */
        }
        else if (argPtr->defValuePtr) {    /* ...or use default value */
            objPtr = argPtr->defValuePtr;
            varPtr->value.objPtr = objPtr;
            varPtr->flags &= ~VAR_UNDEFINED;
            Tcl_IncrRefCount(objPtr);  /* local var is a reference */
        }
        else {
            if (mfunc) {
                objPtr = Tcl_GetObjResult(interp);
                Tcl_AppendToObj(objPtr, "wrong # args: should be \"", -1);
                Itcl_GetMemberFuncUsage(mfunc, contextObj, objPtr);







|

|



|

|








|
|




|
|







1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
                        configVars[vi]->member->classDefn->name, -1);
                    Tcl_AppendToObj(objPtr, "::", -1);
                    Tcl_AppendToObj(objPtr, configVars[vi]->member->name, -1);

                    Tcl_ListObjAppendElement(interp, listPtr, objPtr);
                }

                ItclVarObjValue(varPtr) = listPtr;
                Tcl_IncrRefCount(listPtr); /* local var is a reference */
		ItclClearVarUndefined(varPtr);
            }
            else {
                objPtr = Tcl_NewStringObj("", 0);
                ItclVarObjValue(varPtr) = objPtr;
                Tcl_IncrRefCount(objPtr); /* local var is a reference */
		ItclClearVarUndefined(varPtr);
            }
        }

        /*
         *  Resume the usual processing of arguments...
         */
        else if (objc > 0) {          /* take next arg as value */
            objPtr = *objv;
            ItclVarObjValue(varPtr) = objPtr;
	    ItclClearVarUndefined(varPtr);
            Tcl_IncrRefCount(objPtr);  /* local var is a reference */
        }
        else if (argPtr->defValuePtr) {    /* ...or use default value */
            objPtr = argPtr->defValuePtr;
            ItclVarObjValue(varPtr) = objPtr;
	    ItclClearVarUndefined(varPtr);
            Tcl_IncrRefCount(objPtr);  /* local var is a reference */
        }
        else {
            if (mfunc) {
                objPtr = Tcl_GetObjResult(interp);
                Tcl_AppendToObj(objPtr, "wrong # args: should be \"", -1);
                Itcl_GetMemberFuncUsage(mfunc, contextObj, objPtr);

Changes to generic/itcl_migrate.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 *
 * ========================================================================
 *  AUTHOR:  Michael J. McLennan
 *           Bell Labs Innovations for Lucent Technologies
 *           [email protected]
 *           http://www.tcltk.com/itcl
 *
 *     RCS:  $Id: itcl_migrate.c,v 1.3 2007/05/24 21:40:23 hobbs Exp $
 * ========================================================================
 *           Copyright (c) 1993-1998  Lucent Technologies, Inc.
 * ------------------------------------------------------------------------
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */
#include "itclInt.h"







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 *
 * ========================================================================
 *  AUTHOR:  Michael J. McLennan
 *           Bell Labs Innovations for Lucent Technologies
 *           [email protected]
 *           http://www.tcltk.com/itcl
 *
 *     RCS:  $Id: itcl_migrate.c,v 1.4 2007/08/07 20:05:30 msofer Exp $
 * ========================================================================
 *           Copyright (c) 1993-1998  Lucent Technologies, Inc.
 * ------------------------------------------------------------------------
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */
#include "itclInt.h"
120
121
122
123
124
125
126
127
128
129

130


131
132
133
134
135
136




137

























138
139














 *
 *----------------------------------------------------------------------
 */

Var *
_TclNewVar()
{
    register Var *varPtr;

    varPtr = (Var *) ckalloc(sizeof(Var));

    varPtr->value.objPtr = NULL;


    varPtr->name = NULL;
    varPtr->nsPtr = NULL;
    varPtr->hPtr = NULL;
    varPtr->refCount = 0;
    varPtr->tracePtr = NULL;
    varPtr->searchPtr = NULL;




    varPtr->flags = (VAR_SCALAR | VAR_UNDEFINED | VAR_IN_HASHTABLE);

























    return varPtr;
}





















|

|
>
|
>
>
|
|
|
|
|
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
 *
 *----------------------------------------------------------------------
 */

Var *
_TclNewVar()
{
    Var *varPtr;

    varPtr = (Var *) ckalloc(itclVarLocalSize);
    ItclInitVarFlags(varPtr);
    ItclVarObjValue(varPtr) = NULL;
#if ITCL_TCL_PRE_8_5
    if (itclOldRuntime) {
	varPtr->name = NULL;
	varPtr->nsPtr = NULL;
	varPtr->hPtr = NULL;
	varPtr->refCount = 0;
	varPtr->tracePtr = NULL;
	varPtr->searchPtr = NULL;
    }
#endif
    return varPtr;
}

#if ITCL_TCL_PRE_8_5
Var *
ItclVarHashCreateVar(
    TclVarHashTable *tablePtr,
    const char *key,
    int *newPtr)
{
#if (USE_TCL_STUBS)
    if (itclOldRuntime) {
#endif
	Tcl_HashEntry *hPtr;
	
	if (newPtr) {
	    Var *varPtr = _TclNewVar();

	    hPtr = Tcl_CreateHashEntry(tablePtr, key, newPtr);
	    varPtr->hPtr = hPtr;
	    Tcl_SetHashValue(hPtr, varPtr);	
	} else {
	    hPtr = Tcl_FindHashEntry(tablePtr, key);
	}	
	
	if (hPtr) {
	    return (Var *) Tcl_GetHashValue(hPtr);
	} else {
	    return NULL;
	}
#if (USE_TCL_STUBS)
    } else {
	/*
	 * An 8.5 runtime: TclVarHashCreateVar is at position 234 in the
	 * internal stubs table: call it.
	 */
	
	Var * (*TclVarHashCreateVar)(Tcl_HashTable *, const char *, int *) =
	    (Var * (*)(Tcl_HashTable *, const char *, int *)) *((&tclIntStubsPtr->reserved0)+234);
	return (*TclVarHashCreateVar)(tablePtr, key, newPtr);
    }
#endif
}
#endif

Changes to generic/itcl_objects.c.

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 *
 * ========================================================================
 *  AUTHOR:  Michael J. McLennan
 *           Bell Labs Innovations for Lucent Technologies
 *           [email protected]
 *           http://www.tcltk.com/itcl
 *
 *     RCS:  $Id: itcl_objects.c,v 1.16 2007/05/24 22:12:55 hobbs Exp $
 * ========================================================================
 *           Copyright (c) 1993-1998  Lucent Technologies, Inc.
 * ------------------------------------------------------------------------
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */
#include "itclInt.h"







|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 *
 * ========================================================================
 *  AUTHOR:  Michael J. McLennan
 *           Bell Labs Innovations for Lucent Technologies
 *           [email protected]
 *           http://www.tcltk.com/itcl
 *
 *     RCS:  $Id: itcl_objects.c,v 1.17 2007/08/07 20:05:30 msofer Exp $
 * ========================================================================
 *           Copyright (c) 1993-1998  Lucent Technologies, Inc.
 * ------------------------------------------------------------------------
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */
#include "itclInt.h"
1068
1069
1070
1071
1072
1073
1074


1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090


1091
1092
1093
1094
1095
1096
1097
{
    Var *varPtr;
    Tcl_HashEntry *entry;
    ItclVarLookup *vlookup;
    ItclContext context;

    varPtr = _TclNewVar();


    varPtr->name = vdefn->member->name;
    varPtr->nsPtr = (Namespace*)vdefn->member->classDefn->namesp;

    /*
     *  NOTE:  Tcl reports a "dangling upvar" error for variables
     *         with a null "hPtr" field.  Put something non-zero
     *         in here to keep Tcl_SetVar2() happy.  The only time
     *         this field is really used is it remove a variable
     *         from the hash table that contains it in CleanupVar,
     *         but since these variables are protected by their
     *         higher refCount, they will not be deleted by CleanupVar
     *         anyway.  These variables are unset and removed in
     *         ItclFreeObject().
     */
    varPtr->hPtr = (Tcl_HashEntry*)0x1;
    varPtr->refCount = 1;  /* protect from being deleted */



    /*
     *  Install the new variable in the object's data array.
     *  Look up the appropriate index for the object using
     *  the data table in the class definition.
     */
    entry = Tcl_FindHashEntry(&contextObj->classDefn->resolveVars,







>
>
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
>
>







1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
{
    Var *varPtr;
    Tcl_HashEntry *entry;
    ItclVarLookup *vlookup;
    ItclContext context;

    varPtr = _TclNewVar();
#if ITCL_TCL_PRE_8_5
    if (itclOldRuntime) {    
	varPtr->name = vdefn->member->name;
	varPtr->nsPtr = (Namespace*)vdefn->member->classDefn->namesp;

	/*
	 *  NOTE:  Tcl reports a "dangling upvar" error for variables
	 *         with a null "hPtr" field.  Put something non-zero
	 *         in here to keep Tcl_SetVar2() happy.  The only time
	 *         this field is really used is it remove a variable
	 *         from the hash table that contains it in CleanupVar,
	 *         but since these variables are protected by their
	 *         higher refCount, they will not be deleted by CleanupVar
	 *         anyway.  These variables are unset and removed in
	 *         ItclFreeObject().
	 */
	varPtr->hPtr = (Tcl_HashEntry*)0x1;
	ItclVarRefCount(varPtr) = 1;  /* protect from being deleted */
    }
#endif

    /*
     *  Install the new variable in the object's data array.
     *  Look up the appropriate index for the object using
     *  the data table in the class definition.
     */
    entry = Tcl_FindHashEntry(&contextObj->classDefn->resolveVars,

Changes to generic/itcl_parse.c.

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
 *
 * ========================================================================
 *  AUTHOR:  Michael J. McLennan
 *           Bell Labs Innovations for Lucent Technologies
 *           [email protected]
 *           http://www.tcltk.com/itcl
 *
 *     RCS:  $Id: itcl_parse.c,v 1.11 2007/08/03 18:56:47 msofer Exp $
 * ========================================================================
 *           Copyright (c) 1993-1998  Lucent Technologies, Inc.
 * ------------------------------------------------------------------------
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */
#include "itclInt.h"







|







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
 *
 * ========================================================================
 *  AUTHOR:  Michael J. McLennan
 *           Bell Labs Innovations for Lucent Technologies
 *           [email protected]
 *           http://www.tcltk.com/itcl
 *
 *     RCS:  $Id: itcl_parse.c,v 1.12 2007/08/07 20:05:30 msofer Exp $
 * ========================================================================
 *           Copyright (c) 1993-1998  Lucent Technologies, Inc.
 * ------------------------------------------------------------------------
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */
#include "itclInt.h"
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
{
    ItclObjectInfo *info = (ItclObjectInfo*)clientData;
    ItclClass *cdefnPtr = (ItclClass*)Itcl_PeekStack(&info->cdefnStack);

    int newEntry;
    char *name, *init;
    ItclVarDefn *vdefn;
    Tcl_HashEntry *entry;
    Namespace *nsPtr;
    Var *varPtr;

    if ((objc < 2) || (objc > 3)) {
        Tcl_WrongNumArgs(interp, 1, objv, "varname ?init?");
        return TCL_ERROR;
    }







<







892
893
894
895
896
897
898

899
900
901
902
903
904
905
{
    ItclObjectInfo *info = (ItclObjectInfo*)clientData;
    ItclClass *cdefnPtr = (ItclClass*)Itcl_PeekStack(&info->cdefnStack);

    int newEntry;
    char *name, *init;
    ItclVarDefn *vdefn;

    Namespace *nsPtr;
    Var *varPtr;

    if ((objc < 2) || (objc > 3)) {
        Tcl_WrongNumArgs(interp, 1, objv, "varname ?init?");
        return TCL_ERROR;
    }
932
933
934
935
936
937
938
939
940
941

942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
    /*
     *  Create the variable in the namespace associated with the
     *  class.  Do this the hard way, to avoid the variable resolver
     *  procedures.  These procedures won't work until we rebuild
     *  the virtual tables below.
     */
    nsPtr = (Namespace*)cdefnPtr->namesp;
    entry = Tcl_CreateHashEntry(&nsPtr->varTable,
        vdefn->member->name, &newEntry);


    if (newEntry) {
	varPtr = _TclNewVar();
	varPtr->hPtr = entry;
	varPtr->nsPtr = nsPtr;
	Tcl_SetHashValue(entry, varPtr);
    } else {
	varPtr = (Var *) Tcl_GetHashValue(entry);
    }
    
    if (!(varPtr->flags & VAR_NAMESPACE_VAR)) {
	varPtr->flags |= VAR_NAMESPACE_VAR;
	varPtr->refCount++;    /* one use by namespace */
    }
    varPtr->refCount++;    /* another use by class */


    /*
     *  TRICKY NOTE:  Make sure to rebuild the virtual tables for this
     *    class so that this variable is ready to access.  The variable
     *    resolver for the parser namespace needs this info to find the
     *    variable if the developer tries to set it within the class







|


>
|
<
<

<
<
<

|
|
<
<
<
|







931
932
933
934
935
936
937
938
939
940
941
942


943



944
945
946



947
948
949
950
951
952
953
954
    /*
     *  Create the variable in the namespace associated with the
     *  class.  Do this the hard way, to avoid the variable resolver
     *  procedures.  These procedures won't work until we rebuild
     *  the virtual tables below.
     */
    nsPtr = (Namespace*)cdefnPtr->namesp;
    varPtr = ItclVarHashCreateVar(&nsPtr->varTable,
        vdefn->member->name, &newEntry);

#if ITCL_TCL_PRE_8_5
    if (newEntry && itclOldRuntime) {


	varPtr->nsPtr = nsPtr;



    }
#endif
    TclSetVarNamespaceVar(varPtr);



    ItclVarRefCount(varPtr)++;    /* another use by class */


    /*
     *  TRICKY NOTE:  Make sure to rebuild the virtual tables for this
     *    class so that this variable is ready to access.  The variable
     *    resolver for the parser namespace needs this info to find the
     *    variable if the developer tries to set it within the class

Changes to generic/itcl_util.c.

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 *
 * ========================================================================
 *  AUTHOR:  Michael J. McLennan
 *           Bell Labs Innovations for Lucent Technologies
 *           [email protected]
 *           http://www.tcltk.com/itcl
 *
 *     RCS:  $Id: itcl_util.c,v 1.17 2007/07/03 23:11:24 hobbs Exp $
 * ========================================================================
 *           Copyright (c) 1993-1998  Lucent Technologies, Inc.
 * ------------------------------------------------------------------------
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */
#include "itclInt.h"







|







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 *
 * ========================================================================
 *  AUTHOR:  Michael J. McLennan
 *           Bell Labs Innovations for Lucent Technologies
 *           [email protected]
 *           http://www.tcltk.com/itcl
 *
 *     RCS:  $Id: itcl_util.c,v 1.18 2007/08/07 20:05:30 msofer Exp $
 * ========================================================================
 *           Copyright (c) 1993-1998  Lucent Technologies, Inc.
 * ------------------------------------------------------------------------
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */
#include "itclInt.h"
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
    Tcl_Obj *objResult;             /* result object */
    char *errorInfo;                /* contents of errorInfo variable */
    char *errorCode;                /* contents of errorCode variable */
} InterpState;

#define TCL_STATE_VALID 0x01233210  /* magic bit pattern for validation */

/* Use for interp state APIs */
extern int itclCompatFlags;


/*
 * ------------------------------------------------------------------------
 *  Itcl_Assert()
 *
 *  Called whenever an assert() test fails.  Prints a diagnostic
 *  message and abruptly exits.







<
<
<







65
66
67
68
69
70
71



72
73
74
75
76
77
78
    Tcl_Obj *objResult;             /* result object */
    char *errorInfo;                /* contents of errorInfo variable */
    char *errorCode;                /* contents of errorCode variable */
} InterpState;

#define TCL_STATE_VALID 0x01233210  /* magic bit pattern for validation */





/*
 * ------------------------------------------------------------------------
 *  Itcl_Assert()
 *
 *  Called whenever an assert() test fails.  Prints a diagnostic
 *  message and abruptly exits.