Tcl Source Code

Check-in [e04297dbf7]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

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

Overview
Comment:Bug fix for 3598385

dict exists now throws an error if an invalid dict is encountered, according to the same rules as exists prior to January 2012 (Checkin [22ec97b057])

This patch includes fixes for both the bytecode compiled version of dict exists, the non-bytecode version of dict exists, and updates as well as several new cases for the dict regression tests

The patch for dict.test checks both the compiled and non-compiled versions of the dict exists command

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | bug-3598385 | hypnotoad-bug-3598385
Files: files | file ages | folders
SHA1: e04297dbf76f69e8559898cd2778109c710d4133
User & Date: hypnotoad 2012-12-31 20:39:31
Context
2013-03-18
12:41
Merging in changes from trunk Closed-Leaf check-in: e580295bc9 user: seandeelywoods tags: hypnotoad-bug-3598385
2012-12-31
20:39
Bug fix for 3598385

dict exists now throws an error if an invalid dict is encountered, according to... check-in: e04297dbf7 user: hypnotoad tags: bug-3598385, hypnotoad-bug-3598385

12:32
Marked some string subcommands as obsolete, following discussion on tcl-core. check-in: 1a460ac0d3 user: dkf tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tclDictObj.c.

2000
2001
2002
2003
2004
2005
2006

2007
2008
2009
2010
2011
2012
2013
2014
2015




2016



2017
2018
2019
2020
2021

2022

2023
2024
2025
2026
2027
2028
2029
static int
DictExistsCmd(
    ClientData dummy,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{

    Tcl_Obj *dictPtr, *valuePtr;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "dictionary key ?key ...?");
	return TCL_ERROR;
    }

    dictPtr = TclTraceDictPath(interp, objv[1], objc-3, objv+2,
	    DICT_PATH_EXISTS);




    if (dictPtr == NULL || dictPtr == DICT_PATH_NON_EXISTENT



	    || Tcl_DictObjGet(interp, dictPtr, objv[objc-1],
		    &valuePtr) != TCL_OK) {
	Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
    } else {
	Tcl_SetObjResult(interp, Tcl_NewBooleanObj(valuePtr != NULL));

    }

    return TCL_OK;
}
 
