| ︙ | | |
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
|
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
|
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
|
/*
* A test to see if we are in a call frame that has local variables. This is
* true if we are inside a procedure body.
*/
#define HasLocalVars(framePtr) ((framePtr)->isProcCallFrame & FRAME_IS_PROC)
/*
* The following structure describes an enumerative search in progress on an
* array variable; this are invoked with options to the "array" command.
*/
typedef struct ArraySearch {
Tcl_Obj *name; /* Name of this search */
int id; /* Integer id used to distinguish among
* multiple concurrent searches for the same
* array. */
struct Var *varPtr; /* Pointer to array variable that's being
* searched. */
Tcl_Obj *arrayNameObj; /* Name of the array variable in the current
* resolution context. Usually NULL except for
* in "array for". */
Tcl_HashSearch search; /* Info kept by the hash module about progress
* through the array. */
Tcl_HashEntry *nextEntry; /* Non-null means this is the next element to
* be enumerated (it's leftover from the
* Tcl_FirstHashEntry call or from an "array
* anymore" command). NULL means must call
* Tcl_NextHashEntry to get value to
* return. */
struct ArraySearch *nextPtr;/* Next in list of all active searches for
* this variable, or NULL if this is the last
* one. */
} ArraySearch;
/*
* Forward references to functions defined later in this file:
*/
static void AppendLocals(Tcl_Interp *interp, Tcl_Obj *listPtr,
Tcl_Obj *patternPtr, int includeLinks);
static Tcl_NRPostProc ArrayForLoopCallback;
static void DeleteSearches(Interp *iPtr, Var *arrayVarPtr);
static void DeleteArray(Interp *iPtr, Tcl_Obj *arrayNamePtr,
Var *varPtr, int flags, int index);
static Tcl_Var ObjFindNamespaceVar(Tcl_Interp *interp,
Tcl_Obj *namePtr, Tcl_Namespace *contextNsPtr,
int flags);
static int ObjMakeUpvar(Tcl_Interp *interp,
CallFrame *framePtr, Tcl_Obj *otherP1Ptr,
const char *otherP2, const int otherFlags,
Tcl_Obj *myNamePtr, int myFlags, int index);
static ArraySearch * ParseSearchId(Tcl_Interp *interp, const Var *varPtr,
static Tcl_ArraySearch * ParseSearchId(Tcl_Interp *interp, const Var *varPtr,
Tcl_Obj *varNamePtr, Tcl_Obj *handleObj);
static void UnsetVarStruct(Var *varPtr, Var *arrayPtr,
Interp *iPtr, Tcl_Obj *part1Ptr,
Tcl_Obj *part2Ptr, int flags, int index);
static Var * VerifyArray(Tcl_Interp *interp, Tcl_Obj *varNameObj);
/*
|
| ︙ | | |
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
|
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
|
+
-
-
+
+
+
+
+
+
+
-
+
+
+
+
+
-
+
-
-
+
+
|
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* ArrayForNRCmd --
* ArrayForLoopCallback
*
* These functions implement the "array for" Tcl command. See the user
* documentation for details on what it does.
* These functions implement the "array for" Tcl command.
* array for {k} a {}
* array for {k v} a {}
* The array for command iterates over the array, setting the
* the specified loop variables, and executing the body each iteration.
*
* ArrayForNRCmd() sets up the Tcl_ArraySearch structure, sets arrayNamePtr
* inside the structure and calls VarHashFirstEntry to start the hash
* Results:
* iteration.
*
* ArrayForNRCmd() does not execute the body or set the loop variables,
* it only initializes the iterator.
*
* ArrayForLoopCallback() iterates over the entire array, executing
* Side effects:
* the body each time.
*
*----------------------------------------------------------------------
*/
static int
ArrayForNRCmd(
ClientData dummy,
Tcl_Interp *interp,
int objc,
Tcl_Obj *const *objv)
{
Interp *iPtr = (Interp *) interp;
Tcl_Obj *scriptObj, *keyVarObj, *valueVarObj;
Tcl_Obj **varv;
Tcl_Obj *varNameObj;
ArraySearch *searchPtr = NULL;
Tcl_Obj *arrayNameObj;
Tcl_ArraySearch *searchPtr = NULL;
Var *varPtr;
Var *arrayPtr;
int varc;
/*
* array for {k} a body
* array for {k v} a body
|
| ︙ | | |
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
|
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
|
-
+
-
+
-
+
-
+
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
-
-
-
-
-
+
|
if (varc < 1 || varc > 2) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"must have one or two variable names", -1));
Tcl_SetErrorCode(interp, "TCL", "SYNTAX", "array", "for", NULL);
return TCL_ERROR;
}
varNameObj = objv[2];
arrayNameObj = objv[2];
keyVarObj = varv[0];
valueVarObj = (varc < 2 ? NULL : varv[1]);
scriptObj = objv[3];
/*
* Locate the array variable.
*/
varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0,
varPtr = TclObjLookupVarEx(interp, arrayNameObj, NULL, /*flags*/ 0,
/*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr);
/*
* Special array trace used to keep the env array in sync for array names,
* array get, etc.
*/
if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY)
&& (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) {
if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, varNameObj, NULL,
if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, arrayNameObj, NULL,
(TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY|
TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) {
return TCL_ERROR;
}
}
/*
* Verify that it is indeed an array variable. This test comes after the
* traces; the variable may actually become an array as an effect of said
* traces.
*/
if ((varPtr == NULL) || !TclIsVarArray(varPtr)
|| TclIsVarUndefined(varPtr)) {
const char *varName = Tcl_GetString(varNameObj);
const char *varName = Tcl_GetString(arrayNameObj);
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"\"%s\" isn't an array", varName));
Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY", varName, NULL);
return TCL_ERROR;
}
/*
* Make a new array search, put it on the stack.
*/
searchPtr = TclStackAlloc(interp, sizeof(ArraySearch));
searchPtr = TclStackAlloc(interp, sizeof(Tcl_ArraySearch));
searchPtr->id = 1;
Tcl_ArrayObjFirst(interp, arrayNameObj, searchPtr);
/*
* Do not turn on VAR_SEARCH_ACTIVE in varPtr->flags. This search is not
* stored in the search list.
*/
searchPtr->nextPtr = NULL;
searchPtr->varPtr = varPtr;
searchPtr->arrayNameObj = varNameObj;
searchPtr->nextEntry = VarHashFirstEntry(varPtr->value.tablePtr,
&searchPtr->search);
/*
* Make sure that these objects (which we need throughout the body of the
* loop) don't vanish.
*/
Tcl_IncrRefCount(keyVarObj);
if (valueVarObj != NULL) {
Tcl_IncrRefCount(valueVarObj);
}
Tcl_IncrRefCount(scriptObj);
Tcl_IncrRefCount(varNameObj);
/*
* Run the script.
*/
TclNRAddCallback(interp, ArrayForLoopCallback, searchPtr, keyVarObj,
valueVarObj, scriptObj);
return TCL_OK;
}
/*
* Tcl_ArrayObjFirst
*
* Does not execute the body or set the key/value variables.
*
*/
void
Tcl_ArrayObjFirst(
Tcl_Interp *interp,
Tcl_Obj *arrayObj,
Tcl_ArraySearch *searchPtr)
{
Var *varPtr;
Var *arrayPtr;
searchPtr->id = 1;
/*
* Do not turn on VAR_SEARCH_ACTIVE in varPtr->flags. This search is not
* stored in the search list.
*/
searchPtr->nextPtr = NULL;
varPtr = TclObjLookupVarEx(interp, arrayObj, NULL, /*flags*/ 0,
/*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr);
searchPtr->varPtr = varPtr;
searchPtr->arrayNameObj = arrayObj;
searchPtr->flags = TCL_ARRAYSEARCH_FOR_VALUE;
searchPtr->nextEntry = VarHashFirstEntry(varPtr->value.tablePtr,
&searchPtr->search);
}
int
Tcl_ArrayObjNext(
Tcl_Interp *interp,
Tcl_ArraySearch *searchPtr,
Tcl_Obj **keyPtrPtr, /* Pointer to a variable to have the key
* written into, or NULL. */
Tcl_Obj **valuePtrPtr /* Pointer to a variable to have the
* value written into, or NULL.*/
)
{
Tcl_Obj *keyObj;
Tcl_Obj *valueObj = NULL;
Var *varPtr;
int gotValue;
int donerc;
donerc = 1;
gotValue = 0;
while (1) {
Tcl_HashEntry *hPtr = searchPtr->nextEntry;
/*
* The only time hPtr will be non-NULL is when first started.
* nextEntry is set by the Tcl_FirstHashEntry call in the
* call to Tcl_ArrayObjFirst from ArrayForNRCmd.
*/
if (hPtr != NULL) {
searchPtr->nextEntry = NULL;
} else {
hPtr = Tcl_NextHashEntry(&searchPtr->search);
if (hPtr == NULL) {
gotValue = 0;
break;
}
}
varPtr = VarHashGetValue(hPtr);
if (!TclIsVarUndefined(varPtr)) {
gotValue = 1;
break;
}
}
if (!gotValue) {
donerc = 1;
return donerc;
}
donerc = 0;
keyObj = VarHashGetKey(varPtr);
*keyPtrPtr = keyObj;
*valuePtrPtr = NULL;
if (searchPtr->flags & TCL_ARRAYSEARCH_FOR_VALUE) {
valueObj = Tcl_ObjGetVar2(interp, searchPtr->arrayNameObj,
keyObj, TCL_LEAVE_ERR_MSG);
*valuePtrPtr = valueObj;
}
return donerc;
}
static int
ArrayForLoopCallback(
ClientData data[],
Tcl_Interp *interp,
int result)
{
Interp *iPtr = (Interp *) interp;
ArraySearch *searchPtr = data[0];
Tcl_ArraySearch *searchPtr = data[0];
Tcl_Obj *keyObj, *valueObj;
Tcl_Obj *keyVarObj = data[1];
Tcl_Obj *valueVarObj = data[2];
Tcl_Obj *scriptObj = data[3];
Tcl_Obj *arrayNameObj = searchPtr->arrayNameObj;
Tcl_Obj *keyObj;
Tcl_Obj *valueObj = NULL;
Var *varPtr;
int gotValue;
int done;
/*
* Process the result from the previous execution of the script body.
*/
if (result == TCL_CONTINUE) {
result = TCL_OK;
|
| ︙ | | |
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
|
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
|
-
-
-
+
-
-
-
-
-
-
-
+
+
-
-
-
-
+
-
-
+
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
+
-
-
-
+
+
-
+
-
-
-
-
+
+
+
-
|
goto done;
}
/*
* Get the next mapping from the array.
*/
while (1) {
Tcl_HashEntry *hPtr = searchPtr->nextEntry;
keyObj = NULL;
/*
* The only time hPtr will be non-NULL is when first started.
* nextEntry is set by the Tcl_FirstHashEntry call in the
* ArrayForNRCmd
*/
if (hPtr != NULL) {
valueObj = NULL;
if (valueVarObj != NULL) {
searchPtr->nextEntry = NULL;
varPtr = VarHashGetValue(hPtr);
if (!TclIsVarUndefined(varPtr)) {
gotValue = 1;
valueObj = Tcl_NewObj();
break;
}
}
}
if (hPtr == NULL) {
hPtr = Tcl_NextHashEntry(&searchPtr->search);
done = Tcl_ArrayObjNext (interp, searchPtr, &keyObj, &valueObj);
if (hPtr == NULL) {
gotValue = 0;
break;
}
}
varPtr = VarHashGetValue(hPtr);
if (!TclIsVarUndefined(varPtr)) {
gotValue = 1;
break;
}
}
if (!gotValue) {
result = TCL_OK;
if (done) {
Tcl_ResetResult(interp);
goto done;
}
keyObj = VarHashGetKey(varPtr);
if (valueVarObj != NULL) {
valueObj = Tcl_ObjGetVar2(interp, arrayNameObj, keyObj,
TCL_LEAVE_ERR_MSG);
}
if (Tcl_ObjSetVar2(interp, keyVarObj, NULL, keyObj,
if (Tcl_ObjSetVar2(interp, keyVarObj, NULL, keyObj, TCL_LEAVE_ERR_MSG) == NULL) {
TCL_LEAVE_ERR_MSG) == NULL) {
result = TCL_ERROR;
goto done;
result = TCL_ERROR;
goto done;
}
if (valueVarObj != NULL) {
if (Tcl_ObjSetVar2(interp, valueVarObj, NULL, valueObj,
if (Tcl_ObjSetVar2(interp, valueVarObj, NULL, valueObj, TCL_LEAVE_ERR_MSG) == NULL) {
TCL_LEAVE_ERR_MSG) == NULL) {
result = TCL_ERROR;
goto done;
}
result = TCL_ERROR;
goto done;
}
}
/*
* Run the script.
*/
TclNRAddCallback(interp, ArrayForLoopCallback, searchPtr, keyVarObj,
valueVarObj, scriptObj);
return TclNREvalObjEx(interp, scriptObj, 0, iPtr->cmdFramePtr, 3);
/*
* For unwinding everything once the iterating is done.
*/
done:
TclDecrRefCount(keyVarObj);
if (valueVarObj != NULL) {
TclDecrRefCount(valueVarObj);
}
TclDecrRefCount(scriptObj);
TclDecrRefCount(arrayNameObj);
TclStackFree(interp, searchPtr);
return result;
}
/*
*----------------------------------------------------------------------
*
|
| ︙ | | |
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
|
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
|
-
+
-
+
-
-
+
+
+
|
int objc,
Tcl_Obj *const objv[])
{
Interp *iPtr = (Interp *) interp;
Var *varPtr;
Tcl_HashEntry *hPtr;
int isNew;
ArraySearch *searchPtr;
Tcl_ArraySearch *searchPtr;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "arrayName");
return TCL_ERROR;
}
varPtr = VerifyArray(interp, objv[1]);
if (varPtr == NULL) {
return TCL_ERROR;
}
/*
* Make a new array search with a free name.
*/
searchPtr = ckalloc(sizeof(ArraySearch));
searchPtr = ckalloc(sizeof(Tcl_ArraySearch));
hPtr = Tcl_CreateHashEntry(&iPtr->varSearches, varPtr, &isNew);
if (isNew) {
searchPtr->id = 1;
varPtr->flags |= VAR_SEARCH_ACTIVE;
searchPtr->nextPtr = NULL;
} else {
searchPtr->id = ((ArraySearch *) Tcl_GetHashValue(hPtr))->id + 1;
searchPtr->nextPtr = Tcl_GetHashValue(hPtr);
searchPtr->id = ((Tcl_ArraySearch *) Tcl_GetHashValue(hPtr))->id + 1;
searchPtr->nextPtr = (Tcl_ArraySearch *) Tcl_GetHashValue(hPtr);
}
searchPtr->varPtr = varPtr;
searchPtr->arrayNameObj = NULL;
searchPtr->flags = 0;
searchPtr->nextEntry = VarHashFirstEntry(varPtr->value.tablePtr,
&searchPtr->search);
Tcl_SetHashValue(hPtr, searchPtr);
searchPtr->name = Tcl_ObjPrintf("s-%d-%s", searchPtr->id, TclGetString(objv[1]));
Tcl_IncrRefCount(searchPtr->name);
Tcl_SetObjResult(interp, searchPtr->name);
return TCL_OK;
|
| ︙ | | |
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
|
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
|
-
+
|
int objc,
Tcl_Obj *const objv[])
{
Interp *iPtr = (Interp *) interp;
Var *varPtr;
Tcl_Obj *varNameObj, *searchObj;
int gotValue;
ArraySearch *searchPtr;
Tcl_ArraySearch *searchPtr;
if (objc != 3) {
Tcl_WrongNumArgs(interp, 1, objv, "arrayName searchId");
return TCL_ERROR;
}
varNameObj = objv[1];
searchObj = objv[2];
|
| ︙ | | |
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
|
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
|
-
+
|
ClientData clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *const objv[])
{
Var *varPtr;
Tcl_Obj *varNameObj, *searchObj;
ArraySearch *searchPtr;
Tcl_ArraySearch *searchPtr;
if (objc != 3) {
Tcl_WrongNumArgs(interp, 1, objv, "arrayName searchId");
return TCL_ERROR;
}
varNameObj = objv[1];
searchObj = objv[2];
|
| ︙ | | |
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
|
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
|
-
+
|
int objc,
Tcl_Obj *const objv[])
{
Interp *iPtr = (Interp *) interp;
Var *varPtr;
Tcl_HashEntry *hPtr;
Tcl_Obj *varNameObj, *searchObj;
ArraySearch *searchPtr, *prevPtr;
Tcl_ArraySearch *searchPtr, *prevPtr;
if (objc != 3) {
Tcl_WrongNumArgs(interp, 1, objv, "arrayName searchId");
return TCL_ERROR;
}
varNameObj = objv[1];
searchObj = objv[2];
|
| ︙ | | |
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
|
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
|
-
+
-
+
|
/*
* Unhook the search from the list of searches associated with the
* variable.
*/
hPtr = Tcl_FindHashEntry(&iPtr->varSearches, varPtr);
if (searchPtr == Tcl_GetHashValue(hPtr)) {
if (searchPtr == (Tcl_ArraySearch *) Tcl_GetHashValue(hPtr)) {
if (searchPtr->nextPtr) {
Tcl_SetHashValue(hPtr, searchPtr->nextPtr);
} else {
varPtr->flags &= ~VAR_SEARCH_ACTIVE;
Tcl_DeleteHashEntry(hPtr);
}
} else {
for (prevPtr=Tcl_GetHashValue(hPtr) ;; prevPtr=prevPtr->nextPtr) {
for (prevPtr= (Tcl_ArraySearch *) Tcl_GetHashValue(hPtr) ;; prevPtr=prevPtr->nextPtr) {
if (prevPtr->nextPtr == searchPtr) {
prevPtr->nextPtr = searchPtr->nextPtr;
break;
}
}
}
Tcl_DecrRefCount(searchPtr->name);
|
| ︙ | | |
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
|
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
|
-
+
|
TclInitArrayCmd(
Tcl_Interp *interp) /* Current interpreter. */
{
static const EnsembleImplMap arrayImplMap[] = {
{"anymore", ArrayAnyMoreCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
{"donesearch", ArrayDoneSearchCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
{"exists", ArrayExistsCmd, TclCompileArrayExistsCmd, NULL, NULL, 0},
{"for", NULL, TclCompileBasic3ArgCmd, ArrayForNRCmd, NULL, 0},
{"for", NULL, TclCompileArrayForCmd, ArrayForNRCmd, NULL, 0},
{"get", ArrayGetCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
{"names", ArrayNamesCmd, TclCompileBasic1To3ArgCmd, NULL, NULL, 0},
{"nextelement", ArrayNextElementCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0},
{"set", ArraySetCmd, TclCompileArraySetCmd, NULL, NULL, 0},
{"size", ArraySizeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
{"startsearch", ArrayStartSearchCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
{"statistics", ArrayStatsCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0},
|
| ︙ | | |
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
|
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
|
-
+
-
+
-
+
-
+
|
* The return value is a pointer to the array search indicated by string,
* or NULL if there isn't one. If NULL is returned, the interp's result
* contains an error message.
*
*----------------------------------------------------------------------
*/
static ArraySearch *
static Tcl_ArraySearch *
ParseSearchId(
Tcl_Interp *interp, /* Interpreter containing variable. */
const Var *varPtr, /* Array variable search is for. */
Tcl_Obj *varNamePtr, /* Name of array variable that search is
* supposed to be for. */
Tcl_Obj *handleObj) /* Object containing id of search. Must have
* form "search-num-var" where "num" is a
* decimal number and "var" is a variable
* name. */
{
Interp *iPtr = (Interp *) interp;
ArraySearch *searchPtr;
Tcl_ArraySearch *searchPtr;
const char *handle = TclGetString(handleObj);
char *end;
if (varPtr->flags & VAR_SEARCH_ACTIVE) {
Tcl_HashEntry *hPtr =
Tcl_FindHashEntry(&iPtr->varSearches, varPtr);
/* First look for same (Tcl_Obj *) */
for (searchPtr = Tcl_GetHashValue(hPtr); searchPtr != NULL;
for (searchPtr = (Tcl_ArraySearch *) Tcl_GetHashValue(hPtr); searchPtr != NULL;
searchPtr = searchPtr->nextPtr) {
if (searchPtr->name == handleObj) {
return searchPtr;
}
}
/* Fallback: do string compares. */
for (searchPtr = Tcl_GetHashValue(hPtr); searchPtr != NULL;
for (searchPtr = (Tcl_ArraySearch *) Tcl_GetHashValue(hPtr); searchPtr != NULL;
searchPtr = searchPtr->nextPtr) {
if (strcmp(TclGetString(searchPtr->name), handle) == 0) {
return searchPtr;
}
}
}
if ((handle[0] != 's') || (handle[1] != '-')
|
| ︙ | | |
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
|
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
|
-
+
-
+
|
static void
DeleteSearches(
Interp *iPtr,
register Var *arrayVarPtr) /* Variable whose searches are to be
* deleted. */
{
ArraySearch *searchPtr, *nextPtr;
Tcl_ArraySearch *searchPtr, *nextPtr;
Tcl_HashEntry *sPtr;
if (arrayVarPtr->flags & VAR_SEARCH_ACTIVE) {
sPtr = Tcl_FindHashEntry(&iPtr->varSearches, arrayVarPtr);
for (searchPtr = Tcl_GetHashValue(sPtr); searchPtr != NULL;
for (searchPtr = (Tcl_ArraySearch *) Tcl_GetHashValue(sPtr); searchPtr != NULL;
searchPtr = nextPtr) {
nextPtr = searchPtr->nextPtr;
Tcl_DecrRefCount(searchPtr->name);
ckfree(searchPtr);
}
arrayVarPtr->flags &= ~VAR_SEARCH_ACTIVE;
Tcl_DeleteHashEntry(sPtr);
|
| ︙ | | |