From 5702e695062ec36c3addd403d748af48164db8b1 Mon Sep 17 00:00:00 2001 From: dgp Date: Thu, 28 Apr 2011 14:39:42 +0000 Subject: New utility routines: TclIsSpaceProc() and TclCountSpaceRuns() Use to replace calls to isspace() and their /* INTL */ risk. --- ChangeLog | 29 ++++++++++++++++ generic/tclCmdMZ.c | 2 +- generic/tclInt.h | 3 ++ generic/tclListObj.c | 8 +---- generic/tclParse.c | 26 +++++++++++++- generic/tclStrToD.c | 6 ++-- generic/tclUtil.c | 95 +++++++++++++++++++++++++++++++++------------------- 7 files changed, 123 insertions(+), 46 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6cfe6d1..85fdf61 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +2011-04-28 Don Porter + + * generic/tclInt.h: New utility routines: + * generic/tclParse.c: TclIsSpaceProc() and + * generic/tclUtil.c: TclCountSpaceRuns() + + * generic/tclCmdMZ.c: Use new routines to replace calls to + * generic/tclListObj.c: isspace() and their /* INTL */ risk. + * generic/tclStrToD.c: + +2011-03-16 Jan Nijtmans + + * unix/tcl.m4: Make SHLIB_LD_LIBS='${LIBS}' the default and + * unix/configure: set to "" on per-platform necessary basis. + Backported from TEA, but kept all original platform code which was + removed from TEA. + +2011-03-14 Kevin B. Kenny + + * tools/tclZIC.tcl (onDayOfMonth): Allow for leading zeroes + in month and day so that tzdata2011d parses correctly. + * library/tzdata/America/Havana: + * library/tzdata/America/Juneau: + * library/tzdata/America/Santiago: + * library/tzdata/Europe/Istanbul: + * library/tzdata/Pacific/Apia: + * library/tzdata/Pacific/Easter: + * library/tzdata/Pacific/Honolulu: tzdata2011d + 2011-04-27 Don Porter * generic/tclListObj.c: FreeListInternalRep() cleanup. diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index 7c3855c..5390cf0 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -1643,7 +1643,7 @@ StringIsCmd( * if it is the first "element" that has the failure. */ - while (isspace(UCHAR(*p))) { /* INTL: ? */ + while (TclIsSpaceProc(*p)) { p++; } TclNewStringObj(tmpStr, string1, p-string1); diff --git a/generic/tclInt.h b/generic/tclInt.h index 0705492..a560fe8 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -2573,6 +2573,8 @@ MODULE_SCOPE void TclContinuationsEnterDerived(Tcl_Obj *objPtr, MODULE_SCOPE ContLineLoc* TclContinuationsGet(Tcl_Obj *objPtr); MODULE_SCOPE void TclContinuationsCopy(Tcl_Obj *objPtr, Tcl_Obj *originObjPtr); +MODULE_SCOPE int TclCountSpaceRuns(CONST char *bytes, int numBytes, + CONST char **endPtr); MODULE_SCOPE void TclDeleteNamespaceVars(Namespace *nsPtr); /* TIP #280 - Modified token based evulation, with line information. */ MODULE_SCOPE int TclEvalEx(Tcl_Interp *interp, const char *script, @@ -2659,6 +2661,7 @@ MODULE_SCOPE void TclInitObjSubsystem(void); MODULE_SCOPE void TclInitSubsystems(void); MODULE_SCOPE int TclInterpReady(Tcl_Interp *interp); MODULE_SCOPE int TclIsLocalScalar(const char *src, int len); +MODULE_SCOPE int TclIsSpaceProc(char byte); MODULE_SCOPE int TclJoinThread(Tcl_ThreadId id, int *result); MODULE_SCOPE void TclLimitRemoveAllHandlers(Tcl_Interp *interp); MODULE_SCOPE Tcl_Obj * TclLindexList(Tcl_Interp *interp, diff --git a/generic/tclListObj.c b/generic/tclListObj.c index 3b9dce6..d3465b0 100644 --- a/generic/tclListObj.c +++ b/generic/tclListObj.c @@ -1765,13 +1765,7 @@ SetListFromAny( * elements by counting the number of space characters in the list. */ - limit = string + length; - estCount = 1; - for (p = string; p < limit; p++) { - if (isspace(UCHAR(*p))) { /* INTL: ISO space. */ - estCount++; - } - } + estCount = TclCountSpaceRuns(string, length, &limit) + 1; /* * Allocate a new List structure with enough room for "estCount" elements. diff --git a/generic/tclParse.c b/generic/tclParse.c index 94d9c50..4e1e8b0 100644 --- a/generic/tclParse.c +++ b/generic/tclParse.c @@ -610,6 +610,30 @@ Tcl_ParseCommand( /* *---------------------------------------------------------------------- * + * TclIsSpaceProc -- + * + * Report whether byte is in the set of whitespace characters used by + * Tcl to separate words in scripts or elements in lists. + * + * Results: + * Returns 1, if byte is in the set, 0 otherwise. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TclIsSpaceProc( + char byte) +{ + return CHAR_TYPE(byte) & (TYPE_SPACE) || byte == '\n'; +} + +/* + *---------------------------------------------------------------------- + * * ParseWhiteSpace -- * * Scans up to numBytes bytes starting at src, consuming white space @@ -1758,7 +1782,7 @@ Tcl_ParseBraces( openBrace = 0; break; case '#' : - if (openBrace && isspace(UCHAR(src[-1]))) { + if (openBrace && TclIsSpaceProc(src[-1])) { Tcl_AppendResult(parsePtr->interp, ": possible unbalanced brace in comment", NULL); goto error; diff --git a/generic/tclStrToD.c b/generic/tclStrToD.c index 139b8f2..e8b7538 100755 --- a/generic/tclStrToD.c +++ b/generic/tclStrToD.c @@ -536,7 +536,7 @@ TclParseNumber( * I, N, and whitespace. */ - if (isspace(UCHAR(c))) { + if (TclIsSpaceProc(c)) { if (flags & TCL_PARSE_NO_WHITESPACE) { goto endgame; } @@ -1050,7 +1050,7 @@ TclParseNumber( } /* FALLTHROUGH */ case sNANPAREN: - if (isspace(UCHAR(c))) { + if (TclIsSpaceProc(c)) { break; } if (numSigDigs < 13) { @@ -1101,7 +1101,7 @@ TclParseNumber( * Accept trailing whitespace. */ - while (len != 0 && isspace(UCHAR(*p))) { + while (len != 0 && TclIsSpaceProc(*p)) { p++; len--; } diff --git a/generic/tclUtil.c b/generic/tclUtil.c index b3e1e08..4a7f79f 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -89,6 +89,58 @@ Tcl_ObjType tclEndOffsetType = { /* *---------------------------------------------------------------------- * + * TclCountSpaceRuns -- + * + * Given 'bytes' pointing to 'numBytes' bytes, scan through them and + * count the number of whitespace runs that could be list element + * separators. If 'numBytes' is -1, scan to the terminating '\0'. + * + * Results: + * Returns the count. If 'endPtr' is not NULL, writes a pointer to + * the end of the string scanned there. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TclCountSpaceRuns( + CONST char *bytes, + int numBytes, + CONST char **endPtr) +{ + int count = 0; + + while (numBytes) { + if ((numBytes == -1) && (*bytes == '\0')) { + break; + } + if (TclIsSpaceProc(*bytes)) { + /* Space run started; bump count */ + count++; + do { + bytes++; + numBytes -= (numBytes != -1); + } while (numBytes && TclIsSpaceProc(*bytes)); + if (numBytes == 0) { + break; + } + /* (*bytes) is non-space; return to counting state */ + } + bytes++; + numBytes -= (numBytes != -1); + } + if (endPtr) { + *endPtr = bytes; + } + return count; +} + +/* + *---------------------------------------------------------------------- + * * TclFindElement -- * * Given a pointer into a Tcl list, locate the first (or next) element in @@ -155,7 +207,7 @@ TclFindElement( */ limit = (list + listLength); - while ((p < limit) && (isspace(UCHAR(*p)))) { /* INTL: ISO space. */ + while ((p < limit) && (TclIsSpaceProc(*p))) { p++; } if (p == limit) { /* no element found */ @@ -203,8 +255,7 @@ TclFindElement( } else if (openBraces == 1) { size = (p - elemStart); p++; - if ((p >= limit) - || isspace(UCHAR(*p))) { /* INTL: ISO space. */ + if ((p >= limit) || TclIsSpaceProc(*p)) { goto done; } @@ -214,8 +265,7 @@ TclFindElement( if (interp != NULL) { p2 = p; - while ((p2 < limit) - && (!isspace(UCHAR(*p2))) /* INTL: ISO space. */ + while ((p2 < limit) && (!TclIsSpaceProc(*p2)) && (p2 < p+20)) { p2++; } @@ -262,8 +312,7 @@ TclFindElement( if (inQuotes) { size = (p - elemStart); p++; - if ((p >= limit) - || isspace(UCHAR(*p))) { /* INTL: ISO space */ + if ((p >= limit) || TclIsSpaceProc(*p)) { goto done; } @@ -273,8 +322,7 @@ TclFindElement( if (interp != NULL) { p2 = p; - while ((p2 < limit) - && (!isspace(UCHAR(*p2))) /* INTL: ISO space */ + while ((p2 < limit) && (!TclIsSpaceProc(*p2)) && (p2 < p+20)) { p2++; } @@ -311,7 +359,7 @@ TclFindElement( } done: - while ((p < limit) && (isspace(UCHAR(*p)))) { /* INTL: ISO space. */ + while ((p < limit) && (TclIsSpaceProc(*p))) { p++; } *elementPtr = elemStart; @@ -409,7 +457,7 @@ Tcl_SplitList( CONST char ***argvPtr) /* Pointer to place to store pointer to array * of pointers to list elements. */ { - CONST char **argv, *l, *element; + CONST char **argv, *end, *element; char *p; int length, size, i, result, elSize, brace; @@ -420,29 +468,8 @@ Tcl_SplitList( * the list. */ - for (size = 2, l = list; *l != 0; l++) { - if (isspace(UCHAR(*l))) { /* INTL: ISO space. */ - size++; - - /* - * Consecutive space can only count as a single list delimiter. - */ - - while (1) { - char next = *(l + 1); - - if (next == '\0') { - break; - } - ++l; - if (isspace(UCHAR(next))) { /* INTL: ISO space. */ - continue; - } - break; - } - } - } - length = l - list; + size = TclCountSpaceRuns(list, -1, &end) + 2; + length = end - list; argv = (CONST char **) ckalloc((unsigned) ((size * sizeof(char *)) + length + 1)); for (i = 0, p = ((char *) argv) + size*sizeof(char *); -- cgit v0.12