Compare commits

...
Author SHA1 Message Date
jan.nijtmans 4c1337af19 Start handling 'last' arguments 2022-04-01 15:28:00 +00:00
jan.nijtmans 1316902df3 Undo (unnecessary) change in tclMain.c 2022-04-01 07:32:21 +00:00
jan.nijtmans 170c2e99c3 Merge 8.7 2022-04-01 07:13:51 +00:00
jan.nijtmans 62a5728e7e Fix build 2022-02-27 18:43:19 +00:00
jan.nijtmans f8cf535224 Merge 8.7 2022-02-25 14:44:38 +00:00
jan.nijtmans c0b4d70936 Merge 8.7 2022-02-16 14:18:00 +00:00
jan.nijtmans 3b8a107562 Merge 8.7 2022-02-09 22:12:52 +00:00
jan.nijtmans 228b96efc2 Merge 8.7 2022-02-09 16:36:43 +00:00
jan.nijtmans e8a4a7434f Merge 8.7 2022-02-02 16:51:03 +00:00
jan.nijtmans e212baf6fd code alignment 2022-01-31 12:04:27 +00:00
jan.nijtmans ebcccacc43 Merge 8.7 2022-01-31 11:49:51 +00:00
jan.nijtmans 96d253aab7 Merge 8.7 2022-01-18 23:53:50 +00:00
jan.nijtmans 0e0dffb596 TIP #615: string is index. WIP 2022-01-18 14:40:01 +00:00
9 changed files with 76 additions and 32 deletions
+4
View File
@@ -2687,6 +2687,10 @@ Tcl_LrangeObjCmd(
if (result != TCL_OK) {
return result;
}
if ((last == -1) && Tcl_GetString(objv[3])[0] == '\0') {
/* TIP #615: empty string for 'last' means 'end' */
last = listLen - 1;
}
Tcl_SetObjResult(interp, TclListObjRange(objv[1], first, last));
return TCL_OK;
+26 -8
View File
@@ -1531,18 +1531,18 @@ StringIsCmd(
static const char *const isClasses[] = {
"alnum", "alpha", "ascii", "control",
"boolean", "dict", "digit", "double",
"entier", "false", "graph", "integer",
"list", "lower", "print", "punct",
"space", "true", "upper", "unicode",
"wideinteger", "wordchar", "xdigit", NULL
"entier", "false", "graph", "index",
"integer", "list", "lower", "print",
"punct", "space", "true", "upper",
"unicode", "wideinteger", "wordchar", "xdigit", NULL
};
enum isClassesEnum {
STR_IS_ALNUM, STR_IS_ALPHA, STR_IS_ASCII, STR_IS_CONTROL,
STR_IS_BOOL, STR_IS_DICT, STR_IS_DIGIT, STR_IS_DOUBLE,
STR_IS_ENTIER, STR_IS_FALSE, STR_IS_GRAPH, STR_IS_INT,
STR_IS_LIST, STR_IS_LOWER, STR_IS_PRINT, STR_IS_PUNCT,
STR_IS_SPACE, STR_IS_TRUE, STR_IS_UPPER, STR_IS_UNICODE,
STR_IS_WIDE, STR_IS_WORD, STR_IS_XDIGIT
STR_IS_ENTIER, STR_IS_FALSE, STR_IS_GRAPH, STR_IS_INDEX,
STR_IS_INT, STR_IS_LIST, STR_IS_LOWER, STR_IS_PRINT,
STR_IS_PUNCT, STR_IS_SPACE, STR_IS_TRUE, STR_IS_UPPER,
STR_IS_UNICODE, STR_IS_WIDE, STR_IS_WORD, STR_IS_XDIGIT
};
static const char *const isOptions[] = {
"-strict", "-failindex", NULL
@@ -1710,6 +1710,16 @@ StringIsCmd(
case STR_IS_GRAPH:
chcomp = Tcl_UniCharIsGraph;
break;
case STR_IS_INDEX:
if (TclHasInternalRep(objPtr, &tclIntType) ||
TclHasInternalRep(objPtr, &tclEndOffsetType) ||
TclHasInternalRep(objPtr, &tclBignumType)) {
break;
}
if (Tcl_GetIntForIndex(NULL, objPtr, 0, &i) != TCL_OK) {
result = 0;
}
break;
case STR_IS_INT:
case STR_IS_ENTIER:
if (TclHasInternalRep(objPtr, &tclIntType) ||
@@ -2299,6 +2309,10 @@ StringRangeCmd(
TclGetIntForIndexM(interp, objv[3], length, &last) != TCL_OK) {
return TCL_ERROR;
}
if ((last == -1) && Tcl_GetString(objv[3])[0] == '\0') {
/* TIP #615: empty string for 'last' means 'end' */
last = length;
}
if (last >= 0) {
Tcl_SetObjResult(interp, Tcl_GetRange(objv[1], first, last));
@@ -2401,6 +2415,10 @@ StringRplcCmd(
TclGetIntForIndexM(interp, objv[3], end, &last) != TCL_OK) {
return TCL_ERROR;
}
if ((last == -1) && Tcl_GetString(objv[3])[0] == '\0') {
/* TIP #615: empty string for 'last' means 'end' */
last = end;
}
/*
* The following test screens out most empty substrings as candidates for
+10 -8
View File
@@ -506,18 +506,18 @@ TclCompileStringIsCmd(
static const char *const isClasses[] = {
"alnum", "alpha", "ascii", "control",
"boolean", "dict", "digit", "double",
"entier", "false", "graph", "integer",
"list", "lower", "print", "punct",
"space", "true", "upper", "unicode",
"wideinteger", "wordchar", "xdigit", NULL
"entier", "false", "graph", "index",
"integer", "list", "lower", "print",
"punct", "space", "true", "upper",
"unicode", "wideinteger", "wordchar", "xdigit", NULL
};
enum isClassesEnum {
STR_IS_ALNUM, STR_IS_ALPHA, STR_IS_ASCII, STR_IS_CONTROL,
STR_IS_BOOL, STR_IS_DICT, STR_IS_DIGIT, STR_IS_DOUBLE,
STR_IS_ENTIER, STR_IS_FALSE, STR_IS_GRAPH, STR_IS_INT,
STR_IS_LIST, STR_IS_LOWER, STR_IS_PRINT, STR_IS_PUNCT,
STR_IS_SPACE, STR_IS_TRUE, STR_IS_UPPER, STR_IS_UNICODE,
STR_IS_WIDE, STR_IS_WORD, STR_IS_XDIGIT
STR_IS_ENTIER, STR_IS_FALSE, STR_IS_GRAPH, STR_IS_INDEX,
STR_IS_INT, STR_IS_LIST, STR_IS_LOWER, STR_IS_PRINT,
STR_IS_PUNCT, STR_IS_SPACE, STR_IS_TRUE, STR_IS_UPPER,
STR_IS_UNICODE, STR_IS_WIDE, STR_IS_WORD, STR_IS_XDIGIT
};
int t, range, allowEmpty = 0, end;
InstStringClassType strClassType;
@@ -713,6 +713,8 @@ TclCompileStringIsCmd(
FIXJUMP1( end);
return TCL_OK;
}
case STR_IS_INDEX:
return TCL_ERROR;
case STR_IS_INT:
case STR_IS_WIDE:
+1
View File
@@ -2766,6 +2766,7 @@ MODULE_SCOPE const Tcl_ObjType tclBooleanType;
MODULE_SCOPE const Tcl_ObjType tclByteArrayType;
MODULE_SCOPE const Tcl_ObjType tclByteCodeType;
MODULE_SCOPE const Tcl_ObjType tclDoubleType;
MODULE_SCOPE const Tcl_ObjType tclEndOffsetType;
MODULE_SCOPE const Tcl_ObjType tclIntType;
MODULE_SCOPE const Tcl_ObjType tclListType;
MODULE_SCOPE const Tcl_ObjType tclDictType;
+3 -2
View File
@@ -1441,11 +1441,12 @@ TclLsetList(
/*
* Determine whether the index arg designates a list or a single index.
* We have to be careful about the order of the checks to avoid repeated
* shimmering; see TIP #22 and #23 for details.
* shimmering; see TIP #22 and #23 for details. Don't allow "" as single
* index here, since it cannot be distinguished from an empty list.
*/
ListGetInternalRep(indexArgPtr, listRepPtr);
if (listRepPtr == NULL
if (listRepPtr == NULL && Tcl_GetString(indexArgPtr)[0]
&& TclGetIntForIndexM(NULL, indexArgPtr, INT_MAX - 1, &index) == TCL_OK) {
/*
* indexArgPtr designates a single index.
+26 -9
View File
@@ -124,19 +124,31 @@ static int FindElement(Tcl_Interp *interp, const char *string,
* performance optimization in Tcl_GetIntForIndex. The internal rep is
* stored directly in the wideValue, so no memory management is required
* for it. This is a caching internalrep, keeping the result of a parse
* around. This type is only created from a pre-existing string, so an
* updateStringProc will never be called and need not exist. The type
* is unregistered, so has no need of a setFromAnyProc either.
* around. The type is unregistered, so has no need of a setFromAnyProc.
*/
static const Tcl_ObjType endOffsetType = {
static void
UpdateStringOfIndex(
Tcl_Obj *objPtr) /* Index object whose string rep to update. */
{
/* The only situation that the string rep can be missing is when it
* represents TCL_INDEX_NONE. In all other situations, the string
* rep is never thrown away. See TclNewIndexObj() */
if ((objPtr)->internalRep.wideValue != WIDE_MIN) {
Tcl_Panic("String rep of index %" TCL_LL_MODIFIER "d cannot be generated",
(long long)(objPtr)->internalRep.wideValue);
}
TclInitStringRep(objPtr, NULL, 0);
}
const Tcl_ObjType tclEndOffsetType = {
"end-offset", /* name */
NULL, /* freeIntRepProc */
NULL, /* dupIntRepProc */
NULL, /* updateStringProc */
UpdateStringOfIndex, /* updateStringProc */
NULL /* setFromAnyProc */
};
/*
* * STRING REPRESENTATION OF LISTS * * *
*
@@ -3758,7 +3770,7 @@ GetEndOffsetFromObj(
Tcl_WideInt offset = -1; /* Offset in the "end-offset" expression - 1 */
ClientData cd;
while ((irPtr = TclFetchInternalRep(objPtr, &endOffsetType)) == NULL) {
while ((irPtr = TclFetchInternalRep(objPtr, &tclEndOffsetType)) == NULL) {
Tcl_ObjInternalRep ir;
int length;
const char *bytes = TclGetStringFromObj(objPtr, &length);
@@ -3770,6 +3782,11 @@ GetEndOffsetFromObj(
/* Value doesn't start with "e" */
if (length == 0) {
offset = WIDE_MIN;
goto parseOK;
}
/* If we reach here, the string rep of objPtr exists. */
/*
@@ -3944,7 +3961,7 @@ GetEndOffsetFromObj(
parseOK:
/* Success. Store the new internal rep. */
ir.wideValue = offset;
Tcl_StoreInternalRep(objPtr, &endOffsetType, &ir);
Tcl_StoreInternalRep(objPtr, &tclEndOffsetType, &ir);
}
offset = irPtr->wideValue;
@@ -4049,7 +4066,7 @@ TclIndexEncode(
int idx;
if (TCL_OK == GetWideForIndex(interp, objPtr, (unsigned)TCL_INDEX_END , &wide)) {
const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objPtr, &endOffsetType);
const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objPtr, &tclEndOffsetType);
if (irPtr && irPtr->wideValue >= 0) {
/* "int[+-]int" syntax, works the same here as "int" */
irPtr = NULL;
+1 -1
View File
@@ -46,7 +46,7 @@ test lpop-1.6 {error conditions} -returnCodes error -body {
test lpop-1.7 {error conditions} -returnCodes error -body {
set l "x y"
lpop l {}
} -match glob -result {bad index *}
} -result {index "" out of range}
test lpop-1.8 {error conditions} -returnCodes error -body {
set l "x y"
lpop l 0 0 0 0 1
+4 -3
View File
@@ -529,10 +529,10 @@ test string-6.4.$noComp {string is, too many args} {
} {1 {wrong # args: should be "string is class ?-strict? ?-failindex var? str"}}
test string-6.5.$noComp {string is, class check} {
list [catch {run {string is bogus str}} msg] $msg
} {1 {bad class "bogus": must be alnum, alpha, ascii, control, boolean, dict, digit, double, entier, false, graph, integer, list, lower, print, punct, space, true, upper, unicode, wideinteger, wordchar, or xdigit}}
} {1 {bad class "bogus": must be alnum, alpha, ascii, control, boolean, dict, digit, double, entier, false, graph, index, integer, list, lower, print, punct, space, true, upper, unicode, wideinteger, wordchar, or xdigit}}
test string-6.6.$noComp {string is, ambiguous class} {
list [catch {run {string is al str}} msg] $msg
} {1 {ambiguous class "al": must be alnum, alpha, ascii, control, boolean, dict, digit, double, entier, false, graph, integer, list, lower, print, punct, space, true, upper, unicode, wideinteger, wordchar, or xdigit}}
} {1 {ambiguous class "al": must be alnum, alpha, ascii, control, boolean, dict, digit, double, entier, false, graph, index, integer, list, lower, print, punct, space, true, upper, unicode, wideinteger, wordchar, or xdigit}}
test string-6.7.$noComp {string is alpha, all ok} {
run {string is alpha -strict -failindex var abc}
} 1
@@ -2031,6 +2031,7 @@ test string-23.1.$noComp {string is command with empty string} {
[run {string is double $s}] \
[run {string is false $s}] \
[run {string is graph $s}] \
[run {string is index $s}] \
[run {string is integer $s}] \
[run {string is lower $s}] \
[run {string is print $s}] \
@@ -2041,7 +2042,7 @@ test string-23.1.$noComp {string is command with empty string} {
[run {string is wordchar $s}] \
[run {string is xdigit $s}] \
} {1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1}
} {1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1}
test string-23.2.$noComp {string is command with empty string} {
set s ""
list \
+1 -1
View File
@@ -696,7 +696,7 @@ test util-9.18 {Tcl_GetIntForIndex} {
} b
test util-9.19 {Tcl_GetIntForIndex} -body {
string index a {}
} -returnCodes error -match glob -result *
} -result {}
test util-9.20 {Tcl_GetIntForIndex} -body {
string index a { }
} -returnCodes error -match glob -result *