/*
 *----------------------------------------------------------------------
 *
 * DictInfoCmd --






>






|


>
>
>
>
|
>
>
>
|
|
<
<
<
>

>







2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026



2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
static int
DictExistsCmd(
    ClientData dummy,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    int result;
    Tcl_Obj *dictPtr, *valuePtr;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "dictionary key ?key ...?");
	return TCL_ERROR;
    }
    
    dictPtr = TclTraceDictPath(interp, objv[1], objc-3, objv+2,
	    DICT_PATH_EXISTS);
    
    if (dictPtr == NULL) {
      return TCL_ERROR;
    }
    if (dictPtr == DICT_PATH_NON_EXISTENT) {
      Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
      return TCL_OK;        
    }
    result=Tcl_DictObjGet(interp, dictPtr, objv[objc-1], &valuePtr);
    if(result!=TCL_OK) {



      return result;
    }
    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(valuePtr != NULL));
    return TCL_OK;
}
 
/*
 *----------------------------------------------------------------------
 *
 * DictInfoCmd --

Changes to generic/tclExecute.c.

6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199






6200
6201








6202
6203
6204
6205














6206
6207
6208
6209
6210
6211
6212
6213




































































6214


































































6215
6216
6217
6218
6219
6220
6221
....
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
	    TRACE_APPEND(("ERROR verifying dictionary nature of \"%s\": %s\n",
		    O2S(OBJ_AT_DEPTH(opnd)), O2S(Tcl_GetObjResult(interp))));
	    goto gotError;
	}
	TRACE_APPEND(("OK\n"));
	NEXT_INST_F(1, 1, 0);

    case INST_DICT_GET:
    case INST_DICT_EXISTS: {
	register Tcl_Interp *interp2 = interp;

	opnd = TclGetUInt4AtPtr(pc+1);
	TRACE(("%u => ", opnd));
	dictPtr = OBJ_AT_DEPTH(opnd);
	if (*pc == INST_DICT_EXISTS) {
	    interp2 = NULL;
	}
	if (opnd > 1) {
	    dictPtr = TclTraceDictPath(interp2, dictPtr, opnd-1,
		    &OBJ_AT_DEPTH(opnd-1), DICT_PATH_READ);
	    if (dictPtr == NULL) {
		if (*pc == INST_DICT_EXISTS) {
		    goto dictNotExists;
		}
		TRACE_WITH_OBJ((
			"ERROR tracing dictionary path into \"%s\": ",
			O2S(OBJ_AT_DEPTH(opnd))),
			Tcl_GetObjResult(interp));
		goto gotError;
	    }
	}
	if (Tcl_DictObjGet(interp2, dictPtr, OBJ_AT_TOS,
		&objResultPtr) == TCL_OK) {
	    if (*pc == INST_DICT_EXISTS) {
		objResultPtr = TCONST(objResultPtr ? 1 : 0);
		TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
		NEXT_INST_V(5, opnd+1, 1);
	    }
	    if (objResultPtr) {
		TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
		NEXT_INST_V(5, opnd+1, 1);
	    }
	    DECACHE_STACK_INFO();
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "key \"%s\" not known in dictionary",
		    TclGetString(OBJ_AT_TOS)));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "DICT",
		    TclGetString(OBJ_AT_TOS), NULL);
	    CACHE_STACK_INFO();
	    TRACE_WITH_OBJ(("%u => ERROR ", opnd), Tcl_GetObjResult(interp));
	} else {






	    if (*pc == INST_DICT_EXISTS) {
	    dictNotExists:








		objResultPtr = TCONST(0);
		TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
		NEXT_INST_V(5, opnd+1, 1);
	    }














	    TRACE_WITH_OBJ((
		    "%u => ERROR reading leaf dictionary key \"%s\": ",
		    opnd, O2S(dictPtr)), Tcl_GetObjResult(interp));
	}
	goto gotError;
    }

    case INST_DICT_SET:




































































    case INST_DICT_UNSET:


































































    case INST_DICT_INCR_IMM:
	opnd = TclGetUInt4AtPtr(pc+1);
	opnd2 = TclGetUInt4AtPtr(pc+5);

	varPtr = LOCAL(opnd2);
	while (TclIsVarLink(varPtr)) {
	    varPtr = varPtr->value.linkPtr;
................................................................................
	} else {
	    allocateDict = Tcl_IsShared(dictPtr);
	    if (allocateDict) {
		dictPtr = Tcl_DuplicateObj(dictPtr);
	    }
	}

	switch (*pc) {
	case INST_DICT_SET:
	    cleanup = opnd + 1;
	    result = Tcl_DictObjPutKeyList(interp, dictPtr, opnd,
		    &OBJ_AT_DEPTH(opnd), OBJ_AT_TOS);
	    break;
	case INST_DICT_INCR_IMM:
	    cleanup = 1;
	    opnd = TclGetInt4AtPtr(pc+1);
	    result = Tcl_DictObjGet(interp, dictPtr, OBJ_AT_TOS, &valuePtr);
	    if (result != TCL_OK) {
		break;
	    }
	    if (valuePtr == NULL) {
		Tcl_DictObjPut(NULL, dictPtr, OBJ_AT_TOS,Tcl_NewIntObj(opnd));
	    } else {
		value2Ptr = Tcl_NewIntObj(opnd);
		Tcl_IncrRefCount(value2Ptr);
		if (Tcl_IsShared(valuePtr)) {
		    valuePtr = Tcl_DuplicateObj(valuePtr);
		    Tcl_DictObjPut(NULL, dictPtr, OBJ_AT_TOS, valuePtr);
		}
		result = TclIncrObj(interp, valuePtr, value2Ptr);
		if (result == TCL_OK) {
		    TclInvalidateStringRep(dictPtr);
		}
		TclDecrRefCount(value2Ptr);
	    }
	    break;
	case INST_DICT_UNSET:
	    cleanup = opnd;
	    result = Tcl_DictObjRemoveKeyList(interp, dictPtr, opnd,
		    &OBJ_AT_DEPTH(opnd-1));
	    break;
	default:
	    cleanup = 0; /* stop compiler warning */
	    Tcl_Panic("Should not happen!");
	}

	if (result != TCL_OK) {
	    if (allocateDict) {
		TclDecrRefCount(dictPtr);
	    }
	    TRACE_WITH_OBJ(("%u %u => ERROR updating dictionary: ",
		    opnd, opnd2), Tcl_GetObjResult(interp));
	    goto checkForCatch;






|
<





<
<
<




<
<
<









<
<
<
<
<













>
>
>
>
>
>
|
<
>
>
>
>
>
>
>
>
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>






<

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

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







 







<
<
<
<
<
<
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
<
<
<
<
<
<
<
|
<







6149
6150
6151
6152
6153
6154
6155
6156

6157
6158
6159
6160
6161



6162
6163
6164
6165



6166
6167
6168
6169
6170
6171
6172
6173
6174





6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194

6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226

6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
....
6382
6383
6384
6385
6386
6387
6388







6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409









6410

6411
6412
6413
6414
6415
6416
6417
	    TRACE_APPEND(("ERROR verifying dictionary nature of \"%s\": %s\n",
		    O2S(OBJ_AT_DEPTH(opnd)), O2S(Tcl_GetObjResult(interp))));
	    goto gotError;
	}
	TRACE_APPEND(("OK\n"));
	NEXT_INST_F(1, 1, 0);

    case INST_DICT_GET:  {

	register Tcl_Interp *interp2 = interp;

	opnd = TclGetUInt4AtPtr(pc+1);
	TRACE(("%u => ", opnd));
	dictPtr = OBJ_AT_DEPTH(opnd);



	if (opnd > 1) {
	    dictPtr = TclTraceDictPath(interp2, dictPtr, opnd-1,
		    &OBJ_AT_DEPTH(opnd-1), DICT_PATH_READ);
	    if (dictPtr == NULL) {



		TRACE_WITH_OBJ((
			"ERROR tracing dictionary path into \"%s\": ",
			O2S(OBJ_AT_DEPTH(opnd))),
			Tcl_GetObjResult(interp));
		goto gotError;
	    }
	}
	if (Tcl_DictObjGet(interp2, dictPtr, OBJ_AT_TOS,
		&objResultPtr) == TCL_OK) {





	    if (objResultPtr) {
		TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
		NEXT_INST_V(5, opnd+1, 1);
	    }
	    DECACHE_STACK_INFO();
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "key \"%s\" not known in dictionary",
		    TclGetString(OBJ_AT_TOS)));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "DICT",
		    TclGetString(OBJ_AT_TOS), NULL);
	    CACHE_STACK_INFO();
	    TRACE_WITH_OBJ(("%u => ERROR ", opnd), Tcl_GetObjResult(interp));
	} else {
	    TRACE_WITH_OBJ((
		    "%u => ERROR reading leaf dictionary key \"%s\": ",
		    opnd, O2S(dictPtr)), Tcl_GetObjResult(interp));
	}
	goto gotError;
    }
    case INST_DICT_EXISTS: {

        register Tcl_Interp *interp2 = interp;
        opnd = TclGetUInt4AtPtr(pc+1);
        TRACE(("%u => ", opnd));
	dictPtr = OBJ_AT_DEPTH(opnd);
	if (opnd > 1) {
	    dictPtr = TclTraceDictPath(interp2, dictPtr, opnd-1,
		    &OBJ_AT_DEPTH(opnd-1), DICT_PATH_EXISTS);
            if (dictPtr == DICT_PATH_NON_EXISTENT) {
              objResultPtr = TCONST(0);
              TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
              NEXT_INST_V(5, opnd+1, 1);
            }
	    if (dictPtr == NULL) {
		TRACE_WITH_OBJ((
			"ERROR tracing dictionary path into \"%s\": ",
			O2S(OBJ_AT_DEPTH(opnd))),
			Tcl_GetObjResult(interp));
		goto gotError;
	    }
	}
	if (Tcl_DictObjGet(interp2, dictPtr, OBJ_AT_TOS,
		&objResultPtr) == TCL_OK) {
          objResultPtr = TCONST(objResultPtr ? 1 : 0);
          TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
          NEXT_INST_V(5, opnd+1, 1);
	} else {
	    TRACE_WITH_OBJ((
		    "%u => ERROR reading leaf dictionary key \"%s\": ",
		    opnd, O2S(dictPtr)), Tcl_GetObjResult(interp));
	}
	goto gotError;
    }

    case INST_DICT_SET:
	opnd = TclGetUInt4AtPtr(pc+1);
	opnd2 = TclGetUInt4AtPtr(pc+5);

	varPtr = LOCAL(opnd2);
	while (TclIsVarLink(varPtr)) {
	    varPtr = varPtr->value.linkPtr;
	}
	TRACE(("%u %u => ", opnd, opnd2));
	if (TclIsVarDirectReadable(varPtr)) {
	    dictPtr = varPtr->value.objPtr;
	} else {
	    DECACHE_STACK_INFO();
	    dictPtr = TclPtrGetVar(interp, varPtr, NULL,NULL,NULL, 0, opnd2);
	    CACHE_STACK_INFO();
	}
	if (dictPtr == NULL) {
	    TclNewObj(dictPtr);
	    allocateDict = 1;
	} else {
	    allocateDict = Tcl_IsShared(dictPtr);
	    if (allocateDict) {
		dictPtr = Tcl_DuplicateObj(dictPtr);
	    }
	}

        cleanup = opnd + 1;
        result = Tcl_DictObjPutKeyList(interp, dictPtr, opnd,
                &OBJ_AT_DEPTH(opnd), OBJ_AT_TOS);
	
	if (result != TCL_OK) {
	    if (allocateDict) {
		TclDecrRefCount(dictPtr);
	    }
	    TRACE_WITH_OBJ(("%u %u => ERROR updating dictionary: ",
		    opnd, opnd2), Tcl_GetObjResult(interp));
	    goto checkForCatch;
	}

	if (TclIsVarDirectWritable(varPtr)) {
	    if (allocateDict) {
		value2Ptr = varPtr->value.objPtr;
		Tcl_IncrRefCount(dictPtr);
		if (value2Ptr != NULL) {
		    TclDecrRefCount(value2Ptr);
		}
		varPtr->value.objPtr = dictPtr;
	    }
	    objResultPtr = dictPtr;
	} else {
	    Tcl_IncrRefCount(dictPtr);
	    DECACHE_STACK_INFO();
	    objResultPtr = TclPtrSetVar(interp, varPtr, NULL, NULL, NULL,
		    dictPtr, TCL_LEAVE_ERR_MSG, opnd2);
	    CACHE_STACK_INFO();
	    TclDecrRefCount(dictPtr);
	    if (objResultPtr == NULL) {
		TRACE_APPEND(("ERROR: %.30s\n",
			O2S(Tcl_GetObjResult(interp))));
		goto gotError;
	    }
	}
