Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch tip-677 Excluding Merge-Ins
This is equivalent to a diff from b88bac358d to 83c46ed8c8
2023-12-11
| ||
14:35 | TIP 677: Constant Variables check-in: 0b4db30283 user: dkf tags: trunk, main | |
2023-12-08
| ||
09:57 | Backout [b88bac358d]: "Experimental: update automatic build instructions". Build is already broken f... check-in: c24b1f4852 user: jan.nijtmans tags: trunk, main | |
2023-12-06
| ||
15:01 | Fix introspection with TclOO resolution of consts Closed-Leaf check-in: 83c46ed8c8 user: dkf tags: tip-677 | |
2023-12-05
| ||
15:48 | Bytecode implementation check-in: f86dc8ec6b user: dkf tags: tip-677 | |
2023-11-26
| ||
22:21 | Fix [a606b0a528]: Tcl 9.0 fails to build from source for big-endian architectures check-in: 7af5aa4277 user: jan.nijtmans tags: trunk, main | |
2023-11-25
| ||
15:08 | Merge main into tip-677 check-in: 6cb29772da user: dkf tags: tip-677 | |
2023-11-24
| ||
15:58 | Experimental: update automatic build instructions check-in: b88bac358d user: dkf tags: trunk, main | |
14:38 | Merge 8.7 check-in: 56e92002a8 user: jan.nijtmans tags: trunk, main | |
12:50 | Simpler to use an existing action check-in: 51b3fe2a67 user: dkf tags: update-onfiledist | |
Added doc/const.n.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 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 79 80 81 82 83 84 85 | '\" '\" Copyright (c) 2023 Donal K. Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH const n 9.0 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME const \- create and initialize a constant .SH SYNOPSIS \fBconst \fIvarName value\fR .BE .SH DESCRIPTION .PP This command is normally used within a procedure body (or method body, or lambda term) to create a constant within that procedure, or within a \fBnamespace eval\fR body to create a constant within that namespace. The constant is an unmodifiable variable, called \fIvarName\fR, that is initialized with \fIvalue\fR. The result of \fBconst\fR is always the empty string on success. .PP If a variable \fIvarName\fR does not exist, it is created with its value set to \fIvalue\fR and marked as a constant; this means that no other command (e.g., \fBset\fR, \fBappend\fR, \fBincr\fR, \fBunset\fR) may modify or remove the variable; variables are checked for whether they are constants before any traces are called. If a variable \fIvarName\fR already exists, it is an error unless that variable is marked as a constant (in which case \fBconst\fR is a no-op). .PP The \fIvarName\fR may not be a qualified name or reference an element of an array by any means. If the variable exists and is an array, that is an error. .PP Constants are normally only removed by their containing procedure exiting or their namespace being deleted. .SH EXAMPLES .PP Create a constant in a procedure: .PP .CS proc foo {a b} { \fBconst\fR BAR 12345 return [expr {$a + $b + $BAR}] } .CE .PP Create a constant in a namespace to factor out a regular expression: .PP .CS namespace eval someNS { \fBconst\fR FOO_MATCHER {(?i)}\emfoo\eM} proc findFoos str { variable FOO_MATCHER regexp -all $FOO_MATCHER $str } proc findFooIndices str { variable FOO_MATCHER regexp -all -indices $FOO_MATCHER $str } } .CE .PP Making a constant in a loop doesn't error: .PP .CS proc foo {n} { set result {} for {set i 0} {$i < $n} {incr i} { \fBconst\fR X 123 lappend result [expr {$X + $i**2}] } } .CE .SH "SEE ALSO" proc(n), namespace(n), set(n), unset(n) .SH KEYWORDS namespace, procedure, variable, constant .\" Local variables: .\" mode: nroff .\" fill-column: 78 .\" End: |
Changes to doc/info.n.
︙ | ︙ | |||
80 81 82 83 84 85 86 87 88 89 90 91 92 93 | \fBnamespace\fR(n) documentation. .TP \fBinfo complete \fIcommand\fR . Returns 1 if \fIcommand\fR is a complete command, and \fB0\fR otherwise. Typically used in line-oriented input environments to allow users to type in commands that span multiple lines. .TP \fBinfo coroutine\fR . Returns the name of the current \fBcoroutine\fR, or the empty string if there is no current coroutine or the current coroutine has been deleted. .TP | > > > > > > > > > > > > > | 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | \fBnamespace\fR(n) documentation. .TP \fBinfo complete \fIcommand\fR . Returns 1 if \fIcommand\fR is a complete command, and \fB0\fR otherwise. Typically used in line-oriented input environments to allow users to type in commands that span multiple lines. .TP \fBinfo constant \fIvarName\fR .VS "TIP 677" Returns 1 if \fIvarName\fR is a constant variable (see \fBconst\fR) and 0 otherwise. .VE "TIP 677" .TP \fBinfo consts\fR ?\fIpattern\fR? .VS "TIP 677" Returns the list of constant variables (see \fBconst\fR) in the current scope, or the list of constant variables matching \fIpattern\fR (if that is provided) in a manner similar to \fBinfo vars\fR. .VE "TIP 677" .TP \fBinfo coroutine\fR . Returns the name of the current \fBcoroutine\fR, or the empty string if there is no current coroutine or the current coroutine has been deleted. .TP |
︙ | ︙ |
Changes to generic/tclBasic.c.
︙ | ︙ | |||
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 | */ {"append", Tcl_AppendObjCmd, TclCompileAppendCmd, NULL, CMD_IS_SAFE}, {"apply", Tcl_ApplyObjCmd, NULL, TclNRApplyObjCmd, CMD_IS_SAFE}, {"break", Tcl_BreakObjCmd, TclCompileBreakCmd, NULL, CMD_IS_SAFE}, {"catch", Tcl_CatchObjCmd, TclCompileCatchCmd, TclNRCatchObjCmd, CMD_IS_SAFE}, {"concat", Tcl_ConcatObjCmd, TclCompileConcatCmd, NULL, CMD_IS_SAFE}, {"continue", Tcl_ContinueObjCmd, TclCompileContinueCmd, NULL, CMD_IS_SAFE}, {"coroinject", NULL, NULL, TclNRCoroInjectObjCmd, CMD_IS_SAFE}, {"coroprobe", NULL, NULL, TclNRCoroProbeObjCmd, CMD_IS_SAFE}, {"coroutine", NULL, NULL, TclNRCoroutineObjCmd, CMD_IS_SAFE}, {"error", Tcl_ErrorObjCmd, TclCompileErrorCmd, NULL, CMD_IS_SAFE}, {"eval", Tcl_EvalObjCmd, NULL, TclNREvalObjCmd, CMD_IS_SAFE}, {"expr", Tcl_ExprObjCmd, TclCompileExprCmd, TclNRExprObjCmd, CMD_IS_SAFE}, {"for", Tcl_ForObjCmd, TclCompileForCmd, TclNRForObjCmd, CMD_IS_SAFE}, {"foreach", Tcl_ForeachObjCmd, TclCompileForeachCmd, TclNRForeachCmd, CMD_IS_SAFE}, {"format", Tcl_FormatObjCmd, TclCompileFormatCmd, NULL, CMD_IS_SAFE}, {"fpclassify", FloatClassifyObjCmd, NULL, NULL, CMD_IS_SAFE}, {"global", Tcl_GlobalObjCmd, TclCompileGlobalCmd, NULL, CMD_IS_SAFE}, {"if", Tcl_IfObjCmd, TclCompileIfCmd, TclNRIfObjCmd, CMD_IS_SAFE}, {"incr", Tcl_IncrObjCmd, TclCompileIncrCmd, NULL, CMD_IS_SAFE}, {"join", Tcl_JoinObjCmd, NULL, NULL, CMD_IS_SAFE}, {"lappend", Tcl_LappendObjCmd, TclCompileLappendCmd, NULL, CMD_IS_SAFE}, {"lassign", Tcl_LassignObjCmd, TclCompileLassignCmd, NULL, CMD_IS_SAFE}, | > | | 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 | */ {"append", Tcl_AppendObjCmd, TclCompileAppendCmd, NULL, CMD_IS_SAFE}, {"apply", Tcl_ApplyObjCmd, NULL, TclNRApplyObjCmd, CMD_IS_SAFE}, {"break", Tcl_BreakObjCmd, TclCompileBreakCmd, NULL, CMD_IS_SAFE}, {"catch", Tcl_CatchObjCmd, TclCompileCatchCmd, TclNRCatchObjCmd, CMD_IS_SAFE}, {"concat", Tcl_ConcatObjCmd, TclCompileConcatCmd, NULL, CMD_IS_SAFE}, {"const", Tcl_ConstObjCmd, TclCompileConstCmd, NULL, CMD_IS_SAFE}, {"continue", Tcl_ContinueObjCmd, TclCompileContinueCmd, NULL, CMD_IS_SAFE}, {"coroinject", NULL, NULL, TclNRCoroInjectObjCmd, CMD_IS_SAFE}, {"coroprobe", NULL, NULL, TclNRCoroProbeObjCmd, CMD_IS_SAFE}, {"coroutine", NULL, NULL, TclNRCoroutineObjCmd, CMD_IS_SAFE}, {"error", Tcl_ErrorObjCmd, TclCompileErrorCmd, NULL, CMD_IS_SAFE}, {"eval", Tcl_EvalObjCmd, NULL, TclNREvalObjCmd, CMD_IS_SAFE}, {"expr", Tcl_ExprObjCmd, TclCompileExprCmd, TclNRExprObjCmd, CMD_IS_SAFE}, {"for", Tcl_ForObjCmd, TclCompileForCmd, TclNRForObjCmd, CMD_IS_SAFE}, {"foreach", Tcl_ForeachObjCmd, TclCompileForeachCmd, TclNRForeachCmd, CMD_IS_SAFE}, {"format", Tcl_FormatObjCmd, TclCompileFormatCmd, NULL, CMD_IS_SAFE}, {"fpclassify", FloatClassifyObjCmd, NULL, NULL, CMD_IS_SAFE}, {"global", Tcl_GlobalObjCmd, TclCompileGlobalCmd, NULL, CMD_IS_SAFE}, {"if", Tcl_IfObjCmd, TclCompileIfCmd, TclNRIfObjCmd, CMD_IS_SAFE}, {"incr", Tcl_IncrObjCmd, TclCompileIncrCmd, NULL, CMD_IS_SAFE}, {"join", Tcl_JoinObjCmd, NULL, NULL, CMD_IS_SAFE}, {"lappend", Tcl_LappendObjCmd, TclCompileLappendCmd, NULL, CMD_IS_SAFE}, {"lassign", Tcl_LassignObjCmd, TclCompileLassignCmd, NULL, CMD_IS_SAFE}, {"ledit", Tcl_LeditObjCmd, NULL, NULL, CMD_IS_SAFE}, {"lindex", Tcl_LindexObjCmd, TclCompileLindexCmd, NULL, CMD_IS_SAFE}, {"linsert", Tcl_LinsertObjCmd, TclCompileLinsertCmd, NULL, CMD_IS_SAFE}, {"list", Tcl_ListObjCmd, TclCompileListCmd, NULL, CMD_IS_SAFE|CMD_COMPILES_EXPANDED}, {"llength", Tcl_LlengthObjCmd, TclCompileLlengthCmd, NULL, CMD_IS_SAFE}, {"lmap", Tcl_LmapObjCmd, TclCompileLmapCmd, TclNRLmapCmd, CMD_IS_SAFE}, {"lpop", Tcl_LpopObjCmd, NULL, NULL, CMD_IS_SAFE}, {"lrange", Tcl_LrangeObjCmd, TclCompileLrangeCmd, NULL, CMD_IS_SAFE}, |
︙ | ︙ |
Changes to generic/tclCmdIL.c.
︙ | ︙ | |||
156 157 158 159 160 161 162 163 164 165 166 167 168 169 | static const EnsembleImplMap defaultInfoMap[] = { {"args", InfoArgsCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"body", InfoBodyCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"cmdcount", InfoCmdCountCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0}, {"cmdtype", InfoCmdTypeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 1}, {"commands", InfoCommandsCmd, TclCompileInfoCommandsCmd, NULL, NULL, 0}, {"complete", InfoCompleteCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"coroutine", TclInfoCoroutineCmd, TclCompileInfoCoroutineCmd, NULL, NULL, 0}, {"default", InfoDefaultCmd, TclCompileBasic3ArgCmd, NULL, NULL, 0}, {"errorstack", InfoErrorStackCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"exists", TclInfoExistsCmd, TclCompileInfoExistsCmd, NULL, NULL, 0}, {"frame", InfoFrameCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"functions", InfoFunctionsCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"globals", TclInfoGlobalsCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, | > > | 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | static const EnsembleImplMap defaultInfoMap[] = { {"args", InfoArgsCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"body", InfoBodyCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"cmdcount", InfoCmdCountCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0}, {"cmdtype", InfoCmdTypeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 1}, {"commands", InfoCommandsCmd, TclCompileInfoCommandsCmd, NULL, NULL, 0}, {"complete", InfoCompleteCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"constant", TclInfoConstantCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"consts", TclInfoConstsCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"coroutine", TclInfoCoroutineCmd, TclCompileInfoCoroutineCmd, NULL, NULL, 0}, {"default", InfoDefaultCmd, TclCompileBasic3ArgCmd, NULL, NULL, 0}, {"errorstack", InfoErrorStackCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"exists", TclInfoExistsCmd, TclCompileInfoExistsCmd, NULL, NULL, 0}, {"frame", InfoFrameCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"functions", InfoFunctionsCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"globals", TclInfoGlobalsCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, |
︙ | ︙ |
Changes to generic/tclCompCmds.c.
︙ | ︙ | |||
911 912 913 914 915 916 917 918 919 920 921 922 923 924 | CompileWord(envPtr, tokenPtr, interp, i); } TclEmitInstInt4( INST_CONCAT_STK, i-1, envPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileContinueCmd -- * * Procedure called to compile the "continue" command. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 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 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 | CompileWord(envPtr, tokenPtr, interp, i); } TclEmitInstInt4( INST_CONCAT_STK, i-1, envPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileConstCmd -- * * Procedure called to compile the "const" command. * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "const" command at * runtime. * *---------------------------------------------------------------------- */ int TclCompileConstCmd( Tcl_Interp *interp, /* The interpreter. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ TCL_UNUSED(Command *), CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *varTokenPtr, *valueTokenPtr; int isScalar, localIndex; /* * Need exactly two arguments. */ if (parsePtr->numWords != 3) { return TCL_ERROR; } /* * Decide if we can use a frame slot for the var/array name or if we need * to emit code to compute and push the name at runtime. We use a frame * slot (entry in the array of local vars) if we are compiling a procedure * body and if the name is simple text that does not include namespace * qualifiers. */ varTokenPtr = TokenAfter(parsePtr->tokenPtr); PushVarNameWord(interp, varTokenPtr, envPtr, 0, &localIndex, &isScalar, 1); /* * If the user specified an array element, we don't bother handling * that. */ if (!isScalar) { return TCL_ERROR; } /* * We are doing an assignment to set the value of the constant. This will * need to be extended to push a value for each argument. */ valueTokenPtr = TokenAfter(varTokenPtr); CompileWord(envPtr, valueTokenPtr, interp, 2); if (localIndex < 0) { TclEmitOpcode(INST_CONST_STK, envPtr); } else { TclEmitInstInt4(INST_CONST_IMM, localIndex, envPtr); } /* * The const command's result is an empty string. */ PushStringLiteral(envPtr, ""); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileContinueCmd -- * * Procedure called to compile the "continue" command. |
︙ | ︙ |
Changes to generic/tclCompile.c.
︙ | ︙ | |||
660 661 662 663 664 665 666 667 668 669 670 671 672 673 | {"lreplace4", 6, INT_MIN, 2, {OPERAND_UINT4, OPERAND_UINT1}}, /* Operands: number of arguments, flags * flags: Combination of TCL_LREPLACE4_* flags * Stack: ... listobj index1 ?index2? new1 ... newN => ... newlistobj * where index2 is present only if TCL_LREPLACE_SINGLE_INDEX is not * set in flags. */ {NULL, 0, 0, 0, {OPERAND_NONE}} }; /* * Prototypes for procedures defined later in this file: */ | > > > > > > > | 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 | {"lreplace4", 6, INT_MIN, 2, {OPERAND_UINT4, OPERAND_UINT1}}, /* Operands: number of arguments, flags * flags: Combination of TCL_LREPLACE4_* flags * Stack: ... listobj index1 ?index2? new1 ... newN => ... newlistobj * where index2 is present only if TCL_LREPLACE_SINGLE_INDEX is not * set in flags. */ {"constImm", 5, -1, 1, {OPERAND_LVT4}}, /* Create constant. Index into LVT is immediate, value is on stack. * Stack: ... value => ... */ {"constStk", 1, -2, 0, {OPERAND_NONE}}, /* Create constant. Variable name and value on stack. * Stack: ... varName value => ... */ {NULL, 0, 0, 0, {OPERAND_NONE}} }; /* * Prototypes for procedures defined later in this file: */ |
︙ | ︙ |
Changes to generic/tclCompile.h.
︙ | ︙ | |||
832 833 834 835 836 837 838 839 840 841 842 843 844 845 | /* TIP 461 */ INST_STR_LT, INST_STR_GT, INST_STR_LE, INST_STR_GE, INST_LREPLACE4, /* The last opcode */ LAST_INST_OPCODE }; /* * Table describing the Tcl bytecode instructions: their name (for displaying | > > > > | 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 | /* TIP 461 */ INST_STR_LT, INST_STR_GT, INST_STR_LE, INST_STR_GE, INST_LREPLACE4, /* TIP 667: const */ INST_CONST_IMM, INST_CONST_STK, /* The last opcode */ LAST_INST_OPCODE }; /* * Table describing the Tcl bytecode instructions: their name (for displaying |
︙ | ︙ |
Changes to generic/tclExecute.c.
︙ | ︙ | |||
3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 | TRACE_ERROR(interp); goto gotError; } break; /* * End of INST_UNSET instructions. * ----------------------------------------------------------------- * Start of INST_ARRAY instructions. */ case INST_ARRAY_EXISTS_IMM: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 | TRACE_ERROR(interp); goto gotError; } break; /* * End of INST_UNSET instructions. * ----------------------------------------------------------------- * Start of INST_CONST instructions. */ { const char *msgPart; case INST_CONST_IMM: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; cleanup = 1; part1Ptr = NULL; objPtr = OBJ_AT_TOS; TRACE(("%u "\"%.30s\" => \n", opnd, O2S(objPtr))); varPtr = LOCAL(opnd); arrayPtr = NULL; while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } goto doConst; case INST_CONST_STK: opnd = -1; pcAdjustment = 1; cleanup = 2; part1Ptr = OBJ_UNDER_TOS; objPtr = OBJ_AT_TOS; TRACE(("\"%.30s\" \"%.30s\" => ", O2S(part1Ptr), O2S(objPtr))); varPtr = TclObjLookupVarEx(interp, part1Ptr, NULL, 0, NULL, /*createPart1*/1, /*createPart2*/0, &arrayPtr); doConst: if (TclIsVarConstant(varPtr)) { TRACE_APPEND(("\n")); NEXT_INST_V(pcAdjustment, cleanup, 0); } if (TclIsVarArray(varPtr)) { msgPart = "variable is array"; goto constError; } else if (TclIsVarArrayElement(varPtr)) { msgPart = "name refers to an element in an array"; goto constError; } else if (!TclIsVarUndefined(varPtr)) { msgPart = "variable already exists"; goto constError; } if (TclIsVarDirectModifyable(varPtr)) { varPtr->value.objPtr = objPtr; Tcl_IncrRefCount(objPtr); } else { Tcl_Obj *resPtr; DECACHE_STACK_INFO(); resPtr = TclPtrSetVarIdx(interp, varPtr, arrayPtr, part1Ptr, NULL, objPtr, TCL_LEAVE_ERR_MSG, opnd); CACHE_STACK_INFO(); if (resPtr == NULL) { TRACE_ERROR(interp); goto gotError; } } TclSetVarConstant(varPtr); TRACE_APPEND(("\n")); NEXT_INST_V(pcAdjustment, cleanup, 0); constError: TclObjVarErrMsg(interp, part1Ptr, NULL, "make constant", msgPart, opnd); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CONST", (void *)NULL); TRACE_ERROR(interp); goto gotError; } /* * End of INST_CONST instructions. * ----------------------------------------------------------------- * Start of INST_ARRAY instructions. */ case INST_ARRAY_EXISTS_IMM: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; |
︙ | ︙ |
Changes to generic/tclInt.h.
︙ | ︙ | |||
657 658 659 660 661 662 663 664 665 666 667 668 669 670 | * VAR_LINK - 1 means this Var structure contains a pointer * to another Var structure that either has the * real value or is itself another VAR_LINK * pointer. Variables like this come about * through "upvar" and "global" commands, or * through references to variables in enclosing * namespaces. * * Flags that indicate the type and status of storage; none is set for * compiled local variables (Var structs). * * VAR_IN_HASHTABLE - 1 means this variable is in a hash table and * the Var structure is malloc'ed. 0 if it is a * local variable that was assigned a slot in a | > > > > > | 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 | * VAR_LINK - 1 means this Var structure contains a pointer * to another Var structure that either has the * real value or is itself another VAR_LINK * pointer. Variables like this come about * through "upvar" and "global" commands, or * through references to variables in enclosing * namespaces. * VAR_CONSTANT - 1 means this is a constant "variable", and * cannot be written to by ordinary commands. * Structurally, it's the same as a scalar when * being read, but writes are rejected. Constants * are not supported inside arrays. * * Flags that indicate the type and status of storage; none is set for * compiled local variables (Var structs). * * VAR_IN_HASHTABLE - 1 means this variable is in a hash table and * the Var structure is malloc'ed. 0 if it is a * local variable that was assigned a slot in a |
︙ | ︙ | |||
721 722 723 724 725 726 727 728 729 730 731 732 733 734 | * Keep the flag values for VAR_ARGUMENT and VAR_TEMPORARY so that old values * in precompiled scripts keep working. */ /* Type of value (0 is scalar) */ #define VAR_ARRAY 0x1 #define VAR_LINK 0x2 /* Type of storage (0 is compiled local) */ #define VAR_IN_HASHTABLE 0x4 #define VAR_DEAD_HASH 0x8 #define VAR_ARRAY_ELEMENT 0x1000 #define VAR_NAMESPACE_VAR 0x80 /* KEEP OLD VALUE for Itcl */ | > | 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 | * Keep the flag values for VAR_ARGUMENT and VAR_TEMPORARY so that old values * in precompiled scripts keep working. */ /* Type of value (0 is scalar) */ #define VAR_ARRAY 0x1 #define VAR_LINK 0x2 #define VAR_CONSTANT 0x10000 /* Type of storage (0 is compiled local) */ #define VAR_IN_HASHTABLE 0x4 #define VAR_DEAD_HASH 0x8 #define VAR_ARRAY_ELEMENT 0x1000 #define VAR_NAMESPACE_VAR 0x80 /* KEEP OLD VALUE for Itcl */ |
︙ | ︙ | |||
755 756 757 758 759 760 761 762 763 764 765 766 767 | /* * Macros to ensure that various flag bits are set properly for variables. * The ANSI C "prototypes" for these macros are: * * MODULE_SCOPE void TclSetVarScalar(Var *varPtr); * MODULE_SCOPE void TclSetVarArray(Var *varPtr); * MODULE_SCOPE void TclSetVarLink(Var *varPtr); * MODULE_SCOPE void TclSetVarArrayElement(Var *varPtr); * MODULE_SCOPE void TclSetVarUndefined(Var *varPtr); * MODULE_SCOPE void TclClearVarUndefined(Var *varPtr); */ #define TclSetVarScalar(varPtr) \ | > | > > > | | 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 | /* * Macros to ensure that various flag bits are set properly for variables. * The ANSI C "prototypes" for these macros are: * * MODULE_SCOPE void TclSetVarScalar(Var *varPtr); * MODULE_SCOPE void TclSetVarArray(Var *varPtr); * MODULE_SCOPE void TclSetVarLink(Var *varPtr); * MODULE_SCOPE void TclSetVarConstant(Var *varPtr); * MODULE_SCOPE void TclSetVarArrayElement(Var *varPtr); * MODULE_SCOPE void TclSetVarUndefined(Var *varPtr); * MODULE_SCOPE void TclClearVarUndefined(Var *varPtr); */ #define TclSetVarScalar(varPtr) \ (varPtr)->flags &= ~(VAR_ARRAY|VAR_LINK|VAR_CONSTANT) #define TclSetVarArray(varPtr) \ (varPtr)->flags = ((varPtr)->flags & ~VAR_LINK) | VAR_ARRAY #define TclSetVarLink(varPtr) \ (varPtr)->flags = ((varPtr)->flags & ~VAR_ARRAY) | VAR_LINK #define TclSetVarConstant(varPtr) \ (varPtr)->flags = ((varPtr)->flags & ~(VAR_ARRAY|VAR_LINK)) | VAR_CONSTANT #define TclSetVarArrayElement(varPtr) \ (varPtr)->flags = ((varPtr)->flags & ~VAR_ARRAY) | VAR_ARRAY_ELEMENT #define TclSetVarUndefined(varPtr) \ (varPtr)->flags &= ~(VAR_ARRAY|VAR_LINK|VAR_CONSTANT);\ (varPtr)->value.objPtr = NULL #define TclClearVarUndefined(varPtr) #define TclSetVarTraceActive(varPtr) \ (varPtr)->flags |= VAR_TRACE_ACTIVE |
︙ | ︙ | |||
805 806 807 808 809 810 811 812 813 814 815 816 817 818 | } /* * Macros to read various flag bits of variables. * The ANSI C "prototypes" for these macros are: * * MODULE_SCOPE int TclIsVarScalar(Var *varPtr); * MODULE_SCOPE int TclIsVarLink(Var *varPtr); * MODULE_SCOPE int TclIsVarArray(Var *varPtr); * MODULE_SCOPE int TclIsVarUndefined(Var *varPtr); * MODULE_SCOPE int TclIsVarArrayElement(Var *varPtr); * MODULE_SCOPE int TclIsVarTemporary(Var *varPtr); * MODULE_SCOPE int TclIsVarArgument(Var *varPtr); * MODULE_SCOPE int TclIsVarResolved(Var *varPtr); | > | 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 | } /* * Macros to read various flag bits of variables. * The ANSI C "prototypes" for these macros are: * * MODULE_SCOPE int TclIsVarScalar(Var *varPtr); * MODULE_SCOPE int TclIsVarConstant(Var *varPtr); * MODULE_SCOPE int TclIsVarLink(Var *varPtr); * MODULE_SCOPE int TclIsVarArray(Var *varPtr); * MODULE_SCOPE int TclIsVarUndefined(Var *varPtr); * MODULE_SCOPE int TclIsVarArrayElement(Var *varPtr); * MODULE_SCOPE int TclIsVarTemporary(Var *varPtr); * MODULE_SCOPE int TclIsVarArgument(Var *varPtr); * MODULE_SCOPE int TclIsVarResolved(Var *varPtr); |
︙ | ︙ | |||
831 832 833 834 835 836 837 838 839 840 841 842 843 844 | #define TclIsVarLink(varPtr) \ ((varPtr)->flags & VAR_LINK) #define TclIsVarArray(varPtr) \ ((varPtr)->flags & VAR_ARRAY) #define TclIsVarUndefined(varPtr) \ ((varPtr)->value.objPtr == NULL) #define TclIsVarArrayElement(varPtr) \ ((varPtr)->flags & VAR_ARRAY_ELEMENT) #define TclIsVarNamespaceVar(varPtr) \ | > > > > | 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 | #define TclIsVarLink(varPtr) \ ((varPtr)->flags & VAR_LINK) #define TclIsVarArray(varPtr) \ ((varPtr)->flags & VAR_ARRAY) /* Implies scalar as well. */ #define TclIsVarConstant(varPtr) \ ((varPtr)->flags & VAR_CONSTANT) #define TclIsVarUndefined(varPtr) \ ((varPtr)->value.objPtr == NULL) #define TclIsVarArrayElement(varPtr) \ ((varPtr)->flags & VAR_ARRAY_ELEMENT) #define TclIsVarNamespaceVar(varPtr) \ |
︙ | ︙ | |||
890 891 892 893 894 895 896 | && (TclVarParentArray(varPtr)->flags & (trickyFlags)))) #define TclIsVarDirectReadable(varPtr) \ ( (!TclIsVarTricky(varPtr,VAR_TRACED_READ)) \ && (varPtr)->value.objPtr) #define TclIsVarDirectWritable(varPtr) \ | | | | | 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 | && (TclVarParentArray(varPtr)->flags & (trickyFlags)))) #define TclIsVarDirectReadable(varPtr) \ ( (!TclIsVarTricky(varPtr,VAR_TRACED_READ)) \ && (varPtr)->value.objPtr) #define TclIsVarDirectWritable(varPtr) \ (!TclIsVarTricky(varPtr,VAR_TRACED_WRITE|VAR_DEAD_HASH|VAR_CONSTANT)) #define TclIsVarDirectUnsettable(varPtr) \ (!TclIsVarTricky(varPtr,VAR_TRACED_READ|VAR_TRACED_WRITE|VAR_TRACED_UNSET|VAR_DEAD_HASH|VAR_CONSTANT)) #define TclIsVarDirectModifyable(varPtr) \ ( (!TclIsVarTricky(varPtr,VAR_TRACED_READ|VAR_TRACED_WRITE|VAR_CONSTANT)) \ && (varPtr)->value.objPtr) #define TclIsVarDirectReadable2(varPtr, arrayPtr) \ (TclIsVarDirectReadable(varPtr) &&\ (!(arrayPtr) || !((arrayPtr)->flags & VAR_TRACED_READ))) #define TclIsVarDirectWritable2(varPtr, arrayPtr) \ |
︙ | ︙ | |||
3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 | Tcl_Obj *part2Ptr, Tcl_Obj *incrPtr, int flags); MODULE_SCOPE Tcl_ObjCmdProc TclInfoExistsCmd; MODULE_SCOPE Tcl_ObjCmdProc TclInfoCoroutineCmd; MODULE_SCOPE Tcl_Obj * TclInfoFrame(Tcl_Interp *interp, CmdFrame *framePtr); MODULE_SCOPE Tcl_ObjCmdProc TclInfoGlobalsCmd; MODULE_SCOPE Tcl_ObjCmdProc TclInfoLocalsCmd; MODULE_SCOPE Tcl_ObjCmdProc TclInfoVarsCmd; MODULE_SCOPE void TclInitAlloc(void); MODULE_SCOPE void TclInitDbCkalloc(void); MODULE_SCOPE void TclInitDoubleConversion(void); MODULE_SCOPE void TclInitEmbeddedConfigurationInformation( Tcl_Interp *interp); MODULE_SCOPE void TclInitEncodingSubsystem(void); MODULE_SCOPE void TclInitIOSubsystem(void); | > > | 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 | Tcl_Obj *part2Ptr, Tcl_Obj *incrPtr, int flags); MODULE_SCOPE Tcl_ObjCmdProc TclInfoExistsCmd; MODULE_SCOPE Tcl_ObjCmdProc TclInfoCoroutineCmd; MODULE_SCOPE Tcl_Obj * TclInfoFrame(Tcl_Interp *interp, CmdFrame *framePtr); MODULE_SCOPE Tcl_ObjCmdProc TclInfoGlobalsCmd; MODULE_SCOPE Tcl_ObjCmdProc TclInfoLocalsCmd; MODULE_SCOPE Tcl_ObjCmdProc TclInfoVarsCmd; MODULE_SCOPE Tcl_ObjCmdProc TclInfoConstsCmd; MODULE_SCOPE Tcl_ObjCmdProc TclInfoConstantCmd; MODULE_SCOPE void TclInitAlloc(void); MODULE_SCOPE void TclInitDbCkalloc(void); MODULE_SCOPE void TclInitDoubleConversion(void); MODULE_SCOPE void TclInitEmbeddedConfigurationInformation( Tcl_Interp *interp); MODULE_SCOPE void TclInitEncodingSubsystem(void); MODULE_SCOPE void TclInitIOSubsystem(void); |
︙ | ︙ | |||
3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 | MODULE_SCOPE Tcl_ObjCmdProc TclChanPostEventObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclChanPopObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclChanPushObjCmd; MODULE_SCOPE void TclClockInit(Tcl_Interp *interp); MODULE_SCOPE Tcl_ObjCmdProc TclClockOldscanObjCmd; MODULE_SCOPE Tcl_ObjCmdProc Tcl_CloseObjCmd; MODULE_SCOPE Tcl_ObjCmdProc Tcl_ConcatObjCmd; MODULE_SCOPE Tcl_ObjCmdProc Tcl_ContinueObjCmd; MODULE_SCOPE Tcl_TimerToken TclCreateAbsoluteTimerHandler( Tcl_Time *timePtr, Tcl_TimerProc *proc, void *clientData); MODULE_SCOPE Tcl_ObjCmdProc TclDefaultBgErrorHandlerObjCmd; MODULE_SCOPE Tcl_Command TclInitDictCmd(Tcl_Interp *interp); MODULE_SCOPE int TclDictWithFinish(Tcl_Interp *interp, Var *varPtr, | > | 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 | MODULE_SCOPE Tcl_ObjCmdProc TclChanPostEventObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclChanPopObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclChanPushObjCmd; MODULE_SCOPE void TclClockInit(Tcl_Interp *interp); MODULE_SCOPE Tcl_ObjCmdProc TclClockOldscanObjCmd; MODULE_SCOPE Tcl_ObjCmdProc Tcl_CloseObjCmd; MODULE_SCOPE Tcl_ObjCmdProc Tcl_ConcatObjCmd; MODULE_SCOPE Tcl_ObjCmdProc Tcl_ConstObjCmd; MODULE_SCOPE Tcl_ObjCmdProc Tcl_ContinueObjCmd; MODULE_SCOPE Tcl_TimerToken TclCreateAbsoluteTimerHandler( Tcl_Time *timePtr, Tcl_TimerProc *proc, void *clientData); MODULE_SCOPE Tcl_ObjCmdProc TclDefaultBgErrorHandlerObjCmd; MODULE_SCOPE Tcl_Command TclInitDictCmd(Tcl_Interp *interp); MODULE_SCOPE int TclDictWithFinish(Tcl_Interp *interp, Var *varPtr, |
︙ | ︙ | |||
3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 | MODULE_SCOPE CompileProc TclCompileArraySetCmd; MODULE_SCOPE CompileProc TclCompileArrayUnsetCmd; MODULE_SCOPE CompileProc TclCompileBreakCmd; MODULE_SCOPE CompileProc TclCompileCatchCmd; MODULE_SCOPE CompileProc TclCompileClockClicksCmd; MODULE_SCOPE CompileProc TclCompileClockReadingCmd; MODULE_SCOPE CompileProc TclCompileConcatCmd; MODULE_SCOPE CompileProc TclCompileContinueCmd; MODULE_SCOPE CompileProc TclCompileDictAppendCmd; MODULE_SCOPE CompileProc TclCompileDictCreateCmd; MODULE_SCOPE CompileProc TclCompileDictExistsCmd; MODULE_SCOPE CompileProc TclCompileDictForCmd; MODULE_SCOPE CompileProc TclCompileDictGetCmd; MODULE_SCOPE CompileProc TclCompileDictGetWithDefaultCmd; | > | 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 | MODULE_SCOPE CompileProc TclCompileArraySetCmd; MODULE_SCOPE CompileProc TclCompileArrayUnsetCmd; MODULE_SCOPE CompileProc TclCompileBreakCmd; MODULE_SCOPE CompileProc TclCompileCatchCmd; MODULE_SCOPE CompileProc TclCompileClockClicksCmd; MODULE_SCOPE CompileProc TclCompileClockReadingCmd; MODULE_SCOPE CompileProc TclCompileConcatCmd; MODULE_SCOPE CompileProc TclCompileConstCmd; MODULE_SCOPE CompileProc TclCompileContinueCmd; MODULE_SCOPE CompileProc TclCompileDictAppendCmd; MODULE_SCOPE CompileProc TclCompileDictCreateCmd; MODULE_SCOPE CompileProc TclCompileDictExistsCmd; MODULE_SCOPE CompileProc TclCompileDictForCmd; MODULE_SCOPE CompileProc TclCompileDictGetCmd; MODULE_SCOPE CompileProc TclCompileDictGetWithDefaultCmd; |
︙ | ︙ |
Changes to generic/tclVar.c.
︙ | ︙ | |||
124 125 126 127 128 129 130 131 132 133 134 135 136 137 | "upvar refers to element in deleted array"; static const char DANGLINGVAR[] = "upvar refers to variable in deleted namespace"; static const char BADNAMESPACE[] = "parent namespace doesn't exist"; static const char MISSINGNAME[] = "missing variable name"; static const char ISARRAYELEMENT[] = "name refers to an element in an array"; /* * 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) | > > | 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | "upvar refers to element in deleted array"; static const char DANGLINGVAR[] = "upvar refers to variable in deleted namespace"; static const char BADNAMESPACE[] = "parent namespace doesn't exist"; static const char MISSINGNAME[] = "missing variable name"; static const char ISARRAYELEMENT[] = "name refers to an element in an array"; static const char ISCONST[] = "variable is a constant"; static const char EXISTS[] = "variable already exists"; /* * 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) |
︙ | ︙ | |||
174 175 176 177 178 179 180 | } ArrayVarHashTable; /* * Forward references to functions defined later in this file: */ static void AppendLocals(Tcl_Interp *interp, Tcl_Obj *listPtr, | | > | 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | } ArrayVarHashTable; /* * Forward references to functions defined later in this file: */ static void AppendLocals(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *patternPtr, int includeLinks, int justConstants); static void ArrayPopulateSearch(Tcl_Interp *interp, Tcl_Obj *arrayNameObj, Var *varPtr, ArraySearch *searchPtr); static void ArrayDoneSearch(Interp *iPtr, Var *varPtr, ArraySearch *searchPtr); static Tcl_NRPostProc ArrayForLoopCallback; static Tcl_ObjCmdProc ArrayForNRCmd; |
︙ | ︙ | |||
1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 | TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "set", DANGLINGVAR, index); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", (void *)NULL); } } goto earlyError; } /* * It's an error to try to set an array variable itself. */ if (TclIsVarArray(varPtr)) { if (flags & TCL_LEAVE_ERR_MSG) { | > > > > > > > > > > > | 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 | TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "set", DANGLINGVAR, index); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", (void *)NULL); } } goto earlyError; } /* * It's an error to try to set a constant. */ if (TclIsVarConstant(varPtr)) { if (flags & TCL_LEAVE_ERR_MSG) { TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "set", ISCONST,index); Tcl_SetErrorCode(interp, "TCL", "WRITE", "CONST", (void *)NULL); } goto earlyError; } /* * It's an error to try to set an array variable itself. */ if (TclIsVarArray(varPtr)) { if (flags & TCL_LEAVE_ERR_MSG) { |
︙ | ︙ | |||
2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 | * TCL_APPEND_VALUE, TCL_LIST_ELEMENT, * TCL_LEAVE_ERR_MSG. */ int index) /* Index into the local variable table of the * variable, or -1. Only used when part1Ptr is * NULL. */ { Tcl_Obj *varValuePtr; if (TclIsVarInHash(varPtr)) { VarHashRefCount(varPtr)++; } varValuePtr = TclPtrGetVarIdx(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, flags, index); if (TclIsVarInHash(varPtr)) { | > > > > > > > > > > > | 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 | * TCL_APPEND_VALUE, TCL_LIST_ELEMENT, * TCL_LEAVE_ERR_MSG. */ int index) /* Index into the local variable table of the * variable, or -1. Only used when part1Ptr is * NULL. */ { Tcl_Obj *varValuePtr; /* * It's an error to try to increment a constant. */ if (TclIsVarConstant(varPtr)) { if (flags & TCL_LEAVE_ERR_MSG) { TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "incr", ISCONST,index); Tcl_SetErrorCode(interp, "TCL", "WRITE", "CONST", (void *)NULL); } return NULL; } if (TclIsVarInHash(varPtr)) { VarHashRefCount(varPtr)++; } varValuePtr = TclPtrGetVarIdx(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, flags, index); if (TclIsVarInHash(varPtr)) { |
︙ | ︙ | |||
2425 2426 2427 2428 2429 2430 2431 | *---------------------------------------------------------------------- */ int TclPtrUnsetVarIdx( Tcl_Interp *interp, /* Command interpreter in which varName is to * be looked up. */ | | | > > > > > > > > > > > | 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 | *---------------------------------------------------------------------- */ int TclPtrUnsetVarIdx( Tcl_Interp *interp, /* Command interpreter in which varName is to * be looked up. */ Var *varPtr, /* The variable to be unset. */ Var *arrayPtr, /* NULL for scalar variables, pointer to the * containing array otherwise. */ Tcl_Obj *part1Ptr, /* Name of an array (if part2 is non-NULL) or * the name of a variable. */ Tcl_Obj *part2Ptr, /* If non-NULL, gives the name of an element * in the array part1. */ int flags, /* OR-ed combination of any of * TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * TCL_LEAVE_ERR_MSG. */ int index) /* Index into the local variable table of the * variable, or -1. Only used when part1Ptr is * NULL. */ { Interp *iPtr = (Interp *) interp; int result = (TclIsVarUndefined(varPtr)? TCL_ERROR : TCL_OK); Var *initialArrayPtr = arrayPtr; /* * It's an error to try to unset a constant. */ if (TclIsVarConstant(varPtr)) { if (flags & TCL_LEAVE_ERR_MSG) { TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "unset", ISCONST,index); Tcl_SetErrorCode(interp, "TCL", "UNSET", "CONST", (void *)NULL); } return TCL_ERROR; } /* * Keep the variable alive until we're done with it. We used to * increase/decrease the refCount for each operation, making it hard to * find [Bug 735335] - caused by unsetting the variable whose value was * the variable's name. */ |
︙ | ︙ | |||
4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 | } } } /* *---------------------------------------------------------------------- * * Tcl_GlobalObjCmd -- * * This object-based function is invoked to process the "global" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl object result value. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 | } } } /* *---------------------------------------------------------------------- * * Tcl_ConstObjCmd -- * * This function is invoked to process the "const" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl object result value. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ int Tcl_ConstObjCmd( TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Var *varPtr, *arrayPtr; Tcl_Obj *part1Ptr; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "varName value"); return TCL_ERROR; } part1Ptr = objv[1]; varPtr = TclObjLookupVarEx(interp, part1Ptr, NULL, TCL_LEAVE_ERR_MSG, "const", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr); if (TclIsVarArray(varPtr)) { TclObjVarErrMsg(interp, part1Ptr, NULL, "make constant", ISARRAY, -1); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CONST", (void *)NULL); return TCL_ERROR; } if (TclIsVarArrayElement(varPtr)) { if (TclIsVarUndefined(varPtr)) { CleanupVar(varPtr, arrayPtr); } TclObjVarErrMsg(interp, part1Ptr, NULL, "make constant", ISARRAYELEMENT, -1); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CONST", (void *)NULL); return TCL_ERROR; } /* * If already exists, either a constant (no problem) or an error. */ if (!TclIsVarUndefined(varPtr)) { if (TclIsVarConstant(varPtr)) { return TCL_OK; } TclObjVarErrMsg(interp, part1Ptr, NULL, "make constant", EXISTS, -1); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CONST", (void *)NULL); return TCL_ERROR; } /* * Make the variable and flag it as a constant. */ if (TclPtrSetVar(interp, (Tcl_Var) varPtr, NULL, objv[1], NULL, objv[2], TCL_LEAVE_ERR_MSG) == NULL) { if (TclIsVarUndefined(varPtr)) { CleanupVar(varPtr, arrayPtr); } return TCL_ERROR; }; TclSetVarConstant(varPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * Tcl_GlobalObjCmd -- * * This object-based function is invoked to process the "global" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl object result value. |
︙ | ︙ | |||
6031 6032 6033 6034 6035 6036 6037 | } } varPtr = VarHashNextVar(&search); } } } } else if (iPtr->varFramePtr->procPtr != NULL) { | | | 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 | } } varPtr = VarHashNextVar(&search); } } } } else if (iPtr->varFramePtr->procPtr != NULL) { AppendLocals(interp, listPtr, simplePatternPtr, 1, 0); } if (simplePatternPtr) { Tcl_DecrRefCount(simplePatternPtr); } Tcl_SetObjResult(interp, listPtr); return TCL_OK; |
︙ | ︙ | |||
6185 6186 6187 6188 6189 6190 6191 | /* * Return a list containing names of first the compiled locals (i.e. the * ones stored in the call frame), then the variables in the local hash * table (if one exists). */ listPtr = Tcl_NewListObj(0, NULL); | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | 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 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 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 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 6549 6550 | /* * Return a list containing names of first the compiled locals (i.e. the * ones stored in the call frame), then the variables in the local hash * table (if one exists). */ listPtr = Tcl_NewListObj(0, NULL); AppendLocals(interp, listPtr, patternPtr, 0, 0); Tcl_SetObjResult(interp, listPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclInfoConstsCmd -- * * Called to implement the "info consts" command that returns the list of * constants in the interpreter that match an optional pattern. The * pattern, if any, consists of an optional sequence of namespace names * separated by "::" qualifiers, which is followed by a glob-style * pattern that restricts which variables are returned. Handles the * following syntax: * * info consts ?pattern? * * Results: * Returns TCL_OK if successful and TCL_ERROR if there is an error. * * Side effects: * Returns a result in the interpreter's result object. If there is an * error, the result is an error message. * *---------------------------------------------------------------------- */ int TclInfoConstsCmd( TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; const char *varName, *pattern, *simplePattern; Tcl_HashSearch search; Var *varPtr; Namespace *nsPtr; Namespace *globalNsPtr = (Namespace *) Tcl_GetGlobalNamespace(interp); Namespace *currNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp); Tcl_Obj *listPtr, *elemObjPtr, *varNamePtr; int specificNsInPattern = 0;/* Init. to avoid compiler warning. */ Tcl_Obj *simplePatternPtr = NULL; /* * Get the pattern and find the "effective namespace" in which to list * variables. We only use this effective namespace if there's no active * Tcl procedure frame. */ if (objc == 1) { simplePattern = NULL; nsPtr = currNsPtr; specificNsInPattern = 0; } else if (objc == 2) { /* * From the pattern, get the effective namespace and the simple * pattern (no namespace qualifiers or ::'s) at the end. If an error * was found while parsing the pattern, return it. Otherwise, if the * namespace wasn't found, just leave nsPtr NULL: we will return an * empty list since no variables there can be found. */ Namespace *dummy1NsPtr, *dummy2NsPtr; pattern = TclGetString(objv[1]); TclGetNamespaceForQualName(interp, pattern, NULL, /*flags*/ 0, &nsPtr, &dummy1NsPtr, &dummy2NsPtr, &simplePattern); if (nsPtr != NULL) { /* We successfully found the pattern's ns. */ specificNsInPattern = (strcmp(simplePattern, pattern) != 0); if (simplePattern == pattern) { simplePatternPtr = objv[1]; } else { simplePatternPtr = Tcl_NewStringObj(simplePattern, -1); } Tcl_IncrRefCount(simplePatternPtr); } } else { Tcl_WrongNumArgs(interp, 1, objv, "?pattern?"); return TCL_ERROR; } /* * If the namespace specified in the pattern wasn't found, just return. */ if (nsPtr == NULL) { return TCL_OK; } listPtr = Tcl_NewListObj(0, NULL); if (!HasLocalVars(iPtr->varFramePtr) || specificNsInPattern) { /* * There is no frame pointer, the frame pointer was pushed only to * activate a namespace, or we are in a procedure call frame but a * specific namespace was specified. Create a list containing only the * variables in the effective namespace's variable table. */ if (simplePattern && TclMatchIsTrivial(simplePattern)) { /* * If we can just do hash lookups, that simplifies things a lot. */ varPtr = VarHashFindVar(&nsPtr->varTable, simplePatternPtr); if (varPtr && TclIsVarConstant(varPtr)) { if (!TclIsVarUndefined(varPtr) || TclIsVarNamespaceVar(varPtr)) { if (specificNsInPattern) { TclNewObj(elemObjPtr); Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr, elemObjPtr); } else { elemObjPtr = VarHashGetKey(varPtr); } Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr); } } else if ((nsPtr != globalNsPtr) && !specificNsInPattern) { varPtr = VarHashFindVar(&globalNsPtr->varTable, simplePatternPtr); if (varPtr && TclIsVarConstant(varPtr)) { if (!TclIsVarUndefined(varPtr) || TclIsVarNamespaceVar(varPtr)) { Tcl_ListObjAppendElement(interp, listPtr, VarHashGetKey(varPtr)); } } } } else { /* * Have to scan the tables of variables. */ varPtr = VarHashFirstVar(&nsPtr->varTable, &search); while (varPtr) { if (TclIsVarConstant(varPtr) && (!TclIsVarUndefined(varPtr) || TclIsVarNamespaceVar(varPtr))) { varNamePtr = VarHashGetKey(varPtr); varName = TclGetString(varNamePtr); if ((simplePattern == NULL) || Tcl_StringMatch(varName, simplePattern)) { if (specificNsInPattern) { TclNewObj(elemObjPtr); Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr, elemObjPtr); } else { elemObjPtr = varNamePtr; } Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr); } } varPtr = VarHashNextVar(&search); } /* * If the effective namespace isn't the global :: namespace, and a * specific namespace wasn't requested in the pattern (i.e., the * pattern only specifies variable names), then add in all global * :: variables that match the simple pattern. Of course, add in * only those variables that aren't hidden by a variable in the * effective namespace. */ if ((nsPtr != globalNsPtr) && !specificNsInPattern) { varPtr = VarHashFirstVar(&globalNsPtr->varTable, &search); while (varPtr) { if (TclIsVarConstant(varPtr) && (!TclIsVarUndefined(varPtr) || TclIsVarNamespaceVar(varPtr))) { varNamePtr = VarHashGetKey(varPtr); varName = TclGetString(varNamePtr); if ((simplePattern == NULL) || Tcl_StringMatch(varName, simplePattern)) { if (VarHashFindVar(&nsPtr->varTable, varNamePtr) == NULL) { Tcl_ListObjAppendElement(interp, listPtr, varNamePtr); } } } varPtr = VarHashNextVar(&search); } } } } else if (iPtr->varFramePtr->procPtr != NULL) { AppendLocals(interp, listPtr, simplePatternPtr, 1, 1); } if (simplePatternPtr) { Tcl_DecrRefCount(simplePatternPtr); } Tcl_SetObjResult(interp, listPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * AppendLocals -- * * Append the local variables for the current frame to the specified list * object. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static int ContextObjectContainsConstant( Tcl_ObjectContext context, Tcl_Obj *varNamePtr) { /* * Helper for AppendLocals to check if an object contains a variable * that is a constant. It's too complicated without factoring this * check out! */ Object *oPtr = (Object *) Tcl_ObjectContextObject(context); Namespace *nsPtr = (Namespace *) oPtr->namespacePtr; Var *varPtr = VarHashFindVar(&nsPtr->varTable, varNamePtr); return !TclIsVarUndefined(varPtr) && TclIsVarConstant(varPtr); } static void AppendLocals( Tcl_Interp *interp, /* Current interpreter. */ Tcl_Obj *listPtr, /* List object to append names to. */ Tcl_Obj *patternPtr, /* Pattern to match against. */ int includeLinks, /* 1 if upvars should be included, else 0. */ int justConstants) /* 1 if just constants should be included. */ { Interp *iPtr = (Interp *) interp; Var *varPtr; Tcl_Size i, localVarCt; int added; Tcl_Obj *objNamePtr; const char *varName; |
︙ | ︙ | |||
6241 6242 6243 6244 6245 6246 6247 | for (i = 0; i < localVarCt; i++, varNamePtr++) { /* * Skip nameless (temporary) variables and undefined variables. */ if (*varNamePtr && !TclIsVarUndefined(varPtr) | | > | > | 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 6578 6579 6580 6581 6582 6583 6584 | for (i = 0; i < localVarCt; i++, varNamePtr++) { /* * Skip nameless (temporary) variables and undefined variables. */ if (*varNamePtr && !TclIsVarUndefined(varPtr) && (includeLinks || !TclIsVarLink(varPtr))) { varName = TclGetString(*varNamePtr); if ((pattern == NULL) || Tcl_StringMatch(varName, pattern)) { if (!justConstants || TclIsVarConstant(varPtr)) { Tcl_ListObjAppendElement(interp, listPtr, *varNamePtr); } if (includeLinks) { Tcl_CreateHashEntry(&addedTable, *varNamePtr, &added); } } } varPtr++; } |
︙ | ︙ | |||
6271 6272 6273 6274 6275 6276 6277 | */ if ((pattern != NULL) && TclMatchIsTrivial(pattern)) { varPtr = VarHashFindVar(localVarTablePtr, patternPtr); if (varPtr != NULL) { if (!TclIsVarUndefined(varPtr) && (includeLinks || !TclIsVarLink(varPtr))) { | > | | > | 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 | */ if ((pattern != NULL) && TclMatchIsTrivial(pattern)) { varPtr = VarHashFindVar(localVarTablePtr, patternPtr); if (varPtr != NULL) { if (!TclIsVarUndefined(varPtr) && (includeLinks || !TclIsVarLink(varPtr))) { if ((!justConstants || TclIsVarConstant(varPtr))) { Tcl_ListObjAppendElement(interp, listPtr, VarHashGetKey(varPtr)); } if (includeLinks) { Tcl_CreateHashEntry(&addedTable, VarHashGetKey(varPtr), &added); } } } goto objectVars; |
︙ | ︙ | |||
6294 6295 6296 6297 6298 6299 6300 | varPtr != NULL; varPtr = VarHashNextVar(&search)) { if (!TclIsVarUndefined(varPtr) && (includeLinks || !TclIsVarLink(varPtr))) { objNamePtr = VarHashGetKey(varPtr); varName = TclGetString(objNamePtr); if ((pattern == NULL) || Tcl_StringMatch(varName, pattern)) { | > | > > > | < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 6752 6753 6754 6755 6756 6757 | varPtr != NULL; varPtr = VarHashNextVar(&search)) { if (!TclIsVarUndefined(varPtr) && (includeLinks || !TclIsVarLink(varPtr))) { objNamePtr = VarHashGetKey(varPtr); varName = TclGetString(objNamePtr); if ((pattern == NULL) || Tcl_StringMatch(varName, pattern)) { if (!justConstants || TclIsVarConstant(varPtr)) { Tcl_ListObjAppendElement(interp, listPtr, objNamePtr); } if (includeLinks) { Tcl_CreateHashEntry(&addedTable, objNamePtr, &added); } } } } objectVars: if (!includeLinks) { return; } if (iPtr->varFramePtr->isProcCallFrame & FRAME_IS_METHOD) { Tcl_ObjectContext context = (Tcl_ObjectContext) iPtr->varFramePtr->clientData; Method *mPtr = (Method *) Tcl_ObjectContextMethod(context); PrivateVariableMapping *privatePtr; if (mPtr->declaringObjectPtr) { Object *oPtr = mPtr->declaringObjectPtr; FOREACH(objNamePtr, oPtr->variables) { Tcl_CreateHashEntry(&addedTable, objNamePtr, &added); if (justConstants && !ContextObjectContainsConstant(context, objNamePtr)) { continue; } if (added && (!pattern || Tcl_StringMatch(TclGetString(objNamePtr), pattern))) { Tcl_ListObjAppendElement(interp, listPtr, objNamePtr); } } FOREACH_STRUCT(privatePtr, oPtr->privateVariables) { Tcl_CreateHashEntry(&addedTable, privatePtr->variableObj, &added); if (justConstants && !ContextObjectContainsConstant(context, privatePtr->fullNameObj)) { continue; } if (added && (!pattern || Tcl_StringMatch(TclGetString(privatePtr->variableObj), pattern))) { Tcl_ListObjAppendElement(interp, listPtr, privatePtr->variableObj); } } } else { Class *clsPtr = mPtr->declaringClassPtr; FOREACH(objNamePtr, clsPtr->variables) { Tcl_CreateHashEntry(&addedTable, objNamePtr, &added); if (justConstants && !ContextObjectContainsConstant(context, objNamePtr)) { continue; } if (added && (!pattern || Tcl_StringMatch(TclGetString(objNamePtr), pattern))) { Tcl_ListObjAppendElement(interp, listPtr, objNamePtr); } } FOREACH_STRUCT(privatePtr, clsPtr->privateVariables) { Tcl_CreateHashEntry(&addedTable, privatePtr->variableObj, &added); if (justConstants && !ContextObjectContainsConstant(context, privatePtr->fullNameObj)) { continue; } if (added && (!pattern || Tcl_StringMatch(TclGetString(privatePtr->variableObj), pattern))) { Tcl_ListObjAppendElement(interp, listPtr, privatePtr->variableObj); } } } } Tcl_DeleteHashTable(&addedTable); } /* *---------------------------------------------------------------------- * * TclInfoConstantCmd -- * * Called to implement the "info constant" command that wests whether a * specific variable is a constant. Handles the following syntax: * * info constant varName * * Results: * Returns TCL_OK if successful and TCL_ERROR if there is an error. * * Side effects: * Returns a result in the interpreter's result object. If there is an * error, the result is an error message. * *---------------------------------------------------------------------- */ int TclInfoConstantCmd( TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Var *varPtr, *arrayPtr; int result; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "varName"); return TCL_ERROR; } varPtr = TclObjLookupVar(interp, objv[1], NULL, 0, "lookup", 0, 0, &arrayPtr); result = (varPtr && TclIsVarConstant(varPtr)); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); return TCL_OK; } /* * Hash table implementation - first, just copy and adapt the obj key stuff */ void TclInitVarHashTable( |
︙ | ︙ |
Changes to tests/info.test.
︙ | ︙ | |||
674 675 676 677 678 679 680 | unset functions msg test info-21.1 {miscellaneous error conditions} -returnCodes error -body { info } -result {wrong # args: should be "info subcommand ?arg ...?"} test info-21.2 {miscellaneous error conditions} -returnCodes error -body { info gorp | | | | | | 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 | unset functions msg test info-21.1 {miscellaneous error conditions} -returnCodes error -body { info } -result {wrong # args: should be "info subcommand ?arg ...?"} test info-21.2 {miscellaneous error conditions} -returnCodes error -body { info gorp } -result {unknown or ambiguous subcommand "gorp": must be args, body, class, cmdcount, cmdtype, commands, complete, constant, consts, coroutine, default, errorstack, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars} test info-21.3 {miscellaneous error conditions} -returnCodes error -body { info c } -result {unknown or ambiguous subcommand "c": must be args, body, class, cmdcount, cmdtype, commands, complete, constant, consts, coroutine, default, errorstack, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars} test info-21.4 {miscellaneous error conditions} -returnCodes error -body { info l } -result {unknown or ambiguous subcommand "l": must be args, body, class, cmdcount, cmdtype, commands, complete, constant, consts, coroutine, default, errorstack, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars} test info-21.5 {miscellaneous error conditions} -returnCodes error -body { info s } -result {unknown or ambiguous subcommand "s": must be args, body, class, cmdcount, cmdtype, commands, complete, constant, consts, coroutine, default, errorstack, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars} ## # ### ### ### ######### ######### ######### ## info frame ## Helper # For the more complex results we cut the file name down to remove path |
︙ | ︙ |
Changes to tests/var.test.
︙ | ︙ | |||
1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 | test var-24.24 {array default unset: errors} -setup { unset -nocomplain ary } -body { array default unset ary x } -returnCodes error -cleanup { unset -nocomplain ary } -result * -match glob catch {namespace delete ns} catch {unset arr} catch {unset v} catch {rename getbytes ""} catch {rename p ""} | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 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 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 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 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 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 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 | test var-24.24 {array default unset: errors} -setup { unset -nocomplain ary } -body { array default unset ary x } -returnCodes error -cleanup { unset -nocomplain ary } -result * -match glob # The const command test var-25.1 {const: no argument} -body { apply {{} { const return $X }} } -returnCodes error -result {wrong # args: should be "const varName value"} test var-25.2 {const: single argument} -body { apply {{} { const X return $X }} } -returnCodes error -result {wrong # args: should be "const varName value"} test var-25.3 {const: two arguments (basic correct usage)} { apply {{} { set res [const X gorp] return [list $res $X] }} } {{} gorp} test var-25.4 {const: three arguments} -body { apply {{} { const X gorp foo return $X }} } -returnCodes error -result {wrong # args: should be "const varName value"} test var-25.5 {const: four arguments} -body { apply {{} { const X gorp foo bar return $X }} } -returnCodes error -result {wrong # args: should be "const varName value"} test var-26.1 {const: unmodifiable by set} -body { apply {{} { const X 123 set X gorp }} } -returnCodes error -result {can't set "X": variable is a constant} test var-26.2 {const: unmodifiable by append} -body { apply {{} { const X 123 append X gorp }} } -returnCodes error -result {can't set "X": variable is a constant} test var-26.3 {const: unmodifiable by lappend} -body { apply {{} { const X 123 lappend X gorp }} } -returnCodes error -result {can't set "X": variable is a constant} test var-26.4 {const: unmodifiable by incr} -body { apply {{} { const X 123 incr X }} } -returnCodes error -result {can't incr "X": variable is a constant} test var-26.5 {const: unmodifiable by dict set} -body { apply {{} { const X {a 123} dict set X a gorp }} } -returnCodes error -result {can't set "X": variable is a constant} test var-26.6 {const: unmodifiable by regsub} -body { apply {{} { const X abcabc regsub -all {a(.)} $X {\1\1} X }} } -returnCodes error -result {can't set "X": variable is a constant} test var-26.7 {const: unmodifiable by gets} -setup { set file [makeFile foo var26.7.txt] set f [open $file] } -body { apply {f { const X abcabc gets $f X }} $f } -returnCodes error -cleanup { close $f removeFile $file } -result {can't set "X": variable is a constant} test var-26.8 {const: may not be array} -body { apply {{} { array set X {a b} const X 1 return $X }} } -returnCodes error -result {can't make constant "X": variable is array} test var-26.9.1 {const: may not be array element} -body { apply {{} { array set X {a b} const X(a) 1 return $X(a) }} } -returnCodes error -result {can't make constant "X(a)": name refers to an element in an array} test var-26.9.2 {const: may not be array element} -body { apply {{} { array set X {a b} const X(b) 1 return $X(b) }} } -returnCodes error -result {can't make constant "X(b)": name refers to an element in an array} test var-26.10.1 {const: unmodifiable by const but not an error} { apply {{} { const X 1 const X 2 return $X }} } 1 test var-26.10.2 {const: unmodifiable by const but not an error} { apply {{} { lmap x {1 2 3} { const A 2 const B 3 const C 5 expr {$A * $x**2 + $B * $x + $C} } }} } {10 19 32} test var-26.11 {const: may not be unset} -body { apply {{} { const X 1 unset X }} } -returnCodes error -result {can't unset "X": variable is a constant} test var-26.12 {const: may not be unset, but -nocomplain doesn't complain} { apply {{} { const X 1 unset -nocomplain X return $X }} } 1 test var-26.13 {const and traces: write trace causes fail} -body { apply {{} { trace add variable X write {apply {args { error "ERR: $args" }}} const X gorp return $X }} } -returnCodes error -result {can't set "X": ERR: X {} write} test var-26.14 {const and traces: write trace err causes no const} -body { apply {{} { set trace {apply {args { error "ERR: $args" }}} trace add variable X write $trace catch { const X gorp } trace remove variable X write $trace set X 123 return $X }} } -result 123 test var-26.15 {const and traces: read traces} -setup { unset -nocomplain traces set traces {} } -body { apply {{} { trace add variable X read {apply {args { lappend ::traces $args }}} const X gorp list $X $X $::traces }} } -result {gorp gorp {{X {} read} {X {} read}}} -cleanup { unset -nocomplain traces } test var-26.16 {const and traces: write traces} -setup { unset -nocomplain traces set traces {} } -body { apply {{} { trace add variable X write {apply {args { lappend ::traces $args }}} const X gorp const X foo catch {set X bar} list $X $::traces }} } -result {gorp {{X {} write}}} -cleanup { unset -nocomplain traces } test var-26.17 {const and traces: unset traces} -setup { unset -nocomplain traces set traces {} } -body { list {*}[apply {{} { trace add variable X unset {apply {args { lappend ::traces $args }}} const X gorp unset -nocomplain X list $X $::traces }}] $traces } -result {gorp {} {{X {} unset}}} -cleanup { unset -nocomplain traces } # Same [const], but definitely not compiled test var-27.1 {const: unmodifiable by set} -body { apply {const { $const X 123 set X gorp }} const } -returnCodes error -result {can't set "X": variable is a constant} test var-27.2 {const: unmodifiable by append} -body { apply {const { $const X 123 append X gorp }} const } -returnCodes error -result {can't set "X": variable is a constant} test var-27.3 {const: unmodifiable by lappend} -body { apply {const { $const X 123 lappend X gorp }} const } -returnCodes error -result {can't set "X": variable is a constant} test var-27.4 {const: unmodifiable by incr} -body { apply {const { $const X 123 incr X }} const } -returnCodes error -result {can't incr "X": variable is a constant} test var-27.5 {const: unmodifiable by dict set} -body { apply {const { $const X {a 123} dict set X a gorp }} const } -returnCodes error -result {can't set "X": variable is a constant} test var-27.6 {const: unmodifiable by regsub} -body { apply {const { $const X abcabc regsub -all {a(.)} $X {\1\1} X }} const } -returnCodes error -result {can't set "X": variable is a constant} test var-27.7 {const: unmodifiable by gets} -setup { set file [makeFile foo var27.7.txt] set f [open $file] } -body { apply {{const f} { $const X abcabc gets $f X }} const $f } -returnCodes error -cleanup { close $f removeFile $file } -result {can't set "X": variable is a constant} test var-27.8 {const: may not be array} -body { apply {const { array set X {a b} $const X 1 return $X }} const } -returnCodes error -result {can't make constant "X": variable is array} test var-27.9.1 {const: may not be array element} -body { apply {const { array set X {a b} $const X(a) 1 return $X(a) }} const } -returnCodes error -result {can't make constant "X(a)": name refers to an element in an array} test var-27.9.2 {const: may not be array element} -body { apply {const { array set X {a b} $const X(b) 1 return $X(b) }} const } -returnCodes error -result {can't make constant "X(b)": name refers to an element in an array} test var-27.10.1 {const: unmodifiable by const but not an error} { apply {const { $const X 1 $const X 2 return $X }} const } 1 test var-27.10.2 {const: unmodifiable by const but not an error} { apply {const { lmap x {1 2 3} { $const A 2 $const B 3 $const C 5 expr {$A * $x**2 + $B * $x + $C} } }} const } {10 19 32} test var-27.11 {const: may not be unset} -body { apply {const { $const X 1 unset X }} const } -returnCodes error -result {can't unset "X": variable is a constant} test var-27.12 {const: may not be unset, but -nocomplain doesn't complain} { apply {const { $const X 1 unset -nocomplain X return $X }} const } 1 test var-27.13 {const and traces: write trace causes fail} -body { apply {const { trace add variable X write {apply {args { error "ERR: $args" }}} $const X gorp return $X }} const } -returnCodes error -result {can't set "X": ERR: X {} write} test var-27.14 {const and traces: write trace err causes no const} -body { apply {const { set trace {apply {args { error "ERR: $args" }}} trace add variable X write $trace catch { $const X gorp } trace remove variable X write $trace set X 123 return $X }} const } -result 123 test var-27.15 {const and traces: read traces} -setup { unset -nocomplain traces set traces {} } -body { apply {const { trace add variable X read {apply {args { lappend ::traces $args }}} $const X gorp list $X $X $::traces }} const } -result {gorp gorp {{X {} read} {X {} read}}} -cleanup { unset -nocomplain traces } test var-27.16 {const and traces: write traces} -setup { unset -nocomplain traces set traces {} } -body { apply {const { trace add variable X write {apply {args { lappend ::traces $args }}} $const X gorp $const X foo catch {set X bar} list $X $::traces }} const } -result {gorp {{X {} write}}} -cleanup { unset -nocomplain traces } test var-27.17 {const and traces: unset traces} -setup { unset -nocomplain traces set traces {} } -body { list {*}[apply {const { trace add variable X unset {apply {args { lappend ::traces $args }}} $const X gorp unset -nocomplain X list $X $::traces }} const] $traces } -result {gorp {} {{X {} unset}}} -cleanup { unset -nocomplain traces } test var-28.1 {const: in a namespace} -setup { namespace eval var28 {} } -body { namespace eval var28 { variable X const X gorp return $X } } -cleanup { namespace delete var28 } -result gorp test var-28.2 {const: in a namespace} -setup { namespace eval var28 {} } -body { namespace eval var28 { variable X const X gorp } apply {{} { variable X set X 123 } var28} } -cleanup { namespace delete var28 } -returnCodes error -result {can't set "X": variable is a constant} test var-28.3 {const: in a namespace} -setup { namespace eval var28 {} } -body { namespace eval var28 { variable X const X gorp } apply {{} { variable X unset X } var28} } -cleanup { namespace delete var28 } -returnCodes error -result {can't unset "X": variable is a constant} test var-28.4 {const: in a namespace} -setup { namespace eval var28 {} } -body { namespace eval var28 { variable X const X gorp } namespace delete var28 namespace eval var28 { variable X abc } apply {{} { variable X return $X } var28} } -cleanup { namespace delete var28 } -result abc test var-28.5 {const: in a namespace, direct access from proc} -setup { namespace eval var28 {} } -body { set result [apply {{} { const ::var28::X abc # Constant in namespace, NOT locally! info exists X }}] apply {res { variable X list $res [catch {unset X} msg] $msg $X } var28} $result } -cleanup { namespace delete var28 } -result {0 1 {can't unset "X": variable is a constant} abc} test var-29.1 {const: globally} -setup { set int [interp create] } -body { $int eval { const X gorp apply {{} { global X return $X }} } } -cleanup { interp delete $int } -result gorp test var-29.2 {const: TclOO variable resolution} -setup { oo::class create Parent } -body { oo::class create C { superclass Parent variable X constructor {} { const X 123 } method checkRead {} { return $X } method checkWrite {} { list [catch { set X abc } msg] $msg } method checkUnset {} { list [catch { unset X } msg] $msg } method checkProbe {} { info constant X } method checkList {} { info consts } } set c [C new] list [$c checkRead] [$c checkWrite] [$c checkUnset] [$c checkProbe] [$c checkList] } -cleanup { Parent destroy } -result {123 {1 {can't set "X": variable is a constant}} {1 {can't unset "X": variable is a constant}} 1 X} test var-29.3 {const: TclOO variable resolution} -setup { oo::class create Parent } -body { oo::class create C { superclass Parent private variable X constructor {} { const X 123 } method checkRead {} { return $X } method checkWrite {} { list [catch { set X abc } msg] $msg } method checkUnset {} { list [catch { unset X } msg] $msg } method checkProbe {} { info constant X } method checkList {} { info consts } } set c [C new] list [$c checkRead] [$c checkWrite] [$c checkUnset] [$c checkProbe] [$c checkList] } -cleanup { Parent destroy } -result {123 {1 {can't set "X": variable is a constant}} {1 {can't unset "X": variable is a constant}} 1 X} test var-29.4 {const: TclOO variable resolution} -setup { oo::class create Parent } -body { oo::class create C { superclass Parent variable X constructor {} { set X 123 } method checkRead {} { return $X } method checkWrite {} { list [catch { set X abc } msg] $msg } method checkUnset {} { list [catch { unset X set X gorp } msg] $msg } method checkProbe {} { info constant X } method checkList {} { info consts } } set c [C new] list [$c checkRead] [$c checkWrite] [$c checkUnset] [$c checkProbe] [$c checkList] } -cleanup { Parent destroy } -result {123 {0 abc} {0 gorp} 0 {}} test var-29.5 {const: TclOO variable resolution} -setup { set c [oo::object create Instance] } -body { oo::objdefine $c { variable X method init {} { const X 123 } method checkRead {} { return $X } method checkWrite {} { list [catch { set X abc } msg] $msg } method checkUnset {} { list [catch { unset X } msg] $msg } method checkProbe {} { info constant X } method checkList {} { info consts } } $c init list [$c checkRead] [$c checkWrite] [$c checkUnset] [$c checkProbe] [$c checkList] } -cleanup { Instance destroy } -result {123 {1 {can't set "X": variable is a constant}} {1 {can't unset "X": variable is a constant}} 1 X} test var-29.6 {const: TclOO variable resolution} -setup { set c [oo::object create Instance] } -body { oo::objdefine $c { private variable X method init {} { const X 123 } method checkRead {} { return $X } method checkWrite {} { list [catch { set X abc } msg] $msg } method checkUnset {} { list [catch { unset X } msg] $msg } method checkProbe {} { info constant X } method checkList {} { info consts } } $c init list [$c checkRead] [$c checkWrite] [$c checkUnset] [$c checkProbe] [$c checkList] } -cleanup { Instance destroy } -result {123 {1 {can't set "X": variable is a constant}} {1 {can't unset "X": variable is a constant}} 1 X} test var-29.7 {const: TclOO variable resolution} -setup { set c [oo::object create Instance] } -body { oo::objdefine $c { variable X method init {} { set X 123 } method checkRead {} { return $X } method checkWrite {} { list [catch { set X abc } msg] $msg } method checkUnset {} { list [catch { unset X set X gorp } msg] $msg } method checkProbe {} { info constant X } method checkList {} { info consts } } $c init list [$c checkRead] [$c checkWrite] [$c checkUnset] [$c checkProbe] [$c checkList] } -cleanup { Instance destroy } -result {123 {0 abc} {0 gorp} 0 {}} # The info constant and info consts commands test var-30.1 {info constant and info consts} { apply {{} { lappend consts [lsort [info consts]] [info constant X] const X 1 lappend consts [lsort [info consts]] [info constant X] const Y 2 lappend consts [lsort [info consts]] const X 3 lappend consts [lsort [info consts]] }} } {{} 0 X 1 {X Y} {X Y}} test var-30.2 {info constant and info consts} { apply {{} { lappend consts [lsort [info consts X]] const X 1 lappend consts [lsort [info consts X]] const Y 2 lappend consts [lsort [info consts X]] const X 3 lappend consts [lsort [info consts X]] }} } {{} X X X} test var-30.3 {info constant and info consts} { apply {{} { lappend consts [lsort [info consts ?]] const X 1 lappend consts [lsort [info consts ?]] const Y 2 lappend consts [lsort [info consts ?]] const XX 3 lappend consts [lsort [info consts ?]] }} } {{} X {X Y} {X Y}} test var-30.4 {info constant and info consts} { apply {{} { lappend consts [lsort [info consts X]] set X 1 lappend consts [lsort [info consts X]] set Y 2 lappend consts [lsort [info consts X]] set X 3 lappend consts [lsort [info consts X]] }} } {{} {} {} {}} test var-30.5 {info consts: in a namespace} -setup { namespace eval var30 {} } -body { namespace eval var30 { const X gorp info consts } } -cleanup { namespace delete var30 } -result X test var-30.6 {info consts: in a namespace} -setup { namespace eval var30 {} } -body { namespace eval var30 { const X gorp variable Y foo } info consts var30::* } -cleanup { namespace delete var30 } -result ::var30::X test var-30.7 {info constant: bad constant names: array element} { apply {{} { info constant a(b) }} } 0 test var-30.8 {info constant: bad constant names: array} { apply {{} { array set a {} info constant a }} } 0 test var-30.9 {info constant: bad constant names: no var} { apply {{} { info constant a }} } 0 test var-30.10 {info constant: bad constant names: no namespace} { apply {{} { info constant ::var29::no::such::ns::a }} } 0 test var-30.11 {info constant: bad constant names: dangling upvar} { apply {{} { upvar 0 no_var a info constant a }} } 0 test var-30.12 {info constant: bad constant names: bad name} { apply {{} { info constant a(b }} } 0 test var-30.13 {info constant: bad constant names: nesting} { apply {{} { array set b {c d} upvar 0 b(c) a info constant a(d) }} } 0 test var-31.1 {info constant: syntax} -returnCodes error -body { info constant } -result {wrong # args: should be "info constant varName"} test var-31.2 {info constant: syntax} -returnCodes error -body { info constant foo bar } -result {wrong # args: should be "info constant varName"} test var-31.3 {info consts: syntax} -returnCodes error -body { info consts foo bar } -result {wrong # args: should be "info consts ?pattern?"} catch {namespace delete ns} catch {unset arr} catch {unset v} catch {rename getbytes ""} catch {rename p ""} |
︙ | ︙ |