Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
58a1e3a324 | ||
|
|
43504d449b | ||
|
|
5e6bac514b | ||
|
|
14dd351c95 | ||
|
|
14e867f82b | ||
|
|
368c0890ab | ||
|
|
8c908a8136 |
@@ -3,17 +3,12 @@ compat/zlib/contrib/vstudio/readme.txt
|
||||
compat/zlib/contrib/vstudio/*/zlib.rc
|
||||
compat/zlib/win32/*.txt
|
||||
compat/zlib/win64/*.txt
|
||||
libtommath/*.dsp
|
||||
libtommath/*.sln
|
||||
libtommath/*.vcproj
|
||||
tools/tcl.hpj.in
|
||||
tools/tcl.wse.in
|
||||
win/buildall.vc.bat
|
||||
win/coffbase.txt
|
||||
win/makefile.vc
|
||||
win/rules.vc
|
||||
win/rules-ext.vc
|
||||
win/targets.vc
|
||||
win/tcl.dsp
|
||||
win/tcl.dsw
|
||||
win/tcl.hpj.in
|
||||
@@ -3,17 +3,12 @@ compat/zlib/contrib/vstudio/readme.txt
|
||||
compat/zlib/contrib/vstudio/*/zlib.rc
|
||||
compat/zlib/win32/*.txt
|
||||
compat/zlib/win64/*.txt
|
||||
libtommath/*.dsp
|
||||
libtommath/*.sln
|
||||
libtommath/*.vcproj
|
||||
tools/tcl.hpj.in
|
||||
tools/tcl.wse.in
|
||||
win/buildall.vc.bat
|
||||
win/coffbase.txt
|
||||
win/makefile.vc
|
||||
win/rules.vc
|
||||
win/rules-ext.vc
|
||||
win/targets.vc
|
||||
win/tcl.dsp
|
||||
win/tcl.dsw
|
||||
win/tcl.hpj.in
|
||||
@@ -18,7 +18,6 @@
|
||||
*/tclsh*
|
||||
*/tcltest*
|
||||
*/versions.vc
|
||||
*/version.vc
|
||||
html
|
||||
libtommath/bn.ilg
|
||||
libtommath/bn.ind
|
||||
@@ -41,9 +40,7 @@ unix/dltest.marker
|
||||
unix/tcl.pc
|
||||
unix/tclIndex
|
||||
unix/pkgs/*
|
||||
win/Debug*
|
||||
win/Release*
|
||||
win/Debug_VC*
|
||||
win/Release_VC*
|
||||
win/pkgs/*
|
||||
win/coffbase.txt
|
||||
win/tcl.hpj
|
||||
win/nmhlp-out.txt
|
||||
win/tcl.hpj
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>tcl9</name>
|
||||
<name>tcl8.7</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
README: Tcl
|
||||
This is the Tcl 9.0a0 source distribution.
|
||||
This is the Tcl 8.7a0 source distribution.
|
||||
http://sourceforge.net/projects/tcl/files/Tcl/
|
||||
You can get any source release of Tcl from the URL above.
|
||||
|
||||
@@ -49,7 +49,7 @@ and selling it either in whole or in part. See the file
|
||||
|
||||
Extensive documentation is available at our website.
|
||||
The home page for this release, including new features, is
|
||||
http://www.tcl.tk/software/tcltk/9.0.html
|
||||
http://www.tcl.tk/software/tcltk/8.7.html
|
||||
|
||||
Detailed release notes can be found at the file distributions page
|
||||
by clicking on the relevant version.
|
||||
@@ -61,9 +61,9 @@ Information about Tcl itself can be found at
|
||||
There have been many Tcl books on the market. Many are mentioned in the Wiki:
|
||||
http://wiki.tcl.tk/_/ref?N=25206
|
||||
|
||||
To view the complete set of reference manual entries for Tcl 9.0 online,
|
||||
To view the complete set of reference manual entries for Tcl 8.7 online,
|
||||
visit the URL:
|
||||
http://www.tcl.tk/man/tcl9.0/
|
||||
http://www.tcl.tk/man/tcl8.7/
|
||||
|
||||
2a. Unix Documentation
|
||||
----------------------
|
||||
|
||||
@@ -8624,263 +8624,3 @@ improvements to regexp engine from Postgres (lane,porter,fellows,seltenreich)
|
||||
2016-02-22 (bug)[9b4702] [info exists env(missing)] kills trace (nijtmans)
|
||||
|
||||
--- Released 8.6.5, February 29, 2016 --- http://core.tcl.tk/tcl/ for details
|
||||
|
||||
2016-03-01 (bug)[803042] mem leak due to reference cycle (porter)
|
||||
|
||||
2016-03-08 (bug)[bbc304] reflected watch race condition (porter)
|
||||
|
||||
2016-03-17 (bug)[fadc99] compile-5.3 (rodriguez,porter)
|
||||
|
||||
2016-03-17 (enhancement)[1a25fd] compile [variable ${ns}::v] (porter)
|
||||
|
||||
2016-03-20 (bug)[1af8de] crash in compiled [string replace] (harder,fellows)
|
||||
|
||||
2016-03-21 (bug)[d30718] segv in notifier finalize (hirofumi,nijtmans)
|
||||
|
||||
2016-03-23 (enhancement)[7d0db7] parallel make (yarda,nijtmans)
|
||||
|
||||
2016-03-23 [f12535] enable test bindings customization (vogel,nijtmans)
|
||||
|
||||
2016-04-04 (bug)[47ac84] compiled [lreplace] fixes (aspect,ferrieux,fellows)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2016-04-08 (bug)[866368] RE \w includes 'Punctuation Connector' (nijtmans)
|
||||
|
||||
2016-04-08 (bug)[2538f3] Win crash Tcl_OpenTcpServer() (griffin)
|
||||
|
||||
2016-04-10 [07d13d] Restore TclBlend support lost in 8.6.1 (buratti)
|
||||
|
||||
2016-05-13 (bug)[3154ea] Mem corruption in assembler exceptions (tkob,kenny)
|
||||
|
||||
2016-05-13 (bug) registry package support any Unicode env (nijtmans)
|
||||
=> registry 1.3.2
|
||||
|
||||
2016-05-21 (bug)[f7d4e] [namespace delete] performance (fellows)
|
||||
|
||||
2016-06-02 (TIP 447) execution time verbosity option (cerutti)
|
||||
=> tcltest 2.4.0
|
||||
|
||||
2016-06-16 (bug)[16828b] crash due to [vwait] trace undo fail (dah,porter)
|
||||
|
||||
2016-06-16 (enhancement)[4b61af] good [info frame] from more cases (beric)
|
||||
|
||||
2016-06-21 (bug)[c383eb] crash in [glob -path a] (oehlmann,porter)
|
||||
|
||||
2016-06-21 (update) Update Unicode data to 9.0 (nijtmans)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2016-06-22 (bug)[16896d] Tcl_DString tolerate append to self. (dah,porter)
|
||||
|
||||
2016-06-23 (bug)[d55322] crash in [dict update] (yorick,fellows)
|
||||
|
||||
2016-06-27 (bug)[dd260a] crash in [chan configure -dictionary] (madden,aspect)
|
||||
|
||||
2016-07-02 (bug)[f961d7] usage message with parameters with spaces (porter)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2016-07-02 (enhancement)[09fabc] Sort order of -relateddir (lanam)
|
||||
|
||||
2016-07-07 (bug)[5d7ca0] Win: [file executable] for .cmd and .ps1 (nadkarni)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2016-07-08 (bug)[a47641] [file normalize] & Windows junctions (nadkarni)
|
||||
|
||||
2016-07-09 [ae61a6] [file] handling of Win hardcoded names (CON) (nadkarni)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2016-07-09 [3613671] [file owned] (more) useful on Win (nadkarni)
|
||||
|
||||
2016-07-09 (bug)[1493a4] [namespace upvar] use of resolvers (beric,fellows)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2016-07-10 (bug)[da340d] integer division in clock math (nadkarni)
|
||||
|
||||
2016-07-20 tzdata updated to Olson's tzdata2016f (venkat)
|
||||
|
||||
--- Released 8.6.6, July 27, 2016 --- http://core.tcl.tk/tcl/ for details
|
||||
|
||||
2016-09-07 (bug)[c09edf] Bad caching with custom resolver (neumann,nijtmans)
|
||||
|
||||
2016-09-07 (bug)[4dbdd9] Memleak in test var-8.3 (mr_calvin,porter)
|
||||
|
||||
2016-10-03 (bug)[2bf561] Allow empty command as alias target (yorick,nijtmans)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2016-10-04 (bug)[4d5ae7] Crash in async connects host no address (gahr,fellows)
|
||||
|
||||
2016-10-08 (bug)[838e99] treat application/xml as text (gahr,fellows)
|
||||
=> http 2.8.10
|
||||
|
||||
2016-10-11 (bug)[3cc1d9] Thread finalization crash in zippy (neumann)
|
||||
|
||||
2016-10-12 (bug)[be003d] Fix [scan 0x1 %b], [scan 0x1 %o] (porter)
|
||||
|
||||
2016-10-14 (bug)[eb6b68] Fix stringComp-14.5 (porter)
|
||||
|
||||
2016-10-30 (bug)[b26e38] Fix zlib-7.8 (fellows)
|
||||
|
||||
2016-10-30 (bug)[1ae129] Fix memleak in [history] destruction (fellows)
|
||||
|
||||
2016-11-04 (feature) Provisional Tcl 9 support in msgcat and tcltest (nijtmans)
|
||||
=> msgcat 1.6.1
|
||||
=> tcltest 2.4.1
|
||||
|
||||
2016-11-04 (bug)[824752] Crash in Tcl_ListObjReplace() (gahr,porter)
|
||||
|
||||
2016-11-11 (bug)[79614f] invalidate VFS mounts on sytem encoding change (yorick)
|
||||
|
||||
2016-11-14 OSX: End panic() as legacy support macro; system conflicts (nijtmans)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2016-11-15 (bug) TclOO fix stops crash mixing Itcl and snit (fellows)
|
||||
|
||||
2016-11-17 (update) Reconcile libtommath updates; purge unused files (nijtmans)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2017-01-09 (bug)[b87ad7] Repair drifts in timer clock (sebres)
|
||||
|
||||
2017-01-17 (update) => zlib 1.2.11 (nijtmans)
|
||||
|
||||
2017-01-31 (bug)[39f630] Revise Tcl_LinkVar to tolerate some prefixes (nijtmans)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2017-02-01 (bug)[d0f7ba] Improper NAN optimization. expr-22.1[01] (aspect)
|
||||
|
||||
2017-02-26 (bug)[25842c] zlib stream finalization (aspect)
|
||||
|
||||
2017-03-07 (deprecate) Remove unmaintained makefile.bc file (nijtmans)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2017-03-14 (enhancement) [clock] and [encoding] are now ensembles (kenny)
|
||||
|
||||
2017-03-15 (enhancement) several [clock] subcommands bytecoded (kenny)
|
||||
|
||||
2017-03-23 tzdata updated to Olson's tzdata2017b (jima)
|
||||
|
||||
2017-03-29 (bug)[900cb0] Fix OO unexport introspection (napier)
|
||||
|
||||
2017-04-12 (bug)[42202b] Nesting imbalance in coro injection (nadkarni,sebres)
|
||||
|
||||
2017-04-18 (bug)[bc4322] http package support for safe interps (nash,nijtmans)
|
||||
|
||||
2017-04-28 (bug)[f34cf8] [file join a //b] => /b (neumann,porter)
|
||||
|
||||
2017-05-01 (bug)[8bd13f] Windows threads and pipes (sebres,nijtmans)
|
||||
|
||||
2017-05-01 (bug)[f9fe90] [file join //a b] EIAS violation (aspect,porter)
|
||||
|
||||
2017-05-04 (bug) Make test filesystem-1.52 pass on Windows (nijtmans)
|
||||
|
||||
2017-05-05 (bug)[601522] [binary] field spec overflow -> segfault (porter)
|
||||
|
||||
2017-05-08 (bug)[6ca52a] http memleak handling keep-alive (aspect,nijtmans)
|
||||
=> http 2.8.11
|
||||
|
||||
2017-05-29 (bug)[a3fb33] crash in [lsort] on long lists (sebres)
|
||||
|
||||
2017-06-05 (bug)[67aa9a] Tcl_UtfToUniChar() revised handling invalid UTF-8 (nijtmans)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2017-06-08 (bug)[2738427] Tcl_NumUtfChars() corner case utf-4.9 (nijtmans)
|
||||
|
||||
2017-06-22 (update) Update Unicode data to 10.0 (nijtmans)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2017-06-22 (TIP 473) Let [oo::copy] specify target namespace (fellows)
|
||||
|
||||
2017-06-26 (bug)[46f801] Repair autoloader fragility (porter)
|
||||
|
||||
2017-07-06 (bug)[adb198] Plug memleak in TclJoinPath (sebres,porter)
|
||||
|
||||
2017-07-17 (bug)[fb2208] Repeatable tclIndex generation (wiedemann,nijtmans)
|
||||
|
||||
--- Released 8.6.7, August 9, 2017 --- http://core.tcl.tk/tcl/ for details
|
||||
|
||||
2017-08-10 [array names -regexp] supports backrefs (goth)
|
||||
|
||||
2017-08-10 Fix gcc build failures due to #pragma placement (cassoff,fellows)
|
||||
|
||||
2017-08-29 (bug)[b50fb2] exec redir append stdout and stderr to file (coulter)
|
||||
|
||||
2017-08-31 (bug)[2a9465] http state 100 continue handling broken (oehlmann)
|
||||
=> http 2.8.12
|
||||
|
||||
2017-09-02 (bug)[0e4d88] replace command, delete trace kills namespace (porter)
|
||||
|
||||
2017-10-19 (bug)[1a5655] [info * methods] includes mixins (fellows)
|
||||
|
||||
2017-10-23 tzdata updated to Olson's tzdata2017c (jima)
|
||||
|
||||
2017-10-24 (bug)[fc1409] segfault in method cloning, oo-15.15 (coulter,fellows)
|
||||
|
||||
2017-11-03 (bug)[6f2f83] More robust [load] for ReactOS (werner)
|
||||
|
||||
2017-11-08 (bug)[3298012] Stop crash when hash tables overflow 32 bits (porter)
|
||||
|
||||
2017-11-14 (bug)[5d6de6] Close failing case of [package prefer stable] (kupries)
|
||||
|
||||
2017-11-17 (bug)[fab924] Fix misleading [load] message on Windows (oehlmann)
|
||||
|
||||
2017-12-05 (bug)[4f6a1e] Crash when ensemble map and list are same (sebres)
|
||||
|
||||
2017-12-06 (bug)[ce3a21] file normalize failure when tail is empty (porter)
|
||||
|
||||
2017-12-08 (new)[TIP 477] nmake build system reform (nadkarni)
|
||||
|
||||
2017-12-19 (bug)[586e71] EvalObjv exception handling at level #0 (sebres,porter)
|
||||
|
||||
--- Released 8.6.8, December 22, 2017 --- http://core.tcl.tk/tcl/ for details
|
||||
|
||||
Changes to 8.7a1 include all changes to the 8.6 line through 8.6.7,
|
||||
plus the following, which focuses on the high-level feature changes
|
||||
in this changeset (new minor version) rather than bug fixes:
|
||||
|
||||
2016-03-17 (bug)[0b8c38] socket accept callbacks always in global ns (porter)
|
||||
*** POTENTIAL INCOMPATIBILITY ***
|
||||
|
||||
2016-07-01 Hack accommodations for legacy Itcl 3 disabled (porter)
|
||||
|
||||
2016-07-12 Make TCL_HASH_TYPE build-time configurable (nijtmans)
|
||||
|
||||
2016-07-19 (bug)[0363f0] Partial array search ID reform (porter)
|
||||
|
||||
2016-07-19 (feature removed) Tcl_ObjType "array search" unregistered (porter)
|
||||
*** POTENTIAL INCOMPATIBILITY for Tcl_GetObjType("array search") ***
|
||||
|
||||
2016-10-04 Server socket on port 0 chooses port supporting IPv4 * IPv6 (max)
|
||||
|
||||
2016-11-25 [array named -regexp] supports backrefs (goth)
|
||||
|
||||
2017-01-04 (TIP 456) New routine Tcl_OpenTcpServerEx() (limeboy)
|
||||
|
||||
2017-01-04 (TIP 459) New subcommand [package files] (nijtmans)
|
||||
|
||||
2017-01-16 threaded allocator initialization repair (vasiljevic,nijtmans)
|
||||
|
||||
2017-01-30 Add to Win shell builtins: assoc ftype move (ashok)
|
||||
|
||||
2017-03-31 TCL_MEM_DEBUG facilities better support 64-bit memory (nijtmans)
|
||||
|
||||
2017-04-13 \u escaped content in msg files converted to true utf-8 (nijtmans)
|
||||
|
||||
2017-05-18 (TIP 458) New epoll or kqueue notifiers are default (alborboz)
|
||||
|
||||
2017-05-31 Purge build support for SunOS-4.* (stu)
|
||||
|
||||
2017-06-22 (TIP 463) New option [regsub ... -command ...] (fellows)
|
||||
|
||||
2017-06-22 (TIP 470) Tcl_GetDefineContextObject();[oo::define [self]] (fellows)
|
||||
=> TclOO 1.2.0
|
||||
|
||||
2017-06-23 (TIP 472) Support 0d as prefix of decimal numbers (iyer,griffin)
|
||||
|
||||
2017-08-31 (bug)[2a9465] http state 100 continue handling broken (oehlmann)
|
||||
|
||||
2017-09-02 (bug)[0e4d88] replace command, delete trace kills namespace (porter)
|
||||
|
||||
--- Released 8.7a1, September 8, 2017 --- http://core.tcl.tk/tcl/ for details
|
||||
|
||||
2018-03-12 (TIP 490) add oo support for msgcat => msgcat 1.7.0 (oehlmann)
|
||||
|
||||
2018-03-12 (TIP 499) custom locale preference list (oehlmann)
|
||||
=> msgcat 1.7.0
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* float.h --
|
||||
*
|
||||
* This is a dummy header file to #include in Tcl when there
|
||||
* is no float.h in /usr/include. Right now this file is empty:
|
||||
* Tcl contains #ifdefs to deal with the lack of definitions;
|
||||
* all it needs is for the #include statement to work.
|
||||
*
|
||||
* Copyright (c) 1993 The Regents of the University of California.
|
||||
* Copyright (c) 1994 Sun Microsystems, Inc.
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution
|
||||
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
*/
|
||||
Executable → Regular
Executable → Regular
Executable → Regular
+6
-1
@@ -9,7 +9,7 @@
|
||||
.so man.macros
|
||||
.BS
|
||||
.SH NAME
|
||||
Tcl_GetReturnOptions, Tcl_SetReturnOptions, Tcl_AddErrorInfo, Tcl_AppendObjToErrorInfo, Tcl_AddObjErrorInfo, Tcl_SetObjErrorCode, Tcl_SetErrorCode, Tcl_SetErrorLine, Tcl_GetErrorLine, Tcl_PosixError, Tcl_LogCommandInfo \- retrieve or record information about errors and other return options
|
||||
Tcl_GetReturnOptions, Tcl_SetReturnOptions, Tcl_AddErrorInfo, Tcl_AppendObjToErrorInfo, Tcl_AddObjErrorInfo, Tcl_SetObjErrorCode, Tcl_SetErrorCode, Tcl_SetErrorCodeVA, Tcl_SetErrorLine, Tcl_GetErrorLine, Tcl_PosixError, Tcl_LogCommandInfo \- retrieve or record information about errors and other return options
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
\fB#include <tcl.h>\fR
|
||||
@@ -30,6 +30,8 @@ int
|
||||
.sp
|
||||
\fBTcl_SetErrorCode\fR(\fIinterp, element, element, ... \fB(char *) NULL\fR)
|
||||
.sp
|
||||
\fBTcl_SetErrorCodeVA\fR(\fIinterp, argList\fR)
|
||||
.sp
|
||||
\fBTcl_GetErrorLine\fR(\fIinterp\fR)
|
||||
.sp
|
||||
\fBTcl_SetErrorLine\fR(\fIinterp, lineNum\fR)
|
||||
@@ -243,6 +245,9 @@ The procedure \fBTcl_SetErrorCode\fR is also used to set the
|
||||
record instead of a value. Otherwise, it is similar to
|
||||
\fBTcl_SetObjErrorCode\fR in behavior.
|
||||
.PP
|
||||
\fBTcl_SetErrorCodeVA\fR is the same as \fBTcl_SetErrorCode\fR except that
|
||||
instead of taking a variable number of arguments it takes an argument list.
|
||||
.PP
|
||||
The procedure \fBTcl_GetErrorLine\fR is used to read the integer value
|
||||
of the \fB\-errorline\fR return option without the overhead of a full
|
||||
call to \fBTcl_GetReturnOptions\fR. Likewise, \fBTcl_SetErrorLine\fR
|
||||
|
||||
+2
-1
@@ -30,7 +30,8 @@ or \fBTCL_RETURN\fR, then Tcl normally converts this into a \fBTCL_ERROR\fR
|
||||
return with an appropriate message. The particular script
|
||||
evaluation procedures of Tcl that act in the manner are
|
||||
\fBTcl_EvalObjEx\fR, \fBTcl_EvalObjv\fR, \fBTcl_Eval\fR, \fBTcl_EvalEx\fR,
|
||||
\fBTcl_GlobalEval\fR, \fBTcl_GlobalEvalObj\fR and \fBTcl_VarEval\fR.
|
||||
\fBTcl_GlobalEval\fR, \fBTcl_GlobalEvalObj\fR, \fBTcl_VarEval\fR and
|
||||
\fBTcl_VarEvalVA\fR.
|
||||
.PP
|
||||
However, if \fBTcl_AllowExceptions\fR is invoked immediately before
|
||||
calling one of those a procedures, then arbitrary completion
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
'\"
|
||||
'\" Copyright (c) 1989-1993 The Regents of the University of California.
|
||||
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
|
||||
'\"
|
||||
'\" See the file "license.terms" for information on usage and redistribution
|
||||
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
'\"
|
||||
.TH Tcl_Backslash 3 "8.1" Tcl "Tcl Library Procedures"
|
||||
.so man.macros
|
||||
.BS
|
||||
.SH NAME
|
||||
Tcl_Backslash \- parse a backslash sequence
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
\fB#include <tcl.h>\fR
|
||||
.sp
|
||||
char
|
||||
\fBTcl_Backslash\fR(\fIsrc, countPtr\fR)
|
||||
.SH ARGUMENTS
|
||||
.AS char *countPtr out
|
||||
.AP char *src in
|
||||
Pointer to a string starting with a backslash.
|
||||
.AP int *countPtr out
|
||||
If \fIcountPtr\fR is not NULL, \fI*countPtr\fR gets filled
|
||||
in with number of characters in the backslash sequence, including
|
||||
the backslash character.
|
||||
.BE
|
||||
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
The use of \fBTcl_Backslash\fR is deprecated in favor of
|
||||
\fBTcl_UtfBackslash\fR.
|
||||
.PP
|
||||
This is a utility procedure provided for backwards compatibility with
|
||||
non-internationalized Tcl extensions. It parses a backslash sequence and
|
||||
returns the low byte of the Unicode character corresponding to the sequence.
|
||||
\fBTcl_Backslash\fR modifies \fI*countPtr\fR to contain the number of
|
||||
characters in the backslash sequence.
|
||||
.PP
|
||||
See the Tcl manual entry for information on the valid backslash sequences.
|
||||
All of the sequences described in the Tcl manual entry are supported by
|
||||
\fBTcl_Backslash\fR.
|
||||
.SH "SEE ALSO"
|
||||
Tcl(n), Tcl_UtfBackslash(3)
|
||||
|
||||
.SH KEYWORDS
|
||||
backslash, parse
|
||||
@@ -0,0 +1,162 @@
|
||||
'\"
|
||||
'\" Copyright (c) 1989-1993 The Regents of the University of California.
|
||||
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
|
||||
'\"
|
||||
'\" See the file "license.terms" for information on usage and redistribution
|
||||
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
'\"
|
||||
.TH Tcl_CreateMathFunc 3 8.4 Tcl "Tcl Library Procedures"
|
||||
.so man.macros
|
||||
.BS
|
||||
.SH NAME
|
||||
Tcl_CreateMathFunc, Tcl_GetMathFuncInfo, Tcl_ListMathFuncs \- Define, query and enumerate math functions for expressions
|
||||
.SH "NOTICE OF EVENTUAL DEPRECATION"
|
||||
.PP
|
||||
The \fBTcl_CreateMathFunc\fR and \fBTcl_GetMathFuncInfo\fR functions
|
||||
are rendered somewhat obsolete by the ability to create functions for
|
||||
expressions by placing commands in the \fBtcl::mathfunc\fR namespace,
|
||||
as described in the \fBmathfunc\fR manual page; the API described on
|
||||
this page is not expected to be maintained indefinitely.
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
\fB#include <tcl.h>\fR
|
||||
.sp
|
||||
void
|
||||
\fBTcl_CreateMathFunc\fR(\fIinterp, name, numArgs, argTypes, proc, clientData\fR)
|
||||
.sp
|
||||
int
|
||||
\fBTcl_GetMathFuncInfo\fR(\fIinterp, name, numArgsPtr, argTypesPtr, procPtr,
|
||||
clientDataPtr\fR)
|
||||
.sp
|
||||
Tcl_Obj *
|
||||
\fBTcl_ListMathFuncs\fR(\fIinterp, pattern\fR)
|
||||
.SH ARGUMENTS
|
||||
.AS Tcl_ValueType *clientDataPtr out
|
||||
.AP Tcl_Interp *interp in
|
||||
Interpreter in which new function will be defined.
|
||||
.AP "const char" *name in
|
||||
Name for new function.
|
||||
.AP int numArgs in
|
||||
Number of arguments to new function; also gives size of \fIargTypes\fR array.
|
||||
.AP Tcl_ValueType *argTypes in
|
||||
Points to an array giving the permissible types for each argument to
|
||||
function.
|
||||
.AP Tcl_MathProc *proc in
|
||||
Procedure that implements the function.
|
||||
.AP ClientData clientData in
|
||||
Arbitrary one-word value to pass to \fIproc\fR when it is invoked.
|
||||
.AP int *numArgsPtr out
|
||||
Points to a variable that will be set to contain the number of
|
||||
arguments to the function.
|
||||
.AP Tcl_ValueType **argTypesPtr out
|
||||
Points to a variable that will be set to contain a pointer to an array
|
||||
giving the permissible types for each argument to the function which
|
||||
will need to be freed up using \fITcl_Free\fR.
|
||||
.AP Tcl_MathProc **procPtr out
|
||||
Points to a variable that will be set to contain a pointer to the
|
||||
implementation code for the function (or NULL if the function is
|
||||
implemented directly in bytecode).
|
||||
.AP ClientData *clientDataPtr out
|
||||
Points to a variable that will be set to contain the clientData
|
||||
argument passed to \fITcl_CreateMathFunc\fR when the function was
|
||||
created if the function is not implemented directly in bytecode.
|
||||
.AP "const char" *pattern in
|
||||
Pattern to match against function names so as to filter them (by
|
||||
passing to \fITcl_StringMatch\fR), or NULL to not apply any filter.
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
Tcl allows a number of mathematical functions to be used in
|
||||
expressions, such as \fBsin\fR, \fBcos\fR, and \fBhypot\fR.
|
||||
These functions are represented by commands in the namespace,
|
||||
\fBtcl::mathfunc\fR. The \fBTcl_CreateMathFunc\fR function is
|
||||
an obsolete way for applications to add additional functions
|
||||
to those already provided by Tcl or to replace existing functions.
|
||||
It should not be used by new applications, which should create
|
||||
math functions using \fBTcl_CreateObjCommand\fR to create a command
|
||||
in the \fBtcl::mathfunc\fR namespace.
|
||||
.PP
|
||||
In the \fBTcl_CreateMathFunc\fR interface,
|
||||
\fIName\fR is the name of the function as it will appear in expressions.
|
||||
If \fIname\fR does not already exist in the \fB::tcl::mathfunc\fR
|
||||
namespace, then a new command is created in that namespace.
|
||||
If \fIname\fR does exist, then the existing function is replaced.
|
||||
\fINumArgs\fR and \fIargTypes\fR describe the arguments to the function.
|
||||
Each entry in the \fIargTypes\fR array must be
|
||||
one of \fBTCL_INT\fR, \fBTCL_DOUBLE\fR, \fBTCL_WIDE_INT\fR,
|
||||
or \fBTCL_EITHER\fR to indicate whether the corresponding argument must be an
|
||||
integer, a double-precision floating value, a wide (64-bit) integer,
|
||||
or any, respectively.
|
||||
.PP
|
||||
Whenever the function is invoked in an expression Tcl will invoke
|
||||
\fIproc\fR. \fIProc\fR should have arguments and result that match
|
||||
the type \fBTcl_MathProc\fR:
|
||||
.PP
|
||||
.CS
|
||||
typedef int \fBTcl_MathProc\fR(
|
||||
ClientData \fIclientData\fR,
|
||||
Tcl_Interp *\fIinterp\fR,
|
||||
Tcl_Value *\fIargs\fR,
|
||||
Tcl_Value *\fIresultPtr\fR);
|
||||
.CE
|
||||
.PP
|
||||
When \fIproc\fR is invoked the \fIclientData\fR and \fIinterp\fR
|
||||
arguments will be the same as those passed to \fBTcl_CreateMathFunc\fR.
|
||||
\fIArgs\fR will point to an array of \fInumArgs\fR Tcl_Value structures,
|
||||
which describe the actual arguments to the function:
|
||||
.PP
|
||||
.CS
|
||||
typedef struct Tcl_Value {
|
||||
Tcl_ValueType \fItype\fR;
|
||||
long \fIintValue\fR;
|
||||
double \fIdoubleValue\fR;
|
||||
Tcl_WideInt \fIwideValue\fR;
|
||||
} \fBTcl_Value\fR;
|
||||
.CE
|
||||
.PP
|
||||
The \fItype\fR field indicates the type of the argument and is
|
||||
one of \fBTCL_INT\fR, \fBTCL_DOUBLE\fR or \fBTCL_WIDE_INT\fR.
|
||||
It will match the \fIargTypes\fR value specified for the function unless
|
||||
the \fIargTypes\fR value was \fBTCL_EITHER\fR. Tcl converts
|
||||
the argument supplied in the expression to the type requested in
|
||||
\fIargTypes\fR, if that is necessary.
|
||||
Depending on the value of the \fItype\fR field, the \fIintValue\fR,
|
||||
\fIdoubleValue\fR or \fIwideValue\fR
|
||||
field will contain the actual value of the argument.
|
||||
.PP
|
||||
\fIProc\fR should compute its result and store it either as an integer
|
||||
in \fIresultPtr->intValue\fR or as a floating value in
|
||||
\fIresultPtr->doubleValue\fR.
|
||||
It should set also \fIresultPtr->type\fR to one of
|
||||
\fBTCL_INT\fR, \fBTCL_DOUBLE\fR or \fBTCL_WIDE_INT\fR
|
||||
to indicate which value was set.
|
||||
Under normal circumstances \fIproc\fR should return \fBTCL_OK\fR.
|
||||
If an error occurs while executing the function, \fIproc\fR should
|
||||
return \fBTCL_ERROR\fR and leave an error message in the interpreter's result.
|
||||
.PP
|
||||
\fBTcl_GetMathFuncInfo\fR retrieves the values associated with
|
||||
function \fIname\fR that were passed to a preceding
|
||||
\fBTcl_CreateMathFunc\fR call. Normally, the return code is
|
||||
\fBTCL_OK\fR but if the named function does not exist, \fBTCL_ERROR\fR
|
||||
is returned and an error message is placed in the interpreter's
|
||||
result.
|
||||
.PP
|
||||
If an error did not occur, the array reference placed in the variable
|
||||
pointed to by \fIargTypesPtr\fR is newly allocated, and should be
|
||||
released by passing it to \fBTcl_Free\fR. Some functions (the
|
||||
standard set implemented in the core, and those defined by placing
|
||||
commands in the \fBtcl::mathfunc\fR namespace) do not have
|
||||
argument type information; attempting to retrieve values for
|
||||
them causes a NULL to be stored in the variable pointed to by
|
||||
\fIprocPtr\fR and the variable pointed to by \fIclientDataPtr\fR
|
||||
will not be modified. The variable pointed to by \fInumArgsPointer\fR
|
||||
will contain -1, and no argument types will be stored in the variable
|
||||
pointed to by \fIargTypesPointer\fR.
|
||||
.PP
|
||||
\fBTcl_ListMathFuncs\fR returns a Tcl value containing a list of all
|
||||
the math functions defined in the interpreter whose name matches
|
||||
\fIpattern\fR. The returned value has a reference count of zero.
|
||||
.SH "SEE ALSO"
|
||||
expr(n), info(n), Tcl_CreateObjCommand(3), Tcl_Free(3), Tcl_NewListObj(3)
|
||||
.SH KEYWORDS
|
||||
expression, mathematical function
|
||||
+7
-1
@@ -9,7 +9,7 @@
|
||||
.so man.macros
|
||||
.BS
|
||||
.SH NAME
|
||||
Tcl_DStringInit, Tcl_DStringAppend, Tcl_DStringAppendElement, Tcl_DStringStartSublist, Tcl_DStringEndSublist, Tcl_DStringLength, Tcl_DStringValue, Tcl_DStringSetLength, Tcl_DStringFree, Tcl_DStringResult, Tcl_DStringGetResult \- manipulate dynamic strings
|
||||
Tcl_DStringInit, Tcl_DStringAppend, Tcl_DStringAppendElement, Tcl_DStringStartSublist, Tcl_DStringEndSublist, Tcl_DStringLength, Tcl_DStringValue, Tcl_DStringSetLength, Tcl_DStringTrunc, Tcl_DStringFree, Tcl_DStringResult, Tcl_DStringGetResult \- manipulate dynamic strings
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
\fB#include <tcl.h>\fR
|
||||
@@ -34,6 +34,8 @@ char *
|
||||
.sp
|
||||
\fBTcl_DStringSetLength\fR(\fIdsPtr, newLength\fR)
|
||||
.sp
|
||||
\fBTcl_DStringTrunc\fR(\fIdsPtr, newLength\fR)
|
||||
.sp
|
||||
\fBTcl_DStringFree\fR(\fIdsPtr\fR)
|
||||
.sp
|
||||
\fBTcl_DStringResult\fR(\fIinterp, dsPtr\fR)
|
||||
@@ -126,6 +128,10 @@ caller to fill in the new space.
|
||||
even if the string is truncated to zero length, so \fBTcl_DStringFree\fR
|
||||
will still need to be called.
|
||||
.PP
|
||||
\fBTcl_DStringTrunc\fR changes the length of a dynamic string.
|
||||
This procedure is now deprecated. \fBTcl_DStringSetLength\fR should
|
||||
be used instead.
|
||||
.PP
|
||||
\fBTcl_DStringFree\fR should be called when you are finished using
|
||||
the string. It frees up any memory that was allocated for the string
|
||||
and reinitializes the string's value to an empty string.
|
||||
|
||||
+21
-2
@@ -8,7 +8,7 @@
|
||||
.so man.macros
|
||||
.BS
|
||||
.SH NAME
|
||||
Tcl_GetEncoding, Tcl_FreeEncoding, Tcl_GetEncodingFromObj, Tcl_ExternalToUtfDString, Tcl_ExternalToUtf, Tcl_UtfToExternalDString, Tcl_UtfToExternal, Tcl_WinTCharToUtf, Tcl_WinUtfToTChar, Tcl_GetEncodingName, Tcl_SetSystemEncoding, Tcl_GetEncodingNameFromEnvironment, Tcl_GetEncodingNames, Tcl_CreateEncoding, Tcl_GetEncodingSearchPath, Tcl_SetEncodingSearchPath \- procedures for creating and using encodings
|
||||
Tcl_GetEncoding, Tcl_FreeEncoding, Tcl_GetEncodingFromObj, Tcl_ExternalToUtfDString, Tcl_ExternalToUtf, Tcl_UtfToExternalDString, Tcl_UtfToExternal, Tcl_WinTCharToUtf, Tcl_WinUtfToTChar, Tcl_GetEncodingName, Tcl_SetSystemEncoding, Tcl_GetEncodingNameFromEnvironment, Tcl_GetEncodingNames, Tcl_CreateEncoding, Tcl_GetEncodingSearchPath, Tcl_SetEncodingSearchPath, Tcl_GetDefaultEncodingDir, Tcl_SetDefaultEncodingDir \- procedures for creating and using encodings
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
\fB#include <tcl.h>\fR
|
||||
@@ -62,6 +62,12 @@ Tcl_Obj *
|
||||
.sp
|
||||
int
|
||||
\fBTcl_SetEncodingSearchPath\fR(\fIsearchPath\fR)
|
||||
.sp
|
||||
const char *
|
||||
\fBTcl_GetDefaultEncodingDir\fR(\fIvoid\fR)
|
||||
.sp
|
||||
void
|
||||
\fBTcl_SetDefaultEncodingDir\fR(\fIpath\fR)
|
||||
.SH ARGUMENTS
|
||||
.AS "const Tcl_EncodingType" *dstWrotePtr in/out
|
||||
.AP Tcl_Interp *interp in
|
||||
@@ -254,6 +260,10 @@ Windows-only convenience
|
||||
functions for converting between UTF-8 and Windows strings
|
||||
based on the TCHAR type which is by convention
|
||||
a Unicode character on Windows NT.
|
||||
These functions are essentially wrappers around
|
||||
\fBTcl_UtfToExternalDString\fR and
|
||||
\fBTcl_ExternalToUtfDString\fR that convert to and from the
|
||||
Unicode encoding.
|
||||
.PP
|
||||
\fBTcl_GetEncodingName\fR is roughly the inverse of \fBTcl_GetEncoding\fR.
|
||||
Given an \fIencoding\fR, the return value is the \fIname\fR argument that
|
||||
@@ -281,7 +291,7 @@ the encoding name to it. The \fBTcl_DStringValue\fR is returned.
|
||||
\fBTcl_GetEncodingNames\fR sets the \fIinterp\fR result to a list
|
||||
consisting of the names of all the encodings that are currently defined
|
||||
or can be dynamically loaded, searching the encoding path specified by
|
||||
\fBTcl_SetEncodingSearchPath\fR. This procedure does not ensure that the
|
||||
\fBTcl_SetDefaultEncodingDir\fR. This procedure does not ensure that the
|
||||
dynamically-loadable encoding files contain valid data, but merely that they
|
||||
exist.
|
||||
.PP
|
||||
@@ -396,6 +406,15 @@ are not verified as existing readable filesystem directories. When
|
||||
searching for encoding data files takes place, and non-existent or
|
||||
non-readable filesystem directories on the \fIsearchPath\fR are silently
|
||||
ignored.
|
||||
.PP
|
||||
\fBTcl_GetDefaultEncodingDir\fR and \fBTcl_SetDefaultEncodingDir\fR
|
||||
are obsolete interfaces best replaced with calls to
|
||||
\fBTcl_GetEncodingSearchPath\fR and \fBTcl_SetEncodingSearchPath\fR.
|
||||
They are called to access and set the first element of the \fIsearchPath\fR
|
||||
list. Since Tcl searches \fIsearchPath\fR for encoding data files in
|
||||
list order, these routines establish the
|
||||
.QW default
|
||||
directory in which to find encoding data files.
|
||||
.SH "ENCODING FILES"
|
||||
Space would prohibit precompiling into Tcl every possible encoding
|
||||
algorithm, so many encodings are stored on disk as dynamically-loadable
|
||||
|
||||
+23
-7
@@ -10,7 +10,7 @@
|
||||
.so man.macros
|
||||
.BS
|
||||
.SH NAME
|
||||
Tcl_EvalObjEx, Tcl_EvalFile, Tcl_EvalObjv, Tcl_Eval, Tcl_EvalEx, Tcl_GlobalEval, Tcl_GlobalEvalObj, Tcl_VarEval \- execute Tcl scripts
|
||||
Tcl_EvalObjEx, Tcl_EvalFile, Tcl_EvalObjv, Tcl_Eval, Tcl_EvalEx, Tcl_GlobalEval, Tcl_GlobalEvalObj, Tcl_VarEval, Tcl_VarEvalVA \- execute Tcl scripts
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
\fB#include <tcl.h>\fR
|
||||
@@ -38,6 +38,9 @@ int
|
||||
.sp
|
||||
int
|
||||
\fBTcl_VarEval\fR(\fIinterp, part, part, ... \fB(char *) NULL\fR)
|
||||
.sp
|
||||
int
|
||||
\fBTcl_VarEvalVA\fR(\fIinterp, argList\fR)
|
||||
.SH ARGUMENTS
|
||||
.AS Tcl_Interp **termPtr
|
||||
.AP Tcl_Interp *interp in
|
||||
@@ -64,6 +67,9 @@ first null byte are used.
|
||||
Points to first byte of script to execute (null-terminated and UTF-8).
|
||||
.AP char *part in
|
||||
String forming part of a Tcl script.
|
||||
.AP va_list argList in
|
||||
An argument list which must have been initialized using
|
||||
\fBva_start\fR, and cleared using \fBva_end\fR.
|
||||
.BE
|
||||
|
||||
.SH DESCRIPTION
|
||||
@@ -122,10 +128,16 @@ might be a UTF-8 special code. The string is parsed and executed directly
|
||||
bytecodes. In situations where it is known that the script will never be
|
||||
executed again, \fBTcl_Eval\fR may be faster than \fBTcl_EvalObjEx\fR.
|
||||
\fBTcl_Eval\fR returns a completion code and result just like
|
||||
\fBTcl_EvalObjEx\fR.
|
||||
\fBTcl_EvalObjEx\fR. Note: for backward compatibility with versions before
|
||||
Tcl 8.0, \fBTcl_Eval\fR copies the value result in \fIinterp\fR to
|
||||
\fIinterp->result\fR (use is deprecated) where it can be accessed directly.
|
||||
This makes \fBTcl_Eval\fR somewhat slower than \fBTcl_EvalEx\fR, which
|
||||
does not do the copy.
|
||||
.PP
|
||||
\fBTcl_EvalEx\fR is an extended version of \fBTcl_Eval\fR that takes
|
||||
additional arguments \fInumBytes\fR and \fIflags\fR.
|
||||
additional arguments \fInumBytes\fR and \fIflags\fR. For the
|
||||
efficiency reason given above, \fBTcl_EvalEx\fR is generally preferred
|
||||
over \fBTcl_Eval\fR.
|
||||
.PP
|
||||
\fBTcl_GlobalEval\fR and \fBTcl_GlobalEvalObj\fR are older procedures
|
||||
that are now deprecated. They are similar to \fBTcl_EvalEx\fR and
|
||||
@@ -141,6 +153,10 @@ It returns the result of the command and also modifies
|
||||
\fIinterp->result\fR in the same way as \fBTcl_Eval\fR.
|
||||
The last argument to \fBTcl_VarEval\fR must be NULL to indicate the end
|
||||
of arguments. \fBTcl_VarEval\fR is now deprecated.
|
||||
.PP
|
||||
\fBTcl_VarEvalVA\fR is the same as \fBTcl_VarEval\fR except that
|
||||
instead of taking a variable number of arguments it takes an argument
|
||||
list. Like \fBTcl_VarEval\fR, \fBTcl_VarEvalVA\fR is deprecated.
|
||||
|
||||
.SH "FLAG BITS"
|
||||
.PP
|
||||
@@ -160,10 +176,10 @@ it is faster to execute the script directly.
|
||||
.TP 23
|
||||
\fBTCL_EVAL_GLOBAL\fR
|
||||
.
|
||||
If this flag is set, the script is evaluated in the global namespace instead of
|
||||
the current namespace and its variable context consists of global variables
|
||||
only (it ignores any Tcl procedures that are active).
|
||||
.\" TODO: document TCL_EVAL_INVOKE and TCL_EVAL_NOERR.
|
||||
If this flag is set, the script is processed at global level. This
|
||||
means that it is evaluated in the global namespace and its variable
|
||||
context consists of global variables only (it ignores any Tcl
|
||||
procedures that are active).
|
||||
|
||||
.SH "MISCELLANEOUS DETAILS"
|
||||
.PP
|
||||
|
||||
Regular → Executable
+4
-4
@@ -57,15 +57,15 @@ after the optional white space and sign are
|
||||
.QW \fB0x\fR
|
||||
then \fIsrc\fR is expected to be in hexadecimal form; otherwise,
|
||||
if the first such characters are
|
||||
.QW \fB0d\fR
|
||||
then \fIsrc\fR is expected to be in decimal form; otherwise,
|
||||
if the first such characters are
|
||||
.QW \fB0o\fR
|
||||
then \fIsrc\fR is expected to be in octal form; otherwise,
|
||||
if the first such characters are
|
||||
.QW \fB0b\fR
|
||||
then \fIsrc\fR is expected to be in binary form; otherwise,
|
||||
if the first such character is
|
||||
.QW \fB0\fR
|
||||
then \fIsrc\fR
|
||||
is expected to be in binary form; otherwise, \fIsrc\fR is
|
||||
is expected to be in octal form; otherwise, \fIsrc\fR is
|
||||
expected to be in decimal form.
|
||||
.PP
|
||||
\fBTcl_GetDouble\fR expects \fIsrc\fR to consist of a floating-point
|
||||
|
||||
Regular → Executable
+3
-3
@@ -63,9 +63,9 @@ 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 9.0 ABI on Unix platforms,
|
||||
the library name is \fIlibtclstub9.0.a\fR; on Windows platforms, the
|
||||
library name is \fItclstub90.lib\fR.
|
||||
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
|
||||
|
||||
+1
-1
@@ -97,7 +97,7 @@ are provided by the C language standard. The \fBTcl_WideInt\fR type is a
|
||||
typedef defined to be whatever signed integral type covers at least the
|
||||
64-bit integer range (-9223372036854775808 to 9223372036854775807). Depending
|
||||
on the platform and the C compiler, the actual type might be
|
||||
\fBlong long int\fR, \fB__int64\fR, or something else.
|
||||
\fBlong int\fR, \fBlong long int\fR, \fB__int64\fR, or something else.
|
||||
The \fBmp_int\fR type is a multiple-precision integer type defined
|
||||
by the LibTomMath multiple-precision integer library.
|
||||
.PP
|
||||
|
||||
+14
-1
@@ -33,6 +33,19 @@ the pointer as described below is no longer supported. The supported
|
||||
public routines \fBTcl_SetResult\fR, \fBTcl_GetResult\fR,
|
||||
\fBTcl_SetErrorLine\fR, \fBTcl_GetErrorLine\fR must be used instead.
|
||||
.PP
|
||||
For legacy programs and extensions no longer being maintained, compiles
|
||||
against the Tcl 8.6 header files are only possible with the compiler
|
||||
directives
|
||||
.CS
|
||||
#define USE_INTERP_RESULT
|
||||
.CE
|
||||
and/or
|
||||
.CS
|
||||
#define USE_INTERP_ERRORLINE
|
||||
.CE
|
||||
depending on which fields of the \fBTcl_Interp\fR struct are accessed.
|
||||
These directives may be embedded in code or supplied via compiler options.
|
||||
.PP
|
||||
The \fIresult\fR and \fIfreeProc\fR fields are used to return
|
||||
results or error messages from commands.
|
||||
This information is returned by command procedures back to \fBTcl_Eval\fR,
|
||||
@@ -88,7 +101,7 @@ the command. The \fIfreeProc\fR field will be initialized to zero,
|
||||
and \fIinterp->result\fR will point to an empty string. Commands that
|
||||
do not return any value can simply leave the fields alone.
|
||||
Furthermore, the empty string pointed to by \fIresult\fR is actually
|
||||
part of an array of approximately 200 characters.
|
||||
part of an array of \fBTCL_RESULT_SIZE\fR characters (approximately 200).
|
||||
If a command wishes to return a short string, it can simply copy
|
||||
it to the area pointed to by \fIinterp->result\fR. Or, it can use
|
||||
the sprintf procedure to generate a short result string at the location
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2008 by Kevin B. Kenny.
|
||||
.\" Copyright (c) 2018 by Nathan Coulter.
|
||||
.\"
|
||||
'\" See the file "license.terms" for information on usage and redistribution
|
||||
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
@@ -39,39 +38,43 @@ void
|
||||
.SH ARGUMENTS
|
||||
.AS Tcl_CmdDeleteProc *interp in
|
||||
.AP Tcl_Interp *interp in
|
||||
The relevant Interpreter.
|
||||
Interpreter in which to create or evaluate a command.
|
||||
.AP char *cmdName in
|
||||
Name of the command to create.
|
||||
Name of a new command to create.
|
||||
.AP Tcl_ObjCmdProc *proc in
|
||||
Called in order to evaluate a command. Is often just a small wrapper that uses
|
||||
\fBTcl_NRCallObjProc\fR to call \fInreProc\fR using a new trampoline. Behaves
|
||||
in the same way as the \fIproc\fR argument to \fBTcl_CreateObjCommand\fR(3)
|
||||
(\fIq.v.\fR).
|
||||
Implementation of a command that will be called whenever \fIcmdName\fR
|
||||
is invoked as a command in the unoptimized way.
|
||||
.AP Tcl_ObjCmdProc *nreProc in
|
||||
Called instead of \fIproc\fR when a trampoline is already in use.
|
||||
Implementation of a command that will be called whenever \fIcmdName\fR
|
||||
is invoked and requested to conserve the C stack.
|
||||
.AP ClientData clientData in
|
||||
Arbitrary one-word value passed to \fIproc\fR, \fInreProc\fR, \fIdeleteProc\fR
|
||||
and \fIobjProc\fR.
|
||||
Arbitrary one-word value that will be passed to \fIproc\fR, \fInreProc\fR,
|
||||
\fIdeleteProc\fR and \fIobjProc\fR.
|
||||
.AP Tcl_CmdDeleteProc *deleteProc in/out
|
||||
Called before \fIcmdName\fR is deleted from the interpreter, allowing for
|
||||
command-specific cleanup. May be NULL.
|
||||
Procedure to call before \fIcmdName\fR is deleted from the interpreter.
|
||||
This procedure allows for command-specific cleanup. If \fIdeleteProc\fR
|
||||
is \fBNULL\fR, then no procedure is called before the command is deleted.
|
||||
.AP int objc in
|
||||
Number of items in \fIobjv\fR.
|
||||
Count of parameters provided to the implementation of a command.
|
||||
.AP Tcl_Obj **objv in
|
||||
Words in the command.
|
||||
Pointer to an array of Tcl values. Each value holds the value of a
|
||||
single word in the command to execute.
|
||||
.AP Tcl_Obj *objPtr in
|
||||
A script or expression to evaluate.
|
||||
Pointer to a Tcl_Obj whose value is a script or expression to execute.
|
||||
.AP int flags in
|
||||
As described for \fITcl_EvalObjv\fR.
|
||||
.PP
|
||||
ORed combination of flag bits that specify additional options.
|
||||
\fBTCL_EVAL_GLOBAL\fR is the only flag that is currently supported.
|
||||
.\" TODO: This is a lie. But kbk didn't grasp TCL_EVAL_INVOKE and
|
||||
.\" TCL_EVAL_NOERR well enough to document them.
|
||||
.AP Tcl_Command cmd in
|
||||
Token to use instead of one derived from the first word of \fIobjv\fR in order
|
||||
to evaluate a command.
|
||||
Token for a command that is to be used instead of the currently
|
||||
executing command.
|
||||
.AP Tcl_Obj *resultPtr out
|
||||
Pointer to an unshared Tcl_Obj where the result of the evaluation is stored if
|
||||
the return code is TCL_OK.
|
||||
Pointer to an unshared Tcl_Obj where the result of expression
|
||||
evaluation is written.
|
||||
.AP Tcl_NRPostProc *postProcPtr in
|
||||
A function to push.
|
||||
Pointer to a function that will be invoked when the command currently
|
||||
executing in the interpreter designated by \fIinterp\fR completes.
|
||||
.AP ClientData data0 in
|
||||
.AP ClientData data1 in
|
||||
.AP ClientData data2 in
|
||||
@@ -81,51 +84,98 @@ to the function designated by \fIpostProcPtr\fR when it is invoked.
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
These functions provide an interface to the function stack that an interpreter
|
||||
iterates through to evaluate commands. The routine behind a command is
|
||||
implemented by an initial function and any additional functions that the
|
||||
routine pushes onto the stack as it progresses. The interpreter itself pushes
|
||||
functions onto the stack to react to the end of a routine and to exercise other
|
||||
forms of control such as switching between in-progress stacks and the
|
||||
evaluation of other scripts at additional levels without adding frames to the C
|
||||
stack. To execute a routine, the initial function for the routine is called
|
||||
and then a small bit of code called a \fItrampoline\fR iteratively takes
|
||||
functions off the stack and calls them, using the value of the last call as the
|
||||
value of the routine.
|
||||
This series of C functions provides an interface whereby commands that
|
||||
are implemented in C can be evaluated, and invoke Tcl commands scripts
|
||||
and scripts, without consuming space on the C stack. The non-recursive
|
||||
evaluation is done by installing a \fItrampoline\fR, a small piece of
|
||||
code that invokes a command or script, and then executes a series of
|
||||
callbacks when the command or script returns.
|
||||
.PP
|
||||
\fBTcl_NRCallObjProc\fR calls \fInreProc\fR using a new trampoline.
|
||||
The \fBTcl_NRCreateCommand\fR function creates a Tcl command in the
|
||||
interpreter designated by \fIinterp\fR that is prepared to handle
|
||||
nonrecursive evaluation with a trampoline. The \fIcmdName\fR argument
|
||||
gives the name of the new command. If \fIcmdName\fR contains any
|
||||
namespace qualifiers, then the new command is added to the specified
|
||||
namespace; otherwise, it is added to the global namespace. \fIproc\fR
|
||||
gives the procedure that will be called when the interpreter wishes to
|
||||
evaluate the command in an unoptimized manner, and \fInreProc\fR is
|
||||
the procedure that will be called when the interpreter wishes to
|
||||
evaluate the command using a trampoline. \fIdeleteProc\fR is a
|
||||
function that will be called before the command is deleted from the
|
||||
interpreter. When any of the three functions is invoked, it is passed
|
||||
the \fIclientData\fR parameter.
|
||||
.PP
|
||||
\fBTcl_NRCreateCommand\fR, an alternative to \fBTcl_CreateObjCommand\fR,
|
||||
resolves \fIcmdName\fR, which may contain namespace qualifiers, relative to the
|
||||
current namespace, creates a command by that name, and returns a token for the
|
||||
command which may be used in subsequent calls to \fBTcl_GetCommandName\fR.
|
||||
Except for a few cases noted below any existing command by the same name is
|
||||
first deleted. If \fIinterp\fR is in the process of being deleted
|
||||
\fBTcl_NRCreateCommand\fR does not create any command, does not delete any
|
||||
command, and returns NULL.
|
||||
\fBTcl_NRCreateCommand\fR deletes any existing command
|
||||
\fIname\fR already associated with the interpreter
|
||||
(however see below for an exception where the existing command
|
||||
is not deleted).
|
||||
It returns a token that may be used to refer
|
||||
to the command in subsequent calls to \fBTcl_GetCommandName\fR.
|
||||
If \fBTcl_NRCreateCommand\fR is called for an interpreter that is in
|
||||
the process of being deleted, then it does not create a new command,
|
||||
does not delete any existing command of the same name, and returns NULL.
|
||||
.PP
|
||||
\fBTcl_NREvalObj\fR pushes a function that is like \fBTcl_EvalObjEx\fR but
|
||||
consumes no space on the C stack.
|
||||
The \fIproc\fR and \fInreProc\fR function are expected to conform to
|
||||
all the rules set forth for the \fIproc\fR argument to
|
||||
\fBTcl_CreateObjCommand\fR(3) (\fIq.v.\fR).
|
||||
.PP
|
||||
\fBTcl_NREvalObjv\fR pushes a function that is like \fBTcl_EvalObjv\fR but
|
||||
consumes no space on the C stack.
|
||||
When a command that is written to cope with evaluation via trampoline
|
||||
is invoked without a trampoline on the stack, it will usually respond
|
||||
to the invocation by creating a trampoline and calling the
|
||||
trampoline-enabled implementation of the same command. This call is done by
|
||||
means of \fBTcl_NRCallObjProc\fR. In the call to
|
||||
\fBTcl_NRCallObjProc\fR, the \fIinterp\fR, \fIclientData\fR,
|
||||
\fIobjc\fR and \fIobjv\fR parameters should be the same ones that were
|
||||
passed to \fIproc\fR. The \fInreProc\fR parameter should designate the
|
||||
trampoline-enabled implementation of the command.
|
||||
.PP
|
||||
\fBTcl_NRCmdSwap\fR is like \fBTcl_NREvalObjv\fR, but uses \fIcmd\fR, a token
|
||||
previously returned by \fBTcl_CreateObjCommand\fR or
|
||||
\fBTcl_GetCommandFromObj\fR, instead of resolving the first word of \fIobjv\fR.
|
||||
. The name of this command must be the same as \fIobjv[0]\fR.
|
||||
\fBTcl_NREvalObj\fR arranges for the script contained in \fIobjPtr\fR
|
||||
to be evaluated in the interpreter designated by \fIinterp\fR after
|
||||
the current command (which must be trampoline-enabled) returns. It is
|
||||
the method by which a command may invoke a script without consuming
|
||||
space on the C stack. Similarly, \fBTcl_NREvalObjv\fR arranges to
|
||||
invoke a single Tcl command whose words have already been separated
|
||||
and substituted. The \fIobjc\fR and \fIobjv\fR parameters give the
|
||||
words of the command to be evaluated when execution reaches the
|
||||
trampoline.
|
||||
.PP
|
||||
\fBTcl_NRExprObj\fR pushes a function that evaluates \fIobjPtr\fR as an
|
||||
expression in the same manner as \fBTcl_ExprObj\fR but without consuming space
|
||||
on the C stack.
|
||||
\fBTcl_NRCmdSwap\fR allows for trampoline evaluation of a command whose
|
||||
resolution is already known. The \fIcmd\fR parameter gives a
|
||||
\fBTcl_Command\fR token (returned from \fBTcl_CreateObjCommand\fR or
|
||||
\fBTcl_GetCommandFromObj\fR) identifying the command to be invoked in
|
||||
the trampoline; this command must match the word in \fIobjv[0]\fR.
|
||||
The remaining arguments are as for \fBTcl_NREvalObjv\fR.
|
||||
.PP
|
||||
All of the functions return \fBTCL_OK\fR if the evaluation of the script,
|
||||
command, or expression has been scheduled successfully. Otherwise (for example
|
||||
if the command name cannot be resolved), they return \fBTCL_ERROR\fR and store
|
||||
a message as the interpreter's result.
|
||||
\fBTcl_NREvalObj\fR, \fBTcl_NREvalObjv\fR and \fBTcl_NRCmdSwap\fR
|
||||
all accept a \fIflags\fR parameter, which is an OR-ed-together set of
|
||||
bits to control evaluation. At the present time, the only supported flag
|
||||
available to callers is \fBTCL_EVAL_GLOBAL\fR.
|
||||
.\" TODO: Again, this is a lie. Do we want to explain TCL_EVAL_INVOKE
|
||||
.\" and TCL_EVAL_NOERR?
|
||||
If the \fBTCL_EVAL_GLOBAL\fR flag is set, the script or command is
|
||||
evaluated in the global namespace. If it is not set, it is evaluated
|
||||
in the current namespace.
|
||||
.PP
|
||||
\fBTcl_NRAddCallback\fR pushes \fIpostProcPtr\fR. The signature for
|
||||
\fBTcl_NRPostProc\fR is:
|
||||
\fBTcl_NRExprObj\fR arranges for the expression contained in \fIobjPtr\fR
|
||||
to be evaluated in the interpreter designated by \fIinterp\fR after
|
||||
the current command (which must be trampoline-enabled) returns. It is
|
||||
the method by which a command may evaluate a Tcl expression without consuming
|
||||
space on the C stack. The argument \fIresultPtr\fR is a pointer to an
|
||||
unshared Tcl_Obj where the result of expression evaluation is to be written.
|
||||
If expression evaluation returns any code other than TCL_OK, the
|
||||
\fIresultPtr\fR value is left untouched.
|
||||
.PP
|
||||
All of the routines return \fBTCL_OK\fR if command or expression invocation
|
||||
has been scheduled successfully. If for any reason the scheduling cannot
|
||||
be completed (for example, if the interpreter is unable to find
|
||||
the requested command), they return \fBTCL_ERROR\fR with an
|
||||
appropriate message left in the interpreter's result.
|
||||
.PP
|
||||
\fBTcl_NRAddCallback\fR arranges to have a C function called when the
|
||||
current trampoline-enabled command in the Tcl interpreter designated
|
||||
by \fIinterp\fR returns. The \fIpostProcPtr\fR argument is a pointer
|
||||
to the callback function, which must have arguments and return value
|
||||
consistent with the \fBTcl_NRPostProc\fR data type:
|
||||
.PP
|
||||
.CS
|
||||
typedef int
|
||||
@@ -135,13 +185,25 @@ typedef int
|
||||
int \fIresult\fR);
|
||||
.CE
|
||||
.PP
|
||||
\fIdata\fR is a pointer to an array containing \fIdata0\fR through \fIdata3\fR.
|
||||
\fIresult\fR is the value returned by the previous function implementing part
|
||||
the routine.
|
||||
When the trampoline invokes the callback function, the \fIdata\fR
|
||||
parameter will point to an array containing the four one-word
|
||||
quantities that were passed to \fBTcl_NRAddCallback\fR in the
|
||||
\fIdata0\fR through \fIdata3\fR parameters. The Tcl interpreter will
|
||||
be designated by the \fIinterp\fR parameter, and the \fIresult\fR
|
||||
parameter will contain the result (\fBTCL_OK\fR, \fBTCL_ERROR\fR,
|
||||
\fBTCL_RETURN\fR, \fBTCL_BREAK\fR or \fBTCL_CONTINUE\fR) that was
|
||||
returned by the command evaluation. The callback function is expected,
|
||||
in turn, either to return a \fIresult\fR to control further evaluation.
|
||||
.PP
|
||||
Multiple \fBTcl_NRAddCallback\fR invocations may request multiple
|
||||
callbacks, which may be to the same or different callback
|
||||
functions. If multiple callbacks are requested, they are executed in
|
||||
last-in, first-out order, that is, the most recently requested
|
||||
callback is executed first.
|
||||
.SH EXAMPLE
|
||||
.PP
|
||||
The following command uses \fBTcl_EvalObjEx\fR, which consumes space on the C
|
||||
stack, to evalute a script:
|
||||
The usual pattern for Tcl commands that invoke other Tcl commands
|
||||
is something like:
|
||||
.PP
|
||||
.CS
|
||||
int
|
||||
@@ -166,17 +228,28 @@ int
|
||||
\fITheCmdOldObjProc\fR, clientData, TheCmdDeleteProc);
|
||||
.CE
|
||||
.PP
|
||||
To avoid consuming space on the C stack, \fITheCmdOldObjProc\fR is renamed to
|
||||
\fITheCmdNRObjProc\fR and the postprocessing step is split into a separate
|
||||
function, \fITheCmdPostProc\fR, which is pushed onto the function stack.
|
||||
\fITcl_EvalObjEx\fR is replaced with \fITcl_NREvalObj\fR, which uses a
|
||||
trampoline instead of consuming space on the C stack. A new version of
|
||||
\fITheCmdOldObjProc\fR is just a a wrapper that uses \fBTcl_NRCallObjProc\fR to
|
||||
call \fITheCmdNRObjProc\fR:
|
||||
To enable a command like this one for trampoline-based evaluation,
|
||||
it must be split into three pieces:
|
||||
.IP \(bu
|
||||
A non-trampoline implementation, \fITheCmdNewObjProc\fR,
|
||||
which will simply create a trampoline
|
||||
and invoke the trampoline-based implementation.
|
||||
.IP \(bu
|
||||
A trampoline-enabled implementation, \fITheCmdNRObjProc\fR. This
|
||||
function will perform the initialization, request that the trampoline
|
||||
call the postprocessing routine after command evaluation, and finally,
|
||||
request that the trampoline call the inner command.
|
||||
.IP \(bu
|
||||
A postprocessing routine, \fITheCmdPostProc\fR. This function will
|
||||
perform the postprocessing formerly done after the return from the
|
||||
inner command in \fITheCmdObjProc\fR.
|
||||
.PP
|
||||
The non-trampoline implementation is simple and stylized, containing
|
||||
a single statement:
|
||||
.PP
|
||||
.CS
|
||||
int
|
||||
\fITheCmdOldObjProc\fR(
|
||||
\fITheCmdNewObjProc\fR(
|
||||
ClientData clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
@@ -187,6 +260,9 @@ int
|
||||
}
|
||||
.CE
|
||||
.PP
|
||||
The trampoline-enabled implementation requests postprocessing,
|
||||
and returns to the trampoline requesting command evaluation.
|
||||
.PP
|
||||
.CS
|
||||
int
|
||||
\fITheCmdNRObjProc\fR
|
||||
@@ -208,6 +284,9 @@ int
|
||||
}
|
||||
.CE
|
||||
.PP
|
||||
The postprocessing procedure does whatever the original command did
|
||||
upon return from the inner evaluation.
|
||||
.PP
|
||||
.CS
|
||||
int
|
||||
\fITheCmdNRPostProc\fR(
|
||||
@@ -224,13 +303,26 @@ int
|
||||
}
|
||||
.CE
|
||||
.PP
|
||||
Any function comprising a routine can push other functions, making it possible
|
||||
implement looping and sequencing constructs using the function stack.
|
||||
If \fItheCommand\fR is a command that results in multiple commands or
|
||||
scripts being evaluated, its postprocessing routine may schedule
|
||||
additional postprocessing and then request another command evaluation
|
||||
by means of \fBTcl_NREvalObj\fR or one of the other evaluation
|
||||
routines. Looping and sequencing constructs may be implemented in this way.
|
||||
.PP
|
||||
Finally, to install a trampoline-enabled command in the interpreter,
|
||||
\fBTcl_NRCreateCommand\fR is used in place of
|
||||
\fBTcl_CreateObjCommand\fR. It accepts two command procedures instead
|
||||
of one. The first is for use when no trampoline is yet on the stack,
|
||||
and the second is for use when there is already a trampoline in place.
|
||||
.PP
|
||||
.CS
|
||||
\fBTcl_NRCreateCommand\fR(interp, "theCommand",
|
||||
\fITheCmdNewObjProc\fR, \fITheCmdNRObjProc\fR, clientData,
|
||||
TheCmdDeleteProc);
|
||||
.CE
|
||||
.SH "SEE ALSO"
|
||||
Tcl_CreateCommand(3), Tcl_CreateObjCommand(3), Tcl_EvalObjEx(3), Tcl_GetCommandFromObj(3), Tcl_ExprObj(3)
|
||||
.SH KEYWORDS
|
||||
stackless, nonrecursive, execute, command, global, value, result, script
|
||||
.SH COPYRIGHT
|
||||
Copyright (c) 2008 by Kevin B. Kenny.
|
||||
Copyright (c) 2018 by Nathan Coulter.
|
||||
Copyright (c) 2008 by Kevin B. Kenny
|
||||
|
||||
+1
-1
@@ -257,7 +257,7 @@ The \fBincr\fR command first gets an integer from \fIx\fR's value
|
||||
by calling \fBTcl_GetIntFromObj\fR.
|
||||
This procedure checks whether the value is already an integer value.
|
||||
Since it is not, it converts the value
|
||||
by setting the value's internal representation
|
||||
by setting the value's \fIinternalRep.longValue\fR member
|
||||
to the integer \fB123\fR
|
||||
and setting the value's \fItypePtr\fR
|
||||
to point to the integer Tcl_ObjType structure.
|
||||
|
||||
+3
-1
@@ -32,7 +32,7 @@ int
|
||||
int
|
||||
\fBTcl_GetChannelNamesEx\fR(\fIinterp, pattern\fR)
|
||||
.sp
|
||||
void
|
||||
Tcl_Channel
|
||||
\fBTcl_RegisterChannel\fR(\fIinterp, channel\fR)
|
||||
.sp
|
||||
int
|
||||
@@ -319,6 +319,8 @@ the name given in the call to \fBTcl_CreateChannel\fR. After this call,
|
||||
the channel becomes the property of the interpreter, and the caller should
|
||||
not call \fBTcl_Close\fR for the channel; the channel will be closed
|
||||
automatically when it is unregistered from the interpreter.
|
||||
\fBTcl_RegisterChannel\fR returns the channel, as a convenience to the
|
||||
programmer,
|
||||
.PP
|
||||
Code executing outside of any Tcl interpreter can call
|
||||
\fBTcl_RegisterChannel\fR with \fIinterp\fR as NULL, to indicate that it
|
||||
|
||||
+7
-1
@@ -7,7 +7,7 @@
|
||||
.BS
|
||||
'\" Note: do not modify the .SH NAME line immediately below!
|
||||
.SH NAME
|
||||
Tcl_Panic, Tcl_SetPanicProc \- report fatal error and abort
|
||||
Tcl_Panic, Tcl_PanicVA, Tcl_SetPanicProc \- report fatal error and abort
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
\fB#include <tcl.h>\fR
|
||||
@@ -16,6 +16,9 @@ void
|
||||
\fBTcl_Panic\fR(\fIformat\fR, \fIarg\fR, \fIarg\fR, \fI...\fR)
|
||||
.sp
|
||||
void
|
||||
\fBTcl_PanicVA\fR(\fIformat\fR, \fIargList\fR)
|
||||
.sp
|
||||
void
|
||||
\fBTcl_SetPanicProc\fR(\fIpanicProc\fR)
|
||||
.sp
|
||||
.SH ARGUMENTS
|
||||
@@ -77,6 +80,9 @@ the Tcl library, \fBTcl_Panic\fR is a public function and may be called
|
||||
by any extension or application that wishes to abort the process and
|
||||
have a panic message displayed the same way that panic messages from Tcl
|
||||
will be displayed.
|
||||
.PP
|
||||
\fBTcl_PanicVA\fR is the same as \fBTcl_Panic\fR except that instead of
|
||||
taking a variable number of arguments it takes an argument list.
|
||||
.SH "SEE ALSO"
|
||||
abort(3), printf(3), exec(n), format(n)
|
||||
.SH KEYWORDS
|
||||
|
||||
+19
-5
@@ -8,7 +8,7 @@
|
||||
.so man.macros
|
||||
.BS
|
||||
.SH NAME
|
||||
Tcl_ParseCommand, Tcl_ParseExpr, Tcl_ParseBraces, Tcl_ParseQuotedString, Tcl_ParseVarName, Tcl_ParseVar, Tcl_FreeParse, Tcl_EvalTokensStandard \- parse Tcl scripts and expressions
|
||||
Tcl_ParseCommand, Tcl_ParseExpr, Tcl_ParseBraces, Tcl_ParseQuotedString, Tcl_ParseVarName, Tcl_ParseVar, Tcl_FreeParse, Tcl_EvalTokens, Tcl_EvalTokensStandard \- parse Tcl scripts and expressions
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
\fB#include <tcl.h>\fR
|
||||
@@ -33,16 +33,20 @@ const char *
|
||||
.sp
|
||||
\fBTcl_FreeParse\fR(\fIusedParsePtr\fR)
|
||||
.sp
|
||||
Tcl_Obj *
|
||||
\fBTcl_EvalTokens\fR(\fIinterp, tokenPtr, numTokens\fR)
|
||||
.sp
|
||||
int
|
||||
\fBTcl_EvalTokensStandard\fR(\fIinterp, tokenPtr, numTokens\fR)
|
||||
.SH ARGUMENTS
|
||||
.AS Tcl_Interp *usedParsePtr out
|
||||
.AP Tcl_Interp *interp out
|
||||
For procedures other than \fBTcl_FreeParse\fR and
|
||||
\fBTcl_EvalTokensStandard\fR, used only for error reporting;
|
||||
For procedures other than \fBTcl_FreeParse\fR, \fBTcl_EvalTokens\fR
|
||||
and \fBTcl_EvalTokensStandard\fR, used only for error reporting;
|
||||
if NULL, then no error messages are left after errors.
|
||||
For \fBTcl_EvalTokensStandard\fR, determines the context for evaluating
|
||||
the script and also is used for error reporting; must not be NULL.
|
||||
For \fBTcl_EvalTokens\fR and \fBTcl_EvalTokensStandard\fR,
|
||||
determines the context for evaluating the
|
||||
script and also is used for error reporting; must not be NULL.
|
||||
.AP "const char" *start in
|
||||
Pointer to first character in string to parse.
|
||||
.AP int numBytes in
|
||||
@@ -187,6 +191,16 @@ code with one of the values \fBTCL_OK\fR, \fBTCL_ERROR\fR,
|
||||
some other integer value originating in an extension.
|
||||
In addition, a result value or error message is left in \fIinterp\fR's
|
||||
result; it can be retrieved using \fBTcl_GetObjResult\fR.
|
||||
.PP
|
||||
\fBTcl_EvalTokens\fR differs from \fBTcl_EvalTokensStandard\fR only in
|
||||
the return convention used: it returns the result in a new Tcl_Obj.
|
||||
The reference count of the value returned as result has been
|
||||
incremented, so the caller must
|
||||
invoke \fBTcl_DecrRefCount\fR when it is finished with the value.
|
||||
If an error or other exception occurs while evaluating the tokens
|
||||
(such as a reference to a non-existent variable) then the return value
|
||||
is NULL and an error message is left in \fIinterp\fR's result. The use
|
||||
of \fBTcl_EvalTokens\fR is deprecated.
|
||||
.SH "TCL_PARSE STRUCTURE"
|
||||
.PP
|
||||
\fBTcl_ParseCommand\fR, \fBTcl_ParseExpr\fR, \fBTcl_ParseBraces\fR,
|
||||
|
||||
+7
-2
@@ -18,7 +18,10 @@ Tcl_PrintDouble \- Convert floating value to string
|
||||
.SH ARGUMENTS
|
||||
.AS Tcl_Interp *interp out
|
||||
.AP Tcl_Interp *interp in
|
||||
This argument is ignored.
|
||||
Before Tcl 8.0, the \fBtcl_precision\fR variable in this interpreter
|
||||
controlled the conversion. As of Tcl 8.0, this argument is ignored and
|
||||
the conversion is controlled by the \fBtcl_precision\fR variable
|
||||
that is now shared by all interpreters.
|
||||
.AP double value in
|
||||
Floating-point value to be converted.
|
||||
.AP char *dst out
|
||||
@@ -38,7 +41,9 @@ so that it does not look like an integer. Where \fB%g\fR would
|
||||
generate an integer with no decimal point, \fBTcl_PrintDouble\fR adds
|
||||
.QW .0 .
|
||||
.PP
|
||||
The result will have the fewest digits needed to
|
||||
If the \fBtcl_precision\fR value is non-zero, the result will have
|
||||
precisely that many digits of significance. If the value is zero
|
||||
(the default), the result will have the fewest digits needed to
|
||||
represent the number in such a way that \fBTcl_NewDoubleObj\fR
|
||||
will generate the same number when presented with the given string.
|
||||
IEEE semantics of rounding to even apply to the conversion.
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ the command at global level instead of the current stack level.
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
\fBTcl_RecordAndEvalObj\fR is invoked to record a command as an event
|
||||
on the history list and then execute it using \fBTcl_EvalObjEx\fR.
|
||||
on the history list and then execute it using \fBTcl_EvalObjEx\fR
|
||||
It returns a completion code such as \fBTCL_OK\fR just like \fBTcl_EvalObjEx\fR,
|
||||
as well as a result value containing additional information
|
||||
(a result value or error message)
|
||||
|
||||
+2
-2
@@ -54,9 +54,9 @@ is called, Tcl will take care of memory management.
|
||||
.PP
|
||||
The second triplet stores the snapshot of only the interpreter
|
||||
result (not its complete state) in memory allocated by the caller.
|
||||
These routines are passed a pointer to \fBTcl_SavedResult\fR
|
||||
These routines are passed a pointer to a \fBTcl_SavedResult\fR structure
|
||||
that is used to store enough information to restore the interpreter result.
|
||||
\fBTcl_SavedResult\fR can be allocated on the stack of the calling
|
||||
This structure can be allocated on the stack of the calling
|
||||
procedure. These routines do not save the state of any error
|
||||
information in the interpreter (e.g. the \fB\-errorcode\fR or
|
||||
\fB\-errorinfo\fR return options, when an error is in progress).
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ New limit for nested calls to \fBTcl_Eval\fR for \fIinterp\fR.
|
||||
.PP
|
||||
At any given time Tcl enforces a limit on the number of recursive
|
||||
calls that may be active for \fBTcl_Eval\fR and related procedures
|
||||
such as \fBTcl_EvalEx\fR.
|
||||
such as \fBTcl_GlobalEval\fR.
|
||||
Any call to \fBTcl_Eval\fR that exceeds this depth is aborted with
|
||||
an error.
|
||||
By default the recursion limit is 1000.
|
||||
|
||||
+19
-1
@@ -9,7 +9,7 @@
|
||||
.so man.macros
|
||||
.BS
|
||||
.SH NAME
|
||||
Tcl_SetObjResult, Tcl_GetObjResult, Tcl_SetResult, Tcl_GetStringResult, Tcl_AppendResult, Tcl_AppendElement, Tcl_ResetResult, Tcl_TransferResult, Tcl_FreeResult \- manipulate Tcl result
|
||||
Tcl_SetObjResult, Tcl_GetObjResult, Tcl_SetResult, Tcl_GetStringResult, Tcl_AppendResult, Tcl_AppendResultVA, Tcl_AppendElement, Tcl_ResetResult, Tcl_TransferResult, Tcl_FreeResult \- manipulate Tcl result
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
\fB#include <tcl.h>\fR
|
||||
@@ -26,6 +26,8 @@ const char *
|
||||
.sp
|
||||
\fBTcl_AppendResult\fR(\fIinterp, result, result, ... , \fB(char *) NULL\fR)
|
||||
.sp
|
||||
\fBTcl_AppendResultVA\fR(\fIinterp, argList\fR)
|
||||
.sp
|
||||
\fBTcl_ResetResult\fR(\fIinterp\fR)
|
||||
.sp
|
||||
.VS 8.6
|
||||
@@ -150,6 +152,9 @@ extensions.
|
||||
Any number of \fIresult\fR arguments may be passed in a single
|
||||
call; the last argument in the list must be a NULL pointer.
|
||||
.PP
|
||||
\fBTcl_AppendResultVA\fR is the same as \fBTcl_AppendResult\fR except that
|
||||
instead of taking a variable number of arguments it takes an argument list.
|
||||
.PP
|
||||
.VS 8.6
|
||||
\fBTcl_TransferResult\fR moves a result from one interpreter to another,
|
||||
optionally (dependent on the \fIresult\fR parameter) including the error
|
||||
@@ -192,6 +197,19 @@ It also sets \fIinterp->freeProc\fR to zero, but does not
|
||||
change \fIinterp->result\fR or clear error state.
|
||||
\fBTcl_FreeResult\fR is most commonly used when a procedure
|
||||
is about to replace one result value with another.
|
||||
.SS "DIRECT ACCESS TO INTERP->RESULT"
|
||||
.PP
|
||||
It used to be legal for programs to
|
||||
directly read and write \fIinterp->result\fR
|
||||
to manipulate the interpreter result. The Tcl headers no longer
|
||||
permit this access by default, and C code still doing this must
|
||||
be updated to use supported routines \fBTcl_GetObjResult\fR,
|
||||
\fBTcl_GetStringResult\fR, \fBTcl_SetObjResult\fR, and \fBTcl_SetResult\fR.
|
||||
As a migration aid, access can be restored with the compiler directive
|
||||
.CS
|
||||
#define USE_INTERP_RESULT
|
||||
.CE
|
||||
but this is meant only to offer life support to otherwise dead code.
|
||||
.SH "THE TCL_FREEPROC ARGUMENT TO TCL_SETRESULT"
|
||||
.PP
|
||||
\fBTcl_SetResult\fR's \fIfreeProc\fR argument specifies how
|
||||
|
||||
+10
-4
@@ -8,7 +8,7 @@
|
||||
.so man.macros
|
||||
.BS
|
||||
.SH NAME
|
||||
Tcl_NewStringObj, Tcl_NewUnicodeObj, Tcl_SetStringObj, Tcl_SetUnicodeObj, Tcl_GetStringFromObj, Tcl_GetString, Tcl_GetUnicodeFromObj, Tcl_GetUnicode, Tcl_GetUniChar, Tcl_GetCharLength, Tcl_GetRange, Tcl_AppendToObj, Tcl_AppendUnicodeToObj, Tcl_AppendObjToObj, Tcl_AppendStringsToObj, Tcl_AppendLimitedToObj, Tcl_Format, Tcl_AppendFormatToObj, Tcl_ObjPrintf, Tcl_AppendPrintfToObj, Tcl_SetObjLength, Tcl_AttemptSetObjLength, Tcl_ConcatObj \- manipulate Tcl values as strings
|
||||
Tcl_NewStringObj, Tcl_NewUnicodeObj, Tcl_SetStringObj, Tcl_SetUnicodeObj, Tcl_GetStringFromObj, Tcl_GetString, Tcl_GetUnicodeFromObj, Tcl_GetUnicode, Tcl_GetUniChar, Tcl_GetCharLength, Tcl_GetRange, Tcl_AppendToObj, Tcl_AppendUnicodeToObj, Tcl_AppendObjToObj, Tcl_AppendStringsToObj, Tcl_AppendStringsToObjVA, Tcl_AppendLimitedToObj, Tcl_Format, Tcl_AppendFormatToObj, Tcl_ObjPrintf, Tcl_AppendPrintfToObj, Tcl_SetObjLength, Tcl_AttemptSetObjLength, Tcl_ConcatObj \- manipulate Tcl values as strings
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
\fB#include <tcl.h>\fR
|
||||
@@ -37,7 +37,7 @@ Tcl_UniChar *
|
||||
Tcl_UniChar *
|
||||
\fBTcl_GetUnicode\fR(\fIobjPtr\fR)
|
||||
.sp
|
||||
int
|
||||
Tcl_UniChar
|
||||
\fBTcl_GetUniChar\fR(\fIobjPtr, index\fR)
|
||||
.sp
|
||||
int
|
||||
@@ -59,6 +59,9 @@ void
|
||||
\fBTcl_AppendStringsToObj\fR(\fIobjPtr, string, string, ... \fB(char *) NULL\fR)
|
||||
.sp
|
||||
void
|
||||
\fBTcl_AppendStringsToObjVA\fR(\fIobjPtr, argList\fR)
|
||||
.sp
|
||||
void
|
||||
\fBTcl_AppendLimitedToObj\fR(\fIobjPtr, bytes, length, limit, ellipsis\fR)
|
||||
.sp
|
||||
Tcl_Obj *
|
||||
@@ -201,8 +204,7 @@ where the caller does not need the length of the unicode string
|
||||
representation.
|
||||
.PP
|
||||
\fBTcl_GetUniChar\fR returns the \fIindex\fR'th character in the
|
||||
value's Unicode representation. If the index is out of range or
|
||||
it references a low surrogate preceded by a high surrogate, it returns -1;
|
||||
value's Unicode representation.
|
||||
.PP
|
||||
\fBTcl_GetRange\fR returns a newly created value comprised of the
|
||||
characters between \fIfirst\fR and \fIlast\fR (inclusive) in the
|
||||
@@ -244,6 +246,10 @@ values may contain internal null characters). Any number of
|
||||
\fIstring\fR arguments may be provided, but the last argument
|
||||
must be a NULL pointer to indicate the end of the list.
|
||||
.PP
|
||||
\fBTcl_AppendStringsToObjVA\fR is the same as \fBTcl_AppendStringsToObj\fR
|
||||
except that instead of taking a variable number of arguments it takes an
|
||||
argument list.
|
||||
.PP
|
||||
\fBTcl_AppendLimitedToObj\fR is similar to \fBTcl_AppendToObj\fR
|
||||
except that it imposes a limit on how many bytes are appended.
|
||||
This can be handy when the string to be appended might be
|
||||
|
||||
+4
-4
@@ -13,13 +13,13 @@ Tcl_UniCharToUpper, Tcl_UniCharToLower, Tcl_UniCharToTitle, Tcl_UtfToUpper, Tcl_
|
||||
.nf
|
||||
\fB#include <tcl.h>\fR
|
||||
.sp
|
||||
int
|
||||
Tcl_UniChar
|
||||
\fBTcl_UniCharToUpper\fR(\fIch\fR)
|
||||
.sp
|
||||
int
|
||||
Tcl_UniChar
|
||||
\fBTcl_UniCharToLower\fR(\fIch\fR)
|
||||
.sp
|
||||
int
|
||||
Tcl_UniChar
|
||||
\fBTcl_UniCharToTitle\fR(\fIch\fR)
|
||||
.sp
|
||||
int
|
||||
@@ -33,7 +33,7 @@ int
|
||||
.SH ARGUMENTS
|
||||
.AS char *str in/out
|
||||
.AP int ch in
|
||||
The Unicode character to be converted.
|
||||
The Tcl_UniChar to be converted.
|
||||
.AP char *str in/out
|
||||
Pointer to UTF-8 string to be converted in place.
|
||||
.BE
|
||||
|
||||
@@ -48,16 +48,19 @@ int
|
||||
.SH ARGUMENTS
|
||||
.AS int ch
|
||||
.AP int ch in
|
||||
The Unicode character to be examined.
|
||||
The Tcl_UniChar to be examined.
|
||||
.BE
|
||||
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
All of the routines described examine Unicode characters and return a
|
||||
All of the routines described examine Tcl_UniChars and return a
|
||||
boolean value. A non-zero return value means that the character does
|
||||
belong to the character class associated with the called routine. The
|
||||
rest of this document just describes the character classes associated
|
||||
with the various routines.
|
||||
.PP
|
||||
Note: A Tcl_UniChar is a Unicode character represented as an unsigned,
|
||||
fixed-size quantity.
|
||||
|
||||
.SH "CHARACTER CLASSES"
|
||||
.PP
|
||||
|
||||
@@ -63,7 +63,7 @@ const char *
|
||||
const char *
|
||||
\fBTcl_UtfPrev\fR(\fIsrc, start\fR)
|
||||
.sp
|
||||
int
|
||||
Tcl_UniChar
|
||||
\fBTcl_UniCharAtIndex\fR(\fIsrc, index\fR)
|
||||
.sp
|
||||
const char *
|
||||
@@ -77,7 +77,7 @@ int
|
||||
Buffer in which the UTF-8 representation of the Tcl_UniChar is stored. At most
|
||||
\fBTCL_UTF_MAX\fR bytes are stored in the buffer.
|
||||
.AP int ch in
|
||||
The Unicode character to be converted or examined.
|
||||
The Tcl_UniChar to be converted or examined.
|
||||
.AP Tcl_UniChar *chPtr out
|
||||
Filled with the Tcl_UniChar represented by the head of the UTF-8 string.
|
||||
.AP "const char" *src in
|
||||
@@ -140,9 +140,6 @@ number of bytes read from \fIsrc\fR. The caller must ensure that the
|
||||
source buffer is long enough such that this routine does not run off the
|
||||
end and dereference non-existent or random memory; if the source buffer
|
||||
is known to be null-terminated, this will not happen. If the input is
|
||||
a byte in the range 0x80 - 0x9F, \fBTcl_UtfToUniChar\fR assumes the
|
||||
cp1252 encoding, stores the corresponding Tcl_UniChar in \fI*chPtr\fR
|
||||
and returns 1. If the input is otherwise
|
||||
not in proper UTF-8 format, \fBTcl_UtfToUniChar\fR will store the first
|
||||
byte of \fIsrc\fR in \fI*chPtr\fR as a Tcl_UniChar between 0x0000 and
|
||||
0x00ff and return 1.
|
||||
|
||||
@@ -13,6 +13,7 @@ Tcl_WrongNumArgs \- generate standard error message for wrong number of argument
|
||||
.nf
|
||||
\fB#include <tcl.h>\fR
|
||||
.sp
|
||||
int
|
||||
\fBTcl_WrongNumArgs\fR(\fIinterp, objc, objv, message\fR)
|
||||
.SH ARGUMENTS
|
||||
.AS "Tcl_Obj *const" *message
|
||||
@@ -73,6 +74,9 @@ is now an \fIindexObject\fR because it was passed to
|
||||
.CS
|
||||
wrong # args: should be "foo barfly fileName count"
|
||||
.CE
|
||||
.PP
|
||||
\fBTcl_WrongNumArgs\fR always returns TCL_ERRROR, as a convenience to
|
||||
the programmer.
|
||||
.SH "SEE ALSO"
|
||||
Tcl_GetIndexFromObj(3)
|
||||
.SH KEYWORDS
|
||||
|
||||
@@ -47,15 +47,6 @@ been the return value from a previous invocation of
|
||||
Returns 1 if \fIarrayName\fR is an array variable, 0 if there
|
||||
is no variable by that name or if it is a scalar variable.
|
||||
.TP
|
||||
\fBarray for {\fIkeyVariable valueVariable\fB} \fIarrayName body\fP
|
||||
The first argument is a two element list of variable names for the
|
||||
key and value of each entry in the array. The second argument is the
|
||||
array name to iterate over. The third argument is the body to execute
|
||||
for each key and value returned.
|
||||
The ordering of the returned keys is undefined.
|
||||
If an array element is deleted or a new array element is inserted during
|
||||
the \fIarray for\fP process, the command will terminate with an error.
|
||||
.TP
|
||||
\fBarray get \fIarrayName\fR ?\fIpattern\fR?
|
||||
Returns a list containing pairs of elements. The first
|
||||
element in each pair is the name of an element in \fIarrayName\fR
|
||||
|
||||
+7
-2
@@ -846,8 +846,13 @@ stored in \fIvar2\fR.
|
||||
Moves the cursor to the absolute location in the data string specified
|
||||
by \fIcount\fR. Note that position 0 refers to the first byte in
|
||||
\fIstring\fR. If \fIcount\fR refers to a position beyond the end of
|
||||
\fIstring\fR, then the cursor is positioned after the last byte. If
|
||||
\fIcount\fR is omitted, then an error will be generated. For example,
|
||||
\fIstring\fR, then the cursor is positioned after the last byte.
|
||||
.VS 8.6
|
||||
If \fIcount\fR is omitted, then the cursor position in the data string
|
||||
will be stored in the corresponding variable and an argument will be
|
||||
consumed. If count is supplied then no argument is consumed.
|
||||
.VE 8.6
|
||||
For example,
|
||||
.RS
|
||||
.CS
|
||||
\fBbinary scan\fR \ex01\ex02\ex03\ex04 c2@1H* var1 var2
|
||||
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
'\"
|
||||
'\" Copyright (c) 1993 The Regents of the University of California.
|
||||
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
|
||||
'\"
|
||||
'\" See the file "license.terms" for information on usage and redistribution
|
||||
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
'\"
|
||||
.TH case n 7.0 Tcl "Tcl Built-In Commands"
|
||||
.so man.macros
|
||||
.BS
|
||||
'\" Note: do not modify the .SH NAME line immediately below!
|
||||
.SH NAME
|
||||
case \- Evaluate one of several scripts, depending on a given value
|
||||
.SH SYNOPSIS
|
||||
\fBcase\fI string \fR?\fBin\fR? \fIpatList body \fR?\fIpatList body \fR...?
|
||||
.sp
|
||||
\fBcase\fI string \fR?\fBin\fR? {\fIpatList body \fR?\fIpatList body \fR...?}
|
||||
.BE
|
||||
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
\fINote: the \fBcase\fI command is obsolete and is supported only
|
||||
for backward compatibility. At some point in the future it may be
|
||||
removed entirely. You should use the \fBswitch\fI command instead.\fR
|
||||
.PP
|
||||
The \fBcase\fR command matches \fIstring\fR against each of
|
||||
the \fIpatList\fR arguments in order.
|
||||
Each \fIpatList\fR argument is a list of one or
|
||||
more patterns. If any of these patterns matches \fIstring\fR then
|
||||
\fBcase\fR evaluates the following \fIbody\fR argument
|
||||
by passing it recursively to the Tcl interpreter and returns the result
|
||||
of that evaluation.
|
||||
Each \fIpatList\fR argument consists of a single
|
||||
pattern or list of patterns. Each pattern may contain any of the wild-cards
|
||||
described under \fBstring match\fR. If a \fIpatList\fR
|
||||
argument is \fBdefault\fR, the corresponding body will be evaluated
|
||||
if no \fIpatList\fR matches \fIstring\fR. If no \fIpatList\fR argument
|
||||
matches \fIstring\fR and no default is given, then the \fBcase\fR
|
||||
command returns an empty string.
|
||||
.PP
|
||||
Two syntaxes are provided for the \fIpatList\fR and \fIbody\fR arguments.
|
||||
The first uses a separate argument for each of the patterns and commands;
|
||||
this form is convenient if substitutions are desired on some of the
|
||||
patterns or commands.
|
||||
The second form places all of the patterns and commands together into
|
||||
a single argument; the argument must have proper list structure, with
|
||||
the elements of the list being the patterns and commands.
|
||||
The second form makes it easy to construct multi-line case commands,
|
||||
since the braces around the whole list make it unnecessary to include a
|
||||
backslash at the end of each line.
|
||||
Since the \fIpatList\fR arguments are in braces in the second form,
|
||||
no command or variable substitutions are performed on them; this makes
|
||||
the behavior of the second form different than the first form in some
|
||||
cases.
|
||||
|
||||
.SH "SEE ALSO"
|
||||
switch(n)
|
||||
|
||||
.SH KEYWORDS
|
||||
case, match, regular expression
|
||||
+37
-2
@@ -87,6 +87,15 @@ slowing its clock by a tiny fraction for some minutes until it is
|
||||
back in sync with UTC; its data model does not represent minutes that
|
||||
have 59 or 61 seconds.
|
||||
.TP
|
||||
\fI\-now\fR
|
||||
Instead of \fItimeVal\fR a non-integer option \fI\-now\fR can be used as
|
||||
replacement for today, which is simply interpolated to the runt-time as value
|
||||
of \fBclock seconds\fR. For example:
|
||||
.sp
|
||||
\fBclock format -now -f %a; # current day of the week\fR
|
||||
.sp
|
||||
\fBclock add -now 1 month; # next month\fR
|
||||
.TP
|
||||
\fIunit\fR
|
||||
One of the words, \fBseconds\fR, \fBminutes\fR, \fBhours\fR,
|
||||
\fBdays\fR, \fBweekdays\fR, \fBweeks\fR, \fBmonths\fR, or \fByears\fR.
|
||||
@@ -527,6 +536,12 @@ abbreviation appropriate to the current locale, and uses it to fix
|
||||
whether \fB%Y\fR refers to years before or after Year 1 of the
|
||||
Common Era.
|
||||
.TP
|
||||
\fB%Es\fR
|
||||
This affects similar to \fB%s\fR, but in opposition to \fB%s\fR it parses
|
||||
or formats local seconds (not the posix seconds).
|
||||
Because \fB%s\fR has the same precedence as \fB%s\fR (uniquely determines
|
||||
a point in time), it overrides all other input formats.
|
||||
.TP
|
||||
\fB%Ex\fR
|
||||
On output, produces a locale-dependent representation of the date
|
||||
in the locale's alternative calendar. On input, matches
|
||||
@@ -721,13 +736,15 @@ week number \fB%V\fR; programs should use \fB%G\fR for that purpose.
|
||||
On output, produces the current time zone, expressed in hours and
|
||||
minutes east (+hhmm) or west (\-hhmm) of Greenwich. On input, accepts a
|
||||
time zone specifier (see \fBTIME ZONES\fR below) that will be used to
|
||||
determine the time zone.
|
||||
determine the time zone (this token is optionally applicable on input,
|
||||
so the value is not mandatory and can be missing in input).
|
||||
.TP
|
||||
\fB%Z\fR
|
||||
On output, produces the current time zone's name, possibly
|
||||
translated to the given locale. On input, accepts a time zone
|
||||
specifier (see \fBTIME ZONES\fR below) that will be used to determine the
|
||||
time zone. This option should, in general, be used on input only when
|
||||
time zone (token is also like \fB%z\fR optionally applicable on input).
|
||||
This option should, in general, be used on input only when
|
||||
parsing RFC822 dates. Other uses are fraught with ambiguity; for
|
||||
instance, the string \fBBST\fR may represent British Summer Time or
|
||||
Brazilian Standard Time. It is recommended that date/time strings for
|
||||
@@ -926,6 +943,24 @@ used. Finally, a correction is applied so that the correct hour of
|
||||
the day is produced after allowing for daylight savings time
|
||||
differences and the correct date is given when going from the end
|
||||
of a long month to a short month.
|
||||
.PP
|
||||
The precedence of the applying of single tokens resp. which sequence will be
|
||||
used by calculating of the time is complex, e. g. heavily dependent on the
|
||||
precision of type of the token.
|
||||
.sp
|
||||
In example below the second date-string contains "next January", therefore
|
||||
it results in next year but in January. And third date-string besides "January"
|
||||
contains also additionally "Fri", so it results in the nearest Friday.
|
||||
Thus both win before "385 days" resp. make it more precise, because of higher
|
||||
precision of this token types.
|
||||
.CS
|
||||
% clock format [clock scan "5 years 18 months 385 days" -base 0 -gmt 1] -gmt 1
|
||||
Thu Jul 21 00:00:00 GMT 1977
|
||||
% clock format [clock scan "5 years 18 months 385 days next January" -base 0 -gmt 1] -gmt 1
|
||||
Sat Jan 21 00:00:00 GMT 1978
|
||||
% clock format [clock scan "5 years 18 months 385 days next January Fri" -base 0 -gmt 1] -gmt 1
|
||||
Fri Jan 27 00:00:00 GMT 1978
|
||||
.CE
|
||||
.SH "SEE ALSO"
|
||||
msgcat(n)
|
||||
.SH KEYWORDS
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ exception to occur.
|
||||
The exception causes the current script to be aborted
|
||||
out to the innermost containing loop command, which then
|
||||
continues with the next iteration of the loop.
|
||||
Continue exceptions are also handled in a few other situations, such
|
||||
Catch exceptions are also handled in a few other situations, such
|
||||
as the \fBcatch\fR command and the outermost scripts of procedure
|
||||
bodies.
|
||||
.SH EXAMPLE
|
||||
|
||||
+6
-16
@@ -14,7 +14,7 @@ oo::copy \- create copies of objects and classes
|
||||
.nf
|
||||
package require TclOO
|
||||
|
||||
\fBoo::copy\fI sourceObject \fR?\fItargetObject\fR? ?\fItargetNamespace\fR?
|
||||
\fBoo::copy\fI sourceObject \fR?\fItargetObject\fR?
|
||||
.fi
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
@@ -22,21 +22,11 @@ package require TclOO
|
||||
The \fBoo::copy\fR command creates a copy of an object or class. It takes the
|
||||
name of the object or class to be copied, \fIsourceObject\fR, and optionally
|
||||
the name of the object or class to create, \fItargetObject\fR, which will be
|
||||
resolved relative to the current namespace if not an absolute qualified name
|
||||
and
|
||||
.VS TIP473
|
||||
\fItargetNamespace\fR which is the name of the namespace that will hold the
|
||||
internal state of the object (\fBmy\fR command, etc.); it \fImust not\fR
|
||||
refer to an existing namespace.
|
||||
If either \fItargetObject\fR or \fItargetNamespace\fR is omitted or is given
|
||||
as the empty string, a new name is chosen. Names, unless specified, are
|
||||
chosen with the same algorithm used by the \fBnew\fR method of
|
||||
\fBoo::class\fR.
|
||||
.VE TIP473
|
||||
The copied object will be of the same class as the source object, and will have
|
||||
all its per-object methods copied. If it is a class, it will also have all the
|
||||
class methods in the class copied, but it will not have any of its instances
|
||||
copied.
|
||||
resolved relative to the current namespace if not an absolute qualified name.
|
||||
If \fItargetObject\fR is omitted, a new name is chosen. The copied object will
|
||||
be of the same class as the source object, and will have all its per-object
|
||||
methods copied. If it is a class, it will also have all the class methods in
|
||||
the class copied, but it will not have any of its instances copied.
|
||||
.PP
|
||||
.VS
|
||||
After the \fItargetObject\fR has been created and all definitions of its
|
||||
|
||||
+1
-16
@@ -50,7 +50,7 @@ being constructed. Within the constructor, the \fBnext\fR command should be
|
||||
used to call the superclasses' constructors. If \fIbodyScript\fR is the empty
|
||||
string, the constructor will be deleted.
|
||||
.TP
|
||||
\fBdeletemethod\fI name\fR ?\fIname ...\fR?
|
||||
\fBdeletemethod\fI name\fR ?\fIname ...\fR
|
||||
.
|
||||
This deletes each of the methods called \fIname\fR from a class. The methods
|
||||
must have previously existed in that class. Does not affect the superclasses
|
||||
@@ -142,8 +142,6 @@ be afterwards.
|
||||
\fBself\fI subcommand arg ...\fR
|
||||
.TP
|
||||
\fBself\fI script\fR
|
||||
.TP
|
||||
\fBself\fR
|
||||
.
|
||||
This command is equivalent to calling \fBoo::objdefine\fR on the class being
|
||||
defined (see \fBCONFIGURING OBJECTS\fR below for a description of the
|
||||
@@ -153,13 +151,6 @@ and
|
||||
.QW "\fBoo::define \fIcls \fBself \fIsubcommand ...\fR"
|
||||
operates identically to
|
||||
.QW "\fBoo::objdefine \fIcls subcommand ...\fR" .
|
||||
.RS
|
||||
.PP
|
||||
.VS TIP470
|
||||
If no arguments at all are used, this gives the name of the class currently
|
||||
being configured.
|
||||
.VE TIP470
|
||||
.RE
|
||||
.TP
|
||||
\fBsuperclass\fR ?\fI\-slotOperation\fR? ?\fIclassName ...\fR?
|
||||
.VS
|
||||
@@ -274,12 +265,6 @@ not previously refer to a method in that object. Does not affect the classes
|
||||
that the object is an instance of. Does not change the export status of the
|
||||
method; if it was exported before, it will be afterwards.
|
||||
.TP
|
||||
\fBself \fR
|
||||
.
|
||||
.VS TIP470
|
||||
This gives the name of the object currently being configured.
|
||||
.VE TIP470
|
||||
.TP
|
||||
\fBunexport\fI name \fR?\fIname ...\fR?
|
||||
.
|
||||
This arranges for each of the named methods, \fIname\fR, to be not exported
|
||||
|
||||
+1
-1
@@ -437,7 +437,7 @@ puts $foo
|
||||
# prints: \fIa b foo {a b} bar 2 baz 3\fR
|
||||
.CE
|
||||
.SH "SEE ALSO"
|
||||
append(n), array(n), foreach(n), incr(n), list(n), lappend(n), lmap(n), set(n)
|
||||
append(n), array(n), foreach(n), mapeach(n), incr(n), list(n), lappend(n), set(n)
|
||||
.SH KEYWORDS
|
||||
dictionary, create, update, lookup, iterate, filter, map
|
||||
'\" Local Variables:
|
||||
|
||||
+4
-3
@@ -46,11 +46,12 @@ value is the form produced by the \fB%g\fR format specifier of Tcl's
|
||||
An expression consists of a combination of operands, operators, parentheses and
|
||||
commas, possibly with whitespace between any of these elements, which is
|
||||
ignored.
|
||||
An integer operand may be specified in decimal (the normal case, the optional
|
||||
first two characters are \fB0d\fR), binary
|
||||
An integer operand may be specified in decimal, binary
|
||||
(the first two characters are \fB0b\fR), octal
|
||||
(the first two characters are \fB0o\fR), or hexadecimal
|
||||
(the first two characters are \fB0x\fR) form.
|
||||
(the first two characters are \fB0x\fR) form. For
|
||||
compatibility with older Tcl releases, an operand that begins with \fB0\fR is
|
||||
interpreted as an octal integer even if the second character is not \fBo\fR.
|
||||
A floating-point number may be specified in any of several
|
||||
common decimal formats, and may use the decimal point \fB.\fR,
|
||||
\fBe\fR or \fBE\fR for scientific notation, and
|
||||
|
||||
+8
-23
@@ -83,15 +83,12 @@ Specifies that the number should be padded on the left with
|
||||
zeroes instead of spaces.
|
||||
.TP 10
|
||||
\fB#\fR
|
||||
Requests an alternate output form. For \fBo\fR conversions,
|
||||
\fB0o\fR will be added to the beginning of the result unless
|
||||
it is zero. For \fBx\fR or \fBX\fR conversions, \fB0x\fR
|
||||
Requests an alternate output form. For \fBo\fR and \fBO\fR
|
||||
conversions it guarantees that the first digit is always \fB0\fR.
|
||||
For \fBx\fR or \fBX\fR conversions, \fB0x\fR or \fB0X\fR (respectively)
|
||||
will be added to the beginning of the result unless it is zero.
|
||||
For \fBb\fR conversions, \fB0b\fR
|
||||
will be added to the beginning of the result unless it is zero.
|
||||
For \fBd\fR conversions, \fB0d\fR there is no effect unless
|
||||
the \fB0\fR specifier is used as well: In that case, \fB0d\fR
|
||||
will be added to the beginning.
|
||||
For all floating-point conversions (\fBe\fR, \fBE\fR, \fBf\fR,
|
||||
\fBg\fR, and \fBG\fR) it guarantees that the result always
|
||||
has a decimal point.
|
||||
@@ -133,7 +130,7 @@ it must be a numeric string.
|
||||
.SS "OPTIONAL SIZE MODIFIER"
|
||||
.PP
|
||||
The fifth part of a conversion specifier is a size modifier,
|
||||
which must be \fBll\fR, \fBh\fR, \fBl\fR, or \fBL\fR.
|
||||
which must be \fBll\fR, \fBh\fR, or \fBl\fR.
|
||||
If it is \fBll\fR it specifies that an integer value is taken
|
||||
without truncation for conversion to a formatted substring.
|
||||
If it is \fBh\fR it specifies that an integer value is
|
||||
@@ -141,9 +138,7 @@ truncated to a 16-bit range before converting. This option is rarely useful.
|
||||
If it is \fBl\fR it specifies that the integer value is
|
||||
truncated to the same range as that produced by the \fBwide()\fR
|
||||
function of the \fBexpr\fR command (at least a 64-bit range).
|
||||
If it is \fBL\fR it specifies that an integer or double value is taken
|
||||
without truncation for conversion to a formatted substring.
|
||||
If neither \fBh\fR nor \fBl\fR nor \fBL\fR are present, the integer value is
|
||||
If neither \fBh\fR nor \fBl\fR are present, the integer value is
|
||||
truncated to the same range as that produced by the \fBint()\fR
|
||||
function of the \fBexpr\fR command (at least a 32-bit range, but
|
||||
determined by the value of the \fBwordSize\fR element of the
|
||||
@@ -174,7 +169,7 @@ for \fBx\fR and
|
||||
for \fBX\fR).
|
||||
.TP 10
|
||||
\fBb\fR
|
||||
Convert integer to unsigned binary string, using digits 0 and 1.
|
||||
Convert integer to binary string, using digits 0 and 1.
|
||||
.TP 10
|
||||
\fBc\fR
|
||||
Convert integer to the Unicode character it represents.
|
||||
@@ -203,19 +198,8 @@ precision, then convert number as for \fB%e\fR or
|
||||
Otherwise convert as for \fB%f\fR.
|
||||
Trailing zeroes and a trailing decimal point are omitted.
|
||||
.TP 10
|
||||
\fBa\fR or \fBA\fR
|
||||
Convert double to hexadecimal notation in the form
|
||||
\fI0x1.yyy\fBp\(+-\fIzz\fR, where the number of \fIy\fR's is
|
||||
determined by the precision (default: 13).
|
||||
If the \fBA\fR form is used then the hex characters
|
||||
are printed in uppercase.
|
||||
.TP 10
|
||||
\fB%\fR
|
||||
No conversion: just insert \fB%\fR.
|
||||
.TP 10
|
||||
\fBp\fR
|
||||
Shorthand form for \fB0x%zx\fR, so it outputs the integer in
|
||||
hexadecimal form with \fB0x\fR prefix.
|
||||
.SH "DIFFERENCES FROM ANSI SPRINTF"
|
||||
.PP
|
||||
The behavior of the format command is the same as the
|
||||
@@ -224,12 +208,13 @@ differences:
|
||||
.IP [1]
|
||||
Tcl guarantees that it will be working with UNICODE characters.
|
||||
.IP [2]
|
||||
\fB%n\fR specifier is not supported.
|
||||
\fB%p\fR and \fB%n\fR specifiers are not supported.
|
||||
.IP [3]
|
||||
For \fB%c\fR conversions the argument must be an integer value,
|
||||
which will then be converted to the corresponding character value.
|
||||
.IP [4]
|
||||
The size modifiers are ignored when formatting floating-point values.
|
||||
The \fBll\fR modifier has no \fBsprintf\fR counterpart.
|
||||
The \fBb\fR specifier has no \fBsprintf\fR counterpart.
|
||||
.SH EXAMPLES
|
||||
.PP
|
||||
|
||||
@@ -148,19 +148,6 @@ or \fB\-not\fR.
|
||||
These options are used to search lists of lists. They may be used
|
||||
with any other options.
|
||||
.TP
|
||||
\fB\-stride\0\fIstrideLength\fR
|
||||
.
|
||||
If this option is specified, the list is treated as consisting of
|
||||
groups of \fIstrideLength\fR elements and the groups are searched by
|
||||
either their first element or, if the \fB\-index\fR option is used,
|
||||
by the element within each group given by the first index passed to
|
||||
\fB\-index\fR (which is then ignored by \fB\-index\fR). The resulting
|
||||
index always points to the first element in a group.
|
||||
.PP
|
||||
The list length must be an integer multiple of \fIstrideLength\fR, which
|
||||
in turn must be at least 1. A \fIstrideLength\fR of 1 is the default and
|
||||
indicates no grouping.
|
||||
.TP
|
||||
\fB\-index\fR\0\fIindexList\fR
|
||||
.
|
||||
This option is designed for use when searching within nested lists.
|
||||
@@ -221,13 +208,6 @@ It is also possible to search inside elements:
|
||||
\fBlsearch\fR -index 1 -all -inline {{a abc} {b bcd} {c cde}} *bc*
|
||||
\fI\(-> {a abc} {b bcd}\fR
|
||||
.CE
|
||||
.PP
|
||||
The same thing for a flattened list:
|
||||
.PP
|
||||
.CS
|
||||
\fBlsearch\fR -stride 2 -index 1 -all -inline {a abc b bcd c cde} *bc*
|
||||
\fI\(-> {a abc b bcd}\fR
|
||||
.CE
|
||||
.SH "SEE ALSO"
|
||||
foreach(n), list(n), lappend(n), lindex(n), linsert(n), llength(n),
|
||||
lset(n), lsort(n), lrange(n), lreplace(n),
|
||||
|
||||
Regular → Executable
+4
-1
@@ -106,7 +106,10 @@ of which work solely with floating-point numbers unless otherwise noted:
|
||||
In addition to these predefined functions, applications may
|
||||
define additional functions by using \fBproc\fR (or any other method,
|
||||
such as \fBinterp alias\fR or \fBTcl_CreateObjCommand\fR) to define
|
||||
new commands in the \fBtcl::mathfunc\fR namespace.
|
||||
new commands in the \fBtcl::mathfunc\fR namespace. In addition, an
|
||||
obsolete interface named \fBTcl_CreateMathFunc\fR() is available to
|
||||
extensions that are written in C. The latter interface is not recommended
|
||||
for new implementations.
|
||||
.SS "DETAILED DEFINITIONS"
|
||||
.TP
|
||||
\fBabs \fIarg\fR
|
||||
|
||||
+27
-178
@@ -11,9 +11,9 @@
|
||||
.SH NAME
|
||||
msgcat \- Tcl message catalog
|
||||
.SH SYNOPSIS
|
||||
\fBpackage require Tcl 8.7\fR
|
||||
\fBpackage require Tcl 8.5\fR
|
||||
.sp
|
||||
\fBpackage require msgcat 1.7\fR
|
||||
\fBpackage require msgcat 1.6\fR
|
||||
.sp
|
||||
\fB::msgcat::mc \fIsrc-string\fR ?\fIarg arg ...\fR?
|
||||
.sp
|
||||
@@ -23,15 +23,9 @@ msgcat \- Tcl message catalog
|
||||
\fB::msgcat::mcexists\fR ?\fB-exactnamespace\fR? ?\fB-exactlocale\fR? \fIsrc-string\fR
|
||||
.VE "TIP 412"
|
||||
.sp
|
||||
.VS "TIP 490"
|
||||
\fB::msgcat::mcpackagenamespaceget\fR
|
||||
.VE "TIP 490"
|
||||
.sp
|
||||
\fB::msgcat::mclocale \fR?\fInewLocale\fR?
|
||||
.sp
|
||||
.VS "TIP 499"
|
||||
\fB::msgcat::mcpreferences\fR ?\fIlocale preference\fR? ...
|
||||
.VE "TIP 499"
|
||||
\fB::msgcat::mcpreferences\fR
|
||||
.sp
|
||||
.VS "TIP 412"
|
||||
\fB::msgcat::mcloadedlocales subcommand\fR ?\fIlocale\fR?
|
||||
@@ -56,10 +50,6 @@ msgcat \- Tcl message catalog
|
||||
.sp
|
||||
\fB::msgcat::mcforgetpackage\fR
|
||||
.VE "TIP 412"
|
||||
.sp
|
||||
.VS "TIP 499"
|
||||
\fB::msgcat::mcutil subcommand\fR ?\fIlocale\fR?
|
||||
.VS "TIP 499"
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
@@ -81,11 +71,6 @@ In \fBmsgcat\fR, there is a global locale initialized by the system locale of th
|
||||
Each package may decide to use the global locale or to use a package specific locale.
|
||||
.PP
|
||||
The global locale may be changed on demand, for example by a user initiated language change or within a multi user application like a web server.
|
||||
.PP
|
||||
.VS tip490
|
||||
Object oriented programming is supported by the use of a package namespace.
|
||||
.VE tip490
|
||||
.PP
|
||||
.SH COMMANDS
|
||||
.TP
|
||||
\fB::msgcat::mc \fIsrc-string\fR ?\fIarg arg ...\fR?
|
||||
@@ -110,17 +95,6 @@ use the result. If an application is written for a single language in
|
||||
this fashion, then it is easy to add support for additional languages
|
||||
later simply by defining new message catalog entries.
|
||||
.RE
|
||||
.VS "TIP 490"
|
||||
.TP
|
||||
\fB::msgcat::mcn \fInamespace\fR \fIsrc-string\fR ?\fIarg arg ...\fR?
|
||||
.
|
||||
Like \fB::msgcat::mc\fR, but with the message namespace specified as first argument.
|
||||
.PP
|
||||
.RS
|
||||
\fBmcn\fR may be used for cases where the package namespace is not the namespace of the caller.
|
||||
An example is shown within the description of the command \fB::msgcat::mcpackagenamespaceget\fR below.
|
||||
.RE
|
||||
.PP
|
||||
.TP
|
||||
\fB::msgcat::mcmax ?\fIsrc-string src-string ...\fR?
|
||||
.
|
||||
@@ -128,69 +102,29 @@ Given several source strings, \fB::msgcat::mcmax\fR returns the length
|
||||
of the longest translated string. This is useful when designing
|
||||
localized GUIs, which may require that all buttons, for example, be a
|
||||
fixed width (which will be the width of the widest button).
|
||||
.VS "TIP 412"
|
||||
.TP
|
||||
\fB::msgcat::mcexists\fR ?\fB-exactnamespace\fR? ?\fB-exactlocale\fR? ?\fB-namespace\fR \fInamespace\fR? \fIsrc-string\fR
|
||||
\fB::msgcat::mcexists\fR ?\fB-exactnamespace\fR? ?\fB-exactlocale\fR? \fIsrc-string\fR
|
||||
.
|
||||
.VS "TIP 412"
|
||||
Return true, if there is a translation for the given \fIsrc-string\fR.
|
||||
.PP
|
||||
.RS
|
||||
The search may be limited by the option \fB\-exactnamespace\fR to only check the current namespace and not any parent namespaces.
|
||||
.PP
|
||||
It may also be limited by the option \fB\-exactlocale\fR to only check the first prefered locale (e.g. first element returned by \fB::msgcat::mcpreferences\fR if global locale is used).
|
||||
.PP
|
||||
.RE
|
||||
.VE "TIP 412"
|
||||
.VS "TIP 490"
|
||||
An explicit package namespace may be specified by the option \fB-namespace\fR.
|
||||
The namespace of the caller is used if not explicitly specified.
|
||||
.RE
|
||||
.PP
|
||||
.VE "TIP 490"
|
||||
.VS "TIP 490"
|
||||
.TP
|
||||
\fB::msgcat::mcpackagenamespaceget\fR
|
||||
.
|
||||
Return the package namespace of the caller.
|
||||
This command handles all cases described in section \fBOBJECT ORIENTED PROGRAMMING\fR.
|
||||
.PP
|
||||
.RS
|
||||
Example usage is a tooltip package, which saves the caller package namespace to update the translation each time the tooltip is shown:
|
||||
.CS
|
||||
proc ::tooltip::tooltip {widget message} {
|
||||
...
|
||||
set messagenamespace [uplevel 1 {::msgcat::mcpackagenamespaceget}]
|
||||
...
|
||||
bind $widget [list ::tooltip::show $widget $messagenamespace $message]
|
||||
}
|
||||
|
||||
proc ::tooltip::show {widget messagenamespace message} {
|
||||
...
|
||||
set message [::msgcat::mcn $messagenamespace $message]
|
||||
...
|
||||
}
|
||||
.CE
|
||||
.RE
|
||||
.PP
|
||||
.VE "TIP 490"
|
||||
.TP
|
||||
\fB::msgcat::mclocale \fR?\fInewLocale\fR?
|
||||
.
|
||||
If \fInewLocale\fR is omitted, the current locale is returned, otherwise the current locale
|
||||
is set to \fInewLocale\fR.
|
||||
.PP
|
||||
.RS
|
||||
If the new locale is set to \fInewLocale\fR, the corresponding preferences are calculated and set.
|
||||
For example, if the current locale is en_US_funky, then \fB::msgcat::mcpreferences\fR returns \fB{en_us_funky en_us en {}}\fR.
|
||||
.PP
|
||||
The same result may be acheved by \fB::msgcat::mcpreferences\fR {*}[\fB::msgcat::mcutil getpreferences\fR \fInewLocale\fR].
|
||||
.PP
|
||||
The current locale is always the first element of the list returned by \fBmcpreferences\fR.
|
||||
.PP
|
||||
msgcat stores and compares the locale in a
|
||||
This function sets the locale to \fInewLocale\fR. If \fInewLocale\fR
|
||||
is omitted, the current locale is returned, otherwise the current locale
|
||||
is set to \fInewLocale\fR. msgcat stores and compares the locale in a
|
||||
case-insensitive manner, and returns locales in lowercase.
|
||||
The initial locale is determined by the locale specified in
|
||||
the user's environment. See \fBLOCALE SPECIFICATION\fR
|
||||
below for a description of the locale string format.
|
||||
.RS
|
||||
.PP
|
||||
.VS "TIP 412"
|
||||
If the locale is set, the preference list of locales is evaluated.
|
||||
@@ -198,26 +132,16 @@ Locales in this list are loaded now, if not jet loaded.
|
||||
.VE "TIP 412"
|
||||
.RE
|
||||
.TP
|
||||
\fB::msgcat::mcpreferences\fR ?\fIlocale preference\fR? ...
|
||||
\fB::msgcat::mcpreferences\fR
|
||||
.
|
||||
Without arguments, returns an ordered list of the locales preferred by
|
||||
the user.
|
||||
The list is ordered from most specific to least preference.
|
||||
.PP
|
||||
.VS "TIP 499"
|
||||
.RS
|
||||
A set of locale preferences may be given to set the list of locale preferences.
|
||||
The current locale is also set, which is the first element of the locale preferences list.
|
||||
.PP
|
||||
Locale preferences are loaded now, if not jet loaded.
|
||||
.PP
|
||||
As an example, the user may prefer French or English text. This may be configured by:
|
||||
.CS
|
||||
::msgcat::mcpreferences fr en {}
|
||||
.CE
|
||||
.RE
|
||||
.PP
|
||||
.VS "TIP 499"
|
||||
Returns an ordered list of the locales preferred by
|
||||
the user, based on the user's language specification.
|
||||
The list is ordered from most specific to least
|
||||
preference. The list is derived from the current
|
||||
locale set in msgcat by \fB::msgcat::mclocale\fR, and
|
||||
cannot be set independently. For example, if the
|
||||
current locale is en_US_funky, then \fB::msgcat::mcpreferences\fR
|
||||
returns \fB{en_us_funky en_us en {}}\fR.
|
||||
.TP
|
||||
\fB::msgcat:mcloadedlocales subcommand\fR ?\fIlocale\fR?
|
||||
.
|
||||
@@ -308,22 +232,6 @@ Note that this routine is only called if the concerned package did not set a pac
|
||||
The calling package clears all its state within the \fBmsgcat\fR package including all settings and translations.
|
||||
.VE "TIP 412"
|
||||
.PP
|
||||
.VS "TIP 499"
|
||||
.TP
|
||||
\fB::msgcat::mcutil getpreferences\fR \fIlocale\fR
|
||||
.
|
||||
Return the preferences list of the given locale as described in section \fBLOCALE SPECIFICATION\fR.
|
||||
An example is the composition of a preference list for the bilingual region "Biel/Bienne" as a concatenation of swiss german and swiss french:
|
||||
.CS
|
||||
% concat [lrange [msgcat::mcutil getpreferences fr_CH] 0 end-1] [msgcat::mcutil getpreferences de_CH]
|
||||
fr_ch fr de_ch de {}
|
||||
.CE
|
||||
.TP
|
||||
\fB::msgcat::mcutil getsystemlocale\fR
|
||||
.
|
||||
The system locale is returned as described by the section \fBLOCALE SPECIFICATION\fR.
|
||||
.VE "TIP 499"
|
||||
.PP
|
||||
.SH "LOCALE SPECIFICATION"
|
||||
.PP
|
||||
The locale is specified to \fBmsgcat\fR by a locale string
|
||||
@@ -529,7 +437,7 @@ formatting substitution is done directly.
|
||||
# human-oriented versions by \fBmsgcat::mcset\fR
|
||||
.CE
|
||||
.VS "TIP 412"
|
||||
.SH "PACKAGE PRIVATE LOCALE"
|
||||
.SH Package private locale
|
||||
.PP
|
||||
A package using \fBmsgcat\fR may choose to use its own package private
|
||||
locale and its own set of loaded locales, independent to the global
|
||||
@@ -553,22 +461,10 @@ This command may cause the load of locales.
|
||||
.
|
||||
Return the package private locale or the global locale, if no package private locale is set.
|
||||
.TP
|
||||
\fB::msgcat::mcpackagelocale preferences\fR ?\fIlocale preference\fR? ...
|
||||
\fB::msgcat::mcpackagelocale preferences\fR
|
||||
.
|
||||
With no parameters, return the package private preferences or the global preferences,
|
||||
Return the package private preferences or the global preferences,
|
||||
if no package private locale is set.
|
||||
The package locale state (set or not) is not changed (in contrast to the command \fB::msgcat::mcpackagelocale set\fR).
|
||||
.PP
|
||||
.RS
|
||||
.VS "TIP 499"
|
||||
If a set of locale preferences is given, it is set as package locale preference list.
|
||||
The package locale is set to the first element of the preference list.
|
||||
A package locale is activated, if it was not set so far.
|
||||
.PP
|
||||
Locale preferences are loaded now for the package, if not jet loaded.
|
||||
.VE "TIP 499"
|
||||
.RE
|
||||
.PP
|
||||
.TP
|
||||
\fB::msgcat::mcpackagelocale loaded\fR
|
||||
.
|
||||
@@ -592,7 +488,7 @@ Returns true, if the given locale is loaded for the package.
|
||||
.
|
||||
Clear any loaded locales of the package not present in the package preferences.
|
||||
.PP
|
||||
.SH "CHANGING PACKAGE OPTIONS"
|
||||
.SH Changing package options
|
||||
.PP
|
||||
Each package using msgcat has a set of options within \fBmsgcat\fR.
|
||||
The package options are described in the next sectionPackage options.
|
||||
@@ -667,7 +563,7 @@ A generic unknown handler is used if set to the empty string. This consists in r
|
||||
See section \fBcallback invocation\fR below.
|
||||
The appended arguments are identical to \fB::msgcat::mcunknown\fR.
|
||||
.RE
|
||||
.SH "Callback invocation"
|
||||
.SS Callback invocation
|
||||
A package may decide to register one or multiple callbacks, as described above.
|
||||
.PP
|
||||
Callbacks are invoked, if:
|
||||
@@ -681,54 +577,7 @@ Callbacks are invoked, if:
|
||||
If a called routine fails with an error, the \fBbgerror\fR routine for the interpreter is invoked after command completion.
|
||||
Only exception is the callback \fBunknowncmd\fR, where an error causes the invoking \fBmc\fR-command to fail with that error.
|
||||
.PP
|
||||
.VS tip490
|
||||
.SH "OBJECT ORIENTED PROGRAMMING"
|
||||
\fBmsgcat\fR supports packages implemented by object oriented programming.
|
||||
Objects and classes should be defined within a package namespace.
|
||||
.PP
|
||||
There are 3 supported cases where package namespace sensitive commands of msgcat (\fBmc\fR, \fBmcexists\fR, \fBmcpackagelocale\fR, \fBmcforgetpackage\fR, \fBmcpackagenamespaceget\fR, \fBmcpackageconfig\fR, \fBmcset\fR and \fBmcmset\fR) may be called:
|
||||
.PP
|
||||
.TP
|
||||
\fB1) In class definition script\fR
|
||||
.
|
||||
\fBmsgcat\fR command is called within a class definition script.
|
||||
.CS
|
||||
namespace eval ::N2 {
|
||||
mcload $dir/msgs
|
||||
oo::class create C1 {puts [mc Hi!]}
|
||||
}
|
||||
.CE
|
||||
.PP
|
||||
.TP
|
||||
\fB2) method defined in a class\fR
|
||||
.
|
||||
\fBmsgcat\fR command is called from a method in an object and the method is defined in a class.
|
||||
.CS
|
||||
namespace eval ::N3Class {
|
||||
mcload $dir/msgs
|
||||
oo::class create C1
|
||||
oo::define C1 method m1 {
|
||||
puts [mc Hi!]
|
||||
}
|
||||
}
|
||||
.CE
|
||||
.PP
|
||||
.TP
|
||||
\fB3) method defined in a classless object\fR
|
||||
.
|
||||
\fBmsgcat\fR command is called from a method of a classless object.
|
||||
.CS
|
||||
namespace eval ::N4 {
|
||||
mcload $dir/msgs
|
||||
oo::object create O1
|
||||
oo::objdefine O1 method m1 {} {
|
||||
puts [mc Hi!]
|
||||
}
|
||||
}
|
||||
.CE
|
||||
.PP
|
||||
.VE tip490
|
||||
.SH EXAMPLES
|
||||
.SS Examples
|
||||
Packages which display a GUI may update their widgets when the global locale changes.
|
||||
To register to a callback, use:
|
||||
.CS
|
||||
@@ -794,9 +643,9 @@ proc ::tcl::clock::LocalizeFormat { locale format } {
|
||||
.PP
|
||||
The message catalog code was developed by Mark Harrison.
|
||||
.SH "SEE ALSO"
|
||||
format(n), scan(n), namespace(n), package(n), oo::class(n), oo::object
|
||||
format(n), scan(n), namespace(n), package(n)
|
||||
.SH KEYWORDS
|
||||
internationalization, i18n, localization, l10n, message, text, translation, class, object
|
||||
internationalization, i18n, localization, l10n, message, text, translation
|
||||
.\" Local Variables:
|
||||
.\" mode: nroff
|
||||
.\" End:
|
||||
|
||||
@@ -68,33 +68,6 @@ and
|
||||
sequences are handled for each substitution using the information
|
||||
from the corresponding match.
|
||||
.TP
|
||||
\fB\-command\fR
|
||||
.VS 8.7
|
||||
Changes the handling of \fIsubSpec\fR so that it is not treated
|
||||
as a template for a substitution string and the substrings
|
||||
.QW &
|
||||
and
|
||||
.QW \e\fIn\fR
|
||||
no longer have special meaning. Instead \fIsubSpec\fR must be a
|
||||
command prefix, that is, a non-empty list. The substring of \fIstring\fR
|
||||
that matches \fIexp\fR, and then each substring that matches each
|
||||
capturing sub-RE within \fIexp\fR are appended as additional elements
|
||||
to that list. (The items appended to the list are much like what
|
||||
\fBregexp\fR \fB-inline\fR would return). The completed list is then
|
||||
evaluated as a Tcl command, and the result of that command is the
|
||||
substitution string. Any error or exception from command evaluation
|
||||
becomes an error or exception from the \fBregsub\fR command.
|
||||
.RS
|
||||
.PP
|
||||
If \fB\-all\fR is not also given, the command callback will be invoked at most
|
||||
once (exactly when the regular expression matches). If \fB\-all\fR is given,
|
||||
the command callback will be invoked for each matched location, in sequence.
|
||||
The exact location indices that matched are not made available to the script.
|
||||
.PP
|
||||
See \fBEXAMPLES\fR below for illustrative cases.
|
||||
.RE
|
||||
.VE 8.7
|
||||
.TP
|
||||
\fB\-expanded\fR
|
||||
.
|
||||
Enables use of the expanded regular expression syntax where
|
||||
@@ -210,53 +183,6 @@ set substitution {[format \e\e\e\eu%04x [scan "\e\e&" %c]]}
|
||||
set quoted [subst [string map {\en {\e\eu000a}} \e
|
||||
[\fBregsub\fR -all $RE $string $substitution]]]
|
||||
.CE
|
||||
.PP
|
||||
.VS 8.7
|
||||
The above operation can be done using \fBregsub \-command\fR instead, which is
|
||||
often faster. (A full pre-computed \fBstring map\fR would be faster still, but
|
||||
the cost of computing the map for a transformation as complex as this can be
|
||||
quite large.)
|
||||
.PP
|
||||
.CS
|
||||
# This RE is just a character class for everything "bad"
|
||||
set RE {[][{};#\e\e\e$\es\eu0080-\euffff]}
|
||||
|
||||
# This encodes what the RE described above matches
|
||||
proc encodeChar {ch} {
|
||||
# newline is handled specially since backslash-newline is a
|
||||
# special sequence.
|
||||
if {$ch eq "\en"} {
|
||||
return "\e\eu000a"
|
||||
}
|
||||
# No point in writing this as a one-liner
|
||||
scan $ch %c charNumber
|
||||
format "\e\eu%04x" $charNumber
|
||||
}
|
||||
|
||||
set quoted [\fBregsub\fR -all -command $RE $string encodeChar]
|
||||
.CE
|
||||
.PP
|
||||
Decoding a URL-encoded string using \fBregsub \-command\fR, a lambda term and
|
||||
the \fBapply\fR command.
|
||||
.PP
|
||||
.CS
|
||||
# Match one of the sequences in a URL-encoded string that needs
|
||||
# fixing, converting + to space and %XX to the right character
|
||||
# (e.g., %7e becomes ~)
|
||||
set RE {(\e+)|%([0-9A-Fa-f]{2})}
|
||||
|
||||
# Note that -command uses a command prefix, not a command name
|
||||
set decoded [\fBregsub\fR -all -command $RE $string {apply {{- p h} {
|
||||
# + is a special case; handle directly
|
||||
if {$p eq "+"} {
|
||||
return " "
|
||||
}
|
||||
# convert hex to a char
|
||||
scan $h %x charNumber
|
||||
format %c $charNumber
|
||||
}}}]
|
||||
.CE
|
||||
.VE 8.7
|
||||
.SH "SEE ALSO"
|
||||
regexp(n), re_syntax(n), subst(n), string(n)
|
||||
.SH KEYWORDS
|
||||
|
||||
+4
-2
@@ -224,10 +224,12 @@ set string "#08D03F"
|
||||
\fBscan\fR $string "#%2x%2x%2x" r g b
|
||||
.CE
|
||||
.PP
|
||||
Parse a \fIHH:MM\fR time string:
|
||||
Parse a \fIHH:MM\fR time string, noting that this avoids problems with
|
||||
octal numbers by forcing interpretation as decimals (if we did not
|
||||
care, we would use the \fB%i\fR conversion instead):
|
||||
.PP
|
||||
.CS
|
||||
set string "08:08"
|
||||
set string "08:08" ;# *Not* octal!
|
||||
if {[\fBscan\fR $string "%d:%d" hours minutes] != 2} {
|
||||
error "not a valid time string"
|
||||
}
|
||||
|
||||
+5
-3
@@ -115,7 +115,9 @@ Any Unicode control character.
|
||||
Any Unicode digit character. Note that this includes characters
|
||||
outside of the [0\-9] range.
|
||||
.IP \fBdouble\fR 12
|
||||
Any of the forms allowed to \fBTcl_GetDoubleFromObj\fR.
|
||||
Any of the valid forms for a double in Tcl, with optional surrounding
|
||||
whitespace. In case of under/overflow in the value, 0 is returned and
|
||||
the \fIvarname\fR will contain \-1.
|
||||
.IP \fBentier\fR 12
|
||||
.VS 8.6
|
||||
Any of the valid string formats for an integer value of arbitrary size
|
||||
@@ -129,7 +131,7 @@ false.
|
||||
Any Unicode printing character, except space.
|
||||
.IP \fBinteger\fR 12
|
||||
Any of the valid string formats for a 32-bit integer value in Tcl,
|
||||
with optional surrounding whitespace. In case of overflow in
|
||||
with optional surrounding whitespace. In case of under/overflow in
|
||||
the value, 0 is returned and the \fIvarname\fR will contain \-1.
|
||||
.IP \fBlist\fR 12
|
||||
Any proper list structure, with optional surrounding whitespace. In
|
||||
@@ -154,7 +156,7 @@ true.
|
||||
Any upper case alphabet character in the Unicode character set.
|
||||
.IP \fBwideinteger\fR 12
|
||||
Any of the valid forms for a wide integer in Tcl, with optional
|
||||
surrounding whitespace. In case of overflow in the value, 0 is
|
||||
surrounding whitespace. In case of under/overflow in the value, 0 is
|
||||
returned and the \fIvarname\fR will contain \-1.
|
||||
.IP \fBwordchar\fR 12
|
||||
Any Unicode word character. That is any alphanumeric character, and
|
||||
|
||||
+65
-1
@@ -10,7 +10,7 @@
|
||||
.BS
|
||||
'\" Note: do not modify the .SH NAME line immediately below!
|
||||
.SH NAME
|
||||
argc, argv, argv0, auto_path, env, errorCode, errorInfo, tcl_interactive, tcl_library, tcl_nonwordchars, tcl_patchLevel, tcl_pkgPath, tcl_platform, tcl_rcFileName, tcl_traceCompile, tcl_traceExec, tcl_wordchars, tcl_version \- Variables used by Tcl
|
||||
argc, argv, argv0, auto_path, env, errorCode, errorInfo, tcl_interactive, tcl_library, tcl_nonwordchars, tcl_patchLevel, tcl_pkgPath, tcl_platform, tcl_precision, tcl_rcFileName, tcl_traceCompile, tcl_traceExec, tcl_wordchars, tcl_version \- Variables used by Tcl
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
@@ -356,6 +356,70 @@ This gives the size of the native-machine word in bytes (strictly, it
|
||||
is same as the result of evaluating \fIsizeof(long)\fR in C.)
|
||||
.RE
|
||||
.TP
|
||||
\fBtcl_precision\fR
|
||||
.
|
||||
This variable controls the number of digits to generate
|
||||
when converting floating-point values to strings. It defaults
|
||||
to 0. \fIApplications should not change this value;\fR it is
|
||||
provided for compatibility with legacy code.
|
||||
.PP
|
||||
.RS
|
||||
The default value of 0 is special, meaning that Tcl should
|
||||
convert numbers using as few digits as possible while still
|
||||
distinguishing any floating point number from its nearest
|
||||
neighbours. It differs from using an arbitrarily high value
|
||||
for \fItcl_precision\fR in that an inexact number like \fI1.4\fR
|
||||
will convert as \fI1.4\fR rather than \fI1.3999999999999999\fR
|
||||
even though the latter is nearer to the exact value of the
|
||||
binary number.
|
||||
.RE
|
||||
.PP
|
||||
.RS
|
||||
If \fBtcl_precision\fR is not zero, then when Tcl converts a floating
|
||||
point number, it creates a decimal representation of at most
|
||||
\fBtcl_precision\fR significant digits; the result may be shorter if
|
||||
the shorter result represents the original number exactly. If no
|
||||
result of at most \fBtcl_precision\fR digits is an exact representation
|
||||
of the original number, the one that is closest to the original
|
||||
number is chosen.
|
||||
If the original number lies precisely between two equally accurate
|
||||
decimal representations, then the one with an even value for the least
|
||||
significant digit is chosen; for instance, if \fBtcl_precision\fR is 3, then
|
||||
0.3125 will convert to 0.312, not 0.313, while 0.6875 will convert to
|
||||
0.688, not 0.687. Any string of trailing zeroes that remains is trimmed.
|
||||
.RE
|
||||
.PP
|
||||
.RS
|
||||
a \fBtcl_precision\fR value of 17 digits is
|
||||
.QW perfect
|
||||
for IEEE floating-point in that it allows
|
||||
double-precision values to be converted to strings and back to
|
||||
binary with no loss of information. For this reason, you will often
|
||||
see it as a value in legacy code that must run on Tcl versions before
|
||||
8.5. It is no longer recommended; as noted above, a zero value is the
|
||||
preferred method.
|
||||
.RE
|
||||
.PP
|
||||
.RS
|
||||
All interpreters in a thread share a single \fBtcl_precision\fR value:
|
||||
changing it in one interpreter will affect all other interpreters as
|
||||
well. Safe interpreters are not allowed to modify the
|
||||
variable.
|
||||
.RE
|
||||
.PP
|
||||
.RS
|
||||
Valid values for \fBtcl_precision\fR range from 0 to 17.
|
||||
.RE
|
||||
.TP
|
||||
\fBtcl_rcFileName\fR
|
||||
.
|
||||
This variable is used during initialization to indicate the name of a
|
||||
user-specific startup file. If it is set by application-specific
|
||||
initialization, then the Tcl startup code will check for the existence
|
||||
of this file and \fBsource\fR it if it exists. For example, for \fBwish\fR
|
||||
the variable is set to \fB~/.wishrc\fR for Unix and \fB~/wishrc.tcl\fR
|
||||
for Windows.
|
||||
.TP
|
||||
\fBtcl_traceCompile\fR
|
||||
.
|
||||
The value of this variable can be set to control
|
||||
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
'\"
|
||||
'\" Copyright (c) 2005 Sergey Brester aka sebres.
|
||||
'\"
|
||||
'\" See the file "license.terms" for information on usage and redistribution
|
||||
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
'\"
|
||||
.TH timerate n "" Tcl "Tcl Built-In Commands"
|
||||
.so man.macros
|
||||
.BS
|
||||
'\" Note: do not modify the .SH NAME line immediately below!
|
||||
.SH NAME
|
||||
timerate \- Time-related execution resp. performance measurement of a script
|
||||
.SH SYNOPSIS
|
||||
\fBtimerate \fIscript\fR \fI?time?\fR
|
||||
.sp
|
||||
\fBtimerate \fI?-direct?\fR \fI?-overhead double?\fR \fIscript\fR \fI?time?\fR
|
||||
.sp
|
||||
\fBtimerate \fI?-calibrate?\fR \fI?-direct?\fR \fIscript\fR \fI?time?\fR
|
||||
.BE
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
The first and second form will evaluate \fIscript\fR until the interval
|
||||
\fItime\fR given in milliseconds elapses, or for 1000 milliseconds (1 second)
|
||||
if \fItime\fR is not specified.
|
||||
.sp
|
||||
It will then return a canonical tcl-list of the form
|
||||
.PP
|
||||
.CS
|
||||
\f0.095977 µs/# 52095836 # 10419167 #/sec 5000.000 nett-ms\fR
|
||||
.CE
|
||||
.PP
|
||||
which indicates:
|
||||
.IP \(bu
|
||||
the average amount of time required per iteration, in microseconds (lindex $result 0)
|
||||
.IP \(bu
|
||||
the count how many times it was executed (lindex $result 2)
|
||||
.IP \(bu
|
||||
the estimated rate per second (lindex $result 4)
|
||||
.IP \(bu
|
||||
the estimated real execution time without measurement overhead (lindex $result 6)
|
||||
.PP
|
||||
Time is measured in elapsed time using heighest timer resolution as possible, not CPU time.
|
||||
This command may be used to provide information as to how well the script or a tcl-command
|
||||
is performing and can help determine bottlenecks and fine-tune application performance.
|
||||
.PP
|
||||
\fI-calibrate\fR
|
||||
.
|
||||
To measure very fast scripts as exact as posible the calibration process
|
||||
may be required.
|
||||
|
||||
This parameter used to calibrate \fBtimerate\fR calculating the estimated overhead
|
||||
of given \fIscript\fR as default overhead for further execution of \fBtimerate\fR.
|
||||
It can take up to 10 seconds if parameter \fItime\fR is not specified.
|
||||
.PP
|
||||
\fI-overhead double\fR
|
||||
.
|
||||
This parameter used to supply the measurement overhead of single iteration
|
||||
(in microseconds) that should be ignored during whole evaluation process.
|
||||
.PP
|
||||
\fI-direct\fR
|
||||
.
|
||||
Causes direct execution per iteration (not compiled variant of evaluation used).
|
||||
.PP
|
||||
In opposition to \fBtime\fR the execution limited here by fixed time instead of
|
||||
repetition count.
|
||||
Additionally the compiled variant of the script will be used during whole evaluation
|
||||
(as if it were part of a compiled \fBproc\fR), if parameter \fI-direct\fR is not specified.
|
||||
Therefore it provides more precise results and prevents very long execution time
|
||||
by slow scripts resp. scripts with unknown speed.
|
||||
|
||||
.SH EXAMPLE
|
||||
Estimate how fast it takes for a simple Tcl \fBfor\fR loop (including
|
||||
operations on variable \fIi\fR) to count to a ten:
|
||||
.PP
|
||||
.CS
|
||||
# calibrate:
|
||||
timerate -calibrate {}
|
||||
# measure:
|
||||
timerate { for {set i 0} {$i<10} {incr i} {} } 5000
|
||||
.CE
|
||||
.PP
|
||||
Estimate how fast it takes for a simple Tcl \fBfor\fR loop only (ignoring the
|
||||
overhead for operations on variable \fIi\fR) to count to a ten:
|
||||
.PP
|
||||
.CS
|
||||
# calibrate for overhead of variable operations:
|
||||
set i 0; timerate -calibrate {expr {$i<10}; incr i} 1000
|
||||
# measure:
|
||||
timerate { for {set i 0} {$i<10} {incr i} {} } 5000
|
||||
.CE
|
||||
.PP
|
||||
Estimate the rate of calculating the hour using \fBclock format\fR only, ignoring
|
||||
overhead of the rest, without measurement how fast it takes for a whole script:
|
||||
.PP
|
||||
.CS
|
||||
# calibrate:
|
||||
timerate -calibrate {}
|
||||
# estimate overhead:
|
||||
set tm 0
|
||||
set ovh [lindex [timerate { incr tm [expr {24*60*60}] }] 0]
|
||||
# measure using esimated overhead:
|
||||
set tm 0
|
||||
timerate -overhead $ovh {
|
||||
clock format $tm -format %H
|
||||
incr tm [expr {24*60*60}]; # overhead for this is ignored
|
||||
} 5000
|
||||
.CE
|
||||
.SH "SEE ALSO"
|
||||
time(n)
|
||||
.SH KEYWORDS
|
||||
script, timerate, time
|
||||
.\" Local Variables:
|
||||
.\" mode: nroff
|
||||
.\" End:
|
||||
+5888
-317
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -91,7 +91,7 @@ typedef int celt; /* Type to hold chr, or NOCELT */
|
||||
#if TCL_UTF_MAX > 4
|
||||
#define CHRBITS 32 /* Bits in a chr; must not use sizeof */
|
||||
#define CHR_MIN 0x00000000 /* Smallest and largest chr; the value */
|
||||
#define CHR_MAX 0x10ffff /* CHR_MAX-CHR_MIN+1 should fit in uchr */
|
||||
#define CHR_MAX 0xffffffff /* CHR_MAX-CHR_MIN+1 should fit in uchr */
|
||||
#else
|
||||
#define CHRBITS 16 /* Bits in a chr; must not use sizeof */
|
||||
#define CHR_MIN 0x0000 /* Smallest and largest chr; the value */
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
*/
|
||||
|
||||
#define NOTREACHED 0
|
||||
#define xxx 1
|
||||
|
||||
#define DUPMAX _POSIX2_RE_DUP_MAX
|
||||
#define DUPINF (DUPMAX+1)
|
||||
|
||||
+141
-161
@@ -32,7 +32,7 @@ declare 0 {
|
||||
const char *version, const void *clientData)
|
||||
}
|
||||
declare 1 {
|
||||
const char *Tcl_PkgRequireEx(Tcl_Interp *interp,
|
||||
CONST84_RETURN char *Tcl_PkgRequireEx(Tcl_Interp *interp,
|
||||
const char *name, const char *version, int exact,
|
||||
void *clientDataPtr)
|
||||
}
|
||||
@@ -104,10 +104,9 @@ declare 20 {
|
||||
declare 21 {
|
||||
int Tcl_DbIsShared(Tcl_Obj *objPtr, const char *file, int line)
|
||||
}
|
||||
# Removed in 9.0 (changed to macro):
|
||||
#declare 22 {
|
||||
# Tcl_Obj *Tcl_DbNewBooleanObj(int boolValue, const char *file, int line)
|
||||
#}
|
||||
declare 22 {
|
||||
Tcl_Obj *Tcl_DbNewBooleanObj(int boolValue, const char *file, int line)
|
||||
}
|
||||
declare 23 {
|
||||
Tcl_Obj *Tcl_DbNewByteArrayObj(const unsigned char *bytes, int length,
|
||||
const char *file, int line)
|
||||
@@ -120,10 +119,9 @@ declare 25 {
|
||||
Tcl_Obj *Tcl_DbNewListObj(int objc, Tcl_Obj *const *objv,
|
||||
const char *file, int line)
|
||||
}
|
||||
# Removed in 9.0 (changed to macro):
|
||||
#declare 26 {
|
||||
# Tcl_Obj *Tcl_DbNewLongObj(long longValue, const char *file, int line)
|
||||
#}
|
||||
declare 26 {
|
||||
Tcl_Obj *Tcl_DbNewLongObj(long longValue, const char *file, int line)
|
||||
}
|
||||
declare 27 {
|
||||
Tcl_Obj *Tcl_DbNewObj(const char *file, int line)
|
||||
}
|
||||
@@ -156,7 +154,7 @@ declare 35 {
|
||||
}
|
||||
declare 36 {
|
||||
int Tcl_GetIndexFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
|
||||
const char *const *tablePtr, const char *msg, int flags, int *indexPtr)
|
||||
CONST84 char *const *tablePtr, const char *msg, int flags, int *indexPtr)
|
||||
}
|
||||
declare 37 {
|
||||
int Tcl_GetInt(Tcl_Interp *interp, const char *src, int *intPtr)
|
||||
@@ -168,7 +166,7 @@ declare 39 {
|
||||
int Tcl_GetLongFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, long *longPtr)
|
||||
}
|
||||
declare 40 {
|
||||
const Tcl_ObjType *Tcl_GetObjType(const char *typeName)
|
||||
CONST86 Tcl_ObjType *Tcl_GetObjType(const char *typeName)
|
||||
}
|
||||
declare 41 {
|
||||
char *Tcl_GetStringFromObj(Tcl_Obj *objPtr, int *lengthPtr)
|
||||
@@ -200,37 +198,33 @@ declare 48 {
|
||||
int Tcl_ListObjReplace(Tcl_Interp *interp, Tcl_Obj *listPtr, int first,
|
||||
int count, int objc, Tcl_Obj *const objv[])
|
||||
}
|
||||
# Removed in 9.0 (changed to macro):
|
||||
#declare 49 {
|
||||
# Tcl_Obj *Tcl_NewBooleanObj(int boolValue)
|
||||
#}
|
||||
declare 49 {
|
||||
Tcl_Obj *Tcl_NewBooleanObj(int boolValue)
|
||||
}
|
||||
declare 50 {
|
||||
Tcl_Obj *Tcl_NewByteArrayObj(const unsigned char *bytes, int length)
|
||||
}
|
||||
declare 51 {
|
||||
Tcl_Obj *Tcl_NewDoubleObj(double doubleValue)
|
||||
}
|
||||
# Removed in 9.0 (changed to macro):
|
||||
#declare 52 {
|
||||
# Tcl_Obj *Tcl_NewIntObj(int intValue)
|
||||
#}
|
||||
declare 52 {
|
||||
Tcl_Obj *Tcl_NewIntObj(int intValue)
|
||||
}
|
||||
declare 53 {
|
||||
Tcl_Obj *Tcl_NewListObj(int objc, Tcl_Obj *const objv[])
|
||||
}
|
||||
# Removed in 9.0 (changed to macro):
|
||||
#declare 54 {
|
||||
# Tcl_Obj *Tcl_NewLongObj(long longValue)
|
||||
#}
|
||||
declare 54 {
|
||||
Tcl_Obj *Tcl_NewLongObj(long longValue)
|
||||
}
|
||||
declare 55 {
|
||||
Tcl_Obj *Tcl_NewObj(void)
|
||||
}
|
||||
declare 56 {
|
||||
Tcl_Obj *Tcl_NewStringObj(const char *bytes, int length)
|
||||
}
|
||||
# Removed in 9.0 (changed to macro):
|
||||
#declare 57 {
|
||||
# void Tcl_SetBooleanObj(Tcl_Obj *objPtr, int boolValue)
|
||||
#}
|
||||
declare 57 {
|
||||
void Tcl_SetBooleanObj(Tcl_Obj *objPtr, int boolValue)
|
||||
}
|
||||
declare 58 {
|
||||
unsigned char *Tcl_SetByteArrayLength(Tcl_Obj *objPtr, int length)
|
||||
}
|
||||
@@ -241,17 +235,15 @@ declare 59 {
|
||||
declare 60 {
|
||||
void Tcl_SetDoubleObj(Tcl_Obj *objPtr, double doubleValue)
|
||||
}
|
||||
# Removed in 9.0 (changed to macro):
|
||||
#declare 61 {
|
||||
# void Tcl_SetIntObj(Tcl_Obj *objPtr, int intValue)
|
||||
#}
|
||||
declare 61 {
|
||||
void Tcl_SetIntObj(Tcl_Obj *objPtr, int intValue)
|
||||
}
|
||||
declare 62 {
|
||||
void Tcl_SetListObj(Tcl_Obj *objPtr, int objc, Tcl_Obj *const objv[])
|
||||
}
|
||||
# Removed in 9.0 (changed to macro):
|
||||
#declare 63 {
|
||||
# void Tcl_SetLongObj(Tcl_Obj *objPtr, long longValue)
|
||||
#}
|
||||
declare 63 {
|
||||
void Tcl_SetLongObj(Tcl_Obj *objPtr, long longValue)
|
||||
}
|
||||
declare 64 {
|
||||
void Tcl_SetObjLength(Tcl_Obj *objPtr, int length)
|
||||
}
|
||||
@@ -293,10 +285,9 @@ declare 75 {
|
||||
declare 76 {
|
||||
void Tcl_BackgroundError(Tcl_Interp *interp)
|
||||
}
|
||||
# Removed in 9.0:
|
||||
#declare 77 {deprecated {Use Tcl_UtfBackslash}} {
|
||||
# char Tcl_Backslash(const char *src, int *readPtr)
|
||||
#}
|
||||
declare 77 {
|
||||
char Tcl_Backslash(const char *src, int *readPtr)
|
||||
}
|
||||
declare 78 {
|
||||
int Tcl_BadChannelOption(Tcl_Interp *interp, const char *optionName,
|
||||
const char *optionList)
|
||||
@@ -315,7 +306,7 @@ declare 82 {
|
||||
int Tcl_CommandComplete(const char *cmd)
|
||||
}
|
||||
declare 83 {
|
||||
char *Tcl_Concat(int argc, const char *const *argv)
|
||||
char *Tcl_Concat(int argc, CONST84 char *const *argv)
|
||||
}
|
||||
declare 84 {
|
||||
int Tcl_ConvertElement(const char *src, char *dst, int flags)
|
||||
@@ -327,7 +318,7 @@ declare 85 {
|
||||
declare 86 {
|
||||
int Tcl_CreateAlias(Tcl_Interp *slave, const char *slaveCmd,
|
||||
Tcl_Interp *target, const char *targetCmd, int argc,
|
||||
const char *const *argv)
|
||||
CONST84 char *const *argv)
|
||||
}
|
||||
declare 87 {
|
||||
int Tcl_CreateAliasObj(Tcl_Interp *slave, const char *slaveCmd,
|
||||
@@ -361,12 +352,11 @@ declare 93 {
|
||||
declare 94 {
|
||||
Tcl_Interp *Tcl_CreateInterp(void)
|
||||
}
|
||||
# Removed in 9.0:
|
||||
#declare 95 {deprecated {}} {
|
||||
# void Tcl_CreateMathFunc(Tcl_Interp *interp, const char *name,
|
||||
# int numArgs, Tcl_ValueType *argTypes,
|
||||
# Tcl_MathProc *proc, ClientData clientData)
|
||||
#}
|
||||
declare 95 {
|
||||
void Tcl_CreateMathFunc(Tcl_Interp *interp, const char *name,
|
||||
int numArgs, Tcl_ValueType *argTypes,
|
||||
Tcl_MathProc *proc, ClientData clientData)
|
||||
}
|
||||
declare 96 {
|
||||
Tcl_Command Tcl_CreateObjCommand(Tcl_Interp *interp,
|
||||
const char *cmdName,
|
||||
@@ -471,21 +461,21 @@ declare 126 {
|
||||
int Tcl_Eof(Tcl_Channel chan)
|
||||
}
|
||||
declare 127 {
|
||||
const char *Tcl_ErrnoId(void)
|
||||
CONST84_RETURN char *Tcl_ErrnoId(void)
|
||||
}
|
||||
declare 128 {
|
||||
const char *Tcl_ErrnoMsg(int err)
|
||||
CONST84_RETURN char *Tcl_ErrnoMsg(int err)
|
||||
}
|
||||
declare 129 {
|
||||
int Tcl_Eval(Tcl_Interp *interp, const char *script)
|
||||
}
|
||||
# This is obsolete, use Tcl_FSEvalFile
|
||||
declare 130 {
|
||||
int Tcl_EvalFile(Tcl_Interp *interp, const char *fileName)
|
||||
}
|
||||
# Removed in 9.0, replaced by macro.
|
||||
#declare 131 {
|
||||
# int Tcl_EvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr)
|
||||
#}
|
||||
declare 131 {
|
||||
int Tcl_EvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr)
|
||||
}
|
||||
declare 132 {
|
||||
void Tcl_EventuallyFree(ClientData clientData, Tcl_FreeProc *freeProc)
|
||||
}
|
||||
@@ -539,12 +529,12 @@ declare 147 {
|
||||
}
|
||||
declare 148 {
|
||||
int Tcl_GetAlias(Tcl_Interp *interp, const char *slaveCmd,
|
||||
Tcl_Interp **targetInterpPtr, const char **targetCmdPtr,
|
||||
int *argcPtr, const char ***argvPtr)
|
||||
Tcl_Interp **targetInterpPtr, CONST84 char **targetCmdPtr,
|
||||
int *argcPtr, CONST84 char ***argvPtr)
|
||||
}
|
||||
declare 149 {
|
||||
int Tcl_GetAliasObj(Tcl_Interp *interp, const char *slaveCmd,
|
||||
Tcl_Interp **targetInterpPtr, const char **targetCmdPtr,
|
||||
Tcl_Interp **targetInterpPtr, CONST84 char **targetCmdPtr,
|
||||
int *objcPtr, Tcl_Obj ***objv)
|
||||
}
|
||||
declare 150 {
|
||||
@@ -569,28 +559,28 @@ declare 155 {
|
||||
int Tcl_GetChannelMode(Tcl_Channel chan)
|
||||
}
|
||||
declare 156 {
|
||||
const char *Tcl_GetChannelName(Tcl_Channel chan)
|
||||
CONST84_RETURN char *Tcl_GetChannelName(Tcl_Channel chan)
|
||||
}
|
||||
declare 157 {
|
||||
int Tcl_GetChannelOption(Tcl_Interp *interp, Tcl_Channel chan,
|
||||
const char *optionName, Tcl_DString *dsPtr)
|
||||
}
|
||||
declare 158 {
|
||||
const Tcl_ChannelType *Tcl_GetChannelType(Tcl_Channel chan)
|
||||
CONST86 Tcl_ChannelType *Tcl_GetChannelType(Tcl_Channel chan)
|
||||
}
|
||||
declare 159 {
|
||||
int Tcl_GetCommandInfo(Tcl_Interp *interp, const char *cmdName,
|
||||
Tcl_CmdInfo *infoPtr)
|
||||
}
|
||||
declare 160 {
|
||||
const char *Tcl_GetCommandName(Tcl_Interp *interp,
|
||||
CONST84_RETURN char *Tcl_GetCommandName(Tcl_Interp *interp,
|
||||
Tcl_Command command)
|
||||
}
|
||||
declare 161 {
|
||||
int Tcl_GetErrno(void)
|
||||
}
|
||||
declare 162 {
|
||||
const char *Tcl_GetHostName(void)
|
||||
CONST84_RETURN char *Tcl_GetHostName(void)
|
||||
}
|
||||
declare 163 {
|
||||
int Tcl_GetInterpPath(Tcl_Interp *askInterp, Tcl_Interp *slaveInterp)
|
||||
@@ -633,23 +623,22 @@ declare 173 {
|
||||
Tcl_Channel Tcl_GetStdChannel(int type)
|
||||
}
|
||||
declare 174 {
|
||||
const char *Tcl_GetStringResult(Tcl_Interp *interp)
|
||||
CONST84_RETURN char *Tcl_GetStringResult(Tcl_Interp *interp)
|
||||
}
|
||||
declare 175 {
|
||||
const char *Tcl_GetVar(Tcl_Interp *interp, const char *varName,
|
||||
CONST84_RETURN char *Tcl_GetVar(Tcl_Interp *interp, const char *varName,
|
||||
int flags)
|
||||
}
|
||||
declare 176 {
|
||||
const char *Tcl_GetVar2(Tcl_Interp *interp, const char *part1,
|
||||
CONST84_RETURN char *Tcl_GetVar2(Tcl_Interp *interp, const char *part1,
|
||||
const char *part2, int flags)
|
||||
}
|
||||
declare 177 {
|
||||
int Tcl_GlobalEval(Tcl_Interp *interp, const char *command)
|
||||
}
|
||||
# Removed in 9.0, replaced by macro.
|
||||
#declare 178 {
|
||||
# int Tcl_GlobalEvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr)
|
||||
#}
|
||||
declare 178 {
|
||||
int Tcl_GlobalEvalObj(Tcl_Interp *interp, Tcl_Obj *objPtr)
|
||||
}
|
||||
declare 179 {
|
||||
int Tcl_HideCommand(Tcl_Interp *interp, const char *cmdName,
|
||||
const char *hiddenCmdToken)
|
||||
@@ -674,7 +663,7 @@ declare 185 {
|
||||
}
|
||||
# Obsolete, use Tcl_FSJoinPath
|
||||
declare 186 {
|
||||
char *Tcl_JoinPath(int argc, const char *const *argv,
|
||||
char *Tcl_JoinPath(int argc, CONST84 char *const *argv,
|
||||
Tcl_DString *resultPtr)
|
||||
}
|
||||
declare 187 {
|
||||
@@ -697,7 +686,7 @@ declare 191 {
|
||||
Tcl_Channel Tcl_MakeTcpClientChannel(ClientData tcpSocket)
|
||||
}
|
||||
declare 192 {
|
||||
char *Tcl_Merge(int argc, const char *const *argv)
|
||||
char *Tcl_Merge(int argc, CONST84 char *const *argv)
|
||||
}
|
||||
declare 193 {
|
||||
Tcl_HashEntry *Tcl_NextHashEntry(Tcl_HashSearch *searchPtr)
|
||||
@@ -715,7 +704,7 @@ declare 196 {
|
||||
}
|
||||
declare 197 {
|
||||
Tcl_Channel Tcl_OpenCommandChannel(Tcl_Interp *interp, int argc,
|
||||
const char **argv, int flags)
|
||||
CONST84 char **argv, int flags)
|
||||
}
|
||||
# This is obsolete, use Tcl_FSOpenFileChannel
|
||||
declare 198 {
|
||||
@@ -741,7 +730,7 @@ declare 203 {
|
||||
int Tcl_PutEnv(const char *assignment)
|
||||
}
|
||||
declare 204 {
|
||||
const char *Tcl_PosixError(Tcl_Interp *interp)
|
||||
CONST84_RETURN char *Tcl_PosixError(Tcl_Interp *interp)
|
||||
}
|
||||
declare 205 {
|
||||
void Tcl_QueueEvent(Tcl_Event *evPtr, Tcl_QueuePosition position)
|
||||
@@ -759,7 +748,7 @@ declare 209 {
|
||||
int Tcl_RecordAndEvalObj(Tcl_Interp *interp, Tcl_Obj *cmdPtr, int flags)
|
||||
}
|
||||
declare 210 {
|
||||
void Tcl_RegisterChannel(Tcl_Interp *interp, Tcl_Channel chan)
|
||||
Tcl_Channel Tcl_RegisterChannel(Tcl_Interp *interp, Tcl_Channel chan)
|
||||
}
|
||||
declare 211 {
|
||||
void Tcl_RegisterObjType(const Tcl_ObjType *typePtr)
|
||||
@@ -777,7 +766,7 @@ declare 214 {
|
||||
}
|
||||
declare 215 {
|
||||
void Tcl_RegExpRange(Tcl_RegExp regexp, int index,
|
||||
const char **startPtr, const char **endPtr)
|
||||
CONST84 char **startPtr, CONST84 char **endPtr)
|
||||
}
|
||||
declare 216 {
|
||||
void Tcl_Release(ClientData clientData)
|
||||
@@ -791,10 +780,10 @@ declare 218 {
|
||||
declare 219 {
|
||||
int Tcl_ScanCountedElement(const char *src, int length, int *flagPtr)
|
||||
}
|
||||
# Removed in 9.0:
|
||||
#declare 220 {
|
||||
# int Tcl_SeekOld(Tcl_Channel chan, int offset, int mode)
|
||||
#}
|
||||
# Obsolete
|
||||
declare 220 {
|
||||
int Tcl_SeekOld(Tcl_Channel chan, int offset, int mode)
|
||||
}
|
||||
declare 221 {
|
||||
int Tcl_ServiceAll(void)
|
||||
}
|
||||
@@ -848,29 +837,29 @@ declare 236 {
|
||||
void Tcl_SetStdChannel(Tcl_Channel channel, int type)
|
||||
}
|
||||
declare 237 {
|
||||
const char *Tcl_SetVar(Tcl_Interp *interp, const char *varName,
|
||||
CONST84_RETURN char *Tcl_SetVar(Tcl_Interp *interp, const char *varName,
|
||||
const char *newValue, int flags)
|
||||
}
|
||||
declare 238 {
|
||||
const char *Tcl_SetVar2(Tcl_Interp *interp, const char *part1,
|
||||
CONST84_RETURN char *Tcl_SetVar2(Tcl_Interp *interp, const char *part1,
|
||||
const char *part2, const char *newValue, int flags)
|
||||
}
|
||||
declare 239 {
|
||||
const char *Tcl_SignalId(int sig)
|
||||
CONST84_RETURN char *Tcl_SignalId(int sig)
|
||||
}
|
||||
declare 240 {
|
||||
const char *Tcl_SignalMsg(int sig)
|
||||
CONST84_RETURN char *Tcl_SignalMsg(int sig)
|
||||
}
|
||||
declare 241 {
|
||||
void Tcl_SourceRCFile(Tcl_Interp *interp)
|
||||
}
|
||||
declare 242 {
|
||||
int Tcl_SplitList(Tcl_Interp *interp, const char *listStr, int *argcPtr,
|
||||
const char ***argvPtr)
|
||||
CONST84 char ***argvPtr)
|
||||
}
|
||||
# Obsolete, use Tcl_FSSplitPath
|
||||
declare 243 {
|
||||
void Tcl_SplitPath(const char *path, int *argcPtr, const char ***argvPtr)
|
||||
void Tcl_SplitPath(const char *path, int *argcPtr, CONST84 char ***argvPtr)
|
||||
}
|
||||
declare 244 {
|
||||
void Tcl_StaticPackage(Tcl_Interp *interp, const char *pkgName,
|
||||
@@ -879,10 +868,10 @@ declare 244 {
|
||||
declare 245 {
|
||||
int Tcl_StringMatch(const char *str, const char *pattern)
|
||||
}
|
||||
# Removed in 9.0:
|
||||
#declare 246 {
|
||||
# int Tcl_TellOld(Tcl_Channel chan)
|
||||
#}
|
||||
# Obsolete
|
||||
declare 246 {
|
||||
int Tcl_TellOld(Tcl_Channel chan)
|
||||
}
|
||||
declare 247 {
|
||||
int Tcl_TraceVar(Tcl_Interp *interp, const char *varName, int flags,
|
||||
Tcl_VarTraceProc *proc, ClientData clientData)
|
||||
@@ -947,7 +936,7 @@ declare 263 {
|
||||
int Tcl_Write(Tcl_Channel chan, const char *s, int slen)
|
||||
}
|
||||
declare 264 {
|
||||
void Tcl_WrongNumArgs(Tcl_Interp *interp, int objc,
|
||||
int Tcl_WrongNumArgs(Tcl_Interp *interp, int objc,
|
||||
Tcl_Obj *const objv[], const char *message)
|
||||
}
|
||||
declare 265 {
|
||||
@@ -956,27 +945,25 @@ declare 265 {
|
||||
declare 266 {
|
||||
void Tcl_ValidateAllMemory(const char *file, int line)
|
||||
}
|
||||
# Removed in 9.0:
|
||||
#declare 267 {
|
||||
# void Tcl_AppendResultVA(Tcl_Interp *interp, va_list argList)
|
||||
#}
|
||||
# Removed in 9.0:
|
||||
#declare 268 {
|
||||
# void Tcl_AppendStringsToObjVA(Tcl_Obj *objPtr, va_list argList)
|
||||
#}
|
||||
declare 267 {
|
||||
void Tcl_AppendResultVA(Tcl_Interp *interp, va_list argList)
|
||||
}
|
||||
declare 268 {
|
||||
void Tcl_AppendStringsToObjVA(Tcl_Obj *objPtr, va_list argList)
|
||||
}
|
||||
declare 269 {
|
||||
char *Tcl_HashStats(Tcl_HashTable *tablePtr)
|
||||
}
|
||||
declare 270 {
|
||||
const char *Tcl_ParseVar(Tcl_Interp *interp, const char *start,
|
||||
const char **termPtr)
|
||||
CONST84_RETURN char *Tcl_ParseVar(Tcl_Interp *interp, const char *start,
|
||||
CONST84 char **termPtr)
|
||||
}
|
||||
declare 271 {
|
||||
const char *Tcl_PkgPresent(Tcl_Interp *interp, const char *name,
|
||||
CONST84_RETURN char *Tcl_PkgPresent(Tcl_Interp *interp, const char *name,
|
||||
const char *version, int exact)
|
||||
}
|
||||
declare 272 {
|
||||
const char *Tcl_PkgPresentEx(Tcl_Interp *interp,
|
||||
CONST84_RETURN char *Tcl_PkgPresentEx(Tcl_Interp *interp,
|
||||
const char *name, const char *version, int exact,
|
||||
void *clientDataPtr)
|
||||
}
|
||||
@@ -986,24 +973,21 @@ declare 273 {
|
||||
}
|
||||
# TIP #268: The internally used new Require function is in slot 573.
|
||||
declare 274 {
|
||||
const char *Tcl_PkgRequire(Tcl_Interp *interp, const char *name,
|
||||
CONST84_RETURN char *Tcl_PkgRequire(Tcl_Interp *interp, const char *name,
|
||||
const char *version, int exact)
|
||||
}
|
||||
# Removed in 9.0:
|
||||
#declare 275 {
|
||||
# void Tcl_SetErrorCodeVA(Tcl_Interp *interp, va_list argList)
|
||||
#}
|
||||
# Removed in 9.0:
|
||||
#declare 276 {
|
||||
# int Tcl_VarEvalVA(Tcl_Interp *interp, va_list argList)
|
||||
#}
|
||||
declare 275 {
|
||||
void Tcl_SetErrorCodeVA(Tcl_Interp *interp, va_list argList)
|
||||
}
|
||||
declare 276 {
|
||||
int Tcl_VarEvalVA(Tcl_Interp *interp, va_list argList)
|
||||
}
|
||||
declare 277 {
|
||||
Tcl_Pid Tcl_WaitPid(Tcl_Pid pid, int *statPtr, int options)
|
||||
}
|
||||
# Removed in 9.0:
|
||||
#declare 278 {
|
||||
# TCL_NORETURN void Tcl_PanicVA(const char *format, va_list argList)
|
||||
#}
|
||||
declare 278 {
|
||||
TCL_NORETURN void Tcl_PanicVA(const char *format, va_list argList)
|
||||
}
|
||||
declare 279 {
|
||||
void Tcl_GetVersion(int *major, int *minor, int *patchLevel, int *type)
|
||||
}
|
||||
@@ -1103,7 +1087,7 @@ declare 301 {
|
||||
Tcl_Encoding Tcl_GetEncoding(Tcl_Interp *interp, const char *name)
|
||||
}
|
||||
declare 302 {
|
||||
const char *Tcl_GetEncodingName(Tcl_Encoding encoding)
|
||||
CONST84_RETURN char *Tcl_GetEncodingName(Tcl_Encoding encoding)
|
||||
}
|
||||
declare 303 {
|
||||
void Tcl_GetEncodingNames(Tcl_Interp *interp)
|
||||
@@ -1164,22 +1148,22 @@ declare 319 {
|
||||
Tcl_QueuePosition position)
|
||||
}
|
||||
declare 320 {
|
||||
int Tcl_UniCharAtIndex(const char *src, int index)
|
||||
Tcl_UniChar Tcl_UniCharAtIndex(const char *src, int index)
|
||||
}
|
||||
declare 321 {
|
||||
int Tcl_UniCharToLower(int ch)
|
||||
Tcl_UniChar Tcl_UniCharToLower(int ch)
|
||||
}
|
||||
declare 322 {
|
||||
int Tcl_UniCharToTitle(int ch)
|
||||
Tcl_UniChar Tcl_UniCharToTitle(int ch)
|
||||
}
|
||||
declare 323 {
|
||||
int Tcl_UniCharToUpper(int ch)
|
||||
Tcl_UniChar Tcl_UniCharToUpper(int ch)
|
||||
}
|
||||
declare 324 {
|
||||
int Tcl_UniCharToUtf(int ch, char *buf)
|
||||
}
|
||||
declare 325 {
|
||||
const char *Tcl_UtfAtIndex(const char *src, int index)
|
||||
CONST84_RETURN char *Tcl_UtfAtIndex(const char *src, int index)
|
||||
}
|
||||
declare 326 {
|
||||
int Tcl_UtfCharComplete(const char *src, int length)
|
||||
@@ -1188,16 +1172,16 @@ declare 327 {
|
||||
int Tcl_UtfBackslash(const char *src, int *readPtr, char *dst)
|
||||
}
|
||||
declare 328 {
|
||||
const char *Tcl_UtfFindFirst(const char *src, int ch)
|
||||
CONST84_RETURN char *Tcl_UtfFindFirst(const char *src, int ch)
|
||||
}
|
||||
declare 329 {
|
||||
const char *Tcl_UtfFindLast(const char *src, int ch)
|
||||
CONST84_RETURN char *Tcl_UtfFindLast(const char *src, int ch)
|
||||
}
|
||||
declare 330 {
|
||||
const char *Tcl_UtfNext(const char *src)
|
||||
CONST84_RETURN char *Tcl_UtfNext(const char *src)
|
||||
}
|
||||
declare 331 {
|
||||
const char *Tcl_UtfPrev(const char *src, const char *start)
|
||||
CONST84_RETURN char *Tcl_UtfPrev(const char *src, const char *start)
|
||||
}
|
||||
declare 332 {
|
||||
int Tcl_UtfToExternal(Tcl_Interp *interp, Tcl_Encoding encoding,
|
||||
@@ -1230,14 +1214,12 @@ declare 339 {
|
||||
declare 340 {
|
||||
char *Tcl_GetString(Tcl_Obj *objPtr)
|
||||
}
|
||||
# Removed in 9.0:
|
||||
#declare 341 {deprecated {Use Tcl_GetEncodingSearchPath}} {
|
||||
# const char *Tcl_GetDefaultEncodingDir(void)
|
||||
#}
|
||||
# Removed in 9.0:
|
||||
#declare 342 {deprecated {Use Tcl_SetEncodingSearchPath}} {
|
||||
# void Tcl_SetDefaultEncodingDir(const char *path)
|
||||
#}
|
||||
declare 341 {
|
||||
CONST84_RETURN char *Tcl_GetDefaultEncodingDir(void)
|
||||
}
|
||||
declare 342 {
|
||||
void Tcl_SetDefaultEncodingDir(const char *path)
|
||||
}
|
||||
declare 343 {
|
||||
void Tcl_AlertNotifier(ClientData clientData)
|
||||
}
|
||||
@@ -1284,11 +1266,10 @@ declare 356 {
|
||||
Tcl_RegExp Tcl_GetRegExpFromObj(Tcl_Interp *interp, Tcl_Obj *patObj,
|
||||
int flags)
|
||||
}
|
||||
# Removed in 9.0:
|
||||
#declare 357 {deprecated {Use Tcl_EvalTokensStandard}} {
|
||||
# Tcl_Obj *Tcl_EvalTokens(Tcl_Interp *interp, Tcl_Token *tokenPtr,
|
||||
# int count)
|
||||
#}
|
||||
declare 357 {
|
||||
Tcl_Obj *Tcl_EvalTokens(Tcl_Interp *interp, Tcl_Token *tokenPtr,
|
||||
int count)
|
||||
}
|
||||
declare 358 {
|
||||
void Tcl_FreeParse(Tcl_Parse *parsePtr)
|
||||
}
|
||||
@@ -1298,7 +1279,7 @@ declare 359 {
|
||||
}
|
||||
declare 360 {
|
||||
int Tcl_ParseBraces(Tcl_Interp *interp, const char *start, int numBytes,
|
||||
Tcl_Parse *parsePtr, int append, const char **termPtr)
|
||||
Tcl_Parse *parsePtr, int append, CONST84 char **termPtr)
|
||||
}
|
||||
declare 361 {
|
||||
int Tcl_ParseCommand(Tcl_Interp *interp, const char *start, int numBytes,
|
||||
@@ -1311,7 +1292,7 @@ declare 362 {
|
||||
declare 363 {
|
||||
int Tcl_ParseQuotedString(Tcl_Interp *interp, const char *start,
|
||||
int numBytes, Tcl_Parse *parsePtr, int append,
|
||||
const char **termPtr)
|
||||
CONST84 char **termPtr)
|
||||
}
|
||||
declare 364 {
|
||||
int Tcl_ParseVarName(Tcl_Interp *interp, const char *start, int numBytes,
|
||||
@@ -1370,7 +1351,7 @@ declare 380 {
|
||||
int Tcl_GetCharLength(Tcl_Obj *objPtr)
|
||||
}
|
||||
declare 381 {
|
||||
int Tcl_GetUniChar(Tcl_Obj *objPtr, int index)
|
||||
Tcl_UniChar Tcl_GetUniChar(Tcl_Obj *objPtr, int index)
|
||||
}
|
||||
declare 382 {
|
||||
Tcl_UniChar *Tcl_GetUnicode(Tcl_Obj *objPtr)
|
||||
@@ -1427,7 +1408,7 @@ declare 397 {
|
||||
int Tcl_ChannelBuffered(Tcl_Channel chan)
|
||||
}
|
||||
declare 398 {
|
||||
const char *Tcl_ChannelName(const Tcl_ChannelType *chanTypePtr)
|
||||
CONST84_RETURN char *Tcl_ChannelName(const Tcl_ChannelType *chanTypePtr)
|
||||
}
|
||||
declare 399 {
|
||||
Tcl_ChannelTypeVersion Tcl_ChannelVersion(
|
||||
@@ -1512,15 +1493,13 @@ declare 420 {
|
||||
int Tcl_UniCharCaseMatch(const Tcl_UniChar *uniStr,
|
||||
const Tcl_UniChar *uniPattern, int nocase)
|
||||
}
|
||||
# Removed in 9.0, as it is actually a macro:
|
||||
#declare 421 {
|
||||
# Tcl_HashEntry *Tcl_FindHashEntry(Tcl_HashTable *tablePtr, const void *key)
|
||||
#}
|
||||
# Removed in 9.0, as it is actually a macro:
|
||||
#declare 422 {
|
||||
# Tcl_HashEntry *Tcl_CreateHashEntry(Tcl_HashTable *tablePtr,
|
||||
# const void *key, int *newPtr)
|
||||
#}
|
||||
declare 421 {
|
||||
Tcl_HashEntry *Tcl_FindHashEntry(Tcl_HashTable *tablePtr, const void *key)
|
||||
}
|
||||
declare 422 {
|
||||
Tcl_HashEntry *Tcl_CreateHashEntry(Tcl_HashTable *tablePtr,
|
||||
const void *key, int *newPtr)
|
||||
}
|
||||
declare 423 {
|
||||
void Tcl_InitCustomHashTable(Tcl_HashTable *tablePtr, int keyType,
|
||||
const Tcl_HashKeyType *typePtr)
|
||||
@@ -1569,16 +1548,14 @@ declare 434 {
|
||||
}
|
||||
|
||||
# TIP#15 (math function introspection) dkf
|
||||
# Removed in 9.0:
|
||||
#declare 435 {deprecated {}} {
|
||||
# int Tcl_GetMathFuncInfo(Tcl_Interp *interp, const char *name,
|
||||
# int *numArgsPtr, Tcl_ValueType **argTypesPtr,
|
||||
# Tcl_MathProc **procPtr, ClientData *clientDataPtr)
|
||||
#}
|
||||
# Removed in 9.0:
|
||||
#declare 436 {deprecated {}} {
|
||||
# Tcl_Obj *Tcl_ListMathFuncs(Tcl_Interp *interp, const char *pattern)
|
||||
#}
|
||||
declare 435 {
|
||||
int Tcl_GetMathFuncInfo(Tcl_Interp *interp, const char *name,
|
||||
int *numArgsPtr, Tcl_ValueType **argTypesPtr,
|
||||
Tcl_MathProc **procPtr, ClientData *clientDataPtr)
|
||||
}
|
||||
declare 436 {
|
||||
Tcl_Obj *Tcl_ListMathFuncs(Tcl_Interp *interp, const char *pattern)
|
||||
}
|
||||
|
||||
# TIP#36 (better access to 'subst') dkf
|
||||
declare 437 {
|
||||
@@ -1640,7 +1617,7 @@ declare 452 {
|
||||
int index, Tcl_Obj *pathPtr, Tcl_Obj *objPtr)
|
||||
}
|
||||
declare 453 {
|
||||
const char *const *Tcl_FSFileAttrStrings(Tcl_Obj *pathPtr,
|
||||
const char *CONST86 *Tcl_FSFileAttrStrings(Tcl_Obj *pathPtr,
|
||||
Tcl_Obj **objPtrRef)
|
||||
}
|
||||
declare 454 {
|
||||
@@ -1718,7 +1695,7 @@ declare 476 {
|
||||
Tcl_Obj *pathPtr)
|
||||
}
|
||||
declare 477 {
|
||||
const Tcl_Filesystem *Tcl_FSGetFileSystemForPath(Tcl_Obj *pathPtr)
|
||||
CONST86 Tcl_Filesystem *Tcl_FSGetFileSystemForPath(Tcl_Obj *pathPtr)
|
||||
}
|
||||
declare 478 {
|
||||
Tcl_PathType Tcl_FSGetPathType(Tcl_Obj *pathPtr)
|
||||
@@ -2401,6 +2378,9 @@ declare 1 macosx {
|
||||
|
||||
# Public functions that are not accessible via the stubs table.
|
||||
|
||||
export {
|
||||
void Tcl_Main(int argc, char **argv, Tcl_AppInitProc *appInitProc)
|
||||
}
|
||||
export {
|
||||
const char *Tcl_InitStubs(Tcl_Interp *interp, const char *version,
|
||||
int exact)
|
||||
|
||||
+296
-71
@@ -52,15 +52,30 @@ extern "C" {
|
||||
* tools/tcl.hpj.in (not patchlevel, for windows installer)
|
||||
*/
|
||||
|
||||
#define TCL_MAJOR_VERSION 9
|
||||
#define TCL_MINOR_VERSION 0
|
||||
#define TCL_MAJOR_VERSION 8
|
||||
#define TCL_MINOR_VERSION 7
|
||||
#define TCL_RELEASE_LEVEL TCL_ALPHA_RELEASE
|
||||
#define TCL_RELEASE_SERIAL 0
|
||||
|
||||
#define TCL_VERSION "9.0"
|
||||
#define TCL_PATCH_LEVEL "9.0a0"
|
||||
#define TCL_VERSION "8.7"
|
||||
#define TCL_PATCH_LEVEL "8.7a0"
|
||||
|
||||
#if defined(RC_INVOKED)
|
||||
#if !defined(TCL_NO_DEPRECATED) || defined(RC_INVOKED)
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* The following definitions set up the proper options for Windows compilers.
|
||||
* We use this method because there is no autoconf equivalent.
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifndef __WIN32__
|
||||
# define __WIN32__
|
||||
# endif
|
||||
# ifndef WIN32
|
||||
# define WIN32
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Utility macros: STRINGIFY takes an argument and wraps it in "" (double
|
||||
* quotation marks), JOIN joins two arguments.
|
||||
@@ -74,7 +89,7 @@ extern "C" {
|
||||
# define JOIN(a,b) JOIN1(a,b)
|
||||
# define JOIN1(a,b) a##b
|
||||
#endif
|
||||
#endif /* RC_INVOKED */
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
* A special definition used to allow this header file to be included from
|
||||
@@ -110,11 +125,32 @@ extern "C" {
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* Support for functions with a variable number of arguments.
|
||||
*
|
||||
* The following TCL_VARARGS* macros are to support old extensions
|
||||
* written for older versions of Tcl where the macros permitted
|
||||
* support for the varargs.h system as well as stdarg.h .
|
||||
*
|
||||
* New code should just directly be written to use stdarg.h conventions.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
# define TCL_VARARGS(type, name) (type name, ...)
|
||||
# define TCL_VARARGS_DEF(type, name) (type name, ...)
|
||||
# define TCL_VARARGS_START(type, name, list) (va_start(list, name), name)
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
#if defined(__GNUC__) && (__GNUC__ > 2)
|
||||
# define TCL_FORMAT_PRINTF(a,b) __attribute__ ((__format__ (__printf__, a, b)))
|
||||
# define TCL_NORETURN __attribute__ ((noreturn))
|
||||
# define TCL_NOINLINE __attribute__ ((noinline))
|
||||
# define TCL_NORETURN1 __attribute__ ((noreturn))
|
||||
# if defined(BUILD_tcl) || defined(BUILD_tk)
|
||||
# define TCL_NORETURN1 __attribute__ ((noreturn))
|
||||
# else
|
||||
# define TCL_NORETURN1 /* nothing */
|
||||
# endif
|
||||
#else
|
||||
# define TCL_FORMAT_PRINTF(a,b)
|
||||
# if defined(_MSC_VER) && (_MSC_VER >= 1310)
|
||||
@@ -189,7 +225,7 @@ extern "C" {
|
||||
* to be included in a shared library, then it should have the DLLEXPORT
|
||||
* storage class. If is being declared for use by a module that is going to
|
||||
* link against the shared library, then it should have the DLLIMPORT storage
|
||||
* class. If the symbol is being declared for a static build or for use from a
|
||||
* class. If the symbol is beind declared for a static build or for use from a
|
||||
* stub library, then the storage class should be empty.
|
||||
*
|
||||
* The convention is that a macro called BUILD_xxxx, where xxxx is the name of
|
||||
@@ -210,8 +246,55 @@ extern "C" {
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(CONST86) && !defined(TCL_NO_DEPRECATED)
|
||||
# define CONST86 const
|
||||
/*
|
||||
* The following _ANSI_ARGS_ macro is to support old extensions
|
||||
* written for older versions of Tcl where it permitted support
|
||||
* for compilers written in the pre-prototype era of C.
|
||||
*
|
||||
* New code should use prototypes.
|
||||
*/
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
# undef _ANSI_ARGS_
|
||||
# define _ANSI_ARGS_(x) x
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
* Definitions that allow this header file to be used either with or without
|
||||
* ANSI C features.
|
||||
*/
|
||||
|
||||
#ifndef INLINE
|
||||
# define INLINE
|
||||
#endif
|
||||
|
||||
#ifdef NO_CONST
|
||||
# ifndef const
|
||||
# define const
|
||||
# endif
|
||||
#endif
|
||||
#ifndef CONST
|
||||
# define CONST const
|
||||
#endif
|
||||
|
||||
#ifdef USE_NON_CONST
|
||||
# ifdef USE_COMPAT_CONST
|
||||
# error define at most one of USE_NON_CONST and USE_COMPAT_CONST
|
||||
# endif
|
||||
# define CONST84
|
||||
# define CONST84_RETURN
|
||||
#else
|
||||
# ifdef USE_COMPAT_CONST
|
||||
# define CONST84
|
||||
# define CONST84_RETURN const
|
||||
# else
|
||||
# define CONST84 const
|
||||
# define CONST84_RETURN const
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef CONST86
|
||||
# define CONST86 CONST84
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -228,11 +311,47 @@ extern "C" {
|
||||
# define EXTERN extern TCL_STORAGE_CLASS
|
||||
#endif
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* The following code is copied from winnt.h. If we don't replicate it here,
|
||||
* then <windows.h> can't be included after tcl.h, since tcl.h also defines
|
||||
* VOID. This block is skipped under Cygwin and Mingw.
|
||||
*/
|
||||
|
||||
#if defined(_WIN32) && !defined(HAVE_WINNT_IGNORE_VOID)
|
||||
#ifndef VOID
|
||||
#define VOID void
|
||||
typedef char CHAR;
|
||||
typedef short SHORT;
|
||||
typedef long LONG;
|
||||
#endif
|
||||
#endif /* _WIN32 && !HAVE_WINNT_IGNORE_VOID */
|
||||
|
||||
/*
|
||||
* Macro to use instead of "void" for arguments that must have type "void *"
|
||||
* in ANSI C; maps them to type "char *" in non-ANSI systems.
|
||||
*/
|
||||
|
||||
#ifndef __VXWORKS__
|
||||
# ifndef NO_VOID
|
||||
# define VOID void
|
||||
# else
|
||||
# define VOID char
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Miscellaneous declarations.
|
||||
*/
|
||||
|
||||
typedef void *ClientData;
|
||||
#ifndef _CLIENTDATA
|
||||
# ifndef NO_VOID
|
||||
typedef void *ClientData;
|
||||
# else
|
||||
typedef int *ClientData;
|
||||
# endif
|
||||
# define _CLIENTDATA
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Darwin specific configure overrides (to support fat compiles, where
|
||||
@@ -277,40 +396,44 @@ typedef void *ClientData;
|
||||
# if defined(_WIN32)
|
||||
# define TCL_WIDE_INT_TYPE __int64
|
||||
# define TCL_LL_MODIFIER "I64"
|
||||
# if defined(_WIN64)
|
||||
# define TCL_Z_MODIFIER "I"
|
||||
# endif
|
||||
# elif defined(__GNUC__)
|
||||
# define TCL_Z_MODIFIER "z"
|
||||
# define TCL_WIDE_INT_TYPE long long
|
||||
# define TCL_LL_MODIFIER "ll"
|
||||
# else /* ! _WIN32 && ! __GNUC__ */
|
||||
/*
|
||||
* Don't know what platform it is and configure hasn't discovered what is
|
||||
* going on for us. Try to guess...
|
||||
*/
|
||||
# include <limits.h>
|
||||
# if defined(LLONG_MAX) && (LLONG_MAX == LONG_MAX)
|
||||
# if (INT_MAX < LONG_MAX)
|
||||
# define TCL_WIDE_INT_IS_LONG 1
|
||||
# else
|
||||
# define TCL_WIDE_INT_TYPE long long
|
||||
# endif
|
||||
# endif /* _WIN32 */
|
||||
#endif /* !TCL_WIDE_INT_TYPE & !TCL_WIDE_INT_IS_LONG */
|
||||
|
||||
#ifndef TCL_WIDE_INT_TYPE
|
||||
# define TCL_WIDE_INT_TYPE long long
|
||||
#endif /* !TCL_WIDE_INT_TYPE */
|
||||
#ifdef TCL_WIDE_INT_IS_LONG
|
||||
# undef TCL_WIDE_INT_TYPE
|
||||
# define TCL_WIDE_INT_TYPE long
|
||||
#endif /* TCL_WIDE_INT_IS_LONG */
|
||||
|
||||
typedef TCL_WIDE_INT_TYPE Tcl_WideInt;
|
||||
typedef unsigned TCL_WIDE_INT_TYPE Tcl_WideUInt;
|
||||
|
||||
#ifndef TCL_LL_MODIFIER
|
||||
# define TCL_LL_MODIFIER "ll"
|
||||
#endif /* !TCL_LL_MODIFIER */
|
||||
#ifndef TCL_Z_MODIFIER
|
||||
# if defined(__GNUC__) && !defined(_WIN32)
|
||||
# define TCL_Z_MODIFIER "z"
|
||||
# else
|
||||
# define TCL_Z_MODIFIER ""
|
||||
# endif
|
||||
#endif /* !TCL_Z_MODIFIER */
|
||||
#ifdef TCL_WIDE_INT_IS_LONG
|
||||
# ifndef TCL_LL_MODIFIER
|
||||
# define TCL_LL_MODIFIER "l"
|
||||
# endif /* !TCL_LL_MODIFIER */
|
||||
#else /* TCL_WIDE_INT_IS_LONG */
|
||||
/*
|
||||
* The next short section of defines are only done when not running on Windows
|
||||
* or some other strange platform.
|
||||
*/
|
||||
# ifndef TCL_LL_MODIFIER
|
||||
# define TCL_LL_MODIFIER "ll"
|
||||
# endif /* !TCL_LL_MODIFIER */
|
||||
#endif /* TCL_WIDE_INT_IS_LONG */
|
||||
|
||||
#define Tcl_WideAsLong(val) ((long)((Tcl_WideInt)(val)))
|
||||
#define Tcl_LongAsWide(val) ((Tcl_WideInt)((long)(val)))
|
||||
#define Tcl_WideAsDouble(val) ((double)((Tcl_WideInt)(val)))
|
||||
@@ -369,7 +492,39 @@ typedef unsigned TCL_WIDE_INT_TYPE Tcl_WideUInt;
|
||||
* accessed with Tcl_GetObjResult() and Tcl_SetObjResult().
|
||||
*/
|
||||
|
||||
typedef struct Tcl_Interp Tcl_Interp;
|
||||
typedef struct Tcl_Interp
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
{
|
||||
/* TIP #330: Strongly discourage extensions from using the string
|
||||
* result. */
|
||||
#ifdef USE_INTERP_RESULT
|
||||
char *result TCL_DEPRECATED_API("use Tcl_GetStringResult/Tcl_SetResult");
|
||||
/* If the last command returned a string
|
||||
* result, this points to it. */
|
||||
void (*freeProc) (char *blockPtr)
|
||||
TCL_DEPRECATED_API("use Tcl_GetStringResult/Tcl_SetResult");
|
||||
/* Zero means the string result is statically
|
||||
* allocated. TCL_DYNAMIC means it was
|
||||
* allocated with ckalloc and should be freed
|
||||
* with ckfree. Other values give the address
|
||||
* of function to invoke to free the result.
|
||||
* Tcl_Eval must free it before executing next
|
||||
* command. */
|
||||
#else
|
||||
char *resultDontUse; /* Don't use in extensions! */
|
||||
void (*freeProcDontUse) (char *); /* Don't use in extensions! */
|
||||
#endif
|
||||
#ifdef USE_INTERP_ERRORLINE
|
||||
int errorLine TCL_DEPRECATED_API("use Tcl_GetErrorLine/Tcl_SetErrorLine");
|
||||
/* When TCL_ERROR is returned, this gives the
|
||||
* line number within the command where the
|
||||
* error occurred (1 if first line). */
|
||||
#else
|
||||
int errorLineDontUse; /* Don't use in extensions! */
|
||||
#endif
|
||||
}
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
Tcl_Interp;
|
||||
|
||||
typedef struct Tcl_AsyncHandler_ *Tcl_AsyncHandler;
|
||||
typedef struct Tcl_Channel_ *Tcl_Channel;
|
||||
@@ -518,6 +673,8 @@ typedef struct stat *Tcl_OldStat_;
|
||||
#define TCL_BREAK 3
|
||||
#define TCL_CONTINUE 4
|
||||
|
||||
#define TCL_RESULT_SIZE 200
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* Flags to control what substitutions are performed by Tcl_SubstObj():
|
||||
@@ -528,6 +685,22 @@ typedef struct stat *Tcl_OldStat_;
|
||||
#define TCL_SUBST_BACKSLASHES 004
|
||||
#define TCL_SUBST_ALL 007
|
||||
|
||||
/*
|
||||
* Argument descriptors for math function callbacks in expressions:
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
TCL_INT, TCL_DOUBLE, TCL_EITHER, TCL_WIDE_INT
|
||||
} Tcl_ValueType;
|
||||
|
||||
typedef struct Tcl_Value {
|
||||
Tcl_ValueType type; /* Indicates intValue or doubleValue is valid,
|
||||
* or both. */
|
||||
long intValue; /* Integer value. */
|
||||
double doubleValue; /* Double-precision floating value. */
|
||||
Tcl_WideInt wideValue; /* Wide (min. 64-bit) integer value. */
|
||||
} Tcl_Value;
|
||||
|
||||
/*
|
||||
* Forward declaration of Tcl_Obj to prevent an error when the forward
|
||||
* reference to Tcl_Obj is encountered in the function types declared below.
|
||||
@@ -547,10 +720,10 @@ typedef void (Tcl_ChannelProc) (ClientData clientData, int mask);
|
||||
typedef void (Tcl_CloseProc) (ClientData data);
|
||||
typedef void (Tcl_CmdDeleteProc) (ClientData clientData);
|
||||
typedef int (Tcl_CmdProc) (ClientData clientData, Tcl_Interp *interp,
|
||||
int argc, const char *argv[]);
|
||||
int argc, CONST84 char *argv[]);
|
||||
typedef void (Tcl_CmdTraceProc) (ClientData clientData, Tcl_Interp *interp,
|
||||
int level, char *command, Tcl_CmdProc *proc,
|
||||
ClientData cmdClientData, int argc, const char *argv[]);
|
||||
ClientData cmdClientData, int argc, CONST84 char *argv[]);
|
||||
typedef int (Tcl_CmdObjTraceProc) (ClientData clientData, Tcl_Interp *interp,
|
||||
int level, const char *command, Tcl_Command commandInfo, int objc,
|
||||
struct Tcl_Obj *const *objv);
|
||||
@@ -573,6 +746,8 @@ typedef void (Tcl_FreeProc) (char *blockPtr);
|
||||
typedef void (Tcl_IdleProc) (ClientData clientData);
|
||||
typedef void (Tcl_InterpDeleteProc) (ClientData clientData,
|
||||
Tcl_Interp *interp);
|
||||
typedef int (Tcl_MathProc) (ClientData clientData, Tcl_Interp *interp,
|
||||
Tcl_Value *args, Tcl_Value *resultPtr);
|
||||
typedef void (Tcl_NamespaceDeleteProc) (ClientData clientData);
|
||||
typedef int (Tcl_ObjCmdProc) (ClientData clientData, Tcl_Interp *interp,
|
||||
int objc, struct Tcl_Obj *const *objv);
|
||||
@@ -585,7 +760,7 @@ typedef void (Tcl_TimerProc) (ClientData clientData);
|
||||
typedef int (Tcl_SetFromAnyProc) (Tcl_Interp *interp, struct Tcl_Obj *objPtr);
|
||||
typedef void (Tcl_UpdateStringProc) (struct Tcl_Obj *objPtr);
|
||||
typedef char * (Tcl_VarTraceProc) (ClientData clientData, Tcl_Interp *interp,
|
||||
const char *part1, const char *part2, int flags);
|
||||
CONST84 char *part1, CONST84 char *part2, int flags);
|
||||
typedef void (Tcl_CommandTraceProc) (ClientData clientData, Tcl_Interp *interp,
|
||||
const char *oldName, const char *newName, int flags);
|
||||
typedef void (Tcl_CreateFileHandlerProc) (int fd, int mask, Tcl_FileProc *proc,
|
||||
@@ -684,11 +859,20 @@ int Tcl_IsShared(Tcl_Obj *objPtr);
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* The following type contains the state needed by Tcl_SaveResult. It
|
||||
* is typically allocated on the stack.
|
||||
* The following structure contains the state needed by Tcl_SaveResult. No-one
|
||||
* outside of Tcl should access any of these fields. This structure is
|
||||
* typically allocated on the stack.
|
||||
*/
|
||||
|
||||
typedef Tcl_Obj *Tcl_SavedResult;
|
||||
typedef struct Tcl_SavedResult {
|
||||
char *result;
|
||||
Tcl_FreeProc *freeProc;
|
||||
Tcl_Obj *objResultPtr;
|
||||
char *appendResult;
|
||||
int appendAvl;
|
||||
int appendUsed;
|
||||
char resultSpace[TCL_RESULT_SIZE+1];
|
||||
} Tcl_SavedResult;
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
@@ -813,11 +997,14 @@ typedef struct Tcl_DString {
|
||||
|
||||
#define Tcl_DStringLength(dsPtr) ((dsPtr)->length)
|
||||
#define Tcl_DStringValue(dsPtr) ((dsPtr)->string)
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
# define Tcl_DStringTrunc Tcl_DStringSetLength
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
* Definitions for the maximum number of digits of precision that may be
|
||||
* produced by Tcl_PrintDouble, and the number of bytes of buffer space
|
||||
* required by Tcl_PrintDouble.
|
||||
* specified in the "tcl_precision" variable, and the number of bytes of
|
||||
* buffer space required by Tcl_PrintDouble.
|
||||
*/
|
||||
|
||||
#define TCL_MAX_PREC 17
|
||||
@@ -931,6 +1118,17 @@ typedef struct Tcl_DString {
|
||||
|
||||
#define TCL_ALLOW_INLINE_COMPILATION 0x20000
|
||||
|
||||
/*
|
||||
* The TCL_PARSE_PART1 flag is deprecated and has no effect. The part1 is now
|
||||
* always parsed whenever the part2 is NULL. (This is to avoid a common error
|
||||
* when converting code to use the new object based APIs and forgetting to
|
||||
* give the flag)
|
||||
*/
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
# define TCL_PARSE_PART1 0x400
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
* Types for linked variables:
|
||||
*/
|
||||
@@ -984,7 +1182,9 @@ struct Tcl_HashEntry {
|
||||
Tcl_HashEntry *nextPtr; /* Pointer to next entry in this hash bucket,
|
||||
* or NULL for end of chain. */
|
||||
Tcl_HashTable *tablePtr; /* Pointer to table containing entry. */
|
||||
unsigned int hash; /* Hash value. */
|
||||
void *hash; /* Hash value, stored as pointer to ensure
|
||||
* that the offsets of the fields in this
|
||||
* structure are not changed. */
|
||||
ClientData clientData; /* Application stores something here with
|
||||
* Tcl_SetHashValue. */
|
||||
union { /* Key has one of these forms: */
|
||||
@@ -1079,10 +1279,10 @@ struct Tcl_HashTable {
|
||||
* table. */
|
||||
int rebuildSize; /* Enlarge table when numEntries gets to be
|
||||
* this large. */
|
||||
unsigned int mask; /* Mask value used in hashing function. */
|
||||
int downShift; /* Shift count used in hashing function.
|
||||
* Designed to use high-order bits of
|
||||
* randomized keys. */
|
||||
int mask; /* Mask value used in hashing function. */
|
||||
int keyType; /* Type of keys used in this table. It's
|
||||
* either TCL_CUSTOM_KEYS, TCL_STRING_KEYS,
|
||||
* TCL_ONE_WORD_KEYS, or an integer giving the
|
||||
@@ -1144,8 +1344,8 @@ typedef struct Tcl_HashSearch {
|
||||
typedef struct {
|
||||
void *next; /* Search position for underlying hash
|
||||
* table. */
|
||||
unsigned int epoch; /* Epoch marker for dictionary being searched,
|
||||
* or 0 if search has terminated. */
|
||||
int epoch; /* Epoch marker for dictionary being searched,
|
||||
* or -1 if search has terminated. */
|
||||
Tcl_Dict dictionaryPtr; /* Reference to dictionary being searched. */
|
||||
} Tcl_DictSearch;
|
||||
|
||||
@@ -1203,8 +1403,8 @@ typedef struct Tcl_Time {
|
||||
long usec; /* Microseconds. */
|
||||
} Tcl_Time;
|
||||
|
||||
typedef void (Tcl_SetTimerProc) (const Tcl_Time *timePtr);
|
||||
typedef int (Tcl_WaitForEventProc) (const Tcl_Time *timePtr);
|
||||
typedef void (Tcl_SetTimerProc) (CONST86 Tcl_Time *timePtr);
|
||||
typedef int (Tcl_WaitForEventProc) (CONST86 Tcl_Time *timePtr);
|
||||
|
||||
/*
|
||||
* TIP #233 (Virtualized Time)
|
||||
@@ -1278,14 +1478,14 @@ typedef int (Tcl_DriverClose2Proc) (ClientData instanceData,
|
||||
typedef int (Tcl_DriverInputProc) (ClientData instanceData, char *buf,
|
||||
int toRead, int *errorCodePtr);
|
||||
typedef int (Tcl_DriverOutputProc) (ClientData instanceData,
|
||||
const char *buf, int toWrite, int *errorCodePtr);
|
||||
CONST84 char *buf, int toWrite, int *errorCodePtr);
|
||||
typedef int (Tcl_DriverSeekProc) (ClientData instanceData, long offset,
|
||||
int mode, int *errorCodePtr);
|
||||
typedef int (Tcl_DriverSetOptionProc) (ClientData instanceData,
|
||||
Tcl_Interp *interp, const char *optionName,
|
||||
const char *value);
|
||||
typedef int (Tcl_DriverGetOptionProc) (ClientData instanceData,
|
||||
Tcl_Interp *interp, const char *optionName,
|
||||
Tcl_Interp *interp, CONST84 char *optionName,
|
||||
Tcl_DString *dsPtr);
|
||||
typedef void (Tcl_DriverWatchProc) (ClientData instanceData, int mask);
|
||||
typedef int (Tcl_DriverGetHandleProc) (ClientData instanceData,
|
||||
@@ -1476,7 +1676,7 @@ typedef int (Tcl_FSNormalizePathProc) (Tcl_Interp *interp, Tcl_Obj *pathPtr,
|
||||
int nextCheckpoint);
|
||||
typedef int (Tcl_FSFileAttrsGetProc) (Tcl_Interp *interp, int index,
|
||||
Tcl_Obj *pathPtr, Tcl_Obj **objPtrRef);
|
||||
typedef const char *const * (Tcl_FSFileAttrStringsProc) (Tcl_Obj *pathPtr,
|
||||
typedef const char *CONST86 * (Tcl_FSFileAttrStringsProc) (Tcl_Obj *pathPtr,
|
||||
Tcl_Obj **objPtrRef);
|
||||
typedef int (Tcl_FSFileAttrsSetProc) (Tcl_Interp *interp, int index,
|
||||
Tcl_Obj *pathPtr, Tcl_Obj *objPtr);
|
||||
@@ -2001,7 +2201,7 @@ typedef struct Tcl_EncodingType {
|
||||
*/
|
||||
|
||||
#ifndef TCL_UTF_MAX
|
||||
#define TCL_UTF_MAX 4
|
||||
#define TCL_UTF_MAX 3
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -2063,8 +2263,6 @@ typedef struct mp_int mp_int;
|
||||
#define MP_INT_DECLARED
|
||||
typedef unsigned int mp_digit;
|
||||
#define MP_DIGIT_DECLARED
|
||||
typedef unsigned TCL_WIDE_INT_TYPE mp_word;
|
||||
#define MP_WORD_DECLARED
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
@@ -2191,10 +2389,10 @@ typedef int (Tcl_NRPostProc) (ClientData data[], Tcl_Interp *interp,
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* The following constant is used to test for older versions of Tcl in the
|
||||
* stubs tables. If TCL_UTF_MAX>4 use a different value.
|
||||
* stubs tables.
|
||||
*/
|
||||
|
||||
#define TCL_STUB_MAGIC ((int) 0xFCA3BACF + (TCL_UTF_MAX>4))
|
||||
#define TCL_STUB_MAGIC ((int) 0xFCA3BACF)
|
||||
|
||||
/*
|
||||
* The following function is required to be defined in all stubs aware
|
||||
@@ -2209,27 +2407,14 @@ const char * TclTomMathInitializeStubs(Tcl_Interp *interp,
|
||||
const char *version, int epoch, int revision);
|
||||
|
||||
#ifdef USE_TCL_STUBS
|
||||
#if TCL_RELEASE_LEVEL == TCL_FINAL_RELEASE
|
||||
# define Tcl_InitStubs(interp, version, exact) \
|
||||
(Tcl_InitStubs)(interp, version, \
|
||||
#define Tcl_InitStubs(interp, version, exact) \
|
||||
(Tcl_InitStubs)(interp, version, \
|
||||
(exact)|(TCL_MAJOR_VERSION<<8)|(TCL_MINOR_VERSION<<16), \
|
||||
TCL_STUB_MAGIC)
|
||||
#else
|
||||
# define Tcl_InitStubs(interp, version, exact) \
|
||||
(Tcl_InitStubs)(interp, TCL_PATCH_LEVEL, \
|
||||
1|(TCL_MAJOR_VERSION<<8)|(TCL_MINOR_VERSION<<16), \
|
||||
TCL_STUB_MAGIC)
|
||||
#endif
|
||||
#else
|
||||
#if TCL_RELEASE_LEVEL == TCL_FINAL_RELEASE
|
||||
# define Tcl_InitStubs(interp, version, exact) \
|
||||
Tcl_PkgInitStubsCheck(interp, version, \
|
||||
(exact)|(TCL_MAJOR_VERSION<<8)|(TCL_MINOR_VERSION<<16))
|
||||
#else
|
||||
# define Tcl_InitStubs(interp, version, exact) \
|
||||
Tcl_PkgInitStubsCheck(interp, TCL_PATCH_LEVEL, \
|
||||
1|(TCL_MAJOR_VERSION<<8)|(TCL_MINOR_VERSION<<16))
|
||||
#endif
|
||||
#define Tcl_InitStubs(interp, version, exact) \
|
||||
Tcl_PkgInitStubsCheck(interp, version, \
|
||||
(exact)|(TCL_MAJOR_VERSION<<8)|(TCL_MINOR_VERSION<<16))
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -2357,9 +2542,15 @@ EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr);
|
||||
# undef Tcl_NewDoubleObj
|
||||
# define Tcl_NewDoubleObj(val) \
|
||||
Tcl_DbNewDoubleObj(val, __FILE__, __LINE__)
|
||||
# undef Tcl_NewIntObj
|
||||
# define Tcl_NewIntObj(val) \
|
||||
Tcl_DbNewLongObj(val, __FILE__, __LINE__)
|
||||
# undef Tcl_NewListObj
|
||||
# define Tcl_NewListObj(objc, objv) \
|
||||
Tcl_DbNewListObj(objc, objv, __FILE__, __LINE__)
|
||||
# undef Tcl_NewLongObj
|
||||
# define Tcl_NewLongObj(val) \
|
||||
Tcl_DbNewLongObj(val, __FILE__, __LINE__)
|
||||
# undef Tcl_NewObj
|
||||
# define Tcl_NewObj() \
|
||||
Tcl_DbNewObj(__FILE__, __LINE__)
|
||||
@@ -2389,8 +2580,10 @@ EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr);
|
||||
* hash tables:
|
||||
*/
|
||||
|
||||
#undef Tcl_FindHashEntry
|
||||
#define Tcl_FindHashEntry(tablePtr, key) \
|
||||
(*((tablePtr)->findProc))(tablePtr, (const char *)(key))
|
||||
#undef Tcl_CreateHashEntry
|
||||
#define Tcl_CreateHashEntry(tablePtr, key, newPtr) \
|
||||
(*((tablePtr)->createProc))(tablePtr, (const char *)(key), newPtr)
|
||||
|
||||
@@ -2415,6 +2608,38 @@ EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr);
|
||||
#define Tcl_ConditionFinalize(condPtr)
|
||||
#endif /* TCL_THREADS */
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* Deprecated Tcl functions:
|
||||
*/
|
||||
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
/*
|
||||
* These function have been renamed. The old names are deprecated, but we
|
||||
* define these macros for backwards compatibilty.
|
||||
*/
|
||||
|
||||
# define Tcl_Ckalloc Tcl_Alloc
|
||||
# define Tcl_Ckfree Tcl_Free
|
||||
# define Tcl_Ckrealloc Tcl_Realloc
|
||||
# define Tcl_Return Tcl_SetResult
|
||||
# define Tcl_TildeSubst Tcl_TranslateFileName
|
||||
#if !defined(__APPLE__) /* On OSX, there is a conflict with "mach/mach.h" */
|
||||
# define panic Tcl_Panic
|
||||
#endif
|
||||
# define panicVA Tcl_PanicVA
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------------
|
||||
* Convenience declaration of Tcl_AppInit for backwards compatibility. This
|
||||
* function is not *implemented* by the tcl library, so the storage class is
|
||||
* neither DLLEXPORT nor DLLIMPORT.
|
||||
*/
|
||||
|
||||
extern Tcl_AppInitProc Tcl_AppInit;
|
||||
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
#endif /* RC_INVOKED */
|
||||
|
||||
/*
|
||||
|
||||
+5
-5
@@ -661,14 +661,14 @@ mstats(
|
||||
|
||||
fprintf(stderr, "\nused:\t");
|
||||
for (i = 0; i < NBUCKETS; i++) {
|
||||
fprintf(stderr, " %" TCL_Z_MODIFIER "u", numMallocs[i]);
|
||||
fprintf(stderr, " %" TCL_LL_MODIFIER "d", (Tcl_WideInt)numMallocs[i]);
|
||||
totalUsed += numMallocs[i] * (1 << (i + 3));
|
||||
}
|
||||
|
||||
fprintf(stderr, "\n\tTotal small in use: %" TCL_Z_MODIFIER "u, total free: %" TCL_Z_MODIFIER "u\n",
|
||||
totalUsed, totalFree);
|
||||
fprintf(stderr, "\n\tNumber of big (>%d) blocks in use: %" TCL_Z_MODIFIER "u\n",
|
||||
MAXMALLOC, numMallocs[NBUCKETS]);
|
||||
fprintf(stderr, "\n\tTotal small in use: %" TCL_LL_MODIFIER "d, total free: %" TCL_LL_MODIFIER "d\n",
|
||||
(Tcl_WideInt)totalUsed, (Tcl_WideInt)totalFree);
|
||||
fprintf(stderr, "\n\tNumber of big (>%d) blocks in use: %" TCL_LL_MODIFIER "d\n",
|
||||
MAXMALLOC, (Tcl_WideInt)numMallocs[NBUCKETS]);
|
||||
|
||||
Tcl_MutexUnlock(allocMutexPtr);
|
||||
}
|
||||
|
||||
+16
-15
@@ -406,6 +406,7 @@ static const TalInstDesc TalInstructionTable[] = {
|
||||
{"jumpTrue", ASSEM_JUMP, INST_JUMP_TRUE1, 1, 0},
|
||||
{"jumpTrue4", ASSEM_JUMP4, INST_JUMP_TRUE4, 1, 0},
|
||||
{"label", ASSEM_LABEL, 0, 0, 0},
|
||||
{"land", ASSEM_1BYTE, INST_LAND, 2, 1},
|
||||
{"lappend", ASSEM_LVT, (INST_LAPPEND_SCALAR1<<8
|
||||
| INST_LAPPEND_SCALAR4),
|
||||
1, 1},
|
||||
@@ -433,6 +434,7 @@ static const TalInstDesc TalInstructionTable[] = {
|
||||
| INST_LOAD_ARRAY4), 1, 1},
|
||||
{"loadArrayStk", ASSEM_1BYTE, INST_LOAD_ARRAY_STK, 2, 1},
|
||||
{"loadStk", ASSEM_1BYTE, INST_LOAD_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},
|
||||
@@ -2244,24 +2246,23 @@ GetListIndexOperand(
|
||||
Tcl_Token* tokenPtr = *tokenPtrPtr;
|
||||
/* INOUT: Pointer to the next token in the
|
||||
* source code */
|
||||
Tcl_Obj *value;
|
||||
int status;
|
||||
Tcl_Obj* intObj; /* Integer from the source code */
|
||||
int status; /* Tcl status return */
|
||||
|
||||
/* General operand validity check */
|
||||
if (GetNextOperand(assemEnvPtr, tokenPtrPtr, &value) != TCL_OK) {
|
||||
/*
|
||||
* Extract the next token as a string.
|
||||
*/
|
||||
|
||||
if (GetNextOperand(assemEnvPtr, tokenPtrPtr, &intObj) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/* Convert to an integer, advance to the next token and return. */
|
||||
/*
|
||||
* NOTE: Indexing a list with an index before it yields the
|
||||
* same result as indexing after it, and might be more easily portable
|
||||
* when list size limits grow.
|
||||
*/
|
||||
status = TclIndexEncode(interp, value,
|
||||
TCL_INDEX_BEFORE,TCL_INDEX_BEFORE, result);
|
||||
|
||||
Tcl_DecrRefCount(value);
|
||||
/*
|
||||
* Convert to an integer, advance to the next token and return.
|
||||
*/
|
||||
|
||||
status = TclGetIntForIndex(interp, intObj, -2, result);
|
||||
Tcl_DecrRefCount(intObj);
|
||||
*tokenPtrPtr = TokenAfter(tokenPtr);
|
||||
return status;
|
||||
}
|
||||
@@ -4265,7 +4266,7 @@ AddBasicBlockRangeToErrorInfo(
|
||||
Tcl_AppendObjToErrorInfo(interp, lineNo);
|
||||
Tcl_AddErrorInfo(interp, " and ");
|
||||
if (bbPtr->successor1 != NULL) {
|
||||
TclSetIntObj(lineNo, bbPtr->successor1->startLine);
|
||||
TclSetLongObj(lineNo, bbPtr->successor1->startLine);
|
||||
Tcl_AppendObjToErrorInfo(interp, lineNo);
|
||||
} else {
|
||||
Tcl_AddErrorInfo(interp, "end of assembly code");
|
||||
|
||||
+728
-270
File diff suppressed because it is too large
Load Diff
+18
-13
@@ -267,7 +267,7 @@ const Tcl_ObjType tclByteArrayType = {
|
||||
* fewer mallocs.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
typedef struct ByteArray {
|
||||
int used; /* The number of bytes used in the byte
|
||||
* array. */
|
||||
int allocated; /* The amount of space actually allocated
|
||||
@@ -536,7 +536,7 @@ SetByteArrayFromAny(
|
||||
const char *src, *srcEnd;
|
||||
unsigned char *dst;
|
||||
ByteArray *byteArrayPtr;
|
||||
Tcl_UniChar ch = 0;
|
||||
Tcl_UniChar ch;
|
||||
|
||||
if (objPtr->typePtr == &properByteArrayType) {
|
||||
return TCL_OK;
|
||||
@@ -1300,7 +1300,7 @@ BinaryFormatCmd(
|
||||
|
||||
badField:
|
||||
{
|
||||
Tcl_UniChar ch = 0;
|
||||
Tcl_UniChar ch;
|
||||
char buf[TCL_UTF_MAX + 1];
|
||||
|
||||
TclUtfToUniChar(errorString, &ch);
|
||||
@@ -1634,10 +1634,19 @@ BinaryScanCmd(
|
||||
break;
|
||||
case '@':
|
||||
if (count == BINARY_NOCOUNT) {
|
||||
DeleteScanNumberCache(numberCachePtr);
|
||||
goto badCount;
|
||||
}
|
||||
if ((count == BINARY_ALL) || (count > length)) {
|
||||
if (arg >= objc) {
|
||||
DeleteScanNumberCache(numberCachePtr);
|
||||
goto badIndex;
|
||||
}
|
||||
valuePtr = Tcl_NewIntObj(offset);
|
||||
resultPtr = Tcl_ObjSetVar2(interp, objv[arg], NULL,
|
||||
valuePtr, TCL_LEAVE_ERR_MSG);
|
||||
arg++;
|
||||
if (resultPtr == NULL) {
|
||||
DeleteScanNumberCache(numberCachePtr);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
} else if ((count == BINARY_ALL) || (count > length)) {
|
||||
offset = length;
|
||||
} else {
|
||||
offset = count;
|
||||
@@ -1660,17 +1669,13 @@ BinaryScanCmd(
|
||||
|
||||
return TCL_OK;
|
||||
|
||||
badCount:
|
||||
errorString = "missing count for \"@\" field specifier";
|
||||
goto error;
|
||||
|
||||
badIndex:
|
||||
errorString = "not enough arguments for all format specifiers";
|
||||
goto error;
|
||||
|
||||
badField:
|
||||
{
|
||||
Tcl_UniChar ch = 0;
|
||||
Tcl_UniChar ch;
|
||||
char buf[TCL_UTF_MAX + 1];
|
||||
|
||||
TclUtfToUniChar(errorString, &ch);
|
||||
@@ -2284,7 +2289,7 @@ ScanNumber(
|
||||
Tcl_Obj *bigObj = NULL;
|
||||
mp_int big;
|
||||
|
||||
TclInitBignumFromWideUInt(&big, uwvalue);
|
||||
TclBNInitBignumFromWideUInt(&big, uwvalue);
|
||||
bigObj = Tcl_NewBignumObj(&big);
|
||||
return bigObj;
|
||||
}
|
||||
|
||||
+15
-15
@@ -33,7 +33,7 @@
|
||||
* "memory tag" command is invoked, to hold the current tag.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
typedef struct MemTag {
|
||||
size_t refCount; /* Number of mem_headers referencing this
|
||||
* tag. */
|
||||
char string[1]; /* Actual size of string will be as large as
|
||||
@@ -187,15 +187,15 @@ TclDumpMemoryInfo(
|
||||
"total mallocs %10u\n"
|
||||
"total frees %10u\n"
|
||||
"current packets allocated %10u\n"
|
||||
"current bytes allocated %10" TCL_Z_MODIFIER "u\n"
|
||||
"current bytes allocated %10" TCL_LL_MODIFIER "u\n"
|
||||
"maximum packets allocated %10u\n"
|
||||
"maximum bytes allocated %10" TCL_Z_MODIFIER "u\n",
|
||||
"maximum bytes allocated %10" TCL_LL_MODIFIER "u\n",
|
||||
total_mallocs,
|
||||
total_frees,
|
||||
current_malloc_packets,
|
||||
current_bytes_malloced,
|
||||
(Tcl_WideInt)current_bytes_malloced,
|
||||
maximum_malloc_packets,
|
||||
maximum_bytes_malloced);
|
||||
(Tcl_WideInt)maximum_bytes_malloced);
|
||||
if (flags == 0) {
|
||||
fprintf((FILE *)clientData, "%s", buf);
|
||||
} else {
|
||||
@@ -254,7 +254,7 @@ ValidateMemory(
|
||||
fprintf(stderr, "low guard failed at %p, %s %d\n",
|
||||
memHeaderP->body, file, line);
|
||||
fflush(stderr); /* In case name pointer is bad. */
|
||||
fprintf(stderr, "%" TCL_Z_MODIFIER "u bytes allocated at (%s %d)\n", memHeaderP->length,
|
||||
fprintf(stderr, "%" TCL_LL_MODIFIER "d bytes allocated at (%s %d)\n", (Tcl_WideInt) memHeaderP->length,
|
||||
memHeaderP->file, memHeaderP->line);
|
||||
Tcl_Panic("Memory validation failure");
|
||||
}
|
||||
@@ -276,8 +276,8 @@ ValidateMemory(
|
||||
fprintf(stderr, "high guard failed at %p, %s %d\n",
|
||||
memHeaderP->body, file, line);
|
||||
fflush(stderr); /* In case name pointer is bad. */
|
||||
fprintf(stderr, "%" TCL_Z_MODIFIER "u bytes allocated at (%s %d)\n",
|
||||
memHeaderP->length, memHeaderP->file,
|
||||
fprintf(stderr, "%" TCL_LL_MODIFIER "d bytes allocated at (%s %d)\n",
|
||||
(Tcl_WideInt)memHeaderP->length, memHeaderP->file,
|
||||
memHeaderP->line);
|
||||
Tcl_Panic("Memory validation failure");
|
||||
}
|
||||
@@ -359,9 +359,9 @@ Tcl_DumpActiveMemory(
|
||||
Tcl_MutexLock(ckallocMutexPtr);
|
||||
for (memScanP = allocHead; memScanP != NULL; memScanP = memScanP->flink) {
|
||||
address = &memScanP->body[0];
|
||||
fprintf(fileP, "%p - %p %" TCL_Z_MODIFIER "u @ %s %d %s",
|
||||
fprintf(fileP, "%p - %p %" TCL_LL_MODIFIER "d @ %s %d %s",
|
||||
address, address + memScanP->length - 1,
|
||||
memScanP->length, memScanP->file, memScanP->line,
|
||||
(Tcl_WideInt)memScanP->length, memScanP->file, memScanP->line,
|
||||
(memScanP->tagPtr == NULL) ? "" : memScanP->tagPtr->string);
|
||||
(void) fputc('\n', fileP);
|
||||
}
|
||||
@@ -611,8 +611,8 @@ Tcl_DbCkfree(
|
||||
memp = (struct mem_header *) (((size_t) ptr) - BODY_OFFSET);
|
||||
|
||||
if (alloc_tracing) {
|
||||
fprintf(stderr, "ckfree %p %" TCL_Z_MODIFIER "u %s %d\n",
|
||||
memp->body, memp->length, file, line);
|
||||
fprintf(stderr, "ckfree %p %" TCL_LL_MODIFIER "d %s %d\n",
|
||||
memp->body, (Tcl_WideInt) memp->length, file, line);
|
||||
}
|
||||
|
||||
if (validate_memory) {
|
||||
@@ -859,12 +859,12 @@ MemoryCmd(
|
||||
}
|
||||
if (strcmp(argv[1],"info") == 0) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"%-25s %10u\n%-25s %10u\n%-25s %10u\n%-25s %10" TCL_Z_MODIFIER"u\n%-25s %10u\n%-25s %10" TCL_Z_MODIFIER "u\n",
|
||||
"%-25s %10u\n%-25s %10u\n%-25s %10u\n%-25s %10" TCL_LL_MODIFIER"d\n%-25s %10u\n%-25s %10" TCL_LL_MODIFIER "d\n",
|
||||
"total mallocs", total_mallocs, "total frees", total_frees,
|
||||
"current packets allocated", current_malloc_packets,
|
||||
"current bytes allocated", current_bytes_malloced,
|
||||
"current bytes allocated", (Tcl_WideInt)current_bytes_malloced,
|
||||
"maximum packets allocated", maximum_malloc_packets,
|
||||
"maximum bytes allocated", maximum_bytes_malloced));
|
||||
"maximum bytes allocated", (Tcl_WideInt)maximum_bytes_malloced));
|
||||
return TCL_OK;
|
||||
}
|
||||
if (strcmp(argv[1], "init") == 0) {
|
||||
|
||||
+2300
-280
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -147,6 +147,143 @@ Tcl_BreakObjCmd(
|
||||
return TCL_BREAK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Tcl_CaseObjCmd --
|
||||
*
|
||||
* This procedure is invoked to process the "case" Tcl command. See the
|
||||
* user documentation for details on what it does. THIS COMMAND IS
|
||||
* OBSOLETE AND DEPRECATED. SLATED FOR REMOVAL IN TCL 9.0.
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl object result.
|
||||
*
|
||||
* Side effects:
|
||||
* See the user documentation.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef TCL_NO_DEPRECATED
|
||||
/* ARGSUSED */
|
||||
int
|
||||
Tcl_CaseObjCmd(
|
||||
ClientData dummy, /* Not used. */
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
register int i;
|
||||
int body, result, caseObjc;
|
||||
const char *stringPtr, *arg;
|
||||
Tcl_Obj *const *caseObjv;
|
||||
Tcl_Obj *armPtr;
|
||||
|
||||
if (objc < 3) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv,
|
||||
"string ?in? ?pattern body ...? ?default body?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
stringPtr = TclGetString(objv[1]);
|
||||
body = -1;
|
||||
|
||||
arg = TclGetString(objv[2]);
|
||||
if (strcmp(arg, "in") == 0) {
|
||||
i = 3;
|
||||
} else {
|
||||
i = 2;
|
||||
}
|
||||
caseObjc = objc - i;
|
||||
caseObjv = objv + i;
|
||||
|
||||
/*
|
||||
* If all of the pattern/command pairs are lumped into a single argument,
|
||||
* split them out again.
|
||||
*/
|
||||
|
||||
if (caseObjc == 1) {
|
||||
Tcl_Obj **newObjv;
|
||||
|
||||
TclListObjGetElements(interp, caseObjv[0], &caseObjc, &newObjv);
|
||||
caseObjv = newObjv;
|
||||
}
|
||||
|
||||
for (i = 0; i < caseObjc; i += 2) {
|
||||
int patObjc, j;
|
||||
const char **patObjv;
|
||||
const char *pat, *p;
|
||||
|
||||
if (i == caseObjc-1) {
|
||||
Tcl_ResetResult(interp);
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"extra case pattern with no body", -1));
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for special case of single pattern (no list) with no
|
||||
* backslash sequences.
|
||||
*/
|
||||
|
||||
pat = TclGetString(caseObjv[i]);
|
||||
for (p = pat; *p != '\0'; p++) {
|
||||
if (TclIsSpaceProc(*p) || (*p == '\\')) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (*p == '\0') {
|
||||
if ((*pat == 'd') && (strcmp(pat, "default") == 0)) {
|
||||
body = i + 1;
|
||||
}
|
||||
if (Tcl_StringMatch(stringPtr, pat)) {
|
||||
body = i + 1;
|
||||
goto match;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Break up pattern lists, then check each of the patterns in the
|
||||
* list.
|
||||
*/
|
||||
|
||||
result = Tcl_SplitList(interp, pat, &patObjc, &patObjv);
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
for (j = 0; j < patObjc; j++) {
|
||||
if (Tcl_StringMatch(stringPtr, patObjv[j])) {
|
||||
body = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ckfree(patObjv);
|
||||
if (j < patObjc) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
match:
|
||||
if (body != -1) {
|
||||
armPtr = caseObjv[body - 1];
|
||||
result = Tcl_EvalObjEx(interp, caseObjv[body], 0);
|
||||
if (result == TCL_ERROR) {
|
||||
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
|
||||
"\n (\"%.50s\" arm line %d)",
|
||||
TclGetString(armPtr), Tcl_GetErrorLine(interp)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Nothing matched: return nothing.
|
||||
*/
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif /* !TCL_NO_DEPRECATED */
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
|
||||
+137
-190
@@ -56,7 +56,7 @@ typedef int (*SortMemCmpFn_t) (const void *, const void *, size_t);
|
||||
* The following structure is used to pass this information.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
typedef struct SortInfo {
|
||||
int isIncreasing; /* Nonzero means sort in increasing order. */
|
||||
int sortMode; /* The sort mode. One of SORTMODE_* values
|
||||
* defined below. */
|
||||
@@ -64,9 +64,8 @@ typedef struct {
|
||||
* SORTMODE_COMMAND. Pre-initialized to hold
|
||||
* base of command. */
|
||||
int *indexv; /* If the -index option was specified, this
|
||||
* holds an encoding of the indexes contained
|
||||
* in the list supplied as an argument to
|
||||
* that option.
|
||||
* holds the indexes contained in the list
|
||||
* supplied as an argument to that option.
|
||||
* NULL if no indexes supplied, and points to
|
||||
* singleIndex field when only one
|
||||
* supplied. */
|
||||
@@ -93,6 +92,14 @@ typedef struct {
|
||||
#define SORTMODE_DICTIONARY 4
|
||||
#define SORTMODE_ASCII_NC 8
|
||||
|
||||
/*
|
||||
* Magic values for the index field of the SortInfo structure. Note that the
|
||||
* index "end-1" will be translated to SORTIDX_END-1, etc.
|
||||
*/
|
||||
|
||||
#define SORTIDX_NONE -1 /* Not indexed; use whole value. */
|
||||
#define SORTIDX_END -2 /* Indexed from end. */
|
||||
|
||||
/*
|
||||
* Forward declarations for procedures defined in this file:
|
||||
*/
|
||||
@@ -2153,7 +2160,7 @@ Tcl_JoinObjCmd(
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* The argument objects. */
|
||||
{
|
||||
int length, listLen;
|
||||
int listLen;
|
||||
Tcl_Obj *resObjPtr = NULL, *joinObjPtr, **elemPtrs;
|
||||
|
||||
if ((objc < 2) || (objc > 3)) {
|
||||
@@ -2184,9 +2191,9 @@ Tcl_JoinObjCmd(
|
||||
joinObjPtr = (objc == 2) ? Tcl_NewStringObj(" ", 1) : objv[2];
|
||||
Tcl_IncrRefCount(joinObjPtr);
|
||||
|
||||
(void) Tcl_GetStringFromObj(joinObjPtr, &length);
|
||||
if (length == 0) {
|
||||
resObjPtr = TclStringCat(interp, listLen, elemPtrs, 0);
|
||||
if (Tcl_GetCharLength(joinObjPtr) == 0) {
|
||||
TclStringCatObjv(interp, /* inPlace */ 0, listLen, elemPtrs,
|
||||
&resObjPtr);
|
||||
} else {
|
||||
int i;
|
||||
|
||||
@@ -2536,6 +2543,7 @@ Tcl_LrangeObjCmd(
|
||||
register Tcl_Obj *const objv[])
|
||||
/* Argument objects. */
|
||||
{
|
||||
Tcl_Obj **elemPtrs;
|
||||
int listLen, first, last, result;
|
||||
|
||||
if (objc != 4) {
|
||||
@@ -2553,14 +2561,55 @@ Tcl_LrangeObjCmd(
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
if (first < 0) {
|
||||
first = 0;
|
||||
}
|
||||
|
||||
result = TclGetIntForIndexM(interp, objv[3], /*endValue*/ listLen - 1,
|
||||
&last);
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
if (last >= listLen) {
|
||||
last = listLen - 1;
|
||||
}
|
||||
|
||||
if (first > last) {
|
||||
/*
|
||||
* Returning an empty list is easy.
|
||||
*/
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
result = TclListObjGetElements(interp, objv[1], &listLen, &elemPtrs);
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (Tcl_IsShared(objv[1]) ||
|
||||
((ListRepPtr(objv[1])->refCount > 1))) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewListObj(last - first + 1,
|
||||
&elemPtrs[first]));
|
||||
} else {
|
||||
/*
|
||||
* In-place is possible.
|
||||
*/
|
||||
|
||||
if (last < (listLen - 1)) {
|
||||
Tcl_ListObjReplace(interp, objv[1], last + 1, listLen - 1 - last,
|
||||
0, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* This one is not conditioned on (first > 0) in order to preserve the
|
||||
* string-canonizing effect of [lrange 0 end].
|
||||
*/
|
||||
|
||||
Tcl_ListObjReplace(interp, objv[1], 0, first, 0, NULL);
|
||||
Tcl_SetObjResult(interp, objv[1]);
|
||||
}
|
||||
|
||||
Tcl_SetObjResult(interp, TclListObjRange(objv[1], first, last));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -2738,7 +2787,7 @@ Tcl_LreplaceObjCmd(
|
||||
* (to allow for replacing the last elem).
|
||||
*/
|
||||
|
||||
if ((first >= listLen) && (listLen > 0)) {
|
||||
if ((first > listLen) && (listLen > 0)) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"list doesn't contain element %s", TclGetString(objv[2])));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LREPLACE", "BADIDX",
|
||||
@@ -2889,21 +2938,20 @@ Tcl_LsearchObjCmd(
|
||||
Tcl_Obj *const objv[]) /* Argument values. */
|
||||
{
|
||||
const char *bytes, *patternBytes;
|
||||
int i, match, index, result=TCL_OK, listc, length, elemLen, bisect;
|
||||
int allocatedIndexVector = 0;
|
||||
int dataType, isIncreasing, lower, upper, start, groupSize, groupOffset;
|
||||
int i, match, index, result, listc, length, elemLen, bisect;
|
||||
int dataType, isIncreasing, lower, upper, offset;
|
||||
Tcl_WideInt patWide, objWide;
|
||||
int allMatches, inlineReturn, negatedMatch, returnSubindices, noCase;
|
||||
double patDouble, objDouble;
|
||||
SortInfo sortInfo;
|
||||
Tcl_Obj *patObj, **listv, *listPtr, *startPtr, *itemPtr;
|
||||
SortStrCmpFn_t strCmpFn = TclUtfCmp;
|
||||
SortStrCmpFn_t strCmpFn = strcmp;
|
||||
Tcl_RegExp regexp = NULL;
|
||||
static const char *const options[] = {
|
||||
"-all", "-ascii", "-bisect", "-decreasing", "-dictionary",
|
||||
"-exact", "-glob", "-increasing", "-index",
|
||||
"-inline", "-integer", "-nocase", "-not",
|
||||
"-real", "-regexp", "-sorted", "-start", "-stride",
|
||||
"-real", "-regexp", "-sorted", "-start",
|
||||
"-subindices", NULL
|
||||
};
|
||||
enum options {
|
||||
@@ -2911,7 +2959,7 @@ Tcl_LsearchObjCmd(
|
||||
LSEARCH_DICTIONARY, LSEARCH_EXACT, LSEARCH_GLOB, LSEARCH_INCREASING,
|
||||
LSEARCH_INDEX, LSEARCH_INLINE, LSEARCH_INTEGER, LSEARCH_NOCASE,
|
||||
LSEARCH_NOT, LSEARCH_REAL, LSEARCH_REGEXP, LSEARCH_SORTED,
|
||||
LSEARCH_START, LSEARCH_STRIDE, LSEARCH_SUBINDICES
|
||||
LSEARCH_START, LSEARCH_SUBINDICES
|
||||
};
|
||||
enum datatypes {
|
||||
ASCII, DICTIONARY, INTEGER, REAL
|
||||
@@ -2931,9 +2979,7 @@ Tcl_LsearchObjCmd(
|
||||
bisect = 0;
|
||||
listPtr = NULL;
|
||||
startPtr = NULL;
|
||||
groupSize = 1;
|
||||
groupOffset = 0;
|
||||
start = 0;
|
||||
offset = 0;
|
||||
noCase = 0;
|
||||
sortInfo.compareCmdPtr = NULL;
|
||||
sortInfo.isIncreasing = 1;
|
||||
@@ -2951,6 +2997,9 @@ Tcl_LsearchObjCmd(
|
||||
for (i = 1; i < objc-2; i++) {
|
||||
if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0, &index)
|
||||
!= TCL_OK) {
|
||||
if (startPtr != NULL) {
|
||||
Tcl_DecrRefCount(startPtr);
|
||||
}
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
@@ -3015,7 +3064,6 @@ Tcl_LsearchObjCmd(
|
||||
|
||||
if (startPtr != NULL) {
|
||||
Tcl_DecrRefCount(startPtr);
|
||||
startPtr = NULL;
|
||||
}
|
||||
if (i > objc-4) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
@@ -3036,47 +3084,25 @@ Tcl_LsearchObjCmd(
|
||||
startPtr = Tcl_DuplicateObj(objv[i]);
|
||||
} else {
|
||||
startPtr = objv[i];
|
||||
Tcl_IncrRefCount(startPtr);
|
||||
}
|
||||
Tcl_IncrRefCount(startPtr);
|
||||
break;
|
||||
case LSEARCH_STRIDE: /* -stride */
|
||||
if (i > objc-4) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"\"-stride\" option must be "
|
||||
"followed by stride length", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL);
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
if (Tcl_GetIntFromObj(interp, objv[i+1], &groupSize) != TCL_OK) {
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
if (groupSize < 1) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"stride length must be at least 1", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSORT",
|
||||
"BADSTRIDE", NULL);
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
i++;
|
||||
break;
|
||||
case LSEARCH_INDEX: { /* -index */
|
||||
Tcl_Obj **indices;
|
||||
int j;
|
||||
|
||||
if (allocatedIndexVector) {
|
||||
if (sortInfo.indexc > 1) {
|
||||
TclStackFree(interp, sortInfo.indexv);
|
||||
allocatedIndexVector = 0;
|
||||
}
|
||||
if (i > objc-4) {
|
||||
if (startPtr != NULL) {
|
||||
Tcl_DecrRefCount(startPtr);
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"\"-index\" option must be followed by list index",
|
||||
-1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "ARGUMENT", "MISSING", NULL);
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3088,8 +3114,10 @@ Tcl_LsearchObjCmd(
|
||||
i++;
|
||||
if (TclListObjGetElements(interp, objv[i],
|
||||
&sortInfo.indexc, &indices) != TCL_OK) {
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
if (startPtr != NULL) {
|
||||
Tcl_DecrRefCount(startPtr);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
switch (sortInfo.indexc) {
|
||||
case 0:
|
||||
@@ -3101,8 +3129,6 @@ Tcl_LsearchObjCmd(
|
||||
default:
|
||||
sortInfo.indexv =
|
||||
TclStackAlloc(interp, sizeof(int) * sortInfo.indexc);
|
||||
allocatedIndexVector = 1; /* Cannot use indexc field, as it
|
||||
* might be decreased by 1 later. */
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3112,26 +3138,13 @@ Tcl_LsearchObjCmd(
|
||||
*/
|
||||
|
||||
for (j=0 ; j<sortInfo.indexc ; j++) {
|
||||
int encoded = 0;
|
||||
if (TclIndexEncode(interp, indices[j], TCL_INDEX_BEFORE,
|
||||
TCL_INDEX_AFTER, &encoded) != TCL_OK) {
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
if ((encoded == TCL_INDEX_BEFORE)
|
||||
|| (encoded == TCL_INDEX_AFTER)) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"index \"%s\" cannot select an element "
|
||||
"from any list", Tcl_GetString(indices[j])));
|
||||
Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX"
|
||||
"OUTOFRANGE", NULL);
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
if (result == TCL_ERROR) {
|
||||
if (TclGetIntForIndexM(interp, indices[j], SORTIDX_END,
|
||||
&sortInfo.indexv[j]) != TCL_OK) {
|
||||
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
|
||||
"\n (-index option item number %d)", j));
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
sortInfo.indexv[j] = encoded;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -3143,12 +3156,14 @@ Tcl_LsearchObjCmd(
|
||||
*/
|
||||
|
||||
if (returnSubindices && sortInfo.indexc==0) {
|
||||
if (startPtr != NULL) {
|
||||
Tcl_DecrRefCount(startPtr);
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"-subindices cannot be used without -index option", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSEARCH",
|
||||
"BAD_OPTION_MIX", NULL);
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (bisect && (allMatches || negatedMatch)) {
|
||||
@@ -3156,8 +3171,7 @@ Tcl_LsearchObjCmd(
|
||||
"-bisect is not compatible with -all or -not", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSEARCH",
|
||||
"BAD_OPTION_MIX", NULL);
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (mode == REGEXP) {
|
||||
@@ -3183,6 +3197,9 @@ Tcl_LsearchObjCmd(
|
||||
}
|
||||
|
||||
if (regexp == NULL) {
|
||||
if (startPtr != NULL) {
|
||||
Tcl_DecrRefCount(startPtr);
|
||||
}
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
@@ -3195,64 +3212,24 @@ Tcl_LsearchObjCmd(
|
||||
|
||||
result = TclListObjGetElements(interp, objv[objc - 2], &listc, &listv);
|
||||
if (result != TCL_OK) {
|
||||
if (startPtr != NULL) {
|
||||
Tcl_DecrRefCount(startPtr);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for sanity when grouping elements of the overall list together
|
||||
* because of the -stride option. [TIP #351]
|
||||
*/
|
||||
|
||||
if (groupSize > 1) {
|
||||
if (listc % groupSize) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"list size must be a multiple of the stride length",
|
||||
-1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSEARCH", "BADSTRIDE",
|
||||
NULL);
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
if (sortInfo.indexc > 0) {
|
||||
/*
|
||||
* Use the first value in the list supplied to -index as the
|
||||
* offset of the element within each group by which to sort.
|
||||
*/
|
||||
|
||||
groupOffset = TclIndexDecode(sortInfo.indexv[0], groupSize - 1);
|
||||
if (groupOffset < 0 || groupOffset >= groupSize) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"when used with \"-stride\", the leading \"-index\""
|
||||
" value must be within the group", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSEARCH",
|
||||
"BADINDEX", NULL);
|
||||
result = TCL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
if (sortInfo.indexc == 1) {
|
||||
sortInfo.indexc = 0;
|
||||
sortInfo.indexv = NULL;
|
||||
} else {
|
||||
sortInfo.indexc--;
|
||||
|
||||
for (i = 0; i < sortInfo.indexc; i++) {
|
||||
sortInfo.indexv[i] = sortInfo.indexv[i+1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the user-specified start offset.
|
||||
*/
|
||||
|
||||
if (startPtr) {
|
||||
result = TclGetIntForIndexM(interp, startPtr, listc-1, &start);
|
||||
result = TclGetIntForIndexM(interp, startPtr, listc-1, &offset);
|
||||
Tcl_DecrRefCount(startPtr);
|
||||
if (result != TCL_OK) {
|
||||
goto done;
|
||||
}
|
||||
if (start < 0) {
|
||||
start = 0;
|
||||
if (offset < 0) {
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3260,21 +3237,16 @@ Tcl_LsearchObjCmd(
|
||||
* "did not match anything at all" result straight away. [Bug 1374778]
|
||||
*/
|
||||
|
||||
if (start > listc-1) {
|
||||
if (offset > listc-1) {
|
||||
if (sortInfo.indexc > 1) {
|
||||
TclStackFree(interp, sortInfo.indexv);
|
||||
}
|
||||
if (allMatches || inlineReturn) {
|
||||
Tcl_ResetResult(interp);
|
||||
} else {
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* If start points within a group, it points to the start of the group.
|
||||
*/
|
||||
|
||||
if (groupSize > 1) {
|
||||
start -= (start % groupSize);
|
||||
return TCL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3333,23 +3305,18 @@ Tcl_LsearchObjCmd(
|
||||
* sense in doing this when the match sense is inverted.
|
||||
*/
|
||||
|
||||
/*
|
||||
* With -stride, lower, upper and i are kept as multiples of groupSize.
|
||||
*/
|
||||
|
||||
lower = start - groupSize;
|
||||
lower = offset - 1;
|
||||
upper = listc;
|
||||
while (lower + groupSize != upper && sortInfo.resultCode == TCL_OK) {
|
||||
while (lower + 1 != upper && sortInfo.resultCode == TCL_OK) {
|
||||
i = (lower + upper)/2;
|
||||
i -= i % groupSize;
|
||||
if (sortInfo.indexc != 0) {
|
||||
itemPtr = SelectObjFromSublist(listv[i+groupOffset], &sortInfo);
|
||||
itemPtr = SelectObjFromSublist(listv[i], &sortInfo);
|
||||
if (sortInfo.resultCode != TCL_OK) {
|
||||
result = sortInfo.resultCode;
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
itemPtr = listv[i+groupOffset];
|
||||
itemPtr = listv[i];
|
||||
}
|
||||
switch ((enum datatypes) dataType) {
|
||||
case ASCII:
|
||||
@@ -3438,10 +3405,10 @@ Tcl_LsearchObjCmd(
|
||||
if (allMatches) {
|
||||
listPtr = Tcl_NewListObj(0, NULL);
|
||||
}
|
||||
for (i = start; i < listc; i += groupSize) {
|
||||
for (i = offset; i < listc; i++) {
|
||||
match = 0;
|
||||
if (sortInfo.indexc != 0) {
|
||||
itemPtr = SelectObjFromSublist(listv[i+groupOffset], &sortInfo);
|
||||
itemPtr = SelectObjFromSublist(listv[i], &sortInfo);
|
||||
if (sortInfo.resultCode != TCL_OK) {
|
||||
if (listPtr != NULL) {
|
||||
Tcl_DecrRefCount(listPtr);
|
||||
@@ -3450,7 +3417,7 @@ Tcl_LsearchObjCmd(
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
itemPtr = listv[i+groupOffset];
|
||||
itemPtr = listv[i];
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
@@ -3540,23 +3507,18 @@ Tcl_LsearchObjCmd(
|
||||
*/
|
||||
|
||||
if (returnSubindices && (sortInfo.indexc != 0)) {
|
||||
itemPtr = SelectObjFromSublist(listv[i+groupOffset],
|
||||
&sortInfo);
|
||||
Tcl_ListObjAppendElement(interp, listPtr, itemPtr);
|
||||
} else if (groupSize > 1) {
|
||||
Tcl_ListObjReplace(interp, listPtr, LIST_MAX, 0,
|
||||
groupSize, &listv[i]);
|
||||
itemPtr = SelectObjFromSublist(listv[i], &sortInfo);
|
||||
} else {
|
||||
itemPtr = listv[i];
|
||||
Tcl_ListObjAppendElement(interp, listPtr, itemPtr);
|
||||
}
|
||||
Tcl_ListObjAppendElement(interp, listPtr, itemPtr);
|
||||
} else if (returnSubindices) {
|
||||
int j;
|
||||
|
||||
itemPtr = Tcl_NewIntObj(i+groupOffset);
|
||||
itemPtr = Tcl_NewIntObj(i);
|
||||
for (j=0 ; j<sortInfo.indexc ; j++) {
|
||||
Tcl_ListObjAppendElement(interp, itemPtr, Tcl_NewIntObj(
|
||||
TclIndexDecode(sortInfo.indexv[j], listc)));
|
||||
Tcl_ListObjAppendElement(interp, itemPtr,
|
||||
Tcl_NewIntObj(sortInfo.indexv[j]));
|
||||
}
|
||||
Tcl_ListObjAppendElement(interp, listPtr, itemPtr);
|
||||
} else {
|
||||
@@ -3575,10 +3537,10 @@ Tcl_LsearchObjCmd(
|
||||
if (returnSubindices) {
|
||||
int j;
|
||||
|
||||
itemPtr = Tcl_NewIntObj(index+groupOffset);
|
||||
itemPtr = Tcl_NewIntObj(index);
|
||||
for (j=0 ; j<sortInfo.indexc ; j++) {
|
||||
Tcl_ListObjAppendElement(interp, itemPtr, Tcl_NewIntObj(
|
||||
TclIndexDecode(sortInfo.indexv[j], listc)));
|
||||
Tcl_ListObjAppendElement(interp, itemPtr,
|
||||
Tcl_NewIntObj(sortInfo.indexv[j]));
|
||||
}
|
||||
Tcl_SetObjResult(interp, itemPtr);
|
||||
} else {
|
||||
@@ -3592,14 +3554,7 @@ Tcl_LsearchObjCmd(
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_NewObj());
|
||||
} else {
|
||||
if (returnSubindices) {
|
||||
Tcl_SetObjResult(interp, SelectObjFromSublist(listv[i+groupOffset],
|
||||
&sortInfo));
|
||||
} else if (groupSize > 1) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewListObj(groupSize, &listv[index]));
|
||||
} else {
|
||||
Tcl_SetObjResult(interp, listv[index]);
|
||||
}
|
||||
Tcl_SetObjResult(interp, listv[index]);
|
||||
}
|
||||
result = TCL_OK;
|
||||
|
||||
@@ -3608,10 +3563,7 @@ Tcl_LsearchObjCmd(
|
||||
*/
|
||||
|
||||
done:
|
||||
if (startPtr != NULL) {
|
||||
Tcl_DecrRefCount(startPtr);
|
||||
}
|
||||
if (allocatedIndexVector) {
|
||||
if (sortInfo.indexc > 1) {
|
||||
TclStackFree(interp, sortInfo.indexv);
|
||||
}
|
||||
return result;
|
||||
@@ -3805,7 +3757,7 @@ Tcl_LsortObjCmd(
|
||||
sortInfo.isIncreasing = 1;
|
||||
break;
|
||||
case LSORT_INDEX: {
|
||||
int indexc;
|
||||
int indexc, dummy;
|
||||
Tcl_Obj **indexv;
|
||||
|
||||
if (i == objc-2) {
|
||||
@@ -3831,20 +3783,8 @@ Tcl_LsortObjCmd(
|
||||
*/
|
||||
|
||||
for (j=0 ; j<indexc ; j++) {
|
||||
int encoded = 0;
|
||||
int result = TclIndexEncode(interp, indexv[j],
|
||||
TCL_INDEX_BEFORE, TCL_INDEX_AFTER, &encoded);
|
||||
|
||||
if ((result == TCL_OK) && ((encoded == TCL_INDEX_BEFORE)
|
||||
|| (encoded == TCL_INDEX_AFTER))) {
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"index \"%s\" cannot select an element "
|
||||
"from any list", Tcl_GetString(indexv[j])));
|
||||
Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX"
|
||||
"OUTOFRANGE", NULL);
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
if (result == TCL_ERROR) {
|
||||
if (TclGetIntForIndexM(interp, indexv[j], SORTIDX_END,
|
||||
&dummy) != TCL_OK) {
|
||||
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
|
||||
"\n (-index option item number %d)", j));
|
||||
sortInfo.resultCode = TCL_ERROR;
|
||||
@@ -3924,8 +3864,8 @@ Tcl_LsortObjCmd(
|
||||
* might be decreased by 1 later. */
|
||||
}
|
||||
for (j=0 ; j<sortInfo.indexc ; j++) {
|
||||
/* Prescreened values, no errors or out of range possible */
|
||||
TclIndexEncode(NULL, indexv[j], 0, 0, &sortInfo.indexv[j]);
|
||||
TclGetIntForIndexM(interp, indexv[j], SORTIDX_END,
|
||||
&sortInfo.indexv[j]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3996,7 +3936,10 @@ Tcl_LsortObjCmd(
|
||||
* offset of the element within each group by which to sort.
|
||||
*/
|
||||
|
||||
groupOffset = TclIndexDecode(sortInfo.indexv[0], groupSize - 1);
|
||||
groupOffset = sortInfo.indexv[0];
|
||||
if (groupOffset <= SORTIDX_END) {
|
||||
groupOffset = (groupOffset - SORTIDX_END) + groupSize - 1;
|
||||
}
|
||||
if (groupOffset < 0 || groupOffset >= groupSize) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"when used with \"-stride\", the leading \"-index\""
|
||||
@@ -4015,9 +3958,6 @@ Tcl_LsortObjCmd(
|
||||
/*
|
||||
* Do not shrink the actual memory block used; that doesn't
|
||||
* work with TclStackAlloc-allocated memory. [Bug 2918962]
|
||||
*
|
||||
* TODO: Consider a pointer increment to replace this
|
||||
* array shift.
|
||||
*/
|
||||
|
||||
for (i = 0; i < sortInfo.indexc; i++) {
|
||||
@@ -4323,7 +4263,7 @@ SortCompare(
|
||||
int order = 0;
|
||||
|
||||
if (infoPtr->sortMode == SORTMODE_ASCII) {
|
||||
order = TclUtfCmp(elemPtr1->collationKey.strValuePtr,
|
||||
order = strcmp(elemPtr1->collationKey.strValuePtr,
|
||||
elemPtr2->collationKey.strValuePtr);
|
||||
} else if (infoPtr->sortMode == SORTMODE_ASCII_NC) {
|
||||
order = TclUtfCasecmp(elemPtr1->collationKey.strValuePtr,
|
||||
@@ -4430,7 +4370,7 @@ static int
|
||||
DictionaryCompare(
|
||||
const char *left, const char *right) /* The strings to compare. */
|
||||
{
|
||||
Tcl_UniChar uniLeft = 0, uniRight = 0, uniLeftLower, uniRightLower;
|
||||
Tcl_UniChar uniLeft, uniRight, uniLeftLower, uniRightLower;
|
||||
int diff, zeros;
|
||||
int secondaryDiff = 0;
|
||||
|
||||
@@ -4586,8 +4526,15 @@ SelectObjFromSublist(
|
||||
infoPtr->resultCode = TCL_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
index = infoPtr->indexv[i];
|
||||
|
||||
index = TclIndexDecode(infoPtr->indexv[i], listLen - 1);
|
||||
/*
|
||||
* Adjust for end-based indexing.
|
||||
*/
|
||||
|
||||
if (index < SORTIDX_NONE) {
|
||||
index += listLen + 1;
|
||||
}
|
||||
|
||||
if (Tcl_ListObjIndex(infoPtr->interp, objPtr, index,
|
||||
¤tObj) != TCL_OK) {
|
||||
|
||||
+434
-195
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
#include "tclInt.h"
|
||||
#include "tclCompile.h"
|
||||
#include "tclRegexp.h"
|
||||
#include "tclStringTrim.h"
|
||||
|
||||
@@ -309,7 +310,7 @@ Tcl_RegexpObjCmd(
|
||||
eflags = 0;
|
||||
} else if (offset > stringLength) {
|
||||
eflags = TCL_REG_NOTBOL;
|
||||
} else if (Tcl_GetUniChar(objPtr, offset-1) == '\n') {
|
||||
} else if (Tcl_GetUniChar(objPtr, offset-1) == (Tcl_UniChar)'\n') {
|
||||
eflags = 0;
|
||||
} else {
|
||||
eflags = TCL_REG_NOTBOL;
|
||||
@@ -487,27 +488,26 @@ Tcl_RegsubObjCmd(
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
int idx, result, cflags, all, wlen, wsublen, numMatches, offset;
|
||||
int start, end, subStart, subEnd, match, command, numParts;
|
||||
int start, end, subStart, subEnd, match;
|
||||
Tcl_RegExp regExpr;
|
||||
Tcl_RegExpInfo info;
|
||||
Tcl_Obj *resultPtr, *subPtr, *objPtr, *startIndex = NULL;
|
||||
Tcl_UniChar ch, *wsrc, *wfirstChar, *wstring, *wsubspec = 0, *wend;
|
||||
Tcl_UniChar ch, *wsrc, *wfirstChar, *wstring, *wsubspec, *wend;
|
||||
|
||||
static const char *const options[] = {
|
||||
"-all", "-command", "-expanded", "-line",
|
||||
"-linestop", "-lineanchor", "-nocase", "-start",
|
||||
"-all", "-nocase", "-expanded",
|
||||
"-line", "-linestop", "-lineanchor", "-start",
|
||||
"--", NULL
|
||||
};
|
||||
enum options {
|
||||
REGSUB_ALL, REGSUB_COMMAND, REGSUB_EXPANDED, REGSUB_LINE,
|
||||
REGSUB_LINESTOP, REGSUB_LINEANCHOR, REGSUB_NOCASE, REGSUB_START,
|
||||
REGSUB_ALL, REGSUB_NOCASE, REGSUB_EXPANDED,
|
||||
REGSUB_LINE, REGSUB_LINESTOP, REGSUB_LINEANCHOR, REGSUB_START,
|
||||
REGSUB_LAST
|
||||
};
|
||||
|
||||
cflags = TCL_REG_ADVANCED;
|
||||
all = 0;
|
||||
offset = 0;
|
||||
command = 0;
|
||||
resultPtr = NULL;
|
||||
|
||||
for (idx = 1; idx < objc; idx++) {
|
||||
@@ -529,9 +529,6 @@ Tcl_RegsubObjCmd(
|
||||
case REGSUB_NOCASE:
|
||||
cflags |= TCL_REG_NOCASE;
|
||||
break;
|
||||
case REGSUB_COMMAND:
|
||||
command = 1;
|
||||
break;
|
||||
case REGSUB_EXPANDED:
|
||||
cflags |= TCL_REG_EXPANDED;
|
||||
break;
|
||||
@@ -589,7 +586,7 @@ Tcl_RegsubObjCmd(
|
||||
}
|
||||
}
|
||||
|
||||
if (all && (offset == 0) && (command == 0)
|
||||
if (all && (offset == 0)
|
||||
&& (strpbrk(TclGetString(objv[2]), "&\\") == NULL)
|
||||
&& (strpbrk(TclGetString(objv[0]), "*+?{}()[].\\|^$") == NULL)) {
|
||||
/*
|
||||
@@ -665,28 +662,6 @@ Tcl_RegsubObjCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (command) {
|
||||
/*
|
||||
* In command-prefix mode, we require that the third non-option
|
||||
* argument be a list, so we enforce that here. Afterwards, we fetch
|
||||
* the RE compilation again in case objv[0] and objv[2] are the same
|
||||
* object. (If they aren't, that's cheap to do.)
|
||||
*/
|
||||
|
||||
if (Tcl_ListObjLength(interp, objv[2], &numParts) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (numParts < 1) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"command prefix must be a list of at least one element",
|
||||
-1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "REGSUB",
|
||||
"CMDEMPTY", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
regExpr = Tcl_GetRegExpFromObj(interp, objv[0], cflags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure to avoid problems where the objects are shared. This can
|
||||
* cause RegExpObj <> UnicodeObj shimmering that causes data corruption.
|
||||
@@ -704,9 +679,7 @@ Tcl_RegsubObjCmd(
|
||||
} else {
|
||||
subPtr = objv[2];
|
||||
}
|
||||
if (!command) {
|
||||
wsubspec = Tcl_GetUnicodeFromObj(subPtr, &wsublen);
|
||||
}
|
||||
wsubspec = Tcl_GetUnicodeFromObj(subPtr, &wsublen);
|
||||
|
||||
result = TCL_OK;
|
||||
|
||||
@@ -764,90 +737,6 @@ Tcl_RegsubObjCmd(
|
||||
end = info.matches[0].end;
|
||||
Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, start);
|
||||
|
||||
/*
|
||||
* In command-prefix mode, the substitutions are added as quoted
|
||||
* arguments to the subSpec to form a command, that is then executed
|
||||
* and the result used as the string to substitute in. Actually,
|
||||
* everything is passed through Tcl_EvalObjv, as that's much faster.
|
||||
*/
|
||||
|
||||
if (command) {
|
||||
Tcl_Obj **args = NULL, **parts;
|
||||
int numArgs;
|
||||
|
||||
Tcl_ListObjGetElements(interp, subPtr, &numParts, &parts);
|
||||
numArgs = numParts + info.nsubs + 1;
|
||||
args = ckalloc(sizeof(Tcl_Obj*) * numArgs);
|
||||
memcpy(args, parts, sizeof(Tcl_Obj*) * numParts);
|
||||
|
||||
for (idx = 0 ; idx <= info.nsubs ; idx++) {
|
||||
subStart = info.matches[idx].start;
|
||||
subEnd = info.matches[idx].end;
|
||||
if ((subStart >= 0) && (subEnd >= 0)) {
|
||||
args[idx + numParts] = Tcl_NewUnicodeObj(
|
||||
wstring + offset + subStart, subEnd - subStart);
|
||||
} else {
|
||||
args[idx + numParts] = Tcl_NewObj();
|
||||
}
|
||||
Tcl_IncrRefCount(args[idx + numParts]);
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point, we're locally holding the references to the
|
||||
* argument words we added for this time round the loop, and the
|
||||
* subPtr is holding the references to the words that the user
|
||||
* supplied directly. None are zero-refcount, which is important
|
||||
* because Tcl_EvalObjv is "hairy monster" in terms of refcount
|
||||
* handling, being able to optionally add references to any of its
|
||||
* argument words. We'll drop the local refs immediately
|
||||
* afterwards; subPtr is handled in the main exit stanza.
|
||||
*/
|
||||
|
||||
result = Tcl_EvalObjv(interp, numArgs, args, 0);
|
||||
for (idx = 0 ; idx <= info.nsubs ; idx++) {
|
||||
TclDecrRefCount(args[idx + numParts]);
|
||||
}
|
||||
ckfree(args);
|
||||
if (result != TCL_OK) {
|
||||
if (result == TCL_ERROR) {
|
||||
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
|
||||
"\n (%s substitution computation script)",
|
||||
options[REGSUB_COMMAND]));
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
Tcl_AppendObjToObj(resultPtr, Tcl_GetObjResult(interp));
|
||||
Tcl_ResetResult(interp);
|
||||
|
||||
/*
|
||||
* Refetch the unicode, in case the representation was smashed by
|
||||
* the user code.
|
||||
*/
|
||||
|
||||
wstring = Tcl_GetUnicodeFromObj(objPtr, &wlen);
|
||||
|
||||
offset += end;
|
||||
if (end == 0 || start == end) {
|
||||
/*
|
||||
* Always consume at least one character of the input string
|
||||
* in order to prevent infinite loops, even when we
|
||||
* technically matched the empty string; we must not match
|
||||
* again at the same spot.
|
||||
*/
|
||||
|
||||
if (offset < wlen) {
|
||||
Tcl_AppendUnicodeToObj(resultPtr, wstring + offset, 1);
|
||||
}
|
||||
offset++;
|
||||
}
|
||||
if (all) {
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Append the subSpec argument to the variable, making appropriate
|
||||
* substitutions. This code is a bit hairy because of the backslash
|
||||
@@ -1173,7 +1062,7 @@ Tcl_SplitObjCmd(
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
Tcl_UniChar ch = 0;
|
||||
Tcl_UniChar ch;
|
||||
int len;
|
||||
const char *splitChars;
|
||||
const char *stringPtr;
|
||||
@@ -1216,22 +1105,13 @@ Tcl_SplitObjCmd(
|
||||
Tcl_InitHashTable(&charReuseTable, TCL_ONE_WORD_KEYS);
|
||||
|
||||
for ( ; stringPtr < end; stringPtr += len) {
|
||||
int fullchar;
|
||||
len = TclUtfToUniChar(stringPtr, &ch);
|
||||
fullchar = ch;
|
||||
|
||||
#if TCL_UTF_MAX <= 4
|
||||
if (!len) {
|
||||
len += TclUtfToUniChar(stringPtr, &ch);
|
||||
fullchar = (((fullchar & 0x3ff) << 10) | (ch & 0x3ff)) + 0x10000;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Assume Tcl_UniChar is an integral type...
|
||||
*/
|
||||
|
||||
hPtr = Tcl_CreateHashEntry(&charReuseTable, INT2PTR(fullchar),
|
||||
hPtr = Tcl_CreateHashEntry(&charReuseTable, INT2PTR((int) ch),
|
||||
&isNew);
|
||||
if (isNew) {
|
||||
TclNewStringObj(objPtr, stringPtr, len);
|
||||
@@ -1267,7 +1147,7 @@ Tcl_SplitObjCmd(
|
||||
} else {
|
||||
const char *element, *p, *splitEnd;
|
||||
int splitLen;
|
||||
Tcl_UniChar splitChar = 0;
|
||||
Tcl_UniChar splitChar;
|
||||
|
||||
/*
|
||||
* Normal case: split on any of a given set of characters. Discard
|
||||
@@ -1335,8 +1215,16 @@ StringFirstCmd(
|
||||
if (TCL_OK != TclGetIntForIndexM(interp, objv[3], size - 1, &start)) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (start < 0) {
|
||||
start = 0;
|
||||
}
|
||||
if (start >= size) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
|
||||
return TCL_OK;
|
||||
}
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(TclStringFirst(objv[1],
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(TclStringFind(objv[1],
|
||||
objv[2], start)));
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -1380,6 +1268,14 @@ StringLastCmd(
|
||||
if (TCL_OK != TclGetIntForIndexM(interp, objv[3], size - 1, &last)) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (last < 0) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
|
||||
return TCL_OK;
|
||||
}
|
||||
if (last >= size) {
|
||||
last = size - 1;
|
||||
}
|
||||
}
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(TclStringLast(objv[1],
|
||||
objv[2], last)));
|
||||
@@ -1419,7 +1315,7 @@ StringIndexCmd(
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the char length to calculate what 'end' means.
|
||||
* Get the char length to calulate what 'end' means.
|
||||
*/
|
||||
|
||||
length = Tcl_GetCharLength(objv[1]);
|
||||
@@ -1428,11 +1324,7 @@ StringIndexCmd(
|
||||
}
|
||||
|
||||
if ((index >= 0) && (index < length)) {
|
||||
int ch = Tcl_GetUniChar(objv[1], index);
|
||||
|
||||
if (ch == -1) {
|
||||
return TCL_OK;
|
||||
}
|
||||
Tcl_UniChar ch = Tcl_GetUniChar(objv[1], index);
|
||||
|
||||
/*
|
||||
* If we have a ByteArray object, we're careful to generate a new
|
||||
@@ -1444,7 +1336,7 @@ StringIndexCmd(
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(&uch, 1));
|
||||
} else {
|
||||
char buf[4];
|
||||
char buf[TCL_UTF_MAX];
|
||||
|
||||
length = Tcl_UniCharToUtf(ch, buf);
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, length));
|
||||
@@ -1479,7 +1371,7 @@ StringIsCmd(
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
const char *string1, *end, *stop;
|
||||
Tcl_UniChar ch = 0;
|
||||
Tcl_UniChar ch;
|
||||
int (*chcomp)(int) = NULL; /* The UniChar comparison function. */
|
||||
int i, failat = 0, result = 1, strict = 0, index, length1, length2;
|
||||
Tcl_Obj *objPtr, *failVarObj = NULL;
|
||||
@@ -1576,8 +1468,10 @@ StringIsCmd(
|
||||
string1 = TclGetStringFromObj(objPtr, &length1);
|
||||
result = length1 == 0;
|
||||
}
|
||||
} else if ((objPtr->internalRep.wideValue != 0)
|
||||
? (index == STR_IS_FALSE) : (index == STR_IS_TRUE)) {
|
||||
} else if (((index == STR_IS_TRUE) &&
|
||||
objPtr->internalRep.longValue == 0)
|
||||
|| ((index == STR_IS_FALSE) &&
|
||||
objPtr->internalRep.longValue != 0)) {
|
||||
result = 0;
|
||||
}
|
||||
break;
|
||||
@@ -1588,8 +1482,12 @@ StringIsCmd(
|
||||
chcomp = Tcl_UniCharIsDigit;
|
||||
break;
|
||||
case STR_IS_DOUBLE: {
|
||||
/* TODO */
|
||||
if ((objPtr->typePtr == &tclDoubleType) ||
|
||||
(objPtr->typePtr == &tclIntType) ||
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
(objPtr->typePtr == &tclWideIntType) ||
|
||||
#endif
|
||||
(objPtr->typePtr == &tclBignumType)) {
|
||||
break;
|
||||
}
|
||||
@@ -1624,6 +1522,9 @@ StringIsCmd(
|
||||
goto failedIntParse;
|
||||
case STR_IS_ENTIER:
|
||||
if ((objPtr->typePtr == &tclIntType) ||
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
(objPtr->typePtr == &tclWideIntType) ||
|
||||
#endif
|
||||
(objPtr->typePtr == &tclBignumType)) {
|
||||
break;
|
||||
}
|
||||
@@ -1665,7 +1566,7 @@ StringIsCmd(
|
||||
}
|
||||
break;
|
||||
case STR_IS_WIDE:
|
||||
if (TCL_OK == TclGetWideIntFromObj(NULL, objPtr, &w)) {
|
||||
if (TCL_OK == Tcl_GetWideIntFromObj(NULL, objPtr, &w)) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1802,16 +1703,8 @@ StringIsCmd(
|
||||
}
|
||||
end = string1 + length1;
|
||||
for (; string1 < end; string1 += length2, failat++) {
|
||||
int fullchar;
|
||||
length2 = TclUtfToUniChar(string1, &ch);
|
||||
fullchar = ch;
|
||||
#if TCL_UTF_MAX <= 4
|
||||
if (!length2) {
|
||||
length2 = TclUtfToUniChar(string1, &ch);
|
||||
fullchar = (((fullchar & 0x3ff) << 10) | (ch & 0x3ff)) + 0x10000;
|
||||
}
|
||||
#endif
|
||||
if (!chcomp(fullchar)) {
|
||||
if (!chcomp(ch)) {
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
@@ -2273,12 +2166,11 @@ StringReptCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
resultPtr = TclStringRepeat(interp, objv[1], count, TCL_STRING_IN_PLACE);
|
||||
if (resultPtr) {
|
||||
Tcl_SetObjResult(interp, resultPtr);
|
||||
return TCL_OK;
|
||||
if (TCL_OK != TclStringRepeat(interp, objv[1], count, &resultPtr)) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
return TCL_ERROR;
|
||||
Tcl_SetObjResult(interp, resultPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2306,50 +2198,42 @@ StringRplcCmd(
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
int first, last, length, end;
|
||||
Tcl_UniChar *ustring;
|
||||
int first, last, length;
|
||||
|
||||
if (objc < 4 || objc > 5) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "string first last ?string?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
length = Tcl_GetCharLength(objv[1]);
|
||||
end = length - 1;
|
||||
ustring = Tcl_GetUnicodeFromObj(objv[1], &length);
|
||||
length--;
|
||||
|
||||
if (TclGetIntForIndexM(interp, objv[2], end, &first) != TCL_OK ||
|
||||
TclGetIntForIndexM(interp, objv[3], end, &last) != TCL_OK){
|
||||
if (TclGetIntForIndexM(interp, objv[2], length, &first) != TCL_OK ||
|
||||
TclGetIntForIndexM(interp, objv[3], length, &last) != TCL_OK){
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following test screens out most empty substrings as
|
||||
* candidates for replacement. When they are detected, no
|
||||
* replacement is done, and the result is the original string,
|
||||
*/
|
||||
if ((last < 0) || /* Range ends before start of string */
|
||||
(first > end) || /* Range begins after end of string */
|
||||
(last < first)) { /* Range begins after it starts */
|
||||
|
||||
/*
|
||||
* BUT!!! when (end < 0) -- an empty original string -- we can
|
||||
* have (first <= end < 0 <= last) and an empty string is permitted
|
||||
* to be replaced.
|
||||
*/
|
||||
if ((last < first) || (last < 0) || (first > length)) {
|
||||
Tcl_SetObjResult(interp, objv[1]);
|
||||
} else {
|
||||
Tcl_Obj *resultPtr;
|
||||
|
||||
ustring = Tcl_GetUnicodeFromObj(objv[1], &length);
|
||||
length--;
|
||||
|
||||
if (first < 0) {
|
||||
first = 0;
|
||||
}
|
||||
if (last > end) {
|
||||
last = end;
|
||||
|
||||
resultPtr = Tcl_NewUnicodeObj(ustring, first);
|
||||
if (objc == 5) {
|
||||
Tcl_AppendObjToObj(resultPtr, objv[4]);
|
||||
}
|
||||
if (last < length) {
|
||||
Tcl_AppendUnicodeToObj(resultPtr, ustring + last + 1,
|
||||
length - last);
|
||||
}
|
||||
|
||||
resultPtr = TclStringReplace(interp, objv[1], first,
|
||||
last + 1 - first, (objc == 5) ? objv[4] : NULL,
|
||||
TCL_STRING_IN_PLACE);
|
||||
|
||||
Tcl_SetObjResult(interp, resultPtr);
|
||||
}
|
||||
return TCL_OK;
|
||||
@@ -2385,7 +2269,7 @@ StringRevCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
Tcl_SetObjResult(interp, TclStringReverse(objv[1], TCL_STRING_IN_PLACE));
|
||||
Tcl_SetObjResult(interp, TclStringObjReverse(objv[1]));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -2415,7 +2299,7 @@ StringStartCmd(
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
Tcl_UniChar ch = 0;
|
||||
Tcl_UniChar ch;
|
||||
const char *p, *string;
|
||||
int cur, index, length, numChars;
|
||||
|
||||
@@ -2476,7 +2360,7 @@ StringEndCmd(
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
Tcl_UniChar ch = 0;
|
||||
Tcl_UniChar ch;
|
||||
const char *p, *end, *string;
|
||||
int cur, index, length, numChars;
|
||||
|
||||
@@ -2834,6 +2718,7 @@ StringCatCmd(
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
int code;
|
||||
Tcl_Obj *objResultPtr;
|
||||
|
||||
if (objc < 2) {
|
||||
@@ -2843,15 +2728,23 @@ StringCatCmd(
|
||||
*/
|
||||
return TCL_OK;
|
||||
}
|
||||
if (objc == 2) {
|
||||
/*
|
||||
* Other trivial case, single arg, just return it.
|
||||
*/
|
||||
Tcl_SetObjResult(interp, objv[1]);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
objResultPtr = TclStringCat(interp, objc-1, objv+1, TCL_STRING_IN_PLACE);
|
||||
code = TclStringCatObjv(interp, /* inPlace */ 1, objc-1, objv+1,
|
||||
&objResultPtr);
|
||||
|
||||
if (objResultPtr) {
|
||||
if (code == TCL_OK) {
|
||||
Tcl_SetObjResult(interp, objResultPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
return TCL_ERROR;
|
||||
return code;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3220,7 +3113,8 @@ StringTrimCmd(
|
||||
}
|
||||
string1 = TclGetStringFromObj(objv[1], &length1);
|
||||
|
||||
triml = TclTrim(string1, length1, string2, length2, &trimr);
|
||||
triml = TclTrimLeft(string1, length1, string2, length2);
|
||||
trimr = TclTrimRight(string1 + triml, length1 - triml, string2, length2);
|
||||
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewStringObj(string1 + triml, length1 - triml - trimr));
|
||||
@@ -3525,7 +3419,7 @@ TclNRSwitchObjCmd(
|
||||
OPT_LAST
|
||||
};
|
||||
typedef int (*strCmpFn_t)(const char *, const char *);
|
||||
strCmpFn_t strCmpFn = TclUtfCmp;
|
||||
strCmpFn_t strCmpFn = strcmp;
|
||||
|
||||
mode = OPT_EXACT;
|
||||
foundmode = 0;
|
||||
@@ -4115,7 +4009,7 @@ Tcl_TimeObjCmd(
|
||||
start = TclpGetWideClicks();
|
||||
#endif
|
||||
while (i-- > 0) {
|
||||
result = Tcl_EvalObjEx(interp, objPtr, 0);
|
||||
result = TclEvalObjEx(interp, objPtr, 0, NULL, 0);
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -4152,6 +4046,351 @@ Tcl_TimeObjCmd(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Tcl_TimeRateObjCmd --
|
||||
*
|
||||
* This object-based procedure is invoked to process the "timerate" Tcl
|
||||
* command.
|
||||
* This is similar to command "time", except the execution limited by
|
||||
* given time (in milliseconds) instead of repetition count.
|
||||
*
|
||||
* Example:
|
||||
* timerate {after 5} 1000 ; # equivalent for `time {after 5} [expr 1000/5]`
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl object result.
|
||||
*
|
||||
* Side effects:
|
||||
* See the user documentation.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
Tcl_TimeRateObjCmd(
|
||||
ClientData dummy, /* Not used. */
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
int objc, /* Number of arguments. */
|
||||
Tcl_Obj *const objv[]) /* Argument objects. */
|
||||
{
|
||||
static
|
||||
double measureOverhead = 0; /* global measure-overhead */
|
||||
double overhead = -1; /* given measure-overhead */
|
||||
register Tcl_Obj *objPtr;
|
||||
register int result, i;
|
||||
Tcl_Obj *calibrate = NULL, *direct = NULL;
|
||||
Tcl_WideInt count = 0; /* Holds repetition count */
|
||||
Tcl_WideInt maxms = -0x7FFFFFFFFFFFFFFFL;
|
||||
/* Maximal running time (in milliseconds) */
|
||||
Tcl_WideInt threshold = 1; /* Current threshold for check time (faster
|
||||
* repeat count without time check) */
|
||||
Tcl_WideInt maxIterTm = 1; /* Max time of some iteration as max threshold
|
||||
* additionally avoid divide to zero (never < 1) */
|
||||
register Tcl_WideInt start, middle, stop;
|
||||
#ifndef TCL_WIDE_CLICKS
|
||||
Tcl_Time now;
|
||||
#endif
|
||||
|
||||
static const char *const options[] = {
|
||||
"-direct", "-overhead", "-calibrate", "--", NULL
|
||||
};
|
||||
enum options {
|
||||
TMRT_EV_DIRECT, TMRT_OVERHEAD, TMRT_CALIBRATE, TMRT_LAST
|
||||
};
|
||||
|
||||
NRE_callback *rootPtr;
|
||||
ByteCode *codePtr = NULL;
|
||||
|
||||
for (i = 1; i < objc - 1; i++) {
|
||||
int index;
|
||||
if (Tcl_GetIndexFromObj(NULL, objv[i], options, "option", TCL_EXACT,
|
||||
&index) != TCL_OK) {
|
||||
break;
|
||||
}
|
||||
if (index == TMRT_LAST) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
switch (index) {
|
||||
case TMRT_EV_DIRECT:
|
||||
direct = objv[i];
|
||||
break;
|
||||
case TMRT_OVERHEAD:
|
||||
if (++i >= objc - 1) {
|
||||
goto usage;
|
||||
}
|
||||
if (Tcl_GetDoubleFromObj(interp, objv[i], &overhead) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
break;
|
||||
case TMRT_CALIBRATE:
|
||||
calibrate = objv[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= objc || i < objc-2) {
|
||||
usage:
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?-direct? ?-calibrate? ?-overhead double? command ?time?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
objPtr = objv[i++];
|
||||
if (i < objc) {
|
||||
result = TclGetWideIntFromObj(interp, objv[i], &maxms);
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/* if calibrate */
|
||||
if (calibrate) {
|
||||
|
||||
/* if no time specified for the calibration */
|
||||
if (maxms == -0x7FFFFFFFFFFFFFFFL) {
|
||||
Tcl_Obj *clobjv[6];
|
||||
Tcl_WideInt maxCalTime = 5000;
|
||||
double lastMeasureOverhead = measureOverhead;
|
||||
|
||||
clobjv[0] = objv[0];
|
||||
i = 1;
|
||||
if (direct) {
|
||||
clobjv[i++] = direct;
|
||||
}
|
||||
clobjv[i++] = objPtr;
|
||||
|
||||
/* reset last measurement overhead */
|
||||
measureOverhead = (double)0;
|
||||
|
||||
/* self-call with 100 milliseconds to warm-up,
|
||||
* before entering the calibration cycle */
|
||||
TclNewLongObj(clobjv[i], 100);
|
||||
Tcl_IncrRefCount(clobjv[i]);
|
||||
result = Tcl_TimeRateObjCmd(dummy, interp, i+1, clobjv);
|
||||
Tcl_DecrRefCount(clobjv[i]);
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
i--;
|
||||
clobjv[i++] = calibrate;
|
||||
clobjv[i++] = objPtr;
|
||||
|
||||
/* set last measurement overhead to max */
|
||||
measureOverhead = (double)0x7FFFFFFFFFFFFFFFL;
|
||||
|
||||
/* calibration cycle until it'll be preciser */
|
||||
maxms = -1000;
|
||||
do {
|
||||
lastMeasureOverhead = measureOverhead;
|
||||
TclNewLongObj(clobjv[i], (int)maxms);
|
||||
Tcl_IncrRefCount(clobjv[i]);
|
||||
result = Tcl_TimeRateObjCmd(dummy, interp, i+1, clobjv);
|
||||
Tcl_DecrRefCount(clobjv[i]);
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
maxCalTime += maxms;
|
||||
/* increase maxms for preciser calibration */
|
||||
maxms -= (-maxms / 4);
|
||||
/* as long as new value more as 0.05% better */
|
||||
} while ( (measureOverhead >= lastMeasureOverhead
|
||||
|| measureOverhead / lastMeasureOverhead <= 0.9995)
|
||||
&& maxCalTime > 0
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
if (maxms == 0) {
|
||||
/* reset last measurement overhead */
|
||||
measureOverhead = 0;
|
||||
Tcl_SetObjResult(interp, Tcl_NewLongObj(0));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/* if time is negative - make current overhead more precise */
|
||||
if (maxms > 0) {
|
||||
/* set last measurement overhead to max */
|
||||
measureOverhead = (double)0x7FFFFFFFFFFFFFFFL;
|
||||
} else {
|
||||
maxms = -maxms;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (maxms == -0x7FFFFFFFFFFFFFFFL) {
|
||||
maxms = 1000;
|
||||
}
|
||||
if (overhead == -1) {
|
||||
overhead = measureOverhead;
|
||||
}
|
||||
|
||||
/* be sure that resetting of result will not smudge the further measurement */
|
||||
Tcl_ResetResult(interp);
|
||||
|
||||
/* compile object */
|
||||
if (!direct) {
|
||||
if (TclInterpReady(interp) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
codePtr = TclCompileObj(interp, objPtr, NULL, 0);
|
||||
TclPreserveByteCode(codePtr);
|
||||
}
|
||||
|
||||
/* get start and stop time */
|
||||
#ifdef TCL_WIDE_CLICKS
|
||||
start = middle = TclpGetWideClicks();
|
||||
/* time to stop execution (in wide clicks) */
|
||||
stop = start + (maxms * 1000 / TclpWideClickInMicrosec());
|
||||
#else
|
||||
Tcl_GetTime(&now);
|
||||
start = now.sec; start *= 1000000; start += now.usec;
|
||||
middle = start;
|
||||
/* time to stop execution (in microsecs) */
|
||||
stop = start + maxms * 1000;
|
||||
#endif
|
||||
|
||||
/* start measurement */
|
||||
while (1) {
|
||||
/* eval single iteration */
|
||||
count++;
|
||||
|
||||
if (!direct) {
|
||||
/* precompiled */
|
||||
rootPtr = TOP_CB(interp);
|
||||
result = TclNRExecuteByteCode(interp, codePtr);
|
||||
result = TclNRRunCallbacks(interp, result, rootPtr);
|
||||
} else {
|
||||
/* eval */
|
||||
result = TclEvalObjEx(interp, objPtr, 0, NULL, 0);
|
||||
}
|
||||
if (result != TCL_OK) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* don't check time up to threshold */
|
||||
if (--threshold > 0) continue;
|
||||
|
||||
/* check stop time reached, estimate new threshold */
|
||||
#ifdef TCL_WIDE_CLICKS
|
||||
middle = TclpGetWideClicks();
|
||||
#else
|
||||
Tcl_GetTime(&now);
|
||||
middle = now.sec; middle *= 1000000; middle += now.usec;
|
||||
#endif
|
||||
if (middle >= stop) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* don't calculate threshold by few iterations, because sometimes
|
||||
* first iteration(s) can be too fast (cached, delayed clean up, etc) */
|
||||
if (count < 10) {
|
||||
threshold = 1; continue;
|
||||
}
|
||||
|
||||
/* average iteration time in microsecs */
|
||||
threshold = (middle - start) / count;
|
||||
if (threshold > maxIterTm) {
|
||||
maxIterTm = threshold;
|
||||
}
|
||||
/* as relation between remaining time and time since last check */
|
||||
threshold = ((stop - middle) / maxIterTm) / 4;
|
||||
if (threshold > 100000) { /* fix for too large threshold */
|
||||
threshold = 100000;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Tcl_Obj *objarr[8], **objs = objarr;
|
||||
Tcl_WideInt val;
|
||||
const char *fmt;
|
||||
|
||||
middle -= start; /* execution time in microsecs */
|
||||
|
||||
#ifdef TCL_WIDE_CLICKS
|
||||
/* convert execution time in wide clicks to microsecs */
|
||||
middle *= TclpWideClickInMicrosec();
|
||||
#endif
|
||||
|
||||
/* if not calibrate */
|
||||
if (!calibrate) {
|
||||
/* minimize influence of measurement overhead */
|
||||
if (overhead > 0) {
|
||||
/* estimate the time of overhead (microsecs) */
|
||||
Tcl_WideInt curOverhead = overhead * count;
|
||||
if (middle > curOverhead) {
|
||||
middle -= curOverhead;
|
||||
} else {
|
||||
middle = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* calibration - obtaining new measurement overhead */
|
||||
if (measureOverhead > (double)middle / count) {
|
||||
measureOverhead = (double)middle / count;
|
||||
}
|
||||
objs[0] = Tcl_NewDoubleObj(measureOverhead);
|
||||
TclNewLiteralStringObj(objs[1], "\xC2\xB5s/#-overhead"); /* mics */
|
||||
objs += 2;
|
||||
}
|
||||
|
||||
val = middle / count; /* microsecs per iteration */
|
||||
if (val >= 1000000) {
|
||||
objs[0] = Tcl_NewWideIntObj(val);
|
||||
} else {
|
||||
if (val < 10) { fmt = "%.6f"; } else
|
||||
if (val < 100) { fmt = "%.4f"; } else
|
||||
if (val < 1000) { fmt = "%.3f"; } else
|
||||
if (val < 10000) { fmt = "%.2f"; } else
|
||||
{ fmt = "%.1f"; };
|
||||
objs[0] = Tcl_ObjPrintf(fmt, ((double)middle)/count);
|
||||
}
|
||||
|
||||
objs[2] = Tcl_NewWideIntObj(count); /* iterations */
|
||||
|
||||
/* calculate speed as rate (count) per sec */
|
||||
if (!middle) middle++; /* +1 ms, just to avoid divide by zero */
|
||||
if (count < (0x7FFFFFFFFFFFFFFFL / 1000000)) {
|
||||
val = (count * 1000000) / middle;
|
||||
if (val < 100000) {
|
||||
if (val < 100) { fmt = "%.3f"; } else
|
||||
if (val < 1000) { fmt = "%.2f"; } else
|
||||
{ fmt = "%.1f"; };
|
||||
objs[4] = Tcl_ObjPrintf(fmt, ((double)(count * 1000000)) / middle);
|
||||
} else {
|
||||
objs[4] = Tcl_NewWideIntObj(val);
|
||||
}
|
||||
} else {
|
||||
objs[4] = Tcl_NewWideIntObj((count / middle) * 1000000);
|
||||
}
|
||||
|
||||
/* estimated net execution time (in millisecs) */
|
||||
if (!calibrate) {
|
||||
objs[6] = Tcl_ObjPrintf("%.3f", (double)middle / 1000);
|
||||
TclNewLiteralStringObj(objs[7], "nett-ms");
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct the result as a list because many programs have always parsed
|
||||
* as such (extracting the first element, typically).
|
||||
*/
|
||||
|
||||
TclNewLiteralStringObj(objs[1], "\xC2\xB5s/#"); /* mics/# */
|
||||
TclNewLiteralStringObj(objs[3], "#");
|
||||
TclNewLiteralStringObj(objs[5], "#/sec");
|
||||
Tcl_SetObjResult(interp, Tcl_NewListObj(8, objarr));
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
if (codePtr != NULL) {
|
||||
TclReleaseByteCode(codePtr);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -4288,7 +4527,7 @@ TclNRTryObjCmd(
|
||||
}
|
||||
|
||||
info[0] = objv[i]; /* type */
|
||||
TclNewIntObj(info[1], code); /* returnCode */
|
||||
TclNewLongObj(info[1], code); /* returnCode */
|
||||
if (info[2] == NULL) { /* errorCodePrefix */
|
||||
TclNewObj(info[2]);
|
||||
}
|
||||
|
||||
+3
-15
@@ -322,22 +322,11 @@ TclCompileArraySetCmd(
|
||||
*/
|
||||
|
||||
if (isDataValid && !isDataEven) {
|
||||
/* Abandon custom compile and let invocation raise the error */
|
||||
code = TclCompileBasic2ArgCmd(interp, parsePtr, cmdPtr, envPtr);
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* We used to compile to the bytecode that would throw the error,
|
||||
* but that was wrong because it would not invoke the array trace
|
||||
* on the variable.
|
||||
*
|
||||
PushStringLiteral(envPtr, "list must have an even number of elements");
|
||||
PushStringLiteral(envPtr, "-errorcode {TCL ARGUMENT FORMAT}");
|
||||
TclEmitInstInt4(INST_RETURN_IMM, TCL_ERROR, envPtr);
|
||||
TclEmitInt4( 0, envPtr);
|
||||
goto done;
|
||||
*
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -415,10 +404,6 @@ TclCompileArraySetCmd(
|
||||
* Start issuing instructions to write to the array.
|
||||
*/
|
||||
|
||||
TclEmitInstInt4(INST_ARRAY_EXISTS_IMM, localIndex, envPtr);
|
||||
TclEmitInstInt1(INST_JUMP_TRUE1, 7, envPtr);
|
||||
TclEmitInstInt4(INST_ARRAY_MAKE_IMM, localIndex, envPtr);
|
||||
|
||||
CompileWord(envPtr, dataTokenPtr, interp, 2);
|
||||
if (!isDataLiteral || !isDataValid) {
|
||||
/*
|
||||
@@ -443,6 +428,9 @@ TclCompileArraySetCmd(
|
||||
TclStoreInt1AtPtr(fwd, envPtr->codeStart+offsetFwd+1);
|
||||
}
|
||||
|
||||
TclEmitInstInt4(INST_ARRAY_EXISTS_IMM, localIndex, envPtr);
|
||||
TclEmitInstInt1(INST_JUMP_TRUE1, 7, envPtr);
|
||||
TclEmitInstInt4(INST_ARRAY_MAKE_IMM, localIndex, envPtr);
|
||||
TclEmitInstInt4(INST_FOREACH_START, infoIndex, envPtr);
|
||||
offsetBack = CurrentOffset(envPtr);
|
||||
Emit14Inst( INST_LOAD_SCALAR, keyVar, envPtr);
|
||||
|
||||
+257
-182
@@ -28,39 +28,56 @@ static void CompileReturnInternal(CompileEnv *envPtr,
|
||||
static int IndexTailVarIfKnown(Tcl_Interp *interp,
|
||||
Tcl_Token *varTokenPtr, CompileEnv *envPtr);
|
||||
|
||||
#define INDEX_END (-2)
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclGetIndexFromToken --
|
||||
* GetIndexFromToken --
|
||||
*
|
||||
* Parse a token to determine if an index value is known at
|
||||
* compile time.
|
||||
* Parse a token and get the encoded version of the index (as understood
|
||||
* by TEBC), assuming it is at all knowable at compile time. Only handles
|
||||
* indices that are integers or 'end' or 'end-integer'.
|
||||
*
|
||||
* Returns:
|
||||
* TCL_OK if parsing succeeded, and TCL_ERROR if it failed.
|
||||
*
|
||||
* Side effects:
|
||||
* When TCL_OK is returned, the encoded index value is written
|
||||
* to *index.
|
||||
* Sets *index to the index value if successful.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TclGetIndexFromToken(
|
||||
static inline int
|
||||
GetIndexFromToken(
|
||||
Tcl_Token *tokenPtr,
|
||||
int before,
|
||||
int after,
|
||||
int *indexPtr)
|
||||
int *index)
|
||||
{
|
||||
Tcl_Obj *tmpObj = Tcl_NewObj();
|
||||
int result = TCL_ERROR;
|
||||
int result, idx;
|
||||
|
||||
if (TclWordKnownAtCompileTime(tokenPtr, tmpObj)) {
|
||||
result = TclIndexEncode(NULL, tmpObj, before, after, indexPtr);
|
||||
if (!TclWordKnownAtCompileTime(tokenPtr, tmpObj)) {
|
||||
Tcl_DecrRefCount(tmpObj);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
result = TclGetIntFromObj(NULL, tmpObj, &idx);
|
||||
if (result == TCL_OK) {
|
||||
if (idx < 0) {
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
} else {
|
||||
result = TclGetIntForIndexM(NULL, tmpObj, INDEX_END, &idx);
|
||||
if (result == TCL_OK && idx > INDEX_END) {
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
}
|
||||
Tcl_DecrRefCount(tmpObj);
|
||||
|
||||
if (result == TCL_OK) {
|
||||
*index = idx;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -127,7 +144,7 @@ TclCompileGlobalCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/* TODO: Consider what value can pass through the
|
||||
/* TODO: Consider what value can pass throug the
|
||||
* IndexTailVarIfKnown() screen. Full CompileWord()
|
||||
* likely does not apply here. Push known value instead. */
|
||||
CompileWord(envPtr, varTokenPtr, interp, i);
|
||||
@@ -1036,7 +1053,7 @@ TclCompileLassignCmd(
|
||||
*/
|
||||
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, idx, envPtr);
|
||||
TclEmitInt4( TCL_INDEX_END, envPtr);
|
||||
TclEmitInt4( INDEX_END, envPtr);
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -1087,14 +1104,14 @@ TclCompileLindexCmd(
|
||||
}
|
||||
|
||||
idxTokenPtr = TokenAfter(valTokenPtr);
|
||||
if (TclGetIndexFromToken(idxTokenPtr, TCL_INDEX_BEFORE, TCL_INDEX_BEFORE,
|
||||
&idx) == TCL_OK) {
|
||||
if (GetIndexFromToken(idxTokenPtr, &idx) == TCL_OK) {
|
||||
/*
|
||||
* The idxTokenPtr parsed as a valid index value and was
|
||||
* encoded as expected by INST_LIST_INDEX_IMM.
|
||||
*
|
||||
* NOTE: that we rely on indexing before a list producing the
|
||||
* same result as indexing after a list.
|
||||
* All checks have been completed, and we have exactly one of 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.
|
||||
*/
|
||||
|
||||
CompileWord(envPtr, valTokenPtr, interp, 1);
|
||||
@@ -1241,7 +1258,7 @@ TclCompileListCmd(
|
||||
|
||||
if (concat && numWords == 2) {
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr);
|
||||
TclEmitInt4( TCL_INDEX_END, envPtr);
|
||||
TclEmitInt4( INDEX_END, envPtr);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -1315,25 +1332,21 @@ TclCompileLrangeCmd(
|
||||
}
|
||||
listTokenPtr = TokenAfter(parsePtr->tokenPtr);
|
||||
|
||||
tokenPtr = TokenAfter(listTokenPtr);
|
||||
if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_START, TCL_INDEX_AFTER,
|
||||
&idx1) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
/*
|
||||
* Token was an index value, and we treat all "first" indices
|
||||
* before the list same as the start of the list.
|
||||
* Parse the indices. Will only compile if both are constants and not an
|
||||
* _integer_ less than zero (since we reserve negative indices here for
|
||||
* end-relative indexing) or an end-based index greater than 'end' itself.
|
||||
*/
|
||||
|
||||
tokenPtr = TokenAfter(listTokenPtr);
|
||||
if (GetIndexFromToken(tokenPtr, &idx1) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_BEFORE, TCL_INDEX_END,
|
||||
&idx2) != TCL_OK) {
|
||||
if (GetIndexFromToken(tokenPtr, &idx2) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
/*
|
||||
* Token was an index value, and we treat all "last" indices
|
||||
* after the list same as the end of the list.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Issue instructions. It's not safe to skip doing the LIST_RANGE, as
|
||||
@@ -1383,30 +1396,21 @@ TclCompileLinsertCmd(
|
||||
*/
|
||||
|
||||
tokenPtr = TokenAfter(listTokenPtr);
|
||||
|
||||
/*
|
||||
* NOTE: This command treats all inserts at indices before the list
|
||||
* the same as inserts at the start of the list, and all inserts
|
||||
* after the list the same as inserts at the end of the list. We
|
||||
* make that transformation here so we can use the optimized bytecode
|
||||
* as much as possible.
|
||||
*/
|
||||
if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_START, TCL_INDEX_END,
|
||||
&idx) != TCL_OK) {
|
||||
if (GetIndexFromToken(tokenPtr, &idx) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* There are four main cases. If there are no values to insert, this is
|
||||
* just a confirm-listiness check. If the index is '0', this is a prepend.
|
||||
* If the index is 'end' (== TCL_INDEX_END), this is an append. Otherwise,
|
||||
* If the index is 'end' (== INDEX_END), this is an append. Otherwise,
|
||||
* this is a splice (== split, insert values as list, concat-3).
|
||||
*/
|
||||
|
||||
CompileWord(envPtr, listTokenPtr, interp, 1);
|
||||
if (parsePtr->numWords == 3) {
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr);
|
||||
TclEmitInt4( TCL_INDEX_END, envPtr);
|
||||
TclEmitInt4( INDEX_END, envPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -1416,25 +1420,13 @@ TclCompileLinsertCmd(
|
||||
}
|
||||
TclEmitInstInt4( INST_LIST, i-3, envPtr);
|
||||
|
||||
if (idx == TCL_INDEX_START) {
|
||||
if (idx == 0 /*start*/) {
|
||||
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
|
||||
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
|
||||
} else if (idx == TCL_INDEX_END) {
|
||||
} else if (idx == INDEX_END /*end*/) {
|
||||
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
|
||||
} else {
|
||||
/*
|
||||
* Here we handle two ranges for idx. First when idx > 0, we
|
||||
* want the first half of the split to end at index idx-1 and
|
||||
* the second half to start at index idx.
|
||||
* Second when idx < TCL_INDEX_END, indicating "end-N" indexing,
|
||||
* we want the first half of the split to end at index end-N and
|
||||
* the second half to start at index end-N+1. We accomplish this
|
||||
* with a pre-adjustment of the end-N value.
|
||||
* The root of this is that the commands [lrange] and [linsert]
|
||||
* differ in their interpretation of the "end" index.
|
||||
*/
|
||||
|
||||
if (idx < TCL_INDEX_END) {
|
||||
if (idx < 0) {
|
||||
idx++;
|
||||
}
|
||||
TclEmitInstInt4( INST_OVER, 1, envPtr);
|
||||
@@ -1442,7 +1434,7 @@ TclCompileLinsertCmd(
|
||||
TclEmitInt4( idx-1, envPtr);
|
||||
TclEmitInstInt4( INST_REVERSE, 3, envPtr);
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, idx, envPtr);
|
||||
TclEmitInt4( TCL_INDEX_END, envPtr);
|
||||
TclEmitInt4( INDEX_END, envPtr);
|
||||
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
|
||||
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
|
||||
}
|
||||
@@ -1472,167 +1464,250 @@ TclCompileLreplaceCmd(
|
||||
{
|
||||
Tcl_Token *tokenPtr, *listTokenPtr;
|
||||
DefineLineInformation; /* TIP #280 */
|
||||
Tcl_Obj *tmpObj;
|
||||
int idx1, idx2, i, offset, offset2;
|
||||
int emptyPrefix=1, suffixStart = 0;
|
||||
|
||||
if (parsePtr->numWords < 4) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
listTokenPtr = TokenAfter(parsePtr->tokenPtr);
|
||||
|
||||
/*
|
||||
* Parse the indices. Will only compile if both are constants and not an
|
||||
* _integer_ less than zero (since we reserve negative indices here for
|
||||
* end-relative indexing) or an end-based index greater than 'end' itself.
|
||||
*/
|
||||
|
||||
tokenPtr = TokenAfter(listTokenPtr);
|
||||
if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_START, TCL_INDEX_AFTER,
|
||||
&idx1) != TCL_OK) {
|
||||
if (GetIndexFromToken(tokenPtr, &idx1) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_BEFORE, TCL_INDEX_END,
|
||||
&idx2) != TCL_OK) {
|
||||
if (GetIndexFromToken(tokenPtr, &idx2) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* idx1, idx2 are the conventional encoded forms of the tokens parsed
|
||||
* as all forms of index values. Values of idx1 that come before the
|
||||
* list are treated the same as if they were the start of the list.
|
||||
* Values of idx2 that come after the list are treated the same as if
|
||||
* they were the end of the list.
|
||||
*/
|
||||
|
||||
if (idx1 == TCL_INDEX_AFTER) {
|
||||
/*
|
||||
* [lreplace] treats idx1 value end+1 differently from end+2, etc.
|
||||
* The operand encoding cannot distinguish them, so we must bail
|
||||
* out to direct evaluation.
|
||||
*/
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* General structure of the [lreplace] result is
|
||||
* prefix replacement suffix
|
||||
* In a few cases we can predict various parts will be empty and
|
||||
* take advantage.
|
||||
* idx1, idx2 are now in canonical form:
|
||||
*
|
||||
* The proper suffix begins with the greater of indices idx1 or
|
||||
* idx2 + 1. If we cannot tell at compile time which is greater,
|
||||
* we must defer to direct evaluation.
|
||||
* - integer: [0,len+1]
|
||||
* - end index: INDEX_END
|
||||
* - -ive offset: INDEX_END-[len-1,0]
|
||||
* - +ive offset: INDEX_END+1
|
||||
*/
|
||||
|
||||
if (idx2 == TCL_INDEX_BEFORE) {
|
||||
suffixStart = idx1;
|
||||
} else if (idx2 == TCL_INDEX_END) {
|
||||
suffixStart = TCL_INDEX_AFTER;
|
||||
} else if (((idx2 < TCL_INDEX_END) && (idx1 <= TCL_INDEX_END))
|
||||
|| ((idx2 >= TCL_INDEX_START) && (idx1 >= TCL_INDEX_START))) {
|
||||
suffixStart = (idx1 > idx2 + 1) ? idx1 : idx2 + 1;
|
||||
} else {
|
||||
/*
|
||||
* Compilation fails when one index is end-based but the other isn't.
|
||||
* Fixing this will require more bytecodes, but this is a workaround for
|
||||
* now. [Bug 47ac84309b]
|
||||
*/
|
||||
|
||||
if ((idx1 <= INDEX_END) != (idx2 <= INDEX_END)) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/* All paths start with computing/pushing the original value. */
|
||||
if (idx2 != INDEX_END && idx2 >= 0 && idx2 < idx1) {
|
||||
idx2 = idx1 - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Work out what this [lreplace] is actually doing.
|
||||
*/
|
||||
|
||||
tmpObj = NULL;
|
||||
CompileWord(envPtr, listTokenPtr, interp, 1);
|
||||
|
||||
/*
|
||||
* Push all the replacement values next so any errors raised in
|
||||
* creating them get raised first.
|
||||
*/
|
||||
if (parsePtr->numWords > 4) {
|
||||
/* Push the replacement arguments */
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
for (i=4 ; i<parsePtr->numWords ; i++) {
|
||||
CompileWord(envPtr, tokenPtr, interp, i);
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
}
|
||||
|
||||
/* Make a list of them... */
|
||||
TclEmitInstInt4( INST_LIST, i - 4, envPtr);
|
||||
|
||||
emptyPrefix = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* [lreplace] raises an error when idx1 points after the list, but
|
||||
* only when the list is not empty. This is maximum stupidity.
|
||||
*
|
||||
* TODO: TIP this nonsense away!
|
||||
*/
|
||||
if (idx1 >= TCL_INDEX_START) {
|
||||
if (emptyPrefix) {
|
||||
TclEmitOpcode( INST_DUP, envPtr);
|
||||
if (parsePtr->numWords == 4) {
|
||||
if (idx1 == 0) {
|
||||
if (idx2 == INDEX_END) {
|
||||
goto dropAll;
|
||||
}
|
||||
idx1 = idx2 + 1;
|
||||
idx2 = INDEX_END;
|
||||
goto dropEnd;
|
||||
} else if (idx2 == INDEX_END) {
|
||||
idx2 = idx1 - 1;
|
||||
idx1 = 0;
|
||||
goto dropEnd;
|
||||
} else {
|
||||
TclEmitInstInt4( INST_OVER, 1, envPtr);
|
||||
if (idx2 < idx1) {
|
||||
idx2 = idx1 - 1;
|
||||
}
|
||||
if (idx1 > 0) {
|
||||
tmpObj = Tcl_NewIntObj(idx1);
|
||||
Tcl_IncrRefCount(tmpObj);
|
||||
}
|
||||
goto dropRange;
|
||||
}
|
||||
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
|
||||
TclEmitOpcode( INST_DUP, envPtr);
|
||||
offset = CurrentOffset(envPtr);
|
||||
TclEmitInstInt1( INST_JUMP_FALSE1, 0, envPtr);
|
||||
}
|
||||
|
||||
/* List is not empty */
|
||||
TclEmitPush(TclAddLiteralObj(envPtr, Tcl_NewIntObj(idx1),
|
||||
NULL), envPtr);
|
||||
TclEmitOpcode( INST_GT, envPtr);
|
||||
offset2 = CurrentOffset(envPtr);
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
for (i=4 ; i<parsePtr->numWords ; i++) {
|
||||
CompileWord(envPtr, tokenPtr, interp, i);
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
}
|
||||
TclEmitInstInt4( INST_LIST, i - 4, envPtr);
|
||||
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
|
||||
if (idx1 == 0) {
|
||||
if (idx2 == INDEX_END) {
|
||||
goto replaceAll;
|
||||
}
|
||||
idx1 = idx2 + 1;
|
||||
idx2 = INDEX_END;
|
||||
goto replaceHead;
|
||||
} else if (idx2 == INDEX_END) {
|
||||
idx2 = idx1 - 1;
|
||||
idx1 = 0;
|
||||
goto replaceTail;
|
||||
} else {
|
||||
if (idx2 < idx1) {
|
||||
idx2 = idx1 - 1;
|
||||
}
|
||||
if (idx1 > 0) {
|
||||
tmpObj = Tcl_NewIntObj(idx1);
|
||||
Tcl_IncrRefCount(tmpObj);
|
||||
}
|
||||
goto replaceRange;
|
||||
}
|
||||
|
||||
/*
|
||||
* Issue instructions to perform the operations relating to configurations
|
||||
* that just drop. The only argument pushed on the stack is the list to
|
||||
* operate on.
|
||||
*/
|
||||
|
||||
dropAll: /* This just ensures the arg is a list. */
|
||||
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
|
||||
TclEmitOpcode( INST_POP, envPtr);
|
||||
PushStringLiteral(envPtr, "");
|
||||
goto done;
|
||||
|
||||
dropEnd:
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, idx1, envPtr);
|
||||
TclEmitInt4( idx2, envPtr);
|
||||
goto done;
|
||||
|
||||
dropRange:
|
||||
if (tmpObj != NULL) {
|
||||
/*
|
||||
* Emit bytecode to check the list length.
|
||||
*/
|
||||
|
||||
TclEmitOpcode( INST_DUP, envPtr);
|
||||
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
|
||||
TclEmitPush(TclAddLiteralObj(envPtr, tmpObj, NULL), envPtr);
|
||||
TclEmitOpcode( INST_GE, envPtr);
|
||||
offset = CurrentOffset(envPtr);
|
||||
TclEmitInstInt1( INST_JUMP_TRUE1, 0, envPtr);
|
||||
|
||||
/* Idx1 >= list length ===> raise an error */
|
||||
/*
|
||||
* Emit an error if we've been given an empty list.
|
||||
*/
|
||||
|
||||
TclEmitOpcode( INST_DUP, envPtr);
|
||||
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
|
||||
offset2 = CurrentOffset(envPtr);
|
||||
TclEmitInstInt1( INST_JUMP_FALSE1, 0, envPtr);
|
||||
TclEmitPush(TclAddLiteralObj(envPtr, Tcl_ObjPrintf(
|
||||
"list doesn't contain element %d", idx1), NULL), envPtr);
|
||||
CompileReturnInternal(envPtr, INST_RETURN_IMM, TCL_ERROR, 0,
|
||||
Tcl_ObjPrintf("-errorcode {TCL OPERATION LREPLACE BADIDX}"));
|
||||
TclStoreInt1AtPtr(CurrentOffset(envPtr) - offset,
|
||||
envPtr->codeStart + offset + 1);
|
||||
TclEmitOpcode( INST_POP, envPtr);
|
||||
TclStoreInt1AtPtr(CurrentOffset(envPtr) - offset2,
|
||||
envPtr->codeStart + offset2 + 1);
|
||||
TclAdjustStackDepth(-1, envPtr);
|
||||
}
|
||||
TclEmitOpcode( INST_DUP, envPtr);
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr);
|
||||
TclEmitInt4( idx1 - 1, envPtr);
|
||||
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, idx2 + 1, envPtr);
|
||||
TclEmitInt4( INDEX_END, envPtr);
|
||||
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
|
||||
goto done;
|
||||
|
||||
if ((idx1 == suffixStart) && (parsePtr->numWords == 4)) {
|
||||
/*
|
||||
* Issue instructions to perform the operations relating to configurations
|
||||
* that do real replacement. All arguments are pushed and assembled into a
|
||||
* pair: the list of values to replace with, and the list to do the
|
||||
* surgery on.
|
||||
*/
|
||||
|
||||
replaceAll:
|
||||
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
|
||||
TclEmitOpcode( INST_POP, envPtr);
|
||||
goto done;
|
||||
|
||||
replaceHead:
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, idx1, envPtr);
|
||||
TclEmitInt4( idx2, envPtr);
|
||||
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
|
||||
goto done;
|
||||
|
||||
replaceTail:
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, idx1, envPtr);
|
||||
TclEmitInt4( idx2, envPtr);
|
||||
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
|
||||
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
|
||||
goto done;
|
||||
|
||||
replaceRange:
|
||||
if (tmpObj != NULL) {
|
||||
/*
|
||||
* This is a "no-op". Example: [lreplace {a b c} 2 0]
|
||||
* We still do a list operation to get list-verification
|
||||
* and canonicalization side effects.
|
||||
* Emit bytecode to check the list length.
|
||||
*/
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr);
|
||||
TclEmitInt4( TCL_INDEX_END, envPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
if (idx1 != TCL_INDEX_START) {
|
||||
/* Prefix may not be empty; generate bytecode to push it */
|
||||
if (emptyPrefix) {
|
||||
TclEmitOpcode( INST_DUP, envPtr);
|
||||
} else {
|
||||
TclEmitInstInt4( INST_OVER, 1, envPtr);
|
||||
}
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr);
|
||||
TclEmitInt4( idx1 - 1, envPtr);
|
||||
if (!emptyPrefix) {
|
||||
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
|
||||
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
|
||||
}
|
||||
emptyPrefix = 0;
|
||||
}
|
||||
TclEmitOpcode( INST_DUP, envPtr);
|
||||
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
|
||||
|
||||
if (!emptyPrefix) {
|
||||
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
|
||||
}
|
||||
/*
|
||||
* Check the list length vs idx1.
|
||||
*/
|
||||
|
||||
if (suffixStart == TCL_INDEX_AFTER) {
|
||||
TclEmitOpcode( INST_POP, envPtr);
|
||||
if (emptyPrefix) {
|
||||
PushStringLiteral(envPtr, "");
|
||||
}
|
||||
} else {
|
||||
/* Suffix may not be empty; generate bytecode to push it */
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, suffixStart, envPtr);
|
||||
TclEmitInt4( TCL_INDEX_END, envPtr);
|
||||
if (!emptyPrefix) {
|
||||
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
|
||||
}
|
||||
}
|
||||
TclEmitPush(TclAddLiteralObj(envPtr, tmpObj, NULL), envPtr);
|
||||
TclEmitOpcode( INST_GE, envPtr);
|
||||
offset = CurrentOffset(envPtr);
|
||||
TclEmitInstInt1( INST_JUMP_TRUE1, 0, envPtr);
|
||||
|
||||
/*
|
||||
* Emit an error if we've been given an empty list.
|
||||
*/
|
||||
|
||||
TclEmitOpcode( INST_DUP, envPtr);
|
||||
TclEmitOpcode( INST_LIST_LENGTH, envPtr);
|
||||
offset2 = CurrentOffset(envPtr);
|
||||
TclEmitInstInt1( INST_JUMP_FALSE1, 0, envPtr);
|
||||
TclEmitPush(TclAddLiteralObj(envPtr, Tcl_ObjPrintf(
|
||||
"list doesn't contain element %d", idx1), NULL), envPtr);
|
||||
CompileReturnInternal(envPtr, INST_RETURN_IMM, TCL_ERROR, 0,
|
||||
Tcl_ObjPrintf("-errorcode {TCL OPERATION LREPLACE BADIDX}"));
|
||||
TclStoreInt1AtPtr(CurrentOffset(envPtr) - offset,
|
||||
envPtr->codeStart + offset + 1);
|
||||
TclStoreInt1AtPtr(CurrentOffset(envPtr) - offset2,
|
||||
envPtr->codeStart + offset2 + 1);
|
||||
TclAdjustStackDepth(-1, envPtr);
|
||||
}
|
||||
TclEmitOpcode( INST_DUP, envPtr);
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, 0, envPtr);
|
||||
TclEmitInt4( idx1 - 1, envPtr);
|
||||
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
|
||||
TclEmitInstInt4( INST_LIST_RANGE_IMM, idx2 + 1, envPtr);
|
||||
TclEmitInt4( INDEX_END, envPtr);
|
||||
TclEmitInstInt4( INST_REVERSE, 3, envPtr);
|
||||
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
|
||||
TclEmitInstInt4( INST_REVERSE, 2, envPtr);
|
||||
TclEmitOpcode( INST_LIST_CONCAT, envPtr);
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* Clean up the allocated memory.
|
||||
*/
|
||||
|
||||
done:
|
||||
if (tmpObj != NULL) {
|
||||
Tcl_DecrRefCount(tmpObj);
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
@@ -2858,7 +2933,7 @@ TclCompileVariableCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/* TODO: Consider what value can pass through the
|
||||
/* TODO: Consider what value can pass throug the
|
||||
* IndexTailVarIfKnown() screen. Full CompileWord()
|
||||
* likely does not apply here. Push known value instead. */
|
||||
CompileWord(envPtr, varTokenPtr, interp, i);
|
||||
|
||||
+146
-192
@@ -107,6 +107,58 @@ const AuxDataType tclJumptableInfoType = {
|
||||
#define INVOKE(name) \
|
||||
TclEmitInvoke(envPtr,INST_##name)
|
||||
|
||||
#define INDEX_END (-2)
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* GetIndexFromToken --
|
||||
*
|
||||
* Parse a token and get the encoded version of the index (as understood
|
||||
* by TEBC), assuming it is at all knowable at compile time. Only handles
|
||||
* indices that are integers or 'end' or 'end-integer'.
|
||||
*
|
||||
* Returns:
|
||||
* TCL_OK if parsing succeeded, and TCL_ERROR if it failed.
|
||||
*
|
||||
* Side effects:
|
||||
* Sets *index to the index value if successful.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static inline int
|
||||
GetIndexFromToken(
|
||||
Tcl_Token *tokenPtr,
|
||||
int *index)
|
||||
{
|
||||
Tcl_Obj *tmpObj = Tcl_NewObj();
|
||||
int result, idx;
|
||||
|
||||
if (!TclWordKnownAtCompileTime(tokenPtr, tmpObj)) {
|
||||
Tcl_DecrRefCount(tmpObj);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
result = TclGetIntFromObj(NULL, tmpObj, &idx);
|
||||
if (result == TCL_OK) {
|
||||
if (idx < 0) {
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
} else {
|
||||
result = TclGetIntForIndexM(NULL, tmpObj, INDEX_END, &idx);
|
||||
if (result == TCL_OK && idx > INDEX_END) {
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
}
|
||||
Tcl_DecrRefCount(tmpObj);
|
||||
|
||||
if (result == TCL_OK) {
|
||||
*index = idx;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -930,48 +982,22 @@ TclCompileStringRangeCmd(
|
||||
fromTokenPtr = TokenAfter(stringTokenPtr);
|
||||
toTokenPtr = TokenAfter(fromTokenPtr);
|
||||
|
||||
/* Every path must push the string argument */
|
||||
CompileWord(envPtr, stringTokenPtr, interp, 1);
|
||||
|
||||
/*
|
||||
* Parse the two indices.
|
||||
*/
|
||||
|
||||
if (TclGetIndexFromToken(fromTokenPtr, TCL_INDEX_START, TCL_INDEX_AFTER,
|
||||
&idx1) != TCL_OK) {
|
||||
if (GetIndexFromToken(fromTokenPtr, &idx1) != TCL_OK) {
|
||||
goto nonConstantIndices;
|
||||
}
|
||||
/*
|
||||
* Token parsed as an index expression. We treat all indices before
|
||||
* the string the same as the start of the string.
|
||||
*/
|
||||
|
||||
if (idx1 == TCL_INDEX_AFTER) {
|
||||
/* [string range $s end+1 $last] must be empty string */
|
||||
OP( POP);
|
||||
PUSH( "");
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
if (TclGetIndexFromToken(toTokenPtr, TCL_INDEX_BEFORE, TCL_INDEX_END,
|
||||
&idx2) != TCL_OK) {
|
||||
if (GetIndexFromToken(toTokenPtr, &idx2) != TCL_OK) {
|
||||
goto nonConstantIndices;
|
||||
}
|
||||
/*
|
||||
* Token parsed as an index expression. We treat all indices after
|
||||
* the string the same as the end of the string.
|
||||
*/
|
||||
if (idx2 == TCL_INDEX_BEFORE) {
|
||||
/* [string range $s $first -1] must be empty string */
|
||||
OP( POP);
|
||||
PUSH( "");
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Push the operand onto the stack and then the substring operation.
|
||||
*/
|
||||
|
||||
CompileWord(envPtr, stringTokenPtr, interp, 1);
|
||||
OP44( STR_RANGE_IMM, idx1, idx2);
|
||||
return TCL_OK;
|
||||
|
||||
@@ -980,6 +1006,7 @@ TclCompileStringRangeCmd(
|
||||
*/
|
||||
|
||||
nonConstantIndices:
|
||||
CompileWord(envPtr, stringTokenPtr, interp, 1);
|
||||
CompileWord(envPtr, fromTokenPtr, interp, 2);
|
||||
CompileWord(envPtr, toTokenPtr, interp, 3);
|
||||
OP( STR_RANGE);
|
||||
@@ -995,197 +1022,124 @@ TclCompileStringReplaceCmd(
|
||||
* compiled. */
|
||||
CompileEnv *envPtr) /* Holds the resulting instructions. */
|
||||
{
|
||||
Tcl_Token *tokenPtr, *valueTokenPtr;
|
||||
Tcl_Token *tokenPtr, *valueTokenPtr, *replacementTokenPtr = NULL;
|
||||
DefineLineInformation; /* TIP #280 */
|
||||
int first, last;
|
||||
int idx1, idx2;
|
||||
|
||||
if (parsePtr->numWords < 4 || parsePtr->numWords > 5) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/* Bytecode to compute/push string argument being replaced */
|
||||
valueTokenPtr = TokenAfter(parsePtr->tokenPtr);
|
||||
CompileWord(envPtr, valueTokenPtr, interp, 1);
|
||||
|
||||
/*
|
||||
* Check for first index known and useful at compile time.
|
||||
*/
|
||||
tokenPtr = TokenAfter(valueTokenPtr);
|
||||
if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_BEFORE, TCL_INDEX_AFTER,
|
||||
&first) != TCL_OK) {
|
||||
goto genericReplace;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for last index known and useful at compile time.
|
||||
*/
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_BEFORE, TCL_INDEX_AFTER,
|
||||
&last) != TCL_OK) {
|
||||
goto genericReplace;
|
||||
}
|
||||
|
||||
/*
|
||||
* [string replace] is an odd bird. For many arguments it is
|
||||
* a conventional substring replacer. However it also goes out
|
||||
* of its way to become a no-op for many cases where it would be
|
||||
* replacing an empty substring. Precisely, it is a no-op when
|
||||
*
|
||||
* (last < first) OR
|
||||
* (last < 0) OR
|
||||
* (end < first)
|
||||
*
|
||||
* For some compile-time values we can detect these cases, and
|
||||
* compile direct to bytecode implementing the no-op.
|
||||
*/
|
||||
|
||||
if ((last == TCL_INDEX_BEFORE) /* Know (last < 0) */
|
||||
|| (first == TCL_INDEX_AFTER) /* Know (first > end) */
|
||||
|
||||
/*
|
||||
* Tricky to determine when runtime (last < first) can be
|
||||
* certainly known based on the encoded values. Consider the
|
||||
* cases...
|
||||
*
|
||||
* (first <= TCL_INDEX_END) &&
|
||||
* (last == TCL_INDEX_AFTER) => cannot tell REJECT
|
||||
* (last <= TCL_INDEX END) && (last < first) => ACCEPT
|
||||
* else => cannot tell REJECT
|
||||
*/
|
||||
|| ((first <= TCL_INDEX_END) && (last <= TCL_INDEX_END)
|
||||
&& (last < first)) /* Know (last < first) */
|
||||
/*
|
||||
* (first == TCL_INDEX_BEFORE) &&
|
||||
* (last == TCL_INDEX_AFTER) => (first < last) REJECT
|
||||
* (last <= TCL_INDEX_END) => cannot tell REJECT
|
||||
* else => (first < last) REJECT
|
||||
*
|
||||
* else [[first >= TCL_INDEX_START]] &&
|
||||
* (last == TCL_INDEX_AFTER) => cannot tell REJECT
|
||||
* (last <= TCL_INDEX_END) => cannot tell REJECT
|
||||
* else [[last >= TCL_INDEX START]] && (last < first) => ACCEPT
|
||||
*/
|
||||
|| ((first >= TCL_INDEX_START) && (last >= TCL_INDEX_START)
|
||||
&& (last < first))) { /* Know (last < first) */
|
||||
if (parsePtr->numWords == 5) {
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
CompileWord(envPtr, tokenPtr, interp, 4);
|
||||
OP( POP); /* Pop newString */
|
||||
}
|
||||
/* Original string argument now on TOS as result */
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
if (parsePtr->numWords == 5) {
|
||||
tokenPtr = TokenAfter(valueTokenPtr);
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
replacementTokenPtr = TokenAfter(tokenPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
* When we have a string replacement, we have to take care about
|
||||
* not replacing empty substrings that [string replace] promises
|
||||
* not to replace
|
||||
*
|
||||
* The remaining index values might be suitable for conventional
|
||||
* string replacement, but only if they cannot possibly meet the
|
||||
* conditions described above at runtime. If there's a chance they
|
||||
* might, we would have to emit bytecode to check and at that point
|
||||
* we're paying more in bytecode execution time than would make
|
||||
* things worthwhile. Trouble is we are very limited in
|
||||
* how much we can detect that at compile time. After decoding,
|
||||
* we need, first:
|
||||
*
|
||||
* (first <= end)
|
||||
*
|
||||
* The encoded indices (first <= TCL_INDEX END) and
|
||||
* (first == TCL_INDEX_BEFORE) always meets this condition, but
|
||||
* any other encoded first index has some list for which it fails.
|
||||
*
|
||||
* We also need, second:
|
||||
*
|
||||
* (last >= 0)
|
||||
*
|
||||
* The encoded indices (last >= TCL_INDEX_START) and
|
||||
* (last == TCL_INDEX_AFTER) always meet this condition but any
|
||||
* other encoded last index has some list for which it fails.
|
||||
*
|
||||
* Finally we need, third:
|
||||
*
|
||||
* (first <= last)
|
||||
*
|
||||
* Considered in combination with the constraints we already have,
|
||||
* we see that we can proceed when (first == TCL_INDEX_BEFORE)
|
||||
* or (last == TCL_INDEX_AFTER). These also permit simplification
|
||||
* of the prefix|replace|suffix construction. The other constraints,
|
||||
* though, interfere with getting a guarantee that first <= last.
|
||||
* Parse the indices. Will only compile special cases if both are
|
||||
* constants and not an _integer_ less than zero (since we reserve
|
||||
* negative indices here for end-relative indexing) or an end-based index
|
||||
* greater than 'end' itself.
|
||||
*/
|
||||
|
||||
if ((first == TCL_INDEX_BEFORE) && (last >= TCL_INDEX_START)) {
|
||||
/* empty prefix */
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
CompileWord(envPtr, tokenPtr, interp, 4);
|
||||
OP4( REVERSE, 2);
|
||||
if (last == TCL_INDEX_AFTER) {
|
||||
OP( POP); /* Pop original */
|
||||
} else {
|
||||
OP44( STR_RANGE_IMM, last + 1, TCL_INDEX_END);
|
||||
OP1( STR_CONCAT1, 2);
|
||||
tokenPtr = TokenAfter(valueTokenPtr);
|
||||
if (GetIndexFromToken(tokenPtr, &idx1) != TCL_OK) {
|
||||
goto genericReplace;
|
||||
}
|
||||
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
if (GetIndexFromToken(tokenPtr, &idx2) != TCL_OK) {
|
||||
goto genericReplace;
|
||||
}
|
||||
|
||||
/*
|
||||
* We handle these replacements specially: first character (where
|
||||
* idx1=idx2=0) and last character (where idx1=idx2=INDEX_END). Anything
|
||||
* else and the semantics get rather screwy.
|
||||
*/
|
||||
|
||||
if (idx1 == 0 && idx2 == 0) {
|
||||
int notEq, end;
|
||||
|
||||
/*
|
||||
* Just working with the first character.
|
||||
*/
|
||||
|
||||
CompileWord(envPtr, valueTokenPtr, interp, 1);
|
||||
if (replacementTokenPtr == NULL) {
|
||||
/* Drop first */
|
||||
OP44( STR_RANGE_IMM, 1, INDEX_END);
|
||||
return TCL_OK;
|
||||
}
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
if ((last == TCL_INDEX_AFTER) && (first <= TCL_INDEX_END)) {
|
||||
OP44( STR_RANGE_IMM, 0, first-1);
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
CompileWord(envPtr, tokenPtr, interp, 4);
|
||||
/* Replace first */
|
||||
CompileWord(envPtr, replacementTokenPtr, interp, 4);
|
||||
OP4( OVER, 1);
|
||||
PUSH( "");
|
||||
OP( STR_EQ);
|
||||
JUMP1( JUMP_FALSE, notEq);
|
||||
OP( POP);
|
||||
JUMP1( JUMP, end);
|
||||
FIXJUMP1(notEq);
|
||||
TclAdjustStackDepth(1, envPtr);
|
||||
OP4( REVERSE, 2);
|
||||
OP44( STR_RANGE_IMM, 1, INDEX_END);
|
||||
OP1( STR_CONCAT1, 2);
|
||||
FIXJUMP1(end);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/* FLOW THROUGH TO genericReplace */
|
||||
} else if (idx1 == INDEX_END && idx2 == INDEX_END) {
|
||||
int notEq, end;
|
||||
|
||||
/*
|
||||
* Just working with the last character.
|
||||
*/
|
||||
|
||||
CompileWord(envPtr, valueTokenPtr, interp, 1);
|
||||
if (replacementTokenPtr == NULL) {
|
||||
/* Drop last */
|
||||
OP44( STR_RANGE_IMM, 0, INDEX_END-1);
|
||||
return TCL_OK;
|
||||
}
|
||||
/* Replace last */
|
||||
CompileWord(envPtr, replacementTokenPtr, interp, 4);
|
||||
OP4( OVER, 1);
|
||||
PUSH( "");
|
||||
OP( STR_EQ);
|
||||
JUMP1( JUMP_FALSE, notEq);
|
||||
OP( POP);
|
||||
JUMP1( JUMP, end);
|
||||
FIXJUMP1(notEq);
|
||||
TclAdjustStackDepth(1, envPtr);
|
||||
OP4( REVERSE, 2);
|
||||
OP44( STR_RANGE_IMM, 0, INDEX_END-1);
|
||||
OP4( REVERSE, 2);
|
||||
OP1( STR_CONCAT1, 2);
|
||||
FIXJUMP1(end);
|
||||
return TCL_OK;
|
||||
|
||||
} else {
|
||||
/*
|
||||
* When we have no replacement string to worry about, we may
|
||||
* have more luck, because the forbidden empty string replacements
|
||||
* are harmless when they are replaced by another empty string.
|
||||
/*
|
||||
* Need to process indices at runtime. This could be because the
|
||||
* indices are not constants, or because we need to resolve them to
|
||||
* absolute indices to work out if a replacement is going to happen.
|
||||
* In any case, to runtime it is.
|
||||
*/
|
||||
|
||||
if ((first == TCL_INDEX_BEFORE) || (first == TCL_INDEX_START)) {
|
||||
/* empty prefix - build suffix only */
|
||||
|
||||
if ((last == TCL_INDEX_END) || (last == TCL_INDEX_AFTER)) {
|
||||
/* empty suffix too => empty result */
|
||||
OP( POP); /* Pop original */
|
||||
PUSH ( "");
|
||||
return TCL_OK;
|
||||
}
|
||||
OP44( STR_RANGE_IMM, last + 1, TCL_INDEX_END);
|
||||
return TCL_OK;
|
||||
} else {
|
||||
if ((last == TCL_INDEX_END) || (last == TCL_INDEX_AFTER)) {
|
||||
/* empty suffix - build prefix only */
|
||||
OP44( STR_RANGE_IMM, 0, first-1);
|
||||
return TCL_OK;
|
||||
}
|
||||
OP( DUP);
|
||||
OP44( STR_RANGE_IMM, 0, first-1);
|
||||
OP4( REVERSE, 2);
|
||||
OP44( STR_RANGE_IMM, last + 1, TCL_INDEX_END);
|
||||
OP1( STR_CONCAT1, 2);
|
||||
return TCL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
genericReplace:
|
||||
CompileWord(envPtr, valueTokenPtr, interp, 1);
|
||||
tokenPtr = TokenAfter(valueTokenPtr);
|
||||
CompileWord(envPtr, tokenPtr, interp, 2);
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
CompileWord(envPtr, tokenPtr, interp, 3);
|
||||
if (parsePtr->numWords == 5) {
|
||||
tokenPtr = TokenAfter(tokenPtr);
|
||||
CompileWord(envPtr, tokenPtr, interp, 4);
|
||||
if (replacementTokenPtr != NULL) {
|
||||
CompileWord(envPtr, replacementTokenPtr, interp, 4);
|
||||
} else {
|
||||
PUSH( "");
|
||||
}
|
||||
OP( STR_REPLACE);
|
||||
return TCL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
* The tree is composed of OpNodes.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
typedef struct OpNode {
|
||||
int left; /* "Pointer" to the left operand. */
|
||||
int right; /* "Pointer" to the right operand. */
|
||||
union {
|
||||
@@ -1885,7 +1885,7 @@ ParseLexeme(
|
||||
{
|
||||
const char *end;
|
||||
int scanned;
|
||||
Tcl_UniChar ch = 0;
|
||||
Tcl_UniChar ch;
|
||||
Tcl_Obj *literal = NULL;
|
||||
unsigned char byte;
|
||||
|
||||
|
||||
+22
-4
@@ -129,6 +129,10 @@ InstructionDesc const tclInstructionTable[] = {
|
||||
{"jumpFalse4", 5, -1, 1, {OPERAND_OFFSET4}},
|
||||
/* Jump relative to (pc + op4) if stktop expr object is false */
|
||||
|
||||
{"lor", 1, -1, 0, {OPERAND_NONE}},
|
||||
/* Logical or: push (stknext || stktop) */
|
||||
{"land", 1, -1, 0, {OPERAND_NONE}},
|
||||
/* Logical and: push (stknext && stktop) */
|
||||
{"bitor", 1, -1, 0, {OPERAND_NONE}},
|
||||
/* Bitwise or: push (stknext | stktop) */
|
||||
{"bitxor", 1, -1, 0, {OPERAND_NONE}},
|
||||
@@ -169,6 +173,10 @@ InstructionDesc const tclInstructionTable[] = {
|
||||
/* Bitwise not: push ~stktop */
|
||||
{"not", 1, 0, 0, {OPERAND_NONE}},
|
||||
/* Logical not: push !stktop */
|
||||
{"callBuiltinFunc1", 2, 1, 1, {OPERAND_UINT1}},
|
||||
/* Call builtin math function with index op1; any args are on stk */
|
||||
{"callFunc1", 2, INT_MIN, 1, {OPERAND_UINT1}},
|
||||
/* Call non-builtin func objv[0]; <objc,objv>=<op1,top op1> */
|
||||
{"tryCvtToNumeric", 1, 0, 0, {OPERAND_NONE}},
|
||||
/* Try converting stktop to first int then double if possible. */
|
||||
|
||||
@@ -178,6 +186,13 @@ InstructionDesc const tclInstructionTable[] = {
|
||||
/* Skip to next iteration of closest enclosing loop; if none, return
|
||||
* TCL_CONTINUE code. */
|
||||
|
||||
{"foreach_start4", 5, 0, 1, {OPERAND_AUX4}},
|
||||
/* Initialize execution of a foreach loop. Operand is aux data index
|
||||
* of the ForeachInfo structure for the foreach command. */
|
||||
{"foreach_step4", 5, +1, 1, {OPERAND_AUX4}},
|
||||
/* "Step" or begin next iteration of foreach loop. Push 0 if to
|
||||
* terminate loop, else push 1. */
|
||||
|
||||
{"beginCatch4", 5, 0, 1, {OPERAND_UINT4}},
|
||||
/* Record start of catch with the operand's exception index. Push the
|
||||
* current stack depth onto a special catch stack. */
|
||||
@@ -325,6 +340,9 @@ InstructionDesc const tclInstructionTable[] = {
|
||||
{"dictNext", 5, +3, 1, {OPERAND_LVT4}},
|
||||
/* Get the next iteration from the iterator in op4's local scalar.
|
||||
* Stack: ... => ... value key doneBool */
|
||||
{"dictDone", 5, 0, 1, {OPERAND_LVT4}},
|
||||
/* Terminate the iterator in op4's local scalar. Use unsetScalar
|
||||
* instead (with 0 for flags). */
|
||||
{"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
|
||||
@@ -835,8 +853,8 @@ TclSetByteCodeFromAny(
|
||||
* instruction generator boundaries.
|
||||
*/
|
||||
|
||||
if (iPtr->optimizer) {
|
||||
(iPtr->optimizer)(&compEnv);
|
||||
if (iPtr->extra.optimizer) {
|
||||
(iPtr->extra.optimizer)(&compEnv);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1114,7 +1132,7 @@ CleanupByteCode(
|
||||
}
|
||||
}
|
||||
|
||||
if (codePtr->localCachePtr && (codePtr->localCachePtr->refCount-- <= 1)) {
|
||||
if (codePtr->localCachePtr && (--codePtr->localCachePtr->refCount == 0)) {
|
||||
TclFreeLocalCache(interp, codePtr->localCachePtr);
|
||||
}
|
||||
|
||||
@@ -1410,7 +1428,7 @@ TclInitCompileEnv(
|
||||
{
|
||||
Interp *iPtr = (Interp *) interp;
|
||||
|
||||
assert(tclInstructionTable[LAST_INST_OPCODE].name == NULL);
|
||||
assert(tclInstructionTable[LAST_INST_OPCODE+1].name == NULL);
|
||||
|
||||
envPtr->iPtr = iPtr;
|
||||
envPtr->source = stringPtr;
|
||||
|
||||
+262
-244
@@ -87,7 +87,7 @@ typedef enum {
|
||||
* to a catch PC offset. */
|
||||
} ExceptionRangeType;
|
||||
|
||||
typedef struct {
|
||||
typedef struct ExceptionRange {
|
||||
ExceptionRangeType type; /* The kind of ExceptionRange. */
|
||||
int nestingLevel; /* Static depth of the exception range. Used
|
||||
* to find the most deeply-nested range
|
||||
@@ -162,7 +162,7 @@ typedef struct ExceptionAux {
|
||||
* source offset is not monotonic.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
typedef struct CmdLocation {
|
||||
int codeOffset; /* Offset of first byte of command code. */
|
||||
int numCodeBytes; /* Number of bytes for command's code. */
|
||||
int srcOffset; /* Offset of first char of the command. */
|
||||
@@ -180,7 +180,7 @@ typedef struct {
|
||||
* frame and associated information, like the path of a sourced file.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
typedef struct ECL {
|
||||
int srcOffset; /* Command location to find the entry. */
|
||||
int nline; /* Number of words in the command */
|
||||
int *line; /* Line information for all words in the
|
||||
@@ -190,7 +190,7 @@ typedef struct {
|
||||
* lines. */
|
||||
} ECL;
|
||||
|
||||
typedef struct {
|
||||
typedef struct ExtCmdLoc {
|
||||
int type; /* Context type. */
|
||||
int start; /* Starting line for compiled script. Needed
|
||||
* for the extended recompile check in
|
||||
@@ -417,7 +417,7 @@ typedef struct ByteCode {
|
||||
* procs are specific to an interpreter so the
|
||||
* code emitted will depend on the
|
||||
* interpreter. */
|
||||
size_t compileEpoch; /* Value of iPtr->compileEpoch when this
|
||||
unsigned int compileEpoch; /* Value of iPtr->compileEpoch when this
|
||||
* ByteCode was compiled. Used to invalidate
|
||||
* code when, e.g., commands with compile
|
||||
* procs are redefined. */
|
||||
@@ -429,7 +429,7 @@ typedef struct ByteCode {
|
||||
* ByteCode was compiled. Used to invalidate
|
||||
* code when new namespace resolution rules
|
||||
* are put into effect. */
|
||||
size_t refCount; /* Reference count: set 1 when created plus 1
|
||||
int refCount; /* Reference count: set 1 when created plus 1
|
||||
* for each execution of the code currently
|
||||
* active. This structure can be freed when
|
||||
* refCount becomes zero. */
|
||||
@@ -519,292 +519,312 @@ typedef struct ByteCode {
|
||||
* Opcodes for the Tcl bytecode instructions. These must correspond to the
|
||||
* entries in the table of instruction descriptions, tclInstructionTable, in
|
||||
* tclCompile.c. Also, the order and number of the expression opcodes (e.g.,
|
||||
* INST_BITOR) must match the entries in the array operatorStrings in
|
||||
* INST_LOR) must match the entries in the array operatorStrings in
|
||||
* tclExecute.c.
|
||||
*/
|
||||
|
||||
enum TclInstruction {
|
||||
/* Opcodes 0 to 9 */
|
||||
#define INST_DONE 0
|
||||
#define INST_PUSH1 1
|
||||
#define INST_PUSH4 2
|
||||
#define INST_POP 3
|
||||
#define INST_DUP 4
|
||||
#define INST_STR_CONCAT1 5
|
||||
#define INST_INVOKE_STK1 6
|
||||
#define INST_INVOKE_STK4 7
|
||||
#define INST_EVAL_STK 8
|
||||
#define INST_EXPR_STK 9
|
||||
|
||||
/* Opcodes 0 to 9 */
|
||||
INST_DONE = 0,
|
||||
INST_PUSH1,
|
||||
INST_PUSH4,
|
||||
INST_POP,
|
||||
INST_DUP,
|
||||
INST_STR_CONCAT1,
|
||||
INST_INVOKE_STK1,
|
||||
INST_INVOKE_STK4,
|
||||
INST_EVAL_STK,
|
||||
INST_EXPR_STK,
|
||||
/* Opcodes 10 to 23 */
|
||||
#define INST_LOAD_SCALAR1 10
|
||||
#define INST_LOAD_SCALAR4 11
|
||||
#define INST_LOAD_SCALAR_STK 12
|
||||
#define INST_LOAD_ARRAY1 13
|
||||
#define INST_LOAD_ARRAY4 14
|
||||
#define INST_LOAD_ARRAY_STK 15
|
||||
#define INST_LOAD_STK 16
|
||||
#define INST_STORE_SCALAR1 17
|
||||
#define INST_STORE_SCALAR4 18
|
||||
#define INST_STORE_SCALAR_STK 19
|
||||
#define INST_STORE_ARRAY1 20
|
||||
#define INST_STORE_ARRAY4 21
|
||||
#define INST_STORE_ARRAY_STK 22
|
||||
#define INST_STORE_STK 23
|
||||
|
||||
/* Opcodes 10 to 23 */
|
||||
INST_LOAD_SCALAR1,
|
||||
INST_LOAD_SCALAR4,
|
||||
INST_LOAD_SCALAR_STK,
|
||||
INST_LOAD_ARRAY1,
|
||||
INST_LOAD_ARRAY4,
|
||||
INST_LOAD_ARRAY_STK,
|
||||
INST_LOAD_STK,
|
||||
INST_STORE_SCALAR1,
|
||||
INST_STORE_SCALAR4,
|
||||
INST_STORE_SCALAR_STK,
|
||||
INST_STORE_ARRAY1,
|
||||
INST_STORE_ARRAY4,
|
||||
INST_STORE_ARRAY_STK,
|
||||
INST_STORE_STK,
|
||||
/* Opcodes 24 to 33 */
|
||||
#define INST_INCR_SCALAR1 24
|
||||
#define INST_INCR_SCALAR_STK 25
|
||||
#define INST_INCR_ARRAY1 26
|
||||
#define INST_INCR_ARRAY_STK 27
|
||||
#define INST_INCR_STK 28
|
||||
#define INST_INCR_SCALAR1_IMM 29
|
||||
#define INST_INCR_SCALAR_STK_IMM 30
|
||||
#define INST_INCR_ARRAY1_IMM 31
|
||||
#define INST_INCR_ARRAY_STK_IMM 32
|
||||
#define INST_INCR_STK_IMM 33
|
||||
|
||||
/* Opcodes 24 to 33 */
|
||||
INST_INCR_SCALAR1,
|
||||
INST_INCR_SCALAR_STK,
|
||||
INST_INCR_ARRAY1,
|
||||
INST_INCR_ARRAY_STK,
|
||||
INST_INCR_STK,
|
||||
INST_INCR_SCALAR1_IMM,
|
||||
INST_INCR_SCALAR_STK_IMM,
|
||||
INST_INCR_ARRAY1_IMM,
|
||||
INST_INCR_ARRAY_STK_IMM,
|
||||
INST_INCR_STK_IMM,
|
||||
/* Opcodes 34 to 39 */
|
||||
#define INST_JUMP1 34
|
||||
#define INST_JUMP4 35
|
||||
#define INST_JUMP_TRUE1 36
|
||||
#define INST_JUMP_TRUE4 37
|
||||
#define INST_JUMP_FALSE1 38
|
||||
#define INST_JUMP_FALSE4 39
|
||||
|
||||
/* Opcodes 34 to 39 */
|
||||
INST_JUMP1,
|
||||
INST_JUMP4,
|
||||
INST_JUMP_TRUE1,
|
||||
INST_JUMP_TRUE4,
|
||||
INST_JUMP_FALSE1,
|
||||
INST_JUMP_FALSE4,
|
||||
/* Opcodes 40 to 64 */
|
||||
#define INST_LOR 40
|
||||
#define INST_LAND 41
|
||||
#define INST_BITOR 42
|
||||
#define INST_BITXOR 43
|
||||
#define INST_BITAND 44
|
||||
#define INST_EQ 45
|
||||
#define INST_NEQ 46
|
||||
#define INST_LT 47
|
||||
#define INST_GT 48
|
||||
#define INST_LE 49
|
||||
#define INST_GE 50
|
||||
#define INST_LSHIFT 51
|
||||
#define INST_RSHIFT 52
|
||||
#define INST_ADD 53
|
||||
#define INST_SUB 54
|
||||
#define INST_MULT 55
|
||||
#define INST_DIV 56
|
||||
#define INST_MOD 57
|
||||
#define INST_UPLUS 58
|
||||
#define INST_UMINUS 59
|
||||
#define INST_BITNOT 60
|
||||
#define INST_LNOT 61
|
||||
#define INST_CALL_BUILTIN_FUNC1 62
|
||||
#define INST_CALL_FUNC1 63
|
||||
#define INST_TRY_CVT_TO_NUMERIC 64
|
||||
|
||||
/* Opcodes 42 to 64 */
|
||||
INST_BITOR,
|
||||
INST_BITXOR,
|
||||
INST_BITAND,
|
||||
INST_EQ,
|
||||
INST_NEQ,
|
||||
INST_LT,
|
||||
INST_GT,
|
||||
INST_LE,
|
||||
INST_GE,
|
||||
INST_LSHIFT,
|
||||
INST_RSHIFT,
|
||||
INST_ADD,
|
||||
INST_SUB,
|
||||
INST_MULT,
|
||||
INST_DIV,
|
||||
INST_MOD,
|
||||
INST_UPLUS,
|
||||
INST_UMINUS,
|
||||
INST_BITNOT,
|
||||
INST_LNOT,
|
||||
INST_TRY_CVT_TO_NUMERIC,
|
||||
/* Opcodes 65 to 66 */
|
||||
#define INST_BREAK 65
|
||||
#define INST_CONTINUE 66
|
||||
|
||||
/* Opcodes 65 to 66 */
|
||||
INST_BREAK,
|
||||
INST_CONTINUE,
|
||||
/* Opcodes 67 to 68 */
|
||||
#define INST_FOREACH_START4 67 /* DEPRECATED */
|
||||
#define INST_FOREACH_STEP4 68 /* DEPRECATED */
|
||||
|
||||
/* Opcodes 69 to 72 */
|
||||
INST_BEGIN_CATCH4,
|
||||
INST_END_CATCH,
|
||||
INST_PUSH_RESULT,
|
||||
INST_PUSH_RETURN_CODE,
|
||||
/* Opcodes 69 to 72 */
|
||||
#define INST_BEGIN_CATCH4 69
|
||||
#define INST_END_CATCH 70
|
||||
#define INST_PUSH_RESULT 71
|
||||
#define INST_PUSH_RETURN_CODE 72
|
||||
|
||||
/* Opcodes 73 to 78 */
|
||||
INST_STR_EQ,
|
||||
INST_STR_NEQ,
|
||||
INST_STR_CMP,
|
||||
INST_STR_LEN,
|
||||
INST_STR_INDEX,
|
||||
INST_STR_MATCH,
|
||||
/* Opcodes 73 to 78 */
|
||||
#define INST_STR_EQ 73
|
||||
#define INST_STR_NEQ 74
|
||||
#define INST_STR_CMP 75
|
||||
#define INST_STR_LEN 76
|
||||
#define INST_STR_INDEX 77
|
||||
#define INST_STR_MATCH 78
|
||||
|
||||
/* Opcodes 79 to 81 */
|
||||
INST_LIST,
|
||||
INST_LIST_INDEX,
|
||||
INST_LIST_LENGTH,
|
||||
/* Opcodes 78 to 81 */
|
||||
#define INST_LIST 79
|
||||
#define INST_LIST_INDEX 80
|
||||
#define INST_LIST_LENGTH 81
|
||||
|
||||
/* Opcodes 82 to 87 */
|
||||
INST_APPEND_SCALAR1,
|
||||
INST_APPEND_SCALAR4,
|
||||
INST_APPEND_ARRAY1,
|
||||
INST_APPEND_ARRAY4,
|
||||
INST_APPEND_ARRAY_STK,
|
||||
INST_APPEND_STK,
|
||||
/* Opcodes 82 to 87 */
|
||||
#define INST_APPEND_SCALAR1 82
|
||||
#define INST_APPEND_SCALAR4 83
|
||||
#define INST_APPEND_ARRAY1 84
|
||||
#define INST_APPEND_ARRAY4 85
|
||||
#define INST_APPEND_ARRAY_STK 86
|
||||
#define INST_APPEND_STK 87
|
||||
|
||||
/* Opcodes 88 to 93 */
|
||||
INST_LAPPEND_SCALAR1,
|
||||
INST_LAPPEND_SCALAR4,
|
||||
INST_LAPPEND_ARRAY1,
|
||||
INST_LAPPEND_ARRAY4,
|
||||
INST_LAPPEND_ARRAY_STK,
|
||||
INST_LAPPEND_STK,
|
||||
/* Opcodes 88 to 93 */
|
||||
#define INST_LAPPEND_SCALAR1 88
|
||||
#define INST_LAPPEND_SCALAR4 89
|
||||
#define INST_LAPPEND_ARRAY1 90
|
||||
#define INST_LAPPEND_ARRAY4 91
|
||||
#define INST_LAPPEND_ARRAY_STK 92
|
||||
#define INST_LAPPEND_STK 93
|
||||
|
||||
/* TIP #22 - LINDEX operator with flat arg list */
|
||||
INST_LIST_INDEX_MULTI,
|
||||
/* TIP #22 - LINDEX operator with flat arg list */
|
||||
|
||||
/*
|
||||
* TIP #33 - 'lset' command. Code gen also required a Forth-like
|
||||
* OVER operation.
|
||||
*/
|
||||
INST_OVER,
|
||||
INST_LSET_LIST,
|
||||
INST_LSET_FLAT,
|
||||
#define INST_LIST_INDEX_MULTI 94
|
||||
|
||||
/* TIP#90 - 'return' command. */
|
||||
INST_RETURN_IMM,
|
||||
/*
|
||||
* TIP #33 - 'lset' command. Code gen also required a Forth-like
|
||||
* OVER operation.
|
||||
*/
|
||||
|
||||
/* TIP#123 - exponentiation operator. */
|
||||
INST_EXPON,
|
||||
#define INST_OVER 95
|
||||
#define INST_LSET_LIST 96
|
||||
#define INST_LSET_FLAT 97
|
||||
|
||||
/* TIP #157 - {*}... (word expansion) language syntax support. */
|
||||
INST_EXPAND_START,
|
||||
INST_EXPAND_STKTOP,
|
||||
INST_INVOKE_EXPANDED,
|
||||
/* TIP#90 - 'return' command. */
|
||||
|
||||
/*
|
||||
* TIP #57 - 'lassign' command. Code generation requires immediate
|
||||
* LINDEX and LRANGE operators.
|
||||
*/
|
||||
INST_LIST_INDEX_IMM,
|
||||
INST_LIST_RANGE_IMM,
|
||||
INST_START_CMD,
|
||||
INST_LIST_IN,
|
||||
INST_LIST_NOT_IN,
|
||||
INST_PUSH_RETURN_OPTIONS,
|
||||
INST_RETURN_STK,
|
||||
#define INST_RETURN_IMM 98
|
||||
|
||||
/*
|
||||
* Dictionary (TIP#111) related commands.
|
||||
*/
|
||||
INST_DICT_GET,
|
||||
INST_DICT_SET,
|
||||
INST_DICT_UNSET,
|
||||
INST_DICT_INCR_IMM,
|
||||
INST_DICT_APPEND,
|
||||
INST_DICT_LAPPEND,
|
||||
INST_DICT_FIRST,
|
||||
INST_DICT_NEXT,
|
||||
INST_DICT_UPDATE_START,
|
||||
INST_DICT_UPDATE_END,
|
||||
/* TIP#123 - exponentiation operator. */
|
||||
|
||||
/*
|
||||
* Instruction to support jumps defined by tables (instead of the classic
|
||||
* [switch] technique of chained comparisons).
|
||||
*/
|
||||
INST_JUMP_TABLE,
|
||||
#define INST_EXPON 99
|
||||
|
||||
/*
|
||||
* Instructions to support compilation of global, variable, upvar and
|
||||
* [namespace upvar].
|
||||
*/
|
||||
INST_UPVAR,
|
||||
INST_NSUPVAR,
|
||||
INST_VARIABLE,
|
||||
/* TIP #157 - {*}... (word expansion) language syntax support. */
|
||||
|
||||
/* Instruction to support compiling syntax error to bytecode */
|
||||
INST_SYNTAX,
|
||||
#define INST_EXPAND_START 100
|
||||
#define INST_EXPAND_STKTOP 101
|
||||
#define INST_INVOKE_EXPANDED 102
|
||||
|
||||
/* Instruction to reverse N items on top of stack */
|
||||
INST_REVERSE,
|
||||
/*
|
||||
* TIP #57 - 'lassign' command. Code generation requires immediate
|
||||
* LINDEX and LRANGE operators.
|
||||
*/
|
||||
|
||||
/* regexp instruction */
|
||||
INST_REGEXP,
|
||||
#define INST_LIST_INDEX_IMM 103
|
||||
#define INST_LIST_RANGE_IMM 104
|
||||
|
||||
/* For [info exists] compilation */
|
||||
INST_EXIST_SCALAR,
|
||||
INST_EXIST_ARRAY,
|
||||
INST_EXIST_ARRAY_STK,
|
||||
INST_EXIST_STK,
|
||||
#define INST_START_CMD 105
|
||||
|
||||
/* For [subst] compilation */
|
||||
INST_NOP,
|
||||
INST_RETURN_CODE_BRANCH,
|
||||
#define INST_LIST_IN 106
|
||||
#define INST_LIST_NOT_IN 107
|
||||
|
||||
/* For [unset] compilation */
|
||||
INST_UNSET_SCALAR,
|
||||
INST_UNSET_ARRAY,
|
||||
INST_UNSET_ARRAY_STK,
|
||||
INST_UNSET_STK,
|
||||
#define INST_PUSH_RETURN_OPTIONS 108
|
||||
#define INST_RETURN_STK 109
|
||||
|
||||
/* For [dict with], [dict exists], [dict create] and [dict merge] */
|
||||
INST_DICT_EXPAND,
|
||||
INST_DICT_RECOMBINE_STK,
|
||||
INST_DICT_RECOMBINE_IMM,
|
||||
INST_DICT_EXISTS,
|
||||
INST_DICT_VERIFY,
|
||||
/*
|
||||
* Dictionary (TIP#111) related commands.
|
||||
*/
|
||||
|
||||
/* For [string map] and [regsub] compilation */
|
||||
INST_STR_MAP,
|
||||
INST_STR_FIND,
|
||||
INST_STR_FIND_LAST,
|
||||
INST_STR_RANGE_IMM,
|
||||
INST_STR_RANGE,
|
||||
#define INST_DICT_GET 110
|
||||
#define INST_DICT_SET 111
|
||||
#define INST_DICT_UNSET 112
|
||||
#define INST_DICT_INCR_IMM 113
|
||||
#define INST_DICT_APPEND 114
|
||||
#define INST_DICT_LAPPEND 115
|
||||
#define INST_DICT_FIRST 116
|
||||
#define INST_DICT_NEXT 117
|
||||
#define INST_DICT_DONE 118
|
||||
#define INST_DICT_UPDATE_START 119
|
||||
#define INST_DICT_UPDATE_END 120
|
||||
|
||||
/* For operations to do with coroutines and other NRE-manipulators */
|
||||
INST_YIELD,
|
||||
INST_COROUTINE_NAME,
|
||||
INST_TAILCALL,
|
||||
/*
|
||||
* Instruction to support jumps defined by tables (instead of the classic
|
||||
* [switch] technique of chained comparisons).
|
||||
*/
|
||||
|
||||
/* For compilation of basic information operations */
|
||||
INST_NS_CURRENT,
|
||||
INST_INFO_LEVEL_NUM,
|
||||
INST_INFO_LEVEL_ARGS,
|
||||
INST_RESOLVE_COMMAND,
|
||||
#define INST_JUMP_TABLE 121
|
||||
|
||||
/* For compilation relating to TclOO */
|
||||
INST_TCLOO_SELF,
|
||||
INST_TCLOO_CLASS,
|
||||
INST_TCLOO_NS,
|
||||
INST_TCLOO_IS_OBJECT,
|
||||
/*
|
||||
* Instructions to support compilation of global, variable, upvar and
|
||||
* [namespace upvar].
|
||||
*/
|
||||
|
||||
/* For compilation of [array] subcommands */
|
||||
INST_ARRAY_EXISTS_STK,
|
||||
INST_ARRAY_EXISTS_IMM,
|
||||
INST_ARRAY_MAKE_STK,
|
||||
INST_ARRAY_MAKE_IMM,
|
||||
#define INST_UPVAR 122
|
||||
#define INST_NSUPVAR 123
|
||||
#define INST_VARIABLE 124
|
||||
|
||||
INST_INVOKE_REPLACE,
|
||||
/* Instruction to support compiling syntax error to bytecode */
|
||||
|
||||
INST_LIST_CONCAT,
|
||||
#define INST_SYNTAX 125
|
||||
|
||||
INST_EXPAND_DROP,
|
||||
/* Instruction to reverse N items on top of stack */
|
||||
|
||||
/* New foreach implementation */
|
||||
INST_FOREACH_START,
|
||||
INST_FOREACH_STEP,
|
||||
INST_FOREACH_END,
|
||||
INST_LMAP_COLLECT,
|
||||
#define INST_REVERSE 126
|
||||
|
||||
/* For compilation of [string trim] and related */
|
||||
INST_STR_TRIM,
|
||||
INST_STR_TRIM_LEFT,
|
||||
INST_STR_TRIM_RIGHT,
|
||||
/* regexp instruction */
|
||||
|
||||
INST_CONCAT_STK,
|
||||
#define INST_REGEXP 127
|
||||
|
||||
INST_STR_UPPER,
|
||||
INST_STR_LOWER,
|
||||
INST_STR_TITLE,
|
||||
INST_STR_REPLACE,
|
||||
/* For [info exists] compilation */
|
||||
#define INST_EXIST_SCALAR 128
|
||||
#define INST_EXIST_ARRAY 129
|
||||
#define INST_EXIST_ARRAY_STK 130
|
||||
#define INST_EXIST_STK 131
|
||||
|
||||
INST_ORIGIN_COMMAND,
|
||||
/* For [subst] compilation */
|
||||
#define INST_NOP 132
|
||||
#define INST_RETURN_CODE_BRANCH 133
|
||||
|
||||
INST_TCLOO_NEXT,
|
||||
INST_TCLOO_NEXT_CLASS,
|
||||
/* For [unset] compilation */
|
||||
#define INST_UNSET_SCALAR 134
|
||||
#define INST_UNSET_ARRAY 135
|
||||
#define INST_UNSET_ARRAY_STK 136
|
||||
#define INST_UNSET_STK 137
|
||||
|
||||
INST_YIELD_TO_INVOKE,
|
||||
/* For [dict with], [dict exists], [dict create] and [dict merge] */
|
||||
#define INST_DICT_EXPAND 138
|
||||
#define INST_DICT_RECOMBINE_STK 139
|
||||
#define INST_DICT_RECOMBINE_IMM 140
|
||||
#define INST_DICT_EXISTS 141
|
||||
#define INST_DICT_VERIFY 142
|
||||
|
||||
INST_NUM_TYPE,
|
||||
INST_TRY_CVT_TO_BOOLEAN,
|
||||
INST_STR_CLASS,
|
||||
/* For [string map] and [regsub] compilation */
|
||||
#define INST_STR_MAP 143
|
||||
#define INST_STR_FIND 144
|
||||
#define INST_STR_FIND_LAST 145
|
||||
#define INST_STR_RANGE_IMM 146
|
||||
#define INST_STR_RANGE 147
|
||||
|
||||
INST_LAPPEND_LIST,
|
||||
INST_LAPPEND_LIST_ARRAY,
|
||||
INST_LAPPEND_LIST_ARRAY_STK,
|
||||
INST_LAPPEND_LIST_STK,
|
||||
/* For operations to do with coroutines and other NRE-manipulators */
|
||||
#define INST_YIELD 148
|
||||
#define INST_COROUTINE_NAME 149
|
||||
#define INST_TAILCALL 150
|
||||
|
||||
INST_CLOCK_READ,
|
||||
/* For compilation of basic information operations */
|
||||
#define INST_NS_CURRENT 151
|
||||
#define INST_INFO_LEVEL_NUM 152
|
||||
#define INST_INFO_LEVEL_ARGS 153
|
||||
#define INST_RESOLVE_COMMAND 154
|
||||
|
||||
/* The last opcode */
|
||||
LAST_INST_OPCODE
|
||||
};
|
||||
/* For compilation relating to TclOO */
|
||||
#define INST_TCLOO_SELF 155
|
||||
#define INST_TCLOO_CLASS 156
|
||||
#define INST_TCLOO_NS 157
|
||||
#define INST_TCLOO_IS_OBJECT 158
|
||||
|
||||
/* For compilation of [array] subcommands */
|
||||
#define INST_ARRAY_EXISTS_STK 159
|
||||
#define INST_ARRAY_EXISTS_IMM 160
|
||||
#define INST_ARRAY_MAKE_STK 161
|
||||
#define INST_ARRAY_MAKE_IMM 162
|
||||
|
||||
#define INST_INVOKE_REPLACE 163
|
||||
|
||||
#define INST_LIST_CONCAT 164
|
||||
|
||||
#define INST_EXPAND_DROP 165
|
||||
|
||||
/* New foreach implementation */
|
||||
#define INST_FOREACH_START 166
|
||||
#define INST_FOREACH_STEP 167
|
||||
#define INST_FOREACH_END 168
|
||||
#define INST_LMAP_COLLECT 169
|
||||
|
||||
/* For compilation of [string trim] and related */
|
||||
#define INST_STR_TRIM 170
|
||||
#define INST_STR_TRIM_LEFT 171
|
||||
#define INST_STR_TRIM_RIGHT 172
|
||||
|
||||
#define INST_CONCAT_STK 173
|
||||
|
||||
#define INST_STR_UPPER 174
|
||||
#define INST_STR_LOWER 175
|
||||
#define INST_STR_TITLE 176
|
||||
#define INST_STR_REPLACE 177
|
||||
|
||||
#define INST_ORIGIN_COMMAND 178
|
||||
|
||||
#define INST_TCLOO_NEXT 179
|
||||
#define INST_TCLOO_NEXT_CLASS 180
|
||||
|
||||
#define INST_YIELD_TO_INVOKE 181
|
||||
|
||||
#define INST_NUM_TYPE 182
|
||||
#define INST_TRY_CVT_TO_BOOLEAN 183
|
||||
#define INST_STR_CLASS 184
|
||||
|
||||
#define INST_LAPPEND_LIST 185
|
||||
#define INST_LAPPEND_LIST_ARRAY 186
|
||||
#define INST_LAPPEND_LIST_ARRAY_STK 187
|
||||
#define INST_LAPPEND_LIST_STK 188
|
||||
|
||||
#define INST_CLOCK_READ 189
|
||||
|
||||
/* The last opcode */
|
||||
#define LAST_INST_OPCODE 189
|
||||
|
||||
/*
|
||||
* Table describing the Tcl bytecode instructions: their name (for displaying
|
||||
@@ -1100,8 +1120,6 @@ MODULE_SCOPE int TclFixupForwardJump(CompileEnv *envPtr,
|
||||
int distThreshold);
|
||||
MODULE_SCOPE void TclFreeCompileEnv(CompileEnv *envPtr);
|
||||
MODULE_SCOPE void TclFreeJumpFixupArray(JumpFixupArray *fixupArrayPtr);
|
||||
MODULE_SCOPE int TclGetIndexFromToken(Tcl_Token *tokenPtr,
|
||||
int before, int after, int *indexPtr);
|
||||
MODULE_SCOPE ByteCode * TclInitByteCode(CompileEnv *envPtr);
|
||||
MODULE_SCOPE ByteCode * TclInitByteCodeObj(Tcl_Obj *objPtr,
|
||||
const Tcl_ObjType *typePtr, CompileEnv *envPtr);
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
* the (Tcl_Interp *) in which it is stored, and the encoding.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
typedef struct QCCD {
|
||||
Tcl_Obj *pkg;
|
||||
Tcl_Interp *interp;
|
||||
char *encoding;
|
||||
|
||||
+251
-311
@@ -1,24 +1,22 @@
|
||||
/* A Bison parser, made by GNU Bison 2.3. */
|
||||
/* A Bison parser, made by GNU Bison 2.4.2. */
|
||||
|
||||
/* Skeleton implementation for Bison's Yacc-like parsers in C
|
||||
|
||||
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
|
||||
Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* As a special exception, you may create a larger work that contains
|
||||
part or all of the Bison parser skeleton and distribute that work
|
||||
@@ -29,7 +27,7 @@
|
||||
special exception, which will cause the skeleton and the resulting
|
||||
Bison output files to be licensed under the GNU General Public
|
||||
License without this special exception.
|
||||
|
||||
|
||||
This special exception was added by the Free Software Foundation in
|
||||
version 2.2 of Bison. */
|
||||
|
||||
@@ -47,7 +45,7 @@
|
||||
#define YYBISON 1
|
||||
|
||||
/* Bison version. */
|
||||
#define YYBISON_VERSION "2.3"
|
||||
#define YYBISON_VERSION "2.4.2"
|
||||
|
||||
/* Skeleton name. */
|
||||
#define YYSKELETON_NAME "yacc.c"
|
||||
@@ -55,65 +53,24 @@
|
||||
/* Pure parsers. */
|
||||
#define YYPURE 1
|
||||
|
||||
/* Push parsers. */
|
||||
#define YYPUSH 0
|
||||
|
||||
/* Pull parsers. */
|
||||
#define YYPULL 1
|
||||
|
||||
/* Using locations. */
|
||||
#define YYLSP_NEEDED 1
|
||||
|
||||
/* Substitute the variable and function names. */
|
||||
#define yyparse TclDateparse
|
||||
#define yylex TclDatelex
|
||||
#define yyerror TclDateerror
|
||||
#define yylval TclDatelval
|
||||
#define yychar TclDatechar
|
||||
#define yydebug TclDatedebug
|
||||
#define yynerrs TclDatenerrs
|
||||
#define yylloc TclDatelloc
|
||||
|
||||
/* Tokens. */
|
||||
#ifndef YYTOKENTYPE
|
||||
# define YYTOKENTYPE
|
||||
/* Put the tokens into the symbol table, so that GDB and other debuggers
|
||||
know about them. */
|
||||
enum yytokentype {
|
||||
tAGO = 258,
|
||||
tDAY = 259,
|
||||
tDAYZONE = 260,
|
||||
tID = 261,
|
||||
tMERIDIAN = 262,
|
||||
tMONTH = 263,
|
||||
tMONTH_UNIT = 264,
|
||||
tSTARDATE = 265,
|
||||
tSEC_UNIT = 266,
|
||||
tSNUMBER = 267,
|
||||
tUNUMBER = 268,
|
||||
tZONE = 269,
|
||||
tEPOCH = 270,
|
||||
tDST = 271,
|
||||
tISOBASE = 272,
|
||||
tDAY_UNIT = 273,
|
||||
tNEXT = 274
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
#define tAGO 258
|
||||
#define tDAY 259
|
||||
#define tDAYZONE 260
|
||||
#define tID 261
|
||||
#define tMERIDIAN 262
|
||||
#define tMONTH 263
|
||||
#define tMONTH_UNIT 264
|
||||
#define tSTARDATE 265
|
||||
#define tSEC_UNIT 266
|
||||
#define tSNUMBER 267
|
||||
#define tUNUMBER 268
|
||||
#define tZONE 269
|
||||
#define tEPOCH 270
|
||||
#define tDST 271
|
||||
#define tISOBASE 272
|
||||
#define tDAY_UNIT 273
|
||||
#define tNEXT 274
|
||||
|
||||
|
||||
|
||||
#define yyparse TclDateparse
|
||||
#define yylex TclDatelex
|
||||
#define yyerror TclDateerror
|
||||
#define yylval TclDatelval
|
||||
#define yychar TclDatechar
|
||||
#define yydebug TclDatedebug
|
||||
#define yynerrs TclDatenerrs
|
||||
#define yylloc TclDatelloc
|
||||
|
||||
/* Copy the first part of user declarations. */
|
||||
|
||||
@@ -129,6 +86,7 @@
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution of
|
||||
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
*
|
||||
*/
|
||||
#include "tclInt.h"
|
||||
|
||||
@@ -146,73 +104,11 @@
|
||||
* parsed fields will be returned.
|
||||
*/
|
||||
|
||||
typedef struct DateInfo {
|
||||
|
||||
Tcl_Obj* messages; /* Error messages */
|
||||
const char* separatrix; /* String separating messages */
|
||||
|
||||
time_t dateYear;
|
||||
time_t dateMonth;
|
||||
time_t dateDay;
|
||||
int dateHaveDate;
|
||||
|
||||
time_t dateHour;
|
||||
time_t dateMinutes;
|
||||
time_t dateSeconds;
|
||||
int dateMeridian;
|
||||
int dateHaveTime;
|
||||
|
||||
time_t dateTimezone;
|
||||
int dateDSTmode;
|
||||
int dateHaveZone;
|
||||
|
||||
time_t dateRelMonth;
|
||||
time_t dateRelDay;
|
||||
time_t dateRelSeconds;
|
||||
int dateHaveRel;
|
||||
|
||||
time_t dateMonthOrdinal;
|
||||
int dateHaveOrdinalMonth;
|
||||
|
||||
time_t dateDayOrdinal;
|
||||
time_t dateDayNumber;
|
||||
int dateHaveDay;
|
||||
|
||||
const char *dateStart;
|
||||
const char *dateInput;
|
||||
time_t *dateRelPointer;
|
||||
|
||||
int dateDigitCount;
|
||||
} DateInfo;
|
||||
#include "tclDate.h"
|
||||
|
||||
#define YYMALLOC ckalloc
|
||||
#define YYFREE(x) (ckfree((void*) (x)))
|
||||
|
||||
#define yyDSTmode (info->dateDSTmode)
|
||||
#define yyDayOrdinal (info->dateDayOrdinal)
|
||||
#define yyDayNumber (info->dateDayNumber)
|
||||
#define yyMonthOrdinal (info->dateMonthOrdinal)
|
||||
#define yyHaveDate (info->dateHaveDate)
|
||||
#define yyHaveDay (info->dateHaveDay)
|
||||
#define yyHaveOrdinalMonth (info->dateHaveOrdinalMonth)
|
||||
#define yyHaveRel (info->dateHaveRel)
|
||||
#define yyHaveTime (info->dateHaveTime)
|
||||
#define yyHaveZone (info->dateHaveZone)
|
||||
#define yyTimezone (info->dateTimezone)
|
||||
#define yyDay (info->dateDay)
|
||||
#define yyMonth (info->dateMonth)
|
||||
#define yyYear (info->dateYear)
|
||||
#define yyHour (info->dateHour)
|
||||
#define yyMinutes (info->dateMinutes)
|
||||
#define yySeconds (info->dateSeconds)
|
||||
#define yyMeridian (info->dateMeridian)
|
||||
#define yyRelMonth (info->dateRelMonth)
|
||||
#define yyRelDay (info->dateRelDay)
|
||||
#define yyRelSeconds (info->dateRelSeconds)
|
||||
#define yyRelPointer (info->dateRelPointer)
|
||||
#define yyInput (info->dateInput)
|
||||
#define yyDigitCount (info->dateDigitCount)
|
||||
|
||||
#define EPOCH 1970
|
||||
#define START_OF_TIME 1902
|
||||
#define END_OF_TIME 2037
|
||||
@@ -246,13 +142,6 @@ typedef enum _DSTMODE {
|
||||
DSTon, DSToff, DSTmaybe
|
||||
} DSTMODE;
|
||||
|
||||
/*
|
||||
* Meridian: am, pm, or 24-hour style.
|
||||
*/
|
||||
|
||||
typedef enum _MERIDIAN {
|
||||
MERam, MERpm, MER24
|
||||
} MERIDIAN;
|
||||
|
||||
|
||||
|
||||
@@ -274,19 +163,49 @@ typedef enum _MERIDIAN {
|
||||
# define YYTOKEN_TABLE 0
|
||||
#endif
|
||||
|
||||
|
||||
/* Tokens. */
|
||||
#ifndef YYTOKENTYPE
|
||||
# define YYTOKENTYPE
|
||||
/* Put the tokens into the symbol table, so that GDB and other debuggers
|
||||
know about them. */
|
||||
enum yytokentype {
|
||||
tAGO = 258,
|
||||
tDAY = 259,
|
||||
tDAYZONE = 260,
|
||||
tID = 261,
|
||||
tMERIDIAN = 262,
|
||||
tMONTH = 263,
|
||||
tMONTH_UNIT = 264,
|
||||
tSTARDATE = 265,
|
||||
tSEC_UNIT = 266,
|
||||
tSNUMBER = 267,
|
||||
tUNUMBER = 268,
|
||||
tZONE = 269,
|
||||
tEPOCH = 270,
|
||||
tDST = 271,
|
||||
tISOBASE = 272,
|
||||
tDAY_UNIT = 273,
|
||||
tNEXT = 274
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
typedef union YYSTYPE
|
||||
|
||||
{
|
||||
|
||||
|
||||
time_t Number;
|
||||
enum _MERIDIAN Meridian;
|
||||
}
|
||||
/* Line 187 of yacc.c. */
|
||||
|
||||
YYSTYPE;
|
||||
|
||||
|
||||
} YYSTYPE;
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
#endif
|
||||
|
||||
#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
|
||||
@@ -316,14 +235,10 @@ static int LookupWord(YYSTYPE* yylvalPtr, char *buff);
|
||||
DateInfo* info, const char *s);
|
||||
static int TclDatelex(YYSTYPE* yylvalPtr, YYLTYPE* location,
|
||||
DateInfo* info);
|
||||
static time_t ToSeconds(time_t Hours, time_t Minutes,
|
||||
time_t Seconds, MERIDIAN Meridian);
|
||||
MODULE_SCOPE int yyparse(DateInfo*);
|
||||
|
||||
|
||||
|
||||
/* Line 216 of yacc.c. */
|
||||
|
||||
|
||||
#ifdef short
|
||||
# undef short
|
||||
@@ -359,15 +274,21 @@ typedef short int yytype_int16;
|
||||
#ifndef YYSIZE_T
|
||||
# ifdef __SIZE_TYPE__
|
||||
# define YYSIZE_T __SIZE_TYPE__
|
||||
# else
|
||||
# elif defined size_t
|
||||
# define YYSIZE_T size_t
|
||||
# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
|
||||
|| defined __cplusplus || defined _MSC_VER)
|
||||
# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
|
||||
# define YYSIZE_T size_t
|
||||
# else
|
||||
# define YYSIZE_T unsigned int
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
|
||||
|
||||
#ifndef YY_
|
||||
# if YYENABLE_NLS
|
||||
# if defined YYENABLE_NLS && YYENABLE_NLS
|
||||
# if ENABLE_NLS
|
||||
# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
|
||||
# define YY_(msgid) dgettext ("bison-runtime", msgid)
|
||||
@@ -392,14 +313,14 @@ typedef short int yytype_int16;
|
||||
#if (defined __STDC__ || defined __C99__FUNC__ \
|
||||
|| defined __cplusplus || defined _MSC_VER)
|
||||
static int
|
||||
YYID (int i)
|
||||
YYID (int yyi)
|
||||
#else
|
||||
static int
|
||||
YYID (i)
|
||||
int i;
|
||||
YYID (yyi)
|
||||
int yyi;
|
||||
#endif
|
||||
{
|
||||
return i;
|
||||
return yyi;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -481,9 +402,9 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
|
||||
/* A type that is properly aligned for any stack member. */
|
||||
union yyalloc
|
||||
{
|
||||
yytype_int16 yyss;
|
||||
YYSTYPE yyvs;
|
||||
YYLTYPE yyls;
|
||||
yytype_int16 yyss_alloc;
|
||||
YYSTYPE yyvs_alloc;
|
||||
YYLTYPE yyls_alloc;
|
||||
};
|
||||
|
||||
/* The size of the maximum gap between one aligned stack and the next. */
|
||||
@@ -518,12 +439,12 @@ union yyalloc
|
||||
elements in the stack, and YYPTR gives the new location of the
|
||||
stack. Advance YYPTR to a properly aligned location for the next
|
||||
stack. */
|
||||
# define YYSTACK_RELOCATE(Stack) \
|
||||
# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
|
||||
do \
|
||||
{ \
|
||||
YYSIZE_T yynewbytes; \
|
||||
YYCOPY (&yyptr->Stack, Stack, yysize); \
|
||||
Stack = &yyptr->Stack; \
|
||||
YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
|
||||
Stack = &yyptr->Stack_alloc; \
|
||||
yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
|
||||
yyptr += yynewbytes / sizeof (*yyptr); \
|
||||
} \
|
||||
@@ -624,12 +545,12 @@ static const yytype_int8 yyrhs[] =
|
||||
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
|
||||
static const yytype_uint16 yyrline[] =
|
||||
{
|
||||
0, 225, 225, 226, 229, 232, 235, 238, 241, 244,
|
||||
247, 251, 256, 259, 265, 271, 279, 285, 296, 300,
|
||||
304, 310, 314, 318, 322, 326, 332, 336, 341, 346,
|
||||
351, 356, 360, 365, 369, 374, 381, 385, 391, 400,
|
||||
409, 419, 433, 438, 441, 444, 447, 450, 453, 458,
|
||||
461, 466, 470, 474, 480, 498, 501
|
||||
0, 152, 152, 153, 156, 159, 162, 165, 168, 171,
|
||||
174, 178, 183, 186, 192, 198, 206, 212, 223, 227,
|
||||
231, 237, 241, 245, 249, 253, 259, 263, 268, 273,
|
||||
278, 283, 287, 292, 296, 301, 308, 312, 318, 327,
|
||||
336, 346, 360, 365, 368, 371, 374, 377, 380, 385,
|
||||
388, 393, 397, 401, 407, 425, 428
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -783,9 +704,18 @@ static const yytype_uint8 yystos[] =
|
||||
|
||||
/* Like YYERROR except do call yyerror. This remains here temporarily
|
||||
to ease the transition to the new meaning of YYERROR, for GCC.
|
||||
Once GCC version 2 has supplanted version 1, this can go. */
|
||||
Once GCC version 2 has supplanted version 1, this can go. However,
|
||||
YYFAIL appears to be in use. Nevertheless, it is formally deprecated
|
||||
in Bison 2.4.2's NEWS entry, where a plan to phase it out is
|
||||
discussed. */
|
||||
|
||||
#define YYFAIL goto yyerrlab
|
||||
#if defined YYFAIL
|
||||
/* This is here to suppress warnings from the GCC cpp's
|
||||
-Wunused-macros. Normally we don't worry about that warning, but
|
||||
some users do, and we want to make it easy for users to remove
|
||||
YYFAIL uses, which will produce warnings from Bison 2.5. */
|
||||
#endif
|
||||
|
||||
#define YYRECOVERING() (!!yyerrstatus)
|
||||
|
||||
@@ -842,7 +772,7 @@ while (YYID (0))
|
||||
we won't break user code: when these are the locations we know. */
|
||||
|
||||
#ifndef YY_LOCATION_PRINT
|
||||
# if YYLTYPE_IS_TRIVIAL
|
||||
# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
|
||||
# define YY_LOCATION_PRINT(File, Loc) \
|
||||
fprintf (File, "%d.%d-%d.%d", \
|
||||
(Loc).first_line, (Loc).first_column, \
|
||||
@@ -961,17 +891,20 @@ yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, info)
|
||||
#if (defined __STDC__ || defined __C99__FUNC__ \
|
||||
|| defined __cplusplus || defined _MSC_VER)
|
||||
static void
|
||||
yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
|
||||
yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
|
||||
#else
|
||||
static void
|
||||
yy_stack_print (bottom, top)
|
||||
yytype_int16 *bottom;
|
||||
yytype_int16 *top;
|
||||
yy_stack_print (yybottom, yytop)
|
||||
yytype_int16 *yybottom;
|
||||
yytype_int16 *yytop;
|
||||
#endif
|
||||
{
|
||||
YYFPRINTF (stderr, "Stack now");
|
||||
for (; bottom <= top; ++bottom)
|
||||
YYFPRINTF (stderr, " %d", *bottom);
|
||||
for (; yybottom <= yytop; yybottom++)
|
||||
{
|
||||
int yybot = *yybottom;
|
||||
YYFPRINTF (stderr, " %d", yybot);
|
||||
}
|
||||
YYFPRINTF (stderr, "\n");
|
||||
}
|
||||
|
||||
@@ -1007,11 +940,11 @@ yy_reduce_print (yyvsp, yylsp, yyrule, info)
|
||||
/* The symbols being reduced. */
|
||||
for (yyi = 0; yyi < yynrhs; yyi++)
|
||||
{
|
||||
fprintf (stderr, " $%d = ", yyi + 1);
|
||||
YYFPRINTF (stderr, " $%d = ", yyi + 1);
|
||||
yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
|
||||
&(yyvsp[(yyi + 1) - (yynrhs)])
|
||||
, &(yylsp[(yyi + 1) - (yynrhs)]) , info);
|
||||
fprintf (stderr, "\n");
|
||||
YYFPRINTF (stderr, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1295,10 +1228,8 @@ yydestruct (yymsg, yytype, yyvaluep, yylocationp, info)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Prevent warnings from -Wmissing-prototypes. */
|
||||
|
||||
#ifdef YYPARSE_PARAM
|
||||
#if defined __STDC__ || defined __cplusplus
|
||||
int yyparse (void *YYPARSE_PARAM);
|
||||
@@ -1317,10 +1248,9 @@ int yyparse ();
|
||||
|
||||
|
||||
|
||||
|
||||
/*----------.
|
||||
| yyparse. |
|
||||
`----------*/
|
||||
/*-------------------------.
|
||||
| yyparse or yypush_parse. |
|
||||
`-------------------------*/
|
||||
|
||||
#ifdef YYPARSE_PARAM
|
||||
#if (defined __STDC__ || defined __C99__FUNC__ \
|
||||
@@ -1344,24 +1274,59 @@ yyparse (info)
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
/* The look-ahead symbol. */
|
||||
/* The lookahead symbol. */
|
||||
int yychar;
|
||||
|
||||
/* The semantic value of the look-ahead symbol. */
|
||||
/* The semantic value of the lookahead symbol. */
|
||||
YYSTYPE yylval;
|
||||
|
||||
/* Number of syntax errors so far. */
|
||||
int yynerrs;
|
||||
/* Location data for the look-ahead symbol. */
|
||||
/* Location data for the lookahead symbol. */
|
||||
YYLTYPE yylloc;
|
||||
|
||||
int yystate;
|
||||
/* Number of syntax errors so far. */
|
||||
int yynerrs;
|
||||
|
||||
int yystate;
|
||||
/* Number of tokens to shift before error messages enabled. */
|
||||
int yyerrstatus;
|
||||
|
||||
/* The stacks and their tools:
|
||||
`yyss': related to states.
|
||||
`yyvs': related to semantic values.
|
||||
`yyls': related to locations.
|
||||
|
||||
Refer to the stacks thru separate pointers, to allow yyoverflow
|
||||
to reallocate them elsewhere. */
|
||||
|
||||
/* The state stack. */
|
||||
yytype_int16 yyssa[YYINITDEPTH];
|
||||
yytype_int16 *yyss;
|
||||
yytype_int16 *yyssp;
|
||||
|
||||
/* The semantic value stack. */
|
||||
YYSTYPE yyvsa[YYINITDEPTH];
|
||||
YYSTYPE *yyvs;
|
||||
YYSTYPE *yyvsp;
|
||||
|
||||
/* The location stack. */
|
||||
YYLTYPE yylsa[YYINITDEPTH];
|
||||
YYLTYPE *yyls;
|
||||
YYLTYPE *yylsp;
|
||||
|
||||
/* The locations where the error started and ended. */
|
||||
YYLTYPE yyerror_range[2];
|
||||
|
||||
YYSIZE_T yystacksize;
|
||||
|
||||
int yyn;
|
||||
int yyresult;
|
||||
/* Number of tokens to shift before error messages enabled. */
|
||||
int yyerrstatus;
|
||||
/* Look-ahead token as an internal (translated) token number. */
|
||||
int yytoken = 0;
|
||||
/* Lookahead token as an internal (translated) token number. */
|
||||
int yytoken;
|
||||
/* The variables used to return semantic value and location from the
|
||||
action routines. */
|
||||
YYSTYPE yyval;
|
||||
YYLTYPE yyloc;
|
||||
|
||||
#if YYERROR_VERBOSE
|
||||
/* Buffer for error messages, and its allocated size. */
|
||||
char yymsgbuf[128];
|
||||
@@ -1369,63 +1334,37 @@ YYLTYPE yylloc;
|
||||
YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
|
||||
#endif
|
||||
|
||||
/* Three stacks and their tools:
|
||||
`yyss': related to states,
|
||||
`yyvs': related to semantic values,
|
||||
`yyls': related to locations.
|
||||
|
||||
Refer to the stacks thru separate pointers, to allow yyoverflow
|
||||
to reallocate them elsewhere. */
|
||||
|
||||
/* The state stack. */
|
||||
yytype_int16 yyssa[YYINITDEPTH];
|
||||
yytype_int16 *yyss = yyssa;
|
||||
yytype_int16 *yyssp;
|
||||
|
||||
/* The semantic value stack. */
|
||||
YYSTYPE yyvsa[YYINITDEPTH];
|
||||
YYSTYPE *yyvs = yyvsa;
|
||||
YYSTYPE *yyvsp;
|
||||
|
||||
/* The location stack. */
|
||||
YYLTYPE yylsa[YYINITDEPTH];
|
||||
YYLTYPE *yyls = yylsa;
|
||||
YYLTYPE *yylsp;
|
||||
/* The locations where the error started and ended. */
|
||||
YYLTYPE yyerror_range[2];
|
||||
|
||||
#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
|
||||
|
||||
YYSIZE_T yystacksize = YYINITDEPTH;
|
||||
|
||||
/* The variables used to return semantic value and location from the
|
||||
action routines. */
|
||||
YYSTYPE yyval;
|
||||
YYLTYPE yyloc;
|
||||
|
||||
/* The number of symbols on the RHS of the reduced rule.
|
||||
Keep to zero when no symbol should be popped. */
|
||||
int yylen = 0;
|
||||
|
||||
yytoken = 0;
|
||||
yyss = yyssa;
|
||||
yyvs = yyvsa;
|
||||
yyls = yylsa;
|
||||
yystacksize = YYINITDEPTH;
|
||||
|
||||
YYDPRINTF ((stderr, "Starting parse\n"));
|
||||
|
||||
yystate = 0;
|
||||
yyerrstatus = 0;
|
||||
yynerrs = 0;
|
||||
yychar = YYEMPTY; /* Cause a token to be read. */
|
||||
yychar = YYEMPTY; /* Cause a token to be read. */
|
||||
|
||||
/* Initialize stack pointers.
|
||||
Waste one element of value and location stack
|
||||
so that they stay on the same level as the state stack.
|
||||
The wasted elements are never initialized. */
|
||||
|
||||
yyssp = yyss;
|
||||
yyvsp = yyvs;
|
||||
yylsp = yyls;
|
||||
#if YYLTYPE_IS_TRIVIAL
|
||||
|
||||
#if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
|
||||
/* Initialize the default location before parsing starts. */
|
||||
yylloc.first_line = yylloc.last_line = 1;
|
||||
yylloc.first_column = yylloc.last_column = 0;
|
||||
yylloc.first_column = yylloc.last_column = 1;
|
||||
#endif
|
||||
|
||||
goto yysetstate;
|
||||
@@ -1464,6 +1403,7 @@ YYLTYPE yylloc;
|
||||
&yyvs1, yysize * sizeof (*yyvsp),
|
||||
&yyls1, yysize * sizeof (*yylsp),
|
||||
&yystacksize);
|
||||
|
||||
yyls = yyls1;
|
||||
yyss = yyss1;
|
||||
yyvs = yyvs1;
|
||||
@@ -1485,9 +1425,9 @@ YYLTYPE yylloc;
|
||||
(union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
|
||||
if (! yyptr)
|
||||
goto yyexhaustedlab;
|
||||
YYSTACK_RELOCATE (yyss);
|
||||
YYSTACK_RELOCATE (yyvs);
|
||||
YYSTACK_RELOCATE (yyls);
|
||||
YYSTACK_RELOCATE (yyss_alloc, yyss);
|
||||
YYSTACK_RELOCATE (yyvs_alloc, yyvs);
|
||||
YYSTACK_RELOCATE (yyls_alloc, yyls);
|
||||
# undef YYSTACK_RELOCATE
|
||||
if (yyss1 != yyssa)
|
||||
YYSTACK_FREE (yyss1);
|
||||
@@ -1508,6 +1448,9 @@ YYLTYPE yylloc;
|
||||
|
||||
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
|
||||
|
||||
if (yystate == YYFINAL)
|
||||
YYACCEPT;
|
||||
|
||||
goto yybackup;
|
||||
|
||||
/*-----------.
|
||||
@@ -1516,16 +1459,16 @@ YYLTYPE yylloc;
|
||||
yybackup:
|
||||
|
||||
/* Do appropriate processing given the current state. Read a
|
||||
look-ahead token if we need one and don't already have one. */
|
||||
lookahead token if we need one and don't already have one. */
|
||||
|
||||
/* First try to decide what to do without reference to look-ahead token. */
|
||||
/* First try to decide what to do without reference to lookahead token. */
|
||||
yyn = yypact[yystate];
|
||||
if (yyn == YYPACT_NINF)
|
||||
goto yydefault;
|
||||
|
||||
/* Not known => get a look-ahead token if don't already have one. */
|
||||
/* Not known => get a lookahead token if don't already have one. */
|
||||
|
||||
/* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
|
||||
/* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
|
||||
if (yychar == YYEMPTY)
|
||||
{
|
||||
YYDPRINTF ((stderr, "Reading a token: "));
|
||||
@@ -1557,20 +1500,16 @@ yybackup:
|
||||
goto yyreduce;
|
||||
}
|
||||
|
||||
if (yyn == YYFINAL)
|
||||
YYACCEPT;
|
||||
|
||||
/* Count tokens shifted since error; after three, turn off error
|
||||
status. */
|
||||
if (yyerrstatus)
|
||||
yyerrstatus--;
|
||||
|
||||
/* Shift the look-ahead token. */
|
||||
/* Shift the lookahead token. */
|
||||
YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
|
||||
|
||||
/* Discard the shifted token unless it is eof. */
|
||||
if (yychar != YYEOF)
|
||||
yychar = YYEMPTY;
|
||||
/* Discard the shifted token. */
|
||||
yychar = YYEMPTY;
|
||||
|
||||
yystate = yyn;
|
||||
*++yyvsp = yylval;
|
||||
@@ -1878,16 +1817,16 @@ yyreduce:
|
||||
case 36:
|
||||
|
||||
{
|
||||
yyMonthOrdinal = 1;
|
||||
yyMonth = (yyvsp[(2) - (2)].Number);
|
||||
yyMonthOrdinalIncr = 1;
|
||||
yyMonthOrdinal = (yyvsp[(2) - (2)].Number);
|
||||
;}
|
||||
break;
|
||||
|
||||
case 37:
|
||||
|
||||
{
|
||||
yyMonthOrdinal = (yyvsp[(2) - (3)].Number);
|
||||
yyMonth = (yyvsp[(3) - (3)].Number);
|
||||
yyMonthOrdinalIncr = (yyvsp[(2) - (3)].Number);
|
||||
yyMonthOrdinal = (yyvsp[(3) - (3)].Number);
|
||||
;}
|
||||
break;
|
||||
|
||||
@@ -2062,7 +2001,6 @@ yyreduce:
|
||||
break;
|
||||
|
||||
|
||||
/* Line 1267 of yacc.c. */
|
||||
|
||||
default: break;
|
||||
}
|
||||
@@ -2139,7 +2077,7 @@ yyerrlab:
|
||||
|
||||
if (yyerrstatus == 3)
|
||||
{
|
||||
/* If just tried and failed to reuse look-ahead token after an
|
||||
/* If just tried and failed to reuse lookahead token after an
|
||||
error, discard it. */
|
||||
|
||||
if (yychar <= YYEOF)
|
||||
@@ -2156,7 +2094,7 @@ yyerrlab:
|
||||
}
|
||||
}
|
||||
|
||||
/* Else will try to reuse look-ahead token after shifting the error
|
||||
/* Else will try to reuse lookahead token after shifting the error
|
||||
token. */
|
||||
goto yyerrlab1;
|
||||
|
||||
@@ -2214,14 +2152,11 @@ yyerrlab1:
|
||||
YY_STACK_PRINT (yyss, yyssp);
|
||||
}
|
||||
|
||||
if (yyn == YYFINAL)
|
||||
YYACCEPT;
|
||||
|
||||
*++yyvsp = yylval;
|
||||
|
||||
yyerror_range[1] = yylloc;
|
||||
/* Using YYLLOC is tempting, but would change the location of
|
||||
the look-ahead. YYLOC is available though. */
|
||||
the lookahead. YYLOC is available though. */
|
||||
YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2);
|
||||
*++yylsp = yyloc;
|
||||
|
||||
@@ -2246,7 +2181,7 @@ yyabortlab:
|
||||
yyresult = 1;
|
||||
goto yyreturn;
|
||||
|
||||
#ifndef yyoverflow
|
||||
#if !defined(yyoverflow) || YYERROR_VERBOSE
|
||||
/*-------------------------------------------------.
|
||||
| yyexhaustedlab -- memory exhaustion comes here. |
|
||||
`-------------------------------------------------*/
|
||||
@@ -2257,7 +2192,7 @@ yyexhaustedlab:
|
||||
#endif
|
||||
|
||||
yyreturn:
|
||||
if (yychar != YYEOF && yychar != YYEMPTY)
|
||||
if (yychar != YYEMPTY)
|
||||
yydestruct ("Cleanup: discarding lookahead",
|
||||
yytoken, &yylval, &yylloc, info);
|
||||
/* Do not reclaim the symbols of the rule which action triggered
|
||||
@@ -2513,11 +2448,11 @@ TclDateerror(
|
||||
infoPtr->separatrix = "\n";
|
||||
}
|
||||
|
||||
static time_t
|
||||
MODULE_SCOPE int
|
||||
ToSeconds(
|
||||
time_t Hours,
|
||||
time_t Minutes,
|
||||
time_t Seconds,
|
||||
int Hours,
|
||||
int Minutes,
|
||||
int Seconds,
|
||||
MERIDIAN Meridian)
|
||||
{
|
||||
if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59) {
|
||||
@@ -2680,7 +2615,7 @@ TclDatelex(
|
||||
|
||||
location->first_column = yyInput - info->dateStart;
|
||||
for ( ; ; ) {
|
||||
while (TclIsSpaceProc(*yyInput)) {
|
||||
while (isspace(UCHAR(*yyInput))) {
|
||||
yyInput++;
|
||||
}
|
||||
|
||||
@@ -2740,65 +2675,36 @@ TclDatelex(
|
||||
} while (Count > 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
TclClockOldscanObjCmd(
|
||||
ClientData clientData, /* Unused */
|
||||
TclClockFreeScan(
|
||||
Tcl_Interp *interp, /* Tcl interpreter */
|
||||
int objc, /* Count of paraneters */
|
||||
Tcl_Obj *const *objv) /* Parameters */
|
||||
DateInfo *info) /* Input and result parameters */
|
||||
{
|
||||
Tcl_Obj *result, *resultElement;
|
||||
int yr, mo, da;
|
||||
DateInfo dateInfo;
|
||||
DateInfo* info = &dateInfo;
|
||||
int status;
|
||||
|
||||
if (objc != 5) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv,
|
||||
"stringToParse baseYear baseMonth baseDay" );
|
||||
return TCL_ERROR;
|
||||
}
|
||||
/*
|
||||
* yyInput = stringToParse;
|
||||
*
|
||||
* ClockInitDateInfo(info) should be executed to pre-init info;
|
||||
*/
|
||||
|
||||
yyInput = Tcl_GetString( objv[1] );
|
||||
dateInfo.dateStart = yyInput;
|
||||
yyDSTmode = DSTmaybe;
|
||||
|
||||
yyHaveDate = 0;
|
||||
if (Tcl_GetIntFromObj(interp, objv[2], &yr) != TCL_OK
|
||||
|| Tcl_GetIntFromObj(interp, objv[3], &mo) != TCL_OK
|
||||
|| Tcl_GetIntFromObj(interp, objv[4], &da) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
yyYear = yr; yyMonth = mo; yyDay = da;
|
||||
info->messages = Tcl_NewObj();
|
||||
info->separatrix = "";
|
||||
Tcl_IncrRefCount(info->messages);
|
||||
|
||||
yyHaveTime = 0;
|
||||
yyHour = 0; yyMinutes = 0; yySeconds = 0; yyMeridian = MER24;
|
||||
|
||||
yyHaveZone = 0;
|
||||
yyTimezone = 0; yyDSTmode = DSTmaybe;
|
||||
|
||||
yyHaveOrdinalMonth = 0;
|
||||
yyMonthOrdinal = 0;
|
||||
|
||||
yyHaveDay = 0;
|
||||
yyDayOrdinal = 0; yyDayNumber = 0;
|
||||
|
||||
yyHaveRel = 0;
|
||||
yyRelMonth = 0; yyRelDay = 0; yyRelSeconds = 0; yyRelPointer = NULL;
|
||||
|
||||
dateInfo.messages = Tcl_NewObj();
|
||||
dateInfo.separatrix = "";
|
||||
Tcl_IncrRefCount(dateInfo.messages);
|
||||
|
||||
status = yyparse(&dateInfo);
|
||||
info->dateStart = yyInput;
|
||||
status = yyparse(info);
|
||||
if (status == 1) {
|
||||
Tcl_SetObjResult(interp, dateInfo.messages);
|
||||
Tcl_DecrRefCount(dateInfo.messages);
|
||||
Tcl_SetObjResult(interp, info->messages);
|
||||
Tcl_DecrRefCount(info->messages);
|
||||
Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "PARSE", NULL);
|
||||
return TCL_ERROR;
|
||||
} else if (status == 2) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj("memory exhausted", -1));
|
||||
Tcl_DecrRefCount(dateInfo.messages);
|
||||
Tcl_DecrRefCount(info->messages);
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
return TCL_ERROR;
|
||||
} else if (status != 0) {
|
||||
@@ -2806,11 +2712,11 @@ TclClockOldscanObjCmd(
|
||||
"from date parser. Please "
|
||||
"report this error as a "
|
||||
"bug in Tcl.", -1));
|
||||
Tcl_DecrRefCount(dateInfo.messages);
|
||||
Tcl_DecrRefCount(info->messages);
|
||||
Tcl_SetErrorCode(interp, "TCL", "BUG", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_DecrRefCount(dateInfo.messages);
|
||||
Tcl_DecrRefCount(info->messages);
|
||||
|
||||
if (yyHaveDate > 1) {
|
||||
Tcl_SetObjResult(interp,
|
||||
@@ -2843,6 +2749,40 @@ TclClockOldscanObjCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
int
|
||||
TclClockOldscanObjCmd(
|
||||
ClientData clientData, /* Unused */
|
||||
Tcl_Interp *interp, /* Tcl interpreter */
|
||||
int objc, /* Count of paraneters */
|
||||
Tcl_Obj *const *objv) /* Parameters */
|
||||
{
|
||||
Tcl_Obj *result, *resultElement;
|
||||
int yr, mo, da;
|
||||
DateInfo dateInfo;
|
||||
DateInfo* info = &dateInfo;
|
||||
|
||||
if (objc != 5) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv,
|
||||
"stringToParse baseYear baseMonth baseDay" );
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
yyInput = Tcl_GetString( objv[1] );
|
||||
|
||||
if (Tcl_GetIntFromObj(interp, objv[2], &yr) != TCL_OK
|
||||
|| Tcl_GetIntFromObj(interp, objv[3], &mo) != TCL_OK
|
||||
|| Tcl_GetIntFromObj(interp, objv[4], &da) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
yyYear = yr; yyMonth = mo; yyDay = da;
|
||||
|
||||
if (TclClockFreeScan(interp, info) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
result = Tcl_NewObj();
|
||||
resultElement = Tcl_NewObj();
|
||||
if (yyHaveDate) {
|
||||
@@ -2894,9 +2834,9 @@ TclClockOldscanObjCmd(
|
||||
resultElement = Tcl_NewObj();
|
||||
if (yyHaveOrdinalMonth) {
|
||||
Tcl_ListObjAppendElement(interp, resultElement,
|
||||
Tcl_NewIntObj((int) yyMonthOrdinal));
|
||||
Tcl_NewIntObj((int) yyMonthOrdinalIncr));
|
||||
Tcl_ListObjAppendElement(interp, resultElement,
|
||||
Tcl_NewIntObj((int) yyMonth));
|
||||
Tcl_NewIntObj((int) yyMonthOrdinal));
|
||||
}
|
||||
Tcl_ListObjAppendElement(interp, result, resultElement);
|
||||
|
||||
|
||||
@@ -0,0 +1,512 @@
|
||||
/*
|
||||
* tclDate.h --
|
||||
*
|
||||
* This header file handles common usage of clock primitives
|
||||
* between tclDate.c (yacc), tclClock.c and tclClockFmt.c.
|
||||
*
|
||||
* Copyright (c) 2014 Serg G. Brester (aka sebres)
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution
|
||||
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
*/
|
||||
|
||||
#ifndef _TCLCLOCK_H
|
||||
#define _TCLCLOCK_H
|
||||
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
|
||||
#define JULIAN_DAY_POSIX_EPOCH 2440588
|
||||
#define GREGORIAN_CHANGE_DATE 2361222
|
||||
#define SECONDS_PER_DAY 86400
|
||||
#define JULIAN_SEC_POSIX_EPOCH (((Tcl_WideInt) JULIAN_DAY_POSIX_EPOCH) \
|
||||
* SECONDS_PER_DAY)
|
||||
#define FOUR_CENTURIES 146097 /* days */
|
||||
#define JDAY_1_JAN_1_CE_JULIAN 1721424
|
||||
#define JDAY_1_JAN_1_CE_GREGORIAN 1721426
|
||||
#define ONE_CENTURY_GREGORIAN 36524 /* days */
|
||||
#define FOUR_YEARS 1461 /* days */
|
||||
#define ONE_YEAR 365 /* days */
|
||||
|
||||
#define RODDENBERRY 1946 /* Another epoch (Hi, Jeff!) */
|
||||
|
||||
|
||||
#define CLF_OPTIONAL (1 << 0) /* token is non mandatory */
|
||||
#define CLF_POSIXSEC (1 << 1)
|
||||
#define CLF_LOCALSEC (1 << 2)
|
||||
#define CLF_JULIANDAY (1 << 3)
|
||||
#define CLF_TIME (1 << 4)
|
||||
#define CLF_CENTURY (1 << 6)
|
||||
#define CLF_DAYOFMONTH (1 << 7)
|
||||
#define CLF_DAYOFYEAR (1 << 8)
|
||||
#define CLF_MONTH (1 << 9)
|
||||
#define CLF_YEAR (1 << 10)
|
||||
#define CLF_ISO8601YEAR (1 << 12)
|
||||
#define CLF_ISO8601 (1 << 13)
|
||||
#define CLF_ISO8601CENTURY (1 << 14)
|
||||
#define CLF_SIGNED (1 << 15)
|
||||
/* On demand (lazy) assemble flags */
|
||||
#define CLF_ASSEMBLE_DATE (1 << 28) /* assemble year, month, etc. using julianDay */
|
||||
#define CLF_ASSEMBLE_JULIANDAY (1 << 29) /* assemble julianDay using year, month, etc. */
|
||||
#define CLF_ASSEMBLE_SECONDS (1 << 30) /* assemble localSeconds (and seconds at end) */
|
||||
|
||||
#define CLF_DATE (CLF_JULIANDAY | CLF_DAYOFMONTH | CLF_DAYOFYEAR | \
|
||||
CLF_MONTH | CLF_YEAR | CLF_ISO8601YEAR | CLF_ISO8601)
|
||||
|
||||
/*
|
||||
* Enumeration of the string literals used in [clock]
|
||||
*/
|
||||
|
||||
typedef enum ClockLiteral {
|
||||
LIT__NIL,
|
||||
LIT__DEFAULT_FORMAT,
|
||||
LIT_SYSTEM, LIT_CURRENT, LIT_C,
|
||||
LIT_BCE, LIT_CE,
|
||||
LIT_DAYOFMONTH, LIT_DAYOFWEEK, LIT_DAYOFYEAR,
|
||||
LIT_ERA, LIT_GMT, LIT_GREGORIAN,
|
||||
LIT_INTEGER_VALUE_TOO_LARGE,
|
||||
LIT_ISO8601WEEK, LIT_ISO8601YEAR,
|
||||
LIT_JULIANDAY, LIT_LOCALSECONDS,
|
||||
LIT_MONTH,
|
||||
LIT_SECONDS, LIT_TZNAME, LIT_TZOFFSET,
|
||||
LIT_YEAR,
|
||||
LIT_TZDATA,
|
||||
LIT_GETSYSTEMTIMEZONE,
|
||||
LIT_SETUPTIMEZONE,
|
||||
LIT_MCGET,
|
||||
LIT_GETSYSTEMLOCALE, LIT_GETCURRENTLOCALE,
|
||||
LIT_LOCALIZE_FORMAT,
|
||||
LIT__END
|
||||
} ClockLiteral;
|
||||
|
||||
#define CLOCK_LITERAL_ARRAY(litarr) static const char *const litarr[] = { \
|
||||
"", \
|
||||
"%a %b %d %H:%M:%S %Z %Y", \
|
||||
"system", "current", "C", \
|
||||
"BCE", "CE", \
|
||||
"dayOfMonth", "dayOfWeek", "dayOfYear", \
|
||||
"era", ":GMT", "gregorian", \
|
||||
"integer value too large to represent", \
|
||||
"iso8601Week", "iso8601Year", \
|
||||
"julianDay", "localSeconds", \
|
||||
"month", \
|
||||
"seconds", "tzName", "tzOffset", \
|
||||
"year", \
|
||||
"::tcl::clock::TZData", \
|
||||
"::tcl::clock::GetSystemTimeZone", \
|
||||
"::tcl::clock::SetupTimeZone", \
|
||||
"::tcl::clock::mcget", \
|
||||
"::tcl::clock::GetSystemLocale", "::tcl::clock::mclocale", \
|
||||
"::tcl::clock::LocalizeFormat" \
|
||||
}
|
||||
|
||||
/*
|
||||
* Enumeration of the msgcat literals used in [clock]
|
||||
*/
|
||||
|
||||
typedef enum ClockMsgCtLiteral {
|
||||
MCLIT__NIL, /* placeholder */
|
||||
MCLIT_MONTHS_FULL, MCLIT_MONTHS_ABBREV, MCLIT_MONTHS_COMB,
|
||||
MCLIT_DAYS_OF_WEEK_FULL, MCLIT_DAYS_OF_WEEK_ABBREV, MCLIT_DAYS_OF_WEEK_COMB,
|
||||
MCLIT_AM, MCLIT_PM,
|
||||
MCLIT_LOCALE_ERAS,
|
||||
MCLIT_BCE, MCLIT_CE,
|
||||
MCLIT_BCE2, MCLIT_CE2,
|
||||
MCLIT_BCE3, MCLIT_CE3,
|
||||
MCLIT_LOCALE_NUMERALS,
|
||||
MCLIT__END
|
||||
} ClockMsgCtLiteral;
|
||||
|
||||
#define CLOCK_LOCALE_LITERAL_ARRAY(litarr, pref) static const char *const litarr[] = { \
|
||||
pref "", \
|
||||
pref "MONTHS_FULL", pref "MONTHS_ABBREV", pref "MONTHS_COMB", \
|
||||
pref "DAYS_OF_WEEK_FULL", pref "DAYS_OF_WEEK_ABBREV", pref "DAYS_OF_WEEK_COMB", \
|
||||
pref "AM", pref "PM", \
|
||||
pref "LOCALE_ERAS", \
|
||||
pref "BCE", pref "CE", \
|
||||
pref "b.c.e.", pref "c.e.", \
|
||||
pref "b.c.", pref "a.d.", \
|
||||
pref "LOCALE_NUMERALS", \
|
||||
}
|
||||
|
||||
/*
|
||||
* Structure containing the fields used in [clock format] and [clock scan]
|
||||
*/
|
||||
|
||||
typedef struct TclDateFields {
|
||||
|
||||
/* Cacheable fields: */
|
||||
|
||||
Tcl_WideInt seconds; /* Time expressed in seconds from the Posix
|
||||
* epoch */
|
||||
Tcl_WideInt localSeconds; /* Local time expressed in nominal seconds
|
||||
* from the Posix epoch */
|
||||
int tzOffset; /* Time zone offset in seconds east of
|
||||
* Greenwich */
|
||||
int julianDay; /* Julian Day Number in local time zone */
|
||||
enum {BCE=1, CE=0} era; /* Era */
|
||||
int gregorian; /* Flag == 1 if the date is Gregorian */
|
||||
int year; /* Year of the era */
|
||||
int dayOfYear; /* Day of the year (1 January == 1) */
|
||||
int month; /* Month number */
|
||||
int dayOfMonth; /* Day of the month */
|
||||
int iso8601Year; /* ISO8601 week-based year */
|
||||
int iso8601Week; /* ISO8601 week number */
|
||||
int dayOfWeek; /* Day of the week */
|
||||
int hour; /* Hours of day (in-between time only calculation) */
|
||||
int minutes; /* Minutes of day (in-between time only calculation) */
|
||||
int secondOfDay; /* Seconds of day (in-between time only calculation) */
|
||||
|
||||
/* Non cacheable fields: */
|
||||
|
||||
Tcl_Obj *tzName; /* Name (or corresponding DST-abbreviation) of the
|
||||
* time zone, if set the refCount is incremented */
|
||||
} TclDateFields;
|
||||
|
||||
#define ClockCacheableDateFieldsSize \
|
||||
TclOffset(TclDateFields, tzName)
|
||||
|
||||
/*
|
||||
* Structure contains return parsed fields.
|
||||
*/
|
||||
|
||||
typedef struct DateInfo {
|
||||
const char *dateStart;
|
||||
const char *dateInput;
|
||||
const char *dateEnd;
|
||||
|
||||
TclDateFields date;
|
||||
|
||||
int flags;
|
||||
|
||||
int dateHaveDate;
|
||||
|
||||
int dateMeridian;
|
||||
int dateHaveTime;
|
||||
|
||||
int dateTimezone;
|
||||
int dateDSTmode;
|
||||
int dateHaveZone;
|
||||
|
||||
int dateRelMonth;
|
||||
int dateRelDay;
|
||||
int dateRelSeconds;
|
||||
int dateHaveRel;
|
||||
|
||||
int dateMonthOrdinalIncr;
|
||||
int dateMonthOrdinal;
|
||||
int dateHaveOrdinalMonth;
|
||||
|
||||
int dateDayOrdinal;
|
||||
int dateDayNumber;
|
||||
int dateHaveDay;
|
||||
|
||||
int *dateRelPointer;
|
||||
|
||||
int dateSpaceCount;
|
||||
int dateDigitCount;
|
||||
|
||||
int dateCentury;
|
||||
|
||||
Tcl_Obj* messages; /* Error messages */
|
||||
const char* separatrix; /* String separating messages */
|
||||
} DateInfo;
|
||||
|
||||
#define yydate (info->date) /* Date fields used for converting */
|
||||
|
||||
#define yyDay (info->date.dayOfMonth)
|
||||
#define yyMonth (info->date.month)
|
||||
#define yyYear (info->date.year)
|
||||
|
||||
#define yyHour (info->date.hour)
|
||||
#define yyMinutes (info->date.minutes)
|
||||
#define yySeconds (info->date.secondOfDay)
|
||||
|
||||
#define yyDSTmode (info->dateDSTmode)
|
||||
#define yyDayOrdinal (info->dateDayOrdinal)
|
||||
#define yyDayNumber (info->dateDayNumber)
|
||||
#define yyMonthOrdinalIncr (info->dateMonthOrdinalIncr)
|
||||
#define yyMonthOrdinal (info->dateMonthOrdinal)
|
||||
#define yyHaveDate (info->dateHaveDate)
|
||||
#define yyHaveDay (info->dateHaveDay)
|
||||
#define yyHaveOrdinalMonth (info->dateHaveOrdinalMonth)
|
||||
#define yyHaveRel (info->dateHaveRel)
|
||||
#define yyHaveTime (info->dateHaveTime)
|
||||
#define yyHaveZone (info->dateHaveZone)
|
||||
#define yyTimezone (info->dateTimezone)
|
||||
#define yyMeridian (info->dateMeridian)
|
||||
#define yyRelMonth (info->dateRelMonth)
|
||||
#define yyRelDay (info->dateRelDay)
|
||||
#define yyRelSeconds (info->dateRelSeconds)
|
||||
#define yyRelPointer (info->dateRelPointer)
|
||||
#define yyInput (info->dateInput)
|
||||
#define yyDigitCount (info->dateDigitCount)
|
||||
#define yySpaceCount (info->dateSpaceCount)
|
||||
|
||||
static inline void
|
||||
ClockInitDateInfo(DateInfo *info) {
|
||||
memset(info, 0, sizeof(DateInfo));
|
||||
}
|
||||
|
||||
/*
|
||||
* Structure containing the command arguments supplied to [clock format] and [clock scan]
|
||||
*/
|
||||
|
||||
#define CLF_EXTENDED (1 << 4)
|
||||
#define CLF_STRICT (1 << 8)
|
||||
#define CLF_LOCALE_USED (1 << 15)
|
||||
|
||||
typedef struct ClockFmtScnCmdArgs {
|
||||
ClientData clientData; /* Opaque pointer to literal pool, etc. */
|
||||
Tcl_Interp *interp; /* Tcl interpreter */
|
||||
|
||||
Tcl_Obj *formatObj; /* Format */
|
||||
Tcl_Obj *localeObj; /* Name of the locale where the time will be expressed. */
|
||||
Tcl_Obj *timezoneObj; /* Default time zone in which the time will be expressed */
|
||||
Tcl_Obj *baseObj; /* Base (scan and add) or clockValue (format) */
|
||||
int flags; /* Flags control scanning */
|
||||
|
||||
Tcl_Obj *mcDictObj; /* Current dictionary of tcl::clock package for given localeObj*/
|
||||
} ClockFmtScnCmdArgs;
|
||||
|
||||
/*
|
||||
* Structure containing the client data for [clock]
|
||||
*/
|
||||
|
||||
typedef struct ClockClientData {
|
||||
size_t refCount; /* Number of live references. */
|
||||
Tcl_Obj **literals; /* Pool of object literals (common, locale independent). */
|
||||
Tcl_Obj **mcLiterals; /* Msgcat object literals with mc-keys for search with locale. */
|
||||
Tcl_Obj **mcLitIdxs; /* Msgcat object indices prefixed with _IDX_,
|
||||
* used for quick dictionary search */
|
||||
|
||||
/* Cache for current clock parameters, imparted via "configure" */
|
||||
unsigned long LastTZEpoch;
|
||||
int currentYearCentury;
|
||||
int yearOfCenturySwitch;
|
||||
Tcl_Obj *SystemTimeZone;
|
||||
Tcl_Obj *SystemSetupTZData;
|
||||
Tcl_Obj *GMTSetupTimeZone;
|
||||
Tcl_Obj *GMTSetupTZData;
|
||||
Tcl_Obj *AnySetupTimeZone;
|
||||
Tcl_Obj *AnySetupTZData;
|
||||
Tcl_Obj *LastUnnormSetupTimeZone;
|
||||
Tcl_Obj *LastSetupTimeZone;
|
||||
Tcl_Obj *LastSetupTZData;
|
||||
|
||||
Tcl_Obj *CurrentLocale;
|
||||
Tcl_Obj *CurrentLocaleDict;
|
||||
Tcl_Obj *LastUnnormUsedLocale;
|
||||
Tcl_Obj *LastUsedLocale;
|
||||
Tcl_Obj *LastUsedLocaleDict;
|
||||
|
||||
/* Cache for last base (last-second fast convert if base/tz not changed) */
|
||||
struct {
|
||||
Tcl_Obj *timezoneObj;
|
||||
TclDateFields Date;
|
||||
} lastBase;
|
||||
/* Las-period cache for fast UTC2Local conversion */
|
||||
struct {
|
||||
/* keys */
|
||||
Tcl_Obj *timezoneObj;
|
||||
int changeover;
|
||||
Tcl_WideInt seconds;
|
||||
Tcl_WideInt rangesVal[2]; /* Bounds for cached time zone offset */
|
||||
/* values */
|
||||
int tzOffset;
|
||||
Tcl_Obj *tzName;
|
||||
} UTC2Local;
|
||||
/* Las-period cache for fast Local2UTC conversion */
|
||||
struct {
|
||||
/* keys */
|
||||
Tcl_Obj *timezoneObj;
|
||||
int changeover;
|
||||
Tcl_WideInt localSeconds;
|
||||
Tcl_WideInt rangesVal[2]; /* Bounds for cached time zone offset */
|
||||
/* values */
|
||||
int tzOffset;
|
||||
} Local2UTC;
|
||||
} ClockClientData;
|
||||
|
||||
#define ClockDefaultYearCentury 2000
|
||||
#define ClockDefaultCenturySwitch 38
|
||||
|
||||
/*
|
||||
* Meridian: am, pm, or 24-hour style.
|
||||
*/
|
||||
|
||||
typedef enum _MERIDIAN {
|
||||
MERam, MERpm, MER24
|
||||
} MERIDIAN;
|
||||
|
||||
/*
|
||||
* Clock scan and format facilities.
|
||||
*/
|
||||
|
||||
#define CLOCK_FMT_SCN_STORAGE_GC_SIZE 32
|
||||
|
||||
#define CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE 2
|
||||
|
||||
typedef struct ClockScanToken ClockScanToken;
|
||||
|
||||
|
||||
typedef int ClockScanTokenProc(
|
||||
ClockFmtScnCmdArgs *opts,
|
||||
DateInfo *info,
|
||||
ClockScanToken *tok);
|
||||
|
||||
|
||||
typedef enum _CLCKTOK_TYPE {
|
||||
CTOKT_DIGIT = 1, CTOKT_PARSER, CTOKT_SPACE, CTOKT_WORD, CTOKT_CHAR,
|
||||
CFMTT_INT, CFMTT_WIDE, CFMTT_PROC
|
||||
} CLCKTOK_TYPE;
|
||||
|
||||
typedef struct ClockScanTokenMap {
|
||||
unsigned short int type;
|
||||
unsigned short int flags;
|
||||
unsigned short int clearFlags;
|
||||
unsigned short int minSize;
|
||||
unsigned short int maxSize;
|
||||
unsigned short int offs;
|
||||
ClockScanTokenProc *parser;
|
||||
const void *data;
|
||||
} ClockScanTokenMap;
|
||||
|
||||
typedef struct ClockScanToken {
|
||||
ClockScanTokenMap *map;
|
||||
struct {
|
||||
const char *start;
|
||||
const char *end;
|
||||
} tokWord;
|
||||
unsigned short int endDistance;
|
||||
unsigned short int lookAhMin;
|
||||
unsigned short int lookAhMax;
|
||||
unsigned short int lookAhTok;
|
||||
} ClockScanToken;
|
||||
|
||||
|
||||
#define MIN_FMT_RESULT_BLOCK_ALLOC 200
|
||||
|
||||
typedef struct DateFormat {
|
||||
char *resMem;
|
||||
char *resEnd;
|
||||
char *output;
|
||||
|
||||
TclDateFields date;
|
||||
|
||||
Tcl_Obj *localeEra;
|
||||
} DateFormat;
|
||||
|
||||
#define CLFMT_INCR (1 << 3)
|
||||
#define CLFMT_DECR (1 << 4)
|
||||
#define CLFMT_CALC (1 << 5)
|
||||
#define CLFMT_LOCALE_INDX (1 << 8)
|
||||
|
||||
typedef struct ClockFormatToken ClockFormatToken;
|
||||
|
||||
typedef int ClockFormatTokenProc(
|
||||
ClockFmtScnCmdArgs *opts,
|
||||
DateFormat *dateFmt,
|
||||
ClockFormatToken *tok,
|
||||
int *val);
|
||||
|
||||
typedef struct ClockFormatTokenMap {
|
||||
unsigned short int type;
|
||||
const char *tostr;
|
||||
unsigned short int width;
|
||||
unsigned short int flags;
|
||||
unsigned short int divider;
|
||||
unsigned short int divmod;
|
||||
unsigned short int offs;
|
||||
ClockFormatTokenProc *fmtproc;
|
||||
void *data;
|
||||
} ClockFormatTokenMap;
|
||||
typedef struct ClockFormatToken {
|
||||
ClockFormatTokenMap *map;
|
||||
struct {
|
||||
const char *start;
|
||||
const char *end;
|
||||
} tokWord;
|
||||
} ClockFormatToken;
|
||||
|
||||
|
||||
typedef struct ClockFmtScnStorage ClockFmtScnStorage;
|
||||
|
||||
typedef struct ClockFmtScnStorage {
|
||||
int objRefCount; /* Reference count shared across threads */
|
||||
ClockScanToken *scnTok;
|
||||
unsigned int scnTokC;
|
||||
unsigned int scnSpaceCount; /* Count of mandatory spaces used in format */
|
||||
ClockFormatToken *fmtTok;
|
||||
unsigned int fmtTokC;
|
||||
#if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0
|
||||
ClockFmtScnStorage *nextPtr;
|
||||
ClockFmtScnStorage *prevPtr;
|
||||
#endif
|
||||
#if 0
|
||||
+Tcl_HashEntry hashEntry /* ClockFmtScnStorage is a derivate of Tcl_HashEntry,
|
||||
* stored by offset +sizeof(self) */
|
||||
#endif
|
||||
} ClockFmtScnStorage;
|
||||
|
||||
/*
|
||||
* Prototypes of module functions.
|
||||
*/
|
||||
|
||||
MODULE_SCOPE int ToSeconds(int Hours, int Minutes,
|
||||
int Seconds, MERIDIAN Meridian);
|
||||
MODULE_SCOPE int IsGregorianLeapYear(TclDateFields *);
|
||||
MODULE_SCOPE void
|
||||
GetJulianDayFromEraYearWeekDay(
|
||||
TclDateFields *fields, int changeover);
|
||||
MODULE_SCOPE void
|
||||
GetJulianDayFromEraYearMonthDay(
|
||||
TclDateFields *fields, int changeover);
|
||||
MODULE_SCOPE void
|
||||
GetJulianDayFromEraYearDay(
|
||||
TclDateFields *fields, int changeover);
|
||||
MODULE_SCOPE int ConvertUTCToLocal(ClientData clientData, Tcl_Interp *,
|
||||
TclDateFields *, Tcl_Obj *timezoneObj, int);
|
||||
MODULE_SCOPE Tcl_Obj *
|
||||
LookupLastTransition(Tcl_Interp *, Tcl_WideInt,
|
||||
int, Tcl_Obj *const *, Tcl_WideInt rangesVal[2]);
|
||||
|
||||
MODULE_SCOPE int TclClockFreeScan(Tcl_Interp *interp, DateInfo *info);
|
||||
|
||||
/* tclClock.c module declarations */
|
||||
|
||||
MODULE_SCOPE Tcl_Obj *
|
||||
ClockSetupTimeZone(ClientData clientData,
|
||||
Tcl_Interp *interp, Tcl_Obj *timezoneObj);
|
||||
|
||||
MODULE_SCOPE Tcl_Obj *
|
||||
ClockMCDict(ClockFmtScnCmdArgs *opts);
|
||||
MODULE_SCOPE Tcl_Obj *
|
||||
ClockMCGet(ClockFmtScnCmdArgs *opts, int mcKey);
|
||||
MODULE_SCOPE Tcl_Obj *
|
||||
ClockMCGetIdx(ClockFmtScnCmdArgs *opts, int mcKey);
|
||||
MODULE_SCOPE int ClockMCSetIdx(ClockFmtScnCmdArgs *opts, int mcKey,
|
||||
Tcl_Obj *valObj);
|
||||
|
||||
/* tclClockFmt.c module declarations */
|
||||
|
||||
MODULE_SCOPE Tcl_Obj*
|
||||
ClockFrmObjGetLocFmtKey(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr);
|
||||
|
||||
MODULE_SCOPE ClockFmtScnStorage *
|
||||
Tcl_GetClockFrmScnFromObj(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr);
|
||||
MODULE_SCOPE Tcl_Obj *
|
||||
ClockLocalizeFormat(ClockFmtScnCmdArgs *opts);
|
||||
|
||||
MODULE_SCOPE int ClockScan(register DateInfo *info,
|
||||
Tcl_Obj *strObj, ClockFmtScnCmdArgs *opts);
|
||||
|
||||
MODULE_SCOPE int ClockFormat(register DateFormat *dateFmt,
|
||||
ClockFmtScnCmdArgs *opts);
|
||||
|
||||
MODULE_SCOPE void ClockFrmScnClearCaches(void);
|
||||
|
||||
#endif /* _TCLCLOCK_H */
|
||||
+283
-208
File diff suppressed because it is too large
Load Diff
+121
-24
@@ -51,6 +51,8 @@ static int DictSetCmd(ClientData dummy, Tcl_Interp *interp,
|
||||
int objc, Tcl_Obj *const *objv);
|
||||
static int DictSizeCmd(ClientData dummy, Tcl_Interp *interp,
|
||||
int objc, Tcl_Obj *const *objv);
|
||||
static int DictSmartRefCmd(ClientData dummy, Tcl_Interp *interp,
|
||||
int objc, Tcl_Obj *const *objv);
|
||||
static int DictUnsetCmd(ClientData dummy, Tcl_Interp *interp,
|
||||
int objc, Tcl_Obj *const *objv);
|
||||
static int DictUpdateCmd(ClientData dummy, Tcl_Interp *interp,
|
||||
@@ -98,6 +100,7 @@ static const EnsembleImplMap implementationMap[] = {
|
||||
{"replace", DictReplaceCmd, NULL, NULL, NULL, 0 },
|
||||
{"set", DictSetCmd, TclCompileDictSetCmd, NULL, NULL, 0 },
|
||||
{"size", DictSizeCmd, TclCompileBasic1ArgCmd, NULL, NULL, 0 },
|
||||
{"smartref",DictSmartRefCmd,NULL, NULL, NULL, 0 },
|
||||
{"unset", DictUnsetCmd, TclCompileDictUnsetCmd, NULL, NULL, 0 },
|
||||
{"update", DictUpdateCmd, TclCompileDictUpdateCmd, NULL, NULL, 0 },
|
||||
{"values", DictValuesCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 },
|
||||
@@ -141,7 +144,7 @@ typedef struct Dict {
|
||||
* the dictionary. Used for doing traversal of
|
||||
* the entries in the order that they are
|
||||
* created. */
|
||||
unsigned int epoch; /* Epoch counter */
|
||||
int epoch; /* Epoch counter */
|
||||
size_t refCount; /* Reference counter (see above) */
|
||||
Tcl_Obj *chain; /* Linked list used for invalidating the
|
||||
* string representations of updated nested
|
||||
@@ -235,7 +238,7 @@ AllocChainEntry(
|
||||
cPtr = ckalloc(sizeof(ChainEntry));
|
||||
cPtr->entry.key.objPtr = objPtr;
|
||||
Tcl_IncrRefCount(objPtr);
|
||||
Tcl_SetHashValue(&cPtr->entry, NULL);
|
||||
cPtr->entry.clientData = NULL;
|
||||
cPtr->prevPtr = cPtr->nextPtr = NULL;
|
||||
|
||||
return &cPtr->entry;
|
||||
@@ -390,7 +393,7 @@ DupDictInternalRep(
|
||||
* Initialise other fields.
|
||||
*/
|
||||
|
||||
newDict->epoch = 1;
|
||||
newDict->epoch = 0;
|
||||
newDict->chain = NULL;
|
||||
newDict->refCount = 1;
|
||||
|
||||
@@ -487,14 +490,15 @@ static void
|
||||
UpdateStringOfDict(
|
||||
Tcl_Obj *dictPtr)
|
||||
{
|
||||
#define LOCAL_SIZE 64
|
||||
char localFlags[LOCAL_SIZE], *flagPtr = NULL;
|
||||
#define LOCAL_SIZE 20
|
||||
int localFlags[LOCAL_SIZE], *flagPtr = NULL;
|
||||
Dict *dict = DICT(dictPtr);
|
||||
ChainEntry *cPtr;
|
||||
Tcl_Obj *keyPtr, *valuePtr;
|
||||
int i, length, bytesNeeded = 0;
|
||||
const char *elem;
|
||||
char *dst;
|
||||
const int maxFlags = UINT_MAX / sizeof(int);
|
||||
|
||||
/*
|
||||
* This field is the most useful one in the whole hash structure, and it
|
||||
@@ -516,8 +520,10 @@ UpdateStringOfDict(
|
||||
|
||||
if (numElems <= LOCAL_SIZE) {
|
||||
flagPtr = localFlags;
|
||||
} else if (numElems > maxFlags) {
|
||||
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
|
||||
} else {
|
||||
flagPtr = ckalloc(numElems);
|
||||
flagPtr = ckalloc(numElems * sizeof(int));
|
||||
}
|
||||
for (i=0,cPtr=dict->entryChainHead; i<numElems; i+=2,cPtr=cPtr->nextPtr) {
|
||||
/*
|
||||
@@ -707,7 +713,7 @@ SetDictFromAny(
|
||||
*/
|
||||
|
||||
TclFreeIntRep(objPtr);
|
||||
dict->epoch = 1;
|
||||
dict->epoch = 0;
|
||||
dict->chain = NULL;
|
||||
dict->refCount = 1;
|
||||
DICT(objPtr) = dict;
|
||||
@@ -1106,7 +1112,7 @@ Tcl_DictObjFirst(
|
||||
dict = DICT(dictPtr);
|
||||
cPtr = dict->entryChainHead;
|
||||
if (cPtr == NULL) {
|
||||
searchPtr->epoch = 0;
|
||||
searchPtr->epoch = -1;
|
||||
*donePtr = 1;
|
||||
} else {
|
||||
*donePtr = 0;
|
||||
@@ -1167,7 +1173,7 @@ Tcl_DictObjNext(
|
||||
* If the searh is done; we do no work.
|
||||
*/
|
||||
|
||||
if (!searchPtr->epoch) {
|
||||
if (searchPtr->epoch == -1) {
|
||||
*donePtr = 1;
|
||||
return;
|
||||
}
|
||||
@@ -1224,8 +1230,8 @@ Tcl_DictObjDone(
|
||||
{
|
||||
Dict *dict;
|
||||
|
||||
if (searchPtr->epoch) {
|
||||
searchPtr->epoch = 0;
|
||||
if (searchPtr->epoch != -1) {
|
||||
searchPtr->epoch = -1;
|
||||
dict = (Dict *) searchPtr->dictionaryPtr;
|
||||
if (dict->refCount-- <= 1) {
|
||||
DeleteDict(dict);
|
||||
@@ -1377,7 +1383,7 @@ Tcl_NewDictObj(void)
|
||||
TclInvalidateStringRep(dictPtr);
|
||||
dict = ckalloc(sizeof(Dict));
|
||||
InitChainTable(dict);
|
||||
dict->epoch = 1;
|
||||
dict->epoch = 0;
|
||||
dict->chain = NULL;
|
||||
dict->refCount = 1;
|
||||
DICT(dictPtr) = dict;
|
||||
@@ -1427,7 +1433,7 @@ Tcl_DbNewDictObj(
|
||||
TclInvalidateStringRep(dictPtr);
|
||||
dict = ckalloc(sizeof(Dict));
|
||||
InitChainTable(dict);
|
||||
dict->epoch = 1;
|
||||
dict->epoch = 0;
|
||||
dict->chain = NULL;
|
||||
dict->refCount = 1;
|
||||
DICT(dictPtr) = dict;
|
||||
@@ -1952,6 +1958,102 @@ DictSizeCmd(
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Tcl_DictObjSmartRef --
|
||||
*
|
||||
* This function returns new tcl-object with the smart reference to
|
||||
* dictionary object.
|
||||
*
|
||||
* Object returned with this function is a smart reference (pointer),
|
||||
* so new object of type tclDictType, that directly references given
|
||||
* dictionary object (with internally increased refCount).
|
||||
*
|
||||
* The usage of such pointer objects allows to hold more as one
|
||||
* reference to the same real dictionary object, allows to make a pointer
|
||||
* to part of another dictionary, allows to change the dictionary without
|
||||
* regarding of the "shared" state of the dictionary object.
|
||||
*
|
||||
* Prevents "called with shared object" exception if object is multiple
|
||||
* referenced.
|
||||
*
|
||||
* Results:
|
||||
* The newly create object (contains smart reference) is returned.
|
||||
* The returned object has a ref count of 0.
|
||||
*
|
||||
* Side effects:
|
||||
* Increases ref count of the referenced dictionary.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Tcl_Obj *
|
||||
Tcl_DictObjSmartRef(
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Obj *dictPtr)
|
||||
{
|
||||
Tcl_Obj *result;
|
||||
Dict *dict;
|
||||
|
||||
if (dictPtr->typePtr != &tclDictType
|
||||
&& SetDictFromAny(interp, dictPtr) != TCL_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dict = DICT(dictPtr);
|
||||
|
||||
result = Tcl_NewObj();
|
||||
DICT(result) = dict;
|
||||
dict->refCount++;
|
||||
result->internalRep.twoPtrValue.ptr2 = NULL;
|
||||
result->typePtr = &tclDictType;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* DictSmartRefCmd --
|
||||
*
|
||||
* This function implements the "dict smartref" Tcl command.
|
||||
*
|
||||
* See description of Tcl_DictObjSmartRef for details.
|
||||
*
|
||||
* Results:
|
||||
* A standard Tcl result.
|
||||
*
|
||||
* Side effects:
|
||||
* See the user documentation.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
DictSmartRefCmd(
|
||||
ClientData dummy,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
Tcl_Obj *result;
|
||||
|
||||
if (objc != 2) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "dictionary");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
result = Tcl_DictObjSmartRef(interp, objv[1]);
|
||||
if (result == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
Tcl_SetObjResult(interp, result);
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
@@ -2309,12 +2411,9 @@ DictAppendCmd(
|
||||
|
||||
if (objc == 4) {
|
||||
appendObjPtr = objv[3];
|
||||
} else {
|
||||
appendObjPtr = TclStringCat(interp, objc-3, objv+3,
|
||||
TCL_STRING_IN_PLACE);
|
||||
if (appendObjPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
} else if (TCL_OK != TclStringCatObjv(interp, /* inPlace */ 1,
|
||||
objc-3, objv+3, &appendObjPtr)) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2331,9 +2430,7 @@ DictAppendCmd(
|
||||
valuePtr = Tcl_DuplicateObj(valuePtr);
|
||||
}
|
||||
|
||||
Tcl_IncrRefCount(appendObjPtr);
|
||||
Tcl_AppendObjToObj(valuePtr, appendObjPtr);
|
||||
Tcl_DecrRefCount(appendObjPtr);
|
||||
}
|
||||
|
||||
Tcl_DictObjPut(NULL, dictPtr, objv[2], valuePtr);
|
||||
@@ -3564,7 +3661,7 @@ TclDictWithFinish(
|
||||
* If the dictionary variable doesn't exist, drop everything silently.
|
||||
*/
|
||||
|
||||
dictPtr = TclPtrGetVarIdx(interp, varPtr, arrayPtr, part1Ptr, part2Ptr,
|
||||
dictPtr = TclPtrGetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr,
|
||||
TCL_LEAVE_ERR_MSG, index);
|
||||
if (dictPtr == NULL) {
|
||||
return TCL_OK;
|
||||
@@ -3647,8 +3744,8 @@ TclDictWithFinish(
|
||||
* Write back the outermost dictionary to the variable.
|
||||
*/
|
||||
|
||||
if (TclPtrSetVarIdx(interp, varPtr, arrayPtr, part1Ptr, part2Ptr,
|
||||
dictPtr, TCL_LEAVE_ERR_MSG, index) == NULL) {
|
||||
if (TclPtrSetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, dictPtr,
|
||||
TCL_LEAVE_ERR_MSG, index) == NULL) {
|
||||
if (allocdict) {
|
||||
TclDecrRefCount(dictPtr);
|
||||
}
|
||||
|
||||
+13
-13
@@ -254,7 +254,7 @@ DisassembleByteCodeObj(
|
||||
Tcl_Obj *bufferObj, *fileObj;
|
||||
|
||||
TclNewObj(bufferObj);
|
||||
if (!codePtr->refCount) {
|
||||
if (codePtr->refCount <= 0) {
|
||||
return bufferObj; /* Already freed. */
|
||||
}
|
||||
|
||||
@@ -267,9 +267,9 @@ DisassembleByteCodeObj(
|
||||
*/
|
||||
|
||||
Tcl_AppendPrintfToObj(bufferObj,
|
||||
"ByteCode %p, refCt %" TCL_LL_MODIFIER "d, epoch %" TCL_LL_MODIFIER "d, interp %p (epoch %" TCL_LL_MODIFIER "d)\n",
|
||||
codePtr, (Tcl_WideUInt)codePtr->refCount, (Tcl_WideUInt)codePtr->compileEpoch, iPtr,
|
||||
(Tcl_WideUInt)iPtr->compileEpoch);
|
||||
"ByteCode %p, refCt %u, epoch %u, interp %p (epoch %u)\n",
|
||||
codePtr, codePtr->refCount, codePtr->compileEpoch, iPtr,
|
||||
iPtr->compileEpoch);
|
||||
Tcl_AppendToObj(bufferObj, " Source ", -1);
|
||||
PrintSourceToObj(bufferObj, codePtr->source,
|
||||
TclMin(codePtr->numSrcBytes, 55));
|
||||
@@ -312,8 +312,8 @@ DisassembleByteCodeObj(
|
||||
int numCompiledLocals = procPtr->numCompiledLocals;
|
||||
|
||||
Tcl_AppendPrintfToObj(bufferObj,
|
||||
" Proc %p, refCt %" TCL_LL_MODIFIER "d, args %d, compiled locals %d\n",
|
||||
procPtr, (Tcl_WideUInt)procPtr->refCount, procPtr->numArgs,
|
||||
" Proc %p, refCt %d, args %d, compiled locals %d\n",
|
||||
procPtr, procPtr->refCount, procPtr->numArgs,
|
||||
numCompiledLocals);
|
||||
if (numCompiledLocals > 0) {
|
||||
CompiledLocal *localPtr = procPtr->firstLocalPtr;
|
||||
@@ -797,7 +797,7 @@ TclNewInstNameObj(
|
||||
Tcl_Obj *objPtr = Tcl_NewObj();
|
||||
|
||||
objPtr->typePtr = &tclInstNameType;
|
||||
objPtr->internalRep.wideValue = (long) inst;
|
||||
objPtr->internalRep.longValue = (long) inst;
|
||||
objPtr->bytes = NULL;
|
||||
|
||||
return objPtr;
|
||||
@@ -817,17 +817,17 @@ static void
|
||||
UpdateStringOfInstName(
|
||||
Tcl_Obj *objPtr)
|
||||
{
|
||||
size_t len, inst = (size_t)objPtr->internalRep.wideValue;
|
||||
char *s, buf[TCL_INTEGER_SPACE + 5];
|
||||
int inst = objPtr->internalRep.longValue;
|
||||
char *s, buf[20];
|
||||
int len;
|
||||
|
||||
if (inst >= LAST_INST_OPCODE) {
|
||||
sprintf(buf, "inst_%" TCL_Z_MODIFIER "d", inst);
|
||||
if ((inst < 0) || (inst > LAST_INST_OPCODE)) {
|
||||
sprintf(buf, "inst_%d", inst);
|
||||
s = buf;
|
||||
} else {
|
||||
s = (char *) tclInstructionTable[inst].name;
|
||||
s = (char *) tclInstructionTable[objPtr->internalRep.longValue].name;
|
||||
}
|
||||
len = strlen(s);
|
||||
/* assert (len < UINT_MAX) */
|
||||
objPtr->bytes = ckalloc(len + 1);
|
||||
memcpy(objPtr->bytes, s, len + 1);
|
||||
objPtr->length = len;
|
||||
|
||||
+126
-94
@@ -18,7 +18,7 @@ typedef size_t (LengthProc)(const char *src);
|
||||
* convert between various character sets and UTF-8.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
typedef struct Encoding {
|
||||
char *name; /* Name of encoding. Malloced because (1) hash
|
||||
* table entry that owns this encoding may be
|
||||
* freed prior to this encoding being freed,
|
||||
@@ -57,7 +57,7 @@ typedef struct {
|
||||
* encoding.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
typedef struct TableEncodingData {
|
||||
int fallback; /* Character (in this encoding) to substitute
|
||||
* when this encoding cannot represent a UTF-8
|
||||
* character. */
|
||||
@@ -91,7 +91,7 @@ typedef struct {
|
||||
* for switching character sets.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
typedef struct EscapeSubTable {
|
||||
unsigned sequenceLen; /* Length of following string. */
|
||||
char sequence[16]; /* Escape code that marks this encoding. */
|
||||
char name[32]; /* Name for encoding. */
|
||||
@@ -100,7 +100,7 @@ typedef struct {
|
||||
* yet. */
|
||||
} EscapeSubTable;
|
||||
|
||||
typedef struct {
|
||||
typedef struct EscapeEncodingData {
|
||||
int fallback; /* Character (in this encoding) to substitute
|
||||
* when this encoding cannot represent a UTF-8
|
||||
* character. */
|
||||
@@ -563,7 +563,7 @@ TclInitEncodingSubsystem(void)
|
||||
* formed UTF-8 into a properly formed stream.
|
||||
*/
|
||||
|
||||
type.encodingName = NULL;
|
||||
type.encodingName = "identity";
|
||||
type.toUtfProc = BinaryProc;
|
||||
type.fromUtfProc = BinaryProc;
|
||||
type.freeProc = NULL;
|
||||
@@ -675,6 +675,68 @@ TclFinalizeEncodingSubsystem(void)
|
||||
Tcl_MutexUnlock(&encodingMutex);
|
||||
}
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
* Tcl_GetDefaultEncodingDir --
|
||||
*
|
||||
* Legacy public interface to retrieve first directory in the encoding
|
||||
* searchPath.
|
||||
*
|
||||
* Results:
|
||||
* The directory pathname, as a string, or NULL for an empty encoding
|
||||
* search path.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
const char *
|
||||
Tcl_GetDefaultEncodingDir(void)
|
||||
{
|
||||
int numDirs;
|
||||
Tcl_Obj *first, *searchPath = Tcl_GetEncodingSearchPath();
|
||||
|
||||
Tcl_ListObjLength(NULL, searchPath, &numDirs);
|
||||
if (numDirs == 0) {
|
||||
return NULL;
|
||||
}
|
||||
Tcl_ListObjIndex(NULL, searchPath, 0, &first);
|
||||
|
||||
return TclGetString(first);
|
||||
}
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
* Tcl_SetDefaultEncodingDir --
|
||||
*
|
||||
* Legacy public interface to set the first directory in the encoding
|
||||
* search path.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Modifies the encoding search path.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
Tcl_SetDefaultEncodingDir(
|
||||
const char *path)
|
||||
{
|
||||
Tcl_Obj *searchPath = Tcl_GetEncodingSearchPath();
|
||||
Tcl_Obj *directory = Tcl_NewStringObj(path, -1);
|
||||
|
||||
searchPath = Tcl_DuplicateObj(searchPath);
|
||||
Tcl_ListObjReplace(NULL, searchPath, 0, 0, 1, &directory);
|
||||
Tcl_SetEncodingSearchPath(searchPath);
|
||||
}
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
@@ -789,9 +851,7 @@ FreeEncoding(
|
||||
if (encodingPtr->hPtr != NULL) {
|
||||
Tcl_DeleteHashEntry(encodingPtr->hPtr);
|
||||
}
|
||||
if (encodingPtr->name) {
|
||||
ckfree(encodingPtr->name);
|
||||
}
|
||||
ckfree(encodingPtr->name);
|
||||
ckfree(encodingPtr);
|
||||
}
|
||||
}
|
||||
@@ -980,8 +1040,27 @@ Tcl_CreateEncoding(
|
||||
const Tcl_EncodingType *typePtr)
|
||||
/* The encoding type. */
|
||||
{
|
||||
Encoding *encodingPtr = ckalloc(sizeof(Encoding));
|
||||
encodingPtr->name = NULL;
|
||||
Tcl_HashEntry *hPtr;
|
||||
int isNew;
|
||||
Encoding *encodingPtr;
|
||||
char *name;
|
||||
|
||||
Tcl_MutexLock(&encodingMutex);
|
||||
hPtr = Tcl_CreateHashEntry(&encodingTable, typePtr->encodingName, &isNew);
|
||||
if (isNew == 0) {
|
||||
/*
|
||||
* Remove old encoding from hash table, but don't delete it until last
|
||||
* reference goes away.
|
||||
*/
|
||||
|
||||
encodingPtr = Tcl_GetHashValue(hPtr);
|
||||
encodingPtr->hPtr = NULL;
|
||||
}
|
||||
|
||||
name = ckalloc(strlen(typePtr->encodingName) + 1);
|
||||
|
||||
encodingPtr = ckalloc(sizeof(Encoding));
|
||||
encodingPtr->name = strcpy(name, typePtr->encodingName);
|
||||
encodingPtr->toUtfProc = typePtr->toUtfProc;
|
||||
encodingPtr->fromUtfProc = typePtr->fromUtfProc;
|
||||
encodingPtr->freeProc = typePtr->freeProc;
|
||||
@@ -993,32 +1072,11 @@ Tcl_CreateEncoding(
|
||||
encodingPtr->lengthProc = (LengthProc *) unilen;
|
||||
}
|
||||
encodingPtr->refCount = 1;
|
||||
encodingPtr->hPtr = NULL;
|
||||
|
||||
if (typePtr->encodingName) {
|
||||
Tcl_HashEntry *hPtr;
|
||||
int isNew;
|
||||
char *name;
|
||||
|
||||
Tcl_MutexLock(&encodingMutex);
|
||||
hPtr = Tcl_CreateHashEntry(&encodingTable, typePtr->encodingName, &isNew);
|
||||
if (isNew == 0) {
|
||||
/*
|
||||
* Remove old encoding from hash table, but don't delete it until last
|
||||
* reference goes away.
|
||||
*/
|
||||
|
||||
Encoding *replaceMe = Tcl_GetHashValue(hPtr);
|
||||
replaceMe->hPtr = NULL;
|
||||
}
|
||||
|
||||
name = ckalloc(strlen(typePtr->encodingName) + 1);
|
||||
encodingPtr->name = strcpy(name, typePtr->encodingName);
|
||||
encodingPtr->hPtr = hPtr;
|
||||
Tcl_SetHashValue(hPtr, encodingPtr);
|
||||
|
||||
Tcl_MutexUnlock(&encodingMutex);
|
||||
}
|
||||
|
||||
return (Tcl_Encoding) encodingPtr;
|
||||
}
|
||||
|
||||
@@ -2235,11 +2293,8 @@ UtfToUtfProc(
|
||||
const char *srcStart, *srcEnd, *srcClose;
|
||||
const char *dstStart, *dstEnd;
|
||||
int result, numChars, charLimit = INT_MAX;
|
||||
Tcl_UniChar *chPtr = (Tcl_UniChar *) statePtr;
|
||||
Tcl_UniChar ch;
|
||||
|
||||
if (flags & TCL_ENCODING_START) {
|
||||
*statePtr = 0;
|
||||
}
|
||||
result = TCL_OK;
|
||||
|
||||
srcStart = src;
|
||||
@@ -2271,7 +2326,7 @@ UtfToUtfProc(
|
||||
}
|
||||
if (UCHAR(*src) < 0x80 && !(UCHAR(*src) == 0 && pureNullMode == 0)) {
|
||||
/*
|
||||
* Copy 7bit characters, but skip null-bytes when we are in input
|
||||
* Copy 7bit chatacters, but skip null-bytes when we are in input
|
||||
* mode, so that they get converted to 0xc080.
|
||||
*/
|
||||
|
||||
@@ -2287,23 +2342,16 @@ UtfToUtfProc(
|
||||
} else if (!Tcl_UtfCharComplete(src, srcEnd - src)) {
|
||||
/*
|
||||
* Always check before using TclUtfToUniChar. Not doing can so
|
||||
* cause it run beyond the end of the buffer! If we happen such an
|
||||
* incomplete char its bytes are made to represent themselves.
|
||||
* cause it run beyond the endof the buffer! If we happen such an
|
||||
* incomplete char its byts are made to represent themselves.
|
||||
*/
|
||||
|
||||
*chPtr = (unsigned char) *src;
|
||||
ch = (unsigned char) *src;
|
||||
src += 1;
|
||||
dst += Tcl_UniCharToUtf(*chPtr, dst);
|
||||
dst += Tcl_UniCharToUtf(ch, dst);
|
||||
} else {
|
||||
int len = TclUtfToUniChar(src, chPtr);
|
||||
src += len;
|
||||
dst += Tcl_UniCharToUtf(*chPtr, dst);
|
||||
#if TCL_UTF_MAX <= 4
|
||||
if (!len) {
|
||||
src += TclUtfToUniChar(src, chPtr);
|
||||
dst += Tcl_UniCharToUtf(*chPtr, dst);
|
||||
}
|
||||
#endif
|
||||
src += TclUtfToUniChar(src, &ch);
|
||||
dst += Tcl_UniCharToUtf(ch, dst);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2359,11 +2407,8 @@ UnicodeToUtfProc(
|
||||
const char *srcStart, *srcEnd;
|
||||
const char *dstEnd, *dstStart;
|
||||
int result, numChars, charLimit = INT_MAX;
|
||||
Tcl_UniChar *chPtr = (Tcl_UniChar *) statePtr;
|
||||
Tcl_UniChar ch;
|
||||
|
||||
if (flags & TCL_ENCODING_START) {
|
||||
*statePtr = 0;
|
||||
}
|
||||
if (flags & TCL_ENCODING_CHAR_LIMIT) {
|
||||
charLimit = *dstCharsPtr;
|
||||
}
|
||||
@@ -2391,11 +2436,11 @@ UnicodeToUtfProc(
|
||||
* Tcl_UniChar-size data.
|
||||
*/
|
||||
|
||||
*chPtr = *(Tcl_UniChar *)src;
|
||||
if (*chPtr && *chPtr < 0x80) {
|
||||
*dst++ = (*chPtr & 0xFF);
|
||||
ch = *(Tcl_UniChar *)src;
|
||||
if (ch && ch < 0x80) {
|
||||
*dst++ = (ch & 0xFF);
|
||||
} else {
|
||||
dst += Tcl_UniCharToUtf(*chPtr, dst);
|
||||
dst += Tcl_UniCharToUtf(ch, dst);
|
||||
}
|
||||
src += sizeof(Tcl_UniChar);
|
||||
}
|
||||
@@ -2452,11 +2497,8 @@ UtfToUnicodeProc(
|
||||
{
|
||||
const char *srcStart, *srcEnd, *srcClose, *dstStart, *dstEnd;
|
||||
int result, numChars;
|
||||
Tcl_UniChar *chPtr = (Tcl_UniChar *) statePtr;
|
||||
Tcl_UniChar ch;
|
||||
|
||||
if (flags & TCL_ENCODING_START) {
|
||||
*statePtr = 0;
|
||||
}
|
||||
srcStart = src;
|
||||
srcEnd = src + srcLen;
|
||||
srcClose = srcEnd;
|
||||
@@ -2482,7 +2524,7 @@ UtfToUnicodeProc(
|
||||
result = TCL_CONVERT_NOSPACE;
|
||||
break;
|
||||
}
|
||||
src += TclUtfToUniChar(src, chPtr);
|
||||
src += TclUtfToUniChar(src, &ch);
|
||||
|
||||
/*
|
||||
* Need to handle this in a way that won't cause misalignment by
|
||||
@@ -2491,23 +2533,23 @@ UtfToUnicodeProc(
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#if TCL_UTF_MAX > 4
|
||||
*dst++ = (*chPtr >> 24);
|
||||
*dst++ = ((*chPtr >> 16) & 0xFF);
|
||||
*dst++ = ((*chPtr >> 8) & 0xFF);
|
||||
*dst++ = (*chPtr & 0xFF);
|
||||
*dst++ = (ch >> 24);
|
||||
*dst++ = ((ch >> 16) & 0xFF);
|
||||
*dst++ = ((ch >> 8) & 0xFF);
|
||||
*dst++ = (ch & 0xFF);
|
||||
#else
|
||||
*dst++ = (*chPtr >> 8);
|
||||
*dst++ = (*chPtr & 0xFF);
|
||||
*dst++ = (ch >> 8);
|
||||
*dst++ = (ch & 0xFF);
|
||||
#endif
|
||||
#else
|
||||
#if TCL_UTF_MAX > 4
|
||||
*dst++ = (*chPtr & 0xFF);
|
||||
*dst++ = ((*chPtr >> 8) & 0xFF);
|
||||
*dst++ = ((*chPtr >> 16) & 0xFF);
|
||||
*dst++ = (*chPtr >> 24);
|
||||
*dst++ = (ch & 0xFF);
|
||||
*dst++ = ((ch >> 8) & 0xFF);
|
||||
*dst++ = ((ch >> 16) & 0xFF);
|
||||
*dst++ = (ch >> 24);
|
||||
#else
|
||||
*dst++ = (*chPtr & 0xFF);
|
||||
*dst++ = (*chPtr >> 8);
|
||||
*dst++ = (ch & 0xFF);
|
||||
*dst++ = (ch >> 8);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
@@ -2565,7 +2607,7 @@ TableToUtfProc(
|
||||
const char *srcStart, *srcEnd;
|
||||
const char *dstEnd, *dstStart, *prefixBytes;
|
||||
int result, byte, numChars, charLimit = INT_MAX;
|
||||
Tcl_UniChar ch = 0;
|
||||
Tcl_UniChar ch;
|
||||
const unsigned short *const *toUnicode;
|
||||
const unsigned short *pageZero;
|
||||
TableEncodingData *dataPtr = clientData;
|
||||
@@ -2677,7 +2719,7 @@ TableFromUtfProc(
|
||||
{
|
||||
const char *srcStart, *srcEnd, *srcClose;
|
||||
const char *dstStart, *dstEnd, *prefixBytes;
|
||||
Tcl_UniChar ch = 0;
|
||||
Tcl_UniChar ch;
|
||||
int result, len, word, numChars;
|
||||
TableEncodingData *dataPtr = clientData;
|
||||
const unsigned short *const *fromUnicode;
|
||||
@@ -2709,7 +2751,7 @@ TableFromUtfProc(
|
||||
}
|
||||
len = TclUtfToUniChar(src, &ch);
|
||||
|
||||
#if TCL_UTF_MAX > 4
|
||||
#if TCL_UTF_MAX > 3
|
||||
/*
|
||||
* This prevents a crash condition. More evaluation is required for
|
||||
* full support of int Tcl_UniChar. [Bug 1004065]
|
||||
@@ -2718,10 +2760,6 @@ TableFromUtfProc(
|
||||
if (ch & 0xffff0000) {
|
||||
word = 0;
|
||||
} else
|
||||
#else
|
||||
if (!len) {
|
||||
word = 0;
|
||||
} else
|
||||
#endif
|
||||
word = fromUnicode[(ch >> 8)][ch & 0xff];
|
||||
|
||||
@@ -2815,7 +2853,7 @@ Iso88591ToUtfProc(
|
||||
|
||||
result = TCL_OK;
|
||||
for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) {
|
||||
Tcl_UniChar ch = 0;
|
||||
Tcl_UniChar ch;
|
||||
|
||||
if (dst > dstEnd) {
|
||||
result = TCL_CONVERT_NOSPACE;
|
||||
@@ -2901,7 +2939,7 @@ Iso88591FromUtfProc(
|
||||
dstEnd = dst + dstLen - 1;
|
||||
|
||||
for (numChars = 0; src < srcEnd; numChars++) {
|
||||
Tcl_UniChar ch = 0;
|
||||
Tcl_UniChar ch;
|
||||
int len;
|
||||
|
||||
if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) {
|
||||
@@ -2919,18 +2957,12 @@ Iso88591FromUtfProc(
|
||||
* Check for illegal characters.
|
||||
*/
|
||||
|
||||
if (ch > 0xff
|
||||
#if TCL_UTF_MAX <= 4
|
||||
|| !len
|
||||
#endif
|
||||
) {
|
||||
if (ch > 0xff) {
|
||||
if (flags & TCL_ENCODING_STOPONERROR) {
|
||||
result = TCL_CONVERT_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
#if TCL_UTF_MAX <= 4
|
||||
if (!len) len = 4;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Plunge on, using '?' as a fallback character.
|
||||
*/
|
||||
@@ -3294,7 +3326,7 @@ EscapeFromUtfProc(
|
||||
for (numChars = 0; src < srcEnd; numChars++) {
|
||||
unsigned len;
|
||||
int word;
|
||||
Tcl_UniChar ch = 0;
|
||||
Tcl_UniChar ch;
|
||||
|
||||
if ((src > srcClose) && (!Tcl_UtfCharComplete(src, srcEnd - src))) {
|
||||
/*
|
||||
@@ -3339,7 +3371,7 @@ EscapeFromUtfProc(
|
||||
|
||||
/*
|
||||
* The state variable has the value of oldState when word is 0.
|
||||
* In this case, the escape sequence should not be copied to dst
|
||||
* In this case, the escape sequense should not be copied to dst
|
||||
* because the current character set is not changed.
|
||||
*/
|
||||
|
||||
|
||||
+166
-190
@@ -55,11 +55,12 @@ enum EnsSubcmds {
|
||||
};
|
||||
|
||||
static const char *const ensembleCreateOptions[] = {
|
||||
"-command", "-map", "-parameters", "-prefixes", "-subcommands",
|
||||
"-unknown", NULL
|
||||
"-command", "-compile", "-map", "-parameters", "-prefixes",
|
||||
"-subcommands", "-unknown", NULL
|
||||
};
|
||||
enum EnsCreateOpts {
|
||||
CRT_CMD, CRT_MAP, CRT_PARAM, CRT_PREFIX, CRT_SUBCMDS, CRT_UNKNOWN
|
||||
CRT_CMD, CRT_COMPILE, CRT_MAP, CRT_PARAM, CRT_PREFIX,
|
||||
CRT_SUBCMDS, CRT_UNKNOWN
|
||||
};
|
||||
|
||||
static const char *const ensembleConfigOptions[] = {
|
||||
@@ -146,12 +147,10 @@ TclNamespaceEnsembleCmd(
|
||||
Tcl_Obj *const objv[])
|
||||
{
|
||||
Tcl_Namespace *namespacePtr;
|
||||
Namespace *nsPtr = (Namespace *) TclGetCurrentNamespace(interp), *cxtPtr,
|
||||
*foundNsPtr, *altFoundNsPtr, *actualCxtPtr;
|
||||
Namespace *nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
|
||||
Tcl_Command token;
|
||||
Tcl_DictSearch search;
|
||||
Tcl_Obj *listObj;
|
||||
const char *simpleName;
|
||||
int index, done;
|
||||
|
||||
if (nsPtr == NULL || nsPtr->flags & NS_DYING) {
|
||||
@@ -185,6 +184,7 @@ TclNamespaceEnsembleCmd(
|
||||
int permitPrefix = 1;
|
||||
Tcl_Obj *unknownObj = NULL;
|
||||
Tcl_Obj *paramObj = NULL;
|
||||
int ensCompFlag = -1;
|
||||
|
||||
/*
|
||||
* Check that we've got option-value pairs... [Bug 1558654]
|
||||
@@ -197,8 +197,13 @@ TclNamespaceEnsembleCmd(
|
||||
objv += 2;
|
||||
objc -= 2;
|
||||
|
||||
name = nsPtr->name;
|
||||
cxtPtr = (Namespace *) nsPtr->parentPtr;
|
||||
/*
|
||||
* Work out what name to use for the command to create. If supplied,
|
||||
* it is either fully specified or relative to the current namespace.
|
||||
* If not supplied, it is exactly the name of the current namespace.
|
||||
*/
|
||||
|
||||
name = nsPtr->fullName;
|
||||
|
||||
/*
|
||||
* Parse the option list, applying type checks as we go. Note that we
|
||||
@@ -218,7 +223,6 @@ TclNamespaceEnsembleCmd(
|
||||
switch ((enum EnsCreateOpts) index) {
|
||||
case CRT_CMD:
|
||||
name = TclGetString(objv[1]);
|
||||
cxtPtr = nsPtr;
|
||||
continue;
|
||||
case CRT_SUBCMDS:
|
||||
if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
|
||||
@@ -323,6 +327,12 @@ TclNamespaceEnsembleCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
continue;
|
||||
case CRT_COMPILE:
|
||||
if (Tcl_GetBooleanFromObj(interp, objv[1],
|
||||
&ensCompFlag) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
};
|
||||
continue;
|
||||
case CRT_UNKNOWN:
|
||||
if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
|
||||
if (allocatedMapFlag) {
|
||||
@@ -335,10 +345,6 @@ TclNamespaceEnsembleCmd(
|
||||
}
|
||||
}
|
||||
|
||||
TclGetNamespaceForQualName(interp, name, cxtPtr,
|
||||
TCL_CREATE_NS_IF_UNKNOWN, &foundNsPtr, &altFoundNsPtr, &actualCxtPtr,
|
||||
&simpleName);
|
||||
|
||||
/*
|
||||
* Create the ensemble. Note that this might delete another ensemble
|
||||
* linked to the same namespace, so we must be careful. However, we
|
||||
@@ -346,13 +352,18 @@ TclNamespaceEnsembleCmd(
|
||||
* we've created it (and after any deletions have occurred.)
|
||||
*/
|
||||
|
||||
token = TclCreateEnsembleInNs(interp, simpleName,
|
||||
(Tcl_Namespace *) foundNsPtr, (Tcl_Namespace *) nsPtr,
|
||||
(permitPrefix ? TCL_ENSEMBLE_PREFIX : 0));
|
||||
token = Tcl_CreateEnsemble(interp, name, NULL,
|
||||
(permitPrefix ? TCL_ENSEMBLE_PREFIX : 0));
|
||||
Tcl_SetEnsembleSubcommandList(interp, token, subcmdObj);
|
||||
Tcl_SetEnsembleMappingDict(interp, token, mapObj);
|
||||
Tcl_SetEnsembleUnknownHandler(interp, token, unknownObj);
|
||||
Tcl_SetEnsembleParameterList(interp, token, paramObj);
|
||||
/*
|
||||
* Ensemble should be compiled if it has map (performance purposes)
|
||||
*/
|
||||
if (ensCompFlag > 0 && mapObj != NULL) {
|
||||
Tcl_SetEnsembleFlags(interp, token, ENSEMBLE_COMPILE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tricky! Must ensure that the result is not shared (command delete
|
||||
@@ -639,38 +650,48 @@ TclNamespaceEnsembleCmd(
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* TclCreateEnsembleInNs --
|
||||
* Tcl_CreateEnsemble --
|
||||
*
|
||||
* Like Tcl_CreateEnsemble, but additionally accepts as an argument the
|
||||
* name of the namespace to create the command in.
|
||||
* Create a simple ensemble attached to the given namespace.
|
||||
*
|
||||
* Results:
|
||||
* The token for the command created.
|
||||
*
|
||||
* Side effects:
|
||||
* The ensemble is created and marked for compilation.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Tcl_Command
|
||||
TclCreateEnsembleInNs(
|
||||
Tcl_CreateEnsemble(
|
||||
Tcl_Interp *interp,
|
||||
|
||||
const char *name, /* Simple name of command to create (no */
|
||||
/* namespace components). */
|
||||
Tcl_Namespace /* Name of namespace to create the command in. */
|
||||
*nameNsPtr,
|
||||
Tcl_Namespace
|
||||
*ensembleNsPtr, /* Name of the namespace for the ensemble. */
|
||||
int flags
|
||||
)
|
||||
const char *name,
|
||||
Tcl_Namespace *namespacePtr,
|
||||
int flags)
|
||||
{
|
||||
Namespace *nsPtr = (Namespace *) ensembleNsPtr;
|
||||
EnsembleConfig *ensemblePtr;
|
||||
Tcl_Command token;
|
||||
Namespace *nsPtr = (Namespace *) namespacePtr;
|
||||
EnsembleConfig *ensemblePtr = ckalloc(sizeof(EnsembleConfig));
|
||||
Tcl_Obj *nameObj = NULL;
|
||||
|
||||
ensemblePtr = ckalloc(sizeof(EnsembleConfig));
|
||||
token = TclNRCreateCommandInNs(interp, name,
|
||||
(Tcl_Namespace *) nameNsPtr, NsEnsembleImplementationCmd,
|
||||
NsEnsembleImplementationCmdNR, ensemblePtr, DeleteEnsembleConfig);
|
||||
if (token == NULL) {
|
||||
ckfree(ensemblePtr);
|
||||
return NULL;
|
||||
if (nsPtr == NULL) {
|
||||
nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make the name of the ensemble into a fully qualified name. This might
|
||||
* allocate a temporary object.
|
||||
*/
|
||||
|
||||
if (!(name[0] == ':' && name[1] == ':')) {
|
||||
nameObj = NewNsObj((Tcl_Namespace *) nsPtr);
|
||||
if (nsPtr->parentPtr == NULL) {
|
||||
Tcl_AppendStringsToObj(nameObj, name, NULL);
|
||||
} else {
|
||||
Tcl_AppendStringsToObj(nameObj, "::", name, NULL);
|
||||
}
|
||||
Tcl_IncrRefCount(nameObj);
|
||||
name = TclGetString(nameObj);
|
||||
}
|
||||
|
||||
ensemblePtr->nsPtr = nsPtr;
|
||||
@@ -683,7 +704,9 @@ TclCreateEnsembleInNs(
|
||||
ensemblePtr->numParameters = 0;
|
||||
ensemblePtr->parameterList = NULL;
|
||||
ensemblePtr->unknownHandler = NULL;
|
||||
ensemblePtr->token = token;
|
||||
ensemblePtr->token = Tcl_NRCreateCommand(interp, name,
|
||||
NsEnsembleImplementationCmd, NsEnsembleImplementationCmdNR,
|
||||
ensemblePtr, DeleteEnsembleConfig);
|
||||
ensemblePtr->next = (EnsembleConfig *) nsPtr->ensembles;
|
||||
nsPtr->ensembles = (Tcl_Ensemble *) ensemblePtr;
|
||||
|
||||
@@ -700,52 +723,11 @@ TclCreateEnsembleInNs(
|
||||
((Command *) ensemblePtr->token)->compileProc = TclCompileEnsemble;
|
||||
}
|
||||
|
||||
return ensemblePtr->token;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Tcl_CreateEnsemble
|
||||
*
|
||||
* Create a simple ensemble attached to the given namespace.
|
||||
*
|
||||
* Deprecated by TclCreateEnsembleInNs.
|
||||
*
|
||||
* Value
|
||||
*
|
||||
* The token for the command created.
|
||||
*
|
||||
* Effect
|
||||
* The ensemble is created and marked for compilation.
|
||||
*
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Tcl_Command
|
||||
Tcl_CreateEnsemble(
|
||||
Tcl_Interp *interp,
|
||||
const char *name,
|
||||
Tcl_Namespace *namespacePtr,
|
||||
int flags)
|
||||
{
|
||||
Namespace *nsPtr = (Namespace *)namespacePtr, *foundNsPtr, *altNsPtr,
|
||||
*actualNsPtr;
|
||||
const char * simpleName;
|
||||
|
||||
if (nsPtr == NULL) {
|
||||
nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
|
||||
if (nameObj != NULL) {
|
||||
TclDecrRefCount(nameObj);
|
||||
}
|
||||
|
||||
TclGetNamespaceForQualName(interp, name, nsPtr, TCL_CREATE_NS_IF_UNKNOWN,
|
||||
&foundNsPtr, &altNsPtr, &actualNsPtr, &simpleName);
|
||||
return TclCreateEnsembleInNs(interp, simpleName,
|
||||
(Tcl_Namespace *) foundNsPtr, (Tcl_Namespace *) nsPtr, flags);
|
||||
return ensemblePtr->token;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -1917,7 +1899,6 @@ NsEnsembleImplementationCmdNR(
|
||||
|
||||
TclSkipTailcall(interp);
|
||||
Tcl_ListObjGetElements(NULL, copyPtr, ©Objc, ©Objv);
|
||||
((Interp *)interp)->lookupNsPtr = ensemblePtr->nsPtr;
|
||||
return TclNREvalObjv(interp, copyObjc, copyObjv, TCL_EVAL_INVOKE, NULL);
|
||||
}
|
||||
|
||||
@@ -2431,32 +2412,14 @@ MakeCachedEnsembleCommand(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
ClearTable(
|
||||
EnsembleConfig *ensemblePtr)
|
||||
{
|
||||
Tcl_HashTable *hash = &ensemblePtr->subcommandTable;
|
||||
|
||||
if (hash->numEntries != 0) {
|
||||
Tcl_HashSearch search;
|
||||
Tcl_HashEntry *hPtr = Tcl_FirstHashEntry(hash, &search);
|
||||
|
||||
while (hPtr != NULL) {
|
||||
Tcl_Obj *prefixObj = Tcl_GetHashValue(hPtr);
|
||||
Tcl_DecrRefCount(prefixObj);
|
||||
hPtr = Tcl_NextHashEntry(&search);
|
||||
}
|
||||
ckfree((char *) ensemblePtr->subcommandArrayPtr);
|
||||
}
|
||||
Tcl_DeleteHashTable(hash);
|
||||
}
|
||||
|
||||
static void
|
||||
DeleteEnsembleConfig(
|
||||
ClientData clientData)
|
||||
{
|
||||
EnsembleConfig *ensemblePtr = clientData;
|
||||
Namespace *nsPtr = ensemblePtr->nsPtr;
|
||||
Tcl_HashSearch search;
|
||||
Tcl_HashEntry *hEnt;
|
||||
|
||||
/*
|
||||
* Unlink from the ensemble chain if it has not been marked as having been
|
||||
@@ -2490,7 +2453,17 @@ DeleteEnsembleConfig(
|
||||
* Kill the pointer-containing fields.
|
||||
*/
|
||||
|
||||
ClearTable(ensemblePtr);
|
||||
if (ensemblePtr->subcommandTable.numEntries != 0) {
|
||||
ckfree(ensemblePtr->subcommandArrayPtr);
|
||||
}
|
||||
hEnt = Tcl_FirstHashEntry(&ensemblePtr->subcommandTable, &search);
|
||||
while (hEnt != NULL) {
|
||||
Tcl_Obj *prefixObj = Tcl_GetHashValue(hEnt);
|
||||
|
||||
Tcl_DecrRefCount(prefixObj);
|
||||
hEnt = Tcl_NextHashEntry(&search);
|
||||
}
|
||||
Tcl_DeleteHashTable(&ensemblePtr->subcommandTable);
|
||||
if (ensemblePtr->subcmdList != NULL) {
|
||||
Tcl_DecrRefCount(ensemblePtr->subcmdList);
|
||||
}
|
||||
@@ -2546,101 +2519,100 @@ BuildEnsembleConfig(
|
||||
int i, j, isNew;
|
||||
Tcl_HashTable *hash = &ensemblePtr->subcommandTable;
|
||||
Tcl_HashEntry *hPtr;
|
||||
Tcl_Obj *mapDict = ensemblePtr->subcommandDict;
|
||||
Tcl_Obj *subList = ensemblePtr->subcmdList;
|
||||
|
||||
ClearTable(ensemblePtr);
|
||||
Tcl_InitHashTable(hash, TCL_STRING_KEYS);
|
||||
if (hash->numEntries != 0) {
|
||||
/*
|
||||
* Remove pre-existing table.
|
||||
*/
|
||||
|
||||
if (subList) {
|
||||
int subc;
|
||||
Tcl_Obj **subv, *target, *cmdObj, *cmdPrefixObj;
|
||||
char *name;
|
||||
ckfree(ensemblePtr->subcommandArrayPtr);
|
||||
hPtr = Tcl_FirstHashEntry(hash, &search);
|
||||
while (hPtr != NULL) {
|
||||
Tcl_Obj *prefixObj = Tcl_GetHashValue(hPtr);
|
||||
|
||||
/*
|
||||
* There is a list of exactly what subcommands go in the table.
|
||||
* Must determine the target for each.
|
||||
*/
|
||||
Tcl_DecrRefCount(prefixObj);
|
||||
hPtr = Tcl_NextHashEntry(&search);
|
||||
}
|
||||
Tcl_DeleteHashTable(hash);
|
||||
Tcl_InitHashTable(hash, TCL_STRING_KEYS);
|
||||
}
|
||||
|
||||
Tcl_ListObjGetElements(NULL, subList, &subc, &subv);
|
||||
if (subList == mapDict) {
|
||||
/*
|
||||
* Strange case where explicit list of subcommands is same value
|
||||
* as the dict mapping to targets.
|
||||
*/
|
||||
/*
|
||||
* See if we've got an export list. If so, we will only export exactly
|
||||
* those commands, which may be either implemented by the prefix in the
|
||||
* subcommandDict or mapped directly onto the namespace's commands.
|
||||
*/
|
||||
|
||||
for (i = 0; i < subc; i += 2) {
|
||||
name = TclGetString(subv[i]);
|
||||
hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
|
||||
if (!isNew) {
|
||||
cmdObj = (Tcl_Obj *)Tcl_GetHashValue(hPtr);
|
||||
Tcl_DecrRefCount(cmdObj);
|
||||
}
|
||||
Tcl_SetHashValue(hPtr, subv[i+1]);
|
||||
Tcl_IncrRefCount(subv[i+1]);
|
||||
if (ensemblePtr->subcmdList != NULL) {
|
||||
Tcl_Obj **subcmdv, *target, *cmdObj, *cmdPrefixObj;
|
||||
int subcmdc;
|
||||
|
||||
name = TclGetString(subv[i+1]);
|
||||
hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
|
||||
if (isNew) {
|
||||
cmdObj = Tcl_NewStringObj(name, -1);
|
||||
cmdPrefixObj = Tcl_NewListObj(1, &cmdObj);
|
||||
Tcl_SetHashValue(hPtr, cmdPrefixObj);
|
||||
Tcl_IncrRefCount(cmdPrefixObj);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Usual case where we can freely act on the list and dict. */
|
||||
TclListObjGetElements(NULL, ensemblePtr->subcmdList, &subcmdc,
|
||||
&subcmdv);
|
||||
for (i=0 ; i<subcmdc ; i++) {
|
||||
const char *name = TclGetString(subcmdv[i]);
|
||||
|
||||
for (i = 0; i < subc; i++) {
|
||||
name = TclGetString(subv[i]);
|
||||
hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
|
||||
if (!isNew) {
|
||||
continue;
|
||||
}
|
||||
hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
|
||||
|
||||
/* Lookup target in the dictionary */
|
||||
if (mapDict) {
|
||||
Tcl_DictObjGet(NULL, mapDict, subv[i], &target);
|
||||
if (target) {
|
||||
Tcl_SetHashValue(hPtr, target);
|
||||
Tcl_IncrRefCount(target);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Skip non-unique cases.
|
||||
*/
|
||||
|
||||
/*
|
||||
* target was not in the dictionary so map onto the namespace.
|
||||
* Note in this case that we do not guarantee that the
|
||||
* command is actually there; that is the programmer's
|
||||
* responsibility (or [::unknown] of course).
|
||||
*/
|
||||
cmdObj = Tcl_NewStringObj(name, -1);
|
||||
cmdPrefixObj = Tcl_NewListObj(1, &cmdObj);
|
||||
Tcl_SetHashValue(hPtr, cmdPrefixObj);
|
||||
Tcl_IncrRefCount(cmdPrefixObj);
|
||||
}
|
||||
}
|
||||
} else if (mapDict) {
|
||||
/*
|
||||
* No subcmd list, but we do have a mapping dictionary so we should
|
||||
* use the keys of that. Convert the dictionary's contents into the
|
||||
* form required for the ensemble's internal hashtable.
|
||||
*/
|
||||
if (!isNew) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Tcl_DictSearch dictSearch;
|
||||
Tcl_Obj *keyObj, *valueObj;
|
||||
int done;
|
||||
/*
|
||||
* Look in our dictionary (if present) for the command.
|
||||
*/
|
||||
|
||||
Tcl_DictObjFirst(NULL, ensemblePtr->subcommandDict, &dictSearch,
|
||||
&keyObj, &valueObj, &done);
|
||||
while (!done) {
|
||||
char *name = TclGetString(keyObj);
|
||||
if (ensemblePtr->subcommandDict != NULL) {
|
||||
Tcl_DictObjGet(NULL, ensemblePtr->subcommandDict, subcmdv[i],
|
||||
&target);
|
||||
if (target != NULL) {
|
||||
Tcl_SetHashValue(hPtr, target);
|
||||
Tcl_IncrRefCount(target);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
|
||||
Tcl_SetHashValue(hPtr, valueObj);
|
||||
Tcl_IncrRefCount(valueObj);
|
||||
Tcl_DictObjNext(&dictSearch, &keyObj, &valueObj, &done);
|
||||
}
|
||||
/*
|
||||
* Not there, so map onto the namespace. Note in this case that we
|
||||
* do not guarantee that the command is actually there; that is
|
||||
* the programmer's responsibility (or [::unknown] of course).
|
||||
*/
|
||||
|
||||
cmdObj = NewNsObj((Tcl_Namespace *) ensemblePtr->nsPtr);
|
||||
if (ensemblePtr->nsPtr->parentPtr != NULL) {
|
||||
Tcl_AppendStringsToObj(cmdObj, "::", name, NULL);
|
||||
} else {
|
||||
Tcl_AppendStringsToObj(cmdObj, name, NULL);
|
||||
}
|
||||
cmdPrefixObj = Tcl_NewListObj(1, &cmdObj);
|
||||
Tcl_SetHashValue(hPtr, cmdPrefixObj);
|
||||
Tcl_IncrRefCount(cmdPrefixObj);
|
||||
}
|
||||
} else if (ensemblePtr->subcommandDict != NULL) {
|
||||
/*
|
||||
* No subcmd list, but we do have a mapping dictionary so we should
|
||||
* use the keys of that. Convert the dictionary's contents into the
|
||||
* form required for the ensemble's internal hashtable.
|
||||
*/
|
||||
|
||||
Tcl_DictSearch dictSearch;
|
||||
Tcl_Obj *keyObj, *valueObj;
|
||||
int done;
|
||||
|
||||
Tcl_DictObjFirst(NULL, ensemblePtr->subcommandDict, &dictSearch,
|
||||
&keyObj, &valueObj, &done);
|
||||
while (!done) {
|
||||
const char *name = TclGetString(keyObj);
|
||||
|
||||
hPtr = Tcl_CreateHashEntry(hash, name, &isNew);
|
||||
Tcl_SetHashValue(hPtr, valueObj);
|
||||
Tcl_IncrRefCount(valueObj);
|
||||
Tcl_DictObjNext(&dictSearch, &keyObj, &valueObj, &done);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Discover what commands are actually exported by the namespace.
|
||||
@@ -2676,7 +2648,11 @@ BuildEnsembleConfig(
|
||||
if (isNew) {
|
||||
Tcl_Obj *cmdObj, *cmdPrefixObj;
|
||||
|
||||
cmdObj = Tcl_NewStringObj(nsCmdName, -1);
|
||||
TclNewObj(cmdObj);
|
||||
Tcl_AppendStringsToObj(cmdObj,
|
||||
ensemblePtr->nsPtr->fullName,
|
||||
(ensemblePtr->nsPtr->parentPtr ? "::" : ""),
|
||||
nsCmdName, NULL);
|
||||
cmdPrefixObj = Tcl_NewListObj(1, &cmdObj);
|
||||
Tcl_SetHashValue(hPtr, cmdPrefixObj);
|
||||
Tcl_IncrRefCount(cmdPrefixObj);
|
||||
|
||||
+9
-1
@@ -17,6 +17,11 @@
|
||||
|
||||
TCL_DECLARE_MUTEX(envMutex) /* To serialize access to environ. */
|
||||
|
||||
|
||||
/* MODULE_SCOPE */
|
||||
unsigned long TclEnvEpoch = 0; /* Epoch of the tcl environment
|
||||
* (if changed with tcl-env). */
|
||||
|
||||
static struct {
|
||||
int cacheSize; /* Number of env strings in cache. */
|
||||
char **cache; /* Array containing all of the environment
|
||||
@@ -130,7 +135,6 @@ TclSetupEnv(
|
||||
* '='; ignore the entry.
|
||||
*/
|
||||
|
||||
Tcl_DStringFree(&envString);
|
||||
continue;
|
||||
}
|
||||
p2++;
|
||||
@@ -372,6 +376,7 @@ Tcl_PutEnv(
|
||||
value[0] = '\0';
|
||||
TclSetEnv(name, value+1);
|
||||
}
|
||||
TclEnvEpoch++;
|
||||
|
||||
Tcl_DStringFree(&nameString);
|
||||
return 0;
|
||||
@@ -580,6 +585,7 @@ EnvTraceProc(
|
||||
|
||||
if (flags & TCL_TRACE_ARRAY) {
|
||||
TclSetupEnv(interp);
|
||||
TclEnvEpoch++;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -600,6 +606,7 @@ EnvTraceProc(
|
||||
|
||||
value = Tcl_GetVar2(interp, "env", name2, TCL_GLOBAL_ONLY);
|
||||
TclSetEnv(name2, value);
|
||||
TclEnvEpoch++;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -623,6 +630,7 @@ EnvTraceProc(
|
||||
|
||||
if (flags & TCL_TRACE_UNSETS) {
|
||||
TclUnsetEnv(name2);
|
||||
TclEnvEpoch++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1057,6 +1057,7 @@ TclInitSubsystems(void)
|
||||
* mutexes. */
|
||||
TclInitIOSubsystem(); /* Inits a tsd key (noop). */
|
||||
TclInitEncodingSubsystem(); /* Process wide encoding init. */
|
||||
TclpSetInterfaces();
|
||||
TclInitNamespaceSubsystem();/* Register ns obj type (mutexed). */
|
||||
subsystemsInitialized = 1;
|
||||
}
|
||||
|
||||
+1141
-386
File diff suppressed because it is too large
Load Diff
+10
-10
@@ -363,7 +363,14 @@ TclFileDeleteCmd(
|
||||
*/
|
||||
|
||||
if (Tcl_FSLstat(objv[i], &statBuf) != 0) {
|
||||
result = TCL_ERROR;
|
||||
/*
|
||||
* Trying to delete a file that does not exist is not considered
|
||||
* an error, just a no-op
|
||||
*/
|
||||
|
||||
if (errno != ENOENT) {
|
||||
result = TCL_ERROR;
|
||||
}
|
||||
} else if (S_ISDIR(statBuf.st_mode)) {
|
||||
/*
|
||||
* We own a reference count on errorBuffer, if it was set as a
|
||||
@@ -399,20 +406,13 @@ TclFileDeleteCmd(
|
||||
}
|
||||
|
||||
if (result != TCL_OK) {
|
||||
result = TCL_ERROR;
|
||||
|
||||
/*
|
||||
* Avoid possible race condition (file/directory deleted after call
|
||||
* of lstat), so bypass ENOENT because not an error, just a no-op
|
||||
*/
|
||||
if (errno == ENOENT) {
|
||||
result = TCL_OK;
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* It is important that we break on error, otherwise we might end
|
||||
* up owning reference counts on numerous errorBuffers.
|
||||
*/
|
||||
result = TCL_ERROR;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1904,7 +1904,7 @@ TclGlob(
|
||||
}
|
||||
|
||||
/*
|
||||
* To process a [glob] invocation, this function may be called multiple
|
||||
* To process a [glob] invokation, this function may be called multiple
|
||||
* times. Each time, the previously discovered filenames are in the
|
||||
* interpreter result. We stash that away here so the result is free for
|
||||
* error messsages.
|
||||
|
||||
+1
-1
@@ -142,7 +142,7 @@ Tcl_GetBoolean(
|
||||
Tcl_Panic("invalid sharing of Tcl_Obj on C stack");
|
||||
}
|
||||
if (code == TCL_OK) {
|
||||
*boolPtr = obj.internalRep.wideValue != 0;
|
||||
*boolPtr = obj.internalRep.longValue;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
+65
-131
@@ -9,6 +9,7 @@
|
||||
*
|
||||
* Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans.
|
||||
* Copyright (c) 1995-1997 Sun Microsystems, Inc.
|
||||
* Copyright (c) 2015 Sergey G. Brester aka sebres.
|
||||
*
|
||||
* See the file "license.terms" for information on usage and redistribution of
|
||||
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
@@ -50,73 +51,11 @@
|
||||
* parsed fields will be returned.
|
||||
*/
|
||||
|
||||
typedef struct DateInfo {
|
||||
|
||||
Tcl_Obj* messages; /* Error messages */
|
||||
const char* separatrix; /* String separating messages */
|
||||
|
||||
time_t dateYear;
|
||||
time_t dateMonth;
|
||||
time_t dateDay;
|
||||
int dateHaveDate;
|
||||
|
||||
time_t dateHour;
|
||||
time_t dateMinutes;
|
||||
time_t dateSeconds;
|
||||
int dateMeridian;
|
||||
int dateHaveTime;
|
||||
|
||||
time_t dateTimezone;
|
||||
int dateDSTmode;
|
||||
int dateHaveZone;
|
||||
|
||||
time_t dateRelMonth;
|
||||
time_t dateRelDay;
|
||||
time_t dateRelSeconds;
|
||||
int dateHaveRel;
|
||||
|
||||
time_t dateMonthOrdinal;
|
||||
int dateHaveOrdinalMonth;
|
||||
|
||||
time_t dateDayOrdinal;
|
||||
time_t dateDayNumber;
|
||||
int dateHaveDay;
|
||||
|
||||
const char *dateStart;
|
||||
const char *dateInput;
|
||||
time_t *dateRelPointer;
|
||||
|
||||
int dateDigitCount;
|
||||
} DateInfo;
|
||||
#include "tclDate.h"
|
||||
|
||||
#define YYMALLOC ckalloc
|
||||
#define YYFREE(x) (ckfree((void*) (x)))
|
||||
|
||||
#define yyDSTmode (info->dateDSTmode)
|
||||
#define yyDayOrdinal (info->dateDayOrdinal)
|
||||
#define yyDayNumber (info->dateDayNumber)
|
||||
#define yyMonthOrdinal (info->dateMonthOrdinal)
|
||||
#define yyHaveDate (info->dateHaveDate)
|
||||
#define yyHaveDay (info->dateHaveDay)
|
||||
#define yyHaveOrdinalMonth (info->dateHaveOrdinalMonth)
|
||||
#define yyHaveRel (info->dateHaveRel)
|
||||
#define yyHaveTime (info->dateHaveTime)
|
||||
#define yyHaveZone (info->dateHaveZone)
|
||||
#define yyTimezone (info->dateTimezone)
|
||||
#define yyDay (info->dateDay)
|
||||
#define yyMonth (info->dateMonth)
|
||||
#define yyYear (info->dateYear)
|
||||
#define yyHour (info->dateHour)
|
||||
#define yyMinutes (info->dateMinutes)
|
||||
#define yySeconds (info->dateSeconds)
|
||||
#define yyMeridian (info->dateMeridian)
|
||||
#define yyRelMonth (info->dateRelMonth)
|
||||
#define yyRelDay (info->dateRelDay)
|
||||
#define yyRelSeconds (info->dateRelSeconds)
|
||||
#define yyRelPointer (info->dateRelPointer)
|
||||
#define yyInput (info->dateInput)
|
||||
#define yyDigitCount (info->dateDigitCount)
|
||||
|
||||
#define EPOCH 1970
|
||||
#define START_OF_TIME 1902
|
||||
#define END_OF_TIME 2037
|
||||
@@ -150,14 +89,6 @@ typedef enum _DSTMODE {
|
||||
DSTon, DSToff, DSTmaybe
|
||||
} DSTMODE;
|
||||
|
||||
/*
|
||||
* Meridian: am, pm, or 24-hour style.
|
||||
*/
|
||||
|
||||
typedef enum _MERIDIAN {
|
||||
MERam, MERpm, MER24
|
||||
} MERIDIAN;
|
||||
|
||||
%}
|
||||
|
||||
%union {
|
||||
@@ -176,8 +107,6 @@ static int LookupWord(YYSTYPE* yylvalPtr, char *buff);
|
||||
DateInfo* info, const char *s);
|
||||
static int TclDatelex(YYSTYPE* yylvalPtr, YYLTYPE* location,
|
||||
DateInfo* info);
|
||||
static time_t ToSeconds(time_t Hours, time_t Minutes,
|
||||
time_t Seconds, MERIDIAN Meridian);
|
||||
MODULE_SCOPE int yyparse(DateInfo*);
|
||||
|
||||
%}
|
||||
@@ -377,12 +306,12 @@ date : tUNUMBER '/' tUNUMBER {
|
||||
;
|
||||
|
||||
ordMonth: tNEXT tMONTH {
|
||||
yyMonthOrdinal = 1;
|
||||
yyMonth = $2;
|
||||
yyMonthOrdinalIncr = 1;
|
||||
yyMonthOrdinal = $2;
|
||||
}
|
||||
| tNEXT tUNUMBER tMONTH {
|
||||
yyMonthOrdinal = $2;
|
||||
yyMonth = $3;
|
||||
yyMonthOrdinalIncr = $2;
|
||||
yyMonthOrdinal = $3;
|
||||
}
|
||||
;
|
||||
|
||||
@@ -730,11 +659,11 @@ TclDateerror(
|
||||
infoPtr->separatrix = "\n";
|
||||
}
|
||||
|
||||
static time_t
|
||||
MODULE_SCOPE int
|
||||
ToSeconds(
|
||||
time_t Hours,
|
||||
time_t Minutes,
|
||||
time_t Seconds,
|
||||
int Hours,
|
||||
int Minutes,
|
||||
int Seconds,
|
||||
MERIDIAN Meridian)
|
||||
{
|
||||
if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59) {
|
||||
@@ -957,65 +886,36 @@ TclDatelex(
|
||||
} while (Count > 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
TclClockOldscanObjCmd(
|
||||
ClientData clientData, /* Unused */
|
||||
TclClockFreeScan(
|
||||
Tcl_Interp *interp, /* Tcl interpreter */
|
||||
int objc, /* Count of paraneters */
|
||||
Tcl_Obj *const *objv) /* Parameters */
|
||||
DateInfo *info) /* Input and result parameters */
|
||||
{
|
||||
Tcl_Obj *result, *resultElement;
|
||||
int yr, mo, da;
|
||||
DateInfo dateInfo;
|
||||
DateInfo* info = &dateInfo;
|
||||
int status;
|
||||
|
||||
if (objc != 5) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv,
|
||||
"stringToParse baseYear baseMonth baseDay" );
|
||||
return TCL_ERROR;
|
||||
}
|
||||
/*
|
||||
* yyInput = stringToParse;
|
||||
*
|
||||
* ClockInitDateInfo(info) should be executed to pre-init info;
|
||||
*/
|
||||
|
||||
yyInput = Tcl_GetString( objv[1] );
|
||||
dateInfo.dateStart = yyInput;
|
||||
yyDSTmode = DSTmaybe;
|
||||
|
||||
yyHaveDate = 0;
|
||||
if (Tcl_GetIntFromObj(interp, objv[2], &yr) != TCL_OK
|
||||
|| Tcl_GetIntFromObj(interp, objv[3], &mo) != TCL_OK
|
||||
|| Tcl_GetIntFromObj(interp, objv[4], &da) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
yyYear = yr; yyMonth = mo; yyDay = da;
|
||||
info->messages = Tcl_NewObj();
|
||||
info->separatrix = "";
|
||||
Tcl_IncrRefCount(info->messages);
|
||||
|
||||
yyHaveTime = 0;
|
||||
yyHour = 0; yyMinutes = 0; yySeconds = 0; yyMeridian = MER24;
|
||||
|
||||
yyHaveZone = 0;
|
||||
yyTimezone = 0; yyDSTmode = DSTmaybe;
|
||||
|
||||
yyHaveOrdinalMonth = 0;
|
||||
yyMonthOrdinal = 0;
|
||||
|
||||
yyHaveDay = 0;
|
||||
yyDayOrdinal = 0; yyDayNumber = 0;
|
||||
|
||||
yyHaveRel = 0;
|
||||
yyRelMonth = 0; yyRelDay = 0; yyRelSeconds = 0; yyRelPointer = NULL;
|
||||
|
||||
dateInfo.messages = Tcl_NewObj();
|
||||
dateInfo.separatrix = "";
|
||||
Tcl_IncrRefCount(dateInfo.messages);
|
||||
|
||||
status = yyparse(&dateInfo);
|
||||
info->dateStart = yyInput;
|
||||
status = yyparse(info);
|
||||
if (status == 1) {
|
||||
Tcl_SetObjResult(interp, dateInfo.messages);
|
||||
Tcl_DecrRefCount(dateInfo.messages);
|
||||
Tcl_SetObjResult(interp, info->messages);
|
||||
Tcl_DecrRefCount(info->messages);
|
||||
Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "PARSE", NULL);
|
||||
return TCL_ERROR;
|
||||
} else if (status == 2) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj("memory exhausted", -1));
|
||||
Tcl_DecrRefCount(dateInfo.messages);
|
||||
Tcl_DecrRefCount(info->messages);
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
return TCL_ERROR;
|
||||
} else if (status != 0) {
|
||||
@@ -1023,11 +923,11 @@ TclClockOldscanObjCmd(
|
||||
"from date parser. Please "
|
||||
"report this error as a "
|
||||
"bug in Tcl.", -1));
|
||||
Tcl_DecrRefCount(dateInfo.messages);
|
||||
Tcl_DecrRefCount(info->messages);
|
||||
Tcl_SetErrorCode(interp, "TCL", "BUG", NULL);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
Tcl_DecrRefCount(dateInfo.messages);
|
||||
Tcl_DecrRefCount(info->messages);
|
||||
|
||||
if (yyHaveDate > 1) {
|
||||
Tcl_SetObjResult(interp,
|
||||
@@ -1060,6 +960,40 @@ TclClockOldscanObjCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
int
|
||||
TclClockOldscanObjCmd(
|
||||
ClientData clientData, /* Unused */
|
||||
Tcl_Interp *interp, /* Tcl interpreter */
|
||||
int objc, /* Count of paraneters */
|
||||
Tcl_Obj *const *objv) /* Parameters */
|
||||
{
|
||||
Tcl_Obj *result, *resultElement;
|
||||
int yr, mo, da;
|
||||
DateInfo dateInfo;
|
||||
DateInfo* info = &dateInfo;
|
||||
|
||||
if (objc != 5) {
|
||||
Tcl_WrongNumArgs(interp, 1, objv,
|
||||
"stringToParse baseYear baseMonth baseDay" );
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
yyInput = Tcl_GetString( objv[1] );
|
||||
|
||||
if (Tcl_GetIntFromObj(interp, objv[2], &yr) != TCL_OK
|
||||
|| Tcl_GetIntFromObj(interp, objv[3], &mo) != TCL_OK
|
||||
|| Tcl_GetIntFromObj(interp, objv[4], &da) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
yyYear = yr; yyMonth = mo; yyDay = da;
|
||||
|
||||
if (TclClockFreeScan(interp, info) != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
result = Tcl_NewObj();
|
||||
resultElement = Tcl_NewObj();
|
||||
if (yyHaveDate) {
|
||||
@@ -1111,9 +1045,9 @@ TclClockOldscanObjCmd(
|
||||
resultElement = Tcl_NewObj();
|
||||
if (yyHaveOrdinalMonth) {
|
||||
Tcl_ListObjAppendElement(interp, resultElement,
|
||||
Tcl_NewIntObj((int) yyMonthOrdinal));
|
||||
Tcl_NewIntObj((int) yyMonthOrdinalIncr));
|
||||
Tcl_ListObjAppendElement(interp, resultElement,
|
||||
Tcl_NewIntObj((int) yyMonth));
|
||||
Tcl_NewIntObj((int) yyMonthOrdinal));
|
||||
}
|
||||
Tcl_ListObjAppendElement(interp, result, resultElement);
|
||||
|
||||
|
||||
+60
-25
@@ -13,6 +13,13 @@
|
||||
|
||||
#include "tclInt.h"
|
||||
|
||||
/*
|
||||
* Prevent macros from clashing with function definitions.
|
||||
*/
|
||||
|
||||
#undef Tcl_FindHashEntry
|
||||
#undef Tcl_CreateHashEntry
|
||||
|
||||
/*
|
||||
* When there are this many entries per bucket, on average, rebuild the hash
|
||||
* table to make it larger.
|
||||
@@ -28,7 +35,7 @@
|
||||
*/
|
||||
|
||||
#define RANDOM_INDEX(tablePtr, i) \
|
||||
((((i)*1103515245UL) >> (tablePtr)->downShift) & (tablePtr)->mask)
|
||||
((((i)*1103515245L) >> (tablePtr)->downShift) & (tablePtr)->mask)
|
||||
|
||||
/*
|
||||
* Prototypes for the array hash key methods.
|
||||
@@ -38,6 +45,19 @@ static Tcl_HashEntry * AllocArrayEntry(Tcl_HashTable *tablePtr, void *keyPtr);
|
||||
static int CompareArrayKeys(void *keyPtr, Tcl_HashEntry *hPtr);
|
||||
static TCL_HASH_TYPE HashArrayKey(Tcl_HashTable *tablePtr, void *keyPtr);
|
||||
|
||||
/*
|
||||
* Prototypes for the one word hash key methods. Not actually declared because
|
||||
* this is a critical path that is implemented in the core hash table access
|
||||
* function.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
static Tcl_HashEntry * AllocOneWordEntry(Tcl_HashTable *tablePtr,
|
||||
void *keyPtr);
|
||||
static int CompareOneWordKeys(void *keyPtr, Tcl_HashEntry *hPtr);
|
||||
static unsigned int HashOneWordKey(Tcl_HashTable *tablePtr, void *keyPtr);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Prototypes for the string hash key methods.
|
||||
*/
|
||||
@@ -193,7 +213,7 @@ Tcl_InitCustomHashTable(
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* FindHashEntry --
|
||||
* Tcl_FindHashEntry --
|
||||
*
|
||||
* Given a hash table find the entry with a matching key.
|
||||
*
|
||||
@@ -207,6 +227,14 @@ Tcl_InitCustomHashTable(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Tcl_HashEntry *
|
||||
Tcl_FindHashEntry(
|
||||
Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */
|
||||
const void *key) /* Key to use to find matching entry. */
|
||||
{
|
||||
return (*((tablePtr)->findProc))(tablePtr, key);
|
||||
}
|
||||
|
||||
static Tcl_HashEntry *
|
||||
FindHashEntry(
|
||||
Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */
|
||||
@@ -219,7 +247,7 @@ FindHashEntry(
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* CreateHashEntry --
|
||||
* Tcl_CreateHashEntry --
|
||||
*
|
||||
* Given a hash table with string keys, and a string key, find the entry
|
||||
* with a matching key. If there is no matching entry, then create a new
|
||||
@@ -237,6 +265,17 @@ FindHashEntry(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Tcl_HashEntry *
|
||||
Tcl_CreateHashEntry(
|
||||
Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */
|
||||
const void *key, /* Key to use to find or create matching
|
||||
* entry. */
|
||||
int *newPtr) /* Store info here telling whether a new entry
|
||||
* was created. */
|
||||
{
|
||||
return (*((tablePtr)->createProc))(tablePtr, key, newPtr);
|
||||
}
|
||||
|
||||
static Tcl_HashEntry *
|
||||
CreateHashEntry(
|
||||
Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */
|
||||
@@ -248,7 +287,7 @@ CreateHashEntry(
|
||||
register Tcl_HashEntry *hPtr;
|
||||
const Tcl_HashKeyType *typePtr;
|
||||
unsigned int hash;
|
||||
unsigned int index;
|
||||
int index;
|
||||
|
||||
if (tablePtr->keyType == TCL_STRING_KEYS) {
|
||||
typePtr = &tclStringHashKeyType;
|
||||
@@ -282,7 +321,7 @@ CreateHashEntry(
|
||||
|
||||
for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
|
||||
hPtr = hPtr->nextPtr) {
|
||||
if (hash != hPtr->hash) {
|
||||
if (hash != PTR2UINT(hPtr->hash)) {
|
||||
continue;
|
||||
}
|
||||
if (((void *) key == hPtr) || compareKeysProc((void *) key, hPtr)) {
|
||||
@@ -295,7 +334,7 @@ CreateHashEntry(
|
||||
} else {
|
||||
for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
|
||||
hPtr = hPtr->nextPtr) {
|
||||
if (hash != hPtr->hash) {
|
||||
if (hash != PTR2UINT(hPtr->hash)) {
|
||||
continue;
|
||||
}
|
||||
if (key == hPtr->key.oneWordValue) {
|
||||
@@ -325,7 +364,7 @@ CreateHashEntry(
|
||||
}
|
||||
|
||||
hPtr->tablePtr = tablePtr;
|
||||
hPtr->hash = hash;
|
||||
hPtr->hash = UINT2PTR(hash);
|
||||
hPtr->nextPtr = tablePtr->buckets[index];
|
||||
tablePtr->buckets[index] = hPtr;
|
||||
tablePtr->numEntries++;
|
||||
@@ -367,7 +406,7 @@ Tcl_DeleteHashEntry(
|
||||
const Tcl_HashKeyType *typePtr;
|
||||
Tcl_HashTable *tablePtr;
|
||||
Tcl_HashEntry **bucketPtr;
|
||||
unsigned int index;
|
||||
int index;
|
||||
|
||||
tablePtr = entryPtr->tablePtr;
|
||||
|
||||
@@ -384,9 +423,9 @@ Tcl_DeleteHashEntry(
|
||||
|
||||
if (typePtr->hashKeyProc == NULL
|
||||
|| typePtr->flags & TCL_HASH_KEY_RANDOMIZE_HASH) {
|
||||
index = RANDOM_INDEX(tablePtr, entryPtr->hash);
|
||||
index = RANDOM_INDEX(tablePtr, PTR2INT(entryPtr->hash));
|
||||
} else {
|
||||
index = entryPtr->hash & tablePtr->mask;
|
||||
index = PTR2UINT(entryPtr->hash) & tablePtr->mask;
|
||||
}
|
||||
|
||||
bucketPtr = &tablePtr->buckets[index];
|
||||
@@ -741,14 +780,14 @@ HashArrayKey(
|
||||
void *keyPtr) /* Key from which to compute hash value. */
|
||||
{
|
||||
register const int *array = (const int *) keyPtr;
|
||||
register TCL_HASH_TYPE result;
|
||||
register unsigned int result;
|
||||
int count;
|
||||
|
||||
for (result = 0, count = tablePtr->keyType; count > 0;
|
||||
count--, array++) {
|
||||
result += *array;
|
||||
}
|
||||
return result;
|
||||
return (TCL_HASH_TYPE) result;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -837,7 +876,7 @@ HashStringKey(
|
||||
void *keyPtr) /* Key from which to compute hash value. */
|
||||
{
|
||||
register const char *string = keyPtr;
|
||||
register TCL_HASH_TYPE result;
|
||||
register unsigned int result;
|
||||
register char c;
|
||||
|
||||
/*
|
||||
@@ -877,7 +916,7 @@ HashStringKey(
|
||||
result += (result << 3) + UCHAR(c);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return (TCL_HASH_TYPE) result;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -959,19 +998,12 @@ static void
|
||||
RebuildTable(
|
||||
register Tcl_HashTable *tablePtr) /* Table to enlarge. */
|
||||
{
|
||||
int count, oldSize = tablePtr->numBuckets;
|
||||
unsigned int index;
|
||||
Tcl_HashEntry **oldBuckets = tablePtr->buckets;
|
||||
int oldSize, count, index;
|
||||
Tcl_HashEntry **oldBuckets;
|
||||
register Tcl_HashEntry **oldChainPtr, **newChainPtr;
|
||||
register Tcl_HashEntry *hPtr;
|
||||
const Tcl_HashKeyType *typePtr;
|
||||
|
||||
/* Avoid outgrowing capability of the memory allocators */
|
||||
if (oldSize > (int)(UINT_MAX / (4 * sizeof(Tcl_HashEntry *)))) {
|
||||
tablePtr->rebuildSize = INT_MAX;
|
||||
return;
|
||||
}
|
||||
|
||||
if (tablePtr->keyType == TCL_STRING_KEYS) {
|
||||
typePtr = &tclStringHashKeyType;
|
||||
} else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) {
|
||||
@@ -983,6 +1015,9 @@ RebuildTable(
|
||||
typePtr = &tclArrayHashKeyType;
|
||||
}
|
||||
|
||||
oldSize = tablePtr->numBuckets;
|
||||
oldBuckets = tablePtr->buckets;
|
||||
|
||||
/*
|
||||
* Allocate and initialize the new bucket array, and set up hashing
|
||||
* constants for new array size.
|
||||
@@ -1013,9 +1048,9 @@ RebuildTable(
|
||||
*oldChainPtr = hPtr->nextPtr;
|
||||
if (typePtr->hashKeyProc == NULL
|
||||
|| typePtr->flags & TCL_HASH_KEY_RANDOMIZE_HASH) {
|
||||
index = RANDOM_INDEX(tablePtr, hPtr->hash);
|
||||
index = RANDOM_INDEX(tablePtr, PTR2INT(hPtr->hash));
|
||||
} else {
|
||||
index = hPtr->hash & tablePtr->mask;
|
||||
index = PTR2UINT(hPtr->hash) & tablePtr->mask;
|
||||
}
|
||||
hPtr->nextPtr = tablePtr->buckets[index];
|
||||
tablePtr->buckets[index] = hPtr;
|
||||
|
||||
@@ -73,6 +73,13 @@ Tcl_RecordAndEval(
|
||||
Tcl_IncrRefCount(cmdPtr);
|
||||
result = Tcl_RecordAndEvalObj(interp, cmdPtr, flags);
|
||||
|
||||
/*
|
||||
* Move the interpreter's object result to the string result, then
|
||||
* reset the object result.
|
||||
*/
|
||||
|
||||
(void) Tcl_GetStringResult(interp);
|
||||
|
||||
/*
|
||||
* Discard the Tcl object created to hold the command.
|
||||
*/
|
||||
|
||||
+27
-17
@@ -721,18 +721,17 @@ Tcl_SetStdChannel(
|
||||
{
|
||||
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
|
||||
|
||||
int init = channel ? 1 : -1;
|
||||
switch (type) {
|
||||
case TCL_STDIN:
|
||||
tsdPtr->stdinInitialized = init;
|
||||
tsdPtr->stdinInitialized = 1;
|
||||
tsdPtr->stdinChannel = channel;
|
||||
break;
|
||||
case TCL_STDOUT:
|
||||
tsdPtr->stdoutInitialized = init;
|
||||
tsdPtr->stdoutInitialized = 1;
|
||||
tsdPtr->stdoutChannel = channel;
|
||||
break;
|
||||
case TCL_STDERR:
|
||||
tsdPtr->stderrInitialized = init;
|
||||
tsdPtr->stderrInitialized = 1;
|
||||
tsdPtr->stderrChannel = channel;
|
||||
break;
|
||||
}
|
||||
@@ -769,8 +768,8 @@ Tcl_GetStdChannel(
|
||||
switch (type) {
|
||||
case TCL_STDIN:
|
||||
if (!tsdPtr->stdinInitialized) {
|
||||
tsdPtr->stdinInitialized = -1;
|
||||
tsdPtr->stdinChannel = TclpGetDefaultStdChannel(TCL_STDIN);
|
||||
tsdPtr->stdinInitialized = 1;
|
||||
|
||||
/*
|
||||
* Artificially bump the refcount to ensure that the channel is
|
||||
@@ -782,7 +781,6 @@ Tcl_GetStdChannel(
|
||||
*/
|
||||
|
||||
if (tsdPtr->stdinChannel != NULL) {
|
||||
tsdPtr->stdinInitialized = 1;
|
||||
Tcl_RegisterChannel(NULL, tsdPtr->stdinChannel);
|
||||
}
|
||||
}
|
||||
@@ -790,10 +788,9 @@ Tcl_GetStdChannel(
|
||||
break;
|
||||
case TCL_STDOUT:
|
||||
if (!tsdPtr->stdoutInitialized) {
|
||||
tsdPtr->stdoutInitialized = -1;
|
||||
tsdPtr->stdoutChannel = TclpGetDefaultStdChannel(TCL_STDOUT);
|
||||
tsdPtr->stdoutInitialized = 1;
|
||||
if (tsdPtr->stdoutChannel != NULL) {
|
||||
tsdPtr->stdoutInitialized = 1;
|
||||
Tcl_RegisterChannel(NULL, tsdPtr->stdoutChannel);
|
||||
}
|
||||
}
|
||||
@@ -801,10 +798,9 @@ Tcl_GetStdChannel(
|
||||
break;
|
||||
case TCL_STDERR:
|
||||
if (!tsdPtr->stderrInitialized) {
|
||||
tsdPtr->stderrInitialized = -1;
|
||||
tsdPtr->stderrChannel = TclpGetDefaultStdChannel(TCL_STDERR);
|
||||
tsdPtr->stderrInitialized = 1;
|
||||
if (tsdPtr->stderrChannel != NULL) {
|
||||
tsdPtr->stderrInitialized = 1;
|
||||
Tcl_RegisterChannel(NULL, tsdPtr->stderrChannel);
|
||||
}
|
||||
}
|
||||
@@ -1072,7 +1068,7 @@ CheckForStdChannelsBeingClosed(
|
||||
ChannelState *statePtr = ((Channel *) chan)->state;
|
||||
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
|
||||
|
||||
if (tsdPtr->stdinInitialized == 1
|
||||
if (tsdPtr->stdinInitialized
|
||||
&& tsdPtr->stdinChannel != NULL
|
||||
&& statePtr == ((Channel *)tsdPtr->stdinChannel)->state) {
|
||||
if (statePtr->refCount < 2) {
|
||||
@@ -1080,7 +1076,7 @@ CheckForStdChannelsBeingClosed(
|
||||
tsdPtr->stdinChannel = NULL;
|
||||
return;
|
||||
}
|
||||
} else if (tsdPtr->stdoutInitialized == 1
|
||||
} else if (tsdPtr->stdoutInitialized
|
||||
&& tsdPtr->stdoutChannel != NULL
|
||||
&& statePtr == ((Channel *)tsdPtr->stdoutChannel)->state) {
|
||||
if (statePtr->refCount < 2) {
|
||||
@@ -1088,7 +1084,7 @@ CheckForStdChannelsBeingClosed(
|
||||
tsdPtr->stdoutChannel = NULL;
|
||||
return;
|
||||
}
|
||||
} else if (tsdPtr->stderrInitialized == 1
|
||||
} else if (tsdPtr->stderrInitialized
|
||||
&& tsdPtr->stderrChannel != NULL
|
||||
&& statePtr == ((Channel *)tsdPtr->stderrChannel)->state) {
|
||||
if (statePtr->refCount < 2) {
|
||||
@@ -1142,7 +1138,7 @@ Tcl_IsStandardChannel(
|
||||
* channel refCount.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
* The channel.
|
||||
*
|
||||
* Side effects:
|
||||
* May increment the reference count of a channel.
|
||||
@@ -1150,7 +1146,7 @@ Tcl_IsStandardChannel(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
Tcl_Channel
|
||||
Tcl_RegisterChannel(
|
||||
Tcl_Interp *interp, /* Interpreter in which to add the channel. */
|
||||
Tcl_Channel chan) /* The channel to add to this interpreter
|
||||
@@ -1179,7 +1175,7 @@ Tcl_RegisterChannel(
|
||||
hPtr = Tcl_CreateHashEntry(hTblPtr, statePtr->channelName, &isNew);
|
||||
if (!isNew) {
|
||||
if (chan == Tcl_GetHashValue(hPtr)) {
|
||||
return;
|
||||
return chan;
|
||||
}
|
||||
|
||||
Tcl_Panic("Tcl_RegisterChannel: duplicate channel names");
|
||||
@@ -1187,6 +1183,8 @@ Tcl_RegisterChannel(
|
||||
Tcl_SetHashValue(hPtr, chanPtr);
|
||||
}
|
||||
statePtr->refCount++;
|
||||
|
||||
return chan;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -6712,7 +6710,7 @@ Tcl_Flush(
|
||||
chanPtr = statePtr->topChanPtr;
|
||||
|
||||
if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) {
|
||||
return TCL_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
result = FlushChannel(NULL, chanPtr, 0);
|
||||
@@ -9036,6 +9034,18 @@ ZeroTransferTimerProc(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
TclCopyChannelOld(
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
Tcl_Channel inChan, /* Channel to read from. */
|
||||
Tcl_Channel outChan, /* Channel to write to. */
|
||||
int toRead, /* Amount of data to copy, or -1 for all. */
|
||||
Tcl_Obj *cmdPtr) /* Pointer to script to execute or NULL. */
|
||||
{
|
||||
return TclCopyChannel(interp, inChan, outChan, (Tcl_WideInt) toRead,
|
||||
cmdPtr);
|
||||
}
|
||||
|
||||
int
|
||||
TclCopyChannel(
|
||||
Tcl_Interp *interp, /* Current interpreter. */
|
||||
|
||||
+28
-1
@@ -15,7 +15,7 @@
|
||||
* Callback structure for accept callback in a TCP server.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
typedef struct AcceptCallback {
|
||||
Tcl_Obj *script; /* Script to invoke. */
|
||||
Tcl_Interp *interp; /* Interpreter in which to run it. */
|
||||
} AcceptCallback;
|
||||
@@ -137,6 +137,19 @@ Tcl_PutsObjCmd(
|
||||
chanObjPtr = objv[2];
|
||||
string = objv[3];
|
||||
break;
|
||||
#if TCL_MAJOR_VERSION < 9
|
||||
} else if (strcmp(TclGetString(objv[3]), "nonewline") == 0) {
|
||||
/*
|
||||
* The code below provides backwards compatibility with an old
|
||||
* form of the command that is no longer recommended or
|
||||
* documented. See also [Bug #3151675]. Will be removed in Tcl 9,
|
||||
* maybe even earlier.
|
||||
*/
|
||||
|
||||
chanObjPtr = objv[1];
|
||||
string = objv[2];
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
/* Fall through */
|
||||
default: /* [puts] or
|
||||
@@ -426,11 +439,25 @@ Tcl_ReadObjCmd(
|
||||
if (i < objc) {
|
||||
if ((TclGetIntFromObj(interp, objv[i], &toRead) != TCL_OK)
|
||||
|| (toRead < 0)) {
|
||||
#if TCL_MAJOR_VERSION < 9
|
||||
/*
|
||||
* The code below provides backwards compatibility with an old
|
||||
* form of the command that is no longer recommended or
|
||||
* documented. See also [Bug #3151675]. Will be removed in Tcl 9,
|
||||
* maybe even earlier.
|
||||
*/
|
||||
|
||||
if (strcmp(TclGetString(objv[i]), "nonewline") != 0) {
|
||||
#endif
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
"expected non-negative integer but got \"%s\"",
|
||||
TclGetString(objv[i])));
|
||||
Tcl_SetErrorCode(interp, "TCL", "VALUE", "NUMBER", NULL);
|
||||
return TCL_ERROR;
|
||||
#if TCL_MAJOR_VERSION < 9
|
||||
}
|
||||
newline = 1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,8 +41,6 @@ static void ReflectWatch(ClientData clientData, int mask);
|
||||
static int ReflectBlock(ClientData clientData, int mode);
|
||||
#ifdef TCL_THREADS
|
||||
static void ReflectThread(ClientData clientData, int action);
|
||||
static int ReflectEventRun(Tcl_Event *ev, int flags);
|
||||
static int ReflectEventDelete(Tcl_Event *ev, ClientData cd);
|
||||
#endif
|
||||
static Tcl_WideInt ReflectSeekWide(ClientData clientData,
|
||||
Tcl_WideInt offset, int mode, int *errorCodePtr);
|
||||
@@ -750,7 +748,6 @@ TclChanCreateObjCmd(
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifdef TCL_THREADS
|
||||
typedef struct {
|
||||
Tcl_Event header;
|
||||
ReflectedChannel *rcPtr;
|
||||
@@ -794,7 +791,6 @@ ReflectEventDelete(
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
TclChanPostEventObjCmd(
|
||||
|
||||
@@ -87,7 +87,7 @@ static const Tcl_ChannelType tclRTransformType = {
|
||||
* layers upon reading from the channel, plus the functions to manage such.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
typedef struct _ResultBuffer_ {
|
||||
unsigned char *buf; /* Reference to the buffer area. */
|
||||
int allocated; /* Allocated size of the buffer area. */
|
||||
int used; /* Number of bytes in the buffer,
|
||||
@@ -253,7 +253,7 @@ typedef enum {
|
||||
* sharing problems.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
typedef struct ForwardParamBase {
|
||||
int code; /* O: Ok/Fail of the cmd handler */
|
||||
char *msgStr; /* O: Error message for handler failure */
|
||||
int mustFree; /* O: True if msgStr is allocated, false if
|
||||
@@ -298,7 +298,7 @@ typedef struct ForwardingResult ForwardingResult;
|
||||
* General event structure, with reference to operation specific data.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
typedef struct ForwardingEvent {
|
||||
Tcl_Event event; /* Basic event data, has to be first item */
|
||||
ForwardingResult *resultPtr;
|
||||
ForwardedOperation op; /* Forwarded driver operation */
|
||||
|
||||
+1
-1
@@ -223,7 +223,7 @@ TclCreateSocketAddress(
|
||||
* using AI_ADDRCONFIG is probably low even in situations where it works,
|
||||
* we'll leave it out for now. After all, it is just an optimisation.
|
||||
*
|
||||
* Missing on NetBSD.
|
||||
* Missing on: OpenBSD, NetBSD.
|
||||
* Causes failure when used on AIX 5.1 and HP-UX
|
||||
*/
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user