Compare commits

..
47 changed files with 1980 additions and 3481 deletions
-333
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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]);
}
+218
View File
@@ -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. */
+8 -8
View File
@@ -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;
}
+5 -2
View File
@@ -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
View File
@@ -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) */
+6 -2
View File
@@ -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);
}
+5 -5
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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)
-1
View File
@@ -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
View File
@@ -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
View File
@@ -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 */
-19
View File
@@ -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
View File
@@ -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. */
+5 -9
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -373,7 +373,7 @@ ConvertErrorToList(
default:
TclNewLiteralStringObj(objv[2], "UNKNOWN");
TclNewLongObj(objv[3], code);
TclNewIntObj(objv[3], code);
return Tcl_NewListObj(4, objv);
}
}
-888
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
-25
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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();