Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch tip-508 Excluding Merge-Ins
This is equivalent to a diff from a5de190036 to f0dd67ee95
2018-09-26
| ||
23:17 | Implementation of TIP 508: [array default] check-in: f2890e3bd5 user: dkf tags: core-8-branch | |
19:38 | Improvements for zipfs. Document that TclZipfs_AppHook only works on Windows in UNICODE mode. Also, ... check-in: ca34f32cb7 user: jan.nijtmans tags: core-8-branch | |
13:09 | Improved comment. Closed-Leaf check-in: f0dd67ee95 user: dkf tags: tip-508 | |
13:08 | Make defaults work even when [upvar]ed to just a non-existent element. check-in: 6faaafb401 user: dkf tags: tip-508 | |
09:47 | merge core-8-branch check-in: 4c46bf91dd user: dkf tags: tip-508 | |
2018-09-25
| ||
21:18 | Merge 8.7 check-in: 784c4133aa user: jan.nijtmans tags: trunk | |
21:18 | merge 8.6 check-in: a5de190036 user: jan.nijtmans tags: core-8-branch | |
21:16 | Contributed patch from Gustaf Neumann, preventing problems where "localCachePtr" can be NULL check-in: 4515cab12b user: jan.nijtmans tags: core-8-6-branch | |
2018-09-24
| ||
23:24 | More fixes in Tcl_WinTChar2Utf: Don't restart loop when output contains null-byte. check-in: 050b7ee0e1 user: jan.nijtmans tags: core-8-branch | |
Changes to doc/append.n.
︙ | ︙ | |||
16 17 18 19 20 21 22 23 24 25 26 27 28 29 | .BE .SH DESCRIPTION .PP Append all of the \fIvalue\fR arguments to the current value of variable \fIvarName\fR. If \fIvarName\fR does not exist, it is given a value equal to the concatenation of all the \fIvalue\fR arguments. The result of this command is the new value stored in variable \fIvarName\fR. This command provides an efficient way to build up long variables incrementally. For example, .QW "\fBappend a $b\fR" is much more efficient than | > > > > > | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | .BE .SH DESCRIPTION .PP Append all of the \fIvalue\fR arguments to the current value of variable \fIvarName\fR. If \fIvarName\fR does not exist, it is given a value equal to the concatenation of all the \fIvalue\fR arguments. .VS TIP508 If \fIvarName\fR indicate an element that does not exist of an array that has a default value set, the concatenation of the default value and all the \fIvalue\fR arguments will be stored in the array element. .VE TIP508 The result of this command is the new value stored in variable \fIvarName\fR. This command provides an efficient way to build up long variables incrementally. For example, .QW "\fBappend a $b\fR" is much more efficient than |
︙ | ︙ | |||
40 41 42 43 44 45 46 | puts $var # Prints 0,1,2,3,4,5,6,7,8,9,10 .CE .SH "SEE ALSO" concat(n), lappend(n) .SH KEYWORDS append, variable | | | > | | 45 46 47 48 49 50 51 52 53 54 55 | puts $var # Prints 0,1,2,3,4,5,6,7,8,9,10 .CE .SH "SEE ALSO" concat(n), lappend(n) .SH KEYWORDS append, variable .\" Local variables: .\" mode: nroff .\" fill-column: 78 .\" End: |
Changes to doc/array.n.
1 2 3 4 5 6 7 | '\" '\" Copyright (c) 1993-1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | '\" '\" Copyright (c) 1993-1994 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH array n 8.7 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME array \- Manipulate array variables .SH SYNOPSIS \fBarray \fIoption arrayName\fR ?\fIarg arg ...\fR? |
︙ | ︙ | |||
31 32 33 34 35 36 37 38 39 40 41 42 43 44 | \fISearchId\fR indicates which search on \fIarrayName\fR to check, and must have been the return value from a previous invocation of \fBarray startsearch\fR. This option is particularly useful if an array has an element with an empty name, since the return value from \fBarray nextelement\fR will not indicate whether the search has been completed. .TP \fBarray donesearch \fIarrayName searchId\fR This command terminates an array search and destroys all the state associated with that search. \fISearchId\fR indicates which search on \fIarrayName\fR to destroy, and must have been the return value from a previous invocation of \fBarray startsearch\fR. Returns an empty string. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 86 87 88 89 90 91 | \fISearchId\fR indicates which search on \fIarrayName\fR to check, and must have been the return value from a previous invocation of \fBarray startsearch\fR. This option is particularly useful if an array has an element with an empty name, since the return value from \fBarray nextelement\fR will not indicate whether the search has been completed. .TP \fBarray default \fIsubcommand arrayName args...\fR .VS TIP508 Manages the default value of the array. Arrays initially have no default value, but this command allows you to set one; the default value will be returned when reading from an element of the array \farrayName\fR if the read would otherwise result in an error. Note that this may cause the \fBappend\fR, \fBdict\fR, \fBincr\fR and \fBlappend\fR commands to change their behavior in relation to non-existing array elements. .RS .PP The \fIsubcommand\fR argument controls what exact operation will be performed on the default value of \fIarrayName\fR. Supported \fIsubcommand\fRs are: .VE TIP508 .TP \fBarray default exists \fIarrayName\fR .VS TIP508 This returns a boolean value indicating whether a default value has been set for the array \fIarrayName\fR. Returns a false value if \fIarrayName\fR does not exist. Raises an error if \fIarrayName\fR is an existing variable that is not an array. .VE TIP508 .TP \fBarray default get \fIarrayName\fR .VS TIP508 This returns the current default value for the array \fIarrayName\fR. Raises an error if \fIarrayName\fR is an existing variable that is not an array, or if \fIarrayName\fR is an array without a default value. .VE TIP508 .TP \fBarray default set \fIarrayName value\fR .VS TIP508 This sets the default value for the array \fIarrayName\fR to \fIvalue\fR. Returns the empty string. Raises an error if \fIarrayName\fR is an existing variable that is not an array, or if \fIarrayName\fR is an illegal name for an array. If \fIarrayName\fR does not currently exist, it is created as an empty array as well as having its default value set. .VE TIP508 .TP \fBarray default unset \fIarrayName\fR .VS TIP508 This removes the default value for the array \fIarrayName\fR and returns the empty string. Does nothing if \fIarrayName\fR does not have a default value. Raises an error if \fIarrayName\fR is an existing variable that is not an array. .VE TIP508 .RE .TP \fBarray donesearch \fIarrayName searchId\fR This command terminates an array search and destroys all the state associated with that search. \fISearchId\fR indicates which search on \fIarrayName\fR to destroy, and must have been the return value from a previous invocation of \fBarray startsearch\fR. Returns an empty string. |
︙ | ︙ | |||
190 191 192 193 194 195 196 | number of buckets with 10 or more entries: 0 average search distance for entry: 1.2 .CE .SH "SEE ALSO" list(n), string(n), variable(n), trace(n), foreach(n) .SH KEYWORDS array, element names, search | > > > > | 237 238 239 240 241 242 243 244 245 246 247 | number of buckets with 10 or more entries: 0 average search distance for entry: 1.2 .CE .SH "SEE ALSO" list(n), string(n), variable(n), trace(n), foreach(n) .SH KEYWORDS array, element names, search .\" Local variables: .\" mode: nroff .\" fill-column: 78 .\" End: |
Changes to doc/dict.n.
︙ | ︙ | |||
23 24 25 26 27 28 29 30 31 32 33 34 35 36 | \fBdict append \fIdictionaryVariable key \fR?\fIstring ...\fR? . This appends the given string (or strings) to the value that the given key maps to in the dictionary value contained in the given variable, writing the resulting dictionary value back to that variable. Non-existent keys are treated as if they map to an empty string. The updated dictionary value is returned. .TP \fBdict create \fR?\fIkey value ...\fR? . Return a new dictionary that contains each of the key/value mappings listed as arguments (keys and values alternating, with each key being followed by its associated value.) .TP | > > > > > | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | \fBdict append \fIdictionaryVariable key \fR?\fIstring ...\fR? . This appends the given string (or strings) to the value that the given key maps to in the dictionary value contained in the given variable, writing the resulting dictionary value back to that variable. Non-existent keys are treated as if they map to an empty string. The updated dictionary value is returned. .VS TIP508 If \fIdictionaryVarable\fR indicates an element that does not exist of an array that has a default value set, the default value and will be used as the value of the dictionary prior to the appending operation. .VE TIP508 .TP \fBdict create \fR?\fIkey value ...\fR? . Return a new dictionary that contains each of the key/value mappings listed as arguments (keys and values alternating, with each key being followed by its associated value.) .TP |
︙ | ︙ | |||
120 121 122 123 124 125 126 127 128 129 130 131 132 133 | This adds the given increment value (an integer that defaults to 1 if not specified) to the value that the given key maps to in the dictionary value contained in the given variable, writing the resulting dictionary value back to that variable. Non-existent keys are treated as if they map to 0. It is an error to increment a value for an existing key if that value is not an integer. The updated dictionary value is returned. .TP \fBdict info \fIdictionaryValue\fR . This returns information (intended for display to people) about the given dictionary though the format of this data is dependent on the implementation of the dictionary. For dictionaries that are implemented by hash tables, it is expected that this will return the | > > > > > | 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | This adds the given increment value (an integer that defaults to 1 if not specified) to the value that the given key maps to in the dictionary value contained in the given variable, writing the resulting dictionary value back to that variable. Non-existent keys are treated as if they map to 0. It is an error to increment a value for an existing key if that value is not an integer. The updated dictionary value is returned. .VS TIP508 If \fIdictionaryVarable\fR indicates an element that does not exist of an array that has a default value set, the default value and will be used as the value of the dictionary prior to the incrementing operation. .VE TIP508 .TP \fBdict info \fIdictionaryValue\fR . This returns information (intended for display to people) about the given dictionary though the format of this data is dependent on the implementation of the dictionary. For dictionaries that are implemented by hash tables, it is expected that this will return the |
︙ | ︙ | |||
145 146 147 148 149 150 151 152 153 154 155 156 157 158 | This appends the given items to the list value that the given key maps to in the dictionary value contained in the given variable, writing the resulting dictionary value back to that variable. Non-existent keys are treated as if they map to an empty list, and it is legal for there to be no items to append to the list. It is an error for the value that the key maps to to not be representable as a list. The updated dictionary value is returned. .TP \fBdict map \fR{\fIkeyVariable valueVariable\fR} \fIdictionaryValue body\fR . This command applies a transformation to each element of a dictionary, returning a new dictionary. It takes three arguments: the first is a two-element list of variable names (for the key and value respectively of each mapping in the dictionary), the second the dictionary value to iterate across, | > > > > > | 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | This appends the given items to the list value that the given key maps to in the dictionary value contained in the given variable, writing the resulting dictionary value back to that variable. Non-existent keys are treated as if they map to an empty list, and it is legal for there to be no items to append to the list. It is an error for the value that the key maps to to not be representable as a list. The updated dictionary value is returned. .VS TIP508 If \fIdictionaryVarable\fR indicates an element that does not exist of an array that has a default value set, the default value and will be used as the value of the dictionary prior to the list-appending operation. .VE TIP508 .TP \fBdict map \fR{\fIkeyVariable valueVariable\fR} \fIdictionaryValue body\fR . This command applies a transformation to each element of a dictionary, returning a new dictionary. It takes three arguments: the first is a two-element list of variable names (for the key and value respectively of each mapping in the dictionary), the second the dictionary value to iterate across, |
︙ | ︙ | |||
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | \fBdict set \fIdictionaryVariable key \fR?\fIkey ...\fR? \fIvalue\fR . This operation takes the name of a variable containing a dictionary value and places an updated dictionary value in that variable containing a mapping from the given key to the given value. When multiple keys are present, this operation creates or updates a chain of nested dictionaries. The updated dictionary value is returned. .TP \fBdict size \fIdictionaryValue\fR . Return the number of key/value mappings in the given dictionary value. .TP \fBdict unset \fIdictionaryVariable key \fR?\fIkey ...\fR? . This operation (the companion to \fBdict set\fR) takes the name of a variable containing a dictionary value and places an updated dictionary value in that variable that does not contain a mapping for the given key. Where multiple keys are present, this describes a path through nested dictionaries to the mapping to remove. At least one key must be specified, but the last key on the key-path need not exist. All other components on the path must exist. The updated dictionary value is returned. .TP \fBdict update \fIdictionaryVariable key varName \fR?\fIkey varName ...\fR? \fIbody\fR . Execute the Tcl script in \fIbody\fR with the value for each \fIkey\fR (as found by reading the dictionary value in \fIdictionaryVariable\fR) mapped to the variable \fIvarName\fR. There may be multiple \fIkey\fR/\fIvarName\fR pairs. If a \fIkey\fR does not have a mapping, that corresponds to an unset \fIvarName\fR. When \fIbody\fR terminates, any changes made to the \fIvarName\fRs is reflected back to the dictionary within \fIdictionaryVariable\fR (unless \fIdictionaryVariable\fR itself becomes unreadable, when all updates are silently discarded), even if the result of \fIbody\fR is an error or some other kind of exceptional exit. The result of \fBdict update\fR is (unless some kind of error occurs) the result of the evaluation of \fIbody\fR. .RS .PP Each \fIvarName\fR is mapped in the scope enclosing the \fBdict update\fR; it is recommended that this command only be used in a local scope (\fBproc\fRedure, lambda term for \fBapply\fR, or method). Because of this, the variables set by \fBdict update\fR will continue to exist after the command finishes (unless explicitly \fBunset\fR). | > > > > > > > > > > > > > > > | 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 | \fBdict set \fIdictionaryVariable key \fR?\fIkey ...\fR? \fIvalue\fR . This operation takes the name of a variable containing a dictionary value and places an updated dictionary value in that variable containing a mapping from the given key to the given value. When multiple keys are present, this operation creates or updates a chain of nested dictionaries. The updated dictionary value is returned. .VS TIP508 If \fIdictionaryVarable\fR indicates an element that does not exist of an array that has a default value set, the default value and will be used as the value of the dictionary prior to the value insert/update operation. .VE TIP508 .TP \fBdict size \fIdictionaryValue\fR . Return the number of key/value mappings in the given dictionary value. .TP \fBdict unset \fIdictionaryVariable key \fR?\fIkey ...\fR? . This operation (the companion to \fBdict set\fR) takes the name of a variable containing a dictionary value and places an updated dictionary value in that variable that does not contain a mapping for the given key. Where multiple keys are present, this describes a path through nested dictionaries to the mapping to remove. At least one key must be specified, but the last key on the key-path need not exist. All other components on the path must exist. The updated dictionary value is returned. .VS TIP508 If \fIdictionaryVarable\fR indicates an element that does not exist of an array that has a default value set, the default value and will be used as the value of the dictionary prior to the value remove operation. .VE TIP508 .TP \fBdict update \fIdictionaryVariable key varName \fR?\fIkey varName ...\fR? \fIbody\fR . Execute the Tcl script in \fIbody\fR with the value for each \fIkey\fR (as found by reading the dictionary value in \fIdictionaryVariable\fR) mapped to the variable \fIvarName\fR. There may be multiple \fIkey\fR/\fIvarName\fR pairs. If a \fIkey\fR does not have a mapping, that corresponds to an unset \fIvarName\fR. When \fIbody\fR terminates, any changes made to the \fIvarName\fRs is reflected back to the dictionary within \fIdictionaryVariable\fR (unless \fIdictionaryVariable\fR itself becomes unreadable, when all updates are silently discarded), even if the result of \fIbody\fR is an error or some other kind of exceptional exit. The result of \fBdict update\fR is (unless some kind of error occurs) the result of the evaluation of \fIbody\fR. .VS TIP508 If \fIdictionaryVarable\fR indicates an element that does not exist of an array that has a default value set, the default value and will be used as the value of the dictionary prior to the update operation. .VE TIP508 .RS .PP Each \fIvarName\fR is mapped in the scope enclosing the \fBdict update\fR; it is recommended that this command only be used in a local scope (\fBproc\fRedure, lambda term for \fBapply\fR, or method). Because of this, the variables set by \fBdict update\fR will continue to exist after the command finishes (unless explicitly \fBunset\fR). |
︙ | ︙ | |||
266 267 268 269 270 271 272 273 274 275 276 277 278 279 | for the execution of \fIbody\fR. As with \fBdict update\fR, making \fIdictionaryVariable\fR unreadable will make the updates to the dictionary be discarded, and this also happens if the contents of \fIdictionaryVariable\fR are adjusted so that the chain of dictionaries no longer exists. The result of \fBdict with\fR is (unless some kind of error occurs) the result of the evaluation of \fIbody\fR. .RS .PP The variables are mapped in the scope enclosing the \fBdict with\fR; it is recommended that this command only be used in a local scope (\fBproc\fRedure, lambda term for \fBapply\fR, or method). Because of this, the variables set by \fBdict with\fR will continue to exist after the command finishes (unless explicitly \fBunset\fR). | > > > > > | 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 | for the execution of \fIbody\fR. As with \fBdict update\fR, making \fIdictionaryVariable\fR unreadable will make the updates to the dictionary be discarded, and this also happens if the contents of \fIdictionaryVariable\fR are adjusted so that the chain of dictionaries no longer exists. The result of \fBdict with\fR is (unless some kind of error occurs) the result of the evaluation of \fIbody\fR. .VS TIP508 If \fIdictionaryVarable\fR indicates an element that does not exist of an array that has a default value set, the default value and will be used as the value of the dictionary prior to the updating operation. .VE TIP508 .RS .PP The variables are mapped in the scope enclosing the \fBdict with\fR; it is recommended that this command only be used in a local scope (\fBproc\fRedure, lambda term for \fBapply\fR, or method). Because of this, the variables set by \fBdict with\fR will continue to exist after the command finishes (unless explicitly \fBunset\fR). |
︙ | ︙ |
Changes to doc/incr.n.
︙ | ︙ | |||
23 24 25 26 27 28 29 30 31 32 33 34 35 36 | 1 is added to \fIvarName\fR. The new value is stored as a decimal string in variable \fIvarName\fR and also returned as result. .PP Starting with the Tcl 8.5 release, the variable \fIvarName\fR passed to \fBincr\fR may be unset, and in that case, it will be set to the value \fIincrement\fR or to the default increment value of \fB1\fR. .SH EXAMPLES .PP Add one to the contents of the variable \fIx\fR: .PP .CS \fBincr\fR x .CE | > > > > > | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | 1 is added to \fIvarName\fR. The new value is stored as a decimal string in variable \fIvarName\fR and also returned as result. .PP Starting with the Tcl 8.5 release, the variable \fIvarName\fR passed to \fBincr\fR may be unset, and in that case, it will be set to the value \fIincrement\fR or to the default increment value of \fB1\fR. .VS TIP508 If \fIvarName\fR indicate an element that does not exist of an array that has a default value set, the sum of the default value and the \fIincrement\fR (or 1) will be stored in the array element. .VE TIP508 .SH EXAMPLES .PP Add one to the contents of the variable \fIx\fR: .PP .CS \fBincr\fR x .CE |
︙ | ︙ | |||
55 56 57 58 59 60 61 | .CS \fBincr\fR x 0 .CE .SH "SEE ALSO" expr(n), set(n) .SH KEYWORDS add, increment, variable, value | > > > > | 60 61 62 63 64 65 66 67 68 69 70 | .CS \fBincr\fR x 0 .CE .SH "SEE ALSO" expr(n), set(n) .SH KEYWORDS add, increment, variable, value .\" Local variables: .\" mode: nroff .\" fill-column: 78 .\" End: |
Changes to doc/lappend.n.
︙ | ︙ | |||
18 19 20 21 22 23 24 25 26 27 28 29 30 31 | .SH DESCRIPTION .PP This command treats the variable given by \fIvarName\fR as a list and appends each of the \fIvalue\fR arguments to that list as a separate element, with spaces between elements. If \fIvarName\fR does not exist, it is created as a list with elements given by the \fIvalue\fR arguments. \fBLappend\fR is similar to \fBappend\fR except that the \fIvalue\fRs are appended as list elements rather than raw text. This command provides a relatively efficient way to build up large lists. For example, .QW "\fBlappend a $b\fR" is much more efficient than .QW "\fBset a [concat $a [list $b]]\fR" | > > > > > > | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | .SH DESCRIPTION .PP This command treats the variable given by \fIvarName\fR as a list and appends each of the \fIvalue\fR arguments to that list as a separate element, with spaces between elements. If \fIvarName\fR does not exist, it is created as a list with elements given by the \fIvalue\fR arguments. .VS TIP508 If \fIvarName\fR indicate an element that does not exist of an array that has a default value set, list that is comprised of the default value with all the \fIvalue\fR arguments appended as elements will be stored in the array element. .VE TIP508 \fBLappend\fR is similar to \fBappend\fR except that the \fIvalue\fRs are appended as list elements rather than raw text. This command provides a relatively efficient way to build up large lists. For example, .QW "\fBlappend a $b\fR" is much more efficient than .QW "\fBset a [concat $a [list $b]]\fR" |
︙ | ︙ | |||
43 44 45 46 47 48 49 | 1 2 3 4 5 .CE .SH "SEE ALSO" list(n), lindex(n), linsert(n), llength(n), lset(n), lsort(n), lrange(n) .SH KEYWORDS append, element, list, variable | > > > > | 49 50 51 52 53 54 55 56 57 58 59 | 1 2 3 4 5 .CE .SH "SEE ALSO" list(n), lindex(n), linsert(n), llength(n), lset(n), lsort(n), lrange(n) .SH KEYWORDS append, element, list, variable .\" Local variables: .\" mode: nroff .\" fill-column: 78 .\" End: |
Changes to generic/tclExecute.c.
︙ | ︙ | |||
4066 4067 4068 4069 4070 4071 4072 | "variable isn't array", opnd); DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "TCL", "WRITE", "ARRAY", NULL); CACHE_STACK_INFO(); TRACE_ERROR(interp); goto gotError; } | | < < < | 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 | "variable isn't array", opnd); DECACHE_STACK_INFO(); Tcl_SetErrorCode(interp, "TCL", "WRITE", "ARRAY", NULL); CACHE_STACK_INFO(); TRACE_ERROR(interp); goto gotError; } TclInitArrayVar(varPtr); #ifdef TCL_COMPILE_DEBUG TRACE_APPEND(("done\n")); } else { TRACE_APPEND(("nothing to do\n")); #endif } NEXT_INST_V(pcAdjustment, cleanup, 0); |
︙ | ︙ |
Changes to generic/tclInt.h.
︙ | ︙ | |||
4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 | MODULE_SCOPE Tcl_Command TclInitProcessCmd(Tcl_Interp *interp); MODULE_SCOPE void TclProcessCreated(Tcl_Pid pid); MODULE_SCOPE TclProcessWaitStatus TclProcessWait(Tcl_Pid pid, int options, int *codePtr, Tcl_Obj **msgObjPtr, Tcl_Obj **errorObjPtr); /* * Utility routines for encoding index values as integers. Used by both * some of the command compilers and by [lsort] and [lsearch]. */ MODULE_SCOPE int TclIndexEncode(Tcl_Interp *interp, Tcl_Obj *objPtr, int before, int after, int *indexPtr); | > > > > > > > | 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 | MODULE_SCOPE Tcl_Command TclInitProcessCmd(Tcl_Interp *interp); MODULE_SCOPE void TclProcessCreated(Tcl_Pid pid); MODULE_SCOPE TclProcessWaitStatus TclProcessWait(Tcl_Pid pid, int options, int *codePtr, Tcl_Obj **msgObjPtr, Tcl_Obj **errorObjPtr); /* * TIP #508: [array default] */ MODULE_SCOPE void TclInitArrayVar(Var *arrayPtr); MODULE_SCOPE Tcl_Obj * TclGetArrayDefault(Var *arrayPtr); /* * Utility routines for encoding index values as integers. Used by both * some of the command compilers and by [lsort] and [lsearch]. */ MODULE_SCOPE int TclIndexEncode(Tcl_Interp *interp, Tcl_Obj *objPtr, int before, int after, int *indexPtr); |
︙ | ︙ |
Changes to generic/tclVar.c.
︙ | ︙ | |||
160 161 162 163 164 165 166 167 168 169 170 171 172 173 | * Tcl_NextHashEntry to get value to * return. */ struct ArraySearch *nextPtr;/* Next in list of all active searches for * this variable, or NULL if this is the last * one. */ } ArraySearch; /* * Forward references to functions defined later in this file: */ static void AppendLocals(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *patternPtr, int includeLinks); static void ArrayPopulateSearch(Tcl_Interp *interp, | > > > > > > > > > > > > | 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | * Tcl_NextHashEntry to get value to * return. */ struct ArraySearch *nextPtr;/* Next in list of all active searches for * this variable, or NULL if this is the last * one. */ } ArraySearch; /* * TIP #508: [array default] * * The following structure extends the regular TclVarHashTable used by array * variables to store their optional default value. */ typedef struct ArrayVarHashTable { TclVarHashTable table; Tcl_Obj *defaultObj; } ArrayVarHashTable; /* * Forward references to functions defined later in this file: */ static void AppendLocals(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *patternPtr, int includeLinks); static void ArrayPopulateSearch(Tcl_Interp *interp, |
︙ | ︙ | |||
193 194 195 196 197 198 199 200 201 202 203 204 205 206 | Tcl_Obj *myNamePtr, int myFlags, int index); static ArraySearch * ParseSearchId(Tcl_Interp *interp, const Var *varPtr, Tcl_Obj *varNamePtr, Tcl_Obj *handleObj); static void UnsetVarStruct(Var *varPtr, Var *arrayPtr, Interp *iPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags, int index); /* * Functions defined in this file that may be exported in the future for use * by the bytecode compiler and engine or to the public interface. */ MODULE_SCOPE Var * TclLookupSimpleVar(Tcl_Interp *interp, Tcl_Obj *varNamePtr, int flags, const int create, | > > > > > > > > > > | 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | Tcl_Obj *myNamePtr, int myFlags, int index); static ArraySearch * ParseSearchId(Tcl_Interp *interp, const Var *varPtr, Tcl_Obj *varNamePtr, Tcl_Obj *handleObj); static void UnsetVarStruct(Var *varPtr, Var *arrayPtr, Interp *iPtr, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags, int index); /* * TIP #508: [array default] */ static int ArrayDefaultCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static void DeleteArrayVar(Var *arrayPtr); static void SetArrayDefault(Var *arrayPtr, Tcl_Obj *defaultObj); /* * Functions defined in this file that may be exported in the future for use * by the bytecode compiler and engine or to the public interface. */ MODULE_SCOPE Var * TclLookupSimpleVar(Tcl_Interp *interp, Tcl_Obj *varNamePtr, int flags, const int create, |
︙ | ︙ | |||
232 233 234 235 236 237 238 | FreeLocalVarName, DupLocalVarName, NULL, NULL }; static const Tcl_ObjType tclParsedVarNameType = { "parsedVarName", FreeParsedVarName, DupParsedVarName, NULL, NULL }; | < | 254 255 256 257 258 259 260 261 262 263 264 265 266 267 | FreeLocalVarName, DupLocalVarName, NULL, NULL }; static const Tcl_ObjType tclParsedVarNameType = { "parsedVarName", FreeParsedVarName, DupParsedVarName, NULL, NULL }; Var * TclVarHashCreateVar( TclVarHashTable *tablePtr, const char *key, int *newPtr) { |
︙ | ︙ | |||
1015 1016 1017 1018 1019 1020 1021 | * element, if it doesn't already exist. If 0, * return error if it doesn't exist. */ Var *arrayPtr, /* Pointer to the array's Var structure. */ int index) /* If >=0, the index of the local array. */ { int isNew; Var *varPtr; | < < | 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 | * element, if it doesn't already exist. If 0, * return error if it doesn't exist. */ Var *arrayPtr, /* Pointer to the array's Var structure. */ int index) /* If >=0, the index of the local array. */ { int isNew; Var *varPtr; /* * We're dealing with an array element. Make sure the variable is an array * and look up the element (create the element if desired). */ if (TclIsVarUndefined(arrayPtr) && !TclIsVarArrayElement(arrayPtr)) { |
︙ | ︙ | |||
1049 1050 1051 1052 1053 1054 1055 | danglingVar, index); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", arrayNamePtr?TclGetString(arrayNamePtr):NULL, NULL); } return NULL; } | | < < < < < < < < < | 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 | danglingVar, index); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", arrayNamePtr?TclGetString(arrayNamePtr):NULL, NULL); } return NULL; } TclInitArrayVar(arrayPtr); } else if (!TclIsVarArray(arrayPtr)) { if (flags & TCL_LEAVE_ERR_MSG) { TclObjVarErrMsg(interp, arrayNamePtr, elNamePtr, msg, needArray, index); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", arrayNamePtr?TclGetString(arrayNamePtr):NULL, NULL); } |
︙ | ︙ | |||
1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 | /* * Return the element if it's an existing scalar variable. */ if (TclIsVarScalar(varPtr) && !TclIsVarUndefined(varPtr)) { return varPtr->value.objPtr; } if (flags & TCL_LEAVE_ERR_MSG) { if (TclIsVarUndefined(varPtr) && arrayPtr && !TclIsVarUndefined(arrayPtr)) { msg = noSuchElement; } else if (TclIsVarArray(varPtr)) { msg = isArray; | > > > > > > > > > > > > > > > > > > > > > > | 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 | /* * Return the element if it's an existing scalar variable. */ if (TclIsVarScalar(varPtr) && !TclIsVarUndefined(varPtr)) { return varPtr->value.objPtr; } /* * Return the array default value if any. */ if (arrayPtr && TclIsVarArray(arrayPtr) && TclGetArrayDefault(arrayPtr)) { return TclGetArrayDefault(arrayPtr); } if (TclIsVarArrayElement(varPtr) && !arrayPtr) { /* * UGLY! Peek inside the implementation of things. This lets us get * the default of an array even when we've been [upvar]ed to just an * element of the array. */ ArrayVarHashTable *avhtPtr = (ArrayVarHashTable *) ((VarInHash *) varPtr)->entry.tablePtr; if (avhtPtr->defaultObj) { return avhtPtr->defaultObj; } } if (flags & TCL_LEAVE_ERR_MSG) { if (TclIsVarUndefined(varPtr) && arrayPtr && !TclIsVarUndefined(arrayPtr)) { msg = noSuchElement; } else if (TclIsVarArray(varPtr)) { msg = isArray; |
︙ | ︙ | |||
1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 | return TclPtrSetVarIdx(interp, (Var *) varPtr, (Var *) arrayPtr, part1Ptr, part2Ptr, newValuePtr, flags, -1); } /* *---------------------------------------------------------------------- * * TclPtrSetVarIdx -- * * This function is the same as Tcl_SetVar2Ex above, except that it * requires pointers to the variable's Var structs in addition to the * variable names. * * Results: | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | return TclPtrSetVarIdx(interp, (Var *) varPtr, (Var *) arrayPtr, part1Ptr, part2Ptr, newValuePtr, flags, -1); } /* *---------------------------------------------------------------------- * * ListAppendInVar, StringAppendInVar -- * * Support functions for TclPtrSetVarIdx that implement various types of * appending operations. * * Results: * ListAppendInVar returns a Tcl result code (from the core list append * operation). StringAppendInVar has no return value. * * Side effects: * The variable or element of the array is updated. This may make the * variable/element exist. Reference counts of values may be updated. * *---------------------------------------------------------------------- */ static inline int ListAppendInVar( Tcl_Interp *interp, Var *varPtr, Var *arrayPtr, Tcl_Obj *oldValuePtr, Tcl_Obj *newValuePtr) { if (oldValuePtr == NULL) { /* * No previous value. Check for defaults if there's an array we can * ask this of. */ if (arrayPtr) { Tcl_Obj *defValuePtr = TclGetArrayDefault(arrayPtr); if (defValuePtr) { oldValuePtr = Tcl_DuplicateObj(defValuePtr); } } if (oldValuePtr == NULL) { /* * No default. [lappend] semantics say this is like being an empty * string. */ TclNewObj(oldValuePtr); } varPtr->value.objPtr = oldValuePtr; Tcl_IncrRefCount(oldValuePtr); /* Since var is referenced. */ } else if (Tcl_IsShared(oldValuePtr)) { varPtr->value.objPtr = Tcl_DuplicateObj(oldValuePtr); TclDecrRefCount(oldValuePtr); oldValuePtr = varPtr->value.objPtr; Tcl_IncrRefCount(oldValuePtr); /* Since var is referenced. */ } return Tcl_ListObjAppendElement(interp, oldValuePtr, newValuePtr); } static inline void StringAppendInVar( Var *varPtr, Var *arrayPtr, Tcl_Obj *oldValuePtr, Tcl_Obj *newValuePtr) { /* * If there was no previous value, either we use the array's default (if * this is an array with a default at all) or we treat this as a simple * set. */ if (oldValuePtr == NULL) { if (arrayPtr) { Tcl_Obj *defValuePtr = TclGetArrayDefault(arrayPtr); if (defValuePtr) { /* * This is *almost* the same as the shared path below, except * that the original value reference in defValuePtr is not * decremented. */ Tcl_Obj *valuePtr = Tcl_DuplicateObj(defValuePtr); varPtr->value.objPtr = valuePtr; TclContinuationsCopy(valuePtr, defValuePtr); Tcl_IncrRefCount(valuePtr); Tcl_AppendObjToObj(valuePtr, newValuePtr); if (newValuePtr->refCount == 0) { Tcl_DecrRefCount(newValuePtr); } return; } } varPtr->value.objPtr = newValuePtr; Tcl_IncrRefCount(newValuePtr); return; } /* * We append newValuePtr's bytes but don't change its ref count. Unless * the reference is shared, when we have to duplicate in order to be safe * to modify at all. */ if (Tcl_IsShared(oldValuePtr)) { /* Append to copy. */ varPtr->value.objPtr = Tcl_DuplicateObj(oldValuePtr); TclContinuationsCopy(varPtr->value.objPtr, oldValuePtr); TclDecrRefCount(oldValuePtr); oldValuePtr = varPtr->value.objPtr; Tcl_IncrRefCount(oldValuePtr); /* Since var is ref */ } Tcl_AppendObjToObj(oldValuePtr, newValuePtr); if (newValuePtr->refCount == 0) { Tcl_DecrRefCount(newValuePtr); } } /* *---------------------------------------------------------------------- * * TclPtrSetVarIdx -- * * This function is the same as Tcl_SetVar2Ex above, except that it * requires pointers to the variable's Var structs in addition to the * variable names. * * Results: |
︙ | ︙ | |||
1880 1881 1882 1883 1884 1885 1886 | oldValuePtr = varPtr->value.objPtr; if (flags & TCL_LIST_ELEMENT && !(flags & TCL_APPEND_VALUE)) { varPtr->value.objPtr = NULL; } if (flags & (TCL_APPEND_VALUE|TCL_LIST_ELEMENT)) { if (flags & TCL_LIST_ELEMENT) { /* Append list element. */ | < | < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < | 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 | oldValuePtr = varPtr->value.objPtr; if (flags & TCL_LIST_ELEMENT && !(flags & TCL_APPEND_VALUE)) { varPtr->value.objPtr = NULL; } if (flags & (TCL_APPEND_VALUE|TCL_LIST_ELEMENT)) { if (flags & TCL_LIST_ELEMENT) { /* Append list element. */ result = ListAppendInVar(interp, varPtr, arrayPtr, oldValuePtr, newValuePtr); if (result != TCL_OK) { goto earlyError; } } else { /* Append string. */ StringAppendInVar(varPtr, arrayPtr, oldValuePtr, newValuePtr); } } else if (newValuePtr != oldValuePtr) { /* * In this case we are replacing the value, so we don't need to do * more than swap the objects. */ |
︙ | ︙ | |||
4074 4075 4076 4077 4078 4079 4080 | TclObjVarErrMsg(interp, arrayNameObj, NULL, "array set", needArray, -1); Tcl_SetErrorCode(interp, "TCL", "WRITE", "ARRAY", NULL); return TCL_ERROR; } } | | < < | 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 | TclObjVarErrMsg(interp, arrayNameObj, NULL, "array set", needArray, -1); Tcl_SetErrorCode(interp, "TCL", "WRITE", "ARRAY", NULL); return TCL_ERROR; } } TclInitArrayVar(varPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * ArraySizeCmd -- |
︙ | ︙ | |||
4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 | /* ARGSUSED */ Tcl_Command TclInitArrayCmd( Tcl_Interp *interp) /* Current interpreter. */ { static const EnsembleImplMap arrayImplMap[] = { {"anymore", ArrayAnyMoreCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"donesearch", ArrayDoneSearchCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"exists", ArrayExistsCmd, TclCompileArrayExistsCmd, NULL, NULL, 0}, {"for", ArrayForObjCmd, TclCompileBasic3ArgCmd, ArrayForNRCmd, NULL, 0}, {"get", ArrayGetCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, {"names", ArrayNamesCmd, TclCompileBasic1To3ArgCmd, NULL, NULL, 0}, {"nextelement", ArrayNextElementCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"set", ArraySetCmd, TclCompileArraySetCmd, NULL, NULL, 0}, | > | 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 | /* ARGSUSED */ Tcl_Command TclInitArrayCmd( Tcl_Interp *interp) /* Current interpreter. */ { static const EnsembleImplMap arrayImplMap[] = { {"anymore", ArrayAnyMoreCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"default", ArrayDefaultCmd, TclCompileBasic2Or3ArgCmd, NULL, NULL, 0}, {"donesearch", ArrayDoneSearchCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"exists", ArrayExistsCmd, TclCompileArrayExistsCmd, NULL, NULL, 0}, {"for", ArrayForObjCmd, TclCompileBasic3ArgCmd, ArrayForNRCmd, NULL, 0}, {"get", ArrayGetCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, {"names", ArrayNamesCmd, TclCompileBasic1To3ArgCmd, NULL, NULL, 0}, {"nextelement", ArrayNextElementCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"set", ArraySetCmd, TclCompileArraySetCmd, NULL, NULL, 0}, |
︙ | ︙ | |||
5546 5547 5548 5549 5550 5551 5552 | * variables, some combinations of [upvar] and [variable] may create * such beasts - see [Bug 604239]. This is necessary to avoid leaking * the corresponding Var struct, and is otherwise harmless. */ TclClearVarNamespaceVar(elPtr); } | < | | 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 | * variables, some combinations of [upvar] and [variable] may create * such beasts - see [Bug 604239]. This is necessary to avoid leaking * the corresponding Var struct, and is otherwise harmless. */ TclClearVarNamespaceVar(elPtr); } DeleteArrayVar(varPtr); } /* *---------------------------------------------------------------------- * * TclObjVarErrMsg -- * |
︙ | ︙ | |||
6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 | /* * Only compare string representations of the same length. */ return ((l1 == l2) && !memcmp(p1, p2, l1)); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 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 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857 | /* * Only compare string representations of the same length. */ return ((l1 == l2) && !memcmp(p1, p2, l1)); } /*---------------------------------------------------------------------- * * ArrayDefaultCmd -- * * This function implements the 'array default' Tcl command. * Refer to the user documentation for details on what it does. * * Results: * Returns a standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static int ArrayDefaultCmd( ClientData clientData, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { static const char *const options[] = { "get", "set", "exists", "unset", NULL }; enum options { OPT_GET, OPT_SET, OPT_EXISTS, OPT_UNSET }; Tcl_Obj *arrayNameObj, *defaultValueObj; Var *varPtr, *arrayPtr; int isArray, option; /* * Parse arguments. */ if (objc != 3 && objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "option arrayName ?value?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0, &option) != TCL_OK) { return TCL_ERROR; } arrayNameObj = objv[2]; if (TCL_ERROR == LocateArray(interp, arrayNameObj, &varPtr, &isArray)) { return TCL_ERROR; } switch (option) { case OPT_GET: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "arrayName"); return TCL_ERROR; } if (!varPtr || TclIsVarUndefined(varPtr) || !isArray) { return NotArrayError(interp, arrayNameObj); } defaultValueObj = TclGetArrayDefault(varPtr); if (!defaultValueObj) { /* Array default must exist. */ Tcl_SetObjResult(interp, Tcl_NewStringObj( "array has no default value", -1)); Tcl_SetErrorCode(interp, "TCL", "READ", "ARRAY", "DEFAULT", NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, defaultValueObj); return TCL_OK; case OPT_SET: if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "arrayName value"); return TCL_ERROR; } /* * Attempt to create array if needed. */ varPtr = TclObjLookupVarEx(interp, arrayNameObj, NULL, /*flags*/ TCL_LEAVE_ERR_MSG, /*msg*/ "array default set", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr); if (varPtr == NULL) { return TCL_ERROR; } if (arrayPtr) { /* * Not a valid array name. */ CleanupVar(varPtr, arrayPtr); TclObjVarErrMsg(interp, arrayNameObj, NULL, "array default set", needArray, -1); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", TclGetString(arrayNameObj), NULL); return TCL_ERROR; } if (!TclIsVarArray(varPtr) && !TclIsVarUndefined(varPtr)) { /* * Not an array. */ TclObjVarErrMsg(interp, arrayNameObj, NULL, "array default set", needArray, -1); Tcl_SetErrorCode(interp, "TCL", "WRITE", "ARRAY", NULL); return TCL_ERROR; } if (!TclIsVarArray(varPtr)) { TclInitArrayVar(varPtr); } defaultValueObj = objv[3]; SetArrayDefault(varPtr, defaultValueObj); return TCL_OK; case OPT_EXISTS: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "arrayName"); return TCL_ERROR; } /* * Undefined variables (whether or not they have storage allocated) do * not have defaults, and this is not an error case. */ if (!varPtr || TclIsVarUndefined(varPtr)) { Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0)); } else if (!isArray) { return NotArrayError(interp, arrayNameObj); } else { defaultValueObj = TclGetArrayDefault(varPtr); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(!!defaultValueObj)); } return TCL_OK; case OPT_UNSET: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "arrayName"); return TCL_ERROR; } if (varPtr && !TclIsVarUndefined(varPtr)) { if (!isArray) { return NotArrayError(interp, arrayNameObj); } SetArrayDefault(varPtr, NULL); } return TCL_OK; } /* Unreached */ return TCL_ERROR; } /* * Initialize array variable. */ void TclInitArrayVar( Var *arrayPtr) { ArrayVarHashTable *tablePtr = ckalloc(sizeof(ArrayVarHashTable)); /* * Mark the variable as an array. */ TclSetVarArray(arrayPtr); /* * Regular TclVarHashTable initialization. */ arrayPtr->value.tablePtr = (TclVarHashTable *) tablePtr; TclInitVarHashTable(arrayPtr->value.tablePtr, TclGetVarNsPtr(arrayPtr)); /* * Default value initialization. */ tablePtr->defaultObj = NULL; } /* * Cleanup array variable. */ static void DeleteArrayVar( Var *arrayPtr) { ArrayVarHashTable *tablePtr = (ArrayVarHashTable *) arrayPtr->value.tablePtr; /* * Default value cleanup. */ SetArrayDefault(arrayPtr, NULL); /* * Regular TclVarHashTable cleanup. */ VarHashDeleteTable(arrayPtr->value.tablePtr); ckfree(tablePtr); } /* * Get array default value if any. */ Tcl_Obj * TclGetArrayDefault( Var *arrayPtr) { ArrayVarHashTable *tablePtr = (ArrayVarHashTable *) arrayPtr->value.tablePtr; return tablePtr->defaultObj; } /* * Set/replace/unset array default value. */ static void SetArrayDefault( Var *arrayPtr, Tcl_Obj *defaultObj) { ArrayVarHashTable *tablePtr = (ArrayVarHashTable *) arrayPtr->value.tablePtr; /* * Increment/decrement refcount twice to ensure that the object is shared, * so that it doesn't get modified accidentally by the folling code: * * array default set v 1 * lappend v(a) 2; # returns a new object {1 2} * set v(b); # returns the original default object "1" */ if (tablePtr->defaultObj) { Tcl_DecrRefCount(tablePtr->defaultObj); Tcl_DecrRefCount(tablePtr->defaultObj); } tablePtr->defaultObj = defaultObj; if (tablePtr->defaultObj) { Tcl_IncrRefCount(tablePtr->defaultObj); Tcl_IncrRefCount(tablePtr->defaultObj); } } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ |
Changes to tests/set-old.test.
︙ | ︙ | |||
336 337 338 339 340 341 342 | } foo } {1 {"x" isn't an array}} test set-old-8.6 {array command} { catch {unset a} set a(22) 3 list [catch {array gorp a} msg] $msg | | | 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 | } foo } {1 {"x" isn't an array}} test set-old-8.6 {array command} { catch {unset a} set a(22) 3 list [catch {array gorp a} msg] $msg } {1 {unknown or ambiguous subcommand "gorp": must be anymore, default, donesearch, exists, for, get, names, nextelement, set, size, startsearch, statistics, or unset}} test set-old-8.7 {array command, anymore option} { catch {unset a} list [catch {array anymore a x} msg] $msg } {1 {"a" isn't an array}} test set-old-8.8 {array command, anymore option, array doesn't exist yet but has compiler-allocated procedure slot} { proc foo {x} { if {$x==1} { |
︙ | ︙ | |||
696 697 698 699 700 701 702 | }}} msg] $msg } {1 {list must have an even number of elements}} test set-old-9.1 {ids for array enumeration} { catch {unset a} set a(a) 1 list [array star a] [array star a] [array done a s-1-a; array star a] \ | | | 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 | }}} msg] $msg } {1 {list must have an even number of elements}} test set-old-9.1 {ids for array enumeration} { catch {unset a} set a(a) 1 list [array star a] [array star a] [array done a s-1-a; array star a] \ [array done a s-2-a; array do a s-3-a; array start a] } {s-1-a s-2-a s-3-a s-1-a} test set-old-9.2 {array enumeration} { catch {unset a} set a(a) 1 set a(b) 1 set a(c) 1 set x [array startsearch a] |
︙ | ︙ |
Changes to tests/var.test.
︙ | ︙ | |||
1042 1043 1044 1045 1046 1047 1048 | } -result 0 test var-22.2 {leak in parsedVarName} -constraints memory -body { set i 0 leaktest {lappend x($i)} } -cleanup { unset -nocomplain i x } -result 0 | | | 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 | } -result 0 test var-22.2 {leak in parsedVarName} -constraints memory -body { set i 0 leaktest {lappend x($i)} } -cleanup { unset -nocomplain i x } -result 0 unset -nocomplain a k v test var-23.1 {array command, for loop, too many args} -returnCodes error -body { array for {k v} c d e {} } -result {wrong # args: should be "array for {key value} arrayName script"} test var-23.2 {array command, for loop, not enough args} -returnCodes error -body { array for {k v} {} } -result {wrong # args: should be "array for {key value} arrayName script"} |
︙ | ︙ | |||
1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 | unset -nocomplain $vn } -body { array set $vn {a 1 b 2 c 3} array for $vn $vn {} } -cleanup { unset -nocomplain $vn vn } -result {} catch {namespace delete ns} catch {unset arr} catch {unset v} catch {rename getbytes ""} catch {rename p ""} | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 | unset -nocomplain $vn } -body { array set $vn {a 1 b 2 c 3} array for $vn $vn {} } -cleanup { unset -nocomplain $vn vn } -result {} test var-24.1 {array default set and get: interpreted} -setup { unset -nocomplain ary } -body { array set ary {a 3} array default set ary 7 list $ary(a) $ary(b) [info exist ary(a)] [info exist ary(b)] \ [array default get ary] } -cleanup { unset -nocomplain ary } -result {3 7 1 0 7} test var-24.2 {array default set and get: compiled} { apply {{} { array set ary {a 3} array default set ary 7 list $ary(a) $ary(b) [info exist ary(a)] [info exist ary(b)] \ [array default get ary] }} } {3 7 1 0 7} test var-24.3 {array default unset: interpreted} -setup { unset -nocomplain ary } -body { array set ary {a 3} array default set ary 7 list $ary(a) $ary(b) [array default unset ary] $ary(a) [catch {set ary(b)}] } -cleanup { unset -nocomplain ary } -result {3 7 {} 3 1} test var-24.4 {array default unset: compiled} { apply {{} { array set ary {a 3} array default set ary 7 list $ary(a) $ary(b) [array default unset ary] $ary(a) \ [catch {set ary(b)}] }} } {3 7 {} 3 1} test var-24.5 {array default exists: interpreted} -setup { unset -nocomplain ary result set result {} } -body { array set ary {a 3} lappend result [info exists ary],[array exists ary],[array default exists ary] array default set ary 7 lappend result [info exists ary],[array exists ary],[array default exists ary] array default unset ary lappend result [info exists ary],[array exists ary],[array default exists ary] unset ary lappend result [info exists ary],[array exists ary],[array default exists ary] array default set ary 11 lappend result [info exists ary],[array exists ary],[array default exists ary] } -cleanup { unset -nocomplain ary result } -result {1,1,0 1,1,1 1,1,0 0,0,0 1,1,1} test var-24.6 {array default exists: compiled} { apply {{} { array set ary {a 3} lappend result [info exists ary],[array exists ary],[array default exists ary] array default set ary 7 lappend result [info exists ary],[array exists ary],[array default exists ary] array default unset ary lappend result [info exists ary],[array exists ary],[array default exists ary] unset ary lappend result [info exists ary],[array exists ary],[array default exists ary] array default set ary 11 lappend result [info exists ary],[array exists ary],[array default exists ary] }} } {1,1,0 1,1,1 1,1,0 0,0,0 1,1,1} test var-24.7 {array default and append: interpreted} -setup { unset -nocomplain ary result set result {} } -body { array default set ary grill lappend result [array size ary] [info exist ary(x)] append ary(x) abc lappend result [array size ary] $ary(x) array default unset ary append ary(x) def append ary(y) ghi lappend result [array size ary] $ary(x) $ary(y) } -cleanup { unset -nocomplain ary result } -result {0 0 1 grillabc 2 grillabcdef ghi} test var-24.8 {array default and append: compiled} { apply {{} { array default set ary grill lappend result [array size ary] [info exist ary(x)] append ary(x) abc lappend result [array size ary] $ary(x) array default unset ary append ary(x) def append ary(y) ghi lappend result [array size ary] $ary(x) $ary(y) }} } {0 0 1 grillabc 2 grillabcdef ghi} test var-24.9 {array default and lappend: interpreted} -setup { unset -nocomplain ary result set result {} } -body { array default set ary grill lappend result [array size ary] [info exist ary(x)] lappend ary(x) abc lappend result [array size ary] $ary(x) array default unset ary lappend ary(x) def lappend ary(y) ghi lappend result [array size ary] $ary(x) $ary(y) } -cleanup { unset -nocomplain ary result } -result {0 0 1 {grill abc} 2 {grill abc def} ghi} test var-24.10 {array default and lappend: compiled} { apply {{} { array default set ary grill lappend result [array size ary] [info exist ary(x)] lappend ary(x) abc lappend result [array size ary] $ary(x) array default unset ary lappend ary(x) def lappend ary(y) ghi lappend result [array size ary] $ary(x) $ary(y) }} } {0 0 1 {grill abc} 2 {grill abc def} ghi} test var-24.11 {array default and incr: interpreted} -setup { unset -nocomplain ary result set result {} } -body { array default set ary 7 lappend result [array size ary] [info exist ary(x)] incr ary(x) 11 lappend result [array size ary] $ary(x) array default unset ary incr ary(x) incr ary(y) lappend result [array size ary] $ary(x) $ary(y) } -cleanup { unset -nocomplain ary result } -result {0 0 1 18 2 19 1} test var-24.12 {array default and incr: compiled} { apply {{} { array default set ary 7 lappend result [array size ary] [info exist ary(x)] incr ary(x) 11 lappend result [array size ary] $ary(x) array default unset ary incr ary(x) incr ary(y) lappend result [array size ary] $ary(x) $ary(y) }} } {0 0 1 18 2 19 1} test var-24.13 {array default and dict: interpreted} -setup { unset -nocomplain ary x y z } -body { array default set ary {x y} dict lappend ary(p) x z dict update ary(q) x y { set y z } dict with ary(r) { set x 123 } lsort -stride 2 -index 0 [array get ary] } -cleanup { unset -nocomplain ary x y z } -result {p {x {y z}} q {x z} r {x 123}} test var-24.14 {array default and dict: compiled} { lsort -stride 2 -index 0 [apply {{} { array default set ary {x y} dict lappend ary(p) x z dict update ary(q) x y { set y z } dict with ary(r) { set x 123 } array get ary }}] } {p {x {y z}} q {x z} r {x 123}} test var-24.15 {array default set and get: two-level} { apply {{} { array set ary {a 3} array default set ary 7 apply {{} { upvar 1 ary ary ary(c) c lappend result $ary(a) $ary(b) $c lappend result [info exist ary(a)] [info exist ary(b)] [info exist c] lappend result [array default get ary] }} }} } {3 7 7 1 0 0 7} test var-24.16 {array default set: errors} -setup { unset -nocomplain ary } -body { set ary not-an-array array default set ary 7 } -returnCodes error -cleanup { unset -nocomplain ary } -result {can't array default set "ary": variable isn't array} test var-24.17 {array default set: errors} -setup { unset -nocomplain ary } -body { array default set ary } -returnCodes error -cleanup { unset -nocomplain ary } -result * -match glob test var-24.18 {array default set: errors} -setup { unset -nocomplain ary } -body { array default set ary x y } -returnCodes error -cleanup { unset -nocomplain ary } -result * -match glob test var-24.19 {array default get: errors} -setup { unset -nocomplain ary } -body { set ary not-an-array array default get ary } -returnCodes error -cleanup { unset -nocomplain ary } -result {"ary" isn't an array} test var-24.20 {array default get: errors} -setup { unset -nocomplain ary } -body { array default get ary x y } -returnCodes error -cleanup { unset -nocomplain ary } -result * -match glob test var-24.21 {array default exists: errors} -setup { unset -nocomplain ary } -body { set ary not-an-array array default exists ary } -returnCodes error -cleanup { unset -nocomplain ary } -result {"ary" isn't an array} test var-24.22 {array default exists: errors} -setup { unset -nocomplain ary } -body { array default exists ary x } -returnCodes error -cleanup { unset -nocomplain ary } -result * -match glob test var-24.23 {array default unset: errors} -setup { unset -nocomplain ary } -body { set ary not-an-array array default unset ary } -returnCodes error -cleanup { unset -nocomplain ary } -result {"ary" isn't an array} 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 ""} |
︙ | ︙ |