#ifndef TCL_COMPILE_DEBUG
	if (*(pc+9) == INST_POP) {
	    NEXT_INST_V(10, cleanup, 0);
	}
#endif
	TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
	NEXT_INST_V(9, cleanup, 1);
    case INST_DICT_UNSET:
	opnd = TclGetUInt4AtPtr(pc+1);
	opnd2 = TclGetUInt4AtPtr(pc+5);

	varPtr = LOCAL(opnd2);
	while (TclIsVarLink(varPtr)) {
	    varPtr = varPtr->value.linkPtr;
	}
	TRACE(("%u %u => ", opnd, opnd2));
	if (TclIsVarDirectReadable(varPtr)) {
	    dictPtr = varPtr->value.objPtr;
	} else {
	    DECACHE_STACK_INFO();
	    dictPtr = TclPtrGetVar(interp, varPtr, NULL,NULL,NULL, 0, opnd2);
	    CACHE_STACK_INFO();
	}
	if (dictPtr == NULL) {
	    TclNewObj(dictPtr);
	    allocateDict = 1;
	} else {
	    allocateDict = Tcl_IsShared(dictPtr);
	    if (allocateDict) {
		dictPtr = Tcl_DuplicateObj(dictPtr);
	    }
	}
        cleanup = opnd;
        result = Tcl_DictObjRemoveKeyList(interp, dictPtr, opnd,
                &OBJ_AT_DEPTH(opnd-1));
	if (result != TCL_OK) {
	    if (allocateDict) {
		TclDecrRefCount(dictPtr);
	    }
	    TRACE_WITH_OBJ(("%u %u => ERROR updating dictionary: ",
		    opnd, opnd2), Tcl_GetObjResult(interp));
	    goto checkForCatch;
	}

	if (TclIsVarDirectWritable(varPtr)) {
	    if (allocateDict) {
		value2Ptr = varPtr->value.objPtr;
		Tcl_IncrRefCount(dictPtr);
		if (value2Ptr != NULL) {
		    TclDecrRefCount(value2Ptr);
		}
		varPtr->value.objPtr = dictPtr;
	    }
	    objResultPtr = dictPtr;
	} else {
	    Tcl_IncrRefCount(dictPtr);
	    DECACHE_STACK_INFO();
	    objResultPtr = TclPtrSetVar(interp, varPtr, NULL, NULL, NULL,
		    dictPtr, TCL_LEAVE_ERR_MSG, opnd2);
	    CACHE_STACK_INFO();
	    TclDecrRefCount(dictPtr);
	    if (objResultPtr == NULL) {
		TRACE_APPEND(("ERROR: %.30s\n",
			O2S(Tcl_GetObjResult(interp))));
		goto gotError;
	    }
	}
