tclTestObj.cGo to the documentation of this file.00001 /* 00002 * tclTestObj.c -- 00003 * 00004 * This file contains C command functions for the additional Tcl commands 00005 * that are used for testing implementations of the Tcl object types. 00006 * These commands are not normally included in Tcl applications; they're 00007 * only used for testing. 00008 * 00009 * Copyright (c) 1995-1998 Sun Microsystems, Inc. 00010 * Copyright (c) 1999 by Scriptics Corporation. 00011 * Copyright (c) 2005 by Kevin B. Kenny. All rights reserved. 00012 * 00013 * See the file "license.terms" for information on usage and redistribution of 00014 * this file, and for a DISCLAIMER OF ALL WARRANTIES. 00015 * 00016 * RCS: @(#) $Id: tclTestObj.c,v 1.21 2007/12/13 15:23:20 dgp Exp $ 00017 */ 00018 00019 #include "tclInt.h" 00020 #include "tommath.h" 00021 00022 /* 00023 * An array of Tcl_Obj pointers used in the commands that operate on or get 00024 * the values of Tcl object-valued variables. varPtr[i] is the i-th variable's 00025 * Tcl_Obj *. 00026 */ 00027 00028 #define NUMBER_OF_OBJECT_VARS 20 00029 static Tcl_Obj *varPtr[NUMBER_OF_OBJECT_VARS]; 00030 00031 /* 00032 * Forward declarations for functions defined later in this file: 00033 */ 00034 00035 static int CheckIfVarUnset(Tcl_Interp *interp, int varIndex); 00036 static int GetVariableIndex(Tcl_Interp *interp, 00037 char *string, int *indexPtr); 00038 static void SetVarToObj(int varIndex, Tcl_Obj *objPtr); 00039 int TclObjTest_Init(Tcl_Interp *interp); 00040 static int TestbignumobjCmd(ClientData dummy, Tcl_Interp *interp, 00041 int objc, Tcl_Obj *const objv[]); 00042 static int TestbooleanobjCmd(ClientData dummy, 00043 Tcl_Interp *interp, int objc, 00044 Tcl_Obj *const objv[]); 00045 static int TestdoubleobjCmd(ClientData dummy, Tcl_Interp *interp, 00046 int objc, Tcl_Obj *const objv[]); 00047 static int TestindexobjCmd(ClientData dummy, Tcl_Interp *interp, 00048 int objc, Tcl_Obj *const objv[]); 00049 static int TestintobjCmd(ClientData dummy, Tcl_Interp *interp, 00050 int objc, Tcl_Obj *const objv[]); 00051 static int TestobjCmd(ClientData dummy, Tcl_Interp *interp, 00052 int objc, Tcl_Obj *const objv[]); 00053 static int TeststringobjCmd(ClientData dummy, Tcl_Interp *interp, 00054 int objc, Tcl_Obj *const objv[]); 00055 00056 typedef struct TestString { 00057 int numChars; 00058 size_t allocated; 00059 size_t uallocated; 00060 Tcl_UniChar unicode[2]; 00061 } TestString; 00062 00063 /* 00064 *---------------------------------------------------------------------- 00065 * 00066 * TclObjTest_Init -- 00067 * 00068 * This function creates additional commands that are used to test the 00069 * Tcl object support. 00070 * 00071 * Results: 00072 * Returns a standard Tcl completion code, and leaves an error 00073 * message in the interp's result if an error occurs. 00074 * 00075 * Side effects: 00076 * Creates and registers several new testing commands. 00077 * 00078 *---------------------------------------------------------------------- 00079 */ 00080 00081 int 00082 TclObjTest_Init( 00083 Tcl_Interp *interp) 00084 { 00085 register int i; 00086 00087 for (i = 0; i < NUMBER_OF_OBJECT_VARS; i++) { 00088 varPtr[i] = NULL; 00089 } 00090 00091 Tcl_CreateObjCommand(interp, "testbignumobj", TestbignumobjCmd, 00092 (ClientData) 0, NULL); 00093 Tcl_CreateObjCommand(interp, "testbooleanobj", TestbooleanobjCmd, 00094 (ClientData) 0, NULL); 00095 Tcl_CreateObjCommand(interp, "testdoubleobj", TestdoubleobjCmd, 00096 (ClientData) 0, NULL); 00097 Tcl_CreateObjCommand(interp, "testintobj", TestintobjCmd, 00098 (ClientData) 0, NULL); 00099 Tcl_CreateObjCommand(interp, "testindexobj", TestindexobjCmd, 00100 (ClientData) 0, NULL); 00101 Tcl_CreateObjCommand(interp, "testobj", TestobjCmd, (ClientData) 0, NULL); 00102 Tcl_CreateObjCommand(interp, "teststringobj", TeststringobjCmd, 00103 (ClientData) 0, NULL); 00104 return TCL_OK; 00105 } 00106 00107 /* 00108 *---------------------------------------------------------------------- 00109 * 00110 * TestbignumobjCmd -- 00111 * 00112 * This function implmenets the "testbignumobj" command. It is used 00113 * to exercise the bignum Tcl object type implementation. 00114 * 00115 * Results: 00116 * Returns a standard Tcl object result. 00117 * 00118 * Side effects: 00119 * Creates and frees bignum objects; converts objects to have bignum 00120 * type. 00121 * 00122 *---------------------------------------------------------------------- 00123 */ 00124 00125 static int 00126 TestbignumobjCmd( 00127 ClientData clientData, /* unused */ 00128 Tcl_Interp *interp, /* Tcl interpreter */ 00129 int objc, /* Argument count */ 00130 Tcl_Obj *const objv[]) /* Argument vector */ 00131 { 00132 const char * subcmds[] = { 00133 "set", "get", "mult10", "div10", NULL 00134 }; 00135 enum options { 00136 BIGNUM_SET, BIGNUM_GET, BIGNUM_MULT10, BIGNUM_DIV10 00137 }; 00138 00139 int index, varIndex; 00140 char* string; 00141 mp_int bignumValue, newValue; 00142 00143 if (objc < 3) { 00144 Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?..."); 00145 return TCL_ERROR; 00146 } 00147 if (Tcl_GetIndexFromObj(interp, objv[1], subcmds, "option", 0, 00148 &index) != TCL_OK) { 00149 return TCL_ERROR; 00150 } 00151 string = Tcl_GetString(objv[2]); 00152 if (GetVariableIndex(interp, string, &varIndex) != TCL_OK) { 00153 return TCL_ERROR; 00154 } 00155 00156 switch (index) { 00157 case BIGNUM_SET: 00158 if (objc != 4) { 00159 Tcl_WrongNumArgs(interp, 2, objv, "var value"); 00160 return TCL_ERROR; 00161 } 00162 string = Tcl_GetString(objv[3]); 00163 if (mp_init(&bignumValue) != MP_OKAY) { 00164 Tcl_SetObjResult(interp, 00165 Tcl_NewStringObj("error in mp_init", -1)); 00166 return TCL_ERROR; 00167 } 00168 if (mp_read_radix(&bignumValue, string, 10) != MP_OKAY) { 00169 mp_clear(&bignumValue); 00170 Tcl_SetObjResult(interp, 00171 Tcl_NewStringObj("error in mp_read_radix", -1)); 00172 return TCL_ERROR; 00173 } 00174 00175 /* 00176 * If the object currently bound to the variable with index varIndex 00177 * has ref count 1 (i.e. the object is unshared) we can modify that 00178 * object directly. Otherwise, if RC>1 (i.e. the object is shared), 00179 * we must create a new object to modify/set and decrement the old 00180 * formerly-shared object's ref count. This is "copy on write". 00181 */ 00182 00183 if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { 00184 Tcl_SetBignumObj(varPtr[varIndex], &bignumValue); 00185 } else { 00186 SetVarToObj(varIndex, Tcl_NewBignumObj(&bignumValue)); 00187 } 00188 break; 00189 00190 case BIGNUM_GET: 00191 if (objc != 3) { 00192 Tcl_WrongNumArgs(interp, 2, objv, "varIndex"); 00193 return TCL_ERROR; 00194 } 00195 if (CheckIfVarUnset(interp, varIndex)) { 00196 return TCL_ERROR; 00197 } 00198 break; 00199 00200 case BIGNUM_MULT10: 00201 if (objc != 3) { 00202 Tcl_WrongNumArgs(interp, 2, objv, "varIndex"); 00203 return TCL_ERROR; 00204 } 00205 if (CheckIfVarUnset(interp, varIndex)) { 00206 return TCL_ERROR; 00207 } 00208 if (Tcl_GetBignumFromObj(interp, varPtr[varIndex], 00209 &bignumValue) != TCL_OK) { 00210 return TCL_ERROR; 00211 } 00212 if (mp_init(&newValue) != MP_OKAY 00213 || (mp_mul_d(&bignumValue, 10, &newValue) != MP_OKAY)) { 00214 mp_clear(&bignumValue); 00215 mp_clear(&newValue); 00216 Tcl_SetObjResult(interp, 00217 Tcl_NewStringObj("error in mp_mul_d", -1)); 00218 return TCL_ERROR; 00219 } 00220 mp_clear(&bignumValue); 00221 if (!Tcl_IsShared(varPtr[varIndex])) { 00222 Tcl_SetBignumObj(varPtr[varIndex], &newValue); 00223 } else { 00224 SetVarToObj(varIndex, Tcl_NewBignumObj(&newValue)); 00225 } 00226 break; 00227 00228 case BIGNUM_DIV10: 00229 if (objc != 3) { 00230 Tcl_WrongNumArgs(interp, 2, objv, "varIndex"); 00231 return TCL_ERROR; 00232 } 00233 if (CheckIfVarUnset(interp, varIndex)) { 00234 return TCL_ERROR; 00235 } 00236 if (Tcl_GetBignumFromObj(interp, varPtr[varIndex], 00237 &bignumValue) != TCL_OK) { 00238 return TCL_ERROR; 00239 } 00240 if (mp_init(&newValue) != MP_OKAY 00241 || (mp_div_d(&bignumValue, 10, &newValue, NULL) != MP_OKAY)) { 00242 mp_clear(&bignumValue); 00243 mp_clear(&newValue); 00244 Tcl_SetObjResult(interp, 00245 Tcl_NewStringObj("error in mp_div_d", -1)); 00246 return TCL_ERROR; 00247 } 00248 mp_clear(&bignumValue); 00249 if (!Tcl_IsShared(varPtr[varIndex])) { 00250 Tcl_SetBignumObj(varPtr[varIndex], &newValue); 00251 } else { 00252 SetVarToObj(varIndex, Tcl_NewBignumObj(&newValue)); 00253 } 00254 } 00255 00256 Tcl_SetObjResult(interp, varPtr[varIndex]); 00257 return TCL_OK; 00258 } 00259 00260 /* 00261 *---------------------------------------------------------------------- 00262 * 00263 * TestbooleanobjCmd -- 00264 * 00265 * This function implements the "testbooleanobj" command. It is used to 00266 * test the boolean Tcl object type implementation. 00267 * 00268 * Results: 00269 * A standard Tcl object result. 00270 * 00271 * Side effects: 00272 * Creates and frees boolean objects, and also converts objects to 00273 * have boolean type. 00274 * 00275 *---------------------------------------------------------------------- 00276 */ 00277 00278 static int 00279 TestbooleanobjCmd( 00280 ClientData clientData, /* Not used. */ 00281 Tcl_Interp *interp, /* Current interpreter. */ 00282 int objc, /* Number of arguments. */ 00283 Tcl_Obj *const objv[]) /* Argument objects. */ 00284 { 00285 int varIndex, boolValue; 00286 char *index, *subCmd; 00287 00288 if (objc < 3) { 00289 wrongNumArgs: 00290 Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?"); 00291 return TCL_ERROR; 00292 } 00293 00294 index = Tcl_GetString(objv[2]); 00295 if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { 00296 return TCL_ERROR; 00297 } 00298 00299 subCmd = Tcl_GetString(objv[1]); 00300 if (strcmp(subCmd, "set") == 0) { 00301 if (objc != 4) { 00302 goto wrongNumArgs; 00303 } 00304 if (Tcl_GetBooleanFromObj(interp, objv[3], &boolValue) != TCL_OK) { 00305 return TCL_ERROR; 00306 } 00307 00308 /* 00309 * If the object currently bound to the variable with index varIndex 00310 * has ref count 1 (i.e. the object is unshared) we can modify that 00311 * object directly. Otherwise, if RC>1 (i.e. the object is shared), 00312 * we must create a new object to modify/set and decrement the old 00313 * formerly-shared object's ref count. This is "copy on write". 00314 */ 00315 00316 if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { 00317 Tcl_SetBooleanObj(varPtr[varIndex], boolValue); 00318 } else { 00319 SetVarToObj(varIndex, Tcl_NewBooleanObj(boolValue)); 00320 } 00321 Tcl_SetObjResult(interp, varPtr[varIndex]); 00322 } else if (strcmp(subCmd, "get") == 0) { 00323 if (objc != 3) { 00324 goto wrongNumArgs; 00325 } 00326 if (CheckIfVarUnset(interp, varIndex)) { 00327 return TCL_ERROR; 00328 } 00329 Tcl_SetObjResult(interp, varPtr[varIndex]); 00330 } else if (strcmp(subCmd, "not") == 0) { 00331 if (objc != 3) { 00332 goto wrongNumArgs; 00333 } 00334 if (CheckIfVarUnset(interp, varIndex)) { 00335 return TCL_ERROR; 00336 } 00337 if (Tcl_GetBooleanFromObj(interp, varPtr[varIndex], 00338 &boolValue) != TCL_OK) { 00339 return TCL_ERROR; 00340 } 00341 if (!Tcl_IsShared(varPtr[varIndex])) { 00342 Tcl_SetBooleanObj(varPtr[varIndex], !boolValue); 00343 } else { 00344 SetVarToObj(varIndex, Tcl_NewBooleanObj(!boolValue)); 00345 } 00346 Tcl_SetObjResult(interp, varPtr[varIndex]); 00347 } else { 00348 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), 00349 "bad option \"", Tcl_GetString(objv[1]), 00350 "\": must be set, get, or not", NULL); 00351 return TCL_ERROR; 00352 } 00353 return TCL_OK; 00354 } 00355 00356 /* 00357 *---------------------------------------------------------------------- 00358 * 00359 * TestdoubleobjCmd -- 00360 * 00361 * This function implements the "testdoubleobj" command. It is used to 00362 * test the double-precision floating point Tcl object type 00363 * implementation. 00364 * 00365 * Results: 00366 * A standard Tcl object result. 00367 * 00368 * Side effects: 00369 * Creates and frees double objects, and also converts objects to 00370 * have double type. 00371 * 00372 *---------------------------------------------------------------------- 00373 */ 00374 00375 static int 00376 TestdoubleobjCmd( 00377 ClientData clientData, /* Not used. */ 00378 Tcl_Interp *interp, /* Current interpreter. */ 00379 int objc, /* Number of arguments. */ 00380 Tcl_Obj *const objv[]) /* Argument objects. */ 00381 { 00382 int varIndex; 00383 double doubleValue; 00384 char *index, *subCmd, *string; 00385 00386 if (objc < 3) { 00387 wrongNumArgs: 00388 Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?"); 00389 return TCL_ERROR; 00390 } 00391 00392 index = Tcl_GetString(objv[2]); 00393 if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { 00394 return TCL_ERROR; 00395 } 00396 00397 subCmd = Tcl_GetString(objv[1]); 00398 if (strcmp(subCmd, "set") == 0) { 00399 if (objc != 4) { 00400 goto wrongNumArgs; 00401 } 00402 string = Tcl_GetString(objv[3]); 00403 if (Tcl_GetDouble(interp, string, &doubleValue) != TCL_OK) { 00404 return TCL_ERROR; 00405 } 00406 00407 /* 00408 * If the object currently bound to the variable with index varIndex 00409 * has ref count 1 (i.e. the object is unshared) we can modify that 00410 * object directly. Otherwise, if RC>1 (i.e. the object is shared), we 00411 * must create a new object to modify/set and decrement the old 00412 * formerly-shared object's ref count. This is "copy on write". 00413 */ 00414 00415 if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { 00416 Tcl_SetDoubleObj(varPtr[varIndex], doubleValue); 00417 } else { 00418 SetVarToObj(varIndex, Tcl_NewDoubleObj(doubleValue)); 00419 } 00420 Tcl_SetObjResult(interp, varPtr[varIndex]); 00421 } else if (strcmp(subCmd, "get") == 0) { 00422 if (objc != 3) { 00423 goto wrongNumArgs; 00424 } 00425 if (CheckIfVarUnset(interp, varIndex)) { 00426 return TCL_ERROR; 00427 } 00428 Tcl_SetObjResult(interp, varPtr[varIndex]); 00429 } else if (strcmp(subCmd, "mult10") == 0) { 00430 if (objc != 3) { 00431 goto wrongNumArgs; 00432 } 00433 if (CheckIfVarUnset(interp, varIndex)) { 00434 return TCL_ERROR; 00435 } 00436 if (Tcl_GetDoubleFromObj(interp, varPtr[varIndex], 00437 &doubleValue) != TCL_OK) { 00438 return TCL_ERROR; 00439 } 00440 if (!Tcl_IsShared(varPtr[varIndex])) { 00441 Tcl_SetDoubleObj(varPtr[varIndex], (doubleValue * 10.0)); 00442 } else { 00443 SetVarToObj(varIndex, Tcl_NewDoubleObj( (doubleValue * 10.0) )); 00444 } 00445 Tcl_SetObjResult(interp, varPtr[varIndex]); 00446 } else if (strcmp(subCmd, "div10") == 0) { 00447 if (objc != 3) { 00448 goto wrongNumArgs; 00449 } 00450 if (CheckIfVarUnset(interp, varIndex)) { 00451 return TCL_ERROR; 00452 } 00453 if (Tcl_GetDoubleFromObj(interp, varPtr[varIndex], 00454 &doubleValue) != TCL_OK) { 00455 return TCL_ERROR; 00456 } 00457 if (!Tcl_IsShared(varPtr[varIndex])) { 00458 Tcl_SetDoubleObj(varPtr[varIndex], (doubleValue / 10.0)); 00459 } else { 00460 SetVarToObj(varIndex, Tcl_NewDoubleObj( (doubleValue / 10.0) )); 00461 } 00462 Tcl_SetObjResult(interp, varPtr[varIndex]); 00463 } else { 00464 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), 00465 "bad option \"", Tcl_GetString(objv[1]), 00466 "\": must be set, get, mult10, or div10", NULL); 00467 return TCL_ERROR; 00468 } 00469 return TCL_OK; 00470 } 00471 00472 /* 00473 *---------------------------------------------------------------------- 00474 * 00475 * TestindexobjCmd -- 00476 * 00477 * This function implements the "testindexobj" command. It is used to 00478 * test the index Tcl object type implementation. 00479 * 00480 * Results: 00481 * A standard Tcl object result. 00482 * 00483 * Side effects: 00484 * Creates and frees int objects, and also converts objects to 00485 * have int type. 00486 * 00487 *---------------------------------------------------------------------- 00488 */ 00489 00490 static int 00491 TestindexobjCmd( 00492 ClientData clientData, /* Not used. */ 00493 Tcl_Interp *interp, /* Current interpreter. */ 00494 int objc, /* Number of arguments. */ 00495 Tcl_Obj *const objv[]) /* Argument objects. */ 00496 { 00497 int allowAbbrev, index, index2, setError, i, result; 00498 const char **argv; 00499 static const char *tablePtr[] = {"a", "b", "check", NULL}; 00500 /* 00501 * Keep this structure declaration in sync with tclIndexObj.c 00502 */ 00503 struct IndexRep { 00504 VOID *tablePtr; /* Pointer to the table of strings */ 00505 int offset; /* Offset between table entries */ 00506 int index; /* Selected index into table. */ 00507 }; 00508 struct IndexRep *indexRep; 00509 00510 if ((objc == 3) && (strcmp(Tcl_GetString(objv[1]), 00511 "check") == 0)) { 00512 /* 00513 * This code checks to be sure that the results of Tcl_GetIndexFromObj 00514 * are properly cached in the object and returned on subsequent 00515 * lookups. 00516 */ 00517 00518 if (Tcl_GetIntFromObj(interp, objv[2], &index2) != TCL_OK) { 00519 return TCL_ERROR; 00520 } 00521 00522 Tcl_GetIndexFromObj(NULL, objv[1], tablePtr, "token", 0, &index); 00523 indexRep = (struct IndexRep *) objv[1]->internalRep.otherValuePtr; 00524 indexRep->index = index2; 00525 result = Tcl_GetIndexFromObj(NULL, objv[1], 00526 tablePtr, "token", 0, &index); 00527 if (result == TCL_OK) { 00528 Tcl_SetIntObj(Tcl_GetObjResult(interp), index); 00529 } 00530 return result; 00531 } 00532 00533 if (objc < 5) { 00534 Tcl_AppendToObj(Tcl_GetObjResult(interp), "wrong # args", -1); 00535 return TCL_ERROR; 00536 } 00537 00538 if (Tcl_GetBooleanFromObj(interp, objv[1], &setError) != TCL_OK) { 00539 return TCL_ERROR; 00540 } 00541 if (Tcl_GetBooleanFromObj(interp, objv[2], &allowAbbrev) != TCL_OK) { 00542 return TCL_ERROR; 00543 } 00544 00545 argv = (const char **) ckalloc((unsigned) ((objc-3) * sizeof(char *))); 00546 for (i = 4; i < objc; i++) { 00547 argv[i-4] = Tcl_GetString(objv[i]); 00548 } 00549 argv[objc-4] = NULL; 00550 00551 /* 00552 * Tcl_GetIndexFromObj assumes that the table is statically-allocated so 00553 * that its address is different for each index object. If we accidently 00554 * allocate a table at the same address as that cached in the index 00555 * object, clear out the object's cached state. 00556 */ 00557 00558 if ( objv[3]->typePtr != NULL 00559 && !strcmp( "index", objv[3]->typePtr->name ) ) { 00560 indexRep = (struct IndexRep *) objv[3]->internalRep.otherValuePtr; 00561 if (indexRep->tablePtr == (VOID *) argv) { 00562 objv[3]->typePtr->freeIntRepProc(objv[3]); 00563 objv[3]->typePtr = NULL; 00564 } 00565 } 00566 00567 result = Tcl_GetIndexFromObj((setError? interp : NULL), objv[3], 00568 argv, "token", (allowAbbrev? 0 : TCL_EXACT), &index); 00569 ckfree((char *) argv); 00570 if (result == TCL_OK) { 00571 Tcl_SetIntObj(Tcl_GetObjResult(interp), index); 00572 } 00573 return result; 00574 } 00575 00576 /* 00577 *---------------------------------------------------------------------- 00578 * 00579 * TestintobjCmd -- 00580 * 00581 * This function implements the "testintobj" command. It is used to 00582 * test the int Tcl object type implementation. 00583 * 00584 * Results: 00585 * A standard Tcl object result. 00586 * 00587 * Side effects: 00588 * Creates and frees int objects, and also converts objects to 00589 * have int type. 00590 * 00591 *---------------------------------------------------------------------- 00592 */ 00593 00594 static int 00595 TestintobjCmd( 00596 ClientData clientData, /* Not used. */ 00597 Tcl_Interp *interp, /* Current interpreter. */ 00598 int objc, /* Number of arguments. */ 00599 Tcl_Obj *const objv[]) /* Argument objects. */ 00600 { 00601 int intValue, varIndex, i; 00602 long longValue; 00603 char *index, *subCmd, *string; 00604 00605 if (objc < 3) { 00606 wrongNumArgs: 00607 Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?"); 00608 return TCL_ERROR; 00609 } 00610 00611 index = Tcl_GetString(objv[2]); 00612 if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { 00613 return TCL_ERROR; 00614 } 00615 00616 subCmd = Tcl_GetString(objv[1]); 00617 if (strcmp(subCmd, "set") == 0) { 00618 if (objc != 4) { 00619 goto wrongNumArgs; 00620 } 00621 string = Tcl_GetString(objv[3]); 00622 if (Tcl_GetInt(interp, string, &i) != TCL_OK) { 00623 return TCL_ERROR; 00624 } 00625 intValue = i; 00626 00627 /* 00628 * If the object currently bound to the variable with index varIndex 00629 * has ref count 1 (i.e. the object is unshared) we can modify that 00630 * object directly. Otherwise, if RC>1 (i.e. the object is shared), we 00631 * must create a new object to modify/set and decrement the old 00632 * formerly-shared object's ref count. This is "copy on write". 00633 */ 00634 00635 if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { 00636 Tcl_SetIntObj(varPtr[varIndex], intValue); 00637 } else { 00638 SetVarToObj(varIndex, Tcl_NewIntObj(intValue)); 00639 } 00640 Tcl_SetObjResult(interp, varPtr[varIndex]); 00641 } else if (strcmp(subCmd, "set2") == 0) { /* doesn't set result */ 00642 if (objc != 4) { 00643 goto wrongNumArgs; 00644 } 00645 string = Tcl_GetString(objv[3]); 00646 if (Tcl_GetInt(interp, string, &i) != TCL_OK) { 00647 return TCL_ERROR; 00648 } 00649 intValue = i; 00650 if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { 00651 Tcl_SetIntObj(varPtr[varIndex], intValue); 00652 } else { 00653 SetVarToObj(varIndex, Tcl_NewIntObj(intValue)); 00654 } 00655 } else if (strcmp(subCmd, "setlong") == 0) { 00656 if (objc != 4) { 00657 goto wrongNumArgs; 00658 } 00659 string = Tcl_GetString(objv[3]); 00660 if (Tcl_GetInt(interp, string, &i) != TCL_OK) { 00661 return TCL_ERROR; 00662 } 00663 intValue = i; 00664 if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { 00665 Tcl_SetLongObj(varPtr[varIndex], intValue); 00666 } else { 00667 SetVarToObj(varIndex, Tcl_NewLongObj(intValue)); 00668 } 00669 Tcl_SetObjResult(interp, varPtr[varIndex]); 00670 } else if (strcmp(subCmd, "setmaxlong") == 0) { 00671 long maxLong = LONG_MAX; 00672 if (objc != 3) { 00673 goto wrongNumArgs; 00674 } 00675 if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { 00676 Tcl_SetLongObj(varPtr[varIndex], maxLong); 00677 } else { 00678 SetVarToObj(varIndex, Tcl_NewLongObj(maxLong)); 00679 } 00680 } else if (strcmp(subCmd, "ismaxlong") == 0) { 00681 if (objc != 3) { 00682 goto wrongNumArgs; 00683 } 00684 if (CheckIfVarUnset(interp, varIndex)) { 00685 return TCL_ERROR; 00686 } 00687 if (Tcl_GetLongFromObj(interp, varPtr[varIndex], &longValue) != TCL_OK) { 00688 return TCL_ERROR; 00689 } 00690 Tcl_AppendToObj(Tcl_GetObjResult(interp), 00691 ((longValue == LONG_MAX)? "1" : "0"), -1); 00692 } else if (strcmp(subCmd, "get") == 0) { 00693 if (objc != 3) { 00694 goto wrongNumArgs; 00695 } 00696 if (CheckIfVarUnset(interp, varIndex)) { 00697 return TCL_ERROR; 00698 } 00699 Tcl_SetObjResult(interp, varPtr[varIndex]); 00700 } else if (strcmp(subCmd, "get2") == 0) { 00701 if (objc != 3) { 00702 goto wrongNumArgs; 00703 } 00704 if (CheckIfVarUnset(interp, varIndex)) { 00705 return TCL_ERROR; 00706 } 00707 string = Tcl_GetString(varPtr[varIndex]); 00708 Tcl_AppendToObj(Tcl_GetObjResult(interp), string, -1); 00709 } else if (strcmp(subCmd, "inttoobigtest") == 0) { 00710 /* 00711 * If long ints have more bits than ints on this platform, verify that 00712 * Tcl_GetIntFromObj returns an error if the long int held in an 00713 * integer object's internal representation is too large to fit in an 00714 * int. 00715 */ 00716 00717 if (objc != 3) { 00718 goto wrongNumArgs; 00719 } 00720 #if (INT_MAX == LONG_MAX) /* int is same size as long int */ 00721 Tcl_AppendToObj(Tcl_GetObjResult(interp), "1", -1); 00722 #else 00723 if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) { 00724 Tcl_SetLongObj(varPtr[varIndex], LONG_MAX); 00725 } else { 00726 SetVarToObj(varIndex, Tcl_NewLongObj(LONG_MAX)); 00727 } 00728 if (Tcl_GetIntFromObj(interp, varPtr[varIndex], &i) != TCL_OK) { 00729 Tcl_ResetResult(interp); 00730 Tcl_AppendToObj(Tcl_GetObjResult(interp), "1", -1); 00731 return TCL_OK; 00732 } 00733 Tcl_AppendToObj(Tcl_GetObjResult(interp), "0", -1); 00734 #endif 00735 } else if (strcmp(subCmd, "mult10") == 0) { 00736 if (objc != 3) { 00737 goto wrongNumArgs; 00738 } 00739 if (CheckIfVarUnset(interp, varIndex)) { 00740 return TCL_ERROR; 00741 } 00742 if (Tcl_GetIntFromObj(interp, varPtr[varIndex], 00743 &intValue) != TCL_OK) { 00744 return TCL_ERROR; 00745 } 00746 if (!Tcl_IsShared(varPtr[varIndex])) { 00747 Tcl_SetIntObj(varPtr[varIndex], (intValue * 10)); 00748 } else { 00749 SetVarToObj(varIndex, Tcl_NewIntObj( (intValue * 10) )); 00750 } 00751 Tcl_SetObjResult(interp, varPtr[varIndex]); 00752 } else if (strcmp(subCmd, "div10") == 0) { 00753 if (objc != 3) { 00754 goto wrongNumArgs; 00755 } 00756 if (CheckIfVarUnset(interp, varIndex)) { 00757 return TCL_ERROR; 00758 } 00759 if (Tcl_GetIntFromObj(interp, varPtr[varIndex], 00760 &intValue) != TCL_OK) { 00761 return TCL_ERROR; 00762 } 00763 if (!Tcl_IsShared(varPtr[varIndex])) { 00764 Tcl_SetIntObj(varPtr[varIndex], (intValue / 10)); 00765 } else { 00766 SetVarToObj(varIndex, Tcl_NewIntObj( (intValue / 10) )); 00767 } 00768 Tcl_SetObjResult(interp, varPtr[varIndex]); 00769 } else { 00770 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), 00771 "bad option \"", Tcl_GetString(objv[1]), 00772 "\": must be set, get, get2, mult10, or div10", NULL); 00773 return TCL_ERROR; 00774 } 00775 return TCL_OK; 00776 } 00777 00778 /* 00779 *---------------------------------------------------------------------- 00780 * 00781 * TestobjCmd -- 00782 * 00783 * This function implements the "testobj" command. It is used to test 00784 * the type-independent portions of the Tcl object type implementation. 00785 * 00786 * Results: 00787 * A standard Tcl object result. 00788 * 00789 * Side effects: 00790 * Creates and frees objects. 00791 * 00792 *---------------------------------------------------------------------- 00793 */ 00794 00795 static int 00796 TestobjCmd( 00797 ClientData clientData, /* Not used. */ 00798 Tcl_Interp *interp, /* Current interpreter. */ 00799 int objc, /* Number of arguments. */ 00800 Tcl_Obj *const objv[]) /* Argument objects. */ 00801 { 00802 int varIndex, destIndex, i; 00803 char *index, *subCmd, *string; 00804 Tcl_ObjType *targetType; 00805 00806 if (objc < 2) { 00807 wrongNumArgs: 00808 Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?"); 00809 return TCL_ERROR; 00810 } 00811 00812 subCmd = Tcl_GetString(objv[1]); 00813 if (strcmp(subCmd, "assign") == 0) { 00814 if (objc != 4) { 00815 goto wrongNumArgs; 00816 } 00817 index = Tcl_GetString(objv[2]); 00818 if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { 00819 return TCL_ERROR; 00820 } 00821 if (CheckIfVarUnset(interp, varIndex)) { 00822 return TCL_ERROR; 00823 } 00824 string = Tcl_GetString(objv[3]); 00825 if (GetVariableIndex(interp, string, &destIndex) != TCL_OK) { 00826 return TCL_ERROR; 00827 } 00828 SetVarToObj(destIndex, varPtr[varIndex]); 00829 Tcl_SetObjResult(interp, varPtr[destIndex]); 00830 } else if (strcmp(subCmd, "convert") == 0) { 00831 char *typeName; 00832 if (objc != 4) { 00833 goto wrongNumArgs; 00834 } 00835 index = Tcl_GetString(objv[2]); 00836 if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { 00837 return TCL_ERROR; 00838 } 00839 if (CheckIfVarUnset(interp, varIndex)) { 00840 return TCL_ERROR; 00841 } 00842 typeName = Tcl_GetString(objv[3]); 00843 if ((targetType = Tcl_GetObjType(typeName)) == NULL) { 00844 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), 00845 "no type ", typeName, " found", NULL); 00846 return TCL_ERROR; 00847 } 00848 if (Tcl_ConvertToType(interp, varPtr[varIndex], targetType) 00849 != TCL_OK) { 00850 return TCL_ERROR; 00851 } 00852 Tcl_SetObjResult(interp, varPtr[varIndex]); 00853 } else if (strcmp(subCmd, "duplicate") == 0) { 00854 if (objc != 4) { 00855 goto wrongNumArgs; 00856 } 00857 index = Tcl_GetString(objv[2]); 00858 if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { 00859 return TCL_ERROR; 00860 } 00861 if (CheckIfVarUnset(interp, varIndex)) { 00862 return TCL_ERROR; 00863 } 00864 string = Tcl_GetString(objv[3]); 00865 if (GetVariableIndex(interp, string, &destIndex) != TCL_OK) { 00866 return TCL_ERROR; 00867 } 00868 SetVarToObj(destIndex, Tcl_DuplicateObj(varPtr[varIndex])); 00869 Tcl_SetObjResult(interp, varPtr[destIndex]); 00870 } else if (strcmp(subCmd, "freeallvars") == 0) { 00871 if (objc != 2) { 00872 goto wrongNumArgs; 00873 } 00874 for (i = 0; i < NUMBER_OF_OBJECT_VARS; i++) { 00875 if (varPtr[i] != NULL) { 00876 Tcl_DecrRefCount(varPtr[i]); 00877 varPtr[i] = NULL; 00878 } 00879 } 00880 } else if ( strcmp ( subCmd, "invalidateStringRep" ) == 0 ) { 00881 if ( objc != 3 ) { 00882 goto wrongNumArgs; 00883 } 00884 index = Tcl_GetString( objv[2] ); 00885 if ( GetVariableIndex( interp, index, &varIndex ) != TCL_OK ) { 00886 return TCL_ERROR; 00887 } 00888 if (CheckIfVarUnset(interp, varIndex)) { 00889 return TCL_ERROR; 00890 } 00891 Tcl_InvalidateStringRep( varPtr[varIndex] ); 00892 Tcl_SetObjResult( interp, varPtr[varIndex] ); 00893 } else if (strcmp(subCmd, "newobj") == 0) { 00894 if (objc != 3) { 00895 goto wrongNumArgs; 00896 } 00897 index = Tcl_GetString(objv[2]); 00898 if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { 00899 return TCL_ERROR; 00900 } 00901 SetVarToObj(varIndex, Tcl_NewObj()); 00902 Tcl_SetObjResult(interp, varPtr[varIndex]); 00903 } else if (strcmp(subCmd, "objtype") == 0) { 00904 const char *typeName; 00905 00906 /* 00907 * return an object containing the name of the argument's type 00908 * of internal rep. If none exists, return "none". 00909 */ 00910 00911 if (objc != 3) { 00912 goto wrongNumArgs; 00913 } 00914 if (objv[2]->typePtr == NULL) { 00915 Tcl_SetObjResult(interp, Tcl_NewStringObj("none", -1)); 00916 } else { 00917 typeName = objv[2]->typePtr->name; 00918 Tcl_SetObjResult(interp, Tcl_NewStringObj(typeName, -1)); 00919 } 00920 } else if (strcmp(subCmd, "refcount") == 0) { 00921 char buf[TCL_INTEGER_SPACE]; 00922 00923 if (objc != 3) { 00924 goto wrongNumArgs; 00925 } 00926 index = Tcl_GetString(objv[2]); 00927 if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { 00928 return TCL_ERROR; 00929 } 00930 if (CheckIfVarUnset(interp, varIndex)) { 00931 return TCL_ERROR; 00932 } 00933 TclFormatInt(buf, varPtr[varIndex]->refCount); 00934 Tcl_SetResult(interp, buf, TCL_VOLATILE); 00935 } else if (strcmp(subCmd, "type") == 0) { 00936 if (objc != 3) { 00937 goto wrongNumArgs; 00938 } 00939 index = Tcl_GetString(objv[2]); 00940 if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { 00941 return TCL_ERROR; 00942 } 00943 if (CheckIfVarUnset(interp, varIndex)) { 00944 return TCL_ERROR; 00945 } 00946 if (varPtr[varIndex]->typePtr == NULL) { /* a string! */ 00947 Tcl_AppendToObj(Tcl_GetObjResult(interp), "string", -1); 00948 } else { 00949 Tcl_AppendToObj(Tcl_GetObjResult(interp), 00950 varPtr[varIndex]->typePtr->name, -1); 00951 } 00952 } else if (strcmp(subCmd, "types") == 0) { 00953 if (objc != 2) { 00954 goto wrongNumArgs; 00955 } 00956 if (Tcl_AppendAllObjTypes(interp, 00957 Tcl_GetObjResult(interp)) != TCL_OK) { 00958 return TCL_ERROR; 00959 } 00960 } else { 00961 Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), 00962 "bad option \"", Tcl_GetString(objv[1]), 00963 "\": must be assign, convert, duplicate, freeallvars, " 00964 "newobj, objcount, objtype, refcount, type, or types", NULL); 00965 return TCL_ERROR; 00966 } 00967 return TCL_OK; 00968 } 00969 00970 /* 00971 *---------------------------------------------------------------------- 00972 * 00973 * TeststringobjCmd -- 00974 * 00975 * This function implements the "teststringobj" command. It is used to 00976 * test the string Tcl object type implementation. 00977 * 00978 * Results: 00979 * A standard Tcl object result. 00980 * 00981 * Side effects: 00982 * Creates and frees string objects, and also converts objects to 00983 * have string type. 00984 * 00985 *---------------------------------------------------------------------- 00986 */ 00987 00988 static int 00989 TeststringobjCmd( 00990 ClientData clientData, /* Not used. */ 00991 Tcl_Interp *interp, /* Current interpreter. */ 00992 int objc, /* Number of arguments. */ 00993 Tcl_Obj *const objv[]) /* Argument objects. */ 00994 { 00995 int varIndex, option, i, length; 00996 #define MAX_STRINGS 11 00997 char *index, *string, *strings[MAX_STRINGS+1]; 00998 TestString *strPtr; 00999 static const char *options[] = { 01000 "append", "appendstrings", "get", "get2", "length", "length2", 01001 "set", "set2", "setlength", "ualloc", "getunicode", NULL 01002 }; 01003 01004 if (objc < 3) { 01005 wrongNumArgs: 01006 Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?"); 01007 return TCL_ERROR; 01008 } 01009 01010 index = Tcl_GetString(objv[2]); 01011 if (GetVariableIndex(interp, index, &varIndex) != TCL_OK) { 01012 return TCL_ERROR; 01013 } 01014 01015 if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0, &option) 01016 != TCL_OK) { 01017 return TCL_ERROR; 01018 } 01019 switch (option) { 01020 case 0: /* append */ 01021 if (objc != 5) { 01022 goto wrongNumArgs; 01023 } 01024 if (Tcl_GetIntFromObj(interp, objv[4], &length) != TCL_OK) { 01025 return TCL_ERROR; 01026 } 01027 if (varPtr[varIndex] == NULL) { 01028 SetVarToObj(varIndex, Tcl_NewObj()); 01029 } 01030 01031 /* 01032 * If the object bound to variable "varIndex" is shared, we must 01033 * "copy on write" and append to a copy of the object. 01034 */ 01035 01036 if (Tcl_IsShared(varPtr[varIndex])) { 01037 SetVarToObj(varIndex, Tcl_DuplicateObj(varPtr[varIndex])); 01038 } 01039 string = Tcl_GetString(objv[3]); 01040 Tcl_AppendToObj(varPtr[varIndex], string, length); 01041 Tcl_SetObjResult(interp, varPtr[varIndex]); 01042 break; 01043 case 1: /* appendstrings */ 01044 if (objc > (MAX_STRINGS+3)) { 01045 goto wrongNumArgs; 01046 } 01047 if (varPtr[varIndex] == NULL) { 01048 SetVarToObj(varIndex, Tcl_NewObj()); 01049 } 01050 01051 /* 01052 * If the object bound to variable "varIndex" is shared, we must 01053 * "copy on write" and append to a copy of the object. 01054 */ 01055 01056 if (Tcl_IsShared(varPtr[varIndex])) { 01057 SetVarToObj(varIndex, Tcl_DuplicateObj(varPtr[varIndex])); 01058 } 01059 for (i = 3; i < objc; i++) { 01060 strings[i-3] = Tcl_GetString(objv[i]); 01061 } 01062 for ( ; i < 12 + 3; i++) { 01063 strings[i - 3] = NULL; 01064 } 01065 Tcl_AppendStringsToObj(varPtr[varIndex], strings[0], strings[1], 01066 strings[2], strings[3], strings[4], strings[5], 01067 strings[6], strings[7], strings[8], strings[9], 01068 strings[10], strings[11]); 01069 Tcl_SetObjResult(interp, varPtr[varIndex]); 01070 break; 01071 case 2: /* get */ 01072 if (objc != 3) { 01073 goto wrongNumArgs; 01074 } 01075 if (CheckIfVarUnset(interp, varIndex)) { 01076 return TCL_ERROR; 01077 } 01078 Tcl_SetObjResult(interp, varPtr[varIndex]); 01079 break; 01080 case 3: /* get2 */ 01081 if (objc != 3) { 01082 goto wrongNumArgs; 01083 } 01084 if (CheckIfVarUnset(interp, varIndex)) { 01085 return TCL_ERROR; 01086 } 01087 string = Tcl_GetString(varPtr[varIndex]); 01088 Tcl_AppendToObj(Tcl_GetObjResult(interp), string, -1); 01089 break; 01090 case 4: /* length */ 01091 if (objc != 3) { 01092 goto wrongNumArgs; 01093 } 01094 Tcl_SetIntObj(Tcl_GetObjResult(interp), (varPtr[varIndex] != NULL) 01095 ? varPtr[varIndex]->length : -1); 01096 break; 01097 case 5: /* length2 */ 01098 if (objc != 3) { 01099 goto wrongNumArgs; 01100 } 01101 if (varPtr[varIndex] != NULL) { 01102 strPtr = (TestString *) 01103 (varPtr[varIndex])->internalRep.otherValuePtr; 01104 length = (int) strPtr->allocated; 01105 } else { 01106 length = -1; 01107 } 01108 Tcl_SetIntObj(Tcl_GetObjResult(interp), length); 01109 break; 01110 case 6: /* set */ 01111 if (objc != 4) { 01112 goto wrongNumArgs; 01113 } 01114 01115 /* 01116 * If the object currently bound to the variable with index 01117 * varIndex has ref count 1 (i.e. the object is unshared) we can 01118 * modify that object directly. Otherwise, if RC>1 (i.e. the 01119 * object is shared), we must create a new object to modify/set 01120 * and decrement the old formerly-shared object's ref count. This 01121 * is "copy on write". 01122 */ 01123 01124 string = Tcl_GetStringFromObj(objv[3], &length); 01125 if ((varPtr[varIndex] != NULL) 01126 && !Tcl_IsShared(varPtr[varIndex])) { 01127 Tcl_SetStringObj(varPtr[varIndex], string, length); 01128 } else { 01129 SetVarToObj(varIndex, Tcl_NewStringObj(string, length)); 01130 } 01131 Tcl_SetObjResult(interp, varPtr[varIndex]); 01132 break; 01133 case 7: /* set2 */ 01134 if (objc != 4) { 01135 goto wrongNumArgs; 01136 } 01137 SetVarToObj(varIndex, objv[3]); 01138 break; 01139 case 8: /* setlength */ 01140 if (objc != 4) { 01141 goto wrongNumArgs; 01142 } 01143 if (Tcl_GetIntFromObj(interp, objv[3], &length) != TCL_OK) { 01144 return TCL_ERROR; 01145 } 01146 if (varPtr[varIndex] != NULL) { 01147 Tcl_SetObjLength(varPtr[varIndex], length); 01148 } 01149 break; 01150 case 9: /* ualloc */ 01151 if (objc != 3) { 01152 goto wrongNumArgs; 01153 } 01154 if (varPtr[varIndex] != NULL) { 01155 strPtr = (TestString *) 01156 (varPtr[varIndex])->internalRep.otherValuePtr; 01157 length = (int) strPtr->uallocated; 01158 } else { 01159 length = -1; 01160 } 01161 Tcl_SetIntObj(Tcl_GetObjResult(interp), length); 01162 break; 01163 case 10: /* getunicode */ 01164 if (objc != 3) { 01165 goto wrongNumArgs; 01166 } 01167 Tcl_GetUnicodeFromObj(varPtr[varIndex], NULL); 01168 break; 01169 } 01170 01171 return TCL_OK; 01172 } 01173 01174 /* 01175 *---------------------------------------------------------------------- 01176 * 01177 * SetVarToObj -- 01178 * 01179 * Utility routine to assign a Tcl_Obj* to a test variable. The 01180 * Tcl_Obj* can be NULL. 01181 * 01182 * Results: 01183 * None. 01184 * 01185 * Side effects: 01186 * This routine handles ref counting details for assignment: i.e. the old 01187 * value's ref count must be decremented (if not NULL) and the new one 01188 * incremented (also if not NULL). 01189 * 01190 *---------------------------------------------------------------------- 01191 */ 01192 01193 static void 01194 SetVarToObj( 01195 int varIndex, /* Designates the assignment variable. */ 01196 Tcl_Obj *objPtr) /* Points to object to assign to var. */ 01197 { 01198 if (varPtr[varIndex] != NULL) { 01199 Tcl_DecrRefCount(varPtr[varIndex]); 01200 } 01201 varPtr[varIndex] = objPtr; 01202 if (objPtr != NULL) { 01203 Tcl_IncrRefCount(objPtr); 01204 } 01205 } 01206 01207 /* 01208 *---------------------------------------------------------------------- 01209 * 01210 * GetVariableIndex -- 01211 * 01212 * Utility routine to get a test variable index from the command line. 01213 * 01214 * Results: 01215 * A standard Tcl object result. 01216 * 01217 * Side effects: 01218 * None. 01219 * 01220 *---------------------------------------------------------------------- 01221 */ 01222 01223 static int 01224 GetVariableIndex( 01225 Tcl_Interp *interp, /* Interpreter for error reporting. */ 01226 char *string, /* String containing a variable index 01227 * specified as a nonnegative number less than 01228 * NUMBER_OF_OBJECT_VARS. */ 01229 int *indexPtr) /* Place to store converted result. */ 01230 { 01231 int index; 01232 01233 if (Tcl_GetInt(interp, string, &index) != TCL_OK) { 01234 return TCL_ERROR; 01235 } 01236 if (index < 0 || index >= NUMBER_OF_OBJECT_VARS) { 01237 Tcl_ResetResult(interp); 01238 Tcl_AppendToObj(Tcl_GetObjResult(interp), "bad variable index", -1); 01239 return TCL_ERROR; 01240 } 01241 01242 *indexPtr = index; 01243 return TCL_OK; 01244 } 01245 01246 /* 01247 *---------------------------------------------------------------------- 01248 * 01249 * CheckIfVarUnset -- 01250 * 01251 * Utility function that checks whether a test variable is readable: 01252 * i.e., that varPtr[varIndex] is non-NULL. 01253 * 01254 * Results: 01255 * 1 if the test variable is unset (NULL); 0 otherwise. 01256 * 01257 * Side effects: 01258 * Sets the interpreter result to an error message if the variable is 01259 * unset (NULL). 01260 * 01261 *---------------------------------------------------------------------- 01262 */ 01263 01264 static int 01265 CheckIfVarUnset( 01266 Tcl_Interp *interp, /* Interpreter for error reporting. */ 01267 int varIndex) /* Index of the test variable to check. */ 01268 { 01269 if (varPtr[varIndex] == NULL) { 01270 char buf[32 + TCL_INTEGER_SPACE]; 01271 01272 sprintf(buf, "variable %d is unset (NULL)", varIndex); 01273 Tcl_ResetResult(interp); 01274 Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1); 01275 return 1; 01276 } 01277 return 0; 01278 } 01279 01280 /* 01281 * Local Variables: 01282 * mode: c 01283 * c-basic-offset: 4 01284 * fill-column: 78 01285 * End: 01286 */
Generated on Wed Mar 12 12:18:22 2008 by 1.5.1 |