Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa12f7d709 | ||
|
|
a7909595ec | ||
|
|
7d753e316a |
-333
@@ -1,333 +0,0 @@
|
||||
'\"
|
||||
'\" Copyright (c) 2016 Andy Goth
|
||||
'\"
|
||||
'\" See the file "license.terms" for information on usage and redistribution
|
||||
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
'\"
|
||||
.TH Tcl_ArraySet 3 8.7 Tcl "Tcl Library Procedures"
|
||||
.so man.macros
|
||||
.BS
|
||||
'\" Note: do not modify the .SH NAME line immediately below!
|
||||
.SH NAME
|
||||
Tcl_ArraySet, Tcl_ArrayUnset, Tcl_ArrayGet, Tcl_ArrayNames, Tcl_ArraySize, Tcl_ArrayExists, Tcl_ArraySearchStart, Tcl_ArraySearchPeek, Tcl_ArraySearchNext, Tcl_ArraySearchDone, Tcl_ArrayStatistics \- manipulate Tcl array variables
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
\fB#include <tcl.h>\fR
|
||||
.sp
|
||||
int
|
||||
\fBTcl_ArraySet\fR(\fIinterp, part1Ptr, dictPtr, flags\fR)
|
||||
.sp
|
||||
int
|
||||
\fBTcl_ArrayUnset\fR(\fIinterp, part1Ptr, part2Ptr, flags\fR)
|
||||
.sp
|
||||
int
|
||||
\fBTcl_ArrayGet\fR(\fIinterp, part1Ptr, part2Ptr, dictPtr, flags\fR)
|
||||
.sp
|
||||
int
|
||||
\fBTcl_ArrayNames\fR(\fIinterp, part1Ptr, part2Ptr, listPtr, flags\fR)
|
||||
.sp
|
||||
int
|
||||
\fBTcl_ArraySize\fR(\fIinterp, part1Ptr, part2Ptr, intPtr, flags\fR)
|
||||
.sp
|
||||
int
|
||||
\fBTcl_ArrayExists\fR(\fIinterp, part1Ptr, part2ptr, intPtr, flags\fR)
|
||||
.sp
|
||||
Tcl_ArraySearch
|
||||
\fBTcl_ArraySearchStart\fR(\fIinterp, part1Ptr, part2Ptr, flags\fR)
|
||||
.sp
|
||||
Tcl_Obj *
|
||||
\fBTcl_ArraySearchPeek\fR(\fIsearch\fR)
|
||||
.sp
|
||||
Tcl_Obj *
|
||||
\fBTcl_ArraySearchNext\fR(\fIsearch\fR)
|
||||
.sp
|
||||
void
|
||||
\fBTcl_ArraySearchDone\fR(\fIsearch\fR)
|
||||
.sp
|
||||
int
|
||||
\fBTcl_ArrayStatistics\fR(\fIinterp, part1Ptr, stringPtr, flags\fR)
|
||||
.SH ARGUMENTS
|
||||
.AS Tcl_ArraySearch search
|
||||
.AP Tcl_Interp *interp in
|
||||
Interpreter containing the variable. If an error occurs, an error message is
|
||||
left in the interpreter's result.
|
||||
.AP Tcl_Obj *part1Ptr in
|
||||
Points to a Tcl value containing the array variable's name. The name may
|
||||
include a series of \fB::\fR namespace qualifiers to specify a variable in a
|
||||
particular namespace.
|
||||
.AP Tcl_Obj *part2Ptr in
|
||||
If non-NULL, points to a Tcl value containing an array element name filter
|
||||
specification. The format and interpretation of \fIpart2Ptr\fR are determined
|
||||
by the \fIflags\fR argument.
|
||||
.AP int flags in
|
||||
OR-ed combination of bits providing additional information. See below for valid
|
||||
values.
|
||||
.AP Tcl_Obj *dictPtr in/out
|
||||
Points to the dictionary value to be read or manipulated. If \fIdictPtr\fR does
|
||||
not already point to a dictionary value, an attempt will be made to convert it
|
||||
to one. \fBTcl_ArraySet\fR allows \fIdictPtr\fR to be NULL, in which case it
|
||||
creates an empty array if the array does not already exist.
|
||||
.AP Tcl_Obj *listPtr in/out
|
||||
Points to the list value to be manipulated. If \fIlistPtr\fR does not already
|
||||
point to a list value, an attempt will be made to convert it to one.
|
||||
.AP Tcl_Obj *stringPtr in/out
|
||||
Points to the string value to be manipulated.
|
||||
.AP int *intPtr out
|
||||
Points to location where \fBTcl_ArrayExists\fR stores the array existence flag
|
||||
or \fBTcl_ArraySize\fR stores the number of matching array elements.
|
||||
.AP Tcl_ArraySearch search in/out
|
||||
Token for tracking the progress of enumerating array elements.
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
These functions are used to create, modify, enumerate, analyze, read, and delete
|
||||
Tcl array variables from C code.
|
||||
.PP
|
||||
The \fBTcl_ArraySet\fR, \fBTcl_ArrayUnset\fR, \fBTcl_ArrayGet\fR,
|
||||
\fBTcl_ArrayNames\fR, \fBTcl_ArraySize\fR, \fBTcl_ArrayExists\fR, and
|
||||
\fBTcl_ArrayStatistics\fR functions return \fBTCL_OK\fR on success and
|
||||
\fBTCL_ERROR\fR on error. If an error occurs, an error message is left in the
|
||||
interpreter's result. The possible errors are caused by format (invalid list,
|
||||
dictionary, or regular expression) and traces (array, read, write, or unset).
|
||||
.PP
|
||||
Except for \fBTcl_ArraySet\fR, \fBTcl_ArraySearchStart\fR (not listed above),
|
||||
and \fBTcl_ArrayStatistics\fR, the array functions do not consider it an error
|
||||
for a namespace or variable to not exist or a variable to be a scalar or array
|
||||
element instead of an array. \fBTcl_ArraySet\fR allows the array variable to
|
||||
not exist, in which case it creates it, but it returns \fBTCL_ERROR\fR in all
|
||||
the other situations listed in the previous sentence.
|
||||
.PP
|
||||
Array functions trigger array traces in the same manner as the \fBarray\fR
|
||||
command. After the completion of any array traces, for each accessed array
|
||||
element, \fBTcl_ArraySet\fR triggers write traces, \fBTcl_ArrayUnset\fR triggers
|
||||
unset traces, and \fBTcl_ArrayGet\fR triggers read traces. As discussed above,
|
||||
an error encountered during the execution of a trace causes the function to
|
||||
place error information in the interpreter's result and return \fBTCL_ERROR\fR.
|
||||
.PP
|
||||
The \fBTcl_ArraySet\fR, \fBTcl_ArrayUnset\fR, \fBTcl_ArrayGet\fR,
|
||||
\fBTcl_ArrayNames\fR, \fBTcl_ArraySize\fR, \fBTcl_ArrayExists\fR,
|
||||
\fBTcl_ArraySearchStart\fR, and \fBTcl_ArrayStatistics\fR functions accept a
|
||||
\fIflags\fR argument to control the scope of the variable lookup and to specify
|
||||
the interpretation of \fIpart2Ptr\fR. It consists of an OR-ed combination of
|
||||
zero or more of the following bits.
|
||||
.TP
|
||||
\fBTCL_GLOBAL_ONLY\fR
|
||||
Under normal circumstances the functions look up variables as follows. If a
|
||||
procedure call is active in \fIinterp\fR, the array variable is looked up at the
|
||||
current level of procedure call. Otherwise, the array variable is looked up
|
||||
first in the current namespace, then in the global namespace. However, if this
|
||||
bit is set in \fIflags\fR then the array variable is looked up only in the
|
||||
global namespace even if there is a procedure call active. If both
|
||||
\fBTCL_GLOBAL_ONLY\fR and \fBTCL_NAMESPACE_ONLY\fR are given,
|
||||
\fBTCL_GLOBAL_ONLY\fR is ignored.
|
||||
.TP
|
||||
\fBTCL_NAMESPACE_ONLY\fR
|
||||
If this bit is set in \fIflags\fR then the array variable is looked up only in
|
||||
the current namespace. If a procedure is active, its variables are ignored, and
|
||||
the global namespace is also ignored unless it is the current namespace.
|
||||
.PP
|
||||
With the exception of \fBTcl_ArraySet\fR and \fBTcl_ArrayStatistics\fR which do
|
||||
not support filtering, the \fIflags\fR argument is also OR-ed with zero or one
|
||||
of the following values to select the type of filtering applied by
|
||||
\fIpart2Ptr\fR. Setting more than one filter type may cause \fBTcl_Panic\fR to
|
||||
be called. The filter type is ignored if \fIpart2Ptr\fR is NULL, in which case
|
||||
no filtering is applied and all array elements are matched.
|
||||
.TP
|
||||
\fBTCL_MATCH_EXACT\fR
|
||||
\fIpart2Ptr\fR is an array element name. The filter matches at most a single
|
||||
array element whose name is exactly equal to the value of \fIpart2Ptr\fR. If no
|
||||
filter type is explicitly specified in \fIflags\fR, \fBTCL_MATCH_EXACT\fR is
|
||||
used by default. This differs from the \fBarray\fR commands which default to
|
||||
\fB\-glob\fR.
|
||||
.TP
|
||||
\fBTCL_MATCH_GLOB\fR
|
||||
\fIpart2Ptr\fR is a glob pattern, and it matches array element names according
|
||||
to the rules of \fBstring match\fR. \fIpart2Ptr\fR must match the entire array
|
||||
element name from beginning to end. To match substrings, place \fB*\fR at
|
||||
either end of \fIpart2Ptr\fR.
|
||||
.TP
|
||||
\fBTCL_MATCH_REGEXP\fR
|
||||
\fIpart2Ptr\fR is a regular expression, and it matches array element names
|
||||
according to the rules of \fBregexp\fR. Unless anchored by the \fB^\fR and
|
||||
\fB$\fR constraints, \fIpart2Ptr\fR matches substrings. Thus, an empty
|
||||
\fIpart2Ptr\fR matches every possible array element name. It is an error for
|
||||
\fIpart2Ptr\fR to not be a valid regular expression, but this error is only
|
||||
detected and reported when \fIpart1Ptr\fR names a non-empty array.
|
||||
.PP
|
||||
The \fBTcl_ArraySet\fR, \fBTcl_ArrayGet\fR, and \fBTcl_ArrayNames\fR functions
|
||||
accept \fIdictPtr\fR and \fIlistPtr\fR arguments referencing dictionary and list
|
||||
values, respectively. If these values are not already dictionary and list
|
||||
values, an attempt will be made to convert them. If the conversion fails,
|
||||
\fBTCL_ERROR\fR will be returned and an error message will be left in the
|
||||
interpreter's result.
|
||||
.PP
|
||||
\fBTcl_ArraySet\fR sets the values of zero or more elements in the array named
|
||||
by \fIpart1Ptr\fR. If not NULL, \fIdictPtr\fR must be a valid dictionary, i.e.
|
||||
it must be a list consisting of an even number of elements alternating between
|
||||
key and value. Each key in \fIdictPtr\fR is treated as an element name within
|
||||
the array, and its associated value is used as the new value for that array
|
||||
element. If the variable named by \fIpart1Ptr\fR does not already exist and
|
||||
\fIdictPtr\fR is empty or NULL, the variable is created as an empty array. It
|
||||
is an error for \fIpart1Ptr\fR to name a scalar (non-array) variable or an array
|
||||
element, or for it to reference a nonexistent namespace.
|
||||
.PP
|
||||
\fBTcl_ArrayUnset\fR unsets all elements in the array named by \fIpart1Ptr\fR
|
||||
that match the filter specified by \fIpart2Ptr\fR and \fIflags\fR. It is not an
|
||||
error for \fIpart1Ptr\fR to not name an array or for there to be no matching
|
||||
elements in the array. If \fIpart2Ptr\fR is NULL and \fIpart1Ptr\fR names an
|
||||
array, the entire array is unset, and future calls to \fBTcl_ArrayExists\fR will
|
||||
report it as not existing. This is distinct from unsetting each element of the
|
||||
array (e.g. if \fIpart2Ptr\fR is \fB*\fR and \fIflags\fR is
|
||||
\fBTCL_MATCH_GLOB\fR), which does not cause future calls to
|
||||
\fBTcl_ArrayExists\fR to report the array as not existing.
|
||||
.PP
|
||||
\fBTcl_ArrayGet\fR loads the contents of the array named by \fIpart1Ptr\fR into
|
||||
the \fIdictPtr\fR dictionary object. The array element names and values are
|
||||
used as the dictionary keys and values, respectively. If \fIpart2Ptr\fR is not
|
||||
NULL, \fIpart2Ptr\fR and \fIflags\fR specify a filter used to limit which array
|
||||
elements are loaded into \fIdictPtr\fR. If \fIpart1Ptr\fR does not name an
|
||||
array or if there are no matching elements, \fIdictPtr\fR is not modified.
|
||||
If \fIdictPtr\fR is not empty prior to calling \fBTcl_ArrayGet\fR, the array
|
||||
data is merged into \fIdictPtr\fR. If an array element has the same name as an
|
||||
existing dictionary key, the array element value replaces the existing
|
||||
dictionary value.
|
||||
.PP
|
||||
\fBTcl_ArrayNames\fR loads the element names of the array named by
|
||||
\fIpart1Ptr\fR into the \fIlistPtr\fR list object. If \fIpart2Ptr\fR is not
|
||||
NULL, \fIpart2Ptr\fR and \fIflags\fR specify a filter used to limit which array
|
||||
element names are loaded into \fIlistPtr\fR. If \fIpart1Ptr\fR does not name an
|
||||
array or if there are no matching elements, \fIlistPtr\fR is not modified. If
|
||||
\fIlistPtr\fR is not empty prior to calling \fBTcl_ArrayNames\fR, the array
|
||||
element names are appended to \fIlistPtr\fR.
|
||||
.PP
|
||||
\fBTcl_ArraySize\fR stores the number of elements in the array named by
|
||||
\fIpart1Ptr\fR into the address \fIintPtr\fR. If \fIpart2Ptr\fR is not NULL,
|
||||
\fIpart2Ptr\fR and \fIflags\fR specify a filter used to limit which array
|
||||
elements count toward the total number of elements.
|
||||
.PP
|
||||
\fBTcl_ArrayExists\fR checks for the existence of an array variable named
|
||||
\fIpart1Ptr\fR or (if \fIpart2Ptr\fR is not NULL) an array element within
|
||||
matching the filter specified by \fIpart2Ptr\fR and \fIflags\fR. If the array
|
||||
variable or array element exists, the value \fB1\fR is stored into the location
|
||||
\fIintPtr\fR, even if the array is empty. If \fIpart1Ptr\fR does not name an
|
||||
array variable (the variable does not exist, it is a scalar variable or array
|
||||
element, or it references a nonexistent namespace), or if \fIpart2Ptr\fR is not
|
||||
NULL and no elements match the filter, the value \fB0\fR is stored into the
|
||||
location \fIintPtr\fR.
|
||||
.PP
|
||||
\fBTcl_ArraySearchStart\fR initiates an array search, i.e. an array element
|
||||
enumeration yielding one element at a time. \fIpart1Ptr\fR must name an array.
|
||||
If \fIpart2Ptr\fR is not NULL, \fIpart2Ptr\fR and \fIflags\fR specify a filter
|
||||
used to limit which array elements are included in the enumeration. The return
|
||||
value is a token used to track the progress of the search, and it is to be
|
||||
passed to the \fBTcl_ArraySearchPeek\fR, \fBTcl_ArraySearchNext\fR, and
|
||||
\fBTcl_ArraySearchDone\fR functions. If there is an error looking up the
|
||||
variable, executing an array trace, or validating a regular expression filter,
|
||||
NULL is returned and error information is placed in the interpreter result.
|
||||
.PP
|
||||
\fBTcl_ArraySearchPeek\fR and \fBTcl_ArraySearchNext\fR return the next array
|
||||
element name in the search identified by the \fIsearch\fR argument. If there
|
||||
are no remaining element names, NULL is returned. \fBTcl_ArraySearchPeek\fR
|
||||
does not advance the enumeration, whereas \fBTcl_ArraySearchNext\fR does, so
|
||||
\fBTcl_ArraySearchPeek\fR will return the same value each time it is called if
|
||||
there are no intervening calls to \fBTcl_ArraySearchNext\fR with the same
|
||||
\fIsearch\fR argument.
|
||||
.PP
|
||||
\fBTcl_ArraySearchDone\fR completes the search identified by the \fIsearch\fR
|
||||
argument and deallocates associated resources. To avoid memory leaks,
|
||||
\fBTcl_ArraySearchDone\fR must be called once for each search token returned by
|
||||
\fBTcl_ArraySearchStart\fR.
|
||||
.PP
|
||||
\fBTcl_ArrayStatistics\fR produces statistics about the distribution of data
|
||||
within the hash table underlying the array named by \fIpart1Ptr\fR. This
|
||||
information includes the number of entries in the table, the number of buckets,
|
||||
and the utilization of the buckets. The statistics information is appended to
|
||||
the string value \fIstringPtr\fR.
|
||||
.SH EXAMPLES
|
||||
.PP
|
||||
Common initialization used for subsequent examples:
|
||||
.PP
|
||||
.CS
|
||||
int size, i;
|
||||
Tcl_Obj *obj, **objPtr;
|
||||
Tcl_Obj *varNameObj = Tcl_NewStringObj("colorcount", -1);
|
||||
Tcl_Channel outChan = Tcl_GetChannel(interp, "stdout", NULL);
|
||||
.CE
|
||||
.PP
|
||||
Create an array:
|
||||
.PP
|
||||
.CS
|
||||
obj = Tcl_NewStringObj(
|
||||
" red 1"
|
||||
" green 5"
|
||||
" blue 4"
|
||||
" white 9", -1);
|
||||
\fBTcl_ArraySet\fR(interp, varNameObj, obj, 0);
|
||||
.CE
|
||||
.PP
|
||||
Load the full contents of an array into a single object:
|
||||
.PP
|
||||
.CS
|
||||
Tcl_SetStringObj(obj, NULL, 0);
|
||||
\fBTcl_ArrayGet\fR(interp, varNameObj, NULL, obj, 0);
|
||||
Tcl_ListObjGetElements(interp, obj, &size, &objPtr);
|
||||
for (i = 0; i < size; i += 2, objPtr += 2) {
|
||||
Tcl_WriteChars(outChan, "Color: ", -1);
|
||||
Tcl_WriteObj(outChan, objPtr[0]);
|
||||
Tcl_WriteChars(outChan, " Count: ", -1);
|
||||
Tcl_WriteObj(outChan, objPtr[1]);
|
||||
Tcl_WriteChars(outChan, "\\n", -1);
|
||||
}
|
||||
\fB\(->\fR Color: blue Count: 4
|
||||
Color: white Count: 9
|
||||
Color: green Count: 5
|
||||
Color: red Count: 1
|
||||
.CE
|
||||
.PP
|
||||
Get an array element name list then individually look up each element value:
|
||||
.PP
|
||||
.CS
|
||||
Tcl_SetStringObj(obj, NULL, 0);
|
||||
\fBTcl_ArrayNames\fR(interp, varNameObj, NULL, obj, 0);
|
||||
Tcl_ListObjGetElements(interp, obj, &size, &objPtr);
|
||||
for (i = 0; i < size; ++i, ++objPtr) {
|
||||
Tcl_WriteChars(outChan, "Color: ", -1);
|
||||
Tcl_WriteObj(outChan, *objPtr);
|
||||
Tcl_WriteChars(outChan, " Count: ", -1);
|
||||
Tcl_WriteObj(outChan, Tcl_ObjGetVar2(
|
||||
interp, varNameObj, *objPtr, 0));
|
||||
Tcl_WriteChars(outChan, "\\n", -1);
|
||||
}
|
||||
\fB\(->\fR Color: blue Count: 4
|
||||
Color: white Count: 9
|
||||
Color: green Count: 5
|
||||
Color: red Count: 1
|
||||
.CE
|
||||
.PP
|
||||
Get array hash table statistics:
|
||||
.PP
|
||||
.CS
|
||||
Tcl_SetStringObj(obj, NULL, 0);
|
||||
\fBTcl_ArrayStatistics\fR(interp, varNameObj, obj, 0);
|
||||
Tcl_WriteObj(outChan, obj);
|
||||
Tcl_WriteChars(outChan, "\\n", -1);
|
||||
\fB\(->\fR 4 entries in table, 4 buckets
|
||||
number of buckets with 0 entries: 1
|
||||
number of buckets with 1 entries: 2
|
||||
number of buckets with 2 entries: 1
|
||||
number of buckets with 3 entries: 0
|
||||
number of buckets with 4 entries: 0
|
||||
number of buckets with 5 entries: 0
|
||||
number of buckets with 6 entries: 0
|
||||
number of buckets with 7 entries: 0
|
||||
number of buckets with 8 entries: 0
|
||||
number of buckets with 9 entries: 0
|
||||
number of buckets with 10 or more entries: 0
|
||||
average search distance for entry: 1.2
|
||||
.CE
|
||||
.SH "SEE ALSO"
|
||||
array(n), Tcl_NewObj(3), Tcl_NewListObj(3), Tcl_NewDictObj(3),
|
||||
Tcl_ObjGetVar2(3), Tcl_GetObjResult(3), Tcl_TraceVar2(3)
|
||||
.SH KEYWORDS
|
||||
array, dict, dict value, dictionary, get variable, hash table, iteration,
|
||||
interpreter, set, unset, value, variable
|
||||
+3
-3
@@ -23,11 +23,11 @@ Tcl interpreter handle.
|
||||
A version string consisting of one or more decimal numbers
|
||||
separated by dots.
|
||||
.AP int exact in
|
||||
1 means that only the particular version specified by
|
||||
Non-zero means that only the particular version specified by
|
||||
\fIversion\fR is acceptable.
|
||||
0 means that versions newer than \fIversion\fR are also
|
||||
Zero means that versions newer than \fIversion\fR are also
|
||||
acceptable as long as they have the same major version number
|
||||
as \fIversion\fR. Other bits have no effect.
|
||||
as \fIversion\fR.
|
||||
.BE
|
||||
.SH INTRODUCTION
|
||||
.PP
|
||||
|
||||
+29
-58
@@ -22,42 +22,6 @@ Unless otherwise specified for individual commands below,
|
||||
\fIarrayName\fR must be the name of an existing array variable.
|
||||
The \fIoption\fR argument determines what action is carried
|
||||
out by the command.
|
||||
.PP
|
||||
Many array commands accept \fImode\fR and \fIpattern\fR arguments. These
|
||||
arguments specify a filter to limit which array elements are included in the
|
||||
operation. If neither argument is specified, no filtering is applied, and the
|
||||
entire array is processed. If only one argument is specified, it is used as the
|
||||
\fIpattern\fR argument, and \fB\-glob\fR is used as the default value for
|
||||
\fImode\fR. If both arguments are specified, the first is used as \fImode\fR
|
||||
and the second as \fIpattern\fR. The \fImode\fR argument designates which
|
||||
matching rules to use to match \fIpattern\fR against the names of the elements
|
||||
in the array. The legal \fImode\fR values are:
|
||||
.TP
|
||||
\fB\-exact\fR
|
||||
.
|
||||
\fIPattern\fR is a literal string that is compared for exact equality against
|
||||
each array element name. This mode has limited utility because all uses of the
|
||||
\fBarray\fR command with \fB-exact\fR matching can be implemented by operating
|
||||
directly on the array element with standard \fIname\fB(\fIindex\fB)\fR notation.
|
||||
.TP
|
||||
\fB\-glob\fR
|
||||
.
|
||||
\fIPattern\fR is a glob-style pattern which is matched against each array
|
||||
element name using the same rules as the \fBstring match\fR command.
|
||||
\fIPattern\fR must match the entire array element name from beginning to end.
|
||||
To match substrings, place \fB*\fR at either end of \fIpattern\fR. This mode is
|
||||
the default if no \fImode\fR is specified.
|
||||
.TP
|
||||
\fB\-regexp\fR
|
||||
.
|
||||
\fIPattern\fR is treated as a regular expression and matched against each array
|
||||
element name using the rules described in the \fBre_syntax\fR reference page.
|
||||
Unless anchored by the \fB^\fR and \fB$\fR constraints, \fIpattern\fR matches
|
||||
substrings. Thus, an empty \fIpattern\fR matches every possible array element
|
||||
name. It is an error for \fIpattern\fR to not be a valid regular expression,
|
||||
but this error condition is only detected and reported when \fIarrayName\fR is a
|
||||
non-empty array.
|
||||
.PP
|
||||
The legal \fIoptions\fR (which may be abbreviated) are:
|
||||
.TP
|
||||
\fBarray anymore \fIarrayName searchId\fR
|
||||
@@ -79,20 +43,27 @@ 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.
|
||||
.TP
|
||||
\fBarray exists \fIarrayName\fR ?\fImode\fR? ?\fIpattern\fR?
|
||||
\fBarray exists \fIarrayName\fR
|
||||
Returns 1 if \fIarrayName\fR is an array variable, 0 if there
|
||||
is no variable by that name or if it is a scalar variable.
|
||||
If \fIpattern\fR is specified, this command instead checks if one or more
|
||||
elements of \fIarrayName\fR match the filter defined by \fImode\fR and
|
||||
\fIpattern\fR, returning 1 or 0 if the match succeeds or fails, respectively.
|
||||
.TP
|
||||
\fBarray get \fIarrayName\fR ?\fImode\fR? ?\fIpattern\fR?
|
||||
\fBarray for {\fIkeyVariable ?valueVariable?\fB} \fIarrayName body\fR
|
||||
The first argument is a one or two element list of variable names for the
|
||||
key and value of each entry in the array. The second argument is the
|
||||
array name to iterate over. The third argument is the body to execute
|
||||
for each key and value returned.
|
||||
The ordering of the returned keys is undefined.
|
||||
.TP
|
||||
\fBarray get \fIarrayName\fR ?\fIpattern\fR?
|
||||
Returns a list containing pairs of elements. The first
|
||||
element in each pair is the name of an element in \fIarrayName\fR
|
||||
and the second element of each pair is the value of the
|
||||
array element. The order of the pairs is undefined.
|
||||
The \fImode\fR and \fIpattern\fR arguments can be used to limit which array
|
||||
elements are included in the result.
|
||||
If \fIpattern\fR is not specified, then all of the elements of the
|
||||
array are included in the result.
|
||||
If \fIpattern\fR is specified, then only those elements whose names
|
||||
match \fIpattern\fR (using the matching rules of
|
||||
\fBstring match\fR) are included.
|
||||
If \fIarrayName\fR is not the name of an array variable, or if
|
||||
the array contains no elements, then an empty list is returned.
|
||||
If traces on the array modify the list of elements, the elements
|
||||
@@ -101,10 +72,15 @@ returned are those that exist both before and after the call to
|
||||
.TP
|
||||
\fBarray names \fIarrayName\fR ?\fImode\fR? ?\fIpattern\fR?
|
||||
Returns a list containing the names of all of the elements in
|
||||
the array.
|
||||
The \fImode\fR and \fIpattern\fR arguments can be used to limit which array
|
||||
element names are included in the result.
|
||||
If there are no (matching) elements
|
||||
the array that match \fIpattern\fR. \fIMode\fR may be one of
|
||||
\fB\-exact\fR, \fB\-glob\fR, or \fB\-regexp\fR. If specified, \fImode\fR
|
||||
designates which matching rules to use to match \fIpattern\fR against
|
||||
the names of the elements in the array. If not specified, \fImode\fR
|
||||
defaults to \fB\-glob\fR. See the documentation for \fBstring match\fR
|
||||
for information on glob style matching, and the documentation for
|
||||
\fBregexp\fR for information on regexp matching.
|
||||
If \fIpattern\fR is omitted then the command returns all of
|
||||
the element names in the array. If there are no (matching) elements
|
||||
in the array, or if \fIarrayName\fR is not the name of an array
|
||||
variable, then an empty string is returned.
|
||||
.TP
|
||||
@@ -130,20 +106,16 @@ If the variable \fIarrayName\fR does not already exist
|
||||
and \fIlist\fR is empty,
|
||||
\fIarrayName\fR is created with an empty array value.
|
||||
.TP
|
||||
\fBarray size \fIarrayName\fR ?\fImode\fR? ?\fIpattern\fR?
|
||||
Returns an integer giving the number of elements in the
|
||||
\fBarray size \fIarrayName\fR
|
||||
Returns a decimal string giving the number of elements in the
|
||||
array.
|
||||
The \fImode\fR and \fIpattern\fR arguments can be used to limit which array
|
||||
elements are counted toward the result.
|
||||
If \fIarrayName\fR is not the name of an array then 0 is returned.
|
||||
.TP
|
||||
\fBarray startsearch \fIarrayName\fR ?\fImode\fR? ?\fIpattern\fR?
|
||||
\fBarray startsearch \fIarrayName\fR
|
||||
This command initializes an element-by-element search through the
|
||||
array given by \fIarrayName\fR, such that invocations of the
|
||||
\fBarray nextelement\fR command will return the names of the
|
||||
individual elements in the array.
|
||||
The \fImode\fR and \fIpattern\fR arguments can be used to limit which array
|
||||
element names are returned by future invocations of \fBarray nextelement\fR.
|
||||
When the search has been completed, the \fBarray donesearch\fR
|
||||
command should be invoked.
|
||||
The return value is a
|
||||
@@ -161,10 +133,9 @@ that represents the array. This information includes the number of
|
||||
entries in the table, the number of buckets, and the utilization of
|
||||
the buckets.
|
||||
.TP
|
||||
\fBarray unset \fIarrayName\fR ?\fImode\fR? ?\fIpattern\fR?
|
||||
Unsets all of the elements in the array that match the filter specified by the
|
||||
\fImode\fR and \fIpattern\fR arguments.
|
||||
If \fIarrayName\fR is not the name
|
||||
\fBarray unset \fIarrayName\fR ?\fIpattern\fR?
|
||||
Unsets all of the elements in the array that match \fIpattern\fR (using the
|
||||
matching rules of \fBstring match\fR). If \fIarrayName\fR is not the name
|
||||
of an array variable or there are no matching elements in the array, no
|
||||
error will be raised. If \fIpattern\fR is omitted and \fIarrayName\fR is
|
||||
an array variable, then the command unsets the entire array.
|
||||
|
||||
+10
-42
@@ -2324,53 +2324,21 @@ declare 630 {
|
||||
Tcl_Obj *compressionDictionaryObj)
|
||||
}
|
||||
|
||||
# ----- BASELINE -- FOR -- 8.6.0 ----- #
|
||||
|
||||
# TIP #XXX
|
||||
declare 631 {
|
||||
int Tcl_ArraySet(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *dictPtr,
|
||||
int flags)
|
||||
}
|
||||
# TIP #421
|
||||
declare 632 {
|
||||
int Tcl_ArrayUnset(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr,
|
||||
int flags)
|
||||
void Tcl_ArrayObjFirst(Tcl_Interp *interp,
|
||||
Tcl_Obj *arrayObj,
|
||||
Tcl_ArraySearch *searchPtr)
|
||||
}
|
||||
declare 633 {
|
||||
int Tcl_ArrayGet(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr,
|
||||
Tcl_Obj *dictPtr, int flags)
|
||||
}
|
||||
declare 634 {
|
||||
int Tcl_ArrayNames(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr,
|
||||
Tcl_Obj *listPtr, int flags)
|
||||
}
|
||||
declare 635 {
|
||||
int Tcl_ArraySize(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr,
|
||||
int *intPtr, int flags)
|
||||
}
|
||||
declare 636 {
|
||||
int Tcl_ArrayExists(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
|
||||
Tcl_Obj *part2Ptr, int *intPtr, int flags)
|
||||
}
|
||||
declare 637 {
|
||||
Tcl_ArraySearch Tcl_ArraySearchStart(Tcl_Interp *interp,
|
||||
Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags)
|
||||
}
|
||||
declare 638 {
|
||||
int Tcl_ArraySearchPeek(Tcl_Interp *interp, Tcl_ArraySearch search,
|
||||
Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr)
|
||||
}
|
||||
declare 639 {
|
||||
int Tcl_ArraySearchNext(Tcl_Interp *interp, Tcl_ArraySearch search,
|
||||
Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr)
|
||||
}
|
||||
declare 640 {
|
||||
int Tcl_ArraySearchDone(Tcl_Interp *interp, Tcl_ArraySearch search)
|
||||
}
|
||||
declare 641 {
|
||||
int Tcl_ArrayStatistics(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
|
||||
Tcl_Obj *stringPtr, int flags)
|
||||
int Tcl_ArrayObjNext(Tcl_Interp *interp,
|
||||
Tcl_ArraySearch *searchPtr,
|
||||
Tcl_Obj **keyPtrPtr,
|
||||
Tcl_Obj **valuePtrPtr)
|
||||
}
|
||||
|
||||
# ----- BASELINE -- FOR -- 8.6.0 ----- #
|
||||
|
||||
##############################################################################
|
||||
|
||||
# Define the platform specific public Tcl interface. These functions are only
|
||||
|
||||
+36
-8
@@ -532,7 +532,6 @@ typedef struct Tcl_Interp
|
||||
#endif /* TCL_NO_DEPRECATED */
|
||||
Tcl_Interp;
|
||||
|
||||
typedef struct Tcl_ArraySearch_ *Tcl_ArraySearch;
|
||||
typedef struct Tcl_AsyncHandler_ *Tcl_AsyncHandler;
|
||||
typedef struct Tcl_Channel_ *Tcl_Channel;
|
||||
typedef struct Tcl_ChannelTypeVersion_ *Tcl_ChannelTypeVersion;
|
||||
@@ -1084,10 +1083,9 @@ typedef struct Tcl_DString {
|
||||
/*
|
||||
* Flag values passed to variable-related functions.
|
||||
* WARNING: these bit choices must not conflict with the bit choice for
|
||||
* TCL_CANCEL_UNWIND, above, or TCL_VAR_CREATE (0x4000) in tclVar.c.
|
||||
* TCL_CANCEL_UNWIND, above.
|
||||
*/
|
||||
|
||||
#define TCL_MATCH_EXACT 0
|
||||
#define TCL_GLOBAL_ONLY 1
|
||||
#define TCL_NAMESPACE_ONLY 2
|
||||
#define TCL_APPEND_VALUE 4
|
||||
@@ -1098,19 +1096,14 @@ typedef struct Tcl_DString {
|
||||
#define TCL_TRACE_DESTROYED 0x80
|
||||
#define TCL_INTERP_DESTROYED 0x100
|
||||
#define TCL_LEAVE_ERR_MSG 0x200
|
||||
/* Value 0x400 is reserved for TCL_PARSE_PART1, conditionally defined below. */
|
||||
#define TCL_TRACE_ARRAY 0x800
|
||||
#ifndef TCL_REMOVE_OBSOLETE_TRACES
|
||||
/* Required to support old variable/vdelete/vinfo traces. */
|
||||
#define TCL_TRACE_OLD_STYLE 0x1000
|
||||
#endif
|
||||
#define TCL_MATCH_REGEXP 0x2000
|
||||
/* Value 0x4000 is reserved for TCL_VAR_CREATE, defined in tclVar.c. */
|
||||
/* Indicate the semantics of the result of a trace. */
|
||||
#define TCL_TRACE_RESULT_DYNAMIC 0x8000
|
||||
#define TCL_TRACE_RESULT_OBJECT 0x10000
|
||||
#define TCL_MATCH_GLOB 0x20000
|
||||
/* Value 0x100000 is reserved for TCL_CANCEL_UNWIND, defined above. */
|
||||
|
||||
/*
|
||||
* Flag values for ensemble commands.
|
||||
@@ -1341,6 +1334,37 @@ typedef struct Tcl_HashSearch {
|
||||
#define TCL_CUSTOM_TYPE_KEYS (-2)
|
||||
#define TCL_CUSTOM_PTR_KEYS (-1)
|
||||
|
||||
/*
|
||||
* The following structure describes an enumerative search in progress on an
|
||||
* array variable; this are invoked with options to the "array" command.
|
||||
*/
|
||||
|
||||
# define TCL_ARRAYSEARCH_FOR_VALUE 0x0001
|
||||
typedef struct ArraySearch {
|
||||
Tcl_Obj *name; /* Name of this search */
|
||||
int id; /* Integer id used to distinguish among
|
||||
* multiple concurrent searches for the same
|
||||
* array. */
|
||||
struct Var *varPtr; /* Pointer to array variable that's being
|
||||
* searched. */
|
||||
Tcl_Obj *arrayNameObj; /* Name of the array variable in the current
|
||||
* resolution context. Usually NULL except for
|
||||
* in "array for". */
|
||||
int flags; /* Used by 'array for' to check if the
|
||||
* value is wanted. */
|
||||
Tcl_HashSearch search; /* Info kept by the hash module about progress
|
||||
* through the array. */
|
||||
Tcl_HashEntry *nextEntry; /* Non-null means this is the next element to
|
||||
* be enumerated (it's leftover from the
|
||||
* Tcl_FirstHashEntry call or from an "array
|
||||
* anymore" command). NULL means must call
|
||||
* Tcl_NextHashEntry to get value to
|
||||
* return. */
|
||||
struct ArraySearch *nextPtr;/* Next in list of all active searches for
|
||||
* this variable, or NULL if this is the last
|
||||
* one. */
|
||||
} Tcl_ArraySearch;
|
||||
|
||||
/*
|
||||
* Structure definition for information used to keep track of searches through
|
||||
* dictionaries. These fields should not be accessed by code outside
|
||||
@@ -2416,6 +2440,10 @@ const char * TclTomMathInitializeStubs(Tcl_Interp *interp,
|
||||
(exact)|(TCL_MAJOR_VERSION<<8)|(TCL_MINOR_VERSION<<16))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TODO - tommath stubs export goes here!
|
||||
*/
|
||||
|
||||
/*
|
||||
* Public functions that are not accessible via the stubs table.
|
||||
* Tcl_GetMemoryInfo is needed for AOLserver. [Bug 1868171]
|
||||
|
||||
+22
-22
@@ -32,7 +32,7 @@
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER) || defined(__MSVCRT__) || defined(__BORLANDC__)
|
||||
typedef size_t caddr_t;
|
||||
typedef unsigned long caddr_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -56,7 +56,7 @@ union overhead {
|
||||
unsigned char magic1; /* other magic number */
|
||||
#ifndef NDEBUG
|
||||
unsigned short rmagic; /* range magic number */
|
||||
size_t size; /* actual block size */
|
||||
unsigned long size; /* actual block size */
|
||||
unsigned short unused2; /* padding to 8-byte align */
|
||||
#endif
|
||||
} ovu;
|
||||
@@ -133,7 +133,7 @@ static int allocInit = 0;
|
||||
* a given block size.
|
||||
*/
|
||||
|
||||
static size_t numMallocs[NBUCKETS+1];
|
||||
static unsigned int numMallocs[NBUCKETS+1];
|
||||
#endif
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
@@ -148,7 +148,7 @@ static size_t numMallocs[NBUCKETS+1];
|
||||
* Prototypes for functions used only in this file.
|
||||
*/
|
||||
|
||||
static void MoreCore(size_t bucket);
|
||||
static void MoreCore(int bucket);
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
@@ -254,7 +254,7 @@ TclpAlloc(
|
||||
unsigned int numBytes) /* Number of bytes to allocate. */
|
||||
{
|
||||
register union overhead *overPtr;
|
||||
register size_t bucket;
|
||||
register long bucket;
|
||||
register unsigned amount;
|
||||
struct block *bigBlockPtr = NULL;
|
||||
|
||||
@@ -385,12 +385,12 @@ TclpAlloc(
|
||||
|
||||
static void
|
||||
MoreCore(
|
||||
size_t bucket) /* What bucket to allocate to. */
|
||||
int bucket) /* What bucket to allocat to. */
|
||||
{
|
||||
register union overhead *overPtr;
|
||||
register size_t size; /* size of desired block */
|
||||
size_t amount; /* amount to allocate */
|
||||
size_t numBlocks; /* how many blocks we get */
|
||||
register long size; /* size of desired block */
|
||||
long amount; /* amount to allocate */
|
||||
int numBlocks; /* how many blocks we get */
|
||||
struct block *blockPtr;
|
||||
|
||||
/*
|
||||
@@ -398,14 +398,14 @@ MoreCore(
|
||||
* VAX, I think) or for a negative arg.
|
||||
*/
|
||||
|
||||
size = ((size_t)1) << (bucket + 3);
|
||||
size = 1 << (bucket + 3);
|
||||
ASSERT(size > 0);
|
||||
|
||||
amount = MAXMALLOC;
|
||||
numBlocks = amount / size;
|
||||
ASSERT(numBlocks*size == amount);
|
||||
|
||||
blockPtr = (struct block *) TclpSysAlloc(
|
||||
blockPtr = (struct block *) TclpSysAlloc((unsigned)
|
||||
(sizeof(struct block) + amount), 1);
|
||||
/* no more room! */
|
||||
if (blockPtr == NULL) {
|
||||
@@ -448,7 +448,7 @@ void
|
||||
TclpFree(
|
||||
char *oldPtr) /* Pointer to memory to free. */
|
||||
{
|
||||
register size_t size;
|
||||
register long size;
|
||||
register union overhead *overPtr;
|
||||
struct block *bigBlockPtr;
|
||||
|
||||
@@ -518,7 +518,7 @@ TclpRealloc(
|
||||
union overhead *overPtr;
|
||||
struct block *bigBlockPtr;
|
||||
int expensive;
|
||||
size_t maxSize;
|
||||
unsigned long maxSize;
|
||||
|
||||
if (oldPtr == NULL) {
|
||||
return TclpAlloc(numBytes);
|
||||
@@ -645,30 +645,30 @@ void
|
||||
mstats(
|
||||
char *s) /* Where to write info. */
|
||||
{
|
||||
register unsigned int i, j;
|
||||
register int i, j;
|
||||
register union overhead *overPtr;
|
||||
size_t totalFree = 0, totalUsed = 0;
|
||||
int totalFree = 0, totalUsed = 0;
|
||||
|
||||
Tcl_MutexLock(allocMutexPtr);
|
||||
|
||||
fprintf(stderr, "Memory allocation statistics %s\nTclpFree:\t", s);
|
||||
for (i = 0; i < NBUCKETS; i++) {
|
||||
for (j=0, overPtr=nextf[i]; overPtr; overPtr=overPtr->next, j++) {
|
||||
fprintf(stderr, " %u", j);
|
||||
fprintf(stderr, " %d", j);
|
||||
}
|
||||
totalFree += ((size_t)j) * (1 << (i + 3));
|
||||
totalFree += j * (1 << (i + 3));
|
||||
}
|
||||
|
||||
fprintf(stderr, "\nused:\t");
|
||||
for (i = 0; i < NBUCKETS; i++) {
|
||||
fprintf(stderr, " %" TCL_LL_MODIFIER "d", (Tcl_WideInt)numMallocs[i]);
|
||||
fprintf(stderr, " %d", numMallocs[i]);
|
||||
totalUsed += numMallocs[i] * (1 << (i + 3));
|
||||
}
|
||||
|
||||
fprintf(stderr, "\n\tTotal small in use: %" TCL_LL_MODIFIER "d, total free: %" TCL_LL_MODIFIER "d\n",
|
||||
(Tcl_WideInt)totalUsed, (Tcl_WideInt)totalFree);
|
||||
fprintf(stderr, "\n\tNumber of big (>%d) blocks in use: %" TCL_LL_MODIFIER "d\n",
|
||||
MAXMALLOC, (Tcl_WideInt)numMallocs[NBUCKETS]);
|
||||
fprintf(stderr, "\n\tTotal small in use: %d, total free: %d\n",
|
||||
totalUsed, totalFree);
|
||||
fprintf(stderr, "\n\tNumber of big (>%d) blocks in use: %d\n",
|
||||
MAXMALLOC, numMallocs[NBUCKETS]);
|
||||
|
||||
Tcl_MutexUnlock(allocMutexPtr);
|
||||
}
|
||||
|
||||
+20
-20
@@ -1543,7 +1543,7 @@ AssembleOneLine(
|
||||
* Add the (label_name, address) pair to the hash table.
|
||||
*/
|
||||
|
||||
if (DefineLabel(assemEnvPtr, TclGetString(operand1Obj)) != TCL_OK) {
|
||||
if (DefineLabel(assemEnvPtr, Tcl_GetString(operand1Obj)) != TCL_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
@@ -1722,7 +1722,7 @@ AssembleOneLine(
|
||||
|
||||
default:
|
||||
Tcl_Panic("Instruction \"%s\" could not be found, can't happen\n",
|
||||
TclGetString(instNameObj));
|
||||
Tcl_GetString(instNameObj));
|
||||
}
|
||||
|
||||
status = TCL_OK;
|
||||
@@ -1985,15 +1985,15 @@ CreateMirrorJumpTable(
|
||||
|
||||
DEBUG_PRINT("jump table {\n");
|
||||
for (i = 0; i < objc; i+=2) {
|
||||
DEBUG_PRINT(" %s -> %s\n", TclGetString(objv[i]),
|
||||
TclGetString(objv[i+1]));
|
||||
hashEntry = Tcl_CreateHashEntry(jtHashPtr, TclGetString(objv[i]),
|
||||
DEBUG_PRINT(" %s -> %s\n", Tcl_GetString(objv[i]),
|
||||
Tcl_GetString(objv[i+1]));
|
||||
hashEntry = Tcl_CreateHashEntry(jtHashPtr, Tcl_GetString(objv[i]),
|
||||
&isNew);
|
||||
if (!isNew) {
|
||||
if (assemEnvPtr->flags & TCL_EVAL_DIRECT) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"duplicate entry in jump table for \"%s\"",
|
||||
TclGetString(objv[i])));
|
||||
Tcl_GetString(objv[i])));
|
||||
Tcl_SetErrorCode(interp, "TCL", "ASSEM", "DUPJUMPTABLEENTRY");
|
||||
DeleteMirrorJumpTable(jtPtr);
|
||||
return TCL_ERROR;
|
||||
@@ -2801,7 +2801,7 @@ CalculateJumpRelocations(
|
||||
|
||||
if (bbPtr->jumpTarget != NULL) {
|
||||
entry = Tcl_FindHashEntry(&assemEnvPtr->labelHash,
|
||||
TclGetString(bbPtr->jumpTarget));
|
||||
Tcl_GetString(bbPtr->jumpTarget));
|
||||
if (entry == NULL) {
|
||||
ReportUndefinedLabel(assemEnvPtr, bbPtr,
|
||||
bbPtr->jumpTarget);
|
||||
@@ -2882,10 +2882,10 @@ CheckJumpTableLabels(
|
||||
symEntryPtr = Tcl_NextHashEntry(&search)) {
|
||||
symbolObj = Tcl_GetHashValue(symEntryPtr);
|
||||
valEntryPtr = Tcl_FindHashEntry(&assemEnvPtr->labelHash,
|
||||
TclGetString(symbolObj));
|
||||
Tcl_GetString(symbolObj));
|
||||
DEBUG_PRINT(" %s -> %s (%d)\n",
|
||||
(char*) Tcl_GetHashKey(symHash, symEntryPtr),
|
||||
TclGetString(symbolObj), (valEntryPtr != NULL));
|
||||
Tcl_GetString(symbolObj), (valEntryPtr != NULL));
|
||||
if (valEntryPtr == NULL) {
|
||||
ReportUndefinedLabel(assemEnvPtr, bbPtr, symbolObj);
|
||||
return TCL_ERROR;
|
||||
@@ -2923,9 +2923,9 @@ ReportUndefinedLabel(
|
||||
|
||||
if (assemEnvPtr->flags & TCL_EVAL_DIRECT) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"undefined label \"%s\"", TclGetString(jumpTarget)));
|
||||
"undefined label \"%s\"", Tcl_GetString(jumpTarget)));
|
||||
Tcl_SetErrorCode(interp, "TCL", "ASSEM", "NOLABEL",
|
||||
TclGetString(jumpTarget), NULL);
|
||||
Tcl_GetString(jumpTarget), NULL);
|
||||
Tcl_SetErrorLine(interp, bbPtr->jumpLine);
|
||||
}
|
||||
}
|
||||
@@ -3008,7 +3008,7 @@ FillInJumpOffsets(
|
||||
bbPtr = bbPtr->successor1) {
|
||||
if (bbPtr->jumpTarget != NULL) {
|
||||
entry = Tcl_FindHashEntry(&assemEnvPtr->labelHash,
|
||||
TclGetString(bbPtr->jumpTarget));
|
||||
Tcl_GetString(bbPtr->jumpTarget));
|
||||
jumpTarget = Tcl_GetHashValue(entry);
|
||||
fromOffset = bbPtr->jumpOffset;
|
||||
targetOffset = jumpTarget->startOffset;
|
||||
@@ -3080,17 +3080,17 @@ ResolveJumpTableTargets(
|
||||
symEntryPtr != NULL;
|
||||
symEntryPtr = Tcl_NextHashEntry(&search)) {
|
||||
symbolObj = Tcl_GetHashValue(symEntryPtr);
|
||||
DEBUG_PRINT(" symbol %s\n", TclGetString(symbolObj));
|
||||
DEBUG_PRINT(" symbol %s\n", Tcl_GetString(symbolObj));
|
||||
|
||||
valEntryPtr = Tcl_FindHashEntry(&assemEnvPtr->labelHash,
|
||||
TclGetString(symbolObj));
|
||||
Tcl_GetString(symbolObj));
|
||||
jumpTargetBBPtr = Tcl_GetHashValue(valEntryPtr);
|
||||
|
||||
realJumpEntryPtr = Tcl_CreateHashEntry(realJumpHashPtr,
|
||||
Tcl_GetHashKey(symHash, symEntryPtr), &junk);
|
||||
DEBUG_PRINT(" %s -> %s -> bb %p (pc %d) hash entry %p\n",
|
||||
(char*) Tcl_GetHashKey(symHash, symEntryPtr),
|
||||
TclGetString(symbolObj), jumpTargetBBPtr,
|
||||
Tcl_GetString(symbolObj), jumpTargetBBPtr,
|
||||
jumpTargetBBPtr->startOffset, realJumpEntryPtr);
|
||||
|
||||
Tcl_SetHashValue(realJumpEntryPtr,
|
||||
@@ -3462,7 +3462,7 @@ StackCheckBasicBlock(
|
||||
|
||||
if (result == TCL_OK && blockPtr->jumpTarget != NULL) {
|
||||
entry = Tcl_FindHashEntry(&assemEnvPtr->labelHash,
|
||||
TclGetString(blockPtr->jumpTarget));
|
||||
Tcl_GetString(blockPtr->jumpTarget));
|
||||
jumpTarget = Tcl_GetHashValue(entry);
|
||||
result = StackCheckBasicBlock(assemEnvPtr, jumpTarget, blockPtr,
|
||||
stackDepth);
|
||||
@@ -3479,7 +3479,7 @@ StackCheckBasicBlock(
|
||||
jtEntry = Tcl_NextHashEntry(&jtSearch)) {
|
||||
targetLabel = Tcl_GetHashValue(jtEntry);
|
||||
entry = Tcl_FindHashEntry(&assemEnvPtr->labelHash,
|
||||
TclGetString(targetLabel));
|
||||
Tcl_GetString(targetLabel));
|
||||
jumpTarget = Tcl_GetHashValue(entry);
|
||||
result = StackCheckBasicBlock(assemEnvPtr, jumpTarget,
|
||||
blockPtr, stackDepth);
|
||||
@@ -3784,7 +3784,7 @@ ProcessCatchesInBasicBlock(
|
||||
}
|
||||
if (result == TCL_OK && bbPtr->jumpTarget != NULL) {
|
||||
entry = Tcl_FindHashEntry(&assemEnvPtr->labelHash,
|
||||
TclGetString(bbPtr->jumpTarget));
|
||||
Tcl_GetString(bbPtr->jumpTarget));
|
||||
jumpTarget = Tcl_GetHashValue(entry);
|
||||
result = ProcessCatchesInBasicBlock(assemEnvPtr, jumpTarget,
|
||||
jumpEnclosing, jumpState, catchDepth);
|
||||
@@ -3800,7 +3800,7 @@ ProcessCatchesInBasicBlock(
|
||||
jtEntry = Tcl_NextHashEntry(&jtSearch)) {
|
||||
targetLabel = Tcl_GetHashValue(jtEntry);
|
||||
entry = Tcl_FindHashEntry(&assemEnvPtr->labelHash,
|
||||
TclGetString(targetLabel));
|
||||
Tcl_GetString(targetLabel));
|
||||
jumpTarget = Tcl_GetHashValue(entry);
|
||||
result = ProcessCatchesInBasicBlock(assemEnvPtr, jumpTarget,
|
||||
jumpEnclosing, jumpState, catchDepth);
|
||||
@@ -4104,7 +4104,7 @@ StackFreshCatches(
|
||||
range->codeOffset = bbPtr->startOffset;
|
||||
|
||||
entryPtr = Tcl_FindHashEntry(&assemEnvPtr->labelHash,
|
||||
TclGetString(catch->jumpTarget));
|
||||
Tcl_GetString(catch->jumpTarget));
|
||||
if (entryPtr == NULL) {
|
||||
Tcl_Panic("undefined label in tclAssembly.c:"
|
||||
"BuildExceptionRanges, can't happen");
|
||||
|
||||
+2
-4
@@ -531,8 +531,7 @@ SetByteArrayFromAny(
|
||||
Tcl_Interp *interp, /* Not used. */
|
||||
Tcl_Obj *objPtr) /* The object to convert to type ByteArray. */
|
||||
{
|
||||
size_t length;
|
||||
int improper = 0;
|
||||
int length, improper = 0;
|
||||
const char *src, *srcEnd;
|
||||
unsigned char *dst;
|
||||
ByteArray *byteArrayPtr;
|
||||
@@ -545,8 +544,7 @@ SetByteArrayFromAny(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
src = TclGetString(objPtr);
|
||||
length = objPtr->length;
|
||||
src = TclGetStringFromObj(objPtr, &length);
|
||||
srcEnd = src + length;
|
||||
|
||||
byteArrayPtr = ckalloc(BYTEARRAY_SIZE(length));
|
||||
|
||||
+3
-2
@@ -92,7 +92,7 @@ static const char *const literals[] = {
|
||||
*/
|
||||
|
||||
typedef struct ClockClientData {
|
||||
size_t refCount; /* Number of live references. */
|
||||
int refCount; /* Number of live references. */
|
||||
Tcl_Obj **literals; /* Pool of object literals. */
|
||||
} ClockClientData;
|
||||
|
||||
@@ -2060,7 +2060,8 @@ ClockDeleteCmdProc(
|
||||
ClockClientData *data = clientData;
|
||||
int i;
|
||||
|
||||
if (data->refCount-- <= 1) {
|
||||
data->refCount--;
|
||||
if (data->refCount == 0) {
|
||||
for (i = 0; i < LIT__END; ++i) {
|
||||
Tcl_DecrRefCount(data->literals[i]);
|
||||
}
|
||||
|
||||
+1
-1
@@ -4157,7 +4157,7 @@ TclNRTryObjCmd(
|
||||
}
|
||||
|
||||
info[0] = objv[i]; /* type */
|
||||
TclNewLongObj(info[1], code); /* returnCode */
|
||||
TclNewIntObj(info[1], code); /* returnCode */
|
||||
if (info[2] == NULL) { /* errorCodePrefix */
|
||||
TclNewObj(info[2]);
|
||||
}
|
||||
|
||||
@@ -49,6 +49,9 @@ static int CompileEachloopCmd(Tcl_Interp *interp,
|
||||
static int CompileDictEachCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr, int collect);
|
||||
static int CompileArrayEachCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
|
||||
/*
|
||||
* The structures below define the AuxData types defined in this file.
|
||||
@@ -287,6 +290,221 @@ TclCompileArrayExistsCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
int
|
||||
TclCompileArrayForCmd(
|
||||
Tcl_Interp *interp, /* Used for looking up stuff. */
|
||||
Tcl_Parse *parsePtr, /* Points to a parse structure for the command
|
||||
* created by Tcl_ParseCommand. */
|
||||
Command *cmdPtr, /* Points to defintion of command being
|
||||
* compiled. */
|
||||
CompileEnv *envPtr) /* Holds resulting instructions. */
|
||||
{
|
||||
return CompileArrayEachCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
int
|
||||
CompileArrayEachCmd(
|
||||
Tcl_Interp *interp, /* Used for looking up stuff. */
|
||||
Tcl_Parse *parsePtr, /* Points to a parse structure for the command
|
||||
* created by Tcl_ParseCommand. */
|
||||
Command *cmdPtr, /* Points to defintion of command being
|
||||
* compiled. */
|
||||
CompileEnv *envPtr /* Holds resulting instructions. */
|
||||
)
|
||||
{
|
||||
DefineLineInformation;
|
||||
Tcl_Token *varsTokenPtr, *arrayTokenPtr, *bodyTokenPtr;
|
||||
int keyVarIndex, valueVarIndex, nameChars, loopRange, catchRange;
|
||||
int infoIndex, jumpDisplacement, bodyTargetOffset, emptyTargetOffset;
|
||||
int numVars, endTargetOffset;
|
||||
const char **argv;
|
||||
Tcl_DString buffer;
|
||||
|
||||
/*
|
||||
* There must be three arguments after the command.
|
||||
*/
|
||||
|
||||
if (parsePtr->numWords != 4) {
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
varsTokenPtr = TokenAfter(parsePtr->tokenPtr);
|
||||
arrayTokenPtr = TokenAfter(varsTokenPtr);
|
||||
bodyTokenPtr = TokenAfter(arrayTokenPtr);
|
||||
if (varsTokenPtr->type != TCL_TOKEN_SIMPLE_WORD ||
|
||||
arrayTokenPtr->type != TCL_TOKEN_SIMPLE_WORD ||
|
||||
bodyTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check we've got one or two variables and that they are local variables.
|
||||
* Then extract their indices in the LVT.
|
||||
*/
|
||||
|
||||
Tcl_DStringInit(&buffer);
|
||||
TclDStringAppendToken(&buffer, &varsTokenPtr[1]);
|
||||
if (Tcl_SplitList(NULL, Tcl_DStringValue(&buffer), &numVars,
|
||||
&argv) != TCL_OK) {
|
||||
Tcl_DStringFree(&buffer);
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
Tcl_DStringFree(&buffer);
|
||||
/*
|
||||
* both
|
||||
* array for {k} a {}
|
||||
* array for {k v} a {}
|
||||
* are supported.
|
||||
*/
|
||||
if (numVars != 1 && numVars != 2) {
|
||||
ckfree(argv);
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
nameChars = strlen(argv[0]);
|
||||
keyVarIndex = LocalScalar(argv[0], nameChars, envPtr);
|
||||
valueVarIndex = -1;
|
||||
if (numVars == 2) {
|
||||
nameChars = strlen(argv[1]);
|
||||
valueVarIndex = LocalScalar(argv[1], nameChars, envPtr);
|
||||
}
|
||||
ckfree(argv);
|
||||
|
||||
if ((keyVarIndex < 0) || (numVars == 2 && valueVarIndex < 0)) {
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a temporary variable to store the iterator reference. The
|
||||
* variable will contain a Tcl_ArraySearch reference which will be
|
||||
* allocated by INST_ARRAY_FIRST and disposed when the variable is unset
|
||||
* (at which point it should also have been finished with).
|
||||
*/
|
||||
|
||||
infoIndex = AnonymousLocal(envPtr);
|
||||
if (infoIndex < 0) {
|
||||
return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Preparation complete; issue instructions. Note that this code issues
|
||||
* fixed-sized jumps. That simplifies things a lot!
|
||||
*/
|
||||
|
||||
/*
|
||||
* Get the array and start the iteration. No catching of errors at
|
||||
* this point.
|
||||
*/
|
||||
|
||||
CompileWord(envPtr, arrayTokenPtr, interp, 2);
|
||||
|
||||
/*
|
||||
* Now we catch errors from here on
|
||||
*/
|
||||
|
||||
TclEmitInstInt4( INST_ARRAY_FIRST, infoIndex, envPtr);
|
||||
|
||||
catchRange = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr);
|
||||
TclEmitInstInt4( INST_BEGIN_CATCH4, catchRange, envPtr);
|
||||
ExceptionRangeStarts(envPtr, catchRange);
|
||||
|
||||
/*
|
||||
* Set up the loop exception targets.
|
||||
*/
|
||||
|
||||
loopRange = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr);
|
||||
ExceptionRangeStarts(envPtr, loopRange);
|
||||
|
||||
/*
|
||||
* Inside the iteration, fetch and write the loop variables.
|
||||
*/
|
||||
|
||||
bodyTargetOffset = CurrentOffset(envPtr);
|
||||
|
||||
TclEmitInstInt4( INST_ARRAY_NEXT, infoIndex, envPtr);
|
||||
emptyTargetOffset = CurrentOffset(envPtr);
|
||||
|
||||
Emit14Inst( INST_STORE_SCALAR, keyVarIndex, envPtr);
|
||||
TclEmitOpcode( INST_POP, envPtr);
|
||||
if (valueVarIndex != -1) {
|
||||
Emit14Inst( INST_STORE_SCALAR, valueVarIndex, envPtr);
|
||||
}
|
||||
TclEmitOpcode( INST_POP, envPtr);
|
||||
|
||||
/*
|
||||
* Compile the loop body itself. It should be stack-neutral.
|
||||
*/
|
||||
|
||||
BODY(bodyTokenPtr, 3);
|
||||
TclEmitOpcode( INST_POP, envPtr);
|
||||
|
||||
/*
|
||||
* Both exception target ranges (error and loop) end here.
|
||||
*/
|
||||
|
||||
ExceptionRangeEnds(envPtr, loopRange);
|
||||
ExceptionRangeEnds(envPtr, catchRange);
|
||||
|
||||
/*
|
||||
* Continue (or just normally process) by getting the next pair of items
|
||||
* from the dictionary and jumping back to the code to write them into
|
||||
* variables if there is another pair.
|
||||
*/
|
||||
|
||||
TclAdjustStackDepth(-1, envPtr);
|
||||
ExceptionRangeTarget(envPtr, loopRange, continueOffset);
|
||||
TclEmitInstInt4( INST_ARRAY_NEXT, infoIndex, envPtr);
|
||||
jumpDisplacement = bodyTargetOffset - CurrentOffset(envPtr);
|
||||
/*
|
||||
* checks the 'done' boolean on the stack and if false,
|
||||
* goes back to the top of the loop
|
||||
*/
|
||||
TclEmitInstInt4( INST_JUMP_FALSE4, jumpDisplacement, envPtr);
|
||||
endTargetOffset = CurrentOffset(envPtr);
|
||||
TclEmitInstInt1( INST_JUMP1, 0, envPtr);
|
||||
|
||||
/*
|
||||
* Error handler "finally" clause, which force-terminates the iteration
|
||||
* and rethrows the error.
|
||||
*/
|
||||
|
||||
ExceptionRangeTarget(envPtr, catchRange, catchOffset);
|
||||
TclEmitOpcode( INST_END_CATCH, envPtr);
|
||||
TclEmitInstInt1( INST_UNSET_SCALAR, 0, envPtr);
|
||||
TclEmitInt4( infoIndex, envPtr);
|
||||
TclEmitOpcode( INST_RETURN_STK, envPtr);
|
||||
|
||||
/*
|
||||
* Otherwise we're done and we
|
||||
* need to pop the bogus key/value pair (pushed to keep stack calculations
|
||||
* easy!) Note that we skip the END_CATCH. [Bug 1382528]
|
||||
*/
|
||||
|
||||
jumpDisplacement = CurrentOffset(envPtr) - emptyTargetOffset;
|
||||
TclUpdateInstInt4AtPc(INST_JUMP_TRUE4, jumpDisplacement,
|
||||
envPtr->codeStart + emptyTargetOffset);
|
||||
jumpDisplacement = CurrentOffset(envPtr) - endTargetOffset;
|
||||
TclUpdateInstInt1AtPc(INST_JUMP1, jumpDisplacement,
|
||||
envPtr->codeStart + endTargetOffset);
|
||||
TclEmitOpcode( INST_POP, envPtr);
|
||||
TclEmitOpcode( INST_POP, envPtr);
|
||||
ExceptionRangeTarget(envPtr, loopRange, breakOffset);
|
||||
TclFinalizeLoopExceptionRange(envPtr, loopRange);
|
||||
TclEmitOpcode( INST_END_CATCH, envPtr);
|
||||
|
||||
/*
|
||||
* Final stage of the command (normal case) is that we push an empty
|
||||
* object (or push the accumulator as the result object). This is done
|
||||
* last to promote peephole optimization when it's dropped immediately.
|
||||
*/
|
||||
|
||||
TclEmitInstInt1( INST_UNSET_SCALAR, 0, envPtr);
|
||||
TclEmitInt4( infoIndex, envPtr);
|
||||
PushStringLiteral(envPtr, "");
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
TclCompileArraySetCmd(
|
||||
Tcl_Interp *interp, /* Used for looking up stuff. */
|
||||
|
||||
@@ -522,7 +522,6 @@ InstructionDesc const tclInstructionTable[] = {
|
||||
{"arrayMakeImm", 5, 0, 1, {OPERAND_LVT4}},
|
||||
/* Forces the variable indexed by opnd to be an array. Does not touch
|
||||
* the stack. */
|
||||
|
||||
{"invokeReplace", 6, INT_MIN, 2, {OPERAND_UINT4,OPERAND_UINT1}},
|
||||
/* Invoke command named objv[0], replacing the first two words with
|
||||
* the word at the top of the stack;
|
||||
@@ -653,7 +652,11 @@ InstructionDesc const tclInstructionTable[] = {
|
||||
{"lappendListStk", 1, -1, 0, {OPERAND_NONE}},
|
||||
/* Lappend list to general variable.
|
||||
* Stack: ... varName list => ... listVarContents */
|
||||
|
||||
{"arrayFirst", 5, 0, 1, {OPERAND_LVT4}},
|
||||
/* Set up iteration over the array
|
||||
* no stack effect */
|
||||
{"arrayNext", 5, +3, 1, {OPERAND_LVT4}},
|
||||
/* Stack: key value done */
|
||||
{NULL, 0, 0, 0, {OPERAND_NONE}}
|
||||
};
|
||||
|
||||
@@ -765,8 +768,7 @@ TclSetByteCodeFromAny(
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
CompileEnv compEnv; /* Compilation environment structure allocated
|
||||
* in frame. */
|
||||
size_t length;
|
||||
int result = TCL_OK;
|
||||
int length, result = TCL_OK;
|
||||
const char *stringPtr;
|
||||
Proc *procPtr = iPtr->compiledProcPtr;
|
||||
ContLineLoc *clLocPtr;
|
||||
@@ -781,8 +783,7 @@ TclSetByteCodeFromAny(
|
||||
}
|
||||
#endif
|
||||
|
||||
stringPtr = TclGetString(objPtr);
|
||||
length = objPtr->length;
|
||||
stringPtr = TclGetStringFromObj(objPtr, &length);
|
||||
|
||||
/*
|
||||
* TIP #280: Pick up the CmdFrame in which the BC compiler was invoked and
|
||||
@@ -2978,8 +2979,7 @@ TclFindCompiledLocal(
|
||||
varNamePtr = &cachePtr->varName0;
|
||||
for (i=0; i < cachePtr->numVars; varNamePtr++, i++) {
|
||||
if (*varNamePtr) {
|
||||
localName = TclGetString(*varNamePtr);
|
||||
len = (*varNamePtr)->length;
|
||||
localName = TclGetStringFromObj(*varNamePtr, &len);
|
||||
if ((len == nameBytes) && !strncmp(name, localName, len)) {
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -821,8 +821,11 @@ typedef struct ByteCode {
|
||||
#define INST_LAPPEND_LIST_ARRAY_STK 187
|
||||
#define INST_LAPPEND_LIST_STK 188
|
||||
|
||||
#define INST_ARRAY_FIRST 189
|
||||
#define INST_ARRAY_NEXT 190
|
||||
|
||||
/* The last opcode */
|
||||
#define LAST_INST_OPCODE 188
|
||||
#define LAST_INST_OPCODE 190
|
||||
|
||||
/*
|
||||
* Table describing the Tcl bytecode instructions: their name (for displaying
|
||||
@@ -1241,7 +1244,7 @@ MODULE_SCOPE int TclPushProcCallFrame(ClientData clientData,
|
||||
int dd = (depth); \
|
||||
if (dd != (envPtr)->currStackDepth) { \
|
||||
Tcl_Panic("bad stack depth computations: is %i, should be %i", \
|
||||
(envPtr)->currStackDepth, dd); \
|
||||
(envPtr)->currStackDepth, dd); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
+15
-71
@@ -1816,46 +1816,15 @@ EXTERN int Tcl_FSUnloadFile(Tcl_Interp *interp,
|
||||
EXTERN void Tcl_ZlibStreamSetCompressionDictionary(
|
||||
Tcl_ZlibStream zhandle,
|
||||
Tcl_Obj *compressionDictionaryObj);
|
||||
/* 631 */
|
||||
EXTERN int Tcl_ArraySet(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
|
||||
Tcl_Obj *dictPtr, int flags);
|
||||
/* Slot 631 is reserved */
|
||||
/* 632 */
|
||||
EXTERN int Tcl_ArrayUnset(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
|
||||
Tcl_Obj *part2Ptr, int flags);
|
||||
EXTERN void Tcl_ArrayObjFirst(Tcl_Interp *interp,
|
||||
Tcl_Obj *arrayObj,
|
||||
Tcl_ArraySearch *searchPtr);
|
||||
/* 633 */
|
||||
EXTERN int Tcl_ArrayGet(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
|
||||
Tcl_Obj *part2Ptr, Tcl_Obj *dictPtr,
|
||||
int flags);
|
||||
/* 634 */
|
||||
EXTERN int Tcl_ArrayNames(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
|
||||
Tcl_Obj *part2Ptr, Tcl_Obj *listPtr,
|
||||
int flags);
|
||||
/* 635 */
|
||||
EXTERN int Tcl_ArraySize(Tcl_Interp *interp, Tcl_Obj *part1Ptr,
|
||||
Tcl_Obj *part2Ptr, int *intPtr, int flags);
|
||||
/* 636 */
|
||||
EXTERN int Tcl_ArrayExists(Tcl_Interp *interp,
|
||||
Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr,
|
||||
int *intPtr, int flags);
|
||||
/* 637 */
|
||||
EXTERN Tcl_ArraySearch Tcl_ArraySearchStart(Tcl_Interp *interp,
|
||||
Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr,
|
||||
int flags);
|
||||
/* 638 */
|
||||
EXTERN int Tcl_ArraySearchPeek(Tcl_Interp *interp,
|
||||
Tcl_ArraySearch search, Tcl_Obj **keyPtrPtr,
|
||||
Tcl_Obj **valuePtrPtr);
|
||||
/* 639 */
|
||||
EXTERN int Tcl_ArraySearchNext(Tcl_Interp *interp,
|
||||
Tcl_ArraySearch search, Tcl_Obj **keyPtrPtr,
|
||||
Tcl_Obj **valuePtrPtr);
|
||||
/* 640 */
|
||||
EXTERN int Tcl_ArraySearchDone(Tcl_Interp *interp,
|
||||
Tcl_ArraySearch search);
|
||||
/* 641 */
|
||||
EXTERN int Tcl_ArrayStatistics(Tcl_Interp *interp,
|
||||
Tcl_Obj *part1Ptr, Tcl_Obj *stringPtr,
|
||||
int flags);
|
||||
EXTERN int Tcl_ArrayObjNext(Tcl_Interp *interp,
|
||||
Tcl_ArraySearch *searchPtr,
|
||||
Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr);
|
||||
|
||||
typedef struct {
|
||||
const struct TclPlatStubs *tclPlatStubs;
|
||||
@@ -2522,17 +2491,9 @@ typedef struct TclStubs {
|
||||
void * (*tcl_FindSymbol) (Tcl_Interp *interp, Tcl_LoadHandle handle, const char *symbol); /* 628 */
|
||||
int (*tcl_FSUnloadFile) (Tcl_Interp *interp, Tcl_LoadHandle handlePtr); /* 629 */
|
||||
void (*tcl_ZlibStreamSetCompressionDictionary) (Tcl_ZlibStream zhandle, Tcl_Obj *compressionDictionaryObj); /* 630 */
|
||||
int (*tcl_ArraySet) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *dictPtr, int flags); /* 631 */
|
||||
int (*tcl_ArrayUnset) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags); /* 632 */
|
||||
int (*tcl_ArrayGet) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *dictPtr, int flags); /* 633 */
|
||||
int (*tcl_ArrayNames) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, Tcl_Obj *listPtr, int flags); /* 634 */
|
||||
int (*tcl_ArraySize) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int *intPtr, int flags); /* 635 */
|
||||
int (*tcl_ArrayExists) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int *intPtr, int flags); /* 636 */
|
||||
Tcl_ArraySearch (*tcl_ArraySearchStart) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, int flags); /* 637 */
|
||||
int (*tcl_ArraySearchPeek) (Tcl_Interp *interp, Tcl_ArraySearch search, Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr); /* 638 */
|
||||
int (*tcl_ArraySearchNext) (Tcl_Interp *interp, Tcl_ArraySearch search, Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr); /* 639 */
|
||||
int (*tcl_ArraySearchDone) (Tcl_Interp *interp, Tcl_ArraySearch search); /* 640 */
|
||||
int (*tcl_ArrayStatistics) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *stringPtr, int flags); /* 641 */
|
||||
void (*reserved631)(void);
|
||||
void (*tcl_ArrayObjFirst) (Tcl_Interp *interp, Tcl_Obj *arrayObj, Tcl_ArraySearch *searchPtr); /* 632 */
|
||||
int (*tcl_ArrayObjNext) (Tcl_Interp *interp, Tcl_ArraySearch *searchPtr, Tcl_Obj **keyPtrPtr, Tcl_Obj **valuePtrPtr); /* 633 */
|
||||
} TclStubs;
|
||||
|
||||
extern const TclStubs *tclStubsPtr;
|
||||
@@ -3825,28 +3786,11 @@ extern const TclStubs *tclStubsPtr;
|
||||
(tclStubsPtr->tcl_FSUnloadFile) /* 629 */
|
||||
#define Tcl_ZlibStreamSetCompressionDictionary \
|
||||
(tclStubsPtr->tcl_ZlibStreamSetCompressionDictionary) /* 630 */
|
||||
#define Tcl_ArraySet \
|
||||
(tclStubsPtr->tcl_ArraySet) /* 631 */
|
||||
#define Tcl_ArrayUnset \
|
||||
(tclStubsPtr->tcl_ArrayUnset) /* 632 */
|
||||
#define Tcl_ArrayGet \
|
||||
(tclStubsPtr->tcl_ArrayGet) /* 633 */
|
||||
#define Tcl_ArrayNames \
|
||||
(tclStubsPtr->tcl_ArrayNames) /* 634 */
|
||||
#define Tcl_ArraySize \
|
||||
(tclStubsPtr->tcl_ArraySize) /* 635 */
|
||||
#define Tcl_ArrayExists \
|
||||
(tclStubsPtr->tcl_ArrayExists) /* 636 */
|
||||
#define Tcl_ArraySearchStart \
|
||||
(tclStubsPtr->tcl_ArraySearchStart) /* 637 */
|
||||
#define Tcl_ArraySearchPeek \
|
||||
(tclStubsPtr->tcl_ArraySearchPeek) /* 638 */
|
||||
#define Tcl_ArraySearchNext \
|
||||
(tclStubsPtr->tcl_ArraySearchNext) /* 639 */
|
||||
#define Tcl_ArraySearchDone \
|
||||
(tclStubsPtr->tcl_ArraySearchDone) /* 640 */
|
||||
#define Tcl_ArrayStatistics \
|
||||
(tclStubsPtr->tcl_ArrayStatistics) /* 641 */
|
||||
/* Slot 631 is reserved */
|
||||
#define Tcl_ArrayObjFirst \
|
||||
(tclStubsPtr->tcl_ArrayObjFirst) /* 632 */
|
||||
#define Tcl_ArrayObjNext \
|
||||
(tclStubsPtr->tcl_ArrayObjNext) /* 633 */
|
||||
|
||||
#endif /* defined(USE_TCL_STUBS) */
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ typedef struct Encoding {
|
||||
* nullSize is 2, this is a function that
|
||||
* returns the number of bytes in a 0x0000
|
||||
* terminated string. */
|
||||
size_t refCount; /* Number of uses of this structure. */
|
||||
int refCount; /* Number of uses of this structure. */
|
||||
Tcl_HashEntry *hPtr; /* Hash table entry that owns this encoding. */
|
||||
} Encoding;
|
||||
|
||||
@@ -844,7 +844,11 @@ FreeEncoding(
|
||||
if (encodingPtr == NULL) {
|
||||
return;
|
||||
}
|
||||
if (encodingPtr->refCount-- <= 1) {
|
||||
if (encodingPtr->refCount<=0) {
|
||||
Tcl_Panic("FreeEncoding: refcount problem !!!");
|
||||
}
|
||||
encodingPtr->refCount--;
|
||||
if (encodingPtr->refCount == 0) {
|
||||
if (encodingPtr->freeProc != NULL) {
|
||||
encodingPtr->freeProc(encodingPtr->clientData);
|
||||
}
|
||||
|
||||
@@ -3306,7 +3306,7 @@ CompileToInvokedCommand(
|
||||
Tcl_Token *tokPtr;
|
||||
Tcl_Obj *objPtr, **words;
|
||||
char *bytes;
|
||||
int i, numWords, cmdLit, extraLiteralFlags = LITERAL_CMD_NAME;
|
||||
int length, i, numWords, cmdLit, extraLiteralFlags = LITERAL_CMD_NAME;
|
||||
DefineLineInformation;
|
||||
|
||||
/*
|
||||
@@ -3319,8 +3319,8 @@ CompileToInvokedCommand(
|
||||
for (i = 0, tokPtr = parsePtr->tokenPtr; i < parsePtr->numWords;
|
||||
i++, tokPtr = TokenAfter(tokPtr)) {
|
||||
if (i > 0 && i < numWords+1) {
|
||||
bytes = TclGetString(words[i-1]);
|
||||
PushLiteral(envPtr, bytes, words[i-1]->length);
|
||||
bytes = TclGetStringFromObj(words[i-1], &length);
|
||||
PushLiteral(envPtr, bytes, length);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -3348,11 +3348,11 @@ CompileToInvokedCommand(
|
||||
|
||||
objPtr = Tcl_NewObj();
|
||||
Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr, objPtr);
|
||||
bytes = TclGetString(objPtr);
|
||||
bytes = Tcl_GetStringFromObj(objPtr, &length);
|
||||
if ((cmdPtr != NULL) && (cmdPtr->flags & CMD_VIA_RESOLVER)) {
|
||||
extraLiteralFlags |= LITERAL_UNSHARED;
|
||||
}
|
||||
cmdLit = TclRegisterLiteral(envPtr, bytes, objPtr->length, extraLiteralFlags);
|
||||
cmdLit = TclRegisterLiteral(envPtr, bytes, length, extraLiteralFlags);
|
||||
TclSetCmdNameObj(interp, TclFetchLiteral(envPtr, cmdLit), cmdPtr);
|
||||
TclEmitPush(cmdLit, envPtr);
|
||||
TclDecrRefCount(objPtr);
|
||||
|
||||
+118
-19
@@ -325,7 +325,7 @@ VarHashCreateVar(
|
||||
NEXT_INST_F(((condition)? TclGetInt4AtPtr(pc+1) : 5), (cleanup), 0); \
|
||||
default: \
|
||||
if ((condition) < 0) { \
|
||||
TclNewLongObj(objResultPtr, -1); \
|
||||
TclNewIntObj(objResultPtr, -1); \
|
||||
} else { \
|
||||
objResultPtr = TCONST((condition) > 0); \
|
||||
} \
|
||||
@@ -346,7 +346,7 @@ VarHashCreateVar(
|
||||
NEXT_INST_V(((condition)? TclGetInt4AtPtr(pc+1) : 5), (cleanup), 0); \
|
||||
default: \
|
||||
if ((condition) < 0) { \
|
||||
TclNewLongObj(objResultPtr, -1); \
|
||||
TclNewIntObj(objResultPtr, -1); \
|
||||
} else { \
|
||||
objResultPtr = TCONST((condition) > 0); \
|
||||
} \
|
||||
@@ -357,7 +357,7 @@ VarHashCreateVar(
|
||||
#define JUMP_PEEPHOLE_F(condition, pcAdjustment, cleanup) \
|
||||
do{ \
|
||||
if ((condition) < 0) { \
|
||||
TclNewLongObj(objResultPtr, -1); \
|
||||
TclNewIntObj(objResultPtr, -1); \
|
||||
} else { \
|
||||
objResultPtr = TCONST((condition) > 0); \
|
||||
} \
|
||||
@@ -366,7 +366,7 @@ VarHashCreateVar(
|
||||
#define JUMP_PEEPHOLE_V(condition, pcAdjustment, cleanup) \
|
||||
do{ \
|
||||
if ((condition) < 0) { \
|
||||
TclNewLongObj(objResultPtr, -1); \
|
||||
TclNewIntObj(objResultPtr, -1); \
|
||||
} else { \
|
||||
objResultPtr = TCONST((condition) > 0); \
|
||||
} \
|
||||
@@ -766,6 +766,7 @@ static void IllegalExprOperandType(Tcl_Interp *interp,
|
||||
static void InitByteCodeExecution(Tcl_Interp *interp);
|
||||
static inline int wordSkip(void *ptr);
|
||||
static void ReleaseDictIterator(Tcl_Obj *objPtr);
|
||||
static void ReleaseArrayIterator(Tcl_Obj *objPtr);
|
||||
/* Useful elsewhere, make available in tclInt.h or stubs? */
|
||||
static Tcl_Obj ** StackAllocWords(Tcl_Interp *interp, int numWords);
|
||||
static Tcl_Obj ** StackReallocWords(Tcl_Interp *interp, int numWords);
|
||||
@@ -798,6 +799,11 @@ static const Tcl_ObjType dictIteratorType = {
|
||||
ReleaseDictIterator,
|
||||
NULL, NULL, NULL
|
||||
};
|
||||
static const Tcl_ObjType arrayIteratorType = {
|
||||
"arrayIterator",
|
||||
ReleaseArrayIterator,
|
||||
NULL, NULL, NULL
|
||||
};
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -837,6 +843,45 @@ ReleaseDictIterator(
|
||||
|
||||
objPtr->typePtr = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* ReleaseArrayIterator --
|
||||
*
|
||||
* This takes apart an array iterator that is stored in the given Tcl
|
||||
* object.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Deallocates memory, marks the object as being untyped.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
ReleaseArrayIterator(
|
||||
Tcl_Obj *objPtr)
|
||||
{
|
||||
Tcl_ArraySearch *searchPtr;
|
||||
Tcl_Obj *arrayPtr;
|
||||
|
||||
/*
|
||||
* First kill the search, and then release the reference to the dictionary
|
||||
* that we were holding.
|
||||
*/
|
||||
|
||||
searchPtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
ckfree(searchPtr);
|
||||
|
||||
arrayPtr = objPtr->internalRep.twoPtrValue.ptr2;
|
||||
TclDecrRefCount(arrayPtr);
|
||||
|
||||
objPtr->typePtr = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -1541,10 +1586,11 @@ CompileExprObj(
|
||||
* TIP #280: No invoker (yet) - Expression compilation.
|
||||
*/
|
||||
|
||||
const char *string = TclGetString(objPtr);
|
||||
int length;
|
||||
const char *string = TclGetStringFromObj(objPtr, &length);
|
||||
|
||||
TclInitCompileEnv(interp, &compEnv, string, objPtr->length, NULL, 0);
|
||||
TclCompileExpr(interp, string, objPtr->length, &compEnv, 0);
|
||||
TclInitCompileEnv(interp, &compEnv, string, length, NULL, 0);
|
||||
TclCompileExpr(interp, string, length, &compEnv, 0);
|
||||
|
||||
/*
|
||||
* Successful compilation. If the expression yielded no instructions,
|
||||
@@ -4034,13 +4080,12 @@ TEBCresume(
|
||||
}
|
||||
TRACE(("%s %u \"%.30s\" => ",
|
||||
(flags ? "normal" : "noerr"), opnd, O2S(part2Ptr)));
|
||||
if (TclIsVarArray(arrayPtr) && !UnsetTraced(arrayPtr)
|
||||
&& !TclIsVarArraySearched(arrayPtr)) {
|
||||
if (TclIsVarArray(arrayPtr) && !UnsetTraced(arrayPtr)) {
|
||||
varPtr = VarHashFindVar(arrayPtr->value.tablePtr, part2Ptr);
|
||||
if (varPtr && TclIsVarDirectUnsettable(varPtr)) {
|
||||
/*
|
||||
* No nasty traces or searchesw and element exists, so we can
|
||||
* proceed to unset it. Might still not exist though...
|
||||
* No nasty traces and element exists, so we can proceed to
|
||||
* unset it. Might still not exist though...
|
||||
*/
|
||||
|
||||
if (!TclIsVarUndefined(varPtr)) {
|
||||
@@ -4180,6 +4225,60 @@ TEBCresume(
|
||||
TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
|
||||
NEXT_INST_V(pcAdjustment, cleanup, 1);
|
||||
|
||||
{
|
||||
int done;
|
||||
Tcl_Obj *arrayObj, *statePtr, *keyPtr, *valuePtr;
|
||||
Tcl_Obj *emptyPtr;
|
||||
Tcl_ArraySearch *searchPtr;
|
||||
|
||||
case INST_ARRAY_FIRST:
|
||||
pcAdjustment = 1;
|
||||
opnd = TclGetUInt4AtPtr(pc+1);
|
||||
TRACE(("%u => ", opnd));
|
||||
arrayObj = POP_OBJECT();
|
||||
searchPtr = ckalloc(sizeof(Tcl_ArraySearch));
|
||||
Tcl_ArrayObjFirst(interp, arrayObj, searchPtr);
|
||||
TclNewObj(statePtr);
|
||||
statePtr->typePtr = &arrayIteratorType;
|
||||
statePtr->internalRep.twoPtrValue.ptr1 = searchPtr;
|
||||
statePtr->internalRep.twoPtrValue.ptr2 = arrayObj;
|
||||
varPtr = LOCAL(opnd);
|
||||
if (varPtr->value.objPtr) {
|
||||
if (varPtr->value.objPtr->typePtr == &arrayIteratorType) {
|
||||
Tcl_Panic("mis-issued arrayFirst!");
|
||||
}
|
||||
TclDecrRefCount(varPtr->value.objPtr);
|
||||
}
|
||||
varPtr->value.objPtr = statePtr;
|
||||
Tcl_IncrRefCount(statePtr);
|
||||
NEXT_INST_F(1, 0, 0); /*### ??? */
|
||||
|
||||
case INST_ARRAY_NEXT:
|
||||
opnd = TclGetUInt4AtPtr(pc+1);
|
||||
TRACE(("%u => ", opnd));
|
||||
statePtr = (*LOCAL(opnd)).value.objPtr;
|
||||
if (statePtr == NULL || statePtr->typePtr != &arrayIteratorType) {
|
||||
Tcl_Panic("mis-issued dictNext!");
|
||||
}
|
||||
searchPtr = statePtr->internalRep.twoPtrValue.ptr1;
|
||||
done = Tcl_ArrayObjNext(interp, searchPtr, &keyPtr, &valuePtr);
|
||||
if (done) {
|
||||
TclNewObj(emptyPtr);
|
||||
PUSH_OBJECT(emptyPtr);
|
||||
PUSH_OBJECT(emptyPtr);
|
||||
} else {
|
||||
if (valuePtr != NULL) {
|
||||
PUSH_OBJECT(valuePtr);
|
||||
} else {
|
||||
PUSH_OBJECT(emptyPtr);
|
||||
}
|
||||
PUSH_OBJECT(keyPtr);
|
||||
}
|
||||
TRACE_APPEND(("\"%.30s\" \"%.30s\" %d\n",
|
||||
O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), done));
|
||||
JUMP_PEEPHOLE_F(done, 5, 0); /* ### ??? */
|
||||
}
|
||||
|
||||
case INST_ARRAY_MAKE_IMM:
|
||||
opnd = TclGetUInt4AtPtr(pc+1);
|
||||
pcAdjustment = 5;
|
||||
@@ -4529,7 +4628,7 @@ TEBCresume(
|
||||
NEXT_INST_F(1, 0, 1);
|
||||
}
|
||||
case INST_INFO_LEVEL_NUM:
|
||||
TclNewLongObj(objResultPtr, iPtr->varFramePtr->level);
|
||||
TclNewIntObj(objResultPtr, iPtr->varFramePtr->level);
|
||||
TRACE_WITH_OBJ(("=> "), objResultPtr);
|
||||
NEXT_INST_F(1, 0, 1);
|
||||
case INST_INFO_LEVEL_ARGS: {
|
||||
@@ -4898,7 +4997,7 @@ TEBCresume(
|
||||
TRACE_ERROR(interp);
|
||||
goto gotError;
|
||||
}
|
||||
TclNewLongObj(objResultPtr, length);
|
||||
TclNewIntObj(objResultPtr, length);
|
||||
TRACE_APPEND(("%d\n", length));
|
||||
NEXT_INST_F(1, 1, 1);
|
||||
|
||||
@@ -5369,7 +5468,7 @@ TEBCresume(
|
||||
case INST_STR_LEN:
|
||||
valuePtr = OBJ_AT_TOS;
|
||||
length = Tcl_GetCharLength(valuePtr);
|
||||
TclNewLongObj(objResultPtr, length);
|
||||
TclNewIntObj(objResultPtr, length);
|
||||
TRACE(("\"%.20s\" => %d\n", O2S(valuePtr), length));
|
||||
NEXT_INST_F(1, 1, 1);
|
||||
|
||||
@@ -5724,7 +5823,7 @@ TEBCresume(
|
||||
|
||||
TRACE(("%.20s %.20s => %d\n",
|
||||
O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), match));
|
||||
TclNewLongObj(objResultPtr, match);
|
||||
TclNewIntObj(objResultPtr, match);
|
||||
NEXT_INST_F(1, 2, 1);
|
||||
|
||||
case INST_STR_FIND_LAST:
|
||||
@@ -5732,7 +5831,7 @@ TEBCresume(
|
||||
|
||||
TRACE(("%.20s %.20s => %d\n",
|
||||
O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), match));
|
||||
TclNewLongObj(objResultPtr, match);
|
||||
TclNewIntObj(objResultPtr, match);
|
||||
NEXT_INST_F(1, 2, 1);
|
||||
|
||||
case INST_STR_CLASS:
|
||||
@@ -5936,7 +6035,7 @@ TEBCresume(
|
||||
type1 = TCL_NUMBER_WIDE;
|
||||
}
|
||||
}
|
||||
TclNewLongObj(objResultPtr, type1);
|
||||
TclNewIntObj(objResultPtr, type1);
|
||||
TRACE(("\"%.20s\" => %d\n", O2S(OBJ_AT_TOS), type1));
|
||||
NEXT_INST_F(1, 1, 1);
|
||||
|
||||
@@ -6143,7 +6242,7 @@ TEBCresume(
|
||||
if (l1 > 0L) {
|
||||
objResultPtr = TCONST(0);
|
||||
} else {
|
||||
TclNewLongObj(objResultPtr, -1);
|
||||
TclNewIntObj(objResultPtr, -1);
|
||||
}
|
||||
TRACE(("%s\n", O2S(objResultPtr)));
|
||||
NEXT_INST_F(1, 2, 1);
|
||||
@@ -7043,7 +7142,7 @@ TEBCresume(
|
||||
NEXT_INST_F(1, 0, -1);
|
||||
|
||||
case INST_PUSH_RETURN_CODE:
|
||||
TclNewLongObj(objResultPtr, result);
|
||||
TclNewIntObj(objResultPtr, result);
|
||||
TRACE(("=> %u\n", result));
|
||||
NEXT_INST_F(1, 0, 1);
|
||||
|
||||
|
||||
+2
-2
@@ -323,7 +323,7 @@ typedef struct ResolvedChanName {
|
||||
Tcl_Interp *interp; /* The interp in which the lookup was done. */
|
||||
int epoch; /* The epoch of the channel when the lookup
|
||||
* was done. Use to verify validity. */
|
||||
size_t refCount; /* Share this struct among many Tcl_Obj. */
|
||||
int refCount; /* Share this struct among many Tcl_Obj. */
|
||||
} ResolvedChanName;
|
||||
|
||||
static void DupChannelIntRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr);
|
||||
@@ -11194,7 +11194,7 @@ FreeChannelIntRep(
|
||||
ResolvedChanName *resPtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
objPtr->typePtr = NULL;
|
||||
if (resPtr->refCount-- > 1) {
|
||||
if (--resPtr->refCount) {
|
||||
return;
|
||||
}
|
||||
Tcl_Release(resPtr->statePtr);
|
||||
|
||||
+12
-6
@@ -804,7 +804,6 @@ typedef struct VarInHash {
|
||||
* MODULE_SCOPE int TclIsVarTemporary(Var *varPtr);
|
||||
* MODULE_SCOPE int TclIsVarArgument(Var *varPtr);
|
||||
* MODULE_SCOPE int TclIsVarResolved(Var *varPtr);
|
||||
* MODULE_SCOPE int TclIsVarArraySearched(Var *varPtr);
|
||||
*/
|
||||
|
||||
#define TclIsVarScalar(varPtr) \
|
||||
@@ -846,9 +845,6 @@ typedef struct VarInHash {
|
||||
#define TclIsVarDeadHash(varPtr) \
|
||||
((varPtr)->flags & VAR_DEAD_HASH)
|
||||
|
||||
#define TclIsVarArraySearched(varPtr) \
|
||||
((varPtr)->flags & VAR_SEARCH_ACTIVE)
|
||||
|
||||
#define TclGetVarNsPtr(varPtr) \
|
||||
(TclIsVarInHash(varPtr) \
|
||||
? ((TclVarHashTable *) ((((VarInHash *) (varPtr))->entry.tablePtr)))->nsPtr \
|
||||
@@ -3503,6 +3499,9 @@ MODULE_SCOPE int TclCompileAppendCmd(Tcl_Interp *interp,
|
||||
MODULE_SCOPE int TclCompileArrayExistsCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileArrayForCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
MODULE_SCOPE int TclCompileArraySetCmd(Tcl_Interp *interp,
|
||||
Tcl_Parse *parsePtr, Command *cmdPtr,
|
||||
struct CompileEnv *envPtr);
|
||||
@@ -4566,12 +4565,13 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit;
|
||||
* types, avoiding the corresponding function calls in time critical parts of
|
||||
* the core. The ANSI C "prototypes" for these macros are:
|
||||
*
|
||||
* MODULE_SCOPE void TclNewIntObj(Tcl_Obj *objPtr, int i);
|
||||
* MODULE_SCOPE void TclNewLongObj(Tcl_Obj *objPtr, long l);
|
||||
* MODULE_SCOPE void TclNewBooleanObj(Tcl_Obj *objPtr, int b);
|
||||
* MODULE_SCOPE void TclNewWideObj(Tcl_Obj *objPtr, Tcl_WideInt w);
|
||||
* MODULE_SCOPE void TclNewDoubleObj(Tcl_Obj *objPtr, double d);
|
||||
* MODULE_SCOPE void TclNewStringObj(Tcl_Obj *objPtr, const char *s, int len);
|
||||
* MODULE_SCOPE void TclNewLiteralStringObj(Tcl_Obj*objPtr, const char *sLiteral);
|
||||
* MODULE_SCOPE void TclNewStringObj(Tcl_Obj *objPtr, char *s, int len);
|
||||
* MODULE_SCOPE void TclNewLiteralStringObj(Tcl_Obj*objPtr, char*sLiteral);
|
||||
*
|
||||
*----------------------------------------------------------------
|
||||
*/
|
||||
@@ -4588,6 +4588,9 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit;
|
||||
TCL_DTRACE_OBJ_CREATE(objPtr); \
|
||||
} while (0)
|
||||
|
||||
#define TclNewIntObj(objPtr, l) \
|
||||
TclNewLongObj(objPtr, l)
|
||||
|
||||
/*
|
||||
* NOTE: There is to be no such thing as a "pure" boolean.
|
||||
* See comment above TclSetBooleanObj macro above.
|
||||
@@ -4617,6 +4620,9 @@ MODULE_SCOPE Tcl_PackageInitProc Procbodytest_SafeInit;
|
||||
} while (0)
|
||||
|
||||
#else /* TCL_MEM_DEBUG */
|
||||
#define TclNewIntObj(objPtr, i) \
|
||||
(objPtr) = Tcl_NewIntObj(i)
|
||||
|
||||
#define TclNewLongObj(objPtr, l) \
|
||||
(objPtr) = Tcl_NewLongObj(l)
|
||||
|
||||
|
||||
@@ -410,7 +410,6 @@ Tcl_Init(
|
||||
" {file join $grandParentDir lib tcl[info tclversion]} \\\n"
|
||||
" {file join $parentDir library} \\\n"
|
||||
" {file join $grandParentDir library} \\\n"
|
||||
" {file join $grandParentDir tcl[info tclversion] library} \\\n"
|
||||
" {file join $grandParentDir tcl[info patchlevel] library} \\\n"
|
||||
" {\n"
|
||||
"file join [file dirname $grandParentDir] tcl[info patchlevel] library}\n"
|
||||
|
||||
+17
-24
@@ -393,9 +393,8 @@ LinkTraceProc(
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have integer value";
|
||||
} else {
|
||||
LinkedVar(Tcl_WideInt) = linkPtr->lastValue.w;
|
||||
}
|
||||
LinkedVar(Tcl_WideInt) = linkPtr->lastValue.w;
|
||||
break;
|
||||
|
||||
case TCL_LINK_DOUBLE:
|
||||
@@ -408,9 +407,8 @@ LinkTraceProc(
|
||||
ObjValue(linkPtr), TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have real value";
|
||||
#ifdef ACCEPT_NAN
|
||||
} else {
|
||||
linkPtr->lastValue.d = valueObj->internalRep.doubleValue;
|
||||
}
|
||||
linkPtr->lastValue.d = valueObj->internalRep.doubleValue;
|
||||
#endif
|
||||
}
|
||||
LinkedVar(double) = linkPtr->lastValue.d;
|
||||
@@ -427,7 +425,7 @@ LinkTraceProc(
|
||||
break;
|
||||
|
||||
case TCL_LINK_CHAR:
|
||||
if (Tcl_GetIntFromObj(NULL, valueObj, &valueInt) != TCL_OK
|
||||
if (Tcl_GetIntFromObj(interp, valueObj, &valueInt) != TCL_OK
|
||||
|| valueInt < SCHAR_MIN || valueInt > SCHAR_MAX) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
@@ -438,7 +436,7 @@ LinkTraceProc(
|
||||
break;
|
||||
|
||||
case TCL_LINK_UCHAR:
|
||||
if (Tcl_GetIntFromObj(NULL, valueObj, &valueInt) != TCL_OK
|
||||
if (Tcl_GetIntFromObj(interp, valueObj, &valueInt) != TCL_OK
|
||||
|| valueInt < 0 || valueInt > UCHAR_MAX) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
@@ -449,7 +447,7 @@ LinkTraceProc(
|
||||
break;
|
||||
|
||||
case TCL_LINK_SHORT:
|
||||
if (Tcl_GetIntFromObj(NULL, valueObj, &valueInt) != TCL_OK
|
||||
if (Tcl_GetIntFromObj(interp, valueObj, &valueInt) != TCL_OK
|
||||
|| valueInt < SHRT_MIN || valueInt > SHRT_MAX) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
@@ -460,7 +458,7 @@ LinkTraceProc(
|
||||
break;
|
||||
|
||||
case TCL_LINK_USHORT:
|
||||
if (Tcl_GetIntFromObj(NULL, valueObj, &valueInt) != TCL_OK
|
||||
if (Tcl_GetIntFromObj(interp, valueObj, &valueInt) != TCL_OK
|
||||
|| valueInt < 0 || valueInt > USHRT_MAX) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
@@ -471,38 +469,35 @@ LinkTraceProc(
|
||||
break;
|
||||
|
||||
case TCL_LINK_UINT:
|
||||
if (Tcl_GetWideIntFromObj(NULL, valueObj, &valueWide) != TCL_OK
|
||||
if (Tcl_GetWideIntFromObj(interp, valueObj, &valueWide) != TCL_OK
|
||||
|| valueWide < 0 || valueWide > UINT_MAX) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned int value";
|
||||
} else {
|
||||
linkPtr->lastValue.ui = (unsigned int)valueWide;
|
||||
}
|
||||
linkPtr->lastValue.ui = (unsigned int)valueWide;
|
||||
LinkedVar(unsigned int) = linkPtr->lastValue.ui;
|
||||
break;
|
||||
|
||||
case TCL_LINK_LONG:
|
||||
if (Tcl_GetWideIntFromObj(NULL, valueObj, &valueWide) != TCL_OK
|
||||
if (Tcl_GetWideIntFromObj(interp, valueObj, &valueWide) != TCL_OK
|
||||
|| valueWide < LONG_MIN || valueWide > LONG_MAX) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have long value";
|
||||
} else {
|
||||
linkPtr->lastValue.l = (long)valueWide;
|
||||
}
|
||||
linkPtr->lastValue.l = (long)valueWide;
|
||||
LinkedVar(long) = linkPtr->lastValue.l;
|
||||
break;
|
||||
|
||||
case TCL_LINK_ULONG:
|
||||
if (Tcl_GetWideIntFromObj(NULL, valueObj, &valueWide) != TCL_OK
|
||||
if (Tcl_GetWideIntFromObj(interp, valueObj, &valueWide) != TCL_OK
|
||||
|| valueWide < 0 || (Tcl_WideUInt) valueWide > ULONG_MAX) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned long value";
|
||||
} else {
|
||||
linkPtr->lastValue.ul = (unsigned long)valueWide;
|
||||
}
|
||||
linkPtr->lastValue.ul = (unsigned long)valueWide;
|
||||
LinkedVar(unsigned long) = linkPtr->lastValue.ul;
|
||||
break;
|
||||
|
||||
@@ -510,25 +505,23 @@ LinkTraceProc(
|
||||
/*
|
||||
* FIXME: represent as a bignum.
|
||||
*/
|
||||
if (Tcl_GetWideIntFromObj(NULL, valueObj, &valueWide) != TCL_OK) {
|
||||
if (Tcl_GetWideIntFromObj(interp, valueObj, &valueWide) != TCL_OK) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have unsigned wide int value";
|
||||
} else {
|
||||
linkPtr->lastValue.uw = (Tcl_WideUInt)valueWide;
|
||||
}
|
||||
linkPtr->lastValue.uw = (Tcl_WideUInt)valueWide;
|
||||
LinkedVar(Tcl_WideUInt) = linkPtr->lastValue.uw;
|
||||
break;
|
||||
|
||||
case TCL_LINK_FLOAT:
|
||||
if (Tcl_GetDoubleFromObj(NULL, valueObj, &valueDouble) != TCL_OK
|
||||
if (Tcl_GetDoubleFromObj(interp, valueObj, &valueDouble) != TCL_OK
|
||||
|| valueDouble < -FLT_MAX || valueDouble > FLT_MAX) {
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL, ObjValue(linkPtr),
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have float value";
|
||||
} else {
|
||||
linkPtr->lastValue.f = (float)valueDouble;
|
||||
}
|
||||
linkPtr->lastValue.f = (float)valueDouble;
|
||||
LinkedVar(float) = linkPtr->lastValue.f;
|
||||
break;
|
||||
|
||||
@@ -584,7 +577,7 @@ ObjValue(
|
||||
return Tcl_NewDoubleObj(linkPtr->lastValue.d);
|
||||
case TCL_LINK_BOOLEAN:
|
||||
linkPtr->lastValue.i = LinkedVar(int);
|
||||
return Tcl_NewBooleanObj(linkPtr->lastValue.i);
|
||||
return Tcl_NewBooleanObj(linkPtr->lastValue.i != 0);
|
||||
case TCL_LINK_CHAR:
|
||||
linkPtr->lastValue.c = LinkedVar(char);
|
||||
return Tcl_NewIntObj(linkPtr->lastValue.c);
|
||||
|
||||
+2
-2
@@ -1810,7 +1810,7 @@ Tcl_DbNewBooleanObj(
|
||||
TclDbNewObj(objPtr, file, line);
|
||||
objPtr->bytes = NULL;
|
||||
|
||||
objPtr->internalRep.longValue = (boolValue != 0);
|
||||
objPtr->internalRep.longValue = (boolValue? 1 : 0);
|
||||
objPtr->typePtr = &tclIntType;
|
||||
return objPtr;
|
||||
}
|
||||
@@ -2425,7 +2425,7 @@ Tcl_NewIntObj(
|
||||
{
|
||||
register Tcl_Obj *objPtr;
|
||||
|
||||
TclNewLongObj(objPtr, intValue);
|
||||
TclNewIntObj(objPtr, intValue);
|
||||
return objPtr;
|
||||
}
|
||||
#endif /* if TCL_MEM_DEBUG */
|
||||
|
||||
@@ -1865,14 +1865,6 @@ Tcl_AppendFormatToObj(
|
||||
useWide = 1;
|
||||
#endif
|
||||
}
|
||||
} else if ((ch == 'I') && (format[1] == '6') && (format[2] == '4')) {
|
||||
format += (step + 2);
|
||||
step = Tcl_UtfToUniChar(format, &ch);
|
||||
useBig = 1;
|
||||
} else if (ch == 'L') {
|
||||
format += step;
|
||||
step = Tcl_UtfToUniChar(format, &ch);
|
||||
useBig = 1;
|
||||
}
|
||||
|
||||
format += step;
|
||||
@@ -2517,17 +2509,6 @@ AppendPrintfToObjVA(
|
||||
++size;
|
||||
p++;
|
||||
break;
|
||||
case 'L':
|
||||
size = 2;
|
||||
p++;
|
||||
break;
|
||||
case 'I':
|
||||
if (p[1]=='6' && p[2]=='4') {
|
||||
p += 2;
|
||||
size = 2;
|
||||
}
|
||||
p++;
|
||||
break;
|
||||
case 'h':
|
||||
size = -1;
|
||||
default:
|
||||
|
||||
+3
-11
@@ -1416,17 +1416,9 @@ const TclStubs tclStubs = {
|
||||
Tcl_FindSymbol, /* 628 */
|
||||
Tcl_FSUnloadFile, /* 629 */
|
||||
Tcl_ZlibStreamSetCompressionDictionary, /* 630 */
|
||||
Tcl_ArraySet, /* 631 */
|
||||
Tcl_ArrayUnset, /* 632 */
|
||||
Tcl_ArrayGet, /* 633 */
|
||||
Tcl_ArrayNames, /* 634 */
|
||||
Tcl_ArraySize, /* 635 */
|
||||
Tcl_ArrayExists, /* 636 */
|
||||
Tcl_ArraySearchStart, /* 637 */
|
||||
Tcl_ArraySearchPeek, /* 638 */
|
||||
Tcl_ArraySearchNext, /* 639 */
|
||||
Tcl_ArraySearchDone, /* 640 */
|
||||
Tcl_ArrayStatistics, /* 641 */
|
||||
0, /* 631 */
|
||||
Tcl_ArrayObjFirst, /* 632 */
|
||||
Tcl_ArrayObjNext, /* 633 */
|
||||
};
|
||||
|
||||
/* !END!: Do not edit above this line. */
|
||||
|
||||
@@ -101,16 +101,12 @@ Tcl_InitStubs(
|
||||
}
|
||||
}
|
||||
}
|
||||
if (((exact&0xff00) < 0x900)) {
|
||||
/* We are running Tcl 8.x */
|
||||
stubsPtr = (TclStubs *)pkgData;
|
||||
}
|
||||
tclStubsPtr = stubsPtr;
|
||||
tclStubsPtr = (TclStubs *)pkgData;
|
||||
|
||||
if (stubsPtr->hooks) {
|
||||
tclPlatStubsPtr = stubsPtr->hooks->tclPlatStubs;
|
||||
tclIntStubsPtr = stubsPtr->hooks->tclIntStubs;
|
||||
tclIntPlatStubsPtr = stubsPtr->hooks->tclIntPlatStubs;
|
||||
if (tclStubsPtr->hooks) {
|
||||
tclPlatStubsPtr = tclStubsPtr->hooks->tclPlatStubs;
|
||||
tclIntStubsPtr = tclStubsPtr->hooks->tclIntStubs;
|
||||
tclIntPlatStubsPtr = tclStubsPtr->hooks->tclIntPlatStubs;
|
||||
} else {
|
||||
tclPlatStubsPtr = NULL;
|
||||
tclIntStubsPtr = NULL;
|
||||
|
||||
+4
-46
@@ -318,9 +318,6 @@ static int TestparsevarnameObjCmd(ClientData dummy,
|
||||
static int TestpreferstableObjCmd(ClientData dummy,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
static int TestprintObjCmd(ClientData dummy,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
static int TestregexpObjCmd(ClientData dummy,
|
||||
Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[]);
|
||||
@@ -544,10 +541,10 @@ Tcltest_Init(
|
||||
"-appinitprocclosestderr", "-appinitprocsetrcfile", NULL
|
||||
};
|
||||
|
||||
if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
|
||||
if (Tcl_InitStubs(interp, "8.5", 0) == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (Tcl_TomMath_InitStubs(interp, "8.5-") == NULL) {
|
||||
if (Tcl_TomMath_InitStubs(interp, "8.5") == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (Tcl_OOInitStubs(interp) == NULL) {
|
||||
@@ -652,8 +649,6 @@ Tcltest_Init(
|
||||
NULL, NULL);
|
||||
Tcl_CreateObjCommand(interp, "testpreferstable", TestpreferstableObjCmd,
|
||||
NULL, NULL);
|
||||
Tcl_CreateObjCommand(interp, "testprint", TestprintObjCmd,
|
||||
NULL, NULL);
|
||||
Tcl_CreateObjCommand(interp, "testregexp", TestregexpObjCmd,
|
||||
NULL, NULL);
|
||||
Tcl_CreateObjCommand(interp, "testreturn", TestreturnObjCmd,
|
||||
@@ -786,7 +781,7 @@ int
|
||||
Tcltest_SafeInit(
|
||||
Tcl_Interp *interp) /* Interpreter for application. */
|
||||
{
|
||||
if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
|
||||
if (Tcl_InitStubs(interp, "8.5", 0) == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return Procbodytest_SafeInit(interp);
|
||||
@@ -3822,43 +3817,6 @@ TestpreferstableObjCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TestprintObjCmd --
|
||||
*
|
||||
* This procedure implements the "testprint" command. It is
|
||||
* used for being able to test the Tcl_ObjPrintf() function.
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
TestprintObjCmd(
|
||||
ClientData clientData, /* Not used. */
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* The argument objects. */
|
||||
{
|
||||
Tcl_WideInt argv1 = 0;
|
||||
|
||||
if (objc < 2 || objc > 3) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "format wideint");
|
||||
}
|
||||
|
||||
if (objc > 1) {
|
||||
Tcl_GetWideIntFromObj(interp, objv[2], &argv1);
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(Tcl_GetString(objv[1]), argv1));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -4639,7 +4597,7 @@ TestpanicCmd(
|
||||
int argc, /* Number of arguments. */
|
||||
const char **argv) /* Argument strings. */
|
||||
{
|
||||
char *argString;
|
||||
const char *argString;
|
||||
|
||||
/*
|
||||
* Put the arguments into a var args structure
|
||||
|
||||
+1199
-1738
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -373,7 +373,7 @@ ConvertErrorToList(
|
||||
|
||||
default:
|
||||
TclNewLiteralStringObj(objv[2], "UNKNOWN");
|
||||
TclNewLongObj(objv[3], code);
|
||||
TclNewIntObj(objv[3], code);
|
||||
return Tcl_NewListObj(4, objv);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,888 +0,0 @@
|
||||
# Commands covered: array
|
||||
#
|
||||
# This file contains a collection of tests for one or more of the Tcl
|
||||
# built-in commands. Sourcing this file into Tcl runs the tests and
|
||||
# generates output for errors. No output means no errors were found.
|
||||
#
|
||||
# Copyright (c) 2016 Andy Goth
|
||||
#
|
||||
# See the file "license.terms" for information on usage and redistribution
|
||||
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
|
||||
if {[lsearch [namespace children] ::tcltest] < 0} {
|
||||
package require tcltest 2
|
||||
}
|
||||
::tcltest::loadTestedCommands
|
||||
catch {package require -exact Tcltest [info patchlevel]}
|
||||
set namespaces [namespace children]
|
||||
set procs [info procs]
|
||||
set vars [info vars]
|
||||
|
||||
# test set chapter title
|
||||
# --------- -----------------------
|
||||
# array-1.* subcommand dispatch
|
||||
# array-2.* common argument parsing
|
||||
# array-3.* array set
|
||||
# array-4.* array unset
|
||||
# array-5.* array statistics
|
||||
# array-6.* array exists|size|names|get
|
||||
# array-7.* array anymore|donesearch|nextelement|startsearch
|
||||
|
||||
# test set [array] subcommand arrayName mode and filter
|
||||
# --------- ------------------ -------------------- ---------------
|
||||
# array-7.* anymore array required not allowed
|
||||
# array-7.* donesearch array required not allowed
|
||||
# array-6.* exists anything optional
|
||||
# array-6.* get anything optional
|
||||
# array-6.* names anything optional
|
||||
# array-7.* nextelement array required not allowed
|
||||
# array-3.* set array or nonexistent not allowed
|
||||
# array-6.* size anything optional
|
||||
# array-7.* startsearch array required optional
|
||||
# array-5.* statistics array required not allowed
|
||||
# array-4.* unset anything optional
|
||||
# array-1.* (unique abbrev) (see above) (see above)
|
||||
# array-1.* (ambiguous abbrev) (error) (error)
|
||||
# array-1.* (invalid) (error) (error)
|
||||
|
||||
# oxfordJoin --
|
||||
# and --
|
||||
# or --
|
||||
# Joins a list by commas, a conjunction, or both, using Oxford comma rules,
|
||||
# matching Tcl's internal algorithm for displaying lists in error messages.
|
||||
proc oxfordJoin {conjunction list} {
|
||||
if {[llength $list] > 1} {
|
||||
lset list end "$conjunction [lindex $list end]"
|
||||
}
|
||||
if {[llength $list] < 3} {
|
||||
join $list " "
|
||||
} else {
|
||||
join $list ", "
|
||||
}
|
||||
}
|
||||
interp alias {} and {} oxfordJoin and
|
||||
interp alias {} or {} oxfordJoin or
|
||||
|
||||
# samples --
|
||||
# Produces a list of sample arguments, given a list of parameters.
|
||||
# Customizations can be applied via $args.
|
||||
proc samples {params args} {
|
||||
set map [dict merge {
|
||||
arrayName a
|
||||
searchId s-1-a
|
||||
?mode? -exact
|
||||
?pattern? hello
|
||||
list {hello world}
|
||||
} $args]
|
||||
lmap param $params {dict get $map $param}
|
||||
}
|
||||
|
||||
# test --
|
||||
# Wrapper around [::tcltest::test] with additional features:
|
||||
#
|
||||
# - Single-argument block design gives a cleaner visual presentation.
|
||||
# - All script execution is performed in a new stack frame.
|
||||
# - Script variables are shared across scripts via a temporary namespace.
|
||||
# - All definition values (except scripts) are [subst]'ed.
|
||||
#
|
||||
# The $def argument is a dict which defines the test. Its possible keys are:
|
||||
#
|
||||
# - name | desc
|
||||
# Test name and description.
|
||||
#
|
||||
# - {scalar name} | {array name}
|
||||
# The name component of the key is the name of a scalar or array variable, and
|
||||
# the value is the initial scalar value or array dictionary value. These
|
||||
# variables are shared across the setup, body, and cleanup scripts.
|
||||
#
|
||||
# - link
|
||||
# Uninitialized variables shared across the setup, body, and cleanup scripts.
|
||||
#
|
||||
# - setup | body | cleanup
|
||||
# The scripts are modified to include variable initialization, linkage, and
|
||||
# finalization and to be executed inside new stack frames.
|
||||
#
|
||||
# - constraints | result | output | errorOutput | returnCodes | match
|
||||
# See tcltest(n) for the purpose of these keys.
|
||||
proc test {def} {
|
||||
# Perform uplevel substitutions, and process scalar and array arguments.
|
||||
set scalars {}
|
||||
set arrays {}
|
||||
dict for {key val} $def {
|
||||
if {$key ni {setup body cleanup}} {
|
||||
dict set def $key [set val [uplevel [list subst $val]]]
|
||||
}
|
||||
if {[llength $key] == 2} {
|
||||
if {[lindex $key 0] eq "scalar"} {
|
||||
dict set scalars [lindex $key 1] $val
|
||||
dict unset def $key
|
||||
} elseif {[lindex $key 0] eq "array"} {
|
||||
dict set arrays [lindex $key 1] $val
|
||||
dict unset def $key
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Augment scripts with variable initialization, linkage, and finalization.
|
||||
dict lappend def link {*}[dict keys $scalars] {*}[dict keys $arrays]
|
||||
if {[llength [dict get $def link]]} {
|
||||
# Ensure all three scripts exist, even if empty.
|
||||
foreach key {setup body cleanup} {
|
||||
dict append def $key
|
||||
}
|
||||
|
||||
# Build variable initialization, linkage, and finalization snippets.
|
||||
set initial [list namespace eval ::TestVars [join [list\
|
||||
[list variable {*}$scalars]\
|
||||
{*}[lmap {var val} $arrays {list variable $var}]\
|
||||
{*}[lmap {var val} $arrays {list array set $var $val}]] \n]]
|
||||
set linkage [join [lmap var [dict get $def link]\
|
||||
{list variable ::TestVars::$var}] \n]
|
||||
set final [list namespace delete ::TestVars]
|
||||
|
||||
# Update scripts.
|
||||
dict set def setup $initial\n$linkage\n[dict get $def setup]
|
||||
dict set def body $linkage\n[dict get $def body]
|
||||
dict set def cleanup $linkage\n[dict get $def cleanup]\n$final
|
||||
}
|
||||
dict unset def link
|
||||
|
||||
# Convert scripts to zero-argument lambda invocations.
|
||||
foreach key {setup body cleanup} {
|
||||
if {[dict exists $def $key]} {
|
||||
dict set def $key [list apply [list {} [dict get $def $key]]]
|
||||
}
|
||||
}
|
||||
|
||||
# Assemble the Tcltest command.
|
||||
set command [list ::tcltest::test [dict get $def name] [dict get $def desc]]
|
||||
dict unset def name
|
||||
dict unset def desc
|
||||
foreach key {constraints setup body cleanup result output errorOutput
|
||||
returnCodes match} {
|
||||
if {[dict exists $def $key]} {
|
||||
lappend command -$key [dict get $def $key]
|
||||
dict unset def $key
|
||||
}
|
||||
}
|
||||
|
||||
# Complain if there are any invalid test definition keys.
|
||||
if {[dict size $def]} {
|
||||
error "bad test definition key(s): [and [dict keys $def]]"
|
||||
}
|
||||
|
||||
# Run the Tcltest command.
|
||||
tailcall {*}$command
|
||||
}
|
||||
|
||||
# Formal parameters for each array subcommand.
|
||||
set params {
|
||||
anymore {arrayName searchId}
|
||||
donesearch {arrayName searchId}
|
||||
exists {arrayName ?mode? ?pattern?}
|
||||
get {arrayName ?mode? ?pattern?}
|
||||
names {arrayName ?mode? ?pattern?}
|
||||
nextelement {arrayName searchId}
|
||||
set {arrayName list}
|
||||
size {arrayName ?mode? ?pattern?}
|
||||
startsearch {arrayName ?mode? ?pattern?}
|
||||
statistics {arrayName}
|
||||
unset {arrayName ?mode? ?pattern?}
|
||||
}
|
||||
|
||||
# List of array subcommands.
|
||||
set commands [lsort [dict keys $params]]
|
||||
|
||||
# Ambiguous and unambiguous abbreviations of array subcommands.
|
||||
foreach cmd $commands {
|
||||
for {set i 0} {$i < [string length $cmd] - 1} {incr i} {
|
||||
set abbrev [string range $cmd 0 $i]
|
||||
if {$abbrev in $commands
|
||||
|| [llength [lsearch -all $commands $abbrev*]] == 1} {
|
||||
dict lappend abbrevs $cmd $abbrev
|
||||
} else {
|
||||
dict set ambig $abbrev {}
|
||||
}
|
||||
}
|
||||
}
|
||||
set ambig [lsort [dict keys $ambig]]
|
||||
|
||||
# List of valid array filter mode options.
|
||||
set modes [lsort {-exact -glob -regexp}]
|
||||
|
||||
######################## array-1.*: subcommand dispatch ########################
|
||||
test {
|
||||
name array-1.1
|
||||
desc {no subcommand}
|
||||
body {array}
|
||||
returnCodes error
|
||||
result {wrong # args: should be "array subcommand ?arg ...?"}
|
||||
}
|
||||
test {
|
||||
name array-1.2
|
||||
desc {empty subcommand}
|
||||
body {array {}}
|
||||
returnCodes error
|
||||
result {unknown or ambiguous subcommand "": must be [or $commands]}
|
||||
}
|
||||
test {
|
||||
name array-1.3
|
||||
desc {invalid subcommand}
|
||||
body {array gorp}
|
||||
returnCodes error
|
||||
result {unknown or ambiguous subcommand "gorp": must be [or $commands]}
|
||||
}
|
||||
foreach cmd $ambig {
|
||||
test {
|
||||
name array-1.4.$cmd
|
||||
desc {ambiguous subcommand: \[array $cmd\]}
|
||||
{scalar cmd} $cmd
|
||||
body {array $cmd}
|
||||
returnCodes error
|
||||
result {unknown or ambiguous subcommand "$cmd": must be [or $commands]}
|
||||
}
|
||||
}
|
||||
foreach cmd $commands {
|
||||
test {
|
||||
name array-1.5.$cmd
|
||||
desc {formal parameter lists: \[array $cmd\]}
|
||||
{scalar cmd} $cmd
|
||||
body {array $cmd}
|
||||
returnCodes error
|
||||
result {wrong # args: should be "array $cmd [dict get $params $cmd]"}
|
||||
}
|
||||
}
|
||||
|
||||
###################### array-2.*: common argument parsing ######################
|
||||
foreach {cmd code resultPattern} {
|
||||
anymore error "\"%VAR%\" %MSG%"
|
||||
donesearch error "\"%VAR%\" %MSG%"
|
||||
exists ok 0
|
||||
get ok {}
|
||||
names ok {}
|
||||
nextelement error "\"%VAR%\" %MSG%"
|
||||
set error "can't set \"%VAR%%ELEM%\": %MSG%"
|
||||
size ok 0
|
||||
startsearch error "\"%VAR%\" %MSG%"
|
||||
statistics error "\"%VAR%\" %MSG%"
|
||||
unset ok {}
|
||||
} {
|
||||
test {
|
||||
name array-2.1.$cmd
|
||||
desc {too many arguments: \[array $cmd\]}
|
||||
{scalar cmd} $cmd
|
||||
{scalar args} {[lmap param [dict get $params $cmd] {samples $param}]}
|
||||
body {array $cmd {*}$args extra}
|
||||
returnCodes error
|
||||
result {wrong # args: should be "array $cmd [dict get $params $cmd]"}
|
||||
}
|
||||
if {"?mode?" in [dict get $params $cmd]} {
|
||||
test {
|
||||
name array-2.2.$cmd
|
||||
desc {ambiguous mode: \[array $cmd\]"}
|
||||
{scalar cmd} $cmd
|
||||
{array a} {}
|
||||
body {array $cmd a {} {}}
|
||||
returnCodes error
|
||||
result {ambiguous option "": must be [or $modes]}
|
||||
}
|
||||
test {
|
||||
name array-2.3.$cmd
|
||||
desc {invalid mode: \[array $cmd\]}
|
||||
{scalar cmd} $cmd
|
||||
{array a} {}
|
||||
body {array $cmd a INVALID {}}
|
||||
returnCodes error
|
||||
result {bad option "INVALID": must be [or $modes]}
|
||||
}
|
||||
test {
|
||||
name array-2.4.$cmd
|
||||
desc {invalid regexp: \[array $cmd\]}
|
||||
{scalar cmd} $cmd
|
||||
{array a} {e 1}
|
||||
body {array $cmd a -regexp *}
|
||||
returnCodes error
|
||||
result {couldn't compile regular expression pattern:\
|
||||
quantifier operand invalid}
|
||||
}
|
||||
}
|
||||
test {
|
||||
name array-2.5.$cmd
|
||||
desc {array trace error during variable lookup: \[array $cmd\]}
|
||||
{scalar cmd} $cmd
|
||||
{scalar args} {[lmap param [dict get $params $cmd] {samples $param}]}
|
||||
link a
|
||||
setup {trace add variable a array {apply {{args} {error $args}}}}
|
||||
body {array $cmd {*}$args}
|
||||
returnCodes error
|
||||
result {can't trace array "a": a {} array}
|
||||
}
|
||||
if {$cmd eq "set"} {
|
||||
set nonArray "variable isn't array"
|
||||
set nonNamespace "parent namespace doesn't exist"
|
||||
} else {
|
||||
set nonArray "isn't an array"
|
||||
set nonNamespace "isn't an array"
|
||||
}
|
||||
foreach {
|
||||
desc skip setup
|
||||
name msg var elem extra
|
||||
} {
|
||||
"nonexistent array" set {}
|
||||
array-2.6 nonArray a {} {}
|
||||
|
||||
"element of proc-slot-only array" set {}
|
||||
array-2.7 nonArray a {} {set a(hello) 123}
|
||||
|
||||
"scalar variable" {} {{scalar a} {}}
|
||||
array-2.8 nonArray a (hello) {}
|
||||
|
||||
"element of empty array" {} {{array a} {}}
|
||||
array-2.9 nonArray a(x) {} {}
|
||||
|
||||
"element of nonexistent array" {} {}
|
||||
array-2.10 nonArray a(x) {} {}
|
||||
|
||||
"element of scalar variable" {} {{scalar a} {}}
|
||||
array-2.11 nonArray a(x) {} {}
|
||||
|
||||
"existing element of array" {} {{scalar a} {x 123}}
|
||||
array-2.12 nonArray a(x) {} {}
|
||||
|
||||
"nonexistent element of array" {} {{array a} {}}
|
||||
array-2.13 nonArray a(x) {} {}
|
||||
|
||||
"bad namespace" {} {}
|
||||
array-2.14 nonNamespace ::X::a {} {}
|
||||
} {
|
||||
if {$cmd ni $skip} {
|
||||
set map [list %VAR% $var %MSG% [set $msg] %ELEM% $elem]
|
||||
test [string map [list %SETUP% $setup %EXTRA% $extra] {
|
||||
name $name.$cmd
|
||||
desc {$desc: \[array $cmd\]}
|
||||
{scalar cmd} $cmd
|
||||
{scalar args} {[samples [dict get $params $cmd] arrayName $var]}
|
||||
%SETUP%
|
||||
body {set result [array $cmd {*}$args]; %EXTRA%; return $result}
|
||||
returnCodes $code
|
||||
result {[string map $map $resultPattern]}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
############################# array-3.*: array set #############################
|
||||
test {
|
||||
name array-3.1
|
||||
desc {empty}
|
||||
body {array set a {}; list [array exists a] [array get a]}
|
||||
result {1 {}}
|
||||
}
|
||||
test {
|
||||
name array-3.2
|
||||
desc {one array element}
|
||||
body {array set a {e 1}; array get a}
|
||||
result {e 1}
|
||||
}
|
||||
test {
|
||||
name array-3.3
|
||||
desc {missing value}
|
||||
body {array set a e}
|
||||
returnCodes error
|
||||
result {list must have an even number of elements}
|
||||
}
|
||||
test {
|
||||
name array-3.4
|
||||
desc {duplicate key}
|
||||
body {array set a {e 0 e 1}; array get a}
|
||||
result {e 1}
|
||||
}
|
||||
test {
|
||||
name array-3.5
|
||||
desc {invalid list}
|
||||
body {array set a \{\}x}
|
||||
returnCodes error
|
||||
result {list element in braces followed by "x" instead of space}
|
||||
}
|
||||
test {
|
||||
name array-3.6
|
||||
desc {invalid list part 2}
|
||||
body {array set a \"\"x}
|
||||
returnCodes error
|
||||
result {list element in quotes followed by "x" instead of space}
|
||||
}
|
||||
test {
|
||||
name array-3.7
|
||||
desc {invalid list part 3}
|
||||
body {array set a \{}
|
||||
returnCodes error
|
||||
result {unmatched open brace in list}
|
||||
}
|
||||
test {
|
||||
name array-3.8
|
||||
desc {invalid list part 4}
|
||||
body {array set a \"}
|
||||
returnCodes error
|
||||
result {unmatched open quote in list}
|
||||
}
|
||||
test {
|
||||
name array-3.9
|
||||
desc {hash order}
|
||||
body {array set a {f 2 e 1}; array get a}
|
||||
result {e 1 f 2}
|
||||
}
|
||||
test {
|
||||
name array-3.10
|
||||
desc {adding elements}
|
||||
body {array set a {f 2}; array set a {e 1}; array get a}
|
||||
result {e 1 f 2}
|
||||
}
|
||||
test {
|
||||
name array-3.11
|
||||
desc {adding elements, hash order}
|
||||
body {array set a {e 1}; array set a {f 2}; array get a}
|
||||
result {e 1 f 2}
|
||||
}
|
||||
test {
|
||||
name array-3.12
|
||||
desc {replacing elements}
|
||||
body {array set a {e 1}; array set a {e 2}; array get a}
|
||||
result {e 2}
|
||||
}
|
||||
test {
|
||||
name array-3.13
|
||||
desc {adding and replacing elements}
|
||||
body {array set a {e 1}; array set a {f 3 e 2}; array get a}
|
||||
result {e 2 f 3}
|
||||
}
|
||||
test {
|
||||
name array-3.14
|
||||
desc {former scalar}
|
||||
{scalar a} xxx
|
||||
body {unset a; array set a {e 1}; array get a}
|
||||
result {e 1}
|
||||
}
|
||||
test {
|
||||
name array-3.15
|
||||
desc {weird names}
|
||||
body {array set a {{ a b } 1 ) 2 ( 3 )( 4 () 5 {} 6}; array get a}
|
||||
result {{} 6 ( 3 () 5 )( 4 ) 2 { a b } 1}
|
||||
}
|
||||
|
||||
############################ array-4.*: array unset ############################
|
||||
test {
|
||||
name array-4.1
|
||||
desc {unset empty array}
|
||||
{array a} {}
|
||||
body {array unset a; info exists a}
|
||||
result 0
|
||||
}
|
||||
test {
|
||||
name array-4.2
|
||||
desc {unset non-empty array}
|
||||
{array a} {e 1}
|
||||
body {array unset a; info exists a}
|
||||
result 0
|
||||
}
|
||||
test {
|
||||
name array-4.3
|
||||
desc {unset scalar}
|
||||
{scalar a} x
|
||||
body {array unset a; return $a}
|
||||
result x
|
||||
}
|
||||
test {
|
||||
name array-4.4
|
||||
desc {unset all elements of empty array}
|
||||
{array a} {}
|
||||
body {array unset a *; list [info exists a] [array size a]}
|
||||
result {1 0}
|
||||
}
|
||||
test {
|
||||
name array-4.5
|
||||
desc {unset all elements of non-empty array}
|
||||
{array a} {e 1}
|
||||
body {array unset a *; list [info exists a] [array size a]}
|
||||
result {1 0}
|
||||
}
|
||||
test {
|
||||
name array-4.6
|
||||
desc {unset all elements of scalar array}
|
||||
{scalar a} x
|
||||
body {array unset a *; return $a}
|
||||
result x
|
||||
}
|
||||
test {
|
||||
name array-4.7
|
||||
desc {unset single existing element using -exact}
|
||||
{array a} {f 2 e 1}
|
||||
body {array unset a -exact e; array get a}
|
||||
result {f 2}
|
||||
}
|
||||
test {
|
||||
name array-4.8
|
||||
desc {unset single nonexistent element using -exact}
|
||||
{array a} {f 2 e 1}
|
||||
body {array unset a -exact d; array get a}
|
||||
result {e 1 f 2}
|
||||
}
|
||||
test {
|
||||
name array-4.9
|
||||
desc {unset single existing element using default mode}
|
||||
{array a} {f 2 e 1}
|
||||
body {array unset a e; array get a}
|
||||
result {f 2}
|
||||
}
|
||||
test {
|
||||
name array-4.10
|
||||
desc {unset single nonexistent element using default mode}
|
||||
{array a} {f 2 e 1}
|
||||
body {array unset a d; array get a}
|
||||
result {e 1 f 2}
|
||||
}
|
||||
test {
|
||||
name array-4.11
|
||||
desc {unset single existing element using -glob}
|
||||
{array a} {f 2 e 1}
|
||||
body {array unset a -glob {[e]}; array get a}
|
||||
result {f 2}
|
||||
}
|
||||
test {
|
||||
name array-4.12
|
||||
desc {unset single nonexistent element using -glob}
|
||||
{array a} {f 2 e 1}
|
||||
body {array unset a -glob {[d]}; array get a}
|
||||
result {e 1 f 2}
|
||||
}
|
||||
test {
|
||||
name array-4.13
|
||||
desc {unset single existing element using -regexp}
|
||||
{array a} {f 2 e 1}
|
||||
body {array unset a -regexp {^[e]}; array get a}
|
||||
result {f 2}
|
||||
}
|
||||
test {
|
||||
name array-4.14
|
||||
desc {unset single nonexistent element using -regexp}
|
||||
{array a} {f 2 e 1}
|
||||
body {array unset a -regexp {^[d]}; array get a}
|
||||
result {e 1 f 2}
|
||||
}
|
||||
test {
|
||||
name array-4.15
|
||||
desc {confirm unset -exact does not match substrings}
|
||||
{array a} {abc 1}
|
||||
body {array unset a -exact b; array get a}
|
||||
result {abc 1}
|
||||
}
|
||||
test {
|
||||
name array-4.16
|
||||
desc {confirm unset -glob does not match substrings}
|
||||
{array a} {abc 1}
|
||||
body {array unset a -glob b; array get a}
|
||||
result {abc 1}
|
||||
}
|
||||
test {
|
||||
name array-4.17
|
||||
desc {confirm unset -regexp does match substrings}
|
||||
{array a} {abc 1}
|
||||
body {array unset a -regexp b; array get a}
|
||||
result {}
|
||||
}
|
||||
|
||||
######################### array-5.*: array statistics ##########################
|
||||
# Note: array-5.3 expected results obtained from Tcl version 8.5.7
|
||||
test {
|
||||
name array-5.1
|
||||
desc {empty array}
|
||||
{array a} {}
|
||||
body {array statistics a}
|
||||
result
|
||||
{0 entries in table, 4 buckets
|
||||
number of buckets with 0 entries: 4
|
||||
number of buckets with 1 entries: 0
|
||||
number of buckets with 2 entries: 0
|
||||
number of buckets with 3 entries: 0
|
||||
number of buckets with 4 entries: 0
|
||||
number of buckets with 5 entries: 0
|
||||
number of buckets with 6 entries: 0
|
||||
number of buckets with 7 entries: 0
|
||||
number of buckets with 8 entries: 0
|
||||
number of buckets with 9 entries: 0
|
||||
number of buckets with 10 or more entries: 0
|
||||
average search distance for entry: 0.0}
|
||||
}
|
||||
test {
|
||||
name array-5.2
|
||||
desc {single-element array}
|
||||
{array a} {e 1}
|
||||
body {array statistics a}
|
||||
result
|
||||
{1 entries in table, 4 buckets
|
||||
number of buckets with 0 entries: 3
|
||||
number of buckets with 1 entries: 1
|
||||
number of buckets with 2 entries: 0
|
||||
number of buckets with 3 entries: 0
|
||||
number of buckets with 4 entries: 0
|
||||
number of buckets with 5 entries: 0
|
||||
number of buckets with 6 entries: 0
|
||||
number of buckets with 7 entries: 0
|
||||
number of buckets with 8 entries: 0
|
||||
number of buckets with 9 entries: 0
|
||||
number of buckets with 10 or more entries: 0
|
||||
average search distance for entry: 1.0}
|
||||
}
|
||||
test {
|
||||
name array-5.3
|
||||
desc {thousand-element array}
|
||||
link a
|
||||
setup {for {set i 0} {$i < 1000} {incr i} {set a($i) $i}}
|
||||
body {array statistics a}
|
||||
result
|
||||
{1000 entries in table, 1024 buckets
|
||||
number of buckets with 0 entries: 285
|
||||
number of buckets with 1 entries: 520
|
||||
number of buckets with 2 entries: 180
|
||||
number of buckets with 3 entries: 36
|
||||
number of buckets with 4 entries: 3
|
||||
number of buckets with 5 entries: 0
|
||||
number of buckets with 6 entries: 0
|
||||
number of buckets with 7 entries: 0
|
||||
number of buckets with 8 entries: 0
|
||||
number of buckets with 9 entries: 0
|
||||
number of buckets with 10 or more entries: 0
|
||||
average search distance for entry: 1.3}
|
||||
}
|
||||
test {
|
||||
name array-5.4
|
||||
desc {collision attack}
|
||||
link a
|
||||
setup {
|
||||
for {set i 16} {$i < 29} {incr i} {
|
||||
set a([binary format cc $i [expr {-$i * 9}]]) $i
|
||||
}
|
||||
}
|
||||
body {array statistics a}
|
||||
result
|
||||
{13 entries in table, 16 buckets
|
||||
number of buckets with 0 entries: 15
|
||||
number of buckets with 1 entries: 0
|
||||
number of buckets with 2 entries: 0
|
||||
number of buckets with 3 entries: 0
|
||||
number of buckets with 4 entries: 0
|
||||
number of buckets with 5 entries: 0
|
||||
number of buckets with 6 entries: 0
|
||||
number of buckets with 7 entries: 0
|
||||
number of buckets with 8 entries: 0
|
||||
number of buckets with 9 entries: 0
|
||||
number of buckets with 10 or more entries: 1
|
||||
average search distance for entry: 7.0}
|
||||
}
|
||||
|
||||
################### array-6.*: array exists|size|names|get #####################
|
||||
foreach {
|
||||
desc
|
||||
name dict args exists size names get
|
||||
} {
|
||||
"empty array"
|
||||
array-6.1 {} {} 1 0 {} {}
|
||||
|
||||
"non-empty array"
|
||||
array-6.2 {e 1} {} 1 1 {e} {e 1}
|
||||
|
||||
"nonexistent element using default mode"
|
||||
array-6.3 {e 1} {[d]} 0 0 {} {}
|
||||
|
||||
"existing element using default mode"
|
||||
array-6.4 {e 1} {[e]} 1 1 {e} {e 1}
|
||||
|
||||
"multiple elements using default mode"
|
||||
array-6.5 {e 1 f 2} {[ef]} 1 2 {e f} {e 1 f 2}
|
||||
|
||||
"nonexistent element using -glob"
|
||||
array-6.6 {e 1} {-glob [d]} 0 0 {} {}
|
||||
|
||||
"existing element using -glob"
|
||||
array-6.7 {e 1} {-glob [e]} 1 1 {e} {e 1}
|
||||
|
||||
"multiple elements using -glob"
|
||||
array-6.8 {e 1 f 2} {-glob [ef]} 1 2 {e f} {e 1 f 2}
|
||||
|
||||
"nonexistent element using -exact"
|
||||
array-6.9 {e 1} {-exact d} 0 0 {} {}
|
||||
|
||||
"existing element using -exact"
|
||||
array-6.10 {e 1} {-exact e} 1 1 {e} {e 1}
|
||||
|
||||
"nonexistent element using -regexp"
|
||||
array-6.11 {e 1} {-regexp ^[d]} 0 0 {} {}
|
||||
|
||||
"existing element using -regexp"
|
||||
array-6.12 {e 1} {-regexp ^[e]} 1 1 {e} {e 1}
|
||||
|
||||
"multiple elements using -regexp"
|
||||
array-6.13 {e 1 f 2} {-regexp ^[ef]} 1 2 {e f} {e 1 f 2}
|
||||
} {
|
||||
foreach cmd {exists size names get} {
|
||||
test [string map [list %RESULT% [set $cmd]] {
|
||||
name $name.$cmd
|
||||
desc {$desc: \[array $cmd\]}
|
||||
{scalar cmd} $cmd
|
||||
{scalar args} $args
|
||||
{array a} $dict
|
||||
body {array $cmd a {*}$args}
|
||||
result {%RESULT%}
|
||||
}]
|
||||
}
|
||||
}
|
||||
foreach {
|
||||
cmd small large
|
||||
} {
|
||||
exists 1 1
|
||||
size 1 2
|
||||
names {e} {e f}
|
||||
get {e 1} {e 1 f 2}
|
||||
} {
|
||||
test {
|
||||
name array-6.14.$cmd
|
||||
desc {increasing array size: \[array $cmd\]}
|
||||
{scalar cmd} $cmd
|
||||
{array a} {e 1}
|
||||
body {list [array $cmd a][set a(f) 2; list] [array $cmd a]}
|
||||
result {[list $small $large]}
|
||||
}
|
||||
test {
|
||||
name array-6.15.$cmd
|
||||
desc {decreasing array size: \[array $cmd\]}
|
||||
{scalar cmd} $cmd
|
||||
{array a} {e 1 f 2}
|
||||
body {list [array $cmd a][unset a(f)] [array $cmd a]}
|
||||
result {[list $large $small]}
|
||||
}
|
||||
}
|
||||
|
||||
######### array-7.*: array anymore|donesearch|nextelement|startsearch ##########
|
||||
foreach cmd {anymore donesearch nextelement} {
|
||||
test {
|
||||
name array-7.1.$cmd
|
||||
desc {nonexistent search token}
|
||||
{scalar cmd} $cmd
|
||||
{array a} {}
|
||||
body {array $cmd a s-1-a}
|
||||
returnCodes error
|
||||
result {couldn't find search "s-1-a"}
|
||||
}
|
||||
}
|
||||
foreach {
|
||||
desc
|
||||
name dict args result
|
||||
} {
|
||||
"no filter, empty array"
|
||||
array-7.2 {} {} {}
|
||||
|
||||
"no filter, single element"
|
||||
array-7.3 {e 1} {} {e}
|
||||
|
||||
"no filter, two elements"
|
||||
array-7.4 {f 2 e 1} {} {e f}
|
||||
|
||||
"default filter, matches nothing"
|
||||
array-7.5 {f 2 e 1} {[g]} {}
|
||||
|
||||
"default filter, matches one item"
|
||||
array-7.6 {f 2 e 1} {[f]} {f}
|
||||
|
||||
"default filter, matches two items"
|
||||
array-7.7 {f 2 e 1} {[ef]} {e f}
|
||||
|
||||
"-glob filter, matches nothing"
|
||||
array-7.8 {f 2 e 1} {-glob [g]} {}
|
||||
|
||||
"-glob filter, matches one item"
|
||||
array-7.9 {f 2 e 1} {-glob [f]} {f}
|
||||
|
||||
"-glob filter, matches two items"
|
||||
array-7.10 {f 2 e 1} {-glob [ef]} {e f}
|
||||
|
||||
"-exact filter, matches nothing"
|
||||
array-7.11 {f 2 e 1} {-exact g} {}
|
||||
|
||||
"-exact filter, matches one item"
|
||||
array-7.12 {f 2 e 1} {-exact f} {f}
|
||||
|
||||
"-regexp filter, matches nothing"
|
||||
array-7.13 {f 2 e 1} {-regexp ^[g]} {}
|
||||
|
||||
"-regexp filter, matches one item"
|
||||
array-7.14 {f 2 e 1} {-regexp ^[f]} {f}
|
||||
|
||||
"-regexp filter, matches two items"
|
||||
array-7.15 {f 2 e 1} {-regexp ^[ef]} {e f}
|
||||
} {
|
||||
test {
|
||||
name $name
|
||||
desc $desc
|
||||
{scalar args} $args
|
||||
{array a} $dict
|
||||
body {
|
||||
set result {}
|
||||
set s [array startsearch a {*}$args]
|
||||
while {[array anymore a $s]} {
|
||||
lappend result [array nextelement a $s]
|
||||
}
|
||||
array donesearch a $s
|
||||
return $result
|
||||
}
|
||||
result $result
|
||||
}
|
||||
}
|
||||
test {
|
||||
name array-7.16
|
||||
desc {unset visited element during search, bug 46a2410650, s/a var-13.2}
|
||||
{array a} {aa 11 bb 22 cc 33 dd 44 ee 55 ff 66}
|
||||
body {
|
||||
set s [array startsearch a]
|
||||
unset a([array nextelement a $s])
|
||||
array anymore a $s
|
||||
}
|
||||
returnCodes error
|
||||
result {couldn't find search "s-1-a"}
|
||||
}
|
||||
test {
|
||||
name array-7.17
|
||||
desc {unset future element during search, bug 46a2410650, s/a var-13.3}
|
||||
{array a} {aa 11 bb 22 cc 33 dd 44 ee 55 ff 66}
|
||||
body {
|
||||
set result {}
|
||||
set s [array startsearch a]
|
||||
unset a(ee)
|
||||
array anymore a $s
|
||||
}
|
||||
returnCodes error
|
||||
result {couldn't find search "s-1-a"}
|
||||
}
|
||||
|
||||
# Cleanup.
|
||||
foreach namespace [namespace children] {
|
||||
if {$namespace ni $namespaces} {
|
||||
namespace delete $namespace
|
||||
}
|
||||
}
|
||||
foreach proc [info procs] {
|
||||
if {$proc ni $procs} {
|
||||
rename $proc {}
|
||||
}
|
||||
}
|
||||
foreach var [info vars] {
|
||||
if {$var ne "vars" && $var ni $vars} {
|
||||
unset $var
|
||||
}
|
||||
}
|
||||
unset -nocomplain var vars
|
||||
::tcltest::cleanupTests
|
||||
return
|
||||
|
||||
# vim: set sts=4 sw=4 tw=80 et ft=tcl:
|
||||
# Local Variables:
|
||||
# mode: tcl
|
||||
# End:
|
||||
+9
-7
@@ -23,7 +23,7 @@ cd [temporaryDirectory]
|
||||
testConstraint testsetplatform [llength [info commands testsetplatform]]
|
||||
testConstraint testchmod [llength [info commands testchmod]]
|
||||
testConstraint winVista 0
|
||||
testConstraint winXP 0
|
||||
testConstraint win2000orXP 0
|
||||
# Don't know how to determine this constraint correctly
|
||||
testConstraint notNetworkFilesystem 0
|
||||
testConstraint reg 0
|
||||
@@ -66,10 +66,12 @@ if {[testConstraint unix]} {
|
||||
# Also used in winFCmd...
|
||||
if {[testConstraint win]} {
|
||||
set major [string index $tcl_platform(osVersion) 0]
|
||||
if {$major > 5} {
|
||||
testConstraint winVista 1
|
||||
} else {
|
||||
testConstraint winXP 1
|
||||
if {[testConstraint nt] && $major > 4} {
|
||||
if {$major > 5} {
|
||||
testConstraint winVista 1
|
||||
} elseif {$major == 5} {
|
||||
testConstraint win2000orXP 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -790,7 +792,7 @@ test fCmd-9.3 {file rename: comprehensive: file to new name} -setup {
|
||||
} -result {{tf3 tf4} 1 0}
|
||||
test fCmd-9.4.a {file rename: comprehensive: dir to new name} -setup {
|
||||
cleanup
|
||||
} -constraints {win testchmod} -body {
|
||||
} -constraints {win win2000orXP testchmod} -body {
|
||||
file mkdir td1 td2
|
||||
testchmod 0o555 td2
|
||||
file rename td1 td3
|
||||
@@ -822,7 +824,7 @@ test fCmd-9.5 {file rename: comprehensive: file to self} -setup {
|
||||
} -result {tf1 tf2 1 0}
|
||||
test fCmd-9.6.a {file rename: comprehensive: dir to self} -setup {
|
||||
cleanup
|
||||
} -constraints {win winXP testchmod} -body {
|
||||
} -constraints {win win2000orXP testchmod} -body {
|
||||
file mkdir td1
|
||||
file mkdir td2
|
||||
testchmod 0o555 td2
|
||||
|
||||
+4
-4
@@ -283,7 +283,7 @@ test registry-4.7 {GetKeyNames: Unicode} {win reg english} {
|
||||
registry delete HKEY_CURRENT_USER\\TclFoobar
|
||||
set result
|
||||
} "baz\u00c7bar blat"
|
||||
test registry-4.8 {GetKeyNames: Unicode} {win reg} {
|
||||
test registry-4.8 {GetKeyNames: Unicode} {win reg nt} {
|
||||
registry delete HKEY_CURRENT_USER\\TclFoobar
|
||||
registry set HKEY_CURRENT_USER\\TclFoobar\\baz\u30b7bar
|
||||
registry set HKEY_CURRENT_USER\\TclFoobar\\blat
|
||||
@@ -487,7 +487,7 @@ test registry-6.17 {GetValue: Unicode value names} {win reg} {
|
||||
registry delete HKEY_CURRENT_USER\\TclFoobar
|
||||
set result
|
||||
} foobar
|
||||
test registry-6.18 {GetValue: values with Unicode strings} {win reg} {
|
||||
test registry-6.18 {GetValue: values with Unicode strings} {win reg nt} {
|
||||
registry set HKEY_CURRENT_USER\\TclFoobar val1 {foo ba\u30b7r baz} multi_sz
|
||||
set result [registry get HKEY_CURRENT_USER\\TclFoobar val1]
|
||||
registry delete HKEY_CURRENT_USER\\TclFoobar
|
||||
@@ -505,7 +505,7 @@ test registry-6.20 {GetValue: values with Unicode strings with embedded nulls} {
|
||||
registry delete HKEY_CURRENT_USER\\TclFoobar
|
||||
set result
|
||||
} "foo ba r baz"
|
||||
test registry-6.21 {GetValue: very long value names and values} {win reg} {
|
||||
test registry-6.21 {GetValue: very long value names and values} {pcOnly reg} {
|
||||
registry set HKEY_CURRENT_USER\\TclFoobar [string repeat k 16383] [string repeat x 16383] multi_sz
|
||||
set result [registry get HKEY_CURRENT_USER\\TclFoobar [string repeat k 16383]]
|
||||
registry delete HKEY_CURRENT_USER\\TclFoobar
|
||||
@@ -604,7 +604,7 @@ test registry-9.3 {ParseKeyName: bad keys} -constraints {win reg} -body {
|
||||
test registry-9.4 {ParseKeyName: bad keys} -constraints {win reg} -body {
|
||||
registry values \\\\\\
|
||||
} -returnCodes error -result {bad root name "": must be HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_CURRENT_CONFIG, HKEY_PERFORMANCE_DATA, or HKEY_DYN_DATA}
|
||||
test registry-9.5 {ParseKeyName: bad keys} -constraints {win reg english} -body {
|
||||
test registry-9.5 {ParseKeyName: bad keys} -constraints {win reg english nt} -body {
|
||||
registry values \\\\\\HKEY_CLASSES_ROOT
|
||||
} -returnCodes error -result {unable to open key: The network address is invalid.}
|
||||
test registry-9.6 {ParseKeyName: bad keys} -constraints {win reg} -body {
|
||||
|
||||
+10
-13
@@ -340,7 +340,7 @@ 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, donesearch, exists, get, names, nextelement, set, size, startsearch, statistics, or unset}}
|
||||
} {1 {unknown or ambiguous subcommand "gorp": must be anymore, 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
|
||||
@@ -369,7 +369,7 @@ test set-old-8.10 {array command, donesearch option, array doesn't exist yet but
|
||||
} {1 {"a" isn't an array}}
|
||||
test set-old-8.11 {array command, exists option} {
|
||||
list [catch {array exists a b} msg] $msg
|
||||
} {0 0}
|
||||
} {1 {wrong # args: should be "array exists arrayName"}}
|
||||
test set-old-8.12 {array command, exists option} {
|
||||
catch {unset a}
|
||||
array exists a
|
||||
@@ -390,10 +390,10 @@ test set-old-8.14 {array command, exists option, array doesn't exist yet but has
|
||||
} {0 0}
|
||||
test set-old-8.15 {array command, get option} {
|
||||
list [catch {array get} msg] $msg
|
||||
} {1 {wrong # args: should be "array get arrayName ?mode? ?pattern?"}}
|
||||
} {1 {wrong # args: should be "array get arrayName ?pattern?"}}
|
||||
test set-old-8.16 {array command, get option} {
|
||||
list [catch {array get a b c} msg] $msg
|
||||
} {1 {bad option "b": must be -exact, -glob, or -regexp}}
|
||||
} {1 {wrong # args: should be "array get arrayName ?pattern?"}}
|
||||
test set-old-8.17 {array command, get option} {
|
||||
catch {unset a}
|
||||
array get a
|
||||
@@ -560,7 +560,7 @@ test set-old-8.39 {array command, size option} {
|
||||
} {0}
|
||||
test set-old-8.40 {array command, size option} {
|
||||
list [catch {array size a 4} msg] $msg
|
||||
} {0 0}
|
||||
} {1 {wrong # args: should be "array size arrayName"}}
|
||||
test set-old-8.41 {array command, size option} {
|
||||
catch {unset a}
|
||||
array size a
|
||||
@@ -592,9 +592,8 @@ test set-old-8.45 {array command, size option, array doesn't exist yet but has c
|
||||
list [catch {foo 1} msg] $msg
|
||||
} {0 0}
|
||||
test set-old-8.46 {array command, startsearch option} {
|
||||
catch {unset a}
|
||||
list [catch {array startsearch a b} msg] $msg
|
||||
} {1 {"a" isn't an array}}
|
||||
} {1 {wrong # args: should be "array startsearch arrayName"}}
|
||||
test set-old-8.47 {array command, startsearch option} {
|
||||
catch {unset a}
|
||||
list [catch {array startsearch a} msg] $msg
|
||||
@@ -810,12 +809,10 @@ test set-old-9.12 {array enumeration with traced undefined elements} {
|
||||
|
||||
test set-old-10.1 {array enumeration errors} {
|
||||
list [catch {array start} msg] $msg
|
||||
} {1 {wrong # args: should be "array startsearch arrayName ?mode? ?pattern?"}}
|
||||
test set-old-10.2 {array command, startsearch option} {
|
||||
# Note: appears to be almost identical to set-old-8.47
|
||||
catch {unset a}
|
||||
list [catch {array start a} msg] $msg
|
||||
} {1 {"a" isn't an array}}
|
||||
} {1 {wrong # args: should be "array startsearch arrayName"}}
|
||||
test set-old-10.2 {array enumeration errors} {
|
||||
list [catch {array start a b} msg] $msg
|
||||
} {1 {wrong # args: should be "array startsearch arrayName"}}
|
||||
test set-old-10.3 {array enumeration errors} {
|
||||
catch {unset a}
|
||||
list [catch {array start a} msg] $msg
|
||||
|
||||
@@ -20,7 +20,6 @@ testConstraint testbytestring [llength [info commands testbytestring]]
|
||||
testConstraint testdstring [llength [info commands testdstring]]
|
||||
testConstraint testconcatobj [llength [info commands testconcatobj]]
|
||||
testConstraint testdoubledigits [llength [info commands testdoubledigits]]
|
||||
testConstraint testprint [llength [info commands testprint]]
|
||||
|
||||
# Big test for correct ordering of data in [expr]
|
||||
|
||||
@@ -4018,30 +4017,6 @@ test util-17.1 {bankers' rounding [Bug 3349507]} {ieeeFloatingPoint} {
|
||||
0x4400000000000000 0xc400000000000000
|
||||
}]
|
||||
|
||||
test util-18.1 {Tcl_ObjPrintf} {testprint} {
|
||||
testprint %lld [expr 2**63-1]
|
||||
} {9223372036854775807}
|
||||
|
||||
test util-18.2 {Tcl_ObjPrintf} {testprint} {
|
||||
testprint %I64d [expr 2**63-1]
|
||||
} {9223372036854775807}
|
||||
|
||||
test util-18.3 {Tcl_ObjPrintf} {testprint} {
|
||||
testprint %Ld [expr 2**63-1]
|
||||
} {9223372036854775807}
|
||||
|
||||
test util-18.4 {Tcl_ObjPrintf} {testprint} {
|
||||
testprint %lld [expr -2**63]
|
||||
} {-9223372036854775808}
|
||||
|
||||
test util-18.5 {Tcl_ObjPrintf} {testprint} {
|
||||
testprint %I64d [expr -2**63]
|
||||
} {-9223372036854775808}
|
||||
|
||||
test util-18.6 {Tcl_ObjPrintf} {testprint} {
|
||||
testprint %Ld [expr -2**63]
|
||||
} {-9223372036854775808}
|
||||
|
||||
set ::tcl_precision $saved_precision
|
||||
|
||||
# cleanup
|
||||
|
||||
+118
-19
@@ -22,6 +22,8 @@ if {"::tcltest" ni [namespace children]} {
|
||||
::tcltest::loadTestedCommands
|
||||
catch [list package require -exact Tcltest [info patchlevel]]
|
||||
|
||||
verbose [list line error skip start]
|
||||
|
||||
testConstraint testupvar [llength [info commands testupvar]]
|
||||
testConstraint testgetvarfullname [llength [info commands testgetvarfullname]]
|
||||
testConstraint testsetnoerr [llength [info commands testsetnoerr]]
|
||||
@@ -746,7 +748,7 @@ test var-11.3 {array unset errors} -setup {
|
||||
} -returnCodes error -body {
|
||||
array set a { 1,1 a 1,2 b }
|
||||
array unset a pattern too
|
||||
} -result {bad option "pattern": must be -exact, -glob, or -regexp}
|
||||
} -result {wrong # args: should be "array unset arrayName ?pattern?"}
|
||||
|
||||
test var-12.1 {TclFindCompiledLocals, {} array name} {
|
||||
namespace eval n {
|
||||
@@ -778,24 +780,6 @@ test var-13.1 {Tcl_UnsetVar2, unset array with trace set on element} -setup {
|
||||
set x "If you see this, it worked"
|
||||
} -result "If you see this, it worked"
|
||||
|
||||
test var-13.2 {unset array with search, bug 46a2410650} -body {
|
||||
apply {{} {
|
||||
array set a {aa 11 bb 22 cc 33 dd 44 ee 55 ff 66}
|
||||
set s [array startsearch a]
|
||||
unset a([array nextelement a $s])
|
||||
array nextelement a $s
|
||||
}}
|
||||
} -returnCodes error -result {couldn't find search "s-1-a"}
|
||||
|
||||
test var-13.3 {unset array with search, SIGSEGV, bug 46a2410650} -body {
|
||||
apply {{} {
|
||||
array set a {aa 11 bb 22 cc 33 dd 44 ee 55 ff 66}
|
||||
set s [array startsearch a]
|
||||
unset a(ff)
|
||||
array nextelement a $s
|
||||
}}
|
||||
} -returnCodes error -result {couldn't find search "s-1-a"}
|
||||
|
||||
test var-14.1 {array names syntax} -body {
|
||||
array names foo bar baz snafu
|
||||
} -returnCodes 1 -match glob -result *
|
||||
@@ -1015,6 +999,120 @@ test var-22.2 {leak in parsedVarName} -constraints memory -body {
|
||||
unset -nocomplain i x
|
||||
} -result 0
|
||||
|
||||
unset -nocomplain a k v
|
||||
test var-23.1 {array command, for loop} -returnCodes error -body {
|
||||
array for {k v} c d e {}
|
||||
} -result {wrong # args: should be "array for {keyVarName ?valueVarName?} array script"}
|
||||
test var-23.2 {array command, for loop} -returnCodes error -body {
|
||||
array for d {}
|
||||
} -result {wrong # args: should be "array for {keyVarName ?valueVarName?} array script"}
|
||||
test var-23.3 {array command, for loop, wrong # of list args} -setup {
|
||||
unset -nocomplain a
|
||||
} -returnCodes error -body {
|
||||
array for {k v w} a {}
|
||||
} -result {must have one or two variable names}
|
||||
test var-23.4 {array command, for loop, no array} -setup {
|
||||
unset -nocomplain a
|
||||
} -returnCodes error -body {
|
||||
array for {k v} a {}
|
||||
} -result {"a" isn't an array}
|
||||
test var-23.5 {array command, for loop, array doesn't exist yet but has compiler-allocated procedure slot} -setup {
|
||||
catch {rename p ""}
|
||||
} -returnCodes error -body {
|
||||
apply {{x} {
|
||||
if {$x==1} {
|
||||
return [array for {k v} a {}]
|
||||
}
|
||||
set a(x) 123
|
||||
}} 1
|
||||
} -result {"a" isn't an array}
|
||||
test var-23.6 {array enumeration} -setup {
|
||||
unset -nocomplain a
|
||||
unset -nocomplain reslist
|
||||
set reslist [list]
|
||||
} -body {
|
||||
array set a {a 1 b 2 c 3}
|
||||
array for {k v} a {
|
||||
lappend reslist $k $v
|
||||
}
|
||||
# if someone turns on varPtr->flags |= VAR_SEARCH_ACTIVE
|
||||
# a segmentation violation will result.
|
||||
unset a; # this should not cause a segmentation violation.
|
||||
# there is no guarantee in which order the array contents will be
|
||||
# returned.
|
||||
lsort -stride 2 -index 0 $reslist
|
||||
} -cleanup {
|
||||
unset -nocomplain a
|
||||
unset -nocomplain reslist
|
||||
} -result {a 1 b 2 c 3}
|
||||
test var-23.7 {array enumeration, without value} -setup {
|
||||
unset -nocomplain a
|
||||
set reslist [list]
|
||||
} -body {
|
||||
array set a {a 1 b 2 c 3}
|
||||
array for {k} a {
|
||||
lappend reslist $k
|
||||
}
|
||||
# there is no guarantee in which order the array contents will be
|
||||
# returned.
|
||||
lsort $reslist
|
||||
} -result {a b c}
|
||||
test var-23.8 {array enumeration, nested} -setup {
|
||||
unset -nocomplain a
|
||||
unset -nocomplain reslist
|
||||
set reslist [list]
|
||||
} -body {
|
||||
array set a {a 1 b 2 c 3}
|
||||
array for {k1 v1} a {
|
||||
lappend reslist $k1 $v1
|
||||
set r2 {}
|
||||
array for {k2 v2} a {
|
||||
lappend r2 $k2 $v2
|
||||
}
|
||||
lappend reslist [lsort -stride 2 -index 0 $r2]
|
||||
}
|
||||
# there is no guarantee in which order the array contents will be
|
||||
# returned.
|
||||
lsort -stride 3 -index 0 $reslist
|
||||
} -result {a 1 {a 1 b 2 c 3} b 2 {a 1 b 2 c 3} c 3 {a 1 b 2 c 3}}
|
||||
test var-23.9 {array enumeration, continue} -setup {
|
||||
unset -nocomplain a
|
||||
unset -nocomplain reslist
|
||||
set reslist [list]
|
||||
} -body {
|
||||
array set a {a 1 b 2 c 3}
|
||||
array for {k v} a {
|
||||
if { $k eq {b} } {
|
||||
continue
|
||||
}
|
||||
lappend reslist $k $v
|
||||
}
|
||||
# there is no guarantee in which order the array contents will be
|
||||
# returned.
|
||||
lsort -stride 2 -index 0 $reslist
|
||||
} -cleanup {
|
||||
unset -nocomplain a
|
||||
unset -nocomplain reslist
|
||||
} -result {a 1 c 3}
|
||||
test var-23.10 {array enumeration, break} -setup {
|
||||
unset -nocomplain a
|
||||
unset -nocomplain reslist
|
||||
set reslist [list]
|
||||
} -body {
|
||||
array set a {a 1 b 2 c 3}
|
||||
array for {k v} a {
|
||||
if { $k eq {b} } {
|
||||
break
|
||||
}
|
||||
lappend reslist $k $v
|
||||
}
|
||||
# there is no guarantee in which order the array contents will be
|
||||
# returned.
|
||||
lsort -stride 2 -index 0 $reslist
|
||||
} -cleanup {
|
||||
unset -nocomplain a
|
||||
unset -nocomplain reslist
|
||||
} -result {a 1}
|
||||
|
||||
catch {namespace delete ns}
|
||||
catch {unset arr}
|
||||
@@ -1029,6 +1127,7 @@ catch {unset x}
|
||||
catch {unset y}
|
||||
catch {unset i}
|
||||
catch {unset a}
|
||||
catch {unset reslist}
|
||||
catch {unset xxxxx}
|
||||
catch {unset aaaaa}
|
||||
|
||||
|
||||
+47
-25
@@ -21,7 +21,8 @@ catch [list package require -exact Tcltest [info patchlevel]]
|
||||
# Initialise the test constraints
|
||||
|
||||
testConstraint winVista 0
|
||||
testConstraint winXP 0
|
||||
testConstraint win2000orXP 0
|
||||
testConstraint winOlderThan2000 0
|
||||
testConstraint testvolumetype [llength [info commands testvolumetype]]
|
||||
testConstraint testfile [llength [info commands testfile]]
|
||||
testConstraint testchmod [llength [info commands testchmod]]
|
||||
@@ -55,12 +56,16 @@ proc cleanup {args} {
|
||||
}
|
||||
}
|
||||
|
||||
if {[testConstraint win]} {
|
||||
if {[testConstraint winOnly]} {
|
||||
set major [string index $tcl_platform(osVersion) 0]
|
||||
if {$major > 5} {
|
||||
testConstraint winVista 1
|
||||
} elseif {$major == 5} {
|
||||
testConstraint winXP 1
|
||||
if {[testConstraint nt] && $major > 4} {
|
||||
if {$major > 5} {
|
||||
testConstraint winVista 1
|
||||
} elseif {$major == 5} {
|
||||
testConstraint win2000orXP 1
|
||||
}
|
||||
} else {
|
||||
testConstraint winOlderThan2000 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,12 +205,17 @@ test winFCmd-1.12 {TclpRenameFile: errno: EACCES} -setup {
|
||||
} -returnCodes error -result EACCES
|
||||
test winFCmd-1.13 {TclpRenameFile: errno: EACCES} -setup {
|
||||
cleanup
|
||||
} -constraints {win winXP testfile} -body {
|
||||
} -constraints {win win2000orXP testfile} -body {
|
||||
testfile mv nul tf1
|
||||
} -returnCodes error -result EINVAL
|
||||
test winFCmd-1.14 {TclpRenameFile: errno: EACCES} -setup {
|
||||
cleanup
|
||||
} -constraints {win nt winOlderThan2000 testfile} -body {
|
||||
testfile mv nul tf1
|
||||
} -returnCodes error -result EACCES
|
||||
test winFCmd-1.15 {TclpRenameFile: errno: EEXIST} -setup {
|
||||
cleanup
|
||||
} -constraints {win testfile} -body {
|
||||
} -constraints {win nt testfile} -body {
|
||||
createfile tf1
|
||||
testfile mv tf1 nul
|
||||
} -returnCodes error -result EEXIST
|
||||
@@ -228,12 +238,19 @@ test winFCmd-1.18 {TclpRenameFile: srcAttr == -1} -setup {
|
||||
} -returnCodes error -result ENOENT
|
||||
test winFCmd-1.19 {TclpRenameFile: errno == EACCES} -setup {
|
||||
cleanup
|
||||
} -constraints {win winXP testfile} -body {
|
||||
} -constraints {win win2000orXP testfile} -body {
|
||||
testfile mv nul tf1
|
||||
} -returnCodes error -result EINVAL
|
||||
test winFCmd-1.19.1 {TclpRenameFile: errno == EACCES} -setup {
|
||||
cleanup
|
||||
} -constraints {win nt winOlderThan2000 testfile} -body {
|
||||
testfile mv nul tf1
|
||||
} -returnCodes error -result EACCES
|
||||
test winFCmd-1.20 {TclpRenameFile: src is dir} -setup {
|
||||
cleanup
|
||||
} -constraints {win testfile} -body {
|
||||
} -constraints {win nt testfile} -body {
|
||||
# under 95, this would actually succeed and move the current dir out from
|
||||
# under the current process!
|
||||
file delete /tf1
|
||||
testfile mv [pwd] /tf1
|
||||
} -returnCodes error -result EACCES
|
||||
@@ -441,9 +458,14 @@ test winFCmd-2.6 {TclpCopyFile: errno: ENOENT} -setup {
|
||||
} -returnCodes error -result ENOENT
|
||||
test winFCmd-2.7 {TclpCopyFile: errno: EACCES} -setup {
|
||||
cleanup
|
||||
} -constraints {win winXP testfile} -body {
|
||||
} -constraints {win win2000orXP testfile} -body {
|
||||
testfile cp nul tf1
|
||||
} -returnCodes error -result EINVAL
|
||||
test winFCmd-2.8 {TclpCopyFile: errno: EACCES} -setup {
|
||||
cleanup
|
||||
} -constraints {win nt winOlderThan2000 testfile} -body {
|
||||
testfile cp nul tf1
|
||||
} -returnCodes error -result EACCES
|
||||
test winFCmd-2.10 {TclpCopyFile: CopyFile succeeds} -setup {
|
||||
cleanup
|
||||
} -constraints {win testfile} -body {
|
||||
@@ -601,7 +623,7 @@ test winFCmd-3.11 {TclpDeleteFile: still can't remove path} -setup {
|
||||
|
||||
test winFCmd-4.1 {TclpCreateDirectory: errno: EACCES} -body {
|
||||
testfile mkdir $cdrom/dummy~~.dir
|
||||
} -constraints {win cdrom testfile} -returnCodes error -result EACCES
|
||||
} -constraints {win nt cdrom testfile} -returnCodes error -result EACCES
|
||||
test winFCmd-4.3 {TclpCreateDirectory: errno: EEXIST} -setup {
|
||||
cleanup
|
||||
} -constraints {win testfile} -body {
|
||||
@@ -699,7 +721,7 @@ test winFCmd-6.9 {TclpRemoveDirectory: errno == EACCES} -setup {
|
||||
} -result {td1 EACCES}
|
||||
test winFCmd-6.11 {TclpRemoveDirectory: attr == -1} -setup {
|
||||
cleanup
|
||||
} -constraints {win testfile} -body {
|
||||
} -constraints {win nt testfile} -body {
|
||||
testfile rmdir /
|
||||
# WinXP returns EEXIST, WinNT seems to return EACCES. No policy
|
||||
# decision has been made as to which is correct.
|
||||
@@ -797,7 +819,7 @@ test winFCmd-7.7 {TraverseWinTree: append \ to source if necessary} -setup {
|
||||
} -result {tf1}
|
||||
test winFCmd-7.9 {TraverseWinTree: append \ to source if necessary} -body {
|
||||
testfile rmdir $cdrom/
|
||||
} -constraints {win cdrom testfile} -returnCodes error -match glob \
|
||||
} -constraints {win nt cdrom testfile} -returnCodes error -match glob \
|
||||
-result {* EACCES}
|
||||
test winFCmd-7.10 {TraverseWinTree: can't read directory: handle == INVALID} \
|
||||
{win emptyTest} {
|
||||
@@ -835,7 +857,7 @@ test winFCmd-7.13 {TraverseWinTree: append \ to target if necessary} -setup {
|
||||
} -result {tf1}
|
||||
test winFCmd-7.15 {TraverseWinTree: append \ to target if necessary} -setup {
|
||||
cleanup
|
||||
} -constraints {win testfile} -body {
|
||||
} -constraints {win nt testfile} -body {
|
||||
file mkdir td1
|
||||
testfile cpdir td1 /
|
||||
} -cleanup {
|
||||
@@ -1050,7 +1072,7 @@ test winFCmd-12.5 {ConvertFileNameFormat: absolute path} -body {
|
||||
} -constraints {win} -result {/ /}
|
||||
test winFCmd-12.6 {ConvertFileNameFormat: absolute path with drive} -setup {
|
||||
catch {file delete -force -- c:/td1}
|
||||
} -constraints {win winXP} -body {
|
||||
} -constraints {win win2000orXP} -body {
|
||||
createfile c:/td1 {}
|
||||
string tolower [file attributes c:/td1 -longname]
|
||||
} -cleanup {
|
||||
@@ -1328,13 +1350,13 @@ test winFCmd-18.8 {Windows reserved path names} -constraints win -body {
|
||||
file normalize cOm1:
|
||||
} -result COM1
|
||||
|
||||
test winFCmd-19.1 {Windows extended path names} -constraints win -body {
|
||||
test winFCmd-19.1 {Windows extended path names} -constraints nt -body {
|
||||
file normalize //?/c:/windows/win.ini
|
||||
} -result //?/c:/windows/win.ini
|
||||
test winFCmd-19.2 {Windows extended path names} -constraints win -body {
|
||||
test winFCmd-19.2 {Windows extended path names} -constraints nt -body {
|
||||
file normalize //?/c:/windows/../windows/win.ini
|
||||
} -result //?/c:/windows/win.ini
|
||||
test winFCmd-19.3 {Windows extended path names} -constraints win -setup {
|
||||
test winFCmd-19.3 {Windows extended path names} -constraints nt -setup {
|
||||
set tmpfile [file join $::env(TEMP) tcl[string repeat x 20].tmp]
|
||||
set tmpfile [file normalize $tmpfile]
|
||||
} -body {
|
||||
@@ -1345,7 +1367,7 @@ test winFCmd-19.3 {Windows extended path names} -constraints win -setup {
|
||||
} -cleanup {
|
||||
catch {file delete $tmpfile}
|
||||
} -result [list 0 {}]
|
||||
test winFCmd-19.4 {Windows extended path names} -constraints win -setup {
|
||||
test winFCmd-19.4 {Windows extended path names} -constraints nt -setup {
|
||||
set tmpfile [file join $::env(TEMP) tcl[string repeat x 20].tmp]
|
||||
set tmpfile //?/[file normalize $tmpfile]
|
||||
} -body {
|
||||
@@ -1356,7 +1378,7 @@ test winFCmd-19.4 {Windows extended path names} -constraints win -setup {
|
||||
} -cleanup {
|
||||
catch {file delete $tmpfile}
|
||||
} -result [list 0 {}]
|
||||
test winFCmd-19.5 {Windows extended path names} -constraints win -setup {
|
||||
test winFCmd-19.5 {Windows extended path names} -constraints nt -setup {
|
||||
set tmpfile [file join $::env(TEMP) tcl[string repeat x 248].tmp]
|
||||
set tmpfile [file normalize $tmpfile]
|
||||
} -body {
|
||||
@@ -1367,7 +1389,7 @@ test winFCmd-19.5 {Windows extended path names} -constraints win -setup {
|
||||
} -cleanup {
|
||||
catch {file delete $tmpfile}
|
||||
} -result [list 0 {}]
|
||||
test winFCmd-19.6 {Windows extended path names} -constraints win -setup {
|
||||
test winFCmd-19.6 {Windows extended path names} -constraints nt -setup {
|
||||
set tmpfile [file join $::env(TEMP) tcl[string repeat x 248].tmp]
|
||||
set tmpfile //?/[file normalize $tmpfile]
|
||||
} -body {
|
||||
@@ -1378,7 +1400,7 @@ test winFCmd-19.6 {Windows extended path names} -constraints win -setup {
|
||||
} -cleanup {
|
||||
catch {file delete $tmpfile}
|
||||
} -result [list 0 {}]
|
||||
test winFCmd-19.7 {Windows extended path names} -constraints win -setup {
|
||||
test winFCmd-19.7 {Windows extended path names} -constraints nt -setup {
|
||||
set tmpfile [file join $::env(TEMP) "tcl[pid].tmp "]
|
||||
set tmpfile [file normalize $tmpfile]
|
||||
} -body {
|
||||
@@ -1389,7 +1411,7 @@ test winFCmd-19.7 {Windows extended path names} -constraints win -setup {
|
||||
} -cleanup {
|
||||
catch {file delete $tmpfile}
|
||||
} -result [list 0 {} [list tcl[pid].tmp]]
|
||||
test winFCmd-19.8 {Windows extended path names} -constraints win -setup {
|
||||
test winFCmd-19.8 {Windows extended path names} -constraints nt -setup {
|
||||
set tmpfile [file join $::env(TEMP) "tcl[pid].tmp "]
|
||||
set tmpfile //?/[file normalize $tmpfile]
|
||||
} -body {
|
||||
@@ -1401,7 +1423,7 @@ test winFCmd-19.8 {Windows extended path names} -constraints win -setup {
|
||||
catch {file delete $tmpfile}
|
||||
} -result [list 0 {} [list "tcl[pid].tmp "]]
|
||||
|
||||
test winFCmd-19.9 {Windows devices path names} -constraints win -body {
|
||||
test winFCmd-19.9 {Windows devices path names} -constraints nt -body {
|
||||
file normalize //./com1
|
||||
} -result //./com1
|
||||
|
||||
|
||||
+11
-7
@@ -21,19 +21,23 @@ catch [list package require -exact Tcltest [info patchlevel]]
|
||||
|
||||
testConstraint testvolumetype [llength [info commands testvolumetype]]
|
||||
testConstraint notNTFS 0
|
||||
testConstraint win2000 0
|
||||
|
||||
if {[testConstraint testvolumetype]} {
|
||||
testConstraint notNTFS [expr {[testvolumetype] eq "NTFS"}]
|
||||
}
|
||||
if {[testConstraint nt] && $::tcl_platform(osVersion) >= 5.0} {
|
||||
testConstraint win2000 1
|
||||
}
|
||||
|
||||
test winFile-1.1 {TclpGetUserHome} -constraints {win} -body {
|
||||
glob ~nosuchuser
|
||||
} -returnCodes error -result {user "nosuchuser" doesn't exist}
|
||||
test winFile-1.2 {TclpGetUserHome} -constraints {win nonPortable} -body {
|
||||
test winFile-1.2 {TclpGetUserHome} -constraints {win nt nonPortable} -body {
|
||||
# The administrator account should always exist.
|
||||
glob ~administrator
|
||||
} -match glob -result *
|
||||
test winFile-1.4 {TclpGetUserHome} {win nonPortable} {
|
||||
test winFile-1.4 {TclpGetUserHome} {win nt nonPortable} {
|
||||
catch {glob ~stanton@workgroup}
|
||||
} {0}
|
||||
|
||||
@@ -150,7 +154,7 @@ if {[testConstraint win]} {
|
||||
test winFile-4.0 {
|
||||
Enhanced NTFS user/group permissions: test no acccess
|
||||
} -constraints {
|
||||
win notNTFS
|
||||
win nt notNTFS win2000
|
||||
} -setup {
|
||||
set owner [getuser $fname]
|
||||
set user $::env(USERDOMAIN)\\$::env(USERNAME)
|
||||
@@ -165,7 +169,7 @@ test winFile-4.0 {
|
||||
test winFile-4.1 {
|
||||
Enhanced NTFS user/group permissions: test readable only
|
||||
} -constraints {
|
||||
win notNTFS
|
||||
win nt notNTFS
|
||||
} -setup {
|
||||
set user $::env(USERDOMAIN)\\$::env(USERNAME)
|
||||
} -body {
|
||||
@@ -176,7 +180,7 @@ test winFile-4.1 {
|
||||
test winFile-4.2 {
|
||||
Enhanced NTFS user/group permissions: test writable only
|
||||
} -constraints {
|
||||
win notNTFS
|
||||
win nt notNTFS
|
||||
} -setup {
|
||||
set user $::env(USERDOMAIN)\\$::env(USERNAME)
|
||||
} -body {
|
||||
@@ -188,7 +192,7 @@ test winFile-4.2 {
|
||||
test winFile-4.3 {
|
||||
Enhanced NTFS user/group permissions: test read+write
|
||||
} -constraints {
|
||||
win notNTFS
|
||||
win nt notNTFS
|
||||
} -setup {
|
||||
set user $::env(USERDOMAIN)\\$::env(USERNAME)
|
||||
} -body {
|
||||
@@ -201,7 +205,7 @@ test winFile-4.3 {
|
||||
test winFile-4.4 {
|
||||
Enhanced NTFS user/group permissions: test full access
|
||||
} -constraints {
|
||||
win notNTFS
|
||||
win nt notNTFS
|
||||
} -setup {
|
||||
set user $::env(USERDOMAIN)\\$::env(USERNAME)
|
||||
} -body {
|
||||
|
||||
+3
-3
@@ -74,11 +74,11 @@ test winpipe-1.2 {32 bit comprehensive tests: from big file} {win exec cat32} {
|
||||
exec $cat32 < $path(big) > $path(stdout) 2> $path(stderr)
|
||||
list [contents $path(stdout)] [contents $path(stderr)]
|
||||
} "{$big} stderr32"
|
||||
test winpipe-1.3 {32 bit comprehensive tests: a little from pipe} {win exec cat32} {
|
||||
test winpipe-1.3 {32 bit comprehensive tests: a little from pipe} {win nt exec cat32} {
|
||||
exec [interpreter] $path(more) < $path(little) | $cat32 > $path(stdout) 2> $path(stderr)
|
||||
list [contents $path(stdout)] [contents $path(stderr)]
|
||||
} {little stderr32}
|
||||
test winpipe-1.4 {32 bit comprehensive tests: a lot from pipe} {win exec cat32} {
|
||||
test winpipe-1.4 {32 bit comprehensive tests: a lot from pipe} {win nt exec cat32} {
|
||||
exec [interpreter] $path(more) < $path(big) | $cat32 > $path(stdout) 2> $path(stderr)
|
||||
list [contents $path(stdout)] [contents $path(stderr)]
|
||||
} "{$big} stderr32"
|
||||
@@ -171,7 +171,7 @@ test winpipe-1.21 {32 bit comprehensive tests: read/write application} \
|
||||
set r
|
||||
} "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
|
||||
|
||||
test winpipe-4.1 {Tcl_WaitPid} {win exec cat32} {
|
||||
test winpipe-4.1 {Tcl_WaitPid} {win nt exec cat32} {
|
||||
proc readResults {f} {
|
||||
global x result
|
||||
if { [eof $f] } {
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ tsdPerfGetObjCmd(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const
|
||||
|
||||
int
|
||||
Tsdperf_Init(Tcl_Interp *interp) {
|
||||
if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
|
||||
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -123,7 +123,7 @@ Pkga_Init(
|
||||
{
|
||||
int code;
|
||||
|
||||
if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
|
||||
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
code = Tcl_PkgProvide(interp, "Pkga", "1.0");
|
||||
|
||||
+2
-2
@@ -113,7 +113,7 @@ Pkgc_Init(
|
||||
{
|
||||
int code;
|
||||
|
||||
if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
|
||||
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
code = Tcl_PkgProvide(interp, "Pkgc", "1.7.2");
|
||||
@@ -150,7 +150,7 @@ Pkgc_SafeInit(
|
||||
{
|
||||
int code;
|
||||
|
||||
if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
|
||||
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
code = Tcl_PkgProvide(interp, "Pkgc", "1.7.2");
|
||||
|
||||
+2
-2
@@ -113,7 +113,7 @@ Pkgd_Init(
|
||||
{
|
||||
int code;
|
||||
|
||||
if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
|
||||
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
code = Tcl_PkgProvide(interp, "Pkgd", "7.3");
|
||||
@@ -150,7 +150,7 @@ Pkgd_SafeInit(
|
||||
{
|
||||
int code;
|
||||
|
||||
if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
|
||||
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
code = Tcl_PkgProvide(interp, "Pkgd", "7.3");
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ Pkge_Init(
|
||||
{
|
||||
static const char script[] = "if 44 {open non_existent}";
|
||||
|
||||
if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
|
||||
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return Tcl_EvalEx(interp, script, -1, 0);
|
||||
|
||||
@@ -96,7 +96,7 @@ Pkgooa_Init(
|
||||
* This worked in Tcl 8.6.0, and is expected
|
||||
* to keep working in all future Tcl 8.x releases.
|
||||
*/
|
||||
if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
|
||||
if (Tcl_InitStubs(interp, "8.5", 0) == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (tclStubsPtr == NULL) {
|
||||
|
||||
+1
-1
@@ -199,7 +199,7 @@ Pkgua_Init(
|
||||
int code, cmdIndex = 0;
|
||||
Tcl_Command *cmdTokens;
|
||||
|
||||
if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
|
||||
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
+15
-13
@@ -1507,10 +1507,11 @@ SetGroupAttribute(
|
||||
Tcl_DString ds;
|
||||
struct group *groupPtr = NULL;
|
||||
const char *string;
|
||||
int length;
|
||||
|
||||
string = TclGetString(attributePtr);
|
||||
string = TclGetStringFromObj(attributePtr, &length);
|
||||
|
||||
native = Tcl_UtfToExternalDString(NULL, string, attributePtr->length, &ds);
|
||||
native = Tcl_UtfToExternalDString(NULL, string, length, &ds);
|
||||
groupPtr = TclpGetGrNam(native); /* INTL: Native. */
|
||||
Tcl_DStringFree(&ds);
|
||||
|
||||
@@ -1573,10 +1574,11 @@ SetOwnerAttribute(
|
||||
Tcl_DString ds;
|
||||
struct passwd *pwPtr = NULL;
|
||||
const char *string;
|
||||
int length;
|
||||
|
||||
string = TclGetString(attributePtr);
|
||||
string = TclGetStringFromObj(attributePtr, &length);
|
||||
|
||||
native = Tcl_UtfToExternalDString(NULL, string, attributePtr->length, &ds);
|
||||
native = Tcl_UtfToExternalDString(NULL, string, length, &ds);
|
||||
pwPtr = TclpGetPwNam(native); /* INTL: Native. */
|
||||
Tcl_DStringFree(&ds);
|
||||
|
||||
@@ -1944,9 +1946,9 @@ TclpObjNormalizePath(
|
||||
int nextCheckpoint)
|
||||
{
|
||||
const char *currentPathEndPosition;
|
||||
int pathLen;
|
||||
char cur;
|
||||
const char *path = TclGetString(pathPtr);
|
||||
size_t pathLen = pathPtr->length;
|
||||
const char *path = TclGetStringFromObj(pathPtr, &pathLen);
|
||||
Tcl_DString ds;
|
||||
const char *nativePath;
|
||||
#ifndef NO_REALPATH
|
||||
@@ -2175,15 +2177,15 @@ TclUnixOpenTemporaryFile(
|
||||
{
|
||||
Tcl_DString template, tmp;
|
||||
const char *string;
|
||||
int fd;
|
||||
int len, fd;
|
||||
|
||||
/*
|
||||
* We should also check against making more then TMP_MAX of these.
|
||||
*/
|
||||
|
||||
if (dirObj) {
|
||||
string = TclGetString(dirObj);
|
||||
Tcl_UtfToExternalDString(NULL, string, dirObj->length, &template);
|
||||
string = TclGetStringFromObj(dirObj, &len);
|
||||
Tcl_UtfToExternalDString(NULL, string, len, &template);
|
||||
} else {
|
||||
Tcl_DStringInit(&template);
|
||||
Tcl_DStringAppend(&template, DefaultTempDir(), -1); /* INTL: native */
|
||||
@@ -2192,8 +2194,8 @@ TclUnixOpenTemporaryFile(
|
||||
TclDStringAppendLiteral(&template, "/");
|
||||
|
||||
if (basenameObj) {
|
||||
string = TclGetString(basenameObj);
|
||||
Tcl_UtfToExternalDString(NULL, string, basenameObj->length, &tmp);
|
||||
string = TclGetStringFromObj(basenameObj, &len);
|
||||
Tcl_UtfToExternalDString(NULL, string, len, &tmp);
|
||||
TclDStringAppendDString(&template, &tmp);
|
||||
Tcl_DStringFree(&tmp);
|
||||
} else {
|
||||
@@ -2204,8 +2206,8 @@ TclUnixOpenTemporaryFile(
|
||||
|
||||
#ifdef HAVE_MKSTEMPS
|
||||
if (extensionObj) {
|
||||
string = TclGetString(extensionObj);
|
||||
Tcl_UtfToExternalDString(NULL, string, extensionObj->length, &tmp);
|
||||
string = TclGetStringFromObj(extensionObj, &len);
|
||||
Tcl_UtfToExternalDString(NULL, string, len, &tmp);
|
||||
TclDStringAppendDString(&template, &tmp);
|
||||
fd = mkstemps(Tcl_DStringValue(&template), Tcl_DStringLength(&tmp));
|
||||
Tcl_DStringFree(&tmp);
|
||||
|
||||
+7
-8
@@ -262,15 +262,14 @@ TclpMatchInDirectory(
|
||||
DIR *d;
|
||||
Tcl_DirEntry *entryPtr;
|
||||
const char *dirName;
|
||||
size_t dirLength, nativeDirLen;
|
||||
int dirLength, nativeDirLen;
|
||||
int matchHidden, matchHiddenPat;
|
||||
Tcl_StatBuf statBuf;
|
||||
Tcl_DString ds; /* native encoding of dir */
|
||||
Tcl_DString dsOrig; /* utf-8 encoding of dir */
|
||||
|
||||
Tcl_DStringInit(&dsOrig);
|
||||
dirName = TclGetString(fileNamePtr);
|
||||
dirLength = fileNamePtr->length;
|
||||
dirName = TclGetStringFromObj(fileNamePtr, &dirLength);
|
||||
Tcl_DStringAppend(&dsOrig, dirName, dirLength);
|
||||
|
||||
/*
|
||||
@@ -938,6 +937,7 @@ TclpObjLink(
|
||||
*/
|
||||
|
||||
if (linkAction & TCL_CREATE_SYMBOLIC_LINK) {
|
||||
int targetLen;
|
||||
Tcl_DString ds;
|
||||
Tcl_Obj *transPtr;
|
||||
|
||||
@@ -951,8 +951,8 @@ TclpObjLink(
|
||||
if (transPtr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
target = TclGetString(transPtr);
|
||||
target = Tcl_UtfToExternalDString(NULL, target, transPtr->length, &ds);
|
||||
target = TclGetStringFromObj(transPtr, &targetLen);
|
||||
target = Tcl_UtfToExternalDString(NULL, target, targetLen, &ds);
|
||||
Tcl_DecrRefCount(transPtr);
|
||||
|
||||
if (symlink(target, src) != 0) {
|
||||
@@ -1080,7 +1080,7 @@ TclNativeCreateNativeRep(
|
||||
const char *str;
|
||||
Tcl_DString ds;
|
||||
Tcl_Obj *validPathPtr;
|
||||
size_t len;
|
||||
int len;
|
||||
|
||||
if (TclFSCwdIsNative()) {
|
||||
/*
|
||||
@@ -1105,8 +1105,7 @@ TclNativeCreateNativeRep(
|
||||
Tcl_IncrRefCount(validPathPtr);
|
||||
}
|
||||
|
||||
str = TclGetString(validPathPtr);
|
||||
len = validPathPtr->length;
|
||||
str = TclGetStringFromObj(validPathPtr, &len);
|
||||
Tcl_UtfToExternalDString(NULL, str, len, &ds);
|
||||
len = Tcl_DStringLength(&ds) + sizeof(char);
|
||||
if (strlen(Tcl_DStringValue(&ds)) < len - sizeof(char)) {
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ int
|
||||
Tclxttest_Init(
|
||||
Tcl_Interp *interp) /* Interpreter for application. */
|
||||
{
|
||||
if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
|
||||
if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
XtToolkitInitialize();
|
||||
|
||||
Reference in New Issue
Block a user