#ifndef TCL_COMPILE_DEBUG
	if (*(pc+9) == INST_POP) {
	    NEXT_INST_V(10, cleanup, 0);
	}
#endif
	TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
	NEXT_INST_V(9, cleanup, 1);
    case INST_DICT_INCR_IMM:
	opnd = TclGetUInt4AtPtr(pc+1);
	opnd2 = TclGetUInt4AtPtr(pc+5);

	varPtr = LOCAL(opnd2);
	while (TclIsVarLink(varPtr)) {
	    varPtr = varPtr->value.linkPtr;
................................................................................
	} else {
	    allocateDict = Tcl_IsShared(dictPtr);
	    if (allocateDict) {
		dictPtr = Tcl_DuplicateObj(dictPtr);
	    }
	}








        cleanup = 1;
        opnd = TclGetInt4AtPtr(pc+1);
        result = Tcl_DictObjGet(interp, dictPtr, OBJ_AT_TOS, &valuePtr);
        if (result != TCL_OK) {
            break;
        }
        if (valuePtr == NULL) {
            Tcl_DictObjPut(NULL, dictPtr, OBJ_AT_TOS,Tcl_NewIntObj(opnd));
        } else {
            value2Ptr = Tcl_NewIntObj(opnd);
            Tcl_IncrRefCount(value2Ptr);
            if (Tcl_IsShared(valuePtr)) {
                valuePtr = Tcl_DuplicateObj(valuePtr);
                Tcl_DictObjPut(NULL, dictPtr, OBJ_AT_TOS, valuePtr);
            }
            result = TclIncrObj(interp, valuePtr, value2Ptr);
            if (result == TCL_OK) {
                TclInvalidateStringRep(dictPtr);
            }
            TclDecrRefCount(value2Ptr);
        }









	   

	if (result != TCL_OK) {
	    if (allocateDict) {
		TclDecrRefCount(dictPtr);
	    }
	    TRACE_WITH_OBJ(("%u %u => ERROR updating dictionary: ",
		    opnd, opnd2), Tcl_GetObjResult(interp));
	    goto checkForCatch;

Changes to tests/dict.test.

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
test dict-8.5 {dict size command} -returnCodes error -body {
    dict size a b
} -result {wrong # args: should be "dict size dictionary"}
test dict-8.6 {dict size command} -returnCodes error -body {
    dict size a
} -result {missing value to go with key}

test dict-9.1 {dict exists command} {dict exists {a b} a} 1
test dict-9.2 {dict exists command} {dict exists {a b} b} 0
test dict-9.3 {dict exists command} {dict exists {a {b c}} a b} 1
test dict-9.4 {dict exists command} {dict exists {a {b c}} a c} 0
test dict-9.5 {dict exists command} {dict exists {a {b c}} b c} 0

test dict-9.6 {dict exists command} {dict exists {a {b c d}} a c} 0

test dict-9.7 {dict exists command} -returnCodes error -body {
    dict exists
} -result {wrong # args: should be "dict exists dictionary key ?key ...?"}
test dict-9.8 {dict exists command} -returnCodes error -body {
    dict exists {}
} -result {wrong # args: should be "dict exists dictionary key ?key ...?"}



























test dict-10.1 {dict info command} -body {
    # Actual string returned by this command is undefined; it is
    # intended for human consumption and not for use by scripts.
    dict info {}
} -match glob -result *
test dict-10.2 {dict info command} -returnCodes error -body {






|
|
|
|
|
>
|
>
|


|


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







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
test dict-8.5 {dict size command} -returnCodes error -body {
    dict size a b
} -result {wrong # args: should be "dict size dictionary"}
test dict-8.6 {dict size command} -returnCodes error -body {
    dict size a
} -result {missing value to go with key}

test dict-9.1  {dict exists command} {dict exists {a b} a} 1
test dict-9.2  {dict exists command} {dict exists {a b} b} 0
test dict-9.3  {dict exists command} {dict exists {a {b c}} a b} 1
test dict-9.4  {dict exists command} {dict exists {a {b c}} a c} 0
test dict-9.5  {dict exists command} {dict exists {a {b c}} b c} 0
test dict-9.6  {dict exists command} -returnCodes error -body {
  dict exists {a {b c d}} a c
} -result {missing value to go with key}
test dict-9.7  {dict exists command} -returnCodes error -body {
    dict exists
} -result {wrong # args: should be "dict exists dictionary key ?key ...?"}
test dict-9.8  {dict exists command} -returnCodes error -body {
    dict exists {}
} -result {wrong # args: should be "dict exists dictionary key ?key ...?"}
test dict-9.9  {dict exists command} {dict exists {} any} 0
test dict-9.10 {dict exists command} -returnCodes error  -body {
  dict exists any any
} -result {missing value to go with key}

# Repeat for non-bytecode compiled implementation
set cmd dict
test dict-9.1n  {dict exists command (non-compiled)} {$cmd exists {a b} a} 1
test dict-9.2n  {dict exists command (non-compiled)} {$cmd exists {a b} b} 0
test dict-9.3n  {dict exists command (non-compiled)} {$cmd exists {a {b c}} a b} 1
test dict-9.4n  {dict exists command (non-compiled)} {$cmd exists {a {b c}} a c} 0
test dict-9.5n  {dict exists command (non-compiled)} {$cmd exists {a {b c}} b c} 0
test dict-9.6n  {dict exists command (non-compiled)} -returnCodes error -body {
  $cmd exists {a {b c d}} a c
} -result {missing value to go with key}  
test dict-9.7n  {dict exists command (non-compiled)} -returnCodes error -body {
    $cmd exists
} -result {wrong # args: should be "dict exists dictionary key ?key ...?"}
test dict-9.8n  {dict exists command (non-compiled)} -returnCodes error -body {
    $cmd exists {}
} -result {wrong # args: should be "dict exists dictionary key ?key ...?"}
test dict-9.9n  {dict exists command (non-compiled)} {$cmd exists {} any} 0
test dict-9.10n {dict exists command (non-compiled)} -returnCodes error  -body {
  $cmd exists any any
} -result {missing value to go with key}


test dict-10.1 {dict info command} -body {
    # Actual string returned by this command is undefined; it is
    # intended for human consumption and not for use by scripts.
    dict info {}
} -match glob -result *
test dict-10.2 {dict info command} -returnCodes error -body {