From 0481e3ca74a06381151d36ed72e32d8c12c7c29d Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 9 Jan 2013 10:30:00 +0000 Subject: New function Tcl_InitSubsystems, still to be TIP'ed --- doc/FindExec.3 | 54 ++++++++++++++++++++++++++++++++++++++++++++-- doc/InitStubs.3 | 4 ++++ generic/tcl.h | 10 ++++++++- generic/tclEncoding.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++- generic/tclStubLib.c | 55 +++++++++++++++++++++++++--------------------- 5 files changed, 154 insertions(+), 29 deletions(-) diff --git a/doc/FindExec.3 b/doc/FindExec.3 index e4b4ed0..216588c 100644 --- a/doc/FindExec.3 +++ b/doc/FindExec.3 @@ -8,7 +8,7 @@ .TH Tcl_FindExecutable 3 8.1 Tcl "Tcl Library Procedures" .BS .SH NAME -Tcl_FindExecutable, Tcl_GetNameOfExecutable \- identify or return the name of the binary file containing the application +Tcl_FindExecutable, Tcl_GetNameOfExecutable, Tcl_InitSubsystems \- identify or return the name of the binary file containing the application .SH SYNOPSIS .nf \fB#include \fR @@ -18,11 +18,18 @@ void .sp const char * \fBTcl_GetNameOfExecutable\fR() +.sp +Tcl_Interp * +\fBTcl_InitSubsystems\fR(\fIflags\fR, \fI...\fR) .SH ARGUMENTS .AS char *argv0 .AP char *argv0 in The first command-line argument to the program, which gives the application's name. +.AP int flags in +Any combination of TCL_INIT_PANIC or TCL_INIT_CREATE, which indicate +whether a custom panicProc is registered and/or a real interpreter is created. +The value 0 can be used if Tcl is used as utility library only. .BE .SH DESCRIPTION @@ -58,6 +65,49 @@ internal full path name of the executable file as computed by equivalent to the \fBinfo nameofexecutable\fR command. NULL is returned if the internal full path name has not been computed or unknown. - +.PP +The \fBTcl_InitSubsystems\fR can be used as alternative to +\fBTcl_FindExecutable\fR, when more flexibility is required. +Its flags control exactly what is initialized. +.PP +The call \fBTcl_InitSubsystems(0)\fR does the same as +\fBTcl_FindExecutable(NULL)\fR, except that a Tcl_Interp * +is returned which can be used only by \fBTcl_InitStubs\fR +to initialize the stub table. This opens up the Tcl Stub +technology for Tcl embedders, which now can dynamically +load the Tcl shared library and use functions in it +without ever creating an interpreter. E.g. the +following code can be compiled with -DUSE_TCL_STUBS: +.CS + handle = dlopen("libtcl8.6.so", RTLD_NOW|RTLD_LOCAL); + initSubSystems = dlsym(handle, "Tcl_InitSubsystems"); + interp = initSubSystems(0); /* not a real interpreter */ + Tcl_InitStubs(interp, NULL, 0); /* initialize the stub table */ + interp = Tcl_CreateInterp(); /* now we have a real interpreter */ +.CE +The function \fBTcl_CreateInterp\fR, or any other Tcl function you +would like to call, no longer needs to be searched for in the +shared library. It can be called directly though the stub table. +.PP +If you supply the flag TCL_INIT_PANIC to \fBTcl_InitSubsystems\fR, +the function expects an additional argument, a custom panicProc. +This is equivalent to calling \fBTcl_SetPanicProc\fR immediately +before \fBTcl_InitSubsystems\fR. +.PP +If you supply the flag TCL_INIT_CREATE to \fBTcl_InitSubsystems\fR, +the function gets two additional parameters, argc and argv. A real +Tcl interpreter will be created and if argc > 0 then the variables +"argc" and "argv" will be set in this interpreter. So, the above +example code could be simplified to: +.CS + handle = dlopen("libtcl8.6.so", RTLD_NOW|RTLD_LOCAL); + initSubSystems = dlsym(handle, "Tcl_InitSubsystems"); + interp = initSubSystems(TCL_INIT_CREATE, 0, NULL); /* real interpreter */ + Tcl_InitStubs(interp, NULL, 0); /* initialize the stub table */ +.CE +.PP +The interpreter returned by Tcl_InitSubsystems(0) cannot be passed to +any other function than Tcl_InitStubs(). Tcl functions with an "interp" +argument can only be called if this function supports passing NULL. .SH KEYWORDS binary, executable file diff --git a/doc/InitStubs.3 b/doc/InitStubs.3 index 4dc62c6..8188b0b 100644 --- a/doc/InitStubs.3 +++ b/doc/InitStubs.3 @@ -83,6 +83,10 @@ non-zero means that only the specified \fIversion\fR is acceptable. \fBTcl_InitStubs\fR returns a string containing the actual version of Tcl satisfying the request, or NULL if the Tcl version is not acceptable, does not support stubs, or any other error condition occurred. +.PP +If \fBTcl_InitStubs\fR is called with as first argument the +pseudo interpreter returned by \fBTcl_InitSubsystems(0)\fR, then +the \fIversion\fR and \fIexact\fR parameters have no effect. .SH "SEE ALSO" Tk_InitStubs .SH KEYWORDS diff --git a/generic/tcl.h b/generic/tcl.h index 3003abf..8a7911b 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -2409,13 +2409,21 @@ const char * TclTomMathInitializeStubs(Tcl_Interp *interp, * TODO - tommath stubs export goes here! */ +/* Tcl_InitSubsystems, see TIP ??? */ + +#define TCL_INIT_PANIC (1) /* Set Panic proc */ +#define TCL_INIT_CREATE (4) /* Call Tcl_CreateInterp(), and set argc/argv */ + +EXTERN Tcl_Interp *Tcl_InitSubsystems(int flags, ...); + /* * Public functions that are not accessible via the stubs table. * Tcl_GetMemoryInfo is needed for AOLserver. [Bug 1868171] */ #define Tcl_Main(argc, argv, proc) Tcl_MainEx(argc, argv, proc, \ - (Tcl_FindExecutable(argv[0]), (Tcl_CreateInterp)())) + Tcl_InitSubsystems(TCL_INIT_CREATE, argc, argv)) +// (Tcl_FindExecutable(argv[0]), (Tcl_CreateInterp)())) EXTERN void Tcl_MainEx(int argc, char **argv, Tcl_AppInitProc *appInitProc, Tcl_Interp *interp); EXTERN const char * Tcl_PkgInitStubsCheck(Tcl_Interp *interp, diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c index 7a55724..9a64f10 100644 --- a/generic/tclEncoding.c +++ b/generic/tclEncoding.c @@ -1411,7 +1411,7 @@ Tcl_UtfToExternal( /* *--------------------------------------------------------------------------- * - * Tcl_FindExecutable -- + * Tcl_InitSubsystems/Tcl_FindExecutable -- * * This function computes the absolute path name of the current * application, given its argv[0] value. @@ -1425,6 +1425,64 @@ Tcl_UtfToExternal( * *--------------------------------------------------------------------------- */ +MODULE_SCOPE const TclStubs tclStubs; + +/* Dummy const structure returned by Tcl_InitSubsystems, + * which looks like an Tcl_Interp, but in reality is not. + * It contains just enough for Tcl_InitStubs to be able + * to initialize the stub table. */ +static const struct { + const char *version; /* a real interpreter has interp->result here. */ + void (*unused2) (void); /* a real interpreter has interp->freeProc here. */ + int magic; /* a real interpreter has interp->errorLine here. */ + const struct TclStubs *stubTable; +} dummyInterp = { + TCL_PATCH_LEVEL, 0, TCL_STUB_MAGIC, &tclStubs +}; + +Tcl_Interp * +Tcl_InitSubsystems(int flags, ...) +{ + va_list argList; + + int argc = 0; + char **argv = NULL; + + va_start(argList, flags); + if (flags & TCL_INIT_PANIC) { + Tcl_SetPanicProc(va_arg(argList, Tcl_PanicProc *)); + } + if (flags & TCL_INIT_CREATE) { + argc = va_arg(argList, int); + argv = va_arg(argList, char **); + } + va_end (argList); + + TclInitSubsystems(); + TclpSetInitialEncodings(); + TclpFindExecutable(argv ? argv[0] : NULL); + if (flags & TCL_INIT_CREATE) { + Tcl_Interp *interp = Tcl_CreateInterp(); + if (argc > 0) { + Tcl_Obj *argvPtr; + argc--; + argv++; + + Tcl_SetVar2Ex(interp, "argc", NULL, Tcl_NewIntObj(argc), TCL_GLOBAL_ONLY); + argvPtr = Tcl_NewListObj(argc, NULL); + while (argc--) { + Tcl_DString ds; + + Tcl_ExternalToUtfDString(NULL, *argv++, -1, &ds); + Tcl_ListObjAppendElement(NULL, argvPtr, TclDStringToObj(&ds)); + } + Tcl_SetVar2Ex(interp, "argv", NULL, argvPtr, TCL_GLOBAL_ONLY); + } + return interp; + } + return (Tcl_Interp *) &dummyInterp; +} + #undef Tcl_FindExecutable void Tcl_FindExecutable( diff --git a/generic/tclStubLib.c b/generic/tclStubLib.c index 859cbf9..c5c0d92 100644 --- a/generic/tclStubLib.c +++ b/generic/tclStubLib.c @@ -73,37 +73,42 @@ Tcl_InitStubs( return NULL; } - actualVersion = stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 0, &pkgData); - if (actualVersion == NULL) { - return NULL; - } - if (exact) { - const char *p = version; - int count = 0; - - while (*p) { - count += !isDigit(*p++); + if(iPtr->errorLine == TCL_STUB_MAGIC) { + actualVersion = iPtr->result; + tclStubsPtr = stubsPtr; + } else { + actualVersion = stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 0, &pkgData); + if (actualVersion == NULL) { + return NULL; } - if (count == 1) { - const char *q = actualVersion; + if (exact) { + const char *p = version; + int count = 0; - p = version; - while (*p && (*p == *q)) { - p++; q++; - } - if (*p || isDigit(*q)) { - /* Construct error message */ - stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL); - return NULL; + while (*p) { + count += !isDigit(*p++); } - } else { - actualVersion = stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL); - if (actualVersion == NULL) { - return NULL; + if (count == 1) { + const char *q = actualVersion; + + p = version; + while (*p && (*p == *q)) { + p++; q++; + } + if (*p || isDigit(*q)) { + /* Construct error message */ + stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL); + return NULL; + } + } else { + actualVersion = stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL); + if (actualVersion == NULL) { + return NULL; + } } } + tclStubsPtr = (const TclStubs *)pkgData; } - tclStubsPtr = (TclStubs *)pkgData; if (tclStubsPtr->hooks) { tclPlatStubsPtr = tclStubsPtr->hooks->tclPlatStubs; -- cgit v0.12 From 2c02c2ae5d892599247538f12315b137dbdeba59 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 25 Jan 2013 11:45:17 +0000 Subject: Eliminate some unneeded usages of Tcl_SetResult, Tcl_AddObjErrorInfo Fix "make test-packages" on cygwin --- generic/tclAssembly.c | 9 ++++----- generic/tclEnsemble.c | 2 +- generic/tclExecute.c | 4 ++-- generic/tclOO.c | 2 +- generic/tclResult.c | 2 +- generic/tclThreadTest.c | 2 +- generic/tclTrace.c | 2 +- generic/tclVar.c | 4 ++-- unix/Makefile.in | 2 +- unix/tclUnixTest.c | 10 +++++----- win/tclWinTest.c | 2 +- 11 files changed, 20 insertions(+), 21 deletions(-) diff --git a/generic/tclAssembly.c b/generic/tclAssembly.c index 7833105..99bdf43 100644 --- a/generic/tclAssembly.c +++ b/generic/tclAssembly.c @@ -798,12 +798,11 @@ TclNRAssembleObjCmd( if (codePtr == NULL) { Tcl_AddErrorInfo(interp, "\n (\""); - Tcl_AddErrorInfo(interp, Tcl_GetString(objv[0])); + Tcl_AppendObjToErrorInfo(interp, objv[0]); Tcl_AddErrorInfo(interp, "\" body, line "); backtrace = Tcl_NewIntObj(Tcl_GetErrorLine(interp)); Tcl_IncrRefCount(backtrace); - Tcl_AddErrorInfo(interp, Tcl_GetString(backtrace)); - Tcl_DecrRefCount(backtrace); + Tcl_AppendObjToErrorInfo(interp, backtrace); Tcl_AddErrorInfo(interp, ")"); return TCL_ERROR; } @@ -4270,11 +4269,11 @@ AddBasicBlockRangeToErrorInfo( Tcl_AddErrorInfo(interp, "\n in assembly code between lines "); lineNo = Tcl_NewIntObj(bbPtr->startLine); Tcl_IncrRefCount(lineNo); - Tcl_AddErrorInfo(interp, Tcl_GetString(lineNo)); + Tcl_AppendObjToErrorInfo(interp, lineNo); Tcl_AddErrorInfo(interp, " and "); if (bbPtr->successor1 != NULL) { Tcl_SetIntObj(lineNo, bbPtr->successor1->startLine); - Tcl_AddErrorInfo(interp, Tcl_GetString(lineNo)); + Tcl_AppendObjToErrorInfo(interp, lineNo); } else { Tcl_AddErrorInfo(interp, "end of assembly code"); } diff --git a/generic/tclEnsemble.c b/generic/tclEnsemble.c index 88de9f3..f392cad 100644 --- a/generic/tclEnsemble.c +++ b/generic/tclEnsemble.c @@ -2196,7 +2196,7 @@ EnsembleUnknownCallback( } Tcl_AddErrorInfo(interp, "\n result of " "ensemble unknown subcommand handler: "); - Tcl_AddErrorInfo(interp, TclGetString(unknownCmd)); + Tcl_AppendObjToErrorInfo(interp, unknownCmd); Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "UNKNOWN_RESULT", NULL); } else { diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 8a68e9b..479ab86 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -3464,8 +3464,8 @@ TEBCresume( varPtr = TclObjLookupVarEx(interp, objPtr, part2Ptr, TCL_LEAVE_ERR_MSG, "read", 1, 1, &arrayPtr); if (!varPtr) { - Tcl_AddObjErrorInfo(interp, - "\n (reading value of variable to increment)", -1); + Tcl_AddErrorInfo(interp, + "\n (reading value of variable to increment)"); TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); Tcl_DecrRefCount(incrPtr); goto gotError; diff --git a/generic/tclOO.c b/generic/tclOO.c index d6d2d6a..cb22de6 100644 --- a/generic/tclOO.c +++ b/generic/tclOO.c @@ -843,7 +843,7 @@ ObjectRenamedTrace( result = Tcl_NRCallObjProc(interp, TclOOInvokeContext, contextPtr, 0, NULL); if (result != TCL_OK) { - Tcl_BackgroundError(interp); + Tcl_BackgroundException(interp, result); } Tcl_RestoreInterpState(interp, state); TclOODeleteContext(contextPtr); diff --git a/generic/tclResult.c b/generic/tclResult.c index 9707f20..07f6819 100644 --- a/generic/tclResult.c +++ b/generic/tclResult.c @@ -1587,7 +1587,7 @@ Tcl_GetReturnOptions( } if (result == TCL_ERROR) { - Tcl_AddObjErrorInfo(interp, "", -1); + Tcl_AddErrorInfo(interp, ""); Tcl_DictObjPut(NULL, options, keys[KEY_ERRORSTACK], iPtr->errorStack); } if (iPtr->errorCode) { diff --git a/generic/tclThreadTest.c b/generic/tclThreadTest.c index b90e33d..1115ff0 100644 --- a/generic/tclThreadTest.c +++ b/generic/tclThreadTest.c @@ -926,7 +926,7 @@ ThreadSend( ckfree(resultPtr->errorInfo); } } - Tcl_SetResult(interp, resultPtr->result, TCL_DYNAMIC); + Tcl_AppendResult(interp, resultPtr->result, NULL); Tcl_ConditionFinalize(&resultPtr->done); code = resultPtr->code; diff --git a/generic/tclTrace.c b/generic/tclTrace.c index 519f201..0f297a4 100644 --- a/generic/tclTrace.c +++ b/generic/tclTrace.c @@ -1322,7 +1322,7 @@ TraceCommandProc( Tcl_DStringLength(&cmd), 0); if (code != TCL_OK) { /* We ignore errors in these traced commands */ - /*** QUESTION: Use Tcl_BackgroundError(interp); instead? ***/ + /*** QUESTION: Use Tcl_BackgroundException(interp, code); instead? ***/ } Tcl_DStringFree(&cmd); } diff --git a/generic/tclVar.c b/generic/tclVar.c index 9b8527c..2d1479d 100644 --- a/generic/tclVar.c +++ b/generic/tclVar.c @@ -2036,8 +2036,8 @@ TclIncrObjVar2( varPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr, flags, "read", 1, 1, &arrayPtr); if (varPtr == NULL) { - Tcl_AddObjErrorInfo(interp, - "\n (reading value of variable to increment)", -1); + Tcl_AddErrorInfo(interp, + "\n (reading value of variable to increment)"); return NULL; } return TclPtrIncrObjVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, diff --git a/unix/Makefile.in b/unix/Makefile.in index ee31282..f8dd67c 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -1718,7 +1718,7 @@ install-packages: packages fi; \ done -test-packages: tcltest packages +test-packages: ${TCLTEST_EXE} packages @for i in $(PKGS_DIR)/*; do \ if [ -d $$i ]; then \ pkg=`basename $$i`; \ diff --git a/unix/tclUnixTest.c b/unix/tclUnixTest.c index 46fc972..c10225d 100644 --- a/unix/tclUnixTest.c +++ b/unix/tclUnixTest.c @@ -200,7 +200,7 @@ TestfilehandlerCmd( return TCL_ERROR; } sprintf(buf, "%d %d", pipePtr->readCount, pipePtr->writeCount); - Tcl_SetResult(interp, buf, TCL_VOLATILE); + Tcl_AppendResult(interp, buf, NULL); } else if (strcmp(argv[1], "create") == 0) { if (argc != 5) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", @@ -217,8 +217,8 @@ TestfilehandlerCmd( fcntl(GetFd(pipePtr->readFile), F_SETFL, O_NONBLOCK); fcntl(GetFd(pipePtr->writeFile), F_SETFL, O_NONBLOCK); #else - Tcl_SetResult(interp, "can't make pipes non-blocking", - TCL_STATIC); + Tcl_AppendResult(interp, "can't make pipes non-blocking", + NULL); return TCL_ERROR; #endif } @@ -281,7 +281,7 @@ TestfilehandlerCmd( memset(buffer, 'b', 10); TclFormatInt(buf, write(GetFd(pipePtr->writeFile), buffer, 10)); - Tcl_SetResult(interp, buf, TCL_VOLATILE); + Tcl_AppendResult(interp, buf, NULL); } else if (strcmp(argv[1], "oneevent") == 0) { Tcl_DoOneEvent(TCL_FILE_EVENTS|TCL_DONT_WAIT); } else if (strcmp(argv[1], "wait") == 0) { @@ -390,7 +390,7 @@ TestfilewaitCmd( if (Tcl_GetChannelHandle(channel, (mask & TCL_READABLE) ? TCL_READABLE : TCL_WRITABLE, (ClientData*) &data) != TCL_OK) { - Tcl_SetResult(interp, "couldn't get channel file", TCL_STATIC); + Tcl_AppendResult(interp, "couldn't get channel file", NULL); return TCL_ERROR; } fd = PTR2INT(data); diff --git a/win/tclWinTest.c b/win/tclWinTest.c index 136c4db..b83c0ba 100644 --- a/win/tclWinTest.c +++ b/win/tclWinTest.c @@ -211,7 +211,7 @@ TestvolumetypeCmd( TclWinConvertError(GetLastError()); return TCL_ERROR; } - Tcl_SetResult(interp, volType, TCL_VOLATILE); + Tcl_AppendResult(interp, volType, NULL); return TCL_OK; #undef VOL_BUF_SIZE } -- cgit v0.12 From 4796adf5cb7dda39555411ea4941ab630f2eabec Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 25 Jan 2013 13:07:06 +0000 Subject: Another memory leak, and one Tcl_Free -> ckfree --- generic/tclThreadTest.c | 1 + unix/tclUnixTime.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/generic/tclThreadTest.c b/generic/tclThreadTest.c index 1115ff0..8708f9a 100644 --- a/generic/tclThreadTest.c +++ b/generic/tclThreadTest.c @@ -930,6 +930,7 @@ ThreadSend( Tcl_ConditionFinalize(&resultPtr->done); code = resultPtr->code; + ckfree(resultPtr->result); ckfree(resultPtr); return code; diff --git a/unix/tclUnixTime.c b/unix/tclUnixTime.c index c7921fe..926e8f4 100644 --- a/unix/tclUnixTime.c +++ b/unix/tclUnixTime.c @@ -503,7 +503,7 @@ SetTZIfNecessary(void) if (lastTZ == NULL) { Tcl_CreateExitHandler(CleanupMemory, NULL); } else { - Tcl_Free(lastTZ); + ckfree(lastTZ); } lastTZ = ckalloc(strlen(newTZ) + 1); strcpy(lastTZ, newTZ); -- cgit v0.12 From eecece2afea26aec8b61ab04a7887c203257e82a Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 25 Mar 2013 15:00:55 +0000 Subject: TCL_INIT_ENCODINGPATH --- generic/tcl.h | 1 + generic/tclEncoding.c | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/generic/tcl.h b/generic/tcl.h index e89dff8..eda9eb9 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -2412,6 +2412,7 @@ const char * TclTomMathInitializeStubs(Tcl_Interp *interp, /* Tcl_InitSubsystems, see TIP 414 */ #define TCL_INIT_PANIC (1) /* Set Panic proc */ +#define TCL_INIT_ENCODINGPATH (2) /* Set encoding path */ #define TCL_INIT_CREATE (48) /* Call Tcl_CreateInterp(), and set argc/argv */ #define TCL_INIT_CREATE_UNICODE (16) /* The same, but argv is in unicode */ #define TCL_INIT_CREATE_UTF8 (32) /* The same, but argv is in utf-8 */ diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c index dbe747b..dfcca14 100644 --- a/generic/tclEncoding.c +++ b/generic/tclEncoding.c @@ -1448,11 +1448,15 @@ Tcl_InitSubsystems(int flags, ...) va_list argList; int argc = 0; void **argv = NULL; + const char *encodingpath = NULL; va_start(argList, flags); if (flags & TCL_INIT_PANIC) { Tcl_SetPanicProc(va_arg(argList, Tcl_PanicProc *)); } + if (flags & TCL_INIT_ENCODINGPATH) { + encodingpath = va_arg(argList, const char *); + } if (flags & TCL_INIT_CREATE) { argc = va_arg(argList, int); argv = va_arg(argList, void **); @@ -1460,6 +1464,9 @@ Tcl_InitSubsystems(int flags, ...) va_end(argList); TclInitSubsystems(); + if(encodingpath) { + Tcl_SetEncodingSearchPath(Tcl_NewStringObj(encodingpath, -1)); + } TclpSetInitialEncodings(); TclpFindExecutable(argv ? argv[0] : NULL); if (flags & TCL_INIT_CREATE) { -- cgit v0.12 From d048128004c027a3ee8e8d4fab19039a3bb358e2 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 26 Mar 2013 10:20:03 +0000 Subject: Version having TCL_INIT_PANIC as only Tcl_InitSubsystems() flag --- doc/InitSubSyst.3 | 31 ++----------------------------- generic/tcl.h | 6 +----- generic/tclEncoding.c | 44 +------------------------------------------- 3 files changed, 4 insertions(+), 77 deletions(-) diff --git a/doc/InitSubSyst.3 b/doc/InitSubSyst.3 index c23f2a3..0125912 100644 --- a/doc/InitSubSyst.3 +++ b/doc/InitSubSyst.3 @@ -18,8 +18,8 @@ Tcl_Interp * .SH ARGUMENTS .AS int flags .AP int flags in -Any combination of flags which indicate whether a custom panicProc -is registered and/or a real interpreter is created. +Any combination of flags which might modify the initialization sequence. +At this moment, only 0 and \fBTCL_INIT_PANIC\fR are supported. The value 0 can be used if Tcl is used as utility library only. .BE @@ -74,33 +74,6 @@ could call \fBTcl_SetPanicProc\fR immediately after \fBTcl_InitSubsystems\fR, but then panics which could be produced by the initialization itself still use the default panic procedure. .PP -If you supply one of the flags \fBTCL_INIT_CREATE\fR, \fBTCL_INIT_CREATE_UTF8\fR or -\fBTCL_INIT_CREATE_UNICODE\fR to \fBTcl_InitSubsystems\fR, the function -gets two additional parameters, argc and argv. Then a real -Tcl interpreter will be created. If argc > 0 then the variables -\fBargc\fR and \fBargv\fR will be set in this interpreter. The 3 -variants assume a different encoding for the arguments, except for -\fIargv[0]\fR which is always assumed to be in the system encoding. -So, the above example code could be simplified to: -.CS -Tcl_Interp *interp = Tcl_InitSubSystems(TCL_INIT_CREATE, 0, NULL); -Tcl_InitStubs(interp, TCL_VERSION, 0); /* initialize the stub table */ -.CE -.PP -If the \fBTCL_INIT_PANIC\fR and one of the \fBTCL_INIT_CREATE\fR -flags are used in combination, the \fBpanicProc\fR argument comes -before the argc/argv arguments. -.PP -The reason for \fBargv[0]\fR always using the system encoding is that this way, -argv[0] can be derived directly from the main() (or mainw, on Windows) -arguments without any processing. \fBTCL_INIT_CREATE_UNICODE\fR is really only -useful on Windows. But on Windows, the argv[0] parameter is not used for -determining the value of [info executable] anyway. Modern UNIX system already -have UTF-8 as system encoding, so \fBTCL_INIT_CREATE_UTF8\fR would have the same -effect as \fBTCL_INIT_CREATE\fR, only slightly faster. Other parameters can be -preprocessed at will by the application, and if the application uses unicode -or UTF-8 internally there is no need to convert it back to the system encoding. -.PP The interpreter returned by Tcl_InitSubsystems(0) cannot be passed to any other function than Tcl_InitStubs(). Tcl functions with an "interp" argument can only be called if the function supports passing NULL. diff --git a/generic/tcl.h b/generic/tcl.h index eda9eb9..4049c8a 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -2409,13 +2409,9 @@ const char * TclTomMathInitializeStubs(Tcl_Interp *interp, * TODO - tommath stubs export goes here! */ -/* Tcl_InitSubsystems, see TIP 414 */ +/* Tcl_InitSubsystems, see TIP #414 */ #define TCL_INIT_PANIC (1) /* Set Panic proc */ -#define TCL_INIT_ENCODINGPATH (2) /* Set encoding path */ -#define TCL_INIT_CREATE (48) /* Call Tcl_CreateInterp(), and set argc/argv */ -#define TCL_INIT_CREATE_UNICODE (16) /* The same, but argv is in unicode */ -#define TCL_INIT_CREATE_UTF8 (32) /* The same, but argv is in utf-8 */ EXTERN Tcl_Interp *Tcl_InitSubsystems(int flags, ...); diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c index dfcca14..0ffc481 100644 --- a/generic/tclEncoding.c +++ b/generic/tclEncoding.c @@ -1446,58 +1446,16 @@ Tcl_Interp * Tcl_InitSubsystems(int flags, ...) { va_list argList; - int argc = 0; - void **argv = NULL; - const char *encodingpath = NULL; va_start(argList, flags); if (flags & TCL_INIT_PANIC) { Tcl_SetPanicProc(va_arg(argList, Tcl_PanicProc *)); } - if (flags & TCL_INIT_ENCODINGPATH) { - encodingpath = va_arg(argList, const char *); - } - if (flags & TCL_INIT_CREATE) { - argc = va_arg(argList, int); - argv = va_arg(argList, void **); - } va_end(argList); TclInitSubsystems(); - if(encodingpath) { - Tcl_SetEncodingSearchPath(Tcl_NewStringObj(encodingpath, -1)); - } TclpSetInitialEncodings(); - TclpFindExecutable(argv ? argv[0] : NULL); - if (flags & TCL_INIT_CREATE) { - Tcl_Interp *interp = Tcl_CreateInterp(); - if (--argc >= 0) { - Tcl_Obj *argvPtr; - - Tcl_SetVar2Ex(interp, "argc", NULL, Tcl_NewIntObj(argc), TCL_GLOBAL_ONLY); - argvPtr = Tcl_NewListObj(argc, NULL); - if ((flags & TCL_INIT_CREATE) == TCL_INIT_CREATE_UTF8) { - while (argc--) { - Tcl_ListObjAppendElement(NULL, argvPtr, - Tcl_NewStringObj(*++argv, -1)); - } - } else if ((flags & TCL_INIT_CREATE) == TCL_INIT_CREATE_UNICODE) { - while (argc--) { - Tcl_ListObjAppendElement(NULL, argvPtr, - Tcl_NewUnicodeObj(*++argv, -1)); - } - } else { - Tcl_DString ds; - - while (argc--) { - Tcl_ExternalToUtfDString(NULL, *++argv, -1, &ds); - Tcl_ListObjAppendElement(NULL, argvPtr, TclDStringToObj(&ds)); - } - } - Tcl_SetVar2Ex(interp, "argv", NULL, argvPtr, TCL_GLOBAL_ONLY); - } - return interp; - } + TclpFindExecutable(NULL); return (Tcl_Interp *) &dummyInterp; } -- cgit v0.12 From bb770e33f8e270fc105aa9807a61bec5ac171771 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 26 Mar 2013 13:58:53 +0000 Subject: Add TCL_INIT_STUFF --- doc/InitSubSyst.3 | 8 +++++++- generic/tcl.h | 1 + generic/tclEncoding.c | 7 ++++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/doc/InitSubSyst.3 b/doc/InitSubSyst.3 index 0125912..4a3dc64 100644 --- a/doc/InitSubSyst.3 +++ b/doc/InitSubSyst.3 @@ -19,7 +19,8 @@ Tcl_Interp * .AS int flags .AP int flags in Any combination of flags which might modify the initialization sequence. -At this moment, only 0 and \fBTCL_INIT_PANIC\fR are supported. +At this moment, only 0, \fBTCL_INIT_PANIC\fR and \fBTCL_INIT_STUFF\fR +(or a combination) are supported. The value 0 can be used if Tcl is used as utility library only. .BE @@ -74,6 +75,11 @@ could call \fBTcl_SetPanicProc\fR immediately after \fBTcl_InitSubsystems\fR, but then panics which could be produced by the initialization itself still use the default panic procedure. .PP +If you supply the flag \fBTCL_INIT_STUFF\fR to \fBTcl_InitSubsystems\fR, +the function expects two additional arguments: ClientData and a +custom proc with has ClientData as its only argument. The given +function will be executed just before the encodings are initialized. +.PP The interpreter returned by Tcl_InitSubsystems(0) cannot be passed to any other function than Tcl_InitStubs(). Tcl functions with an "interp" argument can only be called if the function supports passing NULL. diff --git a/generic/tcl.h b/generic/tcl.h index 4049c8a..9325bf2 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -2412,6 +2412,7 @@ const char * TclTomMathInitializeStubs(Tcl_Interp *interp, /* Tcl_InitSubsystems, see TIP #414 */ #define TCL_INIT_PANIC (1) /* Set Panic proc */ +#define TCL_INIT_STUFF (2) /* Do any stuff before initializing the encoding */ EXTERN Tcl_Interp *Tcl_InitSubsystems(int flags, ...); diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c index 0ffc481..753222f 100644 --- a/generic/tclEncoding.c +++ b/generic/tclEncoding.c @@ -1451,9 +1451,14 @@ Tcl_InitSubsystems(int flags, ...) if (flags & TCL_INIT_PANIC) { Tcl_SetPanicProc(va_arg(argList, Tcl_PanicProc *)); } + TclInitSubsystems(); + if (flags & TCL_INIT_STUFF) { + ClientData clientData = va_arg(argList, ClientData); + void (*fn)() = va_arg(argList, void (*)(ClientData)); + fn(clientData); + } va_end(argList); - TclInitSubsystems(); TclpSetInitialEncodings(); TclpFindExecutable(NULL); return (Tcl_Interp *) &dummyInterp; -- cgit v0.12 From e4a0b9dbfd9e5e1261ed40444a27f64feac2833b Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 26 Mar 2013 15:57:45 +0000 Subject: Looks like TCL_INIT_CUSTOM (previously known as TCL_INIT_STUFF) is not a bad idea at all, provided it has a Tcl_Interp* argument as well, so it can initialize the stub table. A typedef for the function is not necessary, as a variable-argument function doesn't do any type checking. It's for the experienced developer anyway. --- doc/InitSubSyst.3 | 16 +++++++++------- generic/tcl.h | 2 +- generic/tclEncoding.c | 10 ++++++---- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/doc/InitSubSyst.3 b/doc/InitSubSyst.3 index 4a3dc64..db3951e 100644 --- a/doc/InitSubSyst.3 +++ b/doc/InitSubSyst.3 @@ -19,7 +19,7 @@ Tcl_Interp * .AS int flags .AP int flags in Any combination of flags which might modify the initialization sequence. -At this moment, only 0, \fBTCL_INIT_PANIC\fR and \fBTCL_INIT_STUFF\fR +At this moment, only 0, \fBTCL_INIT_PANIC\fR and \fBTCL_INIT_CUSTOM\fR (or a combination) are supported. The value 0 can be used if Tcl is used as utility library only. .BE @@ -75,13 +75,15 @@ could call \fBTcl_SetPanicProc\fR immediately after \fBTcl_InitSubsystems\fR, but then panics which could be produced by the initialization itself still use the default panic procedure. .PP -If you supply the flag \fBTCL_INIT_STUFF\fR to \fBTcl_InitSubsystems\fR, +If you supply the flag \fBTCL_INIT_CUSTOM\fR to \fBTcl_InitSubsystems\fR, the function expects two additional arguments: ClientData and a -custom proc with has ClientData as its only argument. The given -function will be executed just before the encodings are initialized. +custom proc. The proc will be supplied two arguments, the (pseudo) +Tcl interpreter and ClientData. The given function will be executed +just before the encodings are initialized. .PP -The interpreter returned by Tcl_InitSubsystems(0) cannot be passed to -any other function than Tcl_InitStubs(). Tcl functions with an "interp" -argument can only be called if the function supports passing NULL. +The interpreter returned by Tcl_InitSubsystems(0) or passed to the +TCL_INIT_CUSTOM function cannot be passed to any other function than +Tcl_InitStubs(). Tcl functions with an "interp" argument can only +be called if the function supports passing NULL. .SH KEYWORDS binary, executable file diff --git a/generic/tcl.h b/generic/tcl.h index 9325bf2..522171e 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -2412,7 +2412,7 @@ const char * TclTomMathInitializeStubs(Tcl_Interp *interp, /* Tcl_InitSubsystems, see TIP #414 */ #define TCL_INIT_PANIC (1) /* Set Panic proc */ -#define TCL_INIT_STUFF (2) /* Do any stuff before initializing the encoding */ +#define TCL_INIT_CUSTOM (2) /* Do any stuff before initializing the encoding */ EXTERN Tcl_Interp *Tcl_InitSubsystems(int flags, ...); diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c index 753222f..9905eaa 100644 --- a/generic/tclEncoding.c +++ b/generic/tclEncoding.c @@ -1446,22 +1446,24 @@ Tcl_Interp * Tcl_InitSubsystems(int flags, ...) { va_list argList; + Tcl_Interp *interp = (Tcl_Interp *) &dummyInterp; va_start(argList, flags); if (flags & TCL_INIT_PANIC) { Tcl_SetPanicProc(va_arg(argList, Tcl_PanicProc *)); } TclInitSubsystems(); - if (flags & TCL_INIT_STUFF) { + if (flags & TCL_INIT_CUSTOM) { ClientData clientData = va_arg(argList, ClientData); - void (*fn)() = va_arg(argList, void (*)(ClientData)); - fn(clientData); + void (*fn)(Tcl_Interp *, ClientData) = va_arg(argList, + void (*)(Tcl_Interp *, ClientData)); + fn(interp, clientData); } va_end(argList); TclpSetInitialEncodings(); TclpFindExecutable(NULL); - return (Tcl_Interp *) &dummyInterp; + return interp; } void -- cgit v0.12 From 6d0db57c023c72893e0a7221030126a4ec637b3c Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Sat, 30 Mar 2013 21:44:39 +0000 Subject: Better Windows console panic proc, still to be TIPped. --- generic/tcl.h | 8 +++++- generic/tclPanic.c | 16 +++-------- win/Makefile.in | 6 +++- win/makefile.bc | 6 +++- win/makefile.vc | 6 +++- win/tcl.dsp | 4 +++ win/tclWinPanic.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 114 insertions(+), 16 deletions(-) create mode 100644 win/tclWinPanic.c diff --git a/generic/tcl.h b/generic/tcl.h index 4de18f0..73229b1 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -2395,6 +2395,11 @@ const char * Tcl_InitStubs(Tcl_Interp *interp, const char *version, int exact); const char * TclTomMathInitializeStubs(Tcl_Interp *interp, const char *version, int epoch, int revision); +#ifdef _WIN32 +void Tcl_ConsolePanic(const char *format, ...); +#else +#define Tcl_ConsolePanic NULL +#endif /* * When not using stubs, make it a macro. @@ -2415,7 +2420,8 @@ const char * TclTomMathInitializeStubs(Tcl_Interp *interp, */ #define Tcl_Main(argc, argv, proc) Tcl_MainEx(argc, argv, proc, \ - (Tcl_FindExecutable(argv[0]), (Tcl_CreateInterp)())) + (Tcl_SetPanicProc(Tcl_ConsolePanic), \ + Tcl_FindExecutable(argv[0]), (Tcl_CreateInterp)())) EXTERN void Tcl_MainEx(int argc, char **argv, Tcl_AppInitProc *appInitProc, Tcl_Interp *interp); EXTERN const char * Tcl_PkgInitStubsCheck(Tcl_Interp *interp, diff --git a/generic/tclPanic.c b/generic/tclPanic.c index b87a8df..a95b9c9 100644 --- a/generic/tclPanic.c +++ b/generic/tclPanic.c @@ -23,11 +23,7 @@ * procedure. */ -#if defined(__CYGWIN__) -static Tcl_PanicProc *panicProc = tclWinDebugPanic; -#else static Tcl_PanicProc *panicProc = NULL; -#endif /* *---------------------------------------------------------------------- @@ -49,10 +45,6 @@ void Tcl_SetPanicProc( Tcl_PanicProc *proc) { -#if defined(_WIN32) - /* tclWinDebugPanic only installs if there is no panicProc yet. */ - if ((proc != tclWinDebugPanic) || (panicProc == NULL)) -#endif panicProc = proc; } @@ -93,15 +85,15 @@ Tcl_PanicVA( if (panicProc != NULL) { panicProc(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); -#ifdef _WIN32 - } else if (IsDebuggerPresent()) { - tclWinDebugPanic(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); -#endif } else { +#if defined(_WIN32) || defined(__CYGWIN__) + tclWinDebugPanic(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); +#else fprintf(stderr, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); fprintf(stderr, "\n"); fflush(stderr); +#endif #if defined(_WIN32) || defined(__CYGWIN__) # if defined(__GNUC__) __builtin_trap(); diff --git a/win/Makefile.in b/win/Makefile.in index 99009b9..2942da4 100644 --- a/win/Makefile.in +++ b/win/Makefile.in @@ -384,7 +384,8 @@ REG_OBJS = tclWinReg.$(OBJEXT) STUB_OBJS = \ tclStubLib.$(OBJEXT) \ tclTomMathStubLib.$(OBJEXT) \ - tclOOStubLib.$(OBJEXT) + tclOOStubLib.$(OBJEXT) \ + tclWinPanic.$(OBJEXT) TCLSH_OBJS = tclAppInit.$(OBJEXT) @@ -519,6 +520,9 @@ tclTomMathStubLib.${OBJEXT}: tclTomMathStubLib.c tclOOStubLib.${OBJEXT}: tclOOStubLib.c $(CC) -c $(CC_SWITCHES) -DSTATIC_BUILD @DEPARG@ $(CC_OBJNAME) +tclWinPanic.${OBJEXT}: tclWinPanic.c + $(CC) -c $(CC_SWITCHES) -DSTATIC_BUILD @DEPARG@ $(CC_OBJNAME) + # Implicit rule for all object files that will end up in the Tcl library %.${OBJEXT}: %.c diff --git a/win/makefile.bc b/win/makefile.bc index 18bfa28..b5f388c 100644 --- a/win/makefile.bc +++ b/win/makefile.bc @@ -278,7 +278,8 @@ TCLOBJS = \ TCLSTUBOBJS = \ $(TMPDIR)\tclStubLib.obj \ $(TMPDIR)\tclTomMathStubLib.obj \ - $(TMPDIR)\tclOOStubLib.obj + $(TMPDIR)\tclOOStubLib.obj \ + $(TMPDIR)\tclWinPanic.obj WINDIR = $(ROOT)\win GENERICDIR = $(ROOT)\generic @@ -532,6 +533,9 @@ $(TMPDIR)\tclTomMathStubLib.obj : $(GENERICDIR)\tclTomMathStubLib.c $(TMPDIR)\tclOOStubLib.obj : $(GENERICDIR)\tclOOStubLib.c $(cc32) $(TCL_CFLAGS) -DSTATIC_BUILD -o$(TMPDIR)\$@ $? +$(TMPDIR)\tclWinPanic.obj : $(GENERICDIR)\tclWinPanic.c + $(cc32) $(TCL_CFLAGS) -DSTATIC_BUILD -o$(TMPDIR)\$@ $? + # Dedependency rules diff --git a/win/makefile.vc b/win/makefile.vc index 2784140..e4f064e 100644 --- a/win/makefile.vc +++ b/win/makefile.vc @@ -449,7 +449,8 @@ TCLOBJS = $(COREOBJS) $(ZLIBOBJS) $(TOMMATHOBJS) $(PLATFORMOBJS) TCLSTUBOBJS = \ $(TMP_DIR)\tclStubLib.obj \ $(TMP_DIR)\tclTomMathStubLib.obj \ - $(TMP_DIR)\tclOOStubLib.obj + $(TMP_DIR)\tclOOStubLib.obj \ + $(TMP_DIR)\tclWinPanic.obj ### The following paths CANNOT have spaces in them. COMPATDIR = $(ROOT)\compat @@ -983,6 +984,9 @@ $(TMP_DIR)\tclTomMathStubLib.obj: $(GENERICDIR)\tclTomMathStubLib.c $(TMP_DIR)\tclOOStubLib.obj: $(GENERICDIR)\tclOOStubLib.c $(cc32) $(STUB_CFLAGS) -Zl -DSTATIC_BUILD $(TCL_INCLUDES) -Fo$@ $? +$(TMP_DIR)\tclWinPanic.obj: $(GENERICDIR)\tclWinPanic.c + $(cc32) $(STUB_CFLAGS) -Zl -DSTATIC_BUILD $(TCL_INCLUDES) -Fo$@ $? + #--------------------------------------------------------------------- # Generate the source dependencies. Having dependency rules will # improve incremental build accuracy without having to resort to a diff --git a/win/tcl.dsp b/win/tcl.dsp index 57ec6bf..5880d09 100644 --- a/win/tcl.dsp +++ b/win/tcl.dsp @@ -1304,6 +1304,10 @@ SOURCE=..\generic\tclOOStubLib.c # End Source File # Begin Source File +SOURCE=..\generic\tclWinPanic.c +# End Source File +# Begin Source File + SOURCE=..\generic\tclTomMathStubLib.c # End Source File # Begin Source File diff --git a/win/tclWinPanic.c b/win/tclWinPanic.c new file mode 100644 index 0000000..266625c --- /dev/null +++ b/win/tclWinPanic.c @@ -0,0 +1,84 @@ +/* + * tclWinPanic.c -- + * + * Contains the Windows-specific command-line panic proc. + * + * Copyright (c) 2013 by Jan Nijtmans. + * All rights reserved. + * + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#include "tclInt.h" + +/* + *---------------------------------------------------------------------- + * + * Tcl_ConsolePanic -- + * + * Display a message. If a debugger is present, present it directly to + * the debugger, otherwise send it to stderr. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +Tcl_ConsolePanic( + const char *format, ...) +{ +#define TCL_MAX_WARN_LEN 1024 + DWORD dummy; + va_list argList; + WCHAR msgString[TCL_MAX_WARN_LEN]; + char buf[TCL_MAX_WARN_LEN * TCL_UTF_MAX]; + HANDLE handle = GetStdHandle(STD_ERROR_HANDLE); + + va_start(argList, format); + _vsnprintf(buf+3, sizeof(buf)-3, format, argList); + buf[sizeof(buf)-1] = 0; + msgString[TCL_MAX_WARN_LEN-1] = L'\0'; + MultiByteToWideChar(CP_UTF8, 0, buf+3, -1, msgString, TCL_MAX_WARN_LEN); + + /* + * Truncate MessageBox string if it is too long to not overflow the buffer. + */ + + if (msgString[TCL_MAX_WARN_LEN-1] != L'\0') { + memcpy(msgString + (TCL_MAX_WARN_LEN - 5), L" ...", 5 * sizeof(WCHAR)); + } + + if (IsDebuggerPresent()) { + OutputDebugStringW(msgString); + } else if (_isatty(2)) { + WriteConsoleW(handle, msgString, wcslen(msgString), &dummy, 0); + } else { + buf[0] = 0xEF; buf[1] = 0xBB; buf[2] = 0xBF; /* UTF-8 bom */ + WriteFile(handle, buf, strlen(buf), &dummy, 0); + FlushFileBuffers(handle); + } +#if defined(__GNUC__) + __builtin_trap(); +#elif defined(_WIN64) + __debugbreak(); +#elif defined(_MSC_VER) + _asm {int 3} +#else + DebugBreak(); +#endif + ExitProcess(1); +} +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * tab-width: 8 + * End: + */ -- cgit v0.12 From 260c2634b9c296b79c7c6adc8326214233e38d87 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Sun, 31 Mar 2013 19:32:57 +0000 Subject: better leave tclPanic.c as it was --- generic/tcl.h | 7 ++++++- generic/tclPanic.c | 16 ++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/generic/tcl.h b/generic/tcl.h index 73229b1..70fee83 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -2419,9 +2419,14 @@ void Tcl_ConsolePanic(const char *format, ...); * Tcl_GetMemoryInfo is needed for AOLserver. [Bug 1868171] */ +#ifdef _WIN32 #define Tcl_Main(argc, argv, proc) Tcl_MainEx(argc, argv, proc, \ (Tcl_SetPanicProc(Tcl_ConsolePanic), \ - Tcl_FindExecutable(argv[0]), (Tcl_CreateInterp)())) + Tcl_FindExecutable(argv[0]), (Tcl_CreateInterp)())) +#else +#define Tcl_Main(argc, argv, proc) Tcl_MainEx(argc, argv, proc, \ + (Tcl_FindExecutable(argv[0]), (Tcl_CreateInterp)())) +#endif EXTERN void Tcl_MainEx(int argc, char **argv, Tcl_AppInitProc *appInitProc, Tcl_Interp *interp); EXTERN const char * Tcl_PkgInitStubsCheck(Tcl_Interp *interp, diff --git a/generic/tclPanic.c b/generic/tclPanic.c index a95b9c9..b87a8df 100644 --- a/generic/tclPanic.c +++ b/generic/tclPanic.c @@ -23,7 +23,11 @@ * procedure. */ +#if defined(__CYGWIN__) +static Tcl_PanicProc *panicProc = tclWinDebugPanic; +#else static Tcl_PanicProc *panicProc = NULL; +#endif /* *---------------------------------------------------------------------- @@ -45,6 +49,10 @@ void Tcl_SetPanicProc( Tcl_PanicProc *proc) { +#if defined(_WIN32) + /* tclWinDebugPanic only installs if there is no panicProc yet. */ + if ((proc != tclWinDebugPanic) || (panicProc == NULL)) +#endif panicProc = proc; } @@ -85,15 +93,15 @@ Tcl_PanicVA( if (panicProc != NULL) { panicProc(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); - } else { -#if defined(_WIN32) || defined(__CYGWIN__) +#ifdef _WIN32 + } else if (IsDebuggerPresent()) { tclWinDebugPanic(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); -#else +#endif + } else { fprintf(stderr, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); fprintf(stderr, "\n"); fflush(stderr); -#endif #if defined(_WIN32) || defined(__CYGWIN__) # if defined(__GNUC__) __builtin_trap(); -- cgit v0.12 From a58db736cfe4a984cd83ab93d38da09d21fb418f Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Sun, 31 Mar 2013 20:27:33 +0000 Subject: Fix Tcl_Main macro --- doc/InitStubs.3 | 4 ---- generic/tcl.h | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/doc/InitStubs.3 b/doc/InitStubs.3 index 8188b0b..4dc62c6 100644 --- a/doc/InitStubs.3 +++ b/doc/InitStubs.3 @@ -83,10 +83,6 @@ non-zero means that only the specified \fIversion\fR is acceptable. \fBTcl_InitStubs\fR returns a string containing the actual version of Tcl satisfying the request, or NULL if the Tcl version is not acceptable, does not support stubs, or any other error condition occurred. -.PP -If \fBTcl_InitStubs\fR is called with as first argument the -pseudo interpreter returned by \fBTcl_InitSubsystems(0)\fR, then -the \fIversion\fR and \fIexact\fR parameters have no effect. .SH "SEE ALSO" Tk_InitStubs .SH KEYWORDS diff --git a/generic/tcl.h b/generic/tcl.h index 451c6cc..4acc39d 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -2432,7 +2432,7 @@ EXTERN const char *Tcl_InitSubsystems(Tcl_PanicProc *panicProc); */ #define Tcl_Main(argc, argv, proc) Tcl_MainEx(argc, argv, proc, \ - (Tcl_InitSubsystems(Tcl_ConsolePanic), Tcl_CreateInterp)()) + (Tcl_InitSubsystems(Tcl_ConsolePanic), Tcl_CreateInterp())) EXTERN void Tcl_MainEx(int argc, char **argv, Tcl_AppInitProc *appInitProc, Tcl_Interp *interp); EXTERN const char * Tcl_PkgInitStubsCheck(Tcl_Interp *interp, -- cgit v0.12 From 1c6a242b2e520aacca113e4189ebb0b95caf9844 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Sun, 31 Mar 2013 22:09:40 +0000 Subject: 2 lines not used any more --- generic/tcl.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/generic/tcl.h b/generic/tcl.h index 4acc39d..67cd181 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -2416,9 +2416,6 @@ void Tcl_ConsolePanic(const char *format, ...); /* Tcl_InitSubsystems, see TIP #414 */ -#define TCL_INIT_PANIC (1) /* Set Panic proc */ -#define TCL_INIT_CUSTOM (2) /* Do any stuff before initializing the encoding */ - #ifdef USE_TCL_STUBS EXTERN Tcl_Interp *Tcl_InitSubsystems(Tcl_PanicProc *panicProc); #define Tcl_InitSubsystems(panicProc) Tcl_InitStubs((Tcl_InitSubsystems)(panicProc), NULL, 0) -- cgit v0.12 From 696a9ba3f9a7c0ed882dc6a3b878970f8a94d27c Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 1 Apr 2013 21:48:51 +0000 Subject: Use Tcl_InitSubsystems in Tcl_Main macro --- generic/tcl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tcl.h b/generic/tcl.h index 5d93e8d..051e2a1 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -2424,7 +2424,7 @@ EXTERN const char *Tcl_InitSubsystems(Tcl_PanicProc *panicProc); */ #define Tcl_Main(argc, argv, proc) Tcl_MainEx(argc, argv, proc, \ - (Tcl_FindExecutable(argv[0]), (Tcl_CreateInterp)())) + (Tcl_InitSubsystems(NULL), Tcl_CreateInterp())) EXTERN void Tcl_MainEx(int argc, char **argv, Tcl_AppInitProc *appInitProc, Tcl_Interp *interp); EXTERN const char * Tcl_PkgInitStubsCheck(Tcl_Interp *interp, -- cgit v0.12 From 07af7d5337d813d6bd0ce15b62b1b04de5db9e06 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 3 Apr 2013 12:38:46 +0000 Subject: better comments --- doc/InitSubSyst.3 | 22 ++++++++++------------ generic/tcl.h | 3 ++- generic/tclEncoding.c | 10 ++++++---- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/doc/InitSubSyst.3 b/doc/InitSubSyst.3 index 4fd99c7..2d5c2bc 100644 --- a/doc/InitSubSyst.3 +++ b/doc/InitSubSyst.3 @@ -5,7 +5,7 @@ '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .so man.macros -.TH Tcl_InitSubsystems 3 8.7 Tcl "Tcl Library Procedures" +.TH Tcl_InitSubsystems 3 8.6.1 Tcl "Tcl Library Procedures" .BS .SH NAME Tcl_InitSubsystems \- initialize the Tcl library. @@ -19,9 +19,8 @@ const char * .SH ARGUMENTS .AS Tcl_PanicProc *panicProc .AP Tcl_PanicProc *panicProc in -Desired panic function, for error reporting. The value NULL is used -when the default panicProc is desired, which normally writes the -message to stderr. +Desired panic function, for error reporting. If NULL, the default +panicProc is used, which normally writes the message to stderr. .BE .SH DESCRIPTION @@ -35,11 +34,12 @@ called once by Tcl embedders. Tcl_SetPanicProc is in the stub table, meant for Tcl extenders, and can be called at any time later to change the panic proc. .PP -\fBTcl_InitSubsystems\fR can be used in stead of -\fBTcl_FindExecutable\fR when Tcl is used as utility library -only, and no other encodings than utf8, iso8859-1 or unicode -are used. The system encoding will not be determined -correctly but being set to iso8859-1. +\fBTcl_InitSubsystems\fR is very similar to +\fBTcl_FindExecutable\fR as well. It can be used when Tcl is +used as utility library, no other encodings than utf8, +iso8859-1 or unicode are used, and no interest exists in the +value of \fBinfo nameofexecutable\fR. The system encoding will not +be extracted from the environment, but falls back to iso8859-1. .PP The return value is the Tcl version. .PP @@ -53,8 +53,6 @@ const char *version = Tcl_InitSubSystems(NULL); int major, minor, patch; Tcl_GetVersion(&major, &minor, &patch); .CE -This will work as expected, both with and without stubs. When -using stubs, this code must be linked with both the normal -Tcl library (static or shared) and the stub library. +This will work as expected, both with and without stubs. .SH KEYWORDS binary, executable file diff --git a/generic/tcl.h b/generic/tcl.h index 051e2a1..543b2a6 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -2413,7 +2413,8 @@ const char * TclTomMathInitializeStubs(Tcl_Interp *interp, #ifdef USE_TCL_STUBS EXTERN Tcl_Interp *Tcl_InitSubsystems(Tcl_PanicProc *panicProc); -#define Tcl_InitSubsystems(panicProc) Tcl_InitStubs((Tcl_InitSubsystems)(panicProc), NULL, 0) +#define Tcl_InitSubsystems(panicProc) \ + Tcl_InitStubs((Tcl_InitSubsystems)(panicProc), NULL, 0) #else EXTERN const char *Tcl_InitSubsystems(Tcl_PanicProc *panicProc); #endif diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c index e57272f..a83a6b0 100644 --- a/generic/tclEncoding.c +++ b/generic/tclEncoding.c @@ -1428,10 +1428,12 @@ Tcl_UtfToExternal( */ MODULE_SCOPE const TclStubs tclStubs; -/* Dummy const structure returned by Tcl_InitSubsystems, - * which looks like an Tcl_Interp, but in reality is not. - * It contains just enough for Tcl_InitStubs to be able - * to initialize the stub table. */ +/* Dummy const structure returned by Tcl_InitSubsystems when + * using stubs, which looks like an Tcl_Interp, but in reality + * is not. It contains just enough for Tcl_InitStubs to be able + * to initialize the stub table. The first bytes of this structure + * are filled with the Tcl version string, so it can be cast to a + * "const char *" holding the Tcl version as well. */ static const struct { /* A real interpreter has interp->result/freeProc here: */ const char version[sizeof(struct {char *r; void (*f)(void);})]; -- cgit v0.12 From 3f5f45f002154ba9fc45f89e99f68beef8ea79c3 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 17 May 2013 14:09:20 +0000 Subject: fix directory where tclWinPanic.c resides --- win/makefile.bc | 2 +- win/makefile.vc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/win/makefile.bc b/win/makefile.bc index b5f388c..891fe69 100644 --- a/win/makefile.bc +++ b/win/makefile.bc @@ -533,7 +533,7 @@ $(TMPDIR)\tclTomMathStubLib.obj : $(GENERICDIR)\tclTomMathStubLib.c $(TMPDIR)\tclOOStubLib.obj : $(GENERICDIR)\tclOOStubLib.c $(cc32) $(TCL_CFLAGS) -DSTATIC_BUILD -o$(TMPDIR)\$@ $? -$(TMPDIR)\tclWinPanic.obj : $(GENERICDIR)\tclWinPanic.c +$(TMPDIR)\tclWinPanic.obj : $(WINDIR)\tclWinPanic.c $(cc32) $(TCL_CFLAGS) -DSTATIC_BUILD -o$(TMPDIR)\$@ $? diff --git a/win/makefile.vc b/win/makefile.vc index e4f064e..1485486 100644 --- a/win/makefile.vc +++ b/win/makefile.vc @@ -984,7 +984,7 @@ $(TMP_DIR)\tclTomMathStubLib.obj: $(GENERICDIR)\tclTomMathStubLib.c $(TMP_DIR)\tclOOStubLib.obj: $(GENERICDIR)\tclOOStubLib.c $(cc32) $(STUB_CFLAGS) -Zl -DSTATIC_BUILD $(TCL_INCLUDES) -Fo$@ $? -$(TMP_DIR)\tclWinPanic.obj: $(GENERICDIR)\tclWinPanic.c +$(TMP_DIR)\tclWinPanic.obj: $(WINDIR)\tclWinPanic.c $(cc32) $(STUB_CFLAGS) -Zl -DSTATIC_BUILD $(TCL_INCLUDES) -Fo$@ $? #--------------------------------------------------------------------- -- cgit v0.12 From 53dc25e532b83e02c84f5991389720106c6d9018 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 23 Jul 2013 11:54:49 +0000 Subject: Add documentation --- doc/Panic.3 | 13 ++++++++++++- generic/tclDecls.h | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/doc/Panic.3 b/doc/Panic.3 index 48aed2b..9013e89 100644 --- a/doc/Panic.3 +++ b/doc/Panic.3 @@ -7,7 +7,7 @@ .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME -Tcl_Panic, Tcl_PanicVA, Tcl_SetPanicProc \- report fatal error and abort +Tcl_Panic, Tcl_PanicVA, Tcl_SetPanicProc, Tcl_ConsolePanic \- report fatal error and abort .SH SYNOPSIS .nf \fB#include \fR @@ -21,6 +21,9 @@ void void \fBTcl_SetPanicProc\fR(\fIpanicProc\fR) .sp +void +\fBTcl_ConsolePanic\fR(\fIformat\fR, \fIarg\fR, \fIarg\fR, \fI...\fR) +.sp .SH ARGUMENTS .AS Tcl_PanicProc *panicProc .AP "const char*" format in @@ -54,6 +57,14 @@ message is sent to the debugger in stead. If the windows executable does not have a stderr channel (e.g. \fBwish.exe\fR), then a system dialog box is used to display the panic message. .PP +If your application doesn't use \fBTcl_Main\fR or \fBTk_Main\fR +and you want to implicitly use the stderr channel of your +application's C runtime (in stead of the stderr channel of the +C runtime used by Tcl), you can call \fBTcl_SetPanicProc\fR +with \fBTcl_ConsolePanic\fR as its argument. On platforms which +only have one C runtime (almost all platforms except Windows +and Cygwin) \fBTcl_ConsolePanic\fR is equivalent to NULL. +.PP \fBTcl_SetPanicProc\fR may be used to modify the behavior of \fBTcl_Panic\fR. The \fIpanicProc\fR argument should match the type \fBTcl_PanicProc\fR: diff --git a/generic/tclDecls.h b/generic/tclDecls.h index 1ade6ef..4d40be1 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -3789,6 +3789,7 @@ extern const TclStubs *tclStubsPtr; # define Tcl_CreateInterp() (tclStubsPtr->tcl_CreateInterp()) # define Tcl_GetStringResult(interp) (tclStubsPtr->tcl_GetStringResult(interp)) # define Tcl_Init(interp) (tclStubsPtr->tcl_Init(interp)) +# define Tcl_SetPanicProc(proc) (tclStubsPtr->tcl_SetPanicProc(proc)) # define Tcl_SetVar(interp, varName, newValue, flags) \ (tclStubsPtr->tcl_SetVar(interp, varName, newValue, flags)) # define Tcl_ObjSetVar2(interp, part1, part2, newValue, flags) \ -- cgit v0.12 From 4ddfe70ae216fd2931131fd6a31a975c7219e8c2 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 23 Jul 2013 12:42:52 +0000 Subject: implement for Cygwin as well --- generic/tcl.h | 2 +- unix/Makefile.in | 5 ++++- unix/configure | 2 +- unix/tcl.m4 | 2 +- win/tclWinPanic.c | 33 ++++++++++++++++++++++++--------- 5 files changed, 31 insertions(+), 13 deletions(-) diff --git a/generic/tcl.h b/generic/tcl.h index af5e8f0..e593910 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -2397,7 +2397,7 @@ const char * Tcl_InitStubs(Tcl_Interp *interp, const char *version, int exact); const char * TclTomMathInitializeStubs(Tcl_Interp *interp, const char *version, int epoch, int revision); -#ifdef _WIN32 +#if defined(_WIN32) || defined(__CYGWIN__) void Tcl_ConsolePanic(const char *format, ...); #else #define Tcl_ConsolePanic ((Tcl_PanicProc *)0) diff --git a/unix/Makefile.in b/unix/Makefile.in index b5ca879..bc66f19 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -1580,10 +1580,13 @@ tclMacOSXFCmd.o: $(MAC_OSX_DIR)/tclMacOSXFCmd.c tclMacOSXNotify.o: $(MAC_OSX_DIR)/tclMacOSXNotify.c $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tclMacOSXNotify.c -# The following is a CYGWIN only source: +# The following are CYGWIN only sources: tclWinError.o: $(TOP_DIR)/win/tclWinError.c $(CC) -c $(CC_SWITCHES) $(TOP_DIR)/win/tclWinError.c +tclWinPanic.o: $(TOP_DIR)/win/tclWinPanic.c + $(CC) -c $(CC_SWITCHES) $(TOP_DIR)/win/tclWinPanic.c + # DTrace support $(TCL_OBJS) $(STUB_LIB_OBJS) $(TCLSH_OBJS) $(TCLTEST_OBJS) $(XTTEST_OBJS): @DTRACE_HDR@ diff --git a/unix/configure b/unix/configure index ef47ac5..54b1a87 100755 --- a/unix/configure +++ b/unix/configure @@ -7170,7 +7170,7 @@ fi SHLIB_CFLAGS="" SHLIB_LD='${CC} -shared' SHLIB_SUFFIX=".dll" - DL_OBJS="tclLoadDl.o tclWinError.o" + DL_OBJS="tclLoadDl.o tclWinError.o tclWinPanic.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" diff --git a/unix/tcl.m4 b/unix/tcl.m4 index b9b6532..d1f9b66 100644 --- a/unix/tcl.m4 +++ b/unix/tcl.m4 @@ -1224,7 +1224,7 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [ SHLIB_CFLAGS="" SHLIB_LD='${CC} -shared' SHLIB_SUFFIX=".dll" - DL_OBJS="tclLoadDl.o tclWinError.o" + DL_OBJS="tclLoadDl.o tclWinError.o tclWinPanic.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" diff --git a/win/tclWinPanic.c b/win/tclWinPanic.c index bc59d75..3c2e072 100644 --- a/win/tclWinPanic.c +++ b/win/tclWinPanic.c @@ -34,11 +34,13 @@ Tcl_ConsolePanic( const char *format, ...) { #define TCL_MAX_WARN_LEN 26000 - DWORD dummy; va_list argList; WCHAR msgString[TCL_MAX_WARN_LEN]; char buf[TCL_MAX_WARN_LEN * TCL_UTF_MAX]; +#ifndef __CYGWIN__ HANDLE handle = GetStdHandle(STD_ERROR_HANDLE); + DWORD dummy; +#endif va_start(argList, format); vsnprintf(buf+3, sizeof(buf)-3, format, argList); @@ -56,23 +58,36 @@ Tcl_ConsolePanic( if (IsDebuggerPresent()) { OutputDebugStringW(msgString); +#ifdef __CYGWIN__ + } else { + buf[0] = 0xEF; buf[1] = 0xBB; buf[2] = 0xBF; /* UTF-8 bom */ + write(2, buf, strlen(buf)); + fsync(2); +#else } else if (_isatty(2)) { WriteConsoleW(handle, msgString, wcslen(msgString), &dummy, 0); } else { buf[0] = 0xEF; buf[1] = 0xBB; buf[2] = 0xBF; /* UTF-8 bom */ WriteFile(handle, buf, strlen(buf), &dummy, 0); FlushFileBuffers(handle); +#endif } -#if defined(__GNUC__) - __builtin_trap(); -#elif defined(_WIN64) - __debugbreak(); -#elif defined(_MSC_VER) - _asm {int 3} +#if defined(_WIN32) || defined(__CYGWIN__) +# if defined(__GNUC__) + __builtin_trap(); +# elif defined(_WIN64) + __debugbreak(); +# elif defined(_MSC_VER) + _asm {int 3} +# else + DebugBreak(); +# endif +#endif +#if defined(_WIN32) + ExitProcess(1); #else - DebugBreak(); + abort(); #endif - ExitProcess(1); } /* * Local Variables: -- cgit v0.12 From 017b8b10b611c4b8dbcbeaadc07559ace4a5e346 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 24 Jul 2013 14:14:34 +0000 Subject: Fix Cygwin build: put Tcl_ConsolePanic in the stub library, not the dll. --- unix/Makefile.in | 4 ++-- unix/configure | 8 ++++++-- unix/tcl.m4 | 5 ++++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/unix/Makefile.in b/unix/Makefile.in index bc66f19..578a896 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -335,7 +335,7 @@ TOMMATH_OBJS = bncore.o bn_reverse.o bn_fast_s_mp_mul_digs.o \ bn_mp_unsigned_bin_size.o bn_mp_xor.o bn_mp_zero.o bn_s_mp_add.o \ bn_s_mp_mul_digs.o bn_s_mp_sqr.o bn_s_mp_sub.o -STUB_LIB_OBJS = tclStubLib.o tclTomMathStubLib.o tclOOStubLib.o ${COMPAT_OBJS} +STUB_LIB_OBJS = tclStubLib.o tclTomMathStubLib.o tclOOStubLib.o ${COMPAT_OBJS} @STUB_OBJS@ UNIX_OBJS = tclUnixChan.o tclUnixEvent.o tclUnixFCmd.o \ tclUnixFile.o tclUnixPipe.o tclUnixSock.o \ @@ -1585,7 +1585,7 @@ tclWinError.o: $(TOP_DIR)/win/tclWinError.c $(CC) -c $(CC_SWITCHES) $(TOP_DIR)/win/tclWinError.c tclWinPanic.o: $(TOP_DIR)/win/tclWinPanic.c - $(CC) -c $(CC_SWITCHES) $(TOP_DIR)/win/tclWinPanic.c + $(CC) -c $(CC_SWITCHES) -DBUILD_STATIC $(TOP_DIR)/win/tclWinPanic.c # DTrace support diff --git a/unix/configure b/unix/configure index 54b1a87..944b342 100755 --- a/unix/configure +++ b/unix/configure @@ -308,7 +308,7 @@ ac_includes_default="\ # include #endif" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS MAN_FLAGS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP TCL_THREADS TCLSH_PROG ZLIB_OBJS ZLIB_SRCS ZLIB_INCLUDE RANLIB ac_ct_RANLIB AR ac_ct_AR LIBOBJS TCL_LIBS DL_LIBS DL_OBJS PLAT_OBJS PLAT_SRCS LDAIX_SRC CFLAGS_DEBUG CFLAGS_OPTIMIZE CFLAGS_WARNING LDFLAGS_DEBUG LDFLAGS_OPTIMIZE CC_SEARCH_FLAGS LD_SEARCH_FLAGS STLIB_LD SHLIB_LD TCL_SHLIB_LD_EXTRAS TK_SHLIB_LD_EXTRAS SHLIB_LD_LIBS SHLIB_CFLAGS SHLIB_SUFFIX MAKE_LIB MAKE_STUB_LIB INSTALL_LIB DLL_INSTALL_DIR INSTALL_STUB_LIB CFLAGS_DEFAULT LDFLAGS_DEFAULT DTRACE TCL_VERSION TCL_MAJOR_VERSION TCL_MINOR_VERSION TCL_PATCH_LEVEL TCL_YEAR PKG_CFG_ARGS TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC TCL_STUB_LIB_PATH TCL_INCLUDE_SPEC TCL_BUILD_STUB_LIB_SPEC TCL_BUILD_STUB_LIB_PATH TCL_SRC_DIR CFG_TCL_SHARED_LIB_SUFFIX CFG_TCL_UNSHARED_LIB_SUFFIX TCL_SHARED_BUILD LD_LIBRARY_PATH_VAR TCL_BUILD_LIB_SPEC TCL_LIB_VERSIONS_OK TCL_SHARED_LIB_SUFFIX TCL_UNSHARED_LIB_SUFFIX TCL_HAS_LONGLONG INSTALL_TZDATA DTRACE_SRC DTRACE_HDR DTRACE_OBJ MAKEFILE_SHELL BUILD_DLTEST TCL_PACKAGE_PATH TCL_MODULE_PATH TCL_LIBRARY PRIVATE_INCLUDE_DIR HTML_DIR PACKAGE_DIR EXTRA_CC_SWITCHES EXTRA_APP_CC_SWITCHES EXTRA_INSTALL EXTRA_INSTALL_BINARIES EXTRA_BUILD_HTML EXTRA_TCLSH_LIBS DLTEST_LD DLTEST_SUFFIX' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS MAN_FLAGS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP TCL_THREADS TCLSH_PROG ZLIB_OBJS ZLIB_SRCS ZLIB_INCLUDE RANLIB ac_ct_RANLIB AR ac_ct_AR LIBOBJS TCL_LIBS DL_LIBS DL_OBJS PLAT_OBJS PLAT_SRCS STUB_OBJS LDAIX_SRC CFLAGS_DEBUG CFLAGS_OPTIMIZE CFLAGS_WARNING LDFLAGS_DEBUG LDFLAGS_OPTIMIZE CC_SEARCH_FLAGS LD_SEARCH_FLAGS STLIB_LD SHLIB_LD TCL_SHLIB_LD_EXTRAS TK_SHLIB_LD_EXTRAS SHLIB_LD_LIBS SHLIB_CFLAGS SHLIB_SUFFIX MAKE_LIB MAKE_STUB_LIB INSTALL_LIB DLL_INSTALL_DIR INSTALL_STUB_LIB CFLAGS_DEFAULT LDFLAGS_DEFAULT DTRACE TCL_VERSION TCL_MAJOR_VERSION TCL_MINOR_VERSION TCL_PATCH_LEVEL TCL_YEAR PKG_CFG_ARGS TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC TCL_STUB_LIB_PATH TCL_INCLUDE_SPEC TCL_BUILD_STUB_LIB_SPEC TCL_BUILD_STUB_LIB_PATH TCL_SRC_DIR CFG_TCL_SHARED_LIB_SUFFIX CFG_TCL_UNSHARED_LIB_SUFFIX TCL_SHARED_BUILD LD_LIBRARY_PATH_VAR TCL_BUILD_LIB_SPEC TCL_LIB_VERSIONS_OK TCL_SHARED_LIB_SUFFIX TCL_UNSHARED_LIB_SUFFIX TCL_HAS_LONGLONG INSTALL_TZDATA DTRACE_SRC DTRACE_HDR DTRACE_OBJ MAKEFILE_SHELL BUILD_DLTEST TCL_PACKAGE_PATH TCL_MODULE_PATH TCL_LIBRARY PRIVATE_INCLUDE_DIR HTML_DIR PACKAGE_DIR EXTRA_CC_SWITCHES EXTRA_APP_CC_SWITCHES EXTRA_INSTALL EXTRA_INSTALL_BINARIES EXTRA_BUILD_HTML EXTRA_TCLSH_LIBS DLTEST_LD DLTEST_SUFFIX' ac_subst_files='' # Initialize some variables set by options. @@ -7170,7 +7170,9 @@ fi SHLIB_CFLAGS="" SHLIB_LD='${CC} -shared' SHLIB_SUFFIX=".dll" - DL_OBJS="tclLoadDl.o tclWinError.o tclWinPanic.o" + DL_OBJS="tclLoadDl.o" + PLAT_OBJS="tclWinError.o" + STUB_OBJS="tclWinPanic.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" @@ -9293,6 +9295,7 @@ _ACEOF + cat >>confdefs.h <<_ACEOF #define TCL_SHLIB_EXT "${SHLIB_SUFFIX}" _ACEOF @@ -20118,6 +20121,7 @@ s,@DL_LIBS@,$DL_LIBS,;t t s,@DL_OBJS@,$DL_OBJS,;t t s,@PLAT_OBJS@,$PLAT_OBJS,;t t s,@PLAT_SRCS@,$PLAT_SRCS,;t t +s,@STUB_OBJS@,$STUB_OBJS,;t t s,@LDAIX_SRC@,$LDAIX_SRC,;t t s,@CFLAGS_DEBUG@,$CFLAGS_DEBUG,;t t s,@CFLAGS_OPTIMIZE@,$CFLAGS_OPTIMIZE,;t t diff --git a/unix/tcl.m4 b/unix/tcl.m4 index d1f9b66..dd8e682 100644 --- a/unix/tcl.m4 +++ b/unix/tcl.m4 @@ -1224,7 +1224,9 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [ SHLIB_CFLAGS="" SHLIB_LD='${CC} -shared' SHLIB_SUFFIX=".dll" - DL_OBJS="tclLoadDl.o tclWinError.o tclWinPanic.o" + DL_OBJS="tclLoadDl.o" + PLAT_OBJS="tclWinError.o" + STUB_OBJS="tclWinPanic.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" @@ -2106,6 +2108,7 @@ dnl # preprocessing tests use only CPPFLAGS. AC_SUBST(DL_OBJS) AC_SUBST(PLAT_OBJS) AC_SUBST(PLAT_SRCS) + AC_SUBST(STUB_OBJS) AC_SUBST(LDAIX_SRC) AC_SUBST(CFLAGS) AC_SUBST(CFLAGS_DEBUG) -- cgit v0.12 From 5470f1329925b63a1ac3def74b82b9b3a4851f0e Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 23 Oct 2017 13:47:57 +0000 Subject: tclWinPanic.c is in the \win directory, not in \generic! --- win/tcl.dsp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/win/tcl.dsp b/win/tcl.dsp index abad0bb..214449c 100644 --- a/win/tcl.dsp +++ b/win/tcl.dsp @@ -1304,10 +1304,6 @@ SOURCE=..\generic\tclOOStubLib.c # End Source File # Begin Source File -SOURCE=..\generic\tclWinPanic.c -# End Source File -# Begin Source File - SOURCE=..\generic\tclTomMathStubLib.c # End Source File # Begin Source File @@ -1532,6 +1528,10 @@ SOURCE=.\tclWinNotify.c # End Source File # Begin Source File +SOURCE=.\tclWinPanic.c +# End Source File +# Begin Source File + SOURCE=.\tclWinPipe.c # End Source File # Begin Source File -- cgit v0.12 From 40ce2eccbc52b403d4a4b7bc479fbde987a14e18 Mon Sep 17 00:00:00 2001 From: fvogel Date: Tue, 24 Oct 2017 21:24:07 +0000 Subject: 'array for' implementation (TIP #421) from Brad Lanam --- doc/array.n | 7 + generic/tclVar.c | 388 +++++++++++++++++++++++++++++++++++++++++++++++++---- tests/set-old.test | 6 +- tests/var.test | 160 +++++++++++++++++++++- 4 files changed, 528 insertions(+), 33 deletions(-) diff --git a/doc/array.n b/doc/array.n index 25ad0c6..751c688 100644 --- a/doc/array.n +++ b/doc/array.n @@ -47,6 +47,13 @@ been the return value from a previous invocation of 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. .TP +\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 diff --git a/generic/tclVar.c b/generic/tclVar.c index 3dd6790..d6f3e96 100644 --- a/generic/tclVar.c +++ b/generic/tclVar.c @@ -165,6 +165,7 @@ typedef struct ArraySearch { struct ArraySearch *nextPtr;/* Next in list of all active searches for * this variable, or NULL if this is the last * one. */ + Tcl_Obj *arrayNameObj; /* name of the array object */ } ArraySearch; /* @@ -173,6 +174,8 @@ typedef struct ArraySearch { static void AppendLocals(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *patternPtr, int includeLinks); +static void ArrayDoneSearch (Interp *iPtr, Var *varPtr, ArraySearch *searchPtr); +static Tcl_NRPostProc ArrayForLoopCallback; static void DeleteSearches(Interp *iPtr, Var *arrayVarPtr); static void DeleteArray(Interp *iPtr, Tcl_Obj *arrayNamePtr, Var *varPtr, int flags, int index); @@ -3098,6 +3101,321 @@ TclArraySet( /* *---------------------------------------------------------------------- * + * ArrayForNRCmd + * ArrayForLoopCallback + * ArrayObjFirst + * ArrayObjNext + * + * These functions implement the "array for" Tcl command. + * array for {k v} a {} + * The array for command iterates over the array, setting the + * the specified loop variables, and executing the body each iteration. + * + * ArrayForNRCmd() sets up the ArraySearch structure, sets arrayNamePtr + * inside the structure and calls VarHashFirstEntry to start the hash + * iteration. + * + * ArrayForNRCmd() does not execute the body or set the loop variables, + * it only initializes the iterator. + * + * ArrayForLoopCallback() iterates over the entire array, executing + * the body each time. + * + * ArrayObjFirst() Does not execute the body or set the key/value variables. + * + *---------------------------------------------------------------------- + */ +void +ArrayObjFirst( + Tcl_Interp *interp, + Tcl_Obj *arrayNameObj, + Var *varPtr, + ArraySearch *searchPtr) +{ + Interp *iPtr = (Interp *) interp; + Tcl_HashEntry *hPtr; + int isNew; + + searchPtr->varPtr = varPtr; + searchPtr->arrayNameObj = arrayNameObj; + + /* add the search to the search table */ + hPtr = Tcl_CreateHashEntry(&iPtr->varSearches, varPtr, &isNew); + if (isNew) { + searchPtr->id = 1; + varPtr->flags |= VAR_SEARCH_ACTIVE; + searchPtr->nextPtr = NULL; + } else { + searchPtr->id = ((ArraySearch *) Tcl_GetHashValue(hPtr))->id + 1; + searchPtr->nextPtr = Tcl_GetHashValue(hPtr); + } + searchPtr->nextEntry = VarHashFirstEntry(varPtr->value.tablePtr, + &searchPtr->search); + Tcl_SetHashValue(hPtr, searchPtr); +} + +int +ArrayObjNext( + Tcl_Interp *interp, + Var *varPtr, /* array */ + ArraySearch *searchPtr, + Tcl_Obj **keyPtrPtr, /* Pointer to a variable to have the key + * written into, or NULL. */ + Tcl_Obj **valuePtrPtr /* Pointer to a variable to have the + * value written into, or NULL.*/ + ) +{ + Tcl_Obj *keyObj; + Tcl_Obj *valueObj = NULL; + int gotValue; + int donerc; + + donerc = TCL_BREAK; + + if ((varPtr->flags & VAR_SEARCH_ACTIVE) != VAR_SEARCH_ACTIVE) { + donerc = TCL_ERROR; + return donerc; + } + + gotValue = 0; + while (1) { + Tcl_HashEntry *hPtr = searchPtr->nextEntry; + if (hPtr != NULL) { + searchPtr->nextEntry = NULL; + } else { + hPtr = Tcl_NextHashEntry(&searchPtr->search); + if (hPtr == NULL) { + gotValue = 0; + break; + } + } + varPtr = VarHashGetValue(hPtr); + if (!TclIsVarUndefined(varPtr)) { + gotValue = 1; + break; + } + } + + if (! gotValue) { + return donerc; + } + + donerc = TCL_CONTINUE; + + keyObj = VarHashGetKey(varPtr); + *keyPtrPtr = keyObj; + valueObj = Tcl_ObjGetVar2(interp, searchPtr->arrayNameObj, + keyObj, TCL_LEAVE_ERR_MSG); + *valuePtrPtr = valueObj; + + return donerc; +} + +static int +ArrayForNRCmd( + ClientData dummy, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const *objv) +{ + Interp *iPtr = (Interp *) interp; + Tcl_Obj *scriptObj, *keyVarObj, *valueVarObj; + Tcl_Obj **varv; + Tcl_Obj *arrayNameObj; + ArraySearch *searchPtr = NULL; + Var *varPtr; + Var *arrayPtr; + int varc; + + /* + * array for {k v} a body + */ + + if (objc != 4) { + Tcl_WrongNumArgs(interp, 1, objv, + "{key value} arrayName script"); + return TCL_ERROR; + } + + /* + * Parse arguments. + */ + + if (TclListObjGetElements(interp, objv[1], &varc, &varv) != TCL_OK) { + return TCL_ERROR; + } + if (varc != 2) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "must have two variable names", -1)); + Tcl_SetErrorCode(interp, "TCL", "SYNTAX", "array", "for", NULL); + return TCL_ERROR; + } + + arrayNameObj = objv[2]; + keyVarObj = varv[0]; + valueVarObj = varv[1]; + scriptObj = objv[3]; + + /* + * Locate the array variable. + */ + + varPtr = TclObjLookupVarEx(interp, arrayNameObj, NULL, /*flags*/ 0, + /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); + + /* + * Special array trace used to keep the env array in sync for array names, + * array get, etc. + */ + + if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) + && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { + if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, arrayNameObj, NULL, + (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| + TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) { + return TCL_ERROR; + } + } + + /* + * Verify that it is indeed an array variable. This test comes after the + * traces; the variable may actually become an array as an effect of said + * traces. + */ + + if ((varPtr == NULL) || !TclIsVarArray(varPtr) + || TclIsVarUndefined(varPtr)) { + const char *varName = Tcl_GetString(arrayNameObj); + + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "\"%s\" isn't an array", varName)); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY", varName, NULL); + return TCL_ERROR; + } + + /* + * Make a new array search, put it on the stack. + */ + + searchPtr = ckalloc(sizeof(ArraySearch)); + searchPtr->arrayNameObj = NULL; + ArrayObjFirst(interp, arrayNameObj, varPtr, searchPtr); + + /* + * Make sure that these objects (which we need throughout the body of the + * loop) don't vanish. + */ + + Tcl_IncrRefCount(keyVarObj); + Tcl_IncrRefCount(valueVarObj); + Tcl_IncrRefCount(scriptObj); + + /* + * Run the script. + */ + + TclNRAddCallback(interp, ArrayForLoopCallback, searchPtr, keyVarObj, + valueVarObj, scriptObj); + return TCL_OK; +} + +static int +ArrayForLoopCallback( + ClientData data[], + Tcl_Interp *interp, + int result) +{ + Interp *iPtr = (Interp *) interp; + ArraySearch *searchPtr = data[0]; + Tcl_Obj *keyVarObj = data[1]; + Tcl_Obj *valueVarObj = data[2]; + Tcl_Obj *scriptObj = data[3]; + Tcl_Obj *keyObj, *valueObj; + Var *varPtr; + Var *arrayPtr; + int done; + + /* + * Process the result from the previous execution of the script body. + */ + + done = TCL_ERROR; + varPtr = TclObjLookupVarEx(interp, searchPtr->arrayNameObj, NULL, /*flags*/ 0, + /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); + + if (result == TCL_CONTINUE) { + result = TCL_OK; + } else if (result != TCL_OK) { + if (result == TCL_BREAK) { + Tcl_ResetResult(interp); + result = TCL_OK; + } else if (result == TCL_ERROR) { + Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( + "\n (\"array for\" body line %d)", + Tcl_GetErrorLine(interp))); + } + goto arrayfordone; + } + + /* + * Get the next mapping from the array. + */ + + keyObj = NULL; + valueObj = NULL; + done = ArrayObjNext (interp, varPtr, searchPtr, &keyObj, &valueObj); + + result = TCL_OK; + if (done != TCL_CONTINUE) { + Tcl_ResetResult(interp); + if (done == TCL_ERROR) { + varPtr->flags |= TCL_LEAVE_ERR_MSG; + Tcl_AddErrorInfo(interp, "array changed during iteration"); + result = done; + } + goto arrayfordone; + } + if (Tcl_ObjSetVar2(interp, keyVarObj, NULL, keyObj, TCL_LEAVE_ERR_MSG) == NULL) { + result = TCL_ERROR; + goto arrayfordone; + } + if (valueObj != NULL) { + if (Tcl_ObjSetVar2(interp, valueVarObj, NULL, valueObj, TCL_LEAVE_ERR_MSG) == NULL) { + result = TCL_ERROR; + goto arrayfordone; + } + } + + /* + * Run the script. + */ + + TclNRAddCallback(interp, ArrayForLoopCallback, searchPtr, keyVarObj, + valueVarObj, scriptObj); + return TclNREvalObjEx(interp, scriptObj, 0, iPtr->cmdFramePtr, 3); + + /* + * For unwinding everything once the iterating is done. + */ + + arrayfordone: + /* if the search was terminated by an array change, the + * VAR_SEARCH_ACTIVE flag will no longer be set + */ + if (done != TCL_ERROR) { + ArrayDoneSearch (iPtr, varPtr, searchPtr); + ckfree(searchPtr); + } + + TclDecrRefCount(keyVarObj); + TclDecrRefCount(valueVarObj); + TclDecrRefCount(scriptObj); + return result; +} + +/* + *---------------------------------------------------------------------- + * * ArrayStartSearchCmd -- * * This object-based function is invoked to process the "array @@ -3197,6 +3515,50 @@ ArrayStartSearchCmd( /* *---------------------------------------------------------------------- * + * ArrayDoneSearch -- + * + * Removes the search from the hash of active searches. + * + *---------------------------------------------------------------------- + */ +static void +ArrayDoneSearch ( + Interp *iPtr, + Var *varPtr, + ArraySearch *searchPtr) +{ + Tcl_HashEntry *hPtr; + ArraySearch *prevPtr; + + /* + * Unhook the search from the list of searches associated with the + * variable. + */ + + hPtr = Tcl_FindHashEntry(&iPtr->varSearches, varPtr); + if (hPtr == NULL) { + return; + } + if (searchPtr == Tcl_GetHashValue(hPtr)) { + if (searchPtr->nextPtr) { + Tcl_SetHashValue(hPtr, searchPtr->nextPtr); + } else { + varPtr->flags &= ~VAR_SEARCH_ACTIVE; + Tcl_DeleteHashEntry(hPtr); + } + } else { + for (prevPtr=Tcl_GetHashValue(hPtr) ;; prevPtr=prevPtr->nextPtr) { + if (prevPtr->nextPtr == searchPtr) { + prevPtr->nextPtr = searchPtr->nextPtr; + break; + } + } + } +} + +/* + *---------------------------------------------------------------------- + * * ArrayAnyMoreCmd -- * * This object-based function is invoked to process the "array anymore" @@ -3437,9 +3799,8 @@ ArrayDoneSearchCmd( { Interp *iPtr = (Interp *) interp; Var *varPtr, *arrayPtr; - Tcl_HashEntry *hPtr; Tcl_Obj *varNameObj, *searchObj; - ArraySearch *searchPtr, *prevPtr; + ArraySearch *searchPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "arrayName searchId"); @@ -3493,27 +3854,7 @@ ArrayDoneSearchCmd( return TCL_ERROR; } - /* - * Unhook the search from the list of searches associated with the - * variable. - */ - - hPtr = Tcl_FindHashEntry(&iPtr->varSearches, varPtr); - if (searchPtr == Tcl_GetHashValue(hPtr)) { - if (searchPtr->nextPtr) { - Tcl_SetHashValue(hPtr, searchPtr->nextPtr); - } else { - varPtr->flags &= ~VAR_SEARCH_ACTIVE; - Tcl_DeleteHashEntry(hPtr); - } - } else { - for (prevPtr=Tcl_GetHashValue(hPtr) ;; prevPtr=prevPtr->nextPtr) { - if (prevPtr->nextPtr == searchPtr) { - prevPtr->nextPtr = searchPtr->nextPtr; - break; - } - } - } + ArrayDoneSearch (iPtr, varPtr, searchPtr); ckfree(searchPtr); return TCL_OK; } @@ -4372,6 +4713,7 @@ TclInitArrayCmd( {"anymore", ArrayAnyMoreCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"donesearch", ArrayDoneSearchCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"exists", ArrayExistsCmd, TclCompileArrayExistsCmd, NULL, NULL, 0}, + {"for", NULL, TclCompileBasic3ArgCmd, ArrayForNRCmd, NULL, 0}, {"get", ArrayGetCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, {"names", ArrayNamesCmd, TclCompileBasic1To3ArgCmd, NULL, NULL, 0}, {"nextelement", ArrayNextElementCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, diff --git a/tests/set-old.test b/tests/set-old.test index 6138ed8..3b4184c 100644 --- a/tests/set-old.test +++ b/tests/set-old.test @@ -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 @@ -652,7 +652,7 @@ test set-old-8.52 {array command, array names -regexp on regexp pattern} { set a(11) 1 list [catch {lsort [array names a -regexp ^1]} msg] $msg } {0 {1*2 11 12}} -test set-old-8.52.1 {array command, array names -regexp, backrefs} { +?test set-old-8.52.1 {array command, array names -regexp, backrefs} { catch {unset a} set a(1*2) 1 set a(12) 1 @@ -940,7 +940,7 @@ catch {rename foo {}} # cleanup ::tcltest::cleanupTests -return +return # Local Variables: # mode: tcl diff --git a/tests/var.test b/tests/var.test index a9d93ac..630202a 100644 --- a/tests/var.test +++ b/tests/var.test @@ -53,7 +53,7 @@ catch {unset arr} test var-1.1 {TclLookupVar, Array handling} -setup { catch {unset a} } -body { - set x "incr" ;# force no compilation and runtime call to Tcl_IncrCmd + set x "incr" ;# force no compilation and runtime call to Tcl_IncrCmd set i 10 set arr(foo) 37 list [$x i] $i [$x arr(foo)] $arr(foo) @@ -234,7 +234,7 @@ test var-3.3 {MakeUpvar, my var has TCL_GLOBAL_ONLY specified} -setup { set a 123321 proc p {} { # create global xx linked to global a - testupvar 1 a {} xx global + testupvar 1 a {} xx global } list [p] $xx [set xx 789] $a } -result {{} 123321 789 789} @@ -246,7 +246,7 @@ test var-3.4 {MakeUpvar, my var has TCL_NAMESPACE_ONLY specified} -setup { catch {unset ::test_ns_var::vv} proc p {} { # create namespace var vv linked to global a - testupvar 1 a {} vv namespace + testupvar 1 a {} vv namespace } p } @@ -548,11 +548,11 @@ test var-7.14 {Tcl_VariableObjCmd, array element parameter} -body { namespace eval test_ns_var { variable arrayvar(1) } } -returnCodes error -result "can't define \"arrayvar(1)\": name refers to an element in an array" test var-7.15 {Tcl_VariableObjCmd, array element parameter} -body { - namespace eval test_ns_var { + namespace eval test_ns_var { variable arrayvar set arrayvar(1) x variable arrayvar(1) y - } + } } -returnCodes error -result "can't define \"arrayvar(1)\": name refers to an element in an array" test var-7.16 {Tcl_VariableObjCmd, no args (TIP 323)} { variable @@ -790,7 +790,7 @@ test var-15.1 {segfault in [unset], [Bug 735335]} { set var $name } # - # Note that the variable name has to be + # Note that the variable name has to be # unused previously for the segfault to # be triggered. # @@ -997,7 +997,153 @@ test var-22.1 {leak in localVarName intrep: Bug 80304238ac} -setup { rename getbytes {} rename doit {} } -result 0 - + +unset -nocomplain a k v +test var-23.1 {array command, for loop, too many args} -returnCodes error -body { + array for {k v} c d e {} +} -result {wrong # args: should be "array for {key value} arrayName script"} +test var-23.2 {array command, for loop, not enough args} -returnCodes error -body { + array for {k v} {} +} -result {wrong # args: should be "array for {key value} arrayName script"} +test var-23.3 {array command, for loop, too many list args} -setup { + unset -nocomplain a +} -returnCodes error -body { + array for {k v w} a {} +} -result {must have two variable names} +test var-23.4 {array command, for loop, not enough list args} -setup { + unset -nocomplain a +} -returnCodes error -body { + array for {k} a {} +} -result {must have two variable names} +test var-23.5 {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.6 {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.7 {array enumeration} -setup { + unset -nocomplain a + set reslist [list] +} -body { + array set a {a 1 b 2 c 3} + array for {k v} a { + lappend reslist $k $v + } + lsort -stride 2 -index 0 $reslist +} -cleanup { + unset -nocomplain a + unset -nocomplain reslist +} -result {a 1 b 2 c 3} +test var-23.9 {array enumeration, nested} -setup { + unset -nocomplain a + 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 +} -cleanup { + unset -nocomplain a + unset -nocomplain 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.10 {array enumeration, delete key} -match glob -setup { + unset -nocomplain a + set reslist [list] +} -body { + set retval {} + try { + array set a {a 1 b 2 c 3 d 4} + array for {k v} a { + lappend reslist $k $v + if { $k eq "a" } { + unset a(c) + } + } + lsort -stride 2 -index 0 $reslist + } on error {err res} { + set retval [dict get $res -errorinfo] + } + set retval +} -cleanup { + unset -nocomplain a + unset -nocomplain reslist + unset -nocomplain retval +} -result {array changed during iteration*} +test var-23.11 {array enumeration, insert key} -match glob -setup { + unset -nocomplain a + set reslist [list] +} -body { + set retval {} + try { + array set a {a 1 b 2 c 3 d 4} + array for {k v} a { + lappend reslist $k $v + if { $k eq "a" } { + set a(e) 5 + } + } + lsort -stride 2 -index 0 $reslist + } on error {err res} { + set retval [dict get $res -errorinfo] + } +} -cleanup { + unset -nocomplain a + unset -nocomplain reslist +} -result {array changed during iteration*} +test var-23.12 {array enumeration, change value} -setup { + unset -nocomplain a + set reslist [list] +} -body { + array set a {a 1 b 2 c 3} + array for {k v} a { + lappend reslist $k $v + if { $k eq "a" } { + set a(c) 9 + } + } + lsort -stride 2 -index 0 $reslist +} -cleanup { + unset -nocomplain a + unset -nocomplain reslist +} -result {a 1 b 2 c 9} +test var-23.13 {array enumeration, number of traces} -setup { + set ::countarrayfor 0 + proc ::tracearrayfor { args } { + incr ::countarrayfor + } + unset -nocomplain ::a + set reslist [list] +} -body { + array set ::a {a 1 b 2 c 3} + foreach {k} [array names a] { + trace add variable ::a($k) read ::tracearrayfor + } + array for {k v} ::a { + lappend reslist $k $v + } + set ::countarrayfor +} -cleanup { + unset -nocomplain ::countarrayfor + unset -nocomplain ::a + unset -nocomplain reslist +} -result 3 catch {namespace delete ns} catch {unset arr} -- cgit v0.12 From d8cae66217adcfb4920030071e54e37b5a88a1c4 Mon Sep 17 00:00:00 2001 From: fvogel Date: Wed, 25 Oct 2017 17:31:09 +0000 Subject: Fix typo in set-old.test --- tests/set-old.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/set-old.test b/tests/set-old.test index 3b4184c..b2e7aa6 100644 --- a/tests/set-old.test +++ b/tests/set-old.test @@ -652,7 +652,7 @@ test set-old-8.52 {array command, array names -regexp on regexp pattern} { set a(11) 1 list [catch {lsort [array names a -regexp ^1]} msg] $msg } {0 {1*2 11 12}} -?test set-old-8.52.1 {array command, array names -regexp, backrefs} { +test set-old-8.52.1 {array command, array names -regexp, backrefs} { catch {unset a} set a(1*2) 1 set a(12) 1 -- cgit v0.12 From 48b529209c87473364215e8aef740e331f88415a Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 7 Nov 2017 12:15:30 +0000 Subject: Somewhat simplified implementation of TIP #389, in which the "string length" if characters > U+FFFF is considered to be 2, not 1. --- doc/StringObj.3 | 2 +- doc/ToUpper.3 | 2 +- doc/Utf.3 | 2 +- generic/tcl.decls | 10 +++--- generic/tcl.h | 2 +- generic/tclCmdMZ.c | 18 ++++++++-- generic/tclDecls.h | 20 +++++------ generic/tclScan.c | 12 +++++-- generic/tclStringObj.c | 12 +++---- generic/tclUtf.c | 95 +++++++++++++++++++++++++++++++++++--------------- tests/string.test | 26 +++++++------- tests/utf.test | 4 +-- 12 files changed, 132 insertions(+), 73 deletions(-) diff --git a/doc/StringObj.3 b/doc/StringObj.3 index 7042cc8..8d9bb56 100644 --- a/doc/StringObj.3 +++ b/doc/StringObj.3 @@ -37,7 +37,7 @@ Tcl_UniChar * Tcl_UniChar * \fBTcl_GetUnicode\fR(\fIobjPtr\fR) .sp -Tcl_UniChar +int \fBTcl_GetUniChar\fR(\fIobjPtr, index\fR) .sp int diff --git a/doc/ToUpper.3 b/doc/ToUpper.3 index b933e9c..14766da 100644 --- a/doc/ToUpper.3 +++ b/doc/ToUpper.3 @@ -13,7 +13,7 @@ Tcl_UniCharToUpper, Tcl_UniCharToLower, Tcl_UniCharToTitle, Tcl_UtfToUpper, Tcl_ .nf \fB#include \fR .sp -Tcl_UniChar +int \fBTcl_UniCharToUpper\fR(\fIch\fR) .sp Tcl_UniChar diff --git a/doc/Utf.3 b/doc/Utf.3 index 378c806..5cd6b7df 100644 --- a/doc/Utf.3 +++ b/doc/Utf.3 @@ -63,7 +63,7 @@ const char * const char * \fBTcl_UtfPrev\fR(\fIsrc, start\fR) .sp -Tcl_UniChar +int \fBTcl_UniCharAtIndex\fR(\fIsrc, index\fR) .sp const char * diff --git a/generic/tcl.decls b/generic/tcl.decls index b2b91a9..e3ea9bc 100644 --- a/generic/tcl.decls +++ b/generic/tcl.decls @@ -1148,16 +1148,16 @@ declare 319 { Tcl_QueuePosition position) } declare 320 { - Tcl_UniChar Tcl_UniCharAtIndex(const char *src, int index) + int Tcl_UniCharAtIndex(const char *src, int index) } declare 321 { - Tcl_UniChar Tcl_UniCharToLower(int ch) + int Tcl_UniCharToLower(int ch) } declare 322 { - Tcl_UniChar Tcl_UniCharToTitle(int ch) + int Tcl_UniCharToTitle(int ch) } declare 323 { - Tcl_UniChar Tcl_UniCharToUpper(int ch) + int Tcl_UniCharToUpper(int ch) } declare 324 { int Tcl_UniCharToUtf(int ch, char *buf) @@ -1351,7 +1351,7 @@ declare 380 { int Tcl_GetCharLength(Tcl_Obj *objPtr) } declare 381 { - Tcl_UniChar Tcl_GetUniChar(Tcl_Obj *objPtr, int index) + int Tcl_GetUniChar(Tcl_Obj *objPtr, int index) } declare 382 { Tcl_UniChar *Tcl_GetUnicode(Tcl_Obj *objPtr) diff --git a/generic/tcl.h b/generic/tcl.h index 07d841d..f874997 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -2201,7 +2201,7 @@ typedef struct Tcl_EncodingType { */ #ifndef TCL_UTF_MAX -#define TCL_UTF_MAX 3 +#define TCL_UTF_MAX 4 #endif /* diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index 2195aa1..b6a8fe9 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -309,7 +309,7 @@ Tcl_RegexpObjCmd( eflags = 0; } else if (offset > stringLength) { eflags = TCL_REG_NOTBOL; - } else if (Tcl_GetUniChar(objPtr, offset-1) == (Tcl_UniChar)'\n') { + } else if (Tcl_GetUniChar(objPtr, offset-1) == '\n') { eflags = 0; } else { eflags = TCL_REG_NOTBOL; @@ -1218,6 +1218,12 @@ Tcl_SplitObjCmd( for ( ; stringPtr < end; stringPtr += len) { len = TclUtfToUniChar(stringPtr, &ch); +#if TCL_UTF_MAX == 4 + if (!len) { + continue; + } +#endif + /* * Assume Tcl_UniChar is an integral type... */ @@ -1814,8 +1820,16 @@ StringIsCmd( } end = string1 + length1; for (; string1 < end; string1 += length2, failat++) { + int fullchar; length2 = TclUtfToUniChar(string1, &ch); - if (!chcomp(ch)) { + fullchar = ch; +#if TCL_UTF_MAX == 4 + if (!length2) { + length2 = TclUtfToUniChar(string1, &ch); + fullchar = (((fullchar & 0x3ff) << 10) | (ch & 0x3ff)) + 0x10000; + } +#endif + if (!chcomp(fullchar)) { result = 0; break; } diff --git a/generic/tclDecls.h b/generic/tclDecls.h index 464fc0f..5f83636 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -959,13 +959,13 @@ EXTERN void Tcl_ThreadAlert(Tcl_ThreadId threadId); EXTERN void Tcl_ThreadQueueEvent(Tcl_ThreadId threadId, Tcl_Event *evPtr, Tcl_QueuePosition position); /* 320 */ -EXTERN Tcl_UniChar Tcl_UniCharAtIndex(const char *src, int index); +EXTERN int Tcl_UniCharAtIndex(const char *src, int index); /* 321 */ -EXTERN Tcl_UniChar Tcl_UniCharToLower(int ch); +EXTERN int Tcl_UniCharToLower(int ch); /* 322 */ -EXTERN Tcl_UniChar Tcl_UniCharToTitle(int ch); +EXTERN int Tcl_UniCharToTitle(int ch); /* 323 */ -EXTERN Tcl_UniChar Tcl_UniCharToUpper(int ch); +EXTERN int Tcl_UniCharToUpper(int ch); /* 324 */ EXTERN int Tcl_UniCharToUtf(int ch, char *buf); /* 325 */ @@ -1117,7 +1117,7 @@ EXTERN void Tcl_SetUnicodeObj(Tcl_Obj *objPtr, /* 380 */ EXTERN int Tcl_GetCharLength(Tcl_Obj *objPtr); /* 381 */ -EXTERN Tcl_UniChar Tcl_GetUniChar(Tcl_Obj *objPtr, int index); +EXTERN int Tcl_GetUniChar(Tcl_Obj *objPtr, int index); /* 382 */ EXTERN Tcl_UniChar * Tcl_GetUnicode(Tcl_Obj *objPtr); /* 383 */ @@ -2186,10 +2186,10 @@ typedef struct TclStubs { Tcl_Obj * (*tcl_SetVar2Ex) (Tcl_Interp *interp, const char *part1, const char *part2, Tcl_Obj *newValuePtr, int flags); /* 317 */ void (*tcl_ThreadAlert) (Tcl_ThreadId threadId); /* 318 */ void (*tcl_ThreadQueueEvent) (Tcl_ThreadId threadId, Tcl_Event *evPtr, Tcl_QueuePosition position); /* 319 */ - Tcl_UniChar (*tcl_UniCharAtIndex) (const char *src, int index); /* 320 */ - Tcl_UniChar (*tcl_UniCharToLower) (int ch); /* 321 */ - Tcl_UniChar (*tcl_UniCharToTitle) (int ch); /* 322 */ - Tcl_UniChar (*tcl_UniCharToUpper) (int ch); /* 323 */ + int (*tcl_UniCharAtIndex) (const char *src, int index); /* 320 */ + int (*tcl_UniCharToLower) (int ch); /* 321 */ + int (*tcl_UniCharToTitle) (int ch); /* 322 */ + int (*tcl_UniCharToUpper) (int ch); /* 323 */ int (*tcl_UniCharToUtf) (int ch, char *buf); /* 324 */ CONST84_RETURN char * (*tcl_UtfAtIndex) (const char *src, int index); /* 325 */ int (*tcl_UtfCharComplete) (const char *src, int length); /* 326 */ @@ -2247,7 +2247,7 @@ typedef struct TclStubs { Tcl_Obj * (*tcl_NewUnicodeObj) (const Tcl_UniChar *unicode, int numChars); /* 378 */ void (*tcl_SetUnicodeObj) (Tcl_Obj *objPtr, const Tcl_UniChar *unicode, int numChars); /* 379 */ int (*tcl_GetCharLength) (Tcl_Obj *objPtr); /* 380 */ - Tcl_UniChar (*tcl_GetUniChar) (Tcl_Obj *objPtr, int index); /* 381 */ + int (*tcl_GetUniChar) (Tcl_Obj *objPtr, int index); /* 381 */ Tcl_UniChar * (*tcl_GetUnicode) (Tcl_Obj *objPtr); /* 382 */ Tcl_Obj * (*tcl_GetRange) (Tcl_Obj *objPtr, int first, int last); /* 383 */ void (*tcl_AppendUnicodeToObj) (Tcl_Obj *objPtr, const Tcl_UniChar *unicode, int length); /* 384 */ diff --git a/generic/tclScan.c b/generic/tclScan.c index e1fcad4..7f71262 100644 --- a/generic/tclScan.c +++ b/generic/tclScan.c @@ -885,9 +885,17 @@ Tcl_ScanObjCmd( * Scan a single Unicode character. */ - string += TclUtfToUniChar(string, &sch); + offset = TclUtfToUniChar(string, &sch); + i = (int)sch; +#if TCL_UTF_MAX == 4 + if (!offset) { + offset = Tcl_UtfToUniChar(string, &sch); + i = (((i<<10) & 0x0FFC00) + 0x10000) + (sch & 0x3FF); + } +#endif + string += offset; if (!(flags & SCAN_SUPPRESS)) { - objPtr = Tcl_NewIntObj((int)sch); + objPtr = Tcl_NewIntObj(i); Tcl_IncrRefCount(objPtr); CLANG_ASSERT(objs); objs[objIndex++] = objPtr; diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 3a35bcf..1ccd778 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -466,7 +466,7 @@ Tcl_GetCharLength( *---------------------------------------------------------------------- */ -Tcl_UniChar +int Tcl_GetUniChar( Tcl_Obj *objPtr, /* The object to get the Unicode charater * from. */ @@ -483,7 +483,7 @@ Tcl_GetUniChar( if (TclIsPureByteArray(objPtr)) { unsigned char *bytes = Tcl_GetByteArrayFromObj(objPtr, NULL); - return (Tcl_UniChar) bytes[index]; + return (int) bytes[index]; } /* @@ -507,7 +507,7 @@ Tcl_GetUniChar( FillUnicodeRep(objPtr); stringPtr = GET_STRING(objPtr); } - return stringPtr->unicode[index]; + return (int) stringPtr->unicode[index]; } /* @@ -3462,7 +3462,6 @@ TclStringObjReverse( * Tcl_SetObjLength into growing the unicode rep buffer. */ - ch = 0; objPtr = Tcl_NewUnicodeObj(&ch, 1); Tcl_SetObjLength(objPtr, stringPtr->numChars); to = Tcl_GetUnicode(objPtr); @@ -3565,7 +3564,7 @@ ExtendUnicodeRepWithString( { String *stringPtr = GET_STRING(objPtr); int needed, numOrigChars = 0; - Tcl_UniChar *dst; + Tcl_UniChar *dst, unichar = 0; if (stringPtr->hasUnicode) { numOrigChars = stringPtr->numChars; @@ -3588,7 +3587,8 @@ ExtendUnicodeRepWithString( numAppendChars = 0; } for (dst=stringPtr->unicode + numOrigChars; numAppendChars-- > 0; dst++) { - bytes += TclUtfToUniChar(bytes, dst); + bytes += TclUtfToUniChar(bytes, &unichar); + *dst = unichar; } *dst = 0; } diff --git a/generic/tclUtf.c b/generic/tclUtf.c index 25cc2d1..859fe78 100644 --- a/generic/tclUtf.c +++ b/generic/tclUtf.c @@ -699,7 +699,7 @@ Tcl_UtfPrev( *--------------------------------------------------------------------------- */ -Tcl_UniChar +int Tcl_UniCharAtIndex( register const char *src, /* The UTF-8 string to dereference. */ register int index) /* The position of the desired character. */ @@ -819,7 +819,8 @@ int Tcl_UtfToUpper( char *str) /* String to convert in place. */ { - Tcl_UniChar ch = 0, upChar; + Tcl_UniChar ch = 0; + int upChar; char *src, *dst; int bytes; @@ -830,7 +831,14 @@ Tcl_UtfToUpper( src = dst = str; while (*src) { bytes = TclUtfToUniChar(src, &ch); - upChar = Tcl_UniCharToUpper(ch); + upChar = ch; + if (!bytes) { + /* TclUtfToUniChar only returns 0 for chars > 0xffff ! */ + bytes = TclUtfToUniChar(src, &ch); + /* Combine surrogates */ + upChar = (((upChar & 0x3ff) << 10) | (ch & 0x3ff)) + 0x10000; + } + upChar = Tcl_UniCharToUpper(upChar); /* * To keep badly formed Utf strings from getting inflated by the @@ -872,7 +880,8 @@ int Tcl_UtfToLower( char *str) /* String to convert in place. */ { - Tcl_UniChar ch = 0, lowChar; + Tcl_UniChar ch = 0; + int lowChar; char *src, *dst; int bytes; @@ -883,7 +892,14 @@ Tcl_UtfToLower( src = dst = str; while (*src) { bytes = TclUtfToUniChar(src, &ch); - lowChar = Tcl_UniCharToLower(ch); + lowChar = ch; + if (!bytes) { + /* TclUtfToUniChar only returns 0 for chars > 0xffff ! */ + bytes = TclUtfToUniChar(src, &ch); + /* Combine surrogates */ + lowChar = (((lowChar & 0x3ff) << 10) | (ch & 0x3ff)) + 0x10000; + } + lowChar = Tcl_UniCharToLower(lowChar); /* * To keep badly formed Utf strings from getting inflated by the @@ -926,7 +942,8 @@ int Tcl_UtfToTitle( char *str) /* String to convert in place. */ { - Tcl_UniChar ch = 0, titleChar, lowChar; + Tcl_UniChar ch = 0; + int titleChar, lowChar; char *src, *dst; int bytes; @@ -939,7 +956,14 @@ Tcl_UtfToTitle( if (*src) { bytes = TclUtfToUniChar(src, &ch); - titleChar = Tcl_UniCharToTitle(ch); + titleChar = ch; + if (!bytes) { + /* TclUtfToUniChar only returns 0 for chars > 0xffff ! */ + bytes = TclUtfToUniChar(src, &ch); + /* Combine surrogates */ + titleChar = (((titleChar & 0x3ff) << 10) | (ch & 0x3ff)) + 0x10000; + } + titleChar = Tcl_UniCharToTitle(titleChar); if (bytes < TclUtfCount(titleChar)) { memcpy(dst, src, (size_t) bytes); @@ -951,7 +975,14 @@ Tcl_UtfToTitle( } while (*src) { bytes = TclUtfToUniChar(src, &ch); - lowChar = Tcl_UniCharToLower(ch); + lowChar = ch; + if (!bytes) { + /* TclUtfToUniChar only returns 0 for chars > 0xffff ! */ + bytes = TclUtfToUniChar(src, &ch); + /* Combine surrogates */ + lowChar = (((lowChar & 0x3ff) << 10) | (ch & 0x3ff)) + 0x10000; + } + lowChar = Tcl_UniCharToLower(lowChar); if (bytes < TclUtfCount(lowChar)) { memcpy(dst, src, (size_t) bytes); @@ -1159,16 +1190,18 @@ TclUtfCasecmp( *---------------------------------------------------------------------- */ -Tcl_UniChar +int Tcl_UniCharToUpper( int ch) /* Unicode character to convert. */ { - int info = GetUniCharInfo(ch); + if (!UNICODE_OUT_OF_RANGE(ch)) { + int info = GetUniCharInfo(ch); - if (GetCaseType(info) & 0x04) { - ch -= GetDelta(info); + if (GetCaseType(info) & 0x04) { + ch -= GetDelta(info); + } } - return (Tcl_UniChar) ch; + return ch & 0x1FFFFF; } /* @@ -1187,16 +1220,18 @@ Tcl_UniCharToUpper( *---------------------------------------------------------------------- */ -Tcl_UniChar +int Tcl_UniCharToLower( int ch) /* Unicode character to convert. */ { - int info = GetUniCharInfo(ch); + if (!UNICODE_OUT_OF_RANGE(ch)) { + int info = GetUniCharInfo(ch); - if (GetCaseType(info) & 0x02) { - ch += GetDelta(info); + if (GetCaseType(info) & 0x02) { + ch += GetDelta(info); + } } - return (Tcl_UniChar) ch; + return ch & 0x1FFFFF; } /* @@ -1215,23 +1250,25 @@ Tcl_UniCharToLower( *---------------------------------------------------------------------- */ -Tcl_UniChar +int Tcl_UniCharToTitle( int ch) /* Unicode character to convert. */ { - int info = GetUniCharInfo(ch); - int mode = GetCaseType(info); + if (!UNICODE_OUT_OF_RANGE(ch)) { + int info = GetUniCharInfo(ch); + int mode = GetCaseType(info); - if (mode & 0x1) { - /* - * Subtract or add one depending on the original case. - */ + if (mode & 0x1) { + /* + * Subtract or add one depending on the original case. + */ - ch += ((mode & 0x4) ? -1 : 1); - } else if (mode == 0x4) { - ch -= GetDelta(info); + ch += ((mode & 0x4) ? -1 : 1); + } else if (mode == 0x4) { + ch -= GetDelta(info); + } } - return (Tcl_UniChar) ch; + return ch & 0x1FFFFF; } /* diff --git a/tests/string.test b/tests/string.test index cb901b9..cebaf4c 100644 --- a/tests/string.test +++ b/tests/string.test @@ -1697,40 +1697,40 @@ test string-24.4 {string reverse command - unshared string} { string reverse $x$y } edcba test string-24.5 {string reverse command - shared unicode string} { - set x abcde\udead + set x abcde\ud0ad string reverse $x -} \udeadedcba +} \ud0adedcba test string-24.6 {string reverse command - unshared string} { set x abc - set y de\udead + set y de\ud0ad string reverse $x$y -} \udeadedcba +} \ud0adedcba test string-24.7 {string reverse command - simple case} { string reverse a } a test string-24.8 {string reverse command - simple case} { - string reverse \udead -} \udead + string reverse \ud0ad +} \ud0ad test string-24.9 {string reverse command - simple case} { string reverse {} } {} test string-24.10 {string reverse command - corner case} { - set x \ubeef\udead + set x \ubeef\ud0ad string reverse $x -} \udead\ubeef +} \ud0ad\ubeef test string-24.11 {string reverse command - corner case} { set x \ubeef - set y \udead + set y \ud0ad string reverse $x$y -} \udead\ubeef +} \ud0ad\ubeef test string-24.12 {string reverse command - corner case} { set x \ubeef - set y \udead + set y \ud0ad string is ascii [string reverse $x$y] } 0 test string-24.13 {string reverse command - pure Unicode string} { - string reverse [string range \ubeef\udead\ubeef\udead\ubeef\udead 1 5] -} \udead\ubeef\udead\ubeef\udead + string reverse [string range \ubeef\ud0ad\ubeef\ud0ad\ubeef\ud0ad 1 5] +} \ud0ad\ubeef\ud0ad\ubeef\ud0ad test string-24.14 {string reverse command - pure bytearray} { binary scan [string reverse [binary format H* 010203]] H* x set x diff --git a/tests/utf.test b/tests/utf.test index 422ab08..45f9c0c 100644 --- a/tests/utf.test +++ b/tests/utf.test @@ -68,10 +68,10 @@ test utf-2.7 {Tcl_UtfToUniChar: lead (3-byte) followed by 2 trail} testbytestrin } {1} test utf-2.8 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} -constraints {fullutf testbytestring} -body { string length [testbytestring "\xF0\x90\x80\x80"] -} -result {1} +} -result {2} test utf-2.9 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} -constraints {fullutf testbytestring} -body { string length [testbytestring "\xF4\x8F\xBF\xBF"] -} -result {1} +} -result {2} test utf-2.10 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail, underflow} testbytestring { string length [testbytestring "\xF0\x8F\xBF\xBF"] } {4} -- cgit v0.12 From 2ea8f0fe98ed8a2f72d7d355b9c080fbb5bdd912 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 17 Nov 2017 16:08:49 +0000 Subject: merge core-8-branch. Fix some Tcl_UniChar initialization, in case TCL_UTF_MAX == 4 --- doc/ToUpper.3 | 6 +++--- doc/UniCharIsAlpha.3 | 7 ++----- doc/Utf.3 | 2 +- generic/tclScan.c | 2 +- generic/tclStringObj.c | 10 +++++----- generic/tclUtf.c | 34 ++++++++++++++++++++++++---------- generic/tclUtil.c | 14 +++++++------- win/tclWinSerial.c | 6 +++--- 8 files changed, 46 insertions(+), 35 deletions(-) diff --git a/doc/ToUpper.3 b/doc/ToUpper.3 index 14766da..b06b793 100644 --- a/doc/ToUpper.3 +++ b/doc/ToUpper.3 @@ -16,10 +16,10 @@ Tcl_UniCharToUpper, Tcl_UniCharToLower, Tcl_UniCharToTitle, Tcl_UtfToUpper, Tcl_ int \fBTcl_UniCharToUpper\fR(\fIch\fR) .sp -Tcl_UniChar +int \fBTcl_UniCharToLower\fR(\fIch\fR) .sp -Tcl_UniChar +int \fBTcl_UniCharToTitle\fR(\fIch\fR) .sp int @@ -33,7 +33,7 @@ int .SH ARGUMENTS .AS char *str in/out .AP int ch in -The Tcl_UniChar to be converted. +The character to be converted. .AP char *str in/out Pointer to UTF-8 string to be converted in place. .BE diff --git a/doc/UniCharIsAlpha.3 b/doc/UniCharIsAlpha.3 index 2336c34..e1d23ab 100644 --- a/doc/UniCharIsAlpha.3 +++ b/doc/UniCharIsAlpha.3 @@ -48,19 +48,16 @@ int .SH ARGUMENTS .AS int ch .AP int ch in -The Tcl_UniChar to be examined. +The character to be examined. .BE .SH DESCRIPTION .PP -All of the routines described examine Tcl_UniChars and return a +All of the routines described examine characters and return a boolean value. A non-zero return value means that the character does belong to the character class associated with the called routine. The rest of this document just describes the character classes associated with the various routines. -.PP -Note: A Tcl_UniChar is a Unicode character represented as an unsigned, -fixed-size quantity. .SH "CHARACTER CLASSES" .PP diff --git a/doc/Utf.3 b/doc/Utf.3 index 5cd6b7df..638f349 100644 --- a/doc/Utf.3 +++ b/doc/Utf.3 @@ -77,7 +77,7 @@ int Buffer in which the UTF-8 representation of the Tcl_UniChar is stored. At most \fBTCL_UTF_MAX\fR bytes are stored in the buffer. .AP int ch in -The Tcl_UniChar to be converted or examined. +The character to be converted or examined. .AP Tcl_UniChar *chPtr out Filled with the Tcl_UniChar represented by the head of the UTF-8 string. .AP "const char" *src in diff --git a/generic/tclScan.c b/generic/tclScan.c index 7f71262..e0798df 100644 --- a/generic/tclScan.c +++ b/generic/tclScan.c @@ -889,7 +889,7 @@ Tcl_ScanObjCmd( i = (int)sch; #if TCL_UTF_MAX == 4 if (!offset) { - offset = Tcl_UtfToUniChar(string, &sch); + offset = TclUtfToUniChar(string, &sch); i = (((i<<10) & 0x0FFC00) + 0x10000) + (sch & 0x3FF); } #endif diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 1ccd778..fda6ac1 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -1869,20 +1869,20 @@ Tcl_AppendFormatToObj( } else if (ch == 'I') { if ((format[1] == '6') && (format[2] == '4')) { format += (step + 2); - step = Tcl_UtfToUniChar(format, &ch); + step = TclUtfToUniChar(format, &ch); #ifndef TCL_WIDE_INT_IS_LONG useWide = 1; #endif } else if ((format[1] == '3') && (format[2] == '2')) { format += (step + 2); - step = Tcl_UtfToUniChar(format, &ch); + step = TclUtfToUniChar(format, &ch); } else { format += step; - step = Tcl_UtfToUniChar(format, &ch); + step = TclUtfToUniChar(format, &ch); } } else if ((ch == 't') || (ch == 'z')) { format += step; - step = Tcl_UtfToUniChar(format, &ch); + step = TclUtfToUniChar(format, &ch); #ifndef TCL_WIDE_INT_IS_LONG if (sizeof(size_t) > sizeof(int)) { useWide = 1; @@ -1890,7 +1890,7 @@ Tcl_AppendFormatToObj( #endif } else if ((ch == 'q') ||(ch == 'j')) { format += step; - step = Tcl_UtfToUniChar(format, &ch); + step = TclUtfToUniChar(format, &ch); #ifndef TCL_WIDE_INT_IS_LONG useWide = 1; #endif diff --git a/generic/tclUtf.c b/generic/tclUtf.c index 859fe78..e651757 100644 --- a/generic/tclUtf.c +++ b/generic/tclUtf.c @@ -398,7 +398,7 @@ Tcl_UtfToUniCharDString( * appended to this previously initialized * DString. */ { - Tcl_UniChar ch, *w, *wString; + Tcl_UniChar ch = 0, *w, *wString; const char *p, *end; int oldLength; @@ -522,12 +522,12 @@ Tcl_NumUtfChars( * * Tcl_UtfFindFirst -- * - * Returns a pointer to the first occurance of the given Tcl_UniChar in + * Returns a pointer to the first occurance of the given character in * the NULL-terminated UTF-8 string. The NULL terminator is considered * part of the UTF-8 string. Equivalent to Plan 9 utfrune(). * * Results: - * As above. If the Tcl_UniChar does not exist in the given string, the + * As above. If the character does not exist in the given string, the * return value is NULL. * * Side effects: @@ -539,14 +539,21 @@ Tcl_NumUtfChars( const char * Tcl_UtfFindFirst( const char *src, /* The UTF-8 string to be searched. */ - int ch) /* The Tcl_UniChar to search for. */ + int ch) /* The character to search for. */ { - int len; + int len, fullchar; Tcl_UniChar find = 0; while (1) { len = TclUtfToUniChar(src, &find); - if (find == ch) { + fullchar = find; +#if TCL_UTF_MAX == 4 + if (!len) { + len += TclUtfToUniChar(stringPtr, &find); + fullchar = (((fullchar & 0x3ff) << 10) | (ch & 0x3ff)) + 0x10000; + } +#endif + if (find == fullchar) { return src; } if (*src == '\0') { @@ -578,16 +585,23 @@ Tcl_UtfFindFirst( const char * Tcl_UtfFindLast( const char *src, /* The UTF-8 string to be searched. */ - int ch) /* The Tcl_UniChar to search for. */ + int ch) /* The character to search for. */ { - int len; + int len, fullchar; Tcl_UniChar find = 0; const char *last; last = NULL; while (1) { len = TclUtfToUniChar(src, &find); - if (find == ch) { + fullchar = find; +#if TCL_UTF_MAX == 4 + if (!len) { + len += TclUtfToUniChar(stringPtr, &find); + fullchar = (((fullchar & 0x3ff) << 10) | (ch & 0x3ff)) + 0x10000; + } +#endif + if (find == fullchar) { last = src; } if (*src == '\0') { @@ -1158,7 +1172,7 @@ TclUtfCasecmp( const char *ct) /* UTF string cs is compared to. */ { while (*cs && *ct) { - Tcl_UniChar ch1, ch2; + Tcl_UniChar ch1 = 0, ch2 = 0; cs += TclUtfToUniChar(cs, &ch1); ct += TclUtfToUniChar(ct, &ch2); diff --git a/generic/tclUtil.c b/generic/tclUtil.c index 8ebace5..21d1071 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -1695,7 +1695,7 @@ TclTrimRight( */ do { - Tcl_UniChar ch2; + Tcl_UniChar ch2 = 0; int qInc = TclUtfToUniChar(q, &ch2); if (ch1 == ch2) { @@ -1763,7 +1763,7 @@ TclTrimLeft( */ do { - Tcl_UniChar ch1; + Tcl_UniChar ch1 = 0; int pInc = TclUtfToUniChar(p, &ch1); const char *q = trim; int bytesLeft = numTrim; @@ -1773,7 +1773,7 @@ TclTrimLeft( */ do { - Tcl_UniChar ch2; + Tcl_UniChar ch2 = 0; int qInc = TclUtfToUniChar(q, &ch2); if (ch1 == ch2) { @@ -2107,7 +2107,7 @@ Tcl_StringCaseMatch( { int p, charLen; const char *pstart = pattern; - Tcl_UniChar ch1, ch2; + Tcl_UniChar ch1 = 0, ch2 = 0; while (1) { p = *pattern; @@ -2217,7 +2217,7 @@ Tcl_StringCaseMatch( */ if (p == '[') { - Tcl_UniChar startChar, endChar; + Tcl_UniChar startChar = 0, endChar = 0; pattern++; if (UCHAR(*str) < 0x80) { @@ -2225,7 +2225,7 @@ Tcl_StringCaseMatch( (nocase ? tolower(UCHAR(*str)) : UCHAR(*str)); str++; } else { - str += Tcl_UtfToUniChar(str, &ch1); + str += TclUtfToUniChar(str, &ch1); if (nocase) { ch1 = Tcl_UniCharToLower(ch1); } @@ -2254,7 +2254,7 @@ Tcl_StringCaseMatch( ? tolower(UCHAR(*pattern)) : UCHAR(*pattern)); pattern++; } else { - pattern += Tcl_UtfToUniChar(pattern, &endChar); + pattern += TclUtfToUniChar(pattern, &endChar); if (nocase) { endChar = Tcl_UniCharToLower(endChar); } diff --git a/win/tclWinSerial.c b/win/tclWinSerial.c index ed1a8e5..894f431 100644 --- a/win/tclWinSerial.c +++ b/win/tclWinSerial.c @@ -1738,15 +1738,15 @@ SerialSetOptionProc( dcb.XonChar = argv[0][0]; dcb.XoffChar = argv[1][0]; if (argv[0][0] & 0x80 || argv[1][0] & 0x80) { - Tcl_UniChar character; + Tcl_UniChar character = 0; int charLen; - charLen = Tcl_UtfToUniChar(argv[0], &character); + charLen = TclUtfToUniChar(argv[0], &character); if (argv[0][charLen]) { goto badXchar; } dcb.XonChar = (char) character; - charLen = Tcl_UtfToUniChar(argv[1], &character); + charLen = TclUtfToUniChar(argv[1], &character); if (argv[1][charLen]) { goto badXchar; } -- cgit v0.12 From 61536390c542d9aa9d1a91d173190cd2421294e5 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 20 Nov 2017 13:05:36 +0000 Subject: Fix executable flags --- generic/tclDecls.h | 0 generic/tclIntDecls.h | 0 generic/tclStubInit.c | 0 3 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 generic/tclDecls.h mode change 100755 => 100644 generic/tclIntDecls.h mode change 100755 => 100644 generic/tclStubInit.c diff --git a/generic/tclDecls.h b/generic/tclDecls.h old mode 100755 new mode 100644 diff --git a/generic/tclIntDecls.h b/generic/tclIntDecls.h old mode 100755 new mode 100644 diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c old mode 100755 new mode 100644 -- cgit v0.12 From 3af16acbcb63ea2935d71b905371252560dc4659 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 29 Nov 2017 08:59:49 +0000 Subject: Treat invalid UTF-8 characters in the range 0x80-0x9F as cp1252: See [https://en.wikipedia.org/wiki/UTF-8]. To be added to TIP #389 --- doc/Utf.3 | 3 +++ generic/tclInt.h | 2 +- generic/tclUtf.c | 17 +++++++++++++++-- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/doc/Utf.3 b/doc/Utf.3 index 638f349..de9545d 100644 --- a/doc/Utf.3 +++ b/doc/Utf.3 @@ -140,6 +140,9 @@ number of bytes read from \fIsrc\fR. The caller must ensure that the source buffer is long enough such that this routine does not run off the end and dereference non-existent or random memory; if the source buffer is known to be null-terminated, this will not happen. If the input is +a byte in the range 0x80 - 0x9F, \fBTcl_UtfToUniChar\fR assumes the +cp1252 encoding, stores the corresponding Tcl_UniChar in \fI*chPtr\fR +and returns 1. If the input is otherwise not in proper UTF-8 format, \fBTcl_UtfToUniChar\fR will store the first byte of \fIsrc\fR in \fI*chPtr\fR as a Tcl_UniChar between 0x0000 and 0x00ff and return 1. diff --git a/generic/tclInt.h b/generic/tclInt.h index ef88bf5..d77889e 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -4446,7 +4446,7 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file, */ #define TclUtfToUniChar(str, chPtr) \ - ((((unsigned char) *(str)) < 0xC0) ? \ + ((((unsigned char) *(str)) < 0x80) ? \ ((*(chPtr) = (unsigned char) *(str)), 1) \ : Tcl_UtfToUniChar(str, chPtr)) diff --git a/generic/tclUtf.c b/generic/tclUtf.c index 4ed201f..aed332f 100644 --- a/generic/tclUtf.c +++ b/generic/tclUtf.c @@ -272,6 +272,13 @@ Tcl_UniCharToUtfDString( *--------------------------------------------------------------------------- */ +static const unsigned short cp1252[32] = { + 0x20ac, 0x81, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x8D, 0x017D, 0x8F, + 0x90, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x2DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x9D, 0x017E, 0x0178 +}; + int Tcl_UtfToUniChar( register const char *src, /* The UTF-8 string. */ @@ -288,11 +295,17 @@ Tcl_UtfToUniChar( if (byte < 0xC0) { /* * Handles properly formed UTF-8 characters between 0x01 and 0x7F. - * Also treats \0 and naked trail bytes 0x80 to 0xBF as valid + * Treats naked trail bytes 0x80 to 0x9F as valid characters from + * the cp1252 table. See: + * Also treats \0 and other naked trail bytes 0xA0 to 0xBF as valid * characters representing themselves. */ - *chPtr = (Tcl_UniChar) byte; + if ((unsigned)(byte-0x80) < (unsigned) 0x20) { + *chPtr = (Tcl_UniChar) cp1252[byte-0x80]; + } else { + *chPtr = (Tcl_UniChar) byte; + } return 1; } else if (byte < 0xE0) { if ((src[1] & 0xC0) == 0x80) { -- cgit v0.12 From 03c66864aa2ffa9871ce216b00cd661eaf1be688 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 29 Nov 2017 09:49:31 +0000 Subject: Fix [8e1e31eac0fd6b6c4452bc108a98ab08c6b64588|8e1e31eac0]: lsort treats NUL chars strangely --- generic/tclCmdIL.c | 4 +-- generic/tclCmdMZ.c | 2 +- generic/tclInt.h | 1 + generic/tclUtf.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 80 insertions(+), 6 deletions(-) diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c index 47076ec..b41d312 100644 --- a/generic/tclCmdIL.c +++ b/generic/tclCmdIL.c @@ -2945,7 +2945,7 @@ Tcl_LsearchObjCmd( double patDouble, objDouble; SortInfo sortInfo; Tcl_Obj *patObj, **listv, *listPtr, *startPtr, *itemPtr; - SortStrCmpFn_t strCmpFn = strcmp; + SortStrCmpFn_t strCmpFn = TclUtfCmp; Tcl_RegExp regexp = NULL; static const char *const options[] = { "-all", "-ascii", "-bisect", "-decreasing", "-dictionary", @@ -4263,7 +4263,7 @@ SortCompare( int order = 0; if (infoPtr->sortMode == SORTMODE_ASCII) { - order = strcmp(elemPtr1->collationKey.strValuePtr, + order = TclUtfCmp(elemPtr1->collationKey.strValuePtr, elemPtr2->collationKey.strValuePtr); } else if (infoPtr->sortMode == SORTMODE_ASCII_NC) { order = TclUtfCasecmp(elemPtr1->collationKey.strValuePtr, diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index ad1dd5f..a206cc5 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -3547,7 +3547,7 @@ TclNRSwitchObjCmd( OPT_LAST }; typedef int (*strCmpFn_t)(const char *, const char *); - strCmpFn_t strCmpFn = strcmp; + strCmpFn_t strCmpFn = TclUtfCmp; mode = OPT_EXACT; foundmode = 0; diff --git a/generic/tclInt.h b/generic/tclInt.h index d77889e..ad1d9c6 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -3219,6 +3219,7 @@ MODULE_SCOPE int TclTrimLeft(const char *bytes, int numBytes, const char *trim, int numTrim); MODULE_SCOPE int TclTrimRight(const char *bytes, int numBytes, const char *trim, int numTrim); +MODULE_SCOPE int TclUtfCmp(const char *cs, const char *ct); MODULE_SCOPE int TclUtfCasecmp(const char *cs, const char *ct); MODULE_SCOPE int TclUtfCount(int ch); MODULE_SCOPE Tcl_Obj * TclpNativeToNormalized(ClientData clientData); diff --git a/generic/tclUtf.c b/generic/tclUtf.c index aed332f..aff10c1 100644 --- a/generic/tclUtf.c +++ b/generic/tclUtf.c @@ -1108,6 +1108,15 @@ Tcl_UtfNcmp( cs += TclUtfToUniChar(cs, &ch1); ct += TclUtfToUniChar(ct, &ch2); +#if TCL_UTF_MAX == 4 + /* map high surrogate characters to values > 0xffff */ + if ((ch1 & 0xFC00) == 0xD800) { + ch1 += 0x4000; + } + if ((ch2 & 0xFC00) == 0xD800) { + ch2 += 0x4000; + } +#endif if (ch1 != ch2) { return (ch1 - ch2); } @@ -1140,6 +1149,7 @@ Tcl_UtfNcasecmp( unsigned long numChars) /* Number of UTF chars to compare. */ { Tcl_UniChar ch1 = 0, ch2 = 0; + while (numChars-- > 0) { /* * n must be interpreted as chars, not bytes. @@ -1148,6 +1158,15 @@ Tcl_UtfNcasecmp( */ cs += TclUtfToUniChar(cs, &ch1); ct += TclUtfToUniChar(ct, &ch2); +#if TCL_UTF_MAX == 4 + /* map high surrogate characters to values > 0xffff */ + if ((ch1 & 0xFC00) == 0xD800) { + ch1 += 0x4000; + } + if ((ch2 & 0xFC00) == 0xD800) { + ch2 += 0x4000; + } +#endif if (ch1 != ch2) { ch1 = Tcl_UniCharToLower(ch1); ch2 = Tcl_UniCharToLower(ch2); @@ -1158,11 +1177,56 @@ Tcl_UtfNcasecmp( } return 0; } + +/* + *---------------------------------------------------------------------- + * + * Tcl_UtfCmp -- + * + * Compare UTF chars of string cs to string ct case sensitively. + * Replacement for strcmp in Tcl core, in places where UTF-8 should + * be handled. + * + * Results: + * Return <0 if cs < ct, 0 if cs == ct, or >0 if cs > ct. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TclUtfCmp( + const char *cs, /* UTF string to compare to ct. */ + const char *ct) /* UTF string cs is compared to. */ +{ + Tcl_UniChar ch1 = 0, ch2 = 0; + + while (*cs && *ct) { + cs += TclUtfToUniChar(cs, &ch1); + ct += TclUtfToUniChar(ct, &ch2); +#if TCL_UTF_MAX == 4 + /* map high surrogate characters to values > 0xffff */ + if ((ch1 & 0xFC00) == 0xD800) { + ch1 += 0x4000; + } + if ((ch2 & 0xFC00) == 0xD800) { + ch2 += 0x4000; + } +#endif + if (ch1 != ch2) { + return ch1 - ch2; + } + } + return UCHAR(*cs) - UCHAR(*ct); +} + /* *---------------------------------------------------------------------- * - * Tcl_UtfNcasecmp -- + * TclUtfCasecmp -- * * Compare UTF chars of string cs to string ct case insensitively. * Replacement for strcasecmp in Tcl core, in places where UTF-8 should @@ -1182,11 +1246,20 @@ TclUtfCasecmp( const char *cs, /* UTF string to compare to ct. */ const char *ct) /* UTF string cs is compared to. */ { - while (*cs && *ct) { - Tcl_UniChar ch1 = 0, ch2 = 0; + Tcl_UniChar ch1 = 0, ch2 = 0; + while (*cs && *ct) { cs += TclUtfToUniChar(cs, &ch1); ct += TclUtfToUniChar(ct, &ch2); +#if TCL_UTF_MAX == 4 + /* map high surrogate characters to values > 0xffff */ + if ((ch1 & 0xFC00) == 0xD800) { + ch1 += 0x4000; + } + if ((ch2 & 0xFC00) == 0xD800) { + ch2 += 0x4000; + } +#endif if (ch1 != ch2) { ch1 = Tcl_UniCharToLower(ch1); ch2 = Tcl_UniCharToLower(ch2); -- cgit v0.12 From bf868c1c56292a44ff5faeef5b348408554cab1a Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 11 Dec 2017 14:19:48 +0000 Subject: Initial implementation of TIP #491. Not tested yet. --- generic/tcl.h | 4 ++++ generic/tclInt.h | 4 ++++ unix/configure.ac | 6 ------ win/configure.ac | 6 ------ win/rules.vc | 43 ++++--------------------------------------- win/tcl.rc | 8 +------- win/tclsh.rc | 8 +------- 7 files changed, 14 insertions(+), 65 deletions(-) diff --git a/generic/tcl.h b/generic/tcl.h index a6a8c94..b7d4e90 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -91,6 +91,10 @@ extern "C" { #endif #endif /* !TCL_NO_DEPRECATED */ +#ifndef TCL_THREADS +# define TCL_THREADS 1 +#endif + /* * A special definition used to allow this header file to be included from * windows resource files so that they can obtain version information. diff --git a/generic/tclInt.h b/generic/tclInt.h index ad1d9c6..1fd252f 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -4149,6 +4149,10 @@ typedef const char *TclDTraceStr; } \ } +#if TCL_THREADS && !defined(USE_THREAD_ALLOC) +# define USE_THREAD_ALLOC 1 +#endif + #if defined(PURIFY) /* diff --git a/unix/configure.ac b/unix/configure.ac index e14d85e..5b982e8 100644 --- a/unix/configure.ac +++ b/unix/configure.ac @@ -120,12 +120,6 @@ if test -z "$no_pipe" && test -n "$GCC"; then fi #------------------------------------------------------------------------ -# Threads support -#------------------------------------------------------------------------ - -SC_ENABLE_THREADS - -#------------------------------------------------------------------------ # Embedded configuration information, encoding to use for the values, TIP #59 #------------------------------------------------------------------------ diff --git a/win/configure.ac b/win/configure.ac index d03695c..179f151 100644 --- a/win/configure.ac +++ b/win/configure.ac @@ -78,12 +78,6 @@ AC_PROG_MAKE_SET AC_OBJEXT AC_EXEEXT -#-------------------------------------------------------------------- -# Check whether --enable-threads or --disable-threads was given. -#-------------------------------------------------------------------- - -SC_ENABLE_THREADS - #------------------------------------------------------------------------ # Embedded configuration information, encoding to use for the values, TIP #59 #------------------------------------------------------------------------ diff --git a/win/rules.vc b/win/rules.vc index 9b917b6..890618c 100644 --- a/win/rules.vc +++ b/win/rules.vc @@ -626,7 +626,6 @@ LINKERFLAGS = $(LINKERFLAGS) -ltcg # The following macros are defined by this section based on OPTS # STATIC_BUILD - 0 -> Tcl is to be built as a shared library # 1 -> build as a static library and shell -# TCL_THREADS - legacy but always 1 on Windows since winsock requires it. # DEBUG - 1 -> debug build, 0 -> release builds # SYMBOLS - 1 -> generate PDB's, 0 -> no PDB's # PROFILE - 1 -> generate profiling info, 0 -> no profiling @@ -648,7 +647,6 @@ LINKERFLAGS = $(LINKERFLAGS) -ltcg # Default values for all the above STATIC_BUILD = 0 -TCL_THREADS = 1 DEBUG = 0 SYMBOLS = 0 PROFILE = 0 @@ -703,15 +701,6 @@ TCL_USE_STATIC_PACKAGES = 1 TCL_USE_STATIC_PACKAGES = 0 !endif -!if [nmakehlp -f $(OPTS) "nothreads"] -!message *** Compile explicitly for non-threaded tcl -TCL_THREADS = 0 -USE_THREAD_ALLOC= 0 -!else -TCL_THREADS = 1 -USE_THREAD_ALLOC= 1 -!endif - !if [nmakehlp -f $(OPTS) "symbols"] !message *** Doing symbols DEBUG = 1 @@ -747,12 +736,6 @@ PGO = 0 !message *** Warning: ignoring option "loimpact" - deprecated on modern Windows. !endif -# TBD - should get rid of this option -!if [nmakehlp -f $(OPTS) "thrdalloc"] -!message *** Doing thrdalloc -USE_THREAD_ALLOC = 1 -!endif - !if [nmakehlp -f $(OPTS) "tclalloc"] USE_THREAD_ALLOC = 0 !endif @@ -943,7 +926,6 @@ VERSION = $(DOTVERSION:.=) # different compilers, build configurations etc., # # Naming convention (suffixes): -# t = full thread support. # s = static library (as opposed to an import library) # g = linked to the debug enabled C run-time. # x = special static build when it links to the dynamic C run-time. @@ -965,7 +947,7 @@ VERSION = $(DOTVERSION:.=) # PRJSTUBLIB - output path of the generated project stubs library # RESFILE - output resource file (only if not static build) -SUFX = tsgx +SUFX = sgx !if $(DEBUG) BUILDDIRTOP = Debug @@ -984,7 +966,7 @@ BUILDDIRTOP =$(BUILDDIRTOP)_VC$(VCVER) SUFX = $(SUFX:g=) !endif -TMP_DIRFULL = .\$(BUILDDIRTOP)\$(PROJECT)_ThreadedDynamicStaticX +TMP_DIRFULL = .\$(BUILDDIRTOP)\$(PROJECT)_DynamicStaticX !if !$(STATIC_BUILD) TMP_DIRFULL = $(TMP_DIRFULL:Static=) @@ -1001,11 +983,6 @@ SUFX = $(SUFX:x=) !endif !endif -!if !$(TCL_THREADS) -TMP_DIRFULL = $(TMP_DIRFULL:Threaded=) -SUFX = $(SUFX:t=) -!endif - !ifndef TMP_DIR TMP_DIR = $(TMP_DIRFULL) !ifndef OUT_DIR @@ -1049,9 +1026,6 @@ TCL_INCLUDES = -I"$(WINDIR)" -I"$(GENERICDIR)" !if $(TCLINSTALL) # Building against an installed Tcl TCLSH = $(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX).exe -!if !exist("$(TCLSH)") && $(TCL_THREADS) -TCLSH = $(_TCLDIR)\bin\tclsh$(TCL_VERSION)t$(SUFX).exe -!endif TCLSTUBLIB = $(_TCLDIR)\lib\tclstub$(TCL_VERSION).lib TCLIMPLIB = $(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX).lib TCL_LIBRARY = $(_TCLDIR)\lib @@ -1063,9 +1037,6 @@ TCL_INCLUDES = -I"$(_TCLDIR)\include" !else # Building against Tcl sources TCLSH = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX).exe -!if !exist($(TCLSH)) && $(TCL_THREADS) -TCLSH = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)t$(SUFX).exe -!endif TCLSTUBLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclstub$(TCL_VERSION).lib TCLIMPLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX).lib TCL_LIBRARY = $(_TCLDIR)\library @@ -1205,11 +1176,8 @@ OPTDEFINES = $(OPTDEFINES) -DTCL_MEM_DEBUG !if $(TCL_COMPILE_DEBUG) OPTDEFINES = $(OPTDEFINES) -DTCL_COMPILE_DEBUG -DTCL_COMPILE_STATS !endif -!if $(TCL_THREADS) -OPTDEFINES = $(OPTDEFINES) -DTCL_THREADS=1 -!if $(USE_THREAD_ALLOC) -OPTDEFINES = $(OPTDEFINES) -DUSE_THREAD_ALLOC=1 -!endif +!if $(USE_THREAD_ALLOC)==0 +OPTDEFINES = $(OPTDEFINES) -DUSE_THREAD_ALLOC=0 !endif !if $(STATIC_BUILD) OPTDEFINES = $(OPTDEFINES) -DSTATIC_BUILD @@ -1662,9 +1630,6 @@ TCLNMAKECONFIG = "$(OUT_DIR)\tcl.nmake" !if defined(CORE_MACHINE) && "$(CORE_MACHINE)" != "$(MACHINE)" !error ERROR: Build target ($(MACHINE)) does not match the Tcl library architecture ($(CORE_MACHINE)). !endif -!if defined(CORE_USE_THREAD_ALLOC) && $(CORE_USE_THREAD_ALLOC) != $(USE_THREAD_ALLOC) -!message WARNING: Value of USE_THREAD_ALLOC ($(USE_THREAD_ALLOC)) does not match its Tcl core value ($(CORE_USE_THREAD_ALLOC)). -!endif !if defined(CORE_DEBUG) && $(CORE_DEBUG) != $(DEBUG) !message WARNING: Value of DEBUG ($(DEBUG)) does not match its Tcl library configuration ($(DEBUG)). !endif diff --git a/win/tcl.rc b/win/tcl.rc index be5e0a7..477512d 100644 --- a/win/tcl.rc +++ b/win/tcl.rc @@ -7,19 +7,13 @@ // // build-up the name suffix that defines the type of build this is. // -#if TCL_THREADS -#define SUFFIX_THREADS "t" -#else -#define SUFFIX_THREADS "" -#endif - #if DEBUG && !UNCHECKED #define SUFFIX_DEBUG "g" #else #define SUFFIX_DEBUG "" #endif -#define SUFFIX SUFFIX_THREADS SUFFIX_DEBUG +#define SUFFIX SUFFIX_DEBUG LANGUAGE 0x9, 0x1 /* LANG_ENGLISH, SUBLANG_DEFAULT */ diff --git a/win/tclsh.rc b/win/tclsh.rc index 161da50..bd1a4da 100644 --- a/win/tclsh.rc +++ b/win/tclsh.rc @@ -8,12 +8,6 @@ // // build-up the name suffix that defines the type of build this is. // -#if TCL_THREADS -#define SUFFIX_THREADS "t" -#else -#define SUFFIX_THREADS "" -#endif - #if STATIC_BUILD #define SUFFIX_STATIC "s" #else @@ -26,7 +20,7 @@ #define SUFFIX_DEBUG "" #endif -#define SUFFIX SUFFIX_THREADS SUFFIX_STATIC SUFFIX_DEBUG +#define SUFFIX SUFFIX_STATIC SUFFIX_DEBUG LANGUAGE 0x9, 0x1 /* LANG_ENGLISH, SUBLANG_DEFAULT */ -- cgit v0.12 From 5c4f8d88b5491e7656dedeab904b42b437b83e01 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 14 Dec 2017 14:38:30 +0000 Subject: fix comment --- win/rules.vc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/win/rules.vc b/win/rules.vc index f22a2dc..2ee8f0e 100644 --- a/win/rules.vc +++ b/win/rules.vc @@ -957,7 +957,7 @@ VERSION = $(DOTVERSION:.=) # different compilers, build configurations etc., # # Naming convention (suffixes): -# t = full thread support. (Not used for Tcl >= 8.6) +# t = full thread support. (Not used for Tcl >= 8.7) # s = static library (as opposed to an import library) # g = linked to the debug enabled C run-time. # x = special static build when it links to the dynamic C run-time. @@ -1048,7 +1048,7 @@ STUBPREFIX = $(PROJECT)stub # Set up paths to various Tcl executables and libraries needed by extensions !if $(DOING_TCL) -TCLSHNAME = $(PROJECT)sh$(TCL_VERSION)$(SUFX).exe +TCLSHNAME = $(PROJECT)sh$(VERSION)$(SUFX).exe TCLSH = $(OUT_DIR)\$(TCLSHNAME) TCLIMPLIB = $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib TCLLIBNAME = $(PROJECT)$(VERSION)$(SUFX).$(EXT) -- cgit v0.12 From 3f03f8189e6b4da3ff496bfbb4faa921124b76f9 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 15 Dec 2017 13:04:15 +0000 Subject: Oops, couldn't build tclWinPanic.o. Fixed now. --- win/makefile.vc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win/makefile.vc b/win/makefile.vc index 1d61f28..d270447 100644 --- a/win/makefile.vc +++ b/win/makefile.vc @@ -741,7 +741,7 @@ $(TMP_DIR)\tclTomMathStubLib.obj: $(GENERICDIR)\tclTomMathStubLib.c $(TMP_DIR)\tclOOStubLib.obj: $(GENERICDIR)\tclOOStubLib.c $(cc32) $(stubscflags) -Fo$@ $? -$(TMP_DIR)\tclWinPanic.obj: $(GENERICDIR)\tclWinPanic.c +$(TMP_DIR)\tclWinPanic.obj: $(WINDIR)\tclWinPanic.c $(cc32) $(stubscflags) -Fo$@ $? $(TMP_DIR)\tclsh.exe.manifest: $(WINDIR)\tclsh.exe.manifest.in -- cgit v0.12 From 04d3db559246ee9e2ac2a5e20e52cf57b7af808b Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 10 Jan 2018 09:32:51 +0000 Subject: Don't use TclUtfToUniChar here: it doesn't give any advantage over Tcl_UtfToUniChar --- generic/tclUtil.c | 4 ++-- win/tclWinSerial.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/generic/tclUtil.c b/generic/tclUtil.c index 41795e8..15018de 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -2223,7 +2223,7 @@ Tcl_StringCaseMatch( (nocase ? tolower(UCHAR(*str)) : UCHAR(*str)); str++; } else { - str += TclUtfToUniChar(str, &ch1); + str += Tcl_UtfToUniChar(str, &ch1); if (nocase) { ch1 = Tcl_UniCharToLower(ch1); } @@ -2252,7 +2252,7 @@ Tcl_StringCaseMatch( ? tolower(UCHAR(*pattern)) : UCHAR(*pattern)); pattern++; } else { - pattern += TclUtfToUniChar(pattern, &endChar); + pattern += Tcl_UtfToUniChar(pattern, &endChar); if (nocase) { endChar = Tcl_UniCharToLower(endChar); } diff --git a/win/tclWinSerial.c b/win/tclWinSerial.c index 894f431..acfeecb 100644 --- a/win/tclWinSerial.c +++ b/win/tclWinSerial.c @@ -1741,12 +1741,12 @@ SerialSetOptionProc( Tcl_UniChar character = 0; int charLen; - charLen = TclUtfToUniChar(argv[0], &character); + charLen = Tcl_UtfToUniChar(argv[0], &character); if (argv[0][charLen]) { goto badXchar; } dcb.XonChar = (char) character; - charLen = TclUtfToUniChar(argv[1], &character); + charLen = Tcl_UtfToUniChar(argv[1], &character); if (argv[1][charLen]) { goto badXchar; } -- cgit v0.12 From eb3422673ff62a7427f2e6d166840fce68237d74 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 11 Jan 2018 14:11:38 +0000 Subject: Add test-cases for bug [11ae2be95dac9417], and make a start fixing it. Almost works. --- generic/tclCmdMZ.c | 12 ++++++++++-- generic/tclStringObj.c | 33 +++++++++++++++++++++++++++++++-- tests/string.test | 7 +++++++ 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index a206cc5..a23f007 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -1435,7 +1435,7 @@ StringIndexCmd( } /* - * Get the char length to calulate what 'end' means. + * Get the char length to calculate what 'end' means. */ length = Tcl_GetCharLength(objv[1]); @@ -1444,7 +1444,15 @@ StringIndexCmd( } if ((index >= 0) && (index < length)) { - Tcl_UniChar ch = Tcl_GetUniChar(objv[1], index); + int ch = Tcl_GetUniChar(objv[1], index); + + if (ch >= 0x10000) { + printf("HI: %x\n", ch); + } + if (ch == -1) { + printf("LO: %x\n", ch); + return TCL_OK; + } /* * If we have a ByteArray object, we're careful to generate a new diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 01f8d80..aa5aba3 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -460,7 +460,8 @@ Tcl_GetCharLength( * Tcl_GetUniChar -- * * Get the index'th Unicode character from the String object. The index - * is assumed to be in the appropriate range. + * is assumed to be in the appropriate range. If index references a lower + * surrogate preceded by a higher surrogate, the result = -1; * * Results: * Returns the index'th Unicode character in the Object. @@ -478,6 +479,7 @@ Tcl_GetUniChar( int index) /* Get the index'th Unicode character. */ { String *stringPtr; + int ch; /* * Optimize the case where we're really dealing with a bytearray object @@ -512,7 +514,23 @@ Tcl_GetUniChar( FillUnicodeRep(objPtr); stringPtr = GET_STRING(objPtr); } - return (int) stringPtr->unicode[index]; + + ch = stringPtr->unicode[index]; +#if TCL_UTF_MAX == 4 + /* See: bug [11ae2be95dac9417] */ + if ((ch&0xF800) == 0xD800) { + if (ch&0x400) { + if ((index > 0) && ((stringPtr->unicode[index-1]&0xFC00) == 0xD800)) { + ch = -1; /* low surrogate preceded by high surrogate */ + } + } else if ((++index < stringPtr->numChars) + && ((stringPtr->unicode[index]&0xFC00) == 0xDC00)) { + /* high surrogate followed by low surrogate */ + ch = (((ch & 0x3FF) << 10) | (stringPtr->unicode[index] & 0x3FF)) + 0x10000; + } + } +#endif + return ch; } /* @@ -656,6 +674,17 @@ Tcl_GetRange( stringPtr = GET_STRING(objPtr); } +#if TCL_UTF_MAX == 4 + /* See: bug [11ae2be95dac9417] */ + if ((first>0) && ((stringPtr->unicode[first]&0xFC00) == 0xDC00) + && ((stringPtr->unicode[first-1]&0xFC00) == 0xD800)) { + ++first; + } + if ((last+1numChars) && ((stringPtr->unicode[last+1]&0xFC00) == 0xDC00) + && ((stringPtr->unicode[last]&0xFC00) == 0xD800)) { + ++last; + } +#endif return Tcl_NewUnicodeObj(stringPtr->unicode + first, last-first+1); } diff --git a/tests/string.test b/tests/string.test index cebaf4c..58328bb 100644 --- a/tests/string.test +++ b/tests/string.test @@ -24,6 +24,7 @@ catch [list package require -exact Tcltest [info patchlevel]] testConstraint testobj [expr {[info commands testobj] != {}}] testConstraint testindexobj [expr {[info commands testindexobj] != {}}] +testConstraint fullutf [expr {[format %c 0x010000] != "\ufffd"}] # Used for constraining memory leak tests testConstraint memory [llength [info commands memory]] @@ -302,6 +303,9 @@ test string-5.19 {string index, bytearray object out of bounds} { test string-5.20 {string index, bytearray object out of bounds} { string index [binary format I* {0x50515253 0x52}] 20 } {} +test string-5.21 {string index, surrogates, bug [11ae2be95dac9417]} fullutf { + list [string index a\U100000b 1] [string index a\U100000b 2] [string index a\U100000b 3] +} [list \U100000 {} b] proc largest_int {} { @@ -1288,6 +1292,9 @@ test string-12.22 {string range, shimmering binary/index} { binary scan $s a* x string range $s $s end } 000000001 +test string-12.23 {string range, surrogates, bug [11ae2be95dac9417]} fullutf { + list [string range a\U100000b 1 1] [string range a\U100000b 2 2] [string range a\U100000b 3 3] +} [list \U100000 {} b] test string-13.1 {string repeat} { list [catch {string repeat} msg] $msg -- cgit v0.12 From c8219a9a2995c5658cd709f4bb7b5b933e6575e9 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 12 Jan 2018 10:03:58 +0000 Subject: Fix [11ae2be95d]: tip-389 branch: string range errors with code points greater than U+FFFF --- generic/tclExecute.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generic/tclExecute.c b/generic/tclExecute.c index f2cda0c..63281a8 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -5445,7 +5445,7 @@ TEBCresume( valuePtr->bytes+index, 1); } else { char buf[TCL_UTF_MAX]; - Tcl_UniChar ch = Tcl_GetUniChar(valuePtr, index); + int ch = Tcl_GetUniChar(valuePtr, index); /* * This could be: Tcl_NewUnicodeObj((const Tcl_UniChar *)&ch, 1) @@ -5453,7 +5453,7 @@ TEBCresume( * practical use. */ - length = Tcl_UniCharToUtf(ch, buf); + length = (ch != -1) ? Tcl_UniCharToUtf(ch, buf) : 0; objResultPtr = Tcl_NewStringObj(buf, length); } -- cgit v0.12 From 77d58c599368d5ecbe0803d79023efe7cd2f24bc Mon Sep 17 00:00:00 2001 From: bll Date: Tue, 6 Mar 2018 17:19:40 +0000 Subject: tip-421: array for: a) Fix bug starting search (name not set). b) Fix error message for array change on iteration. --- generic/tclVar.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/generic/tclVar.c b/generic/tclVar.c index da9fb23..c5df6c8 100644 --- a/generic/tclVar.c +++ b/generic/tclVar.c @@ -3074,6 +3074,8 @@ ArrayObjFirst( Tcl_HashEntry *hPtr; int isNew; + /* this code is duplicated from arraystartsearchcmd, + excepting that arrayNameObj is set */ searchPtr->varPtr = varPtr; searchPtr->arrayNameObj = arrayNameObj; @@ -3090,6 +3092,7 @@ ArrayObjFirst( searchPtr->nextEntry = VarHashFirstEntry(varPtr->value.tablePtr, &searchPtr->search); Tcl_SetHashValue(hPtr, searchPtr); + searchPtr->name = Tcl_ObjPrintf("s-%d-%s", searchPtr->id, TclGetString(arrayNameObj)); } int @@ -3307,8 +3310,10 @@ ArrayForLoopCallback( if (done != TCL_CONTINUE) { Tcl_ResetResult(interp); if (done == TCL_ERROR) { - varPtr->flags |= TCL_LEAVE_ERR_MSG; - Tcl_AddErrorInfo(interp, "array changed during iteration"); + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "array changed during iteration", -1)); + Tcl_SetErrorCode(interp, "TCL", "READ", "array", "for", NULL); + varPtr->flags |= TCL_LEAVE_ERR_MSG; result = done; } goto arrayfordone; -- cgit v0.12 From d2d193de11dddfa68c52223bfee22fc1c7e9de3c Mon Sep 17 00:00:00 2001 From: bll Date: Tue, 6 Mar 2018 18:21:34 +0000 Subject: array for: updated documentation: value variable is not optional, add specifics about when array for terminates. --- doc/array.n | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/array.n b/doc/array.n index 751c688..d6d4dff 100644 --- a/doc/array.n +++ b/doc/array.n @@ -47,12 +47,14 @@ been the return value from a previous invocation of 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. .TP -\fBarray for {\fIkeyVariable ?valueVariable?\fB} \fIarrayName body\fR -The first argument is a one or two element list of variable names for the +\fBarray for {\fIkeyVariable valueVariable\fB} \fIarrayName body\fP +The first argument is a 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. +If an array element is deleted or a new array element is inserted during +the \fIarray for\fP process, the command will terminate with an error. .TP \fBarray get \fIarrayName\fR ?\fIpattern\fR? Returns a list containing pairs of elements. The first -- cgit v0.12 From a735b5d3acb8dadac8bfec4f9b06cb2b1063db2d Mon Sep 17 00:00:00 2001 From: bll Date: Tue, 6 Mar 2018 18:42:25 +0000 Subject: array for: Add missing ObjCmdProc wrapper around the NR proc. --- generic/tclVar.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/generic/tclVar.c b/generic/tclVar.c index c5df6c8..8986fdd 100644 --- a/generic/tclVar.c +++ b/generic/tclVar.c @@ -177,6 +177,7 @@ static void AppendLocals(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *patternPtr, int includeLinks); static void ArrayDoneSearch (Interp *iPtr, Var *varPtr, ArraySearch *searchPtr); static Tcl_NRPostProc ArrayForLoopCallback; +static int ArrayForNRCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); static void DeleteSearches(Interp *iPtr, Var *arrayVarPtr); static void DeleteArray(Interp *iPtr, Tcl_Obj *arrayNamePtr, Var *varPtr, int flags, int index); @@ -3039,6 +3040,7 @@ TclArraySet( /* *---------------------------------------------------------------------- * + * ArrayForObjCmd * ArrayForNRCmd * ArrayForLoopCallback * ArrayObjFirst @@ -3049,6 +3051,8 @@ TclArraySet( * The array for command iterates over the array, setting the * the specified loop variables, and executing the body each iteration. * + * ArrayForObjCmd() is the standard wrapper around ArrayForNRCmd(). + * * ArrayForNRCmd() sets up the ArraySearch structure, sets arrayNamePtr * inside the structure and calls VarHashFirstEntry to start the hash * iteration. @@ -3152,6 +3156,16 @@ ArrayObjNext( return donerc; } +int +ArrayForObjCmd( + ClientData dummy, /* Not used. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + return Tcl_NRCallObjProc(interp, ArrayForNRCmd, dummy, objc, objv); +} + static int ArrayForNRCmd( ClientData dummy, @@ -4577,7 +4591,7 @@ TclInitArrayCmd( {"anymore", ArrayAnyMoreCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"donesearch", ArrayDoneSearchCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"exists", ArrayExistsCmd, TclCompileArrayExistsCmd, NULL, NULL, 0}, - {"for", NULL, TclCompileBasic3ArgCmd, ArrayForNRCmd, NULL, 0}, + {"for", ArrayForObjCmd, TclCompileBasic3ArgCmd, ArrayForNRCmd, NULL, 0}, {"get", ArrayGetCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, {"names", ArrayNamesCmd, TclCompileBasic1To3ArgCmd, NULL, NULL, 0}, {"nextelement", ArrayNextElementCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, -- cgit v0.12 From ba9cf35aa3b00da4e6572ea14c0790b10d733f4b Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 15 Mar 2018 23:01:00 +0000 Subject: In case of redirecting stderr to a file on Windows, append CRLF after Panic output. --- win/tclWinPanic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/win/tclWinPanic.c b/win/tclWinPanic.c index f7d9a72..d23ffcd 100644 --- a/win/tclWinPanic.c +++ b/win/tclWinPanic.c @@ -59,7 +59,8 @@ Tcl_ConsolePanic( WriteConsoleW(handle, msgString, wcslen(msgString), &dummy, 0); } else { buf[0] = 0xEF; buf[1] = 0xBB; buf[2] = 0xBF; /* UTF-8 bom */ - WriteFile(handle, buf, 3, &dummy, 0); + WriteFile(handle, buf, strlen(buf), &dummy, 0); + WriteFile(handle, "\n", 1, &dummy, 0); FlushFileBuffers(handle); } # if defined(__GNUC__) -- cgit v0.12 From 570af6354743c6365032517ef0ecfa8645b3ade7 Mon Sep 17 00:00:00 2001 From: sebres Date: Thu, 22 Mar 2018 16:22:04 +0000 Subject: win: fixes check of file permissions (readable, writable, executable) - more faster and stable solution without direct check of security permissions by optimal terms; additionally corrected executable extensions (missing .ps1/.cmd) in useWide case. --- win/tclWinFile.c | 59 ++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/win/tclWinFile.c b/win/tclWinFile.c index e671058..be31541 100755 --- a/win/tclWinFile.c +++ b/win/tclWinFile.c @@ -1576,33 +1576,51 @@ NativeAccess( return 0; } - if ((mode & W_OK) - && (attr & FILE_ATTRIBUTE_READONLY) - && !(attr & FILE_ATTRIBUTE_DIRECTORY)) { + /* + * If it's not a directory (assume file), do several fast checks: + */ + if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) { /* - * The attributes say the file is not writable. If the file is a + * If the attributes say this is not writable at all. The file is a * regular file (i.e., not a directory), then the file is not * writable, full stop. For directories, the read-only bit is * (mostly) ignored by Windows, so we can't ascertain anything about * directory access from the attrib data. However, if we have the - * advanced 'getFileSecurityProc', then more robust ACL checks + * advanced 'getNamedSecurityInfoProc', then more robust ACL checks * will be done below. */ + if ((mode & W_OK) && (attr & FILE_ATTRIBUTE_READONLY)) { + Tcl_SetErrno(EACCES); + return -1; + } - Tcl_SetErrno(EACCES); - return -1; - } - - if (mode & X_OK) { - if (!(attr & FILE_ATTRIBUTE_DIRECTORY) && !NativeIsExec(nativePath)) { - /* - * It's not a directory and doesn't have the correct extension. - * Therefore it can't be executable - */ - + /* If doesn't have the correct extension, it can't be executable */ + if ((mode & X_OK) && !NativeIsExec(nativePath)) { Tcl_SetErrno(EACCES); return -1; } + /* Special case for read/write/executable check on file */ + if ((mode & (R_OK|W_OK|X_OK)) && !(mode & ~(R_OK|W_OK|X_OK))) { + DWORD mask = 0; + HANDLE hFile; + if (mode & R_OK) { mask |= GENERIC_READ; } + if (mode & W_OK) { mask |= GENERIC_WRITE; } + if (mode & X_OK) { mask |= GENERIC_EXECUTE; } + + hFile = (tclWinProcs->createFileProc)(nativePath, mask, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, + OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL); + if (hFile != INVALID_HANDLE_VALUE) { + CloseHandle(hFile); + return 0; + } + /* fast exit if access was denied */ + if (GetLastError() == ERROR_ACCESS_DENIED) { + Tcl_SetErrno(EACCES); + return -1; + } + } + /* We cannnot verify the access fast, check it below using security info. */ } /* @@ -1811,9 +1829,12 @@ NativeIsExec( * Use wide-char case-insensitive comparison */ - if ((_wcsicmp(path+len-3, L"exe") == 0) - || (_wcsicmp(path+len-3, L"com") == 0) - || (_wcsicmp(path+len-3, L"bat") == 0)) { + path += len-3; + if ((_wcsicmp(path, L"exe") == 0) + || (_wcsicmp(path, L"com") == 0) + || (_wcsicmp(path, L"cmd") == 0) + || (_wcsicmp(path, L"ps1") == 0) + || (_wcsicmp(path, L"bat") == 0)) { return 1; } } else { -- cgit v0.12 From da169b1600f14d5ab924ceefb6383c2a0062e80d Mon Sep 17 00:00:00 2001 From: sebres Date: Thu, 22 Mar 2018 17:45:32 +0000 Subject: minor fix on comment (restored getFileSecurityProc back, because getNamedSecurityInfoProc not used) --- win/tclWinFile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win/tclWinFile.c b/win/tclWinFile.c index be31541..8fc0b8e 100755 --- a/win/tclWinFile.c +++ b/win/tclWinFile.c @@ -1586,7 +1586,7 @@ NativeAccess( * writable, full stop. For directories, the read-only bit is * (mostly) ignored by Windows, so we can't ascertain anything about * directory access from the attrib data. However, if we have the - * advanced 'getNamedSecurityInfoProc', then more robust ACL checks + * advanced 'getFileSecurityProc', then more robust ACL checks * will be done below. */ if ((mode & W_OK) && (attr & FILE_ATTRIBUTE_READONLY)) { -- cgit v0.12 From 9077b8ce60cdb2f2b4f9f4dc518cc8bf4d8268b5 Mon Sep 17 00:00:00 2001 From: sebres Date: Fri, 6 Apr 2018 17:28:56 +0000 Subject: =?UTF-8?q?[27b682284974d0cd]=20command=20"file=20delete":=20avoid?= =?UTF-8?q?=20possible=20race=20condition=20if=20file/directory=20deleted?= =?UTF-8?q?=20after=20call=20of=20lstat,=20so=20bypass=20ENOENT=20error=20?= =?UTF-8?q?code.=20Thanks=20to=20Rainer=20M=C3=BCller=20(aka=20raimue)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- generic/tclFCmd.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/generic/tclFCmd.c b/generic/tclFCmd.c index c52cd1e..5b2fbe1 100644 --- a/generic/tclFCmd.c +++ b/generic/tclFCmd.c @@ -373,14 +373,7 @@ TclFileDeleteCmd( */ if (Tcl_FSLstat(objv[i], &statBuf) != 0) { - /* - * Trying to delete a file that does not exist is not considered - * an error, just a no-op - */ - - if (errno != ENOENT) { - result = TCL_ERROR; - } + result = TCL_ERROR; } else if (S_ISDIR(statBuf.st_mode)) { /* * We own a reference count on errorBuffer, if it was set as a @@ -416,9 +409,16 @@ TclFileDeleteCmd( } if (result != TCL_OK) { - result = TCL_ERROR; /* + * Avoid possible race condition (file/directory deleted after call + * of lstat), so bypass ENOENT because not an error, just a no-op + */ + if (errno == ENOENT) { + result = TCL_OK; + continue; + } + /* * It is important that we break on error, otherwise we might end * up owning reference counts on numerous errorBuffers. */ -- cgit v0.12 From 24a04c081909c75252c8def939e0473206550302 Mon Sep 17 00:00:00 2001 From: sebres Date: Mon, 9 Apr 2018 10:04:23 +0000 Subject: amend to [5acb57c7aec45e05]: set code to TCL_ERROR, because primitives from tclIOUtil return -1 --- generic/tclFCmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tclFCmd.c b/generic/tclFCmd.c index 5b2fbe1..1363829 100644 --- a/generic/tclFCmd.c +++ b/generic/tclFCmd.c @@ -422,7 +422,7 @@ TclFileDeleteCmd( * It is important that we break on error, otherwise we might end * up owning reference counts on numerous errorBuffers. */ - + result = TCL_ERROR; break; } } -- cgit v0.12 From a9ef86f152a4cda4acf25dbb79dbd9cd18449458 Mon Sep 17 00:00:00 2001 From: sebres Date: Mon, 9 Apr 2018 19:50:12 +0000 Subject: win: fix several test-cases for windows platform --- tests/fileName.test | 14 +++++++++----- tests/tcltest.test | 8 +++++--- tests/winFCmd.test | 48 +++++++++++++++++++++++++++++++++--------------- 3 files changed, 47 insertions(+), 23 deletions(-) diff --git a/tests/fileName.test b/tests/fileName.test index d224011..0851e94 100644 --- a/tests/fileName.test +++ b/tests/fileName.test @@ -770,6 +770,7 @@ test filename-11.16 {Tcl_GlobCmd} { set globname "globTest" set horribleglobname "glob\[\{Test" +set tildeglobname "./~test.txt" test filename-11.17 {Tcl_GlobCmd} {unix} { list [catch {lsort [glob -directory $globname *]} msg] $msg @@ -940,11 +941,11 @@ test filename-11.21.1 {Tcl_GlobCmd} { # Get rid of file/dir if it exists, since it will have # been left behind by a previous failed run. -if {[file exists $horribleglobname]} { - file delete -force $horribleglobname -} +file delete -force $horribleglobname file rename globTest $horribleglobname set globname $horribleglobname +file delete -force $tildeglobname +close [open $tildeglobname w] test filename-11.22 {Tcl_GlobCmd} {unix} { list [catch {lsort [glob -dir $globname *]} msg] $msg @@ -1067,7 +1068,9 @@ test filename-11.41 {Tcl_GlobCmd} { test filename-11.42 {Tcl_GlobCmd} { set res [list] foreach f [glob -dir [pwd] *] { - lappend res [file tail $f] + set f [file tail $f] + regsub {^./} $f {} f; # until glob bug [2511011fff] don't fixed (tilde expansion prevention). + lappend res $f } expr {$res == [glob *]} } {1} @@ -1109,8 +1112,9 @@ test filename-11.49 {Tcl_GlobCmd} { } {1 {bad argument to "-types": abcde}} file rename $horribleglobname globTest +file delete -force $tildeglobname set globname globTest -unset horribleglobname +unset horribleglobname tildeglobname test filename-12.1 {simple globbing} {unixOrPc} { list [catch {glob {}} msg] $msg diff --git a/tests/tcltest.test b/tests/tcltest.test index ce8d617..d513856 100644 --- a/tests/tcltest.test +++ b/tests/tcltest.test @@ -549,8 +549,9 @@ switch -- $::tcl_platform(platform) { file attributes $notWriteableDir -permissions 00555 } default { + # note in FAT/NTFS we won't be able to protect directory with read-only attribute... catch {file attributes $notWriteableDir -readonly 1} - catch {testchmod 000 $notWriteableDir} + catch {testchmod 0 $notWriteableDir} } } test tcltest-8.3 {tcltest a.tcl -tmpdir notReadableDir} { @@ -565,9 +566,10 @@ test tcltest-8.3 {tcltest a.tcl -tmpdir notReadableDir} { # This constraint doesn't go at the top of the file so that it doesn't # interfere with tcltest-5.5 testConstraint notFAT [expr { - ![string match "FAT*" [lindex [file system $notWriteableDir] 1]] + ![regexp {^(FAT\d*|NTFS)$} [lindex [file system $notWriteableDir] 1]] + || $::tcl_platform(platform) eq "unix" || [llength [info commands testchmod]] }] -# FAT permissions are fairly hopeless; ignore this test if that FS is used +# FAT/NTFS permissions are fairly hopeless; ignore this test if that FS is used test tcltest-8.4 {tcltest a.tcl -tmpdir notWriteableDir} { -constraints {unixOrPc notRoot notFAT} -body { diff --git a/tests/winFCmd.test b/tests/winFCmd.test index f0cb406..b3fd921 100644 --- a/tests/winFCmd.test +++ b/tests/winFCmd.test @@ -17,6 +17,8 @@ if {[lsearch [namespace children] ::tcltest] == -1} { # Initialise the test constraints +testConstraint winVista 0 +testConstraint winXP 0 testConstraint testvolumetype [llength [info commands testvolumetype]] testConstraint testfile [llength [info commands testfile]] testConstraint testchmod [llength [info commands testchmod]] @@ -50,20 +52,25 @@ proc cleanup {args} { } } +if {[testConstraint win]} { + set major [string index $tcl_platform(osVersion) 0] + if {$major > 5} { + testConstraint winVista 1 + } elseif {$major == 5} { + testConstraint winXP 1 + } +} + # find a CD-ROM so we can test read-only filesystems. proc findfile {dir} { - foreach p [glob -directory $dir *] { - if {[file type $p] == "file"} { - return $p - } + foreach p [glob -nocomplain -type f -directory $dir *] { + return $p } - foreach p [glob -directory $dir *] { - if {[file type $p] == "directory"} { - set f [findfile $p] - if {$f != ""} { - return $f - } + foreach p [glob -nocomplain -type d -directory $dir *] { + set f [findfile $p] + if {$f ne ""} { + return $f } } return "" @@ -71,7 +78,7 @@ proc findfile {dir} { if {[testConstraint testvolumetype]} { foreach p {d e f g h i j k l m n o p q r s t u v w x y z} { - if {![catch {testvolumetype ${p}:} result] && $result eq "CDFS"} { + if {![catch {testvolumetype ${p}:} result] && $result in {CDFS UDF}} { set cdrom ${p}: set cdfile [findfile $cdrom] testConstraint cdrom 1 @@ -893,11 +900,22 @@ test winFCmd-12.4 {ConvertFileNameFormat} {win} { test winFCmd-12.5 {ConvertFileNameFormat: absolute path} {win} { list [file attributes / -longname] [file attributes \\ -longname] } {/ /} -test winFCmd-12.6 {ConvertFileNameFormat: absolute path with drive} {win} { +test winFCmd-12.6 {ConvertFileNameFormat: absolute path with drive} -setup { catch {file delete -force -- c:/td1} - close [open c:/td1 w] - list [catch {string tolower [file attributes c:/td1 -longname]} msg] $msg [file delete -force -- c:/td1] -} {0 c:/td1 {}} +} -constraints {win winXP} -body { + createfile c:/td1 {} + string tolower [file attributes c:/td1 -longname] +} -cleanup { + file delete -force -- c:/td1 +} -result {c:/td1} +test winFCmd-12.6.2 {ConvertFileNameFormat: absolute path with drive (in temp folder)} -setup { + catch {file delete -force -- $::env(TEMP)/td1} +} -constraints {win} -body { + createfile $::env(TEMP)/td1 {} + string tolower [file attributes $::env(TEMP)/td1 -longname] +} -cleanup { + file delete -force -- $::env(TEMP)/td1 +} -result [string tolower [file normalize $::env(TEMP)]/td1] test winFCmd-12.7 {ConvertFileNameFormat} {nonPortable win} { string tolower [file attributes //bisque/tcl/ws -longname] } {//bisque/tcl/ws} -- cgit v0.12 From 9856afd5903e2aec8bed684abb91fe307cd20765 Mon Sep 17 00:00:00 2001 From: sebres Date: Wed, 11 Apr 2018 11:28:41 +0000 Subject: win: some test-cases missing constraint for testexcept (if compiled without test) --- tests/winPipe.test | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/winPipe.test b/tests/winPipe.test index 3f983e1..f993e0c 100644 --- a/tests/winPipe.test +++ b/tests/winPipe.test @@ -21,6 +21,7 @@ set bindir [file join [pwd] [file dirname [info nameofexecutable]]] set cat32 [file join $bindir cat32.exe] testConstraint exec [llength [info commands exec]] +testConstraint testexcept [llength [info commands testexcept]] testConstraint cat32 [file exists $cat32] testConstraint AllocConsole [catch {puts console1 ""}] testConstraint RealConsole [expr {![testConstraint AllocConsole]}] @@ -193,28 +194,28 @@ test winpipe-4.1 {Tcl_WaitPid} {win nt exec cat32} { vwait x list $result $x [contents $path(stderr)] } "{$big} 1 stderr32" -test winpipe-4.2 {Tcl_WaitPid: return of exception codes, SIGFPE} {win exec} { +test winpipe-4.2 {Tcl_WaitPid: return of exception codes, SIGFPE} {win exec testexcept} { set f [open "|[list [interpreter]]" w+] set pid [pid $f] puts $f "testexcept float_underflow" set status [catch {close $f}] list $status [expr {$pid == [lindex $::errorCode 1]}] [lindex $::errorCode 2] } {1 1 SIGFPE} -test winpipe-4.3 {Tcl_WaitPid: return of exception codes, SIGSEGV} {win exec} { +test winpipe-4.3 {Tcl_WaitPid: return of exception codes, SIGSEGV} {win exec testexcept} { set f [open "|[list [interpreter]]" w+] set pid [pid $f] puts $f "testexcept access_violation" set status [catch {close $f}] list $status [expr {$pid == [lindex $::errorCode 1]}] [lindex $::errorCode 2] } {1 1 SIGSEGV} -test winpipe-4.4 {Tcl_WaitPid: return of exception codes, SIGILL} {win exec} { +test winpipe-4.4 {Tcl_WaitPid: return of exception codes, SIGILL} {win exec testexcept} { set f [open "|[list [interpreter]]" w+] set pid [pid $f] puts $f "testexcept illegal_instruction" set status [catch {close $f}] list $status [expr {$pid == [lindex $::errorCode 1]}] [lindex $::errorCode 2] } {1 1 SIGILL} -test winpipe-4.5 {Tcl_WaitPid: return of exception codes, SIGINT} {win exec} { +test winpipe-4.5 {Tcl_WaitPid: return of exception codes, SIGINT} {win exec testexcept} { set f [open "|[list [interpreter]]" w+] set pid [pid $f] puts $f "testexcept ctrl+c" -- cgit v0.12 From 4f69e81ae0e60c65611dedd07e3b36d6b275e056 Mon Sep 17 00:00:00 2001 From: andy Date: Thu, 12 Apr 2018 01:58:52 +0000 Subject: Fix documentation typo --- doc/define.n | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/define.n b/doc/define.n index 1692c94..c836c2f 100644 --- a/doc/define.n +++ b/doc/define.n @@ -50,7 +50,7 @@ being constructed. Within the constructor, the \fBnext\fR command should be used to call the superclasses' constructors. If \fIbodyScript\fR is the empty string, the constructor will be deleted. .TP -\fBdeletemethod\fI name\fR ?\fIname ...\fR +\fBdeletemethod\fI name\fR ?\fIname ...\fR? . This deletes each of the methods called \fIname\fR from a class. The methods must have previously existed in that class. Does not affect the superclasses -- cgit v0.12 From 2d5be386031bb7171009c07d78243bfcb1642d7d Mon Sep 17 00:00:00 2001 From: dgp Date: Mon, 16 Apr 2018 14:15:22 +0000 Subject: Memleak fix from Brad Lanam. --- generic/tclVar.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/generic/tclVar.c b/generic/tclVar.c index 8986fdd..92b3524 100644 --- a/generic/tclVar.c +++ b/generic/tclVar.c @@ -3097,6 +3097,7 @@ ArrayObjFirst( &searchPtr->search); Tcl_SetHashValue(hPtr, searchPtr); searchPtr->name = Tcl_ObjPrintf("s-%d-%s", searchPtr->id, TclGetString(arrayNameObj)); + Tcl_IncrRefCount(searchPtr->name); } int @@ -3361,6 +3362,7 @@ ArrayForLoopCallback( */ if (done != TCL_ERROR) { ArrayDoneSearch (iPtr, varPtr, searchPtr); + Tcl_DecrRefCount(searchPtr->name); ckfree(searchPtr); } -- cgit v0.12 From 04604552b21903025c8b98a936347adae95c6ed3 Mon Sep 17 00:00:00 2001 From: dgp Date: Mon, 16 Apr 2018 14:51:19 +0000 Subject: ran autoconf on the unix directory. This breaks the build. --- unix/configure | 320 --------------------------------------------------------- 1 file changed, 320 deletions(-) diff --git a/unix/configure b/unix/configure index 36bc4b9..a2db021 100755 --- a/unix/configure +++ b/unix/configure @@ -699,7 +699,6 @@ ZLIB_INCLUDE ZLIB_SRCS ZLIB_OBJS TCLSH_PROG -TCL_THREADS EGREP GREP CPP @@ -755,7 +754,6 @@ enable_option_checking enable_man_symlinks enable_man_compression enable_man_suffix -enable_threads with_encoding enable_shared enable_64bit @@ -1395,7 +1393,6 @@ Optional Features: use STRING as a suffix to manpage file names (default: no, tcl if enabled without specifying STRING) - --enable-threads build with threads (default: on) --enable-shared build and link with shared libraries (default: on) --enable-64bit enable 64bit support (default: off) --enable-64bit-vis enable 64bit Sparc VIS support (default: off) @@ -3911,323 +3908,6 @@ $as_echo "$tcl_cv_cc_pipe" >&6; } fi #------------------------------------------------------------------------ -# Threads support -#------------------------------------------------------------------------ - - - # Check whether --enable-threads was given. -if test "${enable_threads+set}" = set; then : - enableval=$enable_threads; tcl_ok=$enableval -else - tcl_ok=yes -fi - - - if test "${TCL_THREADS}" = 1; then - tcl_threaded_core=1; - fi - - if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then - TCL_THREADS=1 - # USE_THREAD_ALLOC tells us to try the special thread-based - # allocator that significantly reduces lock contention - -$as_echo "#define USE_THREAD_ALLOC 1" >>confdefs.h - - -$as_echo "#define _REENTRANT 1" >>confdefs.h - - if test "`uname -s`" = "SunOS" ; then - -$as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h - - fi - -$as_echo "#define _THREAD_SAFE 1" >>confdefs.h - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthread" >&5 -$as_echo_n "checking for pthread_mutex_init in -lpthread... " >&6; } -if ${ac_cv_lib_pthread_pthread_mutex_init+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lpthread $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char pthread_mutex_init (); -int -main () -{ -return pthread_mutex_init (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_pthread_pthread_mutex_init=yes -else - ac_cv_lib_pthread_pthread_mutex_init=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5 -$as_echo "$ac_cv_lib_pthread_pthread_mutex_init" >&6; } -if test "x$ac_cv_lib_pthread_pthread_mutex_init" = xyes; then : - tcl_ok=yes -else - tcl_ok=no -fi - - if test "$tcl_ok" = "no"; then - # Check a little harder for __pthread_mutex_init in the same - # library, as some systems hide it there until pthread.h is - # defined. We could alternatively do an AC_TRY_COMPILE with - # pthread.h, but that will work with libpthread really doesn't - # exist, like AIX 4.2. [Bug: 4359] - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __pthread_mutex_init in -lpthread" >&5 -$as_echo_n "checking for __pthread_mutex_init in -lpthread... " >&6; } -if ${ac_cv_lib_pthread___pthread_mutex_init+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lpthread $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char __pthread_mutex_init (); -int -main () -{ -return __pthread_mutex_init (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_pthread___pthread_mutex_init=yes -else - ac_cv_lib_pthread___pthread_mutex_init=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread___pthread_mutex_init" >&5 -$as_echo "$ac_cv_lib_pthread___pthread_mutex_init" >&6; } -if test "x$ac_cv_lib_pthread___pthread_mutex_init" = xyes; then : - tcl_ok=yes -else - tcl_ok=no -fi - - fi - - if test "$tcl_ok" = "yes"; then - # The space is needed - THREADS_LIBS=" -lpthread" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthreads" >&5 -$as_echo_n "checking for pthread_mutex_init in -lpthreads... " >&6; } -if ${ac_cv_lib_pthreads_pthread_mutex_init+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lpthreads $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char pthread_mutex_init (); -int -main () -{ -return pthread_mutex_init (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_pthreads_pthread_mutex_init=yes -else - ac_cv_lib_pthreads_pthread_mutex_init=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthreads_pthread_mutex_init" >&5 -$as_echo "$ac_cv_lib_pthreads_pthread_mutex_init" >&6; } -if test "x$ac_cv_lib_pthreads_pthread_mutex_init" = xyes; then : - tcl_ok=yes -else - tcl_ok=no -fi - - if test "$tcl_ok" = "yes"; then - # The space is needed - THREADS_LIBS=" -lpthreads" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc" >&5 -$as_echo_n "checking for pthread_mutex_init in -lc... " >&6; } -if ${ac_cv_lib_c_pthread_mutex_init+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lc $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char pthread_mutex_init (); -int -main () -{ -return pthread_mutex_init (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_c_pthread_mutex_init=yes -else - ac_cv_lib_c_pthread_mutex_init=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_pthread_mutex_init" >&5 -$as_echo "$ac_cv_lib_c_pthread_mutex_init" >&6; } -if test "x$ac_cv_lib_c_pthread_mutex_init" = xyes; then : - tcl_ok=yes -else - tcl_ok=no -fi - - if test "$tcl_ok" = "no"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc_r" >&5 -$as_echo_n "checking for pthread_mutex_init in -lc_r... " >&6; } -if ${ac_cv_lib_c_r_pthread_mutex_init+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lc_r $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char pthread_mutex_init (); -int -main () -{ -return pthread_mutex_init (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_c_r_pthread_mutex_init=yes -else - ac_cv_lib_c_r_pthread_mutex_init=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_mutex_init" >&5 -$as_echo "$ac_cv_lib_c_r_pthread_mutex_init" >&6; } -if test "x$ac_cv_lib_c_r_pthread_mutex_init" = xyes; then : - tcl_ok=yes -else - tcl_ok=no -fi - - if test "$tcl_ok" = "yes"; then - # The space is needed - THREADS_LIBS=" -pthread" - else - TCL_THREADS=0 - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Don't know how to find pthread lib on your system - you must disable thread support or edit the LIBS in the Makefile..." >&5 -$as_echo "$as_me: WARNING: Don't know how to find pthread lib on your system - you must disable thread support or edit the LIBS in the Makefile..." >&2;} - fi - fi - fi - fi - - # Does the pthread-implementation provide - # 'pthread_attr_setstacksize' ? - - ac_saved_libs=$LIBS - LIBS="$LIBS $THREADS_LIBS" - for ac_func in pthread_attr_setstacksize pthread_atfork -do : - as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` -ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -if eval test \"x\$"$as_ac_var"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - -fi -done - - LIBS=$ac_saved_libs - else - TCL_THREADS=0 - fi - # Do checking message here to not mess up interleaved configure output - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for building with threads" >&5 -$as_echo_n "checking for building with threads... " >&6; } - if test "${TCL_THREADS}" = 1; then - -$as_echo "#define TCL_THREADS 1" >>confdefs.h - - if test "${tcl_threaded_core}" = 1; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (threaded core)" >&5 -$as_echo "yes (threaded core)" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - fi - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - fi - - - - -#------------------------------------------------------------------------ # Embedded configuration information, encoding to use for the values, TIP #59 #------------------------------------------------------------------------ -- cgit v0.12 From 08d704bbb1b78da3ca7806bfc5c7fd8fae51e570 Mon Sep 17 00:00:00 2001 From: dgp Date: Tue, 17 Apr 2018 03:48:47 +0000 Subject: Test of shimmer segfault. --- tests/var.test | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/var.test b/tests/var.test index a391a01..6ac3e52 100644 --- a/tests/var.test +++ b/tests/var.test @@ -1143,6 +1143,15 @@ test var-23.13 {array enumeration, number of traces} -setup { unset -nocomplain ::a unset -nocomplain reslist } -result 3 +test var-23.14 {array for, shared arguments} -setup { + set vn {k v} + unset -nocomplain $vn +} -body { + array set $vn {a 1 b 2 c 3} + array for $vn $vn {} +} -cleanup { + unset -nocomplain $vn vn +} -result {} catch {namespace delete ns} catch {unset arr} -- cgit v0.12 From 47fc4afd862da2e3956e8437f7689ba043ac3a43 Mon Sep 17 00:00:00 2001 From: dgp Date: Tue, 17 Apr 2018 11:11:35 +0000 Subject: Satisfy test var-23.14 --- generic/tclVar.c | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/generic/tclVar.c b/generic/tclVar.c index 92b3524..a2fa680 100644 --- a/generic/tclVar.c +++ b/generic/tclVar.c @@ -3175,13 +3175,11 @@ ArrayForNRCmd( Tcl_Obj *const *objv) { Interp *iPtr = (Interp *) interp; - Tcl_Obj *scriptObj, *keyVarObj, *valueVarObj; - Tcl_Obj **varv; - Tcl_Obj *arrayNameObj; + Tcl_Obj *varListObj, *arrayNameObj, *scriptObj; ArraySearch *searchPtr = NULL; Var *varPtr; Var *arrayPtr; - int varc; + int numVars; /* * array for {k v} a body @@ -3197,10 +3195,12 @@ ArrayForNRCmd( * Parse arguments. */ - if (TclListObjGetElements(interp, objv[1], &varc, &varv) != TCL_OK) { + + if (Tcl_ListObjLength(interp, objv[1], &numVars) != TCL_OK) { return TCL_ERROR; } - if (varc != 2) { + + if (numVars != 2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "must have two variable names", -1)); Tcl_SetErrorCode(interp, "TCL", "SYNTAX", "array", "for", NULL); @@ -3208,9 +3208,6 @@ ArrayForNRCmd( } arrayNameObj = objv[2]; - keyVarObj = varv[0]; - valueVarObj = varv[1]; - scriptObj = objv[3]; /* * Locate the array variable. @@ -3262,16 +3259,16 @@ ArrayForNRCmd( * loop) don't vanish. */ - Tcl_IncrRefCount(keyVarObj); - Tcl_IncrRefCount(valueVarObj); + varListObj = TclListObjCopy(NULL, objv[1]); + scriptObj = objv[3]; Tcl_IncrRefCount(scriptObj); /* * Run the script. */ - TclNRAddCallback(interp, ArrayForLoopCallback, searchPtr, keyVarObj, - valueVarObj, scriptObj); + TclNRAddCallback(interp, ArrayForLoopCallback, searchPtr, varListObj, + NULL, scriptObj); return TCL_OK; } @@ -3283,13 +3280,13 @@ ArrayForLoopCallback( { Interp *iPtr = (Interp *) interp; ArraySearch *searchPtr = data[0]; - Tcl_Obj *keyVarObj = data[1]; - Tcl_Obj *valueVarObj = data[2]; + Tcl_Obj *varListObj = data[1]; Tcl_Obj *scriptObj = data[3]; + Tcl_Obj **varv; Tcl_Obj *keyObj, *valueObj; Var *varPtr; Var *arrayPtr; - int done; + int done, varc; /* * Process the result from the previous execution of the script body. @@ -3333,12 +3330,14 @@ ArrayForLoopCallback( } goto arrayfordone; } - if (Tcl_ObjSetVar2(interp, keyVarObj, NULL, keyObj, TCL_LEAVE_ERR_MSG) == NULL) { + + Tcl_ListObjGetElements(NULL, varListObj, &varc, &varv); + if (Tcl_ObjSetVar2(interp, varv[0], NULL, keyObj, TCL_LEAVE_ERR_MSG) == NULL) { result = TCL_ERROR; goto arrayfordone; } if (valueObj != NULL) { - if (Tcl_ObjSetVar2(interp, valueVarObj, NULL, valueObj, TCL_LEAVE_ERR_MSG) == NULL) { + if (Tcl_ObjSetVar2(interp, varv[1], NULL, valueObj, TCL_LEAVE_ERR_MSG) == NULL) { result = TCL_ERROR; goto arrayfordone; } @@ -3348,8 +3347,8 @@ ArrayForLoopCallback( * Run the script. */ - TclNRAddCallback(interp, ArrayForLoopCallback, searchPtr, keyVarObj, - valueVarObj, scriptObj); + TclNRAddCallback(interp, ArrayForLoopCallback, searchPtr, varListObj, + NULL, scriptObj); return TclNREvalObjEx(interp, scriptObj, 0, iPtr->cmdFramePtr, 3); /* @@ -3366,8 +3365,7 @@ ArrayForLoopCallback( ckfree(searchPtr); } - TclDecrRefCount(keyVarObj); - TclDecrRefCount(valueVarObj); + TclDecrRefCount(varListObj); TclDecrRefCount(scriptObj); return result; } -- cgit v0.12 From 80e5aed49e2cac237b9d91db0f5dc1139c6462dd Mon Sep 17 00:00:00 2001 From: dgp Date: Tue, 17 Apr 2018 14:32:30 +0000 Subject: Restore build success to the TCL_REMOVE_OBSOLETE_TRACES configuration. --- generic/tclTrace.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/generic/tclTrace.c b/generic/tclTrace.c index 2e1b241..cb465ca 100644 --- a/generic/tclTrace.c +++ b/generic/tclTrace.c @@ -176,7 +176,9 @@ Tcl_TraceObjCmd( Tcl_Obj *const objv[]) /* Argument objects. */ { int optionIndex; +#ifndef TCL_REMOVE_OBSOLETE_TRACES char *name, *flagOps, *p; +#endif /* Main sub commands to 'trace' */ static const char *traceOptions[] = { "add", "info", "remove", @@ -352,10 +354,12 @@ Tcl_TraceObjCmd( } return TCL_OK; +#ifndef TCL_REMOVE_OBSOLETE_TRACES badVarOps: Tcl_AppendResult(interp, "bad operations \"", flagOps, "\": should be one or more of rwua", NULL); return TCL_ERROR; +#endif } /* @@ -902,9 +906,11 @@ TraceVariableObjCmd( (sizeof(CombinedTraceVarInfo) + length + 1 - sizeof(ctvarPtr->traceCmdInfo.command))); ctvarPtr->traceCmdInfo.flags = flags; +#ifndef TCL_REMOVE_OBSOLETE_TRACES if (objv[0] == NULL) { ctvarPtr->traceCmdInfo.flags |= TCL_TRACE_OLD_STYLE; } +#endif ctvarPtr->traceCmdInfo.length = length; flags |= TCL_TRACE_UNSETS | TCL_TRACE_RESULT_OBJECT; memcpy(ctvarPtr->traceCmdInfo.command, command, length+1); @@ -931,7 +937,11 @@ TraceVariableObjCmd( TraceVarProc, clientData)) != 0) { tvarPtr = (TraceVarInfo *) clientData; if ((tvarPtr->length == length) - && ((tvarPtr->flags & ~TCL_TRACE_OLD_STYLE)==flags) + && ((tvarPtr->flags +#ifndef TCL_REMOVE_OBSOLETE_TRACES +& ~TCL_TRACE_OLD_STYLE +#endif + )==flags) && (strncmp(command, tvarPtr->command, (size_t) length) == 0)) { Tcl_UntraceVar2(interp, name, NULL, -- cgit v0.12 From f316d7539c5bb69dc519fc27be251c9ba056c189 Mon Sep 17 00:00:00 2001 From: dgp Date: Tue, 17 Apr 2018 18:34:41 +0000 Subject: [array set] must fire array traces. Don't disrupt that by reporting argument errors too early. --- generic/tclCompCmds.c | 11 +++++++++++ tests/var.test | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/generic/tclCompCmds.c b/generic/tclCompCmds.c index c2b4bdb..9a15ee0 100644 --- a/generic/tclCompCmds.c +++ b/generic/tclCompCmds.c @@ -322,11 +322,22 @@ TclCompileArraySetCmd( */ if (isDataValid && !isDataEven) { + /* Abandon compile and let direct eval raise the error */ + code = TCL_ERROR; + goto done; + + /* + * We used to compile to the bytecode that would throw the error, + * but that was wrong because it would not invoke the array trace + * on the variable. + * PushStringLiteral(envPtr, "list must have an even number of elements"); PushStringLiteral(envPtr, "-errorcode {TCL ARGUMENT FORMAT}"); TclEmitInstInt4(INST_RETURN_IMM, TCL_ERROR, envPtr); TclEmitInt4( 0, envPtr); goto done; + * + */ } /* diff --git a/tests/var.test b/tests/var.test index a9d93ac..d1340f6 100644 --- a/tests/var.test +++ b/tests/var.test @@ -930,6 +930,15 @@ test var-20.9 {[bc1a96407a] array set compiled w/ trace} -setup { test var-20.10 {[bc1a96407a] array set don't compile bad varname} -body { apply {{} {set name foo(bar); array set $name {a 1}}} } -returnCodes error -match glob -result * +test var-20.11 {array set don't compile bad initializer} -setup { + unset -nocomplain foo + trace add variable foo array {set foo(bar) baz;#} +} -body { + catch {array set foo bad} + set foo(bar) +} -cleanup { + unset -nocomplain foo +} -result baz test var-21.0 {PushVarNameWord OBOE in compiled unset} -setup { proc linenumber {} {dict get [info frame -1] line} -- cgit v0.12 From 5dff80f2fe38009bc7e7c6b3f74033a8a05a59a1 Mon Sep 17 00:00:00 2001 From: dgp Date: Tue, 17 Apr 2018 18:54:36 +0000 Subject: Gentler fallback. --- generic/tclCompCmds.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generic/tclCompCmds.c b/generic/tclCompCmds.c index 9a15ee0..22bbca0 100644 --- a/generic/tclCompCmds.c +++ b/generic/tclCompCmds.c @@ -322,8 +322,8 @@ TclCompileArraySetCmd( */ if (isDataValid && !isDataEven) { - /* Abandon compile and let direct eval raise the error */ - code = TCL_ERROR; + /* Abandon custom compile and let invocation raise the error */ + code = TclCompileBasic2ArgCmd(interp, parsePtr, cmdPtr, envPtr); goto done; /* -- cgit v0.12 From 62ea5e49a10037bf3a3896a933db4951ff0b15bc Mon Sep 17 00:00:00 2001 From: dgp Date: Tue, 17 Apr 2018 19:14:01 +0000 Subject: Array trace firing must come before argument checking might raise error. --- generic/tclCompCmds.c | 7 ++++--- tests/var.test | 13 +++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/generic/tclCompCmds.c b/generic/tclCompCmds.c index 22bbca0..838e9d7 100644 --- a/generic/tclCompCmds.c +++ b/generic/tclCompCmds.c @@ -415,6 +415,10 @@ TclCompileArraySetCmd( * Start issuing instructions to write to the array. */ + TclEmitInstInt4(INST_ARRAY_EXISTS_IMM, localIndex, envPtr); + TclEmitInstInt1(INST_JUMP_TRUE1, 7, envPtr); + TclEmitInstInt4(INST_ARRAY_MAKE_IMM, localIndex, envPtr); + CompileWord(envPtr, dataTokenPtr, interp, 2); if (!isDataLiteral || !isDataValid) { /* @@ -439,9 +443,6 @@ TclCompileArraySetCmd( TclStoreInt1AtPtr(fwd, envPtr->codeStart+offsetFwd+1); } - TclEmitInstInt4(INST_ARRAY_EXISTS_IMM, localIndex, envPtr); - TclEmitInstInt1(INST_JUMP_TRUE1, 7, envPtr); - TclEmitInstInt4(INST_ARRAY_MAKE_IMM, localIndex, envPtr); TclEmitInstInt4(INST_FOREACH_START, infoIndex, envPtr); offsetBack = CurrentOffset(envPtr); Emit14Inst( INST_LOAD_SCALAR, keyVar, envPtr); diff --git a/tests/var.test b/tests/var.test index d1340f6..01080bc 100644 --- a/tests/var.test +++ b/tests/var.test @@ -939,6 +939,19 @@ test var-20.11 {array set don't compile bad initializer} -setup { } -cleanup { unset -nocomplain foo } -result baz +test var-20.12 {array set don't compile bad initializer} -setup { + unset -nocomplain ::foo + trace add variable ::foo array {set ::foo(bar) baz;#} +} -body { + catch {apply {{} { + set value bad + array set ::foo $value + + }}} + set ::foo(bar) +} -cleanup { + unset -nocomplain ::foo +} -result baz test var-21.0 {PushVarNameWord OBOE in compiled unset} -setup { proc linenumber {} {dict get [info frame -1] line} -- cgit v0.12 From 6b8039a9524bb88679e0d837a5345f26c8654a52 Mon Sep 17 00:00:00 2001 From: dgp Date: Tue, 17 Apr 2018 20:29:02 +0000 Subject: Refactor array trace handling into a common routine TclCheckArrayTraces(). --- generic/tclExecute.c | 17 ++--- generic/tclInt.h | 2 + generic/tclTrace.c | 41 ++++++++++++ generic/tclVar.c | 180 +++++++++++---------------------------------------- 4 files changed, 86 insertions(+), 154 deletions(-) diff --git a/generic/tclExecute.c b/generic/tclExecute.c index aab9092..5bc5c2d 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -4294,17 +4294,12 @@ TEBCresume( varPtr = TclObjLookupVarEx(interp, part1Ptr, NULL, 0, NULL, /*createPart1*/0, /*createPart2*/0, &arrayPtr); doArrayExists: - if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) - && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { - DECACHE_STACK_INFO(); - result = TclObjCallVarTraces(iPtr, arrayPtr, varPtr, part1Ptr, - NULL, (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY| - TCL_GLOBAL_ONLY|TCL_TRACE_ARRAY), 1, opnd); - CACHE_STACK_INFO(); - if (result == TCL_ERROR) { - TRACE_ERROR(interp); - goto gotError; - } + DECACHE_STACK_INFO(); + result = TclCheckArrayTraces(interp, varPtr, arrayPtr, part1Ptr, opnd); + CACHE_STACK_INFO(); + if (result == TCL_ERROR) { + TRACE_ERROR(interp); + goto gotError; } if (varPtr && TclIsVarArray(varPtr) && !TclIsVarUndefined(varPtr)) { objResultPtr = TCONST(1); diff --git a/generic/tclInt.h b/generic/tclInt.h index dc7909c..371e3fa 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -2873,6 +2873,8 @@ MODULE_SCOPE int TclByteArrayMatch(const unsigned char *string, MODULE_SCOPE double TclCeil(const mp_int *a); MODULE_SCOPE void TclChannelPreserve(Tcl_Channel chan); MODULE_SCOPE void TclChannelRelease(Tcl_Channel chan); +MODULE_SCOPE int TclCheckArrayTraces(Tcl_Interp *interp, Var *varPtr, + Var *arrayPtr, Tcl_Obj *name, int index); MODULE_SCOPE int TclCheckBadOctal(Tcl_Interp *interp, const char *value); MODULE_SCOPE int TclChanCaughtErrorBypass(Tcl_Interp *interp, diff --git a/generic/tclTrace.c b/generic/tclTrace.c index 958399a..d48761b 100644 --- a/generic/tclTrace.c +++ b/generic/tclTrace.c @@ -2478,6 +2478,47 @@ TclVarTraceExists( /* *---------------------------------------------------------------------- * + * TclCheckArrayTraces -- + * + * This function is invoked to when we operate on an array variable, + * to allow any array traces to fire. + * + * Results: + * Returns TCL_OK to indicate normal operation. Returns TCL_ERROR if + * invocation of a trace function indicated an error. When TCL_ERROR is + * returned, then error information is left in interp. + * + * Side effects: + * Almost anything can happen, depending on trace; this function itself + * doesn't have any side effects. + * + *---------------------------------------------------------------------- + */ + +int +TclCheckArrayTraces( + Tcl_Interp *interp, + Var *varPtr, + Var *arrayPtr, + Tcl_Obj *name, + int index) +{ + int code = TCL_OK; + + if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) + && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { + Interp *iPtr = (Interp *)interp; + + code = TclObjCallVarTraces(iPtr, arrayPtr, varPtr, name, NULL, + (TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| TCL_TRACE_ARRAY), + /* leaveErrMsg */ 1, index); + } + return code; +} + +/* + *---------------------------------------------------------------------- + * * TclCallVarTraces -- * * This function is invoked to find and invoke relevant trace functions diff --git a/generic/tclVar.c b/generic/tclVar.c index 3dd6790..e07d39a 100644 --- a/generic/tclVar.c +++ b/generic/tclVar.c @@ -3121,7 +3121,7 @@ ArrayStartSearchCmd( int objc, Tcl_Obj *const objv[]) { - Interp *iPtr = (Interp *) interp; + Interp *iPtr = (Interp *)interp; Var *varPtr, *arrayPtr; Tcl_HashEntry *hPtr; Tcl_Obj *varNameObj; @@ -3143,18 +3143,9 @@ ArrayStartSearchCmd( /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); varName = TclGetString(varNameObj); - /* - * Special array trace used to keep the env array in sync for array names, - * array get, etc. - */ - - if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) - && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { - if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, varNameObj, NULL, - (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| - TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) { - return TCL_ERROR; - } + if (TclCheckArrayTraces(interp, varPtr, arrayPtr, varNameObj, -1) + == TCL_ERROR) { + return TCL_ERROR; } /* @@ -3219,7 +3210,7 @@ ArrayAnyMoreCmd( int objc, Tcl_Obj *const objv[]) { - Interp *iPtr = (Interp *) interp; + Interp *iPtr = (Interp *)interp; Var *varPtr, *arrayPtr; Tcl_Obj *varNameObj, *searchObj; int gotValue; @@ -3239,18 +3230,9 @@ ArrayAnyMoreCmd( varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); - /* - * Special array trace used to keep the env array in sync for array names, - * array get, etc. - */ - - if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) - && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { - if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, varNameObj, NULL, - (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| - TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) { - return TCL_ERROR; - } + if (TclCheckArrayTraces(interp, varPtr, arrayPtr, varNameObj, -1) + == TCL_ERROR) { + return TCL_ERROR; } /* @@ -3326,7 +3308,6 @@ ArrayNextElementCmd( int objc, Tcl_Obj *const objv[]) { - Interp *iPtr = (Interp *) interp; Var *varPtr, *arrayPtr; Tcl_Obj *varNameObj, *searchObj; ArraySearch *searchPtr; @@ -3345,18 +3326,9 @@ ArrayNextElementCmd( varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); - /* - * Special array trace used to keep the env array in sync for array names, - * array get, etc. - */ - - if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) - && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { - if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, varNameObj, NULL, - (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| - TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) { - return TCL_ERROR; - } + if (TclCheckArrayTraces(interp, varPtr, arrayPtr, varNameObj, -1) + == TCL_ERROR) { + return TCL_ERROR; } /* @@ -3435,7 +3407,7 @@ ArrayDoneSearchCmd( int objc, Tcl_Obj *const objv[]) { - Interp *iPtr = (Interp *) interp; + Interp *iPtr = (Interp *)interp; Var *varPtr, *arrayPtr; Tcl_HashEntry *hPtr; Tcl_Obj *varNameObj, *searchObj; @@ -3455,18 +3427,9 @@ ArrayDoneSearchCmd( varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); - /* - * Special array trace used to keep the env array in sync for array names, - * array get, etc. - */ - - if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) - && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { - if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, varNameObj, NULL, - (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| - TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) { - return TCL_ERROR; - } + if (TclCheckArrayTraces(interp, varPtr, arrayPtr, varNameObj, -1) + == TCL_ERROR) { + return TCL_ERROR; } /* @@ -3543,7 +3506,7 @@ ArrayExistsCmd( int objc, Tcl_Obj *const objv[]) { - Interp *iPtr = (Interp *) interp; + Interp *iPtr = (Interp *)interp; Var *varPtr, *arrayPtr; Tcl_Obj *arrayNameObj; int notArray; @@ -3561,18 +3524,9 @@ ArrayExistsCmd( varPtr = TclObjLookupVarEx(interp, arrayNameObj, NULL, /*flags*/ 0, /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); - /* - * Special array trace used to keep the env array in sync for array names, - * array get, etc. - */ - - if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) - && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { - if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, arrayNameObj, NULL, - (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| - TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) { - return TCL_ERROR; - } + if (TclCheckArrayTraces(interp, varPtr, arrayPtr, arrayNameObj, -1) + == TCL_ERROR) { + return TCL_ERROR; } /* @@ -3610,7 +3564,6 @@ ArrayGetCmd( int objc, Tcl_Obj *const objv[]) { - Interp *iPtr = (Interp *) interp; Var *varPtr, *arrayPtr, *varPtr2; Tcl_Obj *varNameObj, *nameObj, *valueObj, *nameLstObj, *tmpResObj; Tcl_Obj **nameObjPtr, *patternObj; @@ -3639,18 +3592,9 @@ ArrayGetCmd( varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); - /* - * Special array trace used to keep the env array in sync for array names, - * array get, etc. - */ - - if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) - && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { - if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, varNameObj, NULL, - (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| - TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) { - return TCL_ERROR; - } + if (TclCheckArrayTraces(interp, varPtr, arrayPtr, varNameObj, -1) + == TCL_ERROR) { + return TCL_ERROR; } /* @@ -3798,7 +3742,6 @@ ArrayNamesCmd( "-exact", "-glob", "-regexp", NULL }; enum options { OPT_EXACT, OPT_GLOB, OPT_REGEXP }; - Interp *iPtr = (Interp *) interp; Var *varPtr, *arrayPtr, *varPtr2; Tcl_Obj *varNameObj, *nameObj, *resultObj, *patternObj; Tcl_HashSearch search; @@ -3819,18 +3762,9 @@ ArrayNamesCmd( varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); - /* - * Special array trace used to keep the env array in sync for array names, - * array get, etc. - */ - - if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) - && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { - if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, varNameObj, NULL, - (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| - TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) { - return TCL_ERROR; - } + if (TclCheckArrayTraces(interp, varPtr, arrayPtr, varNameObj, -1) + == TCL_ERROR) { + return TCL_ERROR; } /* @@ -3986,7 +3920,6 @@ ArraySetCmd( int objc, Tcl_Obj *const objv[]) { - Interp *iPtr = (Interp *) interp; Var *varPtr, *arrayPtr; if (objc != 3) { @@ -4001,18 +3934,9 @@ ArraySetCmd( varPtr = TclObjLookupVarEx(interp, objv[1], NULL, /*flags*/ 0, /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); - /* - * Special array trace used to keep the env array in sync for array names, - * array get, etc. - */ - - if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) - && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { - if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, objv[1], NULL, - (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| - TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) { - return TCL_ERROR; - } + if (TclCheckArrayTraces(interp, varPtr, arrayPtr, objv[1], -1) + == TCL_ERROR) { + return TCL_ERROR; } return TclArraySet(interp, objv[1], objv[2]); @@ -4043,7 +3967,6 @@ ArraySizeCmd( int objc, Tcl_Obj *const objv[]) { - Interp *iPtr = (Interp *) interp; Var *varPtr, *arrayPtr; Tcl_Obj *varNameObj; Tcl_HashSearch search; @@ -4063,18 +3986,9 @@ ArraySizeCmd( varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); - /* - * Special array trace used to keep the env array in sync for array names, - * array get, etc. - */ - - if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) - && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { - if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, varNameObj, NULL, - (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| - TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) { - return TCL_ERROR; - } + if (TclCheckArrayTraces(interp, varPtr, arrayPtr, varNameObj, -1) + == TCL_ERROR) { + return TCL_ERROR; } /* @@ -4127,7 +4041,6 @@ ArrayStatsCmd( int objc, Tcl_Obj *const objv[]) { - Interp *iPtr = (Interp *) interp; Var *varPtr, *arrayPtr; Tcl_Obj *varNameObj; char *stats; @@ -4145,18 +4058,9 @@ ArrayStatsCmd( varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); - /* - * Special array trace used to keep the env array in sync for array names, - * array get, etc. - */ - - if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) - && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { - if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, varNameObj, NULL, - (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| - TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) { - return TCL_ERROR; - } + if (TclCheckArrayTraces(interp, varPtr, arrayPtr, varNameObj, -1) + == TCL_ERROR) { + return TCL_ERROR; } /* @@ -4210,7 +4114,6 @@ ArrayUnsetCmd( int objc, Tcl_Obj *const objv[]) { - Interp *iPtr = (Interp *) interp; Var *varPtr, *arrayPtr, *varPtr2, *protectedVarPtr; Tcl_Obj *varNameObj, *patternObj, *nameObj; Tcl_HashSearch search; @@ -4238,18 +4141,9 @@ ArrayUnsetCmd( varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); - /* - * Special array trace used to keep the env array in sync for array names, - * array get, etc. - */ - - if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) - && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { - if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, varNameObj, NULL, - (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| - TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) { - return TCL_ERROR; - } + if (TclCheckArrayTraces(interp, varPtr, arrayPtr, varNameObj, -1) + == TCL_ERROR) { + return TCL_ERROR; } /* -- cgit v0.12 From 28ac08663306381af8f310b247bec60e5ed694db Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 17 Apr 2018 21:49:00 +0000 Subject: Slightly better unmatched-surrogates handling. Unmatched High surrogates will still be silently removed, but Unmatched Low surrogates will pass through as-is now. Inspired by Kevin Kenny's remarks. Thanks! --- generic/tclUtf.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/generic/tclUtf.c b/generic/tclUtf.c index 923b1f8..ab4e142 100644 --- a/generic/tclUtf.c +++ b/generic/tclUtf.c @@ -148,15 +148,22 @@ Tcl_UniCharToUtf( if ((ch & 0xF800) == 0xD800) { if (ch & 0x0400) { /* Low surrogate */ - buf[3] = (char) ((ch | 0x80) & 0xBF); - buf[2] |= (char) (((ch >> 6) | 0x80) & 0x8F); - return 4; + if (((buf[0] & 0xF8) == 0xF0) && ((buf[1] & 0xC0) == 0x80) + && ((buf[2] & 0xCF) == 0)) { + /* Previous Tcl_UniChar was a High surrogate, so combine */ + buf[3] = (char) ((ch & 0x3F) | 0x80); + buf[2] |= (char) (((ch >> 6) & 0x0F) | 0x80); + return 4; + } + /* Previous Tcl_UniChar was not a High surrogate, so just output */ } else { /* High surrogate */ ch += 0x40; - buf[2] = (char) (((ch << 4) | 0x80) & 0xB0); - buf[1] = (char) (((ch >> 2) | 0x80) & 0xBF); - buf[0] = (char) (((ch >> 8) | 0xF0) & 0xF7); + /* Fill buffer with specific 3-byte (invalid) byte combination, + so following Low surrogate can recognize it and combine */ + buf[2] = (char) ((ch << 4) & 0x30); + buf[1] = (char) (((ch >> 2) & 0x3F) | 0x80); + buf[0] = (char) (((ch >> 8) & 0x07) | 0xF0); return 0; } } -- cgit v0.12 From 327595170bbc91997186ac34d44238537e330cd5 Mon Sep 17 00:00:00 2001 From: oehhar Date: Wed, 18 Apr 2018 11:59:57 +0000 Subject: http::geturl now returns full error stack information if the initial socket command fails Ticket [ff82755e15] --- library/http/http.tcl | 7 ++++--- library/http/pkgIndex.tcl | 2 +- unix/Makefile.in | 4 ++-- win/Makefile.in | 4 ++-- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/library/http/http.tcl b/library/http/http.tcl index 9f5310b..186d067 100644 --- a/library/http/http.tcl +++ b/library/http/http.tcl @@ -11,7 +11,7 @@ package require Tcl 8.6- # Keep this in sync with pkgIndex.tcl and with the install directories in # Makefiles -package provide http 2.8.12 +package provide http 2.8.13 namespace eval http { # Allow resourcing to not clobber existing data @@ -602,7 +602,7 @@ proc http::geturl {url args} { if {[info exists state(-myaddr)]} { lappend sockopts -myaddr $state(-myaddr) } - if {[catch {eval $defcmd $sockopts $targetAddr} sock]} { + if {[catch {eval $defcmd $sockopts $targetAddr} sock errdict]} { # something went wrong while trying to establish the connection. # Clean up after events and such, but DON'T call the command # callback (if available) because we're going to throw an @@ -611,7 +611,8 @@ proc http::geturl {url args} { set state(sock) $sock Finish $token "" 1 cleanup $token - return -code error $sock + dict unset errdict -level + return -options $errdict $sock } } set state(sock) $sock diff --git a/library/http/pkgIndex.tcl b/library/http/pkgIndex.tcl index d3fc7af..3324af9 100644 --- a/library/http/pkgIndex.tcl +++ b/library/http/pkgIndex.tcl @@ -1,2 +1,2 @@ if {![package vsatisfies [package provide Tcl] 8.6-]} {return} -package ifneeded http 2.8.12 [list tclPkgSetup $dir http 2.8.12 {{http.tcl source {::http::config ::http::formatQuery ::http::geturl ::http::reset ::http::wait ::http::register ::http::unregister ::http::mapReply}}}] +package ifneeded http 2.8.13 [list tclPkgSetup $dir http 2.8.13 {{http.tcl source {::http::config ::http::formatQuery ::http::geturl ::http::reset ::http::wait ::http::register ::http::unregister ::http::mapReply}}}] diff --git a/unix/Makefile.in b/unix/Makefile.in index 29c051d..4277fad 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -840,8 +840,8 @@ install-libraries: libraries do \ $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"/http1.0; \ done; - @echo "Installing package http 2.8.12 as a Tcl Module"; - @$(INSTALL_DATA) $(TOP_DIR)/library/http/http.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.6/http-2.8.12.tm; + @echo "Installing package http 2.8.13 as a Tcl Module"; + @$(INSTALL_DATA) $(TOP_DIR)/library/http/http.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.6/http-2.8.13.tm; @echo "Installing package opt0.4 files to $(SCRIPT_INSTALL_DIR)/opt0.4/"; @for i in $(TOP_DIR)/library/opt/*.tcl ; \ do \ diff --git a/win/Makefile.in b/win/Makefile.in index 633a9f5..f063da1 100644 --- a/win/Makefile.in +++ b/win/Makefile.in @@ -651,8 +651,8 @@ install-libraries: libraries install-tzdata install-msgs do \ $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/http1.0"; \ done; - @echo "Installing package http 2.8.12 as a Tcl Module"; - @$(COPY) $(ROOT_DIR)/library/http/http.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.6/http-2.8.12.tm; + @echo "Installing package http 2.8.13 as a Tcl Module"; + @$(COPY) $(ROOT_DIR)/library/http/http.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.6/http-2.8.13.tm; @echo "Installing library opt0.4 directory"; @for j in $(ROOT_DIR)/library/opt/*.tcl; \ do \ -- cgit v0.12 From fb91d4b68b081abb8ff689ed624a567c1a27a260 Mon Sep 17 00:00:00 2001 From: dgp Date: Wed, 18 Apr 2018 19:21:33 +0000 Subject: Refactor the common operations of looking up and checking traces on an array variable into a single routine LocateArray(). --- generic/tclVar.c | 152 +++++++++++++++---------------------------------------- 1 file changed, 41 insertions(+), 111 deletions(-) diff --git a/generic/tclVar.c b/generic/tclVar.c index e07d39a..a4cd62b 100644 --- a/generic/tclVar.c +++ b/generic/tclVar.c @@ -176,6 +176,8 @@ static void AppendLocals(Tcl_Interp *interp, Tcl_Obj *listPtr, static void DeleteSearches(Interp *iPtr, Var *arrayVarPtr); static void DeleteArray(Interp *iPtr, Tcl_Obj *arrayNamePtr, Var *varPtr, int flags, int index); +static int LocateArray(Tcl_Interp *interp, Tcl_Obj *name, + Var **varPtrPtr); static Tcl_Var ObjFindNamespaceVar(Tcl_Interp *interp, Tcl_Obj *namePtr, Tcl_Namespace *contextNsPtr, int flags); @@ -269,6 +271,22 @@ TclVarHashCreateVar( return varPtr; } + +static int +LocateArray( + Tcl_Interp *interp, + Tcl_Obj *name, + Var **varPtrPtr) +{ + Var *arrayPtr, *varPtr = TclObjLookupVarEx(interp, name, NULL, /*flags*/ 0, + /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); + + if (TclCheckArrayTraces(interp, varPtr, arrayPtr, name, -1) == TCL_ERROR) { + return TCL_ERROR; + } + *varPtrPtr = varPtr; + return TCL_OK; +} /* *---------------------------------------------------------------------- @@ -3122,7 +3140,7 @@ ArrayStartSearchCmd( Tcl_Obj *const objv[]) { Interp *iPtr = (Interp *)interp; - Var *varPtr, *arrayPtr; + Var *varPtr; Tcl_HashEntry *hPtr; Tcl_Obj *varNameObj; int isNew; @@ -3135,16 +3153,7 @@ ArrayStartSearchCmd( } varNameObj = objv[1]; - /* - * Locate the array variable. - */ - - varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, - /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); - varName = TclGetString(varNameObj); - - if (TclCheckArrayTraces(interp, varPtr, arrayPtr, varNameObj, -1) - == TCL_ERROR) { + if (TCL_ERROR == LocateArray(interp, varNameObj, &varPtr)) { return TCL_ERROR; } @@ -3154,6 +3163,7 @@ ArrayStartSearchCmd( * traces. */ + varName = TclGetString(varNameObj); if ((varPtr == NULL) || !TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( @@ -3211,7 +3221,7 @@ ArrayAnyMoreCmd( Tcl_Obj *const objv[]) { Interp *iPtr = (Interp *)interp; - Var *varPtr, *arrayPtr; + Var *varPtr; Tcl_Obj *varNameObj, *searchObj; int gotValue; ArraySearch *searchPtr; @@ -3223,15 +3233,7 @@ ArrayAnyMoreCmd( varNameObj = objv[1]; searchObj = objv[2]; - /* - * Locate the array variable. - */ - - varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, - /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); - - if (TclCheckArrayTraces(interp, varPtr, arrayPtr, varNameObj, -1) - == TCL_ERROR) { + if (TCL_ERROR == LocateArray(interp, varNameObj, &varPtr)) { return TCL_ERROR; } @@ -3308,7 +3310,7 @@ ArrayNextElementCmd( int objc, Tcl_Obj *const objv[]) { - Var *varPtr, *arrayPtr; + Var *varPtr; Tcl_Obj *varNameObj, *searchObj; ArraySearch *searchPtr; @@ -3319,15 +3321,7 @@ ArrayNextElementCmd( varNameObj = objv[1]; searchObj = objv[2]; - /* - * Locate the array variable. - */ - - varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, - /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); - - if (TclCheckArrayTraces(interp, varPtr, arrayPtr, varNameObj, -1) - == TCL_ERROR) { + if (TCL_ERROR == LocateArray(interp, varNameObj, &varPtr)) { return TCL_ERROR; } @@ -3408,7 +3402,7 @@ ArrayDoneSearchCmd( Tcl_Obj *const objv[]) { Interp *iPtr = (Interp *)interp; - Var *varPtr, *arrayPtr; + Var *varPtr; Tcl_HashEntry *hPtr; Tcl_Obj *varNameObj, *searchObj; ArraySearch *searchPtr, *prevPtr; @@ -3420,15 +3414,7 @@ ArrayDoneSearchCmd( varNameObj = objv[1]; searchObj = objv[2]; - /* - * Locate the array variable. - */ - - varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, - /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); - - if (TclCheckArrayTraces(interp, varPtr, arrayPtr, varNameObj, -1) - == TCL_ERROR) { + if (TCL_ERROR == LocateArray(interp, varNameObj, &varPtr)) { return TCL_ERROR; } @@ -3507,7 +3493,7 @@ ArrayExistsCmd( Tcl_Obj *const objv[]) { Interp *iPtr = (Interp *)interp; - Var *varPtr, *arrayPtr; + Var *varPtr; Tcl_Obj *arrayNameObj; int notArray; @@ -3517,15 +3503,7 @@ ArrayExistsCmd( } arrayNameObj = objv[1]; - /* - * Locate the array variable. - */ - - varPtr = TclObjLookupVarEx(interp, arrayNameObj, NULL, /*flags*/ 0, - /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); - - if (TclCheckArrayTraces(interp, varPtr, arrayPtr, arrayNameObj, -1) - == TCL_ERROR) { + if (TCL_ERROR == LocateArray(interp, arrayNameObj, &varPtr)) { return TCL_ERROR; } @@ -3564,7 +3542,7 @@ ArrayGetCmd( int objc, Tcl_Obj *const objv[]) { - Var *varPtr, *arrayPtr, *varPtr2; + Var *varPtr, *varPtr2; Tcl_Obj *varNameObj, *nameObj, *valueObj, *nameLstObj, *tmpResObj; Tcl_Obj **nameObjPtr, *patternObj; Tcl_HashSearch search; @@ -3585,15 +3563,7 @@ ArrayGetCmd( return TCL_ERROR; } - /* - * Locate the array variable. - */ - - varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, - /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); - - if (TclCheckArrayTraces(interp, varPtr, arrayPtr, varNameObj, -1) - == TCL_ERROR) { + if (TCL_ERROR == LocateArray(interp, varNameObj, &varPtr)) { return TCL_ERROR; } @@ -3742,7 +3712,7 @@ ArrayNamesCmd( "-exact", "-glob", "-regexp", NULL }; enum options { OPT_EXACT, OPT_GLOB, OPT_REGEXP }; - Var *varPtr, *arrayPtr, *varPtr2; + Var *varPtr, *varPtr2; Tcl_Obj *varNameObj, *nameObj, *resultObj, *patternObj; Tcl_HashSearch search; const char *pattern = NULL; @@ -3755,15 +3725,7 @@ ArrayNamesCmd( varNameObj = objv[1]; patternObj = (objc > 2 ? objv[objc-1] : NULL); - /* - * Locate the array variable. - */ - - varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, - /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); - - if (TclCheckArrayTraces(interp, varPtr, arrayPtr, varNameObj, -1) - == TCL_ERROR) { + if (TCL_ERROR == LocateArray(interp, varNameObj, &varPtr)) { return TCL_ERROR; } @@ -3920,22 +3882,14 @@ ArraySetCmd( int objc, Tcl_Obj *const objv[]) { - Var *varPtr, *arrayPtr; + Var *varPtr; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "arrayName list"); return TCL_ERROR; } - /* - * Locate the array variable. - */ - - varPtr = TclObjLookupVarEx(interp, objv[1], NULL, /*flags*/ 0, - /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); - - if (TclCheckArrayTraces(interp, varPtr, arrayPtr, objv[1], -1) - == TCL_ERROR) { + if (TCL_ERROR == LocateArray(interp, objv[1], &varPtr)) { return TCL_ERROR; } @@ -3967,7 +3921,7 @@ ArraySizeCmd( int objc, Tcl_Obj *const objv[]) { - Var *varPtr, *arrayPtr; + Var *varPtr; Tcl_Obj *varNameObj; Tcl_HashSearch search; Var *varPtr2; @@ -3979,15 +3933,7 @@ ArraySizeCmd( } varNameObj = objv[1]; - /* - * Locate the array variable. - */ - - varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, - /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); - - if (TclCheckArrayTraces(interp, varPtr, arrayPtr, varNameObj, -1) - == TCL_ERROR) { + if (TCL_ERROR == LocateArray(interp, varNameObj, &varPtr)) { return TCL_ERROR; } @@ -4041,7 +3987,7 @@ ArrayStatsCmd( int objc, Tcl_Obj *const objv[]) { - Var *varPtr, *arrayPtr; + Var *varPtr; Tcl_Obj *varNameObj; char *stats; @@ -4051,15 +3997,7 @@ ArrayStatsCmd( } varNameObj = objv[1]; - /* - * Locate the array variable. - */ - - varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, - /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); - - if (TclCheckArrayTraces(interp, varPtr, arrayPtr, varNameObj, -1) - == TCL_ERROR) { + if (TCL_ERROR == LocateArray(interp, varNameObj, &varPtr)) { return TCL_ERROR; } @@ -4114,7 +4052,7 @@ ArrayUnsetCmd( int objc, Tcl_Obj *const objv[]) { - Var *varPtr, *arrayPtr, *varPtr2, *protectedVarPtr; + Var *varPtr, *varPtr2, *protectedVarPtr; Tcl_Obj *varNameObj, *patternObj, *nameObj; Tcl_HashSearch search; const char *pattern; @@ -4134,15 +4072,7 @@ ArrayUnsetCmd( return TCL_ERROR; } - /* - * Locate the array variable - */ - - varPtr = TclObjLookupVarEx(interp, varNameObj, NULL, /*flags*/ 0, - /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); - - if (TclCheckArrayTraces(interp, varPtr, arrayPtr, varNameObj, -1) - == TCL_ERROR) { + if (TCL_ERROR == LocateArray(interp, varNameObj, &varPtr)) { return TCL_ERROR; } -- cgit v0.12 From 08c1a8dd343c7b9f2f21daf4b03894a3d28e1c47 Mon Sep 17 00:00:00 2001 From: dgp Date: Wed, 18 Apr 2018 21:03:53 +0000 Subject: cleanup of refactor --- generic/tclVar.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/generic/tclVar.c b/generic/tclVar.c index a4cd62b..d954f0a 100644 --- a/generic/tclVar.c +++ b/generic/tclVar.c @@ -3142,7 +3142,6 @@ ArrayStartSearchCmd( Interp *iPtr = (Interp *)interp; Var *varPtr; Tcl_HashEntry *hPtr; - Tcl_Obj *varNameObj; int isNew; ArraySearch *searchPtr; const char *varName; @@ -3151,9 +3150,8 @@ ArrayStartSearchCmd( Tcl_WrongNumArgs(interp, 1, objv, "arrayName"); return TCL_ERROR; } - varNameObj = objv[1]; - if (TCL_ERROR == LocateArray(interp, varNameObj, &varPtr)) { + if (TCL_ERROR == LocateArray(interp, objv[1], &varPtr)) { return TCL_ERROR; } @@ -3163,7 +3161,7 @@ ArrayStartSearchCmd( * traces. */ - varName = TclGetString(varNameObj); + varName = TclGetString(objv[1]); if ((varPtr == NULL) || !TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( @@ -3494,16 +3492,14 @@ ArrayExistsCmd( { Interp *iPtr = (Interp *)interp; Var *varPtr; - Tcl_Obj *arrayNameObj; int notArray; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "arrayName"); return TCL_ERROR; } - arrayNameObj = objv[1]; - if (TCL_ERROR == LocateArray(interp, arrayNameObj, &varPtr)) { + if (TCL_ERROR == LocateArray(interp, objv[1], &varPtr)) { return TCL_ERROR; } @@ -3713,7 +3709,7 @@ ArrayNamesCmd( }; enum options { OPT_EXACT, OPT_GLOB, OPT_REGEXP }; Var *varPtr, *varPtr2; - Tcl_Obj *varNameObj, *nameObj, *resultObj, *patternObj; + Tcl_Obj *nameObj, *resultObj, *patternObj; Tcl_HashSearch search; const char *pattern = NULL; int mode = OPT_GLOB; @@ -3722,10 +3718,9 @@ ArrayNamesCmd( Tcl_WrongNumArgs(interp, 1, objv, "arrayName ?mode? ?pattern?"); return TCL_ERROR; } - varNameObj = objv[1]; patternObj = (objc > 2 ? objv[objc-1] : NULL); - if (TCL_ERROR == LocateArray(interp, varNameObj, &varPtr)) { + if (TCL_ERROR == LocateArray(interp, objv[1], &varPtr)) { return TCL_ERROR; } @@ -3922,7 +3917,6 @@ ArraySizeCmd( Tcl_Obj *const objv[]) { Var *varPtr; - Tcl_Obj *varNameObj; Tcl_HashSearch search; Var *varPtr2; int size = 0; @@ -3931,9 +3925,8 @@ ArraySizeCmd( Tcl_WrongNumArgs(interp, 1, objv, "arrayName"); return TCL_ERROR; } - varNameObj = objv[1]; - if (TCL_ERROR == LocateArray(interp, varNameObj, &varPtr)) { + if (TCL_ERROR == LocateArray(interp, objv[1], &varPtr)) { return TCL_ERROR; } -- cgit v0.12 From 61f580bd36bb6b0f50e0d0735c1b72459434c8f5 Mon Sep 17 00:00:00 2001 From: dgp Date: Wed, 18 Apr 2018 23:31:07 +0000 Subject: Refactor to bring the test for existence of an array variable into LocateArray(). --- generic/tclVar.c | 132 +++++++++++++++++++------------------------------------ 1 file changed, 44 insertions(+), 88 deletions(-) diff --git a/generic/tclVar.c b/generic/tclVar.c index d954f0a..f1c8669 100644 --- a/generic/tclVar.c +++ b/generic/tclVar.c @@ -177,7 +177,7 @@ static void DeleteSearches(Interp *iPtr, Var *arrayVarPtr); static void DeleteArray(Interp *iPtr, Tcl_Obj *arrayNamePtr, Var *varPtr, int flags, int index); static int LocateArray(Tcl_Interp *interp, Tcl_Obj *name, - Var **varPtrPtr); + Var **varPtrPtr, int *isArrayPtr); static Tcl_Var ObjFindNamespaceVar(Tcl_Interp *interp, Tcl_Obj *namePtr, Tcl_Namespace *contextNsPtr, int flags); @@ -276,7 +276,8 @@ static int LocateArray( Tcl_Interp *interp, Tcl_Obj *name, - Var **varPtrPtr) + Var **varPtrPtr, + int *isArrayPtr) { Var *arrayPtr, *varPtr = TclObjLookupVarEx(interp, name, NULL, /*flags*/ 0, /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); @@ -284,7 +285,13 @@ LocateArray( if (TclCheckArrayTraces(interp, varPtr, arrayPtr, name, -1) == TCL_ERROR) { return TCL_ERROR; } - *varPtrPtr = varPtr; + if (varPtrPtr) { + *varPtrPtr = varPtr; + } + if (isArrayPtr) { + *isArrayPtr = varPtr && !TclIsVarUndefined(varPtr) + && TclIsVarArray(varPtr); + } return TCL_OK; } @@ -3142,7 +3149,7 @@ ArrayStartSearchCmd( Interp *iPtr = (Interp *)interp; Var *varPtr; Tcl_HashEntry *hPtr; - int isNew; + int isNew, isArray; ArraySearch *searchPtr; const char *varName; @@ -3151,19 +3158,12 @@ ArrayStartSearchCmd( return TCL_ERROR; } - if (TCL_ERROR == LocateArray(interp, objv[1], &varPtr)) { + if (TCL_ERROR == LocateArray(interp, objv[1], &varPtr, &isArray)) { return TCL_ERROR; } - /* - * Verify that it is indeed an array variable. This test comes after the - * traces - the variable may actually become an array as an effect of said - * traces. - */ - varName = TclGetString(objv[1]); - if ((varPtr == NULL) || !TclIsVarArray(varPtr) - || TclIsVarUndefined(varPtr)) { + if (!isArray) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" isn't an array", varName)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY", varName, NULL); @@ -3221,7 +3221,7 @@ ArrayAnyMoreCmd( Interp *iPtr = (Interp *)interp; Var *varPtr; Tcl_Obj *varNameObj, *searchObj; - int gotValue; + int gotValue, isArray; ArraySearch *searchPtr; if (objc != 3) { @@ -3231,18 +3231,11 @@ ArrayAnyMoreCmd( varNameObj = objv[1]; searchObj = objv[2]; - if (TCL_ERROR == LocateArray(interp, varNameObj, &varPtr)) { + if (TCL_ERROR == LocateArray(interp, varNameObj, &varPtr, &isArray)) { return TCL_ERROR; } - /* - * Verify that it is indeed an array variable. This test comes after the - * traces - the variable may actually become an array as an effect of said - * traces. - */ - - if ((varPtr == NULL) || !TclIsVarArray(varPtr) - || TclIsVarUndefined(varPtr)) { + if (!isArray) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" isn't an array", TclGetString(varNameObj))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY", @@ -3311,6 +3304,7 @@ ArrayNextElementCmd( Var *varPtr; Tcl_Obj *varNameObj, *searchObj; ArraySearch *searchPtr; + int isArray; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "arrayName searchId"); @@ -3319,7 +3313,7 @@ ArrayNextElementCmd( varNameObj = objv[1]; searchObj = objv[2]; - if (TCL_ERROR == LocateArray(interp, varNameObj, &varPtr)) { + if (TCL_ERROR == LocateArray(interp, varNameObj, &varPtr, &isArray)) { return TCL_ERROR; } @@ -3328,9 +3322,7 @@ ArrayNextElementCmd( * traces - the variable may actually become an array as an effect of said * traces. */ - - if ((varPtr == NULL) || !TclIsVarArray(varPtr) - || TclIsVarUndefined(varPtr)) { + if (!isArray) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" isn't an array", TclGetString(varNameObj))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY", @@ -3404,6 +3396,7 @@ ArrayDoneSearchCmd( Tcl_HashEntry *hPtr; Tcl_Obj *varNameObj, *searchObj; ArraySearch *searchPtr, *prevPtr; + int isArray; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "arrayName searchId"); @@ -3412,7 +3405,7 @@ ArrayDoneSearchCmd( varNameObj = objv[1]; searchObj = objv[2]; - if (TCL_ERROR == LocateArray(interp, varNameObj, &varPtr)) { + if (TCL_ERROR == LocateArray(interp, varNameObj, &varPtr, &isArray)) { return TCL_ERROR; } @@ -3422,8 +3415,7 @@ ArrayDoneSearchCmd( * traces. */ - if ((varPtr == NULL) || !TclIsVarArray(varPtr) - || TclIsVarUndefined(varPtr)) { + if (!isArray) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" isn't an array", TclGetString(varNameObj))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY", @@ -3491,25 +3483,18 @@ ArrayExistsCmd( Tcl_Obj *const objv[]) { Interp *iPtr = (Interp *)interp; - Var *varPtr; - int notArray; + int isArray; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "arrayName"); return TCL_ERROR; } - if (TCL_ERROR == LocateArray(interp, objv[1], &varPtr)) { + if (TCL_ERROR == LocateArray(interp, objv[1], NULL, &isArray)) { return TCL_ERROR; } - /* - * Check whether we've actually got an array variable. - */ - - notArray = ((varPtr == NULL) || !TclIsVarArray(varPtr) - || TclIsVarUndefined(varPtr)); - Tcl_SetObjResult(interp, iPtr->execEnvPtr->constants[!notArray]); + Tcl_SetObjResult(interp, iPtr->execEnvPtr->constants[isArray]); return TCL_OK; } @@ -3543,7 +3528,7 @@ ArrayGetCmd( Tcl_Obj **nameObjPtr, *patternObj; Tcl_HashSearch search; const char *pattern; - int i, count, result; + int i, count, result, isArray; switch (objc) { case 2: @@ -3559,18 +3544,12 @@ ArrayGetCmd( return TCL_ERROR; } - if (TCL_ERROR == LocateArray(interp, varNameObj, &varPtr)) { + if (TCL_ERROR == LocateArray(interp, varNameObj, &varPtr, &isArray)) { return TCL_ERROR; } - /* - * Verify that it is indeed an array variable. This test comes after the - * traces - the variable may actually become an array as an effect of said - * traces. If not an array, it's an empty result. - */ - - if ((varPtr == NULL) || !TclIsVarArray(varPtr) - || TclIsVarUndefined(varPtr)) { + /* If not an array, it's an empty result. */ + if (!isArray) { return TCL_OK; } @@ -3712,7 +3691,7 @@ ArrayNamesCmd( Tcl_Obj *nameObj, *resultObj, *patternObj; Tcl_HashSearch search; const char *pattern = NULL; - int mode = OPT_GLOB; + int isArray, mode = OPT_GLOB; if ((objc < 2) || (objc > 4)) { Tcl_WrongNumArgs(interp, 1, objv, "arrayName ?mode? ?pattern?"); @@ -3720,7 +3699,7 @@ ArrayNamesCmd( } patternObj = (objc > 2 ? objv[objc-1] : NULL); - if (TCL_ERROR == LocateArray(interp, objv[1], &varPtr)) { + if (TCL_ERROR == LocateArray(interp, objv[1], &varPtr, &isArray)) { return TCL_ERROR; } @@ -3733,14 +3712,9 @@ ArrayNamesCmd( return TCL_ERROR; } - /* - * Verify that it is indeed an array variable. This test comes after the - * traces - the variable may actually become an array as an effect of said - * traces. If not an array, the result is empty. - */ + /* If not an array, the result is empty. */ - if ((varPtr == NULL) || !TclIsVarArray(varPtr) - || TclIsVarUndefined(varPtr)) { + if (!isArray) { return TCL_OK; } @@ -3877,14 +3851,12 @@ ArraySetCmd( int objc, Tcl_Obj *const objv[]) { - Var *varPtr; - if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "arrayName list"); return TCL_ERROR; } - if (TCL_ERROR == LocateArray(interp, objv[1], &varPtr)) { + if (TCL_ERROR == LocateArray(interp, objv[1], NULL, NULL)) { return TCL_ERROR; } @@ -3919,24 +3891,20 @@ ArraySizeCmd( Var *varPtr; Tcl_HashSearch search; Var *varPtr2; - int size = 0; + int isArray, size = 0; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "arrayName"); return TCL_ERROR; } - if (TCL_ERROR == LocateArray(interp, objv[1], &varPtr)) { + if (TCL_ERROR == LocateArray(interp, objv[1], &varPtr, &isArray)) { return TCL_ERROR; } - /* - * Verify that it is indeed an array variable. This test comes after the - * traces - the variable may actually become an array as an effect of said - * traces. We can only iterate over the array if it exists... - */ + /* We can only iterate over the array if it exists... */ - if (varPtr && TclIsVarArray(varPtr) && !TclIsVarUndefined(varPtr)) { + if (isArray) { /* * Must iterate in order to get chance to check for present but * "undefined" entries. @@ -3983,6 +3951,7 @@ ArrayStatsCmd( Var *varPtr; Tcl_Obj *varNameObj; char *stats; + int isArray; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "arrayName"); @@ -3990,18 +3959,11 @@ ArrayStatsCmd( } varNameObj = objv[1]; - if (TCL_ERROR == LocateArray(interp, varNameObj, &varPtr)) { + if (TCL_ERROR == LocateArray(interp, varNameObj, &varPtr, &isArray)) { return TCL_ERROR; } - /* - * Verify that it is indeed an array variable. This test comes after the - * traces - the variable may actually become an array as an effect of said - * traces. - */ - - if ((varPtr == NULL) || !TclIsVarArray(varPtr) - || TclIsVarUndefined(varPtr)) { + if (!isArray) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "\"%s\" isn't an array", TclGetString(varNameObj))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY", @@ -4050,6 +4012,7 @@ ArrayUnsetCmd( Tcl_HashSearch search; const char *pattern; const int unsetFlags = 0; /* Should this be TCL_LEAVE_ERR_MSG? */ + int isArray; switch (objc) { case 2: @@ -4065,18 +4028,11 @@ ArrayUnsetCmd( return TCL_ERROR; } - if (TCL_ERROR == LocateArray(interp, varNameObj, &varPtr)) { + if (TCL_ERROR == LocateArray(interp, varNameObj, &varPtr, &isArray)) { return TCL_ERROR; } - /* - * Verify that it is indeed an array variable. This test comes after the - * traces - the variable may actually become an array as an effect of said - * traces. - */ - - if ((varPtr == NULL) || !TclIsVarArray(varPtr) - || TclIsVarUndefined(varPtr)) { + if (!isArray) { return TCL_OK; } -- cgit v0.12 From 8d0340e39e077c5577acacc1a175b5c412c8905b Mon Sep 17 00:00:00 2001 From: dgp Date: Wed, 18 Apr 2018 23:41:48 +0000 Subject: Refactor error reporting when value is not an expected array variable name. --- generic/tclVar.c | 56 ++++++++++++++++++++------------------------------------ 1 file changed, 20 insertions(+), 36 deletions(-) diff --git a/generic/tclVar.c b/generic/tclVar.c index f1c8669..92ae183 100644 --- a/generic/tclVar.c +++ b/generic/tclVar.c @@ -178,6 +178,7 @@ static void DeleteArray(Interp *iPtr, Tcl_Obj *arrayNamePtr, Var *varPtr, int flags, int index); static int LocateArray(Tcl_Interp *interp, Tcl_Obj *name, Var **varPtrPtr, int *isArrayPtr); +static int NotArrayError(Tcl_Interp *interp, Tcl_Obj *name); static Tcl_Var ObjFindNamespaceVar(Tcl_Interp *interp, Tcl_Obj *namePtr, Tcl_Namespace *contextNsPtr, int flags); @@ -294,6 +295,19 @@ LocateArray( } return TCL_OK; } + +static int +NotArrayError( + Tcl_Interp *interp, + Tcl_Obj *name) +{ + const char *nameStr = Tcl_GetString(name); + + Tcl_SetObjResult(interp, + Tcl_ObjPrintf("\"%s\" isn't an array", nameStr)); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY", nameStr, NULL); + return TCL_ERROR; +} /* *---------------------------------------------------------------------- @@ -3162,18 +3176,15 @@ ArrayStartSearchCmd( return TCL_ERROR; } - varName = TclGetString(objv[1]); if (!isArray) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "\"%s\" isn't an array", varName)); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY", varName, NULL); - return TCL_ERROR; + return NotArrayError(interp, objv[1]); } /* * Make a new array search with a free name. */ + varName = TclGetString(objv[1]); searchPtr = ckalloc(sizeof(ArraySearch)); hPtr = Tcl_CreateHashEntry(&iPtr->varSearches, varPtr, &isNew); if (isNew) { @@ -3236,11 +3247,7 @@ ArrayAnyMoreCmd( } if (!isArray) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "\"%s\" isn't an array", TclGetString(varNameObj))); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY", - TclGetString(varNameObj), NULL); - return TCL_ERROR; + return NotArrayError(interp, varNameObj); } /* @@ -3317,17 +3324,8 @@ ArrayNextElementCmd( return TCL_ERROR; } - /* - * Verify that it is indeed an array variable. This test comes after the - * traces - the variable may actually become an array as an effect of said - * traces. - */ if (!isArray) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "\"%s\" isn't an array", TclGetString(varNameObj))); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY", - TclGetString(varNameObj), NULL); - return TCL_ERROR; + return NotArrayError(interp, varNameObj); } /* @@ -3409,18 +3407,8 @@ ArrayDoneSearchCmd( return TCL_ERROR; } - /* - * Verify that it is indeed an array variable. This test comes after the - * traces - the variable may actually become an array as an effect of said - * traces. - */ - if (!isArray) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "\"%s\" isn't an array", TclGetString(varNameObj))); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY", - TclGetString(varNameObj), NULL); - return TCL_ERROR; + return NotArrayError(interp, varNameObj); } /* @@ -3964,11 +3952,7 @@ ArrayStatsCmd( } if (!isArray) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "\"%s\" isn't an array", TclGetString(varNameObj))); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY", - TclGetString(varNameObj), NULL); - return TCL_ERROR; + return NotArrayError(interp, varNameObj); } stats = Tcl_HashStats((Tcl_HashTable *) varPtr->value.tablePtr); -- cgit v0.12 From df94eecf119611a2fa8de1abb3abe59269be7550 Mon Sep 17 00:00:00 2001 From: dgp Date: Thu, 19 Apr 2018 01:39:38 +0000 Subject: An [array set] from a dict can only take shortcuts when the dict is "pure", that is, has no string rep. --- generic/tclVar.c | 2 +- tests/var.test | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/generic/tclVar.c b/generic/tclVar.c index e540c49..d4e5339 100644 --- a/generic/tclVar.c +++ b/generic/tclVar.c @@ -3411,7 +3411,7 @@ TclArraySet( * Install the contents of the dictionary or list into the array. */ - if (arrayElemObj->typePtr == &tclDictType) { + if (arrayElemObj->typePtr == &tclDictType && arrayElemObj->bytes == NULL) { Tcl_Obj *keyPtr, *valuePtr; Tcl_DictSearch search; int done; diff --git a/tests/var.test b/tests/var.test index 30e340e..aadeb34 100644 --- a/tests/var.test +++ b/tests/var.test @@ -761,6 +761,18 @@ test var-17.1 {TclArraySet [Bug 1669489]} -setup { } -cleanup { unset -nocomplain ::a ::elements } -result {} +test var-17.2 {TclArraySet Dict shortcut only on pure value} -setup { + unset -nocomplain a d + set d {p 1 p 2} + dict get $d p + set foo 0 +} -body { + trace add variable a write "[list incr [namespace which -variable foo]];#" + array set a $d + set foo +} -cleanup { + unset -nocomplain a d foo +} -result 2 test var-18.1 {array unset and unset traces: Bug 2939073} -setup { set already 0 -- cgit v0.12 From 75bd116527ce94efc1c14c6dc82c526614ed6c7f Mon Sep 17 00:00:00 2001 From: dgp Date: Thu, 19 Apr 2018 02:01:29 +0000 Subject: Fold TclArraySet() into its only caller. tclEnv.c no longer calls it --- generic/tclInt.h | 2 - generic/tclVar.c | 311 +++++++++++++++++++++++++------------------------------ 2 files changed, 141 insertions(+), 172 deletions(-) diff --git a/generic/tclInt.h b/generic/tclInt.h index 371e3fa..4db4576 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -2864,8 +2864,6 @@ MODULE_SCOPE void TclArgumentBCRelease(Tcl_Interp *interp, CmdFrame *cfPtr); MODULE_SCOPE void TclArgumentGet(Tcl_Interp *interp, Tcl_Obj *obj, CmdFrame **cfPtrPtr, int *wordPtr); -MODULE_SCOPE int TclArraySet(Tcl_Interp *interp, - Tcl_Obj *arrayNameObj, Tcl_Obj *arrayElemObj); MODULE_SCOPE double TclBignumToDouble(const mp_int *bignum); MODULE_SCOPE int TclByteArrayMatch(const unsigned char *string, int strLen, const unsigned char *pattern, diff --git a/generic/tclVar.c b/generic/tclVar.c index 84f2d7b..c4952be 100644 --- a/generic/tclVar.c +++ b/generic/tclVar.c @@ -2968,175 +2968,6 @@ Tcl_LappendObjCmd( /* *---------------------------------------------------------------------- * - * TclArraySet -- - * - * Set the elements of an array. If there are no elements to set, create - * an empty array. This routine is used by the Tcl_ArrayObjCmd and by the - * TclSetupEnv routine. - * - * Results: - * A standard Tcl result object. - * - * Side effects: - * A variable will be created if one does not already exist. - * Callers must Incr arrayNameObj if they pland to Decr it. - * - *---------------------------------------------------------------------- - */ - -int -TclArraySet( - Tcl_Interp *interp, /* Current interpreter. */ - Tcl_Obj *arrayNameObj, /* The array name. */ - Tcl_Obj *arrayElemObj) /* The array elements list or dict. If this is - * NULL, create an empty array. */ -{ - Var *varPtr, *arrayPtr; - int result, i; - - varPtr = TclObjLookupVarEx(interp, arrayNameObj, NULL, - /*flags*/ TCL_LEAVE_ERR_MSG, /*msg*/ "set", /*createPart1*/ 1, - /*createPart2*/ 1, &arrayPtr); - if (varPtr == NULL) { - return TCL_ERROR; - } - if (arrayPtr) { - CleanupVar(varPtr, arrayPtr); - TclObjVarErrMsg(interp, arrayNameObj, NULL, "set", needArray, -1); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", - TclGetString(arrayNameObj), NULL); - return TCL_ERROR; - } - - if (arrayElemObj == NULL) { - goto ensureArray; - } - - /* - * Install the contents of the dictionary or list into the array. - */ - - if (arrayElemObj->typePtr == &tclDictType && arrayElemObj->bytes == NULL) { - Tcl_Obj *keyPtr, *valuePtr; - Tcl_DictSearch search; - int done; - - if (Tcl_DictObjSize(interp, arrayElemObj, &done) != TCL_OK) { - return TCL_ERROR; - } - if (done == 0) { - /* - * Empty, so we'll just force the array to be properly existing - * instead. - */ - - goto ensureArray; - } - - /* - * Don't need to look at result of Tcl_DictObjFirst as we've just - * successfully used a dictionary operation on the same object. - */ - - for (Tcl_DictObjFirst(interp, arrayElemObj, &search, - &keyPtr, &valuePtr, &done) ; !done ; - Tcl_DictObjNext(&search, &keyPtr, &valuePtr, &done)) { - /* - * At this point, it would be nice if the key was directly usable - * by the array. This isn't the case though. - */ - - Var *elemVarPtr = TclLookupArrayElement(interp, arrayNameObj, - keyPtr, TCL_LEAVE_ERR_MSG, "set", 1, 1, varPtr, -1); - - if ((elemVarPtr == NULL) || - (TclPtrSetVarIdx(interp, elemVarPtr, varPtr, arrayNameObj, - keyPtr, valuePtr, TCL_LEAVE_ERR_MSG, -1) == NULL)) { - Tcl_DictObjDone(&search); - return TCL_ERROR; - } - } - return TCL_OK; - } else { - /* - * Not a dictionary, so assume (and convert to, for backward- - * -compatibility reasons) a list. - */ - - int elemLen; - Tcl_Obj **elemPtrs, *copyListObj; - - result = TclListObjGetElements(interp, arrayElemObj, - &elemLen, &elemPtrs); - if (result != TCL_OK) { - return result; - } - if (elemLen & 1) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "list must have an even number of elements", -1)); - Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "FORMAT", NULL); - return TCL_ERROR; - } - if (elemLen == 0) { - goto ensureArray; - } - - /* - * We needn't worry about traces invalidating arrayPtr: should that be - * the case, TclPtrSetVarIdx will return NULL so that we break out of - * the loop and return an error. - */ - - copyListObj = TclListObjCopy(NULL, arrayElemObj); - for (i=0 ; ivalue.tablePtr = ckalloc(sizeof(TclVarHashTable)); - TclInitVarHashTable(varPtr->value.tablePtr, TclGetVarNsPtr(varPtr)); - return TCL_OK; -} - -/* - *---------------------------------------------------------------------- - * * ArrayStartSearchCmd -- * * This object-based function is invoked to process the "array @@ -3839,6 +3670,11 @@ ArraySetCmd( int objc, Tcl_Obj *const objv[]) { + Tcl_Obj *arrayNameObj; + Tcl_Obj *arrayElemObj; + Var *varPtr, *arrayPtr; + int result, i; + if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "arrayName list"); return TCL_ERROR; @@ -3848,7 +3684,142 @@ ArraySetCmd( return TCL_ERROR; } - return TclArraySet(interp, objv[1], objv[2]); + arrayNameObj = objv[1]; + varPtr = TclObjLookupVarEx(interp, arrayNameObj, NULL, + /*flags*/ TCL_LEAVE_ERR_MSG, /*msg*/ "set", /*createPart1*/ 1, + /*createPart2*/ 1, &arrayPtr); + if (varPtr == NULL) { + return TCL_ERROR; + } + if (arrayPtr) { + CleanupVar(varPtr, arrayPtr); + TclObjVarErrMsg(interp, arrayNameObj, NULL, "set", needArray, -1); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", + TclGetString(arrayNameObj), NULL); + return TCL_ERROR; + } + + /* + * Install the contents of the dictionary or list into the array. + */ + + arrayElemObj = objv[2]; + if (arrayElemObj->typePtr == &tclDictType && arrayElemObj->bytes == NULL) { + Tcl_Obj *keyPtr, *valuePtr; + Tcl_DictSearch search; + int done; + + if (Tcl_DictObjSize(interp, arrayElemObj, &done) != TCL_OK) { + return TCL_ERROR; + } + if (done == 0) { + /* + * Empty, so we'll just force the array to be properly existing + * instead. + */ + + goto ensureArray; + } + + /* + * Don't need to look at result of Tcl_DictObjFirst as we've just + * successfully used a dictionary operation on the same object. + */ + + for (Tcl_DictObjFirst(interp, arrayElemObj, &search, + &keyPtr, &valuePtr, &done) ; !done ; + Tcl_DictObjNext(&search, &keyPtr, &valuePtr, &done)) { + /* + * At this point, it would be nice if the key was directly usable + * by the array. This isn't the case though. + */ + + Var *elemVarPtr = TclLookupArrayElement(interp, arrayNameObj, + keyPtr, TCL_LEAVE_ERR_MSG, "set", 1, 1, varPtr, -1); + + if ((elemVarPtr == NULL) || + (TclPtrSetVarIdx(interp, elemVarPtr, varPtr, arrayNameObj, + keyPtr, valuePtr, TCL_LEAVE_ERR_MSG, -1) == NULL)) { + Tcl_DictObjDone(&search); + return TCL_ERROR; + } + } + return TCL_OK; + } else { + /* + * Not a dictionary, so assume (and convert to, for backward- + * -compatibility reasons) a list. + */ + + int elemLen; + Tcl_Obj **elemPtrs, *copyListObj; + + result = TclListObjGetElements(interp, arrayElemObj, + &elemLen, &elemPtrs); + if (result != TCL_OK) { + return result; + } + if (elemLen & 1) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "list must have an even number of elements", -1)); + Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "FORMAT", NULL); + return TCL_ERROR; + } + if (elemLen == 0) { + goto ensureArray; + } + + /* + * We needn't worry about traces invalidating arrayPtr: should that be + * the case, TclPtrSetVarIdx will return NULL so that we break out of + * the loop and return an error. + */ + + copyListObj = TclListObjCopy(NULL, arrayElemObj); + for (i=0 ; ivalue.tablePtr = ckalloc(sizeof(TclVarHashTable)); + TclInitVarHashTable(varPtr->value.tablePtr, TclGetVarNsPtr(varPtr)); + return TCL_OK; } /* -- cgit v0.12 From ddb7bbe66c5b805d02fc11f55c53e909e1af45ac Mon Sep 17 00:00:00 2001 From: oehhar Date: Thu, 19 Apr 2018 11:48:28 +0000 Subject: correct msgcat test numbering for section util from 15.x (used twice) to 18.x --- tests/msgcat.test | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/msgcat.test b/tests/msgcat.test index d38152b..12030fb 100644 --- a/tests/msgcat.test +++ b/tests/msgcat.test @@ -1317,33 +1317,33 @@ if {[package vsatisfies [package provide msgcat] 1.7]} { interp bgerror {} $bgerrorsaved - # Tests msgcat-15.*: [mcutil] + # Tests msgcat-18.*: [mcutil] - test msgcat-15.5 {mcutil - no argument} -body { + test msgcat-18.1 {mcutil - no argument} -body { mcutil } -returnCodes 1\ -result {wrong # args: should be "mcutil subcommand ?arg ...?"} - test msgcat-15.6 {mcutil - wrong argument} -body { + test msgcat-18.2 {mcutil - wrong argument} -body { mcutil junk } -returnCodes 1\ -result {unknown subcommand "junk": must be getpreferences, or getsystemlocale} - test msgcat-15.7 {mcutil - partial argument} -body { + test msgcat-18.3 {mcutil - partial argument} -body { mcutil getsystem } -returnCodes 1\ -result {unknown subcommand "getsystem": must be getpreferences, or getsystemlocale} - test msgcat-15.8 {mcutil getpreferences - no argument} -body { + test msgcat-18.4 {mcutil getpreferences - no argument} -body { mcutil getpreferences } -returnCodes 1\ -result {wrong # args: should be "mcutil getpreferences locale"} - test msgcat-15.9 {mcutil getpreferences - DE_de} -body { + test msgcat-18.5 {mcutil getpreferences - DE_de} -body { mcutil getpreferences DE_de } -result {de_de de {}} - test msgcat-15.10 {mcutil getsystemlocale - wrong argument} -body { + test msgcat-18.6 {mcutil getsystemlocale - wrong argument} -body { mcutil getsystemlocale DE_de } -returnCodes 1\ -result {wrong # args: should be "mcutil getsystemlocale"} @@ -1351,7 +1351,7 @@ if {[package vsatisfies [package provide msgcat] 1.7]} { # The result is system dependent # So just test if it runs # The environment variable version was test with test 0.x - test msgcat-15.11 {mcutil getsystemlocale} -body { + test msgcat-18.7 {mcutil getsystemlocale} -body { mcutil getsystemlocale set ok ok } -result {ok} -- cgit v0.12 From 5c2ea0542f62da981d08766756c2e421db40955c Mon Sep 17 00:00:00 2001 From: dgp Date: Thu, 19 Apr 2018 17:46:37 +0000 Subject: Adapt [array for] to use the refactored routines. --- generic/tclVar.c | 42 +++++------------------------------------- 1 file changed, 5 insertions(+), 37 deletions(-) diff --git a/generic/tclVar.c b/generic/tclVar.c index 7a71990..51eec61 100644 --- a/generic/tclVar.c +++ b/generic/tclVar.c @@ -3043,12 +3043,10 @@ ArrayForNRCmd( int objc, Tcl_Obj *const *objv) { - Interp *iPtr = (Interp *) interp; Tcl_Obj *varListObj, *arrayNameObj, *scriptObj; ArraySearch *searchPtr = NULL; Var *varPtr; - Var *arrayPtr; - int numVars; + int isArray, numVars; /* * array for {k v} a body @@ -3064,7 +3062,6 @@ ArrayForNRCmd( * Parse arguments. */ - if (Tcl_ListObjLength(interp, objv[1], &numVars) != TCL_OK) { return TCL_ERROR; } @@ -3078,41 +3075,12 @@ ArrayForNRCmd( arrayNameObj = objv[2]; - /* - * Locate the array variable. - */ - - varPtr = TclObjLookupVarEx(interp, arrayNameObj, NULL, /*flags*/ 0, - /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); - - /* - * Special array trace used to keep the env array in sync for array names, - * array get, etc. - */ - - if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) - && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { - if (TclObjCallVarTraces(iPtr, arrayPtr, varPtr, arrayNameObj, NULL, - (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY|TCL_GLOBAL_ONLY| - TCL_TRACE_ARRAY), /* leaveErrMsg */ 1, -1) == TCL_ERROR) { - return TCL_ERROR; - } + if (TCL_ERROR == LocateArray(interp, arrayNameObj, &varPtr, &isArray)) { + return TCL_ERROR; } - /* - * Verify that it is indeed an array variable. This test comes after the - * traces; the variable may actually become an array as an effect of said - * traces. - */ - - if ((varPtr == NULL) || !TclIsVarArray(varPtr) - || TclIsVarUndefined(varPtr)) { - const char *varName = Tcl_GetString(arrayNameObj); - - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "\"%s\" isn't an array", varName)); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ARRAY", varName, NULL); - return TCL_ERROR; + if (!isArray) { + return NotArrayError(interp, arrayNameObj); } /* -- cgit v0.12 From 1734eed89f76598661a4ce4c7d5e43ce7fe4368c Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 19 Apr 2018 22:29:00 +0000 Subject: Slightly improved (more fail-safe) surrogate handling for TCL_UTF_MAX>3. Backported from latest TIP 389 implementation. (to be used for androwish) --- generic/tclUtf.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/generic/tclUtf.c b/generic/tclUtf.c index 6255a4e..0d88d36 100644 --- a/generic/tclUtf.c +++ b/generic/tclUtf.c @@ -154,19 +154,26 @@ Tcl_UniCharToUtf( return 2; } if (ch <= 0xFFFF) { -#if TCL_UTF_MAX == 4 +#if TCL_UTF_MAX > 3 if ((ch & 0xF800) == 0xD800) { if (ch & 0x0400) { /* Low surrogate */ - buf[3] = (char) ((ch | 0x80) & 0xBF); - buf[2] |= (char) (((ch >> 6) | 0x80) & 0x8F); - return 4; + if (((buf[0] & 0xF8) == 0xF0) && ((buf[1] & 0xC0) == 0x80) + && ((buf[2] & 0xCF) == 0)) { + /* Previous Tcl_UniChar was a High surrogate, so combine */ + buf[3] = (char) ((ch & 0x3F) | 0x80); + buf[2] |= (char) (((ch >> 6) & 0x0F) | 0x80); + return 4; + } + /* Previous Tcl_UniChar was not a High surrogate, so just output */ } else { /* High surrogate */ ch += 0x40; - buf[2] = (char) (((ch << 4) | 0x80) & 0xB0); - buf[1] = (char) (((ch >> 2) | 0x80) & 0xBF); - buf[0] = (char) (((ch >> 8) | 0xF0) & 0xF7); + /* Fill buffer with specific 3-byte (invalid) byte combination, + so following Low surrogate can recognize it and combine */ + buf[2] = (char) ((ch << 4) & 0x30); + buf[1] = (char) (((ch >> 2) & 0x3F) | 0x80); + buf[0] = (char) (((ch >> 8) & 0x07) | 0xF0); return 0; } } -- cgit v0.12 From ae76fbd559e8e30a6cb4c448bf4c924cbd79841b Mon Sep 17 00:00:00 2001 From: dgp Date: Fri, 20 Apr 2018 20:17:17 +0000 Subject: DeleteArray has only one caller. It is called on the "dummy" variable that is created during unset, and which cannot be reached by resolving any name. It cannot have VAR_SEARCH_ACTIVE set because the sole thing that sets that flag is an [array startsearch] applied to a named variable. --- generic/tclVar.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/generic/tclVar.c b/generic/tclVar.c index c4952be..ed16c9f 100644 --- a/generic/tclVar.c +++ b/generic/tclVar.c @@ -5324,9 +5324,6 @@ DeleteArray( Tcl_Obj *objPtr; VarTrace *tracePtr; - if (varPtr->flags & VAR_SEARCH_ACTIVE) { - DeleteSearches(iPtr, varPtr); - } for (elPtr = VarHashFirstVar(varPtr->value.tablePtr, &search); elPtr != NULL; elPtr = VarHashNextVar(&search)) { if (TclIsVarScalar(elPtr) && (elPtr->value.objPtr != NULL)) { -- cgit v0.12 From 8e06fd796be19c40e0e82a7d9c9e54d34e975504 Mon Sep 17 00:00:00 2001 From: dgp Date: Sun, 22 Apr 2018 13:22:20 +0000 Subject: [46a2410650] compiled [unset] was bypassing cleanup of active array search. Overdue thanks to Andy Goth for tests and report. --- generic/tclExecute.c | 3 ++- tests/var.test | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 5bc5c2d..af44323 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -4169,7 +4169,8 @@ TEBCresume( } TRACE(("%s %u \"%.30s\" => ", (flags ? "normal" : "noerr"), opnd, O2S(part2Ptr))); - if (TclIsVarArray(arrayPtr) && !UnsetTraced(arrayPtr)) { + if (TclIsVarArray(arrayPtr) && !UnsetTraced(arrayPtr) + && !(arrayPtr->flags & VAR_SEARCH_ACTIVE)) { varPtr = VarHashFindVar(arrayPtr->value.tablePtr, part2Ptr); if (varPtr && TclIsVarDirectUnsettable(varPtr)) { /* diff --git a/tests/var.test b/tests/var.test index b235e5d..8d86fce 100644 --- a/tests/var.test +++ b/tests/var.test @@ -776,6 +776,22 @@ 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 -- cgit v0.12 From 95f246935924442788522c93b95723eeef602e77 Mon Sep 17 00:00:00 2001 From: bll Date: Mon, 23 Apr 2018 12:58:41 +0000 Subject: Rework 'array for' to pass the arrayNameObj to the NRE routines rather than saving it in the ArraySearch structure (which will not work). Create ArrayPopulateSearch to consolidate duplicate code. --- generic/tclVar.c | 114 ++++++++++++++++++++++++------------------------------- 1 file changed, 49 insertions(+), 65 deletions(-) diff --git a/generic/tclVar.c b/generic/tclVar.c index 889e6ba..f22815c 100644 --- a/generic/tclVar.c +++ b/generic/tclVar.c @@ -166,7 +166,6 @@ typedef struct ArraySearch { struct ArraySearch *nextPtr;/* Next in list of all active searches for * this variable, or NULL if this is the last * one. */ - Tcl_Obj *arrayNameObj; /* name of the array object */ } ArraySearch; /* @@ -175,6 +174,7 @@ typedef struct ArraySearch { static void AppendLocals(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *patternPtr, int includeLinks); +static void ArrayPopulateSearch(Tcl_Interp *interp, Tcl_Obj *arrayNameObj, Var *varPtr, ArraySearch *searchPtr); static void ArrayDoneSearch (Interp *iPtr, Var *varPtr, ArraySearch *searchPtr); static Tcl_NRPostProc ArrayForLoopCallback; static int ArrayForNRCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); @@ -2912,7 +2912,6 @@ Tcl_LappendObjCmd( * ArrayForObjCmd * ArrayForNRCmd * ArrayForLoopCallback - * ArrayObjFirst * ArrayObjNext * * These functions implement the "array for" Tcl command. @@ -2932,46 +2931,13 @@ Tcl_LappendObjCmd( * ArrayForLoopCallback() iterates over the entire array, executing * the body each time. * - * ArrayObjFirst() Does not execute the body or set the key/value variables. - * *---------------------------------------------------------------------- */ -void -ArrayObjFirst( - Tcl_Interp *interp, - Tcl_Obj *arrayNameObj, - Var *varPtr, - ArraySearch *searchPtr) -{ - Interp *iPtr = (Interp *) interp; - Tcl_HashEntry *hPtr; - int isNew; - - /* this code is duplicated from arraystartsearchcmd, - excepting that arrayNameObj is set */ - searchPtr->varPtr = varPtr; - searchPtr->arrayNameObj = arrayNameObj; - - /* add the search to the search table */ - hPtr = Tcl_CreateHashEntry(&iPtr->varSearches, varPtr, &isNew); - if (isNew) { - searchPtr->id = 1; - varPtr->flags |= VAR_SEARCH_ACTIVE; - searchPtr->nextPtr = NULL; - } else { - searchPtr->id = ((ArraySearch *) Tcl_GetHashValue(hPtr))->id + 1; - searchPtr->nextPtr = Tcl_GetHashValue(hPtr); - } - searchPtr->nextEntry = VarHashFirstEntry(varPtr->value.tablePtr, - &searchPtr->search); - Tcl_SetHashValue(hPtr, searchPtr); - searchPtr->name = Tcl_ObjPrintf("s-%d-%s", searchPtr->id, TclGetString(arrayNameObj)); - Tcl_IncrRefCount(searchPtr->name); -} -int +static int ArrayObjNext( Tcl_Interp *interp, + Tcl_Obj *arrayNameObj, /* array */ Var *varPtr, /* array */ ArraySearch *searchPtr, Tcl_Obj **keyPtrPtr, /* Pointer to a variable to have the key @@ -3019,7 +2985,7 @@ ArrayObjNext( keyObj = VarHashGetKey(varPtr); *keyPtrPtr = keyObj; - valueObj = Tcl_ObjGetVar2(interp, searchPtr->arrayNameObj, + valueObj = Tcl_ObjGetVar2(interp, arrayNameObj, keyObj, TCL_LEAVE_ERR_MSG); *valuePtrPtr = valueObj; @@ -3088,8 +3054,7 @@ ArrayForNRCmd( */ searchPtr = ckalloc(sizeof(ArraySearch)); - searchPtr->arrayNameObj = NULL; - ArrayObjFirst(interp, arrayNameObj, varPtr, searchPtr); + ArrayPopulateSearch (interp, arrayNameObj, varPtr, searchPtr); /* * Make sure that these objects (which we need throughout the body of the @@ -3105,7 +3070,7 @@ ArrayForNRCmd( */ TclNRAddCallback(interp, ArrayForLoopCallback, searchPtr, varListObj, - NULL, scriptObj); + arrayNameObj, scriptObj); return TCL_OK; } @@ -3118,6 +3083,7 @@ ArrayForLoopCallback( Interp *iPtr = (Interp *) interp; ArraySearch *searchPtr = data[0]; Tcl_Obj *varListObj = data[1]; + Tcl_Obj *arrayNameObj = data[2]; Tcl_Obj *scriptObj = data[3]; Tcl_Obj **varv; Tcl_Obj *keyObj, *valueObj; @@ -3130,8 +3096,6 @@ ArrayForLoopCallback( */ done = TCL_ERROR; - varPtr = TclObjLookupVarEx(interp, searchPtr->arrayNameObj, NULL, /*flags*/ 0, - /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); if (result == TCL_CONTINUE) { result = TCL_OK; @@ -3153,7 +3117,14 @@ ArrayForLoopCallback( keyObj = NULL; valueObj = NULL; - done = ArrayObjNext (interp, varPtr, searchPtr, &keyObj, &valueObj); + varPtr = TclObjLookupVarEx(interp, arrayNameObj, NULL, /*flags*/ 0, + /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); + if (varPtr == NULL) { + done = TCL_ERROR; + } else { + done = ArrayObjNext (interp, arrayNameObj, varPtr, + searchPtr, &keyObj, &valueObj); + } result = TCL_OK; if (done != TCL_CONTINUE) { @@ -3185,7 +3156,7 @@ ArrayForLoopCallback( */ TclNRAddCallback(interp, ArrayForLoopCallback, searchPtr, varListObj, - NULL, scriptObj); + arrayNameObj, scriptObj); return TclNREvalObjEx(interp, scriptObj, 0, iPtr->cmdFramePtr, 3); /* @@ -3208,6 +3179,37 @@ ArrayForLoopCallback( } /* + * ArrayPopulateSearch + */ +static void +ArrayPopulateSearch( + Tcl_Interp *interp, + Tcl_Obj *arrayNameObj, + Var *varPtr, + ArraySearch *searchPtr) +{ + Interp *iPtr = (Interp *)interp; + Tcl_HashEntry *hPtr; + int isNew; + + hPtr = Tcl_CreateHashEntry(&iPtr->varSearches, varPtr, &isNew); + if (isNew) { + searchPtr->id = 1; + varPtr->flags |= VAR_SEARCH_ACTIVE; + searchPtr->nextPtr = NULL; + } else { + searchPtr->id = ((ArraySearch *) Tcl_GetHashValue(hPtr))->id + 1; + searchPtr->nextPtr = Tcl_GetHashValue(hPtr); + } + searchPtr->varPtr = varPtr; + searchPtr->nextEntry = VarHashFirstEntry(varPtr->value.tablePtr, + &searchPtr->search); + Tcl_SetHashValue(hPtr, searchPtr); + searchPtr->name = Tcl_ObjPrintf("s-%d-%s", searchPtr->id, + TclGetString(arrayNameObj)); + Tcl_IncrRefCount(searchPtr->name); +} +/* *---------------------------------------------------------------------- * * ArrayStartSearchCmd -- @@ -3234,12 +3236,9 @@ ArrayStartSearchCmd( int objc, Tcl_Obj *const objv[]) { - Interp *iPtr = (Interp *)interp; Var *varPtr; - Tcl_HashEntry *hPtr; - int isNew, isArray; + int isArray; ArraySearch *searchPtr; - const char *varName; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "arrayName"); @@ -3258,23 +3257,8 @@ ArrayStartSearchCmd( * Make a new array search with a free name. */ - varName = TclGetString(objv[1]); searchPtr = ckalloc(sizeof(ArraySearch)); - hPtr = Tcl_CreateHashEntry(&iPtr->varSearches, varPtr, &isNew); - if (isNew) { - searchPtr->id = 1; - varPtr->flags |= VAR_SEARCH_ACTIVE; - searchPtr->nextPtr = NULL; - } else { - searchPtr->id = ((ArraySearch *) Tcl_GetHashValue(hPtr))->id + 1; - searchPtr->nextPtr = Tcl_GetHashValue(hPtr); - } - searchPtr->varPtr = varPtr; - searchPtr->nextEntry = VarHashFirstEntry(varPtr->value.tablePtr, - &searchPtr->search); - Tcl_SetHashValue(hPtr, searchPtr); - searchPtr->name = Tcl_ObjPrintf("s-%d-%s", searchPtr->id, TclGetString(objv[1])); - Tcl_IncrRefCount(searchPtr->name); + ArrayPopulateSearch (interp, objv[1], varPtr, searchPtr); Tcl_SetObjResult(interp, searchPtr->name); return TCL_OK; } -- cgit v0.12 From 523d6ea42c58bae3ffe912865264036fd8d1b311 Mon Sep 17 00:00:00 2001 From: dgp Date: Mon, 23 Apr 2018 13:51:05 +0000 Subject: Dup test name. --- tests/string.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/string.test b/tests/string.test index 2300f08..35b6880 100644 --- a/tests/string.test +++ b/tests/string.test @@ -487,7 +487,7 @@ test string-5.19.$noComp {string index, bytearray object out of bounds} { test string-5.20.$noComp {string index, bytearray object out of bounds} { run {string index [binary format I* {0x50515253 0x52}] 20} } {} -test string-5.21 {string index, surrogates, bug [11ae2be95dac9417]} fullutf { +test string-5.21.$noComp {string index, surrogates, bug [11ae2be95dac9417]} fullutf { list [string index a\U100000b 1] [string index a\U100000b 2] [string index a\U100000b 3] } [list \U100000 {} b] -- cgit v0.12 From 9acb063268f48f19e3c67a877f2c83e15fd1019d Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 23 Apr 2018 14:56:44 +0000 Subject: Add some state to encodings, so we can do better surrogate handling for TCL_UTF_MAX >= 4. Backported from TIP #389. --- generic/tclEncoding.c | 79 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 26 deletions(-) diff --git a/generic/tclEncoding.c b/generic/tclEncoding.c index 2548b73..6b440e7 100644 --- a/generic/tclEncoding.c +++ b/generic/tclEncoding.c @@ -2296,8 +2296,11 @@ UtfToUtfProc( const char *srcStart, *srcEnd, *srcClose; const char *dstStart, *dstEnd; int result, numChars, charLimit = INT_MAX; - Tcl_UniChar ch = 0; + Tcl_UniChar *chPtr = (Tcl_UniChar *) statePtr; + if (flags & TCL_ENCODING_START) { + *statePtr = 0; + } result = TCL_OK; srcStart = src; @@ -2349,12 +2352,19 @@ UtfToUtfProc( * incomplete char its bytes are made to represent themselves. */ - ch = (unsigned char) *src; + *chPtr = (unsigned char) *src; src += 1; - dst += Tcl_UniCharToUtf(ch, dst); + dst += Tcl_UniCharToUtf(*chPtr, dst); } else { - src += TclUtfToUniChar(src, &ch); - dst += Tcl_UniCharToUtf(ch, dst); + int len = TclUtfToUniChar(src, chPtr); + src += len; + dst += Tcl_UniCharToUtf(*chPtr, dst); +#if TCL_UTF_MAX == 4 + if (!len) { + src += TclUtfToUniChar(src, chPtr); + dst += Tcl_UniCharToUtf(*chPtr, dst); + } +#endif } } @@ -2410,8 +2420,11 @@ UnicodeToUtfProc( const char *srcStart, *srcEnd; const char *dstEnd, *dstStart; int result, numChars, charLimit = INT_MAX; - Tcl_UniChar ch = 0; + Tcl_UniChar *chPtr = (Tcl_UniChar *) statePtr; + if (flags & TCL_ENCODING_START) { + *statePtr = 0; + } if (flags & TCL_ENCODING_CHAR_LIMIT) { charLimit = *dstCharsPtr; } @@ -2439,11 +2452,11 @@ UnicodeToUtfProc( * Tcl_UniChar-size data. */ - ch = *(Tcl_UniChar *)src; - if (ch && ch < 0x80) { - *dst++ = (ch & 0xFF); + *chPtr = *(Tcl_UniChar *)src; + if (*chPtr && *chPtr < 0x80) { + *dst++ = (*chPtr & 0xFF); } else { - dst += Tcl_UniCharToUtf(ch, dst); + dst += Tcl_UniCharToUtf(*chPtr, dst); } src += sizeof(Tcl_UniChar); } @@ -2500,8 +2513,11 @@ UtfToUnicodeProc( { const char *srcStart, *srcEnd, *srcClose, *dstStart, *dstEnd; int result, numChars; - Tcl_UniChar ch = 0; + Tcl_UniChar *chPtr = (Tcl_UniChar *) statePtr; + if (flags & TCL_ENCODING_START) { + *statePtr = 0; + } srcStart = src; srcEnd = src + srcLen; srcClose = srcEnd; @@ -2527,7 +2543,7 @@ UtfToUnicodeProc( result = TCL_CONVERT_NOSPACE; break; } - src += TclUtfToUniChar(src, &ch); + src += TclUtfToUniChar(src, chPtr); /* * Need to handle this in a way that won't cause misalignment by @@ -2536,23 +2552,23 @@ UtfToUnicodeProc( #ifdef WORDS_BIGENDIAN #if TCL_UTF_MAX > 4 - *dst++ = (ch >> 24); - *dst++ = ((ch >> 16) & 0xFF); - *dst++ = ((ch >> 8) & 0xFF); - *dst++ = (ch & 0xFF); + *dst++ = (*chPtr >> 24); + *dst++ = ((*chPtr >> 16) & 0xFF); + *dst++ = ((*chPtr >> 8) & 0xFF); + *dst++ = (*chPtr & 0xFF); #else - *dst++ = (ch >> 8); - *dst++ = (ch & 0xFF); + *dst++ = (*chPtr >> 8); + *dst++ = (*chPtr & 0xFF); #endif #else #if TCL_UTF_MAX > 4 - *dst++ = (ch & 0xFF); - *dst++ = ((ch >> 8) & 0xFF); - *dst++ = ((ch >> 16) & 0xFF); - *dst++ = (ch >> 24); + *dst++ = (*chPtr & 0xFF); + *dst++ = ((*chPtr >> 8) & 0xFF); + *dst++ = ((*chPtr >> 16) & 0xFF); + *dst++ = (*chPtr >> 24); #else - *dst++ = (ch & 0xFF); - *dst++ = (ch >> 8); + *dst++ = (*chPtr & 0xFF); + *dst++ = (*chPtr >> 8); #endif #endif } @@ -2754,7 +2770,7 @@ TableFromUtfProc( } len = TclUtfToUniChar(src, &ch); -#if TCL_UTF_MAX > 3 +#if TCL_UTF_MAX > 4 /* * This prevents a crash condition. More evaluation is required for * full support of int Tcl_UniChar. [Bug 1004065] @@ -2763,6 +2779,10 @@ TableFromUtfProc( if (ch & 0xffff0000) { word = 0; } else +#elif TCL_UTF_MAX == 4 + if (!len) { + word = 0; + } else #endif word = fromUnicode[(ch >> 8)][ch & 0xff]; @@ -2960,11 +2980,18 @@ Iso88591FromUtfProc( * Check for illegal characters. */ - if (ch > 0xff) { + if (ch > 0xff +#if TCL_UTF_MAX == 4 + || !len +#endif + ) { if (flags & TCL_ENCODING_STOPONERROR) { result = TCL_CONVERT_UNKNOWN; break; } +#if TCL_UTF_MAX == 4 + if (!len) len = 4; +#endif /* * Plunge on, using '?' as a fallback character. -- cgit v0.12 From 4519681dcd20c967abbe68795911c77c317fab4f Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 23 Apr 2018 23:23:00 +0000 Subject: Bug-fix in Tcl_UtfAtIndex (for TCL_UTF_MAX=4 only). With test-case (in "string totitle") demonstrating the bug. --- generic/tclUtf.c | 8 ++++++++ tests/string.test | 11 +++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/generic/tclUtf.c b/generic/tclUtf.c index 0d88d36..c08464b 100644 --- a/generic/tclUtf.c +++ b/generic/tclUtf.c @@ -762,10 +762,18 @@ Tcl_UtfAtIndex( register int index) /* The position of the desired character. */ { Tcl_UniChar ch = 0; + int len = 1; while (index-- > 0) { + len = TclUtfToUniChar(src, &ch); + src += len; + } +#if TCL_UTF_MAX == 4 + if (!len) { + /* Index points at character following High Surrogate */ src += TclUtfToUniChar(src, &ch); } +#endif return src; } diff --git a/tests/string.test b/tests/string.test index d69fda4..868fc25 100644 --- a/tests/string.test +++ b/tests/string.test @@ -24,7 +24,7 @@ catch [list package require -exact Tcltest [info patchlevel]] testConstraint testobj [expr {[info commands testobj] != {}}] testConstraint testindexobj [expr {[info commands testindexobj] != {}}] -testConstraint fullutf [expr {[format %c 0x010000] != "\ufffd"}] +testConstraint tip389 [expr {[string length \U010000] == 2}] # Used for constraining memory leak tests testConstraint memory [llength [info commands memory]] @@ -291,6 +291,9 @@ test string-5.19 {string index, bytearray object out of bounds} { test string-5.20 {string index, bytearray object out of bounds} { string index [binary format I* {0x50515253 0x52}] 20 } {} +test string-5.21 {string index, surrogates, bug [11ae2be95dac9417]} tip389 { + list [string index a\U100000b 1] [string index a\U100000b 2] [string index a\U100000b 3] +} [list \U100000 {} b] proc largest_int {} { @@ -1280,7 +1283,7 @@ test string-12.22 {string range, shimmering binary/index} { binary scan $s a* x string range $s $s end } 000000001 -test string-12.23 {string range, surrogates, bug [11ae2be95dac9417]} fullutf { +test string-12.23 {string range, surrogates, bug [11ae2be95dac9417]} tip389 { list [string range a\U100000b 1 1] [string range a\U100000b 2 2] [string range a\U100000b 3 3] } [list \U100000 {} b] @@ -1477,6 +1480,10 @@ test string-17.7 {string totitle, unicode} { test string-17.8 {string totitle, compiled} { lindex [string totitle [list aa bb [list cc]]] 0 } Aa +test string-17.9 {string totitle, surrogates, bug [11ae2be95dac9417]} tip389 { + list [string totitle a\U118c0c 1 1] [string totitle a\U118c0c 2 2] \ + [string totitle a\U118c0c 3 3] +} [list a\U118a0c a\U118c0C a\U118c0C] test string-18.1 {string trim} { list [catch {string trim} msg] $msg -- cgit v0.12 From c876decde3e6b34582d26e1cef4967b777a8753c Mon Sep 17 00:00:00 2001 From: dgp Date: Wed, 25 Apr 2018 11:48:14 +0000 Subject: Doc typo fix from Andy Goth. --- doc/define.n | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/define.n b/doc/define.n index 7599ec0..e619728 100644 --- a/doc/define.n +++ b/doc/define.n @@ -50,7 +50,7 @@ being constructed. Within the constructor, the \fBnext\fR command should be used to call the superclasses' constructors. If \fIbodyScript\fR is the empty string, the constructor will be deleted. .TP -\fBdeletemethod\fI name\fR ?\fIname ...\fR +\fBdeletemethod\fI name\fR ?\fIname ...\fR? . This deletes each of the methods called \fIname\fR from a class. The methods must have previously existed in that class. Does not affect the superclasses -- cgit v0.12 From 36aca800d092b95375035c3e0c66dd3f054ca93b Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 25 Apr 2018 21:57:27 +0000 Subject: Fix MSVC build [9f3c253df5] --- generic/tcl.decls | 4 ++-- generic/tclDecls.h | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/generic/tcl.decls b/generic/tcl.decls index e647017..7bd743c 100644 --- a/generic/tcl.decls +++ b/generic/tcl.decls @@ -826,7 +826,7 @@ declare 229 { void Tcl_SetMaxBlockTime(const Tcl_Time *timePtr) } declare 230 { - void Tcl_SetPanicProc(TCL_NORETURN Tcl_PanicProc *panicProc) + void Tcl_SetPanicProc(TCL_NORETURN1 Tcl_PanicProc *panicProc) } declare 231 { int Tcl_SetRecursionLimit(Tcl_Interp *interp, int depth) @@ -1895,7 +1895,7 @@ declare 518 { # TIP#121 (exit handler) dkf for Joe Mistachkin declare 519 { - Tcl_ExitProc *Tcl_SetExitProc(TCL_NORETURN Tcl_ExitProc *proc) + Tcl_ExitProc *Tcl_SetExitProc(TCL_NORETURN1 Tcl_ExitProc *proc) } # TIP#143 (resource limits) dkf diff --git a/generic/tclDecls.h b/generic/tclDecls.h index ab42131..4b2a78d 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -674,7 +674,7 @@ EXTERN void Tcl_SetErrorCode(Tcl_Interp *interp, ...); EXTERN void Tcl_SetMaxBlockTime(const Tcl_Time *timePtr); /* 230 */ EXTERN void Tcl_SetPanicProc( - TCL_NORETURN Tcl_PanicProc *panicProc); + TCL_NORETURN1 Tcl_PanicProc *panicProc); /* 231 */ EXTERN int Tcl_SetRecursionLimit(Tcl_Interp *interp, int depth); /* 232 */ @@ -1459,7 +1459,7 @@ EXTERN void Tcl_GetCommandFullName(Tcl_Interp *interp, EXTERN int Tcl_FSEvalFileEx(Tcl_Interp *interp, Tcl_Obj *fileName, const char *encodingName); /* 519 */ -EXTERN Tcl_ExitProc * Tcl_SetExitProc(TCL_NORETURN Tcl_ExitProc *proc); +EXTERN Tcl_ExitProc * Tcl_SetExitProc(TCL_NORETURN1 Tcl_ExitProc *proc); /* 520 */ EXTERN void Tcl_LimitAddHandler(Tcl_Interp *interp, int type, Tcl_LimitHandlerProc *handlerProc, @@ -2046,7 +2046,7 @@ typedef struct TclStubs { void (*tcl_SetErrno) (int err); /* 227 */ void (*tcl_SetErrorCode) (Tcl_Interp *interp, ...); /* 228 */ void (*tcl_SetMaxBlockTime) (const Tcl_Time *timePtr); /* 229 */ - void (*tcl_SetPanicProc) (TCL_NORETURN Tcl_PanicProc *panicProc); /* 230 */ + void (*tcl_SetPanicProc) (TCL_NORETURN1 Tcl_PanicProc *panicProc); /* 230 */ int (*tcl_SetRecursionLimit) (Tcl_Interp *interp, int depth); /* 231 */ void (*tcl_SetResult) (Tcl_Interp *interp, char *result, Tcl_FreeProc *freeProc); /* 232 */ int (*tcl_SetServiceMode) (int mode); /* 233 */ @@ -2335,7 +2335,7 @@ typedef struct TclStubs { Tcl_Command (*tcl_GetCommandFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr); /* 516 */ void (*tcl_GetCommandFullName) (Tcl_Interp *interp, Tcl_Command command, Tcl_Obj *objPtr); /* 517 */ int (*tcl_FSEvalFileEx) (Tcl_Interp *interp, Tcl_Obj *fileName, const char *encodingName); /* 518 */ - Tcl_ExitProc * (*tcl_SetExitProc) (TCL_NORETURN Tcl_ExitProc *proc); /* 519 */ + Tcl_ExitProc * (*tcl_SetExitProc) (TCL_NORETURN1 Tcl_ExitProc *proc); /* 519 */ void (*tcl_LimitAddHandler) (Tcl_Interp *interp, int type, Tcl_LimitHandlerProc *handlerProc, ClientData clientData, Tcl_LimitHandlerDeleteProc *deleteProc); /* 520 */ void (*tcl_LimitRemoveHandler) (Tcl_Interp *interp, int type, Tcl_LimitHandlerProc *handlerProc, ClientData clientData); /* 521 */ int (*tcl_LimitReady) (Tcl_Interp *interp); /* 522 */ -- cgit v0.12 From 9e733498f1466c92a943ac1c7843296e7e2e6d64 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 26 Apr 2018 08:32:19 +0000 Subject: Update test-cases, so they are selected or not for -DTCL_UTF_MAX=6. Now all relevant test-cases pass for TCL_UTF_MAX=6 builds on UNIX (but not yet on Windows)! --- tests/cmdIL.test | 5 ++--- tests/encoding.test | 10 +++++----- tests/utf.test | 10 +++++----- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/tests/cmdIL.test b/tests/cmdIL.test index b9444b6..360d6b0 100644 --- a/tests/cmdIL.test +++ b/tests/cmdIL.test @@ -19,7 +19,6 @@ catch [list package require -exact Tcltest [info patchlevel]] # Used for constraining memory leak tests testConstraint memory [llength [info commands memory]] testConstraint testobj [llength [info commands testobj]] -testConstraint fullutf [expr {[format %c 0x010000] != "\ufffd"}] test cmdIL-1.1 {Tcl_LsortObjCmd procedure} -returnCodes error -body { lsort @@ -154,10 +153,10 @@ test cmdIL-1.37 {Tcl_LsortObjCmd procedure, Bug 8e1e31eac0fd6b6c} { test cmdIL-1.38 {Tcl_LsortObjCmd procedure, Bug 8e1e31eac0fd6b6c} { lsort -ascii -nocase [list \0 \x7f \x80 \uffff] } [list \0 \x7f \x80 \uffff] -test cmdIL-1.39 {Tcl_LsortObjCmd procedure, Bug 8e1e31eac0fd6b6c} fullutf { +test cmdIL-1.39 {Tcl_LsortObjCmd procedure, Bug 8e1e31eac0fd6b6c} { lsort -ascii [list \0 \x7f \x80 \U01ffff \uffff] } [list \0 \x7f \x80 \uffff \U01ffff] -test cmdIL-1.40 {Tcl_LsortObjCmd procedure, Bug 8e1e31eac0fd6b6c} fullutf { +test cmdIL-1.40 {Tcl_LsortObjCmd procedure, Bug 8e1e31eac0fd6b6c} { lsort -ascii -nocase [list \0 \x7f \x80 \U01ffff \uffff] } [list \0 \x7f \x80 \uffff \U01ffff] test cmdIL-1.41 {lsort -stride and -index} -body { diff --git a/tests/encoding.test b/tests/encoding.test index e447c20..ab60617 100644 --- a/tests/encoding.test +++ b/tests/encoding.test @@ -36,7 +36,7 @@ proc runtests {} { testConstraint testencoding [llength [info commands testencoding]] testConstraint testbytestring [llength [info commands testbytestring]] testConstraint teststringbytes [llength [info commands teststringbytes]] -testConstraint fullutf [expr {[format %c 0x010000] != "\ufffd"}] +testConstraint tip389 [expr {[string length \U010000] == 2}] testConstraint exec [llength [info commands exec]] testConstraint testgetencpath [llength [info commands testgetencpath]] @@ -323,16 +323,16 @@ test encoding-15.3 {UtfToUtfProc null character input} teststringbytes { set z } c080 -test encoding-16.1 {UnicodeToUtfProc} { +test encoding-16.1 {UnicodeToUtfProc} -constraints tip389 -body { set val [encoding convertfrom unicode NN] list $val [format %x [scan $val %c]] -} "\u4e4e 4e4e" -test encoding-16.2 {UnicodeToUtfProc} -constraints fullutf -body { +} -result "\u4e4e 4e4e" +test encoding-16.2 {UnicodeToUtfProc} -constraints tip389 -body { set val [encoding convertfrom unicode "\xd8\xd8\xdc\xdc"] list $val [format %x [scan $val %c]] } -result "\U460dc 460dc" -test encoding-17.1 {UtfToUnicodeProc} -constraints fullutf -body { +test encoding-17.1 {UtfToUnicodeProc} -constraints tip389 -body { encoding convertto unicode "\U460dc" } -result "\xd8\xd8\xdc\xdc" diff --git a/tests/utf.test b/tests/utf.test index 95775a8..af471e1 100644 --- a/tests/utf.test +++ b/tests/utf.test @@ -21,7 +21,7 @@ testConstraint testbytestring [llength [info commands testbytestring]] catch {unset x} # Some tests require support for 4-byte UTF-8 sequences -testConstraint fullutf [expr {[format %c 0x010000] != "\ufffd"}] +testConstraint tip389 [expr {[string length \U010000] == 2}] test utf-1.1 {Tcl_UniCharToUtf: 1 byte sequences} testbytestring { expr {"\x01" eq [testbytestring "\x01"]} @@ -41,7 +41,7 @@ test utf-1.5 {Tcl_UniCharToUtf: overflowed Tcl_UniChar} testbytestring { test utf-1.6 {Tcl_UniCharToUtf: negative Tcl_UniChar} testbytestring { expr {[format %c -1] eq [testbytestring "\xef\xbf\xbd"]} } 1 -test utf-1.7 {Tcl_UniCharToUtf: 4 byte sequences} -constraints {fullutf testbytestring} -body { +test utf-1.7 {Tcl_UniCharToUtf: 4 byte sequences} -constraints {tip389 testbytestring} -body { expr {"\U014e4e" eq [testbytestring "\xf0\x94\xb9\x8e"]} } -result 1 @@ -66,10 +66,10 @@ test utf-2.6 {Tcl_UtfToUniChar: lead (3-byte) followed by 1 trail} testbytestrin test utf-2.7 {Tcl_UtfToUniChar: lead (3-byte) followed by 2 trail} testbytestring { string length [testbytestring "\xE4\xb9\x8e"] } {1} -test utf-2.8 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} -constraints {fullutf testbytestring} -body { +test utf-2.8 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} -constraints {tip389 testbytestring} -body { string length [testbytestring "\xF0\x90\x80\x80"] } -result {2} -test utf-2.9 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} -constraints {fullutf testbytestring} -body { +test utf-2.9 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} -constraints {tip389 testbytestring} -body { string length [testbytestring "\xF4\x8F\xBF\xBF"] } -result {2} test utf-2.10 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail, underflow} testbytestring { @@ -228,7 +228,7 @@ bsCheck \U4e21 20001 bsCheck \U004e21 20001 bsCheck \U00004e21 20001 bsCheck \U0000004e21 78 -if {[testConstraint fullutf]} { +if {[testConstraint tip389]} { bsCheck \U00110000 69632 bsCheck \U01100000 69632 bsCheck \U11000000 69632 -- cgit v0.12 From c23982e3c203350801e96f4a95d273a9918b248a Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Sun, 29 Apr 2018 20:02:48 +0000 Subject: Now really fix [9f3c253df5eec5669673d05fe3a51e4afcf99418|9f3c253df5] : Tcl build broken on Win. (tested on Visual Studio 2017) --- generic/tclEvent.c | 6 +++--- generic/tclPanic.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/generic/tclEvent.c b/generic/tclEvent.c index f806516..93cf983 100644 --- a/generic/tclEvent.c +++ b/generic/tclEvent.c @@ -89,7 +89,7 @@ static int subsystemsInitialized = 0; * non-NULL value. */ -static TCL_NORETURN Tcl_ExitProc *appExitPtr = NULL; +static TCL_NORETURN1 Tcl_ExitProc *appExitPtr = NULL; typedef struct ThreadSpecificData { ExitHandler *firstExitPtr; /* First in list of all exit handlers for this @@ -857,7 +857,7 @@ Tcl_DeleteThreadExitHandler( Tcl_ExitProc * Tcl_SetExitProc( - TCL_NORETURN Tcl_ExitProc *proc) /* New exit handler for app or NULL */ + TCL_NORETURN1 Tcl_ExitProc *proc) /* New exit handler for app or NULL */ { Tcl_ExitProc *prevExitProc; @@ -938,7 +938,7 @@ Tcl_Exit( int status) /* Exit status for application; typically 0 * for normal return, 1 for error return. */ { - TCL_NORETURN Tcl_ExitProc *currentAppExitPtr; + TCL_NORETURN1 Tcl_ExitProc *currentAppExitPtr; Tcl_MutexLock(&exitMutex); currentAppExitPtr = appExitPtr; diff --git a/generic/tclPanic.c b/generic/tclPanic.c index c9ccf8a..78ccf7c 100644 --- a/generic/tclPanic.c +++ b/generic/tclPanic.c @@ -26,7 +26,7 @@ #if defined(__CYGWIN__) static TCL_NORETURN Tcl_PanicProc *panicProc = tclWinDebugPanic; #else -static TCL_NORETURN Tcl_PanicProc *panicProc = NULL; +static TCL_NORETURN1 Tcl_PanicProc *panicProc = NULL; #endif /* @@ -47,7 +47,7 @@ static TCL_NORETURN Tcl_PanicProc *panicProc = NULL; void Tcl_SetPanicProc( - TCL_NORETURN Tcl_PanicProc *proc) + TCL_NORETURN1 Tcl_PanicProc *proc) { #if defined(_WIN32) /* tclWinDebugPanic only installs if there is no panicProc yet. */ -- cgit v0.12 From bfc5a0090ff536e09dc97682d33965b26416e8a2 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Sun, 29 Apr 2018 21:14:21 +0000 Subject: Upgrade everything to Unicode 11 (still in beta, expected in june 2018) --- generic/regc_locale.c | 524 +++++++++--------- generic/regcustom.h | 2 +- generic/tclUniData.c | 1457 +++++++++++++++++++++++++------------------------ tools/uniClass.tcl | 4 +- tools/uniParse.tcl | 11 +- 5 files changed, 1012 insertions(+), 986 deletions(-) diff --git a/generic/regc_locale.c b/generic/regc_locale.c index d781212..002b264 100644 --- a/generic/regc_locale.c +++ b/generic/regc_locale.c @@ -137,8 +137,8 @@ static const crange alphaRangeTable[] = { {0x41, 0x5a}, {0x61, 0x7a}, {0xc0, 0xd6}, {0xd8, 0xf6}, {0xf8, 0x2c1}, {0x2c6, 0x2d1}, {0x2e0, 0x2e4}, {0x370, 0x374}, {0x37a, 0x37d}, {0x388, 0x38a}, {0x38e, 0x3a1}, {0x3a3, 0x3f5}, - {0x3f7, 0x481}, {0x48a, 0x52f}, {0x531, 0x556}, {0x561, 0x587}, - {0x5d0, 0x5ea}, {0x5f0, 0x5f2}, {0x620, 0x64a}, {0x671, 0x6d3}, + {0x3f7, 0x481}, {0x48a, 0x52f}, {0x531, 0x556}, {0x560, 0x588}, + {0x5d0, 0x5ea}, {0x5ef, 0x5f2}, {0x620, 0x64a}, {0x671, 0x6d3}, {0x6fa, 0x6fc}, {0x712, 0x72f}, {0x74d, 0x7a5}, {0x7ca, 0x7ea}, {0x800, 0x815}, {0x840, 0x858}, {0x860, 0x86a}, {0x8a0, 0x8b4}, {0x8b6, 0x8bd}, {0x904, 0x939}, {0x958, 0x961}, {0x971, 0x980}, @@ -165,45 +165,42 @@ static const crange alphaRangeTable[] = { {0x1401, 0x166c}, {0x166f, 0x167f}, {0x1681, 0x169a}, {0x16a0, 0x16ea}, {0x16f1, 0x16f8}, {0x1700, 0x170c}, {0x170e, 0x1711}, {0x1720, 0x1731}, {0x1740, 0x1751}, {0x1760, 0x176c}, {0x176e, 0x1770}, {0x1780, 0x17b3}, - {0x1820, 0x1877}, {0x1880, 0x1884}, {0x1887, 0x18a8}, {0x18b0, 0x18f5}, + {0x1820, 0x1878}, {0x1880, 0x1884}, {0x1887, 0x18a8}, {0x18b0, 0x18f5}, {0x1900, 0x191e}, {0x1950, 0x196d}, {0x1970, 0x1974}, {0x1980, 0x19ab}, {0x19b0, 0x19c9}, {0x1a00, 0x1a16}, {0x1a20, 0x1a54}, {0x1b05, 0x1b33}, {0x1b45, 0x1b4b}, {0x1b83, 0x1ba0}, {0x1bba, 0x1be5}, {0x1c00, 0x1c23}, - {0x1c4d, 0x1c4f}, {0x1c5a, 0x1c7d}, {0x1c80, 0x1c88}, {0x1ce9, 0x1cec}, - {0x1cee, 0x1cf1}, {0x1d00, 0x1dbf}, {0x1e00, 0x1f15}, {0x1f18, 0x1f1d}, - {0x1f20, 0x1f45}, {0x1f48, 0x1f4d}, {0x1f50, 0x1f57}, {0x1f5f, 0x1f7d}, - {0x1f80, 0x1fb4}, {0x1fb6, 0x1fbc}, {0x1fc2, 0x1fc4}, {0x1fc6, 0x1fcc}, - {0x1fd0, 0x1fd3}, {0x1fd6, 0x1fdb}, {0x1fe0, 0x1fec}, {0x1ff2, 0x1ff4}, - {0x1ff6, 0x1ffc}, {0x2090, 0x209c}, {0x210a, 0x2113}, {0x2119, 0x211d}, - {0x212a, 0x212d}, {0x212f, 0x2139}, {0x213c, 0x213f}, {0x2145, 0x2149}, - {0x2c00, 0x2c2e}, {0x2c30, 0x2c5e}, {0x2c60, 0x2ce4}, {0x2ceb, 0x2cee}, - {0x2d00, 0x2d25}, {0x2d30, 0x2d67}, {0x2d80, 0x2d96}, {0x2da0, 0x2da6}, - {0x2da8, 0x2dae}, {0x2db0, 0x2db6}, {0x2db8, 0x2dbe}, {0x2dc0, 0x2dc6}, - {0x2dc8, 0x2dce}, {0x2dd0, 0x2dd6}, {0x2dd8, 0x2dde}, {0x3031, 0x3035}, - {0x3041, 0x3096}, {0x309d, 0x309f}, {0x30a1, 0x30fa}, {0x30fc, 0x30ff}, - {0x3105, 0x312e}, {0x3131, 0x318e}, {0x31a0, 0x31ba}, {0x31f0, 0x31ff}, - {0x3400, 0x4db5}, {0x4e00, 0x9fea}, {0xa000, 0xa48c}, {0xa4d0, 0xa4fd}, - {0xa500, 0xa60c}, {0xa610, 0xa61f}, {0xa640, 0xa66e}, {0xa67f, 0xa69d}, - {0xa6a0, 0xa6e5}, {0xa717, 0xa71f}, {0xa722, 0xa788}, {0xa78b, 0xa7ae}, - {0xa7b0, 0xa7b7}, {0xa7f7, 0xa801}, {0xa803, 0xa805}, {0xa807, 0xa80a}, - {0xa80c, 0xa822}, {0xa840, 0xa873}, {0xa882, 0xa8b3}, {0xa8f2, 0xa8f7}, - {0xa90a, 0xa925}, {0xa930, 0xa946}, {0xa960, 0xa97c}, {0xa984, 0xa9b2}, - {0xa9e0, 0xa9e4}, {0xa9e6, 0xa9ef}, {0xa9fa, 0xa9fe}, {0xaa00, 0xaa28}, - {0xaa40, 0xaa42}, {0xaa44, 0xaa4b}, {0xaa60, 0xaa76}, {0xaa7e, 0xaaaf}, - {0xaab9, 0xaabd}, {0xaadb, 0xaadd}, {0xaae0, 0xaaea}, {0xaaf2, 0xaaf4}, - {0xab01, 0xab06}, {0xab09, 0xab0e}, {0xab11, 0xab16}, {0xab20, 0xab26}, - {0xab28, 0xab2e}, {0xab30, 0xab5a}, {0xab5c, 0xab65}, {0xab70, 0xabe2}, - {0xac00, 0xd7a3}, {0xd7b0, 0xd7c6}, {0xd7cb, 0xd7fb}, {0xdc00, 0xdc3e}, - {0xdc40, 0xdc7e}, {0xdc80, 0xdcbe}, {0xdcc0, 0xdcfe}, {0xdd00, 0xdd3e}, - {0xdd40, 0xdd7e}, {0xdd80, 0xddbe}, {0xddc0, 0xddfe}, {0xde00, 0xde3e}, - {0xde40, 0xde7e}, {0xde80, 0xdebe}, {0xdec0, 0xdefe}, {0xdf00, 0xdf3e}, - {0xdf40, 0xdf7e}, {0xdf80, 0xdfbe}, {0xdfc0, 0xdffe}, {0xf900, 0xfa6d}, - {0xfa70, 0xfad9}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17}, {0xfb1f, 0xfb28}, - {0xfb2a, 0xfb36}, {0xfb38, 0xfb3c}, {0xfb46, 0xfbb1}, {0xfbd3, 0xfd3d}, - {0xfd50, 0xfd8f}, {0xfd92, 0xfdc7}, {0xfdf0, 0xfdfb}, {0xfe70, 0xfe74}, - {0xfe76, 0xfefc}, {0xff21, 0xff3a}, {0xff41, 0xff5a}, {0xff66, 0xffbe}, - {0xffc2, 0xffc7}, {0xffca, 0xffcf}, {0xffd2, 0xffd7}, {0xffda, 0xffdc} -#if TCL_UTF_MAX > 4 + {0x1c4d, 0x1c4f}, {0x1c5a, 0x1c7d}, {0x1c80, 0x1c88}, {0x1c90, 0x1cba}, + {0x1cbd, 0x1cbf}, {0x1ce9, 0x1cec}, {0x1cee, 0x1cf1}, {0x1d00, 0x1dbf}, + {0x1e00, 0x1f15}, {0x1f18, 0x1f1d}, {0x1f20, 0x1f45}, {0x1f48, 0x1f4d}, + {0x1f50, 0x1f57}, {0x1f5f, 0x1f7d}, {0x1f80, 0x1fb4}, {0x1fb6, 0x1fbc}, + {0x1fc2, 0x1fc4}, {0x1fc6, 0x1fcc}, {0x1fd0, 0x1fd3}, {0x1fd6, 0x1fdb}, + {0x1fe0, 0x1fec}, {0x1ff2, 0x1ff4}, {0x1ff6, 0x1ffc}, {0x2090, 0x209c}, + {0x210a, 0x2113}, {0x2119, 0x211d}, {0x212a, 0x212d}, {0x212f, 0x2139}, + {0x213c, 0x213f}, {0x2145, 0x2149}, {0x2c00, 0x2c2e}, {0x2c30, 0x2c5e}, + {0x2c60, 0x2ce4}, {0x2ceb, 0x2cee}, {0x2d00, 0x2d25}, {0x2d30, 0x2d67}, + {0x2d80, 0x2d96}, {0x2da0, 0x2da6}, {0x2da8, 0x2dae}, {0x2db0, 0x2db6}, + {0x2db8, 0x2dbe}, {0x2dc0, 0x2dc6}, {0x2dc8, 0x2dce}, {0x2dd0, 0x2dd6}, + {0x2dd8, 0x2dde}, {0x3031, 0x3035}, {0x3041, 0x3096}, {0x309d, 0x309f}, + {0x30a1, 0x30fa}, {0x30fc, 0x30ff}, {0x3105, 0x312f}, {0x3131, 0x318e}, + {0x31a0, 0x31ba}, {0x31f0, 0x31ff}, {0x3400, 0x4db5}, {0x4e00, 0x9fef}, + {0xa000, 0xa48c}, {0xa4d0, 0xa4fd}, {0xa500, 0xa60c}, {0xa610, 0xa61f}, + {0xa640, 0xa66e}, {0xa67f, 0xa69d}, {0xa6a0, 0xa6e5}, {0xa717, 0xa71f}, + {0xa722, 0xa788}, {0xa78b, 0xa7b9}, {0xa7f7, 0xa801}, {0xa803, 0xa805}, + {0xa807, 0xa80a}, {0xa80c, 0xa822}, {0xa840, 0xa873}, {0xa882, 0xa8b3}, + {0xa8f2, 0xa8f7}, {0xa90a, 0xa925}, {0xa930, 0xa946}, {0xa960, 0xa97c}, + {0xa984, 0xa9b2}, {0xa9e0, 0xa9e4}, {0xa9e6, 0xa9ef}, {0xa9fa, 0xa9fe}, + {0xaa00, 0xaa28}, {0xaa40, 0xaa42}, {0xaa44, 0xaa4b}, {0xaa60, 0xaa76}, + {0xaa7e, 0xaaaf}, {0xaab9, 0xaabd}, {0xaadb, 0xaadd}, {0xaae0, 0xaaea}, + {0xaaf2, 0xaaf4}, {0xab01, 0xab06}, {0xab09, 0xab0e}, {0xab11, 0xab16}, + {0xab20, 0xab26}, {0xab28, 0xab2e}, {0xab30, 0xab5a}, {0xab5c, 0xab65}, + {0xab70, 0xabe2}, {0xac00, 0xd7a3}, {0xd7b0, 0xd7c6}, {0xd7cb, 0xd7fb}, + {0xf900, 0xfa6d}, {0xfa70, 0xfad9}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17}, + {0xfb1f, 0xfb28}, {0xfb2a, 0xfb36}, {0xfb38, 0xfb3c}, {0xfb46, 0xfbb1}, + {0xfbd3, 0xfd3d}, {0xfd50, 0xfd8f}, {0xfd92, 0xfdc7}, {0xfdf0, 0xfdfb}, + {0xfe70, 0xfe74}, {0xfe76, 0xfefc}, {0xff21, 0xff3a}, {0xff41, 0xff5a}, + {0xff66, 0xffbe}, {0xffc2, 0xffc7}, {0xffca, 0xffcf}, {0xffd2, 0xffd7}, + {0xffda, 0xffdc} +#if CHRBITS > 16 ,{0x10000, 0x1000b}, {0x1000d, 0x10026}, {0x10028, 0x1003a}, {0x1003f, 0x1004d}, {0x10050, 0x1005d}, {0x10080, 0x100fa}, {0x10280, 0x1029c}, {0x102a0, 0x102d0}, {0x10300, 0x1031f}, {0x1032d, 0x10340}, {0x10342, 0x10349}, {0x10350, 0x10375}, @@ -212,23 +209,25 @@ static const crange alphaRangeTable[] = { {0x10600, 0x10736}, {0x10740, 0x10755}, {0x10760, 0x10767}, {0x10800, 0x10805}, {0x1080a, 0x10835}, {0x1083f, 0x10855}, {0x10860, 0x10876}, {0x10880, 0x1089e}, {0x108e0, 0x108f2}, {0x10900, 0x10915}, {0x10920, 0x10939}, {0x10980, 0x109b7}, - {0x10a10, 0x10a13}, {0x10a15, 0x10a17}, {0x10a19, 0x10a33}, {0x10a60, 0x10a7c}, + {0x10a10, 0x10a13}, {0x10a15, 0x10a17}, {0x10a19, 0x10a35}, {0x10a60, 0x10a7c}, {0x10a80, 0x10a9c}, {0x10ac0, 0x10ac7}, {0x10ac9, 0x10ae4}, {0x10b00, 0x10b35}, {0x10b40, 0x10b55}, {0x10b60, 0x10b72}, {0x10b80, 0x10b91}, {0x10c00, 0x10c48}, - {0x10c80, 0x10cb2}, {0x10cc0, 0x10cf2}, {0x11003, 0x11037}, {0x11083, 0x110af}, - {0x110d0, 0x110e8}, {0x11103, 0x11126}, {0x11150, 0x11172}, {0x11183, 0x111b2}, - {0x111c1, 0x111c4}, {0x11200, 0x11211}, {0x11213, 0x1122b}, {0x11280, 0x11286}, - {0x1128a, 0x1128d}, {0x1128f, 0x1129d}, {0x1129f, 0x112a8}, {0x112b0, 0x112de}, - {0x11305, 0x1130c}, {0x11313, 0x11328}, {0x1132a, 0x11330}, {0x11335, 0x11339}, - {0x1135d, 0x11361}, {0x11400, 0x11434}, {0x11447, 0x1144a}, {0x11480, 0x114af}, - {0x11580, 0x115ae}, {0x115d8, 0x115db}, {0x11600, 0x1162f}, {0x11680, 0x116aa}, - {0x11700, 0x11719}, {0x118a0, 0x118df}, {0x11a0b, 0x11a32}, {0x11a5c, 0x11a83}, + {0x10c80, 0x10cb2}, {0x10cc0, 0x10cf2}, {0x10d00, 0x10d23}, {0x10f00, 0x10f1c}, + {0x10f30, 0x10f45}, {0x11003, 0x11037}, {0x11083, 0x110af}, {0x110d0, 0x110e8}, + {0x11103, 0x11126}, {0x11150, 0x11172}, {0x11183, 0x111b2}, {0x111c1, 0x111c4}, + {0x11200, 0x11211}, {0x11213, 0x1122b}, {0x11280, 0x11286}, {0x1128a, 0x1128d}, + {0x1128f, 0x1129d}, {0x1129f, 0x112a8}, {0x112b0, 0x112de}, {0x11305, 0x1130c}, + {0x11313, 0x11328}, {0x1132a, 0x11330}, {0x11335, 0x11339}, {0x1135d, 0x11361}, + {0x11400, 0x11434}, {0x11447, 0x1144a}, {0x11480, 0x114af}, {0x11580, 0x115ae}, + {0x115d8, 0x115db}, {0x11600, 0x1162f}, {0x11680, 0x116aa}, {0x11700, 0x1171a}, + {0x11800, 0x1182b}, {0x118a0, 0x118df}, {0x11a0b, 0x11a32}, {0x11a5c, 0x11a83}, {0x11a86, 0x11a89}, {0x11ac0, 0x11af8}, {0x11c00, 0x11c08}, {0x11c0a, 0x11c2e}, - {0x11c72, 0x11c8f}, {0x11d00, 0x11d06}, {0x11d0b, 0x11d30}, {0x12000, 0x12399}, - {0x12480, 0x12543}, {0x13000, 0x1342e}, {0x14400, 0x14646}, {0x16800, 0x16a38}, - {0x16a40, 0x16a5e}, {0x16ad0, 0x16aed}, {0x16b00, 0x16b2f}, {0x16b40, 0x16b43}, - {0x16b63, 0x16b77}, {0x16b7d, 0x16b8f}, {0x16f00, 0x16f44}, {0x16f93, 0x16f9f}, - {0x17000, 0x187ec}, {0x18800, 0x18af2}, {0x1b000, 0x1b11e}, {0x1b170, 0x1b2fb}, + {0x11c72, 0x11c8f}, {0x11d00, 0x11d06}, {0x11d0b, 0x11d30}, {0x11d60, 0x11d65}, + {0x11d6a, 0x11d89}, {0x11ee0, 0x11ef2}, {0x12000, 0x12399}, {0x12480, 0x12543}, + {0x13000, 0x1342e}, {0x14400, 0x14646}, {0x16800, 0x16a38}, {0x16a40, 0x16a5e}, + {0x16ad0, 0x16aed}, {0x16b00, 0x16b2f}, {0x16b40, 0x16b43}, {0x16b63, 0x16b77}, + {0x16b7d, 0x16b8f}, {0x16e40, 0x16e7f}, {0x16f00, 0x16f44}, {0x16f93, 0x16f9f}, + {0x17000, 0x187f1}, {0x18800, 0x18af2}, {0x1b000, 0x1b11e}, {0x1b170, 0x1b2fb}, {0x1bc00, 0x1bc6a}, {0x1bc70, 0x1bc7c}, {0x1bc80, 0x1bc88}, {0x1bc90, 0x1bc99}, {0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac}, {0x1d4ae, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a}, {0x1d50d, 0x1d514}, @@ -264,17 +263,18 @@ static const chr alphaCharTable[] = { 0x1baf, 0x1cf5, 0x1cf6, 0x1f59, 0x1f5b, 0x1f5d, 0x1fbe, 0x2071, 0x207f, 0x2102, 0x2107, 0x2115, 0x2124, 0x2126, 0x2128, 0x214e, 0x2183, 0x2184, 0x2cf2, 0x2cf3, 0x2d27, 0x2d2d, 0x2d6f, 0x2e2f, 0x3005, 0x3006, 0x303b, - 0x303c, 0xa62a, 0xa62b, 0xa8fb, 0xa8fd, 0xa9cf, 0xaa7a, 0xaab1, 0xaab5, - 0xaab6, 0xaac0, 0xaac2, 0xfb1d, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44 -#if TCL_UTF_MAX > 4 + 0x303c, 0xa62a, 0xa62b, 0xa8fb, 0xa8fd, 0xa8fe, 0xa9cf, 0xaa7a, 0xaab1, + 0xaab5, 0xaab6, 0xaac0, 0xaac2, 0xfb1d, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, + 0xfb44 +#if CHRBITS > 16 ,0x1003c, 0x1003d, 0x10808, 0x10837, 0x10838, 0x1083c, 0x108f4, 0x108f5, 0x109be, - 0x109bf, 0x10a00, 0x11176, 0x111da, 0x111dc, 0x11288, 0x1130f, 0x11310, 0x11332, - 0x11333, 0x1133d, 0x11350, 0x114c4, 0x114c5, 0x114c7, 0x11644, 0x118ff, 0x11a00, - 0x11a3a, 0x11a50, 0x11c40, 0x11d08, 0x11d09, 0x11d46, 0x16f50, 0x16fe0, 0x16fe1, - 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4bb, 0x1d546, 0x1ee21, 0x1ee22, - 0x1ee24, 0x1ee27, 0x1ee39, 0x1ee3b, 0x1ee42, 0x1ee47, 0x1ee49, 0x1ee4b, 0x1ee51, - 0x1ee52, 0x1ee54, 0x1ee57, 0x1ee59, 0x1ee5b, 0x1ee5d, 0x1ee5f, 0x1ee61, 0x1ee62, - 0x1ee64, 0x1ee7e + 0x109bf, 0x10a00, 0x10f27, 0x11144, 0x11176, 0x111da, 0x111dc, 0x11288, 0x1130f, + 0x11310, 0x11332, 0x11333, 0x1133d, 0x11350, 0x114c4, 0x114c5, 0x114c7, 0x11644, + 0x118ff, 0x11a00, 0x11a3a, 0x11a50, 0x11a9d, 0x11c40, 0x11d08, 0x11d09, 0x11d46, + 0x11d67, 0x11d68, 0x11d98, 0x16f50, 0x16fe0, 0x16fe1, 0x1d49e, 0x1d49f, 0x1d4a2, + 0x1d4a5, 0x1d4a6, 0x1d4bb, 0x1d546, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee27, 0x1ee39, + 0x1ee3b, 0x1ee42, 0x1ee47, 0x1ee49, 0x1ee4b, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee57, + 0x1ee59, 0x1ee5b, 0x1ee5d, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee7e #endif }; @@ -288,7 +288,7 @@ static const crange controlRangeTable[] = { {0x0, 0x1f}, {0x7f, 0x9f}, {0x600, 0x605}, {0x200b, 0x200f}, {0x202a, 0x202e}, {0x2060, 0x2064}, {0x2066, 0x206f}, {0xe000, 0xf8ff}, {0xfff9, 0xfffb} -#if TCL_UTF_MAX > 4 +#if CHRBITS > 16 ,{0x1bca0, 0x1bca3}, {0x1d173, 0x1d17a}, {0xe0020, 0xe007f}, {0xf0000, 0xffffd}, {0x100000, 0x10fffd} #endif @@ -298,8 +298,8 @@ static const crange controlRangeTable[] = { static const chr controlCharTable[] = { 0xad, 0x61c, 0x6dd, 0x70f, 0x8e2, 0x180e, 0xfeff -#if TCL_UTF_MAX > 4 - ,0x110bd, 0xe0001 +#if CHRBITS > 16 + ,0x110bd, 0x110cd, 0xe0001 #endif }; @@ -320,12 +320,12 @@ static const crange digitRangeTable[] = { {0x1c50, 0x1c59}, {0xa620, 0xa629}, {0xa8d0, 0xa8d9}, {0xa900, 0xa909}, {0xa9d0, 0xa9d9}, {0xa9f0, 0xa9f9}, {0xaa50, 0xaa59}, {0xabf0, 0xabf9}, {0xff10, 0xff19} -#if TCL_UTF_MAX > 4 - ,{0x104a0, 0x104a9}, {0x11066, 0x1106f}, {0x110f0, 0x110f9}, {0x11136, 0x1113f}, - {0x111d0, 0x111d9}, {0x112f0, 0x112f9}, {0x11450, 0x11459}, {0x114d0, 0x114d9}, - {0x11650, 0x11659}, {0x116c0, 0x116c9}, {0x11730, 0x11739}, {0x118e0, 0x118e9}, - {0x11c50, 0x11c59}, {0x11d50, 0x11d59}, {0x16a60, 0x16a69}, {0x16b50, 0x16b59}, - {0x1d7ce, 0x1d7ff}, {0x1e950, 0x1e959} +#if CHRBITS > 16 + ,{0x104a0, 0x104a9}, {0x10d30, 0x10d39}, {0x11066, 0x1106f}, {0x110f0, 0x110f9}, + {0x11136, 0x1113f}, {0x111d0, 0x111d9}, {0x112f0, 0x112f9}, {0x11450, 0x11459}, + {0x114d0, 0x114d9}, {0x11650, 0x11659}, {0x116c0, 0x116c9}, {0x11730, 0x11739}, + {0x118e0, 0x118e9}, {0x11c50, 0x11c59}, {0x11d50, 0x11d59}, {0x11da0, 0x11da9}, + {0x16a60, 0x16a69}, {0x16b50, 0x16b59}, {0x1d7ce, 0x1d7ff}, {0x1e950, 0x1e959} #endif }; @@ -348,19 +348,20 @@ static const crange punctRangeTable[] = { {0x1b5a, 0x1b60}, {0x1bfc, 0x1bff}, {0x1c3b, 0x1c3f}, {0x1cc0, 0x1cc7}, {0x2010, 0x2027}, {0x2030, 0x2043}, {0x2045, 0x2051}, {0x2053, 0x205e}, {0x2308, 0x230b}, {0x2768, 0x2775}, {0x27e6, 0x27ef}, {0x2983, 0x2998}, - {0x29d8, 0x29db}, {0x2cf9, 0x2cfc}, {0x2e00, 0x2e2e}, {0x2e30, 0x2e49}, + {0x29d8, 0x29db}, {0x2cf9, 0x2cfc}, {0x2e00, 0x2e2e}, {0x2e30, 0x2e4e}, {0x3001, 0x3003}, {0x3008, 0x3011}, {0x3014, 0x301f}, {0xa60d, 0xa60f}, {0xa6f2, 0xa6f7}, {0xa874, 0xa877}, {0xa8f8, 0xa8fa}, {0xa9c1, 0xa9cd}, {0xaa5c, 0xaa5f}, {0xfe10, 0xfe19}, {0xfe30, 0xfe52}, {0xfe54, 0xfe61}, {0xff01, 0xff03}, {0xff05, 0xff0a}, {0xff0c, 0xff0f}, {0xff3b, 0xff3d}, {0xff5f, 0xff65} -#if TCL_UTF_MAX > 4 +#if CHRBITS > 16 ,{0x10100, 0x10102}, {0x10a50, 0x10a58}, {0x10af0, 0x10af6}, {0x10b39, 0x10b3f}, - {0x10b99, 0x10b9c}, {0x11047, 0x1104d}, {0x110be, 0x110c1}, {0x11140, 0x11143}, - {0x111c5, 0x111c9}, {0x111dd, 0x111df}, {0x11238, 0x1123d}, {0x1144b, 0x1144f}, - {0x115c1, 0x115d7}, {0x11641, 0x11643}, {0x11660, 0x1166c}, {0x1173c, 0x1173e}, - {0x11a3f, 0x11a46}, {0x11a9a, 0x11a9c}, {0x11a9e, 0x11aa2}, {0x11c41, 0x11c45}, - {0x12470, 0x12474}, {0x16b37, 0x16b3b}, {0x1da87, 0x1da8b} + {0x10b99, 0x10b9c}, {0x10f55, 0x10f59}, {0x11047, 0x1104d}, {0x110be, 0x110c1}, + {0x11140, 0x11143}, {0x111c5, 0x111c8}, {0x111dd, 0x111df}, {0x11238, 0x1123d}, + {0x1144b, 0x1144f}, {0x115c1, 0x115d7}, {0x11641, 0x11643}, {0x11660, 0x1166c}, + {0x1173c, 0x1173e}, {0x11a3f, 0x11a46}, {0x11a9a, 0x11a9c}, {0x11a9e, 0x11aa2}, + {0x11c41, 0x11c45}, {0x12470, 0x12474}, {0x16b37, 0x16b3b}, {0x16e97, 0x16e9a}, + {0x1da87, 0x1da8b} #endif }; @@ -371,18 +372,20 @@ static const chr punctCharTable[] = { 0xab, 0xb6, 0xb7, 0xbb, 0xbf, 0x37e, 0x387, 0x589, 0x58a, 0x5be, 0x5c0, 0x5c3, 0x5c6, 0x5f3, 0x5f4, 0x609, 0x60a, 0x60c, 0x60d, 0x61b, 0x61e, 0x61f, 0x6d4, 0x85e, 0x964, 0x965, 0x970, - 0x9fd, 0xaf0, 0xdf4, 0xe4f, 0xe5a, 0xe5b, 0xf14, 0xf85, 0xfd9, - 0xfda, 0x10fb, 0x1400, 0x166d, 0x166e, 0x169b, 0x169c, 0x1735, 0x1736, - 0x1944, 0x1945, 0x1a1e, 0x1a1f, 0x1c7e, 0x1c7f, 0x1cd3, 0x207d, 0x207e, - 0x208d, 0x208e, 0x2329, 0x232a, 0x27c5, 0x27c6, 0x29fc, 0x29fd, 0x2cfe, - 0x2cff, 0x2d70, 0x3030, 0x303d, 0x30a0, 0x30fb, 0xa4fe, 0xa4ff, 0xa673, - 0xa67e, 0xa8ce, 0xa8cf, 0xa8fc, 0xa92e, 0xa92f, 0xa95f, 0xa9de, 0xa9df, - 0xaade, 0xaadf, 0xaaf0, 0xaaf1, 0xabeb, 0xfd3e, 0xfd3f, 0xfe63, 0xfe68, - 0xfe6a, 0xfe6b, 0xff1a, 0xff1b, 0xff1f, 0xff20, 0xff3f, 0xff5b, 0xff5d -#if TCL_UTF_MAX > 4 + 0x9fd, 0xa76, 0xaf0, 0xc84, 0xdf4, 0xe4f, 0xe5a, 0xe5b, 0xf14, + 0xf85, 0xfd9, 0xfda, 0x10fb, 0x1400, 0x166d, 0x166e, 0x169b, 0x169c, + 0x1735, 0x1736, 0x1944, 0x1945, 0x1a1e, 0x1a1f, 0x1c7e, 0x1c7f, 0x1cd3, + 0x207d, 0x207e, 0x208d, 0x208e, 0x2329, 0x232a, 0x27c5, 0x27c6, 0x29fc, + 0x29fd, 0x2cfe, 0x2cff, 0x2d70, 0x3030, 0x303d, 0x30a0, 0x30fb, 0xa4fe, + 0xa4ff, 0xa673, 0xa67e, 0xa8ce, 0xa8cf, 0xa8fc, 0xa92e, 0xa92f, 0xa95f, + 0xa9de, 0xa9df, 0xaade, 0xaadf, 0xaaf0, 0xaaf1, 0xabeb, 0xfd3e, 0xfd3f, + 0xfe63, 0xfe68, 0xfe6a, 0xfe6b, 0xff1a, 0xff1b, 0xff1f, 0xff20, 0xff3f, + 0xff5b, 0xff5d +#if CHRBITS > 16 ,0x1039f, 0x103d0, 0x1056f, 0x10857, 0x1091f, 0x1093f, 0x10a7f, 0x110bb, 0x110bc, - 0x11174, 0x11175, 0x111cd, 0x111db, 0x112a9, 0x1145b, 0x1145d, 0x114c6, 0x11c70, - 0x11c71, 0x16a6e, 0x16a6f, 0x16af5, 0x16b44, 0x1bc9f, 0x1e95e, 0x1e95f + 0x11174, 0x11175, 0x111cd, 0x111db, 0x112a9, 0x1145b, 0x1145d, 0x114c6, 0x1183b, + 0x11c70, 0x11c71, 0x11ef7, 0x11ef8, 0x16a6e, 0x16a6f, 0x16af5, 0x16b44, 0x1bc9f, + 0x1e95e, 0x1e95f #endif }; @@ -413,25 +416,25 @@ static const crange lowerRangeTable[] = { {0x61, 0x7a}, {0xdf, 0xf6}, {0xf8, 0xff}, {0x17e, 0x180}, {0x199, 0x19b}, {0x1bd, 0x1bf}, {0x233, 0x239}, {0x24f, 0x293}, {0x295, 0x2af}, {0x37b, 0x37d}, {0x3ac, 0x3ce}, {0x3d5, 0x3d7}, - {0x3ef, 0x3f3}, {0x430, 0x45f}, {0x561, 0x587}, {0x13f8, 0x13fd}, - {0x1c80, 0x1c88}, {0x1d00, 0x1d2b}, {0x1d6b, 0x1d77}, {0x1d79, 0x1d9a}, - {0x1e95, 0x1e9d}, {0x1eff, 0x1f07}, {0x1f10, 0x1f15}, {0x1f20, 0x1f27}, - {0x1f30, 0x1f37}, {0x1f40, 0x1f45}, {0x1f50, 0x1f57}, {0x1f60, 0x1f67}, - {0x1f70, 0x1f7d}, {0x1f80, 0x1f87}, {0x1f90, 0x1f97}, {0x1fa0, 0x1fa7}, - {0x1fb0, 0x1fb4}, {0x1fc2, 0x1fc4}, {0x1fd0, 0x1fd3}, {0x1fe0, 0x1fe7}, - {0x1ff2, 0x1ff4}, {0x2146, 0x2149}, {0x2c30, 0x2c5e}, {0x2c76, 0x2c7b}, - {0x2d00, 0x2d25}, {0xa72f, 0xa731}, {0xa771, 0xa778}, {0xa793, 0xa795}, - {0xab30, 0xab5a}, {0xab60, 0xab65}, {0xab70, 0xabbf}, {0xfb00, 0xfb06}, - {0xfb13, 0xfb17}, {0xff41, 0xff5a} -#if TCL_UTF_MAX > 4 + {0x3ef, 0x3f3}, {0x430, 0x45f}, {0x560, 0x588}, {0x10d0, 0x10fa}, + {0x10fd, 0x10ff}, {0x13f8, 0x13fd}, {0x1c80, 0x1c88}, {0x1d00, 0x1d2b}, + {0x1d6b, 0x1d77}, {0x1d79, 0x1d9a}, {0x1e95, 0x1e9d}, {0x1eff, 0x1f07}, + {0x1f10, 0x1f15}, {0x1f20, 0x1f27}, {0x1f30, 0x1f37}, {0x1f40, 0x1f45}, + {0x1f50, 0x1f57}, {0x1f60, 0x1f67}, {0x1f70, 0x1f7d}, {0x1f80, 0x1f87}, + {0x1f90, 0x1f97}, {0x1fa0, 0x1fa7}, {0x1fb0, 0x1fb4}, {0x1fc2, 0x1fc4}, + {0x1fd0, 0x1fd3}, {0x1fe0, 0x1fe7}, {0x1ff2, 0x1ff4}, {0x2146, 0x2149}, + {0x2c30, 0x2c5e}, {0x2c76, 0x2c7b}, {0x2d00, 0x2d25}, {0xa72f, 0xa731}, + {0xa771, 0xa778}, {0xa793, 0xa795}, {0xab30, 0xab5a}, {0xab60, 0xab65}, + {0xab70, 0xabbf}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17}, {0xff41, 0xff5a} +#if CHRBITS > 16 ,{0x10428, 0x1044f}, {0x104d8, 0x104fb}, {0x10cc0, 0x10cf2}, {0x118c0, 0x118df}, - {0x1d41a, 0x1d433}, {0x1d44e, 0x1d454}, {0x1d456, 0x1d467}, {0x1d482, 0x1d49b}, - {0x1d4b6, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d4cf}, {0x1d4ea, 0x1d503}, - {0x1d51e, 0x1d537}, {0x1d552, 0x1d56b}, {0x1d586, 0x1d59f}, {0x1d5ba, 0x1d5d3}, - {0x1d5ee, 0x1d607}, {0x1d622, 0x1d63b}, {0x1d656, 0x1d66f}, {0x1d68a, 0x1d6a5}, - {0x1d6c2, 0x1d6da}, {0x1d6dc, 0x1d6e1}, {0x1d6fc, 0x1d714}, {0x1d716, 0x1d71b}, - {0x1d736, 0x1d74e}, {0x1d750, 0x1d755}, {0x1d770, 0x1d788}, {0x1d78a, 0x1d78f}, - {0x1d7aa, 0x1d7c2}, {0x1d7c4, 0x1d7c9}, {0x1e922, 0x1e943} + {0x16e60, 0x16e7f}, {0x1d41a, 0x1d433}, {0x1d44e, 0x1d454}, {0x1d456, 0x1d467}, + {0x1d482, 0x1d49b}, {0x1d4b6, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d4cf}, + {0x1d4ea, 0x1d503}, {0x1d51e, 0x1d537}, {0x1d552, 0x1d56b}, {0x1d586, 0x1d59f}, + {0x1d5ba, 0x1d5d3}, {0x1d5ee, 0x1d607}, {0x1d622, 0x1d63b}, {0x1d656, 0x1d66f}, + {0x1d68a, 0x1d6a5}, {0x1d6c2, 0x1d6da}, {0x1d6dc, 0x1d6e1}, {0x1d6fc, 0x1d714}, + {0x1d716, 0x1d71b}, {0x1d736, 0x1d74e}, {0x1d750, 0x1d755}, {0x1d770, 0x1d788}, + {0x1d78a, 0x1d78f}, {0x1d7aa, 0x1d7c2}, {0x1d7c4, 0x1d7c9}, {0x1e922, 0x1e943} #endif }; @@ -501,8 +504,8 @@ static const chr lowerCharTable[] = { 0xa763, 0xa765, 0xa767, 0xa769, 0xa76b, 0xa76d, 0xa76f, 0xa77a, 0xa77c, 0xa77f, 0xa781, 0xa783, 0xa785, 0xa787, 0xa78c, 0xa78e, 0xa791, 0xa797, 0xa799, 0xa79b, 0xa79d, 0xa79f, 0xa7a1, 0xa7a3, 0xa7a5, 0xa7a7, 0xa7a9, - 0xa7b5, 0xa7b7, 0xa7fa -#if TCL_UTF_MAX > 4 + 0xa7af, 0xa7b5, 0xa7b7, 0xa7b9, 0xa7fa +#if CHRBITS > 16 ,0x1d4bb, 0x1d7cb #endif }; @@ -518,20 +521,22 @@ static const crange upperRangeTable[] = { {0x18e, 0x191}, {0x196, 0x198}, {0x1b1, 0x1b3}, {0x1f6, 0x1f8}, {0x243, 0x246}, {0x388, 0x38a}, {0x391, 0x3a1}, {0x3a3, 0x3ab}, {0x3d2, 0x3d4}, {0x3fd, 0x42f}, {0x531, 0x556}, {0x10a0, 0x10c5}, - {0x13a0, 0x13f5}, {0x1f08, 0x1f0f}, {0x1f18, 0x1f1d}, {0x1f28, 0x1f2f}, - {0x1f38, 0x1f3f}, {0x1f48, 0x1f4d}, {0x1f68, 0x1f6f}, {0x1fb8, 0x1fbb}, - {0x1fc8, 0x1fcb}, {0x1fd8, 0x1fdb}, {0x1fe8, 0x1fec}, {0x1ff8, 0x1ffb}, - {0x210b, 0x210d}, {0x2110, 0x2112}, {0x2119, 0x211d}, {0x212a, 0x212d}, - {0x2130, 0x2133}, {0x2c00, 0x2c2e}, {0x2c62, 0x2c64}, {0x2c6d, 0x2c70}, - {0x2c7e, 0x2c80}, {0xa7aa, 0xa7ae}, {0xa7b0, 0xa7b4}, {0xff21, 0xff3a} -#if TCL_UTF_MAX > 4 + {0x13a0, 0x13f5}, {0x1c90, 0x1cba}, {0x1cbd, 0x1cbf}, {0x1f08, 0x1f0f}, + {0x1f18, 0x1f1d}, {0x1f28, 0x1f2f}, {0x1f38, 0x1f3f}, {0x1f48, 0x1f4d}, + {0x1f68, 0x1f6f}, {0x1fb8, 0x1fbb}, {0x1fc8, 0x1fcb}, {0x1fd8, 0x1fdb}, + {0x1fe8, 0x1fec}, {0x1ff8, 0x1ffb}, {0x210b, 0x210d}, {0x2110, 0x2112}, + {0x2119, 0x211d}, {0x212a, 0x212d}, {0x2130, 0x2133}, {0x2c00, 0x2c2e}, + {0x2c62, 0x2c64}, {0x2c6d, 0x2c70}, {0x2c7e, 0x2c80}, {0xa7aa, 0xa7ae}, + {0xa7b0, 0xa7b4}, {0xff21, 0xff3a} +#if CHRBITS > 16 ,{0x10400, 0x10427}, {0x104b0, 0x104d3}, {0x10c80, 0x10cb2}, {0x118a0, 0x118bf}, - {0x1d400, 0x1d419}, {0x1d434, 0x1d44d}, {0x1d468, 0x1d481}, {0x1d4a9, 0x1d4ac}, - {0x1d4ae, 0x1d4b5}, {0x1d4d0, 0x1d4e9}, {0x1d507, 0x1d50a}, {0x1d50d, 0x1d514}, - {0x1d516, 0x1d51c}, {0x1d53b, 0x1d53e}, {0x1d540, 0x1d544}, {0x1d54a, 0x1d550}, - {0x1d56c, 0x1d585}, {0x1d5a0, 0x1d5b9}, {0x1d5d4, 0x1d5ed}, {0x1d608, 0x1d621}, - {0x1d63c, 0x1d655}, {0x1d670, 0x1d689}, {0x1d6a8, 0x1d6c0}, {0x1d6e2, 0x1d6fa}, - {0x1d71c, 0x1d734}, {0x1d756, 0x1d76e}, {0x1d790, 0x1d7a8}, {0x1e900, 0x1e921} + {0x16e40, 0x16e5f}, {0x1d400, 0x1d419}, {0x1d434, 0x1d44d}, {0x1d468, 0x1d481}, + {0x1d4a9, 0x1d4ac}, {0x1d4ae, 0x1d4b5}, {0x1d4d0, 0x1d4e9}, {0x1d507, 0x1d50a}, + {0x1d50d, 0x1d514}, {0x1d516, 0x1d51c}, {0x1d53b, 0x1d53e}, {0x1d540, 0x1d544}, + {0x1d54a, 0x1d550}, {0x1d56c, 0x1d585}, {0x1d5a0, 0x1d5b9}, {0x1d5d4, 0x1d5ed}, + {0x1d608, 0x1d621}, {0x1d63c, 0x1d655}, {0x1d670, 0x1d689}, {0x1d6a8, 0x1d6c0}, + {0x1d6e2, 0x1d6fa}, {0x1d71c, 0x1d734}, {0x1d756, 0x1d76e}, {0x1d790, 0x1d7a8}, + {0x1e900, 0x1e921} #endif }; @@ -600,8 +605,9 @@ static const chr upperCharTable[] = { 0xa756, 0xa758, 0xa75a, 0xa75c, 0xa75e, 0xa760, 0xa762, 0xa764, 0xa766, 0xa768, 0xa76a, 0xa76c, 0xa76e, 0xa779, 0xa77b, 0xa77d, 0xa77e, 0xa780, 0xa782, 0xa784, 0xa786, 0xa78b, 0xa78d, 0xa790, 0xa792, 0xa796, 0xa798, - 0xa79a, 0xa79c, 0xa79e, 0xa7a0, 0xa7a2, 0xa7a4, 0xa7a6, 0xa7a8, 0xa7b6 -#if TCL_UTF_MAX > 4 + 0xa79a, 0xa79c, 0xa79e, 0xa7a0, 0xa7a2, 0xa7a4, 0xa7a6, 0xa7a8, 0xa7b6, + 0xa7b8 +#if CHRBITS > 16 ,0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d504, 0x1d505, 0x1d538, 0x1d539, 0x1d546, 0x1d7ca #endif @@ -616,85 +622,80 @@ static const chr upperCharTable[] = { static const crange graphRangeTable[] = { {0x21, 0x7e}, {0xa1, 0xac}, {0xae, 0x377}, {0x37a, 0x37f}, {0x384, 0x38a}, {0x38e, 0x3a1}, {0x3a3, 0x52f}, {0x531, 0x556}, - {0x559, 0x55f}, {0x561, 0x587}, {0x58d, 0x58f}, {0x591, 0x5c7}, - {0x5d0, 0x5ea}, {0x5f0, 0x5f4}, {0x606, 0x61b}, {0x61e, 0x6dc}, - {0x6de, 0x70d}, {0x710, 0x74a}, {0x74d, 0x7b1}, {0x7c0, 0x7fa}, - {0x800, 0x82d}, {0x830, 0x83e}, {0x840, 0x85b}, {0x860, 0x86a}, - {0x8a0, 0x8b4}, {0x8b6, 0x8bd}, {0x8d4, 0x8e1}, {0x8e3, 0x983}, - {0x985, 0x98c}, {0x993, 0x9a8}, {0x9aa, 0x9b0}, {0x9b6, 0x9b9}, - {0x9bc, 0x9c4}, {0x9cb, 0x9ce}, {0x9df, 0x9e3}, {0x9e6, 0x9fd}, - {0xa01, 0xa03}, {0xa05, 0xa0a}, {0xa13, 0xa28}, {0xa2a, 0xa30}, - {0xa3e, 0xa42}, {0xa4b, 0xa4d}, {0xa59, 0xa5c}, {0xa66, 0xa75}, - {0xa81, 0xa83}, {0xa85, 0xa8d}, {0xa8f, 0xa91}, {0xa93, 0xaa8}, - {0xaaa, 0xab0}, {0xab5, 0xab9}, {0xabc, 0xac5}, {0xac7, 0xac9}, - {0xacb, 0xacd}, {0xae0, 0xae3}, {0xae6, 0xaf1}, {0xaf9, 0xaff}, - {0xb01, 0xb03}, {0xb05, 0xb0c}, {0xb13, 0xb28}, {0xb2a, 0xb30}, - {0xb35, 0xb39}, {0xb3c, 0xb44}, {0xb4b, 0xb4d}, {0xb5f, 0xb63}, - {0xb66, 0xb77}, {0xb85, 0xb8a}, {0xb8e, 0xb90}, {0xb92, 0xb95}, - {0xba8, 0xbaa}, {0xbae, 0xbb9}, {0xbbe, 0xbc2}, {0xbc6, 0xbc8}, - {0xbca, 0xbcd}, {0xbe6, 0xbfa}, {0xc00, 0xc03}, {0xc05, 0xc0c}, - {0xc0e, 0xc10}, {0xc12, 0xc28}, {0xc2a, 0xc39}, {0xc3d, 0xc44}, - {0xc46, 0xc48}, {0xc4a, 0xc4d}, {0xc58, 0xc5a}, {0xc60, 0xc63}, - {0xc66, 0xc6f}, {0xc78, 0xc83}, {0xc85, 0xc8c}, {0xc8e, 0xc90}, - {0xc92, 0xca8}, {0xcaa, 0xcb3}, {0xcb5, 0xcb9}, {0xcbc, 0xcc4}, - {0xcc6, 0xcc8}, {0xcca, 0xccd}, {0xce0, 0xce3}, {0xce6, 0xcef}, - {0xd00, 0xd03}, {0xd05, 0xd0c}, {0xd0e, 0xd10}, {0xd12, 0xd44}, - {0xd46, 0xd48}, {0xd4a, 0xd4f}, {0xd54, 0xd63}, {0xd66, 0xd7f}, - {0xd85, 0xd96}, {0xd9a, 0xdb1}, {0xdb3, 0xdbb}, {0xdc0, 0xdc6}, - {0xdcf, 0xdd4}, {0xdd8, 0xddf}, {0xde6, 0xdef}, {0xdf2, 0xdf4}, - {0xe01, 0xe3a}, {0xe3f, 0xe5b}, {0xe94, 0xe97}, {0xe99, 0xe9f}, - {0xea1, 0xea3}, {0xead, 0xeb9}, {0xebb, 0xebd}, {0xec0, 0xec4}, - {0xec8, 0xecd}, {0xed0, 0xed9}, {0xedc, 0xedf}, {0xf00, 0xf47}, - {0xf49, 0xf6c}, {0xf71, 0xf97}, {0xf99, 0xfbc}, {0xfbe, 0xfcc}, - {0xfce, 0xfda}, {0x1000, 0x10c5}, {0x10d0, 0x1248}, {0x124a, 0x124d}, - {0x1250, 0x1256}, {0x125a, 0x125d}, {0x1260, 0x1288}, {0x128a, 0x128d}, - {0x1290, 0x12b0}, {0x12b2, 0x12b5}, {0x12b8, 0x12be}, {0x12c2, 0x12c5}, - {0x12c8, 0x12d6}, {0x12d8, 0x1310}, {0x1312, 0x1315}, {0x1318, 0x135a}, - {0x135d, 0x137c}, {0x1380, 0x1399}, {0x13a0, 0x13f5}, {0x13f8, 0x13fd}, - {0x1400, 0x167f}, {0x1681, 0x169c}, {0x16a0, 0x16f8}, {0x1700, 0x170c}, - {0x170e, 0x1714}, {0x1720, 0x1736}, {0x1740, 0x1753}, {0x1760, 0x176c}, - {0x176e, 0x1770}, {0x1780, 0x17dd}, {0x17e0, 0x17e9}, {0x17f0, 0x17f9}, - {0x1800, 0x180d}, {0x1810, 0x1819}, {0x1820, 0x1877}, {0x1880, 0x18aa}, - {0x18b0, 0x18f5}, {0x1900, 0x191e}, {0x1920, 0x192b}, {0x1930, 0x193b}, - {0x1944, 0x196d}, {0x1970, 0x1974}, {0x1980, 0x19ab}, {0x19b0, 0x19c9}, - {0x19d0, 0x19da}, {0x19de, 0x1a1b}, {0x1a1e, 0x1a5e}, {0x1a60, 0x1a7c}, - {0x1a7f, 0x1a89}, {0x1a90, 0x1a99}, {0x1aa0, 0x1aad}, {0x1ab0, 0x1abe}, - {0x1b00, 0x1b4b}, {0x1b50, 0x1b7c}, {0x1b80, 0x1bf3}, {0x1bfc, 0x1c37}, - {0x1c3b, 0x1c49}, {0x1c4d, 0x1c88}, {0x1cc0, 0x1cc7}, {0x1cd0, 0x1cf9}, - {0x1d00, 0x1df9}, {0x1dfb, 0x1f15}, {0x1f18, 0x1f1d}, {0x1f20, 0x1f45}, - {0x1f48, 0x1f4d}, {0x1f50, 0x1f57}, {0x1f5f, 0x1f7d}, {0x1f80, 0x1fb4}, - {0x1fb6, 0x1fc4}, {0x1fc6, 0x1fd3}, {0x1fd6, 0x1fdb}, {0x1fdd, 0x1fef}, - {0x1ff2, 0x1ff4}, {0x1ff6, 0x1ffe}, {0x2010, 0x2027}, {0x2030, 0x205e}, - {0x2074, 0x208e}, {0x2090, 0x209c}, {0x20a0, 0x20bf}, {0x20d0, 0x20f0}, - {0x2100, 0x218b}, {0x2190, 0x2426}, {0x2440, 0x244a}, {0x2460, 0x2b73}, - {0x2b76, 0x2b95}, {0x2b98, 0x2bb9}, {0x2bbd, 0x2bc8}, {0x2bca, 0x2bd2}, - {0x2bec, 0x2bef}, {0x2c00, 0x2c2e}, {0x2c30, 0x2c5e}, {0x2c60, 0x2cf3}, + {0x559, 0x58a}, {0x58d, 0x58f}, {0x591, 0x5c7}, {0x5d0, 0x5ea}, + {0x5ef, 0x5f4}, {0x606, 0x61b}, {0x61e, 0x6dc}, {0x6de, 0x70d}, + {0x710, 0x74a}, {0x74d, 0x7b1}, {0x7c0, 0x7fa}, {0x7fd, 0x82d}, + {0x830, 0x83e}, {0x840, 0x85b}, {0x860, 0x86a}, {0x8a0, 0x8b4}, + {0x8b6, 0x8bd}, {0x8d3, 0x8e1}, {0x8e3, 0x983}, {0x985, 0x98c}, + {0x993, 0x9a8}, {0x9aa, 0x9b0}, {0x9b6, 0x9b9}, {0x9bc, 0x9c4}, + {0x9cb, 0x9ce}, {0x9df, 0x9e3}, {0x9e6, 0x9fe}, {0xa01, 0xa03}, + {0xa05, 0xa0a}, {0xa13, 0xa28}, {0xa2a, 0xa30}, {0xa3e, 0xa42}, + {0xa4b, 0xa4d}, {0xa59, 0xa5c}, {0xa66, 0xa76}, {0xa81, 0xa83}, + {0xa85, 0xa8d}, {0xa8f, 0xa91}, {0xa93, 0xaa8}, {0xaaa, 0xab0}, + {0xab5, 0xab9}, {0xabc, 0xac5}, {0xac7, 0xac9}, {0xacb, 0xacd}, + {0xae0, 0xae3}, {0xae6, 0xaf1}, {0xaf9, 0xaff}, {0xb01, 0xb03}, + {0xb05, 0xb0c}, {0xb13, 0xb28}, {0xb2a, 0xb30}, {0xb35, 0xb39}, + {0xb3c, 0xb44}, {0xb4b, 0xb4d}, {0xb5f, 0xb63}, {0xb66, 0xb77}, + {0xb85, 0xb8a}, {0xb8e, 0xb90}, {0xb92, 0xb95}, {0xba8, 0xbaa}, + {0xbae, 0xbb9}, {0xbbe, 0xbc2}, {0xbc6, 0xbc8}, {0xbca, 0xbcd}, + {0xbe6, 0xbfa}, {0xc00, 0xc0c}, {0xc0e, 0xc10}, {0xc12, 0xc28}, + {0xc2a, 0xc39}, {0xc3d, 0xc44}, {0xc46, 0xc48}, {0xc4a, 0xc4d}, + {0xc58, 0xc5a}, {0xc60, 0xc63}, {0xc66, 0xc6f}, {0xc78, 0xc8c}, + {0xc8e, 0xc90}, {0xc92, 0xca8}, {0xcaa, 0xcb3}, {0xcb5, 0xcb9}, + {0xcbc, 0xcc4}, {0xcc6, 0xcc8}, {0xcca, 0xccd}, {0xce0, 0xce3}, + {0xce6, 0xcef}, {0xd00, 0xd03}, {0xd05, 0xd0c}, {0xd0e, 0xd10}, + {0xd12, 0xd44}, {0xd46, 0xd48}, {0xd4a, 0xd4f}, {0xd54, 0xd63}, + {0xd66, 0xd7f}, {0xd85, 0xd96}, {0xd9a, 0xdb1}, {0xdb3, 0xdbb}, + {0xdc0, 0xdc6}, {0xdcf, 0xdd4}, {0xdd8, 0xddf}, {0xde6, 0xdef}, + {0xdf2, 0xdf4}, {0xe01, 0xe3a}, {0xe3f, 0xe5b}, {0xe94, 0xe97}, + {0xe99, 0xe9f}, {0xea1, 0xea3}, {0xead, 0xeb9}, {0xebb, 0xebd}, + {0xec0, 0xec4}, {0xec8, 0xecd}, {0xed0, 0xed9}, {0xedc, 0xedf}, + {0xf00, 0xf47}, {0xf49, 0xf6c}, {0xf71, 0xf97}, {0xf99, 0xfbc}, + {0xfbe, 0xfcc}, {0xfce, 0xfda}, {0x1000, 0x10c5}, {0x10d0, 0x1248}, + {0x124a, 0x124d}, {0x1250, 0x1256}, {0x125a, 0x125d}, {0x1260, 0x1288}, + {0x128a, 0x128d}, {0x1290, 0x12b0}, {0x12b2, 0x12b5}, {0x12b8, 0x12be}, + {0x12c2, 0x12c5}, {0x12c8, 0x12d6}, {0x12d8, 0x1310}, {0x1312, 0x1315}, + {0x1318, 0x135a}, {0x135d, 0x137c}, {0x1380, 0x1399}, {0x13a0, 0x13f5}, + {0x13f8, 0x13fd}, {0x1400, 0x167f}, {0x1681, 0x169c}, {0x16a0, 0x16f8}, + {0x1700, 0x170c}, {0x170e, 0x1714}, {0x1720, 0x1736}, {0x1740, 0x1753}, + {0x1760, 0x176c}, {0x176e, 0x1770}, {0x1780, 0x17dd}, {0x17e0, 0x17e9}, + {0x17f0, 0x17f9}, {0x1800, 0x180d}, {0x1810, 0x1819}, {0x1820, 0x1878}, + {0x1880, 0x18aa}, {0x18b0, 0x18f5}, {0x1900, 0x191e}, {0x1920, 0x192b}, + {0x1930, 0x193b}, {0x1944, 0x196d}, {0x1970, 0x1974}, {0x1980, 0x19ab}, + {0x19b0, 0x19c9}, {0x19d0, 0x19da}, {0x19de, 0x1a1b}, {0x1a1e, 0x1a5e}, + {0x1a60, 0x1a7c}, {0x1a7f, 0x1a89}, {0x1a90, 0x1a99}, {0x1aa0, 0x1aad}, + {0x1ab0, 0x1abe}, {0x1b00, 0x1b4b}, {0x1b50, 0x1b7c}, {0x1b80, 0x1bf3}, + {0x1bfc, 0x1c37}, {0x1c3b, 0x1c49}, {0x1c4d, 0x1c88}, {0x1c90, 0x1cba}, + {0x1cbd, 0x1cc7}, {0x1cd0, 0x1cf9}, {0x1d00, 0x1df9}, {0x1dfb, 0x1f15}, + {0x1f18, 0x1f1d}, {0x1f20, 0x1f45}, {0x1f48, 0x1f4d}, {0x1f50, 0x1f57}, + {0x1f5f, 0x1f7d}, {0x1f80, 0x1fb4}, {0x1fb6, 0x1fc4}, {0x1fc6, 0x1fd3}, + {0x1fd6, 0x1fdb}, {0x1fdd, 0x1fef}, {0x1ff2, 0x1ff4}, {0x1ff6, 0x1ffe}, + {0x2010, 0x2027}, {0x2030, 0x205e}, {0x2074, 0x208e}, {0x2090, 0x209c}, + {0x20a0, 0x20bf}, {0x20d0, 0x20f0}, {0x2100, 0x218b}, {0x2190, 0x2426}, + {0x2440, 0x244a}, {0x2460, 0x2b73}, {0x2b76, 0x2b95}, {0x2b98, 0x2bc8}, + {0x2bca, 0x2bfe}, {0x2c00, 0x2c2e}, {0x2c30, 0x2c5e}, {0x2c60, 0x2cf3}, {0x2cf9, 0x2d25}, {0x2d30, 0x2d67}, {0x2d7f, 0x2d96}, {0x2da0, 0x2da6}, {0x2da8, 0x2dae}, {0x2db0, 0x2db6}, {0x2db8, 0x2dbe}, {0x2dc0, 0x2dc6}, - {0x2dc8, 0x2dce}, {0x2dd0, 0x2dd6}, {0x2dd8, 0x2dde}, {0x2de0, 0x2e49}, + {0x2dc8, 0x2dce}, {0x2dd0, 0x2dd6}, {0x2dd8, 0x2dde}, {0x2de0, 0x2e4e}, {0x2e80, 0x2e99}, {0x2e9b, 0x2ef3}, {0x2f00, 0x2fd5}, {0x2ff0, 0x2ffb}, - {0x3001, 0x303f}, {0x3041, 0x3096}, {0x3099, 0x30ff}, {0x3105, 0x312e}, + {0x3001, 0x303f}, {0x3041, 0x3096}, {0x3099, 0x30ff}, {0x3105, 0x312f}, {0x3131, 0x318e}, {0x3190, 0x31ba}, {0x31c0, 0x31e3}, {0x31f0, 0x321e}, - {0x3220, 0x32fe}, {0x3300, 0x4db5}, {0x4dc0, 0x9fea}, {0xa000, 0xa48c}, - {0xa490, 0xa4c6}, {0xa4d0, 0xa62b}, {0xa640, 0xa6f7}, {0xa700, 0xa7ae}, - {0xa7b0, 0xa7b7}, {0xa7f7, 0xa82b}, {0xa830, 0xa839}, {0xa840, 0xa877}, - {0xa880, 0xa8c5}, {0xa8ce, 0xa8d9}, {0xa8e0, 0xa8fd}, {0xa900, 0xa953}, - {0xa95f, 0xa97c}, {0xa980, 0xa9cd}, {0xa9cf, 0xa9d9}, {0xa9de, 0xa9fe}, - {0xaa00, 0xaa36}, {0xaa40, 0xaa4d}, {0xaa50, 0xaa59}, {0xaa5c, 0xaac2}, - {0xaadb, 0xaaf6}, {0xab01, 0xab06}, {0xab09, 0xab0e}, {0xab11, 0xab16}, - {0xab20, 0xab26}, {0xab28, 0xab2e}, {0xab30, 0xab65}, {0xab70, 0xabed}, - {0xabf0, 0xabf9}, {0xac00, 0xd7a3}, {0xd7b0, 0xd7c6}, {0xd7cb, 0xd7fb}, - {0xdc00, 0xdc3e}, {0xdc40, 0xdc7e}, {0xdc80, 0xdcbe}, {0xdcc0, 0xdcfe}, - {0xdd00, 0xdd3e}, {0xdd40, 0xdd7e}, {0xdd80, 0xddbe}, {0xddc0, 0xddfe}, - {0xde00, 0xde3e}, {0xde40, 0xde7e}, {0xde80, 0xdebe}, {0xdec0, 0xdefe}, - {0xdf00, 0xdf3e}, {0xdf40, 0xdf7e}, {0xdf80, 0xdfbe}, {0xdfc0, 0xdffe}, - {0xf900, 0xfa6d}, {0xfa70, 0xfad9}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17}, - {0xfb1d, 0xfb36}, {0xfb38, 0xfb3c}, {0xfb46, 0xfbc1}, {0xfbd3, 0xfd3f}, - {0xfd50, 0xfd8f}, {0xfd92, 0xfdc7}, {0xfdf0, 0xfdfd}, {0xfe00, 0xfe19}, - {0xfe20, 0xfe52}, {0xfe54, 0xfe66}, {0xfe68, 0xfe6b}, {0xfe70, 0xfe74}, - {0xfe76, 0xfefc}, {0xff01, 0xffbe}, {0xffc2, 0xffc7}, {0xffca, 0xffcf}, - {0xffd2, 0xffd7}, {0xffda, 0xffdc}, {0xffe0, 0xffe6}, {0xffe8, 0xffee} -#if TCL_UTF_MAX > 4 + {0x3220, 0x32fe}, {0x3300, 0x4db5}, {0x4dc0, 0x9fef}, {0xa000, 0xa48c}, + {0xa490, 0xa4c6}, {0xa4d0, 0xa62b}, {0xa640, 0xa6f7}, {0xa700, 0xa7b9}, + {0xa7f7, 0xa82b}, {0xa830, 0xa839}, {0xa840, 0xa877}, {0xa880, 0xa8c5}, + {0xa8ce, 0xa8d9}, {0xa8e0, 0xa953}, {0xa95f, 0xa97c}, {0xa980, 0xa9cd}, + {0xa9cf, 0xa9d9}, {0xa9de, 0xa9fe}, {0xaa00, 0xaa36}, {0xaa40, 0xaa4d}, + {0xaa50, 0xaa59}, {0xaa5c, 0xaac2}, {0xaadb, 0xaaf6}, {0xab01, 0xab06}, + {0xab09, 0xab0e}, {0xab11, 0xab16}, {0xab20, 0xab26}, {0xab28, 0xab2e}, + {0xab30, 0xab65}, {0xab70, 0xabed}, {0xabf0, 0xabf9}, {0xac00, 0xd7a3}, + {0xd7b0, 0xd7c6}, {0xd7cb, 0xd7fb}, {0xf900, 0xfa6d}, {0xfa70, 0xfad9}, + {0xfb00, 0xfb06}, {0xfb13, 0xfb17}, {0xfb1d, 0xfb36}, {0xfb38, 0xfb3c}, + {0xfb46, 0xfbc1}, {0xfbd3, 0xfd3f}, {0xfd50, 0xfd8f}, {0xfd92, 0xfdc7}, + {0xfdf0, 0xfdfd}, {0xfe00, 0xfe19}, {0xfe20, 0xfe52}, {0xfe54, 0xfe66}, + {0xfe68, 0xfe6b}, {0xfe70, 0xfe74}, {0xfe76, 0xfefc}, {0xff01, 0xffbe}, + {0xffc2, 0xffc7}, {0xffca, 0xffcf}, {0xffd2, 0xffd7}, {0xffda, 0xffdc}, + {0xffe0, 0xffe6}, {0xffe8, 0xffee} +#if CHRBITS > 16 ,{0x10000, 0x1000b}, {0x1000d, 0x10026}, {0x10028, 0x1003a}, {0x1003f, 0x1004d}, {0x10050, 0x1005d}, {0x10080, 0x100fa}, {0x10100, 0x10102}, {0x10107, 0x10133}, {0x10137, 0x1018e}, {0x10190, 0x1019b}, {0x101d0, 0x101fd}, {0x10280, 0x1029c}, @@ -705,80 +706,85 @@ static const crange graphRangeTable[] = { {0x10760, 0x10767}, {0x10800, 0x10805}, {0x1080a, 0x10835}, {0x1083f, 0x10855}, {0x10857, 0x1089e}, {0x108a7, 0x108af}, {0x108e0, 0x108f2}, {0x108fb, 0x1091b}, {0x1091f, 0x10939}, {0x10980, 0x109b7}, {0x109bc, 0x109cf}, {0x109d2, 0x10a03}, - {0x10a0c, 0x10a13}, {0x10a15, 0x10a17}, {0x10a19, 0x10a33}, {0x10a38, 0x10a3a}, - {0x10a3f, 0x10a47}, {0x10a50, 0x10a58}, {0x10a60, 0x10a9f}, {0x10ac0, 0x10ae6}, + {0x10a0c, 0x10a13}, {0x10a15, 0x10a17}, {0x10a19, 0x10a35}, {0x10a38, 0x10a3a}, + {0x10a3f, 0x10a48}, {0x10a50, 0x10a58}, {0x10a60, 0x10a9f}, {0x10ac0, 0x10ae6}, {0x10aeb, 0x10af6}, {0x10b00, 0x10b35}, {0x10b39, 0x10b55}, {0x10b58, 0x10b72}, {0x10b78, 0x10b91}, {0x10b99, 0x10b9c}, {0x10ba9, 0x10baf}, {0x10c00, 0x10c48}, - {0x10c80, 0x10cb2}, {0x10cc0, 0x10cf2}, {0x10cfa, 0x10cff}, {0x10e60, 0x10e7e}, - {0x11000, 0x1104d}, {0x11052, 0x1106f}, {0x1107f, 0x110bc}, {0x110be, 0x110c1}, - {0x110d0, 0x110e8}, {0x110f0, 0x110f9}, {0x11100, 0x11134}, {0x11136, 0x11143}, - {0x11150, 0x11176}, {0x11180, 0x111cd}, {0x111d0, 0x111df}, {0x111e1, 0x111f4}, - {0x11200, 0x11211}, {0x11213, 0x1123e}, {0x11280, 0x11286}, {0x1128a, 0x1128d}, - {0x1128f, 0x1129d}, {0x1129f, 0x112a9}, {0x112b0, 0x112ea}, {0x112f0, 0x112f9}, - {0x11300, 0x11303}, {0x11305, 0x1130c}, {0x11313, 0x11328}, {0x1132a, 0x11330}, - {0x11335, 0x11339}, {0x1133c, 0x11344}, {0x1134b, 0x1134d}, {0x1135d, 0x11363}, - {0x11366, 0x1136c}, {0x11370, 0x11374}, {0x11400, 0x11459}, {0x11480, 0x114c7}, - {0x114d0, 0x114d9}, {0x11580, 0x115b5}, {0x115b8, 0x115dd}, {0x11600, 0x11644}, - {0x11650, 0x11659}, {0x11660, 0x1166c}, {0x11680, 0x116b7}, {0x116c0, 0x116c9}, - {0x11700, 0x11719}, {0x1171d, 0x1172b}, {0x11730, 0x1173f}, {0x118a0, 0x118f2}, - {0x11a00, 0x11a47}, {0x11a50, 0x11a83}, {0x11a86, 0x11a9c}, {0x11a9e, 0x11aa2}, - {0x11ac0, 0x11af8}, {0x11c00, 0x11c08}, {0x11c0a, 0x11c36}, {0x11c38, 0x11c45}, - {0x11c50, 0x11c6c}, {0x11c70, 0x11c8f}, {0x11c92, 0x11ca7}, {0x11ca9, 0x11cb6}, - {0x11d00, 0x11d06}, {0x11d0b, 0x11d36}, {0x11d3f, 0x11d47}, {0x11d50, 0x11d59}, + {0x10c80, 0x10cb2}, {0x10cc0, 0x10cf2}, {0x10cfa, 0x10d27}, {0x10d30, 0x10d39}, + {0x10e60, 0x10e7e}, {0x10f00, 0x10f27}, {0x10f30, 0x10f59}, {0x11000, 0x1104d}, + {0x11052, 0x1106f}, {0x1107f, 0x110bc}, {0x110be, 0x110c1}, {0x110d0, 0x110e8}, + {0x110f0, 0x110f9}, {0x11100, 0x11134}, {0x11136, 0x11146}, {0x11150, 0x11176}, + {0x11180, 0x111cd}, {0x111d0, 0x111df}, {0x111e1, 0x111f4}, {0x11200, 0x11211}, + {0x11213, 0x1123e}, {0x11280, 0x11286}, {0x1128a, 0x1128d}, {0x1128f, 0x1129d}, + {0x1129f, 0x112a9}, {0x112b0, 0x112ea}, {0x112f0, 0x112f9}, {0x11300, 0x11303}, + {0x11305, 0x1130c}, {0x11313, 0x11328}, {0x1132a, 0x11330}, {0x11335, 0x11339}, + {0x1133b, 0x11344}, {0x1134b, 0x1134d}, {0x1135d, 0x11363}, {0x11366, 0x1136c}, + {0x11370, 0x11374}, {0x11400, 0x11459}, {0x11480, 0x114c7}, {0x114d0, 0x114d9}, + {0x11580, 0x115b5}, {0x115b8, 0x115dd}, {0x11600, 0x11644}, {0x11650, 0x11659}, + {0x11660, 0x1166c}, {0x11680, 0x116b7}, {0x116c0, 0x116c9}, {0x11700, 0x1171a}, + {0x1171d, 0x1172b}, {0x11730, 0x1173f}, {0x11800, 0x1183b}, {0x118a0, 0x118f2}, + {0x11a00, 0x11a47}, {0x11a50, 0x11a83}, {0x11a86, 0x11aa2}, {0x11ac0, 0x11af8}, + {0x11c00, 0x11c08}, {0x11c0a, 0x11c36}, {0x11c38, 0x11c45}, {0x11c50, 0x11c6c}, + {0x11c70, 0x11c8f}, {0x11c92, 0x11ca7}, {0x11ca9, 0x11cb6}, {0x11d00, 0x11d06}, + {0x11d0b, 0x11d36}, {0x11d3f, 0x11d47}, {0x11d50, 0x11d59}, {0x11d60, 0x11d65}, + {0x11d6a, 0x11d8e}, {0x11d93, 0x11d98}, {0x11da0, 0x11da9}, {0x11ee0, 0x11ef8}, {0x12000, 0x12399}, {0x12400, 0x1246e}, {0x12470, 0x12474}, {0x12480, 0x12543}, {0x13000, 0x1342e}, {0x14400, 0x14646}, {0x16800, 0x16a38}, {0x16a40, 0x16a5e}, {0x16a60, 0x16a69}, {0x16ad0, 0x16aed}, {0x16af0, 0x16af5}, {0x16b00, 0x16b45}, {0x16b50, 0x16b59}, {0x16b5b, 0x16b61}, {0x16b63, 0x16b77}, {0x16b7d, 0x16b8f}, - {0x16f00, 0x16f44}, {0x16f50, 0x16f7e}, {0x16f8f, 0x16f9f}, {0x17000, 0x187ec}, - {0x18800, 0x18af2}, {0x1b000, 0x1b11e}, {0x1b170, 0x1b2fb}, {0x1bc00, 0x1bc6a}, - {0x1bc70, 0x1bc7c}, {0x1bc80, 0x1bc88}, {0x1bc90, 0x1bc99}, {0x1bc9c, 0x1bc9f}, - {0x1d000, 0x1d0f5}, {0x1d100, 0x1d126}, {0x1d129, 0x1d172}, {0x1d17b, 0x1d1e8}, - {0x1d200, 0x1d245}, {0x1d300, 0x1d356}, {0x1d360, 0x1d371}, {0x1d400, 0x1d454}, - {0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac}, {0x1d4ae, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, - {0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a}, {0x1d50d, 0x1d514}, {0x1d516, 0x1d51c}, - {0x1d51e, 0x1d539}, {0x1d53b, 0x1d53e}, {0x1d540, 0x1d544}, {0x1d54a, 0x1d550}, - {0x1d552, 0x1d6a5}, {0x1d6a8, 0x1d7cb}, {0x1d7ce, 0x1da8b}, {0x1da9b, 0x1da9f}, - {0x1daa1, 0x1daaf}, {0x1e000, 0x1e006}, {0x1e008, 0x1e018}, {0x1e01b, 0x1e021}, - {0x1e026, 0x1e02a}, {0x1e800, 0x1e8c4}, {0x1e8c7, 0x1e8d6}, {0x1e900, 0x1e94a}, - {0x1e950, 0x1e959}, {0x1ee00, 0x1ee03}, {0x1ee05, 0x1ee1f}, {0x1ee29, 0x1ee32}, - {0x1ee34, 0x1ee37}, {0x1ee4d, 0x1ee4f}, {0x1ee67, 0x1ee6a}, {0x1ee6c, 0x1ee72}, - {0x1ee74, 0x1ee77}, {0x1ee79, 0x1ee7c}, {0x1ee80, 0x1ee89}, {0x1ee8b, 0x1ee9b}, - {0x1eea1, 0x1eea3}, {0x1eea5, 0x1eea9}, {0x1eeab, 0x1eebb}, {0x1f000, 0x1f02b}, - {0x1f030, 0x1f093}, {0x1f0a0, 0x1f0ae}, {0x1f0b1, 0x1f0bf}, {0x1f0c1, 0x1f0cf}, - {0x1f0d1, 0x1f0f5}, {0x1f100, 0x1f10c}, {0x1f110, 0x1f12e}, {0x1f130, 0x1f16b}, - {0x1f170, 0x1f1ac}, {0x1f1e6, 0x1f202}, {0x1f210, 0x1f23b}, {0x1f240, 0x1f248}, - {0x1f260, 0x1f265}, {0x1f300, 0x1f6d4}, {0x1f6e0, 0x1f6ec}, {0x1f6f0, 0x1f6f8}, - {0x1f700, 0x1f773}, {0x1f780, 0x1f7d4}, {0x1f800, 0x1f80b}, {0x1f810, 0x1f847}, - {0x1f850, 0x1f859}, {0x1f860, 0x1f887}, {0x1f890, 0x1f8ad}, {0x1f900, 0x1f90b}, - {0x1f910, 0x1f93e}, {0x1f940, 0x1f94c}, {0x1f950, 0x1f96b}, {0x1f980, 0x1f997}, - {0x1f9d0, 0x1f9e6}, {0x20000, 0x2a6d6}, {0x2a700, 0x2b734}, {0x2b740, 0x2b81d}, - {0x2b820, 0x2cea1}, {0x2ceb0, 0x2ebe0}, {0x2f800, 0x2fa1d}, {0xe0100, 0xe01ef} + {0x16e40, 0x16e9a}, {0x16f00, 0x16f44}, {0x16f50, 0x16f7e}, {0x16f8f, 0x16f9f}, + {0x17000, 0x187f1}, {0x18800, 0x18af2}, {0x1b000, 0x1b11e}, {0x1b170, 0x1b2fb}, + {0x1bc00, 0x1bc6a}, {0x1bc70, 0x1bc7c}, {0x1bc80, 0x1bc88}, {0x1bc90, 0x1bc99}, + {0x1bc9c, 0x1bc9f}, {0x1d000, 0x1d0f5}, {0x1d100, 0x1d126}, {0x1d129, 0x1d172}, + {0x1d17b, 0x1d1e8}, {0x1d200, 0x1d245}, {0x1d2e0, 0x1d2f3}, {0x1d300, 0x1d356}, + {0x1d360, 0x1d378}, {0x1d400, 0x1d454}, {0x1d456, 0x1d49c}, {0x1d4a9, 0x1d4ac}, + {0x1d4ae, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d505}, {0x1d507, 0x1d50a}, + {0x1d50d, 0x1d514}, {0x1d516, 0x1d51c}, {0x1d51e, 0x1d539}, {0x1d53b, 0x1d53e}, + {0x1d540, 0x1d544}, {0x1d54a, 0x1d550}, {0x1d552, 0x1d6a5}, {0x1d6a8, 0x1d7cb}, + {0x1d7ce, 0x1da8b}, {0x1da9b, 0x1da9f}, {0x1daa1, 0x1daaf}, {0x1e000, 0x1e006}, + {0x1e008, 0x1e018}, {0x1e01b, 0x1e021}, {0x1e026, 0x1e02a}, {0x1e800, 0x1e8c4}, + {0x1e8c7, 0x1e8d6}, {0x1e900, 0x1e94a}, {0x1e950, 0x1e959}, {0x1ec71, 0x1ecb4}, + {0x1ee00, 0x1ee03}, {0x1ee05, 0x1ee1f}, {0x1ee29, 0x1ee32}, {0x1ee34, 0x1ee37}, + {0x1ee4d, 0x1ee4f}, {0x1ee67, 0x1ee6a}, {0x1ee6c, 0x1ee72}, {0x1ee74, 0x1ee77}, + {0x1ee79, 0x1ee7c}, {0x1ee80, 0x1ee89}, {0x1ee8b, 0x1ee9b}, {0x1eea1, 0x1eea3}, + {0x1eea5, 0x1eea9}, {0x1eeab, 0x1eebb}, {0x1f000, 0x1f02b}, {0x1f030, 0x1f093}, + {0x1f0a0, 0x1f0ae}, {0x1f0b1, 0x1f0bf}, {0x1f0c1, 0x1f0cf}, {0x1f0d1, 0x1f0f5}, + {0x1f100, 0x1f10c}, {0x1f110, 0x1f16b}, {0x1f170, 0x1f1ac}, {0x1f1e6, 0x1f202}, + {0x1f210, 0x1f23b}, {0x1f240, 0x1f248}, {0x1f260, 0x1f265}, {0x1f300, 0x1f6d4}, + {0x1f6e0, 0x1f6ec}, {0x1f6f0, 0x1f6f9}, {0x1f700, 0x1f773}, {0x1f780, 0x1f7d8}, + {0x1f800, 0x1f80b}, {0x1f810, 0x1f847}, {0x1f850, 0x1f859}, {0x1f860, 0x1f887}, + {0x1f890, 0x1f8ad}, {0x1f900, 0x1f90b}, {0x1f910, 0x1f93e}, {0x1f940, 0x1f970}, + {0x1f973, 0x1f976}, {0x1f97c, 0x1f9a2}, {0x1f9b0, 0x1f9b9}, {0x1f9c0, 0x1f9c2}, + {0x1f9d0, 0x1f9ff}, {0x1fa60, 0x1fa6d}, {0x20000, 0x2a6d6}, {0x2a700, 0x2b734}, + {0x2b740, 0x2b81d}, {0x2b820, 0x2cea1}, {0x2ceb0, 0x2ebe0}, {0x2f800, 0x2fa1d}, + {0xe0100, 0xe01ef} #endif }; #define NUM_GRAPH_RANGE (sizeof(graphRangeTable)/sizeof(crange)) static const chr graphCharTable[] = { - 0x38c, 0x589, 0x58a, 0x85e, 0x98f, 0x990, 0x9b2, 0x9c7, 0x9c8, - 0x9d7, 0x9dc, 0x9dd, 0xa0f, 0xa10, 0xa32, 0xa33, 0xa35, 0xa36, - 0xa38, 0xa39, 0xa3c, 0xa47, 0xa48, 0xa51, 0xa5e, 0xab2, 0xab3, - 0xad0, 0xb0f, 0xb10, 0xb32, 0xb33, 0xb47, 0xb48, 0xb56, 0xb57, - 0xb5c, 0xb5d, 0xb82, 0xb83, 0xb99, 0xb9a, 0xb9c, 0xb9e, 0xb9f, - 0xba3, 0xba4, 0xbd0, 0xbd7, 0xc55, 0xc56, 0xcd5, 0xcd6, 0xcde, - 0xcf1, 0xcf2, 0xd82, 0xd83, 0xdbd, 0xdca, 0xdd6, 0xe81, 0xe82, - 0xe84, 0xe87, 0xe88, 0xe8a, 0xe8d, 0xea5, 0xea7, 0xeaa, 0xeab, - 0xec6, 0x10c7, 0x10cd, 0x1258, 0x12c0, 0x1772, 0x1773, 0x1940, 0x1f59, - 0x1f5b, 0x1f5d, 0x2070, 0x2071, 0x2d27, 0x2d2d, 0x2d6f, 0x2d70, 0xfb3e, - 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfffc, 0xfffd -#if TCL_UTF_MAX > 4 + 0x38c, 0x85e, 0x98f, 0x990, 0x9b2, 0x9c7, 0x9c8, 0x9d7, 0x9dc, + 0x9dd, 0xa0f, 0xa10, 0xa32, 0xa33, 0xa35, 0xa36, 0xa38, 0xa39, + 0xa3c, 0xa47, 0xa48, 0xa51, 0xa5e, 0xab2, 0xab3, 0xad0, 0xb0f, + 0xb10, 0xb32, 0xb33, 0xb47, 0xb48, 0xb56, 0xb57, 0xb5c, 0xb5d, + 0xb82, 0xb83, 0xb99, 0xb9a, 0xb9c, 0xb9e, 0xb9f, 0xba3, 0xba4, + 0xbd0, 0xbd7, 0xc55, 0xc56, 0xcd5, 0xcd6, 0xcde, 0xcf1, 0xcf2, + 0xd82, 0xd83, 0xdbd, 0xdca, 0xdd6, 0xe81, 0xe82, 0xe84, 0xe87, + 0xe88, 0xe8a, 0xe8d, 0xea5, 0xea7, 0xeaa, 0xeab, 0xec6, 0x10c7, + 0x10cd, 0x1258, 0x12c0, 0x1772, 0x1773, 0x1940, 0x1f59, 0x1f5b, 0x1f5d, + 0x2070, 0x2071, 0x2d27, 0x2d2d, 0x2d6f, 0x2d70, 0xfb3e, 0xfb40, 0xfb41, + 0xfb43, 0xfb44, 0xfffc, 0xfffd +#if CHRBITS > 16 ,0x1003c, 0x1003d, 0x101a0, 0x1056f, 0x10808, 0x10837, 0x10838, 0x1083c, 0x108f4, 0x108f5, 0x1093f, 0x10a05, 0x10a06, 0x11288, 0x1130f, 0x11310, 0x11332, 0x11333, - 0x11347, 0x11348, 0x11350, 0x11357, 0x1145b, 0x1145d, 0x118ff, 0x11d08, 0x11d09, - 0x11d3a, 0x11d3c, 0x11d3d, 0x16a6e, 0x16a6f, 0x16fe0, 0x16fe1, 0x1d49e, 0x1d49f, - 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4bb, 0x1d546, 0x1e023, 0x1e024, 0x1e95e, 0x1e95f, - 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee27, 0x1ee39, 0x1ee3b, 0x1ee42, 0x1ee47, 0x1ee49, - 0x1ee4b, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee57, 0x1ee59, 0x1ee5b, 0x1ee5d, 0x1ee5f, - 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee7e, 0x1eef0, 0x1eef1, 0x1f250, 0x1f251, 0x1f9c0 + 0x11347, 0x11348, 0x11350, 0x11357, 0x1145b, 0x1145d, 0x1145e, 0x118ff, 0x11d08, + 0x11d09, 0x11d3a, 0x11d3c, 0x11d3d, 0x11d67, 0x11d68, 0x11d90, 0x11d91, 0x16a6e, + 0x16a6f, 0x16fe0, 0x16fe1, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4bb, + 0x1d546, 0x1e023, 0x1e024, 0x1e95e, 0x1e95f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee27, + 0x1ee39, 0x1ee3b, 0x1ee42, 0x1ee47, 0x1ee49, 0x1ee4b, 0x1ee51, 0x1ee52, 0x1ee54, + 0x1ee57, 0x1ee59, 0x1ee5b, 0x1ee5d, 0x1ee5f, 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee7e, + 0x1eef0, 0x1eef1, 0x1f250, 0x1f251, 0x1f97a #endif }; diff --git a/generic/regcustom.h b/generic/regcustom.h index c4dbc73..095385d 100644 --- a/generic/regcustom.h +++ b/generic/regcustom.h @@ -91,7 +91,7 @@ typedef int celt; /* Type to hold chr, or NOCELT */ #if TCL_UTF_MAX > 4 #define CHRBITS 32 /* Bits in a chr; must not use sizeof */ #define CHR_MIN 0x00000000 /* Smallest and largest chr; the value */ -#define CHR_MAX 0xffffffff /* CHR_MAX-CHR_MIN+1 should fit in uchr */ +#define CHR_MAX 0x10ffff /* CHR_MAX-CHR_MIN+1 should fit in uchr */ #else #define CHRBITS 16 /* Bits in a chr; must not use sizeof */ #define CHR_MIN 0x0000 /* Smallest and largest chr; the value */ diff --git a/generic/tclUniData.c b/generic/tclUniData.c index 9f05230..faca93d 100644 --- a/generic/tclUniData.c +++ b/generic/tclUniData.c @@ -42,22 +42,22 @@ static const unsigned short pageMap[] = { 4384, 4416, 1344, 4448, 4480, 4512, 4544, 1344, 4576, 4608, 4640, 4672, 1344, 4704, 4736, 4768, 4800, 4832, 1344, 4864, 4896, 4928, 4960, 1344, 4992, 5024, 5056, 5088, 1824, 1824, 5120, 5152, 5184, 5216, 5248, 5280, - 1344, 5312, 1344, 5344, 5376, 5408, 5440, 1824, 5472, 5504, 5536, 5568, - 5600, 5632, 5664, 5600, 704, 5696, 224, 224, 224, 224, 5728, 224, 224, - 224, 5760, 5792, 5824, 5856, 5888, 5920, 5952, 5984, 6016, 6048, 6080, - 6112, 6144, 6176, 6208, 6240, 6272, 6304, 6336, 6368, 6400, 6432, 6464, - 6496, 6528, 6528, 6528, 6528, 6528, 6528, 6528, 6528, 6560, 6592, 4928, - 6624, 6656, 6688, 6720, 6752, 4928, 6784, 6816, 6848, 6880, 6912, 6944, - 6976, 4928, 4928, 4928, 4928, 4928, 7008, 7040, 7072, 4928, 4928, 4928, - 7104, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 7136, 7168, 4928, 7200, - 7232, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 6528, 6528, 6528, - 6528, 7264, 6528, 7296, 7328, 6528, 6528, 6528, 6528, 6528, 6528, 6528, - 6528, 4928, 7360, 7392, 7424, 7456, 7488, 7520, 7552, 7584, 7616, 7648, + 1344, 5312, 1344, 5344, 5376, 5408, 5440, 5472, 5504, 5536, 5568, 5600, + 5632, 5664, 5696, 5632, 704, 5728, 224, 224, 224, 224, 5760, 224, 224, + 224, 5792, 5824, 5856, 5888, 5920, 5952, 5984, 6016, 6048, 6080, 6112, + 6144, 6176, 6208, 6240, 6272, 6304, 6336, 6368, 6400, 6432, 6464, 6496, + 6528, 6560, 6560, 6560, 6560, 6560, 6560, 6560, 6560, 6592, 6624, 4928, + 6656, 6688, 6720, 6752, 6784, 4928, 6816, 6848, 6880, 6912, 6944, 6976, + 7008, 4928, 4928, 4928, 4928, 4928, 7040, 7072, 7104, 4928, 4928, 4928, + 7136, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 7168, 7200, 4928, 7232, + 7264, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 6560, 6560, 6560, + 6560, 7296, 6560, 7328, 7360, 6560, 6560, 6560, 6560, 6560, 6560, 6560, + 6560, 4928, 7392, 7424, 7456, 7488, 4928, 7520, 7552, 7584, 7616, 7648, 7680, 224, 224, 224, 7712, 7744, 7776, 1344, 7808, 7840, 7872, 7872, 704, 7904, 7936, 7968, 1824, 8000, 4928, 4928, 8032, 4928, 4928, 4928, 4928, 4928, 4928, 8064, 8096, 8128, 8160, 3232, 1344, 8192, 4192, 1344, - 8224, 8256, 8288, 1344, 1344, 8320, 8352, 4928, 8384, 8416, 8448, 8480, - 4928, 8448, 8512, 4928, 8416, 4928, 4928, 4928, 4928, 4928, 4928, 4928, + 8224, 8256, 8288, 1344, 1344, 8320, 8352, 4928, 8384, 7552, 8416, 8448, + 4928, 8416, 8480, 4928, 7552, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, @@ -130,7 +130,7 @@ static const unsigned short pageMap[] = { 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1792, 8544, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, + 8512, 8544, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 8576, 4928, 8608, 5408, 1344, 1344, 1344, 1344, 1344, 1344, 1344, @@ -203,37 +203,37 @@ static const unsigned short pageMap[] = { 1344, 11520, 1824, 1824, 1824, 1824, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 7840, 4704, 10272, 1824, 1824, 1824, 1824, 11552, 11584, 11616, 11648, 4736, 11680, 1824, 11712, 11744, 11776, - 1824, 1824, 1344, 11808, 11840, 6848, 11872, 11904, 11936, 11968, 12000, + 1824, 1824, 1344, 11808, 11840, 6880, 11872, 11904, 11936, 11968, 12000, 1824, 12032, 12064, 1344, 12096, 12128, 12160, 12192, 12224, 1824, - 1824, 1344, 1344, 12256, 1824, 12288, 12320, 12352, 12384, 1824, 1824, - 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 12416, 1824, - 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 12448, - 12480, 12512, 12544, 5248, 12576, 12608, 12640, 12672, 12704, 12736, - 12768, 5248, 12800, 12832, 12864, 12896, 12928, 1824, 1824, 12960, - 12992, 13024, 13056, 13088, 2368, 13120, 13152, 1824, 1824, 1824, 1824, - 1344, 13184, 13216, 1824, 1344, 13248, 13280, 1824, 1824, 1824, 1824, - 1824, 1344, 13312, 13344, 1824, 1344, 13376, 13408, 13440, 1344, 13472, - 13504, 1824, 13536, 13568, 1824, 1824, 1824, 1824, 1824, 1824, 1824, - 1824, 1824, 1824, 1824, 13600, 13632, 13664, 1824, 1824, 1824, 1824, - 1824, 1824, 1824, 1824, 13696, 13728, 13760, 1344, 13792, 13824, 1344, - 13856, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 13888, 13920, - 13952, 13984, 14016, 14048, 1824, 1824, 14080, 14112, 14144, 1824, - 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, - 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1344, 1344, 1344, 1344, + 1824, 1344, 1344, 12256, 1824, 12288, 12320, 12352, 12384, 1344, 12416, + 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 12448, 1824, + 1824, 1824, 1824, 12000, 12480, 12512, 1824, 1824, 1824, 1824, 1824, + 12544, 12576, 12608, 12640, 5248, 12672, 12704, 12736, 12768, 12800, + 12832, 12864, 5248, 12896, 12928, 12960, 12992, 13024, 1824, 1824, + 13056, 13088, 13120, 13152, 13184, 13216, 13248, 13280, 1824, 1824, + 1824, 1824, 1344, 13312, 13344, 1824, 1344, 13376, 13408, 1824, 1824, + 1824, 1824, 1824, 1344, 13440, 13472, 1824, 1344, 13504, 13536, 13568, + 1344, 13600, 13632, 1824, 4032, 13664, 1824, 1824, 1824, 1824, 1824, + 1824, 1344, 13696, 1824, 1824, 1824, 13728, 13760, 13792, 1824, 1824, + 1824, 1824, 1824, 1824, 1824, 1824, 13824, 13856, 13888, 1344, 13920, + 13952, 1344, 4608, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, + 13984, 14016, 14048, 14080, 14112, 14144, 1824, 1824, 14176, 14208, + 14240, 14272, 14304, 13632, 1824, 1824, 1824, 1824, 1824, 1824, 1824, + 1824, 1824, 14336, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 9984, 1824, 1824, 1824, 10848, 10848, 10848, 14176, 1344, 1344, 1344, - 1344, 1344, 1344, 14208, 1824, 1824, 1824, 1824, 1824, 1824, 1824, + 1344, 1344, 1344, 1344, 9984, 1824, 1824, 1824, 10848, 10848, 10848, + 14368, 1344, 1344, 1344, 1344, 1344, 1344, 14400, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, - 1824, 1824, 1824, 1824, 1824, 1824, 1344, 1344, 1344, 1344, 1344, 1344, + 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 14240, 1824, 1824, 1824, 1824, 1824, 1824, 1824, + 1344, 1344, 1344, 1344, 1344, 1344, 1344, 14432, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, @@ -243,10 +243,9 @@ static const unsigned short pageMap[] = { 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, - 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 14272, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, + 1824, 1824, 1824, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, + 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 14464, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, @@ -268,12 +267,13 @@ static const unsigned short pageMap[] = { 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 13856, 4736, 14304, 1824, 1824, 10208, - 14336, 1344, 14368, 14400, 14432, 14464, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, - 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1344, 1344, - 14496, 14528, 14560, 1824, 1824, 14592, 1344, 1344, 1344, 1344, 1344, + 1824, 1824, 1824, 1824, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, + 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 4608, 4736, 14496, + 1824, 1824, 10208, 14528, 1344, 14560, 14592, 14624, 8512, 1824, 1824, + 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, + 1824, 1824, 1824, 1824, 1824, 1824, 1824, 13728, 13760, 14656, 1824, + 1824, 1824, 1344, 1344, 14688, 14720, 14752, 1824, 1824, 14784, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, @@ -289,9 +289,9 @@ static const unsigned short pageMap[] = { 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 14624, 1344, 1344, 1344, 1344, + 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 14816, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 14656, 1824, 1824, 1824, + 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 14848, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, @@ -316,17 +316,16 @@ static const unsigned short pageMap[] = { 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, - 1824, 1824, 1824, 1824, 1824, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 4736, 1824, 1824, 10208, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 9856, 1824, 1824, 1824, 1824, 1824, 1824, - 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, + 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1344, 1344, 1344, 1344, + 1344, 1344, 1344, 1344, 4736, 1824, 1824, 10208, 1344, 1344, 1344, + 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 9856, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, - 1824, 1824, 1824, 1824, 1824, 1824, 1344, 1344, 1344, 14688, 14720, - 14752, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, + 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1344, 1344, 1344, + 14880, 14912, 14944, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, @@ -338,41 +337,42 @@ static const unsigned short pageMap[] = { 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, - 4928, 4928, 4928, 4928, 4928, 4928, 4928, 8064, 4928, 14784, 4928, - 14816, 14848, 14880, 4928, 14912, 4928, 4928, 14944, 1824, 1824, 1824, - 1824, 1824, 4928, 4928, 14976, 15008, 1824, 1824, 1824, 1824, 15040, - 15072, 15104, 15136, 15168, 15200, 15232, 15264, 15296, 15328, 15360, - 15392, 15424, 15040, 15072, 15456, 15136, 15488, 15520, 15552, 15264, - 15584, 15616, 15648, 15680, 15712, 15744, 15776, 15808, 15840, 15872, - 15904, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, - 4928, 4928, 4928, 4928, 4928, 4928, 704, 15936, 704, 15968, 16000, - 16032, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, + 1824, 1824, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 8064, 4928, 14976, + 4928, 15008, 15040, 15072, 4928, 15104, 4928, 4928, 15136, 1824, 1824, + 1824, 1824, 15168, 4928, 4928, 15200, 15232, 1824, 1824, 1824, 1824, + 15264, 15296, 15328, 15360, 15392, 15424, 15456, 15488, 15520, 15552, + 15584, 15616, 15648, 15264, 15296, 15680, 15360, 15712, 15744, 15776, + 15488, 15808, 15840, 15872, 15904, 15936, 15968, 16000, 16032, 16064, + 16096, 16128, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, + 4928, 4928, 4928, 4928, 4928, 4928, 4928, 704, 16160, 704, 16192, 16224, + 16256, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, - 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 16064, 16096, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, + 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 16288, 16320, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, - 1824, 1344, 1344, 1344, 1344, 1344, 1344, 16128, 1824, 16160, 16192, - 16224, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, + 1824, 1344, 1344, 1344, 1344, 1344, 1344, 16352, 1824, 16384, 16416, + 16448, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, - 1824, 1824, 1824, 16256, 16288, 16320, 16352, 16384, 16416, 1824, 16448, - 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 4928, 16480, 4928, - 4928, 8032, 16512, 16544, 8064, 16576, 16608, 4928, 16480, 4928, 16640, - 1824, 16672, 16704, 16736, 16768, 16800, 1824, 1824, 1824, 1824, 4928, - 4928, 4928, 4928, 4928, 4928, 4928, 16832, 4928, 4928, 4928, 4928, + 1824, 1824, 16480, 6880, 16512, 1824, 1824, 1824, 1824, 1824, 1824, + 1824, 1824, 1824, 1824, 16544, 16576, 16608, 16640, 16672, 16704, 1824, + 16736, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 4928, 16768, + 4928, 4928, 8032, 16800, 16832, 8064, 16864, 4928, 4928, 16768, 4928, + 16896, 1824, 16928, 16960, 16992, 17024, 17056, 1824, 1824, 1824, 1824, + 4928, 4928, 4928, 4928, 4928, 4928, 4928, 17088, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, - 4928, 4928, 4928, 4928, 4928, 4928, 16864, 16896, 4928, 4928, 4928, - 8032, 4928, 4928, 16864, 1824, 16480, 4928, 16928, 4928, 16960, 16992, - 1824, 1824, 16480, 8416, 17024, 17056, 17088, 1824, 17120, 6784, 1824, + 4928, 4928, 4928, 4928, 4928, 4928, 4928, 17120, 17152, 4928, 4928, + 4928, 8032, 4928, 4928, 17184, 1824, 16768, 4928, 17216, 4928, 17248, + 17280, 1824, 1824, 16768, 7552, 4928, 17312, 4928, 17344, 16960, 4928, + 1824, 1824, 1824, 17280, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, - 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, + 1824, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, @@ -483,7 +483,7 @@ static const unsigned short pageMap[] = { 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 7840, 1824, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, + 1344, 1344, 1344, 7840, 1824, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, @@ -494,7 +494,7 @@ static const unsigned short pageMap[] = { 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 17152, 1344, 1344, 1344, 1344, 1344, 1344, 11360, 1344, 1344, 1344, + 1344, 1344, 17376, 1344, 1344, 1344, 1344, 1344, 1344, 11360, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, @@ -509,7 +509,7 @@ static const unsigned short pageMap[] = { 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 17184, 1344, + 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 17408, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, @@ -529,7 +529,7 @@ static const unsigned short pageMap[] = { 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 17216, 1824, 1824, 1824, 1824, 1824, 1824, + 1344, 1344, 1344, 1344, 1344, 17440, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, @@ -537,8 +537,8 @@ static const unsigned short pageMap[] = { 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, - 1824, 1824, 1824, 1824, 1824, 1824, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 11360 + 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1344, 1344, 1344, 1344, 1344, + 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 11360 #endif /* TCL_UTF_MAX > 3 */ }; @@ -616,100 +616,100 @@ static const unsigned char groupMap[] = { 23, 24, 23, 24, 0, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, - 0, 0, 91, 3, 3, 3, 3, 3, 3, 0, 123, 123, 123, 123, 123, 123, 123, 123, + 0, 0, 91, 3, 3, 3, 3, 3, 3, 21, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 123, 21, 0, 3, 8, 0, 0, 14, 14, 4, 0, 92, 92, 92, 92, 92, 92, + 123, 123, 123, 21, 21, 3, 8, 0, 0, 14, 14, 4, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, - 92, 92, 92, 92, 92, 8, 92, 3, 92, 92, 3, 92, 92, 3, 92, 0, 0, 0, 0, - 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, - 15, 15, 15, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17, - 17, 17, 7, 7, 7, 3, 3, 4, 3, 3, 14, 14, 92, 92, 92, 92, 92, 92, 92, - 92, 92, 92, 92, 3, 17, 0, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 91, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, - 92, 92, 92, 92, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 15, 15, 92, + 92, 92, 92, 92, 92, 92, 8, 92, 3, 92, 92, 3, 92, 92, 3, 92, 0, 0, 0, + 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, + 15, 15, 15, 15, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, + 17, 17, 17, 7, 7, 7, 3, 3, 4, 3, 3, 14, 14, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 3, 17, 0, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 91, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 15, 15, + 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 3, 15, 92, 92, 92, 92, 92, 92, 92, 17, 14, 92, 92, 92, 92, 92, - 92, 91, 91, 92, 92, 14, 92, 92, 92, 92, 15, 15, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 15, 15, 15, 14, 14, 15, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 0, 17, 15, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 3, 15, 92, 92, 92, 92, 92, 92, 92, 17, 14, 92, 92, 92, 92, + 92, 92, 91, 91, 92, 92, 14, 92, 92, 92, 92, 15, 15, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 15, 15, 15, 14, 14, 15, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 0, 17, 15, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, - 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0, 0, 15, 15, 15, 15, 15, + 15, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 15, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, + 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 15, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, - 92, 92, 92, 92, 92, 92, 92, 91, 91, 14, 3, 3, 3, 91, 0, 0, 0, 0, 0, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 91, 91, 14, 3, 3, 3, 91, 0, 0, + 92, 4, 4, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 91, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 91, 92, 92, 92, 91, 92, 92, 92, 92, 92, 0, 0, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 92, 92, 92, 92, 91, 92, 92, 92, 92, 92, 92, 92, - 92, 92, 91, 92, 92, 92, 91, 92, 92, 92, 92, 92, 0, 0, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, - 92, 92, 0, 0, 3, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, + 15, 92, 92, 92, 0, 0, 3, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, - 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 17, 92, 92, 92, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, + 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 17, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, - 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 124, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, - 124, 92, 15, 124, 124, 124, 92, 92, 92, 92, 92, 92, 92, 92, 124, 124, - 124, 124, 92, 124, 124, 15, 92, 92, 92, 92, 92, 92, 92, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 92, 92, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 3, 91, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 92, 124, 124, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 0, 0, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 0, 0, 0, - 15, 15, 15, 15, 0, 0, 92, 15, 124, 124, 124, 92, 92, 92, 92, 0, 0, - 124, 124, 0, 0, 124, 124, 92, 15, 0, 0, 0, 0, 0, 0, 0, 0, 124, 0, 0, - 0, 0, 15, 15, 0, 15, 15, 15, 92, 92, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 15, 15, 4, 4, 18, 18, 18, 18, 18, 18, 14, 4, 15, 3, 0, 0, 0, - 92, 92, 124, 0, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 15, 15, 0, 0, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 15, - 0, 15, 15, 0, 0, 92, 0, 124, 124, 124, 92, 92, 0, 0, 0, 0, 92, 92, - 0, 0, 92, 92, 92, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, - 0, 15, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 92, 92, 15, - 15, 15, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 124, 0, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 124, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 92, 124, 92, 15, 124, 124, 124, 92, 92, 92, 92, 92, 92, 92, + 92, 124, 124, 124, 124, 92, 124, 124, 15, 92, 92, 92, 92, 92, 92, 92, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 3, 3, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 3, 91, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 92, 124, 124, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, + 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, + 0, 0, 0, 15, 15, 15, 15, 0, 0, 92, 15, 124, 124, 124, 92, 92, 92, 92, + 0, 0, 124, 124, 0, 0, 124, 124, 92, 15, 0, 0, 0, 0, 0, 0, 0, 0, 124, + 0, 0, 0, 0, 15, 15, 0, 15, 15, 15, 92, 92, 0, 0, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 15, 15, 4, 4, 18, 18, 18, 18, 18, 18, 14, 4, 15, 3, 92, + 0, 0, 92, 92, 124, 0, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 15, 15, 0, + 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, + 15, 15, 0, 15, 15, 0, 0, 92, 0, 124, 124, 124, 92, 92, 0, 0, 0, 0, + 92, 92, 0, 0, 92, 92, 92, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 15, 15, + 15, 15, 0, 15, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 92, + 92, 15, 15, 15, 92, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 124, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 0, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, + 0, 0, 92, 15, 124, 124, 124, 92, 92, 92, 92, 92, 0, 92, 92, 124, 0, + 124, 124, 92, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 92, 92, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 4, 0, 0, 0, + 0, 0, 0, 0, 15, 92, 92, 92, 92, 92, 92, 0, 92, 124, 124, 0, 15, 15, + 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 0, 0, - 92, 15, 124, 124, 124, 92, 92, 92, 92, 92, 0, 92, 92, 124, 0, 124, - 124, 92, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, - 15, 92, 92, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 4, 0, 0, 0, 0, 0, - 0, 0, 15, 92, 92, 92, 92, 92, 92, 0, 92, 124, 124, 0, 15, 15, 15, 15, - 15, 15, 15, 15, 0, 0, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, - 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 0, 0, 92, 15, - 124, 92, 124, 92, 92, 92, 92, 0, 0, 124, 124, 0, 0, 124, 124, 92, 0, - 0, 0, 0, 0, 0, 0, 0, 92, 124, 0, 0, 0, 0, 15, 15, 0, 15, 15, 15, 92, - 92, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 14, 15, 18, 18, 18, 18, 18, - 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 15, 0, 15, 15, 15, 15, 15, 15, - 0, 0, 0, 15, 15, 15, 0, 15, 15, 15, 15, 0, 0, 0, 15, 15, 0, 15, 0, - 15, 15, 0, 0, 0, 15, 15, 0, 0, 0, 15, 15, 15, 0, 0, 0, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 124, 124, 92, 124, + 92, 15, 124, 92, 124, 92, 92, 92, 92, 0, 0, 124, 124, 0, 0, 124, 124, + 92, 0, 0, 0, 0, 0, 0, 0, 0, 92, 124, 0, 0, 0, 0, 15, 15, 0, 15, 15, + 15, 92, 92, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 14, 15, 18, 18, 18, + 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 15, 0, 15, 15, 15, 15, + 15, 15, 0, 0, 0, 15, 15, 15, 0, 15, 15, 15, 15, 0, 0, 0, 15, 15, 0, + 15, 0, 15, 15, 0, 0, 0, 15, 15, 0, 0, 0, 15, 15, 15, 0, 0, 0, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 124, 124, 92, 124, 124, 0, 0, 0, 124, 124, 124, 0, 124, 124, 124, 92, 0, 0, 15, 0, 0, 0, 0, 0, 0, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 18, 14, 14, 14, 14, 14, 14, 4, 14, 0, - 0, 0, 0, 0, 92, 124, 124, 124, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, - 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 0, 0, 0, 0, 92, 124, 124, 124, 92, 15, 15, 15, 15, 15, 15, 15, 15, + 0, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 15, 92, 92, 92, 124, 124, 124, 124, 0, 92, 92, 92, 0, 92, 92, 92, 92, 0, 0, 0, 0, 0, 0, 0, 92, 92, 0, 15, 15, 15, 0, 0, 0, 0, 0, 15, 15, 92, 92, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, - 18, 18, 14, 15, 92, 124, 124, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, + 18, 18, 14, 15, 92, 124, 124, 3, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 0, 0, 92, 15, 124, 92, 124, @@ -764,353 +764,355 @@ static const unsigned char groupMap[] = { 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 0, 125, 0, 0, 0, 0, 0, 125, 0, 0, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 91, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, - 15, 15, 0, 15, 0, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 0, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, - 15, 15, 15, 0, 15, 0, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 0, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 92, 92, 92, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, - 0, 0, 0, 0, 0, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, - 126, 126, 126, 126, 126, 126, 126, 126, 126, 104, 104, 104, 104, 104, - 104, 0, 0, 110, 110, 110, 110, 110, 110, 0, 0, 8, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 5, - 6, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 3, 3, 127, - 127, 127, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, - 92, 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 3, 3, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, - 0, 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, - 124, 92, 92, 92, 92, 92, 92, 92, 124, 124, 124, 124, 124, 124, 124, - 124, 92, 124, 124, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 3, 3, - 3, 91, 3, 3, 3, 4, 15, 92, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, - 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, - 0, 3, 3, 3, 3, 3, 3, 8, 3, 3, 3, 3, 92, 92, 92, 17, 0, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 15, 15, 15, 91, 15, 15, 15, 15, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 3, 91, 126, 126, 126, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, + 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 0, 15, 15, 15, + 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, + 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 0, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 0, 15, + 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, - 0, 0, 0, 0, 15, 15, 15, 15, 15, 92, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 15, 0, 0, 0, 0, 0, 15, + 15, 0, 0, 92, 92, 92, 3, 3, 3, 3, 3, 3, 3, 3, 3, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 104, 104, 104, 104, 104, 104, 0, 0, 110, 110, 110, 110, + 110, 110, 0, 0, 8, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 3, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 5, 6, 0, 0, 0, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 3, 3, 3, 128, 128, 128, 15, 15, 15, 15, + 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 92, 92, 92, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 92, 92, 92, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, + 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 0, 92, 92, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 124, 92, 92, 92, 92, 92, 92, + 92, 124, 124, 124, 124, 124, 124, 124, 124, 92, 124, 124, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 3, 3, 3, 91, 3, 3, 3, 4, 15, 92, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 8, 3, 3, + 3, 3, 92, 92, 92, 17, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, + 0, 0, 15, 15, 15, 91, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 0, 92, 92, 92, 124, 124, 124, 124, 92, - 92, 124, 124, 124, 0, 0, 0, 0, 124, 124, 92, 124, 124, 124, 124, 124, - 124, 92, 92, 92, 0, 0, 0, 0, 14, 0, 0, 0, 3, 3, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, - 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 0, 0, 0, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, + 92, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 92, 92, 124, 124, 92, 0, 0, 3, 3, 15, 15, 15, + 15, 15, 92, 15, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 124, 92, 124, 92, 92, 92, 92, 92, 92, 92, 0, 92, 124, 92, 124, - 124, 92, 92, 92, 92, 92, 92, 92, 92, 124, 124, 124, 124, 124, 124, - 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0, 0, 92, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, - 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 91, 3, 3, 3, 3, 3, 3, 0, 0, 92, 92, 92, - 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 119, 0, 92, 92, 92, 92, - 124, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, + 92, 92, 92, 124, 124, 124, 124, 92, 92, 124, 124, 124, 0, 0, 0, 0, + 124, 124, 92, 124, 124, 124, 124, 124, 124, 92, 92, 92, 0, 0, 0, 0, + 14, 0, 0, 0, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 124, 92, - 92, 92, 92, 92, 124, 92, 124, 124, 124, 124, 124, 92, 124, 124, 15, - 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, - 3, 3, 3, 3, 3, 3, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 92, 92, 92, - 92, 92, 92, 92, 92, 92, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, - 92, 92, 124, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, - 92, 92, 92, 92, 124, 124, 92, 92, 124, 92, 92, 92, 15, 15, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 92, 124, 92, 92, 124, 124, 124, 92, 124, 92, 92, 92, 124, 124, 0, 0, - 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 15, 15, 15, 15, 124, 124, 124, 124, 124, - 124, 124, 124, 92, 92, 92, 92, 92, 92, 92, 92, 124, 124, 92, 92, 0, - 0, 0, 3, 3, 3, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 15, 15, - 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 91, 91, 91, 91, 91, 91, 3, 3, 128, 129, 130, 131, 131, - 132, 133, 134, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 92, 92, 92, 3, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, - 124, 92, 92, 92, 92, 92, 92, 92, 15, 15, 15, 15, 92, 15, 15, 15, 15, - 124, 124, 92, 15, 15, 124, 92, 92, 0, 0, 0, 0, 0, 0, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, + 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 0, 0, 0, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 92, 92, 124, 124, 92, 0, 0, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 92, 124, 92, 92, + 92, 92, 92, 92, 92, 0, 92, 124, 92, 124, 124, 92, 92, 92, 92, 92, 92, + 92, 92, 124, 124, 124, 124, 124, 124, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 0, 0, 92, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 91, + 3, 3, 3, 3, 3, 3, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 119, 0, 92, 92, 92, 92, 124, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 92, 124, 92, 92, 92, 92, 92, 124, 92, 124, + 124, 124, 124, 124, 92, 124, 124, 15, 15, 15, 15, 15, 15, 15, 0, 0, + 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 3, 3, 3, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 92, 92, 92, 92, 92, 92, 92, 92, 92, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 92, 92, 124, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 92, 92, 92, 92, 124, 124, + 92, 92, 124, 92, 92, 92, 15, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 124, 92, 92, 124, 124, + 124, 92, 124, 92, 92, 92, 124, 124, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, + 3, 15, 15, 15, 15, 124, 124, 124, 124, 124, 124, 124, 124, 92, 92, + 92, 92, 92, 92, 92, 92, 124, 124, 92, 92, 0, 0, 0, 3, 3, 3, 3, 3, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 15, 15, 15, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 91, 91, + 91, 91, 91, 91, 3, 3, 129, 130, 131, 132, 132, 133, 134, 135, 136, + 0, 0, 0, 0, 0, 0, 0, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, + 137, 137, 137, 137, 137, 0, 0, 137, 137, 137, 3, 3, 3, 3, 3, 3, 3, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 92, 3, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 124, 92, 92, 92, 92, 92, 92, 92, 15, 15, 15, + 15, 92, 15, 15, 15, 15, 124, 124, 92, 15, 15, 124, 92, 92, 0, 0, 0, + 0, 0, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, - 91, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 91, 136, 21, - 21, 21, 137, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 91, 91, - 91, 91, 91, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, - 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0, 92, 92, 92, 92, - 92, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, - 23, 24, 23, 24, 23, 24, 21, 21, 21, 21, 21, 138, 21, 21, 139, 21, 140, - 140, 140, 140, 140, 140, 140, 140, 141, 141, 141, 141, 141, 141, 141, - 141, 140, 140, 140, 140, 140, 140, 0, 0, 141, 141, 141, 141, 141, 141, - 0, 0, 140, 140, 140, 140, 140, 140, 140, 140, 141, 141, 141, 141, 141, - 141, 141, 141, 140, 140, 140, 140, 140, 140, 140, 140, 141, 141, 141, - 141, 141, 141, 141, 141, 140, 140, 140, 140, 140, 140, 0, 0, 141, 141, - 141, 141, 141, 141, 0, 0, 21, 140, 21, 140, 21, 140, 21, 140, 0, 141, - 0, 141, 0, 141, 0, 141, 140, 140, 140, 140, 140, 140, 140, 140, 141, - 141, 141, 141, 141, 141, 141, 141, 142, 142, 143, 143, 143, 143, 144, - 144, 145, 145, 146, 146, 147, 147, 0, 0, 140, 140, 140, 140, 140, 140, - 140, 140, 148, 148, 148, 148, 148, 148, 148, 148, 140, 140, 140, 140, - 140, 140, 140, 140, 148, 148, 148, 148, 148, 148, 148, 148, 140, 140, - 140, 140, 140, 140, 140, 140, 148, 148, 148, 148, 148, 148, 148, 148, - 140, 140, 21, 149, 21, 0, 21, 21, 141, 141, 150, 150, 151, 11, 152, - 11, 11, 11, 21, 149, 21, 0, 21, 21, 153, 153, 153, 153, 151, 11, 11, - 11, 140, 140, 21, 21, 0, 0, 21, 21, 141, 141, 154, 154, 0, 11, 11, - 11, 140, 140, 21, 21, 21, 113, 21, 21, 141, 141, 155, 155, 117, 11, - 11, 11, 0, 0, 21, 149, 21, 0, 21, 21, 156, 156, 157, 157, 151, 11, - 11, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 17, 17, 17, 17, 17, 8, 8, 8, - 8, 8, 8, 3, 3, 16, 20, 5, 16, 16, 20, 5, 16, 3, 3, 3, 3, 3, 3, 3, 3, - 158, 159, 17, 17, 17, 17, 17, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 16, 20, - 3, 3, 3, 3, 12, 12, 3, 3, 3, 7, 5, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 7, 3, 12, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 17, 17, 17, 17, 17, 0, - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 91, 0, 0, 18, 18, 18, 18, - 18, 18, 7, 7, 7, 5, 6, 91, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 7, 7, 7, 5, 6, 0, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, - 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, - 119, 119, 119, 119, 92, 119, 119, 119, 92, 92, 92, 92, 92, 92, 92, - 92, 92, 92, 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, - 14, 107, 14, 14, 14, 14, 107, 14, 14, 21, 107, 107, 107, 21, 21, 107, - 107, 107, 21, 14, 107, 14, 14, 7, 107, 107, 107, 107, 107, 14, 14, - 14, 14, 14, 14, 107, 14, 160, 14, 107, 14, 161, 162, 107, 107, 14, - 21, 107, 107, 163, 107, 21, 15, 15, 15, 15, 21, 14, 14, 21, 21, 107, - 107, 7, 7, 7, 7, 7, 107, 21, 21, 21, 21, 14, 7, 14, 14, 164, 14, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 165, 165, - 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, - 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, - 166, 166, 127, 127, 127, 23, 24, 127, 127, 127, 127, 18, 14, 14, 0, - 0, 0, 0, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 7, 7, 14, 14, 14, 14, 7, - 14, 14, 7, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 7, 14, 14, 14, 14, + 91, 91, 91, 91, 91, 91, 91, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 91, 138, 21, 21, 21, 139, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 91, 91, 91, 91, 91, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 0, 92, 92, 92, 92, 92, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, + 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 21, 21, 21, 21, 21, + 140, 21, 21, 141, 21, 142, 142, 142, 142, 142, 142, 142, 142, 143, + 143, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, 142, 142, 0, + 0, 143, 143, 143, 143, 143, 143, 0, 0, 142, 142, 142, 142, 142, 142, + 142, 142, 143, 143, 143, 143, 143, 143, 143, 143, 142, 142, 142, 142, + 142, 142, 142, 142, 143, 143, 143, 143, 143, 143, 143, 143, 142, 142, + 142, 142, 142, 142, 0, 0, 143, 143, 143, 143, 143, 143, 0, 0, 21, 142, + 21, 142, 21, 142, 21, 142, 0, 143, 0, 143, 0, 143, 0, 143, 142, 142, + 142, 142, 142, 142, 142, 142, 143, 143, 143, 143, 143, 143, 143, 143, + 144, 144, 145, 145, 145, 145, 146, 146, 147, 147, 148, 148, 149, 149, + 0, 0, 142, 142, 142, 142, 142, 142, 142, 142, 150, 150, 150, 150, 150, + 150, 150, 150, 142, 142, 142, 142, 142, 142, 142, 142, 150, 150, 150, + 150, 150, 150, 150, 150, 142, 142, 142, 142, 142, 142, 142, 142, 150, + 150, 150, 150, 150, 150, 150, 150, 142, 142, 21, 151, 21, 0, 21, 21, + 143, 143, 152, 152, 153, 11, 154, 11, 11, 11, 21, 151, 21, 0, 21, 21, + 155, 155, 155, 155, 153, 11, 11, 11, 142, 142, 21, 21, 0, 0, 21, 21, + 143, 143, 156, 156, 0, 11, 11, 11, 142, 142, 21, 21, 21, 113, 21, 21, + 143, 143, 157, 157, 117, 11, 11, 11, 0, 0, 21, 151, 21, 0, 21, 21, + 158, 158, 159, 159, 153, 11, 11, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 17, 17, 17, 17, 17, 8, 8, 8, 8, 8, 8, 3, 3, 16, 20, 5, 16, 16, 20, + 5, 16, 3, 3, 3, 3, 3, 3, 3, 3, 160, 161, 17, 17, 17, 17, 17, 2, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 16, 20, 3, 3, 3, 3, 12, 12, 3, 3, 3, 7, 5, + 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 12, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 2, 17, 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 18, 91, 0, 0, 18, 18, 18, 18, 18, 18, 7, 7, 7, 5, 6, 91, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 7, 7, 7, 5, 6, 0, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 119, 119, 119, 119, 92, 119, 119, + 119, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 107, 14, 14, 14, 14, 107, 14, + 14, 21, 107, 107, 107, 21, 21, 107, 107, 107, 21, 14, 107, 14, 14, + 7, 107, 107, 107, 107, 107, 14, 14, 14, 14, 14, 14, 107, 14, 162, 14, + 107, 14, 163, 164, 107, 107, 14, 21, 107, 107, 165, 107, 21, 15, 15, + 15, 15, 21, 14, 14, 21, 21, 107, 107, 7, 7, 7, 7, 7, 107, 21, 21, 21, + 21, 14, 7, 14, 14, 166, 14, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 167, 167, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 167, 167, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 128, 128, 128, 23, 24, + 128, 128, 128, 128, 18, 14, 14, 0, 0, 0, 0, 7, 7, 7, 7, 7, 14, 14, + 14, 14, 14, 7, 7, 14, 14, 14, 14, 7, 14, 14, 7, 14, 14, 7, 14, 14, + 14, 14, 14, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 14, 14, 7, 14, 7, 14, + 14, 14, 14, 7, 7, 14, 14, 7, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, + 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, - 14, 14, 14, 5, 6, 5, 6, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 14, 14, 14, 14, 14, 14, 14, - 5, 6, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 5, 6, 5, 6, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, + 14, 7, 7, 14, 14, 14, 14, 14, 14, 14, 5, 6, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, + 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 14, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 167, 167, 167, 167, 167, 167, 167, 167, - 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, - 167, 167, 167, 167, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, - 168, 168, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, + 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, 7, 7, 7, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 18, 18, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 7, 7, 7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 5, 6, 5, 6, + 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, - 6, 5, 6, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 6, 5, 6, 7, 7, 7, 7, 7, 7, + 18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7, + 7, 7, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 6, 5, 6, 5, + 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 5, 6, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 14, 14, 7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, + 7, 7, 5, 6, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 6, 7, 7, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 14, 14, 7, 7, 7, 7, + 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, + 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, + 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, - 122, 122, 122, 122, 122, 122, 122, 122, 122, 0, 123, 123, 123, 123, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 0, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, - 123, 0, 23, 24, 169, 170, 171, 172, 173, 23, 24, 23, 24, 23, 24, 174, - 175, 176, 177, 21, 23, 24, 21, 23, 24, 21, 21, 21, 21, 21, 91, 91, - 178, 178, 23, 24, 23, 24, 21, 14, 14, 14, 14, 14, 14, 23, 24, 23, 24, - 92, 92, 92, 23, 24, 0, 0, 0, 0, 0, 3, 3, 3, 3, 18, 3, 3, 179, 179, - 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, - 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, - 179, 179, 179, 179, 179, 179, 179, 179, 0, 179, 0, 0, 0, 0, 0, 179, - 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 91, 3, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, - 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, - 0, 3, 3, 16, 20, 16, 20, 3, 3, 3, 16, 20, 3, 16, 20, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 8, 3, 3, 8, 3, 16, 20, 3, 3, 16, 20, 5, 6, 5, 6, 5, 6, - 5, 6, 3, 3, 3, 3, 3, 91, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 8, 8, 3, 3, - 3, 3, 8, 3, 5, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 123, 123, 123, 123, 123, 0, 23, 24, 171, 172, 173, 174, 175, 23, 24, + 23, 24, 23, 24, 176, 177, 178, 179, 21, 23, 24, 21, 23, 24, 21, 21, + 21, 21, 21, 91, 91, 180, 180, 23, 24, 23, 24, 21, 14, 14, 14, 14, 14, + 14, 23, 24, 23, 24, 92, 92, 92, 23, 24, 0, 0, 0, 0, 0, 3, 3, 3, 3, + 18, 3, 3, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, + 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, + 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 0, 181, + 0, 0, 0, 0, 0, 181, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, + 0, 0, 91, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, + 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, + 15, 15, 15, 15, 15, 15, 15, 0, 3, 3, 16, 20, 16, 20, 3, 3, 3, 16, 20, + 3, 16, 20, 3, 3, 3, 3, 3, 3, 3, 3, 3, 8, 3, 3, 8, 3, 16, 20, 3, 3, + 16, 20, 5, 6, 5, 6, 5, 6, 5, 6, 3, 3, 3, 3, 3, 91, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 8, 8, 3, 3, 3, 3, 8, 3, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 0, 0, 0, 0, 2, 3, 3, 3, 14, 91, 15, 127, 5, 6, 5, 6, 5, - 6, 5, 6, 5, 6, 14, 14, 5, 6, 5, 6, 5, 6, 5, 6, 8, 5, 6, 6, 14, 127, - 127, 127, 127, 127, 127, 127, 127, 127, 92, 92, 92, 92, 124, 124, 8, - 91, 91, 91, 91, 91, 14, 14, 127, 127, 127, 91, 15, 3, 14, 14, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 0, 0, 92, 92, 11, 11, 91, 91, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 3, 91, 91, 91, 15, 0, 0, 0, 0, 0, 15, 15, 15, 15, + 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 2, 3, 3, 3, 14, 91, + 15, 128, 5, 6, 5, 6, 5, 6, 5, 6, 5, 6, 14, 14, 5, 6, 5, 6, 5, 6, 5, + 6, 8, 5, 6, 6, 14, 128, 128, 128, 128, 128, 128, 128, 128, 128, 92, + 92, 92, 92, 124, 124, 8, 91, 91, 91, 91, 91, 14, 14, 128, 128, 128, + 91, 15, 3, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 92, 92, 11, 11, 91, + 91, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 91, 91, 91, 15, + 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 14, 14, 18, 18, 18, 18, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 0, 14, 14, 18, 18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 14, 14, - 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 18, 18, 18, - 18, 18, 18, 18, 18, 14, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 91, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 14, 14, + 15, 15, 15, 0, 0, 0, 0, 0, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, + 14, 14, 14, 14, 14, 14, 14, 14, 18, 18, 18, 18, 18, 18, 18, 18, 14, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 91, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 91, 3, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 24, 23, - 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 15, 92, 119, 119, 119, - 3, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 3, 91, 23, 24, 23, 24, 23, - 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, - 23, 24, 23, 24, 23, 24, 91, 91, 92, 92, 15, 15, 15, 15, 15, 15, 127, - 127, 127, 127, 127, 127, 127, 127, 127, 127, 92, 92, 3, 3, 3, 3, 3, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 91, 91, 91, 91, - 91, 91, 91, 91, 91, 11, 11, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, - 23, 24, 23, 24, 21, 21, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, - 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, - 23, 24, 91, 21, 21, 21, 21, 21, 21, 21, 21, 23, 24, 23, 24, 180, 23, - 24, 23, 24, 23, 24, 23, 24, 23, 24, 91, 11, 11, 23, 24, 181, 21, 15, - 23, 24, 23, 24, 21, 21, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, - 24, 23, 24, 23, 24, 23, 24, 23, 24, 182, 183, 184, 185, 182, 0, 186, - 187, 188, 189, 23, 24, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 91, 91, - 21, 15, 15, 15, 15, 15, 15, 15, 92, 15, 15, 15, 92, 15, 15, 15, 15, - 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 124, 124, 92, 92, 124, 14, 14, 14, 14, - 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 14, 14, 4, 14, 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 124, 124, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 91, 3, 3, 3, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 15, + 92, 119, 119, 119, 3, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 3, 91, + 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, + 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 91, 91, 92, 92, 15, 15, + 15, 15, 15, 15, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 92, + 92, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 11, 11, 23, 24, 23, 24, 23, 24, + 23, 24, 23, 24, 23, 24, 23, 24, 21, 21, 23, 24, 23, 24, 23, 24, 23, + 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, + 23, 24, 23, 24, 23, 24, 91, 21, 21, 21, 21, 21, 21, 21, 21, 23, 24, + 23, 24, 182, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 91, 11, 11, 23, + 24, 183, 21, 15, 23, 24, 23, 24, 21, 21, 23, 24, 23, 24, 23, 24, 23, + 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 23, 24, 184, 185, 186, + 187, 184, 21, 188, 189, 190, 191, 23, 24, 23, 24, 23, 24, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 15, 91, 91, 21, 15, 15, 15, 15, 15, 15, 15, 92, 15, 15, 15, + 92, 15, 15, 15, 15, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 124, 92, 92, 124, + 14, 14, 14, 14, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 14, 14, 4, 14, + 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 124, + 124, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 92, - 92, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, - 0, 0, 0, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, - 92, 92, 92, 92, 92, 15, 15, 15, 15, 15, 15, 3, 3, 3, 15, 3, 15, 0, - 0, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92, 3, 3, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 124, - 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 124, 124, 92, 92, 92, 92, 124, - 124, 92, 124, 124, 124, 124, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 0, 91, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 3, 3, 15, 15, 15, - 15, 15, 92, 91, 15, 15, 15, 15, 15, 15, 15, 15, 15, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 92, 92, 92, 92, 92, 92, 124, 124, 92, 92, 124, 124, 92, 92, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 92, 15, 15, 15, 15, 15, 15, 15, - 15, 92, 124, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 3, 3, 3, 3, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 91, - 15, 15, 15, 15, 15, 15, 14, 14, 14, 15, 124, 92, 124, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 15, 92, - 92, 92, 15, 15, 92, 92, 15, 15, 15, 15, 15, 92, 92, 15, 92, 15, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 15, 15, 91, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, - 92, 92, 124, 124, 3, 3, 15, 91, 91, 124, 92, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 15, - 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, - 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 21, 21, 21, 21, 21, 21, 21, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 124, 124, 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 0, 0, 0, 0, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 15, 15, 15, 15, 15, 15, 3, 3, 3, 15, + 3, 15, 15, 92, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 92, + 92, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 124, 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 124, 124, 92, 92, + 92, 92, 124, 124, 92, 124, 124, 124, 124, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 0, 91, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 3, 3, + 15, 15, 15, 15, 15, 92, 91, 15, 15, 15, 15, 15, 15, 15, 15, 15, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 124, 124, 92, 92, 124, 124, + 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 92, 15, 15, 15, 15, + 15, 15, 15, 15, 92, 124, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, + 3, 3, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 91, 15, 15, 15, 15, 15, 15, 14, 14, 14, 15, 124, 92, 124, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 92, 15, 92, 92, 92, 15, 15, 92, 92, 15, 15, 15, 15, 15, 92, 92, 15, + 92, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 15, 15, 91, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 124, 92, 92, 124, 124, 3, 3, 15, 91, 91, 124, 92, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, + 0, 0, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, + 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 190, 21, 21, 21, 21, 21, - 21, 21, 11, 91, 91, 91, 91, 21, 21, 21, 21, 21, 21, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, - 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, - 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, - 191, 191, 191, 191, 191, 191, 191, 191, 191, 15, 15, 15, 124, 124, - 92, 124, 124, 92, 124, 124, 3, 124, 92, 0, 0, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 15, 15, 15, 15, 15, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 192, 21, 21, 21, + 21, 21, 21, 21, 11, 91, 91, 91, 91, 21, 21, 21, 21, 21, 21, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, + 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 15, 15, 15, 124, + 124, 92, 124, 124, 92, 124, 124, 3, 124, 92, 0, 0, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 192, 192, 192, - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, - 192, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, - 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, - 193, 193, 193, 193, 193, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, + 194, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, + 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, + 195, 195, 195, 195, 195, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 21, @@ -1160,10 +1162,10 @@ static const unsigned char groupMap[] = { 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 18, + 14, 14, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 18, 18, 18, 18, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 18, 18, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1176,29 +1178,29 @@ static const unsigned char groupMap[] = { 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 127, 15, 15, 15, 15, 15, 15, - 15, 15, 127, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 128, 15, 15, 15, 15, 15, 15, + 15, 15, 128, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, - 3, 15, 15, 15, 15, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 3, 127, - 127, 127, 127, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194, 194, 194, 194, - 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, - 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, - 194, 194, 194, 194, 194, 194, 194, 194, 195, 195, 195, 195, 195, 195, - 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, - 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, - 195, 195, 195, 195, 195, 195, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 3, 15, 15, 15, 15, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 3, 128, + 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 196, 196, 196, + 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, + 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, + 196, 196, 196, 196, 196, 196, 196, 196, 197, 197, 197, 197, 197, 197, + 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, + 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, + 197, 197, 197, 197, 197, 197, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 194, - 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, - 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, - 194, 194, 194, 194, 194, 194, 194, 0, 0, 0, 0, 195, 195, 195, 195, - 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, - 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, - 195, 195, 195, 195, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, + 15, 15, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 196, + 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, + 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, + 196, 196, 196, 196, 196, 196, 196, 0, 0, 0, 0, 197, 197, 197, 197, + 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, + 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, + 197, 197, 197, 197, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, @@ -1222,304 +1224,316 @@ static const unsigned char groupMap[] = { 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 15, 92, 92, 92, 0, 92, 92, 0, 0, 0, 0, 0, 92, 92, 92, 92, 15, 15, 15, 15, 0, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 92, 92, 92, 0, 0, 0, - 0, 92, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 92, 92, 92, 0, 0, + 0, 0, 92, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 18, 18, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 18, 18, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 18, 18, 18, 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, + 15, 15, 15, 15, 15, 18, 18, 18, 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 0, 0, 0, 0, 18, 18, 18, - 18, 18, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 0, 0, 0, 0, 18, + 18, 18, 18, 18, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 18, 18, + 15, 15, 15, 15, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, + 0, 18, 18, 18, 18, 18, 18, 18, 18, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, - 18, 18, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, + 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, - 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 102, 102, 102, 102, 102, 102, + 97, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, - 102, 102, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 102, 102, 102, 102, 102, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, + 15, 15, 15, 15, 92, 92, 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 124, 92, 124, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 18, 18, 18, 18, 18, 18, 0, 18, 18, 18, 18, 18, 18, 18, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 18, 18, 18, 18, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 124, 92, + 124, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 3, 3, 3, - 3, 3, 3, 3, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 124, 124, 92, 92, 92, - 92, 124, 124, 92, 92, 3, 3, 17, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 92, 92, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 124, 124, + 92, 92, 92, 92, 124, 124, 92, 92, 3, 3, 17, 3, 3, 3, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, + 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 92, + 92, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 92, 92, 92, 92, 92, 124, 92, 92, 92, 92, 92, 92, 92, 92, 0, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 15, 15, 92, 92, 92, 92, 92, 124, 92, 92, 92, 92, 92, 92, 92, + 92, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 3, 3, 3, 3, 15, 124, 124, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 92, 3, 3, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 92, 3, 3, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, + 15, 124, 124, 124, 92, 92, 92, 92, 92, 92, 92, 92, 92, 124, 124, 15, + 15, 15, 15, 3, 3, 3, 3, 92, 92, 92, 92, 3, 0, 0, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 15, 3, 15, 3, 3, 3, 0, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 124, 124, - 92, 92, 92, 92, 92, 92, 92, 92, 92, 124, 124, 15, 15, 15, 15, 3, 3, - 3, 3, 3, 92, 92, 92, 3, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 15, 3, - 15, 3, 3, 3, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 124, 124, 124, 92, 92, 92, 124, 124, - 92, 124, 92, 92, 3, 3, 3, 3, 3, 3, 92, 0, 15, 15, 15, 15, 15, 15, 15, - 0, 15, 0, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 0, - 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 92, 92, 92, 124, 124, 92, 124, 92, 92, 3, 3, 3, 3, 3, 3, 92, 0, 15, + 15, 15, 15, 15, 15, 15, 0, 15, 0, 15, 15, 15, 15, 0, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 3, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 92, 124, 124, 124, 92, 92, 92, 92, 92, 92, 92, 92, 0, 0, 0, 0, 0, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 92, 92, 124, 124, 0, 15, - 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, 0, 0, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 92, 124, 124, 124, 124, 0, 0, 124, - 124, 0, 0, 124, 124, 124, 0, 0, 15, 0, 0, 0, 0, 0, 0, 124, 0, 0, 0, - 0, 0, 15, 15, 15, 15, 15, 124, 124, 0, 0, 92, 92, 92, 92, 92, 92, 92, - 0, 0, 0, 92, 92, 92, 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 124, 124, 124, 92, 92, 92, 92, 92, 92, 92, 92, 124, 124, 92, - 92, 92, 124, 92, 15, 15, 15, 15, 3, 3, 3, 3, 3, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 0, 3, 0, 3, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 124, 124, 124, 92, 92, 92, 92, 92, 92, 124, - 92, 124, 124, 124, 124, 92, 92, 124, 92, 92, 15, 15, 3, 15, 0, 0, 0, - 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 124, 124, - 92, 92, 92, 92, 0, 0, 124, 124, 124, 124, 92, 92, 124, 92, 92, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 15, - 15, 15, 15, 92, 92, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 92, 124, 124, 124, 92, 92, 92, 92, 92, 92, + 92, 92, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, + 0, 92, 92, 124, 124, 0, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 15, 15, + 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, + 15, 15, 15, 15, 15, 0, 92, 92, 15, 124, 124, 92, 124, 124, 124, 124, + 0, 0, 124, 124, 0, 0, 124, 124, 124, 0, 0, 15, 0, 0, 0, 0, 0, 0, 124, + 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 124, 124, 0, 0, 92, 92, 92, 92, + 92, 92, 92, 0, 0, 0, 92, 92, 92, 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 124, 124, 92, 92, 92, 92, 92, 92, 92, 92, - 124, 124, 92, 124, 92, 92, 3, 3, 3, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 124, 92, - 124, 124, 92, 92, 92, 92, 92, 92, 124, 92, 0, 0, 0, 0, 0, 0, 0, 0, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, - 0, 0, 92, 92, 92, 124, 124, 92, 92, 92, 92, 124, 92, 92, 92, 92, 92, - 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 3, 3, 3, 14, 10, + 124, 124, 92, 92, 92, 124, 92, 15, 15, 15, 15, 3, 3, 3, 3, 3, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 3, 0, 3, 92, 0, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 124, 124, 92, 92, 92, + 92, 92, 92, 124, 92, 124, 124, 124, 124, 92, 92, 124, 92, 92, 15, 15, + 3, 15, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, + 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 124, 124, 124, 92, 92, 92, 92, 0, 0, 124, 124, 124, 124, 92, 92, + 124, 92, 92, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 15, 15, 15, 15, 92, 92, 0, 0, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 124, 124, 92, 92, 92, + 92, 92, 92, 92, 92, 124, 124, 92, 124, 92, 92, 3, 3, 3, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 92, 124, 92, 124, 124, 92, 92, 92, 92, 92, 92, 124, 92, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 124, 92, 92, 92, 92, + 124, 92, 92, 92, 92, 92, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 18, 18, 3, 3, 3, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 124, 124, 124, 92, 92, 92, 92, 92, 92, 92, 92, 92, 124, 92, 92, 3, + 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 15, 15, 92, 92, 92, 92, 92, 92, 124, 124, 92, 92, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 124, 15, 92, 92, 92, 92, 3, - 3, 3, 3, 3, 3, 3, 3, 92, 0, 0, 0, 0, 0, 0, 0, 0, 15, 92, 92, 92, 92, - 92, 92, 124, 124, 92, 92, 92, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, - 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, - 124, 92, 92, 3, 3, 3, 0, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 124, 92, 92, 92, 92, 92, 92, 92, 0, 92, - 92, 92, 92, 92, 92, 124, 92, 15, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 3, 3, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 92, 92, 92, 92, - 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, - 92, 0, 124, 92, 92, 92, 92, 92, 92, 92, 124, 92, 92, 124, 92, 92, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 10, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 124, 15, 92, + 92, 92, 92, 3, 3, 3, 3, 3, 3, 3, 3, 92, 0, 0, 0, 0, 0, 0, 0, 0, 15, + 92, 92, 92, 92, 92, 92, 124, 124, 92, 92, 92, 15, 15, 15, 15, 15, 15, + 15, 15, 0, 0, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 124, 92, 92, 3, 3, 3, 15, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 92, 92, 92, 92, 92, 92, 0, 0, 0, 92, 0, 92, 92, 0, 92, - 92, 92, 92, 92, 92, 92, 15, 92, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, 0, 3, 3, 3, 3, 3, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 0, 0, 92, 92, 92, 92, 92, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 92, 92, 92, 92, 92, 92, 92, 3, 3, 3, 3, 3, 14, 14, 14, 14, 91, 91, - 91, 91, 3, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 0, 18, 18, 18, 18, 18, 18, 18, 0, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, - 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, - 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 124, 124, 124, 124, - 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 124, 92, 92, 92, + 92, 92, 92, 92, 0, 92, 92, 92, 92, 92, 92, 124, 92, 15, 3, 3, 3, 3, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 0, 0, 0, 3, 3, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 0, 124, 92, 92, 92, 92, 92, 92, 92, 124, + 92, 92, 124, 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, + 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, 92, 92, 0, 0, 0, + 92, 0, 92, 92, 0, 92, 92, 92, 92, 92, 92, 92, 15, 92, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 15, 15, 15, + 15, 15, 15, 0, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 124, 124, 124, 124, 124, 0, 92, 92, 0, 124, 124, 92, + 124, 92, 15, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 124, 124, 3, 3, 0, + 0, 0, 0, 0, 0, 0, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 0, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, + 0, 92, 92, 92, 92, 92, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 92, 92, 92, 92, + 92, 92, 92, 3, 3, 3, 3, 3, 14, 14, 14, 14, 91, 91, 91, 91, 3, 14, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 18, 18, + 18, 18, 18, 18, 18, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 15, 15, 15, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 3, 3, 3, 3, 0, 0, 0, 0, 0, 15, 15, 15, 15, + 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 92, 92, 91, - 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 0, 0, 0, 0, + 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 92, 92, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, - 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 14, 92, 92, 3, 17, - 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 14, 92, 92, 3, 17, 17, 17, + 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 124, 124, 92, 92, 92, 14, 14, 14, - 124, 124, 124, 124, 124, 124, 17, 17, 17, 17, 17, 17, 17, 17, 92, 92, - 92, 92, 92, 92, 92, 92, 14, 14, 92, 92, 92, 92, 92, 92, 92, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 124, 124, 92, 92, 92, 14, 14, 14, 124, + 124, 124, 124, 124, 124, 17, 17, 17, 17, 17, 17, 17, 17, 92, 92, 92, + 92, 92, 92, 92, 92, 14, 14, 92, 92, 92, 92, 92, 92, 92, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 92, 92, 92, 92, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 92, 92, 92, 92, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 92, 92, 92, 14, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, + 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 92, 92, 92, 14, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 107, 107, 107, 107, 107, 107, 107, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0, + 0, 0, 0, 0, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107, 107, + 107, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 107, 107, 107, 21, 21, 21, 21, 21, 21, - 21, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 21, 21, 21, 21, 21, 21, 21, 0, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 0, 107, 107, 0, 0, 107, - 0, 0, 107, 107, 0, 0, 107, 107, 107, 107, 0, 107, 107, 107, 107, 107, - 107, 107, 107, 21, 21, 21, 21, 0, 21, 0, 21, 21, 21, 21, 21, 21, 21, - 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 107, 0, 107, 107, 0, 0, 107, 0, 0, 107, 107, + 0, 0, 107, 107, 107, 107, 0, 107, 107, 107, 107, 107, 107, 107, 107, + 21, 21, 21, 21, 0, 21, 0, 21, 21, 21, 21, 21, 21, 21, 0, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 107, 107, 21, 21, 21, 21, 21, 21, 21, + 107, 107, 107, 107, 107, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107, + 0, 107, 107, 107, 107, 0, 0, 107, 107, 107, 107, 107, 107, 107, 107, + 0, 107, 107, 107, 107, 107, 107, 107, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 107, 107, 0, 107, 107, 107, 107, 0, 0, 107, 107, 107, 107, - 107, 107, 107, 107, 0, 107, 107, 107, 107, 107, 107, 107, 0, 21, 21, + 21, 21, 107, 107, 0, 107, 107, 107, 107, 0, 107, 107, 107, 107, 107, + 0, 107, 0, 0, 0, 107, 107, 107, 107, 107, 107, 107, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 107, 107, 0, 107, 107, 107, 107, 0, 107, - 107, 107, 107, 107, 0, 107, 0, 0, 0, 107, 107, 107, 107, 107, 107, - 107, 0, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, + 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 107, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 107, 107, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 107, 107, 107, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 107, 107, 107, 21, 21, 21, 21, 21, 21, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 21, 21, 21, 21, 21, 21, 0, 0, 107, 107, 107, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 107, 107, 7, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 7, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 7, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 7, 21, 21, - 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 21, 21, 21, 21, 21, 21, 0, 0, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 7, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 7, 21, 21, 21, 21, 21, 21, 107, + 107, 107, 107, 7, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 7, 21, 21, 21, 21, + 21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 7, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 7, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 7, 21, 21, 21, 21, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 7, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 7, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, + 21, 21, 21, 7, 21, 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 7, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 7, 21, + 21, 21, 21, 21, 21, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, - 107, 107, 107, 107, 107, 107, 7, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 7, - 21, 21, 21, 21, 21, 21, 107, 21, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 107, 7, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 7, 21, 21, 21, 21, 21, 21, + 107, 21, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 92, 92, 92, 92, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 14, 14, 14, 14, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, - 92, 92, 14, 14, 14, 14, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, - 92, 92, 92, 92, 92, 92, 92, 14, 14, 14, 14, 14, 14, 14, 14, 92, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 92, 14, 14, 3, - 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 92, - 92, 92, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, - 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 92, 92, - 92, 92, 92, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, - 92, 92, 92, 92, 0, 0, 92, 92, 92, 92, 92, 92, 92, 0, 92, 92, 0, 92, - 92, 92, 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 15, 15, 15, 15, 15, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 92, 92, 92, 92, 92, 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 196, 196, - 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, - 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, 196, - 196, 196, 196, 196, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, - 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, - 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 92, 92, 92, 92, 92, - 92, 92, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 3, - 3, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, - 15, 0, 15, 0, 0, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, - 15, 15, 15, 15, 0, 15, 0, 15, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 15, - 0, 15, 0, 15, 0, 15, 15, 15, 0, 15, 15, 0, 15, 0, 0, 15, 0, 15, 0, - 15, 0, 15, 0, 15, 0, 15, 15, 0, 15, 0, 0, 15, 15, 15, 15, 0, 15, 15, - 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 15, 0, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 15, 15, - 15, 0, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 14, 14, + 92, 14, 14, 14, 14, 14, 14, 14, 14, 92, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 92, 14, 14, 3, 3, 3, 3, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 92, 92, 92, 0, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 92, 92, 92, 92, 92, 0, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0, 0, 92, 92, + 92, 92, 92, 92, 92, 0, 92, 92, 0, 92, 92, 92, 92, 92, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, + 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 92, 92, 92, 92, 92, 92, 92, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 198, 198, 198, 198, 198, 198, 198, + 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, + 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 199, 199, + 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, + 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, 199, + 199, 199, 199, 199, 92, 92, 92, 92, 92, 92, 92, 0, 0, 0, 0, 0, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 14, + 18, 18, 18, 4, 18, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, + 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, + 0, 15, 0, 0, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, + 15, 15, 15, 0, 15, 0, 15, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 15, 0, + 15, 0, 15, 0, 15, 15, 15, 0, 15, 15, 0, 15, 0, 0, 15, 0, 15, 0, 15, + 0, 15, 0, 15, 0, 15, 15, 0, 15, 0, 0, 15, 15, 15, 15, 0, 15, 15, 15, + 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 15, 0, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 15, 15, 15, + 0, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 18, 18, 18, 18, 18, 18, 18, 18, - 18, 18, 18, 18, 18, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, - 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 14, - 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 11, 11, 11, 11, 11, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, - 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, - 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, + 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, + 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 11, 11, 11, + 11, 11, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, + 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, + 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, + 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 0, 0, 0, 14, 0, 14, + 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 #endif /* TCL_UTF_MAX > 3 */ }; @@ -1535,6 +1549,7 @@ static const unsigned char groupMap[] = { * 100 = subtract delta for title/upper * 101 = sub delta for upper, sub 1 for title * 110 = sub delta for upper, add delta for lower + * 111 = subtract delta for upper * * Bits 8-31 Case delta: delta for case conversions. This should be the * highest field so we can easily sign extend. @@ -1554,16 +1569,16 @@ static const int groups[] = { 29761, 9793, 9537, 16449, 16193, 9858, 9602, 8066, 16514, 16258, 2113, 16002, 14722, 1, 12162, 13954, 2178, 22146, 20610, -1662, 29826, -15295, 24706, -1727, 20545, 7, 3905, 3970, 12353, 12418, - 8, 1859649, 9949249, 10, 1601154, 1600898, 1598594, 1598082, 1598338, - 1596546, 1582466, -9027966, -9044862, -976254, 15234, -1949375, - -1918, -1983, -18814, -21886, -25470, -32638, -28542, -32126, - -1981, -2174, -18879, -2237, 1844610, -21951, -25535, -28607, - -32703, -32191, 13, 14, -1924287, -2145983, -2115007, 7233, 7298, - 4170, 4234, 6749, 6813, -2750143, -976319, -2746047, 2763650, - 2762882, -2759615, -2751679, -2760383, -2760127, -2768575, 1859714, - -9044927, -10823615, -10830783, -10833599, -10832575, -10830015, - -10817983, -10824127, -10818751, 237633, 237698, 9949314, 18, - 17, 10305, 10370, 8769, 8834 + 8, 1859649, -769822, 9949249, 10, 1601154, 1600898, 1598594, 1598082, + 1598338, 1596546, 1582466, -9027966, -769983, -9044862, -976254, + 15234, -1949375, -1918, -1983, -18814, -21886, -25470, -32638, + -28542, -32126, -1981, -2174, -18879, -2237, 1844610, -21951, + -25535, -28607, -32703, -32191, 13, 14, -1924287, -2145983, -2115007, + 7233, 7298, 4170, 4234, 6749, 6813, -2750143, -976319, -2746047, + 2763650, 2762882, -2759615, -2751679, -2760383, -2760127, -2768575, + 1859714, -9044927, -10823615, -10830783, -10833599, -10832575, + -10830015, -10817983, -10824127, -10818751, 237633, 237698, 9949314, + 18, 17, 10305, 10370, 8769, 8834 }; #if TCL_UTF_MAX > 3 diff --git a/tools/uniClass.tcl b/tools/uniClass.tcl index 9b4819d..8047894 100644 --- a/tools/uniClass.tcl +++ b/tools/uniClass.tcl @@ -20,7 +20,7 @@ proc emitRange {first last} { set extranges 1 set numranges 0 set ranges [string trimright $ranges " \n\r\t,"] - append ranges "\n#if TCL_UTF_MAX > 4\n ," + append ranges "\n#if CHRBITS > 16\n ," } append ranges [format "{0x%x, 0x%x}, " \ $first $last] @@ -33,7 +33,7 @@ proc emitRange {first last} { set extchars 1 set numchars 0 set chars [string trimright $chars " \n\r\t,"] - append chars "\n#if TCL_UTF_MAX > 4\n ," + append chars "\n#if CHRBITS > 16\n ," } append chars [format "0x%x, " $first] incr numchars diff --git a/tools/uniParse.tcl b/tools/uniParse.tcl index 8125790..c712e62 100644 --- a/tools/uniParse.tcl +++ b/tools/uniParse.tcl @@ -272,6 +272,7 @@ static const unsigned char groupMap\[\] = {" * 100 = subtract delta for title/upper * 101 = sub delta for upper, sub 1 for title * 110 = sub delta for upper, add delta for lower + * 111 = subtract delta for upper * * Bits 8-31 Case delta: delta for case conversions. This should be the * highest field so we can easily sign extend. @@ -309,10 +310,14 @@ static const int groups\[\] = {" } } } elseif {$toupper} { - # subtract delta for upper, add delta for lower - set case 6 set delta $toupper - if {$tolower != $toupper} { + if {$tolower == $toupper} { + # subtract delta for upper, add delta for lower + set case 6 + } elseif {!$tolower} { + # subtract delta for upper + set case 7 + } else { error "New case conversion type needed: $toupper $tolower $totitle" } } elseif {$tolower} { -- cgit v0.12 From debcb2bf0157aa00be72330199c44e4d38a4b0ab Mon Sep 17 00:00:00 2001 From: sebres Date: Mon, 30 Apr 2018 11:52:12 +0000 Subject: amend after merge 8.5 --- win/tclWinFile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win/tclWinFile.c b/win/tclWinFile.c index 4525d8a..9afe0a9 100644 --- a/win/tclWinFile.c +++ b/win/tclWinFile.c @@ -1592,7 +1592,7 @@ NativeAccess( if (mode & W_OK) { mask |= GENERIC_WRITE; } if (mode & X_OK) { mask |= GENERIC_EXECUTE; } - hFile = (tclWinProcs->createFileProc)(nativePath, mask, + hFile = CreateFile(nativePath, mask, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL); if (hFile != INVALID_HANDLE_VALUE) { -- cgit v0.12 From 0fc27b893e12027a6b5136fb96ba216b823f43e1 Mon Sep 17 00:00:00 2001 From: dgp Date: Mon, 30 Apr 2018 12:11:14 +0000 Subject: Contain platform-specific things in the constraint-controlled parts of the test. --- tests/winFCmd.test | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/winFCmd.test b/tests/winFCmd.test index b3fd921..1b2b042 100644 --- a/tests/winFCmd.test +++ b/tests/winFCmd.test @@ -912,10 +912,11 @@ test winFCmd-12.6.2 {ConvertFileNameFormat: absolute path with drive (in temp fo catch {file delete -force -- $::env(TEMP)/td1} } -constraints {win} -body { createfile $::env(TEMP)/td1 {} - string tolower [file attributes $::env(TEMP)/td1 -longname] + string equal [string tolower [file attributes $::env(TEMP)/td1 -longname]] \ + [string tolower [file normalize $::env(TEMP)]/td1]] } -cleanup { file delete -force -- $::env(TEMP)/td1 -} -result [string tolower [file normalize $::env(TEMP)]/td1] +} -result 1 test winFCmd-12.7 {ConvertFileNameFormat} {nonPortable win} { string tolower [file attributes //bisque/tcl/ws -longname] } {//bisque/tcl/ws} -- cgit v0.12 From 51208ca53e4fceed8f2bea1005d2f5184ce94699 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 1 May 2018 18:41:27 +0000 Subject: Implement special "string totitle" for Extended Georgian characters (new behavior in Unicode 11) --- generic/tclUtf.c | 12 +++++++++--- tests/utf.test | 12 ++++++++++++ tools/uniClass.tcl | 2 +- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/generic/tclUtf.c b/generic/tclUtf.c index 319bfa0..1d73a7a 100644 --- a/generic/tclUtf.c +++ b/generic/tclUtf.c @@ -1034,7 +1034,10 @@ Tcl_UtfToTitle( lowChar = (((lowChar & 0x3ff) << 10) | (ch & 0x3ff)) + 0x10000; } #endif - lowChar = Tcl_UniCharToLower(lowChar); + /* Special exception for Gregorian characters, which don't have titlecase */ + if ((lowChar < 0x1C90) || (lowChar >= 0x1CC0)) { + lowChar = Tcl_UniCharToLower(lowChar); + } if (bytes < TclUtfCount(lowChar)) { memcpy(dst, src, (size_t) bytes); @@ -1355,8 +1358,9 @@ Tcl_UniCharToLower( { if (!UNICODE_OUT_OF_RANGE(ch)) { int info = GetUniCharInfo(ch); + int mode = GetCaseType(info); - if (GetCaseType(info) & 0x02) { + if ((mode & 0x02) && (mode != 0x7)) { ch += GetDelta(info); } } @@ -1392,7 +1396,9 @@ Tcl_UniCharToTitle( * Subtract or add one depending on the original case. */ - ch += ((mode & 0x4) ? -1 : 1); + if (mode != 0x7) { + ch += ((mode & 0x4) ? -1 : 1); + } } else if (mode == 0x4) { ch -= GetDelta(info); } diff --git a/tests/utf.test b/tests/utf.test index af471e1..39818cc 100644 --- a/tests/utf.test +++ b/tests/utf.test @@ -250,6 +250,9 @@ test utf-11.3 {Tcl_UtfToUpper} { test utf-11.4 {Tcl_UtfToUpper} { string toupper \u01e3ab } \u01e2AB +test utf-11.5 {Tcl_UtfToUpper Georgian (new in Unicode 11)} { + string toupper \u10d0\u1c90 +} \u1c90\u1c90 test utf-12.1 {Tcl_UtfToLower} { string tolower {} @@ -263,6 +266,9 @@ test utf-12.3 {Tcl_UtfToLower} { test utf-12.4 {Tcl_UtfToLower} { string tolower \u01e2AB } \u01e3ab +test utf-12.5 {Tcl_UtfToLower Georgian (new in Unicode 11)} { + string tolower \u10d0\u1c90 +} \u10d0\u10d0 test utf-13.1 {Tcl_UtfToTitle} { string totitle {} @@ -276,6 +282,12 @@ test utf-13.3 {Tcl_UtfToTitle} { test utf-13.4 {Tcl_UtfToTitle} { string totitle \u01f3ab } \u01f2ab +test utf-13.5 {Tcl_UtfToTitle Georgian (new in Unicode 11)} { + string totitle \u10d0\u1c90 +} \u10d0\u1c90 +test utf-13.6 {Tcl_UtfToTitle Georgian (new in Unicode 11)} { + string totitle \u1c90\u10d0 +} \u1c90\u10d0 test utf-14.1 {Tcl_UtfNcasecmp} { string compare -nocase a b diff --git a/tools/uniClass.tcl b/tools/uniClass.tcl index 8047894..86ec931 100644 --- a/tools/uniClass.tcl +++ b/tools/uniClass.tcl @@ -66,7 +66,7 @@ proc genTable {type} { for {set i 0} {$i <= 0x10ffff} {incr i} { if {$i == 0xd800} { # Skip surrogates - set i 0xdc00 + set i 0xe000 } if {[string is $type [format %c $i]]} { if {$i == ($last + 1)} { -- cgit v0.12 From ccf2e7a979191fadc531cc0776a96ba26a6f9770 Mon Sep 17 00:00:00 2001 From: oehhar Date: Wed, 2 May 2018 12:22:44 +0000 Subject: Syntax error in msgcat documentation fixed. Ticket [af69c6966d] --- doc/msgcat.n | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/msgcat.n b/doc/msgcat.n index 9074725..3d87ffd 100644 --- a/doc/msgcat.n +++ b/doc/msgcat.n @@ -128,8 +128,8 @@ Given several source strings, \fB::msgcat::mcmax\fR returns the length of the longest translated string. This is useful when designing localized GUIs, which may require that all buttons, for example, be a fixed width (which will be the width of the widest button). -.TP .VS "TIP 412" +.TP \fB::msgcat::mcexists\fR ?\fB-exactnamespace\fR? ?\fB-exactlocale\fR? ?\fB-namespace\fR \fInamespace\fR? \fIsrc-string\fR . Return true, if there is a translation for the given \fIsrc-string\fR. -- cgit v0.12 From 096a011c439f5f857ba14ba0827fcead0572233e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Ignacio=20Mar=C3=ADn?= Date: Fri, 4 May 2018 19:06:09 +0000 Subject: Update TZ info to tzdata2018e. --- library/tzdata/Africa/Windhoek | 95 ++++---- library/tzdata/Asia/Pyongyang | 1 + library/tzdata/Europe/Dublin | 515 ++++++++++++++++++++--------------------- library/tzdata/Europe/Prague | 9 +- 4 files changed, 311 insertions(+), 309 deletions(-) diff --git a/library/tzdata/Africa/Windhoek b/library/tzdata/Africa/Windhoek index 974ebda..d03c8b8 100644 --- a/library/tzdata/Africa/Windhoek +++ b/library/tzdata/Africa/Windhoek @@ -7,53 +7,52 @@ set TZData(:Africa/Windhoek) { {-860976000 10800 1 SAST} {-845254800 7200 0 SAST} {637970400 7200 0 CAT} - {764200800 3600 0 WAT} - {764204400 3600 0 WAT} - {778640400 7200 1 WAST} - {796780800 3600 0 WAT} - {810090000 7200 1 WAST} - {828835200 3600 0 WAT} - {841539600 7200 1 WAST} - {860284800 3600 0 WAT} - {873594000 7200 1 WAST} - {891734400 3600 0 WAT} - {905043600 7200 1 WAST} - {923184000 3600 0 WAT} - {936493200 7200 1 WAST} - {954633600 3600 0 WAT} - {967942800 7200 1 WAST} - {986083200 3600 0 WAT} - {999392400 7200 1 WAST} - {1018137600 3600 0 WAT} - {1030842000 7200 1 WAST} - {1049587200 3600 0 WAT} - {1062896400 7200 1 WAST} - {1081036800 3600 0 WAT} - {1094346000 7200 1 WAST} - {1112486400 3600 0 WAT} - {1125795600 7200 1 WAST} - {1143936000 3600 0 WAT} - {1157245200 7200 1 WAST} - {1175385600 3600 0 WAT} - {1188694800 7200 1 WAST} - {1207440000 3600 0 WAT} - {1220749200 7200 1 WAST} - {1238889600 3600 0 WAT} - {1252198800 7200 1 WAST} - {1270339200 3600 0 WAT} - {1283648400 7200 1 WAST} - {1301788800 3600 0 WAT} - {1315098000 7200 1 WAST} - {1333238400 3600 0 WAT} - {1346547600 7200 1 WAST} - {1365292800 3600 0 WAT} - {1377997200 7200 1 WAST} - {1396742400 3600 0 WAT} - {1410051600 7200 1 WAST} - {1428192000 3600 0 WAT} - {1441501200 7200 1 WAST} - {1459641600 3600 0 WAT} - {1472950800 7200 1 WAST} - {1491091200 3600 0 WAT} + {764200800 3600 1 WAT} + {778640400 7200 0 CAT} + {796780800 3600 1 WAT} + {810090000 7200 0 CAT} + {828835200 3600 1 WAT} + {841539600 7200 0 CAT} + {860284800 3600 1 WAT} + {873594000 7200 0 CAT} + {891734400 3600 1 WAT} + {905043600 7200 0 CAT} + {923184000 3600 1 WAT} + {936493200 7200 0 CAT} + {954633600 3600 1 WAT} + {967942800 7200 0 CAT} + {986083200 3600 1 WAT} + {999392400 7200 0 CAT} + {1018137600 3600 1 WAT} + {1030842000 7200 0 CAT} + {1049587200 3600 1 WAT} + {1062896400 7200 0 CAT} + {1081036800 3600 1 WAT} + {1094346000 7200 0 CAT} + {1112486400 3600 1 WAT} + {1125795600 7200 0 CAT} + {1143936000 3600 1 WAT} + {1157245200 7200 0 CAT} + {1175385600 3600 1 WAT} + {1188694800 7200 0 CAT} + {1207440000 3600 1 WAT} + {1220749200 7200 0 CAT} + {1238889600 3600 1 WAT} + {1252198800 7200 0 CAT} + {1270339200 3600 1 WAT} + {1283648400 7200 0 CAT} + {1301788800 3600 1 WAT} + {1315098000 7200 0 CAT} + {1333238400 3600 1 WAT} + {1346547600 7200 0 CAT} + {1365292800 3600 1 WAT} + {1377997200 7200 0 CAT} + {1396742400 3600 1 WAT} + {1410051600 7200 0 CAT} + {1428192000 3600 1 WAT} + {1441501200 7200 0 CAT} + {1459641600 3600 1 WAT} + {1472950800 7200 0 CAT} + {1491091200 3600 1 WAT} {1504400400 7200 0 CAT} } diff --git a/library/tzdata/Asia/Pyongyang b/library/tzdata/Asia/Pyongyang index 72e7f23..5746472 100644 --- a/library/tzdata/Asia/Pyongyang +++ b/library/tzdata/Asia/Pyongyang @@ -6,4 +6,5 @@ set TZData(:Asia/Pyongyang) { {-1830414600 32400 0 JST} {-768646800 32400 0 KST} {1439564400 30600 0 KST} + {1525447800 32400 0 KST} } diff --git a/library/tzdata/Europe/Dublin b/library/tzdata/Europe/Dublin index c3a5c0e..56afc93 100644 --- a/library/tzdata/Europe/Dublin +++ b/library/tzdata/Europe/Dublin @@ -98,262 +98,261 @@ set TZData(:Europe/Dublin) { {-68680800 0 0 IST} {-59004000 3600 1 IST} {-37238400 3600 0 IST} - {57722400 0 0 IST} - {69818400 3600 1 IST} - {89172000 0 0 IST} - {101268000 3600 1 IST} - {120621600 0 0 IST} - {132717600 3600 1 IST} - {152071200 0 0 IST} - {164167200 3600 1 IST} - {183520800 0 0 IST} - {196221600 3600 1 IST} - {214970400 0 0 IST} - {227671200 3600 1 IST} - {246420000 0 0 IST} - {259120800 3600 1 IST} - {278474400 0 0 IST} - {290570400 3600 1 IST} - {309924000 0 0 IST} - {322020000 3600 1 IST} - {341373600 0 0 IST} - {354675600 3600 1 IST} - {372819600 0 0 IST} - {386125200 3600 1 IST} - {404269200 0 0 IST} - {417574800 3600 1 IST} - {435718800 0 0 IST} - {449024400 3600 1 IST} - {467773200 0 0 IST} - {481078800 3600 1 IST} - {499222800 0 0 IST} - {512528400 3600 1 IST} - {530672400 0 0 IST} - {543978000 3600 1 IST} - {562122000 0 0 IST} - {575427600 3600 1 IST} - {593571600 0 0 IST} - {606877200 3600 1 IST} - {625626000 0 0 IST} - {638326800 3600 1 IST} - {657075600 0 0 IST} - {670381200 3600 1 IST} - {688525200 0 0 IST} - {701830800 3600 1 IST} - {719974800 0 0 IST} - {733280400 3600 1 IST} - {751424400 0 0 IST} - {764730000 3600 1 IST} - {782874000 0 0 IST} - {796179600 3600 1 IST} - {814323600 0 0 IST} - {820454400 0 0 GMT} - {828234000 3600 1 IST} - {846378000 0 0 GMT} - {859683600 3600 1 IST} - {877827600 0 0 GMT} - {891133200 3600 1 IST} - {909277200 0 0 GMT} - {922582800 3600 1 IST} - {941331600 0 0 GMT} - {954032400 3600 1 IST} - {972781200 0 0 GMT} - {985482000 3600 1 IST} - {1004230800 0 0 GMT} - {1017536400 3600 1 IST} - {1035680400 0 0 GMT} - {1048986000 3600 1 IST} - {1067130000 0 0 GMT} - {1080435600 3600 1 IST} - {1099184400 0 0 GMT} - {1111885200 3600 1 IST} - {1130634000 0 0 GMT} - {1143334800 3600 1 IST} - {1162083600 0 0 GMT} - {1174784400 3600 1 IST} - {1193533200 0 0 GMT} - {1206838800 3600 1 IST} - {1224982800 0 0 GMT} - {1238288400 3600 1 IST} - {1256432400 0 0 GMT} - {1269738000 3600 1 IST} - {1288486800 0 0 GMT} - {1301187600 3600 1 IST} - {1319936400 0 0 GMT} - {1332637200 3600 1 IST} - {1351386000 0 0 GMT} - {1364691600 3600 1 IST} - {1382835600 0 0 GMT} - {1396141200 3600 1 IST} - {1414285200 0 0 GMT} - {1427590800 3600 1 IST} - {1445734800 0 0 GMT} - {1459040400 3600 1 IST} - {1477789200 0 0 GMT} - {1490490000 3600 1 IST} - {1509238800 0 0 GMT} - {1521939600 3600 1 IST} - {1540688400 0 0 GMT} - {1553994000 3600 1 IST} - {1572138000 0 0 GMT} - {1585443600 3600 1 IST} - {1603587600 0 0 GMT} - {1616893200 3600 1 IST} - {1635642000 0 0 GMT} - {1648342800 3600 1 IST} - {1667091600 0 0 GMT} - {1679792400 3600 1 IST} - {1698541200 0 0 GMT} - {1711846800 3600 1 IST} - {1729990800 0 0 GMT} - {1743296400 3600 1 IST} - {1761440400 0 0 GMT} - {1774746000 3600 1 IST} - {1792890000 0 0 GMT} - {1806195600 3600 1 IST} - {1824944400 0 0 GMT} - {1837645200 3600 1 IST} - {1856394000 0 0 GMT} - {1869094800 3600 1 IST} - {1887843600 0 0 GMT} - {1901149200 3600 1 IST} - {1919293200 0 0 GMT} - {1932598800 3600 1 IST} - {1950742800 0 0 GMT} - {1964048400 3600 1 IST} - {1982797200 0 0 GMT} - {1995498000 3600 1 IST} - {2014246800 0 0 GMT} - {2026947600 3600 1 IST} - {2045696400 0 0 GMT} - {2058397200 3600 1 IST} - {2077146000 0 0 GMT} - {2090451600 3600 1 IST} - {2108595600 0 0 GMT} - {2121901200 3600 1 IST} - {2140045200 0 0 GMT} - {2153350800 3600 1 IST} - {2172099600 0 0 GMT} - {2184800400 3600 1 IST} - {2203549200 0 0 GMT} - {2216250000 3600 1 IST} - {2234998800 0 0 GMT} - {2248304400 3600 1 IST} - {2266448400 0 0 GMT} - {2279754000 3600 1 IST} - {2297898000 0 0 GMT} - {2311203600 3600 1 IST} - {2329347600 0 0 GMT} - {2342653200 3600 1 IST} - {2361402000 0 0 GMT} - {2374102800 3600 1 IST} - {2392851600 0 0 GMT} - {2405552400 3600 1 IST} - {2424301200 0 0 GMT} - {2437606800 3600 1 IST} - {2455750800 0 0 GMT} - {2469056400 3600 1 IST} - {2487200400 0 0 GMT} - {2500506000 3600 1 IST} - {2519254800 0 0 GMT} - {2531955600 3600 1 IST} - {2550704400 0 0 GMT} - {2563405200 3600 1 IST} - {2582154000 0 0 GMT} - {2595459600 3600 1 IST} - {2613603600 0 0 GMT} - {2626909200 3600 1 IST} - {2645053200 0 0 GMT} - {2658358800 3600 1 IST} - {2676502800 0 0 GMT} - {2689808400 3600 1 IST} - {2708557200 0 0 GMT} - {2721258000 3600 1 IST} - {2740006800 0 0 GMT} - {2752707600 3600 1 IST} - {2771456400 0 0 GMT} - {2784762000 3600 1 IST} - {2802906000 0 0 GMT} - {2816211600 3600 1 IST} - {2834355600 0 0 GMT} - {2847661200 3600 1 IST} - {2866410000 0 0 GMT} - {2879110800 3600 1 IST} - {2897859600 0 0 GMT} - {2910560400 3600 1 IST} - {2929309200 0 0 GMT} - {2942010000 3600 1 IST} - {2960758800 0 0 GMT} - {2974064400 3600 1 IST} - {2992208400 0 0 GMT} - {3005514000 3600 1 IST} - {3023658000 0 0 GMT} - {3036963600 3600 1 IST} - {3055712400 0 0 GMT} - {3068413200 3600 1 IST} - {3087162000 0 0 GMT} - {3099862800 3600 1 IST} - {3118611600 0 0 GMT} - {3131917200 3600 1 IST} - {3150061200 0 0 GMT} - {3163366800 3600 1 IST} - {3181510800 0 0 GMT} - {3194816400 3600 1 IST} - {3212960400 0 0 GMT} - {3226266000 3600 1 IST} - {3245014800 0 0 GMT} - {3257715600 3600 1 IST} - {3276464400 0 0 GMT} - {3289165200 3600 1 IST} - {3307914000 0 0 GMT} - {3321219600 3600 1 IST} - {3339363600 0 0 GMT} - {3352669200 3600 1 IST} - {3370813200 0 0 GMT} - {3384118800 3600 1 IST} - {3402867600 0 0 GMT} - {3415568400 3600 1 IST} - {3434317200 0 0 GMT} - {3447018000 3600 1 IST} - {3465766800 0 0 GMT} - {3479072400 3600 1 IST} - {3497216400 0 0 GMT} - {3510522000 3600 1 IST} - {3528666000 0 0 GMT} - {3541971600 3600 1 IST} - {3560115600 0 0 GMT} - {3573421200 3600 1 IST} - {3592170000 0 0 GMT} - {3604870800 3600 1 IST} - {3623619600 0 0 GMT} - {3636320400 3600 1 IST} - {3655069200 0 0 GMT} - {3668374800 3600 1 IST} - {3686518800 0 0 GMT} - {3699824400 3600 1 IST} - {3717968400 0 0 GMT} - {3731274000 3600 1 IST} - {3750022800 0 0 GMT} - {3762723600 3600 1 IST} - {3781472400 0 0 GMT} - {3794173200 3600 1 IST} - {3812922000 0 0 GMT} - {3825622800 3600 1 IST} - {3844371600 0 0 GMT} - {3857677200 3600 1 IST} - {3875821200 0 0 GMT} - {3889126800 3600 1 IST} - {3907270800 0 0 GMT} - {3920576400 3600 1 IST} - {3939325200 0 0 GMT} - {3952026000 3600 1 IST} - {3970774800 0 0 GMT} - {3983475600 3600 1 IST} - {4002224400 0 0 GMT} - {4015530000 3600 1 IST} - {4033674000 0 0 GMT} - {4046979600 3600 1 IST} - {4065123600 0 0 GMT} - {4078429200 3600 1 IST} - {4096573200 0 0 GMT} + {57722400 0 1 IST} + {69818400 3600 0 IST} + {89172000 0 1 IST} + {101268000 3600 0 IST} + {120621600 0 1 IST} + {132717600 3600 0 IST} + {152071200 0 1 IST} + {164167200 3600 0 IST} + {183520800 0 1 IST} + {196221600 3600 0 IST} + {214970400 0 1 IST} + {227671200 3600 0 IST} + {246420000 0 1 IST} + {259120800 3600 0 IST} + {278474400 0 1 IST} + {290570400 3600 0 IST} + {309924000 0 1 IST} + {322020000 3600 0 IST} + {341373600 0 1 IST} + {354675600 3600 0 IST} + {372819600 0 1 IST} + {386125200 3600 0 IST} + {404269200 0 1 IST} + {417574800 3600 0 IST} + {435718800 0 1 IST} + {449024400 3600 0 IST} + {467773200 0 1 IST} + {481078800 3600 0 IST} + {499222800 0 1 IST} + {512528400 3600 0 IST} + {530672400 0 1 IST} + {543978000 3600 0 IST} + {562122000 0 1 IST} + {575427600 3600 0 IST} + {593571600 0 1 IST} + {606877200 3600 0 IST} + {625626000 0 1 IST} + {638326800 3600 0 IST} + {657075600 0 1 IST} + {670381200 3600 0 IST} + {688525200 0 1 IST} + {701830800 3600 0 IST} + {719974800 0 1 IST} + {733280400 3600 0 IST} + {751424400 0 1 IST} + {764730000 3600 0 IST} + {782874000 0 1 IST} + {796179600 3600 0 IST} + {814323600 0 1 IST} + {828234000 3600 0 IST} + {846378000 0 1 IST} + {859683600 3600 0 IST} + {877827600 0 1 IST} + {891133200 3600 0 IST} + {909277200 0 1 IST} + {922582800 3600 0 IST} + {941331600 0 1 IST} + {954032400 3600 0 IST} + {972781200 0 1 IST} + {985482000 3600 0 IST} + {1004230800 0 1 IST} + {1017536400 3600 0 IST} + {1035680400 0 1 IST} + {1048986000 3600 0 IST} + {1067130000 0 1 IST} + {1080435600 3600 0 IST} + {1099184400 0 1 IST} + {1111885200 3600 0 IST} + {1130634000 0 1 IST} + {1143334800 3600 0 IST} + {1162083600 0 1 IST} + {1174784400 3600 0 IST} + {1193533200 0 1 IST} + {1206838800 3600 0 IST} + {1224982800 0 1 IST} + {1238288400 3600 0 IST} + {1256432400 0 1 IST} + {1269738000 3600 0 IST} + {1288486800 0 1 IST} + {1301187600 3600 0 IST} + {1319936400 0 1 IST} + {1332637200 3600 0 IST} + {1351386000 0 1 IST} + {1364691600 3600 0 IST} + {1382835600 0 1 IST} + {1396141200 3600 0 IST} + {1414285200 0 1 IST} + {1427590800 3600 0 IST} + {1445734800 0 1 IST} + {1459040400 3600 0 IST} + {1477789200 0 1 IST} + {1490490000 3600 0 IST} + {1509238800 0 1 IST} + {1521939600 3600 0 IST} + {1540688400 0 1 IST} + {1553994000 3600 0 IST} + {1572138000 0 1 IST} + {1585443600 3600 0 IST} + {1603587600 0 1 IST} + {1616893200 3600 0 IST} + {1635642000 0 1 IST} + {1648342800 3600 0 IST} + {1667091600 0 1 IST} + {1679792400 3600 0 IST} + {1698541200 0 1 IST} + {1711846800 3600 0 IST} + {1729990800 0 1 IST} + {1743296400 3600 0 IST} + {1761440400 0 1 IST} + {1774746000 3600 0 IST} + {1792890000 0 1 IST} + {1806195600 3600 0 IST} + {1824944400 0 1 IST} + {1837645200 3600 0 IST} + {1856394000 0 1 IST} + {1869094800 3600 0 IST} + {1887843600 0 1 IST} + {1901149200 3600 0 IST} + {1919293200 0 1 IST} + {1932598800 3600 0 IST} + {1950742800 0 1 IST} + {1964048400 3600 0 IST} + {1982797200 0 1 IST} + {1995498000 3600 0 IST} + {2014246800 0 1 IST} + {2026947600 3600 0 IST} + {2045696400 0 1 IST} + {2058397200 3600 0 IST} + {2077146000 0 1 IST} + {2090451600 3600 0 IST} + {2108595600 0 1 IST} + {2121901200 3600 0 IST} + {2140045200 0 1 IST} + {2153350800 3600 0 IST} + {2172099600 0 1 IST} + {2184800400 3600 0 IST} + {2203549200 0 1 IST} + {2216250000 3600 0 IST} + {2234998800 0 1 IST} + {2248304400 3600 0 IST} + {2266448400 0 1 IST} + {2279754000 3600 0 IST} + {2297898000 0 1 IST} + {2311203600 3600 0 IST} + {2329347600 0 1 IST} + {2342653200 3600 0 IST} + {2361402000 0 1 IST} + {2374102800 3600 0 IST} + {2392851600 0 1 IST} + {2405552400 3600 0 IST} + {2424301200 0 1 IST} + {2437606800 3600 0 IST} + {2455750800 0 1 IST} + {2469056400 3600 0 IST} + {2487200400 0 1 IST} + {2500506000 3600 0 IST} + {2519254800 0 1 IST} + {2531955600 3600 0 IST} + {2550704400 0 1 IST} + {2563405200 3600 0 IST} + {2582154000 0 1 IST} + {2595459600 3600 0 IST} + {2613603600 0 1 IST} + {2626909200 3600 0 IST} + {2645053200 0 1 IST} + {2658358800 3600 0 IST} + {2676502800 0 1 IST} + {2689808400 3600 0 IST} + {2708557200 0 1 IST} + {2721258000 3600 0 IST} + {2740006800 0 1 IST} + {2752707600 3600 0 IST} + {2771456400 0 1 IST} + {2784762000 3600 0 IST} + {2802906000 0 1 IST} + {2816211600 3600 0 IST} + {2834355600 0 1 IST} + {2847661200 3600 0 IST} + {2866410000 0 1 IST} + {2879110800 3600 0 IST} + {2897859600 0 1 IST} + {2910560400 3600 0 IST} + {2929309200 0 1 IST} + {2942010000 3600 0 IST} + {2960758800 0 1 IST} + {2974064400 3600 0 IST} + {2992208400 0 1 IST} + {3005514000 3600 0 IST} + {3023658000 0 1 IST} + {3036963600 3600 0 IST} + {3055712400 0 1 IST} + {3068413200 3600 0 IST} + {3087162000 0 1 IST} + {3099862800 3600 0 IST} + {3118611600 0 1 IST} + {3131917200 3600 0 IST} + {3150061200 0 1 IST} + {3163366800 3600 0 IST} + {3181510800 0 1 IST} + {3194816400 3600 0 IST} + {3212960400 0 1 IST} + {3226266000 3600 0 IST} + {3245014800 0 1 IST} + {3257715600 3600 0 IST} + {3276464400 0 1 IST} + {3289165200 3600 0 IST} + {3307914000 0 1 IST} + {3321219600 3600 0 IST} + {3339363600 0 1 IST} + {3352669200 3600 0 IST} + {3370813200 0 1 IST} + {3384118800 3600 0 IST} + {3402867600 0 1 IST} + {3415568400 3600 0 IST} + {3434317200 0 1 IST} + {3447018000 3600 0 IST} + {3465766800 0 1 IST} + {3479072400 3600 0 IST} + {3497216400 0 1 IST} + {3510522000 3600 0 IST} + {3528666000 0 1 IST} + {3541971600 3600 0 IST} + {3560115600 0 1 IST} + {3573421200 3600 0 IST} + {3592170000 0 1 IST} + {3604870800 3600 0 IST} + {3623619600 0 1 IST} + {3636320400 3600 0 IST} + {3655069200 0 1 IST} + {3668374800 3600 0 IST} + {3686518800 0 1 IST} + {3699824400 3600 0 IST} + {3717968400 0 1 IST} + {3731274000 3600 0 IST} + {3750022800 0 1 IST} + {3762723600 3600 0 IST} + {3781472400 0 1 IST} + {3794173200 3600 0 IST} + {3812922000 0 1 IST} + {3825622800 3600 0 IST} + {3844371600 0 1 IST} + {3857677200 3600 0 IST} + {3875821200 0 1 IST} + {3889126800 3600 0 IST} + {3907270800 0 1 IST} + {3920576400 3600 0 IST} + {3939325200 0 1 IST} + {3952026000 3600 0 IST} + {3970774800 0 1 IST} + {3983475600 3600 0 IST} + {4002224400 0 1 IST} + {4015530000 3600 0 IST} + {4033674000 0 1 IST} + {4046979600 3600 0 IST} + {4065123600 0 1 IST} + {4078429200 3600 0 IST} + {4096573200 0 1 IST} } diff --git a/library/tzdata/Europe/Prague b/library/tzdata/Europe/Prague index 222b1ae..34df8ed 100644 --- a/library/tzdata/Europe/Prague +++ b/library/tzdata/Europe/Prague @@ -15,11 +15,14 @@ set TZData(:Europe/Prague) { {-844556400 7200 1 CEST} {-828226800 3600 0 CET} {-812502000 7200 1 CEST} - {-798073200 3600 0 CET} - {-780534000 7200 1 CEST} - {-761180400 3600 0 CET} + {-796777200 3600 0 CET} + {-781052400 7200 1 CEST} + {-777862800 7200 0 CEST} + {-765327600 3600 0 CET} {-746578800 7200 1 CEST} {-733359600 3600 0 CET} + {-728517600 0 1 GMT} + {-721260000 0 0 CET} {-716425200 7200 1 CEST} {-701910000 3600 0 CET} {-684975600 7200 1 CEST} -- cgit v0.12 From 3a3fd2954f11d13424d941346c5ede39c3bf175f Mon Sep 17 00:00:00 2001 From: pooryorick Date: Sat, 5 May 2018 16:38:27 +0000 Subject: Avoid generating string representation when comparing the empty string. --- generic/tclExecute.c | 56 +++++++++++++++++++++++++++++++++++++++++++++----- generic/tclInt.h | 10 +++++++++ generic/tclStringObj.c | 45 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 5 deletions(-) diff --git a/generic/tclExecute.c b/generic/tclExecute.c index af44323..728a847 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -5440,22 +5440,58 @@ TEBCresume( } } else { /* - * strcmp can't do a simple memcmp in order to handle the - * special Tcl \xC0\x80 null encoding for utf-8. + * In order to handle the special Tcl \xC0\x80 null encoding + * for utf-8, strcmp can't do a simple memcmp. */ - s1 = TclGetStringFromObj(valuePtr, &s1len); - s2 = TclGetStringFromObj(value2Ptr, &s2len); + { + int empty; + if ((empty = TclCheckEmptyString(valuePtr)) > 0) { + switch (TclCheckEmptyString(value2Ptr)) { + case -1: + s1 = ""; + s1len = 0; + s2 = TclGetStringFromObj(value2Ptr, &s2len); + break; + case 0: + match = -1; + goto matchdone; + case 1: + match = 0; + goto matchdone; + } + } else if (TclCheckEmptyString(value2Ptr) > 0) { + switch (empty) { + case -1: + s2 = ""; + s2len = 0; + s1 = TclGetStringFromObj(valuePtr, &s1len); + break; + case 0: + match = 1; + goto matchdone; + case 1: + match = 0; + goto matchdone; + } + } else { + s1 = TclGetStringFromObj(valuePtr, &s1len); + s2 = TclGetStringFromObj(value2Ptr, &s2len); + } + } + + if (checkEq) { memCmpFn = memcmp; } else { memCmpFn = (memCmpFn_t) TclpUtfNcmp2; } + } if (checkEq && (s1len != s2len)) { match = 1; - } else { + } else { /* * The comparison function should compare up to the minimum * byte length only. @@ -5468,6 +5504,8 @@ TEBCresume( } } + matchdone: + /* * Make sure only -1,0,1 is returned * TODO: consider peephole opt. @@ -6142,6 +6180,14 @@ TEBCresume( value2Ptr = OBJ_AT_TOS; valuePtr = OBJ_UNDER_TOS; + /* + Try to determine, without triggering generation of a string + representation, whether one value is not a number. + */ + if (TclCheckEmptyString(valuePtr) > 0 || TclCheckEmptyString(value2Ptr) > 0) { + goto stringCompare; + } + if (GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK || GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2) != TCL_OK) { /* diff --git a/generic/tclInt.h b/generic/tclInt.h index 4db4576..4bdaf58 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -2735,6 +2735,10 @@ MODULE_SCOPE long tclObjsShared[TCL_MAX_SHARED_OBJ_STATS]; MODULE_SCOPE char * tclEmptyStringRep; MODULE_SCOPE char tclEmptyString; +enum CheckEmptyStringResult { + TCL_EMPTYSTRING_UNKNOWN = -1, TCL_EMPTYSTRING_NO, TCL_EMPTYSTRING_YES +}; + /* *---------------------------------------------------------------- * Procedures shared among Tcl modules but not used by the outside world, @@ -2875,6 +2879,7 @@ MODULE_SCOPE int TclCheckArrayTraces(Tcl_Interp *interp, Var *varPtr, Var *arrayPtr, Tcl_Obj *name, int index); MODULE_SCOPE int TclCheckBadOctal(Tcl_Interp *interp, const char *value); +MODULE_SCOPE int TclCheckEmptyString(Tcl_Obj *objPtr); MODULE_SCOPE int TclChanCaughtErrorBypass(Tcl_Interp *interp, Tcl_Channel chan); MODULE_SCOPE Tcl_ObjCmdProc TclChannelNamesCmd; @@ -4455,6 +4460,11 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file, #define TclIsPureByteArray(objPtr) \ (((objPtr)->typePtr==&tclByteArrayType) && ((objPtr)->bytes==NULL)) +#define TclIsPureDict(objPtr) \ + (((objPtr)->bytes==NULL) && ((objPtr)->typePtr==&tclDictType)) + +#define TclIsPureList(objPtr) \ + (((objPtr)->bytes==NULL) && ((objPtr)->typePtr==&tclListType)) /* *---------------------------------------------------------------- diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 1b35c56..a503392 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -434,6 +434,7 @@ Tcl_GetCharLength( return length; } + /* * OK, need to work with the object as a string. */ @@ -464,6 +465,50 @@ Tcl_GetCharLength( } return numChars; } + + + +/* + *---------------------------------------------------------------------- + * + * TclCheckEmptyString -- + * + * Determine whether the string value of an object is or would be the + * empty string, without generating a string representation. + * + * Results: + * Returns 1 if empty, 0 if not, and -1 if unknown. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +int +TclCheckEmptyString ( + Tcl_Obj *objPtr +) { + int length = -1; + + if (objPtr->bytes == tclEmptyStringRep) { + return TCL_EMPTYSTRING_YES; + } + + if (TclIsPureList(objPtr)) { + Tcl_ListObjLength(NULL, objPtr, &length); + return length == 0; + } + + if (TclIsPureDict(objPtr)) { + Tcl_DictObjSize(NULL, objPtr, &length); + return length == 0; + } + + if (objPtr->bytes == NULL) { + return TCL_EMPTYSTRING_UNKNOWN; + } + return objPtr->length == 0; +} /* *---------------------------------------------------------------------- -- cgit v0.12 From 86c6a11cdb30d7f9e34ca6882a9882556d0aace2 Mon Sep 17 00:00:00 2001 From: pooryorick Date: Sun, 6 May 2018 13:45:21 +0000 Subject: Preparation to deduplicate code between byte-compiled and legacy implementations of [string compare]. --- generic/tclCmdMZ.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++ generic/tclExecute.c | 120 +------------------------------------------------- generic/tclInt.h | 5 +++ 3 files changed, 129 insertions(+), 118 deletions(-) diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index b686330..9520f86 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -2865,6 +2865,128 @@ StringCmpCmd( return TCL_OK; } +int TclStringCmp ( + Tcl_Obj *value1Ptr, + Tcl_Obj *value2Ptr, + int checkEq +) { + char *s1, *s2; + int empty, match, s1len, s2len; + memCmpFn_t memCmpFn; + + /* + * When we have equal-length we can check only for (in)equality. + * We can use memcmp in all (n)eq cases because we + * don't need to worry about lexical LE/BE variance. + */ + + if (value1Ptr == value2Ptr) { + match = 0; + } else { + if (TclIsPureByteArray(value1Ptr) + && TclIsPureByteArray(value2Ptr)) { + s1 = (char *) Tcl_GetByteArrayFromObj(value1Ptr, &s1len); + s2 = (char *) Tcl_GetByteArrayFromObj(value2Ptr, &s2len); + memCmpFn = memcmp; + } else if ((value1Ptr->typePtr == &tclStringType) + && (value2Ptr->typePtr == &tclStringType)) { + /* + * Do a unicode-specific comparison if both of the args are of + * String type. If the char length == byte length, we can do a + * memcmp. In benchmark testing this proved the most efficient + * check between the unicode and string comparison operations. + */ + + s1len = Tcl_GetCharLength(value1Ptr); + s2len = Tcl_GetCharLength(value2Ptr); + if ((s1len == value1Ptr->length) + && (value1Ptr->bytes != NULL) + && (s2len == value2Ptr->length) + && (value2Ptr->bytes != NULL)) { + s1 = value1Ptr->bytes; + s2 = value2Ptr->bytes; + memCmpFn = memcmp; + } else { + s1 = (char *) Tcl_GetUnicode(value1Ptr); + s2 = (char *) Tcl_GetUnicode(value2Ptr); + if ( +#ifdef WORDS_BIGENDIAN + 1 +#else + checkEq +#endif + ) { + memCmpFn = memcmp; + s1len *= sizeof(Tcl_UniChar); + s2len *= sizeof(Tcl_UniChar); + } else { + memCmpFn = (memCmpFn_t) Tcl_UniCharNcmp; + } + } + } else { + /* + * In order to handle the special Tcl \xC0\x80 null encoding + * for utf-8, strcmp can't do a simple memcmp. + */ + + if ((empty = TclCheckEmptyString(value1Ptr)) > 0) { + switch (TclCheckEmptyString(value2Ptr)) { + case -1: + s1 = ""; + s1len = 0; + s2 = TclGetStringFromObj(value2Ptr, &s2len); + break; + case 0: + match = -1; + goto matchdone; + case 1: + match = 0; + goto matchdone; + } + } else if (TclCheckEmptyString(value2Ptr) > 0) { + switch (empty) { + case -1: + s2 = ""; + s2len = 0; + s1 = TclGetStringFromObj(value1Ptr, &s1len); + break; + case 0: + match = 1; + goto matchdone; + case 1: + match = 0; + goto matchdone; + } + } else { + s1 = TclGetStringFromObj(value1Ptr, &s1len); + s2 = TclGetStringFromObj(value2Ptr, &s2len); + } + + if (checkEq) { + memCmpFn = memcmp; + } else { + memCmpFn = (memCmpFn_t) TclpUtfNcmp2; + } + } + + if (checkEq && (s1len != s2len)) { + match = 1; + } else { + /* + * The comparison function should compare up to the minimum + * byte length only. + */ + match = memCmpFn(s1, s2, + (size_t) ((s1len < s2len) ? s1len : s2len)); + if (match == 0) { + match = s1len - s2len; + } + } + } + matchdone: + return match; +} + /* *---------------------------------------------------------------------- * diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 728a847..a76e686 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -5384,128 +5384,12 @@ TEBCresume( value2Ptr = OBJ_AT_TOS; valuePtr = OBJ_UNDER_TOS; - if (valuePtr == value2Ptr) { - match = 0; - } else { - /* - * We only need to check (in)equality when we have equal length - * strings. We can use memcmp in all (n)eq cases because we - * don't need to worry about lexical LE/BE variance. - */ - - typedef int (*memCmpFn_t)(const void*, const void*, size_t); - memCmpFn_t memCmpFn; + { int checkEq = ((*pc == INST_EQ) || (*pc == INST_NEQ) || (*pc == INST_STR_EQ) || (*pc == INST_STR_NEQ)); - - if (TclIsPureByteArray(valuePtr) - && TclIsPureByteArray(value2Ptr)) { - s1 = (char *) Tcl_GetByteArrayFromObj(valuePtr, &s1len); - s2 = (char *) Tcl_GetByteArrayFromObj(value2Ptr, &s2len); - memCmpFn = memcmp; - } else if ((valuePtr->typePtr == &tclStringType) - && (value2Ptr->typePtr == &tclStringType)) { - /* - * Do a unicode-specific comparison if both of the args are of - * String type. If the char length == byte length, we can do a - * memcmp. In benchmark testing this proved the most efficient - * check between the unicode and string comparison operations. - */ - - s1len = Tcl_GetCharLength(valuePtr); - s2len = Tcl_GetCharLength(value2Ptr); - if ((s1len == valuePtr->length) - && (valuePtr->bytes != NULL) - && (s2len == value2Ptr->length) - && (value2Ptr->bytes != NULL)) { - s1 = valuePtr->bytes; - s2 = value2Ptr->bytes; - memCmpFn = memcmp; - } else { - s1 = (char *) Tcl_GetUnicode(valuePtr); - s2 = (char *) Tcl_GetUnicode(value2Ptr); - if ( -#ifdef WORDS_BIGENDIAN - 1 -#else - checkEq -#endif - ) { - memCmpFn = memcmp; - s1len *= sizeof(Tcl_UniChar); - s2len *= sizeof(Tcl_UniChar); - } else { - memCmpFn = (memCmpFn_t) Tcl_UniCharNcmp; - } - } - } else { - /* - * In order to handle the special Tcl \xC0\x80 null encoding - * for utf-8, strcmp can't do a simple memcmp. - */ - - { - int empty; - if ((empty = TclCheckEmptyString(valuePtr)) > 0) { - switch (TclCheckEmptyString(value2Ptr)) { - case -1: - s1 = ""; - s1len = 0; - s2 = TclGetStringFromObj(value2Ptr, &s2len); - break; - case 0: - match = -1; - goto matchdone; - case 1: - match = 0; - goto matchdone; - } - } else if (TclCheckEmptyString(value2Ptr) > 0) { - switch (empty) { - case -1: - s2 = ""; - s2len = 0; - s1 = TclGetStringFromObj(valuePtr, &s1len); - break; - case 0: - match = 1; - goto matchdone; - case 1: - match = 0; - goto matchdone; - } - } else { - s1 = TclGetStringFromObj(valuePtr, &s1len); - s2 = TclGetStringFromObj(value2Ptr, &s2len); - } - } - - - if (checkEq) { - memCmpFn = memcmp; - } else { - memCmpFn = (memCmpFn_t) TclpUtfNcmp2; - } - - } - - if (checkEq && (s1len != s2len)) { - match = 1; - } else { - /* - * The comparison function should compare up to the minimum - * byte length only. - */ - match = memCmpFn(s1, s2, - (size_t) ((s1len < s2len) ? s1len : s2len)); - if (match == 0) { - match = s1len - s2len; - } - } + match = TclStringCmp(valuePtr, value2Ptr, checkEq); } - matchdone: - /* * Make sure only -1,0,1 is returned * TODO: consider peephole opt. diff --git a/generic/tclInt.h b/generic/tclInt.h index 4bdaf58..1bc8696 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -3155,6 +3155,11 @@ MODULE_SCOPE void TclSpellFix(Tcl_Interp *interp, Tcl_Obj *bad, Tcl_Obj *fix); MODULE_SCOPE void * TclStackRealloc(Tcl_Interp *interp, void *ptr, int numBytes); + +typedef int (*memCmpFn_t)(const void*, const void*, size_t); +MODULE_SCOPE int TclStringCmp (Tcl_Obj *value1Ptr, Tcl_Obj *value2Ptr, + int checkEq); + MODULE_SCOPE int TclStringMatch(const char *str, int strLen, const char *pattern, int ptnLen, int flags); MODULE_SCOPE int TclStringMatchObj(Tcl_Obj *stringObj, -- cgit v0.12 From db133f014426110646fe9631bab793e01cee6129 Mon Sep 17 00:00:00 2001 From: pooryorick Date: Sun, 6 May 2018 18:13:54 +0000 Subject: Factor options handling out of StringCmpCmd. --- generic/tclCmdMZ.c | 94 +++++++++++++++++++++++++++++++++--------------------- generic/tclInt.h | 3 +- 2 files changed, 60 insertions(+), 37 deletions(-) diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index 9520f86..433b9e8 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -2750,45 +2750,19 @@ StringCmpCmd( */ const char *string1, *string2; - int length1, length2, i, match, length, nocase = 0, reqlength = -1; + int length1, length2, match, length, nocase, reqlength, status; typedef int (*strCmpFn_t)(const char *, const char *, unsigned int); strCmpFn_t strCmpFn; - if (objc < 3 || objc > 6) { - str_cmp_args: - Tcl_WrongNumArgs(interp, 1, objv, - "?-nocase? ?-length int? string1 string2"); - return TCL_ERROR; - } - - for (i = 1; i < objc-2; i++) { - string2 = TclGetStringFromObj(objv[i], &length2); - if ((length2 > 1) && !strncmp(string2, "-nocase", (size_t)length2)) { - nocase = 1; - } else if ((length2 > 1) - && !strncmp(string2, "-length", (size_t)length2)) { - if (i+1 >= objc-2) { - goto str_cmp_args; - } - i++; - if (TclGetIntFromObj(interp, objv[i], &reqlength) != TCL_OK) { - return TCL_ERROR; - } - } else { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "bad option \"%s\": must be -nocase or -length", - string2)); - Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "option", - string2, NULL); - return TCL_ERROR; - } + if ((status = TclStringCmpOpts(interp, objc, objv, &reqlength, + (char **)&string2, &length2, &nocase)) != TCL_OK){ + return status; } /* * From now on, we only access the two objects at the end of the argument * array. */ - objv += objc-2; if ((reqlength == 0) || (objv[0] == objv[1])) { @@ -2802,12 +2776,6 @@ StringCmpCmd( if (!nocase && TclIsPureByteArray(objv[0]) && TclIsPureByteArray(objv[1])) { - /* - * Use binary versions of comparisons since that won't cause undue - * type conversions and it is much faster. Only do this if we're - * case-sensitive (which is all that really makes sense with byte - * arrays anyway, and we have no memcasecmp() for some reason... :^) - */ string1 = (char *) Tcl_GetByteArrayFromObj(objv[0], &length1); string2 = (char *) Tcl_GetByteArrayFromObj(objv[1], &length2); @@ -2885,6 +2853,12 @@ int TclStringCmp ( } else { if (TclIsPureByteArray(value1Ptr) && TclIsPureByteArray(value2Ptr)) { + /* + * Use binary versions of comparisons since that won't cause undue + * type conversions and it is much faster. Only do this if we're + * case-sensitive (which is all that really makes sense with byte + * arrays anyway, and we have no memcasecmp() for some reason... :^) + */ s1 = (char *) Tcl_GetByteArrayFromObj(value1Ptr, &s1len); s2 = (char *) Tcl_GetByteArrayFromObj(value2Ptr, &s2len); memCmpFn = memcmp; @@ -2987,6 +2961,54 @@ int TclStringCmp ( return match; } +int TclStringCmpOpts ( + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[], /* Argument objects. */ + int *reqlength, + char **stringPtr, + int *length, + int *nocase + +) +{ + int i; + const char *string = *stringPtr; + + *reqlength = -1; + *nocase = 0; + if (objc < 3 || objc > 6) { + str_cmp_args: + Tcl_WrongNumArgs(interp, 1, objv, + "?-nocase? ?-length int? string1 string2"); + return TCL_ERROR; + } + + for (i = 1; i < objc-2; i++) { + string = TclGetStringFromObj(objv[i], length); + if ((*length > 1) && !strncmp(string, "-nocase", (size_t)*length)) { + *nocase = 1; + } else if ((*length > 1) + && !strncmp(string, "-length", (size_t)*length)) { + if (i+1 >= objc-2) { + goto str_cmp_args; + } + i++; + if (TclGetIntFromObj(interp, objv[i], reqlength) != TCL_OK) { + return TCL_ERROR; + } + } else { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "bad option \"%s\": must be -nocase or -length", + string)); + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "option", + string, NULL); + return TCL_ERROR; + } + } + return TCL_OK; +} + /* *---------------------------------------------------------------------- * diff --git a/generic/tclInt.h b/generic/tclInt.h index 1bc8696..67f53fd 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -3159,7 +3159,8 @@ MODULE_SCOPE void * TclStackRealloc(Tcl_Interp *interp, void *ptr, typedef int (*memCmpFn_t)(const void*, const void*, size_t); MODULE_SCOPE int TclStringCmp (Tcl_Obj *value1Ptr, Tcl_Obj *value2Ptr, int checkEq); - +MODULE_SCOPE int TclStringCmpOpts (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], + int *reqlength, char **stringPtr, int *length2, int *nocase); MODULE_SCOPE int TclStringMatch(const char *str, int strLen, const char *pattern, int ptnLen, int flags); MODULE_SCOPE int TclStringMatchObj(Tcl_Obj *stringObj, -- cgit v0.12 From 5500074eff2f8cd05b593f4dcac0aecd23e00b94 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 7 May 2018 07:40:58 +0000 Subject: Remove some tip389 restrictions in test-cases, which are no longer necessary. Eliminate gcc compiler warnings when compiling with -DTCL_UTF_MAX=6 Other code clean-up and comment improvements. No change in functionality. --- generic/tcl.h | 6 +++--- generic/tclCmdMZ.c | 14 +++++++------- generic/tclUtf.c | 4 ++-- tests/utf.test | 18 ++++++++---------- 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/generic/tcl.h b/generic/tcl.h index c3e0f9d..6dd0ea0 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -2146,9 +2146,9 @@ typedef struct Tcl_EncodingType { /* * The maximum number of bytes that are necessary to represent a single - * Unicode character in UTF-8. The valid values should be 3, 4 or 6 - * (or perhaps 1 if we want to support a non-unicode enabled core). If 3 or - * 4, then Tcl_UniChar must be 2-bytes in size (UCS-2) (the default). If 6, + * Unicode character in UTF-8. The valid values are 4 and 6 + * (or perhaps 1 if we want to support a non-unicode enabled core). If 4, + * then Tcl_UniChar must be 2-bytes in size (UCS-2) (the default). If 6, * then Tcl_UniChar must be 4-bytes in size (UCS-4). At this time UCS-2 mode * is the default and recommended mode. UCS-4 is experimental and not * recommended. It works for the core, but most extensions expect UCS-2. diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index 6aaf1de..7c979bb 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -597,9 +597,9 @@ Tcl_RegsubObjCmd( * slightly modified version of the one pair STR_MAP code. */ - int slen, nocase; + int slen, nocase, wsrclc; int (*strCmpFn)(const Tcl_UniChar*,const Tcl_UniChar*,unsigned long); - Tcl_UniChar *p, wsrclc; + Tcl_UniChar *p; numMatches = 0; nocase = (cflags & TCL_REG_NOCASE); @@ -2001,8 +2001,8 @@ StringMapCmd( * larger strings. */ - int mapLen; - Tcl_UniChar *mapString, u2lc; + int mapLen, u2lc; + Tcl_UniChar *mapString; ustring2 = Tcl_GetUnicodeFromObj(mapElemv[0], &length2); p = ustring1; @@ -2033,8 +2033,8 @@ StringMapCmd( } } } else { - Tcl_UniChar **mapStrings, *u2lc = NULL; - int *mapLens; + Tcl_UniChar **mapStrings; + int *mapLens, *u2lc = NULL; /* * Precompute pointers to the unicode string and length. This saves us @@ -2046,7 +2046,7 @@ StringMapCmd( mapStrings = TclStackAlloc(interp, mapElemc*2*sizeof(Tcl_UniChar *)); mapLens = TclStackAlloc(interp, mapElemc * 2 * sizeof(int)); if (nocase) { - u2lc = TclStackAlloc(interp, mapElemc * sizeof(Tcl_UniChar)); + u2lc = TclStackAlloc(interp, mapElemc * sizeof(int)); } for (index = 0; index < mapElemc; index++) { mapStrings[index] = Tcl_GetUnicodeFromObj(mapElemv[index], diff --git a/generic/tclUtf.c b/generic/tclUtf.c index 1d73a7a..693e210 100644 --- a/generic/tclUtf.c +++ b/generic/tclUtf.c @@ -1034,8 +1034,8 @@ Tcl_UtfToTitle( lowChar = (((lowChar & 0x3ff) << 10) | (ch & 0x3ff)) + 0x10000; } #endif - /* Special exception for Gregorian characters, which don't have titlecase */ - if ((lowChar < 0x1C90) || (lowChar >= 0x1CC0)) { + /* Special exception for Georgian Asomtavruli chars, no titlecase. */ + if ((unsigned)(lowChar - 0x1C90) >= 0x30) { lowChar = Tcl_UniCharToLower(lowChar); } diff --git a/tests/utf.test b/tests/utf.test index 39818cc..9dd8017 100644 --- a/tests/utf.test +++ b/tests/utf.test @@ -41,7 +41,7 @@ test utf-1.5 {Tcl_UniCharToUtf: overflowed Tcl_UniChar} testbytestring { test utf-1.6 {Tcl_UniCharToUtf: negative Tcl_UniChar} testbytestring { expr {[format %c -1] eq [testbytestring "\xef\xbf\xbd"]} } 1 -test utf-1.7 {Tcl_UniCharToUtf: 4 byte sequences} -constraints {tip389 testbytestring} -body { +test utf-1.7 {Tcl_UniCharToUtf: 4 byte sequences} -constraints testbytestring -body { expr {"\U014e4e" eq [testbytestring "\xf0\x94\xb9\x8e"]} } -result 1 @@ -228,15 +228,13 @@ bsCheck \U4e21 20001 bsCheck \U004e21 20001 bsCheck \U00004e21 20001 bsCheck \U0000004e21 78 -if {[testConstraint tip389]} { - bsCheck \U00110000 69632 - bsCheck \U01100000 69632 - bsCheck \U11000000 69632 - bsCheck \U0010FFFF 1114111 - bsCheck \U010FFFF0 1114111 - bsCheck \U10FFFF00 1114111 - bsCheck \UFFFFFFFF 1048575 -} +bsCheck \U00110000 69632 +bsCheck \U01100000 69632 +bsCheck \U11000000 69632 +bsCheck \U0010FFFF 1114111 +bsCheck \U010FFFF0 1114111 +bsCheck \U10FFFF00 1114111 +bsCheck \UFFFFFFFF 1048575 test utf-11.1 {Tcl_UtfToUpper} { string toupper {} -- cgit v0.12 From 5f0cf291f513b75b00ea3d59842b83dc24047c1c Mon Sep 17 00:00:00 2001 From: pooryorick Date: Mon, 7 May 2018 07:43:00 +0000 Subject: Deduplicate code in INST_STR_CMP, StringCmpCmd, and StringEqualCmd. --- generic/tclCmdMZ.c | 369 ++++++++++++++++++--------------------------------- generic/tclExecute.c | 2 +- generic/tclInt.h | 4 +- 3 files changed, 130 insertions(+), 245 deletions(-) diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index 433b9e8..bc798b7 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -2599,10 +2599,8 @@ StringEqualCmd( * the expr string comparison in INST_EQ/INST_NEQ/INST_LT/...). */ - const char *string1, *string2; - int length1, length2, i, match, length, nocase = 0, reqlength = -1; - typedef int (*strCmpFn_t)(const char *, const char *, unsigned int); - strCmpFn_t strCmpFn; + const char *string2; + int length2, i, match, nocase = 0, reqlength = -1; if (objc < 3 || objc > 6) { str_cmp_args: @@ -2641,78 +2639,7 @@ StringEqualCmd( objv += objc-2; - if ((reqlength == 0) || (objv[0] == objv[1])) { - /* - * Always match at 0 chars of if it is the same obj. - */ - - Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1)); - return TCL_OK; - } - - if (!nocase && TclIsPureByteArray(objv[0]) && - TclIsPureByteArray(objv[1])) { - /* - * Use binary versions of comparisons since that won't cause undue - * type conversions and it is much faster. Only do this if we're - * case-sensitive (which is all that really makes sense with byte - * arrays anyway, and we have no memcasecmp() for some reason... :^) - */ - - string1 = (char *) Tcl_GetByteArrayFromObj(objv[0], &length1); - string2 = (char *) Tcl_GetByteArrayFromObj(objv[1], &length2); - strCmpFn = (strCmpFn_t) memcmp; - } else if ((objv[0]->typePtr == &tclStringType) - && (objv[1]->typePtr == &tclStringType)) { - /* - * Do a unicode-specific comparison if both of the args are of String - * type. In benchmark testing this proved the most efficient check - * between the unicode and string comparison operations. - */ - - string1 = (char *) Tcl_GetUnicodeFromObj(objv[0], &length1); - string2 = (char *) Tcl_GetUnicodeFromObj(objv[1], &length2); - strCmpFn = (strCmpFn_t) - (nocase ? Tcl_UniCharNcasecmp : Tcl_UniCharNcmp); - } else { - /* - * As a catch-all we will work with UTF-8. We cannot use memcmp() as - * that is unsafe with any string containing NUL (\xC0\x80 in Tcl's - * utf rep). We can use the more efficient TclpUtfNcmp2 if we are - * case-sensitive and no specific length was requested. - */ - - string1 = (char *) TclGetStringFromObj(objv[0], &length1); - string2 = (char *) TclGetStringFromObj(objv[1], &length2); - if ((reqlength < 0) && !nocase) { - strCmpFn = (strCmpFn_t) TclpUtfNcmp2; - } else { - length1 = Tcl_NumUtfChars(string1, length1); - length2 = Tcl_NumUtfChars(string2, length2); - strCmpFn = (strCmpFn_t) (nocase ? Tcl_UtfNcasecmp : Tcl_UtfNcmp); - } - } - - if ((reqlength < 0) && (length1 != length2)) { - match = 1; /* This will be reversed below. */ - } else { - length = (length1 < length2) ? length1 : length2; - if (reqlength > 0 && reqlength < length) { - length = reqlength; - } else if (reqlength < 0) { - /* - * The requested length is negative, so we ignore it by setting it - * to length + 1 so we correct the match var. - */ - - reqlength = length + 1; - } - - match = strCmpFn(string1, string2, (unsigned) length); - if ((match == 0) && (reqlength > length)) { - match = length1 - length2; - } - } + match = TclStringCmp (objv[0], objv[1], 0, nocase, reqlength); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(match ? 0 : 1)); return TCL_OK; @@ -2749,128 +2676,63 @@ StringCmpCmd( * the expr string comparison in INST_EQ/INST_NEQ/INST_LT/...). */ - const char *string1, *string2; - int length1, length2, match, length, nocase, reqlength, status; - typedef int (*strCmpFn_t)(const char *, const char *, unsigned int); - strCmpFn_t strCmpFn; + int match, nocase, reqlength, status; + + if ((status = TclStringCmpOpts(interp, objc, objv, &nocase, &reqlength)) + != TCL_OK) { - if ((status = TclStringCmpOpts(interp, objc, objv, &reqlength, - (char **)&string2, &length2, &nocase)) != TCL_OK){ return status; } - /* - * From now on, we only access the two objects at the end of the argument - * array. - */ objv += objc-2; - - if ((reqlength == 0) || (objv[0] == objv[1])) { - /* - * Always match at 0 chars of if it is the same obj. - */ - - Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0)); - return TCL_OK; - } - - if (!nocase && TclIsPureByteArray(objv[0]) && - TclIsPureByteArray(objv[1])) { - - string1 = (char *) Tcl_GetByteArrayFromObj(objv[0], &length1); - string2 = (char *) Tcl_GetByteArrayFromObj(objv[1], &length2); - strCmpFn = (strCmpFn_t) memcmp; - } else if ((objv[0]->typePtr == &tclStringType) - && (objv[1]->typePtr == &tclStringType)) { - /* - * Do a unicode-specific comparison if both of the args are of String - * type. In benchmark testing this proved the most efficient check - * between the unicode and string comparison operations. - */ - - string1 = (char *) Tcl_GetUnicodeFromObj(objv[0], &length1); - string2 = (char *) Tcl_GetUnicodeFromObj(objv[1], &length2); - strCmpFn = (strCmpFn_t) - (nocase ? Tcl_UniCharNcasecmp : Tcl_UniCharNcmp); - } else { - /* - * As a catch-all we will work with UTF-8. We cannot use memcmp() as - * that is unsafe with any string containing NUL (\xC0\x80 in Tcl's - * utf rep). We can use the more efficient TclpUtfNcmp2 if we are - * case-sensitive and no specific length was requested. - */ - - string1 = (char *) TclGetStringFromObj(objv[0], &length1); - string2 = (char *) TclGetStringFromObj(objv[1], &length2); - if ((reqlength < 0) && !nocase) { - strCmpFn = (strCmpFn_t) TclpUtfNcmp2; - } else { - length1 = Tcl_NumUtfChars(string1, length1); - length2 = Tcl_NumUtfChars(string2, length2); - strCmpFn = (strCmpFn_t) (nocase ? Tcl_UtfNcasecmp : Tcl_UtfNcmp); - } - } - - length = (length1 < length2) ? length1 : length2; - if (reqlength > 0 && reqlength < length) { - length = reqlength; - } else if (reqlength < 0) { - /* - * The requested length is negative, so we ignore it by setting it to - * length + 1 so we correct the match var. - */ - - reqlength = length + 1; - } - - match = strCmpFn(string1, string2, (unsigned) length); - if ((match == 0) && (reqlength > length)) { - match = length1 - length2; - } - - Tcl_SetObjResult(interp, - Tcl_NewIntObj((match > 0) ? 1 : (match < 0) ? -1 : 0)); + match = TclStringCmp (objv[0], objv[1], 0, nocase, reqlength); + Tcl_SetObjResult(interp, Tcl_NewIntObj(match)); return TCL_OK; } int TclStringCmp ( Tcl_Obj *value1Ptr, Tcl_Obj *value2Ptr, - int checkEq + int checkEq, /* comparison is only for equality */ + int nocase, /* comparison is not case sensitive */ + int reqlength /* requested length */ ) { - char *s1, *s2; - int empty, match, s1len, s2len; - memCmpFn_t memCmpFn; + char *s1, *s2; + int empty, length, match, s1len, s2len; + memCmpFn_t memCmpFn; + if ((reqlength == 0) || (value1Ptr == value2Ptr)) { /* - * When we have equal-length we can check only for (in)equality. - * We can use memcmp in all (n)eq cases because we - * don't need to worry about lexical LE/BE variance. + * Always match at 0 chars of if it is the same obj. */ + match = 0; + } else { - if (value1Ptr == value2Ptr) { - match = 0; - } else { - if (TclIsPureByteArray(value1Ptr) - && TclIsPureByteArray(value2Ptr)) { - /* - * Use binary versions of comparisons since that won't cause undue - * type conversions and it is much faster. Only do this if we're - * case-sensitive (which is all that really makes sense with byte - * arrays anyway, and we have no memcasecmp() for some reason... :^) - */ - s1 = (char *) Tcl_GetByteArrayFromObj(value1Ptr, &s1len); - s2 = (char *) Tcl_GetByteArrayFromObj(value2Ptr, &s2len); - memCmpFn = memcmp; - } else if ((value1Ptr->typePtr == &tclStringType) - && (value2Ptr->typePtr == &tclStringType)) { - /* - * Do a unicode-specific comparison if both of the args are of - * String type. If the char length == byte length, we can do a - * memcmp. In benchmark testing this proved the most efficient - * check between the unicode and string comparison operations. - */ + if (!nocase && TclIsPureByteArray(value1Ptr) + && TclIsPureByteArray(value2Ptr)) { + /* + * Use binary versions of comparisons since that won't cause undue + * type conversions and it is much faster. Only do this if we're + * case-sensitive (which is all that really makes sense with byte + * arrays anyway, and we have no memcasecmp() for some reason... :^) + */ + s1 = (char *) Tcl_GetByteArrayFromObj(value1Ptr, &s1len); + s2 = (char *) Tcl_GetByteArrayFromObj(value2Ptr, &s2len); + memCmpFn = memcmp; + } else if ((value1Ptr->typePtr == &tclStringType) + && (value2Ptr->typePtr == &tclStringType)) { + /* + * Do a unicode-specific comparison if both of the args are of + * String type. If the char length == byte length, we can do a + * memcmp. In benchmark testing this proved the most efficient + * check between the unicode and string comparison operations. + */ + if (nocase) { + s1 = (char *) Tcl_GetUnicodeFromObj(value1Ptr, &s1len); + s2 = (char *) Tcl_GetUnicodeFromObj(value2Ptr, &s2len); + memCmpFn = (memCmpFn_t)Tcl_UniCharNcasecmp; + } else { s1len = Tcl_GetCharLength(value1Ptr); s2len = Tcl_GetCharLength(value2Ptr); if ((s1len == value1Ptr->length) @@ -2897,66 +2759,92 @@ int TclStringCmp ( memCmpFn = (memCmpFn_t) Tcl_UniCharNcmp; } } - } else { - /* - * In order to handle the special Tcl \xC0\x80 null encoding - * for utf-8, strcmp can't do a simple memcmp. - */ - - if ((empty = TclCheckEmptyString(value1Ptr)) > 0) { - switch (TclCheckEmptyString(value2Ptr)) { - case -1: - s1 = ""; - s1len = 0; - s2 = TclGetStringFromObj(value2Ptr, &s2len); - break; - case 0: - match = -1; - goto matchdone; - case 1: - match = 0; - goto matchdone; - } - } else if (TclCheckEmptyString(value2Ptr) > 0) { - switch (empty) { - case -1: - s2 = ""; - s2len = 0; - s1 = TclGetStringFromObj(value1Ptr, &s1len); - break; - case 0: - match = 1; - goto matchdone; - case 1: - match = 0; - goto matchdone; - } - } else { - s1 = TclGetStringFromObj(value1Ptr, &s1len); + } + } else { + if ((empty = TclCheckEmptyString(value1Ptr)) > 0) { + switch (TclCheckEmptyString(value2Ptr)) { + case -1: + s1 = ""; + s1len = 0; s2 = TclGetStringFromObj(value2Ptr, &s2len); + break; + case 0: + match = -1; + goto matchdone; + case 1: + match = 0; + goto matchdone; } - - if (checkEq) { - memCmpFn = memcmp; - } else { - memCmpFn = (memCmpFn_t) TclpUtfNcmp2; + } else if (TclCheckEmptyString(value2Ptr) > 0) { + switch (empty) { + case -1: + s2 = ""; + s2len = 0; + s1 = TclGetStringFromObj(value1Ptr, &s1len); + break; + case 0: + match = 1; + goto matchdone; + case 1: + match = 0; + goto matchdone; } + } else { + s1 = TclGetStringFromObj(value1Ptr, &s1len); + s2 = TclGetStringFromObj(value2Ptr, &s2len); } + if (!nocase && checkEq) { + /* + * When we have equal-length we can check only for (in)equality. + * We can use memcmp in all (n)eq cases because we + * don't need to worry about lexical LE/BE variance. + */ + memCmpFn = memcmp; + } else { - if (checkEq && (s1len != s2len)) { - match = 1; - } else { /* - * The comparison function should compare up to the minimum - * byte length only. + * As a catch-all we will work with UTF-8. We cannot use memcmp() as + * that is unsafe with any string containing NUL (\xC0\x80 in Tcl's + * utf rep). We can use the more efficient TclpUtfNcmp2 if we are + * case-sensitive and no specific length was requested. */ - match = memCmpFn(s1, s2, - (size_t) ((s1len < s2len) ? s1len : s2len)); - if (match == 0) { - match = s1len - s2len; + + if ((reqlength < 0) && !nocase) { + memCmpFn = (memCmpFn_t) TclpUtfNcmp2; + } else { + s1len = Tcl_NumUtfChars(s1, s1len); + s2len = Tcl_NumUtfChars(s2, s2len); + memCmpFn = (memCmpFn_t) (nocase ? Tcl_UtfNcasecmp : Tcl_UtfNcmp); } } } + + length = (s1len < s2len) ? s1len : s2len; + if (reqlength > 0 && reqlength < length) { + length = reqlength; + } else if (reqlength < 0) { + /* + * The requested length is negative, so we ignore it by setting it to + * length + 1 so we correct the match var. + */ + + reqlength = length + 1; + } + + if (checkEq && (s1len != s2len)) { + match = 1; /* This will be reversed below. */ + } else { + /* + * The comparison function should compare up to the minimum + * byte length only. + */ + match = memCmpFn(s1, s2, (size_t) length); + } + if ((match == 0) && (reqlength > length)) { + match = s1len - s2len; + } + match = (match > 0) ? 1 : (match < 0) ? -1 : 0; + } matchdone: return match; } @@ -2965,15 +2853,12 @@ int TclStringCmpOpts ( Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[], /* Argument objects. */ - int *reqlength, - char **stringPtr, - int *length, - int *nocase - + int *nocase, + int *reqlength ) { - int i; - const char *string = *stringPtr; + int i, length; + const char *string; *reqlength = -1; *nocase = 0; @@ -2985,11 +2870,11 @@ int TclStringCmpOpts ( } for (i = 1; i < objc-2; i++) { - string = TclGetStringFromObj(objv[i], length); - if ((*length > 1) && !strncmp(string, "-nocase", (size_t)*length)) { + string = TclGetStringFromObj(objv[i], &length); + if ((length > 1) && !strncmp(string, "-nocase", (size_t)length)) { *nocase = 1; - } else if ((*length > 1) - && !strncmp(string, "-length", (size_t)*length)) { + } else if ((length > 1) + && !strncmp(string, "-length", (size_t)length)) { if (i+1 >= objc-2) { goto str_cmp_args; } diff --git a/generic/tclExecute.c b/generic/tclExecute.c index a76e686..4c14514 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -5387,7 +5387,7 @@ TEBCresume( { int checkEq = ((*pc == INST_EQ) || (*pc == INST_NEQ) || (*pc == INST_STR_EQ) || (*pc == INST_STR_NEQ)); - match = TclStringCmp(valuePtr, value2Ptr, checkEq); + match = TclStringCmp(valuePtr, value2Ptr, checkEq, 0, -1); } /* diff --git a/generic/tclInt.h b/generic/tclInt.h index 67f53fd..0a3285f 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -3158,9 +3158,9 @@ MODULE_SCOPE void * TclStackRealloc(Tcl_Interp *interp, void *ptr, typedef int (*memCmpFn_t)(const void*, const void*, size_t); MODULE_SCOPE int TclStringCmp (Tcl_Obj *value1Ptr, Tcl_Obj *value2Ptr, - int checkEq); + int checkEq, int nocase, int reqlength); MODULE_SCOPE int TclStringCmpOpts (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], - int *reqlength, char **stringPtr, int *length2, int *nocase); + int *nocase, int *reqlength); MODULE_SCOPE int TclStringMatch(const char *str, int strLen, const char *pattern, int ptnLen, int flags); MODULE_SCOPE int TclStringMatchObj(Tcl_Obj *stringObj, -- cgit v0.12 From 78ee8c697e423a5b4718fabb53eef1c5f6a2a2b1 Mon Sep 17 00:00:00 2001 From: sebres Date: Tue, 8 May 2018 09:49:16 +0000 Subject: fixes [92564326a98b5510]: wrong x64-aligned handle from readdir64 by opendir/rewinddir/closedir, if HAVE_STRUCT_DIRENT64 used. --- unix/tclUnixFCmd.c | 14 +++++++------- unix/tclUnixFile.c | 4 ++-- unix/tclUnixPort.h | 6 ++++++ 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/unix/tclUnixFCmd.c b/unix/tclUnixFCmd.c index b5450b1..4377b77 100644 --- a/unix/tclUnixFCmd.c +++ b/unix/tclUnixFCmd.c @@ -333,7 +333,7 @@ DoRenameFile( if ((Realpath((char *) src, srcPath) != NULL) /* INTL: Native. */ && (Realpath((char *) dst, dstPath) != NULL) /* INTL: Native */ && (strncmp(srcPath, dstPath, strlen(srcPath)) != 0)) { - dirPtr = opendir(dst); /* INTL: Native. */ + dirPtr = TclOSopendir(dst); /* INTL: Native. */ if (dirPtr != NULL) { while (1) { dirEntPtr = TclOSreaddir(dirPtr); /* INTL: Native. */ @@ -343,11 +343,11 @@ DoRenameFile( if ((strcmp(dirEntPtr->d_name, ".") != 0) && (strcmp(dirEntPtr->d_name, "..") != 0)) { errno = EEXIST; - closedir(dirPtr); + TclOSclosedir(dirPtr); return TCL_ERROR; } } - closedir(dirPtr); + TclOSclosedir(dirPtr); } } errno = EINVAL; @@ -945,7 +945,7 @@ TraverseUnixTree( errorPtr); } #ifndef HAVE_FTS - dirPtr = opendir(source); /* INTL: Native. */ + dirPtr = TclOSopendir(source); /* INTL: Native. */ if (dirPtr == NULL) { /* * Can't read directory @@ -957,7 +957,7 @@ TraverseUnixTree( result = (*traverseProc)(sourcePtr, targetPtr, &statBuf, DOTREE_PRED, errorPtr); if (result != TCL_OK) { - closedir(dirPtr); + TclOSclosedir(dirPtr); return result; } @@ -1007,11 +1007,11 @@ TraverseUnixTree( * NULL-return that may a symptom of a buggy readdir. */ - rewinddir(dirPtr); + TclOSrewinddir(dirPtr); numProcessed = 0; } } - closedir(dirPtr); + TclOSclosedir(dirPtr); /* * Strip off the trailing slash we added diff --git a/unix/tclUnixFile.c b/unix/tclUnixFile.c index 0a2099c..1dc73ae 100644 --- a/unix/tclUnixFile.c +++ b/unix/tclUnixFile.c @@ -310,7 +310,7 @@ TclpMatchInDirectory( return TCL_OK; } - d = opendir(native); /* INTL: Native. */ + d = TclOSopendir(native); /* INTL: Native. */ if (d == NULL) { Tcl_DStringFree(&ds); if (interp != NULL) { @@ -383,7 +383,7 @@ TclpMatchInDirectory( } } - closedir(d); + TclOSclosedir(d); Tcl_DStringFree(&ds); Tcl_DStringFree(&dsOrig); Tcl_DecrRefCount(fileNamePtr); diff --git a/unix/tclUnixPort.h b/unix/tclUnixPort.h index 965014e..cc31bf9 100644 --- a/unix/tclUnixPort.h +++ b/unix/tclUnixPort.h @@ -60,9 +60,15 @@ #ifdef HAVE_STRUCT_DIRENT64 typedef struct dirent64 Tcl_DirEntry; # define TclOSreaddir readdir64 +# define TclOSopendir opendir64 +# define TclOSrewinddir rewinddir64 +# define TclOSclosedir closedir64 #else typedef struct dirent Tcl_DirEntry; # define TclOSreaddir readdir +# define TclOSopendir opendir +# define TclOSrewinddir rewinddir +# define TclOSclosedir closedir #endif #ifdef HAVE_TYPE_OFF64_T -- cgit v0.12 From 47e9dbdc37939a6e874afd15d6586864649f23c7 Mon Sep 17 00:00:00 2001 From: sebres Date: Tue, 8 May 2018 10:16:26 +0000 Subject: prevents UB/segfault by unexpected return-code (not -1/0/1) and avoid warnings like: tclCmdMZ.c:2815:15: warning: `s1` may be used uninitialized in this function [-Wmaybe-uninitialized] s1len = Tcl_NumUtfChars(s1, s1len); ^~~~~~~~~~~~~~~~~~~~~~~~~~ --- generic/tclCmdMZ.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index bc798b7..8530719 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -2772,6 +2772,7 @@ int TclStringCmp ( match = -1; goto matchdone; case 1: + default: /* avoid warn: `s2` may be used uninitialized */ match = 0; goto matchdone; } @@ -2786,6 +2787,7 @@ int TclStringCmp ( match = 1; goto matchdone; case 1: + default: /* avoid warn: `s1` may be used uninitialized */ match = 0; goto matchdone; } -- cgit v0.12 From 7855612da63e86b43a8a5beb0ad495e6605a2d93 Mon Sep 17 00:00:00 2001 From: pooryorick Date: Tue, 8 May 2018 20:03:14 +0000 Subject: Fix epoll notifier memory leak in initialization/finalization routines, --- unix/tclEpollNotfy.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/unix/tclEpollNotfy.c b/unix/tclEpollNotfy.c index 9d0053c..076e02b 100644 --- a/unix/tclEpollNotfy.c +++ b/unix/tclEpollNotfy.c @@ -88,6 +88,7 @@ typedef struct { LIST_HEAD(PlatformReadyFileHandlerList, FileHandler); typedef struct ThreadSpecificData { + FileHandler *triggerFilePtr; FileHandler *firstFileHandlerPtr; /* Pointer to head of file handler list. */ struct PlatformReadyFileHandlerList firstReadyFileHandlerPtr; @@ -306,6 +307,8 @@ PlatformEventsFinalize( tsdPtr->triggerPipe[1] = -1; } #endif /* HAVE_EVENTFD */ + ckfree(tsdPtr->triggerFilePtr->pedPtr); + ckfree(tsdPtr->triggerFilePtr); if (tsdPtr->eventsFd > 0) { close(tsdPtr->eventsFd); tsdPtr->eventsFd = 0; @@ -368,6 +371,7 @@ PlatformEventsInit( } filePtr->fd = tsdPtr->triggerPipe[0]; #endif + tsdPtr->triggerFilePtr = filePtr; if ((tsdPtr->eventsFd = epoll_create1(EPOLL_CLOEXEC)) == -1) { Tcl_Panic("epoll_create1: %s", strerror(errno)); } -- cgit v0.12 From f5e87513071af9794d48e1b5c1b106343f4bca1f Mon Sep 17 00:00:00 2001 From: sebres Date: Wed, 9 May 2018 10:29:33 +0000 Subject: amend to [85bcf84100]: replaces DIR with Tcl_Dir (DIR/DIR64 regarding HAVE_STRUCT_DIRENT64) --- generic/tclInt.decls | 4 ++-- generic/tclIntPlatDecls.h | 13 +++++++------ unix/tclUnixFCmd.c | 4 ++-- unix/tclUnixFile.c | 2 +- unix/tclUnixPort.h | 2 ++ unix/tclUnixThrd.c | 2 +- 6 files changed, 15 insertions(+), 12 deletions(-) diff --git a/generic/tclInt.decls b/generic/tclInt.decls index 920116c..69e695e 100644 --- a/generic/tclInt.decls +++ b/generic/tclInt.decls @@ -995,7 +995,7 @@ declare 9 win { } # new for 8.4.20+/8.5.12+ Cygwin only declare 10 win { - Tcl_DirEntry *TclpReaddir(DIR *dir) + Tcl_DirEntry *TclpReaddir(Tcl_Dir *dir) } # Removed in 8.3.1 (for Win32s only) #declare 10 win { @@ -1135,7 +1135,7 @@ declare 9 unix { # Added in 8.4: declare 10 unix { - Tcl_DirEntry *TclpReaddir(DIR *dir) + Tcl_DirEntry *TclpReaddir(Tcl_Dir *dir) } # Slots 11 and 12 are forwarders for functions that were promoted to # generic Stubs diff --git a/generic/tclIntPlatDecls.h b/generic/tclIntPlatDecls.h index fc20d09..d792a54 100644 --- a/generic/tclIntPlatDecls.h +++ b/generic/tclIntPlatDecls.h @@ -16,6 +16,7 @@ #ifdef __WIN32__ # define Tcl_DirEntry void # define DIR void +# define Tcl_Dir void #endif #undef TCL_STORAGE_CLASS @@ -101,7 +102,7 @@ EXTERN TclFile TclpCreateTempFile(CONST char *contents); #ifndef TclpReaddir_TCL_DECLARED #define TclpReaddir_TCL_DECLARED /* 10 */ -EXTERN Tcl_DirEntry * TclpReaddir(DIR *dir); +EXTERN Tcl_DirEntry * TclpReaddir(Tcl_Dir *dir); #endif #ifndef TclpLocaltime_unix_TCL_DECLARED #define TclpLocaltime_unix_TCL_DECLARED @@ -202,7 +203,7 @@ EXTERN int TclWinGetPlatformId(void); #ifndef TclpReaddir_TCL_DECLARED #define TclpReaddir_TCL_DECLARED /* 10 */ -EXTERN Tcl_DirEntry * TclpReaddir(DIR *dir); +EXTERN Tcl_DirEntry * TclpReaddir(Tcl_Dir *dir); #endif #ifndef TclGetAndDetachPids_TCL_DECLARED #define TclGetAndDetachPids_TCL_DECLARED @@ -360,7 +361,7 @@ EXTERN TclFile TclpCreateTempFile(CONST char *contents); #ifndef TclpReaddir_TCL_DECLARED #define TclpReaddir_TCL_DECLARED /* 10 */ -EXTERN Tcl_DirEntry * TclpReaddir(DIR *dir); +EXTERN Tcl_DirEntry * TclpReaddir(Tcl_Dir *dir); #endif #ifndef TclpLocaltime_unix_TCL_DECLARED #define TclpLocaltime_unix_TCL_DECLARED @@ -450,7 +451,7 @@ typedef struct TclIntPlatStubs { TclFile (*tclpOpenFile) (CONST char *fname, int mode); /* 7 */ int (*tclUnixWaitForFile) (int fd, int mask, int timeout); /* 8 */ TclFile (*tclpCreateTempFile) (CONST char *contents); /* 9 */ - Tcl_DirEntry * (*tclpReaddir) (DIR *dir); /* 10 */ + Tcl_DirEntry * (*tclpReaddir) (Tcl_Dir *dir); /* 10 */ struct tm * (*tclpLocaltime_unix) (CONST time_t *clock); /* 11 */ struct tm * (*tclpGmtime_unix) (CONST time_t *clock); /* 12 */ char * (*tclpInetNtoa) (struct in_addr addr); /* 13 */ @@ -482,7 +483,7 @@ typedef struct TclIntPlatStubs { int (*tclWinSetSockOpt) (SOCKET s, int level, int optname, CONST char *optval, int optlen); /* 7 */ int (*tclpGetPid) (Tcl_Pid pid); /* 8 */ int (*tclWinGetPlatformId) (void); /* 9 */ - Tcl_DirEntry * (*tclpReaddir) (DIR *dir); /* 10 */ + Tcl_DirEntry * (*tclpReaddir) (Tcl_Dir *dir); /* 10 */ void (*tclGetAndDetachPids) (Tcl_Interp *interp, Tcl_Channel chan); /* 11 */ int (*tclpCloseFile) (TclFile file); /* 12 */ Tcl_Channel (*tclpCreateCommandChannel) (TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid *pidPtr); /* 13 */ @@ -514,7 +515,7 @@ typedef struct TclIntPlatStubs { TclFile (*tclpOpenFile) (CONST char *fname, int mode); /* 7 */ int (*tclUnixWaitForFile) (int fd, int mask, int timeout); /* 8 */ TclFile (*tclpCreateTempFile) (CONST char *contents); /* 9 */ - Tcl_DirEntry * (*tclpReaddir) (DIR *dir); /* 10 */ + Tcl_DirEntry * (*tclpReaddir) (Tcl_Dir *dir); /* 10 */ struct tm * (*tclpLocaltime_unix) (CONST time_t *clock); /* 11 */ struct tm * (*tclpGmtime_unix) (CONST time_t *clock); /* 12 */ char * (*tclpInetNtoa) (struct in_addr addr); /* 13 */ diff --git a/unix/tclUnixFCmd.c b/unix/tclUnixFCmd.c index 4377b77..f4a35af 100644 --- a/unix/tclUnixFCmd.c +++ b/unix/tclUnixFCmd.c @@ -327,7 +327,7 @@ DoRenameFile( if (errno == EINVAL && haveRealpath) { char srcPath[MAXPATHLEN], dstPath[MAXPATHLEN]; - DIR *dirPtr; + Tcl_Dir *dirPtr; Tcl_DirEntry *dirEntPtr; if ((Realpath((char *) src, srcPath) != NULL) /* INTL: Native. */ @@ -920,7 +920,7 @@ TraverseUnixTree( #ifndef HAVE_FTS int numProcessed = 0; Tcl_DirEntry *dirEntPtr; - DIR *dirPtr; + Tcl_Dir *dirPtr; #else CONST char *paths[2] = {NULL, NULL}; FTS *fts = NULL; diff --git a/unix/tclUnixFile.c b/unix/tclUnixFile.c index 1dc73ae..95642b1 100644 --- a/unix/tclUnixFile.c +++ b/unix/tclUnixFile.c @@ -259,7 +259,7 @@ TclpMatchInDirectory( Tcl_DecrRefCount(tailPtr); Tcl_DecrRefCount(fileNamePtr); } else { - DIR *d; + Tcl_Dir *d; Tcl_DirEntry *entryPtr; CONST char *dirName; int dirLength; diff --git a/unix/tclUnixPort.h b/unix/tclUnixPort.h index cc31bf9..58509b0 100644 --- a/unix/tclUnixPort.h +++ b/unix/tclUnixPort.h @@ -58,12 +58,14 @@ */ #ifdef HAVE_STRUCT_DIRENT64 +typedef DIR64 Tcl_Dir; typedef struct dirent64 Tcl_DirEntry; # define TclOSreaddir readdir64 # define TclOSopendir opendir64 # define TclOSrewinddir rewinddir64 # define TclOSclosedir closedir64 #else +typedef DIR Tcl_Dir; typedef struct dirent Tcl_DirEntry; # define TclOSreaddir readdir # define TclOSopendir opendir diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c index 1841242..9401c77 100644 --- a/unix/tclUnixThrd.c +++ b/unix/tclUnixThrd.c @@ -742,7 +742,7 @@ TclpFinalizeCondition( Tcl_DirEntry * TclpReaddir( - DIR * dir) + Tcl_Dir * dir) { return TclOSreaddir(dir); } -- cgit v0.12 From 6dbdfc31d2570ae3f957e2c40d5209ae24533bbb Mon Sep 17 00:00:00 2001 From: fbonnet Date: Thu, 10 May 2018 13:44:43 +0000 Subject: Added man page for tcl::process --- doc/process.n | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 doc/process.n diff --git a/doc/process.n b/doc/process.n new file mode 100644 index 0000000..f9ded02 --- /dev/null +++ b/doc/process.n @@ -0,0 +1,128 @@ +'\" +'\" Copyright (c) 2017 Frederic Bonnet. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +.TH process n 8.7 Tcl "Tcl Built-In Commands" +.so man.macros +.BS +'\" Note: do not modify the .SH NAME line immediately below! +.SH NAME +tcl::process \- Subprocess management +.SH SYNOPSIS +\fB::tcl::process \fIoption \fR?\fIarg arg ...\fR? +.BE +.SH DESCRIPTION +.PP +This command provides a way to manage subprocesses created by the \fBopen\fR +and \fBexec\fR commands. The legal \fIoptions\fR (which may be abbreviated) are: +.TP +\fB::tcl::process list\fR +. +Returns the list of subprocess PIDs. +.TP +\fB::tcl::process status\fR ?\fIswitches\fR? ?\fIpids\fR? +. +Returns a dictionary mapping subprocess PIDs to their respective status. If +\fIpids\fR is specified as a list of PIDs then the command only returns the +status of the matching subprocesses if they exist, and raises an error +otherwise. For active processes, the status is an empty value. For terminated +processes, the status is a list with the following format: +.QW "{code ?\fImsg errorCode\fR?}" , +where: +.RS +.TP +\fBcode\fR\0 +. +is a standard Tcl return code, +.TP +\fBmsg\fR\0 +. +is the human-readable error message, +.TP +\fBerrorCode\fR\0 +. +uses the same format as the \fBerrorCode\fR global variable +.RE +Note that \fBmsg\fR and \fBerrorCode\fR are only present for abnormally +terminated processes (i.e. those where \fBcode\fR is nonzero). Under the hood +this command calls \fBTcl_WaitPid\fR with the \fBWNOHANG\fR flag set for +non-blocking behavior, unless the \fB\-wait\fR switch is set (see below). +.RS +.PP +Additionally, \fB::tcl::process status\fR accepts the following switches: +.TP +\fB\-wait\fR\0 +. +By default the command returns immediately (the underlying \fBTcl_WaitPid\fR is +called with the \fBWNOHANG\fR flag set) unless this switch is set. If \fBpids\fR +is specified as a list of PIDs then the command waits until the status of the +matching subprocesses are available. If \fBpids\fR is not specified then it +waits for all known subprocesses. +.TP +\fB\-\|\-\fR +. +Marks the end of switches. The argument following this one will +be treated as the first \fIarg\fR even if it starts with a \fB\-\fR. +.RE +.TP +\fB::tcl::process purge ?\fIpids\fR? +. +Returns the list of subprocess PIDs. +.TP +\fB::tcl::process autopurge ?\fIflag\fR? +. +Automatic purge facility. If \fBflag\fR is specified as a boolean value then it +activates or deactivate autopurge. In all cases it returns the current status as +a boolean value. When autopurge is active, \fBTcl_ReapDetachedProcs\fR is called +each time the exec command is executed or a pipe channel created by open is +closed. When autopurge is inactive, \fB::tcl::process\fR purge must be called +explicitly. By default autopurge is active. +.RE +.SH "EXAMPLES" +.PP +.CS +\fB::tcl::process autopurge\fR + \fI\(-> true\fR +\fB::tcl::process autopurge\fR false + \fI\(-> false\fR + +set pid1 [exec command1 a b c | command2 d e f &] + \fI\(-> 123 456\fR +set chan [open "|command1 a b c | command2 d e f"] + \fI\(-> file123\fR +set pid2 [pid $chan] + \fI\(-> 789 1011\fR + +\fB::tcl::process list\fR + \fI\(-> 123 456 789 1011\fR + +\fB::tcl::process status\fR + \fI\(-> 123 0 456 {1 "child killed: write on pipe with no readers" {CHILDKILLED 456 SIGPIPE "write on pipe with no readers"}} 789 {1 "child suspended: background tty read" {CHILDSUSP 789 SIGTTIN "background tty read"}} 1011 {}\fR + +\fB::tcl::process status\fR 123 + \fI\(-> 123 0\fR + +\fB::tcl::process status\fR 1011 + \fI\(-> 1011 {}\fR + +\fB::tcl::process status\fR -wait + \fI\(-> 123 0 456 {1 "child killed: write on pipe with no readers" {CHILDKILLED 456 SIGPIPE "write on pipe with no readers"}} 789 {1 "child suspended: background tty read" {CHILDSUSP 789 SIGTTIN "background tty read"}} 1011 {1 "child process exited abnormally" {CHILDSTATUS 1011 -1}}\fR + +\fB::tcl::process status\fR 1011 + \fI\(-> 1011 {1 "child process exited abnormally" {CHILDSTATUS 1011 -1}}\fR + +\fB::tcl::process purge\fR +exec command1 1 2 3 & + \fI\(-> 1213\fR +\fB::tcl::process list\fR + \fI\(-> 1213\fR +.CE +.SH "SEE ALSO" +exec(n), open(n), Tcl_DetachPids(3), Tcl_WaitPid(3), Tcl_ReapDetachedProcs(3) +.SH "KEYWORDS" +background, child, detach, process, wait +'\" Local Variables: +'\" mode: nroff +'\" End: -- cgit v0.12 From eed54b62810c15c58fe073bea486104bf0e4d5c9 Mon Sep 17 00:00:00 2001 From: fbonnet Date: Thu, 10 May 2018 13:47:37 +0000 Subject: Fixed makefile.vc: install will create missing dir "tcl8/8.7" for msgcat --- win/makefile.vc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/win/makefile.vc b/win/makefile.vc index 918c6b7..3e4608e 100644 --- a/win/makefile.vc +++ b/win/makefile.vc @@ -832,6 +832,8 @@ install-libraries: tclConfig tcl-nmake install-msgs install-tzdata $(MKDIR) "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.5" @if not exist "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.6" \ $(MKDIR) "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.6" + @if not exist "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.7" \ + $(MKDIR) "$(SCRIPT_INSTALL_DIR)\..\tcl8\8.7" @if not exist "$(LIB_INSTALL_DIR)\nmake" \ $(MKDIR) "$(LIB_INSTALL_DIR)\nmake" @echo Installing header files -- cgit v0.12 From d3fd405e6bc09ab8392cfbabce1a695bac5f3316 Mon Sep 17 00:00:00 2001 From: fbonnet Date: Thu, 10 May 2018 17:37:10 +0000 Subject: Added tcl::process test suite --- doc/process.n | 5 +- tests/process.test | 262 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 260 insertions(+), 7 deletions(-) diff --git a/doc/process.n b/doc/process.n index f9ded02..fbe307b 100644 --- a/doc/process.n +++ b/doc/process.n @@ -69,7 +69,10 @@ be treated as the first \fIarg\fR even if it starts with a \fB\-\fR. .TP \fB::tcl::process purge ?\fIpids\fR? . -Returns the list of subprocess PIDs. +Cleans up all data associated with terminated subprocesses. If \fBpids\fR is +specified as a list of PIDs then the command only cleanup data for the matching +subprocesses if they exist, and raises an error otherwise. If the process is +still active then it does nothing. .TP \fB::tcl::process autopurge ?\fIflag\fR? . diff --git a/tests/process.test b/tests/process.test index fb3a5e2..5454a31 100644 --- a/tests/process.test +++ b/tests/process.test @@ -13,19 +13,269 @@ if {[lsearch [namespace children] ::tcltest] == -1} { namespace import -force ::tcltest::* } +# Utilities +set path(sleep) [makeFile { + after [expr $argv*1000] + exit +} sleep] +set path(exit) [makeFile { + exit $argv +} exit] + +# Basic syntax checking test process-1.1 {tcl::process command basic syntax} -returnCodes error -body { tcl::process } -result {wrong # args: should be "tcl::process subcommand ?arg ...?"} -test process-1.2 {tcl::process command basic syntax} -returnCodes error -body { +test process-1.2 {tcl::process subcommands} -returnCodes error -body { tcl::process ? } -match glob -result {unknown or ambiguous subcommand "?": must be autopurge, list, purge, or status} -test process-2.1 {tcl::process autopurge get} {tcl::process autopurge} {1} -test process-2.2 {tcl::process autopurge set true} { +# Autopurge flag +# - Default state +test process-2.1 {autopurge default} -body { + tcl::process autopurge +} -result {1} +# - Enabling autopurge +test process-2.2 {enable autopurge} -body { tcl::process autopurge true tcl::process autopurge -} {1} -test process-2.3 {tcl::process autopurge set false} { +} -result {1} +# - Disabling autopurge +test process-2.3 {disable autopurge} -body { tcl::process autopurge false tcl::process autopurge -} {0} +} -result {0} -cleanup {tcl::process autopurge true} + +# Subprocess list & status +test process-3.1 {empty subprocess list} -body { + llength [tcl::process list] +} -result {0} +test process-3.2 {empty subprocess status} -body { + dict size [tcl::process status] +} -result {0} + +# Spawn subprocesses using [exec] +# - One child +test process-4.1 {exec one child} -body { + tcl::process autopurge 0 + set pid [exec [interpreter] $path(exit) 0 &] + set list [tcl::process list] + set statuses [tcl::process status -wait] + set status [lindex [tcl::process status $pid] 1] + expr { + [llength $list] eq 1 + && [lindex $list 0] eq $pid + && [dict size $statuses] eq 1 + && [dict get $statuses $pid] eq $status + && $status eq 0 + } +} -result {1} -cleanup { + tcl::process purge + tcl::process autopurge 1 +} +# - Two children +test process-4.2 {exec two children in parallel} -body { + tcl::process autopurge 0 + set pid1 [exec [interpreter] $path(exit) 0 &] + set pid2 [exec [interpreter] $path(exit) 0 &] + set list [tcl::process list] + set statuses [tcl::process status -wait] + set status1 [lindex [tcl::process status $pid1] 1] + set status2 [lindex [tcl::process status $pid2] 1] + expr { + [llength $list] eq 2 + && [lsearch $list $pid1] >= 0 + && [lsearch $list $pid2] >= 0 + && [dict size $statuses] eq 2 + && [dict get $statuses $pid1] eq $status1 + && [dict get $statuses $pid2] eq $status2 + && $status1 eq 0 + && $status2 eq 0 + } +} -result {1} -cleanup { + tcl::process purge + tcl::process autopurge 1 +} +# - 3-stage pipe +test process-4.3 {exec 3-stage pipe} -body { + tcl::process autopurge 0 + set pids [exec \ + [interpreter] $path(exit) 0 \ + | [interpreter] $path(exit) 0 \ + | [interpreter] $path(exit) 0 \ + &] + lassign $pids pid1 pid2 pid3 + set list [tcl::process list] + set statuses [tcl::process status -wait] + set status1 [lindex [tcl::process status $pid1] 1] + set status2 [lindex [tcl::process status $pid2] 1] + set status3 [lindex [tcl::process status $pid3] 1] + expr { + [llength $pids] eq 3 + && [llength $list] eq 3 + && [lsearch $list $pid1] >= 0 + && [lsearch $list $pid2] >= 0 + && [lsearch $list $pid3] >= 0 + && [dict size $statuses] eq 3 + && [dict get $statuses $pid1] eq $status1 + && [dict get $statuses $pid2] eq $status2 + && [dict get $statuses $pid3] eq $status3 + && $status1 eq 0 + && $status2 eq 0 + && $status3 eq 0 + } +} -result {1} -cleanup { + tcl::process purge + tcl::process autopurge 1 +} + +# Spawn subprocesses using [open "|"] +# - One child +test process-5.1 {exec one child} -body { + tcl::process autopurge 0 + set f [open "|\"[interpreter]\" \"$path(exit)\" 0"] + set pid [pid $f] + set list [tcl::process list] + set statuses [tcl::process status -wait] + set status [lindex [tcl::process status $pid] 1] + expr { + [llength $list] eq 1 + && [lindex $list 0] eq $pid + && [dict size $statuses] eq 1 + && [dict get $statuses $pid] eq $status + && $status eq 0 + } +} -result {1} -cleanup { + close $f + tcl::process purge + tcl::process autopurge 1 +} +# - Two children +test process-5.2 {exec two children in parallel} -body { + tcl::process autopurge 0 + set f1 [open "|\"[interpreter]\" \"$path(exit)\" 0"] + set f2 [open "|\"[interpreter]\" \"$path(exit)\" 0"] + set pid1 [pid $f1] + set pid2 [pid $f2] + set list [tcl::process list] + set statuses [tcl::process status -wait] + set status1 [lindex [tcl::process status $pid1] 1] + set status2 [lindex [tcl::process status $pid2] 1] + expr { + [llength $list] eq 2 + && [lsearch $list $pid1] >= 0 + && [lsearch $list $pid2] >= 0 + && [dict size $statuses] eq 2 + && [dict get $statuses $pid1] eq $status1 + && [dict get $statuses $pid2] eq $status2 + && $status1 eq 0 + && $status2 eq 0 + } +} -result {1} -cleanup { + close $f1 + close $f2 + tcl::process purge + tcl::process autopurge 1 +} +# - 3-stage pipe +test process-5.3 {exec 3-stage pipe} -body { + tcl::process autopurge 0 + set f [open "| + \"[interpreter]\" \"$path(exit)\" 0 + | \"[interpreter]\" \"$path(exit)\" 0 + | \"[interpreter]\" \"$path(exit)\" 0 + "] + set pids [pid $f] + lassign $pids pid1 pid2 pid3 + set list [tcl::process list] + set statuses [tcl::process status -wait] + set status1 [lindex [tcl::process status $pid1] 1] + set status2 [lindex [tcl::process status $pid2] 1] + set status3 [lindex [tcl::process status $pid3] 1] + expr { + [llength $pids] eq 3 + && [llength $list] eq 3 + && [lsearch $list $pid1] >= 0 + && [lsearch $list $pid2] >= 0 + && [lsearch $list $pid3] >= 0 + && [dict size $statuses] eq 3 + && [dict get $statuses $pid1] eq $status1 + && [dict get $statuses $pid2] eq $status2 + && [dict get $statuses $pid3] eq $status3 + && $status1 eq 0 + && $status2 eq 0 + && $status3 eq 0 + } +} -result {1} -cleanup { + close $f + tcl::process purge + tcl::process autopurge 1 +} + +# Async child status +test process-6.1 {async status} -body { + tcl::process autopurge 0 + set pid [exec [interpreter] $path(sleep) 1 &] + set status1 [lindex [tcl::process status $pid] 1] + set status2 [lindex [tcl::process status -wait $pid] 1] + expr { + $status1 eq {} + && $status2 eq 0 + } +} -result {1} -cleanup { + tcl::process purge + tcl::process autopurge 1 +} +test process-6.2 {selective wait} -body { + tcl::process autopurge 0 + # Child 1 sleeps 1s + set pid1 [exec [interpreter] $path(sleep) 1 &] + # Child 2 sleeps 1s + set pid2 [exec [interpreter] $path(sleep) 2 &] + # Initial status + set status1_1 [lindex [tcl::process status $pid1] 1] + set status1_2 [lindex [tcl::process status $pid2] 1] + # Wait until child 1 termination + set status2_1 [lindex [tcl::process status -wait $pid1] 1] + set status2_2 [lindex [tcl::process status $pid2] 1] + # Wait until child 2 termination + set status3_2 [lindex [tcl::process status -wait $pid2] 1] + set status3_1 [lindex [tcl::process status $pid1] 1] + expr { + $status1_1 eq {} + && $status1_2 eq {} + && $status2_1 eq 0 + && $status2_2 eq {} + && $status3_1 eq 0 + && $status3_2 eq 0 + } +} -result {1} -cleanup { + tcl::process purge + tcl::process autopurge 1 +} + +# Error codes +test process-7.1 {normal exit} -body { + tcl::process autopurge 0 + set pid [exec [interpreter] $path(exit) 0 &] + lindex [tcl::process status -wait $pid] 1 +} -result {0} -cleanup { + tcl::process purge + tcl::process autopurge 1 +} +test process-7.2 {abnormal exit} -body { + tcl::process autopurge 0 + set pid [exec [interpreter] $path(exit) 1 &] + lindex [tcl::process status -wait $pid] 1 +} -match glob -result {1 {child process exited abnormally} {CHILDSTATUS * 1}} -cleanup { + tcl::process purge + tcl::process autopurge 1 +} +test process-7.3 {child killed} -body { + tcl::process autopurge 0 + set pid [exec [interpreter] $path(exit) -1 &] + lindex [tcl::process status -wait $pid] 1 +} -match glob -result {1 {child killed: unknown signal} {CHILDKILLED * {unknown signal} {unknown signal}}} -cleanup { + tcl::process purge + tcl::process autopurge 1 +} -- cgit v0.12 From 7bf3f83abd5bc0e24dbd3f02765b7e86d7ba1fa7 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 11 May 2018 07:53:20 +0000 Subject: Rename Tcl_Dir to TclDIR, making it clear that this macro is not part of the public API --- generic/tclInt.decls | 4 ++-- generic/tclIntPlatDecls.h | 15 +++++++-------- unix/tclUnixFCmd.c | 2 +- unix/tclUnixFile.c | 2 +- unix/tclUnixPort.h | 4 ++-- unix/tclUnixThrd.c | 2 +- 6 files changed, 14 insertions(+), 15 deletions(-) diff --git a/generic/tclInt.decls b/generic/tclInt.decls index 69e695e..8acd433 100644 --- a/generic/tclInt.decls +++ b/generic/tclInt.decls @@ -995,7 +995,7 @@ declare 9 win { } # new for 8.4.20+/8.5.12+ Cygwin only declare 10 win { - Tcl_DirEntry *TclpReaddir(Tcl_Dir *dir) + Tcl_DirEntry *TclpReaddir(TclDIR *dir) } # Removed in 8.3.1 (for Win32s only) #declare 10 win { @@ -1135,7 +1135,7 @@ declare 9 unix { # Added in 8.4: declare 10 unix { - Tcl_DirEntry *TclpReaddir(Tcl_Dir *dir) + Tcl_DirEntry *TclpReaddir(TclDIR *dir) } # Slots 11 and 12 are forwarders for functions that were promoted to # generic Stubs diff --git a/generic/tclIntPlatDecls.h b/generic/tclIntPlatDecls.h index d792a54..5a3025a 100644 --- a/generic/tclIntPlatDecls.h +++ b/generic/tclIntPlatDecls.h @@ -15,8 +15,7 @@ #ifdef __WIN32__ # define Tcl_DirEntry void -# define DIR void -# define Tcl_Dir void +# define TclDIR void #endif #undef TCL_STORAGE_CLASS @@ -102,7 +101,7 @@ EXTERN TclFile TclpCreateTempFile(CONST char *contents); #ifndef TclpReaddir_TCL_DECLARED #define TclpReaddir_TCL_DECLARED /* 10 */ -EXTERN Tcl_DirEntry * TclpReaddir(Tcl_Dir *dir); +EXTERN Tcl_DirEntry * TclpReaddir(TclDIR *dir); #endif #ifndef TclpLocaltime_unix_TCL_DECLARED #define TclpLocaltime_unix_TCL_DECLARED @@ -203,7 +202,7 @@ EXTERN int TclWinGetPlatformId(void); #ifndef TclpReaddir_TCL_DECLARED #define TclpReaddir_TCL_DECLARED /* 10 */ -EXTERN Tcl_DirEntry * TclpReaddir(Tcl_Dir *dir); +EXTERN Tcl_DirEntry * TclpReaddir(TclDIR *dir); #endif #ifndef TclGetAndDetachPids_TCL_DECLARED #define TclGetAndDetachPids_TCL_DECLARED @@ -361,7 +360,7 @@ EXTERN TclFile TclpCreateTempFile(CONST char *contents); #ifndef TclpReaddir_TCL_DECLARED #define TclpReaddir_TCL_DECLARED /* 10 */ -EXTERN Tcl_DirEntry * TclpReaddir(Tcl_Dir *dir); +EXTERN Tcl_DirEntry * TclpReaddir(TclDIR *dir); #endif #ifndef TclpLocaltime_unix_TCL_DECLARED #define TclpLocaltime_unix_TCL_DECLARED @@ -451,7 +450,7 @@ typedef struct TclIntPlatStubs { TclFile (*tclpOpenFile) (CONST char *fname, int mode); /* 7 */ int (*tclUnixWaitForFile) (int fd, int mask, int timeout); /* 8 */ TclFile (*tclpCreateTempFile) (CONST char *contents); /* 9 */ - Tcl_DirEntry * (*tclpReaddir) (Tcl_Dir *dir); /* 10 */ + Tcl_DirEntry * (*tclpReaddir) (TclDIR *dir); /* 10 */ struct tm * (*tclpLocaltime_unix) (CONST time_t *clock); /* 11 */ struct tm * (*tclpGmtime_unix) (CONST time_t *clock); /* 12 */ char * (*tclpInetNtoa) (struct in_addr addr); /* 13 */ @@ -483,7 +482,7 @@ typedef struct TclIntPlatStubs { int (*tclWinSetSockOpt) (SOCKET s, int level, int optname, CONST char *optval, int optlen); /* 7 */ int (*tclpGetPid) (Tcl_Pid pid); /* 8 */ int (*tclWinGetPlatformId) (void); /* 9 */ - Tcl_DirEntry * (*tclpReaddir) (Tcl_Dir *dir); /* 10 */ + Tcl_DirEntry * (*tclpReaddir) (TclDIR *dir); /* 10 */ void (*tclGetAndDetachPids) (Tcl_Interp *interp, Tcl_Channel chan); /* 11 */ int (*tclpCloseFile) (TclFile file); /* 12 */ Tcl_Channel (*tclpCreateCommandChannel) (TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid *pidPtr); /* 13 */ @@ -515,7 +514,7 @@ typedef struct TclIntPlatStubs { TclFile (*tclpOpenFile) (CONST char *fname, int mode); /* 7 */ int (*tclUnixWaitForFile) (int fd, int mask, int timeout); /* 8 */ TclFile (*tclpCreateTempFile) (CONST char *contents); /* 9 */ - Tcl_DirEntry * (*tclpReaddir) (Tcl_Dir *dir); /* 10 */ + Tcl_DirEntry * (*tclpReaddir) (TclDIR *dir); /* 10 */ struct tm * (*tclpLocaltime_unix) (CONST time_t *clock); /* 11 */ struct tm * (*tclpGmtime_unix) (CONST time_t *clock); /* 12 */ char * (*tclpInetNtoa) (struct in_addr addr); /* 13 */ diff --git a/unix/tclUnixFCmd.c b/unix/tclUnixFCmd.c index f4a35af..0b79fb6 100644 --- a/unix/tclUnixFCmd.c +++ b/unix/tclUnixFCmd.c @@ -327,7 +327,7 @@ DoRenameFile( if (errno == EINVAL && haveRealpath) { char srcPath[MAXPATHLEN], dstPath[MAXPATHLEN]; - Tcl_Dir *dirPtr; + TclDIR *dirPtr; Tcl_DirEntry *dirEntPtr; if ((Realpath((char *) src, srcPath) != NULL) /* INTL: Native. */ diff --git a/unix/tclUnixFile.c b/unix/tclUnixFile.c index 95642b1..65e144d 100644 --- a/unix/tclUnixFile.c +++ b/unix/tclUnixFile.c @@ -259,7 +259,7 @@ TclpMatchInDirectory( Tcl_DecrRefCount(tailPtr); Tcl_DecrRefCount(fileNamePtr); } else { - Tcl_Dir *d; + TclDIR *d; Tcl_DirEntry *entryPtr; CONST char *dirName; int dirLength; diff --git a/unix/tclUnixPort.h b/unix/tclUnixPort.h index 58509b0..a248213 100644 --- a/unix/tclUnixPort.h +++ b/unix/tclUnixPort.h @@ -58,14 +58,14 @@ */ #ifdef HAVE_STRUCT_DIRENT64 -typedef DIR64 Tcl_Dir; +typedef DIR64 TclDIR; typedef struct dirent64 Tcl_DirEntry; # define TclOSreaddir readdir64 # define TclOSopendir opendir64 # define TclOSrewinddir rewinddir64 # define TclOSclosedir closedir64 #else -typedef DIR Tcl_Dir; +typedef DIR TclDIR; typedef struct dirent Tcl_DirEntry; # define TclOSreaddir readdir # define TclOSopendir opendir diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c index 9401c77..15d9d52 100644 --- a/unix/tclUnixThrd.c +++ b/unix/tclUnixThrd.c @@ -742,7 +742,7 @@ TclpFinalizeCondition( Tcl_DirEntry * TclpReaddir( - Tcl_Dir * dir) + TclDIR * dir) { return TclOSreaddir(dir); } -- cgit v0.12 From d9bc6cbae2f78eb2883de1d9ef9a3131da80614f Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Fri, 11 May 2018 09:14:42 +0000 Subject: Add emoji 11.0 to the set. Only active when compiled with TCL_UTF_MAX>3. Also prepare tooling for Unicode 11.0 (while being on it) --- generic/regc_locale.c | 47 +++++++++++------------- generic/tclUniData.c | 40 ++++++++++----------- generic/tclUtf.c | 98 +++++++++++++++++++++++++++++++++++++++++++-------- tools/uniClass.tcl | 6 ++-- tools/uniParse.tcl | 17 ++++++--- 5 files changed, 138 insertions(+), 70 deletions(-) diff --git a/generic/regc_locale.c b/generic/regc_locale.c index 32adee8..4435557 100644 --- a/generic/regc_locale.c +++ b/generic/regc_locale.c @@ -193,17 +193,13 @@ static const crange alphaRangeTable[] = { {0xaab9, 0xaabd}, {0xaadb, 0xaadd}, {0xaae0, 0xaaea}, {0xaaf2, 0xaaf4}, {0xab01, 0xab06}, {0xab09, 0xab0e}, {0xab11, 0xab16}, {0xab20, 0xab26}, {0xab28, 0xab2e}, {0xab30, 0xab5a}, {0xab5c, 0xab65}, {0xab70, 0xabe2}, - {0xac00, 0xd7a3}, {0xd7b0, 0xd7c6}, {0xd7cb, 0xd7fb}, {0xdc00, 0xdc3e}, - {0xdc40, 0xdc7e}, {0xdc80, 0xdcbe}, {0xdcc0, 0xdcfe}, {0xdd00, 0xdd3e}, - {0xdd40, 0xdd7e}, {0xdd80, 0xddbe}, {0xddc0, 0xddfe}, {0xde00, 0xde3e}, - {0xde40, 0xde7e}, {0xde80, 0xdebe}, {0xdec0, 0xdefe}, {0xdf00, 0xdf3e}, - {0xdf40, 0xdf7e}, {0xdf80, 0xdfbe}, {0xdfc0, 0xdffe}, {0xf900, 0xfa6d}, + {0xac00, 0xd7a3}, {0xd7b0, 0xd7c6}, {0xd7cb, 0xd7fb}, {0xf900, 0xfa6d}, {0xfa70, 0xfad9}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17}, {0xfb1f, 0xfb28}, {0xfb2a, 0xfb36}, {0xfb38, 0xfb3c}, {0xfb46, 0xfbb1}, {0xfbd3, 0xfd3d}, {0xfd50, 0xfd8f}, {0xfd92, 0xfdc7}, {0xfdf0, 0xfdfb}, {0xfe70, 0xfe74}, {0xfe76, 0xfefc}, {0xff21, 0xff3a}, {0xff41, 0xff5a}, {0xff66, 0xffbe}, {0xffc2, 0xffc7}, {0xffca, 0xffcf}, {0xffd2, 0xffd7}, {0xffda, 0xffdc} -#if TCL_UTF_MAX > 4 +#if CHRBITS > 16 ,{0x10000, 0x1000b}, {0x1000d, 0x10026}, {0x10028, 0x1003a}, {0x1003f, 0x1004d}, {0x10050, 0x1005d}, {0x10080, 0x100fa}, {0x10280, 0x1029c}, {0x102a0, 0x102d0}, {0x10300, 0x1031f}, {0x1032d, 0x10340}, {0x10342, 0x10349}, {0x10350, 0x10375}, @@ -266,7 +262,7 @@ static const chr alphaCharTable[] = { 0x2cf2, 0x2cf3, 0x2d27, 0x2d2d, 0x2d6f, 0x2e2f, 0x3005, 0x3006, 0x303b, 0x303c, 0xa62a, 0xa62b, 0xa8fb, 0xa8fd, 0xa9cf, 0xaa7a, 0xaab1, 0xaab5, 0xaab6, 0xaac0, 0xaac2, 0xfb1d, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44 -#if TCL_UTF_MAX > 4 +#if CHRBITS > 16 ,0x1003c, 0x1003d, 0x10808, 0x10837, 0x10838, 0x1083c, 0x108f4, 0x108f5, 0x109be, 0x109bf, 0x10a00, 0x11176, 0x111da, 0x111dc, 0x11288, 0x1130f, 0x11310, 0x11332, 0x11333, 0x1133d, 0x11350, 0x114c4, 0x114c5, 0x114c7, 0x11644, 0x118ff, 0x11a00, @@ -288,7 +284,7 @@ static const crange controlRangeTable[] = { {0x0, 0x1f}, {0x7f, 0x9f}, {0x600, 0x605}, {0x200b, 0x200f}, {0x202a, 0x202e}, {0x2060, 0x2064}, {0x2066, 0x206f}, {0xe000, 0xf8ff}, {0xfff9, 0xfffb} -#if TCL_UTF_MAX > 4 +#if CHRBITS > 16 ,{0x1bca0, 0x1bca3}, {0x1d173, 0x1d17a}, {0xe0020, 0xe007f}, {0xf0000, 0xffffd}, {0x100000, 0x10fffd} #endif @@ -298,7 +294,7 @@ static const crange controlRangeTable[] = { static const chr controlCharTable[] = { 0xad, 0x61c, 0x6dd, 0x70f, 0x8e2, 0x180e, 0xfeff -#if TCL_UTF_MAX > 4 +#if CHRBITS > 16 ,0x110bd, 0xe0001 #endif }; @@ -320,7 +316,7 @@ static const crange digitRangeTable[] = { {0x1c50, 0x1c59}, {0xa620, 0xa629}, {0xa8d0, 0xa8d9}, {0xa900, 0xa909}, {0xa9d0, 0xa9d9}, {0xa9f0, 0xa9f9}, {0xaa50, 0xaa59}, {0xabf0, 0xabf9}, {0xff10, 0xff19} -#if TCL_UTF_MAX > 4 +#if CHRBITS > 16 ,{0x104a0, 0x104a9}, {0x11066, 0x1106f}, {0x110f0, 0x110f9}, {0x11136, 0x1113f}, {0x111d0, 0x111d9}, {0x112f0, 0x112f9}, {0x11450, 0x11459}, {0x114d0, 0x114d9}, {0x11650, 0x11659}, {0x116c0, 0x116c9}, {0x11730, 0x11739}, {0x118e0, 0x118e9}, @@ -354,7 +350,7 @@ static const crange punctRangeTable[] = { {0xaa5c, 0xaa5f}, {0xfe10, 0xfe19}, {0xfe30, 0xfe52}, {0xfe54, 0xfe61}, {0xff01, 0xff03}, {0xff05, 0xff0a}, {0xff0c, 0xff0f}, {0xff3b, 0xff3d}, {0xff5f, 0xff65} -#if TCL_UTF_MAX > 4 +#if CHRBITS > 16 ,{0x10100, 0x10102}, {0x10a50, 0x10a58}, {0x10af0, 0x10af6}, {0x10b39, 0x10b3f}, {0x10b99, 0x10b9c}, {0x11047, 0x1104d}, {0x110be, 0x110c1}, {0x11140, 0x11143}, {0x111c5, 0x111c9}, {0x111dd, 0x111df}, {0x11238, 0x1123d}, {0x1144b, 0x1144f}, @@ -379,7 +375,7 @@ static const chr punctCharTable[] = { 0xa67e, 0xa8ce, 0xa8cf, 0xa8fc, 0xa92e, 0xa92f, 0xa95f, 0xa9de, 0xa9df, 0xaade, 0xaadf, 0xaaf0, 0xaaf1, 0xabeb, 0xfd3e, 0xfd3f, 0xfe63, 0xfe68, 0xfe6a, 0xfe6b, 0xff1a, 0xff1b, 0xff1f, 0xff20, 0xff3f, 0xff5b, 0xff5d -#if TCL_UTF_MAX > 4 +#if CHRBITS > 16 ,0x1039f, 0x103d0, 0x1056f, 0x10857, 0x1091f, 0x1093f, 0x10a7f, 0x110bb, 0x110bc, 0x11174, 0x11175, 0x111cd, 0x111db, 0x112a9, 0x1145b, 0x1145d, 0x114c6, 0x11c70, 0x11c71, 0x16a6e, 0x16a6f, 0x16af5, 0x16b44, 0x1bc9f, 0x1e95e, 0x1e95f @@ -423,7 +419,7 @@ static const crange lowerRangeTable[] = { {0x2d00, 0x2d25}, {0xa72f, 0xa731}, {0xa771, 0xa778}, {0xa793, 0xa795}, {0xab30, 0xab5a}, {0xab60, 0xab65}, {0xab70, 0xabbf}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17}, {0xff41, 0xff5a} -#if TCL_UTF_MAX > 4 +#if CHRBITS > 16 ,{0x10428, 0x1044f}, {0x104d8, 0x104fb}, {0x10cc0, 0x10cf2}, {0x118c0, 0x118df}, {0x1d41a, 0x1d433}, {0x1d44e, 0x1d454}, {0x1d456, 0x1d467}, {0x1d482, 0x1d49b}, {0x1d4b6, 0x1d4b9}, {0x1d4bd, 0x1d4c3}, {0x1d4c5, 0x1d4cf}, {0x1d4ea, 0x1d503}, @@ -502,7 +498,7 @@ static const chr lowerCharTable[] = { 0xa77f, 0xa781, 0xa783, 0xa785, 0xa787, 0xa78c, 0xa78e, 0xa791, 0xa797, 0xa799, 0xa79b, 0xa79d, 0xa79f, 0xa7a1, 0xa7a3, 0xa7a5, 0xa7a7, 0xa7a9, 0xa7b5, 0xa7b7, 0xa7fa -#if TCL_UTF_MAX > 4 +#if CHRBITS > 16 ,0x1d4bb, 0x1d7cb #endif }; @@ -524,7 +520,7 @@ static const crange upperRangeTable[] = { {0x210b, 0x210d}, {0x2110, 0x2112}, {0x2119, 0x211d}, {0x212a, 0x212d}, {0x2130, 0x2133}, {0x2c00, 0x2c2e}, {0x2c62, 0x2c64}, {0x2c6d, 0x2c70}, {0x2c7e, 0x2c80}, {0xa7aa, 0xa7ae}, {0xa7b0, 0xa7b4}, {0xff21, 0xff3a} -#if TCL_UTF_MAX > 4 +#if CHRBITS > 16 ,{0x10400, 0x10427}, {0x104b0, 0x104d3}, {0x10c80, 0x10cb2}, {0x118a0, 0x118bf}, {0x1d400, 0x1d419}, {0x1d434, 0x1d44d}, {0x1d468, 0x1d481}, {0x1d4a9, 0x1d4ac}, {0x1d4ae, 0x1d4b5}, {0x1d4d0, 0x1d4e9}, {0x1d507, 0x1d50a}, {0x1d50d, 0x1d514}, @@ -601,7 +597,7 @@ static const chr upperCharTable[] = { 0xa768, 0xa76a, 0xa76c, 0xa76e, 0xa779, 0xa77b, 0xa77d, 0xa77e, 0xa780, 0xa782, 0xa784, 0xa786, 0xa78b, 0xa78d, 0xa790, 0xa792, 0xa796, 0xa798, 0xa79a, 0xa79c, 0xa79e, 0xa7a0, 0xa7a2, 0xa7a4, 0xa7a6, 0xa7a8, 0xa7b6 -#if TCL_UTF_MAX > 4 +#if CHRBITS > 16 ,0x1d49c, 0x1d49e, 0x1d49f, 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d504, 0x1d505, 0x1d538, 0x1d539, 0x1d546, 0x1d7ca #endif @@ -684,17 +680,13 @@ static const crange graphRangeTable[] = { {0xaadb, 0xaaf6}, {0xab01, 0xab06}, {0xab09, 0xab0e}, {0xab11, 0xab16}, {0xab20, 0xab26}, {0xab28, 0xab2e}, {0xab30, 0xab65}, {0xab70, 0xabed}, {0xabf0, 0xabf9}, {0xac00, 0xd7a3}, {0xd7b0, 0xd7c6}, {0xd7cb, 0xd7fb}, - {0xdc00, 0xdc3e}, {0xdc40, 0xdc7e}, {0xdc80, 0xdcbe}, {0xdcc0, 0xdcfe}, - {0xdd00, 0xdd3e}, {0xdd40, 0xdd7e}, {0xdd80, 0xddbe}, {0xddc0, 0xddfe}, - {0xde00, 0xde3e}, {0xde40, 0xde7e}, {0xde80, 0xdebe}, {0xdec0, 0xdefe}, - {0xdf00, 0xdf3e}, {0xdf40, 0xdf7e}, {0xdf80, 0xdfbe}, {0xdfc0, 0xdffe}, {0xf900, 0xfa6d}, {0xfa70, 0xfad9}, {0xfb00, 0xfb06}, {0xfb13, 0xfb17}, {0xfb1d, 0xfb36}, {0xfb38, 0xfb3c}, {0xfb46, 0xfbc1}, {0xfbd3, 0xfd3f}, {0xfd50, 0xfd8f}, {0xfd92, 0xfdc7}, {0xfdf0, 0xfdfd}, {0xfe00, 0xfe19}, {0xfe20, 0xfe52}, {0xfe54, 0xfe66}, {0xfe68, 0xfe6b}, {0xfe70, 0xfe74}, {0xfe76, 0xfefc}, {0xff01, 0xffbe}, {0xffc2, 0xffc7}, {0xffca, 0xffcf}, {0xffd2, 0xffd7}, {0xffda, 0xffdc}, {0xffe0, 0xffe6}, {0xffe8, 0xffee} -#if TCL_UTF_MAX > 4 +#if CHRBITS > 16 ,{0x10000, 0x1000b}, {0x1000d, 0x10026}, {0x10028, 0x1003a}, {0x1003f, 0x1004d}, {0x10050, 0x1005d}, {0x10080, 0x100fa}, {0x10100, 0x10102}, {0x10107, 0x10133}, {0x10137, 0x1018e}, {0x10190, 0x1019b}, {0x101d0, 0x101fd}, {0x10280, 0x1029c}, @@ -747,12 +739,13 @@ static const crange graphRangeTable[] = { {0x1f030, 0x1f093}, {0x1f0a0, 0x1f0ae}, {0x1f0b1, 0x1f0bf}, {0x1f0c1, 0x1f0cf}, {0x1f0d1, 0x1f0f5}, {0x1f100, 0x1f10c}, {0x1f110, 0x1f12e}, {0x1f130, 0x1f16b}, {0x1f170, 0x1f1ac}, {0x1f1e6, 0x1f202}, {0x1f210, 0x1f23b}, {0x1f240, 0x1f248}, - {0x1f260, 0x1f265}, {0x1f300, 0x1f6d4}, {0x1f6e0, 0x1f6ec}, {0x1f6f0, 0x1f6f8}, + {0x1f260, 0x1f265}, {0x1f300, 0x1f6d4}, {0x1f6e0, 0x1f6ec}, {0x1f6f0, 0x1f6f9}, {0x1f700, 0x1f773}, {0x1f780, 0x1f7d4}, {0x1f800, 0x1f80b}, {0x1f810, 0x1f847}, {0x1f850, 0x1f859}, {0x1f860, 0x1f887}, {0x1f890, 0x1f8ad}, {0x1f900, 0x1f90b}, - {0x1f910, 0x1f93e}, {0x1f940, 0x1f94c}, {0x1f950, 0x1f96b}, {0x1f980, 0x1f997}, - {0x1f9d0, 0x1f9e6}, {0x20000, 0x2a6d6}, {0x2a700, 0x2b734}, {0x2b740, 0x2b81d}, - {0x2b820, 0x2cea1}, {0x2ceb0, 0x2ebe0}, {0x2f800, 0x2fa1d}, {0xe0100, 0xe01ef} + {0x1f910, 0x1f93e}, {0x1f940, 0x1f970}, {0x1f973, 0x1f976}, {0x1f97c, 0x1f9a2}, + {0x1f9b0, 0x1f9b9}, {0x1f9c0, 0x1f9c2}, {0x1f9d0, 0x1f9ff}, {0x1fa60, 0x1fa6d}, + {0x20000, 0x2a6d6}, {0x2a700, 0x2b734}, {0x2b740, 0x2b81d}, {0x2b820, 0x2cea1}, + {0x2ceb0, 0x2ebe0}, {0x2f800, 0x2fa1d}, {0xe0100, 0xe01ef} #endif }; @@ -770,7 +763,7 @@ static const chr graphCharTable[] = { 0xec6, 0x10c7, 0x10cd, 0x1258, 0x12c0, 0x1772, 0x1773, 0x1940, 0x1f59, 0x1f5b, 0x1f5d, 0x2070, 0x2071, 0x2d27, 0x2d2d, 0x2d6f, 0x2d70, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, 0xfffc, 0xfffd -#if TCL_UTF_MAX > 4 +#if CHRBITS > 16 ,0x1003c, 0x1003d, 0x101a0, 0x1056f, 0x10808, 0x10837, 0x10838, 0x1083c, 0x108f4, 0x108f5, 0x1093f, 0x10a05, 0x10a06, 0x11288, 0x1130f, 0x11310, 0x11332, 0x11333, 0x11347, 0x11348, 0x11350, 0x11357, 0x1145b, 0x1145d, 0x118ff, 0x11d08, 0x11d09, @@ -778,7 +771,7 @@ static const chr graphCharTable[] = { 0x1d4a2, 0x1d4a5, 0x1d4a6, 0x1d4bb, 0x1d546, 0x1e023, 0x1e024, 0x1e95e, 0x1e95f, 0x1ee21, 0x1ee22, 0x1ee24, 0x1ee27, 0x1ee39, 0x1ee3b, 0x1ee42, 0x1ee47, 0x1ee49, 0x1ee4b, 0x1ee51, 0x1ee52, 0x1ee54, 0x1ee57, 0x1ee59, 0x1ee5b, 0x1ee5d, 0x1ee5f, - 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee7e, 0x1eef0, 0x1eef1, 0x1f250, 0x1f251, 0x1f9c0 + 0x1ee61, 0x1ee62, 0x1ee64, 0x1ee7e, 0x1eef0, 0x1eef1, 0x1f250, 0x1f251, 0x1f97a #endif }; diff --git a/generic/tclUniData.c b/generic/tclUniData.c index 9f05230..834fcc4 100644 --- a/generic/tclUniData.c +++ b/generic/tclUniData.c @@ -367,11 +367,11 @@ static const unsigned short pageMap[] = { 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 16864, 16896, 4928, 4928, 4928, 8032, 4928, 4928, 16864, 1824, 16480, 4928, 16928, 4928, 16960, 16992, - 1824, 1824, 16480, 8416, 17024, 17056, 17088, 1824, 17120, 6784, 1824, + 1824, 1824, 16480, 8416, 4928, 17024, 4928, 17056, 16704, 4928, 1824, + 1824, 1824, 16992, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, - 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, @@ -483,7 +483,7 @@ static const unsigned short pageMap[] = { 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 7840, 1824, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, + 1344, 1344, 7840, 1824, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, @@ -494,7 +494,7 @@ static const unsigned short pageMap[] = { 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 17152, 1344, 1344, 1344, 1344, 1344, 1344, 11360, 1344, 1344, 1344, + 1344, 17088, 1344, 1344, 1344, 1344, 1344, 1344, 11360, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, @@ -509,7 +509,7 @@ static const unsigned short pageMap[] = { 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 17184, 1344, + 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 17120, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, @@ -529,7 +529,7 @@ static const unsigned short pageMap[] = { 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 17216, 1824, 1824, 1824, 1824, 1824, 1824, + 1344, 1344, 1344, 1344, 1344, 17152, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, @@ -537,8 +537,9 @@ static const unsigned short pageMap[] = { 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, - 1824, 1824, 1824, 1824, 1824, 1824, 1344, 1344, 1344, 1344, 1344, 1344, - 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 11360 + 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1344, 1344, 1344, 1344, 1344, + 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 11360 + #endif /* TCL_UTF_MAX > 3 */ }; @@ -1502,24 +1503,20 @@ static const unsigned char groupMap[] = { 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, + 14, 14, 14, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0 + 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 14, 14, 14, 14, 0, 0, 0, 14, + 0, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0, 0, 0, 0, 0, 0, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 #endif /* TCL_UTF_MAX > 3 */ }; @@ -1535,6 +1532,7 @@ static const unsigned char groupMap[] = { * 100 = subtract delta for title/upper * 101 = sub delta for upper, sub 1 for title * 110 = sub delta for upper, add delta for lower + * 111 = subtract delta for upper * * Bits 8-31 Case delta: delta for case conversions. This should be the * highest field so we can easily sign extend. diff --git a/generic/tclUtf.c b/generic/tclUtf.c index a405367..656a6f0 100644 --- a/generic/tclUtf.c +++ b/generic/tclUtf.c @@ -158,15 +158,22 @@ Tcl_UniCharToUtf( if ((ch & 0xF800) == 0xD800) { if (ch & 0x0400) { /* Low surrogate */ - buf[3] = (char) ((ch | 0x80) & 0xBF); - buf[2] |= (char) (((ch >> 6) | 0x80) & 0x8F); - return 4; + if (((buf[0] & 0xF8) == 0xF0) && ((buf[1] & 0xC0) == 0x80) + && ((buf[2] & 0xCF) == 0)) { + /* Previous Tcl_UniChar was a High surrogate, so combine */ + buf[3] = (char) ((ch & 0x3F) | 0x80); + buf[2] |= (char) (((ch >> 6) & 0x0F) | 0x80); + return 4; + } + /* Previous Tcl_UniChar was not a High surrogate, so just output */ } else { /* High surrogate */ ch += 0x40; - buf[2] = (char) (((ch << 4) | 0x80) & 0xB0); - buf[1] = (char) (((ch >> 2) | 0x80) & 0xBF); - buf[0] = (char) (((ch >> 8) | 0xF0) & 0xF7); + /* Fill buffer with specific 3-byte (invalid) byte combination, + so following Low surrogate can recognize it and combine */ + buf[2] = (char) ((ch << 4) & 0x30); + buf[1] = (char) (((ch >> 2) & 0x3F) | 0x80); + buf[0] = (char) (((ch >> 8) & 0x07) | 0xF0); return 0; } } @@ -259,6 +266,15 @@ Tcl_UniCharToUtfDString( * Tcl_UtfCharComplete() before calling this routine to ensure that * enough bytes remain in the string. * + * If TCL_UTF_MAX == 4, special handling of Surrogate pairs is done: + * For any UTF-8 string containing a character outside of the BMP, the + * first call to this function will fill *chPtr with the high surrogate + * and generate a return value of 0. Calling Tcl_UtfToUniChar again + * will produce the low surrogate and a return value of 4. Because *chPtr + * is used to remember whether the high surrogate is already produced, it + * is recommended to initialize the variable it points to as 0 before + * the first call to Tcl_UtfToUniChar is done. + * * Results: * *chPtr is filled with the Tcl_UniChar, and the return value is the * number of bytes from the UTF-8 string that were consumed. @@ -315,7 +331,7 @@ Tcl_UtfToUniChar( *chPtr = (Tcl_UniChar) (((byte & 0x0F) << 12) | ((src[1] & 0x3F) << 6) | (src[2] & 0x3F)); - if (*chPtr > 0x7ff) { + if (*chPtr > 0x7FF) { return 3; } } @@ -331,12 +347,30 @@ Tcl_UtfToUniChar( /* * Four-byte-character lead byte followed by three trail bytes. */ - +#if TCL_UTF_MAX == 4 + Tcl_UniChar surrogate; + + byte = (((byte & 0x07) << 18) | ((src[1] & 0x3F) << 12) + | ((src[2] & 0x3F) << 6) | (src[3] & 0x3F)) - 0x10000; + surrogate = (Tcl_UniChar) (0xD800 + (byte >> 10)); + if (byte & 0x100000) { + /* out of range, < 0x10000 or > 0x10ffff */ + } else if (*chPtr != surrogate) { + /* produce high surrogate, but don't advance source pointer */ + *chPtr = surrogate; + return 0; + } else { + /* produce low surrogate, and advance source pointer */ + *chPtr = (Tcl_UniChar) (0xDC00 | (byte & 0x3FF)); + return 4; + } +#else *chPtr = (Tcl_UniChar) (((byte & 0x07) << 18) | ((src[1] & 0x3F) << 12) | ((src[2] & 0x3F) << 6) | (src[3] & 0x3F)); if ((unsigned)(*chPtr - 0x10000) <= 0xFFFFF) { return 4; } +#endif } /* @@ -433,10 +467,7 @@ Tcl_UtfCharComplete( * a complete UTF-8 character. */ int length) /* Length of above string in bytes. */ { - int ch; - - ch = *((unsigned char *) src); - return length >= totalBytes[ch]; + return length >= totalBytes[(unsigned char)*src]; } /* @@ -928,7 +959,11 @@ Tcl_UtfToTitle( } while (*src) { bytes = TclUtfToUniChar(src, &ch); - lowChar = Tcl_UniCharToLower(ch); + lowChar = ch; + /* Special exception for Georgian Asomtavruli chars, no titlecase. */ + if ((unsigned)(lowChar - 0x1C90) >= 0x30) { + lowChar = Tcl_UniCharToLower(lowChar); + } if (bytes < UtfCount(lowChar)) { memcpy(dst, src, (size_t) bytes); @@ -1030,6 +1065,16 @@ Tcl_UtfNcmp( cs += TclUtfToUniChar(cs, &ch1); ct += TclUtfToUniChar(ct, &ch2); if (ch1 != ch2) { +#if TCL_UTF_MAX == 4 + /* Surrogates always report higher than non-surrogates */ + if (((ch1 & 0xFC00) == 0xD800)) { + if ((ch2 & 0xFC00) != 0xD800) { + return ch1; + } + } else if ((ch2 & 0xFC00) == 0xD800) { + return -ch2; + } +#endif return (ch1 - ch2); } } @@ -1070,6 +1115,16 @@ Tcl_UtfNcasecmp( cs += TclUtfToUniChar(cs, &ch1); ct += TclUtfToUniChar(ct, &ch2); if (ch1 != ch2) { +#if TCL_UTF_MAX == 4 + /* Surrogates always report higher than non-surrogates */ + if (((ch1 & 0xFC00) == 0xD800)) { + if ((ch2 & 0xFC00) != 0xD800) { + return ch1; + } + } else if ((ch2 & 0xFC00) == 0xD800) { + return -ch2; + } +#endif ch1 = Tcl_UniCharToLower(ch1); ch2 = Tcl_UniCharToLower(ch2); if (ch1 != ch2) { @@ -1109,6 +1164,16 @@ TclUtfCasecmp( cs += TclUtfToUniChar(cs, &ch1); ct += TclUtfToUniChar(ct, &ch2); if (ch1 != ch2) { +#if TCL_UTF_MAX == 4 + /* Surrogates always report higher than non-surrogates */ + if (((ch1 & 0xFC00) == 0xD800)) { + if ((ch2 & 0xFC00) != 0xD800) { + return ch1; + } + } else if ((ch2 & 0xFC00) == 0xD800) { + return -ch2; + } +#endif ch1 = Tcl_UniCharToLower(ch1); ch2 = Tcl_UniCharToLower(ch2); if (ch1 != ch2) { @@ -1169,8 +1234,9 @@ Tcl_UniCharToLower( int ch) /* Unicode character to convert. */ { int info = GetUniCharInfo(ch); + int mode = GetCaseType(info); - if (GetCaseType(info) & 0x02) { + if ((mode & 0x02) && (mode != 0x7)) { ch += GetDelta(info); } return (Tcl_UniChar) ch; @@ -1204,7 +1270,9 @@ Tcl_UniCharToTitle( * Subtract or add one depending on the original case. */ - ch += ((mode & 0x4) ? -1 : 1); + if (mode != 0x7) { + ch += ((mode & 0x4) ? -1 : 1); + } } else if (mode == 0x4) { ch -= GetDelta(info); } diff --git a/tools/uniClass.tcl b/tools/uniClass.tcl index 9b4819d..86ec931 100644 --- a/tools/uniClass.tcl +++ b/tools/uniClass.tcl @@ -20,7 +20,7 @@ proc emitRange {first last} { set extranges 1 set numranges 0 set ranges [string trimright $ranges " \n\r\t,"] - append ranges "\n#if TCL_UTF_MAX > 4\n ," + append ranges "\n#if CHRBITS > 16\n ," } append ranges [format "{0x%x, 0x%x}, " \ $first $last] @@ -33,7 +33,7 @@ proc emitRange {first last} { set extchars 1 set numchars 0 set chars [string trimright $chars " \n\r\t,"] - append chars "\n#if TCL_UTF_MAX > 4\n ," + append chars "\n#if CHRBITS > 16\n ," } append chars [format "0x%x, " $first] incr numchars @@ -66,7 +66,7 @@ proc genTable {type} { for {set i 0} {$i <= 0x10ffff} {incr i} { if {$i == 0xd800} { # Skip surrogates - set i 0xdc00 + set i 0xe000 } if {[string is $type [format %c $i]]} { if {$i == ($last + 1)} { diff --git a/tools/uniParse.tcl b/tools/uniParse.tcl index e33b3c7..c712e62 100644 --- a/tools/uniParse.tcl +++ b/tools/uniParse.tcl @@ -272,6 +272,7 @@ static const unsigned char groupMap\[\] = {" * 100 = subtract delta for title/upper * 101 = sub delta for upper, sub 1 for title * 110 = sub delta for upper, add delta for lower + * 111 = subtract delta for upper * * Bits 8-31 Case delta: delta for case conversions. This should be the * highest field so we can easily sign extend. @@ -309,10 +310,14 @@ static const int groups\[\] = {" } } } elseif {$toupper} { - # subtract delta for upper, add delta for lower - set case 6 set delta $toupper - if {$tolower != $toupper} { + if {$tolower == $toupper} { + # subtract delta for upper, add delta for lower + set case 6 + } elseif {!$tolower} { + # subtract delta for upper + set case 7 + } else { error "New case conversion type needed: $toupper $tolower $totitle" } } elseif {$tolower} { @@ -396,7 +401,11 @@ enum { * Unicode character tables. */ -#define GetUniCharInfo(ch) (groups\[groupMap\[pageMap\[((ch) & 0xffff) >> OFFSET_BITS\] | ((ch) & ((1 << OFFSET_BITS)-1))\]\]) +#if TCL_UTF_MAX > 3 +# define GetUniCharInfo(ch) (groups\[groupMap\[pageMap\[((ch) & 0x1fffff) >> OFFSET_BITS\] | ((ch) & ((1 << OFFSET_BITS)-1))\]\]) +#else +# define GetUniCharInfo(ch) (groups\[groupMap\[pageMap\[((ch) & 0xffff) >> OFFSET_BITS\] | ((ch) & ((1 << OFFSET_BITS)-1))\]\]) +#endif " close $f -- cgit v0.12 From 242d4d7095f98f0b2db0cc1461d78080eedfc224 Mon Sep 17 00:00:00 2001 From: dgp Date: Fri, 11 May 2018 17:26:13 +0000 Subject: Missing test file boilerplate. --- tests/process.test | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/process.test b/tests/process.test index 5454a31..07c6e6f 100644 --- a/tests/process.test +++ b/tests/process.test @@ -279,3 +279,6 @@ test process-7.3 {child killed} -body { tcl::process purge tcl::process autopurge 1 } + +::tcltest::cleanupTests +return -- cgit v0.12 From 49a9e593112024abc7aa2ae142e50b1d37b39b43 Mon Sep 17 00:00:00 2001 From: dkf Date: Sun, 13 May 2018 07:17:00 +0000 Subject: General code style cleanup. --- generic/tclBasic.c | 62 ++++++----- generic/tclCmdMZ.c | 14 +-- generic/tclCompCmdsGR.c | 44 ++++---- generic/tclEnsemble.c | 108 +++++++++--------- generic/tclIOUtil.c | 4 +- generic/tclInt.h | 49 ++++----- generic/tclStrToD.c | 4 +- generic/tclStringObj.c | 279 ++++++++++++++++++++++++++--------------------- generic/tclVar.c | 284 ++++++++++++++++++++++++------------------------ unix/tclUnixFCmd.c | 12 +- 10 files changed, 453 insertions(+), 407 deletions(-) diff --git a/generic/tclBasic.c b/generic/tclBasic.c index 16d7f7c..2ebed06 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -2295,30 +2295,33 @@ Tcl_CreateObjCommand( } Tcl_Command -TclCreateObjCommandInNs ( +TclCreateObjCommandInNs( Tcl_Interp *interp, - const char *cmdName, /* Name of command, without any namespace components */ + const char *cmdName, /* Name of command, without any namespace + * components. */ Tcl_Namespace *namespace, /* The namespace to create the command in */ Tcl_ObjCmdProc *proc, /* Object-based function to associate with * name. */ ClientData clientData, /* Arbitrary value to pass to object * function. */ - Tcl_CmdDeleteProc *deleteProc + Tcl_CmdDeleteProc *deleteProc) /* If not NULL, gives a function to call when * this command is deleted. */ -) { +{ int deleted = 0, isNew = 0; Command *cmdPtr; ImportRef *oldRefPtr = NULL; ImportedCmdData *dataPtr; Tcl_HashEntry *hPtr; Namespace *nsPtr = (Namespace *) namespace; + /* - * If the command name we seek to create already exists, we need to - * delete that first. That can be tricky in the presence of traces. - * Loop until we no longer find an existing command in the way, or - * until we've deleted one command and that didn't finish the job. + * If the command name we seek to create already exists, we need to delete + * that first. That can be tricky in the presence of traces. Loop until we + * no longer find an existing command in the way, or until we've deleted + * one command and that didn't finish the job. */ + while (1) { hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, cmdName, &isNew); @@ -2330,16 +2333,18 @@ TclCreateObjCommandInNs ( break; } + /* + * An existing command conflicts. Try to delete it. + */ - /* An existing command conflicts. Try to delete it.. */ cmdPtr = Tcl_GetHashValue(hPtr); /* - * [***] This is wrong. See Tcl Bug a16752c252. - * However, this buggy behavior is kept under particular - * circumstances to accommodate deployed binaries of the - * "tclcompiler" program. http://sourceforge.net/projects/tclpro/ - * that crash if the bug is fixed. + * [***] This is wrong. See Tcl Bug a16752c252. However, this buggy + * behavior is kept under particular circumstances to accommodate + * deployed binaries of the "tclcompiler" program + * http://sourceforge.net/projects/tclpro/ + * that crash if the bug is fixed. */ if (cmdPtr->objProc == TclInvokeStringCommand @@ -2363,12 +2368,15 @@ TclCreateObjCommandInNs ( cmdPtr->flags |= CMD_REDEF_IN_PROGRESS; } - /* Make sure namespace doesn't get deallocated. */ + /* + * Make sure namespace doesn't get deallocated. + */ + cmdPtr->nsPtr->refCount++; Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr); nsPtr = (Namespace *) TclEnsureNamespace(interp, - (Tcl_Namespace *)cmdPtr->nsPtr); + (Tcl_Namespace *) cmdPtr->nsPtr); TclNsDecrRefCount(cmdPtr->nsPtr); if (cmdPtr->flags & CMD_REDEF_IN_PROGRESS) { @@ -2380,9 +2388,9 @@ TclCreateObjCommandInNs ( } if (!isNew) { /* - * If the deletion callback recreated the command, just throw away - * the new command (if we try to delete it again, we could get - * stuck in an infinite loop). + * If the deletion callback recreated the command, just throw away the + * new command (if we try to delete it again, we could get stuck in an + * infinite loop). */ ckfree(Tcl_GetHashValue(hPtr)); @@ -2437,6 +2445,7 @@ TclCreateObjCommandInNs ( cmdPtr->importRefPtr = oldRefPtr; while (oldRefPtr != NULL) { Command *refCmdPtr = oldRefPtr->importedCmdPtr; + dataPtr = refCmdPtr->objClientData; dataPtr->realCmdPtr = cmdPtr; oldRefPtr = oldRefPtr->nextPtr; @@ -8276,23 +8285,26 @@ Tcl_NRCreateCommand( * this command is deleted. */ { Command *cmdPtr = (Command *) - Tcl_CreateObjCommand(interp,cmdName,proc,clientData,deleteProc); + Tcl_CreateObjCommand(interp, cmdName, proc, clientData, + deleteProc); cmdPtr->nreProc = nreProc; return (Tcl_Command) cmdPtr; } Tcl_Command -TclNRCreateCommandInNs ( +TclNRCreateCommandInNs( Tcl_Interp *interp, const char *cmdName, Tcl_Namespace *nsPtr, Tcl_ObjCmdProc *proc, Tcl_ObjCmdProc *nreProc, ClientData clientData, - Tcl_CmdDeleteProc *deleteProc) { + Tcl_CmdDeleteProc *deleteProc) +{ Command *cmdPtr = (Command *) - TclCreateObjCommandInNs(interp,cmdName,nsPtr,proc,clientData,deleteProc); + TclCreateObjCommandInNs(interp, cmdName, nsPtr, proc, clientData, + deleteProc); cmdPtr->nreProc = nreProc; return (Tcl_Command) cmdPtr; @@ -8396,7 +8408,6 @@ TclPushTailcallPoint( TclNRAddCallback(interp, NRCommand, NULL, NULL, NULL, NULL); ((Interp *) interp)->numLevels++; } - /* *---------------------------------------------------------------------- @@ -8432,7 +8443,6 @@ TclSetTailcall( } runPtr->data[1] = listPtr; } - /* *---------------------------------------------------------------------- @@ -8508,7 +8518,6 @@ TclNRTailcallObjCmd( } return TCL_RETURN; } - /* *---------------------------------------------------------------------- @@ -8576,7 +8585,6 @@ TclNRReleaseValues( } return result; } - void Tcl_NRAddCallback( diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index efe4869..d64299e 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -2586,7 +2586,7 @@ StringEqualCmd( objv += objc-2; - match = TclStringCmp (objv[0], objv[1], 0, nocase, reqlength); + match = TclStringCmp(objv[0], objv[1], 0, nocase, reqlength); Tcl_SetObjResult(interp, Tcl_NewBooleanObj(match ? 0 : 1)); return TCL_OK; @@ -2625,25 +2625,23 @@ StringCmpCmd( int match, nocase, reqlength, status; - if ((status = TclStringCmpOpts(interp, objc, objv, &nocase, &reqlength)) - != TCL_OK) { - + status = TclStringCmpOpts(interp, objc, objv, &nocase, &reqlength); + if (status != TCL_OK) { return status; } objv += objc-2; - match = TclStringCmp (objv[0], objv[1], 0, nocase, reqlength); + match = TclStringCmp(objv[0], objv[1], 0, nocase, reqlength); Tcl_SetObjResult(interp, Tcl_NewIntObj(match)); return TCL_OK; } -int TclStringCmpOpts ( +int TclStringCmpOpts( Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[], /* Argument objects. */ int *nocase, - int *reqlength -) + int *reqlength) { int i, length; const char *string; diff --git a/generic/tclCompCmdsGR.c b/generic/tclCompCmdsGR.c index 3781b9a..858a0c5 100644 --- a/generic/tclCompCmdsGR.c +++ b/generic/tclCompCmdsGR.c @@ -27,7 +27,6 @@ static void CompileReturnInternal(CompileEnv *envPtr, Tcl_Obj *returnOpts); static int IndexTailVarIfKnown(Tcl_Interp *interp, Tcl_Token *varTokenPtr, CompileEnv *envPtr); - /* *---------------------------------------------------------------------- @@ -127,9 +126,12 @@ TclCompileGlobalCmd( return TCL_ERROR; } - /* TODO: Consider what value can pass through the - * IndexTailVarIfKnown() screen. Full CompileWord() - * likely does not apply here. Push known value instead. */ + /* + * TODO: Consider what value can pass through the + * IndexTailVarIfKnown() screen. Full CompileWord() likely does not + * apply here. Push known value instead. + */ + CompileWord(envPtr, varTokenPtr, interp, i); TclEmitInstInt4( INST_NSUPVAR, localIndex, envPtr); } @@ -270,7 +272,7 @@ TclCompileIfCmd( jumpIndex = jumpFalseFixupArray.next; jumpFalseFixupArray.next++; TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, - jumpFalseFixupArray.fixup+jumpIndex); + jumpFalseFixupArray.fixup + jumpIndex); } code = TCL_OK; } @@ -317,7 +319,7 @@ TclCompileIfCmd( } jumpEndFixupArray.next++; TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, - jumpEndFixupArray.fixup+jumpIndex); + jumpEndFixupArray.fixup + jumpIndex); /* * Fix the target of the jumpFalse after the test. Generate a 4 @@ -329,7 +331,7 @@ TclCompileIfCmd( TclAdjustStackDepth(-1, envPtr); if (TclFixupForwardJumpToHere(envPtr, - jumpFalseFixupArray.fixup+jumpIndex, 120)) { + jumpFalseFixupArray.fixup + jumpIndex, 120)) { /* * Adjust the code offset for the proceeding jump to the end * of the "if" command. @@ -412,7 +414,7 @@ TclCompileIfCmd( for (j = jumpEndFixupArray.next; j > 0; j--) { jumpIndex = (j - 1); /* i.e. process the closest jump first. */ if (TclFixupForwardJumpToHere(envPtr, - jumpEndFixupArray.fixup+jumpIndex, 127)) { + jumpEndFixupArray.fixup + jumpIndex, 127)) { /* * Adjust the immediately preceeding "ifFalse" jump. We moved it's * target (just after this jump) down three bytes. @@ -920,7 +922,7 @@ TclCompileLappendCmd( CompileWord(envPtr, valueTokenPtr, interp, i); valueTokenPtr = TokenAfter(valueTokenPtr); } - TclEmitInstInt4( INST_LIST, numWords-2, envPtr); + TclEmitInstInt4( INST_LIST, numWords - 2, envPtr); if (isScalar) { if (localIndex < 0) { TclEmitOpcode( INST_LAPPEND_LIST_STK, envPtr); @@ -997,7 +999,7 @@ TclCompileLassignCmd( */ PushVarNameWord(interp, tokenPtr, envPtr, 0, &localIndex, - &isScalar, idx+2); + &isScalar, idx + 2); /* * Emit instructions to get the idx'th item out of the list value on @@ -1414,7 +1416,7 @@ TclCompileLinsertCmd( tokenPtr = TokenAfter(tokenPtr); CompileWord(envPtr, tokenPtr, interp, i); } - TclEmitInstInt4( INST_LIST, i-3, envPtr); + TclEmitInstInt4( INST_LIST, i - 3, envPtr); if (idx == TCL_INDEX_START) { TclEmitInstInt4( INST_REVERSE, 2, envPtr); @@ -1439,7 +1441,7 @@ TclCompileLinsertCmd( } TclEmitInstInt4( INST_OVER, 1, envPtr); TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr); - TclEmitInt4( idx-1, envPtr); + TclEmitInt4( idx - 1, envPtr); TclEmitInstInt4( INST_REVERSE, 3, envPtr); TclEmitInstInt4( INST_LIST_RANGE_IMM, idx, envPtr); TclEmitInt4( TCL_INDEX_END, envPtr); @@ -2234,7 +2236,7 @@ TclCompileRegexpCmd( } if (!simple) { - CompileWord(envPtr, varTokenPtr, interp, parsePtr->numWords-2); + CompileWord(envPtr, varTokenPtr, interp, parsePtr->numWords - 2); } /* @@ -2242,7 +2244,7 @@ TclCompileRegexpCmd( */ varTokenPtr = TokenAfter(varTokenPtr); - CompileWord(envPtr, varTokenPtr, interp, parsePtr->numWords-1); + CompileWord(envPtr, varTokenPtr, interp, parsePtr->numWords - 1); if (simple) { if (exact && !nocase) { @@ -2426,7 +2428,7 @@ TclCompileRegsubCmd( PushLiteral(envPtr, bytes, len); bytes = TclGetStringFromObj(replacementObj, &len); PushLiteral(envPtr, bytes, len); - CompileWord(envPtr, stringTokenPtr, interp, parsePtr->numWords-2); + CompileWord(envPtr, stringTokenPtr, interp, parsePtr->numWords - 2); TclEmitOpcode( INST_STR_MAP, envPtr); done: @@ -2555,7 +2557,7 @@ TclCompileReturnCmd( */ if (explicitResult) { - CompileWord(envPtr, wordTokenPtr, interp, numWords-1); + CompileWord(envPtr, wordTokenPtr, interp, numWords - 1); } else { /* * No explict result argument, so default result is empty string. @@ -2633,7 +2635,7 @@ TclCompileReturnCmd( */ if (explicitResult) { - CompileWord(envPtr, wordTokenPtr, interp, numWords-1); + CompileWord(envPtr, wordTokenPtr, interp, numWords - 1); } else { PushStringLiteral(envPtr, ""); } @@ -2864,12 +2866,12 @@ TclCompileVariableCmd( CompileWord(envPtr, varTokenPtr, interp, i); TclEmitInstInt4( INST_VARIABLE, localIndex, envPtr); - if (i+1 < numWords) { + if (i + 1 < numWords) { /* * A value has been given: set the variable, pop the value */ - CompileWord(envPtr, valueTokenPtr, interp, i+1); + CompileWord(envPtr, valueTokenPtr, interp, i + 1); Emit14Inst( INST_STORE_SCALAR, localIndex, envPtr); TclEmitOpcode( INST_POP, envPtr); } @@ -2945,7 +2947,7 @@ IndexTailVarIfKnown( tailName = TclGetStringFromObj(tailPtr, &len); if (len) { - if (*(tailName+len-1) == ')') { + if (*(tailName + len - 1) == ')') { /* * Possible array: bail out */ @@ -2959,7 +2961,7 @@ IndexTailVarIfKnown( */ for (p = tailName + len -1; p > tailName; p--) { - if ((*p == ':') && (*(p-1) == ':')) { + if ((*p == ':') && (*(p - 1) == ':')) { p++; break; } diff --git a/generic/tclEnsemble.c b/generic/tclEnsemble.c index e7bfbac..94c0b76 100644 --- a/generic/tclEnsemble.c +++ b/generic/tclEnsemble.c @@ -87,8 +87,8 @@ static const Tcl_ObjType ensembleCmdType = { }; /* - * The internal rep for caching ensemble subcommand lookups and - * spell corrections. + * The internal rep for caching ensemble subcommand lookups and spelling + * corrections. */ typedef struct { @@ -98,10 +98,9 @@ typedef struct { Command *token; /* Reference to the command for which this * structure is a cache of the resolution. */ Tcl_Obj *fix; /* Corrected spelling, if needed. */ - Tcl_HashEntry *hPtr; /* Direct link to entry in the subcommand - * hash table. */ + Tcl_HashEntry *hPtr; /* Direct link to entry in the subcommand hash + * table. */ } EnsembleCmdRep; - static inline Tcl_Obj * NewNsObj( @@ -111,9 +110,8 @@ NewNsObj( if (namespacePtr == TclGetGlobalNamespace(nsPtr->interp)) { return Tcl_NewStringObj("::", 2); - } else { - return Tcl_NewStringObj(nsPtr->fullName, -1); } + return Tcl_NewStringObj(nsPtr->fullName, -1); } /* @@ -147,7 +145,7 @@ TclNamespaceEnsembleCmd( { Tcl_Namespace *namespacePtr; Namespace *nsPtr = (Namespace *) TclGetCurrentNamespace(interp), *cxtPtr, - *foundNsPtr, *altFoundNsPtr, *actualCxtPtr; + *foundNsPtr, *altFoundNsPtr, *actualCxtPtr; Tcl_Command token; Tcl_DictSearch search; Tcl_Obj *listObj; @@ -302,7 +300,8 @@ TclNamespaceEnsembleCmd( Tcl_DictObjPut(NULL, patchedDict, subcmdWordsObj, newList); } - Tcl_DictObjNext(&search, &subcmdWordsObj,&listObj, &done); + Tcl_DictObjNext(&search, &subcmdWordsObj, &listObj, + &done); } while (!done); if (allocatedMapFlag) { @@ -336,8 +335,8 @@ TclNamespaceEnsembleCmd( } TclGetNamespaceForQualName(interp, name, cxtPtr, - TCL_CREATE_NS_IF_UNKNOWN, &foundNsPtr, &altFoundNsPtr, &actualCxtPtr, - &simpleName); + TCL_CREATE_NS_IF_UNKNOWN, &foundNsPtr, &altFoundNsPtr, + &actualCxtPtr, &simpleName); /* * Create the ensemble. Note that this might delete another ensemble @@ -347,8 +346,8 @@ TclNamespaceEnsembleCmd( */ token = TclCreateEnsembleInNs(interp, simpleName, - (Tcl_Namespace *) foundNsPtr, (Tcl_Namespace *) nsPtr, - (permitPrefix ? TCL_ENSEMBLE_PREFIX : 0)); + (Tcl_Namespace *) foundNsPtr, (Tcl_Namespace *) nsPtr, + (permitPrefix ? TCL_ENSEMBLE_PREFIX : 0)); Tcl_SetEnsembleSubcommandList(interp, token, subcmdObj); Tcl_SetEnsembleMappingDict(interp, token, mapObj); Tcl_SetEnsembleUnknownHandler(interp, token, unknownObj); @@ -576,7 +575,8 @@ TclNamespaceEnsembleCmd( Tcl_AppendStringsToObj(newCmd, "::", NULL); } Tcl_AppendObjToObj(newCmd, listv[0]); - Tcl_ListObjReplace(NULL, newList, 0,1, 1,&newCmd); + Tcl_ListObjReplace(NULL, newList, 0, 1, 1, + &newCmd); if (patchedDict == NULL) { patchedDict = Tcl_DuplicateObj(objv[1]); } @@ -650,15 +650,13 @@ TclNamespaceEnsembleCmd( Tcl_Command TclCreateEnsembleInNs( Tcl_Interp *interp, - - const char *name, /* Simple name of command to create (no */ - /* namespace components). */ - Tcl_Namespace /* Name of namespace to create the command in. */ - *nameNsPtr, - Tcl_Namespace - *ensembleNsPtr, /* Name of the namespace for the ensemble. */ - int flags - ) + const char *name, /* Simple name of command to create (no + * namespace components). */ + Tcl_Namespace *nameNsPtr, /* Name of namespace to create the command + * in. */ + Tcl_Namespace *ensembleNsPtr, + /* Name of the namespace for the ensemble. */ + int flags) { Namespace *nsPtr = (Namespace *) ensembleNsPtr; EnsembleConfig *ensemblePtr; @@ -666,8 +664,8 @@ TclCreateEnsembleInNs( ensemblePtr = ckalloc(sizeof(EnsembleConfig)); token = TclNRCreateCommandInNs(interp, name, - (Tcl_Namespace *) nameNsPtr, NsEnsembleImplementationCmd, - NsEnsembleImplementationCmdNR, ensemblePtr, DeleteEnsembleConfig); + (Tcl_Namespace *) nameNsPtr, NsEnsembleImplementationCmd, + NsEnsembleImplementationCmdNR, ensemblePtr, DeleteEnsembleConfig); if (token == NULL) { ckfree(ensemblePtr); return NULL; @@ -701,18 +699,15 @@ TclCreateEnsembleInNs( } return ensemblePtr->token; - } - - + /* *---------------------------------------------------------------------- * * Tcl_CreateEnsemble * - * Create a simple ensemble attached to the given namespace. - * - * Deprecated by TclCreateEnsembleInNs. + * Create a simple ensemble attached to the given namespace. Deprecated + * (internally) by TclCreateEnsembleInNs. * * Value * @@ -732,8 +727,8 @@ Tcl_CreateEnsemble( Tcl_Namespace *namespacePtr, int flags) { - Namespace *nsPtr = (Namespace *)namespacePtr, *foundNsPtr, *altNsPtr, - *actualNsPtr; + Namespace *nsPtr = (Namespace *) namespacePtr, *foundNsPtr, *altNsPtr, + *actualNsPtr; const char * simpleName; if (nsPtr == NULL) { @@ -741,11 +736,10 @@ Tcl_CreateEnsemble( } TclGetNamespaceForQualName(interp, name, nsPtr, TCL_CREATE_NS_IF_UNKNOWN, - &foundNsPtr, &altNsPtr, &actualNsPtr, &simpleName); + &foundNsPtr, &altNsPtr, &actualNsPtr, &simpleName); return TclCreateEnsembleInNs(interp, simpleName, - (Tcl_Namespace *) foundNsPtr, (Tcl_Namespace *) nsPtr, flags); + (Tcl_Namespace *) foundNsPtr, (Tcl_Namespace *) nsPtr, flags); } - /* *---------------------------------------------------------------------- @@ -2117,22 +2111,27 @@ TclSpellFix( iPtr->ensembleRewrite.numInsertedObjs = 0; } - /* Compute the valid length of the ensemble root */ + /* + * Compute the valid length of the ensemble root. + */ size = iPtr->ensembleRewrite.numRemovedObjs + objc - - iPtr->ensembleRewrite.numInsertedObjs; + - iPtr->ensembleRewrite.numInsertedObjs; search = iPtr->ensembleRewrite.sourceObjs; if (search[0] == NULL) { - /* Awful casting abuse here */ + /* + * Awful casting abuse here... + */ search = (Tcl_Obj *const *) search[1]; } if (badIdx < iPtr->ensembleRewrite.numInsertedObjs) { /* - * Misspelled value was inserted. We cannot directly jump - * to the bad value, but have to search. + * Misspelled value was inserted. We cannot directly jump to the bad + * value, but have to search. */ + idx = 1; while (idx < size) { if (search[idx] == bad) { @@ -2156,13 +2155,14 @@ TclSpellFix( search = iPtr->ensembleRewrite.sourceObjs; if (search[0] == NULL) { - store = (Tcl_Obj **)search[2]; - } else { + store = (Tcl_Obj **) search[2]; + } else { Tcl_Obj **tmp = ckalloc(3 * sizeof(Tcl_Obj *)); + tmp[0] = NULL; - tmp[1] = (Tcl_Obj *)iPtr->ensembleRewrite.sourceObjs; - tmp[2] = (Tcl_Obj *)ckalloc(size * sizeof(Tcl_Obj *)); - memcpy(tmp[2], tmp[1], size*sizeof(Tcl_Obj *)); + tmp[1] = (Tcl_Obj *) iPtr->ensembleRewrite.sourceObjs; + tmp[2] = (Tcl_Obj *) ckalloc(size * sizeof(Tcl_Obj *)); + memcpy(tmp[2], tmp[1], size * sizeof(Tcl_Obj *)); iPtr->ensembleRewrite.sourceObjs = (Tcl_Obj *const *) tmp; TclNRAddCallback(interp, FreeER, tmp, NULL, NULL, NULL); @@ -2589,7 +2589,9 @@ BuildEnsembleConfig( } } } else { - /* Usual case where we can freely act on the list and dict. */ + /* + * Usual case where we can freely act on the list and dict. + */ for (i = 0; i < subc; i++) { name = TclGetString(subv[i]); @@ -2598,7 +2600,10 @@ BuildEnsembleConfig( continue; } - /* Lookup target in the dictionary */ + /* + * Lookup target in the dictionary. + */ + if (mapDict) { Tcl_DictObjGet(NULL, mapDict, subv[i], &target); if (target) { @@ -2610,10 +2615,11 @@ BuildEnsembleConfig( /* * target was not in the dictionary so map onto the namespace. - * Note in this case that we do not guarantee that the - * command is actually there; that is the programmer's - * responsibility (or [::unknown] of course). + * Note in this case that we do not guarantee that the command + * is actually there; that is the programmer's responsibility + * (or [::unknown] of course). */ + cmdObj = Tcl_NewStringObj(name, -1); cmdPrefixObj = Tcl_NewListObj(1, &cmdObj); Tcl_SetHashValue(hPtr, cmdPrefixObj); diff --git a/generic/tclIOUtil.c b/generic/tclIOUtil.c index 144bab0..3382825 100644 --- a/generic/tclIOUtil.c +++ b/generic/tclIOUtil.c @@ -3197,8 +3197,8 @@ TclSkipUnlink( #ifndef AUFS_SUPER_MAGIC #define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's') #endif /* AUFS_SUPER_MAGIC */ - if ((statfs(Tcl_GetString (shlibFile), &fs) == 0) && - (fs.f_type == AUFS_SUPER_MAGIC)) { + if ((statfs(Tcl_GetString(shlibFile), &fs) == 0) + && (fs.f_type == AUFS_SUPER_MAGIC)) { return 1; } } diff --git a/generic/tclInt.h b/generic/tclInt.h index 4a8b49d..8f5d8ba 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -2920,19 +2920,13 @@ MODULE_SCOPE void TclContinuationsCopy(Tcl_Obj *objPtr, Tcl_Obj *originObjPtr); MODULE_SCOPE int TclConvertElement(const char *src, int length, char *dst, int flags); -MODULE_SCOPE Tcl_Command TclCreateObjCommandInNs ( - Tcl_Interp *interp, - const char *cmdName, - Tcl_Namespace *nsPtr, - Tcl_ObjCmdProc *proc, - ClientData clientData, +MODULE_SCOPE Tcl_Command TclCreateObjCommandInNs(Tcl_Interp *interp, + const char *cmdName, Tcl_Namespace *nsPtr, + Tcl_ObjCmdProc *proc, ClientData clientData, Tcl_CmdDeleteProc *deleteProc); -MODULE_SCOPE Tcl_Command TclCreateEnsembleInNs( - Tcl_Interp *interp, - const char *name, - Tcl_Namespace *nameNamespacePtr, - Tcl_Namespace *ensembleNamespacePtr, - int flags); +MODULE_SCOPE Tcl_Command TclCreateEnsembleInNs(Tcl_Interp *interp, + const char *name, Tcl_Namespace *nameNamespacePtr, + Tcl_Namespace *ensembleNamespacePtr, int flags); MODULE_SCOPE void TclDeleteNamespaceVars(Namespace *nsPtr); MODULE_SCOPE int TclFindDictElement(Tcl_Interp *interp, const char *dict, int dictLength, @@ -2959,9 +2953,9 @@ MODULE_SCOPE char * TclDStringAppendObj(Tcl_DString *dsPtr, MODULE_SCOPE char * TclDStringAppendDString(Tcl_DString *dsPtr, Tcl_DString *toAppendPtr); MODULE_SCOPE Tcl_Obj * TclDStringToObj(Tcl_DString *dsPtr); -MODULE_SCOPE Tcl_Obj *const * TclFetchEnsembleRoot(Tcl_Interp *interp, +MODULE_SCOPE Tcl_Obj *const *TclFetchEnsembleRoot(Tcl_Interp *interp, Tcl_Obj *const *objv, int objc, int *objcPtr); -MODULE_SCOPE Tcl_Namespace * TclEnsureNamespace(Tcl_Interp *interp, +MODULE_SCOPE Tcl_Namespace *TclEnsureNamespace(Tcl_Interp *interp, Tcl_Namespace *namespacePtr); MODULE_SCOPE void TclFinalizeAllocSubsystem(void); MODULE_SCOPE void TclFinalizeAsync(void); @@ -2989,15 +2983,11 @@ MODULE_SCOPE double TclFloor(const mp_int *a); MODULE_SCOPE void TclFormatNaN(double value, char *buffer); MODULE_SCOPE int TclFSFileAttrIndex(Tcl_Obj *pathPtr, const char *attributeName, int *indexPtr); -MODULE_SCOPE Tcl_Command TclNRCreateCommandInNs ( - Tcl_Interp *interp, - const char *cmdName, - Tcl_Namespace *nsPtr, - Tcl_ObjCmdProc *proc, - Tcl_ObjCmdProc *nreProc, +MODULE_SCOPE Tcl_Command TclNRCreateCommandInNs(Tcl_Interp *interp, + const char *cmdName, Tcl_Namespace *nsPtr, + Tcl_ObjCmdProc *proc, Tcl_ObjCmdProc *nreProc, ClientData clientData, Tcl_CmdDeleteProc *deleteProc); - MODULE_SCOPE int TclNREvalFile(Tcl_Interp *interp, Tcl_Obj *pathPtr, const char *encodingName); MODULE_SCOPE void TclFSUnloadTempFile(Tcl_LoadHandle loadHandle); @@ -3178,7 +3168,8 @@ MODULE_SCOPE void TclSetBgErrorHandler(Tcl_Interp *interp, Tcl_Obj *cmdPrefix); MODULE_SCOPE void TclSetBignumIntRep(Tcl_Obj *objPtr, mp_int *bignumValue); -MODULE_SCOPE int TclSetBooleanFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); +MODULE_SCOPE int TclSetBooleanFromAny(Tcl_Interp *interp, + Tcl_Obj *objPtr); MODULE_SCOPE void TclSetCmdNameObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Command *cmdPtr); MODULE_SCOPE void TclSetDuplicateObj(Tcl_Obj *dupPtr, Tcl_Obj *objPtr); @@ -3190,12 +3181,12 @@ MODULE_SCOPE void TclSpellFix(Tcl_Interp *interp, Tcl_Obj *bad, Tcl_Obj *fix); MODULE_SCOPE void * TclStackRealloc(Tcl_Interp *interp, void *ptr, int numBytes); - typedef int (*memCmpFn_t)(const void*, const void*, size_t); -MODULE_SCOPE int TclStringCmp (Tcl_Obj *value1Ptr, Tcl_Obj *value2Ptr, +MODULE_SCOPE int TclStringCmp(Tcl_Obj *value1Ptr, Tcl_Obj *value2Ptr, int checkEq, int nocase, int reqlength); -MODULE_SCOPE int TclStringCmpOpts (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], - int *nocase, int *reqlength); +MODULE_SCOPE int TclStringCmpOpts(Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[], int *nocase, + int *reqlength); MODULE_SCOPE int TclStringMatch(const char *str, int strLen, const char *pattern, int ptnLen, int flags); MODULE_SCOPE int TclStringMatchObj(Tcl_Obj *stringObj, @@ -3244,8 +3235,8 @@ MODULE_SCOPE void * TclpThreadCreateKey(void); MODULE_SCOPE void TclpThreadDeleteKey(void *keyPtr); MODULE_SCOPE void TclpThreadSetMasterTSD(void *tsdKeyPtr, void *ptr); MODULE_SCOPE void * TclpThreadGetMasterTSD(void *tsdKeyPtr); - -MODULE_SCOPE void TclErrorStackResetIf(Tcl_Interp *interp, const char *msg, int length); +MODULE_SCOPE void TclErrorStackResetIf(Tcl_Interp *interp, + const char *msg, int length); /* *---------------------------------------------------------------- @@ -4098,7 +4089,7 @@ typedef enum TclProcessWaitStatus { TCL_PROCESS_EXITED = 1, /* Process has exited. */ TCL_PROCESS_SIGNALED = 2, /* Child killed because of a signal. */ TCL_PROCESS_STOPPED = 3, /* Child suspended because of a signal. */ - TCL_PROCESS_UNKNOWN_STATUS = 4 + TCL_PROCESS_UNKNOWN_STATUS = 4 /* Child wait status didn't make sense. */ } TclProcessWaitStatus; diff --git a/generic/tclStrToD.c b/generic/tclStrToD.c index 0434919..a46b29a 100644 --- a/generic/tclStrToD.c +++ b/generic/tclStrToD.c @@ -4543,7 +4543,7 @@ Tcl_InitBignumFromDouble( return TCL_ERROR; } - fract = frexp(d,&expt); + fract = frexp(d, &expt); if (expt <= 0) { mp_init(b); mp_zero(b); @@ -4883,7 +4883,7 @@ Pow10TimesFrExp( * Multiply by 10**exponent. */ - retval = frexp(retval * pow10vals[exponent&0xf], &j); + retval = frexp(retval * pow10vals[exponent & 0xf], &j); expt += j; for (i=4; i<9; ++i) { if (exponent & (1<bytes == &tclEmptyString) { @@ -570,20 +567,22 @@ Tcl_GetUniChar( if (index >= stringPtr->numChars) { return -1; } - ch = stringPtr->unicode[index]; + ch = stringPtr->unicode[index]; #if TCL_UTF_MAX <= 4 - /* See: bug [11ae2be95dac9417] */ - if ((ch&0xF800) == 0xD800) { - if (ch&0x400) { - if ((index > 0) && ((stringPtr->unicode[index-1]&0xFC00) == 0xD800)) { - ch = -1; /* low surrogate preceded by high surrogate */ - } - } else if ((++index < stringPtr->numChars) - && ((stringPtr->unicode[index]&0xFC00) == 0xDC00)) { - /* high surrogate followed by low surrogate */ - ch = (((ch & 0x3FF) << 10) | (stringPtr->unicode[index] & 0x3FF)) + 0x10000; + /* See: bug [11ae2be95dac9417] */ + if ((ch & 0xF800) == 0xD800) { + if (ch & 0x400) { + if ((index > 0) + && ((stringPtr->unicode[index-1] & 0xFC00) == 0xD800)) { + ch = -1; /* low surrogate preceded by high surrogate */ } + } else if ((++index < stringPtr->numChars) + && ((stringPtr->unicode[index] & 0xFC00) == 0xDC00)) { + /* high surrogate followed by low surrogate */ + ch = (((ch & 0x3FF) << 10) | + (stringPtr->unicode[index] & 0x3FF)) + 0x10000; } + } #endif return ch; } @@ -689,7 +688,8 @@ Tcl_GetRange( if (first < 0) { first = 0; - } + } + /* * Optimize the case where we're really dealing with a bytearray object * we don't need to convert to a string to perform the substring operation. @@ -697,13 +697,14 @@ Tcl_GetRange( if (TclIsPureByteArray(objPtr)) { unsigned char *bytes = Tcl_GetByteArrayFromObj(objPtr, &length); + if (last >= length) { last = length - 1; } if (last < first) { return Tcl_NewObj(); } - return Tcl_NewByteArrayObj(bytes+first, last-first+1); + return Tcl_NewByteArrayObj(bytes + first, last - first + 1); } /* @@ -742,24 +743,25 @@ Tcl_GetRange( FillUnicodeRep(objPtr); stringPtr = GET_STRING(objPtr); } - if (last > stringPtr->numChars) { - last = stringPtr->numChars; - } - if (last < first) { - return Tcl_NewObj(); - } + if (last > stringPtr->numChars) { + last = stringPtr->numChars; + } + if (last < first) { + return Tcl_NewObj(); + } #if TCL_UTF_MAX <= 4 - /* See: bug [11ae2be95dac9417] */ - if ((first>0) && ((stringPtr->unicode[first]&0xFC00) == 0xDC00) - && ((stringPtr->unicode[first-1]&0xFC00) == 0xD800)) { - ++first; - } - if ((last+1numChars) && ((stringPtr->unicode[last+1]&0xFC00) == 0xDC00) - && ((stringPtr->unicode[last]&0xFC00) == 0xD800)) { - ++last; - } + /* See: bug [11ae2be95dac9417] */ + if ((first > 0) && ((stringPtr->unicode[first] & 0xFC00) == 0xDC00) + && ((stringPtr->unicode[first-1] & 0xFC00) == 0xD800)) { + ++first; + } + if ((last + 1 < stringPtr->numChars) + && ((stringPtr->unicode[last+1] & 0xFC00) == 0xDC00) + && ((stringPtr->unicode[last] & 0xFC00) == 0xD800)) { + ++last; + } #endif - return Tcl_NewUnicodeObj(stringPtr->unicode + first, last-first+1); + return Tcl_NewUnicodeObj(stringPtr->unicode + first, last - first + 1); } /* @@ -1317,45 +1319,51 @@ Tcl_AppendObjToObj( /* * Handle append of one bytearray object to another as a special case. * Note that we only do this when the objects are pure so that the - * bytearray faithfully represent the true value; Otherwise - * appending the byte arrays together could lose information; + * bytearray faithfully represent the true value; Otherwise appending the + * byte arrays together could lose information; */ if ((TclIsPureByteArray(objPtr) || objPtr->bytes == &tclEmptyString) && TclIsPureByteArray(appendObjPtr)) { - /* * You might expect the code here to be * * bytes = Tcl_GetByteArrayFromObj(appendObjPtr, &length); * TclAppendBytesToByteArray(objPtr, bytes, length); * - * and essentially all of the time that would be fine. However, - * it would run into trouble in the case where objPtr and - * appendObjPtr point to the same thing. That may never be a - * good idea. It seems to violate Copy On Write, and we don't - * have any tests for the situation, since making any Tcl commands - * that call Tcl_AppendObjToObj() do that appears impossible - * (They honor Copy On Write!). For the sake of extensions that - * go off into that realm, though, here's a more complex approach - * that can handle all the cases. + * and essentially all of the time that would be fine. However, it + * would run into trouble in the case where objPtr and appendObjPtr + * point to the same thing. That may never be a good idea. It seems to + * violate Copy On Write, and we don't have any tests for the + * situation, since making any Tcl commands that call + * Tcl_AppendObjToObj() do that appears impossible (They honor Copy On + * Write!). For the sake of extensions that go off into that realm, + * though, here's a more complex approach that can handle all the + * cases. + * + * First, get the lengths. */ - /* Get lengths */ int lengthSrc; (void) Tcl_GetByteArrayFromObj(objPtr, &length); (void) Tcl_GetByteArrayFromObj(appendObjPtr, &lengthSrc); - /* Grow buffer enough for the append */ + /* + * Grow buffer enough for the append. + */ + TclAppendBytesToByteArray(objPtr, NULL, lengthSrc); - /* Reset objPtr back to the original value */ + /* + * Reset objPtr back to the original value. + */ + Tcl_SetByteArrayLength(objPtr, length); /* - * Now do the append knowing that buffer growth cannot cause - * any trouble. + * Now do the append knowing that buffer growth cannot cause any + * trouble. */ TclAppendBytesToByteArray(objPtr, @@ -1403,6 +1411,7 @@ Tcl_AppendObjToObj( numChars = stringPtr->numChars; if ((numChars >= 0) && (appendObjPtr->typePtr == &tclStringType)) { String *appendStringPtr = GET_STRING(appendObjPtr); + appendNumChars = appendStringPtr->numChars; } @@ -1988,7 +1997,8 @@ Tcl_AppendFormatToObj( format += step; step = TclUtfToUniChar(format, &ch); } - } else if ((ch == 't') || (ch == 'z') || (ch == 'q') || (ch == 'j') || (ch == 'L')) { + } else if ((ch == 't') || (ch == 'z') || (ch == 'q') || (ch == 'j') + || (ch == 'L')) { format += step; step = TclUtfToUniChar(format, &ch); useBig = 1; @@ -2513,7 +2523,7 @@ Tcl_AppendFormatToObj( /* *--------------------------------------------------------------------------- * - * Tcl_Format-- + * Tcl_Format -- * * Results: * A refcount zero Tcl_Obj. @@ -2904,7 +2914,10 @@ TclStringRepeat( Tcl_GetByteArrayFromObj(objResultPtr, NULL), (count - done) * length); } else if (unichar) { - /* Efficiently produce a pure Tcl_UniChar array result */ + /* + * Efficiently produce a pure Tcl_UniChar array result. + */ + if (!inPlace || Tcl_IsShared(objPtr)) { objResultPtr = Tcl_NewUnicodeObj(Tcl_GetUnicode(objPtr), length); } else { @@ -2930,7 +2943,10 @@ TclStringRepeat( Tcl_AppendUnicodeToObj(objResultPtr, Tcl_GetUnicode(objResultPtr), (count - done) * length); } else { - /* Efficiently concatenate string reps */ + /* + * Efficiently concatenate string reps. + */ + if (!inPlace || Tcl_IsShared(objPtr)) { objResultPtr = Tcl_NewStringObj(Tcl_GetString(objPtr), length); } else { @@ -3014,9 +3030,10 @@ TclStringCat( /* Value has a string rep. */ if (objPtr->length) { /* - * Non-empty string rep. Not a pure bytearray, so we - * won't create a pure bytearray + * Non-empty string rep. Not a pure bytearray, so we won't + * create a pure bytearray. */ + binary = 0; if ((objPtr->typePtr) && (objPtr->typePtr != &tclStringType)) { /* Prevent shimmer of non-string types. */ @@ -3037,8 +3054,12 @@ TclStringCat( } while (--oc && (binary || allowUniChar)); if (binary) { - /* Result will be pure byte array. Pre-size it */ - ov = objv; oc = objc; + /* + * Result will be pure byte array. Pre-size it + */ + + ov = objv; + oc = objc; do { Tcl_Obj *objPtr = *ov++; @@ -3058,8 +3079,12 @@ TclStringCat( } } while (--oc); } else if (allowUniChar && requestUniChar) { - /* Result will be pure Tcl_UniChar array. Pre-size it. */ - ov = objv; oc = objc; + /* + * Result will be pure Tcl_UniChar array. Pre-size it. + */ + + ov = objv; + oc = objc; do { Tcl_Obj *objPtr = *ov++; @@ -3104,9 +3129,9 @@ TclStringCat( } while (--oc && (length == 0) && (pendingPtr == NULL)); /* - * Either we found a possibly non-empty value, and we - * remember this index as the first and last such value so - * far seen, or (oc == 0) and all values are known empty, + * Either we found a possibly non-empty value, and we remember + * this index as the first and last such value so far seen, + * or (oc == 0) and all values are known empty, * so first = last = objc - 1 signals the right quick return. */ @@ -3118,10 +3143,9 @@ TclStringCat( /* assert ( pendingPtr != NULL ) */ /* - * There's a pending value followed by more values. - * Loop over remaining values generating strings until - * a non-empty value is found, or the pending value gets - * its string generated. + * There's a pending value followed by more values. Loop over + * remaining values generating strings until a non-empty value + * is found, or the pending value gets its string generated. */ do { @@ -3177,10 +3201,10 @@ TclStringCat( unsigned char *dst; /* - * Broken interface! Byte array value routines offer no way - * to handle failure to allocate enough space. Following - * stanza may panic. + * Broken interface! Byte array value routines offer no way to handle + * failure to allocate enough space. Following stanza may panic. */ + if (inPlace && !Tcl_IsShared(*objv)) { int start; @@ -3295,6 +3319,7 @@ TclStringCat( if ((objPtr->bytes == NULL) || (objPtr->length)) { int more; char *src = Tcl_GetStringFromObj(objPtr, &more); + memcpy(dst, src, (size_t) more); dst += more; } @@ -3320,7 +3345,7 @@ TclStringCat( * Compare two Tcl_Obj values as strings. * * Results: - * Like memcmp, return -1, 0, or 1. + * Like memcmp, return -1, 0, or 1. * * Side effects: * String representations may be generated. Internal representation may @@ -3329,13 +3354,13 @@ TclStringCat( *--------------------------------------------------------------------------- */ -int TclStringCmp ( - Tcl_Obj *value1Ptr, - Tcl_Obj *value2Ptr, - int checkEq, /* comparison is only for equality */ - int nocase, /* comparison is not case sensitive */ - int reqlength /* requested length */ -) { +int TclStringCmp( + Tcl_Obj *value1Ptr, + Tcl_Obj *value2Ptr, + int checkEq, /* comparison is only for equality */ + int nocase, /* comparison is not case sensitive */ + int reqlength) /* requested length */ +{ char *s1, *s2; int empty, length, match, s1len, s2len; memCmpFn_t memCmpFn; @@ -3355,6 +3380,7 @@ int TclStringCmp ( * case-sensitive (which is all that really makes sense with byte * arrays anyway, and we have no memcasecmp() for some reason... :^) */ + s1 = (char *) Tcl_GetByteArrayFromObj(value1Ptr, &s1len); s2 = (char *) Tcl_GetByteArrayFromObj(value2Ptr, &s2len); memCmpFn = memcmp; @@ -3402,31 +3428,31 @@ int TclStringCmp ( } else { if ((empty = TclCheckEmptyString(value1Ptr)) > 0) { switch (TclCheckEmptyString(value2Ptr)) { - case -1: + case -1: s1 = 0; s1len = 0; s2 = TclGetStringFromObj(value2Ptr, &s2len); break; - case 0: + case 0: match = -1; goto matchdone; - case 1: - default: /* avoid warn: `s2` may be used uninitialized */ + case 1: + default: /* avoid warn: `s2` may be used uninitialized */ match = 0; goto matchdone; } } else if (TclCheckEmptyString(value2Ptr) > 0) { switch (empty) { - case -1: + case -1: s2 = 0; s2len = 0; s1 = TclGetStringFromObj(value1Ptr, &s1len); break; - case 0: + case 0: match = 1; goto matchdone; - case 1: - default: /* avoid warn: `s1` may be used uninitialized */ + case 1: + default: /* avoid warn: `s1` may be used uninitialized */ match = 0; goto matchdone; } @@ -3436,18 +3462,19 @@ int TclStringCmp ( } if (!nocase && checkEq) { /* - * When we have equal-length we can check only for (in)equality. - * We can use memcmp in all (n)eq cases because we - * don't need to worry about lexical LE/BE variance. + * When we have equal-length we can check only for + * (in)equality. We can use memcmp in all (n)eq cases because + * we don't need to worry about lexical LE/BE variance. */ + memCmpFn = memcmp; } else { - /* - * As a catch-all we will work with UTF-8. We cannot use memcmp() as - * that is unsafe with any string containing NUL (\xC0\x80 in Tcl's - * utf rep). We can use the more efficient TclpUtfNcmp2 if we are - * case-sensitive and no specific length was requested. + * As a catch-all we will work with UTF-8. We cannot use + * memcmp() as that is unsafe with any string containing NUL + * (\xC0\x80 in Tcl's utf rep). We can use the more efficient + * TclpUtfNcmp2 if we are case-sensitive and no specific + * length was requested. */ if ((reqlength < 0) && !nocase) { @@ -3455,7 +3482,8 @@ int TclStringCmp ( } else { s1len = Tcl_NumUtfChars(s1, s1len); s2len = Tcl_NumUtfChars(s2, s2len); - memCmpFn = (memCmpFn_t) (nocase ? Tcl_UtfNcasecmp : Tcl_UtfNcmp); + memCmpFn = (memCmpFn_t) + (nocase ? Tcl_UtfNcasecmp : Tcl_UtfNcmp); } } } @@ -3465,8 +3493,8 @@ int TclStringCmp ( length = reqlength; } else if (reqlength < 0) { /* - * The requested length is negative, so we ignore it by setting it to - * length + 1 so we correct the match var. + * The requested length is negative, so we ignore it by setting it + * to length + 1 so we correct the match var. */ reqlength = length + 1; @@ -3474,11 +3502,12 @@ int TclStringCmp ( if (checkEq && (s1len != s2len)) { match = 1; /* This will be reversed below. */ - } else { + } else { /* - * The comparison function should compare up to the minimum - * byte length only. + * The comparison function should compare up to the minimum byte + * length only. */ + match = memCmpFn(s1, s2, (size_t) length); } if ((match == 0) && (reqlength > length)) { @@ -3486,7 +3515,7 @@ int TclStringCmp ( } match = (match > 0) ? 1 : (match < 0) ? -1 : 0; } - matchdone: + matchdone: return match; } @@ -3684,18 +3713,20 @@ static void ReverseBytes( unsigned char *to, /* Copy bytes into here... */ unsigned char *from, /* ...from here... */ - int count) /* Until this many are copied, */ + int count) /* Until this many are copied, */ /* reversing as you go. */ { unsigned char *src = from + count; + if (to == from) { /* Reversing in place */ while (--src > to) { unsigned char c = *src; + *src = *to; *to++ = c; } - } else { + } else { while (--src >= from) { *to++ = *src; } @@ -3744,7 +3775,10 @@ TclStringReverse( *to++ = *src; } } else { - /* Reversing in place */ + /* + * Reversing in place. + */ + while (--src > from) { ch = *src; *src = *from; @@ -3768,20 +3802,22 @@ TclStringReverse( /* * Either numChars == -1 and we don't know how many chars are * represented by objPtr->bytes and we need Pass 1 just in case, - * or numChars >= 0 and we know we have fewer chars than bytes, - * so we know there's a multibyte character needing Pass 1. + * or numChars >= 0 and we know we have fewer chars than bytes, so + * we know there's a multibyte character needing Pass 1. * * Pass 1. Reverse the bytes of each multi-byte character. */ + int charCount = 0; int bytesLeft = numBytes; while (bytesLeft) { /* - * NOTE: We know that the from buffer is NUL-terminated. - * It's part of the contract for objPtr->bytes values. - * Thus, we can skip calling Tcl_UtfCharComplete() here. + * NOTE: We know that the from buffer is NUL-terminated. It's + * part of the contract for objPtr->bytes values. Thus, we can + * skip calling Tcl_UtfCharComplete() here. */ + int bytesInChar = TclUtfToUniChar(from, &ch); ReverseBytes((unsigned char *)to, (unsigned char *)from, @@ -3811,19 +3847,18 @@ TclStringReverse( * * The result is a concatenation of a prefix from objPtr, characters * 0 through first-1, the insertPtr string value, and a suffix from - * objPtr, characters from first + count to the end. The effect is - * as if the inner substring of characters first through first+count-1 - * are removed and replaced with insertPtr. - * If insertPtr is NULL, it is treated as an empty string. - * When passed the flag TCL_STRING_IN_PLACE, this routine will try - * to do the work within objPtr, so long as no sharing forbids it. - * Without that request, or as needed, a new Tcl value will be allocated - * to be the result. + * objPtr, characters from first + count to the end. The effect is as if + * the inner substring of characters first through first+count-1 are + * removed and replaced with insertPtr. If insertPtr is NULL, it is + * treated as an empty string. When passed the flag TCL_STRING_IN_PLACE, + * this routine will try to do the work within objPtr, so long as no + * sharing forbids it. Without that request, or as needed, a new Tcl + * value will be allocated to be the result. * * Results: - * A Tcl value that is the result of the substring replacement. - * May return NULL in case of an error. When NULL is returned and - * interp is non-NULL, error information is left in interp + * A Tcl value that is the result of the substring replacement. May + * return NULL in case of an error. When NULL is returned and interp is + * non-NULL, error information is left in interp * *--------------------------------------------------------------------------- */ diff --git a/generic/tclVar.c b/generic/tclVar.c index f22815c..d5e0fa1 100644 --- a/generic/tclVar.c +++ b/generic/tclVar.c @@ -60,14 +60,12 @@ VarHashCreateVar( Tcl_Obj *key, int *newPtr) { - Tcl_HashEntry *hPtr = Tcl_CreateHashEntry(&tablePtr->table, - key, newPtr); + Tcl_HashEntry *hPtr = Tcl_CreateHashEntry(&tablePtr->table, key, newPtr); - if (hPtr) { - return VarHashGetValue(hPtr); - } else { + if (!hPtr) { return NULL; } + return VarHashGetValue(hPtr); } #define VarHashFindVar(tablePtr, key) \ @@ -92,11 +90,10 @@ VarHashFirstVar( { Tcl_HashEntry *hPtr = VarHashFirstEntry(tablePtr, searchPtr); - if (hPtr) { - return VarHashGetValue(hPtr); - } else { + if (!hPtr) { return NULL; } + return VarHashGetValue(hPtr); } static inline Var * @@ -105,11 +102,10 @@ VarHashNextVar( { Tcl_HashEntry *hPtr = VarHashNextEntry(searchPtr); - if (hPtr) { - return VarHashGetValue(hPtr); - } else { + if (!hPtr) { return NULL; } + return VarHashGetValue(hPtr); } #define VarHashGetKey(varPtr) \ @@ -174,10 +170,14 @@ typedef struct ArraySearch { static void AppendLocals(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *patternPtr, int includeLinks); -static void ArrayPopulateSearch(Tcl_Interp *interp, Tcl_Obj *arrayNameObj, Var *varPtr, ArraySearch *searchPtr); -static void ArrayDoneSearch (Interp *iPtr, Var *varPtr, ArraySearch *searchPtr); +static void ArrayPopulateSearch(Tcl_Interp *interp, + Tcl_Obj *arrayNameObj, Var *varPtr, + ArraySearch *searchPtr); +static void ArrayDoneSearch(Interp *iPtr, Var *varPtr, + ArraySearch *searchPtr); static Tcl_NRPostProc ArrayForLoopCallback; -static int ArrayForNRCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv); +static int ArrayForNRCmd(ClientData dummy, Tcl_Interp *interp, + int objc, Tcl_Obj *const *objv); static void DeleteSearches(Interp *iPtr, Var *arrayVarPtr); static void DeleteArray(Interp *iPtr, Tcl_Obj *arrayNamePtr, Var *varPtr, int flags, int index); @@ -322,7 +322,8 @@ CleanupVar( { if (TclIsVarUndefined(varPtr) && TclIsVarInHash(varPtr) && !TclIsVarTraced(varPtr) - && (VarHashRefCount(varPtr) == (unsigned)!TclIsVarDeadHash(varPtr))) { + && (VarHashRefCount(varPtr) == (unsigned) + !TclIsVarDeadHash(varPtr))) { if (VarHashRefCount(varPtr) == 0) { ckfree(varPtr); } else { @@ -331,7 +332,8 @@ CleanupVar( } if (arrayPtr != NULL && TclIsVarUndefined(arrayPtr) && TclIsVarInHash(arrayPtr) && !TclIsVarTraced(arrayPtr) && - (VarHashRefCount(arrayPtr) == (unsigned)!TclIsVarDeadHash(arrayPtr))) { + (VarHashRefCount(arrayPtr) == (unsigned) + !TclIsVarDeadHash(arrayPtr))) { if (VarHashRefCount(arrayPtr) == 0) { ckfree(arrayPtr); } else { @@ -607,7 +609,6 @@ TclObjLookupVarEx( } if (!parsed) { - /* * part1Ptr is possibly an unparsed array element. */ @@ -615,12 +616,11 @@ TclObjLookupVarEx( int len; const char *part1 = TclGetStringFromObj(part1Ptr, &len); - if (len > 1 && (part1[len - 1] == ')')) { + if ((len > 1) && (part1[len - 1] == ')')) { + const char *part2 = strchr(part1, '('); - const char *part2 = strchr(part1, '('); - - if (part2) { - Tcl_Obj *arrayPtr; + if (part2) { + Tcl_Obj *arrayPtr; if (part2Ptr != NULL) { if (flags & TCL_LEAVE_ERR_MSG) { @@ -632,19 +632,20 @@ TclObjLookupVarEx( return NULL; } - arrayPtr = Tcl_NewStringObj(part1, (part2 - part1)); - part2Ptr = Tcl_NewStringObj(part2 + 1, len - (part2 - part1) - 2); + arrayPtr = Tcl_NewStringObj(part1, (part2 - part1)); + part2Ptr = Tcl_NewStringObj(part2 + 1, + len - (part2 - part1) - 2); - TclFreeIntRep(part1Ptr); + TclFreeIntRep(part1Ptr); - Tcl_IncrRefCount(arrayPtr); - part1Ptr->internalRep.twoPtrValue.ptr1 = arrayPtr; - Tcl_IncrRefCount(part2Ptr); - part1Ptr->internalRep.twoPtrValue.ptr2 = part2Ptr; - part1Ptr->typePtr = &tclParsedVarNameType; + Tcl_IncrRefCount(arrayPtr); + part1Ptr->internalRep.twoPtrValue.ptr1 = arrayPtr; + Tcl_IncrRefCount(part2Ptr); + part1Ptr->internalRep.twoPtrValue.ptr2 = part2Ptr; + part1Ptr->typePtr = &tclParsedVarNameType; - part1Ptr = arrayPtr; - } + part1Ptr = arrayPtr; + } } } @@ -674,6 +675,7 @@ TclObjLookupVarEx( /* * An indexed local variable. */ + Tcl_Obj *cachedNamePtr = localName(varFramePtr, index); part1Ptr->typePtr = &localVarNameType; @@ -682,7 +684,7 @@ TclObjLookupVarEx( Tcl_IncrRefCount(cachedNamePtr); if (cachedNamePtr->typePtr != &localVarNameType || cachedNamePtr->internalRep.twoPtrValue.ptr1 != NULL) { - TclFreeIntRep(cachedNamePtr); + TclFreeIntRep(cachedNamePtr); } } else { part1Ptr->internalRep.twoPtrValue.ptr1 = NULL; @@ -877,38 +879,41 @@ TclLookupSimpleVar( if (varPtr == NULL) { Tcl_Obj *tailPtr; - if (create) { /* Var wasn't found so create it. */ - TclGetNamespaceForQualName(interp, varName, cxtNsPtr, - flags, &varNsPtr, &dummy1Ptr, &dummy2Ptr, &tail); - if (varNsPtr == NULL) { - *errMsgPtr = badNamespace; - return NULL; - } else if (tail == NULL) { - *errMsgPtr = missingName; - return NULL; - } - if (tail != varName) { - tailPtr = Tcl_NewStringObj(tail, -1); - } else { - tailPtr = varNamePtr; - } - varPtr = VarHashCreateVar(&varNsPtr->varTable, tailPtr, - &isNew); - if (lookGlobal) { - /* - * The variable was created starting from the global - * namespace: a global reference is returned even if it - * wasn't explicitly requested. - */ - - *indexPtr = -1; - } else { - *indexPtr = -2; - } - } else { /* Var wasn't found and not to create it. */ + if (!create) { /* Var wasn't found and not to create it. */ *errMsgPtr = noSuchVar; return NULL; } + + /* + * Var wasn't found so create it. + */ + + TclGetNamespaceForQualName(interp, varName, cxtNsPtr, flags, + &varNsPtr, &dummy1Ptr, &dummy2Ptr, &tail); + if (varNsPtr == NULL) { + *errMsgPtr = badNamespace; + return NULL; + } else if (tail == NULL) { + *errMsgPtr = missingName; + return NULL; + } + if (tail != varName) { + tailPtr = Tcl_NewStringObj(tail, -1); + } else { + tailPtr = varNamePtr; + } + varPtr = VarHashCreateVar(&varNsPtr->varTable, tailPtr, &isNew); + if (lookGlobal) { + /* + * The variable was created starting from the global + * namespace: a global reference is returned even if it wasn't + * explicitly requested. + */ + + *indexPtr = -1; + } else { + *indexPtr = -2; + } } } else { /* Local var: look in frame varFramePtr. */ int localLen, localCt = varFramePtr->numCompiledLocals; @@ -2167,7 +2172,6 @@ TclPtrIncrObjVarIdx( } else { /* Unshared - can Incr in place */ if (TCL_OK == TclIncrObj(interp, varValuePtr, incrPtr)) { - /* * This seems dumb to write the incremeted value into the var * after we just adjusted the value in place, but the spec for @@ -2909,27 +2913,24 @@ Tcl_LappendObjCmd( /* *---------------------------------------------------------------------- * - * ArrayForObjCmd - * ArrayForNRCmd - * ArrayForLoopCallback - * ArrayObjNext + * ArrayForObjCmd, ArrayForNRCmd, ArrayForLoopCallback, ArrayObjNext -- * - * These functions implement the "array for" Tcl command. - * array for {k v} a {} - * The array for command iterates over the array, setting the - * the specified loop variables, and executing the body each iteration. + * These functions implement the "array for" Tcl command. + * array for {k v} a {} + * The array for command iterates over the array, setting the the + * specified loop variables, and executing the body each iteration. * - * ArrayForObjCmd() is the standard wrapper around ArrayForNRCmd(). + * ArrayForObjCmd() is the standard wrapper around ArrayForNRCmd(). * - * ArrayForNRCmd() sets up the ArraySearch structure, sets arrayNamePtr - * inside the structure and calls VarHashFirstEntry to start the hash - * iteration. + * ArrayForNRCmd() sets up the ArraySearch structure, sets arrayNamePtr + * inside the structure and calls VarHashFirstEntry to start the hash + * iteration. * - * ArrayForNRCmd() does not execute the body or set the loop variables, - * it only initializes the iterator. + * ArrayForNRCmd() does not execute the body or set the loop variables, + * it only initializes the iterator. * - * ArrayForLoopCallback() iterates over the entire array, executing - * the body each time. + * ArrayForLoopCallback() iterates over the entire array, executing the + * body each time. * *---------------------------------------------------------------------- */ @@ -2937,39 +2938,39 @@ Tcl_LappendObjCmd( static int ArrayObjNext( Tcl_Interp *interp, - Tcl_Obj *arrayNameObj, /* array */ - Var *varPtr, /* array */ + Tcl_Obj *arrayNameObj, /* array */ + Var *varPtr, /* array */ ArraySearch *searchPtr, Tcl_Obj **keyPtrPtr, /* Pointer to a variable to have the key * written into, or NULL. */ - Tcl_Obj **valuePtrPtr /* Pointer to a variable to have the + Tcl_Obj **valuePtrPtr) /* Pointer to a variable to have the * value written into, or NULL.*/ - ) { Tcl_Obj *keyObj; Tcl_Obj *valueObj = NULL; - int gotValue; - int donerc; + int gotValue; + int donerc; donerc = TCL_BREAK; if ((varPtr->flags & VAR_SEARCH_ACTIVE) != VAR_SEARCH_ACTIVE) { - donerc = TCL_ERROR; - return donerc; + donerc = TCL_ERROR; + return donerc; } gotValue = 0; while (1) { Tcl_HashEntry *hPtr = searchPtr->nextEntry; - if (hPtr != NULL) { - searchPtr->nextEntry = NULL; - } else { - hPtr = Tcl_NextHashEntry(&searchPtr->search); - if (hPtr == NULL) { - gotValue = 0; - break; - } - } + + if (hPtr != NULL) { + searchPtr->nextEntry = NULL; + } else { + hPtr = Tcl_NextHashEntry(&searchPtr->search); + if (hPtr == NULL) { + gotValue = 0; + break; + } + } varPtr = VarHashGetValue(hPtr); if (!TclIsVarUndefined(varPtr)) { gotValue = 1; @@ -2977,7 +2978,7 @@ ArrayObjNext( } } - if (! gotValue) { + if (!gotValue) { return donerc; } @@ -2985,8 +2986,8 @@ ArrayObjNext( keyObj = VarHashGetKey(varPtr); *keyPtrPtr = keyObj; - valueObj = Tcl_ObjGetVar2(interp, arrayNameObj, - keyObj, TCL_LEAVE_ERR_MSG); + valueObj = Tcl_ObjGetVar2(interp, arrayNameObj, keyObj, + TCL_LEAVE_ERR_MSG); *valuePtrPtr = valueObj; return donerc; @@ -3019,8 +3020,7 @@ ArrayForNRCmd( */ if (objc != 4) { - Tcl_WrongNumArgs(interp, 1, objv, - "{key value} arrayName script"); + Tcl_WrongNumArgs(interp, 1, objv, "{key value} arrayName script"); return TCL_ERROR; } @@ -3054,7 +3054,7 @@ ArrayForNRCmd( */ searchPtr = ckalloc(sizeof(ArraySearch)); - ArrayPopulateSearch (interp, arrayNameObj, varPtr, searchPtr); + ArrayPopulateSearch(interp, arrayNameObj, varPtr, searchPtr); /* * Make sure that these objects (which we need throughout the body of the @@ -3120,35 +3120,37 @@ ArrayForLoopCallback( varPtr = TclObjLookupVarEx(interp, arrayNameObj, NULL, /*flags*/ 0, /*msg*/ 0, /*createPart1*/ 0, /*createPart2*/ 0, &arrayPtr); if (varPtr == NULL) { - done = TCL_ERROR; + done = TCL_ERROR; } else { - done = ArrayObjNext (interp, arrayNameObj, varPtr, - searchPtr, &keyObj, &valueObj); + done = ArrayObjNext(interp, arrayNameObj, varPtr, searchPtr, &keyObj, + &valueObj); } result = TCL_OK; if (done != TCL_CONTINUE) { Tcl_ResetResult(interp); - if (done == TCL_ERROR) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "array changed during iteration", -1)); - Tcl_SetErrorCode(interp, "TCL", "READ", "array", "for", NULL); - varPtr->flags |= TCL_LEAVE_ERR_MSG; - result = done; - } + if (done == TCL_ERROR) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "array changed during iteration", -1)); + Tcl_SetErrorCode(interp, "TCL", "READ", "array", "for", NULL); + varPtr->flags |= TCL_LEAVE_ERR_MSG; + result = done; + } goto arrayfordone; } Tcl_ListObjGetElements(NULL, varListObj, &varc, &varv); - if (Tcl_ObjSetVar2(interp, varv[0], NULL, keyObj, TCL_LEAVE_ERR_MSG) == NULL) { - result = TCL_ERROR; - goto arrayfordone; + if (Tcl_ObjSetVar2(interp, varv[0], NULL, keyObj, + TCL_LEAVE_ERR_MSG) == NULL) { + result = TCL_ERROR; + goto arrayfordone; } if (valueObj != NULL) { - if (Tcl_ObjSetVar2(interp, varv[1], NULL, valueObj, TCL_LEAVE_ERR_MSG) == NULL) { - result = TCL_ERROR; - goto arrayfordone; - } + if (Tcl_ObjSetVar2(interp, varv[1], NULL, valueObj, + TCL_LEAVE_ERR_MSG) == NULL) { + result = TCL_ERROR; + goto arrayfordone; + } } /* @@ -3164,13 +3166,15 @@ ArrayForLoopCallback( */ arrayfordone: - /* if the search was terminated by an array change, the - * VAR_SEARCH_ACTIVE flag will no longer be set - */ if (done != TCL_ERROR) { - ArrayDoneSearch (iPtr, varPtr, searchPtr); + /* + * If the search was terminated by an array change, the + * VAR_SEARCH_ACTIVE flag will no longer be set. + */ + + ArrayDoneSearch(iPtr, varPtr, searchPtr); Tcl_DecrRefCount(searchPtr->name); - ckfree(searchPtr); + ckfree(searchPtr); } TclDecrRefCount(varListObj); @@ -3181,14 +3185,15 @@ ArrayForLoopCallback( /* * ArrayPopulateSearch */ + static void ArrayPopulateSearch( - Tcl_Interp *interp, - Tcl_Obj *arrayNameObj, - Var *varPtr, + Tcl_Interp *interp, + Tcl_Obj *arrayNameObj, + Var *varPtr, ArraySearch *searchPtr) { - Interp *iPtr = (Interp *)interp; + Interp *iPtr = (Interp *) interp; Tcl_HashEntry *hPtr; int isNew; @@ -3206,7 +3211,7 @@ ArrayPopulateSearch( &searchPtr->search); Tcl_SetHashValue(hPtr, searchPtr); searchPtr->name = Tcl_ObjPrintf("s-%d-%s", searchPtr->id, - TclGetString(arrayNameObj)); + TclGetString(arrayNameObj)); Tcl_IncrRefCount(searchPtr->name); } /* @@ -3258,7 +3263,7 @@ ArrayStartSearchCmd( */ searchPtr = ckalloc(sizeof(ArraySearch)); - ArrayPopulateSearch (interp, objv[1], varPtr, searchPtr); + ArrayPopulateSearch(interp, objv[1], varPtr, searchPtr); Tcl_SetObjResult(interp, searchPtr->name); return TCL_OK; } @@ -3268,12 +3273,12 @@ ArrayStartSearchCmd( * * ArrayDoneSearch -- * - * Removes the search from the hash of active searches. + * Removes the search from the hash of active searches. * *---------------------------------------------------------------------- */ static void -ArrayDoneSearch ( +ArrayDoneSearch( Interp *iPtr, Var *varPtr, ArraySearch *searchPtr) @@ -3288,7 +3293,7 @@ ArrayDoneSearch ( hPtr = Tcl_FindHashEntry(&iPtr->varSearches, varPtr); if (hPtr == NULL) { - return; + return; } if (searchPtr == Tcl_GetHashValue(hPtr)) { if (searchPtr->nextPtr) { @@ -3522,7 +3527,7 @@ ArrayDoneSearchCmd( return TCL_ERROR; } - ArrayDoneSearch (iPtr, varPtr, searchPtr); + ArrayDoneSearch(iPtr, varPtr, searchPtr); Tcl_DecrRefCount(searchPtr->name); ckfree(searchPtr); return TCL_OK; @@ -4034,7 +4039,8 @@ ArraySetCmd( if ((elemVarPtr == NULL) || (TclPtrSetVarIdx(interp, elemVarPtr, varPtr, arrayNameObj, - elemPtrs[i],elemPtrs[i+1],TCL_LEAVE_ERR_MSG,-1) == NULL)){ + elemPtrs[i], elemPtrs[i+1], TCL_LEAVE_ERR_MSG, + -1) == NULL)) { result = TCL_ERROR; break; } @@ -6024,7 +6030,7 @@ TclInfoVarsCmd( */ if ((nsPtr != globalNsPtr) && !specificNsInPattern) { - varPtr = VarHashFirstVar(&globalNsPtr->varTable,&search); + varPtr = VarHashFirstVar(&globalNsPtr->varTable, &search); while (varPtr) { if (!TclIsVarUndefined(varPtr) || TclIsVarNamespaceVar(varPtr)) { @@ -6408,9 +6414,9 @@ CompareVarKeys( /* * If the object pointers are the same then they match. * OPT: this comparison was moved to the caller - - if (objPtr1 == objPtr2) return 1; - */ + * + * if (objPtr1 == objPtr2) return 1; + */ /* * Don't use Tcl_GetStringFromObj as it would prevent l1 and l2 being in a diff --git a/unix/tclUnixFCmd.c b/unix/tclUnixFCmd.c index 8d1de2c..b6b3db2 100644 --- a/unix/tclUnixFCmd.c +++ b/unix/tclUnixFCmd.c @@ -2302,7 +2302,8 @@ winPathFromObj( } static const int attributeArray[] = { - 0x20, 0, 2, 0, 0, 1, 4}; + 0x20, 0, 2, 0, 0, 1, 4 +}; /* *---------------------------------------------------------------------- @@ -2339,8 +2340,8 @@ GetUnixFileAttributes( return TCL_ERROR; } - *attributePtrPtr = Tcl_NewIntObj((fileAttributes&attributeArray[objIndex])!=0); - + *attributePtrPtr = Tcl_NewIntObj( + (fileAttributes & attributeArray[objIndex]) != 0); return TCL_OK; } @@ -2397,7 +2398,7 @@ SetUnixFileAttributes( return TCL_ERROR; } - ckfree(winPath); + ckfree(winPath); return TCL_OK; } #elif defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE) @@ -2439,8 +2440,7 @@ GetUnixFileAttributes( return TCL_ERROR; } - *attributePtrPtr = Tcl_NewBooleanObj(statBuf.st_flags&UF_IMMUTABLE); - + *attributePtrPtr = Tcl_NewBooleanObj(statBuf.st_flags & UF_IMMUTABLE); return TCL_OK; } -- cgit v0.12 From 1f7ca2ff69e3ff8252937f385787336054c6fc11 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Sun, 13 May 2018 13:54:46 +0000 Subject: de-duplicate code in win32 panic implementation. Also eliminate gcc compiler warning. --- generic/tcl.h | 4 ++-- generic/tclPanic.c | 12 +++++------- win/tclWinError.c | 8 +------- win/tclWinFile.c | 14 ++------------ win/tclWinPanic.c | 2 +- 5 files changed, 11 insertions(+), 29 deletions(-) diff --git a/generic/tcl.h b/generic/tcl.h index 790fa12..20889e4 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -2208,9 +2208,9 @@ const char * Tcl_InitStubs(Tcl_Interp *interp, const char *version, const char * TclTomMathInitializeStubs(Tcl_Interp *interp, const char *version, int epoch, int revision); #if defined(_WIN32) - TCL_NORETURN void Tcl_ConsolePanic(const char *format, ...); + TCL_NORETURN1 void Tcl_ConsolePanic(const char *format, ...); #else -# define Tcl_ConsolePanic ((Tcl_PanicProc *)0) +# define Tcl_ConsolePanic NULL #endif #ifdef USE_TCL_STUBS diff --git a/generic/tclPanic.c b/generic/tclPanic.c index 8cdd8bf..07d8b19 100644 --- a/generic/tclPanic.c +++ b/generic/tclPanic.c @@ -15,7 +15,7 @@ #include "tclInt.h" #if defined(_WIN32) || defined(__CYGWIN__) - MODULE_SCOPE TCL_NORETURN void tclWinDebugPanic(const char *format, ...); + MODULE_SCOPE void tclWinDebugPanic(const char *format, ...); #endif /* @@ -96,25 +96,23 @@ Tcl_Panic( if (panicProc != NULL) { panicProc(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); } else { -#ifdef _WIN32 - tclWinDebugPanic(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); +#if defined(_WIN32) || defined(__CYGWIN__) + tclWinDebugPanic(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); #else fprintf(stderr, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); fprintf(stderr, "\n"); fflush(stderr); -#if defined(_WIN32) || defined(__CYGWIN__) +#endif # if defined(__GNUC__) __builtin_trap(); # elif defined(_WIN64) __debugbreak(); # elif defined(_MSC_VER) && defined (_M_IX86) _asm {int 3} -# else +# elif defined(_WIN32) DebugBreak(); # endif -#endif -#endif #if defined(_WIN32) ExitProcess(1); #else diff --git a/win/tclWinError.c b/win/tclWinError.c index 5d4423b..ac98cd4 100644 --- a/win/tclWinError.c +++ b/win/tclWinError.c @@ -381,7 +381,7 @@ TclWinConvertError( *---------------------------------------------------------------------- */ -TCL_NORETURN void +void tclWinDebugPanic( const char *format, ...) { @@ -413,12 +413,6 @@ tclWinDebugPanic( fprintf(stderr, "\n"); fflush(stderr); } -# if defined(__GNUC__) - __builtin_trap(); -# else - DebugBreak(); -# endif - abort(); } #endif /* diff --git a/win/tclWinFile.c b/win/tclWinFile.c index f7ac949..333c526 100644 --- a/win/tclWinFile.c +++ b/win/tclWinFile.c @@ -177,7 +177,7 @@ static int WinLink(const TCHAR *LinkSource, const TCHAR *LinkTarget, int linkAction); static int WinSymLinkDirectory(const TCHAR *LinkDirectory, const TCHAR *LinkTarget); -MODULE_SCOPE TCL_NORETURN void tclWinDebugPanic(const char *format, ...); +MODULE_SCOPE void tclWinDebugPanic(const char *format, ...); /* *-------------------------------------------------------------------- @@ -794,7 +794,7 @@ NativeWriteReparse( *---------------------------------------------------------------------- */ -TCL_NORETURN void +void tclWinDebugPanic( const char *format, ...) { @@ -824,16 +824,6 @@ tclWinDebugPanic( MessageBoxW(NULL, msgString, L"Fatal Error", MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND); } -#if defined(__GNUC__) - __builtin_trap(); -#elif defined(_WIN64) - __debugbreak(); -#elif defined(_MSC_VER) && defined (_M_IX86) - _asm {int 3} -#else - DebugBreak(); -#endif - ExitProcess(1); } /* diff --git a/win/tclWinPanic.c b/win/tclWinPanic.c index 0de7df2..3b9933c 100644 --- a/win/tclWinPanic.c +++ b/win/tclWinPanic.c @@ -28,7 +28,7 @@ *---------------------------------------------------------------------- */ -void +TCL_NORETURN1 void Tcl_ConsolePanic( const char *format, ...) { -- cgit v0.12 From eae621b1753a248fd1add5b5df1069199e783d2f Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 14 May 2018 19:14:40 +0000 Subject: Unbreak build when HAVE_FTS is not set. Move definitions of Tcl_DirEntry and TclDIR to tclWinPort.h, where it actually belongs --- generic/tclIntPlatDecls.h | 5 ----- unix/tclUnixFCmd.c | 2 +- win/tclWinPort.h | 3 +++ 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/generic/tclIntPlatDecls.h b/generic/tclIntPlatDecls.h index 5a3025a..4d2bd0a 100644 --- a/generic/tclIntPlatDecls.h +++ b/generic/tclIntPlatDecls.h @@ -13,11 +13,6 @@ #ifndef _TCLINTPLATDECLS #define _TCLINTPLATDECLS -#ifdef __WIN32__ -# define Tcl_DirEntry void -# define TclDIR void -#endif - #undef TCL_STORAGE_CLASS #ifdef BUILD_tcl # define TCL_STORAGE_CLASS DLLEXPORT diff --git a/unix/tclUnixFCmd.c b/unix/tclUnixFCmd.c index 0b79fb6..7360c32 100644 --- a/unix/tclUnixFCmd.c +++ b/unix/tclUnixFCmd.c @@ -920,7 +920,7 @@ TraverseUnixTree( #ifndef HAVE_FTS int numProcessed = 0; Tcl_DirEntry *dirEntPtr; - Tcl_Dir *dirPtr; + TclDIR *dirPtr; #else CONST char *paths[2] = {NULL, NULL}; FTS *fts = NULL; diff --git a/win/tclWinPort.h b/win/tclWinPort.h index b2bf1d7..0f7d1fa 100644 --- a/win/tclWinPort.h +++ b/win/tclWinPort.h @@ -474,4 +474,7 @@ typedef DWORD_PTR * PDWORD_PTR; # define LABEL_SECURITY_INFORMATION (0x00000010L) #endif +#define Tcl_DirEntry void +#define TclDIR void + #endif /* _TCLWINPORT */ -- cgit v0.12 From 4523d8df2c410219ea470d653d5851701fbc2ed2 Mon Sep 17 00:00:00 2001 From: dkf Date: Sat, 19 May 2018 11:26:13 +0000 Subject: Disable many warnings that are pointless in the stub library. Yes, it accesses deprecated fields, we know because we deprecated them. --- generic/tclStubInit.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c index be37bc0..5057b05 100644 --- a/generic/tclStubInit.c +++ b/generic/tclStubInit.c @@ -454,6 +454,15 @@ tellOld( MODULE_SCOPE const TclStubs tclStubs; MODULE_SCOPE const TclTomMathStubs tclTomMathStubs; +#ifdef __GNUC__ +/* + * The rest of this file shouldn't warn about deprecated functions; they're + * there because we intend them to be so and know that this file is OK to + * touch those fields. + */ +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + /* !BEGIN!: Do not edit below this line. */ static const TclIntStubs tclIntStubs = { -- cgit v0.12 From 708eadd19e5581da93b7d8e801ffe977e6e1376f Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 21 May 2018 08:12:51 +0000 Subject: Demonstrate how Tcl can build without TCL_THREADS defined at all (assuming TCL_THREADS=1 as default). Activated by -DTCL_NO_DEPRECATED=1. See also [eeddb0693a950be980a66de3811630a00c7bab54|eeddb0693a] --- generic/tcl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tcl.h b/generic/tcl.h index ff82bd6..7d6226b 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -89,11 +89,11 @@ extern "C" { # define JOIN(a,b) JOIN1(a,b) # define JOIN1(a,b) a##b #endif -#endif /* !TCL_NO_DEPRECATED */ #ifndef TCL_THREADS # define TCL_THREADS 1 #endif +#endif /* !TCL_NO_DEPRECATED */ /* * A special definition used to allow this header file to be included from -- cgit v0.12 From b729965a3c4258862bc075facb0291c0c765cd57 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 22 May 2018 20:10:21 +0000 Subject: Fix build with TCL_THREADS=0 on Linux/other without epoll or kqueu support. In that case, fallback to select notifier --- unix/tclEpollNotfy.c | 2 +- unix/tclKqueueNotfy.c | 2 +- unix/tclSelectNotfy.c | 2 +- unix/tclUnixNotfy.c | 21 ++++++++++----------- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/unix/tclEpollNotfy.c b/unix/tclEpollNotfy.c index 076e02b..3059643 100644 --- a/unix/tclEpollNotfy.c +++ b/unix/tclEpollNotfy.c @@ -12,7 +12,7 @@ * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#ifdef NOTIFIER_EPOLL +#if defined(NOTIFIER_EPOLL) && (!defined(TCL_THREADS) || TCL_THREADS) #define _GNU_SOURCE /* For pipe2(2) */ #include "tclInt.h" diff --git a/unix/tclKqueueNotfy.c b/unix/tclKqueueNotfy.c index 049829e..3fddeea 100644 --- a/unix/tclKqueueNotfy.c +++ b/unix/tclKqueueNotfy.c @@ -13,7 +13,7 @@ * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#ifdef NOTIFIER_KQUEUE +#if defined(NOTIFIER_KQUEUE) && (!defined(TCL_THREADS) || TCL_THREADS) #include "tclInt.h" #ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is diff --git a/unix/tclSelectNotfy.c b/unix/tclSelectNotfy.c index 4bdfaef..3172d6a 100644 --- a/unix/tclSelectNotfy.c +++ b/unix/tclSelectNotfy.c @@ -11,7 +11,7 @@ * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#if !defined(NOTIFIER_EPOLL) && !defined(NOTIFIER_KQUEUE) +#if (!defined(NOTIFIER_EPOLL) && !defined(NOTIFIER_KQUEUE)) || (defined(TCL_THREADS) && !TCL_THREADS) #include "tclInt.h" #ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is diff --git a/unix/tclUnixNotfy.c b/unix/tclUnixNotfy.c index ccae39b..6572b39 100644 --- a/unix/tclUnixNotfy.c +++ b/unix/tclUnixNotfy.c @@ -17,24 +17,24 @@ * Static routines defined in this file. */ -#ifdef NOTIFIER_SELECT -#if !defined(TCL_THREADS) || TCL_THREADS +static int FileHandlerEventProc(Tcl_Event *evPtr, int flags); +#if defined(TCL_THREADS) && !TCL_THREADS +# undef NOTIFIER_EPOLL +# undef NOTIFIER_KQUEUE +# define NOTIFIER_SELECT +#elif !defined(NOTIFIER_EPOLL) && !defined(NOTIFIER_KQUEUE) +# define NOTIFIER_SELECT static TCL_NORETURN void NotifierThreadProc(ClientData clientData); -#if defined(HAVE_PTHREAD_ATFORK) +# if defined(HAVE_PTHREAD_ATFORK) static void AtForkChild(void); -#endif /* HAVE_PTHREAD_ATFORK */ -#endif /* TCL_THREADS */ -#endif /* NOTIFIER_SELECT */ -static int FileHandlerEventProc(Tcl_Event *evPtr, int flags); +# endif /* HAVE_PTHREAD_ATFORK */ -#ifdef NOTIFIER_SELECT -#if !defined(TCL_THREADS) || TCL_THREADS /* *---------------------------------------------------------------------- * * StartNotifierThread -- * - * Start a notfier thread and wait for the notifier pipe to be created. + * Start a notifier thread and wait for the notifier pipe to be created. * * Results: * None. @@ -70,7 +70,6 @@ StartNotifierThread(const char *proc) pthread_mutex_unlock(¬ifierInitMutex); } } -#endif /* TCL_THREADS */ #endif /* NOTIFIER_SELECT */ /* -- cgit v0.12 From f6af18a9476f566a34901b828e33f7141266174c Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 22 May 2018 20:12:03 +0000 Subject: More removals of TCL_THREADS usage (configure scripts/win makefiles) --- unix/configure | 100 ++++++++++++++++++++------------------------------- unix/configure.ac | 57 ++++++++++++++--------------- unix/tcl.m4 | 53 +++++++++++---------------- unix/tclConfig.h.in | 3 -- unix/tclConfig.sh.in | 3 -- win/makefile.vc | 3 -- win/rules.vc | 18 +++++----- win/tclConfig.sh.in | 4 --- 8 files changed, 95 insertions(+), 146 deletions(-) diff --git a/unix/configure b/unix/configure index 4e3e06f..cb3116d 100755 --- a/unix/configure +++ b/unix/configure @@ -4976,7 +4976,7 @@ fi fi case $system in AIX-*) - if test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"; then : + if test "$GCC" != "yes"; then : # AIX requires the _r compiler when gcc isn't being used case "${CC}" in @@ -5178,9 +5178,6 @@ $as_echo "$ac_cv_cygwin" >&6; } if test "$ac_cv_cygwin" = "no"; then as_fn_error $? "${CC} is not a cygwin compiler." "$LINENO" 5 fi - if test "x${TCL_THREADS}" = "x0"; then - as_fn_error $? "CYGWIN compile is only supported with --enable-threads" "$LINENO" 5 - fi do64bit_ok=yes if test "x${SHARED_BUILD}" = "x1"; then echo "running cd ../win; ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args" @@ -5627,14 +5624,10 @@ fi SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}' LDFLAGS="-Wl,-export-dynamic" CFLAGS_OPTIMIZE="-O2" - if test "${TCL_THREADS}" = "1"; then : - - # On OpenBSD: Compile with -pthread - # Don't link with -lpthread - LIBS=`echo $LIBS | sed s/-lpthread//` - CFLAGS="$CFLAGS -pthread" - -fi + # On OpenBSD: Compile with -pthread + # Don't link with -lpthread + LIBS=`echo $LIBS | sed s/-lpthread//` + CFLAGS="$CFLAGS -pthread" # OpenBSD doesn't do version numbers with dots. UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots @@ -5652,14 +5645,10 @@ fi CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' fi LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} - if test "${TCL_THREADS}" = "1"; then : - - # The -pthread needs to go in the CFLAGS, not LIBS - LIBS=`echo $LIBS | sed s/-pthread//` - CFLAGS="$CFLAGS -pthread" - LDFLAGS="$LDFLAGS -pthread" - -fi + # The -pthread needs to go in the CFLAGS, not LIBS + LIBS=`echo $LIBS | sed s/-pthread//` + CFLAGS="$CFLAGS -pthread" + LDFLAGS="$LDFLAGS -pthread" ;; FreeBSD-*) # This configuration from FreeBSD Ports. @@ -5675,13 +5664,10 @@ fi CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' fi - if test "${TCL_THREADS}" = "1"; then : - - # The -pthread needs to go in the LDFLAGS, not LIBS - LIBS=`echo $LIBS | sed s/-pthread//` - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - LDFLAGS="$LDFLAGS $PTHREAD_LIBS" -fi + # The -pthread needs to go in the LDFLAGS, not LIBS + LIBS=`echo $LIBS | sed s/-pthread//` + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LDFLAGS="$LDFLAGS $PTHREAD_LIBS" case $system in FreeBSD-3.*) # Version numbers are dot-stripped by system policy. @@ -6043,21 +6029,17 @@ else CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee" fi # see pthread_intro(3) for pthread support on osf1, k.furukawa - if test "${TCL_THREADS}" = 1; then : - - CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE" - CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64" - LIBS=`echo $LIBS | sed s/-lpthreads//` - if test "$GCC" = yes; then : + CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE" + CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64" + LIBS=`echo $LIBS | sed s/-lpthreads//` + if test "$GCC" = yes; then : - LIBS="$LIBS -lpthread -lmach -lexc" + LIBS="$LIBS -lpthread -lmach -lexc" else - CFLAGS="$CFLAGS -pthread" - LDFLAGS="$LDFLAGS -pthread" - -fi + CFLAGS="$CFLAGS -pthread" + LDFLAGS="$LDFLAGS -pthread" fi ;; @@ -7316,7 +7298,7 @@ $as_echo "#define NO_UNAME 1" >>confdefs.h fi -if test "`uname -s`" = "Darwin" && test "${TCL_THREADS}" = 1 && \ +if test "`uname -s`" = "Darwin" && \ test "`uname -r | awk -F. '{print $1}'`" -lt 7; then # prior to Darwin 7, realpath is not threadsafe, so don't # use it when threads are enabled, c.f. bug # 711232 @@ -7439,8 +7421,7 @@ fi # Look for thread-safe variants of some library functions. #-------------------------------------------------------------------- -if test "${TCL_THREADS}" = 1; then - ac_fn_c_check_func "$LINENO" "getpwuid_r" "ac_cv_func_getpwuid_r" +ac_fn_c_check_func "$LINENO" "getpwuid_r" "ac_cv_func_getpwuid_r" if test "x$ac_cv_func_getpwuid_r" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getpwuid_r with 5 args" >&5 @@ -7536,7 +7517,7 @@ $as_echo "#define HAVE_GETPWUID_R 1" >>confdefs.h fi - ac_fn_c_check_func "$LINENO" "getpwnam_r" "ac_cv_func_getpwnam_r" +ac_fn_c_check_func "$LINENO" "getpwnam_r" "ac_cv_func_getpwnam_r" if test "x$ac_cv_func_getpwnam_r" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getpwnam_r with 5 args" >&5 @@ -7632,7 +7613,7 @@ $as_echo "#define HAVE_GETPWNAM_R 1" >>confdefs.h fi - ac_fn_c_check_func "$LINENO" "getgrgid_r" "ac_cv_func_getgrgid_r" +ac_fn_c_check_func "$LINENO" "getgrgid_r" "ac_cv_func_getgrgid_r" if test "x$ac_cv_func_getgrgid_r" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getgrgid_r with 5 args" >&5 @@ -7728,7 +7709,7 @@ $as_echo "#define HAVE_GETGRGID_R 1" >>confdefs.h fi - ac_fn_c_check_func "$LINENO" "getgrnam_r" "ac_cv_func_getgrnam_r" +ac_fn_c_check_func "$LINENO" "getgrnam_r" "ac_cv_func_getgrnam_r" if test "x$ac_cv_func_getgrnam_r" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getgrnam_r with 5 args" >&5 @@ -7824,11 +7805,11 @@ $as_echo "#define HAVE_GETGRNAM_R 1" >>confdefs.h fi - if test "`uname -s`" = "Darwin" && \ - test "`uname -r | awk -F. '{print $1}'`" -gt 5; then - # Starting with Darwin 6 (Mac OSX 10.2), gethostbyX - # are actually MT-safe as they always return pointers - # from TSD instead of static storage. +if test "`uname -s`" = "Darwin" && \ + test "`uname -r | awk -F. '{print $1}'`" -gt 5; then + # Starting with Darwin 6 (Mac OSX 10.2), gethostbyX + # are actually MT-safe as they always return pointers + # from TSD instead of static storage. $as_echo "#define HAVE_MTSAFE_GETHOSTBYNAME 1" >>confdefs.h @@ -7836,11 +7817,11 @@ $as_echo "#define HAVE_MTSAFE_GETHOSTBYNAME 1" >>confdefs.h $as_echo "#define HAVE_MTSAFE_GETHOSTBYADDR 1" >>confdefs.h - elif test "`uname -s`" = "HP-UX" && \ - test "`uname -r|sed -e 's|B\.||' -e 's|\..*$||'`" -gt 10; then - # Starting with HPUX 11.00 (we believe), gethostbyX - # are actually MT-safe as they always return pointers - # from TSD instead of static storage. +elif test "`uname -s`" = "HP-UX" && \ + test "`uname -r|sed -e 's|B\.||' -e 's|\..*$||'`" -gt 10; then + # Starting with HPUX 11.00 (we believe), gethostbyX + # are actually MT-safe as they always return pointers + # from TSD instead of static storage. $as_echo "#define HAVE_MTSAFE_GETHOSTBYNAME 1" >>confdefs.h @@ -7848,8 +7829,8 @@ $as_echo "#define HAVE_MTSAFE_GETHOSTBYNAME 1" >>confdefs.h $as_echo "#define HAVE_MTSAFE_GETHOSTBYADDR 1" >>confdefs.h - else - ac_fn_c_check_func "$LINENO" "gethostbyname_r" "ac_cv_func_gethostbyname_r" +else + ac_fn_c_check_func "$LINENO" "gethostbyname_r" "ac_cv_func_gethostbyname_r" if test "x$ac_cv_func_gethostbyname_r" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname_r with 6 args" >&5 @@ -7986,7 +7967,7 @@ $as_echo "#define HAVE_GETHOSTBYNAME_R 1" >>confdefs.h fi - ac_fn_c_check_func "$LINENO" "gethostbyaddr_r" "ac_cv_func_gethostbyaddr_r" + ac_fn_c_check_func "$LINENO" "gethostbyaddr_r" "ac_cv_func_gethostbyaddr_r" if test "x$ac_cv_func_gethostbyaddr_r" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyaddr_r with 7 args" >&5 @@ -8088,7 +8069,6 @@ $as_echo "#define HAVE_GETHOSTBYADDR_R 1" >>confdefs.h fi - fi fi #--------------------------------------------------------------------------- @@ -8280,10 +8260,6 @@ fi;; { $as_echo "$as_me:${as_lineno-$LINENO}: result: OSX" >&5 $as_echo "OSX" >&6; };; *) - cat >>confdefs.h <<_ACEOF -#define NOTIFIER_SELECT 1 -_ACEOF - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; };; esac diff --git a/unix/configure.ac b/unix/configure.ac index 5b982e8..609312b 100644 --- a/unix/configure.ac +++ b/unix/configure.ac @@ -209,7 +209,7 @@ AC_CHECK_FUNC(getwd, , [AC_DEFINE(NO_GETWD, 1, [Do we have getwd()])]) AC_CHECK_FUNC(wait3, , [AC_DEFINE(NO_WAIT3, 1, [Do we have wait3()])]) AC_CHECK_FUNC(uname, , [AC_DEFINE(NO_UNAME, 1, [Do we have uname()])]) -if test "`uname -s`" = "Darwin" && test "${TCL_THREADS}" = 1 && \ +if test "`uname -s`" = "Darwin" && \ test "`uname -r | awk -F. '{print [$]1}'`" -lt 7; then # prior to Darwin 7, realpath is not threadsafe, so don't # use it when threads are enabled, c.f. bug # 711232 @@ -223,35 +223,33 @@ SC_TCL_IPV6 # Look for thread-safe variants of some library functions. #-------------------------------------------------------------------- -if test "${TCL_THREADS}" = 1; then - SC_TCL_GETPWUID_R - SC_TCL_GETPWNAM_R - SC_TCL_GETGRGID_R - SC_TCL_GETGRNAM_R - if test "`uname -s`" = "Darwin" && \ - test "`uname -r | awk -F. '{print [$]1}'`" -gt 5; then - # Starting with Darwin 6 (Mac OSX 10.2), gethostbyX - # are actually MT-safe as they always return pointers - # from TSD instead of static storage. - AC_DEFINE(HAVE_MTSAFE_GETHOSTBYNAME, 1, - [Do we have MT-safe gethostbyname() ?]) - AC_DEFINE(HAVE_MTSAFE_GETHOSTBYADDR, 1, - [Do we have MT-safe gethostbyaddr() ?]) - - elif test "`uname -s`" = "HP-UX" && \ - test "`uname -r|sed -e 's|B\.||' -e 's|\..*$||'`" -gt 10; then - # Starting with HPUX 11.00 (we believe), gethostbyX - # are actually MT-safe as they always return pointers - # from TSD instead of static storage. - AC_DEFINE(HAVE_MTSAFE_GETHOSTBYNAME, 1, - [Do we have MT-safe gethostbyname() ?]) - AC_DEFINE(HAVE_MTSAFE_GETHOSTBYADDR, 1, - [Do we have MT-safe gethostbyaddr() ?]) +SC_TCL_GETPWUID_R +SC_TCL_GETPWNAM_R +SC_TCL_GETGRGID_R +SC_TCL_GETGRNAM_R +if test "`uname -s`" = "Darwin" && \ + test "`uname -r | awk -F. '{print [$]1}'`" -gt 5; then + # Starting with Darwin 6 (Mac OSX 10.2), gethostbyX + # are actually MT-safe as they always return pointers + # from TSD instead of static storage. + AC_DEFINE(HAVE_MTSAFE_GETHOSTBYNAME, 1, + [Do we have MT-safe gethostbyname() ?]) + AC_DEFINE(HAVE_MTSAFE_GETHOSTBYADDR, 1, + [Do we have MT-safe gethostbyaddr() ?]) + +elif test "`uname -s`" = "HP-UX" && \ + test "`uname -r|sed -e 's|B\.||' -e 's|\..*$||'`" -gt 10; then + # Starting with HPUX 11.00 (we believe), gethostbyX + # are actually MT-safe as they always return pointers + # from TSD instead of static storage. + AC_DEFINE(HAVE_MTSAFE_GETHOSTBYNAME, 1, + [Do we have MT-safe gethostbyname() ?]) + AC_DEFINE(HAVE_MTSAFE_GETHOSTBYADDR, 1, + [Do we have MT-safe gethostbyaddr() ?]) - else - SC_TCL_GETHOSTBYNAME_R - SC_TCL_GETHOSTBYADDR_R - fi +else + SC_TCL_GETHOSTBYNAME_R + SC_TCL_GETHOSTBYADDR_R fi #--------------------------------------------------------------------------- @@ -321,7 +319,6 @@ case x`uname -s` in # of wider impact). AC_MSG_RESULT([OSX]);; *) - AC_DEFINE_UNQUOTED(NOTIFIER_SELECT) AC_MSG_RESULT([none]);; esac diff --git a/unix/tcl.m4 b/unix/tcl.m4 index 70f3c3d..aaf5835 100644 --- a/unix/tcl.m4 +++ b/unix/tcl.m4 @@ -994,7 +994,7 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [ AS_IF([test "x${SHLIB_VERSION}" = x], [SHLIB_VERSION="1.0"]) case $system in AIX-*) - AS_IF([test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"], [ + AS_IF([test "$GCC" != "yes"], [ # AIX requires the _r compiler when gcc isn't being used case "${CC}" in *_r|*_r\ *) @@ -1115,9 +1115,6 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [ if test "$ac_cv_cygwin" = "no"; then AC_MSG_ERROR([${CC} is not a cygwin compiler.]) fi - if test "x${TCL_THREADS}" = "x0"; then - AC_MSG_ERROR([CYGWIN compile is only supported with --enable-threads]) - fi do64bit_ok=yes if test "x${SHARED_BUILD}" = "x1"; then echo "running cd ../win; ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args" @@ -1347,12 +1344,10 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}' LDFLAGS="-Wl,-export-dynamic" CFLAGS_OPTIMIZE="-O2" - AS_IF([test "${TCL_THREADS}" = "1"], [ - # On OpenBSD: Compile with -pthread - # Don't link with -lpthread - LIBS=`echo $LIBS | sed s/-lpthread//` - CFLAGS="$CFLAGS -pthread" - ]) + # On OpenBSD: Compile with -pthread + # Don't link with -lpthread + LIBS=`echo $LIBS | sed s/-lpthread//` + CFLAGS="$CFLAGS -pthread" # OpenBSD doesn't do version numbers with dots. UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots @@ -1368,12 +1363,10 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [ AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} - AS_IF([test "${TCL_THREADS}" = "1"], [ - # The -pthread needs to go in the CFLAGS, not LIBS - LIBS=`echo $LIBS | sed s/-pthread//` - CFLAGS="$CFLAGS -pthread" - LDFLAGS="$LDFLAGS -pthread" - ]) + # The -pthread needs to go in the CFLAGS, not LIBS + LIBS=`echo $LIBS | sed s/-pthread//` + CFLAGS="$CFLAGS -pthread" + LDFLAGS="$LDFLAGS -pthread" ;; FreeBSD-*) # This configuration from FreeBSD Ports. @@ -1387,11 +1380,10 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [ AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}']) - AS_IF([test "${TCL_THREADS}" = "1"], [ - # The -pthread needs to go in the LDFLAGS, not LIBS - LIBS=`echo $LIBS | sed s/-pthread//` - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - LDFLAGS="$LDFLAGS $PTHREAD_LIBS"]) + # The -pthread needs to go in the LDFLAGS, not LIBS + LIBS=`echo $LIBS | sed s/-pthread//` + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LDFLAGS="$LDFLAGS $PTHREAD_LIBS" case $system in FreeBSD-3.*) # Version numbers are dot-stripped by system policy. @@ -1563,16 +1555,14 @@ AC_DEFUN([SC_CONFIG_CFLAGS], [ AS_IF([test "$GCC" = yes], [CFLAGS="$CFLAGS -mieee"], [ CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"]) # see pthread_intro(3) for pthread support on osf1, k.furukawa - AS_IF([test "${TCL_THREADS}" = 1], [ - CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE" - CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64" - LIBS=`echo $LIBS | sed s/-lpthreads//` - AS_IF([test "$GCC" = yes], [ - LIBS="$LIBS -lpthread -lmach -lexc" - ], [ - CFLAGS="$CFLAGS -pthread" - LDFLAGS="$LDFLAGS -pthread" - ]) + CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE" + CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64" + LIBS=`echo $LIBS | sed s/-lpthreads//` + AS_IF([test "$GCC" = yes], [ + LIBS="$LIBS -lpthread -lmach -lexc" + ], [ + CFLAGS="$CFLAGS -pthread" + LDFLAGS="$LDFLAGS -pthread" ]) ;; QNX-6*) @@ -2254,7 +2244,6 @@ AC_DEFUN([SC_BUGGY_STRTOD], [ # THREADS_LIBS Thread library(s) # # Defines the following vars: -# TCL_THREADS # _REENTRANT # _THREAD_SAFE # diff --git a/unix/tclConfig.h.in b/unix/tclConfig.h.in index c284cba..b9d0059 100644 --- a/unix/tclConfig.h.in +++ b/unix/tclConfig.h.in @@ -385,9 +385,6 @@ /* What is the default extension for shared libraries? */ #undef TCL_SHLIB_EXT -/* Are we building with threads enabled? */ -#undef TCL_THREADS - /* Do we allow unloading of shared libraries? */ #undef TCL_UNLOAD_DLLS diff --git a/unix/tclConfig.sh.in b/unix/tclConfig.sh.in index fdc56b7..1edee2f 100644 --- a/unix/tclConfig.sh.in +++ b/unix/tclConfig.sh.in @@ -164,6 +164,3 @@ TCL_BUILD_STUB_LIB_PATH='@TCL_BUILD_STUB_LIB_PATH@' # Path to the Tcl stub library in the install directory. TCL_STUB_LIB_PATH='@TCL_STUB_LIB_PATH@' - -# Flag, 1: we built Tcl with threads enabled, 0 we didn't -TCL_THREADS=@TCL_THREADS@ diff --git a/win/makefile.vc b/win/makefile.vc index 3baef7f..ceeaa02 100644 --- a/win/makefile.vc +++ b/win/makefile.vc @@ -582,7 +582,6 @@ $(OUT_DIR)\tcl.nmake: @type << >$@ CORE_MACHINE = $(MACHINE) CORE_DEBUG = $(DEBUG) -CORE_TCL_THREADS = $(TCL_THREADS) CORE_USE_THREAD_ALLOC = $(USE_THREAD_ALLOC) CORE_USE_WIDECHAR_API = $(USE_WIDECHAR_API) << @@ -638,7 +637,6 @@ $(OUT_DIR)\tclConfig.sh: $(WINDIR)\tclConfig.sh.in @TCL_STUB_LIB_FILE@ $(TCLSTUBLIBNAME) @TCL_STUB_LIB_FLAG@ $(TCLSTUBLIBNAME) @TCL_STUB_LIB_SPEC@ -L$(LIB_INSTALL_DIR) $(TCLSTUBLIBNAME) -@TCL_THREADS@ $(TCL_THREADS) @TCL_BUILD_STUB_LIB_SPEC@ -L$(OUT_DIR) $(TCLSTUBLIBNAME) @TCL_BUILD_STUB_LIB_PATH@ $(TCLSTUBLIB) @TCL_STUB_LIB_PATH@ $(LIB_INSTALL_DIR)\$(TCLSTUBLIBNAME) @@ -711,7 +709,6 @@ $(TMP_DIR)\tclAppInit.obj: $(WINDIR)\tclAppInit.c -Fo$@ $? ### The following objects should be built using the stub interfaces -### *ALL* extensions need to built with -DTCL_THREADS=1 $(TMP_DIR)\tclWinReg.obj: $(WINDIR)\tclWinReg.c !if $(STATIC_BUILD) diff --git a/win/rules.vc b/win/rules.vc index f93400c..fbcb235 100644 --- a/win/rules.vc +++ b/win/rules.vc @@ -24,7 +24,7 @@ _RULES_VC = 1 # For modifications that are not backward-compatible, you *must* change # the major version. RULES_VERSION_MAJOR = 1 -RULES_VERSION_MINOR = 2 +RULES_VERSION_MINOR = 3 # The PROJECT macro must be defined by parent makefile. !if "$(PROJECT)" == "" @@ -1063,17 +1063,17 @@ TCL_INCLUDES = -I"$(WINDIR)" -I"$(GENERICDIR)" # When building extensions, we need to locate tclsh. Depending on version # of Tcl we are building against, this may or may not have a "t" suffix. # Try various possibilities in turn. -TCLSH = $(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX).exe +TCLSH = $(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX:t=).exe !if !exist("$(TCLSH)") -TCLSH = $(_TCLDIR)\bin\tclsh$(TCL_VERSION)$(SUFX:t=).exe +TCLSH = $(_TCLDIR)\bin\tclsh$(TCL_VERSION)t$(SUFX:t=).exe !endif TCLSTUBLIB = $(_TCLDIR)\lib\tclstub$(TCL_VERSION).lib -TCLIMPLIB = $(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX).lib +TCLIMPLIB = $(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX:t=).lib # When building extensions, may be linking against Tcl that does not add # "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility. !if !exist("$(TCLIMPLIB)") -TCLIMPLIB = $(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX:t=).lib +TCLIMPLIB = $(_TCLDIR)\lib\tcl$(TCL_VERSION)t$(SUFX:t=).lib !endif TCL_LIBRARY = $(_TCLDIR)\lib TCLREGLIB = $(_TCLDIR)\lib\tclreg13$(SUFX:t=).lib @@ -1083,16 +1083,16 @@ TCL_INCLUDES = -I"$(_TCLDIR)\include" !else # Building against Tcl sources -TCLSH = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX).exe -!if !exist($(TCLSH)) TCLSH = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)$(SUFX:t=).exe +!if !exist($(TCLSH)) +TCLSH = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclsh$(TCL_VERSION)t$(SUFX:t=).exe !endif TCLSTUBLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclstub$(TCL_VERSION).lib -TCLIMPLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX).lib +TCLIMPLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX:t=).lib # When building extensions, may be linking against Tcl that does not add # "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility. !if !exist("$(TCLIMPLIB)") -TCLIMPLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX:t=).lib +TCLIMPLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)t$(SUFX:t=).lib !endif TCL_LIBRARY = $(_TCLDIR)\library TCLREGLIB = $(_TCLDIR)\win\$(BUILDDIRTOP)\tclreg13$(SUFX:t=).lib diff --git a/win/tclConfig.sh.in b/win/tclConfig.sh.in index 97670aa..8aa25f8 100644 --- a/win/tclConfig.sh.in +++ b/win/tclConfig.sh.in @@ -175,7 +175,3 @@ TCL_BUILD_STUB_LIB_PATH='@TCL_BUILD_STUB_LIB_PATH@' # Path to the Tcl stub library in the install directory. TCL_STUB_LIB_PATH='@TCL_STUB_LIB_PATH@' - -# Flag, 1: we built Tcl with threads enabled, 0 we didn't -TCL_THREADS=@TCL_THREADS@ - -- cgit v0.12 From ce025f259b91e61857e70c6690d5db631b5dc747 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Tue, 22 May 2018 20:53:24 +0000 Subject: Simplify usage of TCL_THREAD, along the lines of [eeddb0693a950be980a66de3811630a00c7bab54|eeddb0693a]. Suggested by DKF --- generic/tcl.h | 28 +-------------------------- generic/tclAlloc.c | 6 +++--- generic/tclBasic.c | 4 ++-- generic/tclCkalloc.c | 2 +- generic/tclEvent.c | 10 +++++----- generic/tclIORChan.c | 48 +++++++++++++++++++++++----------------------- generic/tclIORTrans.c | 38 ++++++++++++++++++------------------ generic/tclInt.h | 9 ++++++--- generic/tclObj.c | 22 ++++++++++----------- generic/tclPkgConfig.c | 2 +- generic/tclTest.c | 8 ++++---- generic/tclThread.c | 33 +++++++++---------------------- generic/tclThreadAlloc.c | 2 +- generic/tclThreadStorage.c | 2 +- generic/tclThreadTest.c | 2 +- unix/tclEpollNotfy.c | 2 +- unix/tclKqueueNotfy.c | 2 +- unix/tclSelectNotfy.c | 22 ++++++++++----------- unix/tclUnixCompat.c | 14 +++++++------- unix/tclUnixFCmd.c | 2 +- unix/tclUnixInit.c | 2 +- unix/tclUnixNotfy.c | 8 ++++---- unix/tclUnixThrd.c | 28 +++++++++++++-------------- win/tclWinThrd.c | 10 +++++----- 24 files changed, 134 insertions(+), 172 deletions(-) diff --git a/generic/tcl.h b/generic/tcl.h index 7d6226b..de314fa 100644 --- a/generic/tcl.h +++ b/generic/tcl.h @@ -107,15 +107,10 @@ extern "C" { #ifndef RC_INVOKED /* - * Special macro to define mutexes, that doesn't do anything if we are not - * using threads. + * Special macro to define mutexes. */ -#if !defined(TCL_THREADS) || TCL_THREADS #define TCL_DECLARE_MUTEX(name) static Tcl_Mutex name; -#else -#define TCL_DECLARE_MUTEX(name) -#endif /* * Tcl's public routine Tcl_FSSeek() uses the values SEEK_SET, SEEK_CUR, and @@ -2561,27 +2556,6 @@ EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr); /* *---------------------------------------------------------------------------- - * Macros that eliminate the overhead of the thread synchronization functions - * when compiling without thread support. - */ - -#if defined(TCL_THREADS) && !TCL_THREADS -#undef Tcl_MutexLock -#define Tcl_MutexLock(mutexPtr) -#undef Tcl_MutexUnlock -#define Tcl_MutexUnlock(mutexPtr) -#undef Tcl_MutexFinalize -#define Tcl_MutexFinalize(mutexPtr) -#undef Tcl_ConditionNotify -#define Tcl_ConditionNotify(condPtr) -#undef Tcl_ConditionWait -#define Tcl_ConditionWait(condPtr, mutexPtr, timePtr) -#undef Tcl_ConditionFinalize -#define Tcl_ConditionFinalize(condPtr) -#endif /* !TCL_THREADS */ - -/* - *---------------------------------------------------------------------------- * Deprecated Tcl functions: */ diff --git a/generic/tclAlloc.c b/generic/tclAlloc.c index e04e9c6..df1718b 100644 --- a/generic/tclAlloc.c +++ b/generic/tclAlloc.c @@ -22,7 +22,7 @@ */ #include "tclInt.h" -#if (defined(TCL_THREADS) && !TCL_THREADS) || !defined(USE_THREAD_ALLOC) +#if !TCL_THREADS || !defined(USE_THREAD_ALLOC) #if USE_TCLALLOC @@ -121,7 +121,7 @@ static struct block bigBlocks={ /* Big blocks aren't suballocated. */ * variable. */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS static Tcl_Mutex *allocMutexPtr; #endif static int allocInit = 0; @@ -171,7 +171,7 @@ TclInitAlloc(void) { if (!allocInit) { allocInit = 1; -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS allocMutexPtr = Tcl_GetAllocMutex(); #endif } diff --git a/generic/tclBasic.c b/generic/tclBasic.c index e20c1b3..9c2736c 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -749,7 +749,7 @@ Tcl_CreateInterp(void) * cache was already initialised by the call to alloc the interp struct. */ -#if (!defined(TCL_THREADS) || TCL_THREADS) && defined(USE_THREAD_ALLOC) +#if TCL_THREADS && defined(USE_THREAD_ALLOC) iPtr->allocCache = TclpGetAllocCache(); #else iPtr->allocCache = NULL; @@ -964,7 +964,7 @@ Tcl_CreateInterp(void) #endif /* !TCL_NO_DEPRECATED */ TclpSetVariables(interp); -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* * The existence of the "threaded" element of the tcl_platform array * indicates that this particular Tcl shell has been compiled with threads diff --git a/generic/tclCkalloc.c b/generic/tclCkalloc.c index e00ac19..e3fb98e 100644 --- a/generic/tclCkalloc.c +++ b/generic/tclCkalloc.c @@ -156,7 +156,7 @@ TclInitDbCkalloc(void) if (!ckallocInit) { ckallocInit = 1; ckallocMutexPtr = Tcl_GetAllocMutex(); -#if defined(TCL_THREADS) && !TCL_THREADS +#if !TCL_THREADS /* Silence compiler warning */ (void)ckallocMutexPtr; #endif diff --git a/generic/tclEvent.c b/generic/tclEvent.c index f8ad1ae..913ff0f 100644 --- a/generic/tclEvent.c +++ b/generic/tclEvent.c @@ -100,7 +100,7 @@ typedef struct ThreadSpecificData { } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS typedef struct { Tcl_ThreadCreateProc *proc; /* Main() function of the thread */ ClientData clientData; /* The one argument to Main() */ @@ -1043,7 +1043,7 @@ TclInitSubsystems(void) #if USE_TCLALLOC TclInitAlloc(); /* Process wide mutex init */ #endif -#if (!defined(TCL_THREADS) || TCL_THREADS) && defined(USE_THREAD_ALLOC) +#if TCL_THREADS && defined(USE_THREAD_ALLOC) TclInitThreadAlloc(); /* Setup thread allocator caches */ #endif #ifdef TCL_MEM_DEBUG @@ -1220,7 +1220,7 @@ Tcl_Finalize(void) * Close down the thread-specific object allocator. */ -#if (!defined(TCL_THREADS) || TCL_THREADS) && defined(USE_THREAD_ALLOC) +#if TCL_THREADS && defined(USE_THREAD_ALLOC) TclFinalizeThreadAlloc(); #endif @@ -1538,7 +1538,7 @@ Tcl_UpdateObjCmd( return TCL_OK; } -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* *---------------------------------------------------------------------- * @@ -1601,7 +1601,7 @@ Tcl_CreateThread( int flags) /* Flags controlling behaviour of the new * thread. */ { -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS ThreadClientData *cdPtr = ckalloc(sizeof(ThreadClientData)); int result; diff --git a/generic/tclIORChan.c b/generic/tclIORChan.c index 1553cd0..354f1fb 100644 --- a/generic/tclIORChan.c +++ b/generic/tclIORChan.c @@ -39,7 +39,7 @@ static int ReflectOutput(ClientData clientData, const char *buf, int toWrite, int *errorCodePtr); static void ReflectWatch(ClientData clientData, int mask); static int ReflectBlock(ClientData clientData, int mode); -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS static void ReflectThread(ClientData clientData, int action); static int ReflectEventRun(Tcl_Event *ev, int flags); static int ReflectEventDelete(Tcl_Event *ev, ClientData cd); @@ -76,7 +76,7 @@ static const Tcl_ChannelType tclRChannelType = { NULL, /* Flush channel. Not used by core. NULL'able */ NULL, /* Handle events. NULL'able */ ReflectSeekWide, /* Move access point (64 bit). NULL'able */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS ReflectThread, /* thread action, tracking owner */ #else NULL, /* thread action */ @@ -97,7 +97,7 @@ typedef struct { * interpreter/thread containing its Tcl * command is gone. */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS Tcl_ThreadId thread; /* Thread the 'interp' belongs to. == Handler thread */ Tcl_ThreadId owner; /* Thread owning the structure. == Channel thread */ #endif @@ -201,7 +201,7 @@ typedef enum { #define NEGIMPL(a,b) #define HAS(x,f) (x & FLAG(f)) -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* * Thread specific types and structures. * @@ -451,7 +451,7 @@ static const char *msg_read_toomuch = "{read delivered more than requested}"; static const char *msg_write_toomuch = "{write wrote more than requested}"; static const char *msg_write_nothing = "{write wrote nothing}"; static const char *msg_seek_beforestart = "{Tried to seek before origin}"; -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS static const char *msg_send_originlost = "{Channel thread lost}"; #endif /* TCL_THREADS */ static const char *msg_send_dstlost = "{Owner lost}"; @@ -706,7 +706,7 @@ TclChanCreateObjCmd( Tcl_Panic("TclChanCreateObjCmd: duplicate channel names"); } Tcl_SetHashValue(hPtr, chan); -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS rcmPtr = GetThreadReflectedChannelMap(); hPtr = Tcl_CreateHashEntry(&rcmPtr->map, chanPtr->state->channelName, &isNew); @@ -750,7 +750,7 @@ TclChanCreateObjCmd( *---------------------------------------------------------------------- */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS typedef struct { Tcl_Event header; ReflectedChannel *rcPtr; @@ -917,11 +917,11 @@ TclChanPostEventObjCmd( * We have the channel and the events to post. */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS if (rcPtr->owner == rcPtr->thread) { #endif Tcl_NotifyChannel(chan, events); -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS } else { ReflectEvent *ev = ckalloc(sizeof(ReflectEvent)); @@ -1137,7 +1137,7 @@ ReflectClose( * if lost? */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS if (rcPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; @@ -1169,7 +1169,7 @@ ReflectClose( * Are we in the correct thread? */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS if (rcPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; @@ -1216,7 +1216,7 @@ ReflectClose( Tcl_DeleteHashEntry(hPtr); } } -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS rcmPtr = GetThreadReflectedChannelMap(); hPtr = Tcl_FindHashEntry(&rcmPtr->map, Tcl_GetChannelName(rcPtr->chan)); @@ -1267,7 +1267,7 @@ ReflectInput( * Are we in the correct thread? */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS if (rcPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; @@ -1373,7 +1373,7 @@ ReflectOutput( * Are we in the correct thread? */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS if (rcPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; @@ -1502,7 +1502,7 @@ ReflectSeekWide( * Are we in the correct thread? */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS if (rcPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; @@ -1625,7 +1625,7 @@ ReflectWatch( * Are we in the correct thread? */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS if (rcPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; @@ -1683,7 +1683,7 @@ ReflectBlock( * Are we in the correct thread? */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS if (rcPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; @@ -1719,7 +1719,7 @@ ReflectBlock( return errorNum; } -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* *---------------------------------------------------------------------- * @@ -1789,7 +1789,7 @@ ReflectSetOption( * Are we in the correct thread? */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS if (rcPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; @@ -1868,7 +1868,7 @@ ReflectGetOption( * Are we in the correct thread? */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS if (rcPtr->thread != Tcl_GetCurrentThread()) { int opcode; ForwardParam p; @@ -2131,7 +2131,7 @@ NewReflectedChannel( rcPtr->chan = NULL; rcPtr->interp = interp; rcPtr->dead = 0; -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS rcPtr->thread = Tcl_GetCurrentThread(); #endif rcPtr->mode = mode; @@ -2506,7 +2506,7 @@ DeleteReflectedChannelMap( Tcl_HashEntry *hPtr; /* Search variable. */ ReflectedChannel *rcPtr; Tcl_Channel chan; -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS ForwardingResult *resultPtr; ForwardingEvent *evPtr; ForwardParam *paramPtr; @@ -2536,7 +2536,7 @@ DeleteReflectedChannelMap( Tcl_DeleteHashTable(&rcmPtr->map); ckfree(&rcmPtr->map); -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* * The origin interpreter for one or more reflected channels is gone. */ @@ -2622,7 +2622,7 @@ DeleteReflectedChannelMap( #endif } -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* *---------------------------------------------------------------------- * diff --git a/generic/tclIORTrans.c b/generic/tclIORTrans.c index 03fadd1..1a7b940 100644 --- a/generic/tclIORTrans.c +++ b/generic/tclIORTrans.c @@ -127,7 +127,7 @@ typedef struct { * in the argv, see below. The separate field * gives us direct access, needed when working * with the reflection maps. */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS Tcl_ThreadId thread; /* Thread the 'interp' belongs to. */ #endif @@ -220,7 +220,7 @@ typedef enum { #define NEGIMPL(a,b) #define HAS(x,f) (x & FLAG(f)) -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* * Thread specific types and structures. * @@ -438,7 +438,7 @@ static void DeleteReflectedTransformMap(ClientData clientData, static const char *msg_read_unsup = "{read not supported by Tcl driver}"; static const char *msg_write_unsup = "{write not supported by Tcl driver}"; -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS static const char *msg_send_originlost = "{Channel thread lost}"; static const char *msg_send_dstlost = "{Owner lost}"; #endif /* TCL_THREADS */ @@ -699,7 +699,7 @@ TclChanPushObjCmd( Tcl_Panic("TclChanPushObjCmd: duplicate transformation handle"); } Tcl_SetHashValue(hPtr, rtPtr); -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS rtmPtr = GetThreadReflectedTransformMap(); hPtr = Tcl_CreateHashEntry(&rtmPtr->map, TclGetString(rtId), &isNew); Tcl_SetHashValue(hPtr, rtPtr); @@ -911,7 +911,7 @@ ReflectClose( * if lost? */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; @@ -938,7 +938,7 @@ ReflectClose( if (HAS(rtPtr->methods, METH_DRAIN) && !rtPtr->readIsDrained) { if (!TransformDrain(rtPtr, &errorCode)) { -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *) FreeReflectedTransform); @@ -952,7 +952,7 @@ ReflectClose( if (HAS(rtPtr->methods, METH_FLUSH)) { if (!TransformFlush(rtPtr, &errorCode, FLUSH_WRITE)) { -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *) FreeReflectedTransform); @@ -968,7 +968,7 @@ ReflectClose( * Are we in the correct thread? */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; @@ -1025,7 +1025,7 @@ ReflectClose( * under a channel by deleting the owning thread. */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS rtmPtr = GetThreadReflectedTransformMap(); hPtr = Tcl_FindHashEntry(&rtmPtr->map, TclGetString(rtPtr->handle)); if (hPtr) { @@ -1767,7 +1767,7 @@ NewReflectedTransform( rtPtr->chan = NULL; rtPtr->methods = 0; -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS rtPtr->thread = Tcl_GetCurrentThread(); #endif rtPtr->parent = parentChan; @@ -2152,7 +2152,7 @@ DeleteReflectedTransformMap( Tcl_HashSearch hSearch; /* Search variable. */ Tcl_HashEntry *hPtr; /* Search variable. */ ReflectedTransform *rtPtr; -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS ForwardingResult *resultPtr; ForwardingEvent *evPtr; ForwardParam *paramPtr; @@ -2182,7 +2182,7 @@ DeleteReflectedTransformMap( Tcl_DeleteHashTable(&rtmPtr->map); ckfree(&rtmPtr->map); -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* * The origin interpreter for one or more reflected channels is gone. */ @@ -2254,7 +2254,7 @@ DeleteReflectedTransformMap( #endif /* TCL_THREADS */ } -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* *---------------------------------------------------------------------- * @@ -3088,7 +3088,7 @@ TransformRead( * Are we in the correct thread? */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; @@ -3144,7 +3144,7 @@ TransformWrite( * Are we in the correct thread? */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; @@ -3210,7 +3210,7 @@ TransformDrain( * Are we in the correct thread? */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; @@ -3260,7 +3260,7 @@ TransformFlush( * Are we in the correct thread? */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; @@ -3315,7 +3315,7 @@ TransformClear( * Are we in the correct thread? */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; @@ -3347,7 +3347,7 @@ TransformLimit( * Are we in the correct thread? */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS if (rtPtr->thread != Tcl_GetCurrentThread()) { ForwardParam p; diff --git a/generic/tclInt.h b/generic/tclInt.h index eb1ae68..a29dae8 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -4200,7 +4200,10 @@ typedef const char *TclDTraceStr; } \ } -#if (!defined(TCL_THREADS) || TCL_THREADS) && !defined(USE_THREAD_ALLOC) +#if !defined(TCL_THREADS) +# define TCL_THREADS 1 +#endif +#if TCL_THREADS && !defined(USE_THREAD_ALLOC) # define USE_THREAD_ALLOC 1 #endif @@ -4221,7 +4224,7 @@ typedef const char *TclDTraceStr; #undef USE_THREAD_ALLOC #undef USE_TCLALLOC -#elif (!defined(TCL_THREADS) || TCL_THREADS) && defined(USE_THREAD_ALLOC) +#elif TCL_THREADS && defined(USE_THREAD_ALLOC) /* * The TCL_THREADS mode is like the regular mode but allocates Tcl_Obj's from @@ -4286,7 +4289,7 @@ MODULE_SCOPE void TclpFreeAllocCache(void *); # define USE_TCLALLOC 0 #endif -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* declared in tclObj.c */ MODULE_SCOPE Tcl_Mutex tclObjMutex; #endif diff --git a/generic/tclObj.c b/generic/tclObj.c index 0cd04ef..f93f583 100644 --- a/generic/tclObj.c +++ b/generic/tclObj.c @@ -37,7 +37,7 @@ Tcl_Obj *tclFreeObjList = NULL; * TclNewObj macro, however, so must be visible. */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS MODULE_SCOPE Tcl_Mutex tclObjMutex; Tcl_Mutex tclObjMutex; #endif @@ -50,7 +50,7 @@ Tcl_Mutex tclObjMutex; char tclEmptyString = '\0'; -#if (!defined(TCL_THREADS) || TCL_THREADS) && defined(TCL_MEM_DEBUG) +#if TCL_THREADS && defined(TCL_MEM_DEBUG) /* * Structure for tracking the source file and line number where a given * Tcl_Obj was allocated. We also track the pointer to the Tcl_Obj itself, @@ -87,7 +87,7 @@ typedef struct { * tclCompile.h for the definition of this * structure, and for references to all * related places in the core. */ -#if (!defined(TCL_THREADS) || TCL_THREADS) && defined(TCL_MEM_DEBUG) +#if TCL_THREADS && defined(TCL_MEM_DEBUG) Tcl_HashTable *objThreadMap;/* Thread local table that is used to check * that a Tcl_Obj was not allocated by some * other thread. */ @@ -156,7 +156,7 @@ typedef struct PendingObjData { /* * Macro to set up the local reference to the deletion context. */ -#if defined(TCL_THREADS) && !TCL_THREADS +#if !TCL_THREADS static PendingObjData pendingObjData; #define ObjInitDeletionContext(contextPtr) \ PendingObjData *const contextPtr = &pendingObjData @@ -452,7 +452,7 @@ TclInitObjSubsystem(void) void TclFinalizeThreadObjects(void) { -#if (!defined(TCL_THREADS) || TCL_THREADS) && defined(TCL_MEM_DEBUG) +#if TCL_THREADS && defined(TCL_MEM_DEBUG) Tcl_HashEntry *hPtr; Tcl_HashSearch hSearch; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); @@ -1009,7 +1009,7 @@ void TclDbDumpActiveObjects( FILE *outFile) { -#if (!defined(TCL_THREADS) || TCL_THREADS) && defined(TCL_MEM_DEBUG) +#if TCL_THREADS && defined(TCL_MEM_DEBUG) Tcl_HashSearch hSearch; Tcl_HashEntry *hPtr; Tcl_HashTable *tablePtr; @@ -1069,7 +1069,7 @@ TclDbInitNewObj( objPtr->length = 0; objPtr->typePtr = NULL; -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* * Add entry to a thread local map used to check if a Tcl_Obj was * allocated by the currently executing thread. @@ -1305,7 +1305,7 @@ TclFreeObj( ObjInitDeletionContext(context); -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* * Check to make sure that the Tcl_Obj was allocated by the current * thread. Don't do this check when shutting down since thread local @@ -3598,7 +3598,7 @@ Tcl_DbIncrRefCount( Tcl_Panic("incrementing refCount of previously disposed object"); } -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* * Check to make sure that the Tcl_Obj was allocated by the current * thread. Don't do this check when shutting down since thread local @@ -3661,7 +3661,7 @@ Tcl_DbDecrRefCount( Tcl_Panic("decrementing refCount of previously disposed object"); } -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* * Check to make sure that the Tcl_Obj was allocated by the current * thread. Don't do this check when shutting down since thread local @@ -3726,7 +3726,7 @@ Tcl_DbIsShared( Tcl_Panic("checking whether previously disposed object is shared"); } -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* * Check to make sure that the Tcl_Obj was allocated by the current * thread. Don't do this check when shutting down since thread local diff --git a/generic/tclPkgConfig.c b/generic/tclPkgConfig.c index a456a14..9e194c8 100644 --- a/generic/tclPkgConfig.c +++ b/generic/tclPkgConfig.c @@ -40,7 +40,7 @@ * configuration information. */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS # define CFG_THREADED "1" #else # define CFG_THREADED "0" diff --git a/generic/tclTest.c b/generic/tclTest.c index b4d249f..ac01ecf 100644 --- a/generic/tclTest.c +++ b/generic/tclTest.c @@ -161,7 +161,7 @@ static TestChannel *firstDetached; static int AsyncHandlerProc(ClientData clientData, Tcl_Interp *interp, int code); -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS static Tcl_ThreadCreateType AsyncThreadProc(ClientData); #endif static void CleanupTestSetassocdataTests( @@ -722,7 +722,7 @@ Tcltest_Init( if (Procbodytest_Init(interp) != TCL_OK) { return TCL_ERROR; } -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS if (TclThread_Init(interp) != TCL_OK) { return TCL_ERROR; } @@ -902,7 +902,7 @@ TestasyncCmd( Tcl_SetObjResult(interp, Tcl_NewStringObj(argv[3], -1)); Tcl_MutexUnlock(&asyncTestMutex); return code; -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS } else if (strcmp(argv[1], "marklater") == 0) { if (argc != 3) { goto wrongNumArgs; @@ -999,7 +999,7 @@ AsyncHandlerProc( *---------------------------------------------------------------------- */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS static Tcl_ThreadCreateType AsyncThreadProc( ClientData clientData) /* Parameter is the id of a diff --git a/generic/tclThread.c b/generic/tclThread.c index a70f1aa..8def429 100644 --- a/generic/tclThread.c +++ b/generic/tclThread.c @@ -41,21 +41,6 @@ static void RememberSyncObject(void *objPtr, SyncObjRecord *recPtr); /* - * Several functions are #defined to nothing in tcl.h if TCL_THREADS is not - * specified. Here we undo that so the functions are defined in the stubs - * table. - */ - -#if defined(TCL_THREADS) && !TCL_THREADS -#undef Tcl_MutexLock -#undef Tcl_MutexUnlock -#undef Tcl_MutexFinalize -#undef Tcl_ConditionNotify -#undef Tcl_ConditionWait -#undef Tcl_ConditionFinalize -#endif - -/* *---------------------------------------------------------------------- * * Tcl_GetThreadData -- @@ -79,7 +64,7 @@ Tcl_GetThreadData( int size) /* Size of storage block */ { void *result; -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* * Initialize the key for this thread. */ @@ -126,7 +111,7 @@ TclThreadDataKeyGet( Tcl_ThreadDataKey *keyPtr) /* Identifier for the data chunk. */ { -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS return TclThreadStorageKeyGet(keyPtr); #else /* TCL_THREADS */ return *keyPtr; @@ -273,7 +258,7 @@ void Tcl_MutexFinalize( Tcl_Mutex *mutexPtr) { -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS TclpFinalizeMutex(mutexPtr); #endif TclpMasterLock(); @@ -326,7 +311,7 @@ void Tcl_ConditionFinalize( Tcl_Condition *condPtr) { -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS TclpFinalizeCondition(condPtr); #endif TclpMasterLock(); @@ -356,7 +341,7 @@ void TclFinalizeThreadData(int quick) { TclFinalizeThreadDataThread(); -#if (!defined(TCL_THREADS) || TCL_THREADS) && defined(USE_THREAD_ALLOC) +#if TCL_THREADS && defined(USE_THREAD_ALLOC) if (!quick) { /* * Quick exit principle makes it useless to terminate allocators @@ -389,7 +374,7 @@ TclFinalizeSynchronization(void) int i; void *blockPtr; Tcl_ThreadDataKey *keyPtr; -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS Tcl_Mutex *mutexPtr; Tcl_Condition *condPtr; @@ -413,7 +398,7 @@ TclFinalizeSynchronization(void) keyRecord.max = 0; keyRecord.num = 0; -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* * Call thread storage master cleanup. */ @@ -473,12 +458,12 @@ Tcl_ExitThread( int status) { Tcl_FinalizeThread(); -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS TclpThreadExit(status); #endif } -#if defined(TCL_THREADS) && !TCL_THREADS +#if !TCL_THREADS /* *---------------------------------------------------------------------- diff --git a/generic/tclThreadAlloc.c b/generic/tclThreadAlloc.c index c8132a5..3f1abc2 100644 --- a/generic/tclThreadAlloc.c +++ b/generic/tclThreadAlloc.c @@ -13,7 +13,7 @@ */ #include "tclInt.h" -#if (!defined(TCL_THREADS) || TCL_THREADS) && defined(USE_THREAD_ALLOC) +#if TCL_THREADS && defined(USE_THREAD_ALLOC) /* * If range checking is enabled, an additional byte will be allocated to store diff --git a/generic/tclThreadStorage.c b/generic/tclThreadStorage.c index d925b04..b56ec80 100644 --- a/generic/tclThreadStorage.c +++ b/generic/tclThreadStorage.c @@ -13,7 +13,7 @@ #include "tclInt.h" -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS #include /* diff --git a/generic/tclThreadTest.c b/generic/tclThreadTest.c index dce15eb..3a6fc43 100644 --- a/generic/tclThreadTest.c +++ b/generic/tclThreadTest.c @@ -18,7 +18,7 @@ #endif #include "tclInt.h" -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* * Each thread has an single instance of the following structure. There is one * instance of this structure per thread even if that thread contains multiple diff --git a/unix/tclEpollNotfy.c b/unix/tclEpollNotfy.c index 3059643..b3ee57a 100644 --- a/unix/tclEpollNotfy.c +++ b/unix/tclEpollNotfy.c @@ -12,7 +12,7 @@ * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#if defined(NOTIFIER_EPOLL) && (!defined(TCL_THREADS) || TCL_THREADS) +#if defined(NOTIFIER_EPOLL) && TCL_THREADS #define _GNU_SOURCE /* For pipe2(2) */ #include "tclInt.h" diff --git a/unix/tclKqueueNotfy.c b/unix/tclKqueueNotfy.c index 3fddeea..da52d96 100644 --- a/unix/tclKqueueNotfy.c +++ b/unix/tclKqueueNotfy.c @@ -13,7 +13,7 @@ * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#if defined(NOTIFIER_KQUEUE) && (!defined(TCL_THREADS) || TCL_THREADS) +#if defined(NOTIFIER_KQUEUE) && TCL_THREADS #include "tclInt.h" #ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is diff --git a/unix/tclSelectNotfy.c b/unix/tclSelectNotfy.c index 3172d6a..58dc742 100644 --- a/unix/tclSelectNotfy.c +++ b/unix/tclSelectNotfy.c @@ -11,7 +11,7 @@ * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#if (!defined(NOTIFIER_EPOLL) && !defined(NOTIFIER_KQUEUE)) || (defined(TCL_THREADS) && !TCL_THREADS) +#if (!defined(NOTIFIER_EPOLL) && !defined(NOTIFIER_KQUEUE)) || !TCL_THREADS #include "tclInt.h" #ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is @@ -81,7 +81,7 @@ typedef struct ThreadSpecificData { int numFdBits; /* Number of valid bits in checkMasks (one * more than highest fd for which * Tcl_WatchFile has been called). */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS int onList; /* True if it is in this list */ unsigned int pollState; /* pollState is used to implement a polling * handshake between each thread and the @@ -112,7 +112,7 @@ typedef struct ThreadSpecificData { static Tcl_ThreadDataKey dataKey; -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* * The following static indicates the number of threads that have initialized * notifiers. @@ -193,7 +193,7 @@ static Tcl_ThreadId notifierThread; * Static routines defined in this file. */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS static TCL_NORETURN void NotifierThreadProc(ClientData clientData); #if defined(HAVE_PTHREAD_ATFORK) static int atForkInit = 0; @@ -285,7 +285,7 @@ Tcl_InitNotifier(void) } else { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS tsdPtr->eventReady = 0; /* @@ -370,7 +370,7 @@ Tcl_FinalizeNotifier( tclNotifierHooks.finalizeNotifierProc(clientData); return; } else { -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); pthread_mutex_lock(¬ifierInitMutex); @@ -640,7 +640,7 @@ Tcl_WaitForEvent( FileHandler *filePtr; int mask; Tcl_Time vTime; -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS int waitForFiles; # ifdef __CYGWIN__ MSG msg; @@ -675,7 +675,7 @@ Tcl_WaitForEvent( tclScaleTimeProcPtr(&vTime, tclTimeClientData); timePtr = &vTime; } -#if defined(TCL_THREADS) && !TCL_THREADS +#if !TCL_THREADS timeout.tv_sec = timePtr->sec; timeout.tv_usec = timePtr->usec; timeoutPtr = &timeout; @@ -694,7 +694,7 @@ Tcl_WaitForEvent( #endif /* !TCL_THREADS */ } -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* * Start notifier thread and place this thread on the list of * interested threads, signal the notifier thread, and wait for a @@ -885,14 +885,14 @@ Tcl_WaitForEvent( } filePtr->readyMask = mask; } -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS pthread_mutex_unlock(¬ifierMutex); #endif /* TCL_THREADS */ return 0; } } -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* *---------------------------------------------------------------------- diff --git a/unix/tclUnixCompat.c b/unix/tclUnixCompat.c index 2d2e53b..aa25c6b 100644 --- a/unix/tclUnixCompat.c +++ b/unix/tclUnixCompat.c @@ -47,7 +47,7 @@ * library calls. */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS typedef struct { struct passwd pwd; @@ -182,7 +182,7 @@ struct passwd * TclpGetPwNam( const char *name) { -#if defined(TCL_THREADS) && !TCL_THREADS +#if !TCL_THREADS return getpwnam(name); #else ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); @@ -262,7 +262,7 @@ struct passwd * TclpGetPwUid( uid_t uid) { -#if defined(TCL_THREADS) && !TCL_THREADS +#if !TCL_THREADS return getpwuid(uid); #else ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); @@ -365,7 +365,7 @@ struct group * TclpGetGrNam( const char *name) { -#if defined(TCL_THREADS) && !TCL_THREADS +#if !TCL_THREADS return getgrnam(name); #else ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); @@ -445,7 +445,7 @@ struct group * TclpGetGrGid( gid_t gid) { -#if defined(TCL_THREADS) && !TCL_THREADS +#if !TCL_THREADS return getgrgid(gid); #else ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); @@ -548,7 +548,7 @@ struct hostent * TclpGetHostByName( const char *name) { -#if (defined(TCL_THREADS) && !TCL_THREADS) || defined(HAVE_MTSAFE_GETHOSTBYNAME) +#if !TCL_THREADS || defined(HAVE_MTSAFE_GETHOSTBYNAME) return gethostbyname(name); #else ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); @@ -618,7 +618,7 @@ TclpGetHostByAddr( int length, int type) { -#if (defined(TCL_THREADS) && !TCL_THREADS) || defined(HAVE_MTSAFE_GETHOSTBYADDR) +#if !TCL_THREADS || defined(HAVE_MTSAFE_GETHOSTBYADDR) return gethostbyaddr(addr, length, type); #else ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); diff --git a/unix/tclUnixFCmd.c b/unix/tclUnixFCmd.c index 2b2a613..548e96b 100644 --- a/unix/tclUnixFCmd.c +++ b/unix/tclUnixFCmd.c @@ -256,7 +256,7 @@ Realpath( #endif /* PURIFY */ #ifndef NO_REALPATH -#if defined(__APPLE__) && (!defined(TCL_THREADS) || TCL_THREADS) && \ +#if defined(__APPLE__) && TCL_THREADS && \ defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \ MAC_OS_X_VERSION_MIN_REQUIRED < 1030 /* diff --git a/unix/tclUnixInit.c b/unix/tclUnixInit.c index 78d591a..b6b66da 100644 --- a/unix/tclUnixInit.c +++ b/unix/tclUnixInit.c @@ -316,7 +316,7 @@ static int MacOSXGetLibraryPath(Tcl_Interp *interp, #endif /* HAVE_COREFOUNDATION */ #if defined(__APPLE__) && (defined(TCL_LOAD_FROM_MEMORY) || ( \ defined(MAC_OS_X_VERSION_MIN_REQUIRED) && ( \ - ((!defined(TCL_THREADS) || TCL_THREADS) && MAC_OS_X_VERSION_MIN_REQUIRED < 1030) || \ + (TCL_THREADS && MAC_OS_X_VERSION_MIN_REQUIRED < 1030) || \ (defined(__LP64__) && MAC_OS_X_VERSION_MIN_REQUIRED < 1050) || \ (defined(HAVE_COREFOUNDATION) && MAC_OS_X_VERSION_MIN_REQUIRED < 1050)\ ))) diff --git a/unix/tclUnixNotfy.c b/unix/tclUnixNotfy.c index 6572b39..062d817 100644 --- a/unix/tclUnixNotfy.c +++ b/unix/tclUnixNotfy.c @@ -18,7 +18,7 @@ */ static int FileHandlerEventProc(Tcl_Event *evPtr, int flags); -#if defined(TCL_THREADS) && !TCL_THREADS +#if !TCL_THREADS # undef NOTIFIER_EPOLL # undef NOTIFIER_KQUEUE # define NOTIFIER_SELECT @@ -106,7 +106,7 @@ Tcl_AlertNotifier( return; } else { #ifdef NOTIFIER_SELECT -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS ThreadSpecificData *tsdPtr = clientData; pthread_mutex_lock(¬ifierMutex); @@ -197,7 +197,7 @@ Tcl_ServiceModeHook( return; } else if (mode == TCL_SERVICE_ALL) { #ifdef NOTIFIER_SELECT -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS StartNotifierThread("Tcl_ServiceModeHook"); #endif #endif /* NOTIFIER_SELECT */ @@ -279,7 +279,7 @@ FileHandlerEventProc( } #ifdef NOTIFIER_SELECT -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* *---------------------------------------------------------------------- * diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c index 76228a3..6ea258f 100644 --- a/unix/tclUnixThrd.c +++ b/unix/tclUnixThrd.c @@ -13,7 +13,7 @@ #include "tclInt.h" -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS #ifndef TCL_NO_DEPRECATED typedef struct { @@ -74,7 +74,7 @@ TclpThreadCreate( int flags) /* Flags controlling behaviour of the new * thread. */ { -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS pthread_attr_t attr; pthread_t theThread; int result; @@ -152,7 +152,7 @@ Tcl_JoinThread( * thread we wait upon will be written into. * May be NULL. */ { -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS int result; unsigned long retcode, *retcodePtr = &retcode; @@ -166,7 +166,7 @@ Tcl_JoinThread( #endif } -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* *---------------------------------------------------------------------- * @@ -210,7 +210,7 @@ TclpThreadExit( Tcl_ThreadId Tcl_GetCurrentThread(void) { -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS return (Tcl_ThreadId) pthread_self(); #else return (Tcl_ThreadId) 0; @@ -239,7 +239,7 @@ Tcl_GetCurrentThread(void) void TclpInitLock(void) { -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS pthread_mutex_lock(&initLock); #endif } @@ -265,7 +265,7 @@ TclpInitLock(void) void TclFinalizeLock(void) { -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* * You do not need to destroy mutexes that were created with the * PTHREAD_MUTEX_INITIALIZER macro. These mutexes do not need any @@ -296,7 +296,7 @@ TclFinalizeLock(void) void TclpInitUnlock(void) { -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS pthread_mutex_unlock(&initLock); #endif } @@ -325,7 +325,7 @@ TclpInitUnlock(void) void TclpMasterLock(void) { -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS pthread_mutex_lock(&masterLock); #endif } @@ -351,7 +351,7 @@ TclpMasterLock(void) void TclpMasterUnlock(void) { -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS pthread_mutex_unlock(&masterLock); #endif } @@ -378,7 +378,7 @@ TclpMasterUnlock(void) Tcl_Mutex * Tcl_GetAllocMutex(void) { -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS pthread_mutex_t **allocLockPtrPtr = &allocLockPtr; return (Tcl_Mutex *) allocLockPtrPtr; #else @@ -386,7 +386,7 @@ Tcl_GetAllocMutex(void) #endif } -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* *---------------------------------------------------------------------- @@ -659,7 +659,7 @@ char * TclpInetNtoa( struct in_addr addr) { -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); unsigned char *b = (unsigned char*) &addr.s_addr; @@ -671,7 +671,7 @@ TclpInetNtoa( } #endif /* TCL_NO_DEPRECATED */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* * Additions by AOL for specialized thread memory allocator. */ diff --git a/win/tclWinThrd.c b/win/tclWinThrd.c index 07b6db9..5ea407e 100644 --- a/win/tclWinThrd.c +++ b/win/tclWinThrd.c @@ -41,7 +41,7 @@ static CRITICAL_SECTION initLock; * obvious reasons, cannot use any dyamically allocated storage. */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS static struct Tcl_Mutex_ { CRITICAL_SECTION crit; @@ -76,7 +76,7 @@ static CRITICAL_SECTION joinLock; * The per-thread event and queue pointers. */ -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS typedef struct ThreadSpecificData { HANDLE condEvent; /* Per-thread condition event */ @@ -474,7 +474,7 @@ TclpMasterUnlock(void) Tcl_Mutex * Tcl_GetAllocMutex(void) { -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS if (!allocOnce) { InitializeCriticalSection(&allocLock.crit); allocOnce = 1; @@ -516,7 +516,7 @@ TclFinalizeLock(void) DeleteCriticalSection(&masterLock); initialized = 0; -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS if (allocOnce) { DeleteCriticalSection(&allocLock.crit); allocOnce = 0; @@ -532,7 +532,7 @@ TclFinalizeLock(void) DeleteCriticalSection(&initLock); } -#if !defined(TCL_THREADS) || TCL_THREADS +#if TCL_THREADS /* locally used prototype */ static void FinalizeConditionEvent(ClientData data); -- cgit v0.12 From 46aab3eb09ed92b1b43e3d08484dfe88efe06cab Mon Sep 17 00:00:00 2001 From: dgp Date: Wed, 23 May 2018 13:34:53 +0000 Subject: unbreak the build --- unix/tclEpollNotfy.c | 2 +- unix/tclKqueueNotfy.c | 2 +- unix/tclSelectNotfy.c | 2 +- unix/tclUnixNotfy.c | 1 + 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/unix/tclEpollNotfy.c b/unix/tclEpollNotfy.c index b3ee57a..8a083d8 100644 --- a/unix/tclEpollNotfy.c +++ b/unix/tclEpollNotfy.c @@ -12,10 +12,10 @@ * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ +#include "tclInt.h" #if defined(NOTIFIER_EPOLL) && TCL_THREADS #define _GNU_SOURCE /* For pipe2(2) */ -#include "tclInt.h" #ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is * in tclMacOSXNotify.c */ #include diff --git a/unix/tclKqueueNotfy.c b/unix/tclKqueueNotfy.c index da52d96..c781ce2 100644 --- a/unix/tclKqueueNotfy.c +++ b/unix/tclKqueueNotfy.c @@ -13,9 +13,9 @@ * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ +#include "tclInt.h" #if defined(NOTIFIER_KQUEUE) && TCL_THREADS -#include "tclInt.h" #ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is * in tclMacOSXNotify.c */ #include diff --git a/unix/tclSelectNotfy.c b/unix/tclSelectNotfy.c index 58dc742..811b49a 100644 --- a/unix/tclSelectNotfy.c +++ b/unix/tclSelectNotfy.c @@ -11,9 +11,9 @@ * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ +#include "tclInt.h" #if (!defined(NOTIFIER_EPOLL) && !defined(NOTIFIER_KQUEUE)) || !TCL_THREADS -#include "tclInt.h" #ifndef HAVE_COREFOUNDATION /* Darwin/Mac OS X CoreFoundation notifier is * in tclMacOSXNotify.c */ #include diff --git a/unix/tclUnixNotfy.c b/unix/tclUnixNotfy.c index 062d817..fb7e569 100644 --- a/unix/tclUnixNotfy.c +++ b/unix/tclUnixNotfy.c @@ -12,6 +12,7 @@ */ #include +#include "tclInt.h" /* * Static routines defined in this file. -- cgit v0.12 From edb38932e8f071b1326515067d41bc060807dec2 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 23 May 2018 19:31:15 +0000 Subject: Unbreak build with other CFLAGS, such as TCL_MEM_DEBUG=1 or TCL_THREADS=0 on Linux --- generic/tclInt.h | 23 ++++++++++++++++++++--- generic/tclThread.c | 4 ++-- unix/tclUnixThrd.c | 6 ++++-- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/generic/tclInt.h b/generic/tclInt.h index a29dae8..879d3ae 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -136,6 +136,26 @@ typedef int ptrdiff_t; # define vsnprintf _vsnprintf #endif +#if !defined(TCL_THREADS) +# define TCL_THREADS 1 +#endif +#if !TCL_THREADS +# undef TCL_DECLARE_MUTEX +# define TCL_DECLARE_MUTEX(name) +# undef Tcl_MutexLock +# define Tcl_MutexLock(mutexPtr) +# undef Tcl_MutexUnlock +# define Tcl_MutexUnlock(mutexPtr) +# undef Tcl_MutexFinalize +# define Tcl_MutexFinalize(mutexPtr) +# undef Tcl_ConditionNotify +# define Tcl_ConditionNotify(condPtr) +# undef Tcl_ConditionWait +# define Tcl_ConditionWait(condPtr, mutexPtr, timePtr) +# undef Tcl_ConditionFinalize +# define Tcl_ConditionFinalize(condPtr) +#endif + /* * The following procedures allow namespaces to be customized to support * special name resolution rules for commands/variables. @@ -4200,9 +4220,6 @@ typedef const char *TclDTraceStr; } \ } -#if !defined(TCL_THREADS) -# define TCL_THREADS 1 -#endif #if TCL_THREADS && !defined(USE_THREAD_ALLOC) # define USE_THREAD_ALLOC 1 #endif diff --git a/generic/tclThread.c b/generic/tclThread.c index 8def429..cafd824 100644 --- a/generic/tclThread.c +++ b/generic/tclThread.c @@ -254,6 +254,7 @@ TclRememberMutex( *---------------------------------------------------------------------- */ +#undef Tcl_MutexFinalize void Tcl_MutexFinalize( Tcl_Mutex *mutexPtr) @@ -307,6 +308,7 @@ TclRememberCondition( *---------------------------------------------------------------------- */ +#undef Tcl_ConditionFinalize void Tcl_ConditionFinalize( Tcl_Condition *condPtr) @@ -458,9 +460,7 @@ Tcl_ExitThread( int status) { Tcl_FinalizeThread(); -#if TCL_THREADS TclpThreadExit(status); -#endif } #if !TCL_THREADS diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c index 6ea258f..24c269d 100644 --- a/unix/tclUnixThrd.c +++ b/unix/tclUnixThrd.c @@ -166,7 +166,6 @@ Tcl_JoinThread( #endif } -#if TCL_THREADS /* *---------------------------------------------------------------------- * @@ -187,9 +186,12 @@ void TclpThreadExit( int status) { +#if TCL_THREADS pthread_exit(INT2PTR(status)); -} +#else /* TCL_THREADS */ + exit(status); #endif /* TCL_THREADS */ +} /* *---------------------------------------------------------------------- -- cgit v0.12