Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch novem-no-startcmd Excluding Merge-Ins
This is equivalent to a diff from 59f4f6914f to fc2438ef5f
2013-01-30
| ||
08:19 | merge changes from trunk Closed-Leaf check-in: fc2438ef5f user: dkf tags: novem-no-startcmd | |
07:30 | more style enforcement check-in: 4fbe0cedaf user: dkf tags: novem-no-startcmd | |
2013-01-29
| ||
09:24 | Remove one trampoline bounce in EvalObjv. Leaf check-in: 6201c0ec53 user: mig tags: mig-retest | |
2012-12-04
| ||
14:28 | merge check-in: 7d3e4d8977 user: dkf tags: novem-no-startcmd | |
14:28 | merge main novem branch Closed-Leaf check-in: 59f4f6914f user: dkf tags: novem-reduced-bytecodes | |
13:40 | merge trunk check-in: ab905bcfdc user: jan.nijtmans tags: novem | |
2012-11-30
| ||
07:55 | Improve behavior when exception ranges need retraction. check-in: bcd72865d9 user: dkf tags: novem-reduced-bytecodes | |
Changes to ChangeLog.
1 2 3 4 5 6 7 8 9 | 2012-11-28 Donal K. Fellows <[email protected]> * generic/tclZlib.c (ZlibStreamSubcmd): [Bug 3590483]: Use a mechanism for complex option resolution that has fewer problems with more finicky compilers. 2012-11-26 Reinhard Max <[email protected]> * unix/tclUnixSock.c: Factor out creation of the -sockname and | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 | 2013-01-28 Donal K. Fellows <[email protected]> * generic/tclCompCmds.c (TclCompileArraySetCmd) (TclCompileArrayUnsetCmd, TclCompileDictAppendCmd) (TclCompileDictCreateCmd, CompileDictEachCmd, TclCompileDictIncrCmd) (TclCompileDictLappendCmd, TclCompileDictMergeCmd) (TclCompileDictUnsetCmd, TclCompileDictUpdateCmd) (TclCompileDictWithCmd, TclCompileInfoCommandsCmd): * generic/tclCompCmdsSZ.c (TclCompileStringMatchCmd) (TclCompileStringMapCmd): Improve the code generation in cases where full compilation is impossible but a full ensemble invoke is provably not necessary. 2013-01-26 Jan Nijtmans <[email protected]> * unix/tclUnixCompat.c: [Bug 3601804]: platformCPUID segmentation fault on Darwin. 2013-01-23 Donal K. Fellows <[email protected]> * library/http/http.tcl (http::geturl): [Bug 2911139]: Do not do vwait for connect to avoid reentrancy problems (except when operating without a -command option). Internally, this means that all sockets created by the http package will always be operated in asynchronous mode. 2013-01-21 Jan Nijtmans <[email protected]> * generic/tclInt.decls: Put back Tcl[GS]etStartupScript(Path|FileName) in private stub table, so extensions using this (like Tk 8.4) will continue to work in all Tcl 8.x versions. Extensions using this still cannot be compiled against Tcl 8.6 headers. 2013-01-18 Jan Nijtmans <[email protected]> * generic/tclPort.h: [Bug 3598300]: unix: tcl.h does not include sys/stat.h 2013-01-17 Donal K. Fellows <[email protected]> * generic/tclCompCmds.c (PushVarName): [Bug 3600328]: Added mechanism for suppressing compilation of variables when we couldn't cope with the results. Useful for some [array] subcommands. * generic/tclEnsemble.c (CompileToCompiledCommand): Must restore the compilation environment when a command compiler fails. 2013-01-16 Donal K. Fellows <[email protected]> * generic/tclZlib.c (TclZlibInit): [Bug 3601086]: Register the config info in the iso8859-1 encoding as that is guaranteed to be present. 2013-01-16 Jan Nijtmans <[email protected]> * Makefile.in: Allow win32 build with -DTCL_NO_DEPRECATED, just as * generic/tcl.h: in the UNIX build. Define Tcl_EvalObj and * generic/tclDecls.h: Tcl_GlobalEvalObj as macros, even when * generic/tclBasic.c: TCL_NO_DEPRECATED is defined, so Tk can benefit from it too. 2013-01-14 Jan Nijtmans <[email protected]> * win/tcl.m4: More flexible search for win32 tclConfig.sh, backported from TEA (not actually used in Tcl, only for Tk) 2013-01-14 Jan Nijtmans <[email protected]> * generic/tclInt.decls: Put back Tcl_[GS]etStartupScript in internal stub table, so extensions using this, compiled against 8.5 headers still run in Tcl 8.6. 2013-01-13 Alexandre Ferrieux <[email protected]> * doc/fileevent.n: [Bug 3436609]: Clarify readable fileevent "false positives" in the case of multibyte encodings/transforms. 2013-01-13 Jan Nijtmans <[email protected]> * generic/tclIntDecls.h: If TCL_NO_DEPRECATED is defined, make sure that TIP #139 functions all are taken from the public stub table, even if the inclusion is through tclInt.h. 2013-01-12 Jan Nijtmans <[email protected]> * generic/tclInt.decls: Put back TclBackgroundException in internal stub table, so extensions using this, compiled against 8.5 headers still run in Tcl 8.6. 2013-01-09 Jan Nijtmans <[email protected]> * library/http/http.tcl: [Bug 3599395]: http assumes status line is a proper Tcl list. 2013-01-08 Jan Nijtmans <[email protected]> * win/tclWinFile.c: [Bug 3092089]: [file normalize] can remove path components. [Bug 3587096] win vista/7: "can't find init.tcl" when called via junction without folder list access. 2013-01-07 Jan Nijtmans <[email protected]> * generic/tclOOStubLib.c: Restrict the stub library to only use * generic/tclTomMathStubLib.c: Tcl_PkgRequireEx, Tcl_ResetResult and Tcl_AppendResult, not any other function. This puts least restrictions on eventual Tcl 9 stubs re-organization, and it works on the widest range of Tcl versions. 2013-01-06 Jan Nijtmans <[email protected]> * library/http/http.tcl: Don't depend on Spencer-specific regexp * tests/env.test: syntax (/u and /U) any more in unrelated places. * tests/exec.test: Bump http package to 2.8.6. 2013-01-04 Donal K. Fellows <[email protected]> * generic/tclEnsemble.c (CompileBasicNArgCommand): Added very simple compiler (which just compiles to a normal invoke of the implementation command) for many ensemble subcommands where we can prove that there is no way for scripts to detect the difference even through error handling or [info level]/[info frame]. This improves the code produced from some ensembles (e.g., [info], [string]) to the point where the ensemble is now not normally seen at the bytecode level at all. 2013-01-04 Miguel Sofer <[email protected]> * generic/tclInt.h: Insure that PURIFY builds cannot exploit the * generic/tclExecute.c: Tcl stack to hide mem defects. 2013-01-03 Donal K. Fellows <[email protected]> * doc/fconfigure.n, doc/CrtChannel.3: Updated to reflect the fact that the minimum buffer size is one byte, not ten. Identified by Schelte Bron on the Tcler's Chat. * generic/tclExecute.c (TEBCresume:INST_INVOKE_REPLACE): * generic/tclEnsemble.c (TclCompileEnsemble): Added new mechanism to allow for more efficient dispatch of non-bytecode-compiled subcommands of bytecode-compiled ensembles. This can provide substantial speed benefits in some cases. 2013-01-02 Miguel Sofer <[email protected]> * generic/tclEnsemble.c: Remove stray calls to Tcl_Alloc and friends: * generic/tclExecute.c: the core should only use ckalloc to allow * generic/tclIORTrans.c: MEM_DEBUG to work properly. * generic/tclTomMathInterface.c: 2012-12-31 Donal K. Fellows <[email protected]> * doc/string.n: Noted the obsolescence of the 'bytelength', 'wordstart' and 'wordend' subcommands, and moved them to later in the file. 2012-12-27 Jan Nijtmans <[email protected]> * generic/tclListObj.c: [Bug 3598580]: Tcl_ListObjReplace may release deleted elements too early. 2012-12-22 Alexandre Ferrieux <[email protected]> * generic/tclUtil.c: Stop leaking allocated space when objifying a zero-length DString. [Bug 3598150] spotted by afredd. 2012-12-21 Jan Nijtmans <[email protected]> * unix/dltest/pkgb.c: Inline compat Tcl_GetDefaultEncodingDir. * generic/tclStubLib.c: Eliminate unnecessary static HasStubSupport() and isDigit() functions, just do the same inline. 2012-12-18 Donal K. Fellows <[email protected]> * generic/tclCompCmdsSZ.c (TclSubstCompile): Improved the sequence of instructions issued for [subst] when dealing with simple variable references. 2012-12-14 Don Porter <[email protected]> *** 8.6.0 TAGGED FOR RELEASE *** * changes: updates for 8.6.0 2012-12-13 Don Porter <[email protected]> * generic/tclZlib.c: Repair same issue with misusing the * tests/zlib.test: 'fire and forget' nature of Tcl_ObjSetVar2 in the new TIP 400 implementation. 2012-12-13 Miguel Sofer <[email protected]> * generic/tclCmdAH.c: (CatchObjCmdCallback): do not decrRefCount * tests/cmdAH.test: the newValuePtr sent to Tcl_ObjSetVar2: TOSV2 is 'fire and forget', it decrs on its own. Fix for [Bug 3595576], found by andrewsh. 2012-12-13 Jan Nijtmans <[email protected]> * generic/tcl.h: Fix Tcl_DecrRefCount macro such that it doesn't access its objPtr parameter twice any more. 2012-12-11 Don Porter <[email protected]> * generic/tcl.h: Bump version number to 8.6.0. * library/init.tcl: * unix/configure.in: * win/configure.in: * unix/tcl.spec: * README: * unix/configure: autoconf-2.59 * win/configure: 2012-12-10 Donal K. Fellows <[email protected]> * tools/tcltk-man2html.tcl (plus-pkgs): Increased robustness of version number detection code to deal with packages whose names are prefixes of other packages. * unix/Makefile.in (dist): Added pkgs/package.list.txt to distribution builds to ensure that 'make html' will work better. 2012-12-09 Alexandre Ferrieux <[email protected]> * tests/chan.test: Clean up unwanted eofchar side-effect of chan-4.6 leading to a spurious "'" at end of chan.test under certain conditions (see [Bug 3389289] and [Bug 3389251]). * doc/expr.n: [Bug 3594188]: Clarifications about commas. 2012-12-08 Alexandre Ferrieux <[email protected]> * generic/tclIO.c: Fix busyloop at exit under TCL_FINALIZE_ON_EXIT when there are unflushed nonblocking channels. Thanks Miguel for spotting. 2012-12-07 Jan Nijtmans <[email protected]> * unix/dltest/pkgb.c: Turn pkgb.so into a Tcl9 interoperability test library: Whatever Tcl9 looks like, loading pkgb.so in Tcl 9 should either result in an error-message, either succeed, but never crash. 2012-11-28 Donal K. Fellows <[email protected]> * generic/tclZlib.c (ZlibStreamSubcmd): [Bug 3590483]: Use a mechanism for complex option resolution that has fewer problems with more finicky compilers. 2012-11-26 Reinhard Max <[email protected]> * unix/tclUnixSock.c: Factor out creation of the -sockname and -peername lists from TcpGetOptionProc() to TcpHostPortList(). Make it robust against implementations of getnameinfo() that error out if reverse mapping fails instead of falling back to the numeric representation. 2012-11-20 Donal K. Fellows <[email protected]> * generic/tclBinary.c (BinaryDecode64): [Bug 3033307]: Corrected handling of trailing whitespace when decoding base64. Thanks to Anton Kovalenko for reporting, and Andy Goth for the fix and tests. |
︙ | ︙ | |||
3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 | * tools/genStubs.tcl: [Patch 3034251]: Backport ttkGenStubs.tcl features to genStubs.tcl, partly: remove unneeded ifdeffery and put C++ guard around stubs pointer definition. * generic/*Decls.h: (regenerated) 2010-08-18 Miguel Sofer <[email protected]> * generic/tclBasic.c: New redesign of [tailcall]: find * generic/tclExecute.c: errors early on, so that errorInfo * generic/tclInt.h: contains the proper info [Bug 3047235] * generic/tclNamesp.c: * generic/tclCmdAH.c (TclNRTryObjCmd): [Bug 3046594]: Block tailcalling out of the body of a non-bc'ed [try]. | > | 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 | * tools/genStubs.tcl: [Patch 3034251]: Backport ttkGenStubs.tcl features to genStubs.tcl, partly: remove unneeded ifdeffery and put C++ guard around stubs pointer definition. * generic/*Decls.h: (regenerated) 2010-08-18 Miguel Sofer <[email protected]> * generic/tclBasic.c: New redesign of [tailcall]: find * generic/tclExecute.c: errors early on, so that errorInfo * generic/tclInt.h: contains the proper info [Bug 3047235] * generic/tclNamesp.c: * generic/tclCmdAH.c (TclNRTryObjCmd): [Bug 3046594]: Block tailcalling out of the body of a non-bc'ed [try]. |
︙ | ︙ |
Changes to changes.
︙ | ︙ | |||
8113 8114 8115 8116 8117 8118 8119 8120 8121 8122 8123 8124 8125 8126 | Many revisions to better support a Cygwin environment (nijtmans) Dropped support for OS X versions less than 10.4 (Tiger) (fellows) --- Released 8.6b3, September 18, 2012 --- See ChangeLog for details --- 2012-10-03 (bug fix) exit panic on stacked std channel (griffin,porter) 2012-10-14 (bug fix) [tcl::Bgerror] crash on non-dict options (nijtmans) 2012-11-06 (bug fix)[3581754] avoid multiple callback on keep-alive (fellows) => http 2.8.5 | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 8113 8114 8115 8116 8117 8118 8119 8120 8121 8122 8123 8124 8125 8126 8127 8128 8129 8130 8131 8132 8133 8134 8135 8136 8137 8138 8139 8140 8141 8142 8143 8144 8145 8146 8147 8148 8149 8150 8151 8152 8153 8154 8155 8156 8157 8158 8159 8160 8161 8162 8163 8164 8165 | Many revisions to better support a Cygwin environment (nijtmans) Dropped support for OS X versions less than 10.4 (Tiger) (fellows) --- Released 8.6b3, September 18, 2012 --- See ChangeLog for details --- 2012-09-20 (enhancement) full Unicode support (nijtmans) => dde 1.4.0 2012-09-20 (enhancement) update bundled zlib to 1.2.7 (nijtmans) 2012-10-03 (bug fix) exit panic on stacked std channel (griffin,porter) 2012-10-14 (bug fix) [tcl::Bgerror] crash on non-dict options (nijtmans) 2012-10-16 (TIP 400) New [zlib] options to set compression dict (fellows) 2012-10-16 (TIP 405) New commands [lmap] and [dict map] (fellows) 2012-10-24 (enhancement) [dict unset] now bytecompiled (fellows) 2012-11-05 (TIP 413) Revisions to default [string trim*] trimset (nijtmans) *** POTENTIAL INCOMPATIBILITY *** 2012-11-05 (enhancement) Now bytecompiled: [array exists], [array set], [array unset], [dict create], [dict exists], [dict merge], [format], [info commands], [info coroutine], [info level], [info object], [namespace current], [namespace code], [namespace qualifiers], [namespace tail], [namespace which], [regsub], [self], [string first], [string last], [string map], [string range], [tailcall], [yield]. (fellows) 2012-11-06 (bug fix)[3581754] avoid multiple callback on keep-alive (fellows) => http 2.8.5 2012-11-07 tzdata updated to Olson's tzdata2012i (kenny) 2012-11-13 (bug fix)[3567063] thread fp settings from master (mistachkin) 2012-11-14 (bug fix)[2933003] tempfile creation in $TMPDIR (fellows) 2012-11-15 (TIP 416) New [load] options -global and -lazy (nijtmans) 2012-11-20 (bug fix)[3033307] base64 trail whitespace (kovalenko,goth) 2012-12-03 (bug fix) [configure] query broke init from argv (porter) => tcltest 2.3.5 2012-12-13 (bug fix)[3595576] crash: [catch {} -> noSuchNs::var] (sofer,porter) 2012-12-13 (bug fix) crash: [zlib gunzip $data -header noSuchNs::var] (porter) --- Released 8.6.0, December 20, 2012 --- See ChangeLog for details --- |
Changes to compat/dirent2.h.
︙ | ︙ | |||
10 11 12 13 14 15 16 | * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _DIRENT #define _DIRENT | < < | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _DIRENT #define _DIRENT /* * Dirent structure, which holds information about a single * directory entry. */ #define MAXNAMLEN 255 #define DIRBLKSIZ 512 |
︙ | ︙ |
Changes to compat/dlfcn.h.
︙ | ︙ | |||
22 23 24 25 26 27 28 | * This is an unpublished work copyright (c) 1992 HELIOS Software GmbH * 30159 Hannover, Germany */ #ifndef __dlfcn_h__ #define __dlfcn_h__ | < < | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | * This is an unpublished work copyright (c) 1992 HELIOS Software GmbH * 30159 Hannover, Germany */ #ifndef __dlfcn_h__ #define __dlfcn_h__ #ifdef __cplusplus extern "C" { #endif /* * Mode flags for the dlopen routine. */ |
︙ | ︙ |
Changes to compat/string.h.
︙ | ︙ | |||
9 10 11 12 13 14 15 | * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _STRING #define _STRING | < < | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _STRING #define _STRING /* * The following #include is needed to define size_t. (This used to include * sys/stdtypes.h but that doesn't exist on older versions of SunOS, e.g. * 4.0.2, so I'm trying sys/types.h now.... hopefully it exists everywhere) */ #include <sys/types.h> |
︙ | ︙ |
Changes to compat/unistd.h.
︙ | ︙ | |||
10 11 12 13 14 15 16 | * no representations about the suitability of this software for any purpose. * It is provided "as is" without express or implied warranty. */ #ifndef _UNISTD #define _UNISTD | < | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | * no representations about the suitability of this software for any purpose. * It is provided "as is" without express or implied warranty. */ #ifndef _UNISTD #define _UNISTD #include <sys/types.h> #ifndef NULL #define NULL 0 #endif /* |
︙ | ︙ |
Changes to doc/CrtChannel.3.
︙ | ︙ | |||
246 247 248 249 250 251 252 | \fBTcl_GetChannelBufferSize\fR returns the size, in bytes, of buffers allocated to store input or output in \fIchannel\fR. If the value was not set by a previous call to \fBTcl_SetChannelBufferSize\fR, described below, then the default value of 4096 is returned. .PP \fBTcl_SetChannelBufferSize\fR sets the size, in bytes, of buffers that will be allocated in subsequent operations on the channel to store input or | | | | 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 | \fBTcl_GetChannelBufferSize\fR returns the size, in bytes, of buffers allocated to store input or output in \fIchannel\fR. If the value was not set by a previous call to \fBTcl_SetChannelBufferSize\fR, described below, then the default value of 4096 is returned. .PP \fBTcl_SetChannelBufferSize\fR sets the size, in bytes, of buffers that will be allocated in subsequent operations on the channel to store input or output. The \fIsize\fR argument should be between one and one million, allowing buffers of one byte to one million bytes. If \fIsize\fR is outside this range, \fBTcl_SetChannelBufferSize\fR sets the buffer size to 4096. .PP \fBTcl_NotifyChannel\fR is called by a channel driver to indicate to the generic layer that the events specified by \fImask\fR have occurred on the channel. Channel drivers are responsible for invoking this function whenever the channel handlers need to be called for the |
︙ | ︙ |
Changes to doc/InitStubs.3.
︙ | ︙ | |||
59 60 61 62 63 64 65 | Call \fBTcl_InitStubs\fR in the extension before calling any other Tcl functions. .IP 2) 5 Define the \fBUSE_TCL_STUBS\fR symbol. Typically, you would include the \fB\-DUSE_TCL_STUBS\fR flag when compiling the extension. .IP 3) 5 Link the extension with the Tcl stubs library instead of the standard | | | | | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | Call \fBTcl_InitStubs\fR in the extension before calling any other Tcl functions. .IP 2) 5 Define the \fBUSE_TCL_STUBS\fR symbol. Typically, you would include the \fB\-DUSE_TCL_STUBS\fR flag when compiling the extension. .IP 3) 5 Link the extension with the Tcl stubs library instead of the standard Tcl library. For example, to use the Tcl 8.6 ABI on Unix platforms, the library name is \fIlibtclstub8.6.a\fR; on Windows platforms, the library name is \fItclstub86.lib\fR. .PP If the extension also requires the Tk API, it must also call \fBTk_InitStubs\fR to initialize the Tk stubs interface and link with the Tk stubs libraries. See the \fBTk_InitStubs\fR page for more information. .SH DESCRIPTION \fBTcl_InitStubs\fR attempts to initialize the stub table pointers |
︙ | ︙ |
Changes to doc/NRE.3.
︙ | ︙ | |||
291 292 293 294 295 296 297 | int \fITheCmdNRPostProc\fR( ClientData data[], Tcl_Interp *interp, int result) { /* \fIdata[0] .. data[3]\fR are the four words of data | | | 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 | int \fITheCmdNRPostProc\fR( ClientData data[], Tcl_Interp *interp, int result) { /* \fIdata[0] .. data[3]\fR are the four words of data * passed to \fBTcl_NRAddCallback\fR */ \fI... postprocessing ...\fR return result; } .CE .PP |
︙ | ︙ |
Changes to doc/expr.n.
︙ | ︙ | |||
35 36 37 38 39 40 41 | Tcl expressions differ from C expressions in the way that operands are specified. Also, Tcl expressions support non-numeric operands and string comparisons, as well as some additional operators not found in C. .SS OPERANDS .PP A Tcl expression consists of a combination of operands, operators, | | | | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | Tcl expressions differ from C expressions in the way that operands are specified. Also, Tcl expressions support non-numeric operands and string comparisons, as well as some additional operators not found in C. .SS OPERANDS .PP A Tcl expression consists of a combination of operands, operators, parentheses and commas. White space may be used between the operands and operators and parentheses (or commas); it is ignored by the expression's instructions. Where possible, operands are interpreted as integer values. Integer values may be specified in decimal (the normal case), in binary (if the first two characters of the operand are \fB0b\fR), in octal (if the first two characters of the operand are \fB0o\fR), or in hexadecimal (if the first two characters of the operand are \fB0x\fR). If an operand does not have one of the integer formats given above, then it is treated as a floating-point number if that is |
︙ | ︙ | |||
275 276 277 278 279 280 281 282 283 284 285 286 287 288 | .CE .PP The executor will search for \fBtcl::mathfunc::sin\fR using the usual rules for resolving functions in namespaces. Either \fB::tcl::mathfunc::sin\fR or \fB[namespace current]::tcl::mathfunc::sin\fR will satisfy the request, and others may as well (depending on the current \fBnamespace path\fR setting). .PP See the \fBmathfunc\fR(n) manual page for the math functions that are available by default. .SS "TYPES, OVERFLOW, AND PRECISION" .PP All internal computations involving integers are done calling on the LibTomMath multiple precision integer library as required so that all | > > > > > > > > > > > > | 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 | .CE .PP The executor will search for \fBtcl::mathfunc::sin\fR using the usual rules for resolving functions in namespaces. Either \fB::tcl::mathfunc::sin\fR or \fB[namespace current]::tcl::mathfunc::sin\fR will satisfy the request, and others may as well (depending on the current \fBnamespace path\fR setting). .PP Some mathematical functions have several arguments, separated by commas like in C. Thus: .PP .CS \fBexpr\fR {hypot($x,$y)} .CE .PP ends up as .PP .CS tcl::mathfunc::hypot $x $y .CE .PP See the \fBmathfunc\fR(n) manual page for the math functions that are available by default. .SS "TYPES, OVERFLOW, AND PRECISION" .PP All internal computations involving integers are done calling on the LibTomMath multiple precision integer library as required so that all |
︙ | ︙ |
Changes to doc/fconfigure.n.
︙ | ︙ | |||
68 69 70 71 72 73 74 | is \fBline\fR. Additionally, \fBstdin\fR and \fBstdout\fR are initially set to \fBline\fR, and \fBstderr\fR is set to \fBnone\fR. .TP \fB\-buffersize\fR \fInewSize\fR . \fINewvalue\fR must be an integer; its value is used to set the size of buffers, in bytes, subsequently allocated for this channel to store input | | | | 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | is \fBline\fR. Additionally, \fBstdin\fR and \fBstdout\fR are initially set to \fBline\fR, and \fBstderr\fR is set to \fBnone\fR. .TP \fB\-buffersize\fR \fInewSize\fR . \fINewvalue\fR must be an integer; its value is used to set the size of buffers, in bytes, subsequently allocated for this channel to store input or output. \fINewvalue\fR must be between one and one million, allowing buffers of one to one million bytes in size. .TP \fB\-encoding\fR \fIname\fR . This option is used to specify the encoding of the channel, so that the data can be converted to and from Unicode for use in Tcl. For instance, in order for Tcl to read characters from a Japanese file in \fBshiftjis\fR and properly process and display the contents, the encoding would be set |
︙ | ︙ |
Changes to doc/fileevent.n.
︙ | ︙ | |||
76 77 78 79 80 81 82 | check for end of file, an infinite loop may occur where \fIscript\fR reads no data, returns, and is immediately invoked again. .PP A channel is considered to be writable if at least one byte of data can be written to the underlying file or device without blocking, or if an error condition is present on the underlying file or device. .PP | | | | | | > > > | | | 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | check for end of file, an infinite loop may occur where \fIscript\fR reads no data, returns, and is immediately invoked again. .PP A channel is considered to be writable if at least one byte of data can be written to the underlying file or device without blocking, or if an error condition is present on the underlying file or device. .PP Event-driven I/O works best for channels that have been placed into nonblocking mode with the \fBfconfigure\fR command. In blocking mode, a \fBputs\fR command may block if you give it more data than the underlying file or device can accept, and a \fBgets\fR or \fBread\fR command will block if you attempt to read more data than is ready; a readable underlying file or device may not even guarantee that a blocking [read 1] will succeed (counter-examples being multi-byte encodings, compression or encryption transforms ). In all such cases, no events will be processed while the commands block. .PP In nonblocking mode \fBputs\fR, \fBread\fR, and \fBgets\fR never block. See the documentation for the individual commands for information on how they handle blocking and nonblocking channels. .PP Testing for the end of file condition should be done after any attempts read the channel data. The eof flag is set once an attempt to read the end of data has occurred and testing before this read will require an |
︙ | ︙ |
Changes to doc/namespace.n.
︙ | ︙ | |||
283 284 285 286 287 288 289 | For the \fIstring\fR \fB::foo::bar::x\fR, this command returns \fBx\fR, and for \fB::\fR it returns an empty string. This command is the complement of the \fBnamespace qualifiers\fR command. It does not check whether the namespace names are, in fact, the names of currently defined namespaces. .TP | | | 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 | For the \fIstring\fR \fB::foo::bar::x\fR, this command returns \fBx\fR, and for \fB::\fR it returns an empty string. This command is the complement of the \fBnamespace qualifiers\fR command. It does not check whether the namespace names are, in fact, the names of currently defined namespaces. .TP \fBnamespace upvar\fR \fInamespace\fR ?\fIotherVar myVar \fR...? . This command arranges for zero or more local variables in the current procedure to refer to variables in \fInamespace\fR. The namespace name is resolved as described in section \fBNAME RESOLUTION\fR. The command \fBnamespace upvar $ns a b\fR has the same behaviour as \fBupvar 0 ${ns}::a b\fR, with the sole exception of the resolution rules |
︙ | ︙ |
Changes to doc/string.n.
︙ | ︙ | |||
15 16 17 18 19 20 21 | \fBstring \fIoption arg \fR?\fIarg ...?\fR .BE .SH DESCRIPTION .PP Performs one of several string operations, depending on \fIoption\fR. The legal \fIoption\fRs (which may be abbreviated) are: .TP | < < < < < < < < < < < < < < < < < < < < | | | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | \fBstring \fIoption arg \fR?\fIarg ...?\fR .BE .SH DESCRIPTION .PP Performs one of several string operations, depending on \fIoption\fR. The legal \fIoption\fRs (which may be abbreviated) are: .TP \fBstring compare\fR ?\fB\-nocase\fR? ?\fB\-length\fI length\fR? \fIstring1 string2\fR . Perform a character-by-character comparison of strings \fIstring1\fR and \fIstring2\fR. Returns \-1, 0, or 1, depending on whether \fIstring1\fR is lexicographically less than, equal to, or greater than \fIstring2\fR. If \fB\-length\fR is specified, then only the first \fIlength\fR characters are used in the comparison. If \fB\-length\fR is negative, it is ignored. If \fB\-nocase\fR is specified, then the strings are compared in a case-insensitive manner. .TP \fBstring equal\fR ?\fB\-nocase\fR? ?\fB\-length\fI length\fR? \fIstring1 string2\fR . Perform a character-by-character comparison of strings \fIstring1\fR and \fIstring2\fR. Returns 1 if \fIstring1\fR and \fIstring2\fR are identical, or 0 when not. If \fB\-length\fR is specified, then only the first \fIlength\fR characters are used in the comparison. If \fB\-length\fR is negative, it is ignored. If \fB\-nocase\fR is specified, then the strings are compared in a case-insensitive manner. |
︙ | ︙ | |||
350 351 352 353 354 355 356 357 358 359 360 361 362 363 | .TP \fBstring trimright \fIstring\fR ?\fIchars\fR? . Returns a value equal to \fIstring\fR except that any trailing characters present in the string given by \fIchars\fR are removed. If \fIchars\fR is not specified then white space is removed (any character for which \fBstring is space\fR returns 1, and "\0"). .TP \fBstring wordend \fIstring charIndex\fR . Returns the index of the character just after the last one in the word containing character \fIcharIndex\fR of \fIstring\fR. \fIcharIndex\fR may be specified using the forms in \fBSTRING INDICES\fR. A word is considered to be any contiguous range of alphanumeric (Unicode letters | > > > > > > > > > > > > > > > > > > > > > > > > > | 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 | .TP \fBstring trimright \fIstring\fR ?\fIchars\fR? . Returns a value equal to \fIstring\fR except that any trailing characters present in the string given by \fIchars\fR are removed. If \fIchars\fR is not specified then white space is removed (any character for which \fBstring is space\fR returns 1, and "\0"). .SS "OBSOLETE SUBCOMMANDS" .PP These subcommands are currently supported, but are likely to go away in a future release as their functionality is either virtually never used or highly misleading. .TP \fBstring bytelength \fIstring\fR . Returns a decimal string giving the number of bytes used to represent \fIstring\fR in memory. Because UTF\-8 uses one to three bytes to represent Unicode characters, the byte length will not be the same as the character length in general. The cases where a script cares about the byte length are rare. .RS .PP In almost all cases, you should use the \fBstring length\fR operation (including determining the length of a Tcl byte array value). Refer to the \fBTcl_NumUtfChars\fR manual entry for more details on the UTF\-8 representation. .PP \fICompatibility note:\fR it is likely that this subcommand will be withdrawn in a future version of Tcl. It is better to use the \fBencoding convertto\fR command to convert a string to a known encoding and then apply \fBstring length\fR to that. .RE .TP \fBstring wordend \fIstring charIndex\fR . Returns the index of the character just after the last one in the word containing character \fIcharIndex\fR of \fIstring\fR. \fIcharIndex\fR may be specified using the forms in \fBSTRING INDICES\fR. A word is considered to be any contiguous range of alphanumeric (Unicode letters |
︙ | ︙ |
Changes to generic/tcl.h.
︙ | ︙ | |||
345 346 347 348 349 350 351 | /* Here is a 4-byte gap */ long long st_size; struct {long tv_sec;} st_atim; struct {long tv_sec;} st_mtim; struct {long tv_sec;} st_ctim; /* Here is a 4-byte gap */ } Tcl_StatBuf; | | | 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 | /* Here is a 4-byte gap */ long long st_size; struct {long tv_sec;} st_atim; struct {long tv_sec;} st_mtim; struct {long tv_sec;} st_ctim; /* Here is a 4-byte gap */ } Tcl_StatBuf; #elif defined(HAVE_STRUCT_STAT64) && !defined(__APPLE__) typedef struct stat64 Tcl_StatBuf; #else typedef struct stat Tcl_StatBuf; #endif /* *---------------------------------------------------------------------------- |
︙ | ︙ | |||
677 678 679 680 681 682 683 | } Tcl_Obj; /* * Macros to increment and decrement a Tcl_Obj's reference count, and to test * whether an object is shared (i.e. has reference count > 1). Note: clients * should use Tcl_DecrRefCount() when they are finished using an object, and * should never call TclFreeObj() directly. TclFreeObj() is only defined and | | < < < | 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 | } Tcl_Obj; /* * Macros to increment and decrement a Tcl_Obj's reference count, and to test * whether an object is shared (i.e. has reference count > 1). Note: clients * should use Tcl_DecrRefCount() when they are finished using an object, and * should never call TclFreeObj() directly. TclFreeObj() is only defined and * made public in tcl.h to support Tcl_DecrRefCount's macro definition. */ void Tcl_IncrRefCount(Tcl_Obj *objPtr); void Tcl_DecrRefCount(Tcl_Obj *objPtr); int Tcl_IsShared(Tcl_Obj *objPtr); /* |
︙ | ︙ | |||
2306 2307 2308 2309 2310 2311 2312 | # define Tcl_IncrRefCount(objPtr) \ ++(objPtr)->refCount /* * Use do/while0 idiom for optimum correctness without compiler warnings. * http://c2.com/cgi/wiki?TrivialDoWhileLoop */ # define Tcl_DecrRefCount(objPtr) \ | > > | > > > | 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 | # define Tcl_IncrRefCount(objPtr) \ ++(objPtr)->refCount /* * Use do/while0 idiom for optimum correctness without compiler warnings. * http://c2.com/cgi/wiki?TrivialDoWhileLoop */ # define Tcl_DecrRefCount(objPtr) \ do { \ Tcl_Obj *_objPtr = (objPtr); \ if (--(_objPtr)->refCount <= 0) { \ TclFreeObj(_objPtr); \ } \ } while(0) # define Tcl_IsShared(objPtr) \ ((objPtr)->refCount > 1) #endif /* * Macros and definitions that help to debug the use of Tcl objects. When * TCL_MEM_DEBUG is defined, the Tcl_New declarations are overridden to call |
︙ | ︙ | |||
2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 | * Deprecated Tcl functions: */ #ifndef TCL_NO_DEPRECATED # undef Tcl_EvalObj # define Tcl_EvalObj(interp,objPtr) \ Tcl_EvalObjEx((interp),(objPtr),0) #endif /* !TCL_NO_DEPRECATED */ #endif /* RC_INVOKED */ /* * end block for C++ | > > > | 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 | * Deprecated Tcl functions: */ #ifndef TCL_NO_DEPRECATED # undef Tcl_EvalObj # define Tcl_EvalObj(interp,objPtr) \ Tcl_EvalObjEx((interp),(objPtr),0) # undef Tcl_GlobalEvalObj # define Tcl_GlobalEvalObj(interp,objPtr) \ Tcl_EvalObjEx((interp),(objPtr),TCL_EVAL_GLOBAL) #endif /* !TCL_NO_DEPRECATED */ #endif /* RC_INVOKED */ /* * end block for C++ |
︙ | ︙ |
Changes to generic/tclAssembly.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | */ /*- *- THINGS TO DO: *- More instructions: *- done - alternate exit point (affects stack and exception range checking) *- break and continue - if exception ranges can be sorted out. | | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | */ /*- *- THINGS TO DO: *- More instructions: *- done - alternate exit point (affects stack and exception range checking) *- break and continue - if exception ranges can be sorted out. *- foreach_start, foreach_step *- returnImm, returnStk *- expandStart, expandStkTop, invokeExpanded *- dictFirst, dictNext *- dictUpdateStart, dictUpdateEnd *- jumpTable testing *- syntax (?) *- returnCodeBranch */ #include "tclInt.h" |
︙ | ︙ | |||
45 46 47 48 49 50 51 | * State identified for a basic block's catch context. */ typedef enum BasicBlockCatchState { BBCS_UNKNOWN = 0, /* Catch context has not yet been identified */ BBCS_NONE, /* Block is outside of any catch */ BBCS_INCATCH, /* Block is within a catch context */ | | | | | | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | * State identified for a basic block's catch context. */ typedef enum BasicBlockCatchState { BBCS_UNKNOWN = 0, /* Catch context has not yet been identified */ BBCS_NONE, /* Block is outside of any catch */ BBCS_INCATCH, /* Block is within a catch context */ BBCS_CAUGHT, /* Block is within a catch context and may be * executed after an exception fires */ } BasicBlockCatchState; /* * Structure that defines a basic block - a linear sequence of bytecode * instructions with no jumps in or out (including not changing the state of * any exception range). */ typedef struct BasicBlock { int originalStartOffset; /* Instruction offset before JUMP1s were * substituted with JUMP4's */ int startOffset; /* Instruction offset of the start of the * block */ |
︙ | ︙ | |||
129 130 131 132 133 134 135 | typedef enum TalInstType { ASSEM_1BYTE, /* Fixed arity, 1-byte instruction */ ASSEM_BEGIN_CATCH, /* Begin catch: one 4-byte jump offset to be * converted to appropriate exception * ranges */ ASSEM_BOOL, /* One Boolean operand */ | | | 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | typedef enum TalInstType { ASSEM_1BYTE, /* Fixed arity, 1-byte instruction */ ASSEM_BEGIN_CATCH, /* Begin catch: one 4-byte jump offset to be * converted to appropriate exception * ranges */ ASSEM_BOOL, /* One Boolean operand */ ASSEM_BOOL_LVT, /* One Boolean, one 4-byte LVT ref. */ ASSEM_CONCAT1, /* 1-byte unsigned-integer operand count, must * be strictly positive, consumes N, produces * 1 */ ASSEM_DICT_GET, /* 'dict get' and related - consumes N+1 * operands, produces 1, N > 0 */ ASSEM_DICT_SET, /* specifies key count and LVT index, consumes * N+1 operands, produces 1, N > 0 */ |
︙ | ︙ | |||
157 158 159 160 161 162 163 | * label */ ASSEM_LINDEX_MULTI, /* 4-byte operand count, must be strictly * positive, consumes N, produces 1 */ ASSEM_LIST, /* 4-byte operand count, must be nonnegative, * consumses N, produces 1 */ ASSEM_LSET_FLAT, /* 4-byte operand count, must be >= 3, * consumes N, produces 1 */ | | | | | 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | * label */ ASSEM_LINDEX_MULTI, /* 4-byte operand count, must be strictly * positive, consumes N, produces 1 */ ASSEM_LIST, /* 4-byte operand count, must be nonnegative, * consumses N, produces 1 */ ASSEM_LSET_FLAT, /* 4-byte operand count, must be >= 3, * consumes N, produces 1 */ ASSEM_LVT_SINT1, /* One 4-byte operand that references a local * variable, one signed-integer 1-byte * operand */ ASSEM_LVT, /* One 4-byte operand that references a local * variable */ ASSEM_OVER, /* OVER: 4-byte operand count, consumes N+1, * produces N+2 */ ASSEM_PUSH, /* one literal operand */ ASSEM_REGEXP, /* One Boolean operand, but weird mapping to * call flags */ ASSEM_REVERSE, /* REVERSE: 4-byte operand count, consumes N, * produces N */ ASSEM_SINT1, /* One 1-byte signed-integer operand * (INCR_STK_IMM) */ ASSEM_SINT4_LVT, /* Signed 4-byte integer operand followed by * LVT entry. Fixed arity */ } TalInstType; /* * Description of an instruction recognized by the assembler. */ |
︙ | ︙ | |||
309 310 311 312 313 314 315 | "assemblecode", FreeAssembleCodeInternalRep, /* freeIntRepProc */ DupAssembleCodeInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ NULL /* setFromAnyProc */ }; | < < < < < < < < < < < < < < < < < < < < < < < | | | | | | < | | > | | | | | < | < | | < | | | | | | | > | | | | > | < | | < < | < < | < | 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 | "assemblecode", FreeAssembleCodeInternalRep, /* freeIntRepProc */ DupAssembleCodeInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ NULL /* setFromAnyProc */ }; /* * Source instructions recognized in the Tcl Assembly Language (TAL) */ static const TalInstDesc TalInstructionTable[] = { /* PUSH must be first, see the code near the end of TclAssembleCode */ {"push", ASSEM_PUSH, INST_PUSH, 0, 1}, {"add", ASSEM_1BYTE, INST_ADD, 2, 1}, {"append", ASSEM_LVT, INST_APPEND_SCALAR, 1, 1}, {"appendArray", ASSEM_LVT, INST_APPEND_ARRAY, 2, 1}, {"appendArrayStk", ASSEM_1BYTE, INST_APPEND_ARRAY_STK, 3, 1}, {"appendStk", ASSEM_1BYTE, INST_APPEND_STK, 2, 1}, {"arrayExistsImm", ASSEM_LVT, INST_ARRAY_EXISTS_IMM, 0, 1}, {"arrayExistsStk", ASSEM_1BYTE, INST_ARRAY_EXISTS_STK, 1, 1}, {"arrayMakeImm", ASSEM_LVT, INST_ARRAY_MAKE_IMM, 0, 0}, {"arrayMakeStk", ASSEM_1BYTE, INST_ARRAY_MAKE_STK, 1, 0}, {"beginCatch", ASSEM_BEGIN_CATCH, INST_BEGIN_CATCH, 0, 0}, {"bitand", ASSEM_1BYTE, INST_BITAND, 2, 1}, {"bitnot", ASSEM_1BYTE, INST_BITNOT, 1, 1}, {"bitor", ASSEM_1BYTE, INST_BITOR, 2, 1}, {"bitxor", ASSEM_1BYTE, INST_BITXOR, 2, 1}, {"concat", ASSEM_CONCAT1, INST_CONCAT, INT_MIN,1}, {"coroName", ASSEM_1BYTE, INST_COROUTINE_NAME, 0, 1}, {"currentNamespace",ASSEM_1BYTE, INST_NS_CURRENT, 0, 1}, {"dictAppend", ASSEM_LVT, INST_DICT_APPEND, 2, 1}, {"dictExists", ASSEM_DICT_GET, INST_DICT_EXISTS, INT_MIN,1}, {"dictExpand", ASSEM_1BYTE, INST_DICT_EXPAND, 3, 1}, {"dictGet", ASSEM_DICT_GET, INST_DICT_GET, INT_MIN,1}, {"dictIncrImm", ASSEM_SINT4_LVT,INST_DICT_INCR_IMM, 1, 1}, {"dictLappend", ASSEM_LVT, INST_DICT_LAPPEND, 2, 1}, {"dictRecombineStk",ASSEM_1BYTE, INST_DICT_RECOMBINE_STK,3, 0}, {"dictRecombineImm",ASSEM_LVT, INST_DICT_RECOMBINE_IMM,2, 0}, {"dictSet", ASSEM_DICT_SET, INST_DICT_SET, INT_MIN,1}, {"dictUnset", ASSEM_DICT_UNSET, INST_DICT_UNSET, INT_MIN,1}, {"div", ASSEM_1BYTE, INST_DIV, 2, 1}, {"dup", ASSEM_1BYTE, INST_DUP, 1, 2}, {"endCatch", ASSEM_END_CATCH,INST_END_CATCH, 0, 0}, {"eq", ASSEM_1BYTE, INST_EQ, 2, 1}, {"eval", ASSEM_EVAL, INST_EVAL_STK, 1, 1}, {"evalStk", ASSEM_1BYTE, INST_EVAL_STK, 1, 1}, {"exch", ASSEM_1BYTE, INST_EXCH, 2, 2}, {"exist", ASSEM_LVT, INST_EXIST_SCALAR, 0, 1}, {"existArray", ASSEM_LVT, INST_EXIST_ARRAY, 1, 1}, {"existArrayStk", ASSEM_1BYTE, INST_EXIST_ARRAY_STK, 2, 1}, {"existStk", ASSEM_1BYTE, INST_EXIST_STK, 1, 1}, {"expon", ASSEM_1BYTE, INST_EXPON, 2, 1}, {"expr", ASSEM_EVAL, INST_EXPR_STK, 1, 1}, {"exprStk", ASSEM_1BYTE, INST_EXPR_STK, 1, 1}, {"ge", ASSEM_1BYTE, INST_GE, 2, 1}, {"gt", ASSEM_1BYTE, INST_GT, 2, 1}, {"incr", ASSEM_LVT, INST_INCR_SCALAR, 1, 1}, {"incrArray", ASSEM_LVT, INST_INCR_ARRAY, 2, 1}, {"incrArrayImm", ASSEM_LVT_SINT1,INST_INCR_ARRAY_IMM, 1, 1}, {"incrArrayStk", ASSEM_1BYTE, INST_INCR_ARRAY_STK, 3, 1}, {"incrArrayStkImm", ASSEM_SINT1, INST_INCR_ARRAY_STK_IMM,2, 1}, {"incrImm", ASSEM_LVT_SINT1,INST_INCR_SCALAR_IMM, 0, 1}, {"incrStk", ASSEM_1BYTE, INST_INCR_STK, 2, 1}, {"incrStkImm", ASSEM_SINT1, INST_INCR_STK_IMM, 1, 1}, {"infoLevelArgs", ASSEM_1BYTE, INST_INFO_LEVEL_ARGS, 1, 1}, {"infoLevelNumber", ASSEM_1BYTE, INST_INFO_LEVEL_NUM, 0, 1}, {"invokeStk", ASSEM_INVOKE, INST_INVOKE_STK, INT_MIN,1}, {"jump", ASSEM_JUMP, INST_JUMP, 0, 0}, {"jumpFalse", ASSEM_JUMP, INST_JUMP_FALSE, 1, 0}, {"jumpTable", ASSEM_JUMPTABLE,INST_JUMP_TABLE, 1, 0}, {"jumpTrue", ASSEM_JUMP, INST_JUMP_TRUE, 1, 0}, {"label", ASSEM_LABEL, 0, 0, 0}, {"land", ASSEM_1BYTE, INST_LAND, 2, 1}, {"lappend", ASSEM_LVT, INST_LAPPEND_SCALAR, 1, 1}, {"lappendArray", ASSEM_LVT, INST_LAPPEND_ARRAY, 2, 1}, {"lappendArrayStk", ASSEM_1BYTE, INST_LAPPEND_ARRAY_STK, 3, 1}, {"lappendStk", ASSEM_1BYTE, INST_LAPPEND_STK, 2, 1}, {"le", ASSEM_1BYTE, INST_LE, 2, 1}, {"lindexMulti", ASSEM_LINDEX_MULTI, INST_LIST_INDEX_MULTI, INT_MIN,1}, {"list", ASSEM_LIST, INST_LIST, INT_MIN,1}, {"listIn", ASSEM_1BYTE, INST_LIST_IN, 2, 1}, {"listIndex", ASSEM_1BYTE, INST_LIST_INDEX, 2, 1}, {"listIndexImm", ASSEM_INDEX, INST_LIST_INDEX_IMM, 1, 1}, {"listLength", ASSEM_1BYTE, INST_LIST_LENGTH, 1, 1}, {"listNotIn", ASSEM_1BYTE, INST_LIST_NOT_IN, 2, 1}, {"load", ASSEM_LVT, INST_LOAD_SCALAR, 0, 1}, {"loadArray", ASSEM_LVT, INST_LOAD_ARRAY, 1, 1}, {"loadArrayStk", ASSEM_1BYTE, INST_LOAD_ARRAY_STK, 2, 1}, {"loadStk", ASSEM_1BYTE, INST_LOAD_SCALAR_STK, 1, 1}, {"lor", ASSEM_1BYTE, INST_LOR, 2, 1}, {"lsetFlat", ASSEM_LSET_FLAT,INST_LSET_FLAT, INT_MIN,1}, {"lsetList", ASSEM_1BYTE, INST_LSET_LIST, 3, 1}, {"lshift", ASSEM_1BYTE, INST_LSHIFT, 2, 1}, {"lt", ASSEM_1BYTE, INST_LT, 2, 1}, {"mod", ASSEM_1BYTE, INST_MOD, 2, 1}, {"mult", ASSEM_1BYTE, INST_MULT, 2, 1}, {"neq", ASSEM_1BYTE, INST_NEQ, 2, 1}, {"nop", ASSEM_1BYTE, INST_NOP, 0, 0}, {"not", ASSEM_1BYTE, INST_LNOT, 1, 1}, {"nsupvar", ASSEM_LVT, INST_NSUPVAR, 2, 1}, {"over", ASSEM_OVER, INST_OVER, INT_MIN,-1-1}, {"pop", ASSEM_1BYTE, INST_POP, 1, 0}, {"pushReturnCode", ASSEM_1BYTE, INST_PUSH_RETURN_CODE, 0, 1}, {"pushReturnOpts", ASSEM_1BYTE, INST_PUSH_RETURN_OPTIONS, 0, 1}, {"pushResult", ASSEM_1BYTE, INST_PUSH_RESULT, 0, 1}, {"regexp", ASSEM_REGEXP, INST_REGEXP, 2, 1}, {"resolveCmd", ASSEM_1BYTE, INST_RESOLVE_COMMAND, 1, 1}, {"reverse", ASSEM_REVERSE, INST_REVERSE, INT_MIN,-1-0}, {"rshift", ASSEM_1BYTE, INST_RSHIFT, 2, 1}, {"store", ASSEM_LVT, INST_STORE_SCALAR, 1, 1}, {"storeArray", ASSEM_LVT, INST_STORE_ARRAY, 2, 1}, {"storeArrayStk", ASSEM_1BYTE, INST_STORE_ARRAY_STK, 3, 1}, {"storeStk", ASSEM_1BYTE, INST_STORE_SCALAR_STK, 2, 1}, {"strcmp", ASSEM_1BYTE, INST_STR_CMP, 2, 1}, {"streq", ASSEM_1BYTE, INST_STR_EQ, 2, 1}, {"strfind", ASSEM_1BYTE, INST_STR_FIND, 2, 1}, {"strindex", ASSEM_1BYTE, INST_STR_INDEX, 2, 1}, {"strlen", ASSEM_1BYTE, INST_STR_LEN, 1, 1}, {"strmap", ASSEM_1BYTE, INST_STR_MAP, 3, 1}, {"strmatch", ASSEM_BOOL, INST_STR_MATCH, 2, 1}, {"strneq", ASSEM_1BYTE, INST_STR_NEQ, 2, 1}, {"strrange", ASSEM_1BYTE, INST_STR_RANGE, 3, 1}, {"strrfind", ASSEM_1BYTE, INST_STR_FIND_LAST, 2, 1}, {"sub", ASSEM_1BYTE, INST_SUB, 2, 1}, {"tclooClass", ASSEM_1BYTE, INST_TCLOO_CLASS, 1, 1}, {"tclooIsObject", ASSEM_1BYTE, INST_TCLOO_IS_OBJECT, 1, 1}, {"tclooNamespace", ASSEM_1BYTE, INST_TCLOO_NS, 1, 1}, {"tclooSelf", ASSEM_1BYTE, INST_TCLOO_SELF, 0, 1}, {"tryCvtToNumeric", ASSEM_1BYTE, INST_TRY_CVT_TO_NUMERIC,1, 1}, {"uminus", ASSEM_1BYTE, INST_UMINUS, 1, 1}, {"under", ASSEM_1BYTE, INST_UNDER, 2, 3}, {"unset", ASSEM_BOOL_LVT, INST_UNSET_SCALAR, 0, 0}, {"unsetArray", ASSEM_BOOL_LVT, INST_UNSET_ARRAY, 1, 0}, {"unsetArrayStk", ASSEM_BOOL, INST_UNSET_ARRAY_STK, 2, 0}, {"unsetStk", ASSEM_BOOL, INST_UNSET_STK, 1, 0}, {"uplus", ASSEM_1BYTE, INST_UPLUS, 1, 1}, {"upvar", ASSEM_LVT, INST_UPVAR, 2, 1}, {"variable", ASSEM_LVT, INST_VARIABLE, 1, 0}, {"verifyDict", ASSEM_1BYTE, INST_DICT_VERIFY, 1, 0}, {"yield", ASSEM_1BYTE, INST_YIELD, 1, 1}, {NULL, 0, 0, 0, 0} }; /* * List of instructions that cannot throw an exception under any * circumstances. These instructions are the ones that are permissible after * an exception is caught but before the corresponding exception range is * popped from the stack. * * The instructions must be in ascending order by numeric operation code. */ static const unsigned char NonThrowingByteCodes[] = { INST_PUSH, INST_POP, INST_DUP, INST_JUMP, INST_END_CATCH, INST_PUSH_RESULT, INST_PUSH_RETURN_CODE, INST_PUSH_RETURN_OPTIONS, INST_OVER, INST_REVERSE, INST_NOP, INST_STR_MAP, INST_STR_FIND, INST_COROUTINE_NAME, INST_NS_CURRENT, INST_INFO_LEVEL_NUM, INST_RESOLVE_COMMAND, INST_EXCH, INST_UNDER }; /* * Helper macros. */ #if defined(TCL_DEBUG_ASSEMBLY) && defined(__GNUC__) && __GNUC__ > 2 |
︙ | ︙ | |||
729 730 731 732 733 734 735 | /* * On failure, report error line. */ if (codePtr == NULL) { Tcl_AddErrorInfo(interp, "\n (\""); | | < | < | 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 | /* * On failure, report error line. */ if (codePtr == NULL) { Tcl_AddErrorInfo(interp, "\n (\""); Tcl_AppendObjToErrorInfo(interp, objv[0]); Tcl_AddErrorInfo(interp, "\" body, line "); backtrace = Tcl_NewIntObj(Tcl_GetErrorLine(interp)); Tcl_AppendObjToErrorInfo(interp, backtrace); Tcl_AddErrorInfo(interp, ")"); return TCL_ERROR; } /* * Use NRE to evaluate the bytecode from the trampoline. */ |
︙ | ︙ | |||
1306 1307 1308 1309 1310 1311 1312 | } if (GetBooleanOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK) { goto cleanup; } BBEmitInstInt1(assemEnvPtr, tblIdx, opnd, 0); break; | | | 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 | } if (GetBooleanOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK) { goto cleanup; } BBEmitInstInt1(assemEnvPtr, tblIdx, opnd, 0); break; case ASSEM_BOOL_LVT: if (parsePtr->numWords != 3) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "boolean varName"); goto cleanup; } if (GetBooleanOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK) { goto cleanup; } |
︙ | ︙ | |||
1557 1558 1559 1560 1561 1562 1563 | Tcl_SetErrorCode(interp, "TCL", "ASSEM", "OPERAND>=2", NULL); } goto cleanup; } BBEmitInstInt4(assemEnvPtr, tblIdx, opnd, opnd); break; | | | | 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 | Tcl_SetErrorCode(interp, "TCL", "ASSEM", "OPERAND>=2", NULL); } goto cleanup; } BBEmitInstInt4(assemEnvPtr, tblIdx, opnd, opnd); break; case ASSEM_LVT_SINT1: if (parsePtr->numWords != 3) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "varName imm8"); goto cleanup; } localVar = FindLocalVar(assemEnvPtr, &tokenPtr); if (localVar < 0 || GetIntegerOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK || CheckSignedOneByte(interp, opnd)) { goto cleanup; } BBEmitInstInt4(assemEnvPtr, tblIdx, localVar, 0); TclEmitInt1(opnd, envPtr); break; case ASSEM_LVT: if (parsePtr->numWords != 2) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "varname"); goto cleanup; } localVar = FindLocalVar(assemEnvPtr, &tokenPtr); if (localVar < 0) { goto cleanup; |
︙ | ︙ | |||
1635 1636 1637 1638 1639 1640 1641 | if (GetIntegerOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK || CheckSignedOneByte(interp, opnd) != TCL_OK) { goto cleanup; } BBEmitInstInt1(assemEnvPtr, tblIdx, opnd, 0); break; | | | 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 | if (GetIntegerOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK || CheckSignedOneByte(interp, opnd) != TCL_OK) { goto cleanup; } BBEmitInstInt1(assemEnvPtr, tblIdx, opnd, 0); break; case ASSEM_SINT4_LVT: if (parsePtr->numWords != 3) { Tcl_WrongNumArgs(interp, 1, &instNameObj, "count varName"); goto cleanup; } if (GetIntegerOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK) { goto cleanup; } |
︙ | ︙ | |||
4140 4141 4142 4143 4144 4145 4146 | Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr; /* Tcl interpreter */ Tcl_Obj* lineNo; /* Line number in the source */ Tcl_AddErrorInfo(interp, "\n in assembly code between lines "); lineNo = Tcl_NewIntObj(bbPtr->startLine); Tcl_IncrRefCount(lineNo); | | | | 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 | Tcl_Interp* interp = (Tcl_Interp*) envPtr->iPtr; /* Tcl interpreter */ Tcl_Obj* lineNo; /* Line number in the source */ Tcl_AddErrorInfo(interp, "\n in assembly code between lines "); lineNo = Tcl_NewIntObj(bbPtr->startLine); Tcl_IncrRefCount(lineNo); Tcl_AppendObjToErrorInfo(interp, lineNo); Tcl_AddErrorInfo(interp, " and "); if (bbPtr->successor1 != NULL) { Tcl_SetIntObj(lineNo, bbPtr->successor1->startLine); Tcl_AppendObjToErrorInfo(interp, lineNo); } else { Tcl_AddErrorInfo(interp, "end of assembly code"); } Tcl_DecrRefCount(lineNo); } /* |
︙ | ︙ |
Changes to generic/tclBasic.c.
︙ | ︙ | |||
119 120 121 122 123 124 125 | Tcl_Obj *const objv[], int lookup); static void MathFuncWrongNumArgs(Tcl_Interp *interp, int expected, int actual, Tcl_Obj *const *objv); static Tcl_NRPostProc NRCoroutineCallerCallback; static Tcl_NRPostProc NRCoroutineExitCallback; static int NRCommand(ClientData data[], Tcl_Interp *interp, int result); | < | 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | Tcl_Obj *const objv[], int lookup); static void MathFuncWrongNumArgs(Tcl_Interp *interp, int expected, int actual, Tcl_Obj *const *objv); static Tcl_NRPostProc NRCoroutineCallerCallback; static Tcl_NRPostProc NRCoroutineExitCallback; static int NRCommand(ClientData data[], Tcl_Interp *interp, int result); static void ProcessUnexpectedResult(Tcl_Interp *interp, int returnCode); static int RewindCoroutine(CoroutineData *corPtr, int result); static void TEOV_SwitchVarFrame(Tcl_Interp *interp); static void TEOV_PushExceptionHandlers(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); static inline Command * TEOV_LookupCmdFromObj(Tcl_Interp *interp, |
︙ | ︙ | |||
142 143 144 145 146 147 148 | static Tcl_NRPostProc TEOEx_ByteCodeCallback; static Tcl_NRPostProc TEOEx_ListCallback; static Tcl_NRPostProc TEOV_Error; static Tcl_NRPostProc TEOV_Exception; static Tcl_NRPostProc TEOV_NotFoundCallback; static Tcl_NRPostProc TEOV_RestoreVarFrame; static Tcl_NRPostProc TEOV_RunLeaveTraces; | < < < | 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | static Tcl_NRPostProc TEOEx_ByteCodeCallback; static Tcl_NRPostProc TEOEx_ListCallback; static Tcl_NRPostProc TEOV_Error; static Tcl_NRPostProc TEOV_Exception; static Tcl_NRPostProc TEOV_NotFoundCallback; static Tcl_NRPostProc TEOV_RestoreVarFrame; static Tcl_NRPostProc TEOV_RunLeaveTraces; static Tcl_ObjCmdProc NRCoroInjectObjCmd; MODULE_SCOPE const TclStubs tclStubs; /* * Magical counts for the number of arguments accepted by a coroutine command * after particular kinds of [yield]. |
︙ | ︙ | |||
3766 3767 3768 3769 3770 3771 3772 | * here, otherwise the pointer to the * requested Command struct to be invoked. */ { Interp *iPtr = (Interp *) interp; int result; Namespace *lookupNsPtr = iPtr->lookupNsPtr; Command **cmdPtrPtr; | > | | | | | > | < < | 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 | * here, otherwise the pointer to the * requested Command struct to be invoked. */ { Interp *iPtr = (Interp *) interp; int result; Namespace *lookupNsPtr = iPtr->lookupNsPtr; Command **cmdPtrPtr; NRE_callback *callbackPtr; iPtr->lookupNsPtr = NULL; /* * Push a callback with cleanup tasks for commands; the cmdPtr at data[0] * will be filled later when the command is found: save its address at * objProcPtr. * * data[1] stores a marker for use by tailcalls; it will be set to 1 by * command redirectors (imports, alias, ensembles) so that tailcalls * finishes the source command and not just the target. */ if (iPtr->deferredCallbacks) { callbackPtr = iPtr->deferredCallbacks; iPtr->deferredCallbacks = NULL; } else { TclNRAddCallback(interp, NRCommand, NULL, NULL, NULL, NULL); callbackPtr = TOP_CB(interp); } cmdPtrPtr = (Command **) &(callbackPtr->data[0]); iPtr->numLevels++; result = TclInterpReady(interp); if ((result != TCL_OK) || (objc == 0)) { return result; } |
︙ | ︙ | |||
3901 3902 3903 3904 3905 3906 3907 | * the Command struct lives until the command returns. */ *cmdPtrPtr = cmdPtr; cmdPtr->refCount++; /* | | < < | < < < < < < < < < | 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 | * the Command struct lives until the command returns. */ *cmdPtrPtr = cmdPtr; cmdPtr->refCount++; /* * Find the objProc to call: nreProc if available, objProc otherwise. */ if (cmdPtr->nreProc) { return cmdPtr->nreProc(cmdPtr->objClientData, interp, objc, objv); } else { return cmdPtr->objProc(cmdPtr->objClientData, interp, objc, objv); } } int TclNRRunCallbacks( Tcl_Interp *interp, int result, struct NRE_callback *rootPtr) /* All callbacks down to rootPtr not inclusive * are to be run. */ |
︙ | ︙ | |||
3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 | Command *cmdPtr = data[0]; /* int cmdStart = PTR2INT(data[1]); NOT USED HERE */ if (cmdPtr) { TclCleanupCommandMacro(cmdPtr); } ((Interp *)interp)->numLevels--; /* OPT ?? * Do not interrupt a series of cleanups with async or limit checks: * just check at the end? */ if (TclAsyncReady(iPtr)) { result = Tcl_AsyncInvoke(interp, result); } if ((result == TCL_OK) && TclCanceled(iPtr)) { result = Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG); } if (result == TCL_OK && TclLimitReady(iPtr->limit)) { result = Tcl_LimitCheck(interp); } return result; } | > > > > > > > > < < < < < < < < < < < < < < < < | 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 | Command *cmdPtr = data[0]; /* int cmdStart = PTR2INT(data[1]); NOT USED HERE */ if (cmdPtr) { TclCleanupCommandMacro(cmdPtr); } ((Interp *)interp)->numLevels--; /* * If there is a tailcall, schedule it */ if (data[1] && (data[1] != INT2PTR(1))) { TclNRAddCallback(interp, TclNRTailcallEval, data[1], NULL, NULL, NULL); } /* OPT ?? * Do not interrupt a series of cleanups with async or limit checks: * just check at the end? */ if (TclAsyncReady(iPtr)) { result = Tcl_AsyncInvoke(interp, result); } if ((result == TCL_OK) && TclCanceled(iPtr)) { result = Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG); } if (result == TCL_OK && TclLimitReady(iPtr->limit)) { result = Tcl_LimitCheck(interp); } return result; } /* *---------------------------------------------------------------------- * * TEOV_Exception - * TEOV_LookupCmdFromObj - * TEOV_RunEnterTraces - |
︙ | ︙ | |||
4215 4216 4217 4218 4219 4220 4221 | return TCL_ERROR; } if (lookupNsPtr) { savedNsPtr = varFramePtr->nsPtr; varFramePtr->nsPtr = lookupNsPtr; } | > | < | 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 | return TCL_ERROR; } if (lookupNsPtr) { savedNsPtr = varFramePtr->nsPtr; varFramePtr->nsPtr = lookupNsPtr; } TclSkipTailcall(interp); TclNRAddCallback(interp, TEOV_NotFoundCallback, INT2PTR(handlerObjc), newObjv, savedNsPtr, NULL); return TclNREvalObjv(interp, newObjc, newObjv, TCL_EVAL_NOERR, NULL); } static int TEOV_NotFoundCallback( ClientData data[], Tcl_Interp *interp, |
︙ | ︙ | |||
5368 5369 5370 5371 5372 5373 5374 | { return Tcl_EvalEx(interp, script, -1, 0); } /* *---------------------------------------------------------------------- * | | | 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 | { return Tcl_EvalEx(interp, script, -1, 0); } /* *---------------------------------------------------------------------- * * Tcl_EvalObj, Tcl_GlobalEvalObj -- * * These functions are deprecated but we keep them around for backwards * compatibility reasons. * * Results: * See the functions they call. * |
︙ | ︙ | |||
5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 | int Tcl_EvalObj( Tcl_Interp *interp, Tcl_Obj *objPtr) { return Tcl_EvalObjEx(interp, objPtr, 0); } /* *---------------------------------------------------------------------- * * Tcl_EvalObjEx, TclEvalObjEx -- * * Execute Tcl commands stored in a Tcl object. These commands are | > > > > > > > > | 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 | int Tcl_EvalObj( Tcl_Interp *interp, Tcl_Obj *objPtr) { return Tcl_EvalObjEx(interp, objPtr, 0); } #undef Tcl_GlobalEvalObj int Tcl_GlobalEvalObj( Tcl_Interp *interp, Tcl_Obj *objPtr) { return Tcl_EvalObjEx(interp, objPtr, TCL_EVAL_GLOBAL); } /* *---------------------------------------------------------------------- * * Tcl_EvalObjEx, TclEvalObjEx -- * * Execute Tcl commands stored in a Tcl object. These commands are |
︙ | ︙ | |||
5537 5538 5539 5540 5541 5542 5543 | eoFramePtr->cmd.listPtr = listPtr; eoFramePtr->data.eval.path = NULL; iPtr->cmdFramePtr = eoFramePtr; } | > | | 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 | eoFramePtr->cmd.listPtr = listPtr; eoFramePtr->data.eval.path = NULL; iPtr->cmdFramePtr = eoFramePtr; } TclMarkTailcall(interp); TclNRAddCallback(interp, TEOEx_ListCallback, listPtr, eoFramePtr, NULL, NULL); ListObjGetElements(listPtr, objc, objv); return TclNREvalObjv(interp, objc, objv, flags, NULL); } if (!(flags & TCL_EVAL_DIRECT)) { |
︙ | ︙ | |||
7726 7727 7728 7729 7730 7731 7732 | * implementation does not (or does it? Changed, test!) - it causes an * error. * * FIXME NRE! */ void | > > > > > > > > > > > > > | | > > > > > > > > | > > > > > > > > > > | | | < < | 7712 7713 7714 7715 7716 7717 7718 7719 7720 7721 7722 7723 7724 7725 7726 7727 7728 7729 7730 7731 7732 7733 7734 7735 7736 7737 7738 7739 7740 7741 7742 7743 7744 7745 7746 7747 7748 7749 7750 7751 7752 7753 7754 7755 7756 7757 7758 7759 7760 7761 7762 7763 7764 7765 7766 7767 7768 7769 7770 7771 7772 7773 7774 7775 7776 7777 | * implementation does not (or does it? Changed, test!) - it causes an * error. * * FIXME NRE! */ void TclMarkTailcall( Tcl_Interp *interp) { Interp *iPtr = (Interp *) interp; if (iPtr->deferredCallbacks == NULL) { TclNRAddCallback(interp, NRCommand, NULL, NULL, NULL, NULL); iPtr->deferredCallbacks = TOP_CB(interp); } } void TclSkipTailcall( Tcl_Interp *interp) { Interp *iPtr = (Interp *) interp; TclMarkTailcall(interp); iPtr->deferredCallbacks->data[1] = INT2PTR(1); } void TclPushTailcallPoint( Tcl_Interp *interp) { TclNRAddCallback(interp, NRCommand, NULL, NULL, NULL, NULL); ((Interp *) interp)->numLevels++; } void TclSetTailcall( Tcl_Interp *interp, Tcl_Obj *listPtr) { /* * Find the splicing spot: right before the NRCommand of the thing * being tailcalled. Note that we skip NRCommands marked by a 1 in data[1] * (used by command redirectors). */ NRE_callback *runPtr; for (runPtr = TOP_CB(interp); runPtr; runPtr = runPtr->nextPtr) { if (((runPtr->procPtr) == NRCommand) && !runPtr->data[1]) { break; } } if (!runPtr) { Tcl_Panic("tailcall cannot find the right splicing spot: should not happen!"); } runPtr->data[1] = listPtr; } int TclNRTailcallObjCmd( ClientData clientData, Tcl_Interp *interp, int objc, |
︙ | ︙ | |||
7778 7779 7780 7781 7782 7783 7784 | /* * Invocation without args just clears a scheduled tailcall; invocation * with an argument replaces any previously scheduled tailcall. */ if (iPtr->varFramePtr->tailcallPtr) { | | | > > | | < | | < < < < | | < > > > > | < | < < < < < < < < < < | 7793 7794 7795 7796 7797 7798 7799 7800 7801 7802 7803 7804 7805 7806 7807 7808 7809 7810 7811 7812 7813 7814 7815 7816 7817 7818 7819 7820 7821 7822 7823 7824 7825 7826 7827 7828 7829 7830 7831 7832 7833 7834 7835 7836 7837 7838 7839 7840 7841 7842 7843 7844 7845 7846 7847 7848 7849 7850 7851 7852 7853 7854 7855 7856 7857 7858 7859 7860 7861 7862 7863 7864 7865 7866 7867 7868 7869 7870 7871 7872 7873 7874 7875 7876 7877 7878 7879 7880 7881 7882 7883 7884 7885 7886 7887 7888 | /* * Invocation without args just clears a scheduled tailcall; invocation * with an argument replaces any previously scheduled tailcall. */ if (iPtr->varFramePtr->tailcallPtr) { Tcl_DecrRefCount(iPtr->varFramePtr->tailcallPtr); iPtr->varFramePtr->tailcallPtr = NULL; } /* * Create the callback to actually evaluate the tailcalled * command, then set it in the varFrame so that PopCallFrame can use it * at the proper time. Being lazy: exploit the TclNRAddCallBack macro to * build the callback. */ if (objc > 1) { Tcl_Obj *listPtr, *nsObjPtr; Tcl_Namespace *nsPtr = (Tcl_Namespace *) iPtr->varFramePtr->nsPtr; Tcl_Namespace *ns1Ptr; /* The tailcall data is in a Tcl list: the first element is the * namespace, the rest the command to be tailcalled. */ listPtr = Tcl_NewListObj(objc, objv); nsObjPtr = Tcl_NewStringObj(nsPtr->fullName, -1); if ((TCL_OK != TclGetNamespaceFromObj(interp, nsObjPtr, &ns1Ptr)) || (nsPtr != ns1Ptr)) { Tcl_Panic("Tailcall failed to find the proper namespace"); } TclListObjSetElement(interp, listPtr, 0, nsObjPtr); iPtr->varFramePtr->tailcallPtr = listPtr; } return TCL_RETURN; } int TclNRTailcallEval( ClientData data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; Tcl_Obj *listPtr = data[0], *nsObjPtr; Tcl_Namespace *nsPtr; int objc; Tcl_Obj **objv; Tcl_ListObjGetElements(interp, listPtr, &objc, &objv); nsObjPtr = objv[0]; if (result == TCL_OK) { result = TclGetNamespaceFromObj(interp, nsObjPtr, &nsPtr); } if (result != TCL_OK) { /* * Tailcall execution was preempted, eg by an intervening catch or by * a now-gone namespace: cleanup and return. */ TailcallCleanup(data, interp, result); return result; } /* * Perform the tailcall */ TclMarkTailcall(interp); TclNRAddCallback(interp, TailcallCleanup, listPtr, NULL, NULL,NULL); iPtr->lookupNsPtr = (Namespace *) nsPtr; return TclNREvalObjv(interp, objc-1, objv+1, 0, NULL); } static int TailcallCleanup( ClientData data[], Tcl_Interp *interp, int result) { Tcl_DecrRefCount((Tcl_Obj *) data[0]); return result; } void Tcl_NRAddCallback( Tcl_Interp *interp, Tcl_NRPostProc *postProcPtr, ClientData data0, ClientData data1, |
︙ | ︙ | |||
7972 7973 7974 7975 7976 7977 7978 | /* * Add the tailcall in the caller env, then just yield. * * This is essentially code from TclNRTailcallObjCmd */ | > > > > > > | < > | | < < < < < < < < < < < < < < < < < < < < < < < < | 7976 7977 7978 7979 7980 7981 7982 7983 7984 7985 7986 7987 7988 7989 7990 7991 7992 7993 7994 7995 7996 7997 7998 7999 8000 8001 8002 8003 8004 8005 8006 8007 8008 8009 8010 8011 8012 8013 8014 8015 | /* * Add the tailcall in the caller env, then just yield. * * This is essentially code from TclNRTailcallObjCmd */ /* * Add the tailcall in the caller env, then just yield. * * This is essentially code from TclNRTailcallObjCmd */ listPtr = Tcl_NewListObj(objc, objv); nsObjPtr = Tcl_NewStringObj(nsPtr->fullName, -1); if ((TCL_OK != TclGetNamespaceFromObj(interp, nsObjPtr, &ns1Ptr)) || (nsPtr != ns1Ptr)) { Tcl_Panic("yieldto failed to find the proper namespace"); } TclListObjSetElement(interp, listPtr, 0, nsObjPtr); /* * Add the callback in the caller's env, then instruct TEBC to yield. */ iPtr->execEnvPtr = corPtr->callerEEPtr; TclSetTailcall(interp, listPtr); iPtr->execEnvPtr = corPtr->eePtr; return TclNRYieldObjCmd(INT2PTR(CORO_ACTIVATE_YIELDM), interp, 1, objv); } static int RewindCoroutineCallback( ClientData data[], Tcl_Interp *interp, int result) { |
︙ | ︙ | |||
8468 8469 8470 8471 8472 8473 8474 | * Create the base context. */ corPtr->running.framePtr = iPtr->rootFramePtr; corPtr->running.varFramePtr = iPtr->rootFramePtr; corPtr->running.cmdFramePtr = NULL; corPtr->running.lineLABCPtr = corPtr->lineLABCPtr; | < > > > > | 8454 8455 8456 8457 8458 8459 8460 8461 8462 8463 8464 8465 8466 8467 8468 8469 8470 8471 8472 8473 8474 8475 8476 8477 8478 8479 8480 8481 8482 8483 8484 8485 8486 8487 8488 8489 8490 8491 8492 8493 8494 8495 | * Create the base context. */ corPtr->running.framePtr = iPtr->rootFramePtr; corPtr->running.varFramePtr = iPtr->rootFramePtr; corPtr->running.cmdFramePtr = NULL; corPtr->running.lineLABCPtr = corPtr->lineLABCPtr; corPtr->auxNumLevels = 0; /* * Create the coro's execEnv, switch to it to push the exit and coro * command callbacks, then switch back. */ corPtr->eePtr = TclCreateExecEnv(interp, CORO_STACK_INITIAL_SIZE); corPtr->callerEEPtr = iPtr->execEnvPtr; corPtr->eePtr->corPtr = corPtr; SAVE_CONTEXT(corPtr->caller); corPtr->callerEEPtr = iPtr->execEnvPtr; RESTORE_CONTEXT(corPtr->running); iPtr->execEnvPtr = corPtr->eePtr; TclNRAddCallback(interp, NRCoroutineExitCallback, corPtr, NULL, NULL, NULL); /* Mark the coro as 'not suspended' while scheduling the command */ corPtr->stackLevel = INT2PTR(1); /* insure that the command is looked up in the correct namespace */ iPtr->lookupNsPtr = lookupNsPtr; Tcl_NREvalObj(interp, Tcl_NewListObj(objc-2, objv+2), 0); iPtr->numLevels--; corPtr->stackLevel = NULL; SAVE_CONTEXT(corPtr->running); RESTORE_CONTEXT(corPtr->caller); iPtr->execEnvPtr = corPtr->callerEEPtr; /* * Now just resume the coroutine. */ |
︙ | ︙ |
Changes to generic/tclBinary.c.
︙ | ︙ | |||
123 124 125 126 127 128 129 130 131 132 133 134 135 136 | 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '=' }; /* * The following object type represents an array of bytes. An array of bytes * is not equivalent to an internationalized string. Conceptually, a string is * an array of 16-bit quantities organized as a sequence of properly formed * UTF-8 characters, while a ByteArray is an array of 8-bit quantities. * Accessor functions are provided to convert a ByteArray to a String or a * String to a ByteArray. Two or more consecutive bytes in an array of bytes | > > > > > > > > > > > > > > > > > > > > > > > > | 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '=' }; /* * How to construct the ensembles. */ static const EnsembleImplMap binaryMap[] = { { "format", BinaryFormatCmd, TclCompileBasicMin1ArgCmd, NULL, NULL, 0 }, { "scan", BinaryScanCmd, TclCompileBasicMin2ArgCmd, NULL, NULL, 0 }, { "encode", NULL, NULL, NULL, NULL, 0 }, { "decode", NULL, NULL, NULL, NULL, 0 }, { NULL, NULL, NULL, NULL, NULL, 0 } }; static const EnsembleImplMap encodeMap[] = { { "hex", BinaryEncodeHex, TclCompileBasic1ArgCmd, NULL, (ClientData)HexDigits, 0 }, { "uuencode", BinaryEncode64, NULL, NULL, (ClientData)UueDigits, 0 }, { "base64", BinaryEncode64, NULL, NULL, (ClientData)B64Digits, 0 }, { NULL, NULL, NULL, NULL, NULL, 0 } }; static const EnsembleImplMap decodeMap[] = { { "hex", BinaryDecodeHex, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 }, { "uuencode", BinaryDecodeUu, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 }, { "base64", BinaryDecode64, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 }, { NULL, NULL, NULL, NULL, NULL, 0 } }; /* * The following object type represents an array of bytes. An array of bytes * is not equivalent to an internationalized string. Conceptually, a string is * an array of 16-bit quantities organized as a sequence of properly formed * UTF-8 characters, while a ByteArray is an array of 8-bit quantities. * Accessor functions are provided to convert a ByteArray to a String or a * String to a ByteArray. Two or more consecutive bytes in an array of bytes |
︙ | ︙ | |||
684 685 686 687 688 689 690 | * * Side effects: * Creates a new binary command as a mapped ensemble. * *---------------------------------------------------------------------- */ | < < < < < < < < < < < < < < < < < < < < | 708 709 710 711 712 713 714 715 716 717 718 719 720 721 | * * Side effects: * Creates a new binary command as a mapped ensemble. * *---------------------------------------------------------------------- */ Tcl_Command TclInitBinaryCmd( Tcl_Interp *interp) { Tcl_Command binaryEnsemble; binaryEnsemble = TclMakeEnsemble(interp, "binary", binaryMap); |
︙ | ︙ | |||
2353 2354 2355 2356 2357 2358 2359 | unsigned char *data, *datastart, *dataend; unsigned char *begin, *cursor, c; int i, index, value, size, count = 0, cut = 0, strict = 0; enum {OPT_STRICT }; static const char *const optStrings[] = { "-strict", NULL }; if (objc < 2 || objc > 3) { | | | 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 | unsigned char *data, *datastart, *dataend; unsigned char *begin, *cursor, c; int i, index, value, size, count = 0, cut = 0, strict = 0; enum {OPT_STRICT }; static const char *const optStrings[] = { "-strict", NULL }; if (objc < 2 || objc > 3) { Tcl_WrongNumArgs(interp, 1, objv, "?options? data"); return TCL_ERROR; } for (i = 1; i < objc-1; ++i) { if (Tcl_GetIndexFromObj(interp, objv[i], optStrings, "option", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } |
︙ | ︙ | |||
2567 2568 2569 2570 2571 2572 2573 | unsigned char *begin, *cursor; int i, index, size, count = 0, cut = 0, strict = 0; char c; enum {OPT_STRICT }; static const char *const optStrings[] = { "-strict", NULL }; if (objc < 2 || objc > 3) { | | | 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 | unsigned char *begin, *cursor; int i, index, size, count = 0, cut = 0, strict = 0; char c; enum {OPT_STRICT }; static const char *const optStrings[] = { "-strict", NULL }; if (objc < 2 || objc > 3) { Tcl_WrongNumArgs(interp, 1, objv, "?options? data"); return TCL_ERROR; } for (i = 1; i < objc-1; ++i) { if (Tcl_GetIndexFromObj(interp, objv[i], optStrings, "option", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } |
︙ | ︙ | |||
2663 2664 2665 2666 2667 2668 2669 | unsigned char *cursor = NULL; int strict = 0; int i, index, size, cut = 0, count = 0; enum { OPT_STRICT }; static const char *const optStrings[] = { "-strict", NULL }; if (objc < 2 || objc > 3) { | | | 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 | unsigned char *cursor = NULL; int strict = 0; int i, index, size, cut = 0, count = 0; enum { OPT_STRICT }; static const char *const optStrings[] = { "-strict", NULL }; if (objc < 2 || objc > 3) { Tcl_WrongNumArgs(interp, 1, objv, "?options? data"); return TCL_ERROR; } for (i = 1; i < objc-1; ++i) { if (Tcl_GetIndexFromObj(interp, objv[i], optStrings, "option", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } |
︙ | ︙ |
Changes to generic/tclCkalloc.c.
︙ | ︙ | |||
152 153 154 155 156 157 158 159 160 161 162 163 164 165 | void TclInitDbCkalloc(void) { if (!ckallocInit) { ckallocInit = 1; ckallocMutexPtr = Tcl_GetAllocMutex(); } } /* *---------------------------------------------------------------------- * * TclDumpMemoryInfo -- | > > > > | 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | void TclInitDbCkalloc(void) { if (!ckallocInit) { ckallocInit = 1; ckallocMutexPtr = Tcl_GetAllocMutex(); #ifndef TCL_THREADS /* Silence compiler warning */ (void)ckallocMutexPtr; #endif } } /* *---------------------------------------------------------------------- * * TclDumpMemoryInfo -- |
︙ | ︙ |
Changes to generic/tclCmdAH.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /* * tclCmdAH.c -- * * This file contains the top-level command routines for most of the Tcl * built-in commands whose names begin with the letters A to H. * * Copyright (c) 1987-1993 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include <locale.h> /* * The state structure used by [foreach]. Note that the actual structure has * all its working arrays appended afterwards so they can be allocated and * freed in a single step. | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* * tclCmdAH.c -- * * This file contains the top-level command routines for most of the Tcl * built-in commands whose names begin with the letters A to H. * * Copyright (c) 1987-1993 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include <sys/stat.h> #include "tclInt.h" #include <locale.h> /* * The state structure used by [foreach]. Note that the actual structure has * all its working arrays appended afterwards so they can be allocated and * freed in a single step. |
︙ | ︙ | |||
220 221 222 223 224 225 226 | } } if (objc == 4) { Tcl_Obj *options = Tcl_GetReturnOptions(interp, result); if (NULL == Tcl_ObjSetVar2(interp, optionVarNamePtr, NULL, options, TCL_LEAVE_ERR_MSG)) { | | > | 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 | } } if (objc == 4) { Tcl_Obj *options = Tcl_GetReturnOptions(interp, result); if (NULL == Tcl_ObjSetVar2(interp, optionVarNamePtr, NULL, options, TCL_LEAVE_ERR_MSG)) { /* Do not decrRefCount 'options', it was already done by * Tcl_ObjSetVar2 */ return TCL_ERROR; } } Tcl_ResetResult(interp); Tcl_SetObjResult(interp, Tcl_NewIntObj(result)); return TCL_OK; |
︙ | ︙ | |||
808 809 810 811 812 813 814 | /* * Note that most subcommands are unsafe because either they manipulate * the native filesystem or because they reveal information about the * native filesystem. */ static const EnsembleImplMap initMap[] = { | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 | /* * Note that most subcommands are unsafe because either they manipulate * the native filesystem or because they reveal information about the * native filesystem. */ static const EnsembleImplMap initMap[] = { {"atime", FileAttrAccessTimeCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, {"attributes", TclFileAttrsCmd, NULL, NULL, NULL, 0}, {"channels", TclChannelNamesCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"copy", TclFileCopyCmd, NULL, NULL, NULL, 0}, {"delete", TclFileDeleteCmd, TclCompileBasicMin0ArgCmd, NULL, NULL, 0}, {"dirname", PathDirNameCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"executable", FileAttrIsExecutableCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"exists", FileAttrIsExistingCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"extension", PathExtensionCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"isdirectory", FileAttrIsDirectoryCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"isfile", FileAttrIsFileCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"join", PathJoinCmd, TclCompileBasicMin1ArgCmd, NULL, NULL, 0}, {"link", TclFileLinkCmd, TclCompileBasic1To3ArgCmd, NULL, NULL, 0}, {"lstat", FileAttrLinkStatCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"mtime", FileAttrModifyTimeCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, {"mkdir", TclFileMakeDirsCmd, TclCompileBasicMin0ArgCmd, NULL, NULL, 0}, {"nativename", PathNativeNameCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"normalize", PathNormalizeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"owned", FileAttrIsOwnedCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"pathtype", PathTypeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"readable", FileAttrIsReadableCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"readlink", TclFileReadLinkCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"rename", TclFileRenameCmd, NULL, NULL, NULL, 0}, {"rootname", PathRootNameCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"separator", FilesystemSeparatorCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"size", FileAttrSizeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"split", PathSplitCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"stat", FileAttrStatCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"system", PathFilesystemCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"tail", PathTailCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"tempfile", TclFileTemporaryCmd, TclCompileBasic0To2ArgCmd, NULL, NULL, 0}, {"type", FileAttrTypeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"volumes", FilesystemVolumesCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0}, {"writable", FileAttrIsWritableCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {NULL, NULL, NULL, NULL, NULL, 0} }; return TclMakeEnsemble(interp, "file", initMap); } /* *---------------------------------------------------------------------- |
︙ | ︙ |
Changes to generic/tclCmdIL.c.
︙ | ︙ | |||
157 158 159 160 161 162 163 | /* * Array of values describing how to implement each standard subcommand of the * "info" command. */ static const EnsembleImplMap defaultInfoMap[] = { | | | | | | | | | | | | | | | | | | | | | | 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | /* * Array of values describing how to implement each standard subcommand of the * "info" command. */ static const EnsembleImplMap defaultInfoMap[] = { {"args", InfoArgsCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"body", InfoBodyCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"cmdcount", InfoCmdCountCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0}, {"commands", InfoCommandsCmd, TclCompileInfoCommandsCmd, NULL, NULL, 0}, {"complete", InfoCompleteCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"coroutine", TclInfoCoroutineCmd, TclCompileInfoCoroutineCmd, NULL, NULL, 0}, {"default", InfoDefaultCmd, TclCompileBasic3ArgCmd, NULL, NULL, 0}, {"errorstack", InfoErrorStackCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"exists", TclInfoExistsCmd, TclCompileInfoExistsCmd, NULL, NULL, 0}, {"frame", InfoFrameCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"functions", InfoFunctionsCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"globals", TclInfoGlobalsCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"hostname", InfoHostnameCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0}, {"level", InfoLevelCmd, TclCompileInfoLevelCmd, NULL, NULL, 0}, {"library", InfoLibraryCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0}, {"loaded", InfoLoadedCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"locals", TclInfoLocalsCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"nameofexecutable", InfoNameOfExecutableCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0}, {"patchlevel", InfoPatchLevelCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0}, {"procs", InfoProcsCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"script", InfoScriptCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"sharedlibextension", InfoSharedlibCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0}, {"tclversion", InfoTclVersionCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0}, {"vars", TclInfoVarsCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {NULL, NULL, NULL, NULL, NULL, 0} }; /* *---------------------------------------------------------------------- * * Tcl_IfObjCmd -- |
︙ | ︙ |
Changes to generic/tclCmdMZ.c.
︙ | ︙ | |||
3320 3321 3322 3323 3324 3325 3326 | */ Tcl_Command TclInitStringCmd( Tcl_Interp *interp) /* Current interpreter. */ { static const EnsembleImplMap stringImplMap[] = { | | | | | | | | | | | | | 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 | */ Tcl_Command TclInitStringCmd( Tcl_Interp *interp) /* Current interpreter. */ { static const EnsembleImplMap stringImplMap[] = { {"bytelength", StringBytesCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"compare", StringCmpCmd, TclCompileStringCmpCmd, NULL, NULL, 0}, {"equal", StringEqualCmd, TclCompileStringEqualCmd, NULL, NULL, 0}, {"first", StringFirstCmd, TclCompileStringFirstCmd, NULL, NULL, 0}, {"index", StringIndexCmd, TclCompileStringIndexCmd, NULL, NULL, 0}, {"is", StringIsCmd, NULL, NULL, NULL, 0}, {"last", StringLastCmd, TclCompileStringLastCmd, NULL, NULL, 0}, {"length", StringLenCmd, TclCompileStringLenCmd, NULL, NULL, 0}, {"map", StringMapCmd, TclCompileStringMapCmd, NULL, NULL, 0}, {"match", StringMatchCmd, TclCompileStringMatchCmd, NULL, NULL, 0}, {"range", StringRangeCmd, TclCompileStringRangeCmd, NULL, NULL, 0}, {"repeat", StringReptCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"replace", StringRplcCmd, NULL, NULL, NULL, 0}, {"reverse", StringRevCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"tolower", StringLowerCmd, TclCompileBasic1To3ArgCmd, NULL, NULL, 0}, {"toupper", StringUpperCmd, TclCompileBasic1To3ArgCmd, NULL, NULL, 0}, {"totitle", StringTitleCmd, TclCompileBasic1To3ArgCmd, NULL, NULL, 0}, {"trim", StringTrimCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, {"trimleft", StringTrimLCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, {"trimright", StringTrimRCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, {"wordend", StringEndCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"wordstart", StringStartCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {NULL, NULL, NULL, NULL, NULL, 0} }; return TclMakeEnsemble(interp, "string", stringImplMap); } /* |
︙ | ︙ |
Changes to generic/tclCompCmds.c.
︙ | ︙ | |||
32 33 34 35 36 37 38 | Tcl_Obj *appendObj, ByteCode *codePtr, unsigned int pcOffset); static void CompileReturnInternal(CompileEnv *envPtr, unsigned char op, int code, int level, Tcl_Obj *returnOpts); static int IndexTailVarIfKnown(Tcl_Interp *interp, Tcl_Token *varTokenPtr, CompileEnv *envPtr); | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | Tcl_Obj *appendObj, ByteCode *codePtr, unsigned int pcOffset); static void CompileReturnInternal(CompileEnv *envPtr, unsigned char op, int code, int level, Tcl_Obj *returnOpts); static int IndexTailVarIfKnown(Tcl_Interp *interp, Tcl_Token *varTokenPtr, CompileEnv *envPtr); static int CompileEachloopCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, CompileEnv *envPtr, int collect); static int CompileDictEachCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr, int collect); /* * The structures below define the AuxData types defined in this file. */ const AuxDataType tclForeachInfoType = { "ForeachInfo", /* name */ DupForeachInfo, /* dupProc */ |
︙ | ︙ | |||
145 146 147 148 149 150 151 | Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { | | | 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *varTokenPtr; int simpleVarName, isScalar, localIndex, numWords; DefineLineInformation; /* TIP #280 */ numWords = parsePtr->numWords; if (numWords == 1) { return TCL_ERROR; } else if (numWords == 2) { |
︙ | ︙ | |||
176 177 178 179 180 181 182 | * slot (entry in the array of local vars) if we are compiling a procedure * body and if the name is simple text that does not include namespace * qualifiers. */ varTokenPtr = TokenAfter(parsePtr->tokenPtr); | | | | < | | | | | | 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | * slot (entry in the array of local vars) if we are compiling a procedure * body and if the name is simple text that does not include namespace * qualifiers. */ varTokenPtr = TokenAfter(parsePtr->tokenPtr); PUSH_VAR( varTokenPtr, 1, &localIndex, &simpleVarName, &isScalar); /* * We are doing an assignment, otherwise TclCompileSetCmd was called, so * push the new value. This will need to be extended to push a value for * each argument. */ if (numWords > 2) { PUSH_SUBST_WORD(TokenAfter(varTokenPtr), 2); } /* * Emit instructions to set/get the variable. */ if (simpleVarName) { if (isScalar) { if (localIndex < 0) { OP( APPEND_STK); } else { OP4( APPEND_SCALAR, localIndex); } } else { if (localIndex < 0) { OP( APPEND_ARRAY_STK); } else { OP4( APPEND_ARRAY, localIndex); } } } else { OP( APPEND_STK); } return TCL_OK; } /* *---------------------------------------------------------------------- |
︙ | ︙ | |||
251 252 253 254 255 256 257 | int simpleVarName, isScalar, localIndex; if (parsePtr->numWords != 2) { return TCL_ERROR; } tokenPtr = TokenAfter(parsePtr->tokenPtr); | | | | | | > < | | | | | | | | > > > > > | > > > > > | > > > > > > | > > > > > > > < < < | | | | | | | | | | < < | < | | < | < | | | | | | | | | < | | | < > | < | < | | | | | | | | | < | | | | < > | < | < < > | < | | | | | | < | | | | | < > | | 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 | int simpleVarName, isScalar, localIndex; if (parsePtr->numWords != 2) { return TCL_ERROR; } tokenPtr = TokenAfter(parsePtr->tokenPtr); PushVarNameWord(interp, tokenPtr, envPtr, TCL_NO_ELEMENT, &localIndex, &simpleVarName, &isScalar, 1); if (!isScalar) { return TCL_ERROR; } if (localIndex >= 0) { OP4( ARRAY_EXISTS_IMM, localIndex); } else { OP( ARRAY_EXISTS_STK); } return TCL_OK; } int TclCompileArraySetCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr; int simpleVarName, isScalar, localIndex; int dataVar, iterVar, keyVar, valVar, infoIndex; int offsetBack, offsetFwd, savedStackDepth; ForeachInfo *infoPtr; if (parsePtr->numWords != 3) { return TCL_ERROR; } tokenPtr = TokenAfter(parsePtr->tokenPtr); PushVarNameWord(interp, tokenPtr, envPtr, TCL_NO_ELEMENT, &localIndex, &simpleVarName, &isScalar, 1); tokenPtr = TokenAfter(tokenPtr); if (!isScalar) { return TCL_ERROR; } /* * Special case: literal empty value argument is just an "ensure array" * operation. */ if (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD && tokenPtr[1].size == 0) { if (localIndex >= 0) { OP4( ARRAY_EXISTS_IMM, localIndex); OP4( JUMP_TRUE, 10); OP4( ARRAY_MAKE_IMM, localIndex); } else { OP( DUP); OP( ARRAY_EXISTS_STK); OP4( JUMP_TRUE, 11); savedStackDepth = envPtr->currStackDepth; OP( ARRAY_MAKE_STK); OP4( JUMP, 6); envPtr->currStackDepth = savedStackDepth; OP( POP); } PUSH( ""); return TCL_OK; } if (envPtr->procPtr == NULL) { /* * Right number of arguments, but not compilable as we can't allocate * (unnamed) local variables to manage the internal iteration. */ Tcl_Obj *objPtr = Tcl_NewObj(); char *bytes; int length, cmdLit; Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr, objPtr); bytes = Tcl_GetStringFromObj(objPtr, &length); cmdLit = TclRegisterNewCmdLiteral(envPtr, bytes, length); TclSetCmdNameObj(interp, envPtr->literalArrayPtr[cmdLit].objPtr, cmdPtr); TclEmitPush(cmdLit, envPtr); TclDecrRefCount(objPtr); OP( EXCH); PUSH_SUBST_WORD(tokenPtr, 2); OP4( INVOKE_STK, 3); return TCL_OK; } /* * Prepare for the internal foreach. */ dataVar = NewUnnamedLocal(envPtr); iterVar = NewUnnamedLocal(envPtr); keyVar = NewUnnamedLocal(envPtr); valVar = NewUnnamedLocal(envPtr); infoPtr = ckalloc(sizeof(ForeachInfo) + sizeof(ForeachVarList *)); infoPtr->numLists = 1; infoPtr->firstValueTemp = dataVar; infoPtr->loopCtTemp = iterVar; infoPtr->varLists[0] = ckalloc(sizeof(ForeachVarList) * 2*sizeof(int)); infoPtr->varLists[0]->numVars = 2; infoPtr->varLists[0]->varIndexes[0] = keyVar; infoPtr->varLists[0]->varIndexes[1] = valVar; infoIndex = TclCreateAuxData(infoPtr, &tclForeachInfoType, envPtr); /* * Start issuing instructions to write to the array. */ PUSH_SUBST_WORD( tokenPtr, 2); OP( DUP); OP( LIST_LENGTH); PUSH( "1"); OP( BITAND); JUMP(offsetFwd, JUMP_FALSE); savedStackDepth = envPtr->currStackDepth; PUSH( "list must have an even number of elements"); PUSH( "-errorCode {TCL ARGUMENT FORMAT}"); OP44( RETURN_IMM, 1, 0); envPtr->currStackDepth = savedStackDepth; FIXJUMP( offsetFwd); OP4( STORE_SCALAR, dataVar); OP( POP); if (localIndex >= 0) { OP4( ARRAY_EXISTS_IMM, localIndex); OP4( JUMP_TRUE, 10); OP4( ARRAY_MAKE_IMM, localIndex); OP4( FOREACH_START, infoIndex); LABEL(offsetBack); OP4( FOREACH_STEP, infoIndex); JUMP(offsetFwd, JUMP_FALSE); savedStackDepth = envPtr->currStackDepth; OP4( LOAD_SCALAR, keyVar); OP4( LOAD_SCALAR, valVar); OP4( STORE_ARRAY, localIndex); OP( POP); BACKJUMP( offsetBack, JUMP); FIXJUMP( offsetFwd); envPtr->currStackDepth = savedStackDepth; } else { OP( DUP); OP( ARRAY_EXISTS_STK); OP4( JUMP_TRUE, 7); OP( DUP); OP( ARRAY_MAKE_STK); OP4( FOREACH_START, infoIndex); LABEL(offsetBack); OP4( FOREACH_STEP, infoIndex); JUMP(offsetFwd, JUMP_FALSE); savedStackDepth = envPtr->currStackDepth; OP( DUP); OP4( LOAD_SCALAR, keyVar); OP4( LOAD_SCALAR, valVar); OP( STORE_ARRAY_STK); OP( POP); BACKJUMP( offsetBack, JUMP); FIXJUMP( offsetFwd); envPtr->currStackDepth = savedStackDepth; OP( POP); } OP14( UNSET_SCALAR, 0, dataVar); PUSH( ""); return TCL_OK; } int TclCompileArrayUnsetCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr); int simpleVarName, isScalar, localIndex, savedStackDepth; if (parsePtr->numWords != 2) { return TclCompileBasic2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } PushVarNameWord(interp, tokenPtr, envPtr, TCL_NO_ELEMENT, &localIndex, &simpleVarName, &isScalar, 1); if (!isScalar) { return TCL_ERROR; } if (localIndex >= 0) { OP4( ARRAY_EXISTS_IMM, localIndex); OP4( JUMP_FALSE, 11); OP14( UNSET_SCALAR, 1, localIndex); } else { OP( DUP); OP( ARRAY_EXISTS_STK); OP4( JUMP_FALSE, 12); savedStackDepth = envPtr->currStackDepth; OP1( UNSET_STK, 1); OP4( JUMP, 6); envPtr->currStackDepth = savedStackDepth; OP( POP); } PUSH( ""); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileBreakCmd -- |
︙ | ︙ | |||
489 490 491 492 493 494 495 | return TCL_ERROR; } /* * Emit a break instruction. */ | | | | 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 | return TCL_ERROR; } /* * Emit a break instruction. */ OP( BREAK); PUSH( ""); /* Evil hack! */ return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileCatchCmd -- |
︙ | ︙ | |||
611 612 613 614 615 616 617 | * Care has to be taken to make sure that substitution happens outside the * catch range so that errors in the substitution are not caught. * [Bug 219184] * The reason for duplicating the script is that EVAL_STK would otherwise * begin by undeflowing the stack below the mark set by BEGIN_CATCH4. */ | < | | | | | | | | | | | | | | | | | | | | | | | | | | 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 | * Care has to be taken to make sure that substitution happens outside the * catch range so that errors in the substitution are not caught. * [Bug 219184] * The reason for duplicating the script is that EVAL_STK would otherwise * begin by undeflowing the stack below the mark set by BEGIN_CATCH4. */ if (cmdTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) { savedStackDepth = envPtr->currStackDepth; OP4( BEGIN_CATCH, range); ExceptionRangeStarts(envPtr, range); BODY( cmdTokenPtr, 1); } else { PUSH_SUBST_WORD(cmdTokenPtr, 1); savedStackDepth = envPtr->currStackDepth; OP4( BEGIN_CATCH, range); ExceptionRangeStarts(envPtr, range); OP( DUP); OP( EVAL_STK); } /* Stack at this point: * nonsimple: script <mark> result * simple: <mark> result */ if (resultIndex == -1) { /* * Special case when neither result nor options are being saved. In * that case, we can skip quite a bit of the command epilogue; all we * have to do is drop the result and push the return code (and, of * course, finish the catch context). */ OP( POP); PUSH( "0"); OP4( JUMP, 6); envPtr->currStackDepth = savedStackDepth; ExceptionRangeTarget(envPtr, range, catchOffset); OP( PUSH_RETURN_CODE); ExceptionRangeEnds(envPtr, range); OP( END_CATCH); /* * Stack at this point: * nonsimple: script <mark> returnCode * simple: <mark> returnCode */ goto dropScriptAtEnd; } /* * Emit the "no errors" epilogue: push "0" (TCL_OK) as the catch result, * and jump around the "error case" code. */ PUSH( "0"); TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup); /* Stack at this point: ?script? <mark> result TCL_OK */ /* * Emit the "error case" epilogue. Push the interpreter result and the * return code. */ envPtr->currStackDepth = savedStackDepth; ExceptionRangeTarget(envPtr, range, catchOffset); /* Stack at this point: ?script? */ OP( PUSH_RESULT); OP( PUSH_RETURN_CODE); /* * Update the target of the jump after the "no errors" code. */ /* Stack at this point: ?script? result returnCode */ if (TclFixupForwardJumpToHere(envPtr, &jumpFixup, 127)) { Tcl_Panic("TclCompileCatchCmd: bad jump distance %d", (int)(CurrentOffset(envPtr) - jumpFixup.codeOffset)); } /* * Push the return options if the caller wants them. */ if (optsIndex != -1) { OP( PUSH_RETURN_OPTIONS); } /* * End the catch */ ExceptionRangeEnds(envPtr, range); OP( END_CATCH); /* * At this point, the top of the stack is inconveniently ordered: * ?script? result returnCode ?returnOptions? * Reverse the stack to bring the result to the top. */ if (optsIndex != -1) { OP4( REVERSE, 3); } else { OP( EXCH); } /* * Store the result and remove it from the stack. */ OP4( STORE_SCALAR, resultIndex); OP( POP); /* * Stack is now ?script? ?returnOptions? returnCode. * If the options dict has been requested, it is buried on the stack under * the return code. Reverse the stack to bring it to the top, store it and * remove it from the stack. */ if (optsIndex != -1) { OP( EXCH); OP4( STORE_SCALAR, optsIndex); OP( POP); } dropScriptAtEnd: /* * Stack is now ?script? result. Get rid of the subst'ed script if it's * hanging arond. */ if (cmdTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { OP( EXCH); OP( POP); } /* * Result of all this, on either branch, should have been to leave one * operand -- the return code -- on the stack. */ |
︙ | ︙ | |||
796 797 798 799 800 801 802 | return TCL_ERROR; } /* * Emit a continue instruction. */ | | | | 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 | return TCL_ERROR; } /* * Emit a continue instruction. */ OP( CONTINUE); PUSH( ""); /* Evil hack! */ return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileDict*Cmd -- |
︙ | ︙ | |||
870 871 872 873 874 875 876 | /* * Remaining words (key path and value to set) can be handled normally. */ tokenPtr = TokenAfter(varTokenPtr); numWords = parsePtr->numWords-1; for (i=1 ; i<numWords ; i++) { | | | < | 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 | /* * Remaining words (key path and value to set) can be handled normally. */ tokenPtr = TokenAfter(varTokenPtr); numWords = parsePtr->numWords-1; for (i=1 ; i<numWords ; i++) { PUSH_SUBST_WORD(tokenPtr, i); tokenPtr = TokenAfter(tokenPtr); } /* * Now emit the instruction to do the dict manipulation. */ OP44( DICT_SET, numWords-2, dictVarIndex); TclAdjustStackDepth(-1, envPtr); return TCL_OK; } int TclCompileDictIncrCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ |
︙ | ︙ | |||
920 921 922 923 924 925 926 | const char *word; int numBytes, code; Tcl_Token *incrTokenPtr; Tcl_Obj *intObj; incrTokenPtr = TokenAfter(keyTokenPtr); if (incrTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { | | | | | | | | < | 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 | const char *word; int numBytes, code; Tcl_Token *incrTokenPtr; Tcl_Obj *intObj; incrTokenPtr = TokenAfter(keyTokenPtr); if (incrTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { return TclCompileBasic2Or3ArgCmd(interp, parsePtr,cmdPtr, envPtr); } word = incrTokenPtr[1].start; numBytes = incrTokenPtr[1].size; intObj = Tcl_NewStringObj(word, numBytes); Tcl_IncrRefCount(intObj); code = TclGetIntFromObj(NULL, intObj, &incrAmount); TclDecrRefCount(intObj); if (code != TCL_OK) { return TclCompileBasic2Or3ArgCmd(interp, parsePtr,cmdPtr, envPtr); } } else { incrAmount = 1; } /* * The dictionary variable must be a local scalar that is knowable at * compile time; anything else exceeds the complexity of the opcode. So * discover what the index is. */ if (varTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { return TclCompileBasic2Or3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } name = varTokenPtr[1].start; nameChars = varTokenPtr[1].size; if (!TclIsLocalScalar(name, nameChars)) { return TclCompileBasic2Or3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } dictVarIndex = TclFindCompiledLocal(name, nameChars, 1, envPtr); if (dictVarIndex < 0) { return TclCompileBasic2Or3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } /* * Emit the key and the code to actually do the increment. */ PUSH_SUBST_WORD(keyTokenPtr, 3); OP44( DICT_INCR_IMM, incrAmount, dictVarIndex); return TCL_OK; } int TclCompileDictGetCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command |
︙ | ︙ | |||
994 995 996 997 998 999 1000 | numWords = parsePtr->numWords-1; /* * Only compile this because we need INST_DICT_GET anyway. */ for (i=0 ; i<numWords ; i++) { | | | | 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 | numWords = parsePtr->numWords-1; /* * Only compile this because we need INST_DICT_GET anyway. */ for (i=0 ; i<numWords ; i++) { PUSH_SUBST_WORD(tokenPtr, i); tokenPtr = TokenAfter(tokenPtr); } OP4( DICT_GET, numWords-1); TclAdjustStackDepth(-1, envPtr); return TCL_OK; } int TclCompileDictExistsCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ |
︙ | ︙ | |||
1031 1032 1033 1034 1035 1036 1037 | numWords = parsePtr->numWords-1; /* * Now we do the code generation. */ for (i=0 ; i<numWords ; i++) { | | | | 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 | numWords = parsePtr->numWords-1; /* * Now we do the code generation. */ for (i=0 ; i<numWords ; i++) { PUSH_SUBST_WORD(tokenPtr, i); tokenPtr = TokenAfter(tokenPtr); } OP4( DICT_EXISTS, numWords-1); TclAdjustStackDepth(-1, envPtr); return TCL_OK; } int TclCompileDictUnsetCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ |
︙ | ︙ | |||
1070 1071 1072 1073 1074 1075 1076 | * The dictionary variable must be a local scalar that is knowable at * compile time; anything else exceeds the complexity of the opcode. So * discover what the index is. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { | | | | | | < < | | 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 | * The dictionary variable must be a local scalar that is knowable at * compile time; anything else exceeds the complexity of the opcode. So * discover what the index is. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } name = tokenPtr[1].start; nameChars = tokenPtr[1].size; if (!TclIsLocalScalar(name, nameChars)) { return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } dictVarIndex = TclFindCompiledLocal(name, nameChars, 1, envPtr); if (dictVarIndex < 0) { return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } /* * Remaining words (the key path) can be handled normally. */ for (i=2 ; i<parsePtr->numWords ; i++) { tokenPtr = TokenAfter(tokenPtr); PUSH_SUBST_WORD(tokenPtr, i); } /* * Now emit the instruction to do the dict manipulation. */ OP44( DICT_UNSET, parsePtr->numWords-2, dictVarIndex); return TCL_OK; } int TclCompileDictCreateCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ int worker; /* Temp var for building the value in. */ Tcl_Token *tokenPtr; Tcl_Obj *keyObj, *valueObj, *dictObj; int i; if ((parsePtr->numWords & 1) == 0) { return TCL_ERROR; } /* * See if we can build the value at compile time... |
︙ | ︙ | |||
1154 1155 1156 1157 1158 1159 1160 | Tcl_DecrRefCount(valueObj); } /* * We did! Excellent. The "verifyDict" is to do type forcing. */ | | < | | | | | | | | | | < < > | | < | 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 | Tcl_DecrRefCount(valueObj); } /* * We did! Excellent. The "verifyDict" is to do type forcing. */ PUSH_OBJ( dictObj); OP( DUP); OP( DICT_VERIFY); Tcl_DecrRefCount(dictObj); return TCL_OK; /* * Otherwise, we've got to issue runtime code to do the building, which we * do by [dict set]ting into an unnamed local variable. This requires that * we are in a context with an LVT. */ nonConstant: worker = NewUnnamedLocal(envPtr); if (worker < 0) { return TclCompileBasicMin0ArgCmd(interp, parsePtr, cmdPtr, envPtr); } PUSH( ""); OP4( STORE_SCALAR, worker); OP( POP); tokenPtr = TokenAfter(parsePtr->tokenPtr); for (i=1 ; i<parsePtr->numWords ; i+=2) { PUSH_SUBST_WORD(tokenPtr, i); tokenPtr = TokenAfter(tokenPtr); PUSH_SUBST_WORD(tokenPtr, i+1); tokenPtr = TokenAfter(tokenPtr); OP44( DICT_SET, 1, worker); TclAdjustStackDepth(-1, envPtr); OP( POP); } OP4( LOAD_SCALAR, worker); OP14( UNSET_SCALAR, 0, worker); return TCL_OK; } int TclCompileDictMergeCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command |
︙ | ︙ | |||
1212 1213 1214 1215 1216 1217 1218 | /* * Deal with some special edge cases. Note that in the case with one * argument, the only thing to do is to verify the dict-ness. */ if (parsePtr->numWords < 2) { | | | | | | | | | | | | | | > > | | | | | | | | | | | > | < | | | < | | | | | < | < | | 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 | /* * Deal with some special edge cases. Note that in the case with one * argument, the only thing to do is to verify the dict-ness. */ if (parsePtr->numWords < 2) { PUSH( ""); return TCL_OK; } else if (parsePtr->numWords == 2) { tokenPtr = TokenAfter(parsePtr->tokenPtr); PUSH_SUBST_WORD(tokenPtr, 1); OP( DUP); OP( DICT_VERIFY); return TCL_OK; } /* * There's real merging work to do. * * Allocate some working space. This means we'll only ever compile this * command when there's an LVT present. */ workerIndex = NewUnnamedLocal(envPtr); if (workerIndex < 0) { return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } infoIndex = NewUnnamedLocal(envPtr); /* * Get the first dictionary and verify that it is so. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); PUSH_SUBST_WORD(tokenPtr, 1); OP( DUP); OP( DICT_VERIFY); OP4( STORE_SCALAR, workerIndex); OP( POP); /* * For each of the remaining dictionaries... */ outLoop = DeclareExceptionRange(envPtr, CATCH_EXCEPTION_RANGE); OP4( BEGIN_CATCH, outLoop); ExceptionRangeStarts(envPtr, outLoop); for (i=2 ; i<parsePtr->numWords ; i++) { int endloop, loop; /* * Get the dictionary, and merge its pairs into the first dict (using * a small loop). */ tokenPtr = TokenAfter(tokenPtr); PUSH_SUBST_WORD(tokenPtr, i); OP4( DICT_FIRST, infoIndex); JUMP(endloop, JUMP_TRUE); LABEL(loop); OP( EXCH); OP44( DICT_SET, 1, workerIndex); TclAdjustStackDepth(-1, envPtr); OP( POP); OP4( DICT_NEXT, infoIndex); BACKJUMP(loop, JUMP_FALSE); FIXJUMP(endloop); OP( POP); OP( POP); OP14( UNSET_SCALAR, 0, infoIndex); } ExceptionRangeEnds(envPtr, outLoop); OP( END_CATCH); /* * Clean up any state left over. */ OP4( LOAD_SCALAR, workerIndex); OP14( UNSET_SCALAR, 0, workerIndex); OP4( JUMP, 21); /* * If an exception happens when starting to iterate over the second (and * subsequent) dicts. This is strictly not necessary, but it is nice. */ ExceptionRangeTarget(envPtr, outLoop, catchOffset); OP( PUSH_RETURN_OPTIONS); OP( PUSH_RESULT); OP( END_CATCH); OP14( UNSET_SCALAR, 0, workerIndex); OP14( UNSET_SCALAR, 0, infoIndex); OP( RETURN_STK); return TCL_OK; } int TclCompileDictForCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ |
︙ | ︙ | |||
1345 1346 1347 1348 1349 1350 1351 | CompileEnv *envPtr, /* Holds resulting instructions. */ int collect) /* Flag == TCL_EACH_COLLECT to collect and * construct a new dictionary with the loop * body result. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *varsTokenPtr, *dictTokenPtr, *bodyTokenPtr; | | | < | | | < | | | | | | | | | | | | | | | < | | | | | | < | | < > | < < > < > | | | | < | < | | < | | | < | | < | < < | < < > > | < < < | | | < | | 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 | CompileEnv *envPtr, /* Holds resulting instructions. */ int collect) /* Flag == TCL_EACH_COLLECT to collect and * construct a new dictionary with the loop * body result. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *varsTokenPtr, *dictTokenPtr, *bodyTokenPtr; int keyVarIndex, valueVarIndex, nameChars, loopRange, catchRange, numVars; int infoIndex, bodyTargetOffset, emptyTargetOffset, endTargetOffset; int collectVar = -1; /* Index of temp var holding the result * dict. */ int savedStackDepth = envPtr->currStackDepth; /* Needed because jumps confuse the stack * space calculator. */ const char **argv; Tcl_DString buffer; /* * There must be three arguments after the command. */ if (parsePtr->numWords != 4) { return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } varsTokenPtr = TokenAfter(parsePtr->tokenPtr); dictTokenPtr = TokenAfter(varsTokenPtr); bodyTokenPtr = TokenAfter(dictTokenPtr); if (varsTokenPtr->type != TCL_TOKEN_SIMPLE_WORD || bodyTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } /* * Create temporary variable to capture return values from loop body when * we're collecting results. */ if (collect == TCL_EACH_COLLECT) { collectVar = NewUnnamedLocal(envPtr); if (collectVar < 0) { return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } } /* * Check we've got a pair of variables and that they are local variables. * Then extract their indices in the LVT. */ Tcl_DStringInit(&buffer); TclDStringAppendToken(&buffer, &varsTokenPtr[1]); if (Tcl_SplitList(NULL, Tcl_DStringValue(&buffer), &numVars, &argv) != TCL_OK) { Tcl_DStringFree(&buffer); return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } Tcl_DStringFree(&buffer); if (numVars != 2) { ckfree(argv); return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } nameChars = strlen(argv[0]); if (!TclIsLocalScalar(argv[0], nameChars)) { ckfree(argv); return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } keyVarIndex = TclFindCompiledLocal(argv[0], nameChars, 1, envPtr); nameChars = strlen(argv[1]); if (!TclIsLocalScalar(argv[1], nameChars)) { ckfree(argv); return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } valueVarIndex = TclFindCompiledLocal(argv[1], nameChars, 1, envPtr); ckfree(argv); if ((keyVarIndex < 0) || (valueVarIndex < 0)) { return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } /* * Allocate a temporary variable to store the iterator reference. The * variable will contain a Tcl_DictSearch reference which will be * allocated by INST_DICT_FIRST and disposed when the variable is unset * (at which point it should also have been finished with). */ infoIndex = NewUnnamedLocal(envPtr); if (infoIndex < 0) { return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } /* * Preparation complete; issue instructions. Note that this code issues * fixed-sized jumps. That simplifies things a lot! * * First up, initialize the accumulator dictionary if needed. */ if (collect == TCL_EACH_COLLECT) { PUSH( ""); OP4( STORE_SCALAR, collectVar); OP( POP); } /* * Get the dictionary and start the iteration. No catching of errors at * this point. */ PUSH_SUBST_WORD(dictTokenPtr, 3); OP4( DICT_FIRST, infoIndex); JUMP(emptyTargetOffset, JUMP_TRUE); /* * Now we catch errors from here on so that we can finalize the search * started by Tcl_DictObjFirst above. */ catchRange = DeclareExceptionRange(envPtr, CATCH_EXCEPTION_RANGE); OP4( BEGIN_CATCH, catchRange); ExceptionRangeStarts(envPtr, catchRange); /* * Inside the iteration, write the loop variables. */ LABEL(bodyTargetOffset); OP4( STORE_SCALAR, keyVarIndex); OP( POP); OP4( STORE_SCALAR, valueVarIndex); OP( POP); /* * Set up the loop exception targets. */ loopRange = DeclareExceptionRange(envPtr, LOOP_EXCEPTION_RANGE); ExceptionRangeStarts(envPtr, loopRange); /* * Compile the loop body itself. It should be stack-neutral. */ BODY( bodyTokenPtr, 3); if (collect == TCL_EACH_COLLECT) { OP4( LOAD_SCALAR, keyVarIndex); OP( UNDER); OP44( DICT_SET, 1, collectVar); TclAdjustStackDepth(-1, envPtr); OP( POP); } OP( POP); /* * Both exception target ranges (error and loop) end here. */ ExceptionRangeEnds(envPtr, loopRange); ExceptionRangeEnds(envPtr, catchRange); /* * Continue (or just normally process) by getting the next pair of items * from the dictionary and jumping back to the code to write them into * variables if there is another pair. */ ExceptionRangeTarget(envPtr, loopRange, continueOffset); OP4( DICT_NEXT, infoIndex); BACKJUMP(bodyTargetOffset, JUMP_FALSE); OP( POP); OP( POP); /* * Now do the final cleanup for the no-error case (this is where we break * out of the loop to) by force-terminating the iteration (if not already * terminated), ditching the exception info and jumping to the last * instruction for this command. In theory, this could be done using the * "finally" clause (next generated) but this is faster. */ ExceptionRangeTarget(envPtr, loopRange, breakOffset); OP14( UNSET_SCALAR, 0, infoIndex); OP( END_CATCH); JUMP(endTargetOffset, JUMP); /* * Error handler "finally" clause, which force-terminates the iteration * and rethrows the error. */ ExceptionRangeTarget(envPtr, catchRange, catchOffset); OP( PUSH_RETURN_OPTIONS); OP( PUSH_RESULT); OP14( UNSET_SCALAR, 0, infoIndex); OP( END_CATCH); if (collect == TCL_EACH_COLLECT) { OP14( UNSET_SCALAR, 0, collectVar); } OP( RETURN_STK); /* * Otherwise we're done (the jump after the DICT_FIRST points here) and we * need to pop the bogus key/value pair (pushed to keep stack calculations * easy!) Note that we skip the END_CATCH. [Bug 1382528] */ envPtr->currStackDepth = savedStackDepth + 2; FIXJUMP( emptyTargetOffset); OP( POP); OP( POP); OP14( UNSET_SCALAR, 0, infoIndex); /* * Final stage of the command (normal case) is that we push an empty * object (or push the accumulator as the result object). This is done * last to promote peephole optimization when it's dropped immediately. */ FIXJUMP( endTargetOffset); if (collect == TCL_EACH_COLLECT) { OP4( LOAD_SCALAR, collectVar); OP14( UNSET_SCALAR, 0, collectVar); } else { PUSH( ""); } return TCL_OK; } int TclCompileDictUpdateCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ |
︙ | ︙ | |||
1628 1629 1630 1631 1632 1633 1634 | * The dictionary variable must be a local scalar that is knowable at * compile time; anything else exceeds the complexity of the opcode. So * discover what the index is. */ dictVarTokenPtr = TokenAfter(parsePtr->tokenPtr); if (dictVarTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { | | | | | 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 | * The dictionary variable must be a local scalar that is knowable at * compile time; anything else exceeds the complexity of the opcode. So * discover what the index is. */ dictVarTokenPtr = TokenAfter(parsePtr->tokenPtr); if (dictVarTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } name = dictVarTokenPtr[1].start; nameChars = dictVarTokenPtr[1].size; if (!TclIsLocalScalar(name, nameChars)) { return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } dictIndex = TclFindCompiledLocal(name, nameChars, 1, envPtr); if (dictIndex < 0) { return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } /* * Assemble the instruction metadata. This is complex enough that it is * represented as auxData; it holds an ordered list of variable indices * that are to be used. */ |
︙ | ︙ | |||
1688 1689 1690 1691 1692 1693 1694 | } tokenPtr = TokenAfter(tokenPtr); } if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { failedUpdateInfoAssembly: ckfree(duiPtr); TclStackFree(interp, keyTokenPtrs); | | | | | < | | < | | | < | | | | | < | | 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 | } tokenPtr = TokenAfter(tokenPtr); } if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { failedUpdateInfoAssembly: ckfree(duiPtr); TclStackFree(interp, keyTokenPtrs); return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } bodyTokenPtr = tokenPtr; /* * The list of variables to bind is stored in auxiliary data so that it * can't be snagged by literal sharing and forced to shimmer dangerously. */ infoIndex = TclCreateAuxData(duiPtr, &tclDictUpdateInfoType, envPtr); for (i=0 ; i<numVars ; i++) { PUSH_SUBST_WORD(keyTokenPtrs[i], i); } OP4( LIST, numVars); OP44( DICT_UPDATE_START, dictIndex, infoIndex); range = DeclareExceptionRange(envPtr, CATCH_EXCEPTION_RANGE); OP4( BEGIN_CATCH, range); ExceptionRangeStarts(envPtr, range); envPtr->currStackDepth++; BODY( bodyTokenPtr, parsePtr->numWords - 1); envPtr->currStackDepth = savedStackDepth; ExceptionRangeEnds(envPtr, range); /* * Normal termination code: the stack has the key list below the result of * the body evaluation: swap them and finish the update code. */ OP( END_CATCH); OP( EXCH); OP44( DICT_UPDATE_END, dictIndex, infoIndex); /* * Jump around the exceptional termination code. */ TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup); /* * Termination code for non-ok returns: stash the result and return * options in the stack, bring up the key list, finish the update code, * and finally return with the catched return data */ ExceptionRangeTarget(envPtr, range, catchOffset); OP( PUSH_RESULT); OP( PUSH_RETURN_OPTIONS); OP( END_CATCH); OP4( REVERSE, 3); OP44( DICT_UPDATE_END, dictIndex, infoIndex); OP( RETURN_STK); if (TclFixupForwardJumpToHere(envPtr, &jumpFixup, 127)) { Tcl_Panic("TclCompileDictCmd(update): bad jump distance %d", (int) (CurrentOffset(envPtr) - jumpFixup.codeOffset)); } TclStackFree(interp, keyTokenPtrs); envPtr->currStackDepth = savedStackDepth + 1; |
︙ | ︙ | |||
1786 1787 1788 1789 1790 1791 1792 | /* * Get the index of the local variable that we will be working with. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { | | | | | | | | 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 | /* * Get the index of the local variable that we will be working with. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } else { register const char *name = tokenPtr[1].start; register int nameChars = tokenPtr[1].size; if (!TclIsLocalScalar(name, nameChars)) { return TclCompileBasicMin2ArgCmd(interp, parsePtr,cmdPtr, envPtr); } dictVarIndex = TclFindCompiledLocal(name, nameChars, 1, envPtr); if (dictVarIndex < 0) { return TclCompileBasicMin2ArgCmd(interp, parsePtr,cmdPtr, envPtr); } } /* * Produce the string to concatenate onto the dictionary entry. */ tokenPtr = TokenAfter(tokenPtr); for (i=2 ; i<parsePtr->numWords ; i++) { PUSH_SUBST_WORD(tokenPtr, i); tokenPtr = TokenAfter(tokenPtr); } if (parsePtr->numWords > 4) { OP1( CONCAT, parsePtr->numWords-3); } /* * Do the concatenation. */ OP4( DICT_APPEND, dictVarIndex); return TCL_OK; } int TclCompileDictLappendCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command |
︙ | ︙ | |||
1847 1848 1849 1850 1851 1852 1853 | return TCL_ERROR; } varTokenPtr = TokenAfter(parsePtr->tokenPtr); keyTokenPtr = TokenAfter(varTokenPtr); valueTokenPtr = TokenAfter(keyTokenPtr); if (varTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { | | | | | | | | 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 | return TCL_ERROR; } varTokenPtr = TokenAfter(parsePtr->tokenPtr); keyTokenPtr = TokenAfter(varTokenPtr); valueTokenPtr = TokenAfter(keyTokenPtr); if (varTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } name = varTokenPtr[1].start; nameChars = varTokenPtr[1].size; if (!TclIsLocalScalar(name, nameChars)) { return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } dictVarIndex = TclFindCompiledLocal(name, nameChars, 1, envPtr); if (dictVarIndex < 0) { return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } PUSH_SUBST_WORD(keyTokenPtr, 3); PUSH_SUBST_WORD(valueTokenPtr, 4); OP4( DICT_LAPPEND, dictVarIndex); return TCL_OK; } int TclCompileDictWithCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command |
︙ | ︙ | |||
1900 1901 1902 1903 1904 1905 1906 | varTokenPtr = TokenAfter(parsePtr->tokenPtr); tokenPtr = TokenAfter(varTokenPtr); for (i=3 ; i<parsePtr->numWords ; i++) { tokenPtr = TokenAfter(tokenPtr); } if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { | | | > | 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 | varTokenPtr = TokenAfter(parsePtr->tokenPtr); tokenPtr = TokenAfter(varTokenPtr); for (i=3 ; i<parsePtr->numWords ; i++) { tokenPtr = TokenAfter(tokenPtr); } if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } /* * Test if the last word is an empty script; if so, we can compile it in * all cases, but if it is non-empty we need local variable table entries * to hold the temporary variables (used to keep stack usage simple). */ for (ptr=tokenPtr[1].start,end=ptr+tokenPtr[1].size ; ptr!=end ; ptr++) { if (*ptr!=' ' && *ptr!='\t' && *ptr!='\n' && *ptr!='\r') { if (envPtr->procPtr == NULL) { return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } bodyIsEmpty = 0; break; } } /* |
︙ | ︙ | |||
1947 1948 1949 1950 1951 1952 1953 | if (gotPath) { /* * Case: Path into dict in LVT with empty body. */ tokenPtr = TokenAfter(varTokenPtr); for (i=2 ; i<parsePtr->numWords-1 ; i++) { | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | | | | | | | | | | | | | | | | | | 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 | if (gotPath) { /* * Case: Path into dict in LVT with empty body. */ tokenPtr = TokenAfter(varTokenPtr); for (i=2 ; i<parsePtr->numWords-1 ; i++) { PUSH_SUBST_WORD(tokenPtr, i-1); tokenPtr = TokenAfter(tokenPtr); } OP4( LIST, parsePtr->numWords-3); OP4( LOAD_SCALAR, dictVar); OP( UNDER); OP( DICT_EXPAND); OP4( DICT_RECOMBINE_IMM, dictVar); PUSH( ""); } else { /* * Case: Direct dict in LVT with empty body. */ PUSH( ""); OP4( LOAD_SCALAR, dictVar); PUSH( ""); OP( DICT_EXPAND); OP4( DICT_RECOMBINE_IMM, dictVar); PUSH( ""); } } else { if (gotPath) { /* * Case: Path into dict in non-simple var with empty body. */ tokenPtr = varTokenPtr; for (i=1 ; i<parsePtr->numWords-1 ; i++) { PUSH_SUBST_WORD(tokenPtr, i-1); tokenPtr = TokenAfter(tokenPtr); } OP4( LIST, parsePtr->numWords-3); OP( UNDER); OP( LOAD_STK); OP( UNDER); OP( DICT_EXPAND); OP( DICT_RECOMBINE_STK); PUSH( ""); } else { /* * Case: Direct dict in non-simple var with empty body. */ PUSH_SUBST_WORD(varTokenPtr, 0); OP( DUP); OP( LOAD_STK); PUSH( ""); OP( DICT_EXPAND); PUSH( ""); OP( EXCH); OP( DICT_RECOMBINE_STK); PUSH( ""); } } envPtr->currStackDepth = savedStackDepth + 1; return TCL_OK; } /* * OK, we have a non-trivial body. This means that the focus is on * generating a try-finally structure where the INST_DICT_RECOMBINE_* goes * in the 'finally' clause. * * Start by allocating local (unnamed, untraced) working variables. */ if (dictVar == -1) { varNameTmp = NewUnnamedLocal(envPtr); } else { varNameTmp = -1; } if (gotPath) { pathTmp = NewUnnamedLocal(envPtr); } else { pathTmp = -1; } keysTmp = NewUnnamedLocal(envPtr); /* * Issue instructions. First, the part to expand the dictionary. */ if (varNameTmp > -1) { PUSH_SUBST_WORD(varTokenPtr, 0); OP4( STORE_SCALAR, varNameTmp); } tokenPtr = TokenAfter(varTokenPtr); if (gotPath) { for (i=2 ; i<parsePtr->numWords-1 ; i++) { PUSH_SUBST_WORD(tokenPtr, i-1); tokenPtr = TokenAfter(tokenPtr); } OP4( LIST, parsePtr->numWords-3); OP4( STORE_SCALAR, pathTmp); OP( POP); } if (dictVar == -1) { OP( LOAD_STK); } else { OP4( LOAD_SCALAR, dictVar); } if (gotPath) { OP4( LOAD_SCALAR, pathTmp); } else { PUSH( ""); } OP( DICT_EXPAND); OP4( STORE_SCALAR, keysTmp); OP( POP); /* * Now the body of the [dict with]. */ range = DeclareExceptionRange(envPtr, CATCH_EXCEPTION_RANGE); OP4( BEGIN_CATCH, range); ExceptionRangeStarts(envPtr, range); envPtr->currStackDepth++; BODY( tokenPtr, parsePtr->numWords-1); envPtr->currStackDepth = savedStackDepth; ExceptionRangeEnds(envPtr, range); /* * Now fold the results back into the dictionary in the OK case. */ OP( END_CATCH); if (varNameTmp > -1) { OP4( LOAD_SCALAR, varNameTmp); } if (gotPath) { OP4( LOAD_SCALAR, pathTmp); } else { PUSH( ""); } OP4( LOAD_SCALAR, keysTmp); if (dictVar == -1) { OP( DICT_RECOMBINE_STK); } else { OP4( DICT_RECOMBINE_IMM, dictVar); } TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup); /* * Now fold the results back into the dictionary in the exception case. */ ExceptionRangeTarget(envPtr, range, catchOffset); OP( PUSH_RETURN_OPTIONS); OP( PUSH_RESULT); OP( END_CATCH); if (varNameTmp > -1) { OP4( LOAD_SCALAR, varNameTmp); } if (parsePtr->numWords > 3) { OP4( LOAD_SCALAR, pathTmp); } else { PUSH( ""); } OP4( LOAD_SCALAR, keysTmp); if (dictVar == -1) { OP( DICT_RECOMBINE_STK); } else { OP4( DICT_RECOMBINE_IMM, dictVar); } OP( RETURN_STK); /* * Prepare for the start of the next command. */ envPtr->currStackDepth = savedStackDepth + 1; if (TclFixupForwardJumpToHere(envPtr, &jumpFixup, 127)) { |
︙ | ︙ | |||
2229 2230 2231 2232 2233 2234 2235 | DefineLineInformation; /* TIP #280 */ if (parsePtr->numWords != 2) { return TCL_ERROR; } messageTokenPtr = TokenAfter(parsePtr->tokenPtr); | | | | | 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 | DefineLineInformation; /* TIP #280 */ if (parsePtr->numWords != 2) { return TCL_ERROR; } messageTokenPtr = TokenAfter(parsePtr->tokenPtr); PUSH( "-code error -level 0"); PUSH_SUBST_WORD(messageTokenPtr, 1); OP( RETURN_STK); envPtr->currStackDepth = savedStackDepth + 1; return TCL_OK; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
2356 2357 2358 2359 2360 2361 2362 | bodyRange = DeclareExceptionRange(envPtr, LOOP_EXCEPTION_RANGE); nextRange = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr); /* * Inline compile the initial command. */ | < | | < | | < | | | < | | < | | 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 | bodyRange = DeclareExceptionRange(envPtr, LOOP_EXCEPTION_RANGE); nextRange = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr); /* * Inline compile the initial command. */ BODY( startTokenPtr, 1); OP( POP); /* * Jump to the evaluation of the condition. This code uses the "loop * rotation" optimisation (which eliminates one branch from the loop). * "for start cond next body" produces then: * start * goto A * B: body : bodyCodeOffset * next : nextCodeOffset, continueOffset * A: cond -> result : testCodeOffset * if (result) goto B */ TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpEvalCondFixup); /* * Compile the loop body. */ bodyCodeOffset = ExceptionRangeStarts(envPtr, bodyRange); BODY( bodyTokenPtr, 4); ExceptionRangeEnds(envPtr, bodyRange); envPtr->currStackDepth = savedStackDepth + 1; OP( POP); /* * Compile the "next" subcommand. */ envPtr->currStackDepth = savedStackDepth; nextCodeOffset = ExceptionRangeStarts(envPtr, nextRange); BODY( nextTokenPtr, 3); ExceptionRangeEnds(envPtr, nextRange); envPtr->currStackDepth = savedStackDepth + 1; OP( POP); envPtr->currStackDepth = savedStackDepth; /* * Compile the test expression then emit the conditional jump that * terminates the for. */ LABEL( testCodeOffset); jumpDist = testCodeOffset - jumpEvalCondFixup.codeOffset; if (TclFixupForwardJump(envPtr, &jumpEvalCondFixup, jumpDist, 127)) { bodyCodeOffset += 3; nextCodeOffset += 3; testCodeOffset += 3; } envPtr->currStackDepth = savedStackDepth; PUSH_EXPR_WORD(testTokenPtr, 2); envPtr->currStackDepth = savedStackDepth + 1; BACKJUMP( bodyCodeOffset, JUMP_TRUE); /* * Fix the starting points of the exception ranges (may have moved due to * jump type modification) and set where the exceptions target. */ envPtr->exceptArrayPtr[bodyRange].codeOffset = bodyCodeOffset; envPtr->exceptArrayPtr[bodyRange].continueOffset = nextCodeOffset; envPtr->exceptArrayPtr[nextRange].codeOffset = nextCodeOffset; ExceptionRangeTarget(envPtr, bodyRange, breakOffset); ExceptionRangeTarget(envPtr, nextRange, breakOffset); /* * The for command's result is an empty string. */ envPtr->currStackDepth = savedStackDepth; PUSH( ""); return TCL_OK; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
2515 2516 2517 2518 2519 2520 2521 | * used to point to a value list. */ int loopCtTemp; /* Index of temp var holding the loop's * iteration count. */ int collectVar = -1; /* Index of temp var holding the result var * index. */ Tcl_Token *tokenPtr, *bodyTokenPtr; | < | | 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 | * used to point to a value list. */ int loopCtTemp; /* Index of temp var holding the loop's * iteration count. */ int collectVar = -1; /* Index of temp var holding the result var * index. */ Tcl_Token *tokenPtr, *bodyTokenPtr; JumpFixup jumpFalseFixup; int infoIndex, range, bodyIndex; int numWords, numLists, numVars, loopIndex, tempVar, i, j, code; int savedStackDepth = envPtr->currStackDepth; DefineLineInformation; /* TIP #280 */ /* * We parse the variable list argument words and create two arrays: * varcList[i] is number of variables in i-th var list. |
︙ | ︙ | |||
2630 2631 2632 2633 2634 2635 2636 | goto done; } } loopIndex++; } if (collect == TCL_EACH_COLLECT) { | < | | < | < | 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 | goto done; } } loopIndex++; } if (collect == TCL_EACH_COLLECT) { collectVar = NewUnnamedLocal(envPtr); if (collectVar < 0) { return TCL_ERROR; } } /* * We will compile the foreach command. Reserve (numLists + 1) temporary * variables: * - numLists temps to hold each value list * - 1 temp for the loop counter (index of next element in each list) * * At this time we don't try to reuse temporaries; if there are two * nonoverlapping foreach loops, they don't share any temps. */ code = TCL_OK; firstValueTemp = -1; for (loopIndex = 0; loopIndex < numLists; loopIndex++) { tempVar = NewUnnamedLocal(envPtr); if (loopIndex == 0) { firstValueTemp = tempVar; } } loopCtTemp = NewUnnamedLocal(envPtr); /* * Create and initialize the ForeachInfo and ForeachVarList data * structures describing this command. Then create a AuxData record * pointing to the ForeachInfo structure. */ |
︙ | ︙ | |||
2703 2704 2705 2706 2707 2708 2709 | */ loopIndex = 0; for (i = 0, tokenPtr = parsePtr->tokenPtr; i < numWords-1; i++, tokenPtr = TokenAfter(tokenPtr)) { if ((i%2 == 0) && (i > 0)) { | < | | < > | | | | | < | | | < | < < < < < < < < < < < | | < | | 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 | */ loopIndex = 0; for (i = 0, tokenPtr = parsePtr->tokenPtr; i < numWords-1; i++, tokenPtr = TokenAfter(tokenPtr)) { if ((i%2 == 0) && (i > 0)) { PUSH_SUBST_WORD(tokenPtr, i); tempVar = (firstValueTemp + loopIndex); OP4(STORE_SCALAR, tempVar); OP( POP); loopIndex++; } } /* * Create temporary variable to capture return values from loop body. */ if (collect == TCL_EACH_COLLECT) { PUSH( ""); OP4( STORE_SCALAR, collectVar); OP( POP); } /* * Initialize the temporary var that holds the count of loop iterations. */ OP4( FOREACH_START, infoIndex); /* * Top of loop code: assign each loop variable and check whether * to terminate the loop. */ ExceptionRangeTarget(envPtr, range, continueOffset); OP4( FOREACH_STEP, infoIndex); TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpFalseFixup); /* * Inline compile the loop body. */ ExceptionRangeStarts(envPtr, range); BODY( bodyTokenPtr, bodyIndex); ExceptionRangeEnds(envPtr, range); envPtr->currStackDepth = savedStackDepth + 1; if (collect == TCL_EACH_COLLECT) { OP4( LAPPEND_SCALAR, collectVar); } OP( POP); /* * Jump back to the test at the top of the loop. Generate a 4 byte jump if * the distance to the test is > 120 bytes. This is conservative and * ensures that we won't have to replace this jump if we later need to * replace the ifFalse jump with a 4 byte jump. */ BACKJUMP(envPtr->exceptArrayPtr[range].continueOffset, JUMP); /* * Fix the target of the jump after the foreach_step test. */ if (TclFixupForwardJumpToHere(envPtr, &jumpFalseFixup, 127)) { /* * Update the loop body's starting PC offset since it moved down. */ envPtr->exceptArrayPtr[range].codeOffset += 3; } /* * Set the loop's break target. */ ExceptionRangeTarget(envPtr, range, breakOffset); /* * The command's result is an empty string if not collecting, or the * list of results from evaluating the loop body. */ envPtr->currStackDepth = savedStackDepth; if (collect == TCL_EACH_COLLECT) { OP4( LOAD_SCALAR, collectVar); OP14( UNSET_SCALAR, 0, collectVar); } else { PUSH( ""); } envPtr->currStackDepth = savedStackDepth + 1; done: for (loopIndex = 0; loopIndex < numLists; loopIndex++) { if (varvList[loopIndex] != NULL) { ckfree(varvList[loopIndex]); |
︙ | ︙ | |||
3047 3048 3049 3050 3051 3052 3053 | } /* * Not an error, always a constant result, so just push the result as a * literal. Job done. */ | | < | | 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 | } /* * Not an error, always a constant result, so just push the result as a * literal. Job done. */ PUSH_OBJ(tmpObj); Tcl_DecrRefCount(tmpObj); return TCL_OK; checkForStringConcatCase: /* * See if we can generate a sequence of things to concatenate. This * requires that all the % sequences be %s or %%, as everything else is * sufficiently complex that we don't bother. * * First, get the state of the system relatively sensible (cleaning up * after our attempt to spot a literal). */ for (; i>=0 ; i--) { Tcl_DecrRefCount(objv[i]); } ckfree(objv); tokenPtr = TokenAfter(parsePtr->tokenPtr); tokenPtr = TokenAfter(tokenPtr); i = 0; |
︙ | ︙ | |||
3118 3119 3120 3121 3122 3123 3124 | * being built. */ for (bytes = start ; *bytes ; bytes++) { if (*bytes == '%') { Tcl_AppendToObj(tmpObj, start, bytes - start); if (*++bytes == '%') { Tcl_AppendToObj(tmpObj, "%", 1); } else { | | | | | | | | | | | | 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 | * being built. */ for (bytes = start ; *bytes ; bytes++) { if (*bytes == '%') { Tcl_AppendToObj(tmpObj, start, bytes - start); if (*++bytes == '%') { Tcl_AppendToObj(tmpObj, "%", 1); } else { (void) Tcl_GetStringFromObj(tmpObj, &len); /* * If there is a non-empty literal from the format string, * push it and reset. */ if (len > 0) { PUSH_OBJ(tmpObj); Tcl_DecrRefCount(tmpObj); tmpObj = Tcl_NewObj(); i++; } /* * Push the code to produce the string that would be * substituted with %s, except we'll be concatenating * directly. */ PUSH_SUBST_WORD(tokenPtr, j); tokenPtr = TokenAfter(tokenPtr); j++; i++; } start = bytes + 1; } } /* * Handle the case of a trailing literal. */ Tcl_AppendToObj(tmpObj, start, bytes - start); (void) Tcl_GetStringFromObj(tmpObj, &len); if (len > 0) { PUSH_OBJ(tmpObj); i++; } Tcl_DecrRefCount(tmpObj); Tcl_DecrRefCount(formatObj); if (i > 1) { /* * Do the concatenation, which produces the result. */ OP1( CONCAT, i); } else { /* * EVIL HACK! Force there to be a string representation in the case * where there's just a "%s" in the format; case covered by the test * format-20.1 (and it is horrible...) */ OP( DUP); PUSH( ""); OP( STR_EQ); OP( POP); } return TCL_OK; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
3226 3227 3228 3229 3230 3231 3232 | */ if (envPtr->procPtr == NULL) { return TCL_ERROR; } /* | | | | | | | | 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 | */ if (envPtr->procPtr == NULL) { return TCL_ERROR; } /* * Push the namespace. */ PUSH( "::"); /* * Loop over the variables. */ varTokenPtr = TokenAfter(parsePtr->tokenPtr); for (i=2; i<=numWords; varTokenPtr = TokenAfter(varTokenPtr),i++) { localIndex = IndexTailVarIfKnown(interp, varTokenPtr, envPtr); if (localIndex < 0) { return TCL_ERROR; } PUSH_SUBST_WORD(varTokenPtr, 1); OP4( NSUPVAR, localIndex); } /* * Pop the namespace, and set the result to empty */ OP( POP); PUSH( ""); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileIfCmd -- |
︙ | ︙ | |||
3379 3380 3381 3382 3383 3384 3385 | */ realCond = 0; if (!boolVal) { compileScripts = 0; } } else { | < | | 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 | */ realCond = 0; if (!boolVal) { compileScripts = 0; } } else { Tcl_ResetResult(interp); PUSH_EXPR_WORD(testTokenPtr, wordIdx); if (jumpFalseFixupArray.next >= jumpFalseFixupArray.end) { TclExpandJumpFixupArray(&jumpFalseFixupArray); } jumpIndex = jumpFalseFixupArray.next; jumpFalseFixupArray.next++; TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, jumpFalseFixupArray.fixup+jumpIndex); |
︙ | ︙ | |||
3421 3422 3423 3424 3425 3426 3427 | } /* * Compile the "then" command body. */ if (compileScripts) { | < | | 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 | } /* * Compile the "then" command body. */ if (compileScripts) { envPtr->currStackDepth = savedStackDepth; BODY( tokenPtr, wordIdx); } if (realCond) { /* * Jump to the end of the "if" command. Both jumpFalseFixupArray * and jumpEndFixupArray are indexed by "jumpIndex". */ |
︙ | ︙ | |||
3509 3510 3511 3512 3513 3514 3515 | } if (compileScripts) { /* * Compile the else command body. */ | | < | | 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 | } if (compileScripts) { /* * Compile the else command body. */ BODY(tokenPtr, wordIdx); } /* * Make sure there are no words after the else clause. */ wordIdx++; if (wordIdx < numWords) { code = TCL_ERROR; goto done; } } else { /* * No else clause: the "if" command's result is an empty string. */ if (compileScripts) { PUSH( ""); } } /* * Fix the unconditional jumps to the end of the "if" command. */ |
︙ | ︙ | |||
3606 3607 3608 3609 3610 3611 3612 | DefineLineInformation; /* TIP #280 */ if ((parsePtr->numWords != 2) && (parsePtr->numWords != 3)) { return TCL_ERROR; } varTokenPtr = TokenAfter(parsePtr->tokenPtr); | | < | | 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 | DefineLineInformation; /* TIP #280 */ if ((parsePtr->numWords != 2) && (parsePtr->numWords != 3)) { return TCL_ERROR; } varTokenPtr = TokenAfter(parsePtr->tokenPtr); PUSH_VAR( varTokenPtr, 1, &localIndex, &simpleVarName, &isScalar); /* * If an increment is given, push it, but see first if it's a small * integer. */ haveImmValue = 0; |
︙ | ︙ | |||
3635 3636 3637 3638 3639 3640 3641 | if ((code == TCL_OK) && (-127 <= immValue) && (immValue <= 127)) { haveImmValue = 1; } if (!haveImmValue) { PushLiteral(envPtr, word, numBytes); } } else { | < | | | | < | | | | < | | | | 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 | if ((code == TCL_OK) && (-127 <= immValue) && (immValue <= 127)) { haveImmValue = 1; } if (!haveImmValue) { PushLiteral(envPtr, word, numBytes); } } else { PUSH_SUBST_WORD(incrTokenPtr, 2); } } else { /* No incr amount given so use 1. */ haveImmValue = 1; } /* * Emit the instruction to increment the variable. */ if (!simpleVarName) { if (haveImmValue) { OP1( INCR_STK_IMM, immValue); } else { OP( INCR_STK); } } else if (isScalar) { /* Simple scalar variable. */ if (localIndex >= 0) { if (haveImmValue) { OP41( INCR_SCALAR_IMM, localIndex, immValue); } else { OP4( INCR_SCALAR, localIndex); } } else { if (haveImmValue) { OP1( INCR_STK_IMM, immValue); } else { OP( INCR_STK); } } } else { /* Simple array variable. */ if (localIndex >= 0) { if (haveImmValue) { OP41( INCR_ARRAY_IMM, localIndex, immValue); } else { OP4( INCR_ARRAY, localIndex); } } else { if (haveImmValue) { OP1( INCR_ARRAY_STK_IMM, immValue); } else { OP( INCR_ARRAY_STK); } } } return TCL_OK; } |
︙ | ︙ | |||
3723 3724 3725 3726 3727 3728 3729 | Tcl_Obj *objPtr; char *bytes; /* * We require one compile-time known argument for the case we can compile. */ | | > > | 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 | Tcl_Obj *objPtr; char *bytes; /* * We require one compile-time known argument for the case we can compile. */ if (parsePtr->numWords == 1) { return TclCompileBasic0ArgCmd(interp, parsePtr, cmdPtr, envPtr); } else if (parsePtr->numWords != 2) { return TCL_ERROR; } tokenPtr = TokenAfter(parsePtr->tokenPtr); objPtr = Tcl_NewObj(); Tcl_IncrRefCount(objPtr); if (!TclWordKnownAtCompileTime(tokenPtr, objPtr)) { goto notCompilable; |
︙ | ︙ | |||
3750 3751 3752 3753 3754 3755 3756 | Tcl_DecrRefCount(objPtr); /* * Confirmed as a literal that will not frighten the horses. Compile. Note * that the result needs to be list-ified. */ | | | | | | | | | 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 | Tcl_DecrRefCount(objPtr); /* * Confirmed as a literal that will not frighten the horses. Compile. Note * that the result needs to be list-ified. */ PUSH_SUBST_WORD(tokenPtr, 1); OP( RESOLVE_COMMAND); OP( DUP); OP( STR_LEN); OP4( JUMP_FALSE, 10); OP4( LIST, 1); return TCL_OK; notCompilable: Tcl_DecrRefCount(objPtr); return TclCompileBasic1ArgCmd(interp, parsePtr, cmdPtr, envPtr); } int TclCompileInfoCoroutineCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ |
︙ | ︙ | |||
3784 3785 3786 3787 3788 3789 3790 | return TCL_ERROR; } /* * Not much to do; we compile to a single instruction... */ | | | 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 | return TCL_ERROR; } /* * Not much to do; we compile to a single instruction... */ OP( COROUTINE_NAME); return TCL_OK; } int TclCompileInfoExistsCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command |
︙ | ︙ | |||
3814 3815 3816 3817 3818 3819 3820 | * to emit code to compute and push the name at runtime. We use a frame * slot (entry in the array of local vars) if we are compiling a procedure * body and if the name is simple text that does not include namespace * qualifiers. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); | | | | | | | | | 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 | * to emit code to compute and push the name at runtime. We use a frame * slot (entry in the array of local vars) if we are compiling a procedure * body and if the name is simple text that does not include namespace * qualifiers. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); PUSH_VAR( tokenPtr, 1, &localIndex, &simpleVarName, &isScalar); /* * Emit instruction to check the variable for existence. */ if (!simpleVarName) { OP( EXIST_STK); } else if (isScalar) { if (localIndex < 0) { OP( EXIST_STK); } else { OP4(EXIST_SCALAR, localIndex); } } else { if (localIndex < 0) { OP( EXIST_ARRAY_STK); } else { OP4(EXIST_ARRAY, localIndex); } } return TCL_OK; } int |
︙ | ︙ | |||
3858 3859 3860 3861 3862 3863 3864 | */ if (parsePtr->numWords == 1) { /* * Not much to do; we compile to a single instruction... */ | | < | | | | | 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 | */ if (parsePtr->numWords == 1) { /* * Not much to do; we compile to a single instruction... */ OP( INFO_LEVEL_NUM); } else if (parsePtr->numWords != 2) { return TCL_ERROR; } else { DefineLineInformation; /* TIP #280 */ /* * Compile the argument, then add the instruction to convert it into a * list of arguments. */ PUSH_SUBST_WORD(TokenAfter(parsePtr->tokenPtr), 1); OP( INFO_LEVEL_ARGS); } return TCL_OK; } int TclCompileInfoObjectClassCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr); if (parsePtr->numWords != 2) { return TCL_ERROR; } PUSH_SUBST_WORD(tokenPtr, 1); OP( TCLOO_CLASS); return TCL_OK; } int TclCompileInfoObjectIsACmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command |
︙ | ︙ | |||
3927 3928 3929 3930 3931 3932 3933 | } tokenPtr = TokenAfter(tokenPtr); /* * Issue the code. */ | | | | | | 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 | } tokenPtr = TokenAfter(tokenPtr); /* * Issue the code. */ PUSH_SUBST_WORD(tokenPtr, 2); OP( TCLOO_IS_OBJECT); return TCL_OK; } int TclCompileInfoObjectNamespaceCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr); if (parsePtr->numWords != 2) { return TCL_ERROR; } PUSH_SUBST_WORD(tokenPtr, 1); OP( TCLOO_NS); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileLappendCmd -- |
︙ | ︙ | |||
4012 4013 4014 4015 4016 4017 4018 | * need to emit code to compute and push the name at runtime. We use a * frame slot (entry in the array of local vars) if we are compiling a * procedure body and if the name is simple text that does not include * namespace qualifiers. */ varTokenPtr = TokenAfter(parsePtr->tokenPtr); | < | | | < < | | | | | | 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 | * need to emit code to compute and push the name at runtime. We use a * frame slot (entry in the array of local vars) if we are compiling a * procedure body and if the name is simple text that does not include * namespace qualifiers. */ varTokenPtr = TokenAfter(parsePtr->tokenPtr); PUSH_VAR( varTokenPtr, 1, &localIndex, &simpleVarName, &isScalar); /* * If we are doing an assignment, push the new value. In the no values * case, create an empty object. */ if (numWords > 2) { PUSH_SUBST_WORD(TokenAfter(varTokenPtr), 2); } /* * Emit instructions to set/get the variable. */ /* * The *_STK opcodes should be refactored to make better use of existing * LOAD/STORE instructions. */ if (!simpleVarName) { OP( LAPPEND_STK); } else if (isScalar) { if (localIndex < 0) { OP( LAPPEND_STK); } else { OP4(LAPPEND_SCALAR, localIndex); } } else { if (localIndex < 0) { OP( LAPPEND_ARRAY_STK); } else { OP4(LAPPEND_ARRAY, localIndex); } } return TCL_OK; } /* |
︙ | ︙ | |||
4101 4102 4103 4104 4105 4106 4107 | } /* * Generate code to push list being taken apart by [lassign]. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); | | | | | | | | | | | | | | | | | | | | | | | | | < < | 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 | } /* * Generate code to push list being taken apart by [lassign]. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); PUSH_SUBST_WORD(tokenPtr, 1); /* * Generate code to assign values from the list to variables. */ for (idx=0 ; idx<numWords-2 ; idx++) { tokenPtr = TokenAfter(tokenPtr); /* * Generate the next variable name. */ PUSH_VAR( tokenPtr, idx+2, &localIndex, &simpleVarName, &isScalar); /* * Emit instructions to get the idx'th item out of the list value on * the stack and assign it to the variable. */ if (!simpleVarName) { OP( UNDER); OP4( LIST_INDEX_IMM, idx); OP( STORE_STK); OP( POP); } else if (isScalar) { if (localIndex >= 0) { OP( DUP); OP4( LIST_INDEX_IMM, idx); OP4( STORE_SCALAR, localIndex); OP( POP); } else { OP( UNDER); OP4( LIST_INDEX_IMM, idx); OP( STORE_SCALAR_STK); OP( POP); } } else { if (localIndex >= 0) { OP( UNDER); OP4( LIST_INDEX_IMM, idx); OP4( STORE_ARRAY, localIndex); OP( POP); } else { OP4( OVER, 2); OP4( LIST_INDEX_IMM, idx); OP( STORE_ARRAY_STK); OP( POP); } } } /* * Generate code to leave the rest of the list on the stack. */ OP44( LIST_RANGE_IMM, idx, -2 /* == "end" */); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileLindexCmd -- |
︙ | ︙ | |||
4237 4238 4239 4240 4241 4242 4243 | * these constructs: * lindex <arbitraryValue> <posInt> * lindex <arbitraryValue> end-<posInt> * This is best compiled as a push of the arbitrary value followed * by an "immediate lindex" which is the most efficient variety. */ | | | | | | | 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 | * these constructs: * lindex <arbitraryValue> <posInt> * lindex <arbitraryValue> end-<posInt> * This is best compiled as a push of the arbitrary value followed * by an "immediate lindex" which is the most efficient variety. */ PUSH_SUBST_WORD(valTokenPtr, 1); OP4(LIST_INDEX_IMM, idx); return TCL_OK; } /* * If the conversion failed or the value was negative, we just keep on * going with the more complex compilation. */ } /* * Push the operands onto the stack. */ emitComplexLindex: for (i=1 ; i<numWords ; i++) { PUSH_SUBST_WORD(valTokenPtr, i); valTokenPtr = TokenAfter(valTokenPtr); } /* * Emit INST_LIST_INDEX if objc==3, or INST_LIST_INDEX_MULTI if there are * multiple index args. */ if (numWords == 3) { OP( LIST_INDEX); } else { OP4( LIST_INDEX_MULTI, numWords-1); } return TCL_OK; } /* *---------------------------------------------------------------------- |
︙ | ︙ | |||
4316 4317 4318 4319 4320 4321 4322 | } if (parsePtr->numWords == 1) { /* * [list] without arguments just pushes an empty object. */ | | | | | 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 | } if (parsePtr->numWords == 1) { /* * [list] without arguments just pushes an empty object. */ PUSH( ""); } else { /* * Push the all values onto the stack. */ numWords = parsePtr->numWords; valueTokenPtr = TokenAfter(parsePtr->tokenPtr); for (i = 1; i < numWords; i++) { PUSH_SUBST_WORD(valueTokenPtr, i); valueTokenPtr = TokenAfter(valueTokenPtr); } OP4( LIST, numWords-1); } return TCL_OK; } /* *---------------------------------------------------------------------- |
︙ | ︙ | |||
4369 4370 4371 4372 4373 4374 4375 | DefineLineInformation; /* TIP #280 */ if (parsePtr->numWords != 2) { return TCL_ERROR; } varTokenPtr = TokenAfter(parsePtr->tokenPtr); | | | | 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 | DefineLineInformation; /* TIP #280 */ if (parsePtr->numWords != 2) { return TCL_ERROR; } varTokenPtr = TokenAfter(parsePtr->tokenPtr); PUSH_SUBST_WORD(varTokenPtr, 1); OP( LIST_LENGTH); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileLrangeCmd -- |
︙ | ︙ | |||
4464 4465 4466 4467 4468 4469 4470 | /* * Issue instructions. It's not safe to skip doing the LIST_RANGE, as * we've not proved that the 'list' argument is really a list. Not that it * is worth trying to do that given current knowledge. */ | | | < | 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 | /* * Issue instructions. It's not safe to skip doing the LIST_RANGE, as * we've not proved that the 'list' argument is really a list. Not that it * is worth trying to do that given current knowledge. */ PUSH_SUBST_WORD(listTokenPtr, 1); OP44( LIST_RANGE_IMM, idx1, idx2); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileLreplaceCmd -- |
︙ | ︙ | |||
4582 4583 4584 4585 4586 4587 4588 | /* * Issue instructions. It's not safe to skip doing the LIST_RANGE, as * we've not proved that the 'list' argument is really a list. Not that it * is worth trying to do that given current knowledge. */ | | | | | | < | 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 | /* * Issue instructions. It's not safe to skip doing the LIST_RANGE, as * we've not proved that the 'list' argument is really a list. Not that it * is worth trying to do that given current knowledge. */ PUSH_SUBST_WORD(listTokenPtr, 1); if (guaranteedDropAll) { OP( LIST_LENGTH); OP( POP); PUSH( ""); } else { OP44( LIST_RANGE_IMM, idx1, idx2); } return TCL_OK; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
4674 4675 4676 4677 4678 4679 4680 | * to emit code to compute and push the name at runtime. We use a frame * slot (entry in the array of local vars) if we are compiling a procedure * body and if the name is simple text that does not include namespace * qualifiers. */ varTokenPtr = TokenAfter(parsePtr->tokenPtr); | | | | | | | | | | | | | | | | | | | 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 | * to emit code to compute and push the name at runtime. We use a frame * slot (entry in the array of local vars) if we are compiling a procedure * body and if the name is simple text that does not include namespace * qualifiers. */ varTokenPtr = TokenAfter(parsePtr->tokenPtr); PUSH_VAR( varTokenPtr, 1, &localIndex, &simpleVarName, &isScalar); /* * Push the "index" args and the new element value. */ for (i=2 ; i<parsePtr->numWords ; ++i) { varTokenPtr = TokenAfter(varTokenPtr); PUSH_SUBST_WORD(varTokenPtr, i); } /* * Duplicate the variable name if it's been pushed. */ if (!simpleVarName || localIndex < 0) { if (!simpleVarName || isScalar) { tempDepth = parsePtr->numWords - 2; } else { tempDepth = parsePtr->numWords - 1; } OP4( OVER, tempDepth); } /* * Duplicate an array index if one's been pushed. */ if (simpleVarName && !isScalar) { if (localIndex < 0) { tempDepth = parsePtr->numWords - 1; } else { tempDepth = parsePtr->numWords - 2; } OP4( OVER, tempDepth); } /* * Emit code to load the variable's value. */ if (!simpleVarName) { OP( LOAD_STK); } else if (isScalar) { if (localIndex < 0) { OP( LOAD_SCALAR_STK); } else { OP4(LOAD_SCALAR, localIndex); } } else { if (localIndex < 0) { OP( LOAD_ARRAY_STK); } else { OP4(LOAD_ARRAY, localIndex); } } /* * Emit the correct variety of 'lset' instruction. */ if (parsePtr->numWords == 4) { OP( LSET_LIST); } else { OP4( LSET_FLAT, parsePtr->numWords-1); } /* * Emit code to put the value back in the variable. */ if (!simpleVarName) { OP( STORE_STK); } else if (isScalar) { if (localIndex < 0) { OP( STORE_SCALAR_STK); } else { OP4(STORE_SCALAR, localIndex); } } else { if (localIndex < 0) { OP( STORE_ARRAY_STK); } else { OP4(STORE_ARRAY, localIndex); } } return TCL_OK; } /* |
︙ | ︙ | |||
4837 4838 4839 4840 4841 4842 4843 | return TCL_ERROR; } /* * Not much to do; we compile to a single instruction... */ | | | 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 | return TCL_ERROR; } /* * Not much to do; we compile to a single instruction... */ OP( NS_CURRENT); return TCL_OK; } int TclCompileNamespaceCodeCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command |
︙ | ︙ | |||
4883 4884 4885 4886 4887 4888 4889 | /* * Now we can compile using the same strategy as [namespace code]'s normal * implementation does internally. Note that we can't bind the namespace * name directly here, because TclOO plays complex games with namespaces; * the value needs to be determined at runtime for safety. */ | | | | | | | | | | | | | | | | | | | < | | | 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 | /* * Now we can compile using the same strategy as [namespace code]'s normal * implementation does internally. Note that we can't bind the namespace * name directly here, because TclOO plays complex games with namespaces; * the value needs to be determined at runtime for safety. */ PUSH( "::namespace"); PUSH( "inscope"); OP( NS_CURRENT); PUSH_SUBST_WORD(tokenPtr, 1); OP4( LIST, 4); return TCL_OK; } int TclCompileNamespaceQualifiersCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr); DefineLineInformation; /* TIP #280 */ int off; if (parsePtr->numWords != 2) { return TCL_ERROR; } PUSH_SUBST_WORD(tokenPtr, 1); PUSH( "0"); PUSH( "::"); OP4( OVER, 2); OP( STR_FIND_LAST); LABEL(off); PUSH( "1"); OP( SUB); OP4( OVER, 2); OP( UNDER); OP( STR_INDEX); PUSH( ":"); OP( STR_EQ); BACKJUMP(off, JUMP_TRUE); OP( STR_RANGE); return TCL_OK; } int TclCompileNamespaceTailCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command |
︙ | ︙ | |||
4948 4949 4950 4951 4952 4953 4954 | return TCL_ERROR; } /* * Take care; only add 2 to found index if the string was actually found. */ | | | | | | | | | | | | | 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 | return TCL_ERROR; } /* * Take care; only add 2 to found index if the string was actually found. */ PUSH_SUBST_WORD(tokenPtr, 1); PUSH( "::"); OP( UNDER); OP( STR_FIND_LAST); OP( DUP); PUSH( "0"); OP( GE); TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpFixup); PUSH( "2"); OP( ADD); TclFixupForwardJumpToHere(envPtr, &jumpFixup, 127); PUSH( "end"); OP( STR_RANGE); return TCL_OK; } int TclCompileNamespaceUpvarCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command |
︙ | ︙ | |||
4995 4996 4997 4998 4999 5000 5001 | } /* * Push the namespace */ tokenPtr = TokenAfter(parsePtr->tokenPtr); | | | | | | | | | 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 | } /* * Push the namespace */ tokenPtr = TokenAfter(parsePtr->tokenPtr); PUSH_SUBST_WORD(tokenPtr, 1); /* * Loop over the (otherVar, thisVar) pairs. If any of the thisVar is not a * local variable, return an error so that the non-compiled command will * be called at runtime. */ localTokenPtr = tokenPtr; for (i=3; i<=numWords; i+=2) { otherTokenPtr = TokenAfter(localTokenPtr); localTokenPtr = TokenAfter(otherTokenPtr); PUSH_SUBST_WORD(otherTokenPtr, i-1); PUSH_VAR(localTokenPtr, i, &localIndex, &simpleVarName, &isScalar); if ((localIndex < 0) || !isScalar) { return TCL_ERROR; } OP4( NSUPVAR, localIndex); } /* * Pop the namespace, and set the result to empty */ OP( POP); PUSH( ""); return TCL_OK; } int TclCompileNamespaceWhichCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command |
︙ | ︙ | |||
5068 5069 5070 5071 5072 5073 5074 | idx++; } /* * Issue the bytecode. */ | | | | 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 | idx++; } /* * Issue the bytecode. */ PUSH_SUBST_WORD(tokenPtr, idx); OP( RESOLVE_COMMAND); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileRegexpCmd -- |
︙ | ︙ | |||
5189 5190 5191 5192 5193 5194 5195 | } if (len == 0) { /* * The semantics of regexp are always match on re == "". */ | | | | | | | | | 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 | } if (len == 0) { /* * The semantics of regexp are always match on re == "". */ PUSH( "1"); return TCL_OK; } /* * Attempt to convert pattern to glob. If successful, push the * converted pattern as a literal. */ if (TclReToGlob(NULL, varTokenPtr[1].start, len, &ds, &exact) == TCL_OK) { simple = 1; PUSH_DSTRING(&ds); Tcl_DStringFree(&ds); } } if (!simple) { PUSH_SUBST_WORD(varTokenPtr, parsePtr->numWords-2); } /* * Push the string arg. */ varTokenPtr = TokenAfter(varTokenPtr); PUSH_SUBST_WORD(varTokenPtr, parsePtr->numWords-1); if (simple) { if (exact && !nocase) { OP( STR_EQ); } else { OP1(STR_MATCH, nocase); } } else { /* * Pass correct RE compile flags. We use only Int1 (8-bit), but * that handles all the flags we want to pass. * Don't use TCL_REG_NOSUB as we may have backrefs. */ int cflags = TCL_REG_ADVANCED | (nocase ? TCL_REG_NOCASE : 0); OP1( REGEXP, cflags); } return TCL_OK; } /* *---------------------------------------------------------------------- |
︙ | ︙ | |||
5396 5397 5398 5399 5400 5401 5402 | /* * Proved the simplicity constraints! Time to issue the code. */ result = TCL_OK; bytes = Tcl_DStringValue(&pattern) + 1; PushLiteral(envPtr, bytes, len); | | < | | | 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 | /* * Proved the simplicity constraints! Time to issue the code. */ result = TCL_OK; bytes = Tcl_DStringValue(&pattern) + 1; PushLiteral(envPtr, bytes, len); PUSH_OBJ(replacementObj); PUSH_SUBST_WORD(stringTokenPtr, parsePtr->numWords-2); OP( STR_MAP); done: Tcl_DStringFree(&pattern); if (patternObj) { Tcl_DecrRefCount(patternObj); } if (replacementObj) { |
︙ | ︙ | |||
5467 5468 5469 5470 5471 5472 5473 | if ((numWords == 4) && (wordTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) && (wordTokenPtr[1].size == 8) && (strncmp(wordTokenPtr[1].start, "-options", 8) == 0)) { Tcl_Token *optsTokenPtr = TokenAfter(wordTokenPtr); Tcl_Token *msgTokenPtr = TokenAfter(optsTokenPtr); | | | | | 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 | if ((numWords == 4) && (wordTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) && (wordTokenPtr[1].size == 8) && (strncmp(wordTokenPtr[1].start, "-options", 8) == 0)) { Tcl_Token *optsTokenPtr = TokenAfter(wordTokenPtr); Tcl_Token *msgTokenPtr = TokenAfter(optsTokenPtr); PUSH_SUBST_WORD(optsTokenPtr, 2); PUSH_SUBST_WORD(msgTokenPtr, 3); OP( RETURN_STK); envPtr->currStackDepth = savedStackDepth + 1; return TCL_OK; } /* * Allocate some working space. */ |
︙ | ︙ | |||
5520 5521 5522 5523 5524 5525 5526 | /* * All options are known at compile time, so we're going to bytecompile. * Emit instructions to push the result on the stack. */ if (explicitResult) { | | | | 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 | /* * All options are known at compile time, so we're going to bytecompile. * Emit instructions to push the result on the stack. */ if (explicitResult) { PUSH_SUBST_WORD(wordTokenPtr, numWords-1); } else { /* * No explict result argument, so default result is empty string. */ PUSH( ""); } /* * Check for optimization: When [return] is in a proc, and there's no * enclosing [catch], and there are no return options, then the INST_DONE * instruction is equivalent, and may be more efficient. */ |
︙ | ︙ | |||
5560 5561 5562 5563 5564 5565 5566 | if (!enclosingCatch) { /* * ... and there is no enclosing catch. Issue the maximally * efficient exit instruction. */ Tcl_DecrRefCount(returnOpts); | | | 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 | if (!enclosingCatch) { /* * ... and there is no enclosing catch. Issue the maximally * efficient exit instruction. */ Tcl_DecrRefCount(returnOpts); OP( DONE); return TCL_OK; } } /* Optimize [return -level 0 $x]. */ Tcl_DictObjSize(NULL, returnOpts, &size); if (size == 0 && level == 0 && code == TCL_OK) { |
︙ | ︙ | |||
5674 5675 5676 5677 5678 5679 5680 | newTypePtr = objPtr->typePtr; Tcl_DecrRefCount(objPtr); if (newTypePtr != typePtr) { if (numWords%2) { return TCL_ERROR; } | | | | | | | | | | 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 | newTypePtr = objPtr->typePtr; Tcl_DecrRefCount(objPtr); if (newTypePtr != typePtr) { if (numWords%2) { return TCL_ERROR; } PUSH_SUBST_WORD(tokenPtr, 1); otherTokenPtr = TokenAfter(tokenPtr); i = 4; } else { if (!(numWords%2)) { return TCL_ERROR; } PUSH( "1"); otherTokenPtr = tokenPtr; i = 3; } } else { Tcl_DecrRefCount(objPtr); return TCL_ERROR; } /* * Loop over the (otherVar, thisVar) pairs. If any of the thisVar is not a * local variable, return an error so that the non-compiled command will * be called at runtime. */ for (; i<=numWords; i+=2, otherTokenPtr = TokenAfter(localTokenPtr)) { localTokenPtr = TokenAfter(otherTokenPtr); PUSH_SUBST_WORD(otherTokenPtr, 1); PUSH_VAR(localTokenPtr, 1, &localIndex, &simpleVarName, &isScalar); if ((localIndex < 0) || !isScalar) { return TCL_ERROR; } OP4( UPVAR, localIndex); } /* * Pop the frame index, and set the result to empty */ OP( POP); PUSH( ""); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileVariableCmd -- |
︙ | ︙ | |||
5767 5768 5769 5770 5771 5772 5773 | } /* * Loop over the (var, value) pairs. */ valueTokenPtr = parsePtr->tokenPtr; | | | | | | | | | | 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 | } /* * Loop over the (var, value) pairs. */ valueTokenPtr = parsePtr->tokenPtr; for (i=1; i<numWords; i+=2) { varTokenPtr = TokenAfter(valueTokenPtr); valueTokenPtr = TokenAfter(varTokenPtr); localIndex = IndexTailVarIfKnown(interp, varTokenPtr, envPtr); if (localIndex < 0) { return TCL_ERROR; } PUSH_SUBST_WORD(varTokenPtr, i-1); OP4( VARIABLE, localIndex); if (i+1 < numWords) { /* * A value has been given: set the variable, pop the value */ PUSH_SUBST_WORD(valueTokenPtr, i); OP4(STORE_SCALAR, localIndex); OP( POP); } } /* * Set the result to empty */ PUSH( ""); return TCL_OK; } /* *---------------------------------------------------------------------- * * IndexTailVarIfKnown -- |
︙ | ︙ | |||
5939 5940 5941 5942 5943 5944 5945 | compileSelfObject: /* * This delegates the entire problem to a single opcode. */ | | | < < < < | < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 | compileSelfObject: /* * This delegates the entire problem to a single opcode. */ OP( TCLOO_SELF); return TCL_OK; compileSelfNamespace: /* * This is formally only correct with TclOO methods as they are currently * implemented; it assumes that the current namespace is invariably when a * TclOO context is present is the object's namespace, and that's * technically only something that's a matter of current policy. But it * avoids creating another opcode, so that's all good! */ OP( TCLOO_SELF); OP( POP); OP( NS_CURRENT); return TCL_OK; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ |
Changes to generic/tclCompCmdsSZ.c.
︙ | ︙ | |||
23 24 25 26 27 28 29 | */ static ClientData DupJumptableInfo(ClientData clientData); static void FreeJumptableInfo(ClientData clientData); static void PrintJumptableInfo(ClientData clientData, Tcl_Obj *appendObj, ByteCode *codePtr, unsigned int pcOffset); | < < < < < | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | */ static ClientData DupJumptableInfo(ClientData clientData); static void FreeJumptableInfo(ClientData clientData); static void PrintJumptableInfo(ClientData clientData, Tcl_Obj *appendObj, ByteCode *codePtr, unsigned int pcOffset); static int CompileAssociativeBinaryOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, const char *identity, int instruction, CompileEnv *envPtr); static int CompileComparisonOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, int instruction, CompileEnv *envPtr); static int CompileStrictlyBinaryOpCmd(Tcl_Interp *interp, |
︙ | ︙ | |||
64 65 66 67 68 69 70 | Tcl_Token *finallyToken); static int IssueTryInstructions(Tcl_Interp *interp, CompileEnv *envPtr, Tcl_Token *bodyToken, int numHandlers, int *matchCodes, Tcl_Obj **matchClauses, int *resultVarIndices, int *optionVarIndices, Tcl_Token **handlerTokens); | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | Tcl_Token *finallyToken); static int IssueTryInstructions(Tcl_Interp *interp, CompileEnv *envPtr, Tcl_Token *bodyToken, int numHandlers, int *matchCodes, Tcl_Obj **matchClauses, int *resultVarIndices, int *optionVarIndices, Tcl_Token **handlerTokens); /* * The structures below define the AuxData types defined in this file. */ const AuxDataType tclJumptableInfoType = { "JumptableInfo", /* name */ DupJumptableInfo, /* dupProc */ FreeJumptableInfo, /* freeProc */ PrintJumptableInfo /* printProc */ }; /* *---------------------------------------------------------------------- * * TclCompileSetCmd -- * * Procedure called to compile the "set" command. |
︙ | ︙ | |||
192 193 194 195 196 197 198 | * to emit code to compute and push the name at runtime. We use a frame * slot (entry in the array of local vars) if we are compiling a procedure * body and if the name is simple text that does not include namespace * qualifiers. */ varTokenPtr = TokenAfter(parsePtr->tokenPtr); | | | | | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | * to emit code to compute and push the name at runtime. We use a frame * slot (entry in the array of local vars) if we are compiling a procedure * body and if the name is simple text that does not include namespace * qualifiers. */ varTokenPtr = TokenAfter(parsePtr->tokenPtr); PUSH_VAR( varTokenPtr, 1, &localIndex, &simpleVarName, &isScalar); /* * If we are doing an assignment, push the new value. */ if (isAssignment) { valueTokenPtr = TokenAfter(varTokenPtr); PUSH_SUBST_WORD(valueTokenPtr, 2); } /* * Emit instructions to set/get the variable. */ if (simpleVarName) { |
︙ | ︙ | |||
280 281 282 283 284 285 286 | } /* * Push the two operands onto the stack and then the test. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); | | | | | 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | } /* * Push the two operands onto the stack and then the test. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); PUSH_SUBST_WORD(tokenPtr, 1); tokenPtr = TokenAfter(tokenPtr); PUSH_SUBST_WORD(tokenPtr, 2); OP( STR_CMP); return TCL_OK; } int TclCompileStringEqualCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command |
︙ | ︙ | |||
312 313 314 315 316 317 318 | } /* * Push the two operands onto the stack and then the test. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); | | | | | 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | } /* * Push the two operands onto the stack and then the test. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); PUSH_SUBST_WORD(tokenPtr, 1); tokenPtr = TokenAfter(tokenPtr); PUSH_SUBST_WORD(tokenPtr, 2); OP( STR_EQ); return TCL_OK; } int TclCompileStringFirstCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command |
︙ | ︙ | |||
344 345 346 347 348 349 350 | } /* * Push the two operands onto the stack and then the test. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); | | | | | 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | } /* * Push the two operands onto the stack and then the test. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); PUSH_SUBST_WORD(tokenPtr, 1); tokenPtr = TokenAfter(tokenPtr); PUSH_SUBST_WORD(tokenPtr, 2); OP( STR_FIND); return TCL_OK; } int TclCompileStringLastCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command |
︙ | ︙ | |||
376 377 378 379 380 381 382 | } /* * Push the two operands onto the stack and then the test. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); | | | | | 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 | } /* * Push the two operands onto the stack and then the test. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); PUSH_SUBST_WORD(tokenPtr, 1); tokenPtr = TokenAfter(tokenPtr); PUSH_SUBST_WORD(tokenPtr, 2); OP( STR_FIND_LAST); return TCL_OK; } int TclCompileStringIndexCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command |
︙ | ︙ | |||
404 405 406 407 408 409 410 | } /* * Push the two operands onto the stack and then the index operation. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); | | | | | 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 | } /* * Push the two operands onto the stack and then the index operation. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); PUSH_SUBST_WORD(tokenPtr, 1); tokenPtr = TokenAfter(tokenPtr); PUSH_SUBST_WORD(tokenPtr, 2); OP( STR_INDEX); return TCL_OK; } int TclCompileStringMatchCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command |
︙ | ︙ | |||
436 437 438 439 440 441 442 | /* * Check if we have a -nocase flag. */ if (parsePtr->numWords == 4) { if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { | | | | 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 | /* * Check if we have a -nocase flag. */ if (parsePtr->numWords == 4) { if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } str = tokenPtr[1].start; length = tokenPtr[1].size; if ((length <= 1) || strncmp(str, "-nocase", (size_t) length)) { /* * Fail at run time, not in compilation. */ return TclCompileBasic3ArgCmd(interp, parsePtr, cmdPtr, envPtr); } nocase = 1; tokenPtr = TokenAfter(tokenPtr); } /* * Push the strings to match against each other. |
︙ | ︙ | |||
474 475 476 477 478 479 480 | Tcl_IncrRefCount(copy); exactMatch = TclMatchIsTrivial(TclGetString(copy)); TclDecrRefCount(copy); } PushLiteral(envPtr, str, length); } else { | | < | | | 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 | Tcl_IncrRefCount(copy); exactMatch = TclMatchIsTrivial(TclGetString(copy)); TclDecrRefCount(copy); } PushLiteral(envPtr, str, length); } else { PUSH_SUBST_WORD(tokenPtr, i+1+nocase); } tokenPtr = TokenAfter(tokenPtr); } /* * Push the matcher. */ if (exactMatch) { OP( STR_EQ); } else { OP1( STR_MATCH, nocase); } return TCL_OK; } int TclCompileStringLenCmd( Tcl_Interp *interp, /* Used for error reporting. */ |
︙ | ︙ | |||
518 519 520 521 522 523 524 | if (TclWordKnownAtCompileTime(tokenPtr, objPtr)) { /* * Here someone is asking for the length of a static string (or * something with backslashes). Just push the actual character (not * byte) length. */ | < | | < > < | | < | 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 | if (TclWordKnownAtCompileTime(tokenPtr, objPtr)) { /* * Here someone is asking for the length of a static string (or * something with backslashes). Just push the actual character (not * byte) length. */ Tcl_Obj *lenObj = Tcl_NewIntObj(Tcl_GetCharLength(objPtr)); PUSH_OBJ(lenObj); TclDecrRefCount(lenObj); } else { PUSH_SUBST_WORD(tokenPtr, 1); OP(STR_LEN); } TclDecrRefCount(objPtr); return TCL_OK; } int TclCompileStringMapCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *mapTokenPtr, *stringTokenPtr; Tcl_Obj *mapObj, **objv; int len; /* * We only handle the case: * * string map {foo bar} $thing * |
︙ | ︙ | |||
566 567 568 569 570 571 572 | } mapTokenPtr = TokenAfter(parsePtr->tokenPtr); stringTokenPtr = TokenAfter(mapTokenPtr); mapObj = Tcl_NewObj(); Tcl_IncrRefCount(mapObj); if (!TclWordKnownAtCompileTime(mapTokenPtr, mapObj)) { Tcl_DecrRefCount(mapObj); | | | | | | | | < | | | 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 | } mapTokenPtr = TokenAfter(parsePtr->tokenPtr); stringTokenPtr = TokenAfter(mapTokenPtr); mapObj = Tcl_NewObj(); Tcl_IncrRefCount(mapObj); if (!TclWordKnownAtCompileTime(mapTokenPtr, mapObj)) { Tcl_DecrRefCount(mapObj); return TclCompileBasic2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } else if (Tcl_ListObjGetElements(NULL, mapObj, &len, &objv) != TCL_OK) { Tcl_DecrRefCount(mapObj); return TclCompileBasic2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } else if (len != 2) { Tcl_DecrRefCount(mapObj); return TclCompileBasic2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } /* * Now issue the opcodes. Note that in the case that we know that the * first word is an empty word, we don't issue the map at all. That is the * correct semantics for mapping. */ (void) Tcl_GetStringFromObj(objv[0], &len); if (len == 0) { PUSH_SUBST_WORD(stringTokenPtr, 2); } else { PUSH_OBJ(objv[0]); PUSH_OBJ(objv[1]); PUSH_SUBST_WORD(stringTokenPtr, 2); OP( STR_MAP); } Tcl_DecrRefCount(mapObj); return TCL_OK; } int TclCompileStringRangeCmd( |
︙ | ︙ | |||
668 669 670 671 672 673 674 | goto nonConstantIndices; } /* * Push the operand onto the stack and then the substring operation. */ | | | | | | 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 | goto nonConstantIndices; } /* * Push the operand onto the stack and then the substring operation. */ PUSH_SUBST_WORD( stringTokenPtr, 1); OP44( STR_RANGE_IMM, idx1, idx2); return TCL_OK; /* * Push the operands onto the stack and then the substring operation. */ nonConstantIndices: PUSH_SUBST_WORD( stringTokenPtr, 1); PUSH_SUBST_WORD( fromTokenPtr, 2); PUSH_SUBST_WORD( toTokenPtr, 3); OP( STR_RANGE); return TCL_OK; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
781 782 783 784 785 786 787 | const char *bytes, int numBytes, int flags, int line, CompileEnv *envPtr) { Tcl_Token *endTokenPtr, *tokenPtr; | | | | < | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > | | < | < < < | | | | | | | | | | | | | < | < | < | < > < < | < | | | < < | < < < | | | | < < < < < < < > | | | < < < | | < < < | | | < < < | 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 | const char *bytes, int numBytes, int flags, int line, CompileEnv *envPtr) { Tcl_Token *endTokenPtr, *tokenPtr; int breakOffset = -1, count = 0, bline = line; Tcl_Parse parse; Tcl_InterpState state = NULL; TclSubstParse(interp, bytes, numBytes, flags, &parse, &state); /* * Tricky point! If the first token does not result in a *guaranteed* push * of a Tcl_Obj on the stack, we must push an empty object. Otherwise it * is possible to get to an INST_CONCAT or INST_DONE without enough * values on the stack, resulting in a crash. Thanks to Joe Mistachkin for * identifying a script that could trigger this case. */ tokenPtr = parse.tokenPtr; if (tokenPtr->type != TCL_TOKEN_TEXT && tokenPtr->type != TCL_TOKEN_BS) { PUSH(""); count++; } for (endTokenPtr = tokenPtr + parse.numTokens; tokenPtr < endTokenPtr; tokenPtr = TokenAfter(tokenPtr)) { int length, literal, catchRange; char buf[TCL_UTF_MAX]; int gotOK, gotReturn, gotBreak, gotContinue, gotOther, toEnd; switch (tokenPtr->type) { case TCL_TOKEN_TEXT: literal = TclRegisterNewLiteral(envPtr, tokenPtr->start, tokenPtr->size); TclEmitPush(literal, envPtr); TclAdvanceLines(&bline, tokenPtr->start, tokenPtr->start + tokenPtr->size); count++; continue; case TCL_TOKEN_BS: length = TclParseBackslash(tokenPtr->start, tokenPtr->size, NULL, buf); literal = TclRegisterNewLiteral(envPtr, buf, length); TclEmitPush(literal, envPtr); count++; continue; case TCL_TOKEN_VARIABLE: /* * Check for simple variable access; see if we can only generate * TCL_OK or TCL_ERROR from the substituted variable read; if so, * there is no need to generate elaborate exception-management * code. Note that the first component of TCL_TOKEN_VARIABLE is * always TCL_TOKEN_TEXT... */ if (tokenPtr->numComponents > 1) { int i, foundCommand = 0; for (i=2 ; i<=tokenPtr->numComponents ; i++) { if (tokenPtr[i].type == TCL_TOKEN_COMMAND) { foundCommand = 1; break; } } if (foundCommand) { break; } } envPtr->line = bline; TclCompileVarSubst(interp, tokenPtr, envPtr); bline = envPtr->line; count++; continue; } while (count > 255) { OP1( CONCAT, 255); count -= 254; } if (count > 1) { OP1( CONCAT, count); count = 1; } if (breakOffset == -1) { int start; /* Jump to the start (jump over the jump to end) */ JUMP(start, JUMP); /* Jump to the end (all BREAKs land here) */ JUMP(breakOffset, JUMP); /* Start */ FIXJUMP(start); } envPtr->line = bline; catchRange = DeclareExceptionRange(envPtr, CATCH_EXCEPTION_RANGE); OP4( BEGIN_CATCH, catchRange); ExceptionRangeStarts(envPtr, catchRange); switch (tokenPtr->type) { case TCL_TOKEN_COMMAND: TclCompileScript(interp, tokenPtr->start+1, tokenPtr->size-2, envPtr); count++; break; case TCL_TOKEN_VARIABLE: TclCompileVarSubst(interp, tokenPtr, envPtr); count++; break; default: Tcl_Panic("unexpected token type in TclCompileSubstCmd: %d", tokenPtr->type); } ExceptionRangeEnds(envPtr, catchRange); /* Substitution produced TCL_OK */ OP( END_CATCH); JUMP(gotOK, JUMP); /* Exceptional return codes processed here */ ExceptionRangeTarget(envPtr, catchRange, catchOffset); OP( PUSH_RETURN_OPTIONS); OP( PUSH_RESULT); OP( PUSH_RETURN_CODE); OP( END_CATCH); OP( RETURN_CODE_BRANCH); /* ERROR -> reraise it */ OP( RETURN_STK); OP( NOP); OP( NOP); OP( NOP); OP( NOP); /* RETURN */ JUMP(gotReturn, JUMP); /* BREAK */ JUMP(gotBreak, JUMP); /* CONTINUE */ JUMP(gotContinue, JUMP); /* OTHER */ JUMP(gotOther, JUMP); /* BREAK destination */ FIXJUMP(gotBreak); OP( POP); OP( POP); BACKJUMP(breakOffset, JUMP); /* CONTINUE destination */ FIXJUMP(gotContinue); OP( POP); OP( POP); JUMP(toEnd, JUMP); /* RETURN + other destination */ FIXJUMP(gotReturn); FIXJUMP(gotOther); /* * Pull the result to top of stack, discard options dict. */ OP( EXCH); OP( POP); /* * We've emitted several POP instructions, and the automatic * computations for stack depth requirements have been decrementing * for every one. However, we know that every branch actually taken * only encounters some of those instructions. No branch passes * through them all. So, we now have a stack requirements estimate * that is too low. Here we manually fix that up. */ TclAdjustStackDepth(5, envPtr); /* OK destination */ FIXJUMP(gotOK); if (count > 1) { OP1( CONCAT, count); count = 1; } /* CONTINUE jump to here */ FIXJUMP(toEnd); bline = envPtr->line; } while (count > 255) { OP1( CONCAT, 255); count -= 254; } if (count > 1) { OP1( CONCAT, count); } Tcl_FreeParse(&parse); if (state != NULL) { Tcl_RestoreInterpState(interp, state); TclCompileSyntaxError(interp, envPtr); TclAdjustStackDepth(-1, envPtr); } /* Final target of the multi-jump from all BREAKs */ FIXJUMP(breakOffset); } /* *---------------------------------------------------------------------- * * TclCompileSwitchCmd -- * |
︙ | ︙ | |||
1381 1382 1383 1384 1385 1386 1387 | int simple, exact; /* For extracting the type of regexp. */ int i; /* * First, we push the value we're matching against on the stack. */ | < | | 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 | int simple, exact; /* For extracting the type of regexp. */ int i; /* * First, we push the value we're matching against on the stack. */ PUSH_SUBST_WORD(valueTokenPtr, valueIndex); /* * Generate a test for each arm. */ contFixIndex = -1; contFixCount = 0; |
︙ | ︙ | |||
1412 1413 1414 1415 1416 1417 1418 | case Switch_Exact: OP( DUP); TclCompileTokens(interp, bodyToken[i], 1, envPtr); OP( STR_EQ); break; case Switch_Glob: TclCompileTokens(interp, bodyToken[i], 1, envPtr); | | | < | < > > | 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 | case Switch_Exact: OP( DUP); TclCompileTokens(interp, bodyToken[i], 1, envPtr); OP( STR_EQ); break; case Switch_Glob: TclCompileTokens(interp, bodyToken[i], 1, envPtr); OP( UNDER); OP1( STR_MATCH, noCase); break; case Switch_Regexp: simple = exact = 0; /* * Keep in sync with TclCompileRegexpCmd. */ if (bodyToken[i]->type == TCL_TOKEN_TEXT) { Tcl_DString ds; if (bodyToken[i]->size == 0) { /* * The semantics of regexps are that they always match * when the RE == "". */ PUSH("1"); break; } /* * Attempt to convert pattern to glob. If successful, push * the converted pattern. */ if (TclReToGlob(NULL, bodyToken[i]->start, bodyToken[i]->size, &ds, &exact) == TCL_OK) { simple = 1; PUSH_DSTRING(&ds); Tcl_DStringFree(&ds); } } if (!simple) { TclCompileTokens(interp, bodyToken[i], 1, envPtr); } if (!simple) { /* * Pass correct RE compile flags. We use only Int1 * (8-bit), but that handles all the flags we want to * pass. Don't use TCL_REG_NOSUB as we may have backrefs * or capture vars. */ int cflags = TCL_REG_ADVANCED | (noCase ? TCL_REG_NOCASE : 0); OP( UNDER); OP1(REGEXP, cflags); } else if (exact && !noCase) { OP( STR_EQ); } else { OP( UNDER); OP1(STR_MATCH, noCase); } break; default: Tcl_Panic("unknown switch mode: %d", mode); } |
︙ | ︙ | |||
1522 1523 1524 1525 1526 1527 1528 | * so we must process those first. */ if (contFixIndex != -1) { int j; for (j=0 ; j<contFixCount ; j++) { | | | | | | 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 | * so we must process those first. */ if (contFixIndex != -1) { int j; for (j=0 ; j<contFixCount ; j++) { LABEL(fixupTargetArray[contFixIndex+j]); } contFixIndex = -1; } /* * Now do the actual compilation. Note that we do not use CompileBody * because we may have synthesized the tokens in a non-standard * pattern. */ OP( POP); envPtr->currStackDepth = savedStackDepth + 1; envPtr->line = bodyLines[i+1]; /* TIP #280 */ envPtr->clNext = bodyContLines[i+1]; /* TIP #280 */ TclCompileCmdWord(interp, bodyToken[i+1], 1, envPtr); if (!foundDefault) { TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &fixupArray[fixupCount]); fixupCount++; LABEL(fixupTargetArray[nextArmFixupIndex]); } } /* * Discard the value we are matching against unless we've had a default * clause (in which case it will already be gone due to the code at the * start of processing an arm, guaranteed) and make the result of the * command an empty string. */ if (!foundDefault) { OP( POP); PUSH( ""); } /* * Do jump fixups for arms that were executed. First, fill in the jumps of * all jumps that don't point elsewhere to point to here. */ for (i=0 ; i<fixupCount ; i++) { if (fixupTargetArray[i] == 0) { LABEL(fixupTargetArray[i]); } } /* * Now scan backwards over all the jumps (all of which are forward jumps) * doing each one. When we do one and there is a size changes, we must * scan back over all the previous ones and see if they need adjusting |
︙ | ︙ | |||
1637 1638 1639 1640 1641 1642 1643 | Tcl_DString buffer; Tcl_HashEntry *hPtr; /* * First, we push the value we're matching against on the stack. */ | < | | 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 | Tcl_DString buffer; Tcl_HashEntry *hPtr; /* * First, we push the value we're matching against on the stack. */ PUSH_SUBST_WORD(valueTokenPtr, valueIndex); /* * Compile the switch by using a jump table, which is basically a * hashtable that maps from literal values to match against to the offset * (relative to the INST_JUMP_TABLE instruction) to jump to. The jump * table itself is independent of any invokation of the bytecode, and as * such is stored in an auxData block. |
︙ | ︙ | |||
1666 1667 1668 1669 1670 1671 1672 | * to do if things do not work out (jump to either the default clause or * the "default" default, which just sets the result to empty). Note that * we will come back and rewrite the jump's offset parameter when we know * what it should be, and that all jumps we issue are of the wide kind * because that makes the code much easier to debug! */ | | | < | 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 | * to do if things do not work out (jump to either the default clause or * the "default" default, which just sets the result to empty). Note that * we will come back and rewrite the jump's offset parameter when we know * what it should be, and that all jumps we issue are of the wide kind * because that makes the code much easier to debug! */ LABEL(jumpLocation); OP4( JUMP_TABLE, infoIndex); JUMP(jumpToDefault, JUMP); for (i=0 ; i<numBodyTokens ; i+=2) { /* * For each arm, we must first work out what to do with the match * term. */ |
︙ | ︙ | |||
1708 1709 1710 1711 1712 1713 1714 | /* * This is a default clause, so patch up the fallthrough from the * INST_JUMP_TABLE instruction to here. */ foundDefault = 1; isNew = 1; | < | | 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 | /* * This is a default clause, so patch up the fallthrough from the * INST_JUMP_TABLE instruction to here. */ foundDefault = 1; isNew = 1; FIXJUMP(jumpToDefault); } /* * Now, for each arm we must deal with the body of the clause. * * If this is a continuation body (never true of a final clause, * whether default or not) we're done because the next jump target |
︙ | ︙ | |||
1753 1754 1755 1756 1757 1758 1759 | * Compile a jump in to the end of the command if this body is * anything other than a user-supplied default arm (to either skip * over the remaining bodies or the code that generates an empty * result). */ if (i+2 < numBodyTokens || !foundDefault) { | | < < < < < < < < < | | < | | 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 | * Compile a jump in to the end of the command if this body is * anything other than a user-supplied default arm (to either skip * over the remaining bodies or the code that generates an empty * result). */ if (i+2 < numBodyTokens || !foundDefault) { JUMP(finalFixups[numRealBodies++], JUMP); } } /* * We're at the end. If we've not already done so through the processing * of a user-supplied default clause, add in a "default" default clause * now. */ if (!foundDefault) { envPtr->currStackDepth = savedStackDepth; FIXJUMP(jumpToDefault); PUSH(""); } /* * No more instructions to be issued; everything that needs to jump to the * end of the command is fixed up at this point. */ for (i=0 ; i<numRealBodies ; i++) { FIXJUMP(finalFixups[i]); } /* * Clean up all our temporary space and return. */ TclStackFree(interp, finalFixups); |
︙ | ︙ | |||
1907 1908 1909 1910 1911 1912 1913 | * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = parsePtr->tokenPtr; int i; | | > > | | | 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 | * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { DefineLineInformation; /* TIP #280 */ Tcl_Token *tokenPtr = parsePtr->tokenPtr; int i; if (parsePtr->numWords < 2 || parsePtr->numWords > 255 || envPtr->procPtr == NULL) { return TCL_ERROR; } /* make room for the nsObjPtr */ CompileWord(envPtr, tokenPtr, interp, 0); for (i=1 ; i<parsePtr->numWords ; i++) { tokenPtr = TokenAfter(tokenPtr); PUSH_SUBST_WORD(tokenPtr, i); } OP1( TAILCALL, parsePtr->numWords); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileThrowCmd -- |
︙ | ︙ | |||
1963 1964 1965 1966 1967 1968 1969 | codeToken = TokenAfter(parsePtr->tokenPtr); msgToken = TokenAfter(codeToken); TclNewObj(objPtr); Tcl_IncrRefCount(objPtr); if (TclWordKnownAtCompileTime(codeToken, objPtr)) { Tcl_Obj *errPtr, *dictPtr; | < | | > | < < < > > | | | > | 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 | codeToken = TokenAfter(parsePtr->tokenPtr); msgToken = TokenAfter(codeToken); TclNewObj(objPtr); Tcl_IncrRefCount(objPtr); if (TclWordKnownAtCompileTime(codeToken, objPtr)) { Tcl_Obj *errPtr, *dictPtr; int len; /* * The code is known at compilation time. This allows us to issue a * very efficient sequence of instructions. */ if (Tcl_ListObjLength(interp, objPtr, &len) != TCL_OK) { /* * Must still do this; might generate an error when getting this * "ignored" value prepared as an argument. */ PUSH_SUBST_WORD(msgToken, 2); TclCompileSyntaxError(interp, envPtr); Tcl_DecrRefCount(objPtr); envPtr->currStackDepth = savedStackDepth + 1; return TCL_OK; } if (len == 0) { /* * Must still do this; might generate an error when getting this * "ignored" value prepared as an argument. */ PUSH_SUBST_WORD(msgToken, 2); goto issueErrorForEmptyCode; } TclNewLiteralStringObj(errPtr, "-errorcode"); TclNewObj(dictPtr); Tcl_DictObjPut(NULL, dictPtr, errPtr, objPtr); PUSH_SUBST_WORD(msgToken, 2); PUSH_OBJ(dictPtr); TclDecrRefCount(dictPtr); OP44( RETURN_IMM, 1, 0); envPtr->currStackDepth = savedStackDepth + 1; } else { int badThrowCode; /* * When the code token is not known at compilation time, we need to do * a little bit more work. The main tricky bit here is that the error * code has to be a list (a [throw] restriction) so we must emit extra * instructions to enforce that condition. */ PUSH_SUBST_WORD(codeToken, 1); PUSH( "-errorcode"); PUSH_SUBST_WORD(msgToken, 2); OP4( REVERSE, 3); OP( DUP); OP( LIST_LENGTH); JUMP(badThrowCode, JUMP_FALSE); OP4( LIST, 2); OP44( RETURN_IMM, 1, 0); FIXJUMP(badThrowCode); /* * Generate an error for being an empty list. Can't leverage anything * else to do this for us. */ issueErrorForEmptyCode: |
︙ | ︙ | |||
2299 2300 2301 2302 2303 2304 2305 | int *resultVars, int *optionVars, Tcl_Token **handlerTokens) { DefineLineInformation; /* TIP #280 */ int range, resultVar, optionsVar; int savedStackDepth = envPtr->currStackDepth; | | | | | | > | 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 | int *resultVars, int *optionVars, Tcl_Token **handlerTokens) { DefineLineInformation; /* TIP #280 */ int range, resultVar, optionsVar; int savedStackDepth = envPtr->currStackDepth; int i, j, len, forwardsNeedFixing = 0, pushBodyOpts; int *addrsToFix, *forwardsToFix, notCodeJumpSource, notECJumpSource; char buf[TCL_INTEGER_SPACE]; resultVar = NewUnnamedLocal(envPtr); optionsVar = NewUnnamedLocal(envPtr); if (resultVar < 0 || optionsVar < 0) { return TCL_ERROR; } /* * Compile the body, trapping any error in it so that we can trap on it * and/or run a finally clause. Note that there must be at least one * on/trap clause; when none is present, this whole function is not called * (and it's never called when there's a finally clause). */ range = DeclareExceptionRange(envPtr, CATCH_EXCEPTION_RANGE); OP4( BEGIN_CATCH, range); ExceptionRangeStarts(envPtr, range); BODY( bodyToken, 1); ExceptionRangeEnds(envPtr, range); PUSH( "0"); OP( EXCH); JUMP(pushBodyOpts, JUMP); ExceptionRangeTarget(envPtr, range, catchOffset); OP( PUSH_RETURN_CODE); OP( PUSH_RESULT); FIXJUMP(pushBodyOpts); OP( PUSH_RETURN_OPTIONS); OP( END_CATCH); OP4( STORE_SCALAR, optionsVar); OP( POP); OP4( STORE_SCALAR, resultVar); OP( POP); |
︙ | ︙ | |||
2455 2456 2457 2458 2459 2460 2461 2462 2463 | Tcl_Token **handlerTokens, Tcl_Token *finallyToken) /* Not NULL */ { DefineLineInformation; /* TIP #280 */ int savedStackDepth = envPtr->currStackDepth; int range, resultVar, optionsVar, i, j, len, forwardsNeedFixing = 0; int *addrsToFix, *forwardsToFix, notCodeJumpSource, notECJumpSource; char buf[TCL_INTEGER_SPACE]; | > | | | | > | 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 | Tcl_Token **handlerTokens, Tcl_Token *finallyToken) /* Not NULL */ { DefineLineInformation; /* TIP #280 */ int savedStackDepth = envPtr->currStackDepth; int range, resultVar, optionsVar, i, j, len, forwardsNeedFixing = 0; int *addrsToFix, *forwardsToFix, notCodeJumpSource, notECJumpSource; int pushBodyOpts, saveResultForLater; char buf[TCL_INTEGER_SPACE]; resultVar = NewUnnamedLocal(envPtr); optionsVar = NewUnnamedLocal(envPtr); if (resultVar < 0 || optionsVar < 0) { return TCL_ERROR; } /* * Compile the body, trapping any error in it so that we can trap on it * (if any trap matches) and run a finally clause. */ range = DeclareExceptionRange(envPtr, CATCH_EXCEPTION_RANGE); OP4( BEGIN_CATCH, range); ExceptionRangeStarts(envPtr, range); envPtr->currStackDepth = savedStackDepth; BODY( bodyToken, 1); ExceptionRangeEnds(envPtr, range); PUSH( "0"); OP( EXCH); JUMP(pushBodyOpts, JUMP); ExceptionRangeTarget(envPtr, range, catchOffset); OP( PUSH_RETURN_CODE); OP( PUSH_RESULT); FIXJUMP(pushBodyOpts); OP( PUSH_RETURN_OPTIONS); OP( END_CATCH); OP4( STORE_SCALAR, optionsVar); OP( POP); OP4( STORE_SCALAR, resultVar); OP( POP); envPtr->currStackDepth = savedStackDepth + 1; |
︙ | ︙ | |||
2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 | * next one. */ ExceptionRangeEnds(envPtr, range); OP( END_CATCH); forwardsNeedFixing = 1; JUMP(forwardsToFix[i], JUMP); goto finishTrapCatchHandling; } } else if (!handlerTokens[i]) { /* * No handler. Will not be the last handler (that condition is * checked by the caller). Chain to the next one. */ | > | 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 | * next one. */ ExceptionRangeEnds(envPtr, range); OP( END_CATCH); forwardsNeedFixing = 1; JUMP(forwardsToFix[i], JUMP); saveResultForLater = -1; goto finishTrapCatchHandling; } } else if (!handlerTokens[i]) { /* * No handler. Will not be the last handler (that condition is * checked by the caller). Chain to the next one. */ |
︙ | ︙ | |||
2581 2582 2583 2584 2585 2586 2587 | * where they are to jump to. */ if (forwardsNeedFixing) { forwardsNeedFixing = 0; OP4( JUMP, 10); for (j=0 ; j<i ; j++) { | < < < | | > | 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 | * where they are to jump to. */ if (forwardsNeedFixing) { forwardsNeedFixing = 0; OP4( JUMP, 10); for (j=0 ; j<i ; j++) { FIXJUMP(forwardsToFix[j]); forwardsToFix[j] = -1; } OP4( BEGIN_CATCH, range); } envPtr->currStackDepth = savedStackDepth; BODY( handlerTokens[i], 5+i*4); ExceptionRangeEnds(envPtr, range); OP( PUSH_RETURN_OPTIONS); OP( EXCH); JUMP(saveResultForLater, JUMP); forwardsToFix[i] = -1; /* * Error in handler or setting of variables; replace the stored * exception with the new one. Note that we only push this if we * have either a body or some variable setting here. Otherwise * this code is unreachable. */ finishTrapCatchHandling: ExceptionRangeTarget(envPtr, range, catchOffset); OP( PUSH_RETURN_OPTIONS); OP( PUSH_RESULT); FIXJUMP(saveResultForLater); OP( END_CATCH); OP4( STORE_SCALAR, resultVar); OP( POP); OP4( STORE_SCALAR, optionsVar); OP( POP); endOfThisArm: |
︙ | ︙ | |||
2697 2698 2699 2700 2701 2702 2703 | Tcl_Obj *leadingWord; DefineLineInformation; /* TIP #280 */ numWords = parsePtr->numWords-1; flags = 1; varTokenPtr = TokenAfter(parsePtr->tokenPtr); leadingWord = Tcl_NewObj(); | | | 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 | Tcl_Obj *leadingWord; DefineLineInformation; /* TIP #280 */ numWords = parsePtr->numWords-1; flags = 1; varTokenPtr = TokenAfter(parsePtr->tokenPtr); leadingWord = Tcl_NewObj(); if (numWords > 0 && TclWordKnownAtCompileTime(varTokenPtr, leadingWord)) { int len; const char *bytes = Tcl_GetStringFromObj(leadingWord, &len); if (len == 11 && !strncmp("-nocomplain", bytes, 11)) { flags = 0; varTokenPtr = TokenAfter(varTokenPtr); numWords--; |
︙ | ︙ | |||
2729 2730 2731 2732 2733 2734 2735 | * Decide if we can use a frame slot for the var/array name or if we * need to emit code to compute and push the name at runtime. We use a * frame slot (entry in the array of local vars) if we are compiling a * procedure body and if the name is simple text that does not include * namespace qualifiers. */ | | | | 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 | * Decide if we can use a frame slot for the var/array name or if we * need to emit code to compute and push the name at runtime. We use a * frame slot (entry in the array of local vars) if we are compiling a * procedure body and if the name is simple text that does not include * namespace qualifiers. */ PUSH_VAR( varTokenPtr, 1, &localIndex, &simpleVarName, &isScalar); /* * Emit instructions to unset the variable. */ if (!simpleVarName) { OP1( UNSET_STK, flags); |
︙ | ︙ | |||
2754 2755 2756 2757 2758 2759 2760 | } else { OP14( UNSET_ARRAY, flags, localIndex); } } varTokenPtr = TokenAfter(varTokenPtr); } | | | 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 | } else { OP14( UNSET_ARRAY, flags, localIndex); } } varTokenPtr = TokenAfter(varTokenPtr); } PUSH(""); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileWhileCmd -- |
︙ | ︙ | |||
2873 2874 2875 2876 2877 2878 2879 | } else { /* * Make sure that the first command in the body is preceded by an * INST_START_CMD, and hence counted properly. [Bug 1752146] */ envPtr->atCmdStart = 0; | | | < | | < | < | | 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 | } else { /* * Make sure that the first command in the body is preceded by an * INST_START_CMD, and hence counted properly. [Bug 1752146] */ envPtr->atCmdStart = 0; LABEL(testCodeOffset); } /* * Compile the loop body. */ SetLineInformation(2); bodyCodeOffset = ExceptionRangeStarts(envPtr, range); CompileBody(envPtr, bodyTokenPtr, interp); ExceptionRangeEnds(envPtr, range); envPtr->currStackDepth = savedStackDepth + 1; OP( POP); /* * Compile the test expression then emit the conditional jump that * terminates the while. We already know it's a simple word. */ if (loopMayEnd) { LABEL(testCodeOffset); jumpDist = testCodeOffset - jumpEvalCondFixup.codeOffset; if (TclFixupForwardJump(envPtr, &jumpEvalCondFixup, jumpDist, 127)) { bodyCodeOffset += 3; testCodeOffset += 3; } envPtr->currStackDepth = savedStackDepth; PUSH_EXPR_WORD(testTokenPtr, 1); envPtr->currStackDepth = savedStackDepth + 1; BACKJUMP(bodyCodeOffset, JUMP_TRUE); } else { BACKJUMP(bodyCodeOffset, JUMP); } /* * Set the loop's body, continue and break offsets. */ envPtr->exceptArrayPtr[range].continueOffset = testCodeOffset; envPtr->exceptArrayPtr[range].codeOffset = bodyCodeOffset; ExceptionRangeTarget(envPtr, range, breakOffset); /* * The while command's result is an empty string. */ pushResult: envPtr->currStackDepth = savedStackDepth; PUSH(""); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileYieldCmd -- |
︙ | ︙ | |||
2961 2962 2963 2964 2965 2966 2967 | CompileEnv *envPtr) /* Holds resulting instructions. */ { if (parsePtr->numWords < 1 || parsePtr->numWords > 2) { return TCL_ERROR; } if (parsePtr->numWords == 1) { | | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 | CompileEnv *envPtr) /* Holds resulting instructions. */ { if (parsePtr->numWords < 1 || parsePtr->numWords > 2) { return TCL_ERROR; } if (parsePtr->numWords == 1) { PUSH(""); } else { DefineLineInformation; /* TIP #280 */ PUSH_SUBST_WORD(TokenAfter(parsePtr->tokenPtr), 1); } OP( YIELD); return TCL_OK; } /* *---------------------------------------------------------------------- * * CompileUnaryOpCmd -- * * Utility routine to compile the unary operator commands. |
︙ | ︙ | |||
3244 3245 3246 3247 3248 3249 3250 | Tcl_Token *tokenPtr; DefineLineInformation; /* TIP #280 */ if (parsePtr->numWords != 2) { return TCL_ERROR; } tokenPtr = TokenAfter(parsePtr->tokenPtr); | | | 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 | Tcl_Token *tokenPtr; DefineLineInformation; /* TIP #280 */ if (parsePtr->numWords != 2) { return TCL_ERROR; } tokenPtr = TokenAfter(parsePtr->tokenPtr); PUSH_SUBST_WORD(tokenPtr, 1); TclEmitOpcode(instruction, envPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
3285 3286 3287 3288 3289 3290 3291 | { Tcl_Token *tokenPtr = parsePtr->tokenPtr; DefineLineInformation; /* TIP #280 */ int words; for (words=1 ; words<parsePtr->numWords ; words++) { tokenPtr = TokenAfter(tokenPtr); | | | | 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 | { Tcl_Token *tokenPtr = parsePtr->tokenPtr; DefineLineInformation; /* TIP #280 */ int words; for (words=1 ; words<parsePtr->numWords ; words++) { tokenPtr = TokenAfter(tokenPtr); PUSH_SUBST_WORD(tokenPtr, words); } if (parsePtr->numWords <= 2) { PUSH(identity); words++; } if (words > 3) { /* * Reverse order of arguments to get precise agreement with [expr] in * calcuations, including roundoff errors. */ |
︙ | ︙ | |||
3367 3368 3369 3370 3371 3372 3373 | int instruction, CompileEnv *envPtr) { Tcl_Token *tokenPtr; DefineLineInformation; /* TIP #280 */ if (parsePtr->numWords < 3) { | | | | | | | | | | | 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 | int instruction, CompileEnv *envPtr) { Tcl_Token *tokenPtr; DefineLineInformation; /* TIP #280 */ if (parsePtr->numWords < 3) { PUSH("1"); } else if (parsePtr->numWords == 3) { tokenPtr = TokenAfter(parsePtr->tokenPtr); PUSH_SUBST_WORD(tokenPtr, 1); tokenPtr = TokenAfter(tokenPtr); PUSH_SUBST_WORD(tokenPtr, 2); TclEmitOpcode(instruction, envPtr); } else if (envPtr->procPtr == NULL) { /* * No local variable space! */ return TCL_ERROR; } else { int tmpIndex = NewUnnamedLocal(envPtr); int words; tokenPtr = TokenAfter(parsePtr->tokenPtr); PUSH_SUBST_WORD( tokenPtr, 1); tokenPtr = TokenAfter(tokenPtr); PUSH_SUBST_WORD( tokenPtr, 2); OP4( STORE_SCALAR, tmpIndex); TclEmitOpcode(instruction, envPtr); for (words=3 ; words<parsePtr->numWords ;) { OP4( LOAD_SCALAR, tmpIndex); tokenPtr = TokenAfter(tokenPtr); PUSH_SUBST_WORD( tokenPtr, words); if (++words < parsePtr->numWords) { OP4( STORE_SCALAR, tmpIndex); } TclEmitOpcode(instruction, envPtr); } for (; words>3 ; words--) { OP( BITAND); } /* * Drop the value from the temp variable; retaining that reference * might be expensive elsewhere. */ OP14( UNSET_SCALAR, 0, tmpIndex); } return TCL_OK; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
3535 3536 3537 3538 3539 3540 3541 | Tcl_Token *tokenPtr = parsePtr->tokenPtr; DefineLineInformation; /* TIP #280 */ int words; for (words=1 ; words<parsePtr->numWords ; words++) { tokenPtr = TokenAfter(tokenPtr); | | | | | 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 | Tcl_Token *tokenPtr = parsePtr->tokenPtr; DefineLineInformation; /* TIP #280 */ int words; for (words=1 ; words<parsePtr->numWords ; words++) { tokenPtr = TokenAfter(tokenPtr); PUSH_SUBST_WORD(tokenPtr, words); } if (parsePtr->numWords <= 2) { PUSH("1"); words++; } while (--words > 1) { OP( EXPON); } return TCL_OK; } int TclCompileLshiftOpCmd( Tcl_Interp *interp, |
︙ | ︙ | |||
3712 3713 3714 3715 3716 3717 3718 | * Fallback to direct eval to report syntax error. */ return TCL_ERROR; } for (words=1 ; words<parsePtr->numWords ; words++) { tokenPtr = TokenAfter(tokenPtr); | | | | | | | | 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 | * Fallback to direct eval to report syntax error. */ return TCL_ERROR; } for (words=1 ; words<parsePtr->numWords ; words++) { tokenPtr = TokenAfter(tokenPtr); PUSH_SUBST_WORD(tokenPtr, words); } if (words == 2) { OP( UMINUS); return TCL_OK; } if (words == 3) { OP( SUB); return TCL_OK; } /* * Reverse order of arguments to get precise agreement with [expr] in * calcuations, including roundoff errors. */ OP4( REVERSE, words-1); while (--words > 1) { OP( EXCH); OP( SUB); } return TCL_OK; } int TclCompileDivOpCmd( Tcl_Interp *interp, |
︙ | ︙ | |||
3756 3757 3758 3759 3760 3761 3762 | /* * Fallback to direct eval to report syntax error. */ return TCL_ERROR; } if (parsePtr->numWords == 2) { | | | | | | | | 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 | /* * Fallback to direct eval to report syntax error. */ return TCL_ERROR; } if (parsePtr->numWords == 2) { PUSH("1.0"); } for (words=1 ; words<parsePtr->numWords ; words++) { tokenPtr = TokenAfter(tokenPtr); PUSH_SUBST_WORD(tokenPtr, words); } if (words <= 3) { OP( DIV); return TCL_OK; } /* * Reverse order of arguments to get precise agreement with [expr] in * calcuations, including roundoff errors. */ OP4( REVERSE, words-1); while (--words > 1) { OP( EXCH); OP( DIV); } return TCL_OK; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ |
Changes to generic/tclCompExpr.c.
︙ | ︙ | |||
2389 2390 2391 2392 2393 2394 2395 | break; case AND: case OR: CLANG_ASSERT(jumpPtr); TclEmitForwardJump(envPtr, (nodePtr->lexeme == AND) ? TCL_FALSE_JUMP : TCL_TRUE_JUMP, &jumpPtr->next->jump); | < | < | | 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 | break; case AND: case OR: CLANG_ASSERT(jumpPtr); TclEmitForwardJump(envPtr, (nodePtr->lexeme == AND) ? TCL_FALSE_JUMP : TCL_TRUE_JUMP, &jumpPtr->next->jump); PUSH((nodePtr->lexeme == AND) ? "1" : "0"); TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpPtr->next->next->jump); TclFixupForwardJumpToHere(envPtr, &jumpPtr->next->jump, 127); if (TclFixupForwardJumpToHere(envPtr, &jumpPtr->jump, 127)) { jumpPtr->next->next->jump.codeOffset += 3; } PUSH((nodePtr->lexeme == AND) ? "0" : "1"); TclFixupForwardJumpToHere(envPtr, &jumpPtr->next->next->jump, 127); convert = 0; envPtr->currStackDepth = jumpPtr->depth + 1; freePtr = jumpPtr; jumpPtr = jumpPtr->next; TclStackFree(interp, freePtr); |
︙ | ︙ |
Changes to generic/tclCompile.c.
︙ | ︙ | |||
88 89 90 91 92 93 94 | {"storeArrayStk", 1, -2, 0, {OPERAND_NONE}}, /* Store array element; value is stktop, then elem, array names */ {"storeStk", 1, -1, 0, {OPERAND_NONE}}, /* Store general variable; value is stktop, then unparsed name */ {"incrScalar", 5, 0, 1, {OPERAND_LVT4}}, /* Incr scalar at index op1 in frame; incr amount is stktop */ | < < < < | 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | {"storeArrayStk", 1, -2, 0, {OPERAND_NONE}}, /* Store array element; value is stktop, then elem, array names */ {"storeStk", 1, -1, 0, {OPERAND_NONE}}, /* Store general variable; value is stktop, then unparsed name */ {"incrScalar", 5, 0, 1, {OPERAND_LVT4}}, /* Incr scalar at index op1 in frame; incr amount is stktop */ {"incrArray", 5, -1, 1, {OPERAND_LVT4}}, /* Incr array elem; arr at slot op1, amount is top then elem */ {"incrArrayStk", 1, -2, 0, {OPERAND_NONE}}, /* Incr array element; amount is top then elem then array names */ {"incrStk", 1, -1, 0, {OPERAND_NONE}}, /* Incr general variable; amount is stktop then unparsed var name */ {"incrScalarImm", 6, +1, 2, {OPERAND_LVT4, OPERAND_INT1}}, /* Incr scalar at slot op1 <= 255; amount is 2nd operand byte */ {"incrArrayImm", 6, 0, 2, {OPERAND_LVT4, OPERAND_INT1}}, /* Incr array elem; array at slot op1 <= 255, elem is stktop, * amount is 2nd operand byte */ {"incrArrayStkImm", 2, -1, 1, {OPERAND_INT1}}, /* Incr array element; elem is top then array name, amount is op1 */ {"incrStkImm", 2, 0, 1, {OPERAND_INT1}}, /* Incr general variable; unparsed name is top, amount is op1 */ |
︙ | ︙ | |||
315 316 317 318 319 320 321 | * indicated by op4 to hold the iterator state. The local scalar * should not refer to a named variable as the value is not wholly * managed correctly. * Stack: ... dict => ... value key doneBool */ {"dictNext", 5, +3, 1, {OPERAND_LVT4}}, /* Get the next iteration from the iterator in op4's local scalar. * Stack: ... => ... value key doneBool */ | < < < | 311 312 313 314 315 316 317 318 319 320 321 322 323 324 | * indicated by op4 to hold the iterator state. The local scalar * should not refer to a named variable as the value is not wholly * managed correctly. * Stack: ... dict => ... value key doneBool */ {"dictNext", 5, +3, 1, {OPERAND_LVT4}}, /* Get the next iteration from the iterator in op4's local scalar. * Stack: ... => ... value key doneBool */ {"dictUpdateStart", 9, 0, 2, {OPERAND_LVT4, OPERAND_AUX4}}, /* Create the variables (described in the aux data referred to by the * second immediate argument) to mirror the state of the dictionary in * the variable referred to by the first immediate argument. The list * of keys (top of the stack, not poppsed) must be the same length as * the list of variables. * Stack: ... keyList => ... keyList */ |
︙ | ︙ | |||
495 496 497 498 499 500 501 502 503 504 505 506 507 508 | /* Forces the element on the top of the stack to be the name of an * array. * Stack: ... varName => ... */ {"arrayMakeImm", 5, 0, 1, {OPERAND_UINT4}}, /* Forces the variable indexed by opnd to be an array. Does not touch * the stack. */ {NULL, 0, 0, 0, {OPERAND_NONE}} }; /* * Prototypes for procedures defined later in this file: */ | > > > > > > > > > > > | 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 | /* Forces the element on the top of the stack to be the name of an * array. * Stack: ... varName => ... */ {"arrayMakeImm", 5, 0, 1, {OPERAND_UINT4}}, /* Forces the variable indexed by opnd to be an array. Does not touch * the stack. */ {"exch", 1, 0, 0, {OPERAND_NONE}}, /* Swap the two items on the top of the stack. * Stack: ... a b => ... b a */ {"under", 1, +1, 0, {OPERAND_NONE}}, /* Duplicates the item under the top of the stack. * Stack: ... a b => ... a b a */ {"invokeReplace", 6, INT_MIN, 2, {OPERAND_UINT4,OPERAND_UINT1}}, /* Invoke command named objv[0], replacing the first two words with * the word at the top of the stack; * <objc,objv> = <op4,top op4 after popping 1> */ {NULL, 0, 0, 0, {OPERAND_NONE}} }; /* * Prototypes for procedures defined later in this file: */ |
︙ | ︙ | |||
1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 | Tcl_Token *tokenPtr; int bytesLeft, isFirstCmd, wordIdx, currCmdIndex, commandLength, objIndex; Tcl_DString ds; /* TIP #280 */ ExtCmdLoc *eclPtr = envPtr->extCmdMapPtr; int *wlines, wlineat, cmdLine, *clNext; Tcl_Parse *parsePtr = TclStackAlloc(interp, sizeof(Tcl_Parse)); Tcl_DStringInit(&ds); if (numBytes < 0) { numBytes = strlen(script); } Tcl_ResetResult(interp); | > > | 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 | Tcl_Token *tokenPtr; int bytesLeft, isFirstCmd, wordIdx, currCmdIndex, commandLength, objIndex; Tcl_DString ds; /* TIP #280 */ ExtCmdLoc *eclPtr = envPtr->extCmdMapPtr; int *wlines, wlineat, cmdLine, *clNext; Tcl_Parse *parsePtr = TclStackAlloc(interp, sizeof(Tcl_Parse)); int generateStartCmds = Tcl_IsSafe(interp) || Tcl_LimitTypeEnabled(interp, TCL_LIMIT_COMMANDS|TCL_LIMIT_TIME); Tcl_DStringInit(&ds); if (numBytes < 0) { numBytes = strlen(script); } Tcl_ResetResult(interp); |
︙ | ︙ | |||
1760 1761 1762 1763 1764 1765 1766 | * case. [Bug 1752146] * * Note that the environment is initialised with * atCmdStart=1 to avoid emitting ISC for the first * command. */ | > | | | | | | | > | | > | > | | | | | | > | 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 | * case. [Bug 1752146] * * Note that the environment is initialised with * atCmdStart=1 to avoid emitting ISC for the first * command. */ if (generateStartCmds) { if (envPtr->atCmdStart) { if (savedCodeNext != 0) { /* * Increase the number of commands being * started at the current point. Note that * this depends on the exact layout of the * INST_START_CMD's operands, so be * careful! */ unsigned char *fixPtr = envPtr->codeNext - 4; TclStoreInt4AtPtr( TclGetUInt4AtPtr(fixPtr) + 1, fixPtr); } } else { TclEmitInstInt4(INST_START_CMD, 0, envPtr); TclEmitInt4(1, envPtr); update = 1; } } code = cmdPtr->compileProc(interp, parsePtr, cmdPtr, envPtr); if (code == TCL_OK) { /* |
︙ | ︙ | |||
1803 1804 1805 1806 1807 1808 1809 | *(envPtr->codeNext-1) != INST_DONE)) { Tcl_Panic("bad stack adjustment when compiling" " %.*s (was %d instead of 1)", parsePtr->tokenPtr->size, parsePtr->tokenPtr->start, diff); } #endif | | > | | 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 | *(envPtr->codeNext-1) != INST_DONE)) { Tcl_Panic("bad stack adjustment when compiling" " %.*s (was %d instead of 1)", parsePtr->tokenPtr->size, parsePtr->tokenPtr->start, diff); } #endif if (generateStartCmds && update) { /* * Fix the bytecode length. */ unsigned char *fixPtr = envPtr->codeStart + savedCodeNext + 1; unsigned fixLen = envPtr->codeNext - envPtr->codeStart - savedCodeNext; TclStoreInt4AtPtr(fixLen, fixPtr); } goto finishCommand; } if (generateStartCmds && envPtr->atCmdStart && savedCodeNext != 0) { /* * Decrease the number of commands being started * at the current point. Note that this depends on * the exact layout of the INST_START_CMD's * operands, so be careful! */ |
︙ | ︙ | |||
2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 | concatItems -= 254; } if (concatItems > 1) { TclEmitInstInt1(INST_CONCAT, concatItems, envPtr); } TclEmitOpcode(INST_EXPR_STK, envPtr); } /* *---------------------------------------------------------------------- * * TclCompileNoOp -- * * Function called to compile no-op's | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 | concatItems -= 254; } if (concatItems > 1) { TclEmitInstInt1(INST_CONCAT, concatItems, envPtr); } TclEmitOpcode(INST_EXPR_STK, envPtr); } /* *---------------------------------------------------------------------- * * PushVarName -- * * Procedure used in the compiling where pushing a variable name is * necessary (append, lappend, set). * * Results: * Returns TCL_OK for a successful compile. Returns TCL_ERROR to defer * evaluation to runtime. * * Side effects: * Instructions are added to envPtr to execute the "set" command at * runtime. * *---------------------------------------------------------------------- */ int TclPushVarName( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Token *varTokenPtr, /* Points to a variable token. */ CompileEnv *envPtr, /* Holds resulting instructions. */ int flags, /* TCL_NO_LARGE_INDEX | TCL_NO_ELEMENT. */ int *localIndexPtr, /* Must not be NULL. */ int *simpleVarNamePtr, /* Must not be NULL. */ int *isScalarPtr, /* Must not be NULL. */ int line, /* Line the token starts on. */ int *clNext) /* Reference to offset of next hidden cont. * line. */ { register const char *p; const char *name, *elName; register int i, n; Tcl_Token *elemTokenPtr = NULL; int nameChars, elNameChars, simpleVarName, localIndex; int elemTokenCount = 0, allocedTokens = 0, removedParen = 0; /* * Decide if we can use a frame slot for the var/array name or if we need * to emit code to compute and push the name at runtime. We use a frame * slot (entry in the array of local vars) if we are compiling a procedure * body and if the name is simple text that does not include namespace * qualifiers. */ simpleVarName = 0; name = elName = NULL; nameChars = elNameChars = 0; localIndex = -1; /* * Check not only that the type is TCL_TOKEN_SIMPLE_WORD, but whether * curly braces surround the variable name. This really matters for array * elements to handle things like * set {x($foo)} 5 * which raises an undefined var error if we are not careful here. */ if ((varTokenPtr->type == TCL_TOKEN_SIMPLE_WORD) && (varTokenPtr->start[0] != '{')) { /* * A simple variable name. Divide it up into "name" and "elName" * strings. If it is not a local variable, look it up at runtime. */ simpleVarName = 1; name = varTokenPtr[1].start; nameChars = varTokenPtr[1].size; if (name[nameChars-1] == ')') { /* * last char is ')' => potential array reference. */ for (i=0,p=name ; i<nameChars ; i++,p++) { if (*p == '(') { elName = p + 1; elNameChars = nameChars - i - 2; nameChars = i; break; } } if ((elName != NULL) && elNameChars) { /* * An array element, the element name is a simple string: * assemble the corresponding token. */ elemTokenPtr = TclStackAlloc(interp, sizeof(Tcl_Token)); allocedTokens = 1; elemTokenPtr->type = TCL_TOKEN_TEXT; elemTokenPtr->start = elName; elemTokenPtr->size = elNameChars; elemTokenPtr->numComponents = 0; elemTokenCount = 1; } } } else if (((n = varTokenPtr->numComponents) > 1) && (varTokenPtr[1].type == TCL_TOKEN_TEXT) && (varTokenPtr[n].type == TCL_TOKEN_TEXT) && (varTokenPtr[n].start[varTokenPtr[n].size - 1] == ')')) { /* * Check for parentheses inside first token. */ simpleVarName = 0; for (i = 0, p = varTokenPtr[1].start; i < varTokenPtr[1].size; i++, p++) { if (*p == '(') { simpleVarName = 1; break; } } if (simpleVarName) { int remainingChars; /* * Check the last token: if it is just ')', do not count it. * Otherwise, remove the ')' and flag so that it is restored at * the end. */ if (varTokenPtr[n].size == 1) { n--; } else { varTokenPtr[n].size--; removedParen = n; } name = varTokenPtr[1].start; nameChars = p - varTokenPtr[1].start; elName = p + 1; remainingChars = (varTokenPtr[2].start - p) - 1; elNameChars = (varTokenPtr[n].start-p) + varTokenPtr[n].size - 2; if (remainingChars) { /* * Make a first token with the extra characters in the first * token. */ elemTokenPtr = TclStackAlloc(interp, n * sizeof(Tcl_Token)); allocedTokens = 1; elemTokenPtr->type = TCL_TOKEN_TEXT; elemTokenPtr->start = elName; elemTokenPtr->size = remainingChars; elemTokenPtr->numComponents = 0; elemTokenCount = n; /* * Copy the remaining tokens. */ memcpy(elemTokenPtr+1, varTokenPtr+2, (n-1) * sizeof(Tcl_Token)); } else { /* * Use the already available tokens. */ elemTokenPtr = &varTokenPtr[2]; elemTokenCount = n - 1; } } } if (simpleVarName) { /* * See whether name has any namespace separators (::'s). */ int hasNsQualifiers = 0; for (i = 0, p = name; i < nameChars; i++, p++) { if ((*p == ':') && ((i+1) < nameChars) && (*(p+1) == ':')) { hasNsQualifiers = 1; break; } } /* * Look up the var name's index in the array of local vars in the proc * frame. If retrieving the var's value and it doesn't already exist, * push its name and look it up at runtime. */ if (!hasNsQualifiers) { localIndex = TclFindCompiledLocal(name, nameChars, 1, envPtr); if ((flags & TCL_NO_LARGE_INDEX) && (localIndex > 255)) { /* * We'll push the name. */ localIndex = -1; } } if (localIndex < 0) { PushLiteral(envPtr, name, nameChars); } /* * Compile the element script, if any. */ if (elName != NULL && !(flags & TCL_NO_ELEMENT)) { if (elNameChars) { envPtr->line = line; envPtr->clNext = clNext; TclCompileTokens(interp, elemTokenPtr, elemTokenCount, envPtr); } else { PUSH(""); } } } else { /* * The var name isn't simple: compile and push it. */ envPtr->line = line; envPtr->clNext = clNext; CompileTokens(envPtr, varTokenPtr, interp); } if (removedParen) { varTokenPtr[removedParen].size++; } if (allocedTokens) { TclStackFree(interp, elemTokenPtr); } *localIndexPtr = localIndex; *simpleVarNamePtr = simpleVarName; *isScalarPtr = (elName == NULL); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclCompileNoOp -- * * Function called to compile no-op's |
︙ | ︙ |
Changes to generic/tclCompile.h.
︙ | ︙ | |||
473 474 475 476 477 478 479 | #define INST_LOAD_STK 12 #define INST_STORE_SCALAR 13 #define INST_STORE_SCALAR_STK 14 #define INST_STORE_ARRAY 15 #define INST_STORE_ARRAY_STK 16 #define INST_STORE_STK 17 | | < | | | | < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > > > | 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 | #define INST_LOAD_STK 12 #define INST_STORE_SCALAR 13 #define INST_STORE_SCALAR_STK 14 #define INST_STORE_ARRAY 15 #define INST_STORE_ARRAY_STK 16 #define INST_STORE_STK 17 /* Opcodes 18 to 25: [incr] */ #define INST_INCR_SCALAR 18 #define INST_INCR_ARRAY 19 #define INST_INCR_ARRAY_STK 20 #define INST_INCR_STK 21 #define INST_INCR_SCALAR_IMM 22 #define INST_INCR_ARRAY_IMM 23 #define INST_INCR_ARRAY_STK_IMM 24 #define INST_INCR_STK_IMM 25 /* Opcodes 26 to 28 */ #define INST_JUMP 26 #define INST_JUMP_TRUE 27 #define INST_JUMP_FALSE 28 /* Opcodes 29 to 54: operators */ #define INST_LOR 29 #define INST_LAND 30 #define INST_BITOR 31 #define INST_BITXOR 32 #define INST_BITAND 33 #define INST_EQ 34 #define INST_NEQ 35 #define INST_LT 36 #define INST_GT 37 #define INST_LE 38 #define INST_GE 39 #define INST_LSHIFT 40 #define INST_RSHIFT 41 #define INST_ADD 42 #define INST_SUB 43 #define INST_MULT 44 #define INST_DIV 45 #define INST_MOD 46 #define INST_UPLUS 47 #define INST_UMINUS 48 #define INST_BITNOT 49 #define INST_LNOT 50 #define INST_TRY_CVT_TO_NUMERIC 51 #define INST_EXPON 52 #define INST_LIST_IN 53 #define INST_LIST_NOT_IN 54 /* Opcodes 55 to 56: [foreach] */ #define INST_FOREACH_START 55 #define INST_FOREACH_STEP 56 /* Opcodes 57 to 66 */ #define INST_BREAK 57 #define INST_CONTINUE 58 #define INST_BEGIN_CATCH 59 #define INST_END_CATCH 60 #define INST_PUSH_RESULT 61 #define INST_PUSH_RETURN_CODE 62 #define INST_PUSH_RETURN_OPTIONS 63 #define INST_RETURN_STK 64 #define INST_RETURN_IMM 65 #define INST_RETURN_CODE_BRANCH 66 /* Opcodes 67 to 72 */ #define INST_STR_EQ 67 #define INST_STR_NEQ 68 #define INST_STR_CMP 69 #define INST_STR_LEN 70 #define INST_STR_INDEX 71 #define INST_STR_MATCH 72 /* Opcodes 73 to 75: list ops */ #define INST_LIST 73 #define INST_LIST_INDEX 74 #define INST_LIST_LENGTH 75 /* Opcodes 76 to 79: [append] */ #define INST_APPEND_SCALAR 76 #define INST_APPEND_ARRAY 77 #define INST_APPEND_ARRAY_STK 78 #define INST_APPEND_STK 79 /* Opcodes 80 to 83: [lappend] */ #define INST_LAPPEND_SCALAR 80 #define INST_LAPPEND_ARRAY 81 #define INST_LAPPEND_ARRAY_STK 82 #define INST_LAPPEND_STK 83 /* TIP #22 - LINDEX operator with flat arg list */ #define INST_LIST_INDEX_MULTI 84 /* TIP #33 - 'lset' command. */ #define INST_LSET_LIST 85 #define INST_LSET_FLAT 86 /* TIP #157 - {*}... (word expansion) language syntax support. */ #define INST_EXPAND_START 87 #define INST_EXPAND_STKTOP 88 #define INST_INVOKE_EXPANDED 89 /* * TIP #57 - 'lassign' command. Code generation requires immediate * LINDEX and LRANGE operators. */ #define INST_LIST_INDEX_IMM 90 #define INST_LIST_RANGE_IMM 91 #define INST_START_CMD 92 /* Dictionary (TIP#111) related commands. */ #define INST_DICT_GET 93 #define INST_DICT_SET 94 #define INST_DICT_UNSET 95 #define INST_DICT_INCR_IMM 96 #define INST_DICT_APPEND 97 #define INST_DICT_LAPPEND 98 #define INST_DICT_FIRST 99 #define INST_DICT_NEXT 100 #define INST_DICT_UPDATE_START 101 #define INST_DICT_UPDATE_END 102 #define INST_DICT_EXPAND 103 #define INST_DICT_RECOMBINE_STK 104 #define INST_DICT_RECOMBINE_IMM 105 #define INST_DICT_EXISTS 106 #define INST_DICT_VERIFY 107 /* * Instruction to support jumps defined by tables (instead of the classic * [switch] technique of chained comparisons). */ #define INST_JUMP_TABLE 108 /* * Instructions to support compilation of global, variable, upvar and * [namespace upvar]. */ #define INST_UPVAR 109 #define INST_NSUPVAR 110 #define INST_VARIABLE 111 /* Utilities */ #define INST_OVER 112 #define INST_SYNTAX 113 #define INST_REVERSE 114 #define INST_NOP 115 /* regexp instruction */ #define INST_REGEXP 116 /* For [info exists] compilation */ #define INST_EXIST_SCALAR 117 #define INST_EXIST_ARRAY 118 #define INST_EXIST_ARRAY_STK 119 #define INST_EXIST_STK 120 /* For [unset] compilation */ #define INST_UNSET_SCALAR 121 #define INST_UNSET_ARRAY 122 #define INST_UNSET_ARRAY_STK 123 #define INST_UNSET_STK 124 /* For [string map] and [regsub] compilation */ #define INST_STR_MAP 125 #define INST_STR_FIND 126 #define INST_STR_FIND_LAST 127 #define INST_STR_RANGE_IMM 128 #define INST_STR_RANGE 129 /* For operations to do with coroutines and other NRE-manipulators */ #define INST_YIELD 130 #define INST_COROUTINE_NAME 131 #define INST_TAILCALL 132 /* For compilation of basic information operations */ #define INST_NS_CURRENT 133 #define INST_INFO_LEVEL_NUM 134 #define INST_INFO_LEVEL_ARGS 135 #define INST_RESOLVE_COMMAND 136 #define INST_TCLOO_SELF 137 #define INST_TCLOO_CLASS 138 #define INST_TCLOO_NS 139 #define INST_TCLOO_IS_OBJECT 140 /* For compilation of [array] subcommands */ #define INST_ARRAY_EXISTS_STK 141 #define INST_ARRAY_EXISTS_IMM 142 #define INST_ARRAY_MAKE_STK 143 #define INST_ARRAY_MAKE_IMM 144 #define INST_EXCH 145 #define INST_UNDER 146 #define INST_INVOKE_REPLACE 147 /* The last opcode */ #define LAST_INST_OPCODE 147 /* * Table describing the Tcl bytecode instructions: their name (for displaying * code), total number of code bytes required (including operand bytes), and a |
︙ | ︙ | |||
936 937 938 939 940 941 942 943 944 945 946 947 948 949 | #endif MODULE_SCOPE int TclPrintInstruction(ByteCode *codePtr, const unsigned char *pc); MODULE_SCOPE void TclPrintObject(FILE *outFile, Tcl_Obj *objPtr, int maxChars); MODULE_SCOPE void TclPrintSource(FILE *outFile, const char *string, int maxChars); MODULE_SCOPE void TclRegisterAuxDataType(const AuxDataType *typePtr); MODULE_SCOPE int TclRegisterLiteral(CompileEnv *envPtr, char *bytes, int length, int flags); MODULE_SCOPE void TclReleaseLiteral(Tcl_Interp *interp, Tcl_Obj *objPtr); MODULE_SCOPE void TclInvalidateCmdLiteral(Tcl_Interp *interp, const char *name, Namespace *nsPtr); MODULE_SCOPE int TclSingleOpCmd(ClientData clientData, | > > > > > | 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 | #endif MODULE_SCOPE int TclPrintInstruction(ByteCode *codePtr, const unsigned char *pc); MODULE_SCOPE void TclPrintObject(FILE *outFile, Tcl_Obj *objPtr, int maxChars); MODULE_SCOPE void TclPrintSource(FILE *outFile, const char *string, int maxChars); MODULE_SCOPE int TclPushVarName(Tcl_Interp *interp, Tcl_Token *varTokenPtr, CompileEnv *envPtr, int flags, int *localIndexPtr, int *simpleVarNamePtr, int *isScalarPtr, int line, int *clNext); MODULE_SCOPE void TclRegisterAuxDataType(const AuxDataType *typePtr); MODULE_SCOPE int TclRegisterLiteral(CompileEnv *envPtr, char *bytes, int length, int flags); MODULE_SCOPE void TclReleaseLiteral(Tcl_Interp *interp, Tcl_Obj *objPtr); MODULE_SCOPE void TclInvalidateCmdLiteral(Tcl_Interp *interp, const char *name, Namespace *nsPtr); MODULE_SCOPE int TclSingleOpCmd(ClientData clientData, |
︙ | ︙ | |||
961 962 963 964 965 966 967 | #ifdef TCL_COMPILE_DEBUG MODULE_SCOPE void TclVerifyGlobalLiteralTable(Interp *iPtr); MODULE_SCOPE void TclVerifyLocalLiteralTable(CompileEnv *envPtr); #endif MODULE_SCOPE int TclWordKnownAtCompileTime(Tcl_Token *tokenPtr, Tcl_Obj *valuePtr); MODULE_SCOPE void TclLogCommandInfo(Tcl_Interp *interp, | | | | | | 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 | #ifdef TCL_COMPILE_DEBUG MODULE_SCOPE void TclVerifyGlobalLiteralTable(Interp *iPtr); MODULE_SCOPE void TclVerifyLocalLiteralTable(CompileEnv *envPtr); #endif MODULE_SCOPE int TclWordKnownAtCompileTime(Tcl_Token *tokenPtr, Tcl_Obj *valuePtr); MODULE_SCOPE void TclLogCommandInfo(Tcl_Interp *interp, const char *script, const char *command, int length, const unsigned char *pc, Tcl_Obj **tosPtr); MODULE_SCOPE Tcl_Obj *TclGetInnerContext(Tcl_Interp *interp, const unsigned char *pc, Tcl_Obj **tosPtr); MODULE_SCOPE Tcl_Obj *TclNewInstNameObj(unsigned char inst); /* *---------------------------------------------------------------- * Macros and flag values used by Tcl bytecode compilation and execution * modules inside the Tcl core but not used outside. |
︙ | ︙ | |||
1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 | * static void CompileTokens(CompileEnv *envPtr, Tcl_Token *tokenPtr, * Tcl_Interp *interp); */ #define CompileTokens(envPtr, tokenPtr, interp) \ TclCompileTokens((interp), (tokenPtr)+1, (tokenPtr)->numComponents, \ (envPtr)); /* * Convenience macro for use when pushing literals. The ANSI C "prototype" for * this macro is: * * static void PushLiteral(CompileEnv *envPtr, * const char *string, int length); */ | > | 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 | * static void CompileTokens(CompileEnv *envPtr, Tcl_Token *tokenPtr, * Tcl_Interp *interp); */ #define CompileTokens(envPtr, tokenPtr, interp) \ TclCompileTokens((interp), (tokenPtr)+1, (tokenPtr)->numComponents, \ (envPtr)); /* * Convenience macro for use when pushing literals. The ANSI C "prototype" for * this macro is: * * static void PushLiteral(CompileEnv *envPtr, * const char *string, int length); */ |
︙ | ︙ | |||
1307 1308 1309 1310 1311 1312 1313 | * static int CurrentOffset(CompileEnv *envPtr); */ #define CurrentOffset(envPtr) \ ((envPtr)->codeNext - (envPtr)->codeStart) /* | | | | | < | 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 | * static int CurrentOffset(CompileEnv *envPtr); */ #define CurrentOffset(envPtr) \ ((envPtr)->codeNext - (envPtr)->codeStart) /* * Note: the exceptDepth is a bit of a misnomer: TEBC only needs the maximal * depth of nested CATCH ranges in order to alloc runtime memory. These macros * should compute precisely that? OTOH, the nesting depth of LOOP ranges is an * interesting datum for debugging purposes, and that is what we compute now. * * static int DeclareExceptionRange(CompileEnv *envPtr, int type); * static int ExceptionRangeStarts(CompileEnv *envPtr, int index); * static void ExceptionRangeEnds(CompileEnv *envPtr, int index); * static void ExceptionRangeTarget(CompileEnv *envPtr, int index, LABEL); */ |
︙ | ︙ | |||
1334 1335 1336 1337 1338 1339 1340 | (((envPtr)->exceptDepth--), \ ((envPtr)->exceptArrayPtr[(index)].numCodeBytes = \ CurrentOffset(envPtr) - (envPtr)->exceptArrayPtr[(index)].codeOffset)) #define ExceptionRangeTarget(envPtr, index, targetType) \ ((envPtr)->exceptArrayPtr[(index)].targetType = CurrentOffset(envPtr)) /* | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 | (((envPtr)->exceptDepth--), \ ((envPtr)->exceptArrayPtr[(index)].numCodeBytes = \ CurrentOffset(envPtr) - (envPtr)->exceptArrayPtr[(index)].codeOffset)) #define ExceptionRangeTarget(envPtr, index, targetType) \ ((envPtr)->exceptArrayPtr[(index)].targetType = CurrentOffset(envPtr)) /* * Check if there is an LVT for compiled locals, and issuing a new private * variable. */ #define EnvHasLVT(envPtr) \ (envPtr->procPtr || envPtr->iPtr->varFramePtr->localCachePtr) #define NewUnnamedLocal(envPtr) \ TclFindCompiledLocal(NULL, /*nameChars*/ 0, /*create*/ 1, (envPtr)) /* * Macros for making it easier to deal with tokens and DStrings. */ #define TclDStringAppendToken(dsPtr, tokenPtr) \ Tcl_DStringAppend((dsPtr), (tokenPtr)->start, (tokenPtr)->size) #define TclRegisterDStringLiteral(envPtr, dsPtr) \ TclRegisterLiteral(envPtr, Tcl_DStringValue(dsPtr), \ Tcl_DStringLength(dsPtr), /*flags*/ 0) /* * Macro that encapsulates an efficiency trick that avoids a function call for * the simplest of compiles. The ANSI C "prototype" for this macro is: * * static void CompileWord(CompileEnv *envPtr, Tcl_Token *tokenPtr, * Tcl_Interp *interp, int word); */ #define CompileWord(envPtr, tokenPtr, interp, word) \ if ((tokenPtr)->type == TCL_TOKEN_SIMPLE_WORD) { \ TclEmitPush(TclRegisterNewLiteral((envPtr), (tokenPtr)[1].start, \ (tokenPtr)[1].size), (envPtr)); \ } else { \ envPtr->line = mapPtr->loc[eclIndex].line[word]; \ envPtr->clNext = mapPtr->loc[eclIndex].next[word]; \ TclCompileTokens((interp), (tokenPtr)+1, (tokenPtr)->numComponents, \ (envPtr)); \ } /* * TIP #280: Remember the per-word line information of the current command. An * index is used instead of a pointer as recursive compilation may reallocate, * i.e. move, the array. This is also the reason to save the nuloc now, it may * change during the course of the function. * * Macro to encapsulate the variable definition and setup. */ #define DefineLineInformation \ ExtCmdLoc *mapPtr = envPtr->extCmdMapPtr; \ int eclIndex = mapPtr->nuloc - 1 #define SetLineInformation(word) \ do { \ envPtr->line = mapPtr->loc[eclIndex].line[(word)]; \ envPtr->clNext = mapPtr->loc[eclIndex].next[(word)]; \ } while (0) #define PushVarNameWord(i,v,e,f,l,s,sc,word) \ TclPushVarName(i,v,e,f,l,s,sc, \ mapPtr->loc[eclIndex].line[(word)], \ mapPtr->loc[eclIndex].next[(word)]) /* * Flags bits used by TclPushVarName. */ #define TCL_NO_LARGE_INDEX 1 /* Do not return localIndex value > 255 */ #define TCL_NO_ELEMENT 2 /* Do not push the array element. */ /* * Shorthand macros for instruction issuing. Note that these assume that there * are variables in the current environment called 'envPtr' and 'interp', and * also that there are no side effects in the arguments given. */ #define OP(name) TclEmitOpcode(INST_##name, envPtr) #define OP1(name,val) TclEmitInstInt1(INST_##name, (val), envPtr) #define OP4(name,val) TclEmitInstInt4(INST_##name, (val), envPtr) #define OP14(name,val1,val2) \ do { \ TclEmitInstInt1(INST_##name, (val1), envPtr); \ TclEmitInt4((val2), envPtr); \ } while (0) #define OP41(name,val1,val2) \ do { \ TclEmitInstInt4(INST_##name, (val1), envPtr); \ TclEmitInt1((val2), envPtr); \ } while (0) #define OP44(name,val1,val2) \ do { \ TclEmitInstInt4(INST_##name, (val1), envPtr); \ TclEmitInt4((val2), envPtr); \ } while (0) #define BODY(token,index) \ do { \ SetLineInformation((index)); \ CompileBody(envPtr, (token), interp); \ } while (0) #define PUSH(str) \ PushLiteral(envPtr, (str), strlen(str)) #define PUSH_SUBST_WORD(token,index) \ do { \ Tcl_Token *theTokenToCompile = (token); \ int theIndex = (index); \ CompileWord(envPtr, theTokenToCompile, interp, theIndex); \ } while (0) #define PUSH_EXPR_WORD(token,index) \ do { \ Tcl_Token *theTokenToCompile = (token); \ int theIndex = (index); \ SetLineInformation(theIndex); \ TclCompileExprWords(interp, theTokenToCompile, 1, envPtr); \ } while (0) #define PUSH_VAR(v,word,l,s,sc) \ TclPushVarName(interp,(v),envPtr,0,(l),(s),(sc), \ mapPtr->loc[eclIndex].line[(word)], \ mapPtr->loc[eclIndex].next[(word)]) #define PUSH_OBJ(obj) \ do { \ int objLength; \ char *objBytes = Tcl_GetStringFromObj((obj), &objLength); \ PushLiteral(envPtr, objBytes, objLength); \ } while (0) #define PUSH_DSTRING(dsPtr) \ PushLiteral(envPtr, Tcl_DStringValue((dsPtr)), Tcl_DStringLength((dsPtr))) #define LABEL(var) \ ((var) = CurrentOffset(envPtr)) #define BACKJUMP(var,name) \ do { \ int theOffset = (var) - CurrentOffset(envPtr); \ TclEmitInstInt4(INST_##name, theOffset, envPtr); \ } while (0) #define JUMP(var,name) \ do { \ (var) = CurrentOffset(envPtr); \ TclEmitInstInt4(INST_##name, 0, envPtr); \ } while (0) #define FIXJUMP(var) \ do { \ if ((var) >= 0) { \ TclStoreInt4AtPtr(CurrentOffset(envPtr)-(var), \ envPtr->codeStart+(var)+1); \ } \ } while (0) /* * DTrace probe macros (NOPs if DTrace support is not enabled). */ /* * Define the following macros to enable debug logging of the DTrace proc, * cmd, and inst probes. Note that this does _not_ require a platform with |
︙ | ︙ |
Changes to generic/tclDecls.h.
︙ | ︙ | |||
3740 3741 3742 3743 3744 3745 3746 3747 | #if defined(_WIN32) && defined(UNICODE) # define Tcl_FindExecutable(arg) ((Tcl_FindExecutable)((const char *)(arg))) # define Tcl_MainEx Tcl_MainExW TCLAPI void Tcl_MainExW(int argc, wchar_t **argv, Tcl_AppInitProc *appInitProc, Tcl_Interp *interp); #endif #endif /* _TCLDECLS */ | > > > > > > > > > > > > | 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 | #if defined(_WIN32) && defined(UNICODE) # define Tcl_FindExecutable(arg) ((Tcl_FindExecutable)((const char *)(arg))) # define Tcl_MainEx Tcl_MainExW TCLAPI void Tcl_MainExW(int argc, wchar_t **argv, Tcl_AppInitProc *appInitProc, Tcl_Interp *interp); #endif /* * Deprecated Tcl procedures: */ #if defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) # undef Tcl_EvalObj # define Tcl_EvalObj(interp,objPtr) \ Tcl_EvalObjEx((interp),(objPtr),0) # undef Tcl_GlobalEvalObj # define Tcl_GlobalEvalObj(interp,objPtr) \ Tcl_EvalObjEx((interp),(objPtr),TCL_EVAL_GLOBAL) #endif #endif /* _TCLDECLS */ |
Changes to generic/tclDictObj.c.
︙ | ︙ | |||
87 88 89 90 91 92 93 | * Table of dict subcommand names and implementations. */ static const EnsembleImplMap implementationMap[] = { {"append", DictAppendCmd, TclCompileDictAppendCmd, NULL, NULL, 0 }, {"create", DictCreateCmd, TclCompileDictCreateCmd, NULL, NULL, 0 }, {"exists", DictExistsCmd, TclCompileDictExistsCmd, NULL, NULL, 0 }, | | | | | | | | 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | * Table of dict subcommand names and implementations. */ static const EnsembleImplMap implementationMap[] = { {"append", DictAppendCmd, TclCompileDictAppendCmd, NULL, NULL, 0 }, {"create", DictCreateCmd, TclCompileDictCreateCmd, NULL, NULL, 0 }, {"exists", DictExistsCmd, TclCompileDictExistsCmd, NULL, NULL, 0 }, {"filter", DictFilterCmd, NULL, NULL, NULL, 0 }, {"for", NULL, TclCompileDictForCmd, DictForNRCmd, NULL, 0 }, {"get", DictGetCmd, TclCompileDictGetCmd, NULL, NULL, 0 }, {"incr", DictIncrCmd, TclCompileDictIncrCmd, NULL, NULL, 0 }, {"info", DictInfoCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0 }, {"keys", DictKeysCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 }, {"lappend", DictLappendCmd, TclCompileDictLappendCmd, NULL, NULL, 0 }, {"map", NULL, TclCompileDictMapCmd, DictMapNRCmd, NULL, 0 }, {"merge", DictMergeCmd, TclCompileDictMergeCmd, NULL, NULL, 0 }, {"remove", DictRemoveCmd, TclCompileBasicMin1ArgCmd, NULL, NULL, 0 }, {"replace", DictReplaceCmd, NULL, NULL, NULL, 0 }, {"set", DictSetCmd, TclCompileDictSetCmd, NULL, NULL, 0 }, {"size", DictSizeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0 }, {"unset", DictUnsetCmd, TclCompileDictUnsetCmd, NULL, NULL, 0 }, {"update", DictUpdateCmd, TclCompileDictUpdateCmd, NULL, NULL, 0 }, {"values", DictValuesCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 }, {"with", DictWithCmd, TclCompileDictWithCmd, NULL, NULL, 0 }, {NULL, NULL, NULL, NULL, NULL, 0} }; /* * Internal representation of the entries in the hash table that backs a * dictionary. |
︙ | ︙ |
Changes to generic/tclEncoding.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /* * tclEncoding.c -- * * Contains the implementation of the encoding conversion package. * * Copyright (c) 1996-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" typedef size_t (LengthProc)(const char *src); /* * The following data structure represents an encoding, which describes how to * convert between various character sets and UTF-8. | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* * tclEncoding.c -- * * Contains the implementation of the encoding conversion package. * * Copyright (c) 1996-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include <sys/stat.h> #include "tclInt.h" typedef size_t (LengthProc)(const char *src); /* * The following data structure represents an encoding, which describes how to * convert between various character sets and UTF-8. |
︙ | ︙ |
Changes to generic/tclEnsemble.c.
1 2 3 4 5 6 | /* * tclEnsemble.c -- * * Contains support for ensembles (see TIP#112), which provide simple * mechanism for creating composite commands on top of namespaces. * | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /* * tclEnsemble.c -- * * Contains support for ensembles (see TIP#112), which provide simple * mechanism for creating composite commands on top of namespaces. * * Copyright (c) 2005-2013 Donal K. Fellows. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclCompile.h" |
︙ | ︙ | |||
31 32 33 34 35 36 37 38 39 40 41 42 43 44 | static void DeleteEnsembleConfig(ClientData clientData); static void MakeCachedEnsembleCommand(Tcl_Obj *objPtr, EnsembleConfig *ensemblePtr, const char *subcmdName, Tcl_Obj *prefixObjPtr); static void FreeEnsembleCmdRep(Tcl_Obj *objPtr); static void DupEnsembleCmdRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr); static void StringOfEnsembleCmdRep(Tcl_Obj *objPtr); /* * The lists of subcommands and options for the [namespace ensemble] command. */ static const char *const ensembleSubcommands[] = { "configure", "create", "exists", NULL | > > > > > > > > > | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | static void DeleteEnsembleConfig(ClientData clientData); static void MakeCachedEnsembleCommand(Tcl_Obj *objPtr, EnsembleConfig *ensemblePtr, const char *subcmdName, Tcl_Obj *prefixObjPtr); static void FreeEnsembleCmdRep(Tcl_Obj *objPtr); static void DupEnsembleCmdRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr); static void StringOfEnsembleCmdRep(Tcl_Obj *objPtr); static int CompileToCompiledCommand(Tcl_Interp *interp, Tcl_Parse *parsePtr, int depth, Command *cmdPtr, CompileEnv *envPtr); static void CompileToInvokedCommand(Tcl_Interp *interp, Tcl_Parse *parsePtr, Tcl_Obj *replacements, Command *cmdPtr, CompileEnv *envPtr); static int CompileBasicNArgCommand(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, CompileEnv *envPtr); /* * The lists of subcommands and options for the [namespace ensemble] command. */ static const char *const ensembleSubcommands[] = { "configure", "create", "exists", NULL |
︙ | ︙ | |||
1561 1562 1563 1564 1565 1566 1567 | cmdPtr = (Command *) Tcl_NRCreateCommand(interp, TclGetString(toObj), map[i].proc, map[i].nreProc, map[i].clientData, NULL); } cmdPtr->compileProc = map[i].compileProc; | < < < | > | > > | > > | | 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 | cmdPtr = (Command *) Tcl_NRCreateCommand(interp, TclGetString(toObj), map[i].proc, map[i].nreProc, map[i].clientData, NULL); } cmdPtr->compileProc = map[i].compileProc; } } Tcl_SetEnsembleMappingDict(interp, ensemble, mapDict); /* * Switch on compilation always for core ensembles now that we can do * nice bytecode things with them. */ Tcl_SetEnsembleFlags(interp, ensemble, ensembleFlags | ENSEMBLE_COMPILE); } Tcl_DStringFree(&buf); Tcl_DStringFree(&hiddenBuf); if (nameParts != NULL) { ckfree((char *) nameParts); } return ensemble; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
1888 1889 1890 1891 1892 1893 1894 | } } /* * Hand off to the target command. */ | | | 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 | } } /* * Hand off to the target command. */ TclSkipTailcall(interp); return TclNREvalObjEx(interp, copyPtr, TCL_EVAL_INVOKE, NULL,INT_MIN); } unknownOrAmbiguousSubcommand: /* * Have not been able to match the subcommand asked for with a real * subcommand that we export. See whether a handler has been registered |
︙ | ︙ | |||
2096 2097 2098 2099 2100 2101 2102 | * Now call the unknown handler. (We don't bother NRE-enabling this; deep * recursing through unknown handlers is horribly perverse.) Note that it * is always an error for an unknown handler to delete its ensemble; don't * do that! */ Tcl_Preserve(ensemblePtr); | | | 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 | * Now call the unknown handler. (We don't bother NRE-enabling this; deep * recursing through unknown handlers is horribly perverse.) Note that it * is always an error for an unknown handler to delete its ensemble; don't * do that! */ Tcl_Preserve(ensemblePtr); TclSkipTailcall(interp); result = Tcl_EvalObjv(interp, paramc, paramv, 0); if ((result == TCL_OK) && (ensemblePtr->flags & ENSEMBLE_DEAD)) { if (!Tcl_InterpDeleted(interp)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "unknown subcommand handler deleted its ensemble", -1)); Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "UNKNOWN_DELETED", NULL); |
︙ | ︙ | |||
2170 2171 2172 2173 2174 2175 2176 | Tcl_AppendToObj(Tcl_GetObjResult(interp), "continue", -1); break; default: Tcl_AppendPrintfToObj(Tcl_GetObjResult(interp), "%d", result); } Tcl_AddErrorInfo(interp, "\n result of " "ensemble unknown subcommand handler: "); | | | 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 | Tcl_AppendToObj(Tcl_GetObjResult(interp), "continue", -1); break; default: Tcl_AppendPrintfToObj(Tcl_GetObjResult(interp), "%d", result); } Tcl_AddErrorInfo(interp, "\n result of " "ensemble unknown subcommand handler: "); Tcl_AppendObjToErrorInfo(interp, unknownCmd); Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "UNKNOWN_RESULT", NULL); } else { Tcl_AddErrorInfo(interp, "\n (ensemble unknown subcommand handler)"); } } |
︙ | ︙ | |||
2727 2728 2729 2730 2731 2732 2733 | Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { | | > < > | > > | > | > > | > > > | < | | | | 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 | Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr); Tcl_Obj *mapObj, *subcmdObj, *targetCmdObj, *listObj, **elems; Tcl_Obj *replaced = Tcl_NewObj(), *replacement; Tcl_Command ensemble = (Tcl_Command) cmdPtr; Command *oldCmdPtr = cmdPtr, *newCmdPtr; int len, result, flags = 0, i, depth = 1, invokeAnyway = 0; int ourResult = TCL_ERROR; unsigned numBytes; const char *word; Tcl_IncrRefCount(replaced); /* * This is where we return to if we are parsing multiple nested compiled * ensembles. [info object] is such a beast. */ checkNextWord: if (parsePtr->numWords < depth + 1) { goto failed; } if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { /* * Too hard. */ goto failed; } word = tokenPtr[1].start; numBytes = tokenPtr[1].size; /* * There's a sporting chance we'll be able to compile this. But now we * must check properly. To do that, check that we're compiling an ensemble * that has a compilable command as its appropriate subcommand. */ if (Tcl_GetEnsembleMappingDict(NULL, ensemble, &mapObj) != TCL_OK || mapObj == NULL) { /* * Either not an ensemble or a mapping isn't installed. Crud. Too hard * to proceed. */ goto failed; } /* * Also refuse to compile anything that uses a formal parameter list for * now, on the grounds that it is too complex. */ if (Tcl_GetEnsembleParameterList(NULL, ensemble, &listObj) != TCL_OK || listObj != NULL) { /* * Figuring out how to compile this has become too much. Bail out. */ goto failed; } /* * Next, get the flags. We need them on several code paths so that we can * know whether we're to do prefix matching. */ |
︙ | ︙ | |||
2801 2802 2803 2804 2805 2806 2807 | (void) Tcl_GetEnsembleSubcommandList(NULL, ensemble, &listObj); if (listObj != NULL) { int sclen; const char *str; Tcl_Obj *matchObj = NULL; if (Tcl_ListObjGetElements(NULL, listObj, &len, &elems) != TCL_OK) { | | | > | | | > < > > | > > | > > > | > > > > > | < < > > | | | | > > > > | > > > > | > > > > | > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | > > > > > > > > > > > > > > > > > > > | | | | | | | | < < | | | > | > | > < | | | | < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 | (void) Tcl_GetEnsembleSubcommandList(NULL, ensemble, &listObj); if (listObj != NULL) { int sclen; const char *str; Tcl_Obj *matchObj = NULL; if (Tcl_ListObjGetElements(NULL, listObj, &len, &elems) != TCL_OK) { goto failed; } for (i=0 ; i<len ; i++) { str = Tcl_GetStringFromObj(elems[i], &sclen); if ((sclen == (int) numBytes) && !memcmp(word, str, numBytes)) { /* * Exact match! Excellent! */ result = Tcl_DictObjGet(NULL, mapObj,elems[i], &targetCmdObj); if (result != TCL_OK || targetCmdObj == NULL) { goto failed; } replacement = elems[i]; goto doneMapLookup; } /* * Check to see if we've got a prefix match. A single prefix match * is fine, and allows us to refine our dictionary lookup, but * multiple prefix matches is a Bad Thing and will prevent us from * making progress. Note that we cannot do the lookup immediately * in the prefix case; might be another entry later in the list * that causes things to fail. */ if ((flags & TCL_ENSEMBLE_PREFIX) && strncmp(word, str, numBytes) == 0) { if (matchObj != NULL) { goto failed; } matchObj = elems[i]; } } if (matchObj == NULL) { goto failed; } result = Tcl_DictObjGet(NULL, mapObj, matchObj, &targetCmdObj); if (result != TCL_OK || targetCmdObj == NULL) { goto failed; } replacement = matchObj; } else { Tcl_DictSearch s; int done, matched; Tcl_Obj *tmpObj; /* * No map, so check the dictionary directly. */ TclNewStringObj(subcmdObj, word, (int) numBytes); result = Tcl_DictObjGet(NULL, mapObj, subcmdObj, &targetCmdObj); if (result == TCL_OK && targetCmdObj != NULL) { /* * Got it. Skip the fiddling around with prefixes. */ replacement = subcmdObj; goto doneMapLookup; } TclDecrRefCount(subcmdObj); /* * We've not literally got a valid subcommand. But maybe we have a * prefix. Check if prefix matches are allowed. */ if (!(flags & TCL_ENSEMBLE_PREFIX)) { goto failed; } /* * Iterate over the keys in the dictionary, checking to see if we're a * prefix. */ Tcl_DictObjFirst(NULL, mapObj, &s, &subcmdObj, &tmpObj, &done); matched = 0; replacement = NULL; /* Silence, fool compiler! */ while (!done) { if (strncmp(TclGetString(subcmdObj), word, numBytes) == 0) { if (matched++) { /* * Must have matched twice! Not unique, so no point * looking further. */ break; } replacement = subcmdObj; targetCmdObj = tmpObj; } Tcl_DictObjNext(&s, &subcmdObj, &tmpObj, &done); } Tcl_DictObjDone(&s); /* * If we have anything other than a single match, we've failed the * unique prefix check. */ if (matched != 1) { invokeAnyway = 1; goto failed; } } /* * OK, we definitely map to something. But what? * * The command we map to is the first word out of the map element. Note * that we also reject dealing with multi-element rewrites if we are in a * safe interpreter, as there is otherwise a (highly gnarly!) way to make * Tcl crash open to exploit. */ doneMapLookup: Tcl_ListObjAppendElement(NULL, replaced, replacement); if (Tcl_ListObjGetElements(NULL, targetCmdObj, &len, &elems) != TCL_OK) { goto failed; } else if (len != 1) { /* * Note that at this point we know we can't issue any special * instruction sequence as the mapping isn't one that we support at * the compiled level. */ goto cleanup; } targetCmdObj = elems[0]; oldCmdPtr = cmdPtr; Tcl_IncrRefCount(targetCmdObj); newCmdPtr = (Command *) Tcl_GetCommandFromObj(interp, targetCmdObj); TclDecrRefCount(targetCmdObj); if (newCmdPtr == NULL || Tcl_IsSafe(interp) || newCmdPtr->nsPtr->flags & NS_SUPPRESS_COMPILATION || newCmdPtr->flags & CMD_HAS_EXEC_TRACES || ((Interp *)interp)->flags & DONT_COMPILE_CMDS_INLINE) { /* * Maps to an undefined command or a command without a compiler. * Cannot compile. */ goto cleanup; } cmdPtr = newCmdPtr; depth++; /* * See whether we have a nested ensemble. If we do, we can go round the * mulberry bush again, consuming the next word. */ if (cmdPtr->compileProc == TclCompileEnsemble) { tokenPtr = TokenAfter(tokenPtr); ensemble = (Tcl_Command) cmdPtr; goto checkNextWord; } /* * Now we've done the mapping process, can now actually try to compile. * If there is a subcommand compiler and that successfully produces code, * we'll use that. Otherwise, we fall back to generating opcodes to do the * invoke at runtime. */ invokeAnyway = 1; if (CompileToCompiledCommand(interp, parsePtr, depth, cmdPtr, envPtr) == TCL_OK) { ourResult = TCL_OK; goto cleanup; } /* * Failed to do a full compile for some reason. Try to do a direct invoke * instead of going through the ensemble lookup process again. */ failed: if (depth < 250) { if (depth > 1) { if (!invokeAnyway) { cmdPtr = oldCmdPtr; depth--; } (void) Tcl_ListObjReplace(NULL, replaced, depth, 2, 0, NULL); } CompileToInvokedCommand(interp, parsePtr, replaced, cmdPtr, envPtr); ourResult = TCL_OK; } /* * Release the memory we allocated. If we've got here, we've either done * something useful or we're in a case that we can't compile at all and * we're just giving up. */ cleanup: Tcl_DecrRefCount(replaced); return ourResult; } /* * How to compile a subcommand using its own command compiler. To do that, we * have to perform some trickery to rewrite the arguments, as compilers *must* * have parse tokens that refer to addresses in the original script. */ static int CompileToCompiledCommand( Tcl_Interp *interp, Tcl_Parse *parsePtr, int depth, Command *cmdPtr, CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Parse synthetic; Tcl_Token *tokenPtr; int result, i; int savedNumCmds = envPtr->numCommands; int savedStackDepth = envPtr->currStackDepth; unsigned savedCodeNext = envPtr->codeNext - envPtr->codeStart; if (cmdPtr->compileProc == NULL) { return TCL_ERROR; } TclParseInit(interp, NULL, 0, &synthetic); synthetic.numWords = parsePtr->numWords - depth + 1; TclGrowParseTokenArray(&synthetic, 2); synthetic.numTokens = 2; /* * Now we have the space to work in, install something rewritten. The * first word will "officially" be the bytes of the structured ensemble * name. That's technically wrong, but nobody will care; we just need * *something* here... */ synthetic.tokenPtr[0].type = TCL_TOKEN_SIMPLE_WORD; synthetic.tokenPtr[0].start = parsePtr->tokenPtr[0].start; synthetic.tokenPtr[0].numComponents = 1; synthetic.tokenPtr[1].type = TCL_TOKEN_TEXT; synthetic.tokenPtr[1].start = parsePtr->tokenPtr[0].start; synthetic.tokenPtr[1].numComponents = 0; for (i=0,tokenPtr=parsePtr->tokenPtr ; i<depth ; i++) { int sclen = (tokenPtr->start - synthetic.tokenPtr[0].start) + tokenPtr->size; synthetic.tokenPtr[0].size = sclen; synthetic.tokenPtr[1].size = sclen; tokenPtr = TokenAfter(tokenPtr); } /* * Copy over the real argument tokens. */ for (i=1; i<synthetic.numWords; i++) { int toCopy; toCopy = tokenPtr->numComponents + 1; TclGrowParseTokenArray(&synthetic, toCopy); memcpy(synthetic.tokenPtr + synthetic.numTokens, tokenPtr, sizeof(Tcl_Token) * toCopy); synthetic.numTokens += toCopy; tokenPtr = TokenAfter(tokenPtr); } /* * Hand off compilation to the subcommand compiler. At last! */ result = cmdPtr->compileProc(interp, &synthetic, cmdPtr, envPtr); /* * If our target fails to compile, revert the number of commands and the * pointer to the place to issue the next instruction. [Bug 3600328] */ if (result != TCL_OK) { envPtr->numCommands = savedNumCmds; envPtr->currStackDepth = savedStackDepth; envPtr->codeNext = envPtr->codeStart + savedCodeNext; } /* * Clean up if necessary. */ Tcl_FreeParse(&synthetic); return result; } /* * How to compile a subcommand to a _replacing_ invoke of its implementation * command. */ static void CompileToInvokedCommand( Tcl_Interp *interp, Tcl_Parse *parsePtr, Tcl_Obj *replacements, Command *cmdPtr, CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokPtr; Tcl_Obj *objPtr, **words; char *bytes; int length, i, numWords, cmdLit; DefineLineInformation; /* * Push the words of the command. Take care; the command words may be * scripts that have backslashes in them, and [info frame 0] can see the * difference. Hence the call to TclContinuationsEnterDerived... */ Tcl_ListObjGetElements(NULL, replacements, &numWords, &words); for (i=0,tokPtr=parsePtr->tokenPtr ; i<parsePtr->numWords ; i++) { if (i > 0 && i < numWords+1) { bytes = Tcl_GetStringFromObj(words[i-1], &length); PushLiteral(envPtr, bytes, length); } else if (tokPtr->type == TCL_TOKEN_SIMPLE_WORD) { int literal = TclRegisterNewLiteral(envPtr, tokPtr[1].start, tokPtr[1].size); if (envPtr->clNext) { TclContinuationsEnterDerived( envPtr->literalArrayPtr[literal].objPtr, tokPtr[1].start - envPtr->source, mapPtr->loc[eclIndex].next[i]); } TclEmitPush(literal, envPtr); } else { if (envPtr->clNext) { SetLineInformation(i); } CompileTokens(envPtr, tokPtr, interp); } tokPtr = TokenAfter(tokPtr); } /* * Push the name of the command we're actually dispatching to as part of * the implementation. */ objPtr = Tcl_NewObj(); Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr, objPtr); bytes = Tcl_GetStringFromObj(objPtr, &length); cmdLit = TclRegisterNewCmdLiteral(envPtr, bytes, length); TclSetCmdNameObj(interp, envPtr->literalArrayPtr[cmdLit].objPtr, cmdPtr); TclEmitPush(cmdLit, envPtr); TclDecrRefCount(objPtr); /* * Do the replacing dispatch. */ OP41( INVOKE_REPLACE, parsePtr->numWords, numWords+1); TclAdjustStackDepth(-1, envPtr); /* Correction to stack depth calcs. */ } /* * Helpers that do issuing of instructions for commands that "don't have * compilers" (well, they do; these). They all work by just generating base * code to invoke the command; they're intended for ensemble subcommands so * that the costs of INST_INVOKE_REPLACE can be avoided where we can work out * that they're not needed. * * Note that these are NOT suitable for commands where there's an argument * that is a script, as an [info level] or [info frame] in the inner context * can see the difference. */ static int CompileBasicNArgCommand( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { Tcl_Token *tokenPtr; Tcl_Obj *objPtr; char *bytes; int length, i, literal; DefineLineInformation; /* * Push the name of the command we're actually dispatching to as part of * the implementation. */ objPtr = Tcl_NewObj(); Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr, objPtr); bytes = Tcl_GetStringFromObj(objPtr, &length); literal = TclRegisterNewCmdLiteral(envPtr, bytes, length); TclSetCmdNameObj(interp, envPtr->literalArrayPtr[literal].objPtr, cmdPtr); TclEmitPush(literal, envPtr); TclDecrRefCount(objPtr); /* * Push the words of the command. */ tokenPtr = TokenAfter(parsePtr->tokenPtr); for (i=1 ; i<parsePtr->numWords ; i++) { if (envPtr->clNext) { SetLineInformation(i); } if (tokenPtr->type == TCL_TOKEN_SIMPLE_WORD) { PushLiteral(envPtr, tokenPtr[1].start, tokenPtr[1].size); } else { CompileTokens(envPtr, tokenPtr, interp); } tokenPtr = TokenAfter(tokenPtr); } /* * Do the standard dispatch. */ OP4( INVOKE_STK, i); return TCL_OK; } int TclCompileBasic0ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ if (parsePtr->numWords != 1) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } int TclCompileBasic1ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ if (parsePtr->numWords != 2) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } int TclCompileBasic2ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ if (parsePtr->numWords != 3) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } int TclCompileBasic3ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ if (parsePtr->numWords != 4) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } int TclCompileBasic0Or1ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ if (parsePtr->numWords != 1 && parsePtr->numWords != 2) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } int TclCompileBasic1Or2ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ if (parsePtr->numWords != 2 && parsePtr->numWords != 3) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } int TclCompileBasic2Or3ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ if (parsePtr->numWords != 3 && parsePtr->numWords != 4) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } int TclCompileBasic0To2ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ if (parsePtr->numWords < 1 || parsePtr->numWords > 3) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } int TclCompileBasic1To3ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ if (parsePtr->numWords < 2 || parsePtr->numWords > 4) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } int TclCompileBasicMin0ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ if (parsePtr->numWords < 1) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } int TclCompileBasicMin1ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ if (parsePtr->numWords < 2) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } int TclCompileBasicMin2ArgCmd( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command * created by Tcl_ParseCommand. */ Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) /* Holds resulting instructions. */ { /* * Verify that the number of arguments is correct; that's the only case * that we know will avoid the call to Tcl_WrongNumArgs() at invoke time, * which is the only code that sees the shenanigans of ensemble dispatch. */ if (parsePtr->numWords < 3) { return TCL_ERROR; } return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ |
Changes to generic/tclExecute.c.
︙ | ︙ | |||
129 130 131 132 133 134 135 | } TEBCdata; #define TEBC_YIELD() \ do { \ esPtr->tosPtr = tosPtr; \ TD->pc = pc; \ TD->cleanup = cleanup; \ | | | 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | } TEBCdata; #define TEBC_YIELD() \ do { \ esPtr->tosPtr = tosPtr; \ TD->pc = pc; \ TD->cleanup = cleanup; \ TclNRAddCallback(interp, ExecuteByteCode, TD, INT2PTR(1),NULL,NULL); \ } while (0) #define TEBC_DATA_DIG() \ do { \ pc = TD->pc; \ cleanup = TD->cleanup; \ tosPtr = esPtr->tosPtr; \ |
︙ | ︙ | |||
190 191 192 193 194 195 196 | * ARGUMENTS: * pcAdjustment: how much to increment pc * nCleanup: how many objects to remove from the stack * resultHandling: 0 indicates no object should be pushed on the stack; * otherwise, push objResultPtr. If (result < 0), objResultPtr already * has the correct reference count. * | | > > > > > > > > > > > > > | > | 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 | * ARGUMENTS: * pcAdjustment: how much to increment pc * nCleanup: how many objects to remove from the stack * resultHandling: 0 indicates no object should be pushed on the stack; * otherwise, push objResultPtr. If (result < 0), objResultPtr already * has the correct reference count. * * We use the new compile-time assertions to check that nCleanup is constant * and within range. */ /* Verify the stack depth, only when no expansion is in progress */ #if TCL_COMPILE_DEBUG #define CHECK_STACK() \ do { \ ValidatePcAndStackTop(codePtr, pc, CURR_DEPTH, \ /*checkStack*/ !(starting || auxObjList)); \ starting = 0; \ } while (0) #else #define CHECK_STACK() #endif #define NEXT_INST_F(pcAdjustment, nCleanup, resultHandling) \ do { \ TCL_CT_ASSERT((nCleanup >= 0) && (nCleanup <= 2)); \ CHECK_STACK(); \ if (nCleanup == 0) { \ if (resultHandling != 0) { \ if ((resultHandling) > 0) { \ PUSH_OBJECT(objResultPtr); \ } else { \ *(++tosPtr) = objResultPtr; \ } \ |
︙ | ︙ | |||
225 226 227 228 229 230 231 | switch (nCleanup) { \ case 1: goto cleanup1; \ case 2: goto cleanup2; \ } \ } \ } while (0) | | > | | | | | | 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 | switch (nCleanup) { \ case 1: goto cleanup1; \ case 2: goto cleanup2; \ } \ } \ } while (0) #define NEXT_INST_V(pcAdjustment, nCleanup, resultHandling) \ CHECK_STACK(); \ do { \ pc += (pcAdjustment); \ cleanup = (nCleanup); \ if (resultHandling) { \ if ((resultHandling) > 0) { \ Tcl_IncrRefCount(objResultPtr); \ } \ goto cleanupV_pushObjResultPtr; \ } else { \ goto cleanupV; \ } \ } while (0) /* * Macros used to cache often-referenced Tcl evaluation stack information in * local variables. Note that a DECACHE_STACK_INFO()-CACHE_STACK_INFO() pair * must surround any call inside ExecuteByteCode (and a few other procedures * that use this scheme) that could result in a recursive call to * ExecuteByteCode. */ #define CACHE_STACK_INFO() \ checkInterp = 1 #define DECACHE_STACK_INFO() \ esPtr->tosPtr = tosPtr |
︙ | ︙ | |||
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | * before the caller had a chance to, e.g., store it in a variable. It is the * caller's responsibility to decrement the ref count when it is finished with * an object. * * WARNING! It is essential that objPtr only appear once in the PUSH_OBJECT * macro. The actual parameter might be an expression with side effects, and * this ensures that it will be executed only once. */ #define PUSH_OBJECT(objPtr) \ Tcl_IncrRefCount(*(++tosPtr) = (objPtr)) #define POP_OBJECT() *(tosPtr--) #define OBJ_AT_TOS *tosPtr #define OBJ_UNDER_TOS *(tosPtr-1) #define OBJ_AT_DEPTH(n) *(tosPtr-(n)) | > > > > > > > | 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 | * before the caller had a chance to, e.g., store it in a variable. It is the * caller's responsibility to decrement the ref count when it is finished with * an object. * * WARNING! It is essential that objPtr only appear once in the PUSH_OBJECT * macro. The actual parameter might be an expression with side effects, and * this ensures that it will be executed only once. * * For actually discarding an object from the stack, use POP_DROP_OBJECT(). */ #define PUSH_OBJECT(objPtr) \ Tcl_IncrRefCount(*(++tosPtr) = (objPtr)) #define POP_OBJECT() *(tosPtr--) #define POP_DROP_OBJECT() \ do { \ register Tcl_Obj *discardPtr = POP_OBJECT(); \ TclDecrRefCount(discardPtr); \ } while (0) #define OBJ_AT_TOS *tosPtr #define OBJ_UNDER_TOS *(tosPtr-1) #define OBJ_AT_DEPTH(n) *(tosPtr-(n)) |
︙ | ︙ | |||
614 615 616 617 618 619 620 | #define GENERAL_ARITHMETIC_ERROR ((Tcl_Obj *) -3) /* * Declarations for local procedures to this file: */ #ifdef TCL_COMPILE_STATS | | < < | | 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 | #define GENERAL_ARITHMETIC_ERROR ((Tcl_Obj *) -3) /* * Declarations for local procedures to this file: */ #ifdef TCL_COMPILE_STATS static Tcl_ObjCmdProc EvalStatsCmd; #endif /* TCL_COMPILE_STATS */ #ifdef TCL_COMPILE_DEBUG static const char * GetOpcodeName(const unsigned char *pc); static void PrintByteCodeInfo(ByteCode *codePtr); static const char * StringForResultCode(int result); static void ValidatePcAndStackTop(ByteCode *codePtr, const unsigned char *pc, int stackTop, int checkStack); #endif /* TCL_COMPILE_DEBUG */ static ByteCode * CompileExprObj(Tcl_Interp *interp, Tcl_Obj *objPtr); static void DeleteExecStack(ExecStack *esPtr); static void DupExprCodeInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); MODULE_SCOPE int TclCompareTwoNumbers(Tcl_Obj *valuePtr, Tcl_Obj *value2Ptr); |
︙ | ︙ | |||
655 656 657 658 659 660 661 | static inline int OFFSET(void *ptr); static void ReleaseDictIterator(Tcl_Obj *objPtr); /* Useful elsewhere, make available in tclInt.h or stubs? */ static Tcl_Obj ** StackAllocWords(Tcl_Interp *interp, int numWords); static Tcl_Obj ** StackReallocWords(Tcl_Interp *interp, int numWords); static Tcl_NRPostProc CopyCallback; static Tcl_NRPostProc ExprObjCallback; | < | | 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 | static inline int OFFSET(void *ptr); static void ReleaseDictIterator(Tcl_Obj *objPtr); /* Useful elsewhere, make available in tclInt.h or stubs? */ static Tcl_Obj ** StackAllocWords(Tcl_Interp *interp, int numWords); static Tcl_Obj ** StackReallocWords(Tcl_Interp *interp, int numWords); static Tcl_NRPostProc CopyCallback; static Tcl_NRPostProc ExprObjCallback; static Tcl_NRPostProc ExecuteByteCode; /* * The structure below defines a bytecode Tcl object type to hold the * compiled bytecode for Tcl expressions. */ static const Tcl_ObjType exprCodeType = { |
︙ | ︙ | |||
987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 | if (!markerPtr) { Tcl_Panic("STACK: Reallocating with no previous alloc"); } if (needed <= 0) { return MEMSTART(markerPtr); } } else { Tcl_Obj **tmpMarkerPtr = esPtr->tosPtr + 1; int offset = OFFSET(tmpMarkerPtr); if (needed + offset < 0) { /* * Put a marker pointing to the previous marker in this stack, and * store it in esPtr as the current marker. Return a pointer to * the start of aligned memory. */ esPtr->markerPtr = tmpMarkerPtr; memStart = tmpMarkerPtr + offset; esPtr->tosPtr = memStart - 1; *esPtr->markerPtr = (Tcl_Obj *) markerPtr; return memStart; } } /* * Reset move to hold the number of words to be moved to new stack (if * any) and growth to hold the complete stack requirements: add one for * the marker, (WALLOCALIGN-1) for the maximal possible offset. */ if (move) { moveWords = esPtr->tosPtr - MEMSTART(markerPtr) + 1; } needed = growth + moveWords + WALLOCALIGN; /* * Check if there is enough room in the next stack (if there is one, it * should be both empty and the last one!) */ if (esPtr->nextPtr) { oldPtr = esPtr; | > > > | 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 | if (!markerPtr) { Tcl_Panic("STACK: Reallocating with no previous alloc"); } if (needed <= 0) { return MEMSTART(markerPtr); } } else { #ifndef PURIFY Tcl_Obj **tmpMarkerPtr = esPtr->tosPtr + 1; int offset = OFFSET(tmpMarkerPtr); if (needed + offset < 0) { /* * Put a marker pointing to the previous marker in this stack, and * store it in esPtr as the current marker. Return a pointer to * the start of aligned memory. */ esPtr->markerPtr = tmpMarkerPtr; memStart = tmpMarkerPtr + offset; esPtr->tosPtr = memStart - 1; *esPtr->markerPtr = (Tcl_Obj *) markerPtr; return memStart; } #endif } /* * Reset move to hold the number of words to be moved to new stack (if * any) and growth to hold the complete stack requirements: add one for * the marker, (WALLOCALIGN-1) for the maximal possible offset. */ if (move) { moveWords = esPtr->tosPtr - MEMSTART(markerPtr) + 1; } needed = growth + moveWords + WALLOCALIGN; /* * Check if there is enough room in the next stack (if there is one, it * should be both empty and the last one!) */ if (esPtr->nextPtr) { oldPtr = esPtr; |
︙ | ︙ | |||
1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 | } /* * We need to allocate a new stack! It needs to store 'growth' words, * including the elements to be copied over and the new marker. */ newElems = 2*currElems; while (needed > newElems) { newElems *= 2; } newBytes = sizeof(ExecStack) + (newElems-1) * sizeof(Tcl_Obj *); oldPtr = esPtr; esPtr = ckalloc(newBytes); oldPtr->nextPtr = esPtr; esPtr->prevPtr = oldPtr; | > > > > > | 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 | } /* * We need to allocate a new stack! It needs to store 'growth' words, * including the elements to be copied over and the new marker. */ #ifndef PURIFY newElems = 2*currElems; while (needed > newElems) { newElems *= 2; } #else newElems = needed; #endif newBytes = sizeof(ExecStack) + (newElems-1) * sizeof(Tcl_Obj *); oldPtr = esPtr; esPtr = ckalloc(newBytes); oldPtr->nextPtr = esPtr; esPtr->prevPtr = oldPtr; |
︙ | ︙ | |||
1151 1152 1153 1154 1155 1156 1157 | { Interp *iPtr = (Interp *) interp; ExecEnv *eePtr; ExecStack *esPtr; Tcl_Obj **markerPtr, *marker; if (iPtr == NULL || iPtr->execEnvPtr == NULL) { | | | 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 | { Interp *iPtr = (Interp *) interp; ExecEnv *eePtr; ExecStack *esPtr; Tcl_Obj **markerPtr, *marker; if (iPtr == NULL || iPtr->execEnvPtr == NULL) { ckfree((char *) freePtr); return; } /* * Rewind the stack to the previous marker position. The current marker, * as set in the last call to GrowEvaluationStack, contains a pointer to * the previous marker. |
︙ | ︙ | |||
1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 | DeleteExecStack(tmpPtr); } else { break; } } if (esPtr->prevPtr) { eePtr->execStackPtr = esPtr->prevPtr; } else { eePtr->execStackPtr = esPtr; } } void * TclStackAlloc( Tcl_Interp *interp, int numBytes) { Interp *iPtr = (Interp *) interp; int numWords = (numBytes + (sizeof(Tcl_Obj *) - 1))/sizeof(Tcl_Obj *); if (iPtr == NULL || iPtr->execEnvPtr == NULL) { | > > > > | | | 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 | DeleteExecStack(tmpPtr); } else { break; } } if (esPtr->prevPtr) { eePtr->execStackPtr = esPtr->prevPtr; #ifdef PURIFY eePtr->execStackPtr->nextPtr = NULL; DeleteExecStack(esPtr); #endif } else { eePtr->execStackPtr = esPtr; } } void * TclStackAlloc( Tcl_Interp *interp, int numBytes) { Interp *iPtr = (Interp *) interp; int numWords = (numBytes + (sizeof(Tcl_Obj *) - 1))/sizeof(Tcl_Obj *); if (iPtr == NULL || iPtr->execEnvPtr == NULL) { return (void *) ckalloc(numBytes); } return (void *) StackAllocWords(interp, numWords); } void * TclStackRealloc( Tcl_Interp *interp, void *ptr, int numBytes) { Interp *iPtr = (Interp *) interp; ExecEnv *eePtr; ExecStack *esPtr; Tcl_Obj **markerPtr; int numWords; if (iPtr == NULL || iPtr->execEnvPtr == NULL) { return (void *) ckrealloc((char *) ptr, numBytes); } eePtr = iPtr->execEnvPtr; esPtr = eePtr->execStackPtr; markerPtr = esPtr->markerPtr; if (MEMSTART(markerPtr) != (Tcl_Obj **)ptr) { |
︙ | ︙ | |||
1931 1932 1933 1934 1935 1936 1937 | iPtr->stats.numExecutions++; #endif /* * Push the callback for bytecode execution */ | | | | 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 | iPtr->stats.numExecutions++; #endif /* * Push the callback for bytecode execution */ TclNRAddCallback(interp, ExecuteByteCode, TD, /*resume*/ INT2PTR(0), NULL, NULL); return TCL_OK; } static int ExecuteByteCode( ClientData data[], Tcl_Interp *interp, int result) { /* * Compiler cast directive - not a real variable. * Interp *iPtr = (Interp *) interp; |
︙ | ︙ | |||
1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 | #endif Var *compiledLocals = iPtr->varFramePtr->compiledLocals; Tcl_Obj **constants = &iPtr->execEnvPtr->constants[0]; #define LOCAL(i) (&compiledLocals[(i)]) #define TCONST(i) (constants[(i)]) /* * These macros are just meant to save some global variables that are not * used too frequently */ TEBCdata *TD = data[0]; | > > > > > > > > | 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 | #endif Var *compiledLocals = iPtr->varFramePtr->compiledLocals; Tcl_Obj **constants = &iPtr->execEnvPtr->constants[0]; #define LOCAL(i) (&compiledLocals[(i)]) #define TCONST(i) (constants[(i)]) #define LOCALVAR(varPtr,i) \ do { \ register Var *vPtr = LOCAL(i); \ while (TclIsVarLink(vPtr)) { \ vPtr = vPtr->value.linkPtr; \ } \ (varPtr) = vPtr; \ } while (0) /* * These macros are just meant to save some global variables that are not * used too frequently */ TEBCdata *TD = data[0]; |
︙ | ︙ | |||
1999 2000 2001 2002 2003 2004 2005 | /* * Globals: variables that store state, must remain valid at all times. */ Tcl_Obj **tosPtr; /* Cached pointer to top of evaluation * stack. */ const unsigned char *pc; /* The current program counter. */ | > | | 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 | /* * Globals: variables that store state, must remain valid at all times. */ Tcl_Obj **tosPtr; /* Cached pointer to top of evaluation * stack. */ const unsigned char *pc; /* The current program counter. */ unsigned char inst; /* The currently running instruction */ /* * Transfer variables - needed only between opcodes, but not while * executing an instruction. */ int cleanup = 0; Tcl_Obj *objResultPtr; |
︙ | ︙ | |||
2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 | int opnd, length, pcAdjustment; Var *varPtr, *arrayPtr; #ifdef TCL_COMPILE_DEBUG char cmdNameBuf[21]; #endif #ifdef TCL_COMPILE_DEBUG traceInstructions = (tclTraceExec == 3); #endif TEBC_DATA_DIG(); #ifdef TCL_COMPILE_DEBUG if (!data[1] && (tclTraceExec >= 2)) { | > | 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 | int opnd, length, pcAdjustment; Var *varPtr, *arrayPtr; #ifdef TCL_COMPILE_DEBUG char cmdNameBuf[21]; #endif #ifdef TCL_COMPILE_DEBUG int starting = 1; traceInstructions = (tclTraceExec == 3); #endif TEBC_DATA_DIG(); #ifdef TCL_COMPILE_DEBUG if (!data[1] && (tclTraceExec >= 2)) { |
︙ | ︙ | |||
2124 2125 2126 2127 2128 2129 2130 | switch (cleanup) { case 0: *(++tosPtr) = (objResultPtr); goto cleanup0; default: cleanup -= 2; while (cleanup--) { | | < | < | < | < | < < < < < < < < < < < < < < < < < < < | 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 | switch (cleanup) { case 0: *(++tosPtr) = (objResultPtr); goto cleanup0; default: cleanup -= 2; while (cleanup--) { POP_DROP_OBJECT(); } case 2: cleanup2_pushObjResultPtr: POP_DROP_OBJECT(); case 1: cleanup1_pushObjResultPtr: objPtr = OBJ_AT_TOS; TclDecrRefCount(objPtr); } OBJ_AT_TOS = objResultPtr; goto cleanup0; cleanupV: switch (cleanup) { default: cleanup -= 2; while (cleanup--) { POP_DROP_OBJECT(); } case 2: cleanup2: POP_DROP_OBJECT(); case 1: cleanup1: POP_DROP_OBJECT(); case 0: /* * We really want to do nothing now, but this is needed for some * compilers (SunPro CC). */ break; } cleanup0: /* * Check for asynchronous handlers [Bug 746722]; we do the check every * ASYNC_CHECK_COUNT_MASK instruction, of the form (2**n-1). */ if ((instructionCount++ & ASYNC_CHECK_COUNT_MASK) == 0) { DECACHE_STACK_INFO(); |
︙ | ︙ | |||
2214 2215 2216 2217 2218 2219 2220 | CACHE_STACK_INFO(); goto gotError; } } CACHE_STACK_INFO(); } | < < > > > > > > > > > > > > > > > > > > > > > > | | > > > > > > > > > > > > > > | | | > > > > | | 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 | CACHE_STACK_INFO(); goto gotError; } } CACHE_STACK_INFO(); } /* * These two instructions account for 26% of all instructions (according * to measurements on tclbench by Ben Vitale * [http://www.cs.toronto.edu/syslab/pubs/tcl2005-vitale-zaleski.pdf] * Resolving them before the switch reduces the cost of branch * mispredictions, seems to improve runtime by 5% to 15%, and (amazingly!) * reduces total obj size. */ inst = *pc; peepholeStart: #ifdef TCL_COMPILE_STATS iPtr->stats.instructionCount[*pc]++; #endif #ifdef TCL_COMPILE_DEBUG /* * Skip the stack depth check if an expansion is in progress. */ CHECK_STACK(); if (traceInstructions) { fprintf(stdout, "%2d: %2d ", iPtr->numLevels, (int) CURR_DEPTH); TclPrintInstruction(codePtr, pc); fflush(stdout); } #endif /* TCL_COMPILE_DEBUG */ TCL_DTRACE_INST_NEXT(); if (inst == INST_LOAD_SCALAR) { goto instLoadScalar; } else if (inst == INST_PUSH) { PUSH_OBJECT(codePtr->objArrayPtr[TclGetUInt4AtPtr(pc+1)]); TRACE_WITH_OBJ(("%u => ", TclGetInt4AtPtr(pc+1)), OBJ_AT_TOS); inst = *(pc += 5); goto peepholeStart; } else if (inst == INST_START_CMD) { /* * Peephole: do not run INST_START_CMD, just skip it */ iPtr->cmdCount += TclGetUInt4AtPtr(pc+5); if (checkInterp) { checkInterp = 0; if ((codePtr->compileEpoch != iPtr->compileEpoch) || (codePtr->nsEpoch != iPtr->varFramePtr->nsPtr->resolverEpoch)) { goto instStartCmdFailed; } } inst = *(pc += 9); goto peepholeStart; } switch (inst) { case INST_SYNTAX: case INST_RETURN_IMM: { int code = TclGetInt4AtPtr(pc+1); int level = TclGetUInt4AtPtr(pc+5); /* * OBJ_AT_TOS is returnOpts, OBJ_UNDER_TOS is resultObjPtr. |
︙ | ︙ | |||
2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 | TRACE_APPEND(("ERROR: yield outside coroutine\n")); Tcl_SetObjResult(interp, Tcl_NewStringObj( "yield can only be called in a coroutine", -1)); Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ILLEGAL_YIELD", NULL); goto gotError; } #ifdef TCL_COMPILE_DEBUG TRACE_WITH_OBJ(("yield, result="), iPtr->objResultPtr); if (traceInstructions) { fprintf(stdout, "\n"); } #endif | > | 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 | TRACE_APPEND(("ERROR: yield outside coroutine\n")); Tcl_SetObjResult(interp, Tcl_NewStringObj( "yield can only be called in a coroutine", -1)); Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ILLEGAL_YIELD", NULL); goto gotError; } NRE_ASSERT(!COR_IS_SUSPENDED(corPtr)); #ifdef TCL_COMPILE_DEBUG TRACE_WITH_OBJ(("yield, result="), iPtr->objResultPtr); if (traceInstructions) { fprintf(stdout, "\n"); } #endif |
︙ | ︙ | |||
2315 2316 2317 2318 2319 2320 2321 | INT2PTR(0), NULL, NULL); return TCL_OK; } case INST_TAILCALL: { Tcl_Obj *listPtr, *nsObjPtr; | < | 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 | INT2PTR(0), NULL, NULL); return TCL_OK; } case INST_TAILCALL: { Tcl_Obj *listPtr, *nsObjPtr; opnd = TclGetUInt1AtPtr(pc+1); if (!(iPtr->varFramePtr->isProcCallFrame & 1)) { TRACE(("%d => ERROR: tailcall in non-proc context\n", opnd)); Tcl_SetObjResult(interp, Tcl_NewStringObj( "tailcall can only be called from a proc or lambda", -1)); |
︙ | ︙ | |||
2349 2350 2351 2352 2353 2354 2355 | /* * Push the evaluation of the called command into the NR callback * stack. */ listPtr = Tcl_NewListObj(opnd, &OBJ_AT_DEPTH(opnd-1)); nsObjPtr = Tcl_NewStringObj(iPtr->varFramePtr->nsPtr->fullName, -1); | < | | < | < < < | < < | > | 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 | /* * Push the evaluation of the called command into the NR callback * stack. */ listPtr = Tcl_NewListObj(opnd, &OBJ_AT_DEPTH(opnd-1)); nsObjPtr = Tcl_NewStringObj(iPtr->varFramePtr->nsPtr->fullName, -1); TclListObjSetElement(interp, listPtr, 0, nsObjPtr); if (iPtr->varFramePtr->tailcallPtr) { Tcl_DecrRefCount(iPtr->varFramePtr->tailcallPtr); } iPtr->varFramePtr->tailcallPtr = listPtr; result = TCL_RETURN; cleanup = opnd; goto processExceptionReturn; } case INST_DONE: if (tosPtr > initTosPtr) { |
︙ | ︙ | |||
2388 2389 2390 2391 2392 2393 2394 | } #endif goto checkForCatch; } (void) POP_OBJECT(); goto abnormalReturn; | < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < | | < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < | > > > < > > > > > > > > > > > > > | 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 | } #endif goto checkForCatch; } (void) POP_OBJECT(); goto abnormalReturn; case INST_POP: TRACE_WITH_OBJ(("=> discarding "), OBJ_AT_TOS); POP_DROP_OBJECT(); NEXT_INST_F(1, 0, 0); case INST_NOP: NEXT_INST_F(1, 0, 0); case INST_DUP: objResultPtr = OBJ_AT_TOS; TRACE_WITH_OBJ(("=> "), objResultPtr); NEXT_INST_F(1, 0, 1); case INST_UNDER: objResultPtr = OBJ_UNDER_TOS; TRACE_WITH_OBJ(("=> "), objResultPtr); NEXT_INST_F(1, 0, 1); case INST_OVER: opnd = TclGetUInt4AtPtr(pc+1); objResultPtr = OBJ_AT_DEPTH(opnd); TRACE_WITH_OBJ(("=> "), objResultPtr); NEXT_INST_F(5, 0, 1); { Tcl_Obj **a, **b; case INST_EXCH: TRACE(("\"%.20s\" \"%.20s\" => ", O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS))); tmpPtr = OBJ_AT_TOS; OBJ_AT_TOS = OBJ_UNDER_TOS; OBJ_UNDER_TOS = tmpPtr; TRACE_APPEND(("\"%.20s\" \"%.20s\"", O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS))); NEXT_INST_F(1, 0, 0); case INST_REVERSE: opnd = TclGetUInt4AtPtr(pc+1); TRACE(("%u\n", opnd)); a = tosPtr-(opnd-1); b = tosPtr; while (a<b) { tmpPtr = *a; *a = *b; *b = tmpPtr; a++; b--; |
︙ | ︙ | |||
2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 | DECACHE_STACK_INFO(); pc += pcAdjustment; TEBC_YIELD(); return TclNREvalObjv(interp, objc, objv, TCL_EVAL_NOERR, NULL); /* * ----------------------------------------------------------------- * Start of INST_LOAD instructions. * * WARNING: more 'goto' here than your doctor recommended! The different * instructions set the value of some variables and then jump to some * common execution code. */ case INST_LOAD_SCALAR: instLoadScalar: opnd = TclGetUInt4AtPtr(pc+1); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < < < | < < < | 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 | DECACHE_STACK_INFO(); pc += pcAdjustment; TEBC_YIELD(); return TclNREvalObjv(interp, objc, objv, TCL_EVAL_NOERR, NULL); case INST_INVOKE_REPLACE: objc = TclGetUInt4AtPtr(pc+1); opnd = TclGetUInt1AtPtr(pc+5); objPtr = POP_OBJECT(); objv = &OBJ_AT_DEPTH(objc-1); cleanup = objc; #ifdef TCL_COMPILE_DEBUG if (tclTraceExec >= 2) { int i; if (traceInstructions) { strncpy(cmdNameBuf, TclGetString(objv[0]), 20); TRACE(("%u => call (implementation %s) ", objc, O2S(objPtr))); } else { fprintf(stdout, "%d: (%u) invoking (using implementation %s) ", iPtr->numLevels, (unsigned)(pc - codePtr->codeStart), O2S(objPtr)); } for (i = 0; i < objc; i++) { if (i < opnd) { fprintf(stdout, "<"); TclPrintObject(stdout, objv[i], 15); fprintf(stdout, ">"); } else { TclPrintObject(stdout, objv[i], 15); } fprintf(stdout, " "); } fprintf(stdout, "\n"); fflush(stdout); } #endif /*TCL_COMPILE_DEBUG*/ { Tcl_Obj *copyPtr = Tcl_NewListObj(objc - opnd + 1, NULL); register List *listRepPtr = copyPtr->internalRep.twoPtrValue.ptr1; Tcl_Obj **copyObjv = &listRepPtr->elements; int i; listRepPtr->elemCount = objc - opnd + 1; copyObjv[0] = objPtr; memcpy(copyObjv+1, objv+opnd, sizeof(Tcl_Obj *) * (objc - opnd)); for (i=1 ; i<objc-opnd+1 ; i++) { Tcl_IncrRefCount(copyObjv[i]); } objPtr = copyPtr; } bcFramePtr->data.tebc.pc = (char *) pc; iPtr->cmdFramePtr = bcFramePtr; if (iPtr->flags & INTERP_DEBUG_FRAME) { TclArgumentBCEnter((Tcl_Interp *) iPtr, objv, objc, codePtr, bcFramePtr, pc - codePtr->codeStart); } iPtr->ensembleRewrite.sourceObjs = objv; iPtr->ensembleRewrite.numRemovedObjs = opnd; iPtr->ensembleRewrite.numInsertedObjs = 1; DECACHE_STACK_INFO(); pc += 6; TEBC_YIELD(); TclNRAddCallback(interp, TclClearRootEnsemble, NULL,NULL,NULL,NULL); TclSkipTailcall(interp); return TclNREvalObjEx(interp, objPtr, TCL_EVAL_INVOKE, NULL, INT_MIN); /* * ----------------------------------------------------------------- * Start of INST_LOAD instructions. * * WARNING: more 'goto' here than your doctor recommended! The different * instructions set the value of some variables and then jump to some * common execution code. */ case INST_LOAD_SCALAR: instLoadScalar: opnd = TclGetUInt4AtPtr(pc+1); LOCALVAR(varPtr, opnd); TRACE(("%u => ", opnd)); if (TclIsVarDirectReadable(varPtr)) { /* * No errors, no traces: just get the value. */ objResultPtr = varPtr->value.objPtr; TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_F(5, 0, 1); } pcAdjustment = 5; cleanup = 0; arrayPtr = NULL; part1Ptr = part2Ptr = NULL; goto doCallPtrGetVar; case INST_LOAD_ARRAY: opnd = TclGetUInt4AtPtr(pc+1); part1Ptr = NULL; part2Ptr = OBJ_AT_TOS; LOCALVAR(arrayPtr, opnd); TRACE(("%u \"%.30s\" => ", opnd, O2S(part2Ptr))); if (TclIsVarArray(arrayPtr) && !ReadTraced(arrayPtr)) { varPtr = VarHashFindVar(arrayPtr->value.tablePtr, part2Ptr); if (varPtr && TclIsVarDirectReadable(varPtr)) { /* * No errors, no traces: just get the value. */ |
︙ | ︙ | |||
2950 2951 2952 2953 2954 2955 2956 | case INST_STORE_ARRAY: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; valuePtr = OBJ_AT_TOS; part2Ptr = OBJ_UNDER_TOS; | | < < < | < < < | 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 | case INST_STORE_ARRAY: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; valuePtr = OBJ_AT_TOS; part2Ptr = OBJ_UNDER_TOS; LOCALVAR(arrayPtr, opnd); TRACE(("%u \"%.30s\" <- \"%.30s\" => ", opnd, O2S(part2Ptr), O2S(valuePtr))); if (TclIsVarArray(arrayPtr) && !WriteTraced(arrayPtr)) { varPtr = VarHashFindVar(arrayPtr->value.tablePtr, part2Ptr); if (varPtr && TclIsVarDirectWritable(varPtr)) { tosPtr--; Tcl_DecrRefCount(OBJ_AT_TOS); OBJ_AT_TOS = valuePtr; goto doStoreVarDirect; } } cleanup = 2; storeFlags = TCL_LEAVE_ERR_MSG; part1Ptr = NULL; goto doStoreArrayDirectFailed; case INST_STORE_SCALAR: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; valuePtr = OBJ_AT_TOS; LOCALVAR(varPtr, opnd); TRACE(("%u <- \"%.30s\" => ", opnd, O2S(valuePtr))); if (!TclIsVarDirectWritable(varPtr)) { storeFlags = TCL_LEAVE_ERR_MSG; part1Ptr = NULL; goto doStoreScalar; } /* |
︙ | ︙ | |||
3085 3086 3087 3088 3089 3090 3091 | opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE); doStoreArray: valuePtr = OBJ_AT_TOS; part2Ptr = OBJ_UNDER_TOS; | | < < < | 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 | opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE); doStoreArray: valuePtr = OBJ_AT_TOS; part2Ptr = OBJ_UNDER_TOS; LOCALVAR(arrayPtr, opnd); TRACE(("%u \"%.30s\" <- \"%.30s\" => ", opnd, O2S(part2Ptr), O2S(valuePtr))); cleanup = 2; part1Ptr = NULL; doStoreArrayDirectFailed: varPtr = TclLookupArrayElement(interp, part1Ptr, part2Ptr, TCL_LEAVE_ERR_MSG, "set", 1, 1, arrayPtr, opnd); if (!varPtr) { |
︙ | ︙ | |||
3117 3118 3119 3120 3121 3122 3123 | case INST_APPEND_SCALAR: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE); doStoreScalar: valuePtr = OBJ_AT_TOS; | | < < < | 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 | case INST_APPEND_SCALAR: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; storeFlags = (TCL_LEAVE_ERR_MSG | TCL_APPEND_VALUE); doStoreScalar: valuePtr = OBJ_AT_TOS; LOCALVAR(varPtr, opnd); TRACE(("%u <- \"%.30s\" => ", opnd, O2S(valuePtr))); cleanup = 1; arrayPtr = NULL; part1Ptr = part2Ptr = NULL; doCallPtrSetVar: DECACHE_STACK_INFO(); objResultPtr = TclPtrSetVar(interp, varPtr, arrayPtr, |
︙ | ︙ | |||
3163 3164 3165 3166 3167 3168 3169 | { Tcl_Obj *incrPtr; #ifndef NO_WIDE_TYPE Tcl_WideInt w; #endif long increment; | < < < < < < < < < < < | | | < < | | | | > > > > > | < < < > > > > > > > < < | < < < | | | | | | | | | | | | | | | | | | | | | > > > < | > | < < < < < < < < | | < > > > | < < < < < < | < < < < < < < < | | | | | | | | | | < | | | | > | > > | < > > | < < < < < < < | < < < < < < | < < < < | > | > | < < < | > > > > > > | 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 | { Tcl_Obj *incrPtr; #ifndef NO_WIDE_TYPE Tcl_WideInt w; #endif long increment; case INST_INCR_ARRAY_STK: case INST_INCR_STK: opnd = TclGetUInt4AtPtr(pc+1); incrPtr = POP_OBJECT(); pcAdjustment = 1; goto doIncrStk; case INST_INCR_ARRAY_STK_IMM: case INST_INCR_STK_IMM: increment = TclGetInt1AtPtr(pc+1); TclNewIntObj(incrPtr, increment); Tcl_IncrRefCount(incrPtr); pcAdjustment = 2; doIncrStk: if ((*pc == INST_INCR_ARRAY_STK_IMM) || (*pc == INST_INCR_ARRAY_STK)) { part2Ptr = OBJ_AT_TOS; objPtr = OBJ_UNDER_TOS; TRACE(("\"%.30s(%.30s)\" (by %ld) => ", O2S(objPtr), O2S(part2Ptr), increment)); } else { part2Ptr = NULL; objPtr = OBJ_AT_TOS; TRACE(("\"%.30s\" (by %ld) => ", O2S(objPtr), increment)); } part1Ptr = objPtr; opnd = -1; varPtr = TclObjLookupVarEx(interp, objPtr, part2Ptr, TCL_LEAVE_ERR_MSG, "read", 1, 1, &arrayPtr); if (!varPtr) { Tcl_AddErrorInfo(interp, "\n (reading value of variable to increment)"); TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); Tcl_DecrRefCount(incrPtr); goto gotError; } cleanup = ((part2Ptr == NULL)? 1 : 2); goto doIncrVar; case INST_INCR_ARRAY_IMM: opnd = TclGetUInt4AtPtr(pc+1); increment = TclGetInt1AtPtr(pc+5); TclNewIntObj(incrPtr, increment); Tcl_IncrRefCount(incrPtr); pcAdjustment = 6; goto doIncrArray; case INST_INCR_ARRAY: opnd = TclGetUInt4AtPtr(pc+1); incrPtr = POP_OBJECT(); pcAdjustment = 5; doIncrArray: part1Ptr = NULL; part2Ptr = OBJ_AT_TOS; LOCALVAR(arrayPtr, opnd); cleanup = 1; TRACE(("%u \"%.30s\" (by %ld) => ", opnd, O2S(part2Ptr), increment)); varPtr = TclLookupArrayElement(interp, part1Ptr, part2Ptr, TCL_LEAVE_ERR_MSG, "read", 1, 1, arrayPtr, opnd); if (!varPtr) { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); Tcl_DecrRefCount(incrPtr); goto gotError; } goto doIncrVar; /* * This is the most common type of INST_INCR_* as it is the one that * [incr foo] (of a local variable) is compiled into, where 'foo' * holds a small integer. Thus we take special effort to make sure * that it goes faster than many other instructions. */ case INST_INCR_SCALAR_IMM: opnd = TclGetUInt4AtPtr(pc+1); increment = TclGetInt1AtPtr(pc+5); LOCALVAR(varPtr, opnd); if (TclIsVarDirectModifyable(varPtr)) { ClientData ptr; int type; objPtr = varPtr->value.objPtr; if (GetNumberFromObj(NULL, objPtr, &ptr, &type) == TCL_OK && type == TCL_NUMBER_LONG) { long augend = *((const long *)ptr); long sum = augend + increment; /* * Overflow when (augend and sum have different sign) and * (augend and increment have the same sign). This is * encapsulated in the Overflowing macro. */ if (!Overflowing(augend, increment, sum)) { TRACE(("%u %ld => ", opnd, increment)); if (Tcl_IsShared(objPtr)) { objPtr->refCount--; /* We know it's shared. */ TclNewLongObj(objResultPtr, sum); Tcl_IncrRefCount(objResultPtr); varPtr->value.objPtr = objResultPtr; } else { objResultPtr = objPtr; TclSetLongObj(objPtr, sum); } TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); #ifndef TCL_COMPILE_DEBUG if (*(pc+6) == INST_POP) { NEXT_INST_F(7, 0, 0); } #endif /*!TCL_COMPILE_DEBUG*/ NEXT_INST_F(6, 0, 1); } /* * If adding a byte to a long won't fit but we've got a * functional wide integer type defined, we *know* that we'll * be able to fit in that. (That is, long is 32 bits and wide * is 64 bits, and our increment is only 8 bits.) */ #ifndef NO_WIDE_TYPE w = (Tcl_WideInt)augend; TRACE(("%u %ld => ", opnd, increment)); if (Tcl_IsShared(objPtr)) { objPtr->refCount--; /* We know it's shared. */ TclNewWideIntObj(objResultPtr, w+increment); Tcl_IncrRefCount(objResultPtr); varPtr->value.objPtr = objResultPtr; } else { objResultPtr = objPtr; /* * We know the sum value is outside the long range; use * macro form that doesn't range test again. */ TclSetWideIntObj(objPtr, w+increment); } TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); #ifndef TCL_COMPILE_DEBUG if (*(pc+6) == INST_POP) { NEXT_INST_F(7, 0, 0); } #endif /*!TCL_COMPILE_DEBUG*/ NEXT_INST_F(6, 0, 1); #endif /*!NO_WIDE_TYPE*/ } } /* * All other cases, flow through to generic handling. Note that we've * already followed the linked-var chain so we can skip that. */ TclNewLongObj(incrPtr, increment); Tcl_IncrRefCount(incrPtr); pcAdjustment = 6; cleanup = 0; goto doIncrScalar; case INST_INCR_SCALAR: opnd = TclGetUInt4AtPtr(pc+1); incrPtr = POP_OBJECT(); pcAdjustment = 5; LOCALVAR(varPtr, opnd); doIncrScalar: arrayPtr = NULL; part1Ptr = part2Ptr = NULL; cleanup = 0; TRACE(("%u %ld => ", opnd, increment)); doIncrVar: if (TclIsVarDirectModifyable2(varPtr, arrayPtr)) { |
︙ | ︙ | |||
3402 3403 3404 3405 3406 3407 3408 | Tcl_DecrRefCount(incrPtr); if (objResultPtr == NULL) { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto gotError; } } | < | < < < | 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 | Tcl_DecrRefCount(incrPtr); if (objResultPtr == NULL) { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto gotError; } } TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); #ifndef TCL_COMPILE_DEBUG if (*(pc+pcAdjustment) == INST_POP) { NEXT_INST_V((pcAdjustment+1), cleanup, 0); } #endif NEXT_INST_V(pcAdjustment, cleanup, 1); } /* * End of INST_INCR instructions. * ----------------------------------------------------------------- * Start of INST_EXIST instructions. */ case INST_EXIST_SCALAR: opnd = TclGetUInt4AtPtr(pc+1); LOCALVAR(varPtr, opnd); TRACE(("%u => ", opnd)); if (ReadTraced(varPtr)) { DECACHE_STACK_INFO(); TclObjCallVarTraces(iPtr, NULL, varPtr, NULL, NULL, TCL_TRACE_READS, 0, opnd); CACHE_STACK_INFO(); if (TclIsVarUndefined(varPtr)) { |
︙ | ︙ | |||
3447 3448 3449 3450 3451 3452 3453 | objResultPtr = TCONST(!varPtr || TclIsVarUndefined(varPtr) ? 0 : 1); TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_F(5, 0, 1); case INST_EXIST_ARRAY: opnd = TclGetUInt4AtPtr(pc+1); part2Ptr = OBJ_AT_TOS; | | < < < | 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 | objResultPtr = TCONST(!varPtr || TclIsVarUndefined(varPtr) ? 0 : 1); TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_F(5, 0, 1); case INST_EXIST_ARRAY: opnd = TclGetUInt4AtPtr(pc+1); part2Ptr = OBJ_AT_TOS; LOCALVAR(arrayPtr, opnd); TRACE(("%u \"%.30s\" => ", opnd, O2S(part2Ptr))); if (TclIsVarArray(arrayPtr) && !ReadTraced(arrayPtr)) { varPtr = VarHashFindVar(arrayPtr->value.tablePtr, part2Ptr); if (!varPtr || !ReadTraced(varPtr)) { goto doneExistArray; } } |
︙ | ︙ | |||
3521 3522 3523 3524 3525 3526 3527 | { int flags; case INST_UNSET_SCALAR: flags = TclGetUInt1AtPtr(pc+1) ? TCL_LEAVE_ERR_MSG : 0; opnd = TclGetUInt4AtPtr(pc+2); | | < < < | 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 | { int flags; case INST_UNSET_SCALAR: flags = TclGetUInt1AtPtr(pc+1) ? TCL_LEAVE_ERR_MSG : 0; opnd = TclGetUInt4AtPtr(pc+2); LOCALVAR(varPtr, opnd); TRACE(("%s %u\n", (flags?"normal":"noerr"), opnd)); if (TclIsVarDirectUnsettable(varPtr) && !TclIsVarInHash(varPtr)) { /* * No errors, no traces, no searches: just make the variable cease * to exist. */ |
︙ | ︙ | |||
3554 3555 3556 3557 3558 3559 3560 | CACHE_STACK_INFO(); NEXT_INST_F(6, 0, 0); case INST_UNSET_ARRAY: flags = TclGetUInt1AtPtr(pc+1) ? TCL_LEAVE_ERR_MSG : 0; opnd = TclGetUInt4AtPtr(pc+2); part2Ptr = OBJ_AT_TOS; | | < < < | 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 | CACHE_STACK_INFO(); NEXT_INST_F(6, 0, 0); case INST_UNSET_ARRAY: flags = TclGetUInt1AtPtr(pc+1) ? TCL_LEAVE_ERR_MSG : 0; opnd = TclGetUInt4AtPtr(pc+2); part2Ptr = OBJ_AT_TOS; LOCALVAR(arrayPtr, opnd); TRACE(("%s %u \"%.30s\"\n", (flags ? "normal" : "noerr"), opnd, O2S(part2Ptr))); if (TclIsVarArray(arrayPtr) && !UnsetTraced(arrayPtr)) { varPtr = VarHashFindVar(arrayPtr->value.tablePtr, part2Ptr); if (varPtr && TclIsVarDirectUnsettable(varPtr)) { /* * No nasty traces and element exists, so we can proceed to |
︙ | ︙ | |||
3627 3628 3629 3630 3631 3632 3633 | CACHE_STACK_INFO(); NEXT_INST_V(2, cleanup, 0); errorInUnset: CACHE_STACK_INFO(); TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto gotError; | < < < < < < < < < < < < < < < < < < < < < < < | < < < | 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 | CACHE_STACK_INFO(); NEXT_INST_V(2, cleanup, 0); errorInUnset: CACHE_STACK_INFO(); TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto gotError; } /* * End of INST_UNSET instructions. * ----------------------------------------------------------------- * Start of INST_ARRAY instructions. */ case INST_ARRAY_EXISTS_IMM: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; cleanup = 0; part1Ptr = NULL; arrayPtr = NULL; TRACE(("%u => ", opnd)); LOCALVAR(varPtr, opnd); goto doArrayExists; case INST_ARRAY_EXISTS_STK: opnd = -1; pcAdjustment = 1; cleanup = 1; part1Ptr = OBJ_AT_TOS; TRACE(("\"%.30s\" => ", O2S(part1Ptr))); |
︙ | ︙ | |||
3692 3693 3694 3695 3696 3697 3698 | CACHE_STACK_INFO(); if (result == TCL_ERROR) { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto gotError; } } | < | < < < > | < < < | 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 | CACHE_STACK_INFO(); if (result == TCL_ERROR) { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto gotError; } } objResultPtr = TCONST((varPtr && TclIsVarArray(varPtr) && !TclIsVarUndefined(varPtr)) ? 1 : 0); TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_V(pcAdjustment, cleanup, 1); case INST_ARRAY_MAKE_IMM: opnd = TclGetUInt4AtPtr(pc+1); pcAdjustment = 5; cleanup = 0; part1Ptr = NULL; arrayPtr = NULL; TRACE(("%u => ", opnd)); LOCALVAR(varPtr, opnd); goto doArrayMake; case INST_ARRAY_MAKE_STK: opnd = -1; pcAdjustment = 1; cleanup = 1; part1Ptr = OBJ_AT_TOS; TRACE(("\"%.30s\" => ", O2S(part1Ptr))); |
︙ | ︙ | |||
3829 3830 3831 3832 3833 3834 3835 | /* * If we are here, the local variable has already been created: do the * little work of TclPtrMakeUpvar that remains to be done right here * if there are no errors; otherwise, let it handle the case. */ opnd = TclGetInt4AtPtr(pc+1);; | | | 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 | /* * If we are here, the local variable has already been created: do the * little work of TclPtrMakeUpvar that remains to be done right here * if there are no errors; otherwise, let it handle the case. */ opnd = TclGetInt4AtPtr(pc+1);; varPtr = LOCAL(opnd); /* Not LOCALVAR()! */ if ((varPtr != otherPtr) && !TclIsVarTraced(varPtr) && (TclIsVarUndefined(varPtr) || TclIsVarLink(varPtr))) { if (!TclIsVarUndefined(varPtr)) { /* * Then it is a defined link. */ |
︙ | ︙ | |||
4131 4132 4133 4134 4135 4136 4137 | /* * ----------------------------------------------------------------- * Start of INST_LIST and related instructions. */ { | | < | 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 | /* * ----------------------------------------------------------------- * Start of INST_LIST and related instructions. */ { int index, fromIdx, toIdx, numIndices, match, s1len, s2len; const char *s1, *s2; case INST_LIST: /* * Pop the opnd (objc) top stack elements into a new list obj and then * decrement their ref counts. */ |
︙ | ︙ | |||
4404 4405 4406 4407 4408 4409 4410 | } if (fromIdx == 0 && toIdx != objc-1 && !Tcl_IsShared(valuePtr)) { /* * BEWARE! This is looking inside the implementation of the * list type. */ | | | 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 | } if (fromIdx == 0 && toIdx != objc-1 && !Tcl_IsShared(valuePtr)) { /* * BEWARE! This is looking inside the implementation of the * list type. */ List *listPtr = ListRepPtr(valuePtr); if (listPtr->refCount == 1) { TRACE(("\"%.30s\" %d %d => ", O2S(valuePtr), TclGetInt4AtPtr(pc+1), TclGetInt4AtPtr(pc+5))); for (index=toIdx+1 ; index<objc-1 ; index++) { TclDecrRefCount(objv[index]); } |
︙ | ︙ | |||
4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 | NEXT_INST_F((match ? 5 : TclGetInt4AtPtr(pc+1)), 2, 0); case INST_JUMP_TRUE: NEXT_INST_F((match ? TclGetInt4AtPtr(pc+1) : 5), 2, 0); } #endif objResultPtr = TCONST(match); NEXT_INST_F(0, 2, 1); /* * End of INST_LIST and related instructions. * ----------------------------------------------------------------- * Start of string-related instructions. */ case INST_STR_EQ: case INST_STR_NEQ: /* String (in)equality check */ case INST_STR_CMP: /* String compare. */ stringCompare: value2Ptr = OBJ_AT_TOS; valuePtr = OBJ_UNDER_TOS; | > > > > > > | 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 | NEXT_INST_F((match ? 5 : TclGetInt4AtPtr(pc+1)), 2, 0); case INST_JUMP_TRUE: NEXT_INST_F((match ? TclGetInt4AtPtr(pc+1) : 5), 2, 0); } #endif objResultPtr = TCONST(match); NEXT_INST_F(0, 2, 1); } /* * End of INST_LIST and related instructions. * ----------------------------------------------------------------- * Start of string-related instructions. */ { int index, fromIdx, toIdx, nocase, match; int length2, cflags, s1len, s2len; const char *s1, *s2; case INST_STR_EQ: case INST_STR_NEQ: /* String (in)equality check */ case INST_STR_CMP: /* String compare. */ stringCompare: value2Ptr = OBJ_AT_TOS; valuePtr = OBJ_UNDER_TOS; |
︙ | ︙ | |||
4583 4584 4585 4586 4587 4588 4589 | if (match == 0) { match = s1len - s2len; } } } /* | | < > | < > | < > > | < > | | | | | | | | | | | | | | | | | | | | | | < < < < < | 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 | if (match == 0) { match = s1len - s2len; } } } /* * Make sure only -1,0,1 is returned. */ switch (*pc) { case INST_STR_CMP: if (match < 0) { TclNewIntObj(objResultPtr, -1); } else { objResultPtr = TCONST(match > 0); } break; case INST_STR_EQ: case INST_EQ: objResultPtr = TCONST(match == 0); break; case INST_STR_NEQ: case INST_NEQ: objResultPtr = TCONST(match != 0); break; case INST_LT: objResultPtr = TCONST(match < 0); break; case INST_GT: objResultPtr = TCONST(match > 0); break; case INST_LE: objResultPtr = TCONST(match <= 0); break; case INST_GE: objResultPtr = TCONST(match >= 0); break; } TRACE(("%.20s %.20s => %s\n", O2S(valuePtr), O2S(value2Ptr), O2S(objResultPtr))); NEXT_INST_F(1, 2, 1); case INST_STR_LEN: valuePtr = OBJ_AT_TOS; length = Tcl_GetCharLength(valuePtr); |
︙ | ︙ | |||
4693 4694 4695 4696 4697 4698 4699 | } if (toIdx >= fromIdx) { objResultPtr = Tcl_GetRange(OBJ_AT_DEPTH(2), fromIdx, toIdx); } else { TclNewObj(objResultPtr); } TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); | > | | 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 | } if (toIdx >= fromIdx) { objResultPtr = Tcl_GetRange(OBJ_AT_DEPTH(2), fromIdx, toIdx); } else { TclNewObj(objResultPtr); } TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); POP_DROP_OBJECT(); NEXT_INST_F(1, 2, 1); case INST_STR_RANGE_IMM: valuePtr = OBJ_AT_TOS; fromIdx = TclGetInt4AtPtr(pc+1); toIdx = TclGetInt4AtPtr(pc+5); length = Tcl_GetCharLength(valuePtr); TRACE(("\"%.20s\" %d %d => ", O2S(valuePtr), fromIdx, toIdx)); |
︙ | ︙ | |||
4738 4739 4740 4741 4742 4743 4744 | { Tcl_UniChar *ustring1, *ustring2, *ustring3, *end, *p; int length3; Tcl_Obj *value3Ptr; case INST_STR_MAP: | | | | | | | | | < | 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 | { Tcl_UniChar *ustring1, *ustring2, *ustring3, *end, *p; int length3; Tcl_Obj *value3Ptr; case INST_STR_MAP: valuePtr = POP_OBJECT(); /* "Main" string. */ value3Ptr = OBJ_AT_TOS; /* "Target" string. */ value2Ptr = OBJ_UNDER_TOS; /* "Source" string. */ if (value3Ptr == value2Ptr) { objResultPtr = valuePtr; goto doneStringMap; } else if (valuePtr == value2Ptr) { objResultPtr = value3Ptr; goto doneStringMap; } ustring1 = Tcl_GetUnicodeFromObj(valuePtr, &length); if (length == 0) { objResultPtr = valuePtr; goto doneStringMap; } ustring2 = Tcl_GetUnicodeFromObj(value2Ptr, &length2); if (length2 > length || length2 == 0) { objResultPtr = valuePtr; goto doneStringMap; } else if (length2 == length) { if (memcmp(ustring1, ustring2, sizeof(Tcl_UniChar) * length)) { objResultPtr = valuePtr; } else { objResultPtr = value3Ptr; } goto doneStringMap; } ustring3 = Tcl_GetUnicodeFromObj(value3Ptr, &length3); objResultPtr = Tcl_NewUnicodeObj(ustring1, 0); p = ustring1; end = ustring1 + length; for (; ustring1 < end; ustring1++) { if ((*ustring1 == *ustring2) && (length2==1 || memcmp(ustring1, ustring2, sizeof(Tcl_UniChar) * length2) == 0)) { |
︙ | ︙ | |||
4792 4793 4794 4795 4796 4797 4798 4799 4800 | if (p != ustring1) { /* * Put the rest of the unmapped chars onto result. */ Tcl_AppendUnicodeToObj(objResultPtr, p, ustring1 - p); } TRACE_WITH_OBJ(("%.20s %.20s %.20s => ", O2S(value2Ptr), O2S(value3Ptr), O2S(valuePtr)), objResultPtr); | > > | < < < < < < | 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 | if (p != ustring1) { /* * Put the rest of the unmapped chars onto result. */ Tcl_AppendUnicodeToObj(objResultPtr, p, ustring1 - p); } doneStringMap: TRACE_WITH_OBJ(("%.20s %.20s %.20s => ", O2S(value2Ptr), O2S(value3Ptr), O2S(valuePtr)), objResultPtr); TclDecrRefCount(valuePtr); NEXT_INST_F(1, 2, 1); case INST_STR_FIND: ustring1 = Tcl_GetUnicodeFromObj(OBJ_AT_TOS, &length); /* Haystack */ ustring2 = Tcl_GetUnicodeFromObj(OBJ_UNDER_TOS, &length2);/* Needle */ match = -1; if (length2 > 0 && length2 <= length) { end = ustring1 + length - length2 + 1; for (p=ustring1 ; p<end ; p++) { if ((*p == *ustring2) && memcmp(ustring2,p,sizeof(Tcl_UniChar)*length2) == 0) { match = p - ustring1; break; } } } TRACE(("%.20s %.20s => %d\n", O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), match)); TclNewIntObj(objResultPtr, match); NEXT_INST_F(1, 2, 1); case INST_STR_FIND_LAST: ustring1 = Tcl_GetUnicodeFromObj(OBJ_AT_TOS, &length); /* Haystack */ ustring2 = Tcl_GetUnicodeFromObj(OBJ_UNDER_TOS, &length2);/* Needle */ match = -1; if (length2 > 0 && length2 <= length) { for (p=ustring1+length-length2 ; p>=ustring1 ; p--) { if ((*p == *ustring2) && memcmp(ustring2,p,sizeof(Tcl_UniChar)*length2) == 0) { match = p - ustring1; break; } } } TRACE(("%.20s %.20s => %d\n", O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), match)); TclNewIntObj(objResultPtr, match); NEXT_INST_F(1, 2, 1); } case INST_STR_MATCH: nocase = TclGetInt1AtPtr(pc+1); valuePtr = OBJ_AT_TOS; /* String */ |
︙ | ︙ | |||
4908 4909 4910 4911 4912 4913 4914 | { Tcl_RegExp regExpr = Tcl_GetRegExpFromObj(interp, value2Ptr, cflags); if (regExpr == NULL) { goto regexpFailure; } | < < | 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 | { Tcl_RegExp regExpr = Tcl_GetRegExpFromObj(interp, value2Ptr, cflags); if (regExpr == NULL) { goto regexpFailure; } match = Tcl_RegExpExecObj(interp, regExpr, valuePtr, 0, 0, 0); if (match < 0) { regexpFailure: #ifdef TCL_COMPILE_DEBUG objResultPtr = Tcl_GetObjResult(interp); TRACE_WITH_OBJ(("%.20s %.20s => ERROR: ", O2S(valuePtr), O2S(value2Ptr)), objResultPtr); #endif |
︙ | ︙ | |||
5666 5667 5668 5669 5670 5671 5672 | * Initialize the temporary local var that holds the count of the * number of iterations of the loop body to -1. */ opnd = TclGetUInt4AtPtr(pc+1); infoPtr = codePtr->auxDataArrayPtr[opnd].clientData; iterTmpIndex = infoPtr->loopCtTemp; | | | 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 | * Initialize the temporary local var that holds the count of the * number of iterations of the loop body to -1. */ opnd = TclGetUInt4AtPtr(pc+1); infoPtr = codePtr->auxDataArrayPtr[opnd].clientData; iterTmpIndex = infoPtr->loopCtTemp; LOCALVAR(iterVarPtr, iterTmpIndex); oldValuePtr = iterVarPtr->value.objPtr; if (oldValuePtr == NULL) { TclNewLongObj(iterVarPtr->value.objPtr, -1); Tcl_IncrRefCount(iterVarPtr->value.objPtr); } else { TclSetLongObj(oldValuePtr, -1); |
︙ | ︙ | |||
5704 5705 5706 5707 5708 5709 5710 | infoPtr = codePtr->auxDataArrayPtr[opnd].clientData; numLists = infoPtr->numLists; /* * Increment the temp holding the loop iteration number. */ | | | | 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 | infoPtr = codePtr->auxDataArrayPtr[opnd].clientData; numLists = infoPtr->numLists; /* * Increment the temp holding the loop iteration number. */ LOCALVAR(iterVarPtr, infoPtr->loopCtTemp); valuePtr = iterVarPtr->value.objPtr; iterNum = valuePtr->internalRep.longValue + 1; TclSetLongObj(valuePtr, iterNum); /* * Check whether all value lists are exhausted and we should stop the * loop. */ continueLoop = 0; listTmpIndex = infoPtr->firstValueTemp; for (i = 0; i < numLists; i++) { varListPtr = infoPtr->varLists[i]; numVars = varListPtr->numVars; LOCALVAR(listVarPtr, listTmpIndex); listPtr = listVarPtr->value.objPtr; if (TclListObjLength(interp, listPtr, &listLen) != TCL_OK) { TRACE_WITH_OBJ(("%u => ERROR converting list %ld, \"%s\": ", opnd, i, O2S(listPtr)), Tcl_GetObjResult(interp)); goto gotError; } if (listLen > iterNum * numVars) { |
︙ | ︙ | |||
5748 5749 5750 5751 5752 5753 5754 | if (continueLoop) { listTmpIndex = infoPtr->firstValueTemp; for (i = 0; i < numLists; i++) { varListPtr = infoPtr->varLists[i]; numVars = varListPtr->numVars; | | < | < < | 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 | if (continueLoop) { listTmpIndex = infoPtr->firstValueTemp; for (i = 0; i < numLists; i++) { varListPtr = infoPtr->varLists[i]; numVars = varListPtr->numVars; LOCALVAR(listVarPtr, listTmpIndex); listPtr = TclListObjCopy(NULL, listVarPtr->value.objPtr); TclListObjGetElements(interp, listPtr, &listLen, &elements); valIndex = (iterNum * numVars); for (j = 0; j < numVars; j++) { if (valIndex >= listLen) { TclNewObj(valuePtr); } else { valuePtr = elements[valIndex]; } varIndex = varListPtr->varIndexes[j]; LOCALVAR(varPtr, varIndex); if (TclIsVarDirectWritable(varPtr)) { value2Ptr = varPtr->value.objPtr; if (valuePtr != value2Ptr) { if (value2Ptr != NULL) { TclDecrRefCount(value2Ptr); } varPtr->value.objPtr = valuePtr; |
︙ | ︙ | |||
5919 5920 5921 5922 5923 5924 5925 | goto gotError; } } if (Tcl_DictObjGet(interp2, dictPtr, OBJ_AT_TOS, &objResultPtr) == TCL_OK) { if (*pc == INST_DICT_EXISTS) { objResultPtr = TCONST(objResultPtr ? 1 : 0); | < < > > > > > > | < < < | 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 | goto gotError; } } if (Tcl_DictObjGet(interp2, dictPtr, OBJ_AT_TOS, &objResultPtr) == TCL_OK) { if (*pc == INST_DICT_EXISTS) { objResultPtr = TCONST(objResultPtr ? 1 : 0); } if (objResultPtr) { TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); if (opnd == 1) { NEXT_INST_F(5, 2, 1); } NEXT_INST_V(5, opnd+1, 1); } DECACHE_STACK_INFO(); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "key \"%s\" not known in dictionary", TclGetString(OBJ_AT_TOS))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "DICT", TclGetString(OBJ_AT_TOS), NULL); CACHE_STACK_INFO(); TRACE_WITH_OBJ(("%u => ERROR ", opnd), Tcl_GetObjResult(interp)); } else { if (*pc == INST_DICT_EXISTS) { dictNotExists: objResultPtr = TCONST(0); TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); if (opnd == 1) { NEXT_INST_F(5, 2, 1); } NEXT_INST_V(5, opnd+1, 1); } TRACE_WITH_OBJ(( "%u => ERROR reading leaf dictionary key \"%s\": ", opnd, O2S(dictPtr)), Tcl_GetObjResult(interp)); } goto gotError; } case INST_DICT_SET: case INST_DICT_UNSET: case INST_DICT_INCR_IMM: opnd = TclGetUInt4AtPtr(pc+1); opnd2 = TclGetUInt4AtPtr(pc+5); LOCALVAR(varPtr, opnd2); TRACE(("%u %u => ", opnd, opnd2)); if (TclIsVarDirectReadable(varPtr)) { dictPtr = varPtr->value.objPtr; } else { DECACHE_STACK_INFO(); dictPtr = TclPtrGetVar(interp, varPtr, NULL,NULL,NULL, 0, opnd2); CACHE_STACK_INFO(); |
︙ | ︙ | |||
5989 5990 5991 5992 5993 5994 5995 5996 | case INST_DICT_INCR_IMM: cleanup = 1; opnd = TclGetInt4AtPtr(pc+1); result = Tcl_DictObjGet(interp, dictPtr, OBJ_AT_TOS, &valuePtr); if (result != TCL_OK) { break; } if (valuePtr == NULL) { | > | < | 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 | case INST_DICT_INCR_IMM: cleanup = 1; opnd = TclGetInt4AtPtr(pc+1); result = Tcl_DictObjGet(interp, dictPtr, OBJ_AT_TOS, &valuePtr); if (result != TCL_OK) { break; } TclNewIntObj(value2Ptr, opnd); if (valuePtr == NULL) { Tcl_DictObjPut(NULL, dictPtr, OBJ_AT_TOS, value2Ptr); } else { Tcl_IncrRefCount(value2Ptr); if (Tcl_IsShared(valuePtr)) { valuePtr = Tcl_DuplicateObj(valuePtr); Tcl_DictObjPut(NULL, dictPtr, OBJ_AT_TOS, valuePtr); } result = TclIncrObj(interp, valuePtr, value2Ptr); if (result == TCL_OK) { |
︙ | ︙ | |||
6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 | TclDecrRefCount(dictPtr); if (objResultPtr == NULL) { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto gotError; } } #ifndef TCL_COMPILE_DEBUG if (*(pc+9) == INST_POP) { NEXT_INST_V(10, cleanup, 0); } #endif | > > > > | > > | < < < | 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 | TclDecrRefCount(dictPtr); if (objResultPtr == NULL) { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto gotError; } } TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); #ifndef TCL_COMPILE_DEBUG if (*(pc+9) == INST_POP) { if (cleanup == 2) { NEXT_INST_F(10, 2, 0); } NEXT_INST_V(10, cleanup, 0); } #endif if (cleanup == 2) { NEXT_INST_F(9, 2, 1); } NEXT_INST_V(9, cleanup, 1); case INST_DICT_APPEND: case INST_DICT_LAPPEND: opnd = TclGetUInt4AtPtr(pc+1); LOCALVAR(varPtr, opnd); TRACE(("%u => ", opnd)); if (TclIsVarDirectReadable(varPtr)) { dictPtr = varPtr->value.objPtr; } else { DECACHE_STACK_INFO(); dictPtr = TclPtrGetVar(interp, varPtr, NULL, NULL, NULL, 0, opnd); CACHE_STACK_INFO(); |
︙ | ︙ | |||
6205 6206 6207 6208 6209 6210 6211 | ckfree(searchPtr); goto gotError; } TclNewObj(statePtr); statePtr->typePtr = &dictIteratorType; statePtr->internalRep.twoPtrValue.ptr1 = searchPtr; statePtr->internalRep.twoPtrValue.ptr2 = dictPtr; | | > | | 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 | ckfree(searchPtr); goto gotError; } TclNewObj(statePtr); statePtr->typePtr = &dictIteratorType; statePtr->internalRep.twoPtrValue.ptr1 = searchPtr; statePtr->internalRep.twoPtrValue.ptr2 = dictPtr; LOCALVAR(varPtr, opnd); if (varPtr->value.objPtr) { if (varPtr->value.objPtr->typePtr == &dictIteratorType) { Tcl_Panic("mis-issued dictFirst!"); } TclDecrRefCount(varPtr->value.objPtr); } varPtr->value.objPtr = statePtr; Tcl_IncrRefCount(statePtr); goto pushDictIteratorResult; case INST_DICT_NEXT: opnd = TclGetUInt4AtPtr(pc+1); TRACE(("%u => ", opnd)); LOCALVAR(varPtr, opnd); statePtr = varPtr->value.objPtr; if (statePtr == NULL || statePtr->typePtr != &dictIteratorType) { Tcl_Panic("mis-issued dictNext!"); } searchPtr = statePtr->internalRep.twoPtrValue.ptr1; Tcl_DictObjNext(searchPtr, &keyPtr, &valuePtr, &done); pushDictIteratorResult: if (done) { |
︙ | ︙ | |||
6258 6259 6260 6261 6262 6263 6264 | /* fall through to non-debug handling */ } #endif TRACE_APPEND(("\"%.30s\" \"%.30s\" %d", O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), done)); objResultPtr = TCONST(done); | < | < < < | 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 | /* fall through to non-debug handling */ } #endif TRACE_APPEND(("\"%.30s\" \"%.30s\" %d", O2S(OBJ_UNDER_TOS), O2S(OBJ_AT_TOS), done)); objResultPtr = TCONST(done); NEXT_INST_F(5, 0, 1); case INST_DICT_UPDATE_START: opnd = TclGetUInt4AtPtr(pc+1); opnd2 = TclGetUInt4AtPtr(pc+5); LOCALVAR(varPtr, opnd); duiPtr = codePtr->auxDataArrayPtr[opnd2].clientData; TRACE(("%u => ", opnd)); if (TclIsVarDirectReadable(varPtr)) { dictPtr = varPtr->value.objPtr; } else { DECACHE_STACK_INFO(); dictPtr = TclPtrGetVar(interp, varPtr, NULL, NULL, NULL, TCL_LEAVE_ERR_MSG, opnd); |
︙ | ︙ | |||
6293 6294 6295 6296 6297 6298 6299 | Tcl_Panic("dictUpdateStart argument length mismatch"); } for (i=0 ; i<length ; i++) { if (Tcl_DictObjGet(interp, dictPtr, keyPtrPtr[i], &valuePtr) != TCL_OK) { goto gotError; } | | < < < | < < < | 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 | Tcl_Panic("dictUpdateStart argument length mismatch"); } for (i=0 ; i<length ; i++) { if (Tcl_DictObjGet(interp, dictPtr, keyPtrPtr[i], &valuePtr) != TCL_OK) { goto gotError; } LOCALVAR(varPtr, duiPtr->varIndices[i]); DECACHE_STACK_INFO(); if (valuePtr == NULL) { TclObjUnsetVar2(interp, localName(iPtr->varFramePtr, duiPtr->varIndices[i]), NULL, 0); } else if (TclPtrSetVar(interp, varPtr, NULL, NULL, NULL, valuePtr, TCL_LEAVE_ERR_MSG, duiPtr->varIndices[i]) == NULL) { CACHE_STACK_INFO(); goto gotError; } CACHE_STACK_INFO(); } NEXT_INST_F(9, 0, 0); case INST_DICT_UPDATE_END: opnd = TclGetUInt4AtPtr(pc+1); opnd2 = TclGetUInt4AtPtr(pc+5); LOCALVAR(varPtr, opnd); duiPtr = codePtr->auxDataArrayPtr[opnd2].clientData; TRACE(("%u => ", opnd)); if (TclIsVarDirectReadable(varPtr)) { dictPtr = varPtr->value.objPtr; } else { DECACHE_STACK_INFO(); dictPtr = TclPtrGetVar(interp, varPtr, NULL, NULL, NULL, 0, opnd); CACHE_STACK_INFO(); |
︙ | ︙ | |||
6344 6345 6346 6347 6348 6349 6350 | if (allocdict) { dictPtr = Tcl_DuplicateObj(dictPtr); } if (length > 0) { TclInvalidateStringRep(dictPtr); } for (i=0 ; i<length ; i++) { | | | < < | 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 | if (allocdict) { dictPtr = Tcl_DuplicateObj(dictPtr); } if (length > 0) { TclInvalidateStringRep(dictPtr); } for (i=0 ; i<length ; i++) { Var *var2Ptr; LOCALVAR(var2Ptr, duiPtr->varIndices[i]); if (TclIsVarDirectReadable(var2Ptr)) { valuePtr = var2Ptr->value.objPtr; } else { DECACHE_STACK_INFO(); valuePtr = TclPtrGetVar(interp, var2Ptr, NULL, NULL, NULL, 0, duiPtr->varIndices[i]); CACHE_STACK_INFO(); |
︙ | ︙ | |||
6435 6436 6437 6438 6439 6440 6441 | TRACE_APPEND(("OK\n")); NEXT_INST_F(1, 2, 0); case INST_DICT_RECOMBINE_IMM: opnd = TclGetUInt4AtPtr(pc+1); listPtr = OBJ_UNDER_TOS; keysPtr = OBJ_AT_TOS; | | < < < | 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 | TRACE_APPEND(("OK\n")); NEXT_INST_F(1, 2, 0); case INST_DICT_RECOMBINE_IMM: opnd = TclGetUInt4AtPtr(pc+1); listPtr = OBJ_UNDER_TOS; keysPtr = OBJ_AT_TOS; LOCALVAR(varPtr, opnd); TRACE(("%u <- \"%.30s\" \"%.30s\" => ", opnd, O2S(valuePtr), O2S(keysPtr))); if (TclListObjGetElements(interp, listPtr, &objc, &objv) != TCL_OK) { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto gotError; } DECACHE_STACK_INFO(); result = TclDictWithFinish(interp, varPtr, NULL, NULL, NULL, opnd, objc, objv, keysPtr); CACHE_STACK_INFO(); if (result != TCL_OK) { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto gotError; |
︙ | ︙ | |||
6515 6516 6517 6518 6519 6520 6521 | goto abnormalReturn; } if (rangePtr->type == CATCH_EXCEPTION_RANGE) { TRACE_APPEND(("%s ...\n", StringForResultCode(result))); goto processCatch; } while (cleanup--) { | | < | 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 | goto abnormalReturn; } if (rangePtr->type == CATCH_EXCEPTION_RANGE) { TRACE_APPEND(("%s ...\n", StringForResultCode(result))); goto processCatch; } while (cleanup--) { POP_DROP_OBJECT(); } if (result == TCL_BREAK) { result = TCL_OK; pc = (codePtr->codeStart + rangePtr->breakOffset); TRACE_APPEND(("%s, range at %d, new pc %d\n", StringForResultCode(result), rangePtr->codeOffset, rangePtr->breakOffset)); |
︙ | ︙ | |||
6692 6693 6694 6695 6696 6697 6698 | * an instruction during break, continue, or error processing. Jump to * its catchOffset after unwinding the operand stack to the depth it * had when starting to execute the range's catch command. */ processCatch: while (CURR_DEPTH > *catchTop) { | | < | 6628 6629 6630 6631 6632 6633 6634 6635 6636 6637 6638 6639 6640 6641 6642 | * an instruction during break, continue, or error processing. Jump to * its catchOffset after unwinding the operand stack to the depth it * had when starting to execute the range's catch command. */ processCatch: while (CURR_DEPTH > *catchTop) { POP_DROP_OBJECT(); } #ifdef TCL_COMPILE_DEBUG if (traceInstructions) { fprintf(stdout, " ... found catch at %d, catchTop=%d, " "unwound to %ld, new pc %u\n", rangePtr->codeOffset, (int) (catchTop - initCatchTop - 1), (long) *catchTop, (unsigned) rangePtr->catchOffset); |
︙ | ︙ | |||
6730 6731 6732 6733 6734 6735 6736 | * markers. */ while (auxObjList) { POP_TAUX_OBJ(); } while (tosPtr > initTosPtr) { | | < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 6710 6711 6712 6713 6714 6715 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 | * markers. */ while (auxObjList) { POP_TAUX_OBJ(); } while (tosPtr > initTosPtr) { POP_DROP_OBJECT(); } if (tosPtr < initTosPtr) { fprintf(stderr, "\nTclNRExecuteByteCode: abnormal return at pc %u: " "stack top %d < entry stack top %d\n", (unsigned)(pc - codePtr->codeStart), (unsigned) CURR_DEPTH, (unsigned) 0); Tcl_Panic("TclNRExecuteByteCode execution failure: end stack top < start stack top"); } CLANG_ASSERT(bcFramePtr); } iPtr->cmdFramePtr = bcFramePtr->nextPtr; if (--codePtr->refCount <= 0) { TclCleanupByteCode(codePtr); } TclStackFree(interp, TD); /* free my stack */ return result; /* * INST_START_CMD failure case removed where it doesn't bother that much * * Remark that if the interpreter is marked for deletion its * compileEpoch is modified, so that the epoch check also verifies * that the interp is not deleted. If no outside call has been made * since the last check, it is safe to omit the check. * case INST_START_CMD: */ instStartCmdFailed: { const char *bytes; checkInterp = 1; length = 0; /* * We used to switch to direct eval; for NRE-awareness we now compile * and eval the command so that this evaluation does not add a new * TEBC instance. [Bug 2910748] */ if (TclInterpReady(interp) == TCL_ERROR) { goto gotError; } codePtr->flags |= TCL_BYTECODE_RECOMPILE; bytes = GetSrcInfoForPc(pc, codePtr, &length, NULL); opnd = TclGetUInt4AtPtr(pc+1); pc += (opnd-1); PUSH_OBJECT(Tcl_NewStringObj(bytes, length)); goto instEvalStk; } } #undef codePtr #undef iPtr #undef bcFramePtr #undef initCatchTop #undef initTosPtr |
︙ | ︙ | |||
8123 8124 8125 8126 8127 8128 8129 | } default: Tcl_Panic("unexpected number type"); return TCL_ERROR; } } | < > | 8093 8094 8095 8096 8097 8098 8099 8100 8101 8102 8103 8104 8105 8106 8107 8108 8109 8110 8111 8112 8113 8114 8115 8116 8117 8118 8119 8120 8121 8122 8123 8124 8125 | } default: Tcl_Panic("unexpected number type"); return TCL_ERROR; } } /* *---------------------------------------------------------------------- * * PrintByteCodeInfo -- * * This procedure prints a summary about a bytecode object to stdout. It * is called by TclNRExecuteByteCode when starting to execute the bytecode * object if tclTraceExec has the value 2 or more. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ #ifdef TCL_COMPILE_DEBUG static void PrintByteCodeInfo( register ByteCode *codePtr) /* The bytecode whose summary is printed to * stdout. */ { Proc *procPtr = codePtr->procPtr; Interp *iPtr = (Interp *) *codePtr->interpHandle; |
︙ | ︙ | |||
8215 8216 8217 8218 8219 8220 8221 | register ByteCode *codePtr, /* The bytecode whose summary is printed to * stdout. */ const unsigned char *pc, /* Points to first byte of a bytecode * instruction. The program counter. */ int stackTop, /* Current stack top. Must be between * stackLowerBound and stackUpperBound * (inclusive). */ | < | | | | | | 8185 8186 8187 8188 8189 8190 8191 8192 8193 8194 8195 8196 8197 8198 8199 8200 8201 8202 8203 8204 8205 8206 8207 8208 8209 8210 8211 8212 8213 8214 8215 8216 8217 8218 8219 8220 8221 8222 8223 8224 8225 8226 | register ByteCode *codePtr, /* The bytecode whose summary is printed to * stdout. */ const unsigned char *pc, /* Points to first byte of a bytecode * instruction. The program counter. */ int stackTop, /* Current stack top. Must be between * stackLowerBound and stackUpperBound * (inclusive). */ int checkStack) /* 0 if the stack depth check should be * skipped. */ { int stackUpperBound = codePtr->maxStackDepth; /* Greatest legal value for stackTop. */ unsigned relativePc = (unsigned) (pc - codePtr->codeStart); unsigned long codeStart = (unsigned long) codePtr->codeStart; unsigned long codeEnd = (unsigned long) (codePtr->codeStart + codePtr->numCodeBytes); unsigned char opCode = *pc; if (((unsigned long) pc < codeStart) || ((unsigned long) pc > codeEnd)) { fprintf(stderr, "\nBad instruction pc 0x%p in TclNRExecuteByteCode\n", pc); Tcl_Panic("TclNRExecuteByteCode execution failure: bad pc"); } if ((unsigned) opCode > LAST_INST_OPCODE) { fprintf(stderr, "\nBad opcode %d at pc %u in TclNRExecuteByteCode\n", (unsigned) opCode, relativePc); Tcl_Panic("TclNRExecuteByteCode execution failure: bad opcode"); } if (checkStack && ((stackTop < 0) || (stackTop > stackUpperBound))) { int numChars; const char *cmd = GetSrcInfoForPc(pc, codePtr, &numChars, NULL); fprintf(stderr, "\nBad stack top %d at pc %u in TclNRExecuteByteCode (min 0, max %i)", stackTop, relativePc, stackUpperBound); if (cmd != NULL) { Tcl_Obj *message; TclNewLiteralStringObj(message, "\n executing "); Tcl_IncrRefCount(message); Tcl_AppendLimitedToObj(message, cmd, numChars, 100, NULL); fprintf(stderr,"%s\n", Tcl_GetString(message)); |
︙ | ︙ | |||
8676 8677 8678 8679 8680 8681 8682 | Tcl_SetErrorCode(interp, "ARITH", "UNKNOWN", Tcl_GetString(objPtr), NULL); Tcl_SetObjResult(interp, objPtr); } } | < > > > | 8645 8646 8647 8648 8649 8650 8651 8652 8653 8654 8655 8656 8657 8658 8659 8660 8661 8662 8663 8664 8665 8666 8667 8668 8669 8670 8671 8672 8673 8674 8675 8676 8677 8678 8679 8680 8681 8682 8683 8684 8685 8686 8687 8688 8689 8690 8691 8692 8693 8694 8695 8696 8697 8698 8699 8700 8701 8702 8703 8704 8705 8706 8707 8708 8709 8710 8711 | Tcl_SetErrorCode(interp, "ARITH", "UNKNOWN", Tcl_GetString(objPtr), NULL); Tcl_SetObjResult(interp, objPtr); } } /* *---------------------------------------------------------------------- * * TclLog2 -- * * Procedure used while collecting compilation statistics to determine * the log base 2 of an integer. * * Results: * Returns the log base 2 of the operand. If the argument is less than or * equal to zero, a zero is returned. * * Side effects: * None. * *---------------------------------------------------------------------- */ #ifdef TCL_COMPILE_STATS int TclLog2( register int value) /* The integer for which to compute the log * base 2. */ { register int n = value; register int result = 0; while (n > 1) { n = n >> 1; result++; } return result; } #endif /* TCL_COMPILE_STATS */ /* *---------------------------------------------------------------------- * * EvalStatsCmd -- * * Implements the "evalstats" command that prints instruction execution * counts to stdout. * * Results: * Standard Tcl results. * * Side effects: * None. * *---------------------------------------------------------------------- */ #ifdef TCL_COMPILE_STATS static int EvalStatsCmd( ClientData unused, /* Unused. */ Tcl_Interp *interp, /* The current interpreter. */ int objc, /* The number of arguments. */ Tcl_Obj *const objv[]) /* The argument strings. */ { |
︙ | ︙ | |||
9131 9132 9133 9134 9135 9136 9137 | } } Tcl_DecrRefCount(objPtr); return TCL_OK; } #endif /* TCL_COMPILE_STATS */ | < | 9102 9103 9104 9105 9106 9107 9108 9109 9110 9111 9112 9113 9114 9115 | } } Tcl_DecrRefCount(objPtr); return TCL_OK; } #endif /* TCL_COMPILE_STATS */ /* *---------------------------------------------------------------------- * * StringForResultCode -- * * Procedure that returns a human-readable string representing a Tcl * result code such as TCL_ERROR. |
︙ | ︙ | |||
9153 9154 9155 9156 9157 9158 9159 9160 9161 9162 9163 9164 9165 9166 | * * Side effects: * None. * *---------------------------------------------------------------------- */ static const char * StringForResultCode( int result) /* The Tcl result code for which to generate a * string. */ { static char buf[TCL_INTEGER_SPACE]; | > | 9123 9124 9125 9126 9127 9128 9129 9130 9131 9132 9133 9134 9135 9136 9137 | * * Side effects: * None. * *---------------------------------------------------------------------- */ #ifdef TCL_COMPILE_DEBUG static const char * StringForResultCode( int result) /* The Tcl result code for which to generate a * string. */ { static char buf[TCL_INTEGER_SPACE]; |
︙ | ︙ |
Changes to generic/tclFCmd.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* * tclFCmd.c * * This file implements the generic portion of file manipulation * subcommands of the "file" command. * * Copyright (c) 1996-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclFileSystem.h" /* * Declarations for local functions defined in this file: */ | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /* * tclFCmd.c * * This file implements the generic portion of file manipulation * subcommands of the "file" command. * * Copyright (c) 1996-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include <sys/stat.h> #include "tclInt.h" #include "tclFileSystem.h" /* * Declarations for local functions defined in this file: */ |
︙ | ︙ |
Changes to generic/tclFileName.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /* * tclFileName.c -- * * This file contains routines for converting file names betwen native * and network form. * * Copyright (c) 1995-1998 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclRegexp.h" #include "tclFileSystem.h" /* For TclGetPathType() */ /* * The following variable is set in the TclPlatformInit call to one of: * TCL_PLATFORM_UNIX or TCL_PLATFORM_WINDOWS. | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* * tclFileName.c -- * * This file contains routines for converting file names betwen native * and network form. * * Copyright (c) 1995-1998 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include <sys/stat.h> #include "tclInt.h" #include "tclRegexp.h" #include "tclFileSystem.h" /* For TclGetPathType() */ /* * The following variable is set in the TclPlatformInit call to one of: * TCL_PLATFORM_UNIX or TCL_PLATFORM_WINDOWS. |
︙ | ︙ |
Changes to generic/tclIO.c.
︙ | ︙ | |||
2468 2469 2470 2471 2472 2473 2474 | /* * This used to check for CHANNEL_NONBLOCKING, and panic if * the channel was blocking. However, it appears that setting * stdin to -blocking 0 has some effect on the stdout when * it's a tty channel (dup'ed underneath) */ | | | 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 | /* * This used to check for CHANNEL_NONBLOCKING, and panic if * the channel was blocking. However, it appears that setting * stdin to -blocking 0 has some effect on the stdout when * it's a tty channel (dup'ed underneath) */ if (!GotFlag(statePtr, BG_FLUSH_SCHEDULED) && !TclInExit()) { SetFlag(statePtr, BG_FLUSH_SCHEDULED); UpdateInterest(chanPtr); } errorCode = 0; break; } |
︙ | ︙ |
Changes to generic/tclIOCmd.c.
︙ | ︙ | |||
1935 1936 1937 1938 1939 1940 1941 | * Most commands are plugged directly together, but some are done via * alias-like rewriting; [chan configure] is this way for security reasons * (want overwriting of [fconfigure] to control that nicely), and [chan * names] because the functionality isn't available as a separate command * function at the moment. */ static const EnsembleImplMap initMap[] = { | | | | | | | | | | | > | | | | | | < | | | 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 | * Most commands are plugged directly together, but some are done via * alias-like rewriting; [chan configure] is this way for security reasons * (want overwriting of [fconfigure] to control that nicely), and [chan * names] because the functionality isn't available as a separate command * function at the moment. */ static const EnsembleImplMap initMap[] = { {"blocked", Tcl_FblockedObjCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"close", Tcl_CloseObjCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, {"copy", Tcl_FcopyObjCmd, NULL, NULL, NULL, 0}, {"create", TclChanCreateObjCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, /* TIP #219 */ {"eof", Tcl_EofObjCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"event", Tcl_FileEventObjCmd, TclCompileBasic2Or3ArgCmd, NULL, NULL, 0}, {"flush", Tcl_FlushObjCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"gets", Tcl_GetsObjCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, {"names", TclChannelNamesCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"pending", ChanPendingObjCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, /* TIP #287 */ {"pipe", ChanPipeObjCmd, TclCompileBasic0ArgCmd, NULL, NULL, 0}, /* TIP #304 */ {"pop", TclChanPopObjCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, /* TIP #230 */ {"postevent", TclChanPostEventObjCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, /* TIP #219 */ {"push", TclChanPushObjCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, /* TIP #230 */ {"puts", Tcl_PutsObjCmd, NULL, NULL, NULL, 0}, {"read", Tcl_ReadObjCmd, NULL, NULL, NULL, 0}, {"seek", Tcl_SeekObjCmd, TclCompileBasic2Or3ArgCmd, NULL, NULL, 0}, {"tell", Tcl_TellObjCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"truncate", ChanTruncateObjCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, /* TIP #208 */ {NULL, NULL, NULL, NULL, NULL, 0} }; static const char *const extras[] = { "configure", "::fconfigure", NULL }; Tcl_Command ensemble; |
︙ | ︙ |
Changes to generic/tclIORTrans.c.
︙ | ︙ | |||
2938 2939 2940 2941 2942 2943 2944 | { rPtr->used = 0; if (!rPtr->allocated) { return; } | | | 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 | { rPtr->used = 0; if (!rPtr->allocated) { return; } ckfree((char *) rPtr->buf); rPtr->buf = NULL; rPtr->allocated = 0; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
2973 2974 2975 2976 2977 2978 2979 | /* * Extension of the internal buffer is required. * NOTE: Currently linear. Should be doubling to amortize. */ if (rPtr->allocated == 0) { rPtr->allocated = toWrite + RB_INCREMENT; | | | | 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 | /* * Extension of the internal buffer is required. * NOTE: Currently linear. Should be doubling to amortize. */ if (rPtr->allocated == 0) { rPtr->allocated = toWrite + RB_INCREMENT; rPtr->buf = UCHARP(ckalloc(rPtr->allocated)); } else { rPtr->allocated += toWrite + RB_INCREMENT; rPtr->buf = UCHARP(ckrealloc((char *) rPtr->buf, rPtr->allocated)); } } /* * Now copy data. */ |
︙ | ︙ |
Changes to generic/tclIOUtil.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 2001-2004 Vincent Darley. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ | < | < | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 2001-2004 Vincent Darley. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include <sys/stat.h> #include "tclInt.h" #ifdef __WIN32__ # include "tclWinInt.h" #endif #include "tclFileSystem.h" /* |
︙ | ︙ |
Changes to generic/tclIndexObj.c.
︙ | ︙ | |||
65 66 67 68 69 70 71 | int index; /* Selected index into table. */ } IndexRep; /* * The following macros greatly simplify moving through a table... */ | | | | | | 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | int index; /* Selected index into table. */ } IndexRep; /* * The following macros greatly simplify moving through a table... */ #define STRING_AT(table, offset) \ (*((const char *const *)(((char *)(table)) + (offset)))) #define NEXT_ENTRY(table, offset) \ (&(STRING_AT(table, offset))) #define EXPAND_OF(indexRep) \ STRING_AT((indexRep)->tablePtr, (indexRep)->offset*(indexRep)->index) /* *---------------------------------------------------------------------- * * Tcl_GetIndexFromObj -- * * This function looks up an object's value in a table of strings and |
︙ | ︙ | |||
234 235 236 237 238 239 240 | * Results: * If the value of objPtr is identical to or a unique abbreviation for * one of the entries in tablePtr, then the return value is TCL_OK and * the index of the matching entry is stored at *indexPtr. If there isn't * a proper match, then TCL_ERROR is returned and an error message is * left in interp's result (unless interp is NULL). The msg argument is * used in the error message; for example, if msg has the value "option" | | | 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | * Results: * If the value of objPtr is identical to or a unique abbreviation for * one of the entries in tablePtr, then the return value is TCL_OK and * the index of the matching entry is stored at *indexPtr. If there isn't * a proper match, then TCL_ERROR is returned and an error message is * left in interp's result (unless interp is NULL). The msg argument is * used in the error message; for example, if msg has the value "option" * then the error message will say something like 'bad option "foo": must * be ...' * * Side effects: * The result of the lookup is cached as the internal rep of objPtr, so * that repeated lookups can be done quickly. * *---------------------------------------------------------------------- |
︙ | ︙ | |||
266 267 268 269 270 271 272 273 274 275 276 277 278 279 | int index, idx, numAbbrev; const char *key, *p1; const char *p2; const char *const *entryPtr; Tcl_Obj *resultPtr; IndexRep *indexRep; /* * See if there is a valid cached result from a previous lookup. */ if (objPtr->typePtr == &indexType) { indexRep = objPtr->internalRep.otherValuePtr; if (indexRep->tablePtr==tablePtr && indexRep->offset==offset) { | > > > > | 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 | int index, idx, numAbbrev; const char *key, *p1; const char *p2; const char *const *entryPtr; Tcl_Obj *resultPtr; IndexRep *indexRep; /* Protect against invalid values, like -1 or 0. */ if (offset < (int)sizeof(char *)) { offset = (int)sizeof(char *); } /* * See if there is a valid cached result from a previous lookup. */ if (objPtr->typePtr == &indexType) { indexRep = objPtr->internalRep.otherValuePtr; if (indexRep->tablePtr==tablePtr && indexRep->offset==offset) { |
︙ | ︙ | |||
529 530 531 532 533 534 535 | */ Tcl_Command TclInitPrefixCmd( Tcl_Interp *interp) /* Current interpreter. */ { static const EnsembleImplMap prefixImplMap[] = { | | | | | 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 | */ Tcl_Command TclInitPrefixCmd( Tcl_Interp *interp) /* Current interpreter. */ { static const EnsembleImplMap prefixImplMap[] = { {"all", PrefixAllObjCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"longest", PrefixLongestObjCmd,TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"match", PrefixMatchObjCmd, TclCompileBasicMin2ArgCmd, NULL, NULL, 0}, {NULL, NULL, NULL, NULL, NULL, 0} }; Tcl_Command prefixCmd; prefixCmd = TclMakeEnsemble(interp, "::tcl::prefix", prefixImplMap); Tcl_Export(interp, Tcl_FindNamespace(interp, "::tcl", NULL, 0), "prefix", 0); |
︙ | ︙ |
Changes to generic/tclInt.decls.
︙ | ︙ | |||
625 626 627 628 629 630 631 | declare 156 { void TclRegError(Tcl_Interp *interp, const char *msg, int status) } declare 157 { Var *TclVarTraceExists(Tcl_Interp *interp, const char *varName) } | | | | < > | | | < > | 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 | declare 156 { void TclRegError(Tcl_Interp *interp, const char *msg, int status) } declare 157 { Var *TclVarTraceExists(Tcl_Interp *interp, const char *varName) } # REMOVED (except from stub table) - use public Tcl_SetStartupScript() declare 158 { void TclSetStartupScriptFileName(const char *filename) } # REMOVED (except from stub table) - use public Tcl_GetStartupScript() declare 159 { const char *TclGetStartupScriptFileName(void) } #declare 160 { # int TclpMatchFilesTypes(Tcl_Interp *interp, char *separators, # Tcl_DString *dirPtr, char *pattern, char *tail, # GlobTypeData *types) #} # new in 8.3.2/8.4a2 |
︙ | ︙ | |||
677 678 679 680 681 682 683 | # New function due to TIP #33 declare 166 { int TclListObjSetElement(Tcl_Interp *interp, Tcl_Obj *listPtr, int index, Tcl_Obj *valuePtr) } # VFS-aware versions of Tcl*StartupScriptFileName (158 and 159 above) | | | | < > | | | < > | 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 | # New function due to TIP #33 declare 166 { int TclListObjSetElement(Tcl_Interp *interp, Tcl_Obj *listPtr, int index, Tcl_Obj *valuePtr) } # VFS-aware versions of Tcl*StartupScriptFileName (158 and 159 above) # REMOVED (except from stub table) - use public Tcl_SetStartupScript() declare 167 { void TclSetStartupScriptPath(Tcl_Obj *pathPtr) } # REMOVED (except from stub table) - use public Tcl_GetStartupScript() declare 168 { Tcl_Obj *TclGetStartupScriptPath(void) } # variant of Tcl_UtfNCmp that takes n as bytes, not chars declare 169 { int TclpUtfNcmp2(const char *s1, const char *s2, unsigned long n) } declare 170 { int TclCheckInterpTraces(Tcl_Interp *interp, const char *command, int numChars, Command *cmdPtr, int result, int traceFlags, |
︙ | ︙ | |||
730 731 732 733 734 735 736 | declare 176 { void TclCleanupVar(Var *varPtr, Var *arrayPtr) } declare 177 { void TclVarErrMsg(Tcl_Interp *interp, const char *part1, const char *part2, const char *operation, const char *reason) } | | | | < > | | < > | 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 | declare 176 { void TclCleanupVar(Var *varPtr, Var *arrayPtr) } declare 177 { void TclVarErrMsg(Tcl_Interp *interp, const char *part1, const char *part2, const char *operation, const char *reason) } # TIP 338 made these public - now declared in tcl.h too declare 178 { void Tcl_SetStartupScript(Tcl_Obj *pathPtr, const char *encodingName) } declare 179 { Tcl_Obj *Tcl_GetStartupScript(const char **encodingNamePtr) } # REMOVED # Allocate lists without copying arrays # declare 180 { # Tcl_Obj *TclNewListObjDirect(int objc, Tcl_Obj **objv) # } #declare 181 { |
︙ | ︙ | |||
1148 1149 1150 1151 1152 1153 1154 | } # Added in 8.4.2 declare 28 win { void TclWinResetInterfaces(void) } | < < < | 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 | } # Added in 8.4.2 declare 28 win { void TclWinResetInterfaces(void) } ################################ # Unix specific functions # Pipe channel functions declare 0 unix { |
︙ | ︙ | |||
1218 1219 1220 1221 1222 1223 1224 | # Added in 8.5: declare 14 unix { int TclUnixCopyFile(const char *src, const char *dst, const Tcl_StatBuf *statBufPtr, int dontCopyAtts) } | < < < < < < | 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 | # Added in 8.5: declare 14 unix { int TclUnixCopyFile(const char *src, const char *dst, const Tcl_StatBuf *statBufPtr, int dontCopyAtts) } ################################ # Mac OS X specific functions declare 15 macosx { int TclMacOSXGetFileAttribute(Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr) } |
︙ | ︙ | |||
1247 1248 1249 1250 1251 1252 1253 | int TclMacOSXMatchType(Tcl_Interp *interp, const char *pathName, const char *fileName, Tcl_StatBuf *statBufPtr, Tcl_GlobTypeData *types) } declare 19 macosx { void TclMacOSXNotifierAddRunLoopMode(const void *runLoopMode) } | > | > > > > > > > | 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 | int TclMacOSXMatchType(Tcl_Interp *interp, const char *pathName, const char *fileName, Tcl_StatBuf *statBufPtr, Tcl_GlobTypeData *types) } declare 19 macosx { void TclMacOSXNotifierAddRunLoopMode(const void *runLoopMode) } declare 29 {win unix} { int TclWinCPUID(unsigned int index, unsigned int *regs) } # Added in 8.6; core of TclpOpenTemporaryFile declare 30 {win unix} { int TclUnixOpenTemporaryFile(Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj) } # Local Variables: # mode: tcl # End: |
Changes to generic/tclInt.h.
︙ | ︙ | |||
1150 1151 1152 1153 1154 1155 1156 | * sets it, and it should only ever be set by * the code that is pushing the frame. In that * case, the code that sets it should also * have some means of discovering what the * meaning of the value is, which we do not * specify. */ LocalCache *localCachePtr; | | | 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 | * sets it, and it should only ever be set by * the code that is pushing the frame. In that * case, the code that sets it should also * have some means of discovering what the * meaning of the value is, which we do not * specify. */ LocalCache *localCachePtr; Tcl_Obj *tailcallPtr; /* NULL if no tailcall is scheduled */ } CallFrame; #define FRAME_IS_PROC 0x1 #define FRAME_IS_LAMBDA 0x2 #define FRAME_IS_METHOD 0x4 /* The frame is a method body, and the frame's * clientData field contains a CallContext |
︙ | ︙ | |||
1489 1490 1491 1492 1493 1494 1495 | * coroutine; -2 means "0 or 1" (default), -1 * means "any" */ } CoroutineData; typedef struct ExecEnv { ExecStack *execStackPtr; /* Points to the first item in the evaluation * stack on the heap. */ | | > | 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 | * coroutine; -2 means "0 or 1" (default), -1 * means "any" */ } CoroutineData; typedef struct ExecEnv { ExecStack *execStackPtr; /* Points to the first item in the evaluation * stack on the heap. */ Tcl_Obj *constants[2]; /* Pointers to constant "-1", "0" and "1" * objs. */ struct Tcl_Interp *interp; struct NRE_callback *callbackPtr; /* Top callback in NRE's stack. */ struct CoroutineData *corPtr; int rewind; } ExecEnv; |
︙ | ︙ | |||
2219 2220 2221 2222 2223 2224 2225 | * code other than TCL_OK or TCL_ERROR; 0 means codes * other than these should be turned into errors. */ #define TCL_ALLOW_EXCEPTIONS 4 #define TCL_EVAL_FILE 2 #define TCL_EVAL_CTX 8 | < | 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 | * code other than TCL_OK or TCL_ERROR; 0 means codes * other than these should be turned into errors. */ #define TCL_ALLOW_EXCEPTIONS 4 #define TCL_EVAL_FILE 2 #define TCL_EVAL_CTX 8 /* * Flag bits for Interp structures: * * DELETED: Non-zero means the interpreter has been deleted: * don't process any more commands for it, and destroy * the structure as soon as all nested invocations of |
︙ | ︙ | |||
2764 2765 2766 2767 2768 2769 2770 | MODULE_SCOPE Tcl_ObjCmdProc TclNRTailcallObjCmd; MODULE_SCOPE Tcl_NRPostProc TclNRTailcallEval; MODULE_SCOPE Tcl_ObjCmdProc TclNRCoroutineObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRYieldObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRYieldmObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRYieldToObjCmd; | | > | > > > | 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 | MODULE_SCOPE Tcl_ObjCmdProc TclNRTailcallObjCmd; MODULE_SCOPE Tcl_NRPostProc TclNRTailcallEval; MODULE_SCOPE Tcl_ObjCmdProc TclNRCoroutineObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRYieldObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRYieldmObjCmd; MODULE_SCOPE Tcl_ObjCmdProc TclNRYieldToObjCmd; MODULE_SCOPE void TclSetTailcall(Tcl_Interp *interp, Tcl_Obj *tailcallPtr); MODULE_SCOPE void TclPushTailcallPoint(Tcl_Interp *interp); /* These two can be considered for the public api */ MODULE_SCOPE void TclMarkTailcall(Tcl_Interp *interp); MODULE_SCOPE void TclSkipTailcall(Tcl_Interp *interp); /* * This structure holds the data for the various iteration callbacks used to * NRE the 'for' and 'while' commands. We need a separate structure because we * have more than the 4 client data entries we can provide directly thorugh * the callback API. It is the 'word' information which puts us over the * limit. It is needed because the loop body is argument 4 of 'for' and |
︙ | ︙ | |||
2840 2841 2842 2843 2844 2845 2846 | *---------------------------------------------------------------- */ MODULE_SCOPE void TclAppendBytesToByteArray(Tcl_Obj *objPtr, const unsigned char *bytes, int len); MODULE_SCOPE int TclNREvalCmd(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); | < | 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 | *---------------------------------------------------------------- */ MODULE_SCOPE void TclAppendBytesToByteArray(Tcl_Obj *objPtr, const unsigned char *bytes, int len); MODULE_SCOPE int TclNREvalCmd(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags); MODULE_SCOPE void TclAdvanceContinuations(int *line, int **next, int loc); MODULE_SCOPE void TclAdvanceLines(int *line, const char *start, const char *end); MODULE_SCOPE void TclArgumentEnter(Tcl_Interp *interp, Tcl_Obj *objv[], int objc, CmdFrame *cf); MODULE_SCOPE void TclArgumentRelease(Tcl_Interp *interp, |
︙ | ︙ | |||
3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 | struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileWhileCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileYieldCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclInvertOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileInvertOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 | struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileWhileCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileYieldCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileBasic0ArgCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileBasic1ArgCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileBasic2ArgCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileBasic3ArgCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileBasic0Or1ArgCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileBasic1Or2ArgCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileBasic2Or3ArgCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileBasic0To2ArgCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileBasic1To3ArgCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileBasicMin0ArgCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileBasicMin1ArgCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileBasicMin2ArgCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclInvertOpCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclCompileInvertOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); |
︙ | ︙ | |||
3959 3960 3961 3962 3963 3964 3965 | * The PURIFY mode is like the regular mode, but instead of doing block * Tcl_Obj allocation and keeping a freed list for efficiency, it always * allocates and frees a single Tcl_Obj so that tools like Purify can better * track memory leaks. */ # define TclAllocObjStorageEx(interp, objPtr) \ | | > | 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 | * The PURIFY mode is like the regular mode, but instead of doing block * Tcl_Obj allocation and keeping a freed list for efficiency, it always * allocates and frees a single Tcl_Obj so that tools like Purify can better * track memory leaks. */ # define TclAllocObjStorageEx(interp, objPtr) \ (objPtr) = (Tcl_Obj *) ckalloc(sizeof(Tcl_Obj)) # define TclFreeObjStorageEx(interp, objPtr) \ ckfree((char *) (objPtr)) #undef USE_THREAD_ALLOC #undef USE_TCLALLOC #elif defined(TCL_THREADS) && defined(USE_THREAD_ALLOC) /* * The TCL_THREADS mode is like the regular mode but allocates Tcl_Obj's from * per-thread caches. */ |
︙ | ︙ | |||
4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 | (objPtr)->typePtr = &tclIntType; \ TCL_DTRACE_OBJ_CREATE(objPtr); \ } while (0) #define TclNewLongObj(objPtr, l) \ TclNewIntObj((objPtr), (l)) /* * NOTE: There is to be no such thing as a "pure" boolean. * See comment above TclSetBooleanObj macro above. */ #define TclNewBooleanObj(objPtr, b) \ TclNewIntObj((objPtr), ((b)? 1 : 0)) | > > > > > > > > > > > > > | 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 | (objPtr)->typePtr = &tclIntType; \ TCL_DTRACE_OBJ_CREATE(objPtr); \ } while (0) #define TclNewLongObj(objPtr, l) \ TclNewIntObj((objPtr), (l)) #ifndef NO_WIDE_TYPE #define TclNewWideIntObj(objPtr, w) \ do { \ TclIncrObjsAllocated(); \ TclAllocObjStorage(objPtr); \ (objPtr)->refCount = 0; \ (objPtr)->bytes = NULL; \ (objPtr)->internalRep.wideValue = (Tcl_WideInt)(w); \ (objPtr)->typePtr = &tclWideIntType; \ TCL_DTRACE_OBJ_CREATE(objPtr); \ } while (0) #endif /*!NO_WIDE_TYPE*/ /* * NOTE: There is to be no such thing as a "pure" boolean. * See comment above TclSetBooleanObj macro above. */ #define TclNewBooleanObj(objPtr, b) \ TclNewIntObj((objPtr), ((b)? 1 : 0)) |
︙ | ︙ | |||
4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 | #else /* TCL_MEM_DEBUG */ #define TclNewIntObj(objPtr, i) \ (objPtr) = Tcl_NewIntObj(i) #define TclNewLongObj(objPtr, l) \ (objPtr) = Tcl_NewLongObj(l) #define TclNewBooleanObj(objPtr, b) \ (objPtr) = Tcl_NewBooleanObj(b) #define TclNewDoubleObj(objPtr, d) \ (objPtr) = Tcl_NewDoubleObj(d) #define TclNewStringObj(objPtr, s, len) \ | > > > > > | 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 | #else /* TCL_MEM_DEBUG */ #define TclNewIntObj(objPtr, i) \ (objPtr) = Tcl_NewIntObj(i) #define TclNewLongObj(objPtr, l) \ (objPtr) = Tcl_NewLongObj(l) #ifndef NO_WIDE_TYPE #define TclNewWideIntObj(objPtr, w) \ (objPtr) = Tcl_NewWideIntObj(w) #endif /*!NO_WIDE_TYPE*/ #define TclNewBooleanObj(objPtr, b) \ (objPtr) = Tcl_NewBooleanObj(b) #define TclNewDoubleObj(objPtr, d) \ (objPtr) = Tcl_NewDoubleObj(d) #define TclNewStringObj(objPtr, s, len) \ |
︙ | ︙ | |||
4722 4723 4724 4725 4726 4727 4728 | callbackPtr->data[1] = (ClientData)(data1); \ callbackPtr->data[2] = (ClientData)(data2); \ callbackPtr->data[3] = (ClientData)(data3); \ callbackPtr->nextPtr = TOP_CB(interp); \ TOP_CB(interp) = callbackPtr; \ } while (0) | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 | callbackPtr->data[1] = (ClientData)(data1); \ callbackPtr->data[2] = (ClientData)(data2); \ callbackPtr->data[3] = (ClientData)(data3); \ callbackPtr->nextPtr = TOP_CB(interp); \ TOP_CB(interp) = callbackPtr; \ } while (0) #if NRE_USE_SMALL_ALLOC #define TCLNR_ALLOC(interp, ptr) \ TclSmallAllocEx(interp, sizeof(NRE_callback), (ptr)) #define TCLNR_FREE(interp, ptr) TclSmallFreeEx((interp), (ptr)) #else #define TCLNR_ALLOC(interp, ptr) \ (ptr = ((ClientData) ckalloc(sizeof(NRE_callback)))) |
︙ | ︙ |
Changes to generic/tclIntDecls.h.
︙ | ︙ | |||
14 15 16 17 18 19 20 | #ifndef _TCLINTDECLS #define _TCLINTDECLS #include "tclPort.h" /* [Bug #803489] Tcl_FindNamespace problem in the Stubs table */ | < > | | > > | | | | < | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | #ifndef _TCLINTDECLS #define _TCLINTDECLS #include "tclPort.h" /* [Bug #803489] Tcl_FindNamespace problem in the Stubs table */ #undef Tcl_CreateNamespace #undef Tcl_DeleteNamespace #undef Tcl_AppendExportList #undef Tcl_Export #undef Tcl_Import #undef Tcl_ForgetImport #undef Tcl_GetCurrentNamespace #undef Tcl_GetGlobalNamespace #undef Tcl_FindNamespace #undef Tcl_FindCommand #undef Tcl_GetCommandFromObj #undef Tcl_GetCommandFullName #undef Tcl_SetStartupScript #undef Tcl_GetStartupScript /* * WARNING: This file is automatically generated by the tools/genStubs.tcl * script. Any modifications to the function declarations below should be made * in the generic/tclInt.decls script. */ |
︙ | ︙ | |||
372 373 374 375 376 377 378 | /* Slot 155 is reserved */ /* 156 */ TCLAPI void TclRegError(Tcl_Interp *interp, const char *msg, int status); /* 157 */ TCLAPI Var * TclVarTraceExists(Tcl_Interp *interp, const char *varName); | | > | > | > | > | 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 | /* Slot 155 is reserved */ /* 156 */ TCLAPI void TclRegError(Tcl_Interp *interp, const char *msg, int status); /* 157 */ TCLAPI Var * TclVarTraceExists(Tcl_Interp *interp, const char *varName); /* 158 */ TCLAPI void TclSetStartupScriptFileName(const char *filename); /* 159 */ TCLAPI const char * TclGetStartupScriptFileName(void); /* Slot 160 is reserved */ /* 161 */ TCLAPI int TclChannelTransform(Tcl_Interp *interp, Tcl_Channel chan, Tcl_Obj *cmdObjPtr); /* 162 */ TCLAPI void TclChannelEventScriptInvoker(ClientData clientData, int flags); /* 163 */ TCLAPI const void * TclGetInstructionTable(void); /* 164 */ TCLAPI void TclExpandCodeArray(void *envPtr); /* 165 */ TCLAPI void TclpSetInitialEncodings(void); /* 166 */ TCLAPI int TclListObjSetElement(Tcl_Interp *interp, Tcl_Obj *listPtr, int index, Tcl_Obj *valuePtr); /* 167 */ TCLAPI void TclSetStartupScriptPath(Tcl_Obj *pathPtr); /* 168 */ TCLAPI Tcl_Obj * TclGetStartupScriptPath(void); /* 169 */ TCLAPI int TclpUtfNcmp2(const char *s1, const char *s2, unsigned long n); /* 170 */ TCLAPI int TclCheckInterpTraces(Tcl_Interp *interp, const char *command, int numChars, Command *cmdPtr, int result, int traceFlags, |
︙ | ︙ | |||
424 425 426 427 428 429 430 | int leaveErrMsg); /* 176 */ TCLAPI void TclCleanupVar(Var *varPtr, Var *arrayPtr); /* 177 */ TCLAPI void TclVarErrMsg(Tcl_Interp *interp, const char *part1, const char *part2, const char *operation, const char *reason); | | > > | > | 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 | int leaveErrMsg); /* 176 */ TCLAPI void TclCleanupVar(Var *varPtr, Var *arrayPtr); /* 177 */ TCLAPI void TclVarErrMsg(Tcl_Interp *interp, const char *part1, const char *part2, const char *operation, const char *reason); /* 178 */ TCLAPI void Tcl_SetStartupScript(Tcl_Obj *pathPtr, const char *encodingName); /* 179 */ TCLAPI Tcl_Obj * Tcl_GetStartupScript(const char **encodingNamePtr); /* Slot 180 is reserved */ /* Slot 181 is reserved */ /* Slot 182 is reserved */ /* Slot 183 is reserved */ /* Slot 184 is reserved */ /* Slot 185 is reserved */ /* Slot 186 is reserved */ |
︙ | ︙ | |||
739 740 741 742 743 744 745 | void (*tclRegExpRangeUniChar) (Tcl_RegExp re, int index, int *startPtr, int *endPtr); /* 151 */ void (*tclSetLibraryPath) (Tcl_Obj *pathPtr); /* 152 */ Tcl_Obj * (*tclGetLibraryPath) (void); /* 153 */ void (*reserved154)(void); void (*reserved155)(void); void (*tclRegError) (Tcl_Interp *interp, const char *msg, int status); /* 156 */ Var * (*tclVarTraceExists) (Tcl_Interp *interp, const char *varName); /* 157 */ | | | | | | | | 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 | void (*tclRegExpRangeUniChar) (Tcl_RegExp re, int index, int *startPtr, int *endPtr); /* 151 */ void (*tclSetLibraryPath) (Tcl_Obj *pathPtr); /* 152 */ Tcl_Obj * (*tclGetLibraryPath) (void); /* 153 */ void (*reserved154)(void); void (*reserved155)(void); void (*tclRegError) (Tcl_Interp *interp, const char *msg, int status); /* 156 */ Var * (*tclVarTraceExists) (Tcl_Interp *interp, const char *varName); /* 157 */ void (*tclSetStartupScriptFileName) (const char *filename); /* 158 */ const char * (*tclGetStartupScriptFileName) (void); /* 159 */ void (*reserved160)(void); int (*tclChannelTransform) (Tcl_Interp *interp, Tcl_Channel chan, Tcl_Obj *cmdObjPtr); /* 161 */ void (*tclChannelEventScriptInvoker) (ClientData clientData, int flags); /* 162 */ const void * (*tclGetInstructionTable) (void); /* 163 */ void (*tclExpandCodeArray) (void *envPtr); /* 164 */ void (*tclpSetInitialEncodings) (void); /* 165 */ int (*tclListObjSetElement) (Tcl_Interp *interp, Tcl_Obj *listPtr, int index, Tcl_Obj *valuePtr); /* 166 */ void (*tclSetStartupScriptPath) (Tcl_Obj *pathPtr); /* 167 */ Tcl_Obj * (*tclGetStartupScriptPath) (void); /* 168 */ int (*tclpUtfNcmp2) (const char *s1, const char *s2, unsigned long n); /* 169 */ int (*tclCheckInterpTraces) (Tcl_Interp *interp, const char *command, int numChars, Command *cmdPtr, int result, int traceFlags, int objc, Tcl_Obj *const objv[]); /* 170 */ int (*tclCheckExecutionTraces) (Tcl_Interp *interp, const char *command, int numChars, Command *cmdPtr, int result, int traceFlags, int objc, Tcl_Obj *const objv[]); /* 171 */ int (*tclInThreadExit) (void); /* 172 */ int (*tclUniCharMatch) (const Tcl_UniChar *string, int strLen, const Tcl_UniChar *pattern, int ptnLen, int flags); /* 173 */ void (*reserved174)(void); int (*tclCallVarTraces) (Interp *iPtr, Var *arrayPtr, Var *varPtr, const char *part1, const char *part2, int flags, int leaveErrMsg); /* 175 */ void (*tclCleanupVar) (Var *varPtr, Var *arrayPtr); /* 176 */ void (*tclVarErrMsg) (Tcl_Interp *interp, const char *part1, const char *part2, const char *operation, const char *reason); /* 177 */ void (*tcl_SetStartupScript) (Tcl_Obj *pathPtr, const char *encodingName); /* 178 */ Tcl_Obj * (*tcl_GetStartupScript) (const char **encodingNamePtr); /* 179 */ void (*reserved180)(void); void (*reserved181)(void); void (*reserved182)(void); void (*reserved183)(void); void (*reserved184)(void); void (*reserved185)(void); void (*reserved186)(void); |
︙ | ︙ | |||
1101 1102 1103 1104 1105 1106 1107 | (tclIntStubsPtr->tclGetLibraryPath) /* 153 */ /* Slot 154 is reserved */ /* Slot 155 is reserved */ #define TclRegError \ (tclIntStubsPtr->tclRegError) /* 156 */ #define TclVarTraceExists \ (tclIntStubsPtr->tclVarTraceExists) /* 157 */ | > | > | > | > | > | > | | 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 | (tclIntStubsPtr->tclGetLibraryPath) /* 153 */ /* Slot 154 is reserved */ /* Slot 155 is reserved */ #define TclRegError \ (tclIntStubsPtr->tclRegError) /* 156 */ #define TclVarTraceExists \ (tclIntStubsPtr->tclVarTraceExists) /* 157 */ #define TclSetStartupScriptFileName \ (tclIntStubsPtr->tclSetStartupScriptFileName) /* 158 */ #define TclGetStartupScriptFileName \ (tclIntStubsPtr->tclGetStartupScriptFileName) /* 159 */ /* Slot 160 is reserved */ #define TclChannelTransform \ (tclIntStubsPtr->tclChannelTransform) /* 161 */ #define TclChannelEventScriptInvoker \ (tclIntStubsPtr->tclChannelEventScriptInvoker) /* 162 */ #define TclGetInstructionTable \ (tclIntStubsPtr->tclGetInstructionTable) /* 163 */ #define TclExpandCodeArray \ (tclIntStubsPtr->tclExpandCodeArray) /* 164 */ #define TclpSetInitialEncodings \ (tclIntStubsPtr->tclpSetInitialEncodings) /* 165 */ #define TclListObjSetElement \ (tclIntStubsPtr->tclListObjSetElement) /* 166 */ #define TclSetStartupScriptPath \ (tclIntStubsPtr->tclSetStartupScriptPath) /* 167 */ #define TclGetStartupScriptPath \ (tclIntStubsPtr->tclGetStartupScriptPath) /* 168 */ #define TclpUtfNcmp2 \ (tclIntStubsPtr->tclpUtfNcmp2) /* 169 */ #define TclCheckInterpTraces \ (tclIntStubsPtr->tclCheckInterpTraces) /* 170 */ #define TclCheckExecutionTraces \ (tclIntStubsPtr->tclCheckExecutionTraces) /* 171 */ #define TclInThreadExit \ (tclIntStubsPtr->tclInThreadExit) /* 172 */ #define TclUniCharMatch \ (tclIntStubsPtr->tclUniCharMatch) /* 173 */ /* Slot 174 is reserved */ #define TclCallVarTraces \ (tclIntStubsPtr->tclCallVarTraces) /* 175 */ #define TclCleanupVar \ (tclIntStubsPtr->tclCleanupVar) /* 176 */ #define TclVarErrMsg \ (tclIntStubsPtr->tclVarErrMsg) /* 177 */ #define Tcl_SetStartupScript \ (tclIntStubsPtr->tcl_SetStartupScript) /* 178 */ #define Tcl_GetStartupScript \ (tclIntStubsPtr->tcl_GetStartupScript) /* 179 */ /* Slot 180 is reserved */ /* Slot 181 is reserved */ /* Slot 182 is reserved */ /* Slot 183 is reserved */ /* Slot 184 is reserved */ /* Slot 185 is reserved */ /* Slot 186 is reserved */ |
︙ | ︙ | |||
1254 1255 1256 1257 1258 1259 1260 1261 1262 | (tclIntStubsPtr->tclDoubleDigits) /* 249 */ #define TclSetSlaveCancelFlags \ (tclIntStubsPtr->tclSetSlaveCancelFlags) /* 250 */ #endif /* defined(USE_TCL_STUBS) */ /* !END!: Do not edit above this line. */ #endif /* _TCLINTDECLS */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 | (tclIntStubsPtr->tclDoubleDigits) /* 249 */ #define TclSetSlaveCancelFlags \ (tclIntStubsPtr->tclSetSlaveCancelFlags) /* 250 */ #endif /* defined(USE_TCL_STUBS) */ /* !END!: Do not edit above this line. */ #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLIMPORT #undef TclGetStartupScriptFileName #undef TclSetStartupScriptFileName #undef TclGetStartupScriptPath #undef TclSetStartupScriptPath #undef TclBackgroundException #if defined(USE_TCL_STUBS) && defined(TCL_NO_DEPRECATED) # undef Tcl_SetStartupScript # define Tcl_SetStartupScript \ (tclStubsPtr->tcl_SetStartupScript) /* 622 */ # undef Tcl_GetStartupScript # define Tcl_GetStartupScript \ (tclStubsPtr->tcl_GetStartupScript) /* 623 */ # undef Tcl_CreateNamespace # define Tcl_CreateNamespace \ (tclStubsPtr->tcl_CreateNamespace) /* 506 */ # undef Tcl_DeleteNamespace # define Tcl_DeleteNamespace \ (tclStubsPtr->tcl_DeleteNamespace) /* 507 */ # undef Tcl_AppendExportList # define Tcl_AppendExportList \ (tclStubsPtr->tcl_AppendExportList) /* 508 */ # undef Tcl_Export # define Tcl_Export \ (tclStubsPtr->tcl_Export) /* 509 */ # undef Tcl_Import # define Tcl_Import \ (tclStubsPtr->tcl_Import) /* 510 */ # undef Tcl_ForgetImport # define Tcl_ForgetImport \ (tclStubsPtr->tcl_ForgetImport) /* 511 */ # undef Tcl_GetCurrentNamespace # define Tcl_GetCurrentNamespace \ (tclStubsPtr->tcl_GetCurrentNamespace) /* 512 */ # undef Tcl_GetGlobalNamespace # define Tcl_GetGlobalNamespace \ (tclStubsPtr->tcl_GetGlobalNamespace) /* 513 */ # undef Tcl_FindNamespace # define Tcl_FindNamespace \ (tclStubsPtr->tcl_FindNamespace) /* 514 */ # undef Tcl_FindCommand # define Tcl_FindCommand \ (tclStubsPtr->tcl_FindCommand) /* 515 */ # undef Tcl_GetCommandFromObj # define Tcl_GetCommandFromObj \ (tclStubsPtr->tcl_GetCommandFromObj) /* 516 */ # undef Tcl_GetCommandFullName # define Tcl_GetCommandFullName \ (tclStubsPtr->tcl_GetCommandFullName) /* 517 */ #endif #endif /* _TCLINTDECLS */ |
Changes to generic/tclIntPlatDecls.h.
︙ | ︙ | |||
67 68 69 70 71 72 73 | const Tcl_StatBuf *statBufPtr, int dontCopyAtts); /* Slot 15 is reserved */ /* Slot 16 is reserved */ /* Slot 17 is reserved */ /* Slot 18 is reserved */ /* Slot 19 is reserved */ | | < < < > > > > | 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | const Tcl_StatBuf *statBufPtr, int dontCopyAtts); /* Slot 15 is reserved */ /* Slot 16 is reserved */ /* Slot 17 is reserved */ /* Slot 18 is reserved */ /* Slot 19 is reserved */ /* Slot 20 is reserved */ /* Slot 21 is reserved */ /* Slot 22 is reserved */ /* Slot 23 is reserved */ /* Slot 24 is reserved */ /* Slot 25 is reserved */ /* Slot 26 is reserved */ /* Slot 27 is reserved */ /* Slot 28 is reserved */ /* 29 */ TCLAPI int TclWinCPUID(unsigned int index, unsigned int *regs); /* 30 */ TCLAPI int TclUnixOpenTemporaryFile(Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj); #endif /* UNIX */ #if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */ /* 0 */ TCLAPI void TclWinConvertError(DWORD errCode); /* Slot 1 is reserved */ /* 2 */ TCLAPI struct servent * TclWinGetServByName(const char *nm, |
︙ | ︙ | |||
151 152 153 154 155 156 157 158 159 160 161 162 163 164 | TCLAPI void TclWinSetInterfaces(int wide); /* 27 */ TCLAPI void TclWinFlushDirtyChannels(void); /* 28 */ TCLAPI void TclWinResetInterfaces(void); /* 29 */ TCLAPI int TclWinCPUID(unsigned int index, unsigned int *regs); #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ /* 0 */ TCLAPI void TclGetAndDetachPids(Tcl_Interp *interp, Tcl_Channel chan); /* 1 */ TCLAPI int TclpCloseFile(TclFile file); | > > > > | 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | TCLAPI void TclWinSetInterfaces(int wide); /* 27 */ TCLAPI void TclWinFlushDirtyChannels(void); /* 28 */ TCLAPI void TclWinResetInterfaces(void); /* 29 */ TCLAPI int TclWinCPUID(unsigned int index, unsigned int *regs); /* 30 */ TCLAPI int TclUnixOpenTemporaryFile(Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj); #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ /* 0 */ TCLAPI void TclGetAndDetachPids(Tcl_Interp *interp, Tcl_Channel chan); /* 1 */ TCLAPI int TclpCloseFile(TclFile file); |
︙ | ︙ | |||
208 209 210 211 212 213 214 | TCLAPI int TclMacOSXMatchType(Tcl_Interp *interp, const char *pathName, const char *fileName, Tcl_StatBuf *statBufPtr, Tcl_GlobTypeData *types); /* 19 */ TCLAPI void TclMacOSXNotifierAddRunLoopMode( const void *runLoopMode); | | < < < > > > > | 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | TCLAPI int TclMacOSXMatchType(Tcl_Interp *interp, const char *pathName, const char *fileName, Tcl_StatBuf *statBufPtr, Tcl_GlobTypeData *types); /* 19 */ TCLAPI void TclMacOSXNotifierAddRunLoopMode( const void *runLoopMode); /* Slot 20 is reserved */ /* Slot 21 is reserved */ /* Slot 22 is reserved */ /* Slot 23 is reserved */ /* Slot 24 is reserved */ /* Slot 25 is reserved */ /* Slot 26 is reserved */ /* Slot 27 is reserved */ /* Slot 28 is reserved */ /* 29 */ TCLAPI int TclWinCPUID(unsigned int index, unsigned int *regs); /* 30 */ TCLAPI int TclUnixOpenTemporaryFile(Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj); #endif /* MACOSX */ typedef struct TclIntPlatStubs { int magic; void *hooks; #if !defined(__WIN32__) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */ |
︙ | ︙ | |||
249 250 251 252 253 254 255 | char * (*tclpInetNtoa) (struct in_addr addr); /* 13 */ int (*tclUnixCopyFile) (const char *src, const char *dst, const Tcl_StatBuf *statBufPtr, int dontCopyAtts); /* 14 */ void (*reserved15)(void); void (*reserved16)(void); void (*reserved17)(void); void (*reserved18)(void); void (*reserved19)(void); | | > | 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 | char * (*tclpInetNtoa) (struct in_addr addr); /* 13 */ int (*tclUnixCopyFile) (const char *src, const char *dst, const Tcl_StatBuf *statBufPtr, int dontCopyAtts); /* 14 */ void (*reserved15)(void); void (*reserved16)(void); void (*reserved17)(void); void (*reserved18)(void); void (*reserved19)(void); void (*reserved20)(void); void (*reserved21)(void); void (*reserved22)(void); void (*reserved23)(void); void (*reserved24)(void); void (*reserved25)(void); void (*reserved26)(void); void (*reserved27)(void); void (*reserved28)(void); int (*tclWinCPUID) (unsigned int index, unsigned int *regs); /* 29 */ int (*tclUnixOpenTemporaryFile) (Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj); /* 30 */ #endif /* UNIX */ #if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */ void (*tclWinConvertError) (DWORD errCode); /* 0 */ void (*reserved1)(void); struct servent * (*tclWinGetServByName) (const char *nm, const char *proto); /* 2 */ int (*tclWinGetSockOpt) (SOCKET s, int level, int optname, char *optval, int *optlen); /* 3 */ HINSTANCE (*tclWinGetTclInstance) (void); /* 4 */ |
︙ | ︙ | |||
291 292 293 294 295 296 297 298 299 300 301 302 303 304 | void (*reserved23)(void); char * (*tclWinNoBackslash) (char *path); /* 24 */ void (*reserved25)(void); void (*tclWinSetInterfaces) (int wide); /* 26 */ void (*tclWinFlushDirtyChannels) (void); /* 27 */ void (*tclWinResetInterfaces) (void); /* 28 */ int (*tclWinCPUID) (unsigned int index, unsigned int *regs); /* 29 */ #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ void (*tclGetAndDetachPids) (Tcl_Interp *interp, Tcl_Channel chan); /* 0 */ int (*tclpCloseFile) (TclFile file); /* 1 */ Tcl_Channel (*tclpCreateCommandChannel) (TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid *pidPtr); /* 2 */ int (*tclpCreatePipe) (TclFile *readPipe, TclFile *writePipe); /* 3 */ int (*tclpCreateProcess) (Tcl_Interp *interp, int argc, const char **argv, TclFile inputFile, TclFile outputFile, TclFile errorFile, Tcl_Pid *pidPtr); /* 4 */ | > | 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 | void (*reserved23)(void); char * (*tclWinNoBackslash) (char *path); /* 24 */ void (*reserved25)(void); void (*tclWinSetInterfaces) (int wide); /* 26 */ void (*tclWinFlushDirtyChannels) (void); /* 27 */ void (*tclWinResetInterfaces) (void); /* 28 */ int (*tclWinCPUID) (unsigned int index, unsigned int *regs); /* 29 */ int (*tclUnixOpenTemporaryFile) (Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj); /* 30 */ #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ void (*tclGetAndDetachPids) (Tcl_Interp *interp, Tcl_Channel chan); /* 0 */ int (*tclpCloseFile) (TclFile file); /* 1 */ Tcl_Channel (*tclpCreateCommandChannel) (TclFile readFile, TclFile writeFile, TclFile errorFile, int numPids, Tcl_Pid *pidPtr); /* 2 */ int (*tclpCreatePipe) (TclFile *readPipe, TclFile *writePipe); /* 3 */ int (*tclpCreateProcess) (Tcl_Interp *interp, int argc, const char **argv, TclFile inputFile, TclFile outputFile, TclFile errorFile, Tcl_Pid *pidPtr); /* 4 */ |
︙ | ︙ | |||
313 314 315 316 317 318 319 | char * (*tclpInetNtoa) (struct in_addr addr); /* 13 */ int (*tclUnixCopyFile) (const char *src, const char *dst, const Tcl_StatBuf *statBufPtr, int dontCopyAtts); /* 14 */ int (*tclMacOSXGetFileAttribute) (Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr); /* 15 */ int (*tclMacOSXSetFileAttribute) (Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj *attributePtr); /* 16 */ int (*tclMacOSXCopyFileAttributes) (const char *src, const char *dst, const Tcl_StatBuf *statBufPtr); /* 17 */ int (*tclMacOSXMatchType) (Tcl_Interp *interp, const char *pathName, const char *fileName, Tcl_StatBuf *statBufPtr, Tcl_GlobTypeData *types); /* 18 */ void (*tclMacOSXNotifierAddRunLoopMode) (const void *runLoopMode); /* 19 */ | | > | 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 | char * (*tclpInetNtoa) (struct in_addr addr); /* 13 */ int (*tclUnixCopyFile) (const char *src, const char *dst, const Tcl_StatBuf *statBufPtr, int dontCopyAtts); /* 14 */ int (*tclMacOSXGetFileAttribute) (Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr); /* 15 */ int (*tclMacOSXSetFileAttribute) (Tcl_Interp *interp, int objIndex, Tcl_Obj *fileName, Tcl_Obj *attributePtr); /* 16 */ int (*tclMacOSXCopyFileAttributes) (const char *src, const char *dst, const Tcl_StatBuf *statBufPtr); /* 17 */ int (*tclMacOSXMatchType) (Tcl_Interp *interp, const char *pathName, const char *fileName, Tcl_StatBuf *statBufPtr, Tcl_GlobTypeData *types); /* 18 */ void (*tclMacOSXNotifierAddRunLoopMode) (const void *runLoopMode); /* 19 */ void (*reserved20)(void); void (*reserved21)(void); void (*reserved22)(void); void (*reserved23)(void); void (*reserved24)(void); void (*reserved25)(void); void (*reserved26)(void); void (*reserved27)(void); void (*reserved28)(void); int (*tclWinCPUID) (unsigned int index, unsigned int *regs); /* 29 */ int (*tclUnixOpenTemporaryFile) (Tcl_Obj *dirObj, Tcl_Obj *basenameObj, Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj); /* 30 */ #endif /* MACOSX */ } TclIntPlatStubs; #ifdef __cplusplus extern "C" { #endif extern const TclIntPlatStubs *tclIntPlatStubsPtr; |
︙ | ︙ | |||
373 374 375 376 377 378 379 | #define TclUnixCopyFile \ (tclIntPlatStubsPtr->tclUnixCopyFile) /* 14 */ /* Slot 15 is reserved */ /* Slot 16 is reserved */ /* Slot 17 is reserved */ /* Slot 18 is reserved */ /* Slot 19 is reserved */ | | < > > | 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 | #define TclUnixCopyFile \ (tclIntPlatStubsPtr->tclUnixCopyFile) /* 14 */ /* Slot 15 is reserved */ /* Slot 16 is reserved */ /* Slot 17 is reserved */ /* Slot 18 is reserved */ /* Slot 19 is reserved */ /* Slot 20 is reserved */ /* Slot 21 is reserved */ /* Slot 22 is reserved */ /* Slot 23 is reserved */ /* Slot 24 is reserved */ /* Slot 25 is reserved */ /* Slot 26 is reserved */ /* Slot 27 is reserved */ /* Slot 28 is reserved */ #define TclWinCPUID \ (tclIntPlatStubsPtr->tclWinCPUID) /* 29 */ #define TclUnixOpenTemporaryFile \ (tclIntPlatStubsPtr->tclUnixOpenTemporaryFile) /* 30 */ #endif /* UNIX */ #if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */ #define TclWinConvertError \ (tclIntPlatStubsPtr->tclWinConvertError) /* 0 */ /* Slot 1 is reserved */ #define TclWinGetServByName \ (tclIntPlatStubsPtr->tclWinGetServByName) /* 2 */ |
︙ | ︙ | |||
444 445 446 447 448 449 450 451 452 453 454 455 456 457 | (tclIntPlatStubsPtr->tclWinSetInterfaces) /* 26 */ #define TclWinFlushDirtyChannels \ (tclIntPlatStubsPtr->tclWinFlushDirtyChannels) /* 27 */ #define TclWinResetInterfaces \ (tclIntPlatStubsPtr->tclWinResetInterfaces) /* 28 */ #define TclWinCPUID \ (tclIntPlatStubsPtr->tclWinCPUID) /* 29 */ #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ #define TclGetAndDetachPids \ (tclIntPlatStubsPtr->tclGetAndDetachPids) /* 0 */ #define TclpCloseFile \ (tclIntPlatStubsPtr->tclpCloseFile) /* 1 */ #define TclpCreateCommandChannel \ | > > | 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 | (tclIntPlatStubsPtr->tclWinSetInterfaces) /* 26 */ #define TclWinFlushDirtyChannels \ (tclIntPlatStubsPtr->tclWinFlushDirtyChannels) /* 27 */ #define TclWinResetInterfaces \ (tclIntPlatStubsPtr->tclWinResetInterfaces) /* 28 */ #define TclWinCPUID \ (tclIntPlatStubsPtr->tclWinCPUID) /* 29 */ #define TclUnixOpenTemporaryFile \ (tclIntPlatStubsPtr->tclUnixOpenTemporaryFile) /* 30 */ #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ #define TclGetAndDetachPids \ (tclIntPlatStubsPtr->tclGetAndDetachPids) /* 0 */ #define TclpCloseFile \ (tclIntPlatStubsPtr->tclpCloseFile) /* 1 */ #define TclpCreateCommandChannel \ |
︙ | ︙ | |||
483 484 485 486 487 488 489 | (tclIntPlatStubsPtr->tclMacOSXSetFileAttribute) /* 16 */ #define TclMacOSXCopyFileAttributes \ (tclIntPlatStubsPtr->tclMacOSXCopyFileAttributes) /* 17 */ #define TclMacOSXMatchType \ (tclIntPlatStubsPtr->tclMacOSXMatchType) /* 18 */ #define TclMacOSXNotifierAddRunLoopMode \ (tclIntPlatStubsPtr->tclMacOSXNotifierAddRunLoopMode) /* 19 */ | | < > > | 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 | (tclIntPlatStubsPtr->tclMacOSXSetFileAttribute) /* 16 */ #define TclMacOSXCopyFileAttributes \ (tclIntPlatStubsPtr->tclMacOSXCopyFileAttributes) /* 17 */ #define TclMacOSXMatchType \ (tclIntPlatStubsPtr->tclMacOSXMatchType) /* 18 */ #define TclMacOSXNotifierAddRunLoopMode \ (tclIntPlatStubsPtr->tclMacOSXNotifierAddRunLoopMode) /* 19 */ /* Slot 20 is reserved */ /* Slot 21 is reserved */ /* Slot 22 is reserved */ /* Slot 23 is reserved */ /* Slot 24 is reserved */ /* Slot 25 is reserved */ /* Slot 26 is reserved */ /* Slot 27 is reserved */ /* Slot 28 is reserved */ #define TclWinCPUID \ (tclIntPlatStubsPtr->tclWinCPUID) /* 29 */ #define TclUnixOpenTemporaryFile \ (tclIntPlatStubsPtr->tclUnixOpenTemporaryFile) /* 30 */ #endif /* MACOSX */ #endif /* defined(USE_TCL_STUBS) */ /* !END!: Do not edit above this line. */ #if defined(__WIN32__) || defined(__CYGWIN__) |
︙ | ︙ |
Changes to generic/tclInterp.c.
︙ | ︙ | |||
1794 1795 1796 1797 1798 1799 1800 | /* * We are sending a 0-refCount obj, do not need a callback: it will be * cleaned up automatically. But we may need to clear the rootEnsemble * stuff ... */ if (isRootEnsemble) { | | | | 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 | /* * We are sending a 0-refCount obj, do not need a callback: it will be * cleaned up automatically. But we may need to clear the rootEnsemble * stuff ... */ if (isRootEnsemble) { TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL); } TclSkipTailcall(interp); return Tcl_NREvalObj(interp, listPtr, flags); } static int AliasObjCmd( ClientData clientData, /* Alias record. */ Tcl_Interp *interp, /* Current interpreter. */ |
︙ | ︙ |
Changes to generic/tclListObj.c.
︙ | ︙ | |||
904 905 906 907 908 909 910 911 912 913 914 915 916 917 | */ count = numElems - first; } isShared = (listRepPtr->refCount > 1); numRequired = numElems - count + objc; if ((numRequired <= listRepPtr->maxElemCount) && !isShared) { int shift; /* * Can use the current List struct. First "delete" count elements * starting at first. | > > > > | 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 | */ count = numElems - first; } isShared = (listRepPtr->refCount > 1); numRequired = numElems - count + objc; for (i = 0; i < objc; i++) { Tcl_IncrRefCount(objv[i]); } if ((numRequired <= listRepPtr->maxElemCount) && !isShared) { int shift; /* * Can use the current List struct. First "delete" count elements * starting at first. |
︙ | ︙ | |||
959 960 961 962 963 964 965 966 967 968 969 970 971 972 | + TCL_MIN_ELEMENT_GROWTH; int growth = (int) ((extra > limit) ? limit : extra); listRepPtr = AttemptNewList(NULL, numRequired + growth, NULL); if (listRepPtr == NULL) { listRepPtr = AttemptNewList(interp, numRequired, NULL); if (listRepPtr == NULL) { return TCL_ERROR; } } } listPtr->internalRep.twoPtrValue.ptr1 = listRepPtr; listRepPtr->refCount++; | > > > > > > > > | 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 | + TCL_MIN_ELEMENT_GROWTH; int growth = (int) ((extra > limit) ? limit : extra); listRepPtr = AttemptNewList(NULL, numRequired + growth, NULL); if (listRepPtr == NULL) { listRepPtr = AttemptNewList(interp, numRequired, NULL); if (listRepPtr == NULL) { for (i = 0; i < objc; i++) { /* See bug 3598580 */ #if TCL_MAJOR_VERSION > 8 Tcl_DecrRefCount(objv[i]); #else objv[i]->refCount--; #endif } return TCL_ERROR; } } } listPtr->internalRep.twoPtrValue.ptr1 = listRepPtr; listRepPtr->refCount++; |
︙ | ︙ | |||
1023 1024 1025 1026 1027 1028 1029 | } ckfree(oldListRepPtr); } } /* | | < < < | 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 | } ckfree(oldListRepPtr); } } /* * Insert the new elements into elemPtrs before "first". */ for (i=0,j=first ; i<objc ; i++,j++) { elemPtrs[j] = objv[i]; } /* * Update the count of elements. */ listRepPtr->elemCount = numRequired; |
︙ | ︙ |
Changes to generic/tclNamesp.c.
︙ | ︙ | |||
156 157 158 159 160 161 162 | /* * Array of values describing how to implement each standard subcommand of the * "namespace" command. */ static const EnsembleImplMap defaultNamespaceMap[] = { | | | | | | | | | | | | 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | /* * Array of values describing how to implement each standard subcommand of the * "namespace" command. */ static const EnsembleImplMap defaultNamespaceMap[] = { {"children", NamespaceChildrenCmd, TclCompileBasic0To2ArgCmd, NULL, NULL, 0}, {"code", NamespaceCodeCmd, TclCompileNamespaceCodeCmd, NULL, NULL, 0}, {"current", NamespaceCurrentCmd, TclCompileNamespaceCurrentCmd, NULL, NULL, 0}, {"delete", NamespaceDeleteCmd, TclCompileBasicMin0ArgCmd, NULL, NULL, 0}, {"ensemble", TclNamespaceEnsembleCmd, NULL, NULL, NULL, 0}, {"eval", NamespaceEvalCmd, NULL, NRNamespaceEvalCmd, NULL, 0}, {"exists", NamespaceExistsCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"export", NamespaceExportCmd, TclCompileBasicMin0ArgCmd, NULL, NULL, 0}, {"forget", NamespaceForgetCmd, TclCompileBasicMin0ArgCmd, NULL, NULL, 0}, {"import", NamespaceImportCmd, TclCompileBasicMin0ArgCmd, NULL, NULL, 0}, {"inscope", NamespaceInscopeCmd, NULL, NRNamespaceInscopeCmd, NULL, 0}, {"origin", NamespaceOriginCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"parent", NamespaceParentCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"path", NamespacePathCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"qualifiers", NamespaceQualifiersCmd, TclCompileNamespaceQualifiersCmd, NULL, NULL, 0}, {"tail", NamespaceTailCmd, TclCompileNamespaceTailCmd, NULL, NULL, 0}, {"unknown", NamespaceUnknownCmd, TclCompileBasic0Or1ArgCmd, NULL, NULL, 0}, {"upvar", NamespaceUpvarCmd, TclCompileNamespaceUpvarCmd, NULL, NULL, 0}, {"which", NamespaceWhichCmd, TclCompileNamespaceWhichCmd, NULL, NULL, 0}, {NULL, NULL, NULL, NULL, NULL, 0} }; /* *---------------------------------------------------------------------- |
︙ | ︙ | |||
419 420 421 422 423 424 425 | if ((nsPtr->flags & NS_DYING) && (nsPtr->activationCount - (nsPtr == iPtr->globalNsPtr) == 0)) { Tcl_DeleteNamespace((Tcl_Namespace *) nsPtr); } framePtr->nsPtr = NULL; if (framePtr->tailcallPtr) { | | | 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 | if ((nsPtr->flags & NS_DYING) && (nsPtr->activationCount - (nsPtr == iPtr->globalNsPtr) == 0)) { Tcl_DeleteNamespace((Tcl_Namespace *) nsPtr); } framePtr->nsPtr = NULL; if (framePtr->tailcallPtr) { TclSetTailcall(interp, framePtr->tailcallPtr); } } /* *---------------------------------------------------------------------- * * TclPushStackFrame -- |
︙ | ︙ | |||
1941 1942 1943 1944 1945 1946 1947 | Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { ImportedCmdData *dataPtr = clientData; Command *realCmdPtr = dataPtr->realCmdPtr; | | | 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 | Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* The argument objects. */ { ImportedCmdData *dataPtr = clientData; Command *realCmdPtr = dataPtr->realCmdPtr; TclSkipTailcall(interp); return Tcl_NRCmdSwap(interp, (Tcl_Command) realCmdPtr, objc, objv, 0); } static int InvokeImportedCmd( ClientData clientData, /* Points to the imported command's * ImportedCmdData structure. */ |
︙ | ︙ |
Changes to generic/tclOO.c.
︙ | ︙ | |||
839 840 841 842 843 844 845 | if (contextPtr != NULL) { contextPtr->callPtr->flags |= DESTRUCTOR; contextPtr->skip = 0; state = Tcl_SaveInterpState(interp, TCL_OK); result = Tcl_NRCallObjProc(interp, TclOOInvokeContext, contextPtr, 0, NULL); if (result != TCL_OK) { | | | 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 | if (contextPtr != NULL) { contextPtr->callPtr->flags |= DESTRUCTOR; contextPtr->skip = 0; state = Tcl_SaveInterpState(interp, TCL_OK); result = Tcl_NRCallObjProc(interp, TclOOInvokeContext, contextPtr, 0, NULL); if (result != TCL_OK) { Tcl_BackgroundException(interp, result); } Tcl_RestoreInterpState(interp, state); TclOODeleteContext(contextPtr); } } /* |
︙ | ︙ |
Changes to generic/tclOO.h.
︙ | ︙ | |||
35 36 37 38 39 40 41 | * * tests/oo.test * tests/ooNext2.test * unix/tclooConfig.sh * win/tclooConfig.sh */ | | | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | * * tests/oo.test * tests/ooNext2.test * unix/tclooConfig.sh * win/tclooConfig.sh */ #define TCLOO_VERSION "1.0" #define TCLOO_PATCHLEVEL TCLOO_VERSION /* * These are opaque types. */ typedef struct Tcl_Class_ *Tcl_Class; |
︙ | ︙ |
Changes to generic/tclOOInfo.c.
︙ | ︙ | |||
44 45 46 47 48 49 50 | static Tcl_ObjCmdProc InfoClassVariablesCmd; /* * List of commands that are used to implement the [info object] subcommands. */ static const EnsembleImplMap infoObjectCmds[] = { | | | | | | | | | | | | | | | | | | | | | | | > < < < | < < < < < < | | | | < < | < < | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | static Tcl_ObjCmdProc InfoClassVariablesCmd; /* * List of commands that are used to implement the [info object] subcommands. */ static const EnsembleImplMap infoObjectCmds[] = { {"call", InfoObjectCallCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"class", InfoObjectClassCmd, TclCompileInfoObjectClassCmd, NULL, NULL, 0}, {"definition", InfoObjectDefnCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"filters", InfoObjectFiltersCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"forward", InfoObjectForwardCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"isa", InfoObjectIsACmd, TclCompileInfoObjectIsACmd, NULL, NULL, 0}, {"methods", InfoObjectMethodsCmd, TclCompileBasicMin1ArgCmd, NULL, NULL, 0}, {"methodtype", InfoObjectMethodTypeCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"mixins", InfoObjectMixinsCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"namespace", InfoObjectNsCmd, TclCompileInfoObjectNamespaceCmd, NULL, NULL, 0}, {"variables", InfoObjectVariablesCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"vars", InfoObjectVarsCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, {NULL, NULL, NULL, NULL, NULL, 0} }; /* * List of commands that are used to implement the [info class] subcommands. */ static const EnsembleImplMap infoClassCmds[] = { {"call", InfoClassCallCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"constructor", InfoClassConstrCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"definition", InfoClassDefnCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"destructor", InfoClassDestrCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"filters", InfoClassFiltersCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"forward", InfoClassForwardCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"instances", InfoClassInstancesCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, {"methods", InfoClassMethodsCmd, TclCompileBasicMin1ArgCmd, NULL, NULL, 0}, {"methodtype", InfoClassMethodTypeCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"mixins", InfoClassMixinsCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"subclasses", InfoClassSubsCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, {"superclasses", InfoClassSupersCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"variables", InfoClassVariablesCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {NULL, NULL, NULL, NULL, NULL, 0} }; /* * ---------------------------------------------------------------------- * * TclOOInitInfo -- * * Adjusts the Tcl core [info] command to contain subcommands ("object" * and "class") for introspection of objects and classes. * * ---------------------------------------------------------------------- */ void TclOOInitInfo( Tcl_Interp *interp) { Tcl_Command infoCmd; Tcl_Obj *mapDict; /* * Build the ensembles used to implement [info object] and [info class]. */ TclMakeEnsemble(interp, "::oo::InfoObject", infoObjectCmds); TclMakeEnsemble(interp, "::oo::InfoClass", infoClassCmds); /* * Install into the master [info] ensemble. */ infoCmd = Tcl_FindCommand(interp, "info", NULL, TCL_GLOBAL_ONLY); Tcl_GetEnsembleMappingDict(NULL, infoCmd, &mapDict); Tcl_DictObjPut(NULL, mapDict, Tcl_NewStringObj("object", -1), Tcl_NewStringObj("::oo::InfoObject", -1)); Tcl_DictObjPut(NULL, mapDict, Tcl_NewStringObj("class", -1), Tcl_NewStringObj("::oo::InfoClass", -1)); Tcl_SetEnsembleMappingDict(interp, infoCmd, mapDict); } /* * ---------------------------------------------------------------------- * * GetClassFromObj -- * |
︙ | ︙ |
Changes to generic/tclOOStubLib.c.
1 2 3 4 | /* * ORIGINAL SOURCE: tk/generic/tkStubLib.c, version 1.9 2004/03/17 */ | < < < < < < < < < < < < < | | > | | < < < < < < | < < < < < | | | | < | < < | > > > | > | < | | | | | | | > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | /* * ORIGINAL SOURCE: tk/generic/tkStubLib.c, version 1.9 2004/03/17 */ #include "tclOOInt.h" MODULE_SCOPE const TclOOStubs *tclOOStubsPtr; MODULE_SCOPE const TclOOIntStubs *tclOOIntStubsPtr; const TclOOStubs *tclOOStubsPtr = NULL; const TclOOIntStubs *tclOOIntStubsPtr = NULL; /* *---------------------------------------------------------------------- * * TclOOInitializeStubs -- * Load the tclOO package, initialize stub table pointer. Do not call * this function directly, use Tcl_OOInitStubs() macro instead. * * Results: * The actual version of the package that satisfies the request, or NULL * to indicate that an error occurred. * * Side effects: * Sets the stub table pointers. * *---------------------------------------------------------------------- */ MODULE_SCOPE const char * TclOOInitializeStubs( Tcl_Interp *interp, const char *version) { int exact = 0; const char *packageName = "TclOO"; const char *errMsg = NULL; TclOOStubs *stubsPtr = NULL; const char *actualVersion = tclStubsPtr->tcl_PkgRequireEx(interp, packageName, version, exact, &stubsPtr); if (actualVersion == NULL) { return NULL; } if (stubsPtr == NULL) { errMsg = "missing stub table pointer"; } else { tclOOStubsPtr = stubsPtr; if (stubsPtr->hooks) { tclOOIntStubsPtr = stubsPtr->hooks->tclOOIntStubs; } else { tclOOIntStubsPtr = NULL; } return actualVersion; } tclStubsPtr->tcl_ResetResult(interp); tclStubsPtr->tcl_AppendResult(interp, "Error loading ", packageName, " (requested version ", version, ", actual version ", actualVersion, "): ", errMsg, NULL); return NULL; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ |
Changes to generic/tclPkg.c.
︙ | ︙ | |||
351 352 353 354 355 356 357 358 359 360 361 362 363 364 | Package *pkgPtr; PkgAvail *availPtr, *bestPtr, *bestStablePtr; char *availVersion, *bestVersion; /* Internal rep. of versions */ int availStable, code, satisfies, pass; char *script, *pkgVersionI; Tcl_DString command; /* * It can take up to three passes to find the package: one pass to run the * "package unknown" script, one to run the "package ifneeded" script for * a specific version, and a final pass to lookup the package loaded by * the "package ifneeded" script. */ | > > > > | 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 | Package *pkgPtr; PkgAvail *availPtr, *bestPtr, *bestStablePtr; char *availVersion, *bestVersion; /* Internal rep. of versions */ int availStable, code, satisfies, pass; char *script, *pkgVersionI; Tcl_DString command; if (TCL_OK != CheckAllRequirements(interp, reqc, reqv)) { return NULL; } /* * It can take up to three passes to find the package: one pass to run the * "package unknown" script, one to run the "package ifneeded" script for * a specific version, and a final pass to lookup the package loaded by * the "package ifneeded" script. */ |
︙ | ︙ |
Changes to generic/tclPort.h.
︙ | ︙ | |||
15 16 17 18 19 20 21 | #define _TCLPORT #ifdef HAVE_TCL_CONFIG_H #include "tclConfig.h" #endif #if defined(_WIN32) # include "tclWinPort.h" | | < < > | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | #define _TCLPORT #ifdef HAVE_TCL_CONFIG_H #include "tclConfig.h" #endif #if defined(_WIN32) # include "tclWinPort.h" #else # include "tclUnixPort.h" #endif #include "tcl.h" #if !defined(LLONG_MIN) # ifdef TCL_WIDE_INT_IS_LONG # define LLONG_MIN LONG_MIN # else # ifdef LLONG_BIT # define LLONG_MIN ((Tcl_WideInt)(Tcl_LongAsWide(1)<<(LLONG_BIT-1))) |
︙ | ︙ |
Changes to generic/tclResult.c.
︙ | ︙ | |||
1274 1275 1276 1277 1278 1279 1280 | Tcl_DictObjPut(NULL, options, keys[KEY_CODE], Tcl_NewIntObj(result)); Tcl_DictObjPut(NULL, options, keys[KEY_LEVEL], Tcl_NewIntObj(0)); } if (result == TCL_ERROR) { | | | 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 | Tcl_DictObjPut(NULL, options, keys[KEY_CODE], Tcl_NewIntObj(result)); Tcl_DictObjPut(NULL, options, keys[KEY_LEVEL], Tcl_NewIntObj(0)); } if (result == TCL_ERROR) { Tcl_AddErrorInfo(interp, ""); Tcl_DictObjPut(NULL, options, keys[KEY_ERRORSTACK], iPtr->errorStack); } if (iPtr->errorCode) { Tcl_DictObjPut(NULL, options, keys[KEY_ERRORCODE], iPtr->errorCode); } if (iPtr->errorInfo) { Tcl_DictObjPut(NULL, options, keys[KEY_ERRORINFO], iPtr->errorInfo); |
︙ | ︙ |
Changes to generic/tclStubInit.c.
︙ | ︙ | |||
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | #undef Tcl_ValidateAllMemory #undef Tcl_FindHashEntry #undef Tcl_CreateHashEntry #undef Tcl_Panic #undef Tcl_FindExecutable #undef TclpGetPid #undef TclSockMinimumBuffers #if defined(_WIN32) || defined(__CYGWIN__) #undef TclWinNToHS #define TclWinNToHS winNToHS static unsigned short TclWinNToHS(unsigned short ns) { return ntohs(ns); } #endif #ifdef __WIN32__ # define TclUnixWaitForFile 0 # define TclUnixCopyFile 0 # define TclpReaddir 0 # define TclpIsAtty 0 #elif defined(__CYGWIN__) # define TclpIsAtty TclPlatIsAtty # define TclWinSetInterfaces (void (*) (int)) doNothing # define TclWinAddProcess (void (*) (void *, unsigned int)) doNothing # define TclWinFlushDirtyChannels doNothing | > > > > > > > > > > > > > > > > > > > > > > > > > > | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | #undef Tcl_ValidateAllMemory #undef Tcl_FindHashEntry #undef Tcl_CreateHashEntry #undef Tcl_Panic #undef Tcl_FindExecutable #undef TclpGetPid #undef TclSockMinimumBuffers #define TclSetStartupScriptPath setStartupScriptPath static void TclSetStartupScriptPath(Tcl_Obj *path) { Tcl_SetStartupScript(path, NULL); } #define TclGetStartupScriptPath getStartupScriptPath static Tcl_Obj *TclGetStartupScriptPath(void) { return Tcl_GetStartupScript(NULL); } #define TclSetStartupScriptFileName setStartupScriptFileName static void TclSetStartupScriptFileName( const char *fileName) { Tcl_SetStartupScript(Tcl_NewStringObj(fileName,-1), NULL); } #define TclGetStartupScriptFileName getStartupScriptFileName static const char *TclGetStartupScriptFileName(void) { Tcl_Obj *path = Tcl_GetStartupScript(NULL); if (path == NULL) { return NULL; } return Tcl_GetStringFromObj(path, NULL); } #if defined(_WIN32) || defined(__CYGWIN__) #undef TclWinNToHS #define TclWinNToHS winNToHS static unsigned short TclWinNToHS(unsigned short ns) { return ntohs(ns); } #endif #ifdef __WIN32__ # define TclUnixWaitForFile 0 # define TclUnixCopyFile 0 # define TclUnixOpenTemporaryFile 0 # define TclpReaddir 0 # define TclpIsAtty 0 #elif defined(__CYGWIN__) # define TclpIsAtty TclPlatIsAtty # define TclWinSetInterfaces (void (*) (int)) doNothing # define TclWinAddProcess (void (*) (void *, unsigned int)) doNothing # define TclWinFlushDirtyChannels doNothing |
︙ | ︙ | |||
327 328 329 330 331 332 333 | TclRegExpRangeUniChar, /* 151 */ TclSetLibraryPath, /* 152 */ TclGetLibraryPath, /* 153 */ 0, /* 154 */ 0, /* 155 */ TclRegError, /* 156 */ TclVarTraceExists, /* 157 */ | | | | | | | | 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 | TclRegExpRangeUniChar, /* 151 */ TclSetLibraryPath, /* 152 */ TclGetLibraryPath, /* 153 */ 0, /* 154 */ 0, /* 155 */ TclRegError, /* 156 */ TclVarTraceExists, /* 157 */ TclSetStartupScriptFileName, /* 158 */ TclGetStartupScriptFileName, /* 159 */ 0, /* 160 */ TclChannelTransform, /* 161 */ TclChannelEventScriptInvoker, /* 162 */ TclGetInstructionTable, /* 163 */ TclExpandCodeArray, /* 164 */ TclpSetInitialEncodings, /* 165 */ TclListObjSetElement, /* 166 */ TclSetStartupScriptPath, /* 167 */ TclGetStartupScriptPath, /* 168 */ TclpUtfNcmp2, /* 169 */ TclCheckInterpTraces, /* 170 */ TclCheckExecutionTraces, /* 171 */ TclInThreadExit, /* 172 */ TclUniCharMatch, /* 173 */ 0, /* 174 */ TclCallVarTraces, /* 175 */ TclCleanupVar, /* 176 */ TclVarErrMsg, /* 177 */ Tcl_SetStartupScript, /* 178 */ Tcl_GetStartupScript, /* 179 */ 0, /* 180 */ 0, /* 181 */ 0, /* 182 */ 0, /* 183 */ 0, /* 184 */ 0, /* 185 */ 0, /* 186 */ |
︙ | ︙ | |||
446 447 448 449 450 451 452 | TclpInetNtoa, /* 13 */ TclUnixCopyFile, /* 14 */ 0, /* 15 */ 0, /* 16 */ 0, /* 17 */ 0, /* 18 */ 0, /* 19 */ | | > | 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 | TclpInetNtoa, /* 13 */ TclUnixCopyFile, /* 14 */ 0, /* 15 */ 0, /* 16 */ 0, /* 17 */ 0, /* 18 */ 0, /* 19 */ 0, /* 20 */ 0, /* 21 */ 0, /* 22 */ 0, /* 23 */ 0, /* 24 */ 0, /* 25 */ 0, /* 26 */ 0, /* 27 */ 0, /* 28 */ TclWinCPUID, /* 29 */ TclUnixOpenTemporaryFile, /* 30 */ #endif /* UNIX */ #if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */ TclWinConvertError, /* 0 */ 0, /* 1 */ TclWinGetServByName, /* 2 */ TclWinGetSockOpt, /* 3 */ TclWinGetTclInstance, /* 4 */ |
︙ | ︙ | |||
488 489 490 491 492 493 494 495 496 497 498 499 500 501 | 0, /* 23 */ TclWinNoBackslash, /* 24 */ 0, /* 25 */ TclWinSetInterfaces, /* 26 */ TclWinFlushDirtyChannels, /* 27 */ TclWinResetInterfaces, /* 28 */ TclWinCPUID, /* 29 */ #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ TclGetAndDetachPids, /* 0 */ TclpCloseFile, /* 1 */ TclpCreateCommandChannel, /* 2 */ TclpCreatePipe, /* 3 */ TclpCreateProcess, /* 4 */ | > | 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 | 0, /* 23 */ TclWinNoBackslash, /* 24 */ 0, /* 25 */ TclWinSetInterfaces, /* 26 */ TclWinFlushDirtyChannels, /* 27 */ TclWinResetInterfaces, /* 28 */ TclWinCPUID, /* 29 */ TclUnixOpenTemporaryFile, /* 30 */ #endif /* WIN */ #ifdef MAC_OSX_TCL /* MACOSX */ TclGetAndDetachPids, /* 0 */ TclpCloseFile, /* 1 */ TclpCreateCommandChannel, /* 2 */ TclpCreatePipe, /* 3 */ TclpCreateProcess, /* 4 */ |
︙ | ︙ | |||
510 511 512 513 514 515 516 | TclpInetNtoa, /* 13 */ TclUnixCopyFile, /* 14 */ TclMacOSXGetFileAttribute, /* 15 */ TclMacOSXSetFileAttribute, /* 16 */ TclMacOSXCopyFileAttributes, /* 17 */ TclMacOSXMatchType, /* 18 */ TclMacOSXNotifierAddRunLoopMode, /* 19 */ | | > | 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 | TclpInetNtoa, /* 13 */ TclUnixCopyFile, /* 14 */ TclMacOSXGetFileAttribute, /* 15 */ TclMacOSXSetFileAttribute, /* 16 */ TclMacOSXCopyFileAttributes, /* 17 */ TclMacOSXMatchType, /* 18 */ TclMacOSXNotifierAddRunLoopMode, /* 19 */ 0, /* 20 */ 0, /* 21 */ 0, /* 22 */ 0, /* 23 */ 0, /* 24 */ 0, /* 25 */ 0, /* 26 */ 0, /* 27 */ 0, /* 28 */ TclWinCPUID, /* 29 */ TclUnixOpenTemporaryFile, /* 30 */ #endif /* MACOSX */ }; static const TclPlatStubs tclPlatStubs = { TCL_STUB_MAGIC, 0, #if defined(__WIN32__) || defined(__CYGWIN__) /* WIN */ |
︙ | ︙ |
Changes to generic/tclStubLib.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* * tclStubLib.c -- * * Stub object that will be statically linked into extensions that want * to access Tcl. * * Copyright (c) 1998-1999 by Scriptics Corporation. * Copyright (c) 1998 Paul Duffin. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | /* * tclStubLib.c -- * * Stub object that will be statically linked into extensions that want * to access Tcl. * * Copyright (c) 1998-1999 by Scriptics Corporation. * Copyright (c) 1998 Paul Duffin. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" MODULE_SCOPE const TclStubs *tclStubsPtr; MODULE_SCOPE const TclPlatStubs *tclPlatStubsPtr; MODULE_SCOPE const TclIntStubs *tclIntStubsPtr; MODULE_SCOPE const TclIntPlatStubs *tclIntPlatStubsPtr; const TclStubs *tclStubsPtr = NULL; const TclPlatStubs *tclPlatStubsPtr = NULL; const TclIntStubs *tclIntStubsPtr = NULL; const TclIntPlatStubs *tclIntPlatStubsPtr = NULL; /* * Use our own isDigit to avoid linking to libc on windows */ static int isDigit(const int c) { return (c >= '0' && c <= '9'); } |
︙ | ︙ | |||
74 75 76 77 78 79 80 | * indicate that an error occurred. * * Side effects: * Sets the stub table pointers. * *---------------------------------------------------------------------- */ | | > > | | > > | | | | | | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | * indicate that an error occurred. * * Side effects: * Sets the stub table pointers. * *---------------------------------------------------------------------- */ #undef Tcl_InitStubs MODULE_SCOPE const char * TclInitStubs( Tcl_Interp *interp, const char *version, int exact, const char *tclversion, int magic) { Interp *iPtr = (Interp *) interp; const char *actualVersion = NULL; ClientData pkgData = NULL; const TclStubs *stubsPtr = iPtr->stubTable; /* * We can't optimize this check by caching tclStubsPtr because that * prevents apps from being able to load/unload Tcl dynamically multiple * times. [Bug 615304] */ if (!stubsPtr || (stubsPtr->magic != TCL_STUB_MAGIC)) { iPtr->legacyResult = "interpreter uses an incompatible stubs mechanism"; iPtr->legacyFreeProc = 0; /* TCL_STATIC */ 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 (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 = (TclStubs *)pkgData; if (tclStubsPtr->hooks) { tclPlatStubsPtr = tclStubsPtr->hooks->tclPlatStubs; tclIntStubsPtr = tclStubsPtr->hooks->tclIntStubs; tclIntPlatStubsPtr = tclStubsPtr->hooks->tclIntPlatStubs; } else { tclPlatStubsPtr = NULL; |
︙ | ︙ |
Changes to generic/tclTest.c.
︙ | ︙ | |||
15 16 17 18 19 20 21 22 23 24 25 26 27 28 | * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #undef STATIC_BUILD #ifndef USE_TCL_STUBS # define USE_TCL_STUBS #endif #include "tclInt.h" #include "tclOO.h" #include <math.h> /* * Required for Testregexp*Cmd */ | > | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #undef STATIC_BUILD #ifndef USE_TCL_STUBS # define USE_TCL_STUBS #endif #include <sys/stat.h> #include "tclInt.h" #include "tclOO.h" #include <math.h> /* * Required for Testregexp*Cmd */ |
︙ | ︙ |
Changes to generic/tclTestObj.c.
︙ | ︙ | |||
959 960 961 962 963 964 965 966 967 968 969 970 971 972 | } string = Tcl_GetString(objv[3]); if (GetVariableIndex(interp, string, &destIndex) != TCL_OK) { return TCL_ERROR; } SetVarToObj(varPtr, destIndex, varPtr[varIndex]); Tcl_SetObjResult(interp, varPtr[destIndex]); } else if (strcmp(subCmd, "convert") == 0) { const char *typeName; if (objc != 4) { goto wrongNumArgs; } index = Tcl_GetString(objv[2]); | > > > > > > > > > > > | 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 | } string = Tcl_GetString(objv[3]); if (GetVariableIndex(interp, string, &destIndex) != TCL_OK) { return TCL_ERROR; } SetVarToObj(varPtr, destIndex, varPtr[varIndex]); Tcl_SetObjResult(interp, varPtr[destIndex]); } else if (strcmp(subCmd, "bug3598580") == 0) { Tcl_Obj *listObjPtr, *elemObjPtr; if (objc != 2) { goto wrongNumArgs; } elemObjPtr = Tcl_NewIntObj(123); listObjPtr = Tcl_NewListObj(1, &elemObjPtr); /* Replace the single list element through itself, nonsense but legal. */ Tcl_ListObjReplace(interp, listObjPtr, 0, 1, 1, &elemObjPtr); Tcl_SetObjResult(interp, listObjPtr); return TCL_OK; } else if (strcmp(subCmd, "convert") == 0) { const char *typeName; if (objc != 4) { goto wrongNumArgs; } index = Tcl_GetString(objv[2]); |
︙ | ︙ |
Changes to generic/tclThreadTest.c.
︙ | ︙ | |||
509 510 511 512 513 514 515 | joinable = joinable ? TCL_THREAD_JOINABLE : TCL_THREAD_NOFLAGS; Tcl_MutexLock(&threadMutex); if (Tcl_CreateThread(&id, NewTestThread, (ClientData) &ctrl, TCL_THREAD_STACK_DEFAULT, joinable) != TCL_OK) { Tcl_MutexUnlock(&threadMutex); Tcl_AppendResult(interp, "can't create a new thread", NULL); | < | 509 510 511 512 513 514 515 516 517 518 519 520 521 522 | joinable = joinable ? TCL_THREAD_JOINABLE : TCL_THREAD_NOFLAGS; Tcl_MutexLock(&threadMutex); if (Tcl_CreateThread(&id, NewTestThread, (ClientData) &ctrl, TCL_THREAD_STACK_DEFAULT, joinable) != TCL_OK) { Tcl_MutexUnlock(&threadMutex); Tcl_AppendResult(interp, "can't create a new thread", NULL); return TCL_ERROR; } /* * Wait for the thread to start because it is using something on our stack! */ |
︙ | ︙ | |||
923 924 925 926 927 928 929 | ckfree(resultPtr->errorCode); } if (resultPtr->errorInfo) { Tcl_AddErrorInfo(interp, resultPtr->errorInfo); ckfree(resultPtr->errorInfo); } } | | > | 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 | ckfree(resultPtr->errorCode); } if (resultPtr->errorInfo) { Tcl_AddErrorInfo(interp, resultPtr->errorInfo); ckfree(resultPtr->errorInfo); } } Tcl_AppendResult(interp, resultPtr->result, NULL); Tcl_ConditionFinalize(&resultPtr->done); code = resultPtr->code; ckfree(resultPtr->result); ckfree(resultPtr); return code; } /* *------------------------------------------------------------------------ |
︙ | ︙ |
Changes to generic/tclTomMathInterface.c.
︙ | ︙ | |||
107 108 109 110 111 112 113 | *---------------------------------------------------------------------- */ extern void * TclBNAlloc( size_t x) { | | | 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | *---------------------------------------------------------------------- */ extern void * TclBNAlloc( size_t x) { return (void *) ckalloc((unsigned int) x); } /* *---------------------------------------------------------------------- * * TclBNRealloc -- * |
︙ | ︙ | |||
131 132 133 134 135 136 137 | */ void * TclBNRealloc( void *p, size_t s) { | | | 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | */ void * TclBNRealloc( void *p, size_t s) { return (void *) ckrealloc((char *) p, (unsigned int) s); } /* *---------------------------------------------------------------------- * * TclBNFree -- * |
︙ | ︙ | |||
157 158 159 160 161 162 163 | *---------------------------------------------------------------------- */ extern void TclBNFree( void *p) { | | | 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | *---------------------------------------------------------------------- */ extern void TclBNFree( void *p) { ckree((char *) p); } #endif /* *---------------------------------------------------------------------- * * TclBNInitBignumFromLong -- |
︙ | ︙ |
Changes to generic/tclTomMathStubLib.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* * tclTomMathStubLib.c -- * * Stub object that will be statically linked into extensions that want * to access Tcl. * * Copyright (c) 1998-1999 by Scriptics Corporation. * Copyright (c) 1998 Paul Duffin. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ | < < < < < < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /* * tclTomMathStubLib.c -- * * Stub object that will be statically linked into extensions that want * to access Tcl. * * Copyright (c) 1998-1999 by Scriptics Corporation. * Copyright (c) 1998 Paul Duffin. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" MODULE_SCOPE const TclTomMathStubs *tclTomMathStubsPtr; const TclTomMathStubs *tclTomMathStubsPtr = NULL; |
︙ | ︙ | |||
51 52 53 54 55 56 57 | int epoch, /* Stubs table epoch from the header files */ int revision) /* Stubs table revision number from the * header files */ { int exact = 0; const char *packageName = "tcl::tommath"; const char *errMsg = NULL; | | | | < | | | | | | | | | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | int epoch, /* Stubs table epoch from the header files */ int revision) /* Stubs table revision number from the * header files */ { int exact = 0; const char *packageName = "tcl::tommath"; const char *errMsg = NULL; TclTomMathStubs *stubsPtr = NULL; const char *actualVersion = tclStubsPtr->tcl_PkgRequireEx(interp, packageName, version, exact, &stubsPtr); if (actualVersion == NULL) { return NULL; } if (stubsPtr == NULL) { errMsg = "missing stub table pointer"; } else if(stubsPtr->tclBN_epoch() != epoch) { errMsg = "epoch number mismatch"; } else if(stubsPtr->tclBN_revision() != revision) { errMsg = "requires a later revision"; } else { tclTomMathStubsPtr = stubsPtr; return actualVersion; } tclStubsPtr->tcl_ResetResult(interp); tclStubsPtr->tcl_AppendResult(interp, "Error loading ", packageName, " (requested version ", version, ", actual version ", actualVersion, "): ", errMsg, NULL); return NULL; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ |
Changes to generic/tclTrace.c.
︙ | ︙ | |||
1318 1319 1320 1321 1322 1323 1324 | if (flags & TCL_TRACE_DESTROYED) { tcmdPtr->flags |= TCL_TRACE_DESTROYED; } code = Tcl_EvalEx(interp, Tcl_DStringValue(&cmd), Tcl_DStringLength(&cmd), 0); if (code != TCL_OK) { /* We ignore errors in these traced commands */ | | | 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 | if (flags & TCL_TRACE_DESTROYED) { tcmdPtr->flags |= TCL_TRACE_DESTROYED; } code = Tcl_EvalEx(interp, Tcl_DStringValue(&cmd), Tcl_DStringLength(&cmd), 0); if (code != TCL_OK) { /* We ignore errors in these traced commands */ /*** QUESTION: Use Tcl_BackgroundException(interp, code); instead? ***/ } Tcl_DStringFree(&cmd); } /* * We delete when the trace was destroyed or if this is a delete trace, * because command deletes are unconditional, so the trace must go away. |
︙ | ︙ |
Changes to generic/tclUtil.c.
︙ | ︙ | |||
163 164 165 166 167 168 169 | * in Tcl lists. * * * The NUL byte ought not appear, as it is not in strings properly * encoded for Tcl, but if it is present, it is not treated as * separating whitespace, or a string terminator. It is just another * character in a list element. * | | | | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | * in Tcl lists. * * * The NUL byte ought not appear, as it is not in strings properly * encoded for Tcl, but if it is present, it is not treated as * separating whitespace, or a string terminator. It is just another * character in a list element. * * The interpretation of a formatted substring as a list element follows rules * similar to the parsing of the words of a command in a Tcl script. Backslash * substitution plays a key role, and is defined exactly as it is in command * parsing. The same routine, TclParseBackslash() is used in both command * parsing and list parsing. * * NOTE: This means that if and when backslash substitution rules ever change * for command parsing, the interpretation of strings as lists also changes. * * Backslash substitution replaces an "escape sequence" of one or more * characters starting with * \u005c \ BACKSLASH * with a single character. The one character escape sequence case happens only * when BACKSLASH is the last character in the string. In all other cases, the * escape sequence is at least two characters long. * * The formatted substrings are interpreted as element values according to the * following cases: * * * If the first character of a formatted substring is |
︙ | ︙ | |||
2823 2824 2825 2826 2827 2828 2829 | Tcl_Obj * TclDStringToObj( Tcl_DString *dsPtr) { Tcl_Obj *result; | > | | | | | | | | > | 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 | Tcl_Obj * TclDStringToObj( Tcl_DString *dsPtr) { Tcl_Obj *result; if (dsPtr->string == dsPtr->staticSpace) { if (dsPtr->length == 0) { TclNewObj(result); } else { /* * Static buffer, so must copy. */ TclNewStringObj(result, dsPtr->string, dsPtr->length); } } else { /* * Dynamic buffer, so transfer ownership and reset. */ TclNewObj(result); result->bytes = dsPtr->string; |
︙ | ︙ |
Changes to generic/tclVar.c.
︙ | ︙ | |||
43 44 45 46 47 48 49 50 51 52 53 54 55 56 | Tcl_HashSearch *searchPtr); static inline Var * VarHashNextVar(Tcl_HashSearch *searchPtr); static inline void CleanupVar(Var *varPtr, Var *arrayPtr); #define VarHashGetValue(hPtr) \ ((Var *) ((char *)hPtr - TclOffset(VarInHash, entry))) static inline Var * VarHashCreateVar( TclVarHashTable *tablePtr, Tcl_Obj *key, int *newPtr) { Tcl_HashEntry *hPtr = Tcl_CreateHashEntry(&tablePtr->table, | > > > > > > > | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | Tcl_HashSearch *searchPtr); static inline Var * VarHashNextVar(Tcl_HashSearch *searchPtr); static inline void CleanupVar(Var *varPtr, Var *arrayPtr); #define VarHashGetValue(hPtr) \ ((Var *) ((char *)hPtr - TclOffset(VarInHash, entry))) /* * NOTE: VarHashCreateVar increments the recount of its key argument. * All callers that will call Tcl_DecrRefCount on that argument must * call Tcl_IncrRefCount on it before passing it in. This requirement * can bubble up to callers of callers .... etc. */ static inline Var * VarHashCreateVar( TclVarHashTable *tablePtr, Tcl_Obj *key, int *newPtr) { Tcl_HashEntry *hPtr = Tcl_CreateHashEntry(&tablePtr->table, |
︙ | ︙ | |||
379 380 381 382 383 384 385 | * name, if it doesn't already exist. If 0, * return error if it doesn't exist. */ Var **arrayPtrPtr) /* If the name refers to an element of an * array, *arrayPtrPtr gets filled in with * address of array variable. Otherwise this * is set to NULL. */ { | < > | | > | 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 | * name, if it doesn't already exist. If 0, * return error if it doesn't exist. */ Var **arrayPtrPtr) /* If the name refers to an element of an * array, *arrayPtrPtr gets filled in with * address of array variable. Otherwise this * is set to NULL. */ { Var *varPtr; Tcl_Obj *part1Ptr = Tcl_NewStringObj(part1, -1); if (createPart1) { Tcl_IncrRefCount(part1Ptr); } varPtr = TclObjLookupVar(interp, part1Ptr, part2, flags, msg, createPart1, createPart2, arrayPtrPtr); TclDecrRefCount(part1Ptr); return varPtr; } |
︙ | ︙ | |||
428 429 430 431 432 433 434 435 436 437 438 439 440 441 | * VAR_UNDEFINED) by a trace. * * Side effects: * New hashtable entries may be created if createPart1 or createPart2 * are 1. The object part1Ptr is converted to one of localVarNameType, * tclNsVarNameType or tclParsedVarNameType and caches as much of the * lookup as it can. * *---------------------------------------------------------------------- */ Var * TclObjLookupVar( Tcl_Interp *interp, /* Interpreter to use for lookup. */ | > > | 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 | * VAR_UNDEFINED) by a trace. * * Side effects: * New hashtable entries may be created if createPart1 or createPart2 * are 1. The object part1Ptr is converted to one of localVarNameType, * tclNsVarNameType or tclParsedVarNameType and caches as much of the * lookup as it can. * When createPart1 is 1, callers must IncrRefCount part1Ptr if they * plan to DecrRefCount it. * *---------------------------------------------------------------------- */ Var * TclObjLookupVar( Tcl_Interp *interp, /* Interpreter to use for lookup. */ |
︙ | ︙ | |||
456 457 458 459 460 461 462 | * name, if it doesn't already exist. If 0, * return error if it doesn't exist. */ Var **arrayPtrPtr) /* If the name refers to an element of an * array, *arrayPtrPtr gets filled in with * address of array variable. Otherwise this * is set to NULL. */ { | | < < < | 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 | * name, if it doesn't already exist. If 0, * return error if it doesn't exist. */ Var **arrayPtrPtr) /* If the name refers to an element of an * array, *arrayPtrPtr gets filled in with * address of array variable. Otherwise this * is set to NULL. */ { Tcl_Obj *part2Ptr = NULL; Var *resPtr; if (part2) { part2Ptr = Tcl_NewStringObj(part2, -1); } resPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr, flags, msg, createPart1, createPart2, arrayPtrPtr); if (part2Ptr) { Tcl_DecrRefCount(part2Ptr); |
︙ | ︙ | |||
840 841 842 843 844 845 846 847 848 849 850 851 852 853 | * if create is 1 (this only causes the hash table entry to be created). * For example, the variable might be a global that has been unset but is * still referenced by a procedure, or a variable that has been unset but * it only being kept in existence (if VAR_UNDEFINED) by a trace. * * Side effects: * A new hashtable entry may be created if create is 1. * *---------------------------------------------------------------------- */ Var * TclLookupSimpleVar( Tcl_Interp *interp, /* Interpreter to use for lookup. */ | > | 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 | * if create is 1 (this only causes the hash table entry to be created). * For example, the variable might be a global that has been unset but is * still referenced by a procedure, or a variable that has been unset but * it only being kept in existence (if VAR_UNDEFINED) by a trace. * * Side effects: * A new hashtable entry may be created if create is 1. * Callers must Incr varNamePtr if they plan to Decr it if create is 1. * *---------------------------------------------------------------------- */ Var * TclLookupSimpleVar( Tcl_Interp *interp, /* Interpreter to use for lookup. */ |
︙ | ︙ | |||
1307 1308 1309 1310 1311 1312 1313 | const char *part1, /* Name of an array (if part2 is non-NULL) or * the name of a variable. */ const char *part2, /* If non-NULL, gives the name of an element * in the array part1. */ int flags) /* OR-ed combination of TCL_GLOBAL_ONLY, and * TCL_LEAVE_ERR_MSG bits. */ { | | < < < < < | 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 | const char *part1, /* Name of an array (if part2 is non-NULL) or * the name of a variable. */ const char *part2, /* If non-NULL, gives the name of an element * in the array part1. */ int flags) /* OR-ed combination of TCL_GLOBAL_ONLY, and * TCL_LEAVE_ERR_MSG bits. */ { Tcl_Obj *resPtr, *part2Ptr = NULL, *part1Ptr = Tcl_NewStringObj(part1, -1); if (part2) { part2Ptr = Tcl_NewStringObj(part2, -1); } resPtr = Tcl_ObjGetVar2(interp, part1Ptr, part2Ptr, flags); Tcl_DecrRefCount(part1Ptr); if (part2Ptr) { Tcl_DecrRefCount(part2Ptr); |
︙ | ︙ | |||
1611 1612 1613 1614 1615 1616 1617 | * NULL. */ const char *newValue, /* New value for variable. */ int flags) /* Various flags that tell how to set value: * any of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * TCL_APPEND_VALUE, TCL_LIST_ELEMENT, or * TCL_LEAVE_ERR_MSG. */ { | < | < < < < < < < < < | < < < < < < < < | 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 | * NULL. */ const char *newValue, /* New value for variable. */ int flags) /* Various flags that tell how to set value: * any of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * TCL_APPEND_VALUE, TCL_LIST_ELEMENT, or * TCL_LEAVE_ERR_MSG. */ { Tcl_Obj *varValuePtr = Tcl_SetVar2Ex(interp, part1, part2, Tcl_NewStringObj(newValue, -1), flags); if (varValuePtr == NULL) { return NULL; } return TclGetString(varValuePtr); } /* |
︙ | ︙ | |||
1690 1691 1692 1693 1694 1695 1696 | * in the array part1. */ Tcl_Obj *newValuePtr, /* New value for variable. */ int flags) /* Various flags that tell how to set value: * any of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * TCL_APPEND_VALUE, TCL_LIST_ELEMENT or * TCL_LEAVE_ERR_MSG. */ { | | < < < | 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 | * in the array part1. */ Tcl_Obj *newValuePtr, /* New value for variable. */ int flags) /* Various flags that tell how to set value: * any of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * TCL_APPEND_VALUE, TCL_LIST_ELEMENT or * TCL_LEAVE_ERR_MSG. */ { Tcl_Obj *resPtr, *part2Ptr = NULL, *part1Ptr = Tcl_NewStringObj(part1, -1); Tcl_IncrRefCount(part1Ptr); if (part2) { part2Ptr = Tcl_NewStringObj(part2, -1); Tcl_IncrRefCount(part2Ptr); } resPtr = Tcl_ObjSetVar2(interp, part1Ptr, part2Ptr, newValuePtr, flags); Tcl_DecrRefCount(part1Ptr); if (part2Ptr) { Tcl_DecrRefCount(part2Ptr); |
︙ | ︙ | |||
1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 | * left in the interpreter's result. Note that the returned object may * not be the same one referenced by newValuePtr; this is because * variable traces may modify the variable's value. * * Side effects: * The value of the given variable is set. If either the array or the * entry didn't exist then a new variable is created. * *---------------------------------------------------------------------- */ Tcl_Obj * Tcl_ObjSetVar2( Tcl_Interp *interp, /* Command interpreter in which variable is to | > | 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 | * left in the interpreter's result. Note that the returned object may * not be the same one referenced by newValuePtr; this is because * variable traces may modify the variable's value. * * Side effects: * The value of the given variable is set. If either the array or the * entry didn't exist then a new variable is created. * Callers must Incr part1Ptr if they plan to Decr it. * *---------------------------------------------------------------------- */ Tcl_Obj * Tcl_ObjSetVar2( Tcl_Interp *interp, /* Command interpreter in which variable is to |
︙ | ︙ | |||
2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 | * * Side effects: * The value of the given variable is incremented by the specified * amount. If either the array or the entry didn't exist then a new * variable is created. The ref count for the returned object is _not_ * incremented to reflect the returned reference; if you want to keep a * reference to the object you must increment its ref count yourself. * *---------------------------------------------------------------------- */ Tcl_Obj * TclIncrObjVar2( Tcl_Interp *interp, /* Command interpreter in which variable is to | > | 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 | * * Side effects: * The value of the given variable is incremented by the specified * amount. If either the array or the entry didn't exist then a new * variable is created. The ref count for the returned object is _not_ * incremented to reflect the returned reference; if you want to keep a * reference to the object you must increment its ref count yourself. * Callers must Incr part1Ptr if they plan to Decr it. * *---------------------------------------------------------------------- */ Tcl_Obj * TclIncrObjVar2( Tcl_Interp *interp, /* Command interpreter in which variable is to |
︙ | ︙ | |||
2045 2046 2047 2048 2049 2050 2051 | * TCL_LEAVE_ERR_MSG. */ { Var *varPtr, *arrayPtr; varPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr, flags, "read", 1, 1, &arrayPtr); if (varPtr == NULL) { | | | | 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 | * TCL_LEAVE_ERR_MSG. */ { Var *varPtr, *arrayPtr; varPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr, flags, "read", 1, 1, &arrayPtr); if (varPtr == NULL) { Tcl_AddErrorInfo(interp, "\n (reading value of variable to increment)"); return NULL; } return TclPtrIncrObjVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, incrPtr, flags, -1); } /* |
︙ | ︙ | |||
2102 2103 2104 2105 2106 2107 2108 | * any of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * TCL_APPEND_VALUE, TCL_LIST_ELEMENT, * TCL_LEAVE_ERR_MSG. */ int index) /* Index into the local variable table of the * variable, or -1. Only used when part1Ptr is * NULL. */ { | | < | < < | | < | | | | > | > > > > > > > > > > > > > > | > > | 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 | * any of TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * TCL_APPEND_VALUE, TCL_LIST_ELEMENT, * TCL_LEAVE_ERR_MSG. */ int index) /* Index into the local variable table of the * variable, or -1. Only used when part1Ptr is * NULL. */ { register Tcl_Obj *varValuePtr; if (TclIsVarInHash(varPtr)) { VarHashRefCount(varPtr)++; } varValuePtr = TclPtrGetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, flags, index); if (TclIsVarInHash(varPtr)) { VarHashRefCount(varPtr)--; } if (varValuePtr == NULL) { varValuePtr = Tcl_NewIntObj(0); } if (Tcl_IsShared(varValuePtr)) { /* Copy on write */ varValuePtr = Tcl_DuplicateObj(varValuePtr); if (TCL_OK == TclIncrObj(interp, varValuePtr, incrPtr)) { return TclPtrSetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, varValuePtr, flags, index); } else { Tcl_DecrRefCount(varValuePtr); return NULL; } } 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 * [incr] requires that write traces fire, and making this call * is the way to make that happen. */ return TclPtrSetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, varValuePtr, flags, index); } else { return NULL; } } } /* *---------------------------------------------------------------------- * * Tcl_UnsetVar -- * |
︙ | ︙ | |||
2212 2213 2214 2215 2216 2217 2218 | const char *part1, /* Name of variable or array. */ const char *part2, /* Name of element within array or NULL. */ int flags) /* OR-ed combination of any of * TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * TCL_LEAVE_ERR_MSG. */ { int result; | | < < < | 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 | const char *part1, /* Name of variable or array. */ const char *part2, /* Name of element within array or NULL. */ int flags) /* OR-ed combination of any of * TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY, * TCL_LEAVE_ERR_MSG. */ { int result; Tcl_Obj *part2Ptr = NULL, *part1Ptr = Tcl_NewStringObj(part1, -1); if (part2) { part2Ptr = Tcl_NewStringObj(part2, -1); } /* * Filter to pass through only the flags this interface supports. */ flags &= (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG); |
︙ | ︙ | |||
2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 | * TclSetupEnv routine. * * Results: * A standard Tcl result object. * * Side effects: * A variable will be created if one does not already exist. * *---------------------------------------------------------------------- */ int TclArraySet( Tcl_Interp *interp, /* Current interpreter. */ | > | 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 | * 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. */ |
︙ | ︙ | |||
4215 4216 4217 4218 4219 4220 4221 | /* ARGSUSED */ Tcl_Command TclInitArrayCmd( Tcl_Interp *interp) /* Current interpreter. */ { static const EnsembleImplMap arrayImplMap[] = { | | | | | | | | | | 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 | /* ARGSUSED */ Tcl_Command TclInitArrayCmd( Tcl_Interp *interp) /* Current interpreter. */ { static const EnsembleImplMap arrayImplMap[] = { {"anymore", ArrayAnyMoreCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"donesearch", ArrayDoneSearchCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"exists", ArrayExistsCmd, TclCompileArrayExistsCmd, NULL, NULL, 0}, {"get", ArrayGetCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0}, {"names", ArrayNamesCmd, TclCompileBasic1To3ArgCmd, NULL, NULL, 0}, {"nextelement", ArrayNextElementCmd, TclCompileBasic2ArgCmd, NULL, NULL, 0}, {"set", ArraySetCmd, TclCompileArraySetCmd, NULL, NULL, 0}, {"size", ArraySizeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"startsearch", ArrayStartSearchCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"statistics", ArrayStatsCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0}, {"unset", ArrayUnsetCmd, TclCompileArrayUnsetCmd, NULL, NULL, 0}, {NULL, NULL, NULL, NULL, NULL, 0} }; return TclMakeEnsemble(interp, "array", arrayImplMap); } |
︙ | ︙ | |||
4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 | * A standard Tcl completion code. If an error occurs then an error * message is left in iPtr->result. * * Side effects: * The variable given by myName is linked to the variable in framePtr * given by otherP1 and otherP2, so that references to myName are * redirected to the other variable like a symbolic link. * *---------------------------------------------------------------------- */ static int ObjMakeUpvar( Tcl_Interp *interp, /* Interpreter containing variables. Used for | > > | 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 | * A standard Tcl completion code. If an error occurs then an error * message is left in iPtr->result. * * Side effects: * The variable given by myName is linked to the variable in framePtr * given by otherP1 and otherP2, so that references to myName are * redirected to the other variable like a symbolic link. * Callers must Incr myNamePtr if they plan to Decr it. * Callers must Incr otherP1Ptr if they plan to Decr it. * *---------------------------------------------------------------------- */ static int ObjMakeUpvar( Tcl_Interp *interp, /* Interpreter containing variables. Used for |
︙ | ︙ | |||
4356 4357 4358 4359 4360 4361 4362 | const char *myName, /* Name of variable which will refer to * otherP1/otherP2. Must be a scalar. */ int myFlags, /* 0, TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY: * indicates scope of myName. */ int index) /* If the variable to be linked is an indexed * scalar, this is its index. Otherwise, -1 */ { | | < < > > | 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 | const char *myName, /* Name of variable which will refer to * otherP1/otherP2. Must be a scalar. */ int myFlags, /* 0, TCL_GLOBAL_ONLY or TCL_NAMESPACE_ONLY: * indicates scope of myName. */ int index) /* If the variable to be linked is an indexed * scalar, this is its index. Otherwise, -1 */ { Tcl_Obj *myNamePtr = NULL; int result; if (myName) { myNamePtr = Tcl_NewStringObj(myName, -1); Tcl_IncrRefCount(myNamePtr); } result = TclPtrObjMakeUpvar(interp, otherPtr, myNamePtr, myFlags, index); if (myNamePtr) { Tcl_DecrRefCount(myNamePtr); } return result; } /* Callers must Incr myNamePtr if they plan to Decr it. */ int TclPtrObjMakeUpvar( Tcl_Interp *interp, /* Interpreter containing variables. Used for * error messages, too. */ Var *otherPtr, /* Pointer to the variable being linked-to. */ Tcl_Obj *myNamePtr, /* Name of variable which will refer to * otherP1/otherP2. Must be a scalar. */ |
︙ | ︙ | |||
5235 5236 5237 5238 5239 5240 5241 | } else if (nsPtr == (Namespace *) TclGetCurrentNamespace(interp)) { flags = TCL_NAMESPACE_ONLY; } for (varPtr = VarHashFirstVar(tablePtr, &search); varPtr != NULL; varPtr = VarHashFirstVar(tablePtr, &search)) { Tcl_Obj *objPtr = Tcl_NewObj(); | < < | 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 | } else if (nsPtr == (Namespace *) TclGetCurrentNamespace(interp)) { flags = TCL_NAMESPACE_ONLY; } for (varPtr = VarHashFirstVar(tablePtr, &search); varPtr != NULL; varPtr = VarHashFirstVar(tablePtr, &search)) { Tcl_Obj *objPtr = Tcl_NewObj(); VarHashRefCount(varPtr)++; /* Make sure we get to remove from * hash. */ Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr, objPtr); UnsetVarStruct(varPtr, NULL, iPtr, /* part1 */ objPtr, NULL, flags, -1); Tcl_DecrRefCount(objPtr); /* Free no longer needed obj */ |
︙ | ︙ | |||
5500 5501 5502 5503 5504 5505 5506 | Tcl_Interp *interp, /* Interpreter in which to record message. */ const char *part1, const char *part2, /* Variable's two-part name. */ const char *operation, /* String describing operation that failed, * e.g. "read", "set", or "unset". */ const char *reason) /* String describing why operation failed. */ { | | < < < < < | 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 | Tcl_Interp *interp, /* Interpreter in which to record message. */ const char *part1, const char *part2, /* Variable's two-part name. */ const char *operation, /* String describing operation that failed, * e.g. "read", "set", or "unset". */ const char *reason) /* String describing why operation failed. */ { Tcl_Obj *part2Ptr = NULL, *part1Ptr = Tcl_NewStringObj(part1, -1); if (part2) { part2Ptr = Tcl_NewStringObj(part2, -1); } TclObjVarErrMsg(interp, part1Ptr, part2Ptr, operation, reason, -1); Tcl_DecrRefCount(part1Ptr); if (part2Ptr) { Tcl_DecrRefCount(part2Ptr); |
︙ | ︙ | |||
5781 5782 5783 5784 5785 5786 5787 | * TCL_LEAVE_ERR_MSG. If both TCL_GLOBAL_ONLY * and TCL_NAMESPACE_ONLY are given, * TCL_GLOBAL_ONLY is ignored. */ { Tcl_Obj *namePtr = Tcl_NewStringObj(name, -1); Tcl_Var var; | < | 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 | * TCL_LEAVE_ERR_MSG. If both TCL_GLOBAL_ONLY * and TCL_NAMESPACE_ONLY are given, * TCL_GLOBAL_ONLY is ignored. */ { Tcl_Obj *namePtr = Tcl_NewStringObj(name, -1); Tcl_Var var; var = ObjFindNamespaceVar(interp, namePtr, contextNsPtr, flags); Tcl_DecrRefCount(namePtr); return var; } static Tcl_Var ObjFindNamespaceVar( |
︙ | ︙ | |||
5876 5877 5878 5879 5880 5881 5882 | * to check both possible search paths: from the specified namespace * context and from the global namespace. */ varPtr = NULL; if (simpleName != name) { simpleNamePtr = Tcl_NewStringObj(simpleName, -1); | < | 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 | * to check both possible search paths: from the specified namespace * context and from the global namespace. */ varPtr = NULL; if (simpleName != name) { simpleNamePtr = Tcl_NewStringObj(simpleName, -1); } else { simpleNamePtr = namePtr; } for (search = 0; (search < 2) && (varPtr == NULL); search++) { if ((nsPtr[search] != NULL) && (simpleName != NULL)) { varPtr = VarHashFindVar(&nsPtr[search]->varTable, simpleNamePtr); |
︙ | ︙ |
Changes to generic/tclZlib.c.
︙ | ︙ | |||
503 504 505 506 507 508 509 | /* *---------------------------------------------------------------------- * * ExtractHeader -- * * Take the values out of a gzip header and store them in a dictionary. | | < | < < < < < < < | < < | 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 | /* *---------------------------------------------------------------------- * * ExtractHeader -- * * Take the values out of a gzip header and store them in a dictionary. * SetValue is a helper macro. * * Results: * None. * * Side effects: * Updates the dictionary, which must be writable (i.e. refCount < 2). * *---------------------------------------------------------------------- */ #define SetValue(dictObj, key, value) \ Tcl_DictObjPut(NULL, (dictObj), Tcl_NewStringObj((key), -1), (value)) static void ExtractHeader( gz_header *headerPtr, /* The gzip header to extract from. */ Tcl_Obj *dictObj) /* The dictionary to store in. */ { Tcl_Encoding latin1enc = NULL; |
︙ | ︙ | |||
2115 2116 2117 2118 2119 2120 2121 | if (headerDictObj) { TclDecrRefCount(headerDictObj); } return TCL_ERROR; } if (headerVarObj != NULL && Tcl_ObjSetVar2(interp, headerVarObj, NULL, headerDictObj, TCL_LEAVE_ERR_MSG) == NULL) { | < < < | 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 | if (headerDictObj) { TclDecrRefCount(headerDictObj); } return TCL_ERROR; } if (headerVarObj != NULL && Tcl_ObjSetVar2(interp, headerVarObj, NULL, headerDictObj, TCL_LEAVE_ERR_MSG) == NULL) { return TCL_ERROR; } return TCL_OK; } case CMD_STREAM: /* stream deflate/inflate/...gunzip \ * ?options...? * -> handleCmd */ |
︙ | ︙ | |||
3874 3875 3876 3877 3878 3879 3880 | * TODO: Describe whether we're using the system version of the library or * a compatibility version built into Tcl? */ cfg[0].key = "zlibVersion"; cfg[0].value = zlibVersion(); cfg[1].key = NULL; | | | 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 | * TODO: Describe whether we're using the system version of the library or * a compatibility version built into Tcl? */ cfg[0].key = "zlibVersion"; cfg[0].value = zlibVersion(); cfg[1].key = NULL; Tcl_RegisterConfig(interp, "zlib", cfg, "iso8859-1"); /* * Formally provide the package as a Tcl built-in. */ return Tcl_PkgProvide(interp, "zlib", TCL_ZLIB_VERSION); } |
︙ | ︙ |
Changes to library/http/http.tcl.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # http.tcl -- # # Client-side HTTP for GET, POST, and HEAD commands. These routines can # be used in untrusted code that uses the Safesock security policy. # These procedures use a callback interface to avoid using vwait, which # is not defined in the safe base. # # See the file "license.terms" for information on usage and redistribution of # this file, and for a DISCLAIMER OF ALL WARRANTIES. package require Tcl 8.6- # Keep this in sync with pkgIndex.tcl and with the install directories in # Makefiles | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # http.tcl -- # # Client-side HTTP for GET, POST, and HEAD commands. These routines can # be used in untrusted code that uses the Safesock security policy. # These procedures use a callback interface to avoid using vwait, which # is not defined in the safe base. # # See the file "license.terms" for information on usage and redistribution of # this file, and for a DISCLAIMER OF ALL WARRANTIES. package require Tcl 8.6- # Keep this in sync with pkgIndex.tcl and with the install directories in # Makefiles package provide http 2.8.6 namespace eval http { # Allow resourcing to not clobber existing data variable http if {![info exists http]} { array set http { |
︙ | ︙ | |||
533 534 535 536 537 538 539 | append url $srvurl # Don't append the fragment! set state(url) $url # If a timeout is specified we set up the after event and arrange for an # asynchronous socket connection. | | < | 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 | append url $srvurl # Don't append the fragment! set state(url) $url # If a timeout is specified we set up the after event and arrange for an # asynchronous socket connection. set sockopts [list -async] if {$state(-timeout) > 0} { set state(after) [after $state(-timeout) \ [list http::reset $token timeout]] } # If we are using the proxy, we must pass in the full URL that includes # the server name. if {[info exists phost] && ($phost ne "")} { set srvurl $url |
︙ | ︙ | |||
593 594 595 596 597 598 599 | set state(sock) $sock Log "Using $sock for $state(socketinfo)" \ [expr {$state(-keepalive)?"keepalive":""}] if {$state(-keepalive)} { set socketmap($state(socketinfo)) $sock } | | > | < | > > > > > > > | < | | | | > > > > > > > > > > > > > > > | 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 | set state(sock) $sock Log "Using $sock for $state(socketinfo)" \ [expr {$state(-keepalive)?"keepalive":""}] if {$state(-keepalive)} { set socketmap($state(socketinfo)) $sock } if {![info exists phost]} { set phost "" } fileevent $sock writable [list http::Connect $token $proto $phost $srvurl] # Wait for the connection to complete. if {![info exists state(-command)]} { # geturl does EVERYTHING asynchronously, so if the user # calls it synchronously, we just do a wait here. http::wait $token if {![info exists state]} { # If we timed out then Finish has been called and the users # command callback may have cleaned up the token. If so we end up # here with nothing left to do. return $token } elseif {$state(status) eq "error"} { # 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 # exception from here instead. set err [lindex $state(error) 0] cleanup $token return -code error $err } } return $token } proc http::Connected { token proto phost srvurl} { variable http variable urlTypes variable $token upvar 0 $token state # Set back the variables needed here set sock $state(sock) set isQueryChannel [info exists state(-querychannel)] set isQuery [info exists state(-query)] set host [lindex [split $state(socketinfo) :] 0] set port [lindex [split $state(socketinfo) :] 1] set defport [lindex $urlTypes($proto) 0] # Send data in cr-lf format, but accept any line terminators fconfigure $sock -translation {auto crlf} -buffersize $state(-blocksize) # The following is disallowed in safe interpreters, but the socket is # already in non-blocking mode in that case. |
︙ | ︙ | |||
749 750 751 752 753 754 755 | fileevent $sock writable [list http::Write $token] } else { puts $sock "" flush $sock fileevent $sock readable [list http::Event $sock $token] } | < < < < < < < < < < < < < < < | < < < | 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 | fileevent $sock writable [list http::Write $token] } else { puts $sock "" flush $sock fileevent $sock readable [list http::Event $sock $token] } } err]} { # The socket probably was never connected, or the connection dropped # later. # if state(status) is error, it means someone's already called Finish # to do the above-described clean up. if {$state(status) ne "error"} { Finish $token $err } } } # Data access functions: # Data - the URL data # Status - the transaction status: ok, reset, eof, timeout # Code - the HTTP transaction code, e.g., 200 # Size - the size of the URL data |
︙ | ︙ | |||
861 862 863 864 865 866 867 | # Arguments # token The token returned from http::geturl # # Side Effects # Sets the status of the connection, which unblocks # the waiting geturl call | | | < > | 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 | # Arguments # token The token returned from http::geturl # # Side Effects # Sets the status of the connection, which unblocks # the waiting geturl call proc http::Connect {token proto phost srvurl} { variable $token upvar 0 $token state set err "due to unexpected EOF" if { [eof $state(sock)] || [set err [fconfigure $state(sock) -error]] ne "" } { Finish $token "connect failed $err" } else { fileevent $state(sock) writable {} ::http::Connected $token $proto $phost $srvurl } return } # http::Write # # Write POST query data to the socket |
︙ | ︙ | |||
977 978 979 980 981 982 983 | } } elseif {$state(state) eq "header"} { if {[catch {gets $sock line} n]} { return [Finish $token $n] } elseif {$n == 0} { # We have now read all headers # We ignore HTTP/1.1 100 Continue returns. RFC2616 sec 8.2.3 | | | 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 | } } elseif {$state(state) eq "header"} { if {[catch {gets $sock line} n]} { return [Finish $token $n] } elseif {$n == 0} { # We have now read all headers # We ignore HTTP/1.1 100 Continue returns. RFC2616 sec 8.2.3 if {$state(http) == "" || ([regexp {^\S+\s(\d+)} $state(http) {} x] && $x == 100)} { return } set state(state) body # If doing a HEAD, then we won't get any body if {$state(-validate)} { |
︙ | ︙ | |||
1375 1376 1377 1378 1379 1380 1381 | if {$http(-urlencoding) ne ""} { set string [encoding convertto $http(-urlencoding) $string] return [string map $formMap $string] } set converted [string map $formMap $string] if {[string match "*\[\u0100-\uffff\]*" $converted]} { | | | 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 | if {$http(-urlencoding) ne ""} { set string [encoding convertto $http(-urlencoding) $string] return [string map $formMap $string] } set converted [string map $formMap $string] if {[string match "*\[\u0100-\uffff\]*" $converted]} { regexp "\[\u0100-\uffff\]" $converted badChar # Return this error message for maximum compatability... :^/ return -code error \ "can't read \"formMap($badChar)\": no such element in array" } return $converted } |
︙ | ︙ |
Changes to library/http/pkgIndex.tcl.
1 | if {![package vsatisfies [package provide Tcl] 8.6-]} {return} | | | 1 2 | if {![package vsatisfies [package provide Tcl] 8.6-]} {return} package ifneeded http 2.8.6 [list tclPkgSetup $dir http 2.8.6 {{http.tcl source {::http::config ::http::formatQuery ::http::geturl ::http::reset ::http::wait ::http::register ::http::unregister ::http::mapReply}}}] |
Changes to macosx/tclMacOSXFCmd.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* * tclMacOSXFCmd.c * * This file implements the MacOSX specific portion of file manipulation * subcommands of the "file" command. * * Copyright (c) 2003-2007 Daniel A. Steffen <[email protected]> * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #ifdef HAVE_GETATTRLIST #include <sys/attr.h> #include <sys/paths.h> #include <libkern/OSByteOrder.h> #endif | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /* * tclMacOSXFCmd.c * * This file implements the MacOSX specific portion of file manipulation * subcommands of the "file" command. * * Copyright (c) 2003-2007 Daniel A. Steffen <[email protected]> * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include <sys/stat.h> #include "tclInt.h" #ifdef HAVE_GETATTRLIST #include <sys/attr.h> #include <sys/paths.h> #include <libkern/OSByteOrder.h> #endif |
︙ | ︙ |
Changes to pkgs/package.list.txt.
︙ | ︙ | |||
19 20 21 22 23 24 25 | tdbc TDBC Tdbc TDBC TDBC TDBC # Drivers for TDBC tdbcmysql tdbc::mysql tdbcodbc tdbc::odbc tdbcpostgres tdbc::postgres | | | 19 20 21 22 23 24 25 26 | tdbc TDBC Tdbc TDBC TDBC TDBC # Drivers for TDBC tdbcmysql tdbc::mysql tdbcodbc tdbc::odbc tdbcpostgres tdbc::postgres tdbcsqlite3 tdbc::sqlite3 |
Changes to tests/chan.test.
︙ | ︙ | |||
57 58 59 60 61 62 63 | chan configure stdout -eofchar [list \x27 {}] } -returnCodes ok -result {} test chan-4.5 {chan command: check valid inValue, invalid outValue} -body { chan configure stdout -eofchar [list \x27 \x80] } -returnCodes error -match glob -result {bad value for -eofchar:*} test chan-4.6 {chan command: check no inValue, valid outValue} -body { chan configure stdout -eofchar [list {} \x27] | | | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | chan configure stdout -eofchar [list \x27 {}] } -returnCodes ok -result {} test chan-4.5 {chan command: check valid inValue, invalid outValue} -body { chan configure stdout -eofchar [list \x27 \x80] } -returnCodes error -match glob -result {bad value for -eofchar:*} test chan-4.6 {chan command: check no inValue, valid outValue} -body { chan configure stdout -eofchar [list {} \x27] } -returnCodes ok -result {} -cleanup {chan configure stdout -eofchar [list {} {}]} test chan-5.1 {chan command: copy subcommand} -body { chan copy foo } -returnCodes error -result "wrong # args: should be \"chan copy input output ?-size size? ?-command callback?\"" test chan-6.1 {chan command: eof subcommand} -body { chan eof foo bar |
︙ | ︙ |
Changes to tests/cmdAH.test.
︙ | ︙ | |||
64 65 66 67 68 69 70 71 72 73 74 75 76 77 | } -result {wrong # args: should be "catch script ?resultVarName? ?optionVarName?"} test cmdAH-1.2 {Tcl_CatchObjCmd, errors} { list [catch {catch foo bar baz} msg] $msg } {0 1} test cmdAH-1.3 {Tcl_CatchObjCmd, errors} -returnCodes error -body { catch foo bar baz spaz } -result {wrong # args: should be "catch script ?resultVarName? ?optionVarName?"} test cmdAH-2.1 {Tcl_CdObjCmd} -returnCodes error -body { cd foo bar } -result {wrong # args: should be "cd ?dirName?"} set foodir [file join [temporaryDirectory] foo] test cmdAH-2.2 {Tcl_CdObjCmd} -setup { file delete -force $foodir | > > > > > > | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | } -result {wrong # args: should be "catch script ?resultVarName? ?optionVarName?"} test cmdAH-1.2 {Tcl_CatchObjCmd, errors} { list [catch {catch foo bar baz} msg] $msg } {0 1} test cmdAH-1.3 {Tcl_CatchObjCmd, errors} -returnCodes error -body { catch foo bar baz spaz } -result {wrong # args: should be "catch script ?resultVarName? ?optionVarName?"} test cmdAH-1.4 {Bug 3595576} { catch {catch {} -> noSuchNs::var} } 1 test cmdAH-1.5 {Bug 3595576} { catch {catch error -> noSuchNs::var} } 1 test cmdAH-2.1 {Tcl_CdObjCmd} -returnCodes error -body { cd foo bar } -result {wrong # args: should be "cd ?dirName?"} set foodir [file join [temporaryDirectory] foo] test cmdAH-2.2 {Tcl_CdObjCmd} -setup { file delete -force $foodir |
︙ | ︙ |
Changes to tests/env.test.
︙ | ︙ | |||
66 67 68 69 70 71 72 | if {$i >= 0} { set list [lreplace $list $i $i] } return $list } proc mangle s { regsub -all {\[|\\|\]} $s {\\&} s | | | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | if {$i >= 0} { set list [lreplace $list $i $i] } return $list } proc mangle s { regsub -all {\[|\\|\]} $s {\\&} s regsub -all "\[\u0000-\u001f\u007f-\uffff\]" $s {[manglechar &]} s return [subst -novariables $s] } proc manglechar c { return [format {\u%04x} [scan $c %c]] } set names [lsort [array names env]] |
︙ | ︙ |
Changes to tests/exec.test.
︙ | ︙ | |||
153 154 155 156 157 158 159 | exec [interpreter] $path(cat) "<<Joined to arrows" } {Joined to arrows} test exec-2.6 {redirecting input from immediate source, with UTF} -setup { set sysenc [encoding system] encoding system iso8859-1 proc quotenonascii s { regsub -all {\[|\\|\]} $s {\\&} s | | | 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | exec [interpreter] $path(cat) "<<Joined to arrows" } {Joined to arrows} test exec-2.6 {redirecting input from immediate source, with UTF} -setup { set sysenc [encoding system] encoding system iso8859-1 proc quotenonascii s { regsub -all {\[|\\|\]} $s {\\&} s regsub -all "\[\u007f-\uffff\]" $s \ {[apply {c {format {\u%04x} [scan $c %c]}} &]} s return [subst -novariables $s] } } -constraints {exec} -body { # If this fails, it may give back: "\uC3\uA9\uC3\uA0\uC3\uBC\uC3\uB1" # If it does, this means that the UTF -> external conversion did not occur # before writing out the temp file. |
︙ | ︙ |
Changes to tests/http.test.
︙ | ︙ | |||
543 544 545 546 547 548 549 | # connection "completes" but the socket is bad. test http-4.14 {http::Event} -body { set token [http::geturl $badurl/?timeout=10 -timeout 10000 -command \#] if {$token eq ""} { error "bogus return from http::geturl" } http::wait $token | | < | | | 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 | # connection "completes" but the socket is bad. test http-4.14 {http::Event} -body { set token [http::geturl $badurl/?timeout=10 -timeout 10000 -command \#] if {$token eq ""} { error "bogus return from http::geturl" } http::wait $token lindex [http::error $token] 0 } -cleanup { catch {http::cleanup $token} } -result {connect failed connection refused} # Bogus host test http-4.15 {http::Event} -body { # This test may fail if you use a proxy server. That is to be # expected and is not a problem with Tcl. set token [http::geturl //not_a_host.tcl.tk -timeout 1000 -command \#] http::wait $token http::status $token |
︙ | ︙ |
Changes to tests/info.test.
︙ | ︙ | |||
688 689 690 691 692 693 694 695 696 697 698 699 700 701 | test info-21.5 {miscellaneous error conditions} -returnCodes error -body { info s } -result {unknown or ambiguous subcommand "s": must be args, body, class, cmdcount, commands, complete, coroutine, default, errorstack, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars} ## # ### ### ### ######### ######### ######### ## info frame ## Helper # For the more complex results we cut the file name down to remove path # dependencies, and we use only part of the first line of the reported # command. The latter is required because otherwise the whole test case may # appear in some results, but the result is part of the testcase. An infinite # string would be required to describe that. The cutting-down breaks this. proc reduce {frame} { | > > | < < > | < | < < | | | > > | 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 | test info-21.5 {miscellaneous error conditions} -returnCodes error -body { info s } -result {unknown or ambiguous subcommand "s": must be args, body, class, cmdcount, commands, complete, coroutine, default, errorstack, exists, frame, functions, globals, hostname, level, library, loaded, locals, nameofexecutable, object, patchlevel, procs, script, sharedlibextension, tclversion, or vars} ## # ### ### ### ######### ######### ######### ## info frame ## Helper # For the more complex results we cut the file name down to remove path # dependencies, and we use only part of the first line of the reported # command. The latter is required because otherwise the whole test case may # appear in some results, but the result is part of the testcase. An infinite # string would be required to describe that. The cutting-down breaks this. proc reduce {frame} { set cmd [dict get $frame cmd] if {[regexp \n $cmd]} { dict set frame cmd \ [string range [lindex [split $cmd \n] 0] 0 end-4] } if {[dict exists $frame file]} { dict set frame file \ [file tail [dict get $frame file]] } return $frame } proc subinterp {} { interp create sub ; interp debug sub -frame 1; interp eval sub [list proc reduce [info args reduce] [info body reduce]] } ## Helper # Generate a stacktrace from the current location to top. This code # not only depends on the exact location of things, but also on the # implementation of tcltest. Any changes and these tests will have to # be updated. proc etrace {} { |
︙ | ︙ | |||
1450 1451 1452 1453 1454 1455 1456 | } -cleanup { rename abra {} } -result {type source line 1446 file info.test cmd {info frame 0} proc ::abra level 0} test info-30.2 {bs+nl in literal words, namespace script} { namespace eval xxx { variable res \ | | | | 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 | } -cleanup { rename abra {} } -result {type source line 1446 file info.test cmd {info frame 0} proc ::abra level 0} test info-30.2 {bs+nl in literal words, namespace script} { namespace eval xxx { variable res \ [info frame 0];# line 1457 } return [reduce $xxx::res] } {type source line 1457 file info.test cmd {info frame 0} level 0} test info-30.3 {bs+nl in literal words, namespace multi-word script} { namespace eval xxx variable res \ [list [reduce [info frame 0]]];# line 1464 return $xxx::res } {type source line 1464 file info.test cmd {info frame 0} proc ::tcltest::RunTest} |
︙ | ︙ |
Changes to tests/listObj.test.
︙ | ︙ | |||
191 192 193 194 195 196 197 198 199 200 201 202 203 204 | [testlistobj get 1] } -cleanup { testobj freeallvars } -result {{a b c d e} {} {a b c d e f}} } # cleanup ::tcltest::cleanupTests return # Local Variables: # mode: tcl | > > > > | 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | [testlistobj get 1] } -cleanup { testobj freeallvars } -result {{a b c d e} {} {a b c d e f}} } test listobj-11.1 {bug 3598580} { testobj bug3598580 } 123 # cleanup ::tcltest::cleanupTests return # Local Variables: # mode: tcl |
︙ | ︙ |
Changes to tests/load.test.
︙ | ︙ | |||
184 185 186 187 188 189 190 | } {1 {could not find interpreter "gorp"}} test load-8.3 {TclGetLoadedPackages procedure} [list teststaticpkg $dll $loaded] { list [info loaded {}] [info loaded child] } [list [concat [list {{} Double} {{} More} {{} Another} {{} Test} [list [file join $testDir pkga$ext] Pkga]] $alreadyLoaded] [list {{} Test} [list [file join $testDir pkgb$ext] Pkgb]]] test load-8.4 {TclGetLoadedPackages procedure} [list $dll $loaded teststaticpkg] { load [file join $testDir pkgb$ext] pkgb list [info loaded {}] [lsort [info commands pkgb_*]] | | | 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | } {1 {could not find interpreter "gorp"}} test load-8.3 {TclGetLoadedPackages procedure} [list teststaticpkg $dll $loaded] { list [info loaded {}] [info loaded child] } [list [concat [list {{} Double} {{} More} {{} Another} {{} Test} [list [file join $testDir pkga$ext] Pkga]] $alreadyLoaded] [list {{} Test} [list [file join $testDir pkgb$ext] Pkgb]]] test load-8.4 {TclGetLoadedPackages procedure} [list $dll $loaded teststaticpkg] { load [file join $testDir pkgb$ext] pkgb list [info loaded {}] [lsort [info commands pkgb_*]] } [list [concat [list [list [file join $testDir pkgb$ext] Pkgb] {{} Double} {{} More} {{} Another} {{} Test} [list [file join $testDir pkga$ext] Pkga]] $alreadyLoaded] {pkgb_demo pkgb_sub pkgb_unsafe}] interp delete child test load-9.1 {Tcl_StaticPackage, load already-loaded package into another interp} \ -constraints {teststaticpkg} \ -setup { interp create child1 interp create child2 |
︙ | ︙ |
Changes to tests/nre.test.
︙ | ︙ | |||
70 71 72 73 74 75 76 | setabs a 0 } -cleanup { rename a {} } -constraints { testnrelevels } -result {{0 1 1 1} 0} | < < | 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | setabs a 0 } -cleanup { rename a {} } -constraints { testnrelevels } -result {{0 1 1 1} 0} test nre-1.2 {self-recursive lambdas} -setup { set a [list i [makebody {apply $::a $i}]] } -body { setabs apply $a 0 } -cleanup { unset a } -constraints { testnrelevels } -result {{0 1 1 1} 0} test nre-1.3 {mutually recursive procs and lambdas} -setup { proc a i { apply $::b [incr i] } set b [list i [makebody {a $i}]] } -body { setabs |
︙ | ︙ | |||
160 161 162 163 164 165 166 | proc foo::a i [makebody {namespace eval ::foo [list a $i]}] } -body { ::foo::a 0 } -cleanup { namespace delete ::foo } -constraints { testnrelevels | | < | < | 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | proc foo::a i [makebody {namespace eval ::foo [list a $i]}] } -body { ::foo::a 0 } -cleanup { namespace delete ::foo } -constraints { testnrelevels } -result {{0 2 2 2} 0} test nre-5.2 {[namespace eval] is not recursive} -setup { namespace eval ::foo { setabs } proc foo::a i [makebody {namespace eval ::foo "set x $i; a $i"}] } -body { foo::a 0 } -cleanup { namespace delete ::foo } -constraints { testnrelevels } -result {{0 2 2 2} 0} test nre-6.1 {[uplevel] is not recursive} -setup { proc a i [makebody {uplevel 1 [list a $i]}] } -body { setabs a 0 } -cleanup { rename a {} } -constraints { testnrelevels } -result {{0 2 2 0} 0} test nre-6.2 {[uplevel] is not recursive} -setup { setabs proc a i [makebody {uplevel 1 "set x $i; a $i"}] } -body { a 0 } -cleanup { rename a {} |
︙ | ︙ | |||
207 208 209 210 211 212 213 | } -body { a 0 } -cleanup { rename a {} } -constraints { testnrelevels } -result {{0 3 3 0} 0} | < < < < < < < < < < < < < < < < < < | 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 | } -body { a 0 } -cleanup { rename a {} } -constraints { testnrelevels } -result {{0 3 3 0} 0} test nre-7.2 {[if] is not recursive} -setup { setabs proc a i [makebody {uplevel 1 "if 1 {a $i}"}] } -body { a 0 } -cleanup { rename a {} } -constraints { testnrelevels } -result {{0 2 2 0} 0} test nre-7.3 {[while] is not recursive} -setup { setabs proc a i [makebody {uplevel 1 "while 1 {set res \[a $i\]; break}; set res"}] } -body { a 0 } -cleanup { rename a {} } -constraints { testnrelevels } -result {{0 2 2 0} 0} test nre-7.4 {[for] is not recursive} -setup { setabs proc a i [makebody {uplevel 1 "for {set j 0} {\$j < 10} {incr j} {set res \[a $i\]; break}; set res"}] } -body { a 0 } -cleanup { rename a {} } -constraints { testnrelevels } -result {{0 2 2 0} 0} test nre-7.5 {[foreach] is not recursive} -setup { # # Enable once [foreach] is NR-enabled # setabs proc a i [makebody {uplevel 1 "foreach j {1 2 3 4 5 6} {set res \[a $i\]; break}; set res"}] } -body { a 0 } -cleanup { rename a {} } -constraints { testnrelevels } -result {{0 3 3 0} 0} test nre-7.6 {[eval] is not recursive} -setup { proc a i [makebody {eval [list a $i]}] } -body { setabs a 0 } -cleanup { rename a {} } -constraints { testnrelevels } -result {{0 2 2 1} 0} test nre-7.7 {[eval] is not recursive} -setup { proc a i [makebody {eval "a $i"}] } -body { setabs a 0 } -cleanup { rename a {} } -constraints { testnrelevels } -result {{0 2 2 1} 0} test nre-7.8 {bug #2910748: switch out of stale BC is not nre-aware} -setup { proc foo args {} foo coroutine bar apply {{} { yield proc foo args {return ok} while 1 { yield [incr i] foo } }} } -body { # if switching to plain eval is not nre aware, this will cause a "cannot # yield" error list [bar] [bar] [bar] } -cleanup { rename bar {} rename foo {} } -result {1 2 3} test nre-8.1 {nre and {*}} -body { # force an expansion that grows the evaluation stack, check that nre # adapts the TEBCdataPtr. This crashes on failure. proc inner {} { set long [lrepeat 1000000 1] list {*}$long } proc outer {} inner lrange [outer] 0 2 } -cleanup { rename inner {} rename outer {} } -result {1 1 1} test nre-8.2 {nre and {*}, [Bug 2415422]} -body { # force an expansion that grows the evaluation stack, check that nre # adapts the bcFramePtr. This causes an NRE assertion to fail if it is not # done properly. proc nop {} {} proc crash {} { foreach val [list {*}[lrepeat 100000 x]] { nop } } crash } -cleanup { rename nop {} rename crash {} } # # Basic TclOO tests # test nre-oo.1 {really deep calls in oo - direct} -setup { oo::object create foo oo::objdefine foo method bar i [makebody {foo bar $i}] } -body { setabs foo bar 0 } -cleanup { foo destroy } -constraints { testnrelevels } -result {{0 1 1 1} 0} test nre-oo.2 {really deep calls in oo - call via [self]} -setup { oo::object create foo oo::objdefine foo method bar i [makebody {[self] bar $i}] } -body { setabs foo bar 0 } -cleanup { foo destroy } -constraints { testnrelevels } -result {{0 1 1 1} 0} test nre-oo.3 {really deep calls in oo - private calls} -setup { oo::object create foo oo::objdefine foo method bar i [makebody {my bar $i}] } -body { setabs foo bar 0 } -cleanup { foo destroy } -constraints { testnrelevels } -result {{0 1 1 1} 0} test nre-oo.4 {really deep calls in oo - overriding} -setup { oo::class create foo { method bar i [makebody {my bar $i}] } oo::class create boo { superclass foo method bar i [makebody {next $i}] } } -body { setabs [boo new] bar 0 } -cleanup { foo destroy } -constraints { testnrelevels } -result {{0 1 1 1} 0} test nre-oo.5 {really deep calls in oo - forwards} -setup { oo::object create foo set body [makebody {my boo $i}] oo::objdefine foo " method bar i {$body} forward boo ::foo bar " } -body { setabs foo bar 0 } -cleanup { foo destroy } -constraints { testnrelevels } -result {{0 2 1 1} 0} # # NASTY BUG found by tcllib's interp package # test nre-X.1 {eval in wrong interp} -setup { set i [interp create] |
︙ | ︙ |
Changes to tests/oo.test.
1 2 3 4 5 6 7 8 9 | # This file contains a collection of tests for Tcl's built-in object system. # Sourcing this file into Tcl runs the tests and generates output for errors. # No output means no errors were found. # # Copyright (c) 2006-2012 Donal K. Fellows # # See the file "license.terms" for information on usage and redistribution of # this file, and for a DISCLAIMER OF ALL WARRANTIES. | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # This file contains a collection of tests for Tcl's built-in object system. # Sourcing this file into Tcl runs the tests and generates output for errors. # No output means no errors were found. # # Copyright (c) 2006-2012 Donal K. Fellows # # See the file "license.terms" for information on usage and redistribution of # this file, and for a DISCLAIMER OF ALL WARRANTIES. package require TclOO 1.0 package require tcltest 2 if {"::tcltest" in [namespace children]} { namespace import -force ::tcltest::* } testConstraint memory [llength [info commands memory]] if {[testConstraint memory]} { |
︙ | ︙ |
Changes to tests/ooNext2.test.
1 2 3 4 5 6 7 8 9 | # This file contains a collection of tests for Tcl's built-in object system. # Sourcing this file into Tcl runs the tests and generates output for errors. # No output means no errors were found. # # Copyright (c) 2006-2011 Donal K. Fellows # # See the file "license.terms" for information on usage and redistribution of # this file, and for a DISCLAIMER OF ALL WARRANTIES. | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # This file contains a collection of tests for Tcl's built-in object system. # Sourcing this file into Tcl runs the tests and generates output for errors. # No output means no errors were found. # # Copyright (c) 2006-2011 Donal K. Fellows # # See the file "license.terms" for information on usage and redistribution of # this file, and for a DISCLAIMER OF ALL WARRANTIES. package require TclOO 1.0 package require tcltest 2 if {"::tcltest" in [namespace children]} { namespace import -force ::tcltest::* } testConstraint memory [llength [info commands memory]] if {[testConstraint memory]} { |
︙ | ︙ |
Changes to tests/parse.test.
︙ | ︙ | |||
22 23 24 25 26 27 28 29 30 31 32 33 34 35 | testConstraint testparser [llength [info commands testparser]] testConstraint testevalobjv [llength [info commands testevalobjv]] testConstraint testevalex [llength [info commands testevalex]] testConstraint testparsevarname [llength [info commands testparsevarname]] testConstraint testparsevar [llength [info commands testparsevar]] testConstraint testasync [llength [info commands testasync]] testConstraint testcmdtrace [llength [info commands testcmdtrace]] test parse-1.1 {Tcl_ParseCommand procedure, computing string length} testparser { testparser [bytestring "foo\0 bar"] -1 } {- foo 1 simple foo 1 text foo 0 {}} test parse-1.2 {Tcl_ParseCommand procedure, computing string length} testparser { testparser "foo bar" -1 } {- {foo bar} 2 simple foo 1 text foo 0 simple bar 1 text bar 0 {}} | > | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | testConstraint testparser [llength [info commands testparser]] testConstraint testevalobjv [llength [info commands testevalobjv]] testConstraint testevalex [llength [info commands testevalex]] testConstraint testparsevarname [llength [info commands testparsevarname]] testConstraint testparsevar [llength [info commands testparsevar]] testConstraint testasync [llength [info commands testasync]] testConstraint testcmdtrace [llength [info commands testcmdtrace]] testConstraint testevent [llength [info commands testevent]] test parse-1.1 {Tcl_ParseCommand procedure, computing string length} testparser { testparser [bytestring "foo\0 bar"] -1 } {- foo 1 simple foo 1 text foo 0 {}} test parse-1.2 {Tcl_ParseCommand procedure, computing string length} testparser { testparser "foo bar" -1 } {- {foo bar} 2 simple foo 1 text foo 0 simple bar 1 text bar 0 {}} |
︙ | ︙ | |||
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 | } {- {\x1} 1 word {\x1} 1 backslash {\x1} 0 2X} test parse-20.11 {TclParseBackslash: truncated escape} testparser { testparser {\x12X} 4 } {- {\x12} 1 word {\x12} 1 backslash {\x12} 0 X} test parse-20.12 {TclParseBackslash: truncated escape} testparser { testparser {\x12X} 5 } {- {\x12X} 1 word {\x12X} 2 backslash {\x12} 0 text X 0 {}} cleanupTests } namespace delete ::tcl::test::parse return | > > > > > > > > | 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 | } {- {\x1} 1 word {\x1} 1 backslash {\x1} 0 2X} test parse-20.11 {TclParseBackslash: truncated escape} testparser { testparser {\x12X} 4 } {- {\x12} 1 word {\x12} 1 backslash {\x12} 0 X} test parse-20.12 {TclParseBackslash: truncated escape} testparser { testparser {\x12X} 5 } {- {\x12X} 1 word {\x12X} 2 backslash {\x12} 0 text X 0 {}} test parse-21.0 {Bug 1884496} testevent { set ::script {set a [p]; return -level 0 $a} proc ::p {} {string first s $::script} testevent queue a head $::script update } {} cleanupTests } namespace delete ::tcl::test::parse return |
Changes to tests/proc.test.
︙ | ︙ | |||
358 359 360 361 362 363 364 | } -cleanup { namespace delete ugly } -result bar test proc-7.3 {Returning loop exception from redefined cmd: Bug 729692} -body { namespace eval ugly {} proc ugly::foo {} { set i 0 | | | 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 | } -cleanup { namespace delete ugly } -result bar test proc-7.3 {Returning loop exception from redefined cmd: Bug 729692} -body { namespace eval ugly {} proc ugly::foo {} { set i 0 while { $i < 10 } { if { [incr i] > 3 } { proc continue {} {return -code break} } continue } return $i } |
︙ | ︙ |
Changes to tests/zlib.test.
︙ | ︙ | |||
822 823 824 825 826 827 828 829 830 831 832 833 834 835 | close $f set d [zlib gunzip $d -header h] list [regexp -all "hello" $d] [dict get $h filename] \ [string length [regsub -all "hello" $d {}]] } -cleanup { removeFile $file } -result {1000 /foo/bar 0} ::tcltest::cleanupTests return # Local Variables: # mode: tcl # End: | > > > > > > > > > > > > > > | 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 | close $f set d [zlib gunzip $d -header h] list [regexp -all "hello" $d] [dict get $h filename] \ [string length [regsub -all "hello" $d {}]] } -cleanup { removeFile $file } -result {1000 /foo/bar 0} test zlib-11.3 {Bug 3595576 variant} -setup { set file [makeFile {} test.input] } -constraints zlib -body { set f [open $file wb] puts -nonewline [zlib push gzip $f -header {filename /foo/bar}] \ [string repeat "hello" 1000] close $f set f [open $file rb] set d [read $f] close $f zlib gunzip $d -header noSuchNs::foo } -cleanup { removeFile $file } -returnCodes error -result {can't set "noSuchNs::foo": parent namespace doesn't exist} ::tcltest::cleanupTests return # Local Variables: # mode: tcl # End: |
Changes to tools/tcltk-man2html.tcl.
1 2 | #!/usr/bin/env tclsh | | > > > > > > | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | #!/usr/bin/env tclsh if {[catch {package require Tcl 8.6-} msg]} { puts stderr "ERROR: $msg" puts stderr "If running this script from 'make html', set the\ NATIVE_TCLSH environment\nvariable to point to an installed\ tclsh8.6 (or the equivalent tclsh86.exe\non Windows)." exit 1 } # Convert Ousterhout format man pages into highly crosslinked hypertext. # # Along the way detect many unmatched font changes and other odd things. # # Note well, this program is a hack rather than a piece of software # engineering. In that sense it's probably a good example of things # that a scripting language, like Tcl, can do well. It is offered as # an example of how someone might convert a specific set of man pages # into hypertext, not as a general solution to the problem. If you # try to use this, you'll be very much on your own. # # Copyright (c) 1995-1997 Roger E. Critchlow Jr # Copyright (c) 2004-2010 Donal K. Fellows set ::Version "50/8.6" set ::CSSFILE "docs.css" ## ## Source the utility functions that provide most of the ## implementation of the transformation from nroff to html. ## source [file join [file dirname [info script]] tcltk-man2html-utils.tcl] |
︙ | ︙ | |||
450 451 452 453 454 455 456 | proc plus-pkgs {type args} { global build_tcl tcltkdir tcldir if {$type ni {n 3}} { error "unknown type \"$type\": must be 3 or n" } if {!$build_tcl} return set result {} | > | | | | | < < | 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 | proc plus-pkgs {type args} { global build_tcl tcltkdir tcldir if {$type ni {n 3}} { error "unknown type \"$type\": must be 3 or n" } if {!$build_tcl} return set result {} set pkgsdir $tcltkdir/$tcldir/pkgs foreach {dir name version} $args { set globpat $pkgsdir/$dir/doc/*.$type if {![llength [glob -type f -nocomplain $globpat]]} { # Fallback for manpages generated using doctools set globpat $pkgsdir/$dir/doc/man/*.$type if {![llength [glob -type f -nocomplain $globpat]]} { continue } } switch $type { n { set title "$name Package Commands" if {$version ne ""} { append title ", version $version" } set dir [string totitle $dir]Cmd |
︙ | ︙ | |||
638 639 640 641 642 643 644 645 646 647 648 649 650 651 | } if {$build_tk} { append tcltkdesc "Tk" append cmdesc "Tk" append appdir "$tkdir" } # Get the list of packages to try, and what their human-readable names # are. Note that the package directory list should be version-less. try { set packageDirNameMap {} if {$build_tcl} { set f [open $tcltkdir/$tcldir/pkgs/package.list.txt] try { | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 | } if {$build_tk} { append tcltkdesc "Tk" append cmdesc "Tk" append appdir "$tkdir" } # When building docs for Tcl, try to build docs for bundled packages too set packageBuildList {} if {$build_tcl} { set pkgsDir [file join $tcltkdir $tcldir pkgs] set subdirs [glob -nocomplain -types d -tails -directory $pkgsDir *] foreach dir [lsort $subdirs] { # Parse the subdir name into (name, version) as fallback... set description [split $dir -] if {2 != [llength $description]} { regexp {([^0-9]*)(.*)} $dir -> n v set description [list $n $v] } # ... but try to extract (name, version) from subdir contents try { set f [open [file join $pkgsDir $dir configure.in]] foreach line [split [read $f] \n] { if {2 == [scan $line \ { AC_INIT ( [%[^]]] , [%[^]]] ) } n v]} { set description [list $n $v] break } } } finally { catch {close $f; unset f} } if {[file exists [file join $pkgsDir $dir configure]]} { # Looks like a package, record our best extraction attempt lappend packageBuildList $dir {*}$description } } } # Get the list of packages to try, and what their human-readable names # are. Note that the package directory list should be version-less. try { set packageDirNameMap {} if {$build_tcl} { set f [open $tcltkdir/$tcldir/pkgs/package.list.txt] try { |
︙ | ︙ | |||
662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 | set packageDirNameMap { itcl {[incr Tcl]} tdbc {TDBC} thread Thread } } # # Invoke the scraper/converter engine. # make-man-pages $webdir \ [list $tcltkdir/{$appdir}/doc/*.1 "$tcltkdesc Applications" UserCmd \ "The interpreters which implement $cmdesc."] \ [plus-base $build_tcl $tcldir doc/*.n {Tcl Commands} TclCmd \ "The commands which the <B>tclsh</B> interpreter implements."] \ [plus-base $build_tk $tkdir doc/*.n {Tk Commands} TkCmd \ "The additional commands which the <B>wish</B> interpreter implements."] \ | > > > > > > > > | | | 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 | set packageDirNameMap { itcl {[incr Tcl]} tdbc {TDBC} thread Thread } } # Convert to human readable names, if applicable for {set idx 0} {$idx < [llength $packageBuildList]} {incr idx 3} { lassign [lrange $packageBuildList $idx $idx+2] d n v if {[dict exists $packageDirNameMap $n]} { lset packageBuildList $idx+1 [dict get $packageDirNameMap $n] } } # # Invoke the scraper/converter engine. # make-man-pages $webdir \ [list $tcltkdir/{$appdir}/doc/*.1 "$tcltkdesc Applications" UserCmd \ "The interpreters which implement $cmdesc."] \ [plus-base $build_tcl $tcldir doc/*.n {Tcl Commands} TclCmd \ "The commands which the <B>tclsh</B> interpreter implements."] \ [plus-base $build_tk $tkdir doc/*.n {Tk Commands} TkCmd \ "The additional commands which the <B>wish</B> interpreter implements."] \ {*}[plus-pkgs n {*}$packageBuildList] \ [plus-base $build_tcl $tcldir doc/*.3 {Tcl C API} TclLib \ "The C functions which a Tcl extended C program may use."] \ [plus-base $build_tk $tkdir doc/*.3 {Tk C API} TkLib \ "The additional C functions which a Tk extended C program may use."] \ {*}[plus-pkgs 3 {*}$packageBuildList] } on error {msg opts} { # On failure make sure we show what went wrong. We're not supposed # to get here though; it represents a bug in the script. puts $msg\n[dict get $opts -errorinfo] exit 1 } # Local-Variables: # mode: tcl # End: |
Changes to unix/Makefile.in.
︙ | ︙ | |||
835 836 837 838 839 840 841 | $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"; \ done; @echo "Installing package http1.0 files to $(SCRIPT_INSTALL_DIR)/http1.0/"; @for i in $(TOP_DIR)/library/http1.0/*.tcl ; \ do \ $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"/http1.0; \ done; | | | | 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 | $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"; \ done; @echo "Installing package http1.0 files to $(SCRIPT_INSTALL_DIR)/http1.0/"; @for i in $(TOP_DIR)/library/http1.0/*.tcl ; \ do \ $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"/http1.0; \ done; @echo "Installing package http 2.8.6 as a Tcl Module"; @$(INSTALL_DATA) $(TOP_DIR)/library/http/http.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.6/http-2.8.6.tm; @echo "Installing package opt0.4 files to $(SCRIPT_INSTALL_DIR)/opt0.4/"; @for i in $(TOP_DIR)/library/opt/*.tcl ; \ do \ $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"/opt0.4; \ done; @echo "Installing package msgcat 1.5.0 as a Tcl Module"; @$(INSTALL_DATA) $(TOP_DIR)/library/msgcat/msgcat.tcl "$(SCRIPT_INSTALL_DIR)"/../tcl8/8.5/msgcat-1.5.0.tm; |
︙ | ︙ | |||
1714 1715 1716 1717 1718 1719 1720 | echo "Installing package '$$pkg'"; \ ( cd $(PKG_DIR)/$$pkg; $(MAKE) install \ "DESTDIR=$(INSTALL_ROOT)"; ) || exit $$?; \ fi; \ fi; \ done | | | 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 | echo "Installing package '$$pkg'"; \ ( cd $(PKG_DIR)/$$pkg; $(MAKE) install \ "DESTDIR=$(INSTALL_ROOT)"; ) || exit $$?; \ fi; \ fi; \ done test-packages: ${TCLTEST_EXE} packages @for i in $(PKGS_DIR)/*; do \ if [ -d $$i ]; then \ pkg=`basename $$i`; \ if [ -f $(PKG_DIR)/$$pkg/Makefile ]; then \ echo "Testing package '$$pkg'"; \ ( cd $(PKG_DIR)/$$pkg; $(MAKE) \ "@LD_LIBRARY_PATH_VAR@=../..:$${@LD_LIBRARY_PATH_VAR@}" \ |
︙ | ︙ |
Changes to unix/dltest/pkgb.c.
︙ | ︙ | |||
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | * Prototypes for procedures defined later in this file: */ static int Pkgb_SubObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int Pkgb_UnsafeObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* *---------------------------------------------------------------------- * * Pkgb_SubObjCmd -- * * This procedure is invoked to process the "pkgb_sub" Tcl command. It * expects two arguments and returns their difference. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ static int Pkgb_SubObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int first, second; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "num num"); return TCL_ERROR; } if ((Tcl_GetIntFromObj(interp, objv[1], &first) != TCL_OK) || (Tcl_GetIntFromObj(interp, objv[2], &second) != TCL_OK)) { return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewIntObj(first - second)); return TCL_OK; } /* | > > > > > > > > > | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | * Prototypes for procedures defined later in this file: */ static int Pkgb_SubObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int Pkgb_UnsafeObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int Pkgb_DemoObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* *---------------------------------------------------------------------- * * Pkgb_SubObjCmd -- * * This procedure is invoked to process the "pkgb_sub" Tcl command. It * expects two arguments and returns their difference. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ #ifndef Tcl_GetErrorLine # define Tcl_GetErrorLine(interp) ((interp)->errorLine) #endif static int Pkgb_SubObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int first, second; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "num num"); return TCL_ERROR; } if ((Tcl_GetIntFromObj(interp, objv[1], &first) != TCL_OK) || (Tcl_GetIntFromObj(interp, objv[2], &second) != TCL_OK)) { char buf[TCL_INTEGER_SPACE]; sprintf(buf, "%d", Tcl_GetErrorLine(interp)); Tcl_AppendResult(interp, " in line: ", buf, NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewIntObj(first - second)); return TCL_OK; } /* |
︙ | ︙ | |||
80 81 82 83 84 85 86 | static int Pkgb_UnsafeObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { | > > > > > > > > > > > > > > > > > > | > | 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | static int Pkgb_UnsafeObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return Tcl_EvalEx(interp, "list unsafe command invoked", -1, TCL_EVAL_GLOBAL); } static int Pkgb_DemoObjCmd( ClientData dummy, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { #if (TCL_MAJOR_VERSION > 8) || (TCL_MINOR_VERSION > 4) Tcl_Obj *first; if (Tcl_ListObjIndex(NULL, Tcl_GetEncodingSearchPath(), 0, &first) == TCL_OK) { Tcl_SetObjResult(interp, first); } #else Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_GetDefaultEncodingDir(), -1)); #endif return TCL_OK; } /* *---------------------------------------------------------------------- * * Pkgb_Init -- |
︙ | ︙ | |||
108 109 110 111 112 113 114 | DLLEXPORT int Pkgb_Init( Tcl_Interp *interp) /* Interpreter in which the package is to be * made available. */ { int code; | | | | | | 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | DLLEXPORT int Pkgb_Init( Tcl_Interp *interp) /* Interpreter in which the package is to be * made available. */ { int code; if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) { return TCL_ERROR; } code = Tcl_PkgProvideEx(interp, "Pkgb", "2.3", NULL); if (code != TCL_OK) { return code; } Tcl_CreateObjCommand(interp, "pkgb_sub", Pkgb_SubObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "pkgb_unsafe", Pkgb_UnsafeObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "pkgb_demo", Pkgb_DemoObjCmd, NULL, NULL); return TCL_OK; } /* *---------------------------------------------------------------------- * * Pkgb_SafeInit -- |
︙ | ︙ | |||
145 146 147 148 149 150 151 | DLLEXPORT int Pkgb_SafeInit( Tcl_Interp *interp) /* Interpreter in which the package is to be * made available. */ { int code; | | | | 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | DLLEXPORT int Pkgb_SafeInit( Tcl_Interp *interp) /* Interpreter in which the package is to be * made available. */ { int code; if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) { return TCL_ERROR; } code = Tcl_PkgProvideEx(interp, "Pkgb", "2.3", NULL); if (code != TCL_OK) { return code; } Tcl_CreateObjCommand(interp, "pkgb_sub", Pkgb_SubObjCmd, NULL, NULL); return TCL_OK; } |
Changes to unix/tclUnixCompat.c.
︙ | ︙ | |||
991 992 993 994 995 996 997 | unsigned int index, /* Which CPUID value to retrieve. */ unsigned int *regsPtr) /* Registers after the CPUID. */ { int status = TCL_ERROR; /* See: <http://en.wikipedia.org/wiki/CPUID> */ #if defined(HAVE_CPUID) | > > > > > > > | < | | > | 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 | unsigned int index, /* Which CPUID value to retrieve. */ unsigned int *regsPtr) /* Registers after the CPUID. */ { int status = TCL_ERROR; /* See: <http://en.wikipedia.org/wiki/CPUID> */ #if defined(HAVE_CPUID) #if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64) __asm__ __volatile__("movq %%rbx, %%rsi \n\t" /* save %rbx */ "cpuid \n\t" "xchgq %%rsi, %%rbx \n\t" /* restore the old %rbx */ : "=a"(regsPtr[0]), "=S"(regsPtr[1]), "=c"(regsPtr[2]), "=d"(regsPtr[3]) : "a"(index)); #else __asm__ __volatile__("mov %%ebx, %%esi \n\t" /* save %ebx */ "cpuid \n\t" "xchg %%esi, %%ebx \n\t" /* restore the old %ebx */ : "=a"(regsPtr[0]), "=S"(regsPtr[1]), "=c"(regsPtr[2]), "=d"(regsPtr[3]) : "a"(index)); #endif status = TCL_OK; #endif return status; } /* * Local Variables: |
︙ | ︙ |
Changes to unix/tclUnixFCmd.c.
︙ | ︙ | |||
36 37 38 39 40 41 42 43 44 45 46 47 48 49 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ #include "tclInt.h" #include <utime.h> #include <grp.h> #ifndef HAVE_STRUCT_STAT_ST_BLKSIZE #ifndef NO_FSTATFS #include <sys/statfs.h> #endif | > | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. */ #include <sys/stat.h> #include "tclInt.h" #include <utime.h> #include <grp.h> #ifndef HAVE_STRUCT_STAT_ST_BLKSIZE #ifndef NO_FSTATFS #include <sys/statfs.h> #endif |
︙ | ︙ | |||
240 241 242 243 244 245 246 | # define haveRealpath (tclMacOSXDarwinRelease >= 7) #else # define haveRealpath 1 #endif #endif /* NO_REALPATH */ #ifdef HAVE_FTS | | | 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 | # define haveRealpath (tclMacOSXDarwinRelease >= 7) #else # define haveRealpath 1 #endif #endif /* NO_REALPATH */ #ifdef HAVE_FTS #if defined(HAVE_STRUCT_STAT64) && !defined(__APPLE__) /* fts doesn't do stat64 */ # define noFtsStat 1 #elif defined(__APPLE__) && defined(__LP64__) && \ defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \ MAC_OS_X_VERSION_MIN_REQUIRED < 1050 /* * Prior to Darwin 9, 64bit fts_open() without FTS_NOSTAT may crash (due to a |
︙ | ︙ |
Changes to unix/tclUnixFile.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* * tclUnixFile.c -- * * This file contains wrappers around UNIX file handling functions. * These wrappers mask differences between Windows and UNIX. * * Copyright (c) 1995-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclFileSystem.h" static int NativeMatchType(Tcl_Interp *interp, const char* nativeEntry, const char* nativeName, Tcl_GlobTypeData *types); /* | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /* * tclUnixFile.c -- * * This file contains wrappers around UNIX file handling functions. * These wrappers mask differences between Windows and UNIX. * * Copyright (c) 1995-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include <sys/stat.h> #include "tclInt.h" #include "tclFileSystem.h" static int NativeMatchType(Tcl_Interp *interp, const char* nativeEntry, const char* nativeName, Tcl_GlobTypeData *types); /* |
︙ | ︙ | |||
1177 1178 1179 1180 1181 1182 1183 | } #ifdef __CYGWIN__ int TclOSstat( const char *name, | | > | > | 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 | } #ifdef __CYGWIN__ int TclOSstat( const char *name, void *cygstat) { struct stat buf; Tcl_StatBuf *statBuf = cygstat; int result = stat(name, &buf); statBuf->st_mode = buf.st_mode; statBuf->st_ino = buf.st_ino; statBuf->st_dev = buf.st_dev; statBuf->st_rdev = buf.st_rdev; statBuf->st_nlink = buf.st_nlink; statBuf->st_uid = buf.st_uid; statBuf->st_gid = buf.st_gid; statBuf->st_size = buf.st_size; statBuf->st_atime = buf.st_atime; statBuf->st_mtime = buf.st_mtime; statBuf->st_ctime = buf.st_ctime; return result; } int TclOSlstat( const char *name, void *cygstat) { struct stat buf; Tcl_StatBuf *statBuf = cygstat; int result = lstat(name, &buf); statBuf->st_mode = buf.st_mode; statBuf->st_ino = buf.st_ino; statBuf->st_dev = buf.st_dev; statBuf->st_rdev = buf.st_rdev; statBuf->st_nlink = buf.st_nlink; |
︙ | ︙ |
Changes to unix/tclUnixInit.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | /* * tclUnixInit.c -- * * Contains the Unix-specific interpreter initialization functions. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright (c) 1999 by Scriptics Corporation. * All rights reserved. */ #include "tclInt.h" #include <stddef.h> #include <locale.h> #ifdef HAVE_LANGINFO # include <langinfo.h> # ifdef __APPLE__ # if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1030 | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /* * tclUnixInit.c -- * * Contains the Unix-specific interpreter initialization functions. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright (c) 1999 by Scriptics Corporation. * All rights reserved. */ #include <sys/stat.h> #include "tclInt.h" #include <stddef.h> #include <locale.h> #ifdef HAVE_LANGINFO # include <langinfo.h> # ifdef __APPLE__ # if defined(HAVE_WEAK_IMPORT) && MAC_OS_X_VERSION_MIN_REQUIRED < 1030 |
︙ | ︙ |
Changes to unix/tclUnixPort.h.
︙ | ︙ | |||
17 18 19 20 21 22 23 | * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TCLUNIXPORT #define _TCLUNIXPORT | < < < < | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TCLUNIXPORT #define _TCLUNIXPORT /* *--------------------------------------------------------------------------- * The following sets of #includes and #ifdefs are required to get Tcl to * compile under the various flavors of unix. *--------------------------------------------------------------------------- */ |
︙ | ︙ | |||
85 86 87 88 89 90 91 | # define CP_UTF8 65001 # define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 0x00000004 # define HANDLE void * # define HINSTANCE void * # define SOCKET unsigned int # define WSAEWOULDBLOCK 10035 typedef unsigned short WCHAR; | | | | | | | | | | | | | < | < | 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | # define CP_UTF8 65001 # define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 0x00000004 # define HANDLE void * # define HINSTANCE void * # define SOCKET unsigned int # define WSAEWOULDBLOCK 10035 typedef unsigned short WCHAR; __declspec(dllimport) extern __stdcall int GetModuleHandleExW(unsigned int, const char *, void *); __declspec(dllimport) extern __stdcall int GetModuleFileNameW(void *, const char *, int); __declspec(dllimport) extern __stdcall int WideCharToMultiByte(int, int, const char *, int, const char *, int, const char *, const char *); __declspec(dllimport) extern __stdcall int MultiByteToWideChar(int, int, const char *, int, WCHAR *, int); __declspec(dllimport) extern __stdcall void OutputDebugStringW(const WCHAR *); __declspec(dllimport) extern __stdcall int IsDebuggerPresent(); __declspec(dllimport) extern int cygwin_conv_path(int, const void *, void *, int); __declspec(dllimport) extern int cygwin_conv_path_list(int, const void *, void *, int); # define USE_PUTENV 1 # define USE_PUTENV_FOR_UNSET 1 /* On Cygwin, the environment is imported from the Cygwin DLL. */ # define environ __cygwin_environ # define timezone _timezone extern char **__cygwin_environ; extern int TclOSstat(const char *name, void *statBuf); extern int TclOSlstat(const char *name, void *statBuf); #elif defined(HAVE_STRUCT_STAT64) && !defined(__APPLE__) # define TclOSstat stat64 # define TclOSlstat lstat64 #else # define TclOSstat stat # define TclOSlstat lstat #endif /* *--------------------------------------------------------------------------- * Miscellaneous includes that might be missing. *--------------------------------------------------------------------------- */ #include <sys/file.h> #ifdef HAVE_SYS_SELECT_H # include <sys/select.h> #endif #include <sys/stat.h> #if TIME_WITH_SYS_TIME # include <sys/time.h> # include <time.h> #else #if HAVE_SYS_TIME_H # include <sys/time.h> #else |
︙ | ︙ | |||
155 156 157 158 159 160 161 | #endif #ifdef HAVE_UNISTD_H # include <unistd.h> #else # include "../compat/unistd.h" #endif | | | 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | #endif #ifdef HAVE_UNISTD_H # include <unistd.h> #else # include "../compat/unistd.h" #endif extern int TclUnixSetBlockingMode(int fd, int mode); #include <utime.h> /* *--------------------------------------------------------------------------- * Socket support stuff: This likely needs more work to parameterize for each * system. |
︙ | ︙ | |||
315 316 317 318 319 320 321 | #else # ifdef HAVE_BSDGETTIMEOFDAY # define gettimeofday BSDgettimeofday # endif #endif #ifdef GETTOD_NOT_DECLARED | | | 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 | #else # ifdef HAVE_BSDGETTIMEOFDAY # define gettimeofday BSDgettimeofday # endif #endif #ifdef GETTOD_NOT_DECLARED extern int gettimeofday(struct timeval *tp, struct timezone *tzp); #endif /* *--------------------------------------------------------------------------- * Define access mode constants if they aren't already defined. *--------------------------------------------------------------------------- |
︙ | ︙ | |||
733 734 735 736 737 738 739 | * to the TSD data. *--------------------------------------------------------------------------- */ #include <pwd.h> #include <grp.h> | | | | | | | | | | 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 | * to the TSD data. *--------------------------------------------------------------------------- */ #include <pwd.h> #include <grp.h> extern struct passwd * TclpGetPwNam(const char *name); extern struct group * TclpGetGrNam(const char *name); extern struct passwd * TclpGetPwUid(uid_t uid); extern struct group * TclpGetGrGid(gid_t gid); extern struct hostent * TclpGetHostByName(const char *name); extern struct hostent * TclpGetHostByAddr(const char *addr, int length, int type); extern void *TclpMakeTcpClientChannelMode( void *tcpSocket, int mode); #endif /* _TCLUNIXPORT */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ |
Changes to unix/tclUnixSock.c.
︙ | ︙ | |||
1198 1199 1200 1201 1202 1203 1204 | *---------------------------------------------------------------------- */ Tcl_Channel Tcl_MakeTcpClientChannel( ClientData sock) /* The socket to wrap up into a channel. */ { | | < > | | 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 | *---------------------------------------------------------------------- */ Tcl_Channel Tcl_MakeTcpClientChannel( ClientData sock) /* The socket to wrap up into a channel. */ { return (Tcl_Channel) TclpMakeTcpClientChannelMode(sock, (TCL_READABLE | TCL_WRITABLE)); } /* *---------------------------------------------------------------------- * * TclpMakeTcpClientChannelMode -- * * Creates a Tcl_Channel from an existing client TCP socket * with given mode. * * Results: * The Tcl_Channel wrapped around the preexisting TCP socket. * * Side effects: * None. * *---------------------------------------------------------------------- */ void * TclpMakeTcpClientChannelMode( void *sock, /* The socket to wrap up into a channel. */ int mode) /* ORed combination of TCL_READABLE and * TCL_WRITABLE to indicate file mode. */ { TcpState *statePtr; char channelName[SOCK_CHAN_LENGTH]; statePtr = ckalloc(sizeof(TcpState)); |
︙ | ︙ |
Changes to unix/tclUnixTest.c.
︙ | ︙ | |||
196 197 198 199 200 201 202 | if (argc != 3) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], " counts index\"", NULL); return TCL_ERROR; } sprintf(buf, "%d %d", pipePtr->readCount, pipePtr->writeCount); | | | | | 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | if (argc != 3) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], " counts index\"", NULL); return TCL_ERROR; } sprintf(buf, "%d %d", pipePtr->readCount, pipePtr->writeCount); Tcl_AppendResult(interp, buf, NULL); } else if (strcmp(argv[1], "create") == 0) { if (argc != 5) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], " create index readMode writeMode\"", NULL); return TCL_ERROR; } if (pipePtr->readFile == NULL) { if (!TclpCreatePipe(&pipePtr->readFile, &pipePtr->writeFile)) { Tcl_AppendResult(interp, "couldn't open pipe: ", Tcl_PosixError(interp), NULL); return TCL_ERROR; } #ifdef O_NONBLOCK fcntl(GetFd(pipePtr->readFile), F_SETFL, O_NONBLOCK); fcntl(GetFd(pipePtr->writeFile), F_SETFL, O_NONBLOCK); #else Tcl_AppendResult(interp, "can't make pipes non-blocking", NULL); return TCL_ERROR; #endif } pipePtr->readCount = 0; pipePtr->writeCount = 0; if (strcmp(argv[3], "readable") == 0) { |
︙ | ︙ | |||
277 278 279 280 281 282 283 | Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], " fillpartial index\"", NULL); return TCL_ERROR; } memset(buffer, 'b', 10); TclFormatInt(buf, write(GetFd(pipePtr->writeFile), buffer, 10)); | | | 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 | Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], " fillpartial index\"", NULL); return TCL_ERROR; } memset(buffer, 'b', 10); TclFormatInt(buf, write(GetFd(pipePtr->writeFile), buffer, 10)); 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) { if (argc != 5) { Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0], " wait index readable|writable timeout\"", NULL); return TCL_ERROR; |
︙ | ︙ | |||
386 387 388 389 390 391 392 | Tcl_AppendResult(interp, "bad argument \"", argv[2], "\": must be readable, writable, or both", NULL); return TCL_ERROR; } if (Tcl_GetChannelHandle(channel, (mask & TCL_READABLE) ? TCL_READABLE : TCL_WRITABLE, (ClientData*) &data) != TCL_OK) { | | | 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 | Tcl_AppendResult(interp, "bad argument \"", argv[2], "\": must be readable, writable, or both", NULL); return TCL_ERROR; } if (Tcl_GetChannelHandle(channel, (mask & TCL_READABLE) ? TCL_READABLE : TCL_WRITABLE, (ClientData*) &data) != TCL_OK) { Tcl_AppendResult(interp, "couldn't get channel file", NULL); return TCL_ERROR; } fd = PTR2INT(data); if (Tcl_GetInt(interp, argv[3], &timeout) != TCL_OK) { return TCL_ERROR; } result = TclUnixWaitForFile(fd, mask, timeout); |
︙ | ︙ |
Changes to unix/tclUnixTime.c.
︙ | ︙ | |||
379 380 381 382 383 384 385 | newTZ = ""; } if (lastTZ == NULL || strcmp(lastTZ, newTZ)) { tzset(); if (lastTZ == NULL) { Tcl_CreateExitHandler(CleanupMemory, NULL); } else { | | | 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 | newTZ = ""; } if (lastTZ == NULL || strcmp(lastTZ, newTZ)) { tzset(); if (lastTZ == NULL) { Tcl_CreateExitHandler(CleanupMemory, NULL); } else { ckfree(lastTZ); } lastTZ = ckalloc(strlen(newTZ) + 1); strcpy(lastTZ, newTZ); } Tcl_MutexUnlock(&tmMutex); } |
︙ | ︙ |
Changes to unix/tclooConfig.sh.
︙ | ︙ | |||
12 13 14 15 16 17 18 | # These are mostly empty because no special steps are ever needed from Tcl 8.6 # onwards; all libraries and include files are just part of Tcl. TCLOO_LIB_SPEC="" TCLOO_STUB_LIB_SPEC="" TCLOO_INCLUDE_SPEC="" TCLOO_PRIVATE_INCLUDE_SPEC="" TCLOO_CFLAGS="" | | | 12 13 14 15 16 17 18 19 | # These are mostly empty because no special steps are ever needed from Tcl 8.6 # onwards; all libraries and include files are just part of Tcl. TCLOO_LIB_SPEC="" TCLOO_STUB_LIB_SPEC="" TCLOO_INCLUDE_SPEC="" TCLOO_PRIVATE_INCLUDE_SPEC="" TCLOO_CFLAGS="" TCLOO_VERSION=1.0 |
Changes to win/Makefile.in.
︙ | ︙ | |||
77 78 79 80 81 82 83 84 85 86 87 88 89 90 | # To change the compiler switches, for example to change from optimization to # debugging symbols, change the following line: #CFLAGS = $(CFLAGS_DEBUG) #CFLAGS = $(CFLAGS_OPTIMIZE) #CFLAGS = $(CFLAGS_DEBUG) $(CFLAGS_OPTIMIZE) CFLAGS = @CFLAGS@ @CFLAGS_DEFAULT@ -DUNICODE -D_UNICODE # To enable compilation debugging reverse the comment characters on one of the # following lines. COMPILE_DEBUG_FLAGS = #COMPILE_DEBUG_FLAGS = -DTCL_COMPILE_DEBUG #COMPILE_DEBUG_FLAGS = -DTCL_COMPILE_DEBUG -DTCL_COMPILE_STATS | > > > > > | 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | # To change the compiler switches, for example to change from optimization to # debugging symbols, change the following line: #CFLAGS = $(CFLAGS_DEBUG) #CFLAGS = $(CFLAGS_OPTIMIZE) #CFLAGS = $(CFLAGS_DEBUG) $(CFLAGS_OPTIMIZE) CFLAGS = @CFLAGS@ @CFLAGS_DEFAULT@ -DUNICODE -D_UNICODE # To compile without backward compatibility and deprecated code uncomment the # following NO_DEPRECATED_FLAGS = #NO_DEPRECATED_FLAGS = -DTCL_NO_DEPRECATED # To enable compilation debugging reverse the comment characters on one of the # following lines. COMPILE_DEBUG_FLAGS = #COMPILE_DEBUG_FLAGS = -DTCL_COMPILE_DEBUG #COMPILE_DEBUG_FLAGS = -DTCL_COMPILE_DEBUG -DTCL_COMPILE_STATS |
︙ | ︙ | |||
183 184 185 186 187 188 189 | SHELL = @SHELL@ RM = rm -f COPY = cp CC_SWITCHES = ${CFLAGS} ${CFLAGS_WARNING} ${TCL_SHLIB_CFLAGS} -I"${ZLIB_DIR}" \ -I"${GENERIC_DIR_NATIVE}" -DTCL_TOMMATH -DMP_PREC=4 -I"${TOMMATH_DIR_NATIVE}" \ -I"${WIN_DIR_NATIVE}" ${AC_FLAGS} \ | | | 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | SHELL = @SHELL@ RM = rm -f COPY = cp CC_SWITCHES = ${CFLAGS} ${CFLAGS_WARNING} ${TCL_SHLIB_CFLAGS} -I"${ZLIB_DIR}" \ -I"${GENERIC_DIR_NATIVE}" -DTCL_TOMMATH -DMP_PREC=4 -I"${TOMMATH_DIR_NATIVE}" \ -I"${WIN_DIR_NATIVE}" ${AC_FLAGS} \ ${COMPILE_DEBUG_FLAGS} ${NO_DEPRECATED_FLAGS} CC_OBJNAME = @CC_OBJNAME@ CC_EXENAME = @CC_EXENAME@ STUB_CC_SWITCHES = ${CFLAGS} ${CFLAGS_WARNING} ${SHLIB_CFLAGS} \ -I"${GENERIC_DIR_NATIVE}" -DTCL_TOMMATH -DMP_PREC=4 -I"${TOMMATH_DIR_NATIVE}" \ -I"${WIN_DIR_NATIVE}" ${AC_FLAGS} \ |
︙ | ︙ | |||
630 631 632 633 634 635 636 | $(COPY) "$$i" "$(SCRIPT_INSTALL_DIR)"; \ done; @echo "Installing library http1.0 directory"; @for j in $(ROOT_DIR)/library/http1.0/*.tcl; \ do \ $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/http1.0"; \ done; | | | | 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 | $(COPY) "$$i" "$(SCRIPT_INSTALL_DIR)"; \ done; @echo "Installing library http1.0 directory"; @for j in $(ROOT_DIR)/library/http1.0/*.tcl; \ do \ $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/http1.0"; \ done; @echo "Installing package http 2.8.6 as a Tcl Module"; @$(COPY) $(ROOT_DIR)/library/http/http.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.6/http-2.8.6.tm; @echo "Installing library opt0.4 directory"; @for j in $(ROOT_DIR)/library/opt/*.tcl; \ do \ $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/opt0.4"; \ done; @echo "Installing package msgcat 1.5.0 as a Tcl Module"; @$(COPY) $(ROOT_DIR)/library/msgcat/msgcat.tcl $(SCRIPT_INSTALL_DIR)/../tcl8/8.5/msgcat-1.5.0.tm; |
︙ | ︙ | |||
747 748 749 750 751 752 753 | if [ -d $$i ] ; then \ if [ -x $$i/configure ] ; then \ pkg=`basename $$i`; \ mkdir -p $(PKG_DIR)/$$pkg; \ if [ ! -f $(PKG_DIR)/$$pkg/Makefile ]; then \ ( cd $(PKG_DIR)/$$pkg; \ echo "Configuring package '$$i' wd = `pwd -P`"; \ | | | 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 | if [ -d $$i ] ; then \ if [ -x $$i/configure ] ; then \ pkg=`basename $$i`; \ mkdir -p $(PKG_DIR)/$$pkg; \ if [ ! -f $(PKG_DIR)/$$pkg/Makefile ]; then \ ( cd $(PKG_DIR)/$$pkg; \ echo "Configuring package '$$i' wd = `pwd -P`"; \ $$i/configure --with-tcl=$$builddir --with-tclinclude=$(GENERIC_DIR) $(PKG_CFG_ARGS) --enable-shared --enable-threads; ) \ fi ; \ echo "Building package '$$pkg'"; \ ( cd $(PKG_DIR)/$$pkg; $(MAKE); ) \ fi; \ fi; \ done; \ cd $$builddir |
︙ | ︙ |
Changes to win/tcl.m4.
1 2 3 4 5 | #------------------------------------------------------------------------ # SC_PATH_TCLCONFIG -- # # Locate the tclConfig.sh file and perform a sanity check on # the Tcl compile flags | < < > | | > > | > > | | > > > > > > > > > | > | > | > > > > > > > | < > | > > > > > > > > > > > > > > > > > > > > > > > < < > > > > > > > > > > > > | < > > | > > | > | > > > > > | > > | > > > > > > > > > > | | | < | | > > | > > | | > > > > > > > > > | > | > | > > > > > > > | < > | > > > > > > > > > > > > > > > > > > > > > > > < < > > > > > > > > > > > > | < > > | > > | > > > > > > > | > > | > > > > > > > > > | > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 | #------------------------------------------------------------------------ # SC_PATH_TCLCONFIG -- # # Locate the tclConfig.sh file and perform a sanity check on # the Tcl compile flags # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --with-tcl=... # # Defines the following vars: # TCL_BIN_DIR Full path to the directory containing # the tclConfig.sh file #------------------------------------------------------------------------ AC_DEFUN([SC_PATH_TCLCONFIG], [ # # Ok, lets find the tcl configuration # First, look for one uninstalled. # the alternative search directory is invoked by --with-tcl # if test x"${no_tcl}" = x ; then # we reset no_tcl in case something fails here no_tcl=true AC_ARG_WITH(tcl, AC_HELP_STRING([--with-tcl], [directory containing tcl configuration (tclConfig.sh)]), with_tclconfig="${withval}") AC_MSG_CHECKING([for Tcl configuration]) AC_CACHE_VAL(ac_cv_c_tclconfig,[ # First check to see if --with-tcl was specified. if test x"${with_tclconfig}" != x ; then case "${with_tclconfig}" in */tclConfig.sh ) if test -f "${with_tclconfig}"; then AC_MSG_WARN([--with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself]) with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`" fi ;; esac if test -f "${with_tclconfig}/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`" else AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh]) fi fi # then check for a private Tcl installation if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ ../tcl \ `ls -dr ../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../tcl[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ ../../tcl \ `ls -dr ../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../../tcl[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ ../../../tcl \ `ls -dr ../../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../../../tcl[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do if test -f "$i/win/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/win; pwd)`" break fi done fi # check in a few common install locations if test x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d ${libdir} 2>/dev/null` \ `ls -d ${exec_prefix}/lib 2>/dev/null` \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /cygdrive/c/Tcl/lib 2>/dev/null` \ `ls -d /cygdrive/c/Progra~1/Tcl/lib 2>/dev/null` \ `ls -d /c/Tcl/lib 2>/dev/null` \ `ls -d /c/Progra~1/Tcl/lib 2>/dev/null` \ `ls -d C:/Tcl/lib 2>/dev/null` \ `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ ; do if test -f "$i/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i; pwd)`" break fi done fi # check in a few other private locations if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ ${srcdir}/../tcl \ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do if test -f "$i/win/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/win; pwd)`" break fi done fi ]) if test x"${ac_cv_c_tclconfig}" = x ; then TCL_BIN_DIR="# no Tcl configs found" AC_MSG_ERROR([Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh]) else no_tcl= TCL_BIN_DIR="${ac_cv_c_tclconfig}" AC_MSG_RESULT([found ${TCL_BIN_DIR}/tclConfig.sh]) fi fi ]) #------------------------------------------------------------------------ # SC_PATH_TKCONFIG -- # # Locate the tkConfig.sh file # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --with-tk=... # # Defines the following vars: # TK_BIN_DIR Full path to the directory containing # the tkConfig.sh file #------------------------------------------------------------------------ AC_DEFUN([SC_PATH_TKCONFIG], [ # # Ok, lets find the tk configuration # First, look for one uninstalled. # the alternative search directory is invoked by --with-tk # if test x"${no_tk}" = x ; then # we reset no_tk in case something fails here no_tk=true AC_ARG_WITH(tk, AC_HELP_STRING([--with-tk], [directory containing tk configuration (tkConfig.sh)]), with_tkconfig="${withval}") AC_MSG_CHECKING([for Tk configuration]) AC_CACHE_VAL(ac_cv_c_tkconfig,[ # First check to see if --with-tkconfig was specified. if test x"${with_tkconfig}" != x ; then case "${with_tkconfig}" in */tkConfig.sh ) if test -f "${with_tkconfig}"; then AC_MSG_WARN([--with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself]) with_tkconfig="`echo "${with_tkconfig}" | sed 's!/tkConfig\.sh$!!'`" fi ;; esac if test -f "${with_tkconfig}/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd "${with_tkconfig}"; pwd)`" else AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh]) fi fi # then check for a private Tk library if test x"${ac_cv_c_tkconfig}" = x ; then for i in \ ../tk \ `ls -dr ../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../tk[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../tk[[8-9]].[[0-9]]* 2>/dev/null` \ ../../tk \ `ls -dr ../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../../tk[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../tk[[8-9]].[[0-9]]* 2>/dev/null` \ ../../../tk \ `ls -dr ../../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../../../tk[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do if test -f "$i/win/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i/win; pwd)`" break fi done fi # check in a few common install locations if test x"${ac_cv_c_tkconfig}" = x ; then for i in `ls -d ${libdir} 2>/dev/null` \ `ls -d ${exec_prefix}/lib 2>/dev/null` \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /cygdrive/c/Tcl/lib 2>/dev/null` \ `ls -d /cygdrive/c/Progra~1/Tcl/lib 2>/dev/null` \ `ls -d /c/Tcl/lib 2>/dev/null` \ `ls -d /c/Progra~1/Tcl/lib 2>/dev/null` \ `ls -d C:/Tcl/lib 2>/dev/null` \ `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ ; do if test -f "$i/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i; pwd)`" break fi done fi # check in a few other private locations if test x"${ac_cv_c_tkconfig}" = x ; then for i in \ ${srcdir}/../tk \ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do if test -f "$i/win/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i/win; pwd)`" break fi done fi ]) if test x"${ac_cv_c_tkconfig}" = x ; then TK_BIN_DIR="# no Tk configs found" AC_MSG_ERROR([Can't find Tk configuration definitions. Use --with-tk to specify a directory containing tkConfig.sh]) else no_tk= TK_BIN_DIR="${ac_cv_c_tkconfig}" AC_MSG_RESULT([found ${TK_BIN_DIR}/tkConfig.sh]) fi fi ]) #------------------------------------------------------------------------ # SC_LOAD_TCLCONFIG -- # # Load the tclConfig.sh file. # |
︙ | ︙ |
Changes to win/tclWinFile.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 15 16 17 | * * Copyright (c) 1995-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclWinInt.h" #include "tclFileSystem.h" #include <winioctl.h> | > < | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | * * Copyright (c) 1995-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include <sys/stat.h> #include "tclWinInt.h" #include "tclFileSystem.h" #include <winioctl.h> #include <shlobj.h> #include <lm.h> /* For TclpGetUserHome(). */ /* * The number of 100-ns intervals between the Windows system epoch (1601-01-01 * on the proleptic Gregorian calendar) and the Posix epoch (1970-01-01). */ |
︙ | ︙ | |||
156 157 158 159 160 161 162 | static int NativeDev(const TCHAR *path); static int NativeStat(const TCHAR *path, Tcl_StatBuf *statPtr, int checkLinks); static unsigned short NativeStatMode(DWORD attr, int checkLinks, int isExec); static int NativeIsExec(const TCHAR *path); static int NativeReadReparse(const TCHAR *LinkDirectory, | | | 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | static int NativeDev(const TCHAR *path); static int NativeStat(const TCHAR *path, Tcl_StatBuf *statPtr, int checkLinks); static unsigned short NativeStatMode(DWORD attr, int checkLinks, int isExec); static int NativeIsExec(const TCHAR *path); static int NativeReadReparse(const TCHAR *LinkDirectory, REPARSE_DATA_BUFFER *buffer, DWORD desiredAccess); static int NativeWriteReparse(const TCHAR *LinkDirectory, REPARSE_DATA_BUFFER *buffer); static int NativeMatchType(int isDrive, DWORD attr, const TCHAR *nativeName, Tcl_GlobTypeData *types); static int WinIsDrive(const char *name, int nameLen); static int WinIsReserved(const char *path); static Tcl_Obj * WinReadLink(const TCHAR *LinkSource); |
︙ | ︙ | |||
440 441 442 443 444 445 446 | TclWinSymLinkCopyDirectory( const TCHAR *linkOrigPath, /* Existing junction - reparse point */ const TCHAR *linkCopyPath) /* Will become a duplicate junction */ { DUMMY_REPARSE_BUFFER dummy; REPARSE_DATA_BUFFER *reparseBuffer = (REPARSE_DATA_BUFFER *) &dummy; | | | 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 | TclWinSymLinkCopyDirectory( const TCHAR *linkOrigPath, /* Existing junction - reparse point */ const TCHAR *linkCopyPath) /* Will become a duplicate junction */ { DUMMY_REPARSE_BUFFER dummy; REPARSE_DATA_BUFFER *reparseBuffer = (REPARSE_DATA_BUFFER *) &dummy; if (NativeReadReparse(linkOrigPath, reparseBuffer, GENERIC_READ)) { return -1; } return NativeWriteReparse(linkCopyPath, reparseBuffer); } /* *-------------------------------------------------------------------- |
︙ | ︙ | |||
538 539 540 541 542 543 544 | Tcl_DString ds; const char *copy; attr = GetFileAttributes(linkDirPath); if (!(attr & FILE_ATTRIBUTE_REPARSE_POINT)) { goto invalidError; } | | | 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 | Tcl_DString ds; const char *copy; attr = GetFileAttributes(linkDirPath); if (!(attr & FILE_ATTRIBUTE_REPARSE_POINT)) { goto invalidError; } if (NativeReadReparse(linkDirPath, reparseBuffer, 0)) { return NULL; } switch (reparseBuffer->ReparseTag) { case 0x80000000|IO_REPARSE_TAG_SYMBOLIC_LINK: case IO_REPARSE_TAG_SYMBOLIC_LINK: case IO_REPARSE_TAG_MOUNT_POINT: |
︙ | ︙ | |||
659 660 661 662 663 664 665 | * *-------------------------------------------------------------------- */ static int NativeReadReparse( const TCHAR *linkDirPath, /* The junction to read */ | | > | | 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 | * *-------------------------------------------------------------------- */ static int NativeReadReparse( const TCHAR *linkDirPath, /* The junction to read */ REPARSE_DATA_BUFFER *buffer,/* Pointer to buffer. Cannot be NULL */ DWORD desiredAccess) { HANDLE hFile; DWORD returnedLength; hFile = CreateFile(linkDirPath, desiredAccess, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL); if (hFile == INVALID_HANDLE_VALUE) { /* * Error creating directory. */ |
︙ | ︙ |
Changes to win/tclWinTest.c.
︙ | ︙ | |||
207 208 209 210 211 212 213 | if (found == 0) { Tcl_AppendResult(interp, "could not get volume type for \"", (path?path:""), "\"", NULL); TclWinConvertError(GetLastError()); return TCL_ERROR; } | | | 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | if (found == 0) { Tcl_AppendResult(interp, "could not get volume type for \"", (path?path:""), "\"", NULL); TclWinConvertError(GetLastError()); return TCL_ERROR; } Tcl_AppendResult(interp, volType, NULL); return TCL_OK; #undef VOL_BUF_SIZE } /* *---------------------------------------------------------------------- * |
︙ | ︙ |
Changes to win/tclooConfig.sh.
︙ | ︙ | |||
12 13 14 15 16 17 18 | # These are mostly empty because no special steps are ever needed from Tcl 8.6 # onwards; all libraries and include files are just part of Tcl. TCLOO_LIB_SPEC="" TCLOO_STUB_LIB_SPEC="" TCLOO_INCLUDE_SPEC="" TCLOO_PRIVATE_INCLUDE_SPEC="" TCLOO_CFLAGS="" | | | 12 13 14 15 16 17 18 19 | # These are mostly empty because no special steps are ever needed from Tcl 8.6 # onwards; all libraries and include files are just part of Tcl. TCLOO_LIB_SPEC="" TCLOO_STUB_LIB_SPEC="" TCLOO_INCLUDE_SPEC="" TCLOO_PRIVATE_INCLUDE_SPEC="" TCLOO_CFLAGS="" TCLOO_VERSION=1.0 |