Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Comment: | Merge 9.0 |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | tip-626 |
Files: | files | file ages | folders |
SHA3-256: |
e906cead7811f1c5fc00dc2be71a09d6 |
User & Date: | jan.nijtmans 2024-05-21 22:06:38 |
2024-06-07
| ||
11:31 | Merge 9.0 check-in: 84ae5008cc user: jan.nijtmans tags: tip-626 | |
2024-05-21
| ||
22:06 | Merge 9.0 check-in: e906cead78 user: jan.nijtmans tags: tip-626 | |
21:22 | "TCL_TOMMATH" is not used anywhere check-in: 134a992bae user: jan.nijtmans tags: trunk, main | |
2024-05-03
| ||
13:26 | Merge 9.0 check-in: 58f49ce426 user: jan.nijtmans tags: tip-626 | |
Changes to changes.md.
|
| < < < < < | < < < < > | < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < | < < < < < < < | < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | The source code for Tcl is managed by fossil. Tcl developers coordinate all changes to the Tcl source code at > [Tcl Source Code](https://core.tcl-lang.org/tcl/timeline) Release Tcl 9.1a0 arises from the check-in with tag core-9-1-a0. Highlighted differences between Tcl 9.1 and Tcl 9.0 are summarized below, with focus on changes important to programmers using the Tcl library and writing Tcl scripts. ## Continued 64-bit capacity: Command line arguments larger than 2Gb |
Changes to doc/Tcl.n.
1 2 3 | '\" '\" Copyright (c) 1993 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. | < < | | | > > > | | > | < < | | > | < < < < < < < < | > > | | < < < | < < > | < < < < < < | | > > > | > | < > | < < < < | | | < | > | | | | | < < | < > > | | < | > | | | > > > > > > | < > | | | > > > > | | > > > > | | | | < < > | > | > > > > > > > > > > > | > > | > > | > | > > > | | > > > > > < < | | > > | | | > > | | < | < | < | < | < | < | < | | | | > | | < > | | > > | | > > | | > > | | > | | > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 | '\" '\" 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 Tcl n "8.6" Tcl "Tcl Built-In Commands" .so man.macros .BS .SH NAME Tcl \- Tool Command Language .SH SYNOPSIS Summary of Tcl language syntax. .BE .SH DESCRIPTION .PP The following rules define the syntax and semantics of the Tcl language: .IP "[1] \fBCommands.\fR" A Tcl script is a string containing one or more commands. Semi-colons and newlines are command separators unless quoted as described below. Close brackets are command terminators during command substitution (see below) unless quoted. .IP "[2] \fBEvaluation.\fR" A command is evaluated in two steps. First, the Tcl interpreter breaks the command into \fIwords\fR and performs substitutions as described below. These substitutions are performed in the same way for all commands. Secondly, the first word is used to locate a routine to carry out the command, and the remaining words of the command are passed to that routine. The routine is free to interpret each of its words in any way it likes, such as an integer, variable name, list, or Tcl script. Different commands interpret their words differently. .IP "[3] \fBWords.\fR" Words of a command are separated by white space (except for newlines, which are command separators). .IP "[4] \fBDouble quotes.\fR" If the first character of a word is double-quote .PQ \N'34' then the word is terminated by the next double-quote character. If semi-colons, close brackets, or white space characters (including newlines) appear between the quotes then they are treated as ordinary characters and included in the word. Command substitution, variable substitution, and backslash substitution are performed on the characters between the quotes as described below. The double-quotes are not retained as part of the word. .IP "[5] \fBArgument expansion.\fR" If a word starts with the string .QW {*} followed by a non-whitespace character, then the leading .QW {*} is removed and the rest of the word is parsed and substituted as any other word. After substitution, the word is parsed as a list (without command or variable substitutions; backslash substitutions are performed as is normal for a list and individual internal words may be surrounded by either braces or double-quote characters), and its words are added to the command being substituted. For instance, .QW "cmd a {*}{b [c]} d {*}{$e f {g h}}" is equivalent to .QW "cmd a b {[c]} d {$e} f {g h}" . .IP "[6] \fBBraces.\fR" If the first character of a word is an open brace .PQ { and rule [5] does not apply, then the word is terminated by the matching close brace .PQ } "" . Braces nest within the word: for each additional open brace there must be an additional close brace (however, if an open brace or close brace within the word is quoted with a backslash then it is not counted in locating the matching close brace). No substitutions are performed on the characters between the braces except for backslash-newline substitutions described below, nor do semi-colons, newlines, close brackets, or white space receive any special interpretation. The word will consist of exactly the characters between the outer braces, not including the braces themselves. .IP "[7] \fBCommand substitution.\fR" If a word contains an open bracket .PQ [ then Tcl performs \fIcommand substitution\fR. To do this it invokes the Tcl interpreter recursively to process the characters following the open bracket as a Tcl script. The script may contain any number of commands and must be terminated by a close bracket .PQ ] "" . The result of the script (i.e. the result of its last command) is substituted into the word in place of the brackets and all of the characters between them. There may be any number of command substitutions in a single word. Command substitution is not performed on words enclosed in braces. .IP "[8] \fBVariable substitution.\fR" If a word contains a dollar-sign .PQ $ followed by one of the forms described below, then Tcl performs \fIvariable substitution\fR: the dollar-sign and the following characters are replaced in the word by the value of a variable. Variable substitution may take any of the following forms: .RS .TP 15 \fB$\fIname\fR . \fIName\fR is the name of a scalar variable; the name is a sequence of one or more characters that are a letter, digit, underscore, or namespace separators (two or more colons). Letters and digits are \fIonly\fR the standard ASCII ones (\fB0\fR\(en\fB9\fR, \fBA\fR\(en\fBZ\fR and \fBa\fR\(en\fBz\fR). .TP 15 \fB$\fIname\fB(\fIindex\fB)\fR . \fIName\fR gives the name of an array variable and \fIindex\fR gives the name of an element within that array. \fIName\fR must contain only letters, digits, underscores, and namespace separators, and may be an empty string. Letters and digits are \fIonly\fR the standard ASCII ones (\fB0\fR\(en\fB9\fR, \fBA\fR\(en\fBZ\fR and \fBa\fR\(en\fBz\fR). Command substitutions, variable substitutions, and backslash substitutions are performed on the characters of \fIindex\fR. .TP 15 \fB${\fIname\fB}\fR . \fIName\fR is the name of a scalar variable or array element. It may contain any characters whatsoever except for close braces. It indicates an array element if \fIname\fR is in the form .QW \fIarrayName\fB(\fIindex\fB)\fR where \fIarrayName\fR does not contain any open parenthesis characters, .QW \fB(\fR , or close brace characters, .QW \fB}\fR , and \fIindex\fR can be any sequence of characters except for close brace characters. No further substitutions are performed during the parsing of \fIname\fR. .PP There may be any number of variable substitutions in a single word. Variable substitution is not performed on words enclosed in braces. .PP Note that variables may contain character sequences other than those listed above, but in that case other mechanisms must be used to access them (e.g., via the \fBset\fR command's single-argument form). .RE .IP "[9] \fBBackslash substitution.\fR" If a backslash .PQ \e appears within a word then \fIbackslash substitution\fR occurs. In all cases but those described below the backslash is dropped and the following character is treated as an ordinary character and included in the word. This allows characters such as double quotes, close brackets, and dollar signs to be included in words without triggering special processing. The following table lists the backslash sequences that are handled specially, along with the value that replaces each sequence. .RS .RS .RS .TP 7 \e\fBa\fR Audible alert (bell) (Unicode U+000007). .TP 7 \e\fBb\fR Backspace (Unicode U+000008). .TP 7 \e\fBf\fR Form feed (Unicode U+00000C). .TP 7 \e\fBn\fR Newline (Unicode U+00000A). .TP 7 \e\fBr\fR Carriage-return (Unicode U+00000D). .TP 7 \e\fBt\fR Tab (Unicode U+000009). .TP 7 \e\fBv\fR Vertical tab (Unicode U+00000B). .TP 7 \e\fB<newline>\fIwhiteSpace\fR . A single space character replaces the backslash, newline, and all spaces and tabs after the newline. This backslash sequence is unique in that it is replaced in a separate pre-pass before the command is actually parsed. This means that it will be replaced even when it occurs between braces, and the resulting space will be treated as a word separator if it is not in braces or quotes. .TP 7 \e\e Backslash .PQ \e "" . .TP 7 \e\fIooo\fR . The digits \fIooo\fR (one, two, or three of them) give a eight-bit octal value for the Unicode character that will be inserted, in the range \fI000\fR\(en\fI377\fR (i.e., the range U+000000\(enU+0000FF). The parser will stop just before this range overflows, or when the maximum of three digits is reached. The upper bits of the Unicode character will be 0. .TP 7 \e\fBx\fIhh\fR . The hexadecimal digits \fIhh\fR (one or two of them) give an eight-bit hexadecimal value for the Unicode character that will be inserted. The upper bits of the Unicode character will be 0 (i.e., the character will be in the range U+000000\(enU+0000FF). .TP 7 \e\fBu\fIhhhh\fR . The hexadecimal digits \fIhhhh\fR (one, two, three, or four of them) give a sixteen-bit hexadecimal value for the Unicode character that will be inserted. The upper bits of the Unicode character will be 0 (i.e., the character will be in the range U+000000\(enU+00FFFF). .TP 7 \e\fBU\fIhhhhhhhh\fR . The hexadecimal digits \fIhhhhhhhh\fR (one up to eight of them) give a twenty-one-bit hexadecimal value for the Unicode character that will be inserted, in the range U+000000\(enU+10FFFF. The parser will stop just before this range overflows, or when the maximum of eight digits is reached. The upper bits of the Unicode character will be 0. .RE .RE .PP Backslash substitution is not performed on words enclosed in braces, except for backslash-newline as described above. .RE .IP "[10] \fBComments.\fR" If a hash character .PQ # appears at a point where Tcl is expecting the first character of the first word of a command, then the hash character and the characters that follow it, up through the next newline, are treated as a comment and ignored. The comment character only has significance when it appears at the beginning of a command. .IP "[11] \fBOrder of substitution.\fR" Each character is processed exactly once by the Tcl interpreter as part of creating the words of a command. For example, if variable substitution occurs then no further substitutions are performed on the value of the variable; the value is inserted into the word verbatim. If command substitution occurs then the nested command is processed entirely by the recursive call to the Tcl interpreter; no substitutions are performed before making the recursive call and no additional substitutions are performed on the result of the nested script. .RS .PP Substitutions take place from left to right, and each substitution is evaluated completely before attempting to evaluate the next. Thus, a sequence like .PP .CS set y [set x 0][incr x][incr x] .CE .PP will always set the variable \fIy\fR to the value, \fI012\fR. .RE .IP "[12] \fBSubstitution and word boundaries.\fR" Substitutions do not affect the word boundaries of a command, except for argument expansion as specified in rule [5]. For example, during variable substitution the entire value of the variable becomes part of a single word, even if the variable's value contains spaces. .SH KEYWORDS backslash, command, comment, script, substitution, variable '\" Local Variables: '\" mode: nroff '\" fill-column: 78 '\" End: |
Changes to doc/unknown.n.
︙ | ︙ | |||
43 44 45 46 47 48 49 | The result of the \fBunknown\fR command is used as the result for the original non-existent command. .PP The default implementation of \fBunknown\fR behaves as follows. It first calls the \fBauto_load\fR library procedure to load the command. If this succeeds, then it executes the original command with its original arguments. | | | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | The result of the \fBunknown\fR command is used as the result for the original non-existent command. .PP The default implementation of \fBunknown\fR behaves as follows. It first calls the \fBauto_load\fR library procedure to load the command. If this succeeds, then it executes the original command with its original arguments. If the auto-load fails and Tcl is run interactively then \fBunknown\fR calls \fBauto_execok\fR to see if there is an executable file by the name \fIcmd\fR. If so, it invokes the Tcl \fBexec\fR command with \fIcmd\fR and all the \fIargs\fR as arguments. If \fIcmd\fR cannot be auto-executed, \fBunknown\fR checks to see if the command was invoked at top-level and outside of any script. If so, then \fBunknown\fR takes two additional steps. First, it sees if \fIcmd\fR has one of the following three forms: |
︙ | ︙ |
Changes to generic/tcl.decls.
︙ | ︙ | |||
244 245 246 247 248 249 250 | declare 79 { void Tcl_CallWhenDeleted(Tcl_Interp *interp, Tcl_InterpDeleteProc *proc, void *clientData) } declare 80 { void Tcl_CancelIdleCall(Tcl_IdleProc *idleProc, void *clientData) } | < | 244 245 246 247 248 249 250 251 252 253 254 255 256 257 | declare 79 { void Tcl_CallWhenDeleted(Tcl_Interp *interp, Tcl_InterpDeleteProc *proc, void *clientData) } declare 80 { void Tcl_CancelIdleCall(Tcl_IdleProc *idleProc, void *clientData) } declare 82 { int Tcl_CommandComplete(const char *cmd) } declare 83 { char *Tcl_Concat(Tcl_Size argc, const char *const *argv) } declare 84 { |
︙ | ︙ |
Changes to generic/tcl.h.
︙ | ︙ | |||
44 45 46 47 48 49 50 | * README.md (sections 0 and 2, with and without separator) * macosx/Tcl-Common.xcconfig (not patchlevel) 1 LOC * win/README (not patchlevel) (sections 0 and 2) * unix/tcl.spec (1 LOC patch) */ #if !defined(TCL_MAJOR_VERSION) | | | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | * README.md (sections 0 and 2, with and without separator) * macosx/Tcl-Common.xcconfig (not patchlevel) 1 LOC * win/README (not patchlevel) (sections 0 and 2) * unix/tcl.spec (1 LOC patch) */ #if !defined(TCL_MAJOR_VERSION) # define TCL_MAJOR_VERSION 9 #endif #if TCL_MAJOR_VERSION != 9 # error "This header-file is for Tcl 9 only" #endif #define TCL_MINOR_VERSION 1 #define TCL_RELEASE_LEVEL TCL_ALPHA_RELEASE #define TCL_RELEASE_SERIAL 0 |
︙ | ︙ | |||
87 88 89 90 91 92 93 | #ifndef RC_INVOKED /* * Special macro to define mutexes. */ | | > | 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | #ifndef RC_INVOKED /* * Special macro to define mutexes. */ #define TCL_DECLARE_MUTEX(name) \ static Tcl_Mutex name; /* * Tcl's public routine Tcl_FSSeek() uses the values SEEK_SET, SEEK_CUR, and * SEEK_END, all #define'd by stdio.h . * * Also, many extensions need stdio.h, and they've grown accustomed to tcl.h * providing it for them rather than #include-ing it themselves as they |
︙ | ︙ | |||
448 449 450 451 452 453 454 | /* * Structures filled in by Tcl_RegExpInfo. Note that all offset values are * relative to the start of the match string, not the beginning of the entire * string. */ typedef struct Tcl_RegExpIndices { | | | | | | 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 | /* * Structures filled in by Tcl_RegExpInfo. Note that all offset values are * relative to the start of the match string, not the beginning of the entire * string. */ typedef struct Tcl_RegExpIndices { Tcl_Size start; /* Character offset of first character in * match. */ Tcl_Size end; /* Character offset of first character after * the match. */ } Tcl_RegExpIndices; typedef struct Tcl_RegExpInfo { Tcl_Size nsubs; /* Number of subexpressions in the compiled * expression. */ Tcl_RegExpIndices *matches; /* Array of nsubs match offset pairs. */ Tcl_Size extendStart; /* The offset at which a subsequent match * might begin. */ } Tcl_RegExpInfo; /* * Picky compilers complain if this typdef doesn't appear before the struct's * reference in tclDecls.h. */ |
︙ | ︙ | |||
588 589 590 591 592 593 594 | void *clientData); typedef void (Tcl_DeleteFileHandlerProc) (int fd); typedef void (Tcl_AlertNotifierProc) (void *clientData); typedef void (Tcl_ServiceModeHookProc) (int mode); typedef void *(Tcl_InitNotifierProc) (void); typedef void (Tcl_FinalizeNotifierProc) (void *clientData); typedef void (Tcl_MainLoopProc) (void); | | | | | | | < | | | | | | | < | | | < | | | 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 | void *clientData); typedef void (Tcl_DeleteFileHandlerProc) (int fd); typedef void (Tcl_AlertNotifierProc) (void *clientData); typedef void (Tcl_ServiceModeHookProc) (int mode); typedef void *(Tcl_InitNotifierProc) (void); typedef void (Tcl_FinalizeNotifierProc) (void *clientData); typedef void (Tcl_MainLoopProc) (void); /* Abstract List functions */ typedef Tcl_Size (Tcl_ObjTypeLengthProc) (struct Tcl_Obj *listPtr); typedef int (Tcl_ObjTypeIndexProc) (Tcl_Interp *interp, struct Tcl_Obj *listPtr, Tcl_Size index, struct Tcl_Obj** elemObj); typedef int (Tcl_ObjTypeSliceProc) (Tcl_Interp *interp, struct Tcl_Obj *listPtr, Tcl_Size fromIdx, Tcl_Size toIdx, struct Tcl_Obj **newObjPtr); typedef int (Tcl_ObjTypeReverseProc) (Tcl_Interp *interp, struct Tcl_Obj *listPtr, struct Tcl_Obj **newObjPtr); typedef int (Tcl_ObjTypeGetElements) (Tcl_Interp *interp, struct Tcl_Obj *listPtr, Tcl_Size *objcptr, struct Tcl_Obj ***objvptr); typedef struct Tcl_Obj *(Tcl_ObjTypeSetElement) (Tcl_Interp *interp, struct Tcl_Obj *listPtr, Tcl_Size indexCount, struct Tcl_Obj *const indexArray[], struct Tcl_Obj *valueObj); typedef int (Tcl_ObjTypeReplaceProc) (Tcl_Interp *interp, struct Tcl_Obj *listObj, Tcl_Size first, Tcl_Size numToDelete, Tcl_Size numToInsert, struct Tcl_Obj *const insertObjs[]); typedef int (Tcl_ObjTypeInOperatorProc) (Tcl_Interp *interp, struct Tcl_Obj *valueObj, struct Tcl_Obj *listObj, int *boolResult); #ifndef TCL_NO_DEPRECATED # define Tcl_PackageInitProc Tcl_LibraryInitProc # define Tcl_PackageUnloadProc Tcl_LibraryUnloadProc #endif /* |
︙ | ︙ | |||
642 643 644 645 646 647 648 | Tcl_SetFromAnyProc *setFromAnyProc; /* Called to convert the object's internal rep * to this type. Frees the internal rep of the * old type. Returns TCL_ERROR on failure. */ size_t version; /* List emulation functions - ObjType Version 1 */ | | | | | | > | | | | | | > | | > | | | | | 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 | Tcl_SetFromAnyProc *setFromAnyProc; /* Called to convert the object's internal rep * to this type. Frees the internal rep of the * old type. Returns TCL_ERROR on failure. */ size_t version; /* List emulation functions - ObjType Version 1 */ Tcl_ObjTypeLengthProc *lengthProc; /* Return the [llength] of the AbstractList */ Tcl_ObjTypeIndexProc *indexProc; /* Return a value (Tcl_Obj) at a given index */ Tcl_ObjTypeSliceProc *sliceProc; /* Return an AbstractList for * [lrange $al $start $end] */ Tcl_ObjTypeReverseProc *reverseProc; /* Return an AbstractList for [lreverse $al] */ Tcl_ObjTypeGetElements *getElementsProc; /* Return an objv[] of all elements in the list */ Tcl_ObjTypeSetElement *setElementProc; /* Replace the element at the indicies with the * given valueObj. */ Tcl_ObjTypeReplaceProc *replaceProc; /* Replace sublist with another sublist */ Tcl_ObjTypeInOperatorProc *inOperProc; /* "in" and "ni" expr list operation. * Determine if the given string value matches * an element in the list. */ } Tcl_ObjType; #define TCL_OBJTYPE_V0 0, \ 0,0,0,0,0,0,0,0 /* Pre-Tcl 9 */ #define TCL_OBJTYPE_V1(a) offsetof(Tcl_ObjType, indexProc), \ a,0,0,0,0,0,0,0 /* Tcl 9 Version 1 */ #define TCL_OBJTYPE_V2(a,b,c,d,e,f,g,h) sizeof(Tcl_ObjType), \ |
︙ | ︙ | |||
716 717 718 719 720 721 722 | * array as a readonly value. */ Tcl_Size length; /* The number of bytes at *bytes, not * including the terminating null. */ const Tcl_ObjType *typePtr; /* Denotes the object's type. Always * corresponds to the type of the object's * internal rep. NULL indicates the object has * no internal rep (has no type). */ | | > < | | 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 | * array as a readonly value. */ Tcl_Size length; /* The number of bytes at *bytes, not * including the terminating null. */ const Tcl_ObjType *typePtr; /* Denotes the object's type. Always * corresponds to the type of the object's * internal rep. NULL indicates the object has * no internal rep (has no type). */ Tcl_ObjInternalRep internalRep; /* The internal representation: */ } Tcl_Obj; /* *---------------------------------------------------------------------------- * The following definitions support Tcl's namespace facility. Note: the first * five fields must match exactly the fields in a Namespace structure (see * tclInt.h). */ typedef struct Tcl_Namespace { char *name; /* The namespace's name within its parent * namespace. This contains no ::'s. The name * of the global namespace is "" although "::" * is an synonym. */ char *fullName; /* The namespace's fully qualified name. This * starts with ::. */ void *clientData; /* Arbitrary value associated with this * namespace. */ Tcl_NamespaceDeleteProc *deleteProc; /* Function invoked when deleting the * namespace to, e.g., free clientData. */ struct Tcl_Namespace *parentPtr; /* Points to the namespace that contains this * one. NULL if this is the global |
︙ | ︙ | |||
813 814 815 816 817 818 819 | void *objProcNotUsed; /* Command's object-based function. */ void *objClientDataNotUsed; /* ClientData for object proc. */ #else Tcl_ObjCmdProc *objProc; /* Command's object-based function. */ void *objClientData; /* ClientData for object proc. */ #endif Tcl_CmdProc *proc; /* Command's string-based function. */ | | | | 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 | void *objProcNotUsed; /* Command's object-based function. */ void *objClientDataNotUsed; /* ClientData for object proc. */ #else Tcl_ObjCmdProc *objProc; /* Command's object-based function. */ void *objClientData; /* ClientData for object proc. */ #endif Tcl_CmdProc *proc; /* Command's string-based function. */ void *clientData; /* ClientData for string proc. */ Tcl_CmdDeleteProc *deleteProc; /* Function to call when command is * deleted. */ void *deleteData; /* Value to pass to deleteProc (usually the * same as clientData). */ Tcl_Namespace *namespacePtr;/* Points to the namespace that contains this * command. Note that Tcl_SetCmdInfo will not * change a command's namespace; use * TclRenameCommand or Tcl_Eval (of 'rename') * to do that. */ Tcl_ObjCmdProc2 *objProc2; /* Command's object2-based function. */ |
︙ | ︙ | |||
932 933 934 935 936 937 938 | * o Run in iPtr->lookupNsPtr or global namespace * o Cut out of error traces * o Don't reset the flags controlling ensemble * error message rewriting. * TCL_CANCEL_UNWIND: Magical Tcl_CancelEval mode that causes the * stack for the script in progress to be * completely unwound. | | | 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 | * o Run in iPtr->lookupNsPtr or global namespace * o Cut out of error traces * o Don't reset the flags controlling ensemble * error message rewriting. * TCL_CANCEL_UNWIND: Magical Tcl_CancelEval mode that causes the * stack for the script in progress to be * completely unwound. * TCL_EVAL_NOERR: Do no exception reporting at all, just return * as the caller will report. */ #define TCL_NO_EVAL 0x010000 #define TCL_EVAL_GLOBAL 0x020000 #define TCL_EVAL_DIRECT 0x040000 #define TCL_EVAL_INVOKE 0x080000 |
︙ | ︙ | |||
1041 1042 1043 1044 1045 1046 1047 | */ 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. */ size_t hash; /* Hash value. */ | | | 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 | */ 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. */ size_t hash; /* Hash value. */ void *clientData; /* Application stores something here with * Tcl_SetHashValue. */ union { /* Key has one of these forms: */ char *oneWordValue; /* One-word value for key. */ Tcl_Obj *objPtr; /* Tcl_Obj * key value. */ int words[1]; /* Multiple integer words for key. The actual * size will be as large as necessary for this * table's keys. */ |
︙ | ︙ | |||
1137 1138 1139 1140 1141 1142 1143 | struct Tcl_HashTable { Tcl_HashEntry **buckets; /* Pointer to bucket array. Each element * points to first entry in bucket's hash * chain, or NULL. */ Tcl_HashEntry *staticBuckets[TCL_SMALL_HASH_TABLE]; /* Bucket array used for small tables (to * avoid mallocs and frees). */ | | | | | 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 | struct Tcl_HashTable { Tcl_HashEntry **buckets; /* Pointer to bucket array. Each element * points to first entry in bucket's hash * chain, or NULL. */ Tcl_HashEntry *staticBuckets[TCL_SMALL_HASH_TABLE]; /* Bucket array used for small tables (to * avoid mallocs and frees). */ Tcl_Size numBuckets; /* Total number of buckets allocated at * **bucketPtr. */ Tcl_Size numEntries; /* Total number of entries present in * table. */ Tcl_Size rebuildSize; /* Enlarge table when numEntries gets to be * this large. */ size_t 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 keyType; /* Type of keys used in this table. It's * either TCL_CUSTOM_KEYS, TCL_STRING_KEYS, |
︙ | ︙ | |||
1727 1728 1729 1730 1731 1732 1733 | * token. */ typedef struct Tcl_Token { int type; /* Type of token, such as TCL_TOKEN_WORD; see * below for valid types. */ const char *start; /* First character in token. */ | | | | 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 | * token. */ typedef struct Tcl_Token { int type; /* Type of token, such as TCL_TOKEN_WORD; see * below for valid types. */ const char *start; /* First character in token. */ Tcl_Size size; /* Number of bytes in token. */ Tcl_Size numComponents; /* If this token is composed of other tokens, * this field tells how many of them there are * (including components of components, etc.). * The component tokens immediately follow * this one. */ } Tcl_Token; /* |
︙ | ︙ | |||
1842 1843 1844 1845 1846 1847 1848 | */ #define NUM_STATIC_TOKENS 20 typedef struct Tcl_Parse { const char *commentStart; /* Pointer to # that begins the first of one * or more comments preceding the command. */ | | | | 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 | */ #define NUM_STATIC_TOKENS 20 typedef struct Tcl_Parse { const char *commentStart; /* Pointer to # that begins the first of one * or more comments preceding the command. */ Tcl_Size commentSize; /* Number of bytes in comments (up through * newline character that terminates the last * comment). If there were no comments, this * field is 0. */ const char *commandStart; /* First character in first word of * command. */ Tcl_Size commandSize; /* Number of bytes in command, including first * character of first word, up through the * terminating newline, close bracket, or * semicolon. */ Tcl_Size numWords; /* Total number of words in command. May be * 0. */ Tcl_Token *tokenPtr; /* Pointer to first token representing the * words of the command. Initially points to |
︙ | ︙ | |||
1913 1914 1915 1916 1917 1918 1919 | * into UTF-8. */ Tcl_EncodingConvertProc *fromUtfProc; /* Function to convert from UTF-8 into * external encoding. */ Tcl_FreeProc *freeProc; /* If non-NULL, function to call when this * encoding is deleted. */ | | | 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 | * into UTF-8. */ Tcl_EncodingConvertProc *fromUtfProc; /* Function to convert from UTF-8 into * external encoding. */ Tcl_FreeProc *freeProc; /* If non-NULL, function to call when this * encoding is deleted. */ void *clientData; /* Arbitrary value associated with encoding * type. Passed to conversion functions. */ Tcl_Size nullSize; /* Number of zero bytes that signify * end-of-string in this encoding. This number * is used to determine the source string * length when the srcLen argument is * negative. Must be 1, 2, or 4. */ } Tcl_EncodingType; |
︙ | ︙ | |||
2107 2108 2109 2110 2111 2112 2113 | * argv array. */ void *srcPtr; /* Value to be used in setting dst; usage * depends on type.*/ void *dstPtr; /* Address of value to be modified; usage * depends on type.*/ const char *helpStr; /* Documentation message describing this * option. */ | | | 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 | * argv array. */ void *srcPtr; /* Value to be used in setting dst; usage * depends on type.*/ void *dstPtr; /* Address of value to be modified; usage * depends on type.*/ const char *helpStr; /* Documentation message describing this * option. */ void *clientData; /* Word to pass to function callbacks. */ } Tcl_ArgvInfo; /* * Legal values for the type field of a Tcl_ArgInfo: see the user * documentation for details. */ |
︙ | ︙ | |||
2242 2243 2244 2245 2246 2247 2248 | const char * Tcl_InitStubs(Tcl_Interp *interp, const char *version, int exact, int magic); const char * TclTomMathInitializeStubs(Tcl_Interp *interp, const char *version, int epoch, int revision); const char * TclInitStubTable(const char *version); void * TclStubCall(void *arg); #if defined(_WIN32) | | | > | | | 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 | const char * Tcl_InitStubs(Tcl_Interp *interp, const char *version, int exact, int magic); const char * TclTomMathInitializeStubs(Tcl_Interp *interp, const char *version, int epoch, int revision); const char * TclInitStubTable(const char *version); void * TclStubCall(void *arg); #if defined(_WIN32) TCL_NORETURN void Tcl_ConsolePanic(const char *format, ...); #else # define Tcl_ConsolePanic ((Tcl_PanicProc *)NULL) #endif #ifdef USE_TCL_STUBS # 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_PkgInitStubsCheck(interp, version, \ (exact)|(TCL_MAJOR_VERSION<<8)|(TCL_MINOR_VERSION<<16)) #endif /* * Public functions that are not accessible via the stubs table. * Tcl_GetMemoryInfo is needed for AOLserver. [Bug 1868171] */ #define Tcl_Main(argc, argv, proc) \ Tcl_MainEx(argc, argv, proc, \ ((Tcl_SetPanicProc(Tcl_ConsolePanic), Tcl_CreateInterp()))) EXTERN TCL_NORETURN void Tcl_MainEx(Tcl_Size argc, char **argv, Tcl_AppInitProc *appInitProc, Tcl_Interp *interp); EXTERN const char * Tcl_PkgInitStubsCheck(Tcl_Interp *interp, const char *version, int exact); EXTERN const char * Tcl_InitSubsystems(void); EXTERN void Tcl_GetMemoryInfo(Tcl_DString *dsPtr); EXTERN const char * Tcl_FindExecutable(const char *argv0); EXTERN const char * Tcl_SetPreInitScript(const char *string); EXTERN const char * Tcl_SetPanicProc( Tcl_PanicProc *panicProc); EXTERN void Tcl_StaticLibrary(Tcl_Interp *interp, const char *prefix, Tcl_LibraryInitProc *initProc, Tcl_LibraryInitProc *safeInitProc); #ifndef TCL_NO_DEPRECATED # define Tcl_StaticPackage Tcl_StaticLibrary #endif EXTERN Tcl_ExitProc * Tcl_SetExitProc(Tcl_ExitProc *proc); #ifdef _WIN32 EXTERN const char * TclZipfs_AppHook(int *argc, wchar_t ***argv); #else EXTERN const char *TclZipfs_AppHook(int *argc, char ***argv); #endif #if defined(_WIN32) && defined(UNICODE) #ifndef USE_TCL_STUBS # define Tcl_FindExecutable(arg) ((Tcl_FindExecutable)((const char *)(arg))) #endif |
︙ | ︙ | |||
2404 2405 2406 2407 2408 2409 2410 | * Tcl_DecrRefCount(objPtr); * * This will free the obj if there are no references to the obj. */ # define Tcl_BounceRefCount(objPtr) \ TclBounceRefCount(objPtr, __FILE__, __LINE__) | | > > > > | | | | | | | > > | 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 | * Tcl_DecrRefCount(objPtr); * * This will free the obj if there are no references to the obj. */ # define Tcl_BounceRefCount(objPtr) \ TclBounceRefCount(objPtr, __FILE__, __LINE__) static inline void TclBounceRefCount( Tcl_Obj* objPtr, const char* fn, int line) { if (objPtr) { if ((objPtr)->refCount == 0) { Tcl_DbDecrRefCount(objPtr, fn, line); } } } #else # undef Tcl_IncrRefCount # define Tcl_IncrRefCount(objPtr) \ ((void)++(objPtr)->refCount) /* * Use do/while0 idiom for optimum correctness without compiler warnings. * https://wiki.c2.com/?TrivialDoWhileLoop */ # undef Tcl_DecrRefCount # define Tcl_DecrRefCount(objPtr) \ do { \ Tcl_Obj *_objPtr = (objPtr); \ if (_objPtr->refCount-- <= 1) { \ TclFreeObj(_objPtr); \ } \ } while(0) # undef Tcl_IsShared # define Tcl_IsShared(objPtr) \ ((objPtr)->refCount > 1) /* * Declare that obj will no longer be used or referenced. * This will release the obj if there is no referece count, * otherwise let it be. */ # define Tcl_BounceRefCount(objPtr) \ TclBounceRefCount(objPtr); static inline void TclBounceRefCount( Tcl_Obj* objPtr) { if (objPtr) { if ((objPtr)->refCount == 0) { Tcl_DecrRefCount(objPtr); } } } |
︙ | ︙ | |||
2492 2493 2494 2495 2496 2497 2498 | *---------------------------------------------------------------------------- * Macros for clients to use to access fields of hash entries: */ #define Tcl_GetHashValue(h) ((h)->clientData) #define Tcl_SetHashValue(h, value) ((h)->clientData = (void *)(value)) #define Tcl_GetHashKey(tablePtr, h) \ | | | | | | 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 | *---------------------------------------------------------------------------- * Macros for clients to use to access fields of hash entries: */ #define Tcl_GetHashValue(h) ((h)->clientData) #define Tcl_SetHashValue(h, value) ((h)->clientData = (void *)(value)) #define Tcl_GetHashKey(tablePtr, h) \ ((void *) (((tablePtr)->keyType == TCL_ONE_WORD_KEYS || \ (tablePtr)->keyType == TCL_CUSTOM_PTR_KEYS) \ ? (h)->key.oneWordValue \ : (h)->key.string)) /* * Macros to use for clients to use to invoke find and create functions for * hash tables: */ #undef Tcl_FindHashEntry |
︙ | ︙ |
Changes to generic/tclAlloc.c.
︙ | ︙ | |||
43 44 45 46 47 48 49 | * enabled then a second word holds the size of the requested block, less 1, * rounded up to a multiple of sizeof(RMAGIC). The order of elements is * critical: ov.magic must overlay the low order bits of ov.next, and ov.magic * can not be a valid ov.next bit pattern. */ union overhead { | | | > | | | | | | < | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | * enabled then a second word holds the size of the requested block, less 1, * rounded up to a multiple of sizeof(RMAGIC). The order of elements is * critical: ov.magic must overlay the low order bits of ov.next, and ov.magic * can not be a valid ov.next bit pattern. */ union overhead { union overhead *next; /* when free */ unsigned char padding[TCL_ALLOCALIGN]; /* align struct to TCL_ALLOCALIGN bytes */ struct { unsigned char magic0; /* magic number */ unsigned char index; /* bucket # */ unsigned char unused; /* unused */ unsigned char magic1; /* other magic number */ #ifndef NDEBUG unsigned short rmagic; /* range magic number */ size_t size; /* actual block size */ unsigned short unused2; /* padding to 8-byte align */ #endif } ovu; #define overMagic0 ovu.magic0 #define overMagic1 ovu.magic1 #define bucketIndex ovu.index #define rangeCheckMagic ovu.rmagic #define realBlockSize ovu.size }; #define MAGIC 0xEF /* magic # on accounting info */ #define RMAGIC 0x5555 /* magic # on range info */ #ifndef NDEBUG #define RSLOP sizeof(unsigned short) #else |
︙ | ︙ | |||
88 89 90 91 92 93 94 | /* * nextf[i] is the pointer to the next free block of size 2^(i+3). The * smallest allocatable block is MINBLOCK bytes. The overhead information * precedes the data area returned to the user. */ | > | | 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | /* * nextf[i] is the pointer to the next free block of size 2^(i+3). The * smallest allocatable block is MINBLOCK bytes. The overhead information * precedes the data area returned to the user. */ #define MINBLOCK \ ((sizeof(union overhead) + (TCL_ALLOCALIGN-1)) & ~(TCL_ALLOCALIGN-1)) #define NBUCKETS (13 - (MINBLOCK >> 4)) #define MAXMALLOC ((size_t)1 << (NBUCKETS+2)) static union overhead *nextf[NBUCKETS]; /* * The following structure is used to keep track of all system memory * currently owned by Tcl. When finalizing, all this memory will be returned |
︙ | ︙ | |||
247 248 249 250 251 252 253 | * None. * *---------------------------------------------------------------------- */ void * TclpAlloc( | | | 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 | * None. * *---------------------------------------------------------------------- */ void * TclpAlloc( size_t numBytes) /* Number of bytes to allocate. */ { union overhead *overPtr; size_t bucket; size_t amount; struct block *bigBlockPtr = NULL; if (!allocInit) { |
︙ | ︙ | |||
381 382 383 384 385 386 387 | * Attempts to get more memory from the system. * *---------------------------------------------------------------------- */ static void MoreCore( | | | | 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 | * Attempts to get more memory from the system. * *---------------------------------------------------------------------- */ static void MoreCore( size_t bucket) /* What bucket to allocate to. */ { union overhead *overPtr; size_t size; /* size of desired block */ size_t amount; /* amount to allocate */ size_t numBlocks; /* how many blocks we get */ struct block *blockPtr; /* * sbrk_size <= 0 only for big, FLUFFY, requests (about 2^30 bytes on a * VAX, I think) or for a negative arg. |
︙ | ︙ | |||
507 508 509 510 511 512 513 | * *---------------------------------------------------------------------- */ void * TclpRealloc( void *oldPtr, /* Pointer to alloc'ed block. */ | | | 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 | * *---------------------------------------------------------------------- */ void * TclpRealloc( void *oldPtr, /* Pointer to alloc'ed block. */ size_t numBytes) /* New size of memory. */ { int i; union overhead *overPtr; struct block *bigBlockPtr; int expensive; size_t maxSize; |
︙ | ︙ | |||
739 740 741 742 743 744 745 | * *---------------------------------------------------------------------- */ void * TclpRealloc( void *oldPtr, /* Pointer to alloced block. */ | | | 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 | * *---------------------------------------------------------------------- */ void * TclpRealloc( void *oldPtr, /* Pointer to alloced block. */ size_t numBytes) /* New size of memory. */ { return realloc(oldPtr, numBytes); } #endif /* !USE_TCLALLOC */ #else TCL_MAC_EMPTY_FILE(generic_tclAlloc_c) |
︙ | ︙ |
Changes to generic/tclBasic.c.
︙ | ︙ | |||
59 60 61 62 63 64 65 | * double layout and a 32-bit 'int' type). */ #define TCL_FPCLASSIFY_MODE 2 #endif /* !fpclassify */ /* actually there is no fallback to builtin fpclassify */ #endif /* !TCL_FPCLASSIFY_MODE */ | < | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | * double layout and a 32-bit 'int' type). */ #define TCL_FPCLASSIFY_MODE 2 #endif /* !fpclassify */ /* actually there is no fallback to builtin fpclassify */ #endif /* !TCL_FPCLASSIFY_MODE */ /* * Bug 7371b6270b: to check C call stack depth, prefer an approach which is * compatible with AddressSanitizer (ASan) use-after-return detection. */ #if defined(_MSC_VER) && defined(HAVE_INTRIN_H) #include <intrin.h> /* for _AddressOfReturnAddress() */ |
︙ | ︙ | |||
81 82 83 84 85 86 87 | #define __has_builtin(x) 0 /* for non-clang compilers */ #endif void * TclGetCStackPtr(void) { #if defined( __GNUC__ ) || __has_builtin(__builtin_frame_address) | | | | | | | | | | | 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | #define __has_builtin(x) 0 /* for non-clang compilers */ #endif void * TclGetCStackPtr(void) { #if defined( __GNUC__ ) || __has_builtin(__builtin_frame_address) return __builtin_frame_address(0); #elif defined(_MSC_VER) && defined(HAVE_INTRIN_H) return _AddressOfReturnAddress(); #else ptrdiff_t unused = 0; /* * LLVM recommends using volatile: * https://github.com/llvm/llvm-project/blob/llvmorg-10.0.0-rc1/clang/lib/Basic/Stack.cpp#L31 */ ptrdiff_t *volatile stackLevel = &unused; return (void *)stackLevel; #endif } #define INTERP_STACK_INITIAL_SIZE 2000 #define CORO_STACK_INITIAL_SIZE 200 /* |
︙ | ︙ | |||
164 165 166 167 168 169 170 | iPtr->cmdFramePtr = (context).cmdFramePtr; \ iPtr->lineLABCPtr = (context).lineLABCPtr /* * Static functions in this file: */ | | | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | iPtr->cmdFramePtr = (context).cmdFramePtr; \ iPtr->lineLABCPtr = (context).lineLABCPtr /* * Static functions in this file: */ static Tcl_ObjCmdProc2 BadEnsembleSubcommand; static char * CallCommandTraces(Interp *iPtr, Command *cmdPtr, const char *oldName, const char *newName, int flags); static int CancelEvalProc(void *clientData, Tcl_Interp *interp, int code); static int CheckDoubleResult(Tcl_Interp *interp, double dResult); static void DeleteCoroutine(void *clientData); |
︙ | ︙ | |||
189 190 191 192 193 194 195 | static Tcl_ObjCmdProc2 ExprBinaryFunc; static Tcl_ObjCmdProc2 ExprBoolFunc; static Tcl_ObjCmdProc2 ExprCeilFunc; static Tcl_ObjCmdProc2 ExprDoubleFunc; static Tcl_ObjCmdProc2 ExprFloorFunc; static Tcl_ObjCmdProc2 ExprIntFunc; static Tcl_ObjCmdProc2 ExprIsqrtFunc; | | | | | | | | | 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | static Tcl_ObjCmdProc2 ExprBinaryFunc; static Tcl_ObjCmdProc2 ExprBoolFunc; static Tcl_ObjCmdProc2 ExprCeilFunc; static Tcl_ObjCmdProc2 ExprDoubleFunc; static Tcl_ObjCmdProc2 ExprFloorFunc; static Tcl_ObjCmdProc2 ExprIntFunc; static Tcl_ObjCmdProc2 ExprIsqrtFunc; static Tcl_ObjCmdProc2 ExprIsFiniteFunc; static Tcl_ObjCmdProc2 ExprIsInfinityFunc; static Tcl_ObjCmdProc2 ExprIsNaNFunc; static Tcl_ObjCmdProc2 ExprIsNormalFunc; static Tcl_ObjCmdProc2 ExprIsSubnormalFunc; static Tcl_ObjCmdProc2 ExprIsUnorderedFunc; static Tcl_ObjCmdProc2 ExprMaxFunc; static Tcl_ObjCmdProc2 ExprMinFunc; static Tcl_ObjCmdProc2 ExprRandFunc; static Tcl_ObjCmdProc2 ExprRoundFunc; static Tcl_ObjCmdProc2 ExprSqrtFunc; static Tcl_ObjCmdProc2 ExprSrandFunc; static Tcl_ObjCmdProc2 ExprUnaryFunc; static Tcl_ObjCmdProc2 ExprWideFunc; static Tcl_ObjCmdProc2 FloatClassifyObjCmd; static void MathFuncWrongNumArgs(Tcl_Interp *interp, int expected, int actual, Tcl_Obj *const *objv); static Tcl_NRPostProc NRCoroutineCallerCallback; static Tcl_NRPostProc NRCoroutineExitCallback; static Tcl_NRPostProc NRCommand; static void ProcessUnexpectedResult(Tcl_Interp *interp, |
︙ | ︙ | |||
249 250 251 252 253 254 255 | MODULE_SCOPE const TclStubs tclStubs; /* * Magical counts for the number of arguments accepted by a coroutine command * after particular kinds of [yield]. */ | | | | | | | | | | | | | | | | | | | | | 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 | MODULE_SCOPE const TclStubs tclStubs; /* * Magical counts for the number of arguments accepted by a coroutine command * after particular kinds of [yield]. */ #define CORO_ACTIVATE_YIELD NULL #define CORO_ACTIVATE_YIELDM INT2PTR(1) #define COROUTINE_ARGUMENTS_SINGLE_OPTIONAL (-1) #define COROUTINE_ARGUMENTS_ARBITRARY (-2) /* * The following structure define the commands in the Tcl core. */ typedef struct { const char *name; /* Name of object-based command. */ Tcl_ObjCmdProc2 *objProc; /* Object-based function for command. */ CompileProc *compileProc; /* Function called to compile command. */ Tcl_ObjCmdProc2 *nreProc; /* NR-based function for command */ int flags; /* Various flag bits, as defined below. */ } CmdInfo; #define CMD_IS_SAFE 1 /* Whether this command is part of the set of * commands present by default in a safe * interpreter. */ /* CMD_COMPILES_EXPANDED - Whether the compiler for this command can handle * expansion for itself rather than needing the generic layer to take care of * it for it. Defined in tclInt.h. */ /* * The following struct states that the command it talks about (a subcommand * of one of Tcl's built-in ensembles) is unsafe and must be hidden when an * interpreter is made safe. (TclHideUnsafeCommands accesses an array of these * structs.) Alas, we can't sensibly just store the information directly in * the commands. */ typedef struct { const char *ensembleNsName; /* The ensemble's name within ::tcl. NULL for * the end of the list of commands to hide. */ const char *commandName; /* The name of the command within the * ensemble. If this is NULL, we want to also * make the overall command be hidden, an ugly * hack because it is expected by security * policies in the wild. */ } UnsafeEnsembleInfo; /* * The built-in commands, and the functions that implement them: */ static const CmdInfo builtInCmds[] = { /* * Commands in the generic core. */ {"append", Tcl_AppendObjCmd, TclCompileAppendCmd, NULL, CMD_IS_SAFE}, {"apply", Tcl_ApplyObjCmd, NULL, TclNRApplyObjCmd, CMD_IS_SAFE}, {"break", Tcl_BreakObjCmd, TclCompileBreakCmd, NULL, CMD_IS_SAFE}, {"catch", Tcl_CatchObjCmd, TclCompileCatchCmd, TclNRCatchObjCmd, CMD_IS_SAFE}, {"concat", Tcl_ConcatObjCmd, TclCompileConcatCmd, NULL, CMD_IS_SAFE}, {"const", Tcl_ConstObjCmd, TclCompileConstCmd, NULL, CMD_IS_SAFE}, {"continue", Tcl_ContinueObjCmd, TclCompileContinueCmd, NULL, CMD_IS_SAFE}, {"coroinject", NULL, NULL, TclNRCoroInjectObjCmd, CMD_IS_SAFE}, {"coroprobe", NULL, NULL, TclNRCoroProbeObjCmd, CMD_IS_SAFE}, {"coroutine", NULL, NULL, TclNRCoroutineObjCmd, CMD_IS_SAFE}, {"error", Tcl_ErrorObjCmd, TclCompileErrorCmd, NULL, CMD_IS_SAFE}, {"eval", Tcl_EvalObjCmd, NULL, TclNREvalObjCmd, CMD_IS_SAFE}, {"expr", Tcl_ExprObjCmd, TclCompileExprCmd, TclNRExprObjCmd, CMD_IS_SAFE}, {"for", Tcl_ForObjCmd, TclCompileForCmd, TclNRForObjCmd, CMD_IS_SAFE}, {"foreach", Tcl_ForeachObjCmd, TclCompileForeachCmd, TclNRForeachCmd, CMD_IS_SAFE}, {"format", Tcl_FormatObjCmd, TclCompileFormatCmd, NULL, CMD_IS_SAFE}, {"fpclassify", FloatClassifyObjCmd, NULL, NULL, CMD_IS_SAFE}, {"global", Tcl_GlobalObjCmd, TclCompileGlobalCmd, NULL, CMD_IS_SAFE}, {"if", Tcl_IfObjCmd, TclCompileIfCmd, TclNRIfObjCmd, CMD_IS_SAFE}, {"incr", Tcl_IncrObjCmd, TclCompileIncrCmd, NULL, CMD_IS_SAFE}, {"join", Tcl_JoinObjCmd, NULL, NULL, CMD_IS_SAFE}, {"lappend", Tcl_LappendObjCmd, TclCompileLappendCmd, NULL, CMD_IS_SAFE}, {"lassign", Tcl_LassignObjCmd, TclCompileLassignCmd, NULL, CMD_IS_SAFE}, {"ledit", Tcl_LeditObjCmd, NULL, NULL, CMD_IS_SAFE}, {"lindex", Tcl_LindexObjCmd, TclCompileLindexCmd, NULL, CMD_IS_SAFE}, {"linsert", Tcl_LinsertObjCmd, TclCompileLinsertCmd, NULL, CMD_IS_SAFE}, {"list", Tcl_ListObjCmd, TclCompileListCmd, NULL, CMD_IS_SAFE|CMD_COMPILES_EXPANDED}, {"llength", Tcl_LlengthObjCmd, TclCompileLlengthCmd, NULL, CMD_IS_SAFE}, {"lmap", Tcl_LmapObjCmd, TclCompileLmapCmd, TclNRLmapCmd, CMD_IS_SAFE}, {"lpop", Tcl_LpopObjCmd, NULL, NULL, CMD_IS_SAFE}, {"lrange", Tcl_LrangeObjCmd, TclCompileLrangeCmd, NULL, CMD_IS_SAFE}, {"lremove", Tcl_LremoveObjCmd, NULL, NULL, CMD_IS_SAFE}, {"lrepeat", Tcl_LrepeatObjCmd, NULL, NULL, CMD_IS_SAFE}, {"lreplace", Tcl_LreplaceObjCmd, TclCompileLreplaceCmd, NULL, CMD_IS_SAFE}, {"lreverse", Tcl_LreverseObjCmd, NULL, NULL, CMD_IS_SAFE}, {"lsearch", Tcl_LsearchObjCmd, NULL, NULL, CMD_IS_SAFE}, {"lseq", Tcl_LseqObjCmd, NULL, NULL, CMD_IS_SAFE}, {"lset", Tcl_LsetObjCmd, TclCompileLsetCmd, NULL, CMD_IS_SAFE}, {"lsort", Tcl_LsortObjCmd, NULL, NULL, CMD_IS_SAFE}, {"package", Tcl_PackageObjCmd, NULL, TclNRPackageObjCmd, CMD_IS_SAFE}, {"proc", Tcl_ProcObjCmd, NULL, NULL, CMD_IS_SAFE}, {"regexp", Tcl_RegexpObjCmd, TclCompileRegexpCmd, NULL, CMD_IS_SAFE}, {"regsub", Tcl_RegsubObjCmd, TclCompileRegsubCmd, NULL, CMD_IS_SAFE}, {"rename", Tcl_RenameObjCmd, NULL, NULL, CMD_IS_SAFE}, |
︙ | ︙ | |||
465 466 467 468 469 470 471 472 473 474 475 | {NULL, NULL} }; /* * Math functions. All are safe. */ typedef struct { const char *name; /* Name of the function. The full name is * "::tcl::mathfunc::<name>". */ Tcl_ObjCmdProc2 *objCmdProc; /* Function that evaluates the function */ | > > > > | | | | | | | | | | | | | | | | | 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 | {NULL, NULL} }; /* * Math functions. All are safe. */ typedef double (BuiltinUnaryFunc)(double x); typedef double (BuiltinBinaryFunc)(double x, double y); #define BINARY_TYPECAST(fn) \ (BuiltinUnaryFunc *)(void *)(BuiltinBinaryFunc *) fn typedef struct { const char *name; /* Name of the function. The full name is * "::tcl::mathfunc::<name>". */ Tcl_ObjCmdProc2 *objCmdProc; /* Function that evaluates the function */ BuiltinUnaryFunc *fn; /* Real function pointer */ } BuiltinFuncDef; static const BuiltinFuncDef BuiltinFuncTable[] = { { "abs", ExprAbsFunc, NULL }, { "acos", ExprUnaryFunc, acos }, { "asin", ExprUnaryFunc, asin }, { "atan", ExprUnaryFunc, atan }, { "atan2", ExprBinaryFunc, BINARY_TYPECAST(atan2) }, { "bool", ExprBoolFunc, NULL }, { "ceil", ExprCeilFunc, NULL }, { "cos", ExprUnaryFunc, cos }, { "cosh", ExprUnaryFunc, cosh }, { "double", ExprDoubleFunc, NULL }, { "entier", ExprIntFunc, NULL }, { "exp", ExprUnaryFunc, exp }, { "floor", ExprFloorFunc, NULL }, { "fmod", ExprBinaryFunc, BINARY_TYPECAST(fmod) }, { "hypot", ExprBinaryFunc, BINARY_TYPECAST(hypot) }, { "int", ExprIntFunc, NULL }, { "isfinite", ExprIsFiniteFunc, NULL }, { "isinf", ExprIsInfinityFunc, NULL }, { "isnan", ExprIsNaNFunc, NULL }, { "isnormal", ExprIsNormalFunc, NULL }, { "isqrt", ExprIsqrtFunc, NULL }, { "issubnormal", ExprIsSubnormalFunc, NULL, }, { "isunordered", ExprIsUnorderedFunc, NULL, }, { "log", ExprUnaryFunc, log }, { "log10", ExprUnaryFunc, log10 }, { "max", ExprMaxFunc, NULL }, { "min", ExprMinFunc, NULL }, { "pow", ExprBinaryFunc, BINARY_TYPECAST(pow) }, { "rand", ExprRandFunc, NULL }, { "round", ExprRoundFunc, NULL }, { "sin", ExprUnaryFunc, sin }, { "sinh", ExprUnaryFunc, sinh }, { "sqrt", ExprSqrtFunc, NULL }, { "srand", ExprSrandFunc, NULL }, { "tan", ExprUnaryFunc, tan }, { "tanh", ExprUnaryFunc, tanh }, { "wide", ExprWideFunc, NULL }, { NULL, NULL, NULL } }; /* * TIP#174's math operators. All are safe. |
︙ | ︙ | |||
614 615 616 617 618 619 620 | Tcl_DeleteHashTable(&cancelTable); cancelTableInitialized = 0; } Tcl_MutexUnlock(&cancelLock); Tcl_MutexLock(&commandTypeLock); if (commandTypeInit) { | | | | 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 | Tcl_DeleteHashTable(&cancelTable); cancelTableInitialized = 0; } Tcl_MutexUnlock(&cancelLock); Tcl_MutexLock(&commandTypeLock); if (commandTypeInit) { Tcl_DeleteHashTable(&commandTypeTable); commandTypeInit = 0; } Tcl_MutexUnlock(&commandTypeLock); } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
643 644 645 646 647 648 649 650 651 652 653 | static int buildInfoObjCmd2( void *clientData, Tcl_Interp *interp, /* Current interpreter. */ Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { if (objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "?option?"); return TCL_ERROR; } | > > > > > > > > > > > > > > > | > > > | | < < < | < < | | | > > > | | | | | | > | | > > | | | | | | | | < | < | | | | | > | < | < > | > > > | | | > | < < | | | | | | > > > > > > > | < > > > | > > | > > > > | < | < < < < < < < | | | 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 | static int buildInfoObjCmd2( void *clientData, Tcl_Interp *interp, /* Current interpreter. */ Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { const char *buildData = (const char *) clientData; char buf[80]; const char *arg, *p, *q; Tcl_Size len; int idx; static const char *identifiers[] = { "commit", "compiler", "patchlevel", "version", NULL }; enum Identifiers { ID_COMMIT, ID_COMPILER, ID_PATCHLEVEL, ID_VERSION, ID_OTHER }; if (objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "?option?"); return TCL_ERROR; } else if (objc < 2) { Tcl_SetObjResult(interp, Tcl_NewStringObj(buildData, TCL_INDEX_NONE)); return TCL_OK; } /* * Query for a specific piece of build info */ if (Tcl_GetIndexFromObj(NULL, objv[1], identifiers, NULL, TCL_EXACT, &idx) != TCL_OK) { idx = ID_OTHER; } switch (idx) { case ID_PATCHLEVEL: if ((p = strchr(buildData, '+')) != NULL) { memcpy(buf, buildData, p - buildData); buf[p - buildData] = '\0'; Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, TCL_INDEX_NONE)); } return TCL_OK; case ID_VERSION: if ((p = strchr(buildData, '.')) != NULL) { const char *r = strchr(p++, '+'); q = strchr(p, '.'); p = (q < r) ? q : r; } if (p != NULL) { memcpy(buf, buildData, p - buildData); buf[p - buildData] = '\0'; Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, TCL_INDEX_NONE)); } return TCL_OK; case ID_COMMIT: if ((p = strchr(buildData, '+')) != NULL) { if ((q = strchr(p++, '.')) != NULL) { memcpy(buf, p, q - p); buf[q - p] = '\0'; Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, TCL_INDEX_NONE)); } else { Tcl_SetObjResult(interp, Tcl_NewStringObj(p, TCL_INDEX_NONE)); } } return TCL_OK; case ID_COMPILER: for (p = strchr(buildData, '.'); p++; p = strchr(p, '.')) { /* * Does the word begin with one of the standard prefixes? */ if (!strncmp(p, "clang-", 6) || !strncmp(p, "gcc-", 4) || !strncmp(p, "icc-", 4) || !strncmp(p, "msvc-", 5)) { if ((q = strchr(p, '.')) != NULL) { memcpy(buf, p, q - p); buf[q - p] = '\0'; Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, TCL_INDEX_NONE)); } else { Tcl_SetObjResult(interp, Tcl_NewStringObj(p, TCL_INDEX_NONE)); } return TCL_OK; } } break; default: /* Boolean test for other identifiers' presence */ arg = TclGetStringFromObj(objv[1], &len); for (p = strchr(buildData, '.'); p++; p = strchr(p, '.')) { if (!strncmp(p, arg, len) && ((p[len] == '.') || (p[len] == '-') || (p[len] == '\0'))) { if (p[len] == '-') { p += len; q = strchr(++p, '.'); if (!q) { q = p + strlen(p); } memcpy(buf, p, q - p); buf[q - p] = '\0'; Tcl_SetObjResult(interp, Tcl_NewStringObj(buf, TCL_INDEX_NONE)); } else { Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1)); } return TCL_OK; } } } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0)); return TCL_OK; } #ifndef TCL_NO_DEPRECATED static int buildInfoObjCmd( void *clientData, Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { return buildInfoObjCmd2(clientData, interp, objc, objv); } #endif /* *---------------------------------------------------------------------- * * Tcl_CreateInterp -- |
︙ | ︙ | |||
806 807 808 809 810 811 812 | cancelTableInitialized = 1; } Tcl_MutexUnlock(&cancelLock); } if (commandTypeInit == 0) { | | | | | | | | | | | | 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 | cancelTableInitialized = 1; } Tcl_MutexUnlock(&cancelLock); } if (commandTypeInit == 0) { TclRegisterCommandTypeName(TclObjInterpProc2, "proc"); TclRegisterCommandTypeName(TclEnsembleImplementationCmd, "ensemble"); TclRegisterCommandTypeName(TclAliasObjCmd, "alias"); TclRegisterCommandTypeName(TclLocalAliasObjCmd, "alias"); TclRegisterCommandTypeName(TclChildObjCmd, "interp"); TclRegisterCommandTypeName(TclInvokeImportedCmd, "import"); TclRegisterCommandTypeName(TclOOPublicObjectCmd, "object"); TclRegisterCommandTypeName(TclOOPrivateObjectCmd, "privateObject"); TclRegisterCommandTypeName(TclOOMyClassObjCmd, "privateClass"); TclRegisterCommandTypeName(TclNRInterpCoroutine, "coroutine"); } /* * Initialize support for namespaces and create the global namespace * (whose name is ""; an alias is "::"). This also initializes the Tcl * object type table and other object management code. */ |
︙ | ︙ | |||
928 929 930 931 932 933 934 | iPtr->threadId = Tcl_GetCurrentThread(); /* TIP #378 */ #ifdef TCL_INTERP_DEBUG_FRAME iPtr->flags |= INTERP_DEBUG_FRAME; #else if (getenv("TCL_INTERP_DEBUG_FRAME") != NULL) { | | | 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 | iPtr->threadId = Tcl_GetCurrentThread(); /* TIP #378 */ #ifdef TCL_INTERP_DEBUG_FRAME iPtr->flags |= INTERP_DEBUG_FRAME; #else if (getenv("TCL_INTERP_DEBUG_FRAME") != NULL) { iPtr->flags |= INTERP_DEBUG_FRAME; } #endif /* * Initialise the tables for variable traces and searches *before* * creating the global ns - so that the trace on errorInfo can be * recorded. |
︙ | ︙ | |||
1085 1086 1087 1088 1089 1090 1091 | cmdPtr->proc = NULL; cmdPtr->clientData = cmdPtr; cmdPtr->objProc2 = cmdInfoPtr->objProc; cmdPtr->objClientData2 = NULL; cmdPtr->deleteProc = NULL; cmdPtr->deleteData = NULL; cmdPtr->flags = 0; | | | | | 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 | cmdPtr->proc = NULL; cmdPtr->clientData = cmdPtr; cmdPtr->objProc2 = cmdInfoPtr->objProc; cmdPtr->objClientData2 = NULL; cmdPtr->deleteProc = NULL; cmdPtr->deleteData = NULL; cmdPtr->flags = 0; if (cmdInfoPtr->flags & CMD_COMPILES_EXPANDED) { cmdPtr->flags |= CMD_COMPILES_EXPANDED; } cmdPtr->importRefPtr = NULL; cmdPtr->tracePtr = NULL; cmdPtr->nreProc2 = cmdInfoPtr->nreProc; Tcl_SetHashValue(hPtr, cmdPtr); } } |
︙ | ︙ | |||
1147 1148 1149 1150 1151 1152 1153 | Tcl_CreateObjCommand2(interp, "::tcl::unsupported::getbytecode", Tcl_DisassembleObjCmd, INT2PTR(1), NULL); Tcl_CreateObjCommand2(interp, "::tcl::unsupported::representation", Tcl_RepresentationCmd, NULL, NULL); /* Adding the bytecode assembler command */ cmdPtr = (Command *) Tcl_NRCreateCommand2(interp, | | | | < | 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 | Tcl_CreateObjCommand2(interp, "::tcl::unsupported::getbytecode", Tcl_DisassembleObjCmd, INT2PTR(1), NULL); Tcl_CreateObjCommand2(interp, "::tcl::unsupported::representation", Tcl_RepresentationCmd, NULL, NULL); /* Adding the bytecode assembler command */ cmdPtr = (Command *) Tcl_NRCreateCommand2(interp, "::tcl::unsupported::assemble", Tcl_AssembleObjCmd, TclNRAssembleObjCmd, NULL, NULL); cmdPtr->compileProc = &TclCompileAssembleCmd; /* Coroutine monkeybusiness */ Tcl_NRCreateCommand2(interp, "::tcl::unsupported::inject", NULL, NRInjectObjCmd, NULL, NULL); Tcl_CreateObjCommand2(interp, "::tcl::unsupported::corotype", CoroTypeObjCmd, NULL, NULL); /* Export unsupported commands */ nsPtr = Tcl_FindNamespace(interp, "::tcl::unsupported", NULL, 0); if (nsPtr) { Tcl_Export(interp, nsPtr, "*", 1); } #ifdef USE_DTRACE /* * Register the tcl::dtrace command. */ Tcl_CreateObjCommand2(interp, "::tcl::dtrace", DTraceObjCmd, NULL, NULL); |
︙ | ︙ | |||
1184 1185 1186 1187 1188 1189 1190 | if (nsPtr == NULL) { Tcl_Panic("Can't create math function namespace"); } #define MATH_FUNC_PREFIX_LEN 17 /* == strlen("::tcl::mathfunc::") */ memcpy(mathFuncName, "::tcl::mathfunc::", MATH_FUNC_PREFIX_LEN); for (builtinFuncPtr = BuiltinFuncTable; builtinFuncPtr->name != NULL; builtinFuncPtr++) { | | | 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 | if (nsPtr == NULL) { Tcl_Panic("Can't create math function namespace"); } #define MATH_FUNC_PREFIX_LEN 17 /* == strlen("::tcl::mathfunc::") */ memcpy(mathFuncName, "::tcl::mathfunc::", MATH_FUNC_PREFIX_LEN); for (builtinFuncPtr = BuiltinFuncTable; builtinFuncPtr->name != NULL; builtinFuncPtr++) { strcpy(mathFuncName + MATH_FUNC_PREFIX_LEN, builtinFuncPtr->name); Tcl_CreateObjCommand2(interp, mathFuncName, builtinFuncPtr->objCmdProc, (void *)builtinFuncPtr->fn, NULL); Tcl_Export(interp, nsPtr, builtinFuncPtr->name, 0); } /* * Register the mathematical "operator" commands. [TIP #174] |
︙ | ︙ | |||
1323 1324 1325 1326 1327 1328 1329 | } /* * --------------------------------------------------------------------- * * TclRegisterCommandTypeName, TclGetCommandTypeName -- * | | | | | | | | | | | | | | | | | | | | | | 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 | } /* * --------------------------------------------------------------------- * * TclRegisterCommandTypeName, TclGetCommandTypeName -- * * Command type registration and lookup mechanism. Everything is keyed by * the Tcl_ObjCmdProc for the command, and that is used as the *key* into * the hash table that maps to constant strings that are names. (It is * recommended that those names be ASCII.) * * --------------------------------------------------------------------- */ void TclRegisterCommandTypeName( Tcl_ObjCmdProc2 *implementationProc, const char *nameStr) { Tcl_HashEntry *hPtr; Tcl_MutexLock(&commandTypeLock); if (commandTypeInit == 0) { Tcl_InitHashTable(&commandTypeTable, TCL_ONE_WORD_KEYS); commandTypeInit = 1; } if (nameStr != NULL) { int isNew; hPtr = Tcl_CreateHashEntry(&commandTypeTable, implementationProc, &isNew); Tcl_SetHashValue(hPtr, (void *) nameStr); } else { hPtr = Tcl_FindHashEntry(&commandTypeTable, implementationProc); if (hPtr != NULL) { Tcl_DeleteHashEntry(hPtr); } } Tcl_MutexUnlock(&commandTypeLock); } const char * TclGetCommandTypeName( Tcl_Command command) { Command *cmdPtr = (Command *) command; Tcl_ObjCmdProc2 *procPtr = cmdPtr->objProc2; const char *name = "native"; if (procPtr == NULL) { procPtr = cmdPtr->nreProc2; } Tcl_MutexLock(&commandTypeLock); if (commandTypeInit) { Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&commandTypeTable, procPtr); if (hPtr && Tcl_GetHashValue(hPtr)) { name = (const char *) Tcl_GetHashValue(hPtr); } } Tcl_MutexUnlock(&commandTypeLock); return name; } /* |
︙ | ︙ | |||
1416 1417 1418 1419 1420 1421 1422 | for (cmdInfoPtr = builtInCmds; cmdInfoPtr->name != NULL; cmdInfoPtr++) { if (!(cmdInfoPtr->flags & CMD_IS_SAFE)) { Tcl_HideCommand(interp, cmdInfoPtr->name, cmdInfoPtr->name); } } for (unsafePtr = unsafeEnsembleCommands; | | | | | | | | | | > > | | | | | | | | | | | | | | | | | | | | | | | | 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 | for (cmdInfoPtr = builtInCmds; cmdInfoPtr->name != NULL; cmdInfoPtr++) { if (!(cmdInfoPtr->flags & CMD_IS_SAFE)) { Tcl_HideCommand(interp, cmdInfoPtr->name, cmdInfoPtr->name); } } for (unsafePtr = unsafeEnsembleCommands; unsafePtr->ensembleNsName; unsafePtr++) { if (unsafePtr->commandName) { /* * Hide an ensemble subcommand. */ Tcl_Obj *cmdName = Tcl_ObjPrintf("::tcl::%s::%s", unsafePtr->ensembleNsName, unsafePtr->commandName); Tcl_Obj *hideName = Tcl_ObjPrintf("tcl:%s:%s", unsafePtr->ensembleNsName, unsafePtr->commandName); #define INTERIM_HACK_NAME "___tmp" if (TclRenameCommand(interp, TclGetString(cmdName), INTERIM_HACK_NAME) != TCL_OK || Tcl_HideCommand(interp, INTERIM_HACK_NAME, TclGetString(hideName)) != TCL_OK) { Tcl_Panic("problem making '%s %s' safe: %s", unsafePtr->ensembleNsName, unsafePtr->commandName, Tcl_GetStringResult(interp)); } Tcl_CreateObjCommand2(interp, TclGetString(cmdName), BadEnsembleSubcommand, (void *)unsafePtr, NULL); TclDecrRefCount(cmdName); TclDecrRefCount(hideName); } else { /* * Hide an ensemble main command (for compatibility). */ if (Tcl_HideCommand(interp, unsafePtr->ensembleNsName, unsafePtr->ensembleNsName) != TCL_OK) { Tcl_Panic("problem making '%s' safe: %s", unsafePtr->ensembleNsName, Tcl_GetStringResult(interp)); } } } return TCL_OK; } /* *---------------------------------------------------------------------- |
︙ | ︙ | |||
1484 1485 1486 1487 1488 1489 1490 | Tcl_Interp *interp, TCL_UNUSED(Tcl_Size) /*objc*/, TCL_UNUSED(Tcl_Obj *const *) /* objv */) { const UnsafeEnsembleInfo *infoPtr = (const UnsafeEnsembleInfo *)clientData; Tcl_SetObjResult(interp, Tcl_ObjPrintf( | | | | 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 | Tcl_Interp *interp, TCL_UNUSED(Tcl_Size) /*objc*/, TCL_UNUSED(Tcl_Obj *const *) /* objv */) { const UnsafeEnsembleInfo *infoPtr = (const UnsafeEnsembleInfo *)clientData; Tcl_SetObjResult(interp, Tcl_ObjPrintf( "not allowed to invoke subcommand %s of %s", infoPtr->commandName, infoPtr->ensembleNsName)); Tcl_SetErrorCode(interp, "TCL", "SAFE", "SUBCOMMAND", (char *)NULL); return TCL_ERROR; } /* *-------------------------------------------------------------- * |
︙ | ︙ | |||
1516 1517 1518 1519 1520 1521 1522 | */ void Tcl_CallWhenDeleted( Tcl_Interp *interp, /* Interpreter to watch. */ Tcl_InterpDeleteProc *proc, /* Function to call when interpreter is about * to be deleted. */ | | | | | 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 | */ void Tcl_CallWhenDeleted( Tcl_Interp *interp, /* Interpreter to watch. */ Tcl_InterpDeleteProc *proc, /* Function to call when interpreter is about * to be deleted. */ void *clientData) /* One-word value to pass to proc. */ { Interp *iPtr = (Interp *) interp; static Tcl_ThreadDataKey assocDataCounterKey; int *assocDataCounterPtr = (int *) Tcl_GetThreadData(&assocDataCounterKey, sizeof(int)); int isNew; char buffer[32 + TCL_INTEGER_SPACE]; AssocData *dPtr = (AssocData *)Tcl_Alloc(sizeof(AssocData)); Tcl_HashEntry *hPtr; snprintf(buffer, sizeof(buffer), "Assoc Data Key #%d", *assocDataCounterPtr); (*assocDataCounterPtr)++; |
︙ | ︙ | |||
1564 1565 1566 1567 1568 1569 1570 | */ void Tcl_DontCallWhenDeleted( Tcl_Interp *interp, /* Interpreter to watch. */ Tcl_InterpDeleteProc *proc, /* Function to call when interpreter is about * to be deleted. */ | | | 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 | */ void Tcl_DontCallWhenDeleted( Tcl_Interp *interp, /* Interpreter to watch. */ Tcl_InterpDeleteProc *proc, /* Function to call when interpreter is about * to be deleted. */ void *clientData) /* One-word value to pass to proc. */ { Interp *iPtr = (Interp *) interp; Tcl_HashTable *hTablePtr; Tcl_HashSearch hSearch; Tcl_HashEntry *hPtr; AssocData *dPtr; |
︙ | ︙ | |||
1612 1613 1614 1615 1616 1617 1618 | void Tcl_SetAssocData( Tcl_Interp *interp, /* Interpreter to associate with. */ const char *name, /* Name for association. */ Tcl_InterpDeleteProc *proc, /* Proc to call when interpreter is about to * be deleted. */ | | | 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 | void Tcl_SetAssocData( Tcl_Interp *interp, /* Interpreter to associate with. */ const char *name, /* Name for association. */ Tcl_InterpDeleteProc *proc, /* Proc to call when interpreter is about to * be deleted. */ void *clientData) /* One-word value to pass to proc. */ { Interp *iPtr = (Interp *) interp; AssocData *dPtr; Tcl_HashEntry *hPtr; int isNew; if (iPtr->assocData == NULL) { |
︙ | ︙ | |||
1929 1930 1931 1932 1933 1934 1935 | for (; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { Tcl_DeleteCommandFromToken(interp, (Tcl_Command)Tcl_GetHashValue(hPtr)); } Tcl_DeleteHashTable(hTablePtr); Tcl_Free(hTablePtr); } | < | 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 | for (; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { Tcl_DeleteCommandFromToken(interp, (Tcl_Command)Tcl_GetHashValue(hPtr)); } Tcl_DeleteHashTable(hTablePtr); Tcl_Free(hTablePtr); } if (iPtr->assocData != NULL) { AssocData *dPtr; hTablePtr = iPtr->assocData; /* * Invoke deletion callbacks; note that a callback can create new * callbacks, so we iterate. |
︙ | ︙ | |||
2182 2183 2184 2185 2186 2187 2188 | * the token too. - dl */ if (strstr(hiddenCmdToken, "::") != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot use namespace qualifiers in hidden command" " token (rename)", TCL_INDEX_NONE)); | | | 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 | * the token too. - dl */ if (strstr(hiddenCmdToken, "::") != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot use namespace qualifiers in hidden command" " token (rename)", TCL_INDEX_NONE)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "HIDDENTOKEN", (char *)NULL); return TCL_ERROR; } /* * Find the command to hide. An error is returned if cmdName can't be * found. Look up the command only from the global namespace. Full path of * the command must be given if using namespaces. |
︙ | ︙ | |||
2205 2206 2207 2208 2209 2210 2211 | /* * Check that the command is really in global namespace */ if (cmdPtr->nsPtr != iPtr->globalNsPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( | | | | | 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 | /* * Check that the command is really in global namespace */ if (cmdPtr->nsPtr != iPtr->globalNsPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "can only hide global namespace commands (use rename then hide)", TCL_INDEX_NONE)); Tcl_SetErrorCode(interp, "TCL", "HIDE", "NON_GLOBAL", (char *)NULL); return TCL_ERROR; } /* * Initialize the hidden command table if necessary. */ |
︙ | ︙ | |||
2231 2232 2233 2234 2235 2236 2237 | * hiddenCmdToken if a hidden command with the name hiddenCmdToken already * exists. */ hPtr = Tcl_CreateHashEntry(hiddenCmdTablePtr, hiddenCmdToken, &isNew); if (!isNew) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( | | | | | 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 | * hiddenCmdToken if a hidden command with the name hiddenCmdToken already * exists. */ hPtr = Tcl_CreateHashEntry(hiddenCmdTablePtr, hiddenCmdToken, &isNew); if (!isNew) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "hidden command named \"%s\" already exists", hiddenCmdToken)); Tcl_SetErrorCode(interp, "TCL", "HIDE", "ALREADY_HIDDEN", (char *)NULL); return TCL_ERROR; } /* * NB: This code is currently 'like' a rename to a special separate name * table. Changes here and in TclRenameCommand must be kept in synch until * the common parts are actually factorized out. |
︙ | ︙ | |||
2335 2336 2337 2338 2339 2340 2341 | * Check that we have a regular name for the command (that the user is not * trying to do an expose and a rename (to another namespace) at the same * time). */ if (strstr(cmdName, "::") != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( | | | | | | | | | | | 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 | * Check that we have a regular name for the command (that the user is not * trying to do an expose and a rename (to another namespace) at the same * time). */ if (strstr(cmdName, "::") != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot expose to a namespace (use expose to toplevel, then rename)", TCL_INDEX_NONE)); Tcl_SetErrorCode(interp, "TCL", "EXPOSE", "NON_GLOBAL", (char *)NULL); return TCL_ERROR; } /* * Get the command from the hidden command table: */ hPtr = NULL; hiddenCmdTablePtr = iPtr->hiddenCmdTablePtr; if (hiddenCmdTablePtr != NULL) { hPtr = Tcl_FindHashEntry(hiddenCmdTablePtr, hiddenCmdToken); } if (hPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unknown hidden command \"%s\"", hiddenCmdToken)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "HIDDENTOKEN", hiddenCmdToken, (char *)NULL); return TCL_ERROR; } cmdPtr = (Command *)Tcl_GetHashValue(hPtr); /* * Check that we have a true global namespace command (enforced by * Tcl_HideCommand but let's double check. (If it was not, we would not * really know how to handle it). */ if (cmdPtr->nsPtr != iPtr->globalNsPtr) { /* * This case is theoretically impossible, we might rather Tcl_Panic * than 'nicely' erroring out ? */ Tcl_SetObjResult(interp, Tcl_NewStringObj( "trying to expose a non-global command namespace command", TCL_INDEX_NONE)); return TCL_ERROR; } /* * This is the global table. */ nsPtr = cmdPtr->nsPtr; /* * It is an error to overwrite an existing exposed command as a result of * exposing a previously hidden command. */ hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, cmdName, &isNew); if (!isNew) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "exposed command \"%s\" already exists", cmdName)); Tcl_SetErrorCode(interp, "TCL", "EXPOSE", "COMMAND_EXISTS", (char *)NULL); return TCL_ERROR; } /* * Command resolvers (per-interp, per-namespace) might have resolved to a * command for the given namespace scope with this command not being * registered with the namespace's command table. During BC compilation, |
︙ | ︙ | |||
2489 2490 2491 2492 2493 2494 2495 | Tcl_Interp *interp, /* Token for command interpreter returned by a * previous call to Tcl_CreateInterp. */ const char *cmdName, /* Name of command. If it contains namespace * qualifiers, the new command is put in the * specified namespace; otherwise it is put in * the global namespace. */ Tcl_CmdProc *proc, /* Function to associate with cmdName. */ | | | 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 | Tcl_Interp *interp, /* Token for command interpreter returned by a * previous call to Tcl_CreateInterp. */ const char *cmdName, /* Name of command. If it contains namespace * qualifiers, the new command is put in the * specified namespace; otherwise it is put in * the global namespace. */ Tcl_CmdProc *proc, /* Function to associate with cmdName. */ void *clientData, /* Arbitrary value passed to string proc. */ Tcl_CmdDeleteProc *deleteProc) /* If not NULL, gives a function to call when * this command is deleted. */ { Interp *iPtr = (Interp *) interp; ImportRef *oldRefPtr = NULL; Namespace *nsPtr; |
︙ | ︙ | |||
2520 2521 2522 2523 2524 2525 2526 | * If the command name we seek to create already exists, we need to * delete that first. That can be tricky in the presence of traces. * Loop until we no longer find an existing command in the way, or * until we've deleted one command and that didn't finish the job. */ while (1) { | | | | | | | | | | | | | 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 | * If the command name we seek to create already exists, we need to * delete that first. That can be tricky in the presence of traces. * Loop until we no longer find an existing command in the way, or * until we've deleted one command and that didn't finish the job. */ while (1) { /* * Determine where the command should reside. If its name contains * namespace qualifiers, we put it in the specified namespace; * otherwise, we always put it in the global namespace. */ if (strstr(cmdName, "::") != NULL) { Namespace *dummy1, *dummy2; TclGetNamespaceForQualName(interp, cmdName, NULL, TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1, &dummy2, &tail); if ((nsPtr == NULL) || (tail == NULL)) { return (Tcl_Command) NULL; } } else { nsPtr = iPtr->globalNsPtr; tail = cmdName; } hPtr = Tcl_CreateHashEntry(&nsPtr->cmdTable, tail, &isNew); if (isNew || deleted) { /* * isNew - No conflict with existing command. * deleted - We've already deleted a conflicting command */ break; } /* * An existing command conflicts. Try to delete it... */ cmdPtr = (Command *)Tcl_GetHashValue(hPtr); /* * Be careful to preserve any existing import links so we can restore * them down below. That way, you can redefine a command and its * import status will remain intact. |
︙ | ︙ | |||
2685 2686 2687 2688 2689 2690 2691 | Tcl_ObjCmdProc *proc; void *clientData; /* Arbitrary value to pass to proc function. */ Tcl_CmdDeleteProc *deleteProc; void *deleteData; /* Arbitrary value to pass to deleteProc function. */ Tcl_ObjCmdProc *nreProc; } CmdWrapperInfo; | < | | | | < | 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 | Tcl_ObjCmdProc *proc; void *clientData; /* Arbitrary value to pass to proc function. */ Tcl_CmdDeleteProc *deleteProc; void *deleteData; /* Arbitrary value to pass to deleteProc function. */ Tcl_ObjCmdProc *nreProc; } CmdWrapperInfo; static int cmdWrapperProc( void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj * const *objv) { CmdWrapperInfo *info = (CmdWrapperInfo *) clientData; if (objc > INT_MAX) { Tcl_WrongNumArgs(interp, 1, objv, "?args?"); return TCL_ERROR; } return info->proc(info->clientData, interp, (int)objc, objv); } static void cmdWrapperDeleteProc( void *clientData) { CmdWrapperInfo *info = (CmdWrapperInfo *) clientData; clientData = info->deleteData; Tcl_CmdDeleteProc *deleteProc = info->deleteProc; Tcl_Free(info); if (deleteProc != NULL) { deleteProc(clientData); } } Tcl_Command Tcl_CreateObjCommand( Tcl_Interp *interp, /* Token for command interpreter (returned by * previous call to Tcl_CreateInterp). */ const char *cmdName, /* Name of command. If it contains namespace * qualifiers, the new command is put in the * specified namespace; otherwise it is put in * the global namespace. */ Tcl_ObjCmdProc *proc, /* Object-based function to associate with * name. */ void *clientData, /* Arbitrary value to pass to object * function. */ Tcl_CmdDeleteProc *deleteProc) /* If not NULL, gives a function to call when * this command is deleted. */ { CmdWrapperInfo *info = (CmdWrapperInfo *)Tcl_Alloc(sizeof(CmdWrapperInfo)); info->proc = proc; info->clientData = clientData; info->deleteProc = deleteProc; info->deleteData = clientData; |
︙ | ︙ | |||
2754 2755 2756 2757 2758 2759 2760 | * previous call to Tcl_CreateInterp). */ const char *cmdName, /* Name of command. If it contains namespace * qualifiers, the new command is put in the * specified namespace; otherwise it is put in * the global namespace. */ Tcl_ObjCmdProc2 *proc, /* Object-based function to associate with * name. */ | | | < | 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 | * previous call to Tcl_CreateInterp). */ const char *cmdName, /* Name of command. If it contains namespace * qualifiers, the new command is put in the * specified namespace; otherwise it is put in * the global namespace. */ Tcl_ObjCmdProc2 *proc, /* Object-based function to associate with * name. */ void *clientData, /* Arbitrary value to pass to object * function. */ Tcl_CmdDeleteProc *deleteProc) /* If not NULL, gives a function to call when * this command is deleted. */ { Interp *iPtr = (Interp *) interp; Namespace *nsPtr; const char *tail; if (iPtr->flags & DELETED) { /* |
︙ | ︙ | |||
2800 2801 2802 2803 2804 2805 2806 | proc, clientData, deleteProc); } Tcl_Command TclCreateObjCommandInNs( Tcl_Interp *interp, const char *cmdName, /* Name of command, without any namespace | | | | | 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 | proc, clientData, deleteProc); } Tcl_Command TclCreateObjCommandInNs( Tcl_Interp *interp, const char *cmdName, /* Name of command, without any namespace * components. */ Tcl_Namespace *namesp, /* The namespace to create the command in */ Tcl_ObjCmdProc2 *proc, /* Object-based function to associate with * name. */ void *clientData, /* Arbitrary value to pass to object * function. */ Tcl_CmdDeleteProc *deleteProc) /* If not NULL, gives a function to call when * this command is deleted. */ { int deleted = 0, isNew = 0; Command *cmdPtr; |
︙ | ︙ | |||
2836 2837 2838 2839 2840 2841 2842 | * isNew - No conflict with existing command. * deleted - We've already deleted a conflicting command */ break; } /* | | | | | | | 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 | * isNew - No conflict with existing command. * deleted - We've already deleted a conflicting command */ break; } /* * An existing command conflicts. Try to delete it... */ cmdPtr = (Command *)Tcl_GetHashValue(hPtr); /* * Command already exists; delete it. Be careful to preserve any * existing import links so we can restore them down below. That way, * you can redefine a command and its import status will remain * intact. */ cmdPtr->refCount++; if (cmdPtr->importRefPtr) { cmdPtr->flags |= CMD_REDEF_IN_PROGRESS; } /* * Make sure namespace doesn't get deallocated. */ cmdPtr->nsPtr->refCount++; Tcl_DeleteCommandFromToken(interp, (Tcl_Command) cmdPtr); nsPtr = (Namespace *) TclEnsureNamespace(interp, (Tcl_Namespace *) cmdPtr->nsPtr); TclNsDecrRefCount(cmdPtr->nsPtr); if (cmdPtr->flags & CMD_REDEF_IN_PROGRESS) { oldRefPtr = cmdPtr->importRefPtr; cmdPtr->importRefPtr = NULL; } TclCleanupCommandMacro(cmdPtr); |
︙ | ︙ | |||
3053 3054 3055 3056 3057 3058 3059 | * found. */ cmd = Tcl_FindCommand(interp, oldName, NULL, /*flags*/ 0); cmdPtr = (Command *) cmd; if (cmdPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( | | | | | 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 | * found. */ cmd = Tcl_FindCommand(interp, oldName, NULL, /*flags*/ 0); cmdPtr = (Command *) cmd; if (cmdPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't %s \"%s\": command doesn't exist", ((newName == NULL) || (*newName == '\0')) ? "delete" : "rename", oldName)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", oldName, (char *)NULL); return TCL_ERROR; } /* * If the new command name is NULL or empty, delete the command. Do this * with Tcl_DeleteCommandFromToken, since we already have the command. */ |
︙ | ︙ | |||
3086 3087 3088 3089 3090 3091 3092 | */ TclGetNamespaceForQualName(interp, newName, NULL, TCL_CREATE_NS_IF_UNKNOWN, &newNsPtr, &dummy1, &dummy2, &newTail); if ((newNsPtr == NULL) || (newTail == NULL)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( | | | | | | | 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 | */ TclGetNamespaceForQualName(interp, newName, NULL, TCL_CREATE_NS_IF_UNKNOWN, &newNsPtr, &dummy1, &dummy2, &newTail); if ((newNsPtr == NULL) || (newTail == NULL)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't rename to \"%s\": bad command name", newName)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", (char *)NULL); result = TCL_ERROR; goto done; } if (Tcl_FindHashEntry(&newNsPtr->cmdTable, newTail) != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't rename to \"%s\": command already exists", newName)); Tcl_SetErrorCode(interp, "TCL", "OPERATION", "RENAME", "TARGET_EXISTS", (char *)NULL); result = TCL_ERROR; goto done; } /* * Warning: any changes done in the code here are likely to be needed in * Tcl_HideCommand code too (until the common parts are extracted out). |
︙ | ︙ | |||
3268 3269 3270 3271 3272 3273 3274 | * *---------------------------------------------------------------------- */ #ifndef TCL_NO_DEPRECATED static int invokeObj2Command( | | | | | 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 | * *---------------------------------------------------------------------- */ #ifndef TCL_NO_DEPRECATED static int invokeObj2Command( void *clientData, /* Points to command's Command structure. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int result; Command *cmdPtr = (Command *)clientData; if (objc < 0) { objc = TCL_INDEX_NONE; } if (cmdPtr->objProc2 != NULL) { result = cmdPtr->objProc2(cmdPtr->objClientData2, interp, (size_t)objc, objv); } else { result = Tcl_NRCallObjProc2(interp, cmdPtr->nreProc2, cmdPtr->objClientData2, (size_t)objc, objv); } return result; } static int cmdWrapper2Proc( void *clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Command *cmdPtr = (Command *) clientData; if (objc < 0) { objc = -1; } return cmdPtr->objProc2(cmdPtr->objClientData2, interp, (size_t)objc, objv); } #endif |
︙ | ︙ | |||
3334 3335 3336 3337 3338 3339 3340 | cmdPtr->nreProc2 = NULL; cmdPtr->objProc2 = infoPtr->objProc2; } cmdPtr->objClientData2 = infoPtr->objClientData2; } #ifndef TCL_NO_DEPRECATED if (cmdPtr->deleteProc == cmdWrapperDeleteProc) { | | | 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 | cmdPtr->nreProc2 = NULL; cmdPtr->objProc2 = infoPtr->objProc2; } cmdPtr->objClientData2 = infoPtr->objClientData2; } #ifndef TCL_NO_DEPRECATED if (cmdPtr->deleteProc == cmdWrapperDeleteProc) { CmdWrapperInfo *info = (CmdWrapperInfo *) cmdPtr->deleteData; if (infoPtr->objProc == NULL) { info->proc = invokeObj2Command; info->clientData = cmdPtr; info->nreProc = NULL; } else { if (infoPtr->objProc != info->proc) { info->nreProc = NULL; |
︙ | ︙ | |||
3680 3681 3682 3683 3684 3685 3686 | */ cmdPtr->nsPtr->refCount++; if (cmdPtr->tracePtr != NULL) { CommandTrace *tracePtr; /* CallCommandTraces() does not cmdPtr, that's | | | 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 | */ cmdPtr->nsPtr->refCount++; if (cmdPtr->tracePtr != NULL) { CommandTrace *tracePtr; /* CallCommandTraces() does not cmdPtr, that's * done just before Tcl_DeleteCommandFromToken() returns */ CallCommandTraces(iPtr,cmdPtr,NULL,NULL,TCL_TRACE_DELETE); /* * Now delete these traces. */ tracePtr = cmdPtr->tracePtr; |
︙ | ︙ | |||
4164 4165 4166 4167 4168 4169 4170 | /* * Has the current script in progress for this interpreter been canceled * or is the stack being unwound due to the previous script cancellation? */ if (!TclCanceled(iPtr)) { | | | | | | | | | | | | | | | | | | | | | | | | | | | | 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 | /* * Has the current script in progress for this interpreter been canceled * or is the stack being unwound due to the previous script cancellation? */ if (!TclCanceled(iPtr)) { return TCL_OK; } /* * The CANCELED flag is a one-shot flag that is reset immediately upon * being detected; however, if the TCL_CANCEL_UNWIND flag is set we will * continue to report that the script in progress has been canceled * thereby allowing the evaluation stack for the interp to be fully * unwound. */ iPtr->flags &= ~CANCELED; /* * The CANCELED flag was detected and reset; however, if the caller * specified the TCL_CANCEL_UNWIND flag, we only return TCL_ERROR * (indicating that the script in progress has been canceled) if the * evaluation stack for the interp is being fully unwound. */ if ((flags & TCL_CANCEL_UNWIND) && !(iPtr->flags & TCL_CANCEL_UNWIND)) { return TCL_OK; } /* * If the TCL_LEAVE_ERR_MSG flags bit is set, place an error in the * interp's result; otherwise, we leave it alone. */ if (flags & TCL_LEAVE_ERR_MSG) { const char *id, *message = NULL; Tcl_Size length; /* * Setup errorCode variables so that we can differentiate between * being canceled and unwound. */ if (iPtr->asyncCancelMsg != NULL) { message = TclGetStringFromObj(iPtr->asyncCancelMsg, &length); } else { length = 0; } if (iPtr->flags & TCL_CANCEL_UNWIND) { id = "IUNWIND"; if (length == 0) { message = "eval unwound"; } } else { id = "ICANCEL"; if (length == 0) { message = "eval canceled"; } } Tcl_SetObjResult(interp, Tcl_NewStringObj(message, TCL_INDEX_NONE)); Tcl_SetErrorCode(interp, "TCL", "CANCEL", id, message, (char *)NULL); } /* * Return TCL_ERROR to the caller (not necessarily just the Tcl core * itself) that indicates further processing of the script or command in * progress should halt gracefully and as soon as possible. */ |
︙ | ︙ | |||
4260 4261 4262 4263 4264 4265 4266 | int Tcl_CancelEval( Tcl_Interp *interp, /* Interpreter in which to cancel the * script. */ Tcl_Obj *resultObjPtr, /* The script cancellation error message or * NULL for a default error message. */ | | | 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 | int Tcl_CancelEval( Tcl_Interp *interp, /* Interpreter in which to cancel the * script. */ Tcl_Obj *resultObjPtr, /* The script cancellation error message or * NULL for a default error message. */ void *clientData, /* Passed to CancelEvalProc. */ int flags) /* Collection of OR-ed bits that control * the cancellation of the script. Only * TCL_CANCEL_UNWIND is currently * supported. */ { Tcl_HashEntry *hPtr; CancelInfo *cancelInfo; |
︙ | ︙ | |||
4303 4304 4305 4306 4307 4308 4309 | * TCL_CANCEL_UNWIND flags bit is set, the script in progress is not * allowed to catch the script cancellation because the evaluation stack * for the interp is completely unwound. */ if (resultObjPtr != NULL) { result = TclGetStringFromObj(resultObjPtr, &cancelInfo->length); | | | 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 | * TCL_CANCEL_UNWIND flags bit is set, the script in progress is not * allowed to catch the script cancellation because the evaluation stack * for the interp is completely unwound. */ if (resultObjPtr != NULL) { result = TclGetStringFromObj(resultObjPtr, &cancelInfo->length); cancelInfo->result = (char *)Tcl_Realloc(cancelInfo->result, cancelInfo->length); memcpy(cancelInfo->result, result, cancelInfo->length); TclDecrRefCount(resultObjPtr); /* Discard their result object. */ } else { cancelInfo->result = NULL; cancelInfo->length = 0; } cancelInfo->clientData = clientData; |
︙ | ︙ | |||
4406 4407 4408 4409 4410 4411 4412 | * data[1] stores a marker for use by tailcalls; it will be set to 1 by * command redirectors (imports, alias, ensembles) so that tailcall skips * this callback (that marks the end of the target command) and goes back * to the end of the source command. */ if (iPtr->deferredCallbacks) { | | | 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 | * data[1] stores a marker for use by tailcalls; it will be set to 1 by * command redirectors (imports, alias, ensembles) so that tailcall skips * this callback (that marks the end of the target command) and goes back * to the end of the source command. */ if (iPtr->deferredCallbacks) { iPtr->deferredCallbacks = NULL; } else { TclNRAddCallback(interp, NRCommand, NULL, NULL, NULL, NULL); } iPtr->numLevels++; TclNRAddCallback(interp, EvalObjvCore, cmdPtr, INT2PTR(flags), INT2PTR(objc), objv); |
︙ | ︙ | |||
4494 4495 4496 4497 4498 4499 4500 | * Lookup the Command to dispatch. */ reresolve: assert(cmdPtr == NULL); if (preCmdPtr) { /* | | | | | | 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 | * Lookup the Command to dispatch. */ reresolve: assert(cmdPtr == NULL); if (preCmdPtr) { /* * Caller gave it to us. */ if (!(preCmdPtr->flags & CMD_DEAD)) { /* * So long as it exists, use it. */ cmdPtr = preCmdPtr; } else if (flags & TCL_EVAL_NORESOLVE) { /* * When it's been deleted, and we're told not to attempt resolving * it ourselves, all we can do is raise an error. */ |
︙ | ︙ | |||
4525 4526 4527 4528 4529 4530 4531 | return TEOV_NotFound(interp, objc, objv, lookupNsPtr); } } if (enterTracesDone || iPtr->tracePtr || (cmdPtr->flags & CMD_HAS_EXEC_TRACES)) { Tcl_Obj *commandPtr = TclGetSourceFromFrame( | | | 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 | return TEOV_NotFound(interp, objc, objv, lookupNsPtr); } } if (enterTracesDone || iPtr->tracePtr || (cmdPtr->flags & CMD_HAS_EXEC_TRACES)) { Tcl_Obj *commandPtr = TclGetSourceFromFrame( flags & TCL_EVAL_SOURCE_IN_FRAME ? iPtr->cmdFramePtr : NULL, objc, objv); Tcl_IncrRefCount(commandPtr); if (!enterTracesDone) { int code = TEOV_RunEnterTraces(interp, &cmdPtr, commandPtr, objc, objv); |
︙ | ︙ | |||
4568 4569 4570 4571 4572 4573 4574 | * Schedule leave traces. Raise the refCount on the resolved cmdPtr, * so that when it passes to the leave traces we know it's still * valid. */ cmdPtr->refCount++; TclNRAddCallback(interp, TEOV_RunLeaveTraces, INT2PTR(objc), | | | 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 | * Schedule leave traces. Raise the refCount on the resolved cmdPtr, * so that when it passes to the leave traces we know it's still * valid. */ cmdPtr->refCount++; TclNRAddCallback(interp, TEOV_RunLeaveTraces, INT2PTR(objc), commandPtr, cmdPtr, objv); } TclNRAddCallback(interp, Dispatch, cmdPtr->nreProc2 ? cmdPtr->nreProc2 : cmdPtr->objProc2, cmdPtr->objClientData2, INT2PTR(objc), objv); return TCL_OK; } |
︙ | ︙ | |||
4631 4632 4633 4634 4635 4636 4637 | Tcl_Interp *interp, int result, struct NRE_callback *rootPtr) /* All callbacks down to rootPtr not inclusive * are to be run. */ { while (TOP_CB(interp) != rootPtr) { | | | | | | | 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 | Tcl_Interp *interp, int result, struct NRE_callback *rootPtr) /* All callbacks down to rootPtr not inclusive * are to be run. */ { while (TOP_CB(interp) != rootPtr) { NRE_callback *callbackPtr = TOP_CB(interp); Tcl_NRPostProc *procPtr = callbackPtr->procPtr; TOP_CB(interp) = callbackPtr->nextPtr; result = procPtr(callbackPtr->data, interp, result); TCLNR_FREE(interp, callbackPtr); } return result; } static int NRCommand( void *data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; Tcl_Obj *listPtr; iPtr->numLevels--; /* * If there is a tailcall, schedule it next */ if (data[1] && (data[1] != INT2PTR(1))) { listPtr = (Tcl_Obj *)data[1]; data[1] = NULL; TclNRAddCallback(interp, TclNRTailcallEval, listPtr, NULL, NULL, NULL); } |
︙ | ︙ | |||
4869 4870 4871 4872 4873 4874 4875 | * to increment the reference count of all the handler arguments anyway. */ for (i = 0; i < handlerObjc; ++i) { newObjv[i] = handlerObjv[i]; Tcl_IncrRefCount(newObjv[i]); } | | | | | | 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 | * to increment the reference count of all the handler arguments anyway. */ for (i = 0; i < handlerObjc; ++i) { newObjv[i] = handlerObjv[i]; Tcl_IncrRefCount(newObjv[i]); } memcpy(newObjv + handlerObjc, objv, sizeof(Tcl_Obj *) * objc); /* * Look up and invoke the handler (by recursive call to this function). If * there is no handler at all, instead of doing the recursive call we just * generate a generic error message; it would be an infinite-recursion * nightmare otherwise. * * In this case we worry a bit less about recursion for now, and call the * "blocking" interface. */ cmdPtr = TEOV_LookupCmdFromObj(interp, newObjv[0], lookupNsPtr); if (cmdPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid command name \"%s\"", TclGetString(objv[0]))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", TclGetString(objv[0]), (char *)NULL); /* * Release any resources we locked and allocated during the handler * call. */ for (i = 0; i < handlerObjc; ++i) { |
︙ | ︙ | |||
5085 5086 5087 5088 5089 5090 5091 | int Tcl_EvalTokensStandard( Tcl_Interp *interp, /* Interpreter in which to lookup variables, * execute nested commands, and report * errors. */ Tcl_Token *tokenPtr, /* Pointer to first in an array of tokens to * evaluate and concatenate. */ | | | 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 | int Tcl_EvalTokensStandard( Tcl_Interp *interp, /* Interpreter in which to lookup variables, * execute nested commands, and report * errors. */ Tcl_Token *tokenPtr, /* Pointer to first in an array of tokens to * evaluate and concatenate. */ Tcl_Size count) /* Number of tokens to consider at tokenPtr. * Must be at least 1. */ { return TclSubstTokens(interp, tokenPtr, count, /* numLeftPtr */ NULL, 1, NULL, NULL); } /* |
︙ | ︙ | |||
5140 5141 5142 5143 5144 5145 5146 | Tcl_Size numBytes, /* Number of bytes in script. If -1, the * script consists of all bytes up to the * first NUL character. */ int flags, /* Collection of OR-ed bits that control the * evaluation of the script. Only * TCL_EVAL_GLOBAL is currently supported. */ Tcl_Size line, /* The line the script starts on. */ | | | 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 | Tcl_Size numBytes, /* Number of bytes in script. If -1, the * script consists of all bytes up to the * first NUL character. */ int flags, /* Collection of OR-ed bits that control the * evaluation of the script. Only * TCL_EVAL_GLOBAL is currently supported. */ Tcl_Size line, /* The line the script starts on. */ Tcl_Size *clNextOuter, /* Information about an outer context for */ const char *outerScript) /* continuation line data. This is set only in * TclSubstTokens(), to properly handle * [...]-nested commands. The 'outerScript' * refers to the most-outer script containing * the embedded command, which is referred to * by 'script'. The 'clNextOuter' refers to * the current entry in the table of |
︙ | ︙ | |||
5178 5179 5180 5181 5182 5183 5184 | Tcl_Size i, objectsUsed = 0; /* These variables keep track of how much * state has been allocated while evaluating * the script, so that it can be freed * properly if an error occurs. */ Tcl_Parse *parsePtr = (Tcl_Parse *)TclStackAlloc(interp, sizeof(Tcl_Parse)); CmdFrame *eeFramePtr = (CmdFrame *)TclStackAlloc(interp, sizeof(CmdFrame)); | | < | | 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 | Tcl_Size i, objectsUsed = 0; /* These variables keep track of how much * state has been allocated while evaluating * the script, so that it can be freed * properly if an error occurs. */ Tcl_Parse *parsePtr = (Tcl_Parse *)TclStackAlloc(interp, sizeof(Tcl_Parse)); CmdFrame *eeFramePtr = (CmdFrame *)TclStackAlloc(interp, sizeof(CmdFrame)); Tcl_Obj **stackObjArray = (Tcl_Obj **)TclStackAlloc(interp, minObjs * sizeof(Tcl_Obj *)); int *expandStack = (int *)TclStackAlloc(interp, minObjs * sizeof(int)); Tcl_Size *linesStack = (Tcl_Size *)TclStackAlloc(interp, minObjs * sizeof(Tcl_Size)); /* TIP #280 Structures for tracking of command * locations. */ Tcl_Size *clNext = NULL; /* Pointer for the tracking of invisible * continuation lines. Initialized only if the * caller gave us a table of locations to * track, via scriptCLLocPtr. It always refers * to the table entry holding the location of * the next invisible continuation line to * look for, while parsing the script. */ |
︙ | ︙ | |||
5317 5318 5319 5320 5321 5322 5323 | Tcl_Size numWords = parsePtr->numWords; /* * Generate an array of objects for the words of the command. */ if (numWords > minObjs) { | | | > | > | | | 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 | Tcl_Size numWords = parsePtr->numWords; /* * Generate an array of objects for the words of the command. */ if (numWords > minObjs) { expand = (int *)Tcl_Alloc(numWords * sizeof(int)); objvSpace = (Tcl_Obj **) Tcl_Alloc(numWords * sizeof(Tcl_Obj *)); lineSpace = (Tcl_Size *) Tcl_Alloc(numWords * sizeof(Tcl_Size)); } expandRequested = 0; objv = objvSpace; lines = lineSpace; iPtr->cmdFramePtr = eeFramePtr->nextPtr; for (objectsUsed = 0, tokenPtr = parsePtr->tokenPtr; objectsUsed < numWords; objectsUsed++, tokenPtr += tokenPtr->numComponents + 1) { /* * TIP #280. Track lines to current word. Save the information * on a per-word basis, signaling dynamic words as needed. * Make the information available to the recursively called * evaluator as well, including the type of context (source * vs. eval). */ TclAdvanceLines(&wordLine, wordStart, tokenPtr->start); TclAdvanceContinuations(&wordLine, &wordCLNext, tokenPtr->start - outerScript); wordStart = tokenPtr->start; lines[objectsUsed] = TclWordKnownAtCompileTime(tokenPtr, NULL) ? wordLine : -1; if (eeFramePtr->type == TCL_LOCATION_SOURCE) { iPtr->evalFlags |= TCL_EVAL_FILE; } code = TclSubstTokens(interp, tokenPtr + 1, tokenPtr->numComponents, NULL, wordLine, wordCLNext, outerScript); iPtr->evalFlags = 0; if (code != TCL_OK) { break; |
︙ | ︙ | |||
5404 5405 5406 5407 5408 5409 5410 | Tcl_Obj **copy = objvSpace; Tcl_Size *lcopy = lineSpace; Tcl_Size wordIdx = numWords; Tcl_Size objIdx = objectsNeeded - 1; if ((numWords > minObjs) || (objectsNeeded > minObjs)) { | < | | 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 | Tcl_Obj **copy = objvSpace; Tcl_Size *lcopy = lineSpace; Tcl_Size wordIdx = numWords; Tcl_Size objIdx = objectsNeeded - 1; if ((numWords > minObjs) || (objectsNeeded > minObjs)) { objv = objvSpace = (Tcl_Obj **)Tcl_Alloc(objectsNeeded * sizeof(Tcl_Obj *)); lines = lineSpace = (Tcl_Size *)Tcl_Alloc(objectsNeeded * sizeof(Tcl_Size)); } objectsUsed = 0; while (wordIdx--) { if (expand[wordIdx]) { Tcl_Size numElements; |
︙ | ︙ | |||
5430 5431 5432 5433 5434 5435 5436 | Tcl_DecrRefCount(temp); } else { lines[objIdx] = lcopy[wordIdx]; objv[objIdx--] = copy[wordIdx]; objectsUsed++; } } | | | 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 | Tcl_DecrRefCount(temp); } else { lines[objIdx] = lcopy[wordIdx]; objv[objIdx--] = copy[wordIdx]; objectsUsed++; } } objv += objIdx + 1; if (copy != stackObjArray) { Tcl_Free(copy); } if (lcopy != linesStack) { Tcl_Free(lcopy); } |
︙ | ︙ | |||
5776 5777 5778 5779 5780 5781 5782 | Tcl_Size objc) { Interp *iPtr = (Interp *) interp; Tcl_Size i; for (i = 1; i < objc; i++) { CFWord *cfwPtr; | < | | 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 | Tcl_Size objc) { Interp *iPtr = (Interp *) interp; Tcl_Size i; for (i = 1; i < objc; i++) { CFWord *cfwPtr; Tcl_HashEntry *hPtr = Tcl_FindHashEntry(iPtr->lineLAPtr, objv[i]); if (!hPtr) { continue; } cfwPtr = (CFWord *)Tcl_GetHashValue(hPtr); if (cfwPtr->refCount-- > 1) { |
︙ | ︙ | |||
5828 5829 5830 5831 5832 5833 5834 | Tcl_Size pc) { ExtCmdLoc *eclPtr; Tcl_Size word; ECL *ePtr; CFWordBC *lastPtr = NULL; Interp *iPtr = (Interp *) interp; | < | | 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 | Tcl_Size pc) { ExtCmdLoc *eclPtr; Tcl_Size word; ECL *ePtr; CFWordBC *lastPtr = NULL; Interp *iPtr = (Interp *) interp; Tcl_HashEntry *hePtr = Tcl_FindHashEntry(iPtr->lineBCPtr, codePtr); if (!hePtr) { return; } eclPtr = (ExtCmdLoc *)Tcl_GetHashValue(hePtr); ePtr = &eclPtr->loc[cmd]; |
︙ | ︙ | |||
5851 5852 5853 5854 5855 5856 5857 | * evaluation are not supposed to get compiled, because a command * such as [info level] in the script can expose some of the dispatch * shenanigans. This means that we don't have to tend to the * housekeeping, and can escape now. */ if (ePtr->nline != objc) { | | | | 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 | * evaluation are not supposed to get compiled, because a command * such as [info level] in the script can expose some of the dispatch * shenanigans. This means that we don't have to tend to the * housekeeping, and can escape now. */ if (ePtr->nline != objc) { return; } /* * Having disposed of the ensemble cases, we can state... * A few truths ... * (1) ePtr->nline == objc * (2) (ePtr->line[word] < 0) => !literal, for all words * (3) (word == 0) => !literal * * Item (2) is why we can use objv to get the literals, and do not * have to save them at compile time. */ for (word = 1; word < objc; word++) { if (ePtr->line[word] >= 0) { int isNew; Tcl_HashEntry *hPtr = Tcl_CreateHashEntry(iPtr->lineLABCPtr, objv[word], &isNew); CFWordBC *cfwPtr = (CFWordBC *)Tcl_Alloc(sizeof(CFWordBC)); cfwPtr->framePtr = cfPtr; cfwPtr->obj = objv[word]; cfwPtr->pc = pc; cfwPtr->word = word; cfwPtr->nextPtr = lastPtr; |
︙ | ︙ | |||
6059 6060 6061 6062 6063 6064 6065 | *---------------------------------------------------------------------- */ int Tcl_EvalObjEx( Tcl_Interp *interp, /* Token for command interpreter (returned by * a previous call to Tcl_CreateInterp). */ | | | | | 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 | *---------------------------------------------------------------------- */ int Tcl_EvalObjEx( Tcl_Interp *interp, /* Token for command interpreter (returned by * a previous call to Tcl_CreateInterp). */ Tcl_Obj *objPtr, /* Pointer to object containing commands to * execute. */ int flags) /* Collection of OR-ed bits that control the * evaluation of the script. Supported values * are TCL_EVAL_GLOBAL and TCL_EVAL_DIRECT. */ { return TclEvalObjEx(interp, objPtr, flags, NULL, 0); } int TclEvalObjEx( Tcl_Interp *interp, /* Token for command interpreter (returned by * a previous call to Tcl_CreateInterp). */ Tcl_Obj *objPtr, /* Pointer to object containing commands to * execute. */ int flags, /* Collection of OR-ed bits that control the * evaluation of the script. Supported values * are TCL_EVAL_GLOBAL and TCL_EVAL_DIRECT. */ const CmdFrame *invoker, /* Frame of the command doing the eval. */ int word) /* Index of the word which is in objPtr. */ { int result = TCL_OK; NRE_callback *rootPtr = TOP_CB(interp); result = TclNREvalObjEx(interp, objPtr, flags, invoker, word); return TclNRRunCallbacks(interp, result, rootPtr); } int TclNREvalObjEx( Tcl_Interp *interp, /* Token for command interpreter (returned by * a previous call to Tcl_CreateInterp). */ Tcl_Obj *objPtr, /* Pointer to object containing commands to * execute. */ int flags, /* Collection of OR-ed bits that control the * evaluation of the script. Supported values * are TCL_EVAL_GLOBAL and TCL_EVAL_DIRECT. */ const CmdFrame *invoker, /* Frame of the command doing the eval. */ int word) /* Index of the word which is in objPtr. */ { |
︙ | ︙ | |||
6176 6177 6178 6179 6180 6181 6182 | iPtr->cmdFramePtr = eoFramePtr; flags |= TCL_EVAL_SOURCE_IN_FRAME; } TclMarkTailcall(interp); | | | | | | | 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 | iPtr->cmdFramePtr = eoFramePtr; flags |= TCL_EVAL_SOURCE_IN_FRAME; } TclMarkTailcall(interp); TclNRAddCallback(interp, TEOEx_ListCallback, listPtr, eoFramePtr, objPtr, NULL); TclListObjGetElements(NULL, listPtr, &objc, &objv); return TclNREvalObjv(interp, objc, objv, flags, NULL); } if (!(flags & TCL_EVAL_DIRECT)) { /* * Let the compiler/engine subsystem do the evaluation. * * TIP #280 The invoker provides us with the context for the script. * We transfer this to the byte code compiler. */ int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS); ByteCode *codePtr; CallFrame *savedVarFramePtr = NULL; /* Saves old copy of * iPtr->varFramePtr in case * TCL_EVAL_GLOBAL was set. */ if (TclInterpReady(interp) != TCL_OK) { return TCL_ERROR; } if (flags & TCL_EVAL_GLOBAL) { savedVarFramePtr = iPtr->varFramePtr; iPtr->varFramePtr = iPtr->rootFramePtr; } Tcl_IncrRefCount(objPtr); codePtr = TclCompileObj(interp, objPtr, invoker, word); TclNRAddCallback(interp, TEOEx_ByteCodeCallback, savedVarFramePtr, objPtr, INT2PTR(allowExceptions), NULL); return TclNRExecuteByteCode(interp, codePtr); } { /* * We're not supposed to use the compiler or byte-code * interpreter. Let Tcl_EvalEx evaluate the command directly (and * probably more slowly). |
︙ | ︙ | |||
6492 6493 6494 6495 6496 6497 6498 | *-------------------------------------------------------------- */ int Tcl_ExprLongObj( Tcl_Interp *interp, /* Context in which to evaluate the * expression. */ | | | | 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 | *-------------------------------------------------------------- */ int Tcl_ExprLongObj( Tcl_Interp *interp, /* Context in which to evaluate the * expression. */ Tcl_Obj *objPtr, /* Expression to evaluate. */ long *ptr) /* Where to store long result. */ { Tcl_Obj *resultPtr; int result, type; double d; void *internalPtr; result = Tcl_ExprObj(interp, objPtr, &resultPtr); if (result != TCL_OK) { return TCL_ERROR; } if (Tcl_GetNumberFromObj(interp, resultPtr, &internalPtr, &type) != TCL_OK) { return TCL_ERROR; } switch (type) { case TCL_NUMBER_DOUBLE: { mp_int big; |
︙ | ︙ | |||
6539 6540 6541 6542 6543 6544 6545 | return result; } int Tcl_ExprDoubleObj( Tcl_Interp *interp, /* Context in which to evaluate the * expression. */ | | | 6563 6564 6565 6566 6567 6568 6569 6570 6571 6572 6573 6574 6575 6576 6577 | return result; } int Tcl_ExprDoubleObj( Tcl_Interp *interp, /* Context in which to evaluate the * expression. */ Tcl_Obj *objPtr, /* Expression to evaluate. */ double *ptr) /* Where to store double result. */ { Tcl_Obj *resultPtr; int result, type; void *internalPtr; result = Tcl_ExprObj(interp, objPtr, &resultPtr); |
︙ | ︙ | |||
6615 6616 6617 6618 6619 6620 6621 | *---------------------------------------------------------------------- */ int TclObjInvokeNamespace( Tcl_Interp *interp, /* Interpreter in which command is to be * invoked. */ | | | 6639 6640 6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 | *---------------------------------------------------------------------- */ int TclObjInvokeNamespace( Tcl_Interp *interp, /* Interpreter in which command is to be * invoked. */ Tcl_Size objc, /* Count of arguments. */ Tcl_Obj *const objv[], /* Argument objects; objv[0] points to the * name of the command to invoke. */ Tcl_Namespace *nsPtr, /* The namespace to use. */ int flags) /* Combination of flags controlling the call: * TCL_INVOKE_HIDDEN, TCL_INVOKE_NO_UNKNOWN, * or TCL_INVOKE_NO_TRACEBACK. */ { |
︙ | ︙ | |||
6659 6660 6661 6662 6663 6664 6665 | *---------------------------------------------------------------------- */ int TclObjInvoke( Tcl_Interp *interp, /* Interpreter in which command is to be * invoked. */ | | | | 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 6698 6699 6700 6701 6702 6703 6704 6705 6706 6707 6708 6709 | *---------------------------------------------------------------------- */ int TclObjInvoke( Tcl_Interp *interp, /* Interpreter in which command is to be * invoked. */ Tcl_Size objc, /* Count of arguments. */ Tcl_Obj *const objv[], /* Argument objects; objv[0] points to the * name of the command to invoke. */ int flags) /* Combination of flags controlling the call: * TCL_INVOKE_HIDDEN, TCL_INVOKE_NO_UNKNOWN, * or TCL_INVOKE_NO_TRACEBACK. */ { if (interp == NULL) { return TCL_ERROR; } if ((objc < 1) || (objv == NULL)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "illegal argument vector", TCL_INDEX_NONE)); return TCL_ERROR; } if ((flags & TCL_INVOKE_HIDDEN) == 0) { Tcl_Panic("TclObjInvoke: called without TCL_INVOKE_HIDDEN"); } return Tcl_NRCallObjProc2(interp, TclNRInvoke, NULL, objc, objv); } |
︙ | ︙ | |||
6700 6701 6702 6703 6704 6705 6706 | cmdName = TclGetString(objv[0]); hTblPtr = iPtr->hiddenCmdTablePtr; if (hTblPtr != NULL) { hPtr = Tcl_FindHashEntry(hTblPtr, cmdName); } if (hPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( | | | | | 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 | cmdName = TclGetString(objv[0]); hTblPtr = iPtr->hiddenCmdTablePtr; if (hTblPtr != NULL) { hPtr = Tcl_FindHashEntry(hTblPtr, cmdName); } if (hPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid hidden command name \"%s\"", cmdName)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "HIDDENTOKEN", cmdName, (char *)NULL); return TCL_ERROR; } cmdPtr = (Command *)Tcl_GetHashValue(hPtr); /* * Avoid the exception-handling brain damage when numLevels == 0 */ |
︙ | ︙ | |||
7190 7191 7192 7193 7194 7195 7196 | } Tcl_SetObjResult(interp, Tcl_NewBignumObj(&root)); } return TCL_OK; negarg: Tcl_SetObjResult(interp, Tcl_NewStringObj( | | | 7214 7215 7216 7217 7218 7219 7220 7221 7222 7223 7224 7225 7226 7227 7228 | } Tcl_SetObjResult(interp, Tcl_NewBignumObj(&root)); } return TCL_OK; negarg: Tcl_SetObjResult(interp, Tcl_NewStringObj( "square root of negative argument", TCL_INDEX_NONE)); Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", "domain error: argument not in valid range", (char *)NULL); return TCL_ERROR; } static int ExprSqrtFunc( |
︙ | ︙ | |||
7250 7251 7252 7253 7254 7255 7256 | Tcl_SetObjResult(interp, Tcl_NewDoubleObj(sqrt(d))); } return TCL_OK; } static int ExprUnaryFunc( | | | | 7274 7275 7276 7277 7278 7279 7280 7281 7282 7283 7284 7285 7286 7287 7288 7289 7290 7291 7292 7293 7294 7295 7296 7297 7298 | Tcl_SetObjResult(interp, Tcl_NewDoubleObj(sqrt(d))); } return TCL_OK; } static int ExprUnaryFunc( void *clientData, /* Contains the address of a function that * takes one double argument and returns a * double result. */ Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ Tcl_Size objc, /* Actual parameter count */ Tcl_Obj *const *objv) /* Actual parameter list */ { int code; double d; BuiltinUnaryFunc *func = (BuiltinUnaryFunc *) clientData; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } code = Tcl_GetDoubleFromObj(interp, objv[1], &d); #ifdef ACCEPT_NAN |
︙ | ︙ | |||
7314 7315 7316 7317 7318 7319 7320 | } Tcl_SetObjResult(interp, Tcl_NewDoubleObj(dResult)); return TCL_OK; } static int ExprBinaryFunc( | | | | 7338 7339 7340 7341 7342 7343 7344 7345 7346 7347 7348 7349 7350 7351 7352 7353 7354 7355 7356 7357 7358 7359 7360 7361 7362 | } Tcl_SetObjResult(interp, Tcl_NewDoubleObj(dResult)); return TCL_OK; } static int ExprBinaryFunc( void *clientData, /* Contains the address of a function that * takes two double arguments and returns a * double result. */ Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ Tcl_Size objc, /* Actual parameter count. */ Tcl_Obj *const *objv) /* Parameter vector. */ { int code; double d1, d2; BuiltinBinaryFunc *func = (BuiltinBinaryFunc *)clientData; if (objc != 3) { MathFuncWrongNumArgs(interp, 3, objc, objv); return TCL_ERROR; } code = Tcl_GetDoubleFromObj(interp, objv[1], &d1); #ifdef ACCEPT_NAN |
︙ | ︙ | |||
7400 7401 7402 7403 7404 7405 7406 | const char *bytes = TclGetStringFromObj(objv[1], &numBytes); while (numBytes) { if (*bytes == '-') { Tcl_SetObjResult(interp, Tcl_NewWideIntObj(0)); return TCL_OK; } | | > | 7424 7425 7426 7427 7428 7429 7430 7431 7432 7433 7434 7435 7436 7437 7438 7439 | const char *bytes = TclGetStringFromObj(objv[1], &numBytes); while (numBytes) { if (*bytes == '-') { Tcl_SetObjResult(interp, Tcl_NewWideIntObj(0)); return TCL_OK; } bytes++; numBytes--; } } goto unChanged; } else if (l == WIDE_MIN) { if (sizeof(Tcl_WideInt) > sizeof(int64_t)) { Tcl_WideUInt ul = -(Tcl_WideUInt)WIDE_MIN; if (mp_init(&big) != MP_OKAY || mp_unpack(&big, 1, 1, |
︙ | ︙ | |||
7618 7619 7620 7621 7622 7623 7624 | if (objc < 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } res = objv[1]; for (i = 1; i < objc; i++) { | | | | | | | | | | | | | | | 7643 7644 7645 7646 7647 7648 7649 7650 7651 7652 7653 7654 7655 7656 7657 7658 7659 7660 7661 7662 7663 7664 7665 7666 7667 7668 7669 7670 | if (objc < 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } res = objv[1]; for (i = 1; i < objc; i++) { if (Tcl_GetNumberFromObj(interp, objv[i], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_NAN) { /* * Get the error message for NaN. */ Tcl_GetDoubleFromObj(interp, objv[i], &d); return TCL_ERROR; } if (TclCompareTwoNumbers(objv[i], res) == op) { res = objv[i]; } } Tcl_SetObjResult(interp, res); return TCL_OK; } static int |
︙ | ︙ | |||
7687 7688 7689 7690 7691 7692 7693 | iPtr->flags |= RAND_SEED_INITIALIZED; /* * To ensure different seeds in different threads (bug #416643), * take into consideration the thread this interp is running in. */ | | | 7712 7713 7714 7715 7716 7717 7718 7719 7720 7721 7722 7723 7724 7725 7726 | iPtr->flags |= RAND_SEED_INITIALIZED; /* * To ensure different seeds in different threads (bug #416643), * take into consideration the thread this interp is running in. */ iPtr->randSeed = TclpGetClicks() + PTR2UINT(Tcl_GetCurrentThread()) * 4093U; /* * Make sure 1 <= randSeed <= (2^31) - 2. See below. */ iPtr->randSeed &= 0x7FFFFFFFL; if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7FFFFFFFL)) { |
︙ | ︙ | |||
7884 7885 7886 7887 7888 7889 7890 | *---------------------------------------------------------------------- * * Double Classification Functions -- * * This page contains the functions that implement all of the built-in * math functions for classifying IEEE doubles. * | | | | 7909 7910 7911 7912 7913 7914 7915 7916 7917 7918 7919 7920 7921 7922 7923 7924 | *---------------------------------------------------------------------- * * Double Classification Functions -- * * This page contains the functions that implement all of the built-in * math functions for classifying IEEE doubles. * * These have to be a little bit careful while Tcl_GetDoubleFromObj() * rejects NaN values, which these functions *explicitly* accept. * * Results: * Each function returns TCL_OK if it succeeds and pushes an Tcl object * holding the result. If it fails it returns TCL_ERROR and leaves an * error message in the interpreter's result. * * Side effects: |
︙ | ︙ | |||
7919 7920 7921 7922 7923 7924 7925 | return fpclassify(d); #else /* TCL_FPCLASSIFY_MODE != 0 */ /* * If we don't have fpclassify(), we also don't have the values it returns. * Hence we define those here. */ #ifndef FP_NAN | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 7944 7945 7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 7956 7957 7958 7959 7960 7961 7962 7963 7964 7965 7966 7967 7968 7969 7970 7971 7972 7973 7974 7975 7976 7977 7978 7979 7980 7981 7982 7983 7984 7985 7986 7987 7988 7989 7990 7991 7992 7993 7994 7995 7996 7997 7998 7999 8000 8001 8002 8003 8004 8005 8006 8007 8008 8009 8010 8011 8012 8013 8014 8015 8016 8017 8018 8019 8020 8021 8022 8023 8024 8025 8026 8027 8028 8029 8030 8031 8032 8033 8034 8035 8036 8037 8038 8039 8040 8041 8042 8043 8044 8045 8046 8047 8048 8049 8050 8051 8052 | return fpclassify(d); #else /* TCL_FPCLASSIFY_MODE != 0 */ /* * If we don't have fpclassify(), we also don't have the values it returns. * Hence we define those here. */ #ifndef FP_NAN # define FP_NAN 1 /* Value is NaN */ # define FP_INFINITE 2 /* Value is an infinity */ # define FP_ZERO 3 /* Value is a zero */ # define FP_NORMAL 4 /* Value is a normal float */ # define FP_SUBNORMAL 5 /* Value has lost accuracy */ #endif /* !FP_NAN */ #if TCL_FPCLASSIFY_MODE == 3 return __builtin_fpclassify( FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, d); #elif TCL_FPCLASSIFY_MODE == 2 /* * We assume this hack is only needed on little-endian systems. * Specifically, x86 running Windows. It's fairly easy to enable for * others if they need it (because their libc/libm is broken) but we'll * jump that hurdle when requred. We can solve the word ordering then. */ union { double d; /* Interpret as double */ struct { unsigned int low; /* Lower 32 bits */ unsigned int high; /* Upper 32 bits */ } w; /* Interpret as unsigned integer words */ } doubleMeaning; /* So we can look at the representation of a * double directly. Platform (i.e., processor) * specific; this is for x86 (and most other * little-endian processors, but those are * untested). */ unsigned int exponent, mantissaLow, mantissaHigh; /* The pieces extracted from the double. */ int zeroMantissa; /* Was the mantissa zero? That's special. */ /* * Shifts and masks to use with the doubleMeaning variable above. */ #define EXPONENT_MASK 0x7FF /* 11 bits (after shifting) */ #define EXPONENT_SHIFT 20 /* Moves exponent to bottom of word */ #define MANTISSA_MASK 0xFFFFF /* 20 bits (plus 32 from other word) */ /* * Extract the exponent (11 bits) and mantissa (52 bits). Note that we * totally ignore the sign bit. */ doubleMeaning.d = d; exponent = (doubleMeaning.w.high >> EXPONENT_SHIFT) & EXPONENT_MASK; mantissaLow = doubleMeaning.w.low; mantissaHigh = doubleMeaning.w.high & MANTISSA_MASK; zeroMantissa = (mantissaHigh == 0 && mantissaLow == 0); /* * Look for the special cases of exponent. */ switch (exponent) { case 0: /* * When the exponent is all zeros, it's a ZERO or a SUBNORMAL. */ return zeroMantissa ? FP_ZERO : FP_SUBNORMAL; case EXPONENT_MASK: /* * When the exponent is all ones, it's an INF or a NAN. */ return zeroMantissa ? FP_INFINITE : FP_NAN; default: /* * Everything else is a NORMAL double precision float. */ return FP_NORMAL; } #elif TCL_FPCLASSIFY_MODE == 1 switch (_fpclass(d)) { case _FPCLASS_NZ: case _FPCLASS_PZ: return FP_ZERO; case _FPCLASS_NN: case _FPCLASS_PN: return FP_NORMAL; case _FPCLASS_ND: case _FPCLASS_PD: return FP_SUBNORMAL; case _FPCLASS_NINF: case _FPCLASS_PINF: return FP_INFINITE; default: Tcl_Panic("result of _fpclass() outside documented range!"); case _FPCLASS_QNAN: case _FPCLASS_SNAN: return FP_NAN; } #else /* TCL_FPCLASSIFY_MODE not in (0..3) */ #error "unknown or unexpected TCL_FPCLASSIFY_MODE" #endif /* TCL_FPCLASSIFY_MODE */ #endif /* !fpclassify */ } |
︙ | ︙ | |||
8039 8040 8041 8042 8043 8044 8045 | if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { | | | | | | | | 8064 8065 8066 8067 8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082 8083 8084 8085 | if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type != TCL_NUMBER_NAN) { if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { return TCL_ERROR; } type = ClassifyDouble(d); result = (type != FP_INFINITE && type != FP_NAN); } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); return TCL_OK; } static int ExprIsInfinityFunc( |
︙ | ︙ | |||
8070 8071 8072 8073 8074 8075 8076 | if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { | | | | | | | 8095 8096 8097 8098 8099 8100 8101 8102 8103 8104 8105 8106 8107 8108 8109 8110 8111 8112 8113 8114 8115 | if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type != TCL_NUMBER_NAN) { if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { return TCL_ERROR; } result = (ClassifyDouble(d) == FP_INFINITE); } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); return TCL_OK; } static int ExprIsNaNFunc( |
︙ | ︙ | |||
8100 8101 8102 8103 8104 8105 8106 | if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { | | | | | | | 8125 8126 8127 8128 8129 8130 8131 8132 8133 8134 8135 8136 8137 8138 8139 8140 8141 8142 8143 8144 8145 | if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type != TCL_NUMBER_NAN) { if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { return TCL_ERROR; } result = (ClassifyDouble(d) == FP_NAN); } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); return TCL_OK; } static int ExprIsNormalFunc( |
︙ | ︙ | |||
8130 8131 8132 8133 8134 8135 8136 | if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { | | | | | | | 8155 8156 8157 8158 8159 8160 8161 8162 8163 8164 8165 8166 8167 8168 8169 8170 8171 8172 8173 8174 8175 | if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type != TCL_NUMBER_NAN) { if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { return TCL_ERROR; } result = (ClassifyDouble(d) == FP_NORMAL); } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); return TCL_OK; } static int ExprIsSubnormalFunc( |
︙ | ︙ | |||
8160 8161 8162 8163 8164 8165 8166 | if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { | | | | | | | 8185 8186 8187 8188 8189 8190 8191 8192 8193 8194 8195 8196 8197 8198 8199 8200 8201 8202 8203 8204 8205 | if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type != TCL_NUMBER_NAN) { if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { return TCL_ERROR; } result = (ClassifyDouble(d) == FP_SUBNORMAL); } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); return TCL_OK; } static int ExprIsUnorderedFunc( |
︙ | ︙ | |||
8190 8191 8192 8193 8194 8195 8196 | if (objc != 3) { MathFuncWrongNumArgs(interp, 3, objc, objv); return TCL_ERROR; } if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { | | | | | | | | | | | | | | | | | | | | | | | | | | | 8215 8216 8217 8218 8219 8220 8221 8222 8223 8224 8225 8226 8227 8228 8229 8230 8231 8232 8233 8234 8235 8236 8237 8238 8239 8240 8241 8242 8243 8244 8245 8246 8247 8248 8249 8250 8251 8252 8253 8254 8255 8256 8257 8258 8259 8260 8261 8262 8263 8264 8265 8266 8267 8268 8269 8270 8271 8272 8273 8274 8275 8276 8277 8278 8279 8280 8281 8282 8283 8284 8285 8286 8287 8288 8289 8290 8291 8292 8293 8294 8295 8296 8297 8298 | if (objc != 3) { MathFuncWrongNumArgs(interp, 3, objc, objv); return TCL_ERROR; } if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_NAN) { result = 1; } else { d = *((const double *) ptr); result = (ClassifyDouble(d) == FP_NAN); } if (Tcl_GetNumberFromObj(interp, objv[2], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_NAN) { result |= 1; } else { d = *((const double *) ptr); result |= (ClassifyDouble(d) == FP_NAN); } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); return TCL_OK; } static int FloatClassifyObjCmd( TCL_UNUSED(void *), Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ Tcl_Size objc, /* Actual parameter count */ Tcl_Obj *const *objv) /* Actual parameter list */ { double d; Tcl_Obj *objPtr; void *ptr; int type; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "floatValue"); return TCL_ERROR; } if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_NAN) { goto gotNaN; } else if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { return TCL_ERROR; } switch (ClassifyDouble(d)) { case FP_INFINITE: TclNewLiteralStringObj(objPtr, "infinite"); break; case FP_NAN: gotNaN: TclNewLiteralStringObj(objPtr, "nan"); break; case FP_NORMAL: TclNewLiteralStringObj(objPtr, "normal"); break; case FP_SUBNORMAL: TclNewLiteralStringObj(objPtr, "subnormal"); break; case FP_ZERO: TclNewLiteralStringObj(objPtr, "zero"); break; default: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unable to classify number: %f", d)); return TCL_ERROR; } Tcl_SetObjResult(interp, objPtr); return TCL_OK; } /* *---------------------------------------------------------------------- |
︙ | ︙ | |||
8292 8293 8294 8295 8296 8297 8298 | int expected, /* Formal parameter count. */ int found, /* Actual parameter count. */ Tcl_Obj *const *objv) /* Actual parameter vector. */ { const char *name = TclGetString(objv[0]); const char *tail = name + strlen(name); | | | | 8317 8318 8319 8320 8321 8322 8323 8324 8325 8326 8327 8328 8329 8330 8331 8332 8333 8334 | int expected, /* Formal parameter count. */ int found, /* Actual parameter count. */ Tcl_Obj *const *objv) /* Actual parameter vector. */ { const char *name = TclGetString(objv[0]); const char *tail = name + strlen(name); while (tail > name + 1) { tail--; if (*tail == ':' && tail[-1] == ':') { name = tail + 1; break; } } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s arguments for math function \"%s\"", (found < expected ? "not enough" : "too many"), name)); Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", (char *)NULL); |
︙ | ︙ | |||
8491 8492 8493 8494 8495 8496 8497 | static int wrapperNRObjProc( void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]) { | | | 8516 8517 8518 8519 8520 8521 8522 8523 8524 8525 8526 8527 8528 8529 8530 | static int wrapperNRObjProc( void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]) { CmdWrapperInfo *info = (CmdWrapperInfo *) clientData; clientData = info->clientData; Tcl_ObjCmdProc *proc = info->proc; Tcl_Free(info); return proc(clientData, interp, (int)objc, objv); } int |
︙ | ︙ | |||
8558 8559 8560 8561 8562 8563 8564 | static int cmdWrapperNreProc( void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]) { | | > | > < | | | | | 8583 8584 8585 8586 8587 8588 8589 8590 8591 8592 8593 8594 8595 8596 8597 8598 8599 8600 8601 8602 8603 8604 8605 8606 8607 8608 8609 8610 8611 8612 8613 8614 8615 8616 8617 8618 8619 8620 8621 8622 8623 8624 8625 8626 8627 8628 8629 8630 8631 8632 8633 8634 8635 8636 8637 8638 8639 8640 8641 8642 8643 8644 8645 8646 8647 8648 8649 8650 8651 8652 8653 8654 8655 8656 8657 8658 8659 8660 8661 8662 8663 8664 8665 8666 8667 8668 8669 8670 8671 8672 8673 8674 | static int cmdWrapperNreProc( void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]) { CmdWrapperInfo *info = (CmdWrapperInfo *) clientData; return info->nreProc(info->clientData, interp, objc, objv); } Tcl_Command Tcl_NRCreateCommand( Tcl_Interp *interp, /* Token for command interpreter (returned by * previous call to Tcl_CreateInterp). */ const char *cmdName, /* Name of command. If it contains namespace * qualifiers, the new command is put in the * specified namespace; otherwise it is put in * the global namespace. */ Tcl_ObjCmdProc *proc, /* Object-based function to associate with * name, provides direct access for direct * calls. */ Tcl_ObjCmdProc *nreProc, /* Object-based function to associate with * name, provides NR implementation */ void *clientData, /* Arbitrary value to pass to object * function. */ Tcl_CmdDeleteProc *deleteProc) /* If not NULL, gives a function to call when * this command is deleted. */ { CmdWrapperInfo *info = (CmdWrapperInfo *)Tcl_Alloc(sizeof(CmdWrapperInfo)); info->proc = proc; info->clientData = clientData; info->nreProc = nreProc; info->deleteProc = deleteProc; info->deleteData = clientData; return Tcl_NRCreateCommand2(interp, cmdName, (proc ? cmdWrapperProc : NULL), (nreProc ? cmdWrapperNreProc : NULL), info, cmdWrapperDeleteProc); } #endif /* TCL_NO_DEPRECATED */ Tcl_Command Tcl_NRCreateCommand2( Tcl_Interp *interp, /* Token for command interpreter (returned by * previous call to Tcl_CreateInterp). */ const char *cmdName, /* Name of command. If it contains namespace * qualifiers, the new command is put in the * specified namespace; otherwise it is put in * the global namespace. */ Tcl_ObjCmdProc2 *proc, /* Object-based function to associate with * name, provides direct access for direct * calls. */ Tcl_ObjCmdProc2 *nreProc, /* Object-based function to associate with * name, provides NR implementation */ void *clientData, /* Arbitrary value to pass to object * function. */ Tcl_CmdDeleteProc *deleteProc) /* If not NULL, gives a function to call when * this command is deleted. */ { Command *cmdPtr = (Command *) Tcl_CreateObjCommand2(interp, cmdName, proc, clientData, deleteProc); cmdPtr->nreProc2 = nreProc; return (Tcl_Command) cmdPtr; } Tcl_Command TclNRCreateCommandInNs( Tcl_Interp *interp, const char *cmdName, Tcl_Namespace *nsPtr, Tcl_ObjCmdProc2 *proc, Tcl_ObjCmdProc2 *nreProc, void *clientData, Tcl_CmdDeleteProc *deleteProc) { Command *cmdPtr = (Command *) TclCreateObjCommandInNs(interp, cmdName, nsPtr, proc, clientData, deleteProc); cmdPtr->nreProc2 = nreProc; return (Tcl_Command) cmdPtr; } /**************************************************************************** * Stuff for the public api |
︙ | ︙ | |||
8657 8658 8659 8660 8661 8662 8663 | return TclNREvalObjEx(interp, objPtr, flags, NULL, INT_MIN); } int Tcl_NREvalObjv( Tcl_Interp *interp, /* Interpreter in which to evaluate the * command. Also used for error reporting. */ | | | 8683 8684 8685 8686 8687 8688 8689 8690 8691 8692 8693 8694 8695 8696 8697 | return TclNREvalObjEx(interp, objPtr, flags, NULL, INT_MIN); } int Tcl_NREvalObjv( Tcl_Interp *interp, /* Interpreter in which to evaluate the * command. Also used for error reporting. */ Tcl_Size objc, /* Number of words in command. */ Tcl_Obj *const objv[], /* An array of pointers to objects that are * the words that make up the command. */ int flags) /* Collection of OR-ed bits that control the * evaluation of the script. Only * TCL_EVAL_GLOBAL, TCL_EVAL_INVOKE and * TCL_EVAL_NOERR are currently supported. */ { |
︙ | ︙ | |||
8698 8699 8700 8701 8702 8703 8704 | * 3. when the NRCommand callback runs, it schedules the tailcall callback * to run immediately after it returns * * One delicate point is to properly define the NRCommand where the tailcall * will execute. There are functions whose purpose is to help define the * precise spot: * TclMarkTailcall: if the NEXT command to be pushed tailcalls, execution | | | | | | | | | | 8724 8725 8726 8727 8728 8729 8730 8731 8732 8733 8734 8735 8736 8737 8738 8739 8740 8741 8742 8743 8744 8745 8746 8747 8748 8749 8750 8751 8752 8753 8754 8755 8756 8757 | * 3. when the NRCommand callback runs, it schedules the tailcall callback * to run immediately after it returns * * One delicate point is to properly define the NRCommand where the tailcall * will execute. There are functions whose purpose is to help define the * precise spot: * TclMarkTailcall: if the NEXT command to be pushed tailcalls, execution * should continue right here * TclSkipTailcall: if the NEXT command to be pushed tailcalls, execution * should continue after the CURRENT command is fully returned ("skip * the next command: we are redirecting to it, tailcalls should run * after WE return") * TclPushTailcallPoint: the search for a tailcalling spot cannot traverse * this point. This is special for OO, as some of the oo constructs * that behave like commands may not push an NRCommand callback. */ void TclMarkTailcall( Tcl_Interp *interp) { Interp *iPtr = (Interp *) interp; if (iPtr->deferredCallbacks == NULL) { TclNRAddCallback(interp, NRCommand, NULL, NULL, NULL, NULL); iPtr->deferredCallbacks = TOP_CB(interp); } } void TclSkipTailcall( Tcl_Interp *interp) { |
︙ | ︙ | |||
8764 8765 8766 8767 8768 8769 8770 | * being tailcalled. Note that we skip NRCommands marked by a 1 in data[1] * (used by command redirectors). */ NRE_callback *runPtr; for (runPtr = TOP_CB(interp); runPtr; runPtr = runPtr->nextPtr) { | | | | | | 8790 8791 8792 8793 8794 8795 8796 8797 8798 8799 8800 8801 8802 8803 8804 8805 8806 8807 8808 8809 | * being tailcalled. Note that we skip NRCommands marked by a 1 in data[1] * (used by command redirectors). */ NRE_callback *runPtr; for (runPtr = TOP_CB(interp); runPtr; runPtr = runPtr->nextPtr) { if (((runPtr->procPtr) == NRCommand) && !runPtr->data[1]) { break; } } if (!runPtr) { Tcl_Panic("tailcall cannot find the right splicing spot: should not happen!"); } runPtr->data[1] = listPtr; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
8805 8806 8807 8808 8809 8810 8811 | if (objc < 1) { Tcl_WrongNumArgs(interp, 1, objv, "?command? ?arg ...?"); return TCL_ERROR; } if (!(iPtr->varFramePtr->isProcCallFrame & 1)) { | | | | | | | | | | | | | | | | 8831 8832 8833 8834 8835 8836 8837 8838 8839 8840 8841 8842 8843 8844 8845 8846 8847 8848 8849 8850 8851 8852 8853 8854 8855 8856 8857 8858 8859 8860 8861 8862 8863 8864 8865 8866 8867 8868 8869 8870 8871 8872 8873 8874 8875 8876 8877 8878 8879 8880 | if (objc < 1) { Tcl_WrongNumArgs(interp, 1, objv, "?command? ?arg ...?"); return TCL_ERROR; } if (!(iPtr->varFramePtr->isProcCallFrame & 1)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "tailcall can only be called from a proc, lambda or method", TCL_INDEX_NONE)); Tcl_SetErrorCode(interp, "TCL", "TAILCALL", "ILLEGAL", (char *)NULL); return TCL_ERROR; } /* * Invocation without args just clears a scheduled tailcall; invocation * with an argument replaces any previously scheduled tailcall. */ if (iPtr->varFramePtr->tailcallPtr) { Tcl_DecrRefCount(iPtr->varFramePtr->tailcallPtr); iPtr->varFramePtr->tailcallPtr = NULL; } /* * Create the callback to actually evaluate the tailcalled * command, then set it in the varFrame so that PopCallFrame can use it * at the proper time. */ if (objc > 1) { Tcl_Obj *listPtr, *nsObjPtr; Tcl_Namespace *nsPtr = (Tcl_Namespace *) iPtr->varFramePtr->nsPtr; /* * The tailcall data is in a Tcl list: the first element is the * namespace, the rest the command to be tailcalled. */ nsObjPtr = Tcl_NewStringObj(nsPtr->fullName, TCL_INDEX_NONE); listPtr = Tcl_NewListObj(objc, objv); TclListObjSetElement(interp, listPtr, 0, nsObjPtr); iPtr->varFramePtr->tailcallPtr = listPtr; } return TCL_RETURN; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
8875 8876 8877 8878 8879 8880 8881 | nsObjPtr = objv[0]; if (result == TCL_OK) { result = TclGetNamespaceFromObj(interp, nsObjPtr, &nsPtr); } if (result != TCL_OK) { | | | | | | | | 8901 8902 8903 8904 8905 8906 8907 8908 8909 8910 8911 8912 8913 8914 8915 8916 8917 8918 8919 8920 8921 8922 8923 8924 8925 8926 8927 8928 8929 8930 8931 | nsObjPtr = objv[0]; if (result == TCL_OK) { result = TclGetNamespaceFromObj(interp, nsObjPtr, &nsPtr); } if (result != TCL_OK) { /* * Tailcall execution was preempted, eg by an intervening catch or by * a now-gone namespace: cleanup and return. */ Tcl_DecrRefCount(listPtr); return result; } /* * Perform the tailcall */ TclMarkTailcall(interp); TclNRAddCallback(interp, TclNRReleaseValues, listPtr, NULL, NULL,NULL); iPtr->lookupNsPtr = (Namespace *) nsPtr; return TclNREvalObjv(interp, objc - 1, objv + 1, 0, NULL); } int TclNRReleaseValues( void *data[], TCL_UNUSED(Tcl_Interp *), int result) |
︙ | ︙ | |||
8968 8969 8970 8971 8972 8973 8974 | if (objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "?returnValue?"); return TCL_ERROR; } if (!corPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( | | | | 8994 8995 8996 8997 8998 8999 9000 9001 9002 9003 9004 9005 9006 9007 9008 9009 9010 9011 9012 9013 9014 9015 9016 9017 9018 9019 | if (objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "?returnValue?"); return TCL_ERROR; } if (!corPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "yield can only be called in a coroutine", TCL_INDEX_NONE)); Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ILLEGAL_YIELD", (char *)NULL); return TCL_ERROR; } if (objc == 2) { Tcl_SetObjResult(interp, objv[1]); } NRE_ASSERT(!COR_IS_SUSPENDED(corPtr)); TclNRAddCallback(interp, TclNRCoroutineActivateCallback, corPtr, clientData, NULL, NULL); return TCL_OK; } int TclNRYieldToObjCmd( TCL_UNUSED(void *), Tcl_Interp *interp, |
︙ | ︙ | |||
9001 9002 9003 9004 9005 9006 9007 | if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "command ?arg ...?"); return TCL_ERROR; } if (!corPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( | | | | | | 9027 9028 9029 9030 9031 9032 9033 9034 9035 9036 9037 9038 9039 9040 9041 9042 9043 9044 9045 9046 9047 9048 9049 9050 9051 | if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "command ?arg ...?"); return TCL_ERROR; } if (!corPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "yieldto can only be called in a coroutine", TCL_INDEX_NONE)); Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ILLEGAL_YIELD", (char *)NULL); return TCL_ERROR; } if (((Namespace *) nsPtr)->flags & NS_DYING) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "yieldto called in deleted namespace", TCL_INDEX_NONE)); Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "YIELDTO_IN_DELETED", (char *)NULL); return TCL_ERROR; } /* * Add the tailcall in the caller env, then just yield. * * This is essentially code from TclNRTailcallObjCmd */ |
︙ | ︙ | |||
9176 9177 9178 9179 9180 9181 9182 | } /* *---------------------------------------------------------------------- * * TclNRCoroutineActivateCallback -- * | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | | | | | | | | | | | | | | | | | | | | | 9202 9203 9204 9205 9206 9207 9208 9209 9210 9211 9212 9213 9214 9215 9216 9217 9218 9219 9220 9221 9222 9223 9224 9225 9226 9227 9228 9229 9230 9231 9232 9233 9234 9235 9236 9237 9238 9239 9240 9241 9242 9243 9244 9245 9246 9247 9248 9249 9250 9251 9252 9253 9254 9255 9256 9257 9258 9259 9260 9261 9262 9263 9264 9265 9266 9267 9268 9269 9270 9271 9272 9273 9274 9275 9276 9277 9278 9279 9280 9281 9282 9283 9284 9285 9286 9287 9288 9289 9290 9291 9292 9293 9294 9295 9296 9297 9298 9299 9300 9301 9302 9303 9304 9305 9306 9307 9308 9309 9310 9311 9312 9313 9314 9315 9316 | } /* *---------------------------------------------------------------------- * * TclNRCoroutineActivateCallback -- * * This is the workhorse for coroutines: it implements both yield and * resume. * * It is important that both be implemented in the same callback: the * detection of the impossibility to suspend due to a busy C-stack relies * on the precise position of a local variable in the stack. We do not * want the compiler to play tricks on us, either by moving things around * or inlining. * *---------------------------------------------------------------------- */ int TclNRCoroutineActivateCallback( void *data[], Tcl_Interp *interp, TCL_UNUSED(int) /*result*/) { CoroutineData *corPtr = (CoroutineData *)data[0]; void *stackLevel = TclGetCStackPtr(); if (!corPtr->stackLevel) { /* * -- Coroutine is suspended -- * Push the callback to restore the caller's context on yield or * return. */ TclNRAddCallback(interp, NRCoroutineCallerCallback, corPtr, NULL, NULL, NULL); /* * Record the stackLevel at which the resume is happening, then swap * the interp's environment to make it suitable to run this coroutine. */ corPtr->stackLevel = stackLevel; Tcl_Size numLevels = corPtr->auxNumLevels; corPtr->auxNumLevels = iPtr->numLevels; SAVE_CONTEXT(corPtr->caller); corPtr->callerEEPtr = iPtr->execEnvPtr; RESTORE_CONTEXT(corPtr->running); iPtr->execEnvPtr = corPtr->eePtr; iPtr->numLevels += numLevels; } else { /* * Coroutine is active: yield */ if (corPtr->stackLevel != stackLevel) { NRE_callback *runPtr; iPtr->execEnvPtr = corPtr->callerEEPtr; if (corPtr->yieldPtr) { for (runPtr = TOP_CB(interp); runPtr; runPtr = runPtr->nextPtr) { if (runPtr->data[1] == corPtr->yieldPtr) { Tcl_DecrRefCount((Tcl_Obj *)runPtr->data[1]); runPtr->data[1] = NULL; corPtr->yieldPtr = NULL; break; } } } iPtr->execEnvPtr = corPtr->eePtr; Tcl_SetObjResult(interp, Tcl_NewStringObj( "cannot yield: C stack busy", TCL_INDEX_NONE)); Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "CANT_YIELD", (char *)NULL); return TCL_ERROR; } void *type = data[1]; if (type == CORO_ACTIVATE_YIELD) { corPtr->nargs = COROUTINE_ARGUMENTS_SINGLE_OPTIONAL; } else if (type == CORO_ACTIVATE_YIELDM) { corPtr->nargs = COROUTINE_ARGUMENTS_ARBITRARY; } else { Tcl_Panic("Yield received an option which is not implemented"); } corPtr->yieldPtr = NULL; corPtr->stackLevel = NULL; Tcl_Size numLevels = iPtr->numLevels; iPtr->numLevels = corPtr->auxNumLevels; corPtr->auxNumLevels = numLevels - corPtr->auxNumLevels; iPtr->execEnvPtr = corPtr->callerEEPtr; } return TCL_OK; } /* *---------------------------------------------------------------------- * * TclNREvalList -- * * Callback to invoke command as list, used in order to delayed * processing of canonical list command in sane environment. * *---------------------------------------------------------------------- */ static int TclNREvalList( |
︙ | ︙ | |||
9306 9307 9308 9309 9310 9311 9312 | } /* *---------------------------------------------------------------------- * * CoroTypeObjCmd -- * | | | 9331 9332 9333 9334 9335 9336 9337 9338 9339 9340 9341 9342 9343 9344 9345 | } /* *---------------------------------------------------------------------- * * CoroTypeObjCmd -- * * Implementation of [::tcl::unsupported::corotype] command. * *---------------------------------------------------------------------- */ static int CoroTypeObjCmd( TCL_UNUSED(void *), |
︙ | ︙ | |||
9332 9333 9334 9335 9336 9337 9338 | /* * Look up the coroutine. */ cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objv[1]); if ((!cmdPtr) || (cmdPtr->nreProc2 != TclNRInterpCoroutine)) { | | | | | | | | | | | | | | | | | | | | | | 9357 9358 9359 9360 9361 9362 9363 9364 9365 9366 9367 9368 9369 9370 9371 9372 9373 9374 9375 9376 9377 9378 9379 9380 9381 9382 9383 9384 9385 9386 9387 9388 9389 9390 9391 9392 9393 9394 9395 9396 9397 9398 9399 9400 9401 9402 9403 9404 9405 9406 9407 9408 9409 9410 9411 9412 9413 9414 9415 9416 9417 9418 9419 9420 9421 9422 9423 9424 9425 9426 9427 9428 9429 9430 9431 9432 9433 9434 9435 | /* * Look up the coroutine. */ cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objv[1]); if ((!cmdPtr) || (cmdPtr->nreProc2 != TclNRInterpCoroutine)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "can only get coroutine type of a coroutine", TCL_INDEX_NONE)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COROUTINE", TclGetString(objv[1]), (char *)NULL); return TCL_ERROR; } /* * An active coroutine is "active". Can't tell what it might do in the * future. */ corPtr = (CoroutineData *)cmdPtr->objClientData2; if (!COR_IS_SUSPENDED(corPtr)) { Tcl_SetObjResult(interp, Tcl_NewStringObj("active", TCL_INDEX_NONE)); return TCL_OK; } /* * Inactive coroutines are classified by the (effective) command used to * suspend them, which matters when you're injecting a probe. */ switch (corPtr->nargs) { case COROUTINE_ARGUMENTS_SINGLE_OPTIONAL: Tcl_SetObjResult(interp, Tcl_NewStringObj("yield", TCL_INDEX_NONE)); return TCL_OK; case COROUTINE_ARGUMENTS_ARBITRARY: Tcl_SetObjResult(interp, Tcl_NewStringObj("yieldto", TCL_INDEX_NONE)); return TCL_OK; default: Tcl_SetObjResult(interp, Tcl_NewStringObj( "unknown coroutine type", TCL_INDEX_NONE)); Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "BAD_TYPE", (char *)NULL); return TCL_ERROR; } } /* *---------------------------------------------------------------------- * * TclNRCoroInjectObjCmd, TclNRCoroProbeObjCmd -- * * Implementation of [coroinject] and [coroprobe] commands. * *---------------------------------------------------------------------- */ static inline CoroutineData * GetCoroutineFromObj( Tcl_Interp *interp, Tcl_Obj *objPtr, const char *errMsg) { /* * How to get a coroutine from its handle. */ Command *cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, objPtr); if ((!cmdPtr) || (cmdPtr->nreProc2 != TclNRInterpCoroutine)) { Tcl_SetObjResult(interp, Tcl_NewStringObj(errMsg, TCL_INDEX_NONE)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COROUTINE", TclGetString(objPtr), (char *)NULL); return NULL; } return (CoroutineData *)cmdPtr->objClientData2; } static int TclNRCoroInjectObjCmd( TCL_UNUSED(void *), |
︙ | ︙ | |||
9421 9422 9423 9424 9425 9426 9427 | if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "coroName cmd ?arg1 arg2 ...?"); return TCL_ERROR; } corPtr = GetCoroutineFromObj(interp, objv[1], | | | | | | | | | 9446 9447 9448 9449 9450 9451 9452 9453 9454 9455 9456 9457 9458 9459 9460 9461 9462 9463 9464 9465 9466 9467 9468 9469 9470 9471 9472 9473 9474 9475 9476 9477 9478 9479 | if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "coroName cmd ?arg1 arg2 ...?"); return TCL_ERROR; } corPtr = GetCoroutineFromObj(interp, objv[1], "can only inject a command into a coroutine"); if (!corPtr) { return TCL_ERROR; } if (!COR_IS_SUSPENDED(corPtr)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "can only inject a command into a suspended coroutine", TCL_INDEX_NONE)); Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ACTIVE", (char *)NULL); return TCL_ERROR; } /* * Add the callback to the coro's execEnv, so that it is the first thing * to happen when the coro is resumed. */ ExecEnv *savedEEPtr = iPtr->execEnvPtr; iPtr->execEnvPtr = corPtr->eePtr; TclNRAddCallback(interp, InjectHandler, corPtr, Tcl_NewListObj(objc - 2, objv + 2), INT2PTR(corPtr->nargs), NULL); iPtr->execEnvPtr = savedEEPtr; return TCL_OK; } static int TclNRCoroProbeObjCmd( |
︙ | ︙ | |||
9466 9467 9468 9469 9470 9471 9472 | if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "coroName cmd ?arg1 arg2 ...?"); return TCL_ERROR; } corPtr = GetCoroutineFromObj(interp, objv[1], | | | | | | | | | | | 9491 9492 9493 9494 9495 9496 9497 9498 9499 9500 9501 9502 9503 9504 9505 9506 9507 9508 9509 9510 9511 9512 9513 9514 9515 9516 9517 9518 9519 9520 9521 9522 9523 9524 9525 9526 9527 9528 9529 9530 9531 9532 9533 9534 9535 9536 | if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "coroName cmd ?arg1 arg2 ...?"); return TCL_ERROR; } corPtr = GetCoroutineFromObj(interp, objv[1], "can only inject a probe command into a coroutine"); if (!corPtr) { return TCL_ERROR; } if (!COR_IS_SUSPENDED(corPtr)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "can only inject a probe command into a suspended coroutine", TCL_INDEX_NONE)); Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ACTIVE", (char *)NULL); return TCL_ERROR; } /* * Add the callback to the coro's execEnv, so that it is the first thing * to happen when the coro is resumed. */ ExecEnv *savedEEPtr = iPtr->execEnvPtr; iPtr->execEnvPtr = corPtr->eePtr; TclNRAddCallback(interp, InjectHandler, corPtr, Tcl_NewListObj(objc - 2, objv + 2), INT2PTR(corPtr->nargs), corPtr); iPtr->execEnvPtr = savedEEPtr; /* * Now we immediately transfer control to the coroutine to run our probe. * TRICKY STUFF copied from the [yield] implementation. * * Push the callback to restore the caller's context on yield back. */ TclNRAddCallback(interp, NRCoroutineCallerCallback, corPtr, NULL, NULL, NULL); /* * Record the stackLevel at which the resume is happening, then swap * the interp's environment to make it suitable to run this coroutine. */ corPtr->stackLevel = &corPtr; |
︙ | ︙ | |||
9525 9526 9527 9528 9529 9530 9531 | } /* *---------------------------------------------------------------------- * * InjectHandler, InjectHandlerPostProc -- * | | | | | | | | | | | | 9550 9551 9552 9553 9554 9555 9556 9557 9558 9559 9560 9561 9562 9563 9564 9565 9566 9567 9568 9569 9570 9571 9572 9573 9574 9575 | } /* *---------------------------------------------------------------------- * * InjectHandler, InjectHandlerPostProc -- * * Part of the implementation of [coroinject] and [coroprobe]. These are * run inside the context of the coroutine being injected/probed into. * * InjectHandler runs a script (possibly adding arguments) in the context * of the coroutine. The script is specified as a one-shot list (with * reference count equal to 1) in data[1]. This function also arranges * for InjectHandlerPostProc to be the part that runs after the script * completes. * * InjectHandlerPostProc cleans up after InjectHandler (deleting the * list) and, for the [coroprobe] command *only*, yields back to the * caller context (i.e., where [coroprobe] was run). *s *---------------------------------------------------------------------- */ static int InjectHandler( void *data[], |
︙ | ︙ | |||
9583 9584 9585 9586 9587 9588 9589 | /* * Call the user's script; we're in the right place. */ Tcl_IncrRefCount(listPtr); TclMarkTailcall(interp); TclNRAddCallback(interp, InjectHandlerPostCall, corPtr, listPtr, | | | 9608 9609 9610 9611 9612 9613 9614 9615 9616 9617 9618 9619 9620 9621 9622 | /* * Call the user's script; we're in the right place. */ Tcl_IncrRefCount(listPtr); TclMarkTailcall(interp); TclNRAddCallback(interp, InjectHandlerPostCall, corPtr, listPtr, INT2PTR(nargs), isProbe); TclListObjGetElements(NULL, listPtr, &objc, &objv); return TclNREvalObjv(interp, objc, objv, 0, NULL); } static int InjectHandlerPostCall( void *data[], |
︙ | ︙ | |||
9613 9614 9615 9616 9617 9618 9619 | * If we were doing a probe, splice ourselves back out of the stack * cleanly here. General injection should instead just look after itself. * * Code from guts of [yield] implementation. */ if (isProbe) { | | | | | | | | | | | | | 9638 9639 9640 9641 9642 9643 9644 9645 9646 9647 9648 9649 9650 9651 9652 9653 9654 9655 9656 9657 9658 9659 9660 9661 9662 9663 9664 9665 9666 9667 9668 9669 9670 9671 | * If we were doing a probe, splice ourselves back out of the stack * cleanly here. General injection should instead just look after itself. * * Code from guts of [yield] implementation. */ if (isProbe) { if (result == TCL_ERROR) { Tcl_AddErrorInfo(interp, "\n (injected coroutine probe command)"); } corPtr->nargs = nargs; corPtr->stackLevel = NULL; Tcl_Size numLevels = iPtr->numLevels; iPtr->numLevels = corPtr->auxNumLevels; corPtr->auxNumLevels = numLevels - corPtr->auxNumLevels; iPtr->execEnvPtr = corPtr->callerEEPtr; } return result; } /* *---------------------------------------------------------------------- * * NRInjectObjCmd -- * * Implementation of [::tcl::unsupported::inject] command. * *---------------------------------------------------------------------- */ static int NRInjectObjCmd( TCL_UNUSED(void *), |
︙ | ︙ | |||
9658 9659 9660 9661 9662 9663 9664 | if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "coroName cmd ?arg1 arg2 ...?"); return TCL_ERROR; } corPtr = GetCoroutineFromObj(interp, objv[1], | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 9683 9684 9685 9686 9687 9688 9689 9690 9691 9692 9693 9694 9695 9696 9697 9698 9699 9700 9701 9702 9703 9704 9705 9706 9707 9708 9709 9710 9711 9712 9713 9714 9715 9716 9717 9718 9719 9720 9721 9722 9723 9724 9725 9726 9727 9728 9729 9730 9731 9732 9733 9734 9735 9736 9737 9738 9739 9740 9741 9742 9743 9744 9745 9746 9747 9748 9749 9750 9751 9752 9753 9754 9755 9756 9757 9758 9759 9760 9761 9762 9763 9764 9765 9766 9767 9768 9769 9770 9771 9772 9773 9774 9775 9776 9777 9778 9779 9780 | if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "coroName cmd ?arg1 arg2 ...?"); return TCL_ERROR; } corPtr = GetCoroutineFromObj(interp, objv[1], "can only inject a command into a coroutine"); if (!corPtr) { return TCL_ERROR; } if (!COR_IS_SUSPENDED(corPtr)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "can only inject a command into a suspended coroutine", TCL_INDEX_NONE)); Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "ACTIVE", (char *)NULL); return TCL_ERROR; } /* * Add the callback to the coro's execEnv, so that it is the first thing * to happen when the coro is resumed. */ iPtr->execEnvPtr = corPtr->eePtr; TclNRAddCallback(interp, TclNREvalList, Tcl_NewListObj(objc - 2, objv + 2), NULL, NULL, NULL); iPtr->execEnvPtr = savedEEPtr; return TCL_OK; } int TclNRInterpCoroutine( void *clientData, Tcl_Interp *interp, /* Current interpreter. */ Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { CoroutineData *corPtr = (CoroutineData *)clientData; if (!COR_IS_SUSPENDED(corPtr)) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "coroutine \"%s\" is already running", TclGetString(objv[0]))); Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "BUSY", (char *)NULL); return TCL_ERROR; } /* * Parse all the arguments to work out what to feed as the result of the * [yield]. TRICKY POINT: objc==0 happens here! It occurs when a coroutine * is deleted! */ switch (corPtr->nargs) { case COROUTINE_ARGUMENTS_SINGLE_OPTIONAL: if (objc == 2) { Tcl_SetObjResult(interp, objv[1]); } else if (objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "?arg?"); return TCL_ERROR; } break; default: if (corPtr->nargs + 1 != objc) { Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong coro nargs; how did we get here? " "not implemented!", TCL_INDEX_NONE)); Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", (char *)NULL); return TCL_ERROR; } /* fallthrough */ case COROUTINE_ARGUMENTS_ARBITRARY: if (objc > 1) { Tcl_SetObjResult(interp, Tcl_NewListObj(objc - 1, objv + 1)); } break; } TclNRAddCallback(interp, TclNRCoroutineActivateCallback, corPtr, NULL, NULL, NULL); return TCL_OK; } /* *---------------------------------------------------------------------- * * TclNRCoroutineObjCmd -- * * Implementation of [coroutine] command; see documentation for * description of what this does. * *---------------------------------------------------------------------- */ int TclNRCoroutineObjCmd( TCL_UNUSED(void *), |
︙ | ︙ | |||
9771 9772 9773 9774 9775 9776 9777 | procName = TclGetString(objv[1]); TclGetNamespaceForQualName(interp, procName, inNsPtr, 0, &nsPtr, &altNsPtr, &cxtNsPtr, &simpleName); if (nsPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( | | | | | | | | 9796 9797 9798 9799 9800 9801 9802 9803 9804 9805 9806 9807 9808 9809 9810 9811 9812 9813 9814 9815 9816 9817 9818 9819 | procName = TclGetString(objv[1]); TclGetNamespaceForQualName(interp, procName, inNsPtr, 0, &nsPtr, &altNsPtr, &cxtNsPtr, &simpleName); if (nsPtr == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't create procedure \"%s\": unknown namespace", procName)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE", (char *)NULL); return TCL_ERROR; } if (simpleName == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't create procedure \"%s\": bad procedure name", procName)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", procName, (char *)NULL); return TCL_ERROR; } /* * We ARE creating the coroutine command: allocate the corresponding * struct and create the corresponding command. */ |
︙ | ︙ | |||
9872 9873 9874 9875 9876 9877 9878 | iPtr->execEnvPtr = corPtr->callerEEPtr; /* * Now just resume the coroutine. */ TclNRAddCallback(interp, TclNRCoroutineActivateCallback, corPtr, | | | 9897 9898 9899 9900 9901 9902 9903 9904 9905 9906 9907 9908 9909 9910 9911 | iPtr->execEnvPtr = corPtr->callerEEPtr; /* * Now just resume the coroutine. */ TclNRAddCallback(interp, TclNRCoroutineActivateCallback, corPtr, NULL, NULL, NULL); return TCL_OK; } /* * This is used in the [info] ensemble */ |
︙ | ︙ |
Changes to generic/tclBinary.c.
︙ | ︙ | |||
553 554 555 556 557 558 559 | } SET_BYTEARRAY(&ir, byteArrayPtr); Tcl_StoreInternalRep(objPtr, &properByteArrayType, &ir); } Tcl_IncrRefCount(objPtr); return objPtr; } | < | 553 554 555 556 557 558 559 560 561 562 563 564 565 566 | } SET_BYTEARRAY(&ir, byteArrayPtr); Tcl_StoreInternalRep(objPtr, &properByteArrayType, &ir); } Tcl_IncrRefCount(objPtr); return objPtr; } /* *---------------------------------------------------------------------- * * SetByteArrayFromAny -- * * Generate the ByteArray internal rep from the string rep. |
︙ | ︙ |
Changes to generic/tclCkalloc.c.
︙ | ︙ | |||
715 716 717 718 719 720 721 | if (newPtr == NULL) { return NULL; } memcpy(newPtr, ptr, copySize); Tcl_DbCkfree(ptr, file, line); return newPtr; } | < | 715 716 717 718 719 720 721 722 723 724 725 726 727 728 | if (newPtr == NULL) { return NULL; } memcpy(newPtr, ptr, copySize); Tcl_DbCkfree(ptr, file, line); return newPtr; } /* *---------------------------------------------------------------------- * * Tcl_Alloc, et al. -- * * These functions are defined in terms of the debugging versions when |
︙ | ︙ | |||
1006 1007 1008 1009 1010 1011 1012 | * added */ { TclInitDbCkalloc(); Tcl_CreateObjCommand2(interp, "memory", MemoryCmd, NULL, NULL); Tcl_CreateObjCommand2(interp, "checkmem", CheckmemCmd, NULL, NULL); } | < < | 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 | * added */ { TclInitDbCkalloc(); Tcl_CreateObjCommand2(interp, "memory", MemoryCmd, NULL, NULL); Tcl_CreateObjCommand2(interp, "checkmem", CheckmemCmd, NULL, NULL); } #else /* TCL_MEM_DEBUG */ /* This is the !TCL_MEM_DEBUG case */ #undef Tcl_InitMemory #undef Tcl_DumpActiveMemory #undef Tcl_ValidateAllMemory /* *---------------------------------------------------------------------- * * Tcl_Alloc -- * * Interface to TclpAlloc when TCL_MEM_DEBUG is disabled. It does check |
︙ | ︙ | |||
1249 1250 1251 1252 1253 1254 1255 | * Panics if memory of at least the requested size could not be * allocated. * *------------------------------------------------------------------------ */ void * TclAllocElemsEx( | | | | | | | 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 | * Panics if memory of at least the requested size could not be * allocated. * *------------------------------------------------------------------------ */ void * TclAllocElemsEx( Tcl_Size elemCount, /* Allocation will store at least these many... */ Tcl_Size elemSize, /* ...elements of this size */ Tcl_Size leadSize, /* Additional leading space in bytes */ Tcl_Size *capacityPtr) /* OUTPUT: Actual capacity is stored here if * non-NULL. Only modified on success */ { void *ptr = TclAttemptReallocElemsEx( NULL, elemCount, elemSize, leadSize, capacityPtr); if (ptr == NULL) { Tcl_Panic("Failed to allocate %" TCL_SIZE_MODIFIER "d elements of size %" TCL_SIZE_MODIFIER "d bytes.", elemCount, |
︙ | ︙ | |||
1284 1285 1286 1287 1288 1289 1290 | * Pointer to allocated memory block which is at least as large * as the requested size or NULL if allocation failed. * *------------------------------------------------------------------------ */ void * TclAttemptReallocElemsEx( | | | | | | | | | 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 | * Pointer to allocated memory block which is at least as large * as the requested size or NULL if allocation failed. * *------------------------------------------------------------------------ */ void * TclAttemptReallocElemsEx( void *oldPtr, /* Pointer to memory block to reallocate or * NULL to indicate this is a new allocation */ Tcl_Size elemCount, /* Allocation will store at least these many... */ Tcl_Size elemSize, /* ...elements of this size */ Tcl_Size leadSize, /* Additional leading space in bytes */ Tcl_Size *capacityPtr) /* OUTPUT: Actual capacity is stored here if * non-NULL. Only modified on success */ { void *ptr; Tcl_Size limit; Tcl_Size attempt; assert(elemCount > 0); assert(elemSize > 0); |
︙ | ︙ | |||
1354 1355 1356 1357 1358 1359 1360 | * Panics if memory of at least the requested size could not be * allocated. * *------------------------------------------------------------------------ */ void * TclReallocElemsEx( | | | | | | | | 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 | * Panics if memory of at least the requested size could not be * allocated. * *------------------------------------------------------------------------ */ void * TclReallocElemsEx( void *oldPtr, /* Pointer to memory block to reallocate */ Tcl_Size elemCount, /* Allocation will store at least these many... */ Tcl_Size elemSize, /* ...elements of this size */ Tcl_Size leadSize, /* Additional leading space in bytes */ Tcl_Size *capacityPtr) /* OUTPUT: Actual capacity is stored here if * non-NULL. Only modified on success */ { void *ptr = TclAttemptReallocElemsEx( oldPtr, elemCount, elemSize, leadSize, capacityPtr); if (ptr == NULL) { Tcl_Panic("Failed to reallocate %" TCL_SIZE_MODIFIER "d elements of size %" TCL_SIZE_MODIFIER "d bytes.", elemCount, |
︙ | ︙ |
Changes to generic/tclClock.c.
︙ | ︙ | |||
1960 1961 1962 1963 1964 1965 1966 | } ltzoc->localSeconds = fields->localSeconds; ltzoc->rangesVal[0] = rangesVal[0]; ltzoc->rangesVal[1] = rangesVal[1]; ltzoc->tzOffset = fields->tzOffset; } | < | 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 | } ltzoc->localSeconds = fields->localSeconds; ltzoc->rangesVal[0] = rangesVal[0]; ltzoc->rangesVal[1] = rangesVal[1]; ltzoc->tzOffset = fields->tzOffset; } /* check DST-hole: if retrieved seconds is out of range */ if (ltzoc->rangesVal[0] > seconds || seconds >= ltzoc->rangesVal[1]) { dstHole: #if 0 printf("given local-time is outside the time-zone (in DST-hole): " "%d - offs %d => %d <= %d < %d\n", (int)fields->localSeconds, fields->tzOffset, |
︙ | ︙ | |||
2896 2897 2898 2899 2900 2901 2902 | * * Side effects: * Stores day number in 'julianDay' * *---------------------------------------------------------------------- */ | < | 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 | * * Side effects: * Stores day number in 'julianDay' * *---------------------------------------------------------------------- */ void GetJulianDayFromEraYearDay( TclDateFields *fields, /* Date to convert */ int changeover) /* Gregorian transition date as a Julian Day */ { Tcl_WideInt year, ym1; |
︙ | ︙ | |||
4246 4247 4248 4249 4250 4251 4252 | yydate.julianDay -= 7; } info->flags |= CLF_ASSEMBLE_DATE|CLF_ASSEMBLE_SECONDS; } return TCL_OK; } | < | 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 | yydate.julianDay -= 7; } info->flags |= CLF_ASSEMBLE_DATE|CLF_ASSEMBLE_SECONDS; } return TCL_OK; } /*---------------------------------------------------------------------- * * ClockWeekdaysOffs -- * * Get offset in days for the number of week days corresponding the * given day of week (skipping Saturdays and Sundays). |
︙ | ︙ | |||
4305 4306 4307 4308 4309 4310 4311 | /* adjust if we end up on a weekend */ if (resDayOfWeek > 5) { offs += 2; } return offs; } | < < | 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 | /* adjust if we end up on a weekend */ if (resDayOfWeek > 5) { offs += 2; } return offs; } /*---------------------------------------------------------------------- * * ClockAddObjCmd -- , clock add -- * * Adds an offset to a given time. * |
︙ | ︙ |
Changes to generic/tclClockFmt.c.
︙ | ︙ | |||
2136 2137 2138 2139 2140 2141 2142 | } else { tokcnt += tokcnt; } } return ++tokcnt; } | | | | < < < | | | | 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 | } else { tokcnt += tokcnt; } } return ++tokcnt; } #define AllocTokenInChain(tok, chain, tokCnt, type) \ if (++(tok) >= (chain) + (tokCnt)) { \ chain = (type)Tcl_Realloc((char *)(chain), \ (tokCnt + CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE) * sizeof(*(tok))); \ (tok) = (chain) + (tokCnt); \ (tokCnt) += CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE; \ } \ memset(tok, 0, sizeof(*(tok))); /* *---------------------------------------------------------------------- */ ClockFmtScnStorage * ClockGetOrParseScanFormat( |
︙ | ︙ | |||
2278 2279 2280 2281 2282 2283 2284 | /* next token */ AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *); tokCnt++; p++; continue; } default: | | | | > | | > | > > | > | > > > > | | > < < < < < | 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 | /* next token */ AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *); tokCnt++; p++; continue; } default: if (isspace(UCHAR(*p))) { tok->map = &ScnSpaceTokenMap; tok->tokWord.start = p++; while (p < e && isspace(UCHAR(*p))) { p++; } tok->tokWord.end = p; /* increase space count used in format */ fss->scnSpaceCount++; /* next token */ AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *); tokCnt++; continue; } word_tok: { /* try continue with previous word token */ ClockScanToken *wordTok = tok - 1; if (wordTok < scnTok || wordTok->map != &ScnWordTokenMap) { /* start with new word token */ wordTok = tok; wordTok->tokWord.start = p; wordTok->map = &ScnWordTokenMap; } do { if (isspace(UCHAR(*p))) { fss->scnSpaceCount++; } p = Tcl_UtfNext(p); } while (p < e && *p != '%'); wordTok->tokWord.end = p; if (wordTok == tok) { AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *); tokCnt++; } } break; } } /* calculate end distance value for each tokens */ if (tok > scnTok) { unsigned endDist = 0; ClockScanToken *prevTok = tok - 1; |
︙ | ︙ | |||
2345 2346 2347 2348 2349 2350 2351 | } } /* now we're ready - assign now to storage (note the threaded race condition) */ fss->scnTok = scnTok; fss->scnTokC = tokCnt; } | | < | 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 | } } /* now we're ready - assign now to storage (note the threaded race condition) */ fss->scnTok = scnTok; fss->scnTokC = tokCnt; } Tcl_MutexUnlock(&ClockFmtMutex); return fss; } /* *---------------------------------------------------------------------- */ int |
︙ | ︙ | |||
3331 3332 3333 3334 3335 3336 3337 | /* next token */ AllocTokenInChain(tok, fmtTok, fss->fmtTokC, ClockFormatToken *); tokCnt++; p++; continue; } default: | | > > | | > | > > > | > | | > < < < | > | | 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 | /* next token */ AllocTokenInChain(tok, fmtTok, fss->fmtTokC, ClockFormatToken *); tokCnt++; p++; continue; } default: word_tok: { /* try continue with previous word token */ ClockFormatToken *wordTok = tok - 1; if (wordTok < fmtTok || wordTok->map != &FmtWordTokenMap) { /* start with new word token */ wordTok = tok; wordTok->tokWord.start = p; wordTok->map = &FmtWordTokenMap; } do { p = Tcl_UtfNext(p); } while (p < e && *p != '%'); wordTok->tokWord.end = p; if (wordTok == tok) { AllocTokenInChain(tok, fmtTok, fss->fmtTokC, ClockFormatToken *); tokCnt++; } } break; } } /* correct count of real used tokens and free mem if desired * (1 is acceptable delta to prevent memory fragmentation) */ if (fss->fmtTokC > tokCnt + (CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE / 2)) { if ((tok = (ClockFormatToken *) Tcl_AttemptRealloc(fmtTok, tokCnt * sizeof(*tok))) != NULL) { fmtTok = tok; } } /* now we're ready - assign now to storage (note the threaded race condition) */ fss->fmtTok = fmtTok; fss->fmtTokC = tokCnt; } Tcl_MutexUnlock(&ClockFmtMutex); return fss; } /* *---------------------------------------------------------------------- */ |
︙ | ︙ | |||
3556 3557 3558 3559 3560 3561 3562 | { Tcl_MutexLock(&ClockFmtMutex); /* clear caches ... */ Tcl_MutexUnlock(&ClockFmtMutex); } void | | | 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 | { Tcl_MutexLock(&ClockFmtMutex); /* clear caches ... */ Tcl_MutexUnlock(&ClockFmtMutex); } void ClockFrmScnFinalize(void) { if (!initialized) { return; } Tcl_MutexLock(&ClockFmtMutex); #if CLOCK_FMT_SCN_STORAGE_GC_SIZE > 0 /* clear GC */ |
︙ | ︙ |
Changes to generic/tclCmdIL.c.
︙ | ︙ | |||
5286 5287 5288 5289 5290 5291 5292 | /* * Once an error has occurred, skip any future comparisons so as * to preserve the error message in sortInterp->result. */ return 0; } | < | 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 | /* * Once an error has occurred, skip any future comparisons so as * to preserve the error message in sortInterp->result. */ return 0; } objPtr1 = elemPtr1->collationKey.objValuePtr; objPtr2 = elemPtr2->collationKey.objValuePtr; paramObjv[0] = objPtr1; paramObjv[1] = objPtr2; |
︙ | ︙ |
Changes to generic/tclCompCmds.c.
︙ | ︙ | |||
653 654 655 656 657 658 659 | /* drop the script */ dropScript = 1; TclEmitInstInt4( INST_REVERSE, 2, envPtr); TclEmitOpcode( INST_POP, envPtr); } ExceptionRangeEnds(envPtr, range); | < < | 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 | /* drop the script */ dropScript = 1; TclEmitInstInt4( INST_REVERSE, 2, envPtr); TclEmitOpcode( INST_POP, envPtr); } ExceptionRangeEnds(envPtr, range); /* * Emit the "no errors" epilogue: push "0" (TCL_OK) as the catch result, * and jump around the "error case" code. */ TclCheckStackDepth(depth+1, envPtr); PushStringLiteral(envPtr, "0"); TclEmitForwardJump(envPtr, TCL_UNCONDITIONAL_JUMP, &jumpFixup); /* * Emit the "error case" epilogue. Push the interpreter result and the * return code. */ ExceptionRangeTarget(envPtr, range, catchOffset); TclSetStackDepth(depth + dropScript, envPtr); if (dropScript) { TclEmitOpcode( INST_POP, envPtr); } /* Stack at this point is empty */ TclEmitOpcode( INST_PUSH_RESULT, envPtr); TclEmitOpcode( INST_PUSH_RETURN_CODE, envPtr); /* Stack at this point on both branches: result returnCode */ |
︙ | ︙ | |||
787 788 789 790 791 792 793 | return TCL_ERROR; } default: return TCL_ERROR; } return TCL_OK; } | < | 785 786 787 788 789 790 791 792 793 794 795 796 797 798 | return TCL_ERROR; } default: return TCL_ERROR; } return TCL_OK; } /*---------------------------------------------------------------------- * * TclCompileClockReadingCmd -- * * Procedure called to compile the "tcl::clock::microseconds", * "tcl::clock::milliseconds" and "tcl::clock::seconds" commands. |
︙ | ︙ | |||
2846 2847 2848 2849 2850 2851 2852 | infoPtr->numLists++; for (j = 0; j < numVars; j++) { Tcl_Obj *varNameObj; const char *bytes; int varIndex; Tcl_Size length; | < | 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 | infoPtr->numLists++; for (j = 0; j < numVars; j++) { Tcl_Obj *varNameObj; const char *bytes; int varIndex; Tcl_Size length; Tcl_ListObjIndex(NULL, varListObj, j, &varNameObj); bytes = TclGetStringFromObj(varNameObj, &length); varIndex = LocalScalar(bytes, length, envPtr); if (varIndex < 0) { code = TCL_ERROR; goto done; |
︙ | ︙ |
Changes to generic/tclCompCmdsSZ.c.
︙ | ︙ | |||
97 98 99 100 101 102 103 | TclStoreInt1AtPtr(CurrentOffset(envPtr)-(var),envPtr->codeStart+(var)+1) #define LOAD(idx) \ if ((idx)<256) {OP1(LOAD_SCALAR1,(idx));} else {OP4(LOAD_SCALAR4,(idx));} #define STORE(idx) \ if ((idx)<256) {OP1(STORE_SCALAR1,(idx));} else {OP4(STORE_SCALAR4,(idx));} #define INVOKE(name) \ TclEmitInvoke(envPtr,INST_##name) | < | 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | TclStoreInt1AtPtr(CurrentOffset(envPtr)-(var),envPtr->codeStart+(var)+1) #define LOAD(idx) \ if ((idx)<256) {OP1(LOAD_SCALAR1,(idx));} else {OP4(LOAD_SCALAR4,(idx));} #define STORE(idx) \ if ((idx)<256) {OP1(STORE_SCALAR1,(idx));} else {OP4(STORE_SCALAR4,(idx));} #define INVOKE(name) \ TclEmitInvoke(envPtr,INST_##name) /* *---------------------------------------------------------------------- * * TclCompileSetCmd -- * * Procedure called to compile the "set" command. |
︙ | ︙ |
Changes to generic/tclCompExpr.c.
︙ | ︙ | |||
1920 1921 1922 1923 1924 1925 1926 | static Tcl_Size ParseLexeme( const char *start, /* Start of lexeme to parse. */ Tcl_Size numBytes, /* Number of bytes in string. */ unsigned char *lexemePtr, /* Write code of parsed lexeme to this * storage. */ Tcl_Obj **literalPtr) /* Write corresponding literal value to this | | | 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 | static Tcl_Size ParseLexeme( const char *start, /* Start of lexeme to parse. */ Tcl_Size numBytes, /* Number of bytes in string. */ unsigned char *lexemePtr, /* Write code of parsed lexeme to this * storage. */ Tcl_Obj **literalPtr) /* Write corresponding literal value to this * storage, if non-NULL. */ { const char *end; int ch; Tcl_Obj *literal = NULL; unsigned char byte; if (numBytes == 0) { |
︙ | ︙ |
Changes to generic/tclCompile.h.
︙ | ︙ | |||
85 86 87 88 89 90 91 | CATCH_EXCEPTION_RANGE /* Exception's range is controlled by a catch * command. Errors in the range cause a jump * to a catch PC offset. */ } ExceptionRangeType; typedef struct { ExceptionRangeType type; /* The kind of ExceptionRange. */ | | | | | | | | | | | | | | > | > | | | | | | | | | | | | | | 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 | CATCH_EXCEPTION_RANGE /* Exception's range is controlled by a catch * command. Errors in the range cause a jump * to a catch PC offset. */ } ExceptionRangeType; typedef struct { ExceptionRangeType type; /* The kind of ExceptionRange. */ Tcl_Size nestingLevel; /* Static depth of the exception range. Used * to find the most deeply-nested range * surrounding a PC at runtime. */ Tcl_Size codeOffset; /* Offset of the first instruction byte of the * code range. */ Tcl_Size numCodeBytes; /* Number of bytes in the code range. */ Tcl_Size breakOffset; /* If LOOP_EXCEPTION_RANGE, the target PC * offset for a break command in the range. */ Tcl_Size continueOffset; /* If LOOP_EXCEPTION_RANGE and not TCL_INDEX_NONE, * the target PC offset for a continue command * in the code range. Otherwise, ignore this * range when processing a continue * command. */ Tcl_Size catchOffset; /* If a CATCH_EXCEPTION_RANGE, the target PC * offset for any "exception" in range. */ } ExceptionRange; /* * Auxiliary data used when issuing (currently just loop) exception ranges, * but which is not required during execution. */ typedef struct ExceptionAux { int supportsContinue; /* Whether this exception range will have a * continueOffset created for it; if it is a * loop exception range that *doesn't* have * one (see [for] next-clause) then we must * not pick up the range when scanning for a * target to continue to. */ Tcl_Size stackDepth; /* The stack depth at the point where the * exception range was created. This is used * to calculate the number of POPs required to * restore the stack to its prior state. */ Tcl_Size expandTarget; /* The number of expansions expected on the * auxData stack at the time the loop starts; * we can't currently discard them except by * doing INST_INVOKE_EXPANDED; this is a known * problem. */ Tcl_Size expandTargetDepth; /* The stack depth expected at the outermost * expansion within the loop. Not meaningful * if there are no open expansions between the * looping level and the point of jump * issue. */ Tcl_Size numBreakTargets; /* The number of [break]s that want to be * targeted to the place where this loop * exception will be bound to. */ TCL_HASH_TYPE *breakTargets;/* The offsets of the INST_JUMP4 instructions * issued by the [break]s that we must * update. Note that resizing a jump (via * TclFixupForwardJump) can cause the contents * of this array to be updated. When * numBreakTargets==0, this is NULL. */ Tcl_Size allocBreakTargets; /* The size of the breakTargets array. */ Tcl_Size numContinueTargets;/* The number of [continue]s that want to be * targeted to the place where this loop * exception will be bound to. */ TCL_HASH_TYPE *continueTargets; /* The offsets of the INST_JUMP4 instructions * issued by the [continue]s that we must * update. Note that resizing a jump (via * TclFixupForwardJump) can cause the contents * of this array to be updated. When * numContinueTargets==0, this is NULL. */ Tcl_Size allocContinueTargets; /* The size of the continueTargets array. */ } ExceptionAux; /* * Structure used to map between instruction pc and source locations. It * defines for each compiled Tcl command its code's starting offset and its * source's starting offset and length. Note that the code offset increases * monotonically: that is, the table is sorted in code offset order. The * source offset is not monotonic. */ typedef struct { Tcl_Size codeOffset; /* Offset of first byte of command code. */ Tcl_Size numCodeBytes; /* Number of bytes for command's code. */ Tcl_Size srcOffset; /* Offset of first char of the command. */ Tcl_Size numSrcBytes; /* Number of command source chars. */ } CmdLocation; /* * TIP #280 * Structure to record additional location information for byte code. This * information is internal and not saved. i.e. tbcload'ed code will not have * this information. It records the lines for all words of all commands found * in the byte code. The association with a ByteCode structure BC is done * through the 'lineBCPtr' HashTable in Interp, keyed by the address of BC. * Also recorded is information coming from the context, i.e. type of the * frame and associated information, like the path of a sourced file. */ typedef struct { Tcl_Size srcOffset; /* Command location to find the entry. */ Tcl_Size nline; /* Number of words in the command */ Tcl_Size *line; /* Line information for all words in the * command. */ Tcl_Size **next; /* Transient information used by the compiler * for tracking of hidden continuation * lines. */ } ECL; typedef struct { int type; /* Context type. */ Tcl_Size start; /* Starting line for compiled script. Needed * for the extended recompile check in * tclCompileObj. */ Tcl_Obj *path; /* Path of the sourced file the command is * in. */ ECL *loc; /* Command word locations (lines). */ Tcl_Size nloc; /* Number of allocated entries in 'loc'. */ Tcl_Size nuloc; /* Number of used entries in 'loc'. */ } ExtCmdLoc; /* * CompileProcs need the ability to record information during compilation that * can be used by bytecode instructions during execution. The AuxData * structure provides this "auxiliary data" mechanism. An arbitrary number of * these structures can be stored in the ByteCode record (during compilation * they are stored in a CompileEnv structure). Each AuxData record holds one * word of client-specified data (often a pointer) and is given an index that * instructions can later use to look up the structure and its data. * * The following definitions declare the types of procedures that are called * to duplicate or free this auxiliary data when the containing ByteCode * objects are duplicated and freed. Pointers to these procedures are kept in * the AuxData structure. */ typedef void * (AuxDataDupProc) (void *clientData); typedef void (AuxDataFreeProc) (void *clientData); typedef void (AuxDataPrintProc) (void *clientData, Tcl_Obj *appendObj, struct ByteCode *codePtr, TCL_HASH_TYPE pcOffset); /* * We define a separate AuxDataType struct to hold type-related information * for the AuxData structure. This separation makes it possible for clients * outside of the TCL core to manipulate (in a limited fashion!) AuxData; for * example, it makes it possible to pickle and unpickle AuxData structs. */ |
︙ | ︙ | |||
262 263 264 265 266 267 268 | * during compilation by CompileProcs and used by instructions during * execution. */ typedef struct AuxData { const AuxDataType *type; /* Pointer to the AuxData type associated with * this ClientData. */ | | | 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 | * during compilation by CompileProcs and used by instructions during * execution. */ typedef struct AuxData { const AuxDataType *type; /* Pointer to the AuxData type associated with * this ClientData. */ void *clientData; /* The compilation data itself. */ } AuxData; /* * Structure defining the compilation environment. After compilation, fields * describing bytecode instructions are copied out into the more compact * ByteCode structure defined below. */ |
︙ | ︙ | |||
286 287 288 289 290 291 292 | * compiled. Commands and their compile procs * are specific to an interpreter so the code * emitted will depend on the interpreter. */ const char *source; /* The source string being compiled by * SetByteCodeFromAny. This pointer is not * owned by the CompileEnv and must not be * freed or changed by it. */ | | | | > | | | > | | | 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 | * compiled. Commands and their compile procs * are specific to an interpreter so the code * emitted will depend on the interpreter. */ const char *source; /* The source string being compiled by * SetByteCodeFromAny. This pointer is not * owned by the CompileEnv and must not be * freed or changed by it. */ Tcl_Size numSrcBytes; /* Number of bytes in source. */ Proc *procPtr; /* If a procedure is being compiled, a pointer * to its Proc structure; otherwise NULL. Used * to compile local variables. Set from * information provided by ObjInterpProc in * tclProc.c. */ Tcl_Size numCommands; /* Number of commands compiled. */ Tcl_Size exceptDepth; /* Current exception range nesting level; * TCL_INDEX_NONE if not in any range * currently. */ Tcl_Size maxExceptDepth; /* Max nesting level of exception ranges; * TCL_INDEX_NONE if no ranges have been * compiled. */ Tcl_Size maxStackDepth; /* Maximum number of stack elements needed to * execute the code. Set by compilation * procedures before returning. */ Tcl_Size currStackDepth; /* Current stack depth. */ LiteralTable localLitTable; /* Contains LiteralEntry's describing all Tcl * objects referenced by this compiled code. * Indexed by the string representations of * the literals. Used to avoid creating * duplicate objects. */ unsigned char *codeStart; /* Points to the first byte of the code. */ unsigned char *codeNext; /* Points to next code array byte to use. */ |
︙ | ︙ | |||
327 328 329 330 331 332 333 | ExceptionRange *exceptArrayPtr; /* Points to start of the ExceptionRange * array. */ Tcl_Size exceptArrayNext; /* Next free ExceptionRange array index. * exceptArrayNext is the number of ranges and * (exceptArrayNext-1) is the index of the * current range's array entry. */ | | | 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 | ExceptionRange *exceptArrayPtr; /* Points to start of the ExceptionRange * array. */ Tcl_Size exceptArrayNext; /* Next free ExceptionRange array index. * exceptArrayNext is the number of ranges and * (exceptArrayNext-1) is the index of the * current range's array entry. */ Tcl_Size exceptArrayEnd; /* Index after the last ExceptionRange array * entry. */ ExceptionAux *exceptAuxArrayPtr; /* Array of information used to restore the * state when processing BREAK/CONTINUE * exceptions. Must be the same size as the * exceptArrayPtr. */ CmdLocation *cmdMapPtr; /* Points to start of CmdLocation array. |
︙ | ︙ | |||
365 366 367 368 369 370 371 | CmdLocation staticCmdMapSpace[COMPILEENV_INIT_CMD_MAP_SIZE]; /* Initial storage for cmd location map. */ AuxData staticAuxDataArraySpace[COMPILEENV_INIT_AUX_DATA_SIZE]; /* Initial storage for aux data array. */ /* TIP #280 */ ExtCmdLoc *extCmdMapPtr; /* Extended command location information for * 'info frame'. */ | | | | | 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 | CmdLocation staticCmdMapSpace[COMPILEENV_INIT_CMD_MAP_SIZE]; /* Initial storage for cmd location map. */ AuxData staticAuxDataArraySpace[COMPILEENV_INIT_AUX_DATA_SIZE]; /* Initial storage for aux data array. */ /* TIP #280 */ ExtCmdLoc *extCmdMapPtr; /* Extended command location information for * 'info frame'. */ Tcl_Size line; /* First line of the script, based on the * invoking context, then the line of the * command currently compiled. */ int atCmdStart; /* Flag to say whether an INST_START_CMD * should be issued; they should never be * issued repeatedly, as that is significantly * inefficient. If set to 2, that instruction * should not be issued at all (by the generic * part of the command compiler). */ Tcl_Size expandCount; /* Number of INST_EXPAND_START instructions * encountered that have not yet been paired * with a corresponding * INST_INVOKE_EXPANDED. */ Tcl_Size *clNext; /* If not NULL, it refers to the next slot in * clLoc to check for an invisible * continuation line. */ } CompileEnv; /* * The structure defining the bytecode instructions resulting from compiling a * Tcl script. Note that this structure is variable length: a single heap |
︙ | ︙ | |||
413 414 415 416 417 418 419 | typedef struct ByteCode { TclHandle interpHandle; /* Handle for interpreter containing the * compiled code. Commands and their compile * procs are specific to an interpreter so the * code emitted will depend on the * interpreter. */ | | | 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 | typedef struct ByteCode { TclHandle interpHandle; /* Handle for interpreter containing the * compiled code. Commands and their compile * procs are specific to an interpreter so the * code emitted will depend on the * interpreter. */ Tcl_Size compileEpoch; /* Value of iPtr->compileEpoch when this * ByteCode was compiled. Used to invalidate * code when, e.g., commands with compile * procs are redefined. */ Namespace *nsPtr; /* Namespace context in which this code was * compiled. If the code is executed if a * different namespace, it must be * recompiled. */ |
︙ | ︙ | |||
445 446 447 448 449 450 451 | * Proc structure; otherwise NULL. This * pointer is also not owned by the ByteCode * and must not be freed by it. */ size_t structureSize; /* Number of bytes in the ByteCode structure * itself. Does not include heap space for * literal Tcl objects or storage referenced * by AuxData entries. */ | | | | | | | | | 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 | * Proc structure; otherwise NULL. This * pointer is also not owned by the ByteCode * and must not be freed by it. */ size_t structureSize; /* Number of bytes in the ByteCode structure * itself. Does not include heap space for * literal Tcl objects or storage referenced * by AuxData entries. */ Tcl_Size numCommands; /* Number of commands compiled. */ Tcl_Size numSrcBytes; /* Number of source bytes compiled. */ Tcl_Size numCodeBytes; /* Number of code bytes. */ Tcl_Size numLitObjects; /* Number of objects in literal array. */ Tcl_Size numExceptRanges; /* Number of ExceptionRange array elems. */ Tcl_Size numAuxDataItems; /* Number of AuxData items. */ Tcl_Size numCmdLocBytes; /* Number of bytes needed for encoded command * location information. */ Tcl_Size maxExceptDepth; /* Maximum nesting level of ExceptionRanges; * TCL_INDEX_NONE if no ranges were compiled. */ Tcl_Size maxStackDepth; /* Maximum number of stack elements needed to * execute the code. */ unsigned char *codeStart; /* Points to the first byte of the code. This * is just after the final ByteCode member * cmdMapPtr. */ Tcl_Obj **objArrayPtr; /* Points to the start of the literal object * array. This is just after the last code * byte. */ |
︙ | ︙ | |||
511 512 513 514 515 516 517 | * variables. */ #ifdef TCL_COMPILE_STATS Tcl_Time createTime; /* Absolute time when the ByteCode was * created. */ #endif /* TCL_COMPILE_STATS */ } ByteCode; | | < < | | | | | 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 | * variables. */ #ifdef TCL_COMPILE_STATS Tcl_Time createTime; /* Absolute time when the ByteCode was * created. */ #endif /* TCL_COMPILE_STATS */ } ByteCode; #define ByteCodeSetInternalRep(objPtr, typePtr, codePtr) \ do { \ Tcl_ObjInternalRep ir; \ ir.twoPtrValue.ptr1 = (codePtr); \ ir.twoPtrValue.ptr2 = NULL; \ Tcl_StoreInternalRep((objPtr), (typePtr), &ir); \ } while (0) #define ByteCodeGetInternalRep(objPtr, typePtr, codePtr) \ do { \ const Tcl_ObjInternalRep *irPtr; \ irPtr = TclFetchInternalRep((objPtr), (typePtr)); \ (codePtr) = irPtr ? (ByteCode*)irPtr->twoPtrValue.ptr1 : NULL; \ } while (0) /* * 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 |
︙ | ︙ | |||
815 816 817 818 819 820 821 | INST_LAPPEND_LIST_ARRAY_STK, INST_LAPPEND_LIST_STK, INST_CLOCK_READ, INST_DICT_GET_DEF, | | | | | | | 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 | INST_LAPPEND_LIST_ARRAY_STK, INST_LAPPEND_LIST_STK, INST_CLOCK_READ, INST_DICT_GET_DEF, /* TIP 461 */ INST_STR_LT, INST_STR_GT, INST_STR_LE, INST_STR_GE, INST_LREPLACE4, /* TIP 667: const */ INST_CONST_IMM, INST_CONST_STK, |
︙ | ︙ | |||
954 955 956 957 958 959 960 | * to 5 bytes. */ } JumpFixup; #define JUMPFIXUP_INIT_ENTRIES 10 typedef struct JumpFixupArray { JumpFixup *fixup; /* Points to start of jump fixup array. */ | | | | > | | | > | 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 | * to 5 bytes. */ } JumpFixup; #define JUMPFIXUP_INIT_ENTRIES 10 typedef struct JumpFixupArray { JumpFixup *fixup; /* Points to start of jump fixup array. */ Tcl_Size next; /* Index of next free array entry. */ Tcl_Size end; /* Index of last usable entry in array. */ int mallocedArray; /* 1 if array was expanded and fixups points * into the heap, else 0. */ JumpFixup staticFixupSpace[JUMPFIXUP_INIT_ENTRIES]; /* Initial storage for jump fixup array. */ } JumpFixupArray; /* * The structure describing one variable list of a foreach command. Note that * only foreach commands inside procedure bodies are compiled inline so a * ForeachVarList structure always describes local variables. Furthermore, * only scalar variables are supported for inline-compiled foreach loops. */ typedef struct ForeachVarList { Tcl_Size numVars; /* The number of variables in the list. */ Tcl_Size varIndexes[TCLFLEXARRAY]; /* An array of the indexes ("slot numbers") * for each variable in the procedure's array * of local variables. Only scalar variables * are supported. The actual size of this * field will be large enough to numVars * indexes. THIS MUST BE THE LAST FIELD IN THE * STRUCTURE! */ } ForeachVarList; /* * Structure used to hold information about a foreach command that is needed * during program execution. These structures are stored in CompileEnv and * ByteCode structures as auxiliary data. */ typedef struct ForeachInfo { Tcl_Size numLists; /* The number of both the variable and value * lists of the foreach command. */ Tcl_Size firstValueTemp; /* Index of the first temp var in a proc frame * used to point to a value list. */ Tcl_Size loopCtTemp; /* Index of temp var in a proc frame holding * the loop's iteration count. Used to * determine next value list element to assign * each loop var. */ ForeachVarList *varLists[TCLFLEXARRAY]; /* An array of pointers to ForeachVarList * structures describing each var list. The * actual size of this field will be large * enough to numVars indexes. THIS MUST BE THE * LAST FIELD IN THE STRUCTURE! */ } ForeachInfo; /* |
︙ | ︙ | |||
1026 1027 1028 1029 1030 1031 1032 | * Structure used to hold information about a [dict update] command that is * needed during program execution. These structures are stored in CompileEnv * and ByteCode structures as auxiliary data. */ typedef struct { Tcl_Size length; /* Size of array */ | | > | 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 | * Structure used to hold information about a [dict update] command that is * needed during program execution. These structures are stored in CompileEnv * and ByteCode structures as auxiliary data. */ typedef struct { Tcl_Size length; /* Size of array */ Tcl_Size varIndices[TCLFLEXARRAY]; /* Array of variable indices to manage when * processing the start and end of a [dict * update]. There is really more than one * entry, and the structure is allocated to * take account of this. MUST BE LAST FIELD IN * STRUCTURE. */ } DictUpdateInfo; |
︙ | ︙ | |||
1185 1186 1187 1188 1189 1190 1191 | #endif MODULE_SCOPE int TclWordKnownAtCompileTime(Tcl_Token *tokenPtr, Tcl_Obj *valuePtr); MODULE_SCOPE void TclLogCommandInfo(Tcl_Interp *interp, const char *script, const char *command, Tcl_Size length, const unsigned char *pc, Tcl_Obj **tosPtr); | | | | 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 | #endif MODULE_SCOPE int TclWordKnownAtCompileTime(Tcl_Token *tokenPtr, Tcl_Obj *valuePtr); MODULE_SCOPE void TclLogCommandInfo(Tcl_Interp *interp, const char *script, const char *command, Tcl_Size length, const unsigned char *pc, Tcl_Obj **tosPtr); MODULE_SCOPE Tcl_Obj * TclGetInnerContext(Tcl_Interp *interp, const unsigned char *pc, Tcl_Obj **tosPtr); MODULE_SCOPE Tcl_Obj * TclNewInstNameObj(unsigned char inst); MODULE_SCOPE int TclPushProcCallFrame(void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], int isLambda); /* *---------------------------------------------------------------- * Macros and flag values used by Tcl bytecode compilation and execution |
︙ | ︙ | |||
1213 1214 1215 1216 1217 1218 1219 | (envPtr)->auxDataArrayPtr[(index)].clientData #define LITERAL_ON_HEAP 0x01 #define LITERAL_CMD_NAME 0x02 #define LITERAL_UNSHARED 0x04 /* | | | | | > | > | | < < | | | < < > > | < | > | | > > > > > | < | > > | | > | < < > > | | | > | > > | | < < | | | | < > | < < > > | | | | | | | | | | 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 | (envPtr)->auxDataArrayPtr[(index)].clientData #define LITERAL_ON_HEAP 0x01 #define LITERAL_CMD_NAME 0x02 #define LITERAL_UNSHARED 0x04 /* * Adjust the stack requirements. Manually used in cases where the stack * effect cannot be computed from the opcode and its operands, but is still * known at compile time. */ static inline void TclAdjustStackDepth( int delta, CompileEnv *envPtr) { if (delta < 0) { if ((int) envPtr->maxStackDepth < (int) envPtr->currStackDepth) { envPtr->maxStackDepth = envPtr->currStackDepth; } } envPtr->currStackDepth += delta; } #define TclGetStackDepth(envPtr) \ ((envPtr)->currStackDepth) #define TclSetStackDepth(depth, envPtr) \ (envPtr)->currStackDepth = (depth) /* * Verify that the current stack depth is what we think it should be. When * this is wrong, code generation is broken! */ static inline void TclCheckStackDepth( size_t depth, CompileEnv *envPtr) { if (depth != (size_t) envPtr->currStackDepth) { Tcl_Panic("bad stack depth computations: " "is %" TCL_Z_MODIFIER "u, should be %" TCL_Z_MODIFIER "u", (size_t) envPtr->currStackDepth, depth); } } /* * Update the stack requirements based on the instruction definition. It is * called by the macros TclEmitOpCode, TclEmitInst1 and TclEmitInst4. * Remark that the very last instruction of a bytecode always reduces the * stack level: INST_DONE or INST_POP, so that the maxStackdepth is always * updated. */ static inline void TclUpdateStackReqs( unsigned char op, int i, CompileEnv *envPtr) { int delta = tclInstructionTable[op].stackEffect; if (delta) { if (delta == INT_MIN) { delta = 1 - i; } TclAdjustStackDepth(delta, envPtr); } } /* * Macros used to update the flag that indicates if we are at the start of a * command, based on whether the opcode is INST_START_COMMAND. * * void TclUpdateAtCmdStart(unsigned char op, CompileEnv *envPtr); */ #define TclUpdateAtCmdStart(op, envPtr) \ if ((envPtr)->atCmdStart < 2) { \ (envPtr)->atCmdStart = ((op) == INST_START_CMD ? 1 : 0); \ } /* * Macro to emit an opcode byte into a CompileEnv's code array. The ANSI C * "prototype" for this macro is: * * void TclEmitOpcode(unsigned char op, CompileEnv *envPtr); */ #define TclEmitOpcode(op, envPtr) \ do { \ if ((envPtr)->codeNext == (envPtr)->codeEnd) { \ TclExpandCodeArray(envPtr); \ } \ *(envPtr)->codeNext++ = (unsigned char) (op); \ TclUpdateAtCmdStart(op, envPtr); \ TclUpdateStackReqs(op, 0, envPtr); \ } while (0) /* * Macros to emit an integer operand. The ANSI C "prototype" for these macros * are: * * void TclEmitInt1(int i, CompileEnv *envPtr); |
︙ | ︙ | |||
1348 1349 1350 1351 1352 1353 1354 | *(envPtr)->codeNext++ = (unsigned char) (op); \ *(envPtr)->codeNext++ = (unsigned char) ((unsigned int) (i)); \ TclUpdateAtCmdStart(op, envPtr); \ TclUpdateStackReqs(op, i, envPtr); \ } while (0) #define TclEmitInstInt4(op, i, envPtr) \ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 | *(envPtr)->codeNext++ = (unsigned char) (op); \ *(envPtr)->codeNext++ = (unsigned char) ((unsigned int) (i)); \ TclUpdateAtCmdStart(op, envPtr); \ TclUpdateStackReqs(op, i, envPtr); \ } while (0) #define TclEmitInstInt4(op, i, envPtr) \ do { \ if (((envPtr)->codeNext + 5) > (envPtr)->codeEnd) { \ TclExpandCodeArray(envPtr); \ } \ *(envPtr)->codeNext++ = (unsigned char) (op); \ *(envPtr)->codeNext++ = \ (unsigned char) ((unsigned int) (i) >> 24); \ *(envPtr)->codeNext++ = \ (unsigned char) ((unsigned int) (i) >> 16); \ *(envPtr)->codeNext++ = \ (unsigned char) ((unsigned int) (i) >> 8); \ *(envPtr)->codeNext++ = \ (unsigned char) ((unsigned int) (i) ); \ TclUpdateAtCmdStart(op, envPtr); \ TclUpdateStackReqs(op, i, envPtr); \ } while (0) /* * Macro to push a Tcl object onto the Tcl evaluation stack. It emits the * object's one or four byte array index into the CompileEnv's code array. * These support, respectively, a maximum of 256 (2**8) and 2**32 objects in a * CompileEnv. The ANSI C "prototype" for this macro is: * * void TclEmitPush(int objIndex, CompileEnv *envPtr); */ #define TclEmitPush(objIndex, envPtr) \ do { \ int _objIndexCopy = (objIndex); \ if (_objIndexCopy <= 255) { \ TclEmitInstInt1(INST_PUSH1, _objIndexCopy, (envPtr)); \ } else { \ TclEmitInstInt4(INST_PUSH4, _objIndexCopy, (envPtr)); \ } \ } while (0) /* * Macros to update a (signed or unsigned) integer starting at a pointer. The * two variants depend on the number of bytes. The ANSI C "prototypes" for * these macros are: * * void TclStoreInt1AtPtr(int i, unsigned char *p); * void TclStoreInt4AtPtr(int i, unsigned char *p); */ #define TclStoreInt1AtPtr(i, p) \ *(p) = (unsigned char) ((unsigned int) (i)) #define TclStoreInt4AtPtr(i, p) \ do { \ *(p) = (unsigned char) ((unsigned int) (i) >> 24); \ *(p+1) = (unsigned char) ((unsigned int) (i) >> 16); \ *(p+2) = (unsigned char) ((unsigned int) (i) >> 8); \ *(p+3) = (unsigned char) ((unsigned int) (i) ); \ } while (0) /* * Macros to update instructions at a particular pc with a new op code and a * (signed or unsigned) int operand. The ANSI C "prototypes" for these macros * are: * * void TclUpdateInstInt1AtPc(unsigned char op, int i, unsigned char *pc); * void TclUpdateInstInt4AtPc(unsigned char op, int i, unsigned char *pc); */ #define TclUpdateInstInt1AtPc(op, i, pc) \ do { \ *(pc) = (unsigned char) (op); \ TclStoreInt1AtPtr((i), ((pc)+1)); \ } while (0) #define TclUpdateInstInt4AtPc(op, i, pc) \ do { \ *(pc) = (unsigned char) (op); \ TclStoreInt4AtPtr((i), ((pc)+1)); \ } while (0) /* * Macro to fix up a forward jump to point to the current code-generation * position in the bytecode being created (the most common case). The ANSI C * "prototypes" for this macro is: * |
︙ | ︙ | |||
1469 1470 1471 1472 1473 1474 1475 | # define TclGetInt1AtPtr(p) ((int) *((signed char *) p)) #else # define TclGetInt1AtPtr(p) \ ((int) ((*((char *) p)) | ((*(p) & 0200) ? (-256) : 0))) #endif #define TclGetInt4AtPtr(p) \ | | | | | | | | | 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 | # define TclGetInt1AtPtr(p) ((int) *((signed char *) p)) #else # define TclGetInt1AtPtr(p) \ ((int) ((*((char *) p)) | ((*(p) & 0200) ? (-256) : 0))) #endif #define TclGetInt4AtPtr(p) \ ((int) ((TclGetUInt1AtPtr(p) << 24) | \ (*((p)+1) << 16) | \ (*((p)+2) << 8) | \ (*((p)+3)))) #define TclGetUInt1AtPtr(p) \ ((unsigned int) *(p)) #define TclGetUInt4AtPtr(p) \ ((unsigned int) ((*(p) << 24) | \ (*((p)+1) << 16) | \ (*((p)+2) << 8) | \ (*((p)+3)))) /* * Macros used to compute the minimum and maximum of two values. The ANSI C * "prototypes" for these macros are: * * size_t TclMin(size_t i, size_t j); * size_t TclMax(size_t i, size_t j); */ #define TclMin(i, j) ((((size_t) i) + 1 < ((size_t) j) + 1 )? (i) : (j)) #define TclMax(i, j) ((((size_t) i) + 1 > ((size_t) j) + 1 )? (i) : (j)) /* * Convenience macros for use when compiling bodies of commands. The ANSI C * "prototype" for these macros are: * * static void BODY(Tcl_Token *tokenPtr, int word); */ #define BODY(tokenPtr, word) \ SetLineInformation((word)); \ TclCompileCmdWord(interp, (tokenPtr)+1, (tokenPtr)->numComponents, \ envPtr) /* * Convenience macro for use when compiling tokens to be pushed. The ANSI C * "prototype" for this macro is: |
︙ | ︙ | |||
1798 1799 1800 1801 1802 1803 1804 | MODULE_SCOPE int tclDTraceDebugEnabled, tclDTraceDebugIndent; MODULE_SCOPE FILE *tclDTraceDebugLog; MODULE_SCOPE void TclDTraceOpenDebugLog(void); MODULE_SCOPE void TclDTraceInfo(Tcl_Obj *info, const char **args, Tcl_Size *argsi); #define TCL_DTRACE_DEBUG_LOG() \ | | | | | | | | | 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 | MODULE_SCOPE int tclDTraceDebugEnabled, tclDTraceDebugIndent; MODULE_SCOPE FILE *tclDTraceDebugLog; MODULE_SCOPE void TclDTraceOpenDebugLog(void); MODULE_SCOPE void TclDTraceInfo(Tcl_Obj *info, const char **args, Tcl_Size *argsi); #define TCL_DTRACE_DEBUG_LOG() \ int tclDTraceDebugEnabled = TCL_DTRACE_DEBUG_LOG_ENABLED; \ int tclDTraceDebugIndent = 0; \ FILE *tclDTraceDebugLog = NULL; \ void TclDTraceOpenDebugLog(void) { \ char n[35]; \ snprintf(n, sizeof(n), "/tmp/tclDTraceDebug-%" TCL_Z_MODIFIER "u.log", \ (size_t) getpid()); \ tclDTraceDebugLog = fopen(n, "a"); \ } #define TclDTraceDbgMsg(p, m, ...) \ do { \ if (tclDTraceDebugEnabled) { \ int _l, _t = 0; \ if (!tclDTraceDebugLog) { TclDTraceOpenDebugLog(); } \ |
︙ | ︙ | |||
1832 1833 1834 1835 1836 1837 1838 | #define TCL_DTRACE_PROC_ENTRY_ENABLED() 1 #define TCL_DTRACE_PROC_RETURN_ENABLED() 1 #define TCL_DTRACE_PROC_RESULT_ENABLED() 1 #define TCL_DTRACE_PROC_ARGS_ENABLED() 1 #define TCL_DTRACE_PROC_INFO_ENABLED() 1 #define TCL_DTRACE_PROC_ENTRY(a0, a1, a2) \ | | | | | | 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 | #define TCL_DTRACE_PROC_ENTRY_ENABLED() 1 #define TCL_DTRACE_PROC_RETURN_ENABLED() 1 #define TCL_DTRACE_PROC_RESULT_ENABLED() 1 #define TCL_DTRACE_PROC_ARGS_ENABLED() 1 #define TCL_DTRACE_PROC_INFO_ENABLED() 1 #define TCL_DTRACE_PROC_ENTRY(a0, a1, a2) \ tclDTraceDebugIndent++; \ TclDTraceDbgMsg("-> proc-entry", "%s %" TCL_SIZE_MODIFIER "d %p", a0, a1, a2) #define TCL_DTRACE_PROC_RETURN(a0, a1) \ TclDTraceDbgMsg("<- proc-return", "%s %d", a0, a1); \ tclDTraceDebugIndent-- #define TCL_DTRACE_PROC_RESULT(a0, a1, a2, a3) \ TclDTraceDbgMsg(" | proc-result", "%s %d %s %p", a0, a1, a2, a3) #define TCL_DTRACE_PROC_ARGS(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) \ TclDTraceDbgMsg(" | proc-args", "%s %s %s %s %s %s %s %s %s %s", a0, \ a1, a2, a3, a4, a5, a6, a7, a8, a9) #define TCL_DTRACE_PROC_INFO(a0, a1, a2, a3, a4, a5, a6, a7) \ TclDTraceDbgMsg(" | proc-info", "%s %s %s %s %d %d %s %s", a0, a1, \ a2, a3, a4, a5, a6, a7) #define TCL_DTRACE_CMD_ENTRY_ENABLED() 1 #define TCL_DTRACE_CMD_RETURN_ENABLED() 1 #define TCL_DTRACE_CMD_RESULT_ENABLED() 1 #define TCL_DTRACE_CMD_ARGS_ENABLED() 1 #define TCL_DTRACE_CMD_INFO_ENABLED() 1 #define TCL_DTRACE_CMD_ENTRY(a0, a1, a2) \ tclDTraceDebugIndent++; \ TclDTraceDbgMsg("-> cmd-entry", "%s %" TCL_SIZE_MODIFIER "d %p", a0, a1, a2) #define TCL_DTRACE_CMD_RETURN(a0, a1) \ TclDTraceDbgMsg("<- cmd-return", "%s %d", a0, a1); \ tclDTraceDebugIndent-- #define TCL_DTRACE_CMD_RESULT(a0, a1, a2, a3) \ TclDTraceDbgMsg(" | cmd-result", "%s %d %s %p", a0, a1, a2, a3) #define TCL_DTRACE_CMD_ARGS(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9) \ TclDTraceDbgMsg(" | cmd-args", "%s %s %s %s %s %s %s %s %s %s", a0, \ a1, a2, a3, a4, a5, a6, a7, a8, a9) #define TCL_DTRACE_CMD_INFO(a0, a1, a2, a3, a4, a5, a6, a7) \ |
︙ | ︙ |
Changes to generic/tclDisassemble.c.
︙ | ︙ | |||
41 42 43 44 45 46 47 | NULL, /* freeIntRepProc */ NULL, /* dupIntRepProc */ UpdateStringOfInstName, /* updateStringProc */ NULL, /* setFromAnyProc */ TCL_OBJTYPE_V0 }; | | | | | | | | | | < | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | NULL, /* freeIntRepProc */ NULL, /* dupIntRepProc */ UpdateStringOfInstName, /* updateStringProc */ NULL, /* setFromAnyProc */ TCL_OBJTYPE_V0 }; #define InstNameSetInternalRep(objPtr, inst) \ do { \ Tcl_ObjInternalRep ir; \ ir.wideValue = (inst); \ Tcl_StoreInternalRep((objPtr), &instNameType, &ir); \ } while (0) #define InstNameGetInternalRep(objPtr, inst) \ do { \ const Tcl_ObjInternalRep *irPtr; \ irPtr = TclFetchInternalRep((objPtr), &instNameType); \ assert(irPtr != NULL); \ (inst) = irPtr->wideValue; \ } while (0) /* *---------------------------------------------------------------------- * * GetLocationInformation -- * * This procedure looks up the information about where a procedure was |
︙ | ︙ |
Changes to generic/tclEncoding.c.
︙ | ︙ | |||
254 255 256 257 258 259 260 | static Tcl_EncodingConvertProc Utf16ToUtfProc; static Tcl_EncodingConvertProc UtfToUtf16Proc; static Tcl_EncodingConvertProc UtfToUcs2Proc; static Tcl_EncodingConvertProc UtfToUtfProc; static Tcl_EncodingConvertProc Iso88591FromUtfProc; static Tcl_EncodingConvertProc Iso88591ToUtfProc; | < | | | | | < | 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 | static Tcl_EncodingConvertProc Utf16ToUtfProc; static Tcl_EncodingConvertProc UtfToUtf16Proc; static Tcl_EncodingConvertProc UtfToUcs2Proc; static Tcl_EncodingConvertProc UtfToUtfProc; static Tcl_EncodingConvertProc Iso88591FromUtfProc; static Tcl_EncodingConvertProc Iso88591ToUtfProc; /* * A Tcl_ObjType for holding a cached Tcl_Encoding in the twoPtrValue.ptr1 field * of the internalrep. This should help the lifetime of encodings be more useful. * See concerns raised in [Bug 1077262]. */ static const Tcl_ObjType encodingType = { "encoding", FreeEncodingInternalRep, DupEncodingInternalRep, NULL, NULL, TCL_OBJTYPE_V0 }; #define EncodingSetInternalRep(objPtr, encoding) \ do { \ Tcl_ObjInternalRep ir; \ ir.twoPtrValue.ptr1 = (encoding); \ ir.twoPtrValue.ptr2 = NULL; \ Tcl_StoreInternalRep((objPtr), &encodingType, &ir); \ } while (0) #define EncodingGetInternalRep(objPtr, encoding) \ do { \ const Tcl_ObjInternalRep *irPtr; \ irPtr = TclFetchInternalRep ((objPtr), &encodingType); \ (encoding) = irPtr ? (Tcl_Encoding)irPtr->twoPtrValue.ptr1 : NULL; \ } while (0) /* *---------------------------------------------------------------------- * * Tcl_GetEncodingFromObj -- * * Writes to (*encodingPtr) the Tcl_Encoding value of (*objPtr), if |
︙ | ︙ | |||
1108 1109 1110 1111 1112 1113 1114 | Tcl_DString *dstPtr) /* Uninitialized or free DString in which the * converted string is stored. */ { Tcl_ExternalToUtfDStringEx( NULL, encoding, src, srcLen, TCL_ENCODING_PROFILE_TCL8, dstPtr, NULL); return Tcl_DStringValue(dstPtr); } | < | 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 | Tcl_DString *dstPtr) /* Uninitialized or free DString in which the * converted string is stored. */ { Tcl_ExternalToUtfDStringEx( NULL, encoding, src, srcLen, TCL_ENCODING_PROFILE_TCL8, dstPtr, NULL); return Tcl_DStringValue(dstPtr); } /* *------------------------------------------------------------------------- * * Tcl_ExternalToUtfDStringEx -- * * Convert a source buffer from the specified encoding into UTF-8. |
︙ | ︙ | |||
1154 1155 1156 1157 1158 1159 1160 | int Tcl_ExternalToUtfDStringEx( Tcl_Interp *interp, /* For error messages. May be NULL. */ Tcl_Encoding encoding, /* The encoding for the source string, or NULL * for the default system encoding. */ const char *src, /* Source string in specified encoding. */ | | | | | 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 | int Tcl_ExternalToUtfDStringEx( Tcl_Interp *interp, /* For error messages. May be NULL. */ Tcl_Encoding encoding, /* The encoding for the source string, or NULL * for the default system encoding. */ const char *src, /* Source string in specified encoding. */ Tcl_Size srcLen, /* Source string length in bytes, or < 0 for * encoding-specific string length. */ int flags, /* Conversion control flags. */ Tcl_DString *dstPtr, /* Uninitialized or free DString in which the * converted string is stored. */ Tcl_Size *errorLocPtr) /* Where to store the error location * (or TCL_INDEX_NONE if no error). May * be NULL. */ { char *dst; Tcl_EncodingState state; const Encoding *encodingPtr; int result; Tcl_Size dstLen, soFar; const char *srcStart = src; |
︙ | ︙ | |||
1426 1427 1428 1429 1430 1431 1432 | Tcl_DString *dstPtr) /* Uninitialized or free DString in which the * converted string is stored. */ { Tcl_UtfToExternalDStringEx( NULL, encoding, src, srcLen, TCL_ENCODING_PROFILE_TCL8, dstPtr, NULL); return Tcl_DStringValue(dstPtr); } | < | 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 | Tcl_DString *dstPtr) /* Uninitialized or free DString in which the * converted string is stored. */ { Tcl_UtfToExternalDStringEx( NULL, encoding, src, srcLen, TCL_ENCODING_PROFILE_TCL8, dstPtr, NULL); return Tcl_DStringValue(dstPtr); } /* *------------------------------------------------------------------------- * * Tcl_UtfToExternalDStringEx -- * * Convert a source buffer from UTF-8 to the specified encoding. |
︙ | ︙ | |||
1477 1478 1479 1480 1481 1482 1483 | const char *src, /* Source string in UTF-8. */ Tcl_Size srcLen, /* Source string length in bytes, or < 0 for * strlen(). */ int flags, /* Conversion control flags. */ Tcl_DString *dstPtr, /* Uninitialized or free DString in which the * converted string is stored. */ Tcl_Size *errorLocPtr) /* Where to store the error location | | | | 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 | const char *src, /* Source string in UTF-8. */ Tcl_Size srcLen, /* Source string length in bytes, or < 0 for * strlen(). */ int flags, /* Conversion control flags. */ Tcl_DString *dstPtr, /* Uninitialized or free DString in which the * converted string is stored. */ Tcl_Size *errorLocPtr) /* Where to store the error location * (or TCL_INDEX_NONE if no error). May * be NULL. */ { char *dst; Tcl_EncodingState state; const Encoding *encodingPtr; int result; const char *srcStart = src; Tcl_Size dstLen, soFar; |
︙ | ︙ |
Changes to generic/tclEnv.c.
︙ | ︙ | |||
16 17 18 19 20 21 22 | #include "tclInt.h" TCL_DECLARE_MUTEX(envMutex) /* To serialize access to environ. */ #if defined(_WIN32) # define tenviron _wenviron # define tenviron2utfdstr(str, dsPtr) (Tcl_DStringInit(dsPtr), \ | | | | | < | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | #include "tclInt.h" TCL_DECLARE_MUTEX(envMutex) /* To serialize access to environ. */ #if defined(_WIN32) # define tenviron _wenviron # define tenviron2utfdstr(str, dsPtr) (Tcl_DStringInit(dsPtr), \ (char *)Tcl_Char16ToUtfDString((const unsigned short *)(str), -1, (dsPtr))) # define utf2tenvirondstr(str, dsPtr) (Tcl_DStringInit(dsPtr), \ (const WCHAR *)Tcl_UtfToChar16DString((str), -1, (dsPtr))) # define techar WCHAR # ifdef USE_PUTENV # define putenv(env) _wputenv((const wchar_t *)env) # endif #else # define tenviron environ # define tenviron2utfdstr(str, dsPtr) \ Tcl_ExternalToUtfDString(NULL, str, -1, dsPtr) # define utf2tenvirondstr(str, dsPtr) \ Tcl_UtfToExternalDString(NULL, str, -1, dsPtr) # define techar char #endif /* MODULE_SCOPE */ size_t TclEnvEpoch = 0; /* Epoch of the tcl environment * (if changed with tcl-env). */ static struct { Tcl_Size cacheSize; /* Number of env strings in cache. */ |
︙ | ︙ |
Changes to generic/tclEvent.c.
︙ | ︙ | |||
889 890 891 892 893 894 895 | Tcl_MutexLock(&exitMutex); prevExitProc = appExitPtr; appExitPtr = proc; Tcl_MutexUnlock(&exitMutex); return prevExitProc; } | < | 889 890 891 892 893 894 895 896 897 898 899 900 901 902 | Tcl_MutexLock(&exitMutex); prevExitProc = appExitPtr; appExitPtr = proc; Tcl_MutexUnlock(&exitMutex); return prevExitProc; } /* *---------------------------------------------------------------------- * * InvokeExitHandlers -- * * Call the registered exit handlers. |
︙ | ︙ | |||
931 932 933 934 935 936 937 | exitPtr->proc(exitPtr->clientData); Tcl_Free(exitPtr); Tcl_MutexLock(&exitMutex); } firstExitPtr = NULL; Tcl_MutexUnlock(&exitMutex); } | < | 930 931 932 933 934 935 936 937 938 939 940 941 942 943 | exitPtr->proc(exitPtr->clientData); Tcl_Free(exitPtr); Tcl_MutexLock(&exitMutex); } firstExitPtr = NULL; Tcl_MutexUnlock(&exitMutex); } /* *---------------------------------------------------------------------- * * Tcl_Exit -- * * This function is called to terminate the application. |
︙ | ︙ | |||
1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 | ".profile" #endif #ifdef PURIFY ".purify" #endif #ifdef STATIC_BUILD ".static" #endif }}; const char * Tcl_InitSubsystems(void) { if (inExit != 0) { | > > > > > > > > > > > > > > | 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 | ".profile" #endif #ifdef PURIFY ".purify" #endif #ifdef STATIC_BUILD ".static" #endif #ifndef TCL_WITH_EXTERNAL_TOMMATH ".tommath-0103" #endif #ifdef TCL_WITH_INTERNAL_ZLIB ".zlib-" #if ZLIB_VER_MAJOR < 10 "0" #endif STRINGIFY(ZLIB_VER_MAJOR) #if ZLIB_VER_MINOR < 10 "0" #endif STRINGIFY(ZLIB_VER_MINOR) #endif }}; const char * Tcl_InitSubsystems(void) { if (inExit != 0) { |
︙ | ︙ |
Changes to generic/tclExecute.c.
︙ | ︙ | |||
188 189 190 191 192 193 194 | * We use the new compile-time assertions to check that nCleanup is constant * and within range. */ /* Verify the stack depth, only when no expansion is in progress */ #ifdef TCL_COMPILE_DEBUG | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 | * We use the new compile-time assertions to check that nCleanup is constant * and within range. */ /* Verify the stack depth, only when no expansion is in progress */ #ifdef TCL_COMPILE_DEBUG #define CHECK_STACK() \ do { \ ValidatePcAndStackTop(codePtr, pc, CURR_DEPTH, \ /*checkStack*/ !(starting || auxObjList)); \ starting = 0; \ } while (0) #else #define CHECK_STACK() #endif #define NEXT_INST_F(pcAdjustment, nCleanup, resultHandling) \ do { \ TCL_CT_ASSERT((nCleanup >= 0) && (nCleanup <= 2)); \ CHECK_STACK(); \ if (nCleanup == 0) { \ if (resultHandling != 0) { \ if ((resultHandling) > 0) { \ PUSH_OBJECT(objResultPtr); \ } else { \ *(++tosPtr) = objResultPtr; \ } \ } \ pc += (pcAdjustment); \ goto cleanup0; \ } else if (resultHandling != 0) { \ if ((resultHandling) > 0) { \ Tcl_IncrRefCount(objResultPtr); \ } \ pc += (pcAdjustment); \ switch (nCleanup) { \ case 1: goto cleanup1_pushObjResultPtr; \ case 2: goto cleanup2_pushObjResultPtr; \ case 0: break; \ } \ } else { \ pc += (pcAdjustment); \ switch (nCleanup) { \ case 1: goto cleanup1; \ case 2: goto cleanup2; \ case 0: break; \ } \ } \ } while (0) #define NEXT_INST_V(pcAdjustment, nCleanup, resultHandling) \ CHECK_STACK(); \ do { \ pc += (pcAdjustment); \ cleanup = (nCleanup); \ if (resultHandling) { \ if ((resultHandling) > 0) { \ Tcl_IncrRefCount(objResultPtr); \ } \ goto cleanupV_pushObjResultPtr; \ } else { \ goto cleanupV; \ } \ } while (0) #ifndef TCL_COMPILE_DEBUG #define JUMP_PEEPHOLE_F(condition, pcAdjustment, cleanup) \ do { \ pc += (pcAdjustment); \ switch (*pc) { \ case INST_JUMP_FALSE1: \ NEXT_INST_F(((condition)? 2 : TclGetInt1AtPtr(pc+1)), (cleanup), 0); \ break; \ case INST_JUMP_TRUE1: \ NEXT_INST_F(((condition)? TclGetInt1AtPtr(pc+1) : 2), (cleanup), 0); \ break; \ case INST_JUMP_FALSE4: \ NEXT_INST_F(((condition)? 5 : TclGetInt4AtPtr(pc+1)), (cleanup), 0); \ break; \ case INST_JUMP_TRUE4: \ NEXT_INST_F(((condition)? TclGetInt4AtPtr(pc+1) : 5), (cleanup), 0); \ break; \ default: \ if ((condition) < 0) { \ TclNewIntObj(objResultPtr, -1); \ } else { \ objResultPtr = TCONST((condition) > 0); \ } \ NEXT_INST_F(0, (cleanup), 1); \ break; \ } \ } while (0) #define JUMP_PEEPHOLE_V(condition, pcAdjustment, cleanup) \ do { \ pc += (pcAdjustment); \ switch (*pc) { \ case INST_JUMP_FALSE1: \ NEXT_INST_V(((condition)? 2 : TclGetInt1AtPtr(pc+1)), (cleanup), 0); \ break; \ case INST_JUMP_TRUE1: \ NEXT_INST_V(((condition)? TclGetInt1AtPtr(pc+1) : 2), (cleanup), 0); \ break; \ case INST_JUMP_FALSE4: \ NEXT_INST_V(((condition)? 5 : TclGetInt4AtPtr(pc+1)), (cleanup), 0); \ break; \ case INST_JUMP_TRUE4: \ NEXT_INST_V(((condition)? TclGetInt4AtPtr(pc+1) : 5), (cleanup), 0); \ break; \ default: \ if ((condition) < 0) { \ TclNewIntObj(objResultPtr, -1); \ } else { \ objResultPtr = TCONST((condition) > 0); \ } \ NEXT_INST_V(0, (cleanup), 1); \ break; \ } \ } while (0) #else /* TCL_COMPILE_DEBUG */ #define JUMP_PEEPHOLE_F(condition, pcAdjustment, cleanup) \ do{ \ if ((condition) < 0) { \ TclNewIntObj(objResultPtr, -1); \ |
︙ | ︙ | |||
373 374 375 376 377 378 379 | * Macros used to trace instruction execution. The macros TRACE, * TRACE_WITH_OBJ, and O2S are only used inside TclNRExecuteByteCode. O2S is * only used in TRACE* calls to get a string from an object. */ #ifdef TCL_COMPILE_DEBUG # define TRACE(a) \ | | | > | | | | | | | > | | | | | | | | 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 | * Macros used to trace instruction execution. The macros TRACE, * TRACE_WITH_OBJ, and O2S are only used inside TclNRExecuteByteCode. O2S is * only used in TRACE* calls to get a string from an object. */ #ifdef TCL_COMPILE_DEBUG # define TRACE(a) \ while (traceInstructions) { \ fprintf(stdout, "%2" TCL_SIZE_MODIFIER "d: %2" TCL_T_MODIFIER \ "d (%" TCL_T_MODIFIER "d) %s ", iPtr->numLevels, \ CURR_DEPTH, \ (pc - codePtr->codeStart), \ GetOpcodeName(pc)); \ printf a; \ break; \ } # define TRACE_APPEND(a) \ while (traceInstructions) { \ printf a; \ break; \ } # define TRACE_ERROR(interp) \ TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); # define TRACE_WITH_OBJ(a, objPtr) \ while (traceInstructions) { \ fprintf(stdout, "%2" TCL_SIZE_MODIFIER "d: %2" TCL_T_MODIFIER \ "d (%" TCL_T_MODIFIER "d) %s ", iPtr->numLevels, \ CURR_DEPTH, \ (pc - codePtr->codeStart), \ GetOpcodeName(pc)); \ printf a; \ TclPrintObject(stdout, objPtr, 30); \ fprintf(stdout, "\n"); \ break; \ } # define O2S(objPtr) \ (objPtr ? TclGetString(objPtr) : "") #else /* !TCL_COMPILE_DEBUG */ # define TRACE(a) # define TRACE_APPEND(a) # define TRACE_ERROR(interp) |
︙ | ︙ | |||
471 472 473 474 475 476 477 | * * MODULE_SCOPE int Overflowing(inttype_t a, inttype_t b, inttype_t sum); * * Check first the condition most likely to fail in usual code (at least for * usage in [incr]: do the first summand and the sum have != signs? */ | | > | 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 | * * MODULE_SCOPE int Overflowing(inttype_t a, inttype_t b, inttype_t sum); * * Check first the condition most likely to fail in usual code (at least for * usage in [incr]: do the first summand and the sum have != signs? */ #define Overflowing(a,b,sum) \ ((((a)^(sum)) < 0) && (((a)^(b)) >= 0)) /* * Macro for checking whether the type is NaN, used when we're thinking about * throwing an error for supplying a non-number number. */ #ifndef ACCEPT_NAN |
︙ | ︙ | |||
1020 1021 1022 1023 1024 1025 1026 | */ if (move) { moveWords = esPtr->tosPtr - MEMSTART(markerPtr) + 1; } needed = growth + moveWords + WALLOCALIGN; | < | 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 | */ if (move) { moveWords = esPtr->tosPtr - MEMSTART(markerPtr) + 1; } needed = growth + moveWords + WALLOCALIGN; /* * Check if there is enough room in the next stack (if there is one, it * should be both empty and the last one!) */ if (esPtr->nextPtr) { oldPtr = esPtr; |
︙ | ︙ | |||
1403 1404 1405 1406 1407 1408 1409 | CompileExprObj( Tcl_Interp *interp, Tcl_Obj *objPtr) { Interp *iPtr = (Interp *) interp; CompileEnv compEnv; /* Compilation environment structure allocated * in frame. */ | | < | 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 | CompileExprObj( Tcl_Interp *interp, Tcl_Obj *objPtr) { Interp *iPtr = (Interp *) interp; CompileEnv compEnv; /* Compilation environment structure allocated * in frame. */ ByteCode *codePtr = NULL; /* Tcl Internal type of bytecode. Initialized * to avoid compiler warning. */ /* * Get the expression ByteCode from the object. If it exists, make sure it * is valid in the current context. */ |
︙ | ︙ | |||
1559 1560 1561 1562 1563 1564 1565 | TclCompileObj( Tcl_Interp *interp, Tcl_Obj *objPtr, const CmdFrame *invoker, int word) { Interp *iPtr = (Interp *) interp; | | | 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 | TclCompileObj( Tcl_Interp *interp, Tcl_Obj *objPtr, const CmdFrame *invoker, int word) { Interp *iPtr = (Interp *) interp; ByteCode *codePtr; /* Tcl Internal type of bytecode. */ Namespace *namespacePtr = iPtr->varFramePtr->nsPtr; /* * If the object is not already of tclByteCodeType, compile it (and reset * the compilation flags in the interpreter; this should be done after any * compilation). Otherwise, check that it is "fresh" enough. */ |
︙ | ︙ | |||
2023 2024 2025 2026 2027 2028 2029 | /* * Globals: variables that store state, must remain valid at all times. */ Tcl_Obj **tosPtr; /* Cached pointer to top of evaluation * stack. */ const unsigned char *pc = (const unsigned char *)data[1]; | | | | | 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 | /* * Globals: variables that store state, must remain valid at all times. */ Tcl_Obj **tosPtr; /* Cached pointer to top of evaluation * stack. */ const unsigned char *pc = (const unsigned char *)data[1]; /* The current program counter. */ unsigned char inst; /* The currently running instruction */ /* * Transfer variables - needed only between opcodes, but not while * executing an instruction. */ int cleanup = PTR2INT(data[2]); Tcl_Obj *objResultPtr; int checkInterp = 0; /* Indicates when a check of interp readyness * is necessary. Set by CACHE_STACK_INFO() */ /* * Locals - variables that are used within opcodes or bounded sections of * the file (jumps between opcodes within a family). * NOTE: These are now mostly defined locally where needed. */ |
︙ | ︙ | |||
2087 2088 2089 2090 2091 2092 2093 | TclNewObj(objPtr); Tcl_IncrRefCount(objPtr); iPtr->objResultPtr = objPtr; } goto cleanup0; } else { | | | 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 | TclNewObj(objPtr); Tcl_IncrRefCount(objPtr); iPtr->objResultPtr = objPtr; } goto cleanup0; } else { /* resume from invocation */ CACHE_STACK_INFO(); NRE_ASSERT(iPtr->cmdFramePtr == bcFramePtr); if (bcFramePtr->cmdObj) { Tcl_DecrRefCount(bcFramePtr->cmdObj); bcFramePtr->cmdObj = NULL; bcFramePtr->cmd = NULL; |
︙ | ︙ | |||
2577 2578 2579 2580 2581 2582 2583 | TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr); NEXT_INST_F(5, 0, 1); break; case INST_REVERSE: { Tcl_Obj **a, **b; | | | | | > | 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 | TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr); NEXT_INST_F(5, 0, 1); break; case INST_REVERSE: { Tcl_Obj **a, **b; opnd = TclGetUInt4AtPtr(pc + 1); a = tosPtr - (opnd - 1); b = tosPtr; while (a < b) { tmpPtr = *a; *a = *b; *b = tmpPtr; a++; b--; } TRACE(("%u => OK\n", opnd)); NEXT_INST_F(5, 0, 0); } break; case INST_STR_CONCAT1: |
︙ | ︙ | |||
2615 2616 2617 2618 2619 2620 2621 | case INST_CONCAT_STK: /* * Pop the opnd (objc) top stack elements, run through Tcl_ConcatObj, * and then decrement their ref counts. */ opnd = TclGetUInt4AtPtr(pc+1); | | | 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 | case INST_CONCAT_STK: /* * Pop the opnd (objc) top stack elements, run through Tcl_ConcatObj, * and then decrement their ref counts. */ opnd = TclGetUInt4AtPtr(pc+1); objResultPtr = Tcl_ConcatObj(opnd, &OBJ_AT_DEPTH(opnd - 1)); TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr); NEXT_INST_V(5, opnd, 1); break; case INST_EXPAND_START: /* * Push an element to the auxObjList. This records the current |
︙ | ︙ | |||
3174 3175 3176 3177 3178 3179 3180 | if (part2Ptr == NULL) { TRACE(("\"%.30s\" <- \"%.30s\" =>", O2S(part1Ptr),O2S(valuePtr))); } else { TRACE(("\"%.30s(%.30s)\" <- \"%.30s\" => ", O2S(part1Ptr), O2S(part2Ptr), O2S(valuePtr))); } #endif | | | 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 | if (part2Ptr == NULL) { TRACE(("\"%.30s\" <- \"%.30s\" =>", O2S(part1Ptr),O2S(valuePtr))); } else { TRACE(("\"%.30s(%.30s)\" <- \"%.30s\" => ", O2S(part1Ptr), O2S(part2Ptr), O2S(valuePtr))); } #endif varPtr = TclObjLookupVarEx(interp, objPtr, part2Ptr, TCL_LEAVE_ERR_MSG, "set", /*createPart1*/ 1, /*createPart2*/ 1, &arrayPtr); if (!varPtr) { TRACE_ERROR(interp); goto gotError; } cleanup = ((part2Ptr == NULL)? 2 : 3); pcAdjustment = 1; |
︙ | ︙ | |||
3765 3766 3767 3768 3769 3770 3771 | doExistStk: varPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr, 0, "access", /*createPart1*/0, /*createPart2*/1, &arrayPtr); if (varPtr) { if (ReadTraced(varPtr) || (arrayPtr && ReadTraced(arrayPtr))) { DECACHE_STACK_INFO(); | | | 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 | doExistStk: varPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr, 0, "access", /*createPart1*/0, /*createPart2*/1, &arrayPtr); if (varPtr) { if (ReadTraced(varPtr) || (arrayPtr && ReadTraced(arrayPtr))) { DECACHE_STACK_INFO(); TclObjCallVarTraces(iPtr, arrayPtr, varPtr, part1Ptr, part2Ptr, TCL_TRACE_READS, 0, -1); CACHE_STACK_INFO(); } if (TclIsVarUndefined(varPtr)) { TclCleanupVar(varPtr, arrayPtr); varPtr = NULL; } |
︙ | ︙ | |||
4695 4696 4697 4698 4699 4700 4701 | TclNewStringObj(objResultPtr, oPtr->namespacePtr->fullName, strlen(oPtr->namespacePtr->fullName)); TRACE_WITH_OBJ(("%.30s => ", O2S(OBJ_AT_TOS)), objResultPtr); NEXT_INST_F(1, 1, 1); } /* | | | 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 | TclNewStringObj(objResultPtr, oPtr->namespacePtr->fullName, strlen(oPtr->namespacePtr->fullName)); TRACE_WITH_OBJ(("%.30s => ", O2S(OBJ_AT_TOS)), objResultPtr); NEXT_INST_F(1, 1, 1); } /* * End of TclOO support instructions. * ----------------------------------------------------------------- * Start of INST_LIST and related instructions. */ { int numIndices, nocase, match, cflags; Tcl_Size slength, length2, fromIdx, toIdx, index, s1len, s2len; |
︙ | ︙ | |||
4732 4733 4734 4735 4736 4737 4738 | case INST_LIST_INDEX: /* lindex with objc == 3 */ value2Ptr = OBJ_AT_TOS; valuePtr = OBJ_UNDER_TOS; TRACE(("\"%.30s\" \"%.30s\" => ", O2S(valuePtr), O2S(value2Ptr))); /* special case for AbstractList */ | | | 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 | case INST_LIST_INDEX: /* lindex with objc == 3 */ value2Ptr = OBJ_AT_TOS; valuePtr = OBJ_UNDER_TOS; TRACE(("\"%.30s\" \"%.30s\" => ", O2S(valuePtr), O2S(value2Ptr))); /* special case for AbstractList */ if (TclObjTypeHasProc(valuePtr, indexProc)) { DECACHE_STACK_INFO(); length = TclObjTypeLength(valuePtr); if (TclGetIntForIndexM(interp, value2Ptr, length-1, &index)!=TCL_OK) { CACHE_STACK_INFO(); TRACE_ERROR(interp); goto gotError; } |
︙ | ︙ | |||
4823 4824 4825 4826 4827 4828 4829 | /* * Get the contents of the list, making sure that it really is a list * in the process. */ /* special case for AbstractList */ | | | 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 | /* * Get the contents of the list, making sure that it really is a list * in the process. */ /* special case for AbstractList */ if (TclObjTypeHasProc(valuePtr, indexProc)) { length = TclObjTypeLength(valuePtr); /* Decode end-offset index values. */ index = TclIndexDecode(opnd, length-1); if (index >= 0 && index < length) { /* Compute value @ index */ |
︙ | ︙ | |||
4922 4923 4924 4925 4926 4927 4928 | /* * Compute the new variable value. */ DECACHE_STACK_INFO(); if (TclObjTypeHasProc(valuePtr, setElementProc)) { objResultPtr = TclObjTypeSetElement(interp, | | | | | 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 | /* * Compute the new variable value. */ DECACHE_STACK_INFO(); if (TclObjTypeHasProc(valuePtr, setElementProc)) { objResultPtr = TclObjTypeSetElement(interp, valuePtr, numIndices, &OBJ_AT_DEPTH(numIndices), OBJ_AT_TOS); } else { objResultPtr = TclLsetFlat(interp, valuePtr, numIndices, &OBJ_AT_DEPTH(numIndices), OBJ_AT_TOS); } if (!objResultPtr) { CACHE_STACK_INFO(); TRACE_ERROR(interp); goto gotError; } |
︙ | ︙ | |||
5072 5073 5074 5075 5076 5077 5078 | NEXT_INST_F(9, 1, 1); case INST_LIST_IN: case INST_LIST_NOT_IN: /* Basic list containment operators. */ value2Ptr = OBJ_AT_TOS; valuePtr = OBJ_UNDER_TOS; | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 | NEXT_INST_F(9, 1, 1); case INST_LIST_IN: case INST_LIST_NOT_IN: /* Basic list containment operators. */ value2Ptr = OBJ_AT_TOS; valuePtr = OBJ_UNDER_TOS; s1 = TclGetStringFromObj(valuePtr, &s1len); TRACE(("\"%.30s\" \"%.30s\" => ", O2S(valuePtr), O2S(value2Ptr))); if (TclObjTypeHasProc(value2Ptr, inOperProc) != NULL) { int status = TclObjTypeInOperator(interp, valuePtr, value2Ptr, &match); if (status != TCL_OK) { TRACE_ERROR(interp); goto gotError; } } else { if (TclListObjLength(interp, value2Ptr, &length) != TCL_OK) { TRACE_ERROR(interp); goto gotError; } match = 0; if (length > 0) { Tcl_Size i = 0; Tcl_Obj *o; int isAbstractList = TclObjTypeHasProc(value2Ptr, indexProc) != NULL; /* * An empty list doesn't match anything. */ do { if (isAbstractList) { DECACHE_STACK_INFO(); if (TclObjTypeIndex(interp, value2Ptr, i, &o) != TCL_OK) { CACHE_STACK_INFO(); TRACE_ERROR(interp); goto gotError; } CACHE_STACK_INFO(); } else { Tcl_ListObjIndex(NULL, value2Ptr, i, &o); } if (o != NULL) { s2 = TclGetStringFromObj(o, &s2len); } else { s2 = ""; s2len = 0; } if (s1len == s2len) { match = (memcmp(s1, s2, s1len) == 0); } /* Could be an ephemeral abstract obj */ Tcl_BounceRefCount(o); i++; } while (i < length && match == 0); } } if (*pc == INST_LIST_NOT_IN) { match = !match; } TRACE_APPEND(("%d\n", match)); |
︙ | ︙ | |||
5164 5165 5166 5167 5168 5169 5170 | TRACE_ERROR(interp); goto gotError; } TRACE_APPEND(("\"%.30s\"\n", O2S(valuePtr))); NEXT_INST_F(1, 1, 0); } | | < | 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 | TRACE_ERROR(interp); goto gotError; } TRACE_APPEND(("\"%.30s\"\n", O2S(valuePtr))); NEXT_INST_F(1, 1, 0); } case INST_LREPLACE4: { size_t numToDelete, numNewElems; int end_indicator; int haveSecondIndex, flags; Tcl_Obj *fromIdxObj, *toIdxObj; opnd = TclGetInt4AtPtr(pc + 1); flags = TclGetInt1AtPtr(pc + 5); |
︙ | ︙ | |||
5561 5562 5563 5564 5565 5566 5567 | objResultPtr = Tcl_NewUnicodeObj(ustring1, 0); p = ustring1; end = ustring1 + slength; for (; ustring1 < end; ustring1++) { if ((*ustring1 == *ustring2) && /* Fix bug [69218ab7b]: restrict max compare length. */ ((end - ustring1) >= length2) && (length2 == 1 || | | | 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 | objResultPtr = Tcl_NewUnicodeObj(ustring1, 0); p = ustring1; end = ustring1 + slength; for (; ustring1 < end; ustring1++) { if ((*ustring1 == *ustring2) && /* Fix bug [69218ab7b]: restrict max compare length. */ ((end - ustring1) >= length2) && (length2 == 1 || memcmp(ustring1, ustring2, sizeof(Tcl_UniChar) * length2) == 0)) { if (p != ustring1) { Tcl_AppendUnicodeToObj(objResultPtr, p, ustring1-p); p = ustring1 + length2; } else { p += length2; } |
︙ | ︙ | |||
6602 6603 6604 6605 6606 6607 6608 | } if (status != TCL_OK) { CACHE_STACK_INFO(); goto gotError; } CACHE_STACK_INFO(); | < | 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 | } if (status != TCL_OK) { CACHE_STACK_INFO(); goto gotError; } CACHE_STACK_INFO(); valIndex = (iterNum * numVars); for (j = 0; j < numVars; j++) { if (valIndex >= listLen) { TclNewObj(valuePtr); } else { DECACHE_STACK_INFO(); if (elements) { |
︙ | ︙ | |||
7381 7382 7383 7384 7385 7386 7387 | TCL_LEAVE_ERR_MSG, "set", 1, 1, &arrayPtr); if (varPtr == NULL) { TRACE_ERROR(interp); TclDecrRefCount(keysPtr); goto gotError; } DECACHE_STACK_INFO(); | | | 7381 7382 7383 7384 7385 7386 7387 7388 7389 7390 7391 7392 7393 7394 7395 | TCL_LEAVE_ERR_MSG, "set", 1, 1, &arrayPtr); if (varPtr == NULL) { TRACE_ERROR(interp); TclDecrRefCount(keysPtr); goto gotError; } DECACHE_STACK_INFO(); result = TclDictWithFinish(interp, varPtr, arrayPtr, varNamePtr, NULL, -1, objc, objv, keysPtr); CACHE_STACK_INFO(); TclDecrRefCount(keysPtr); if (result != TCL_OK) { TRACE_ERROR(interp); goto gotError; } |
︙ | ︙ | |||
7424 7425 7426 7427 7428 7429 7430 | break; /* * End of dictionary-related instructions. * ----------------------------------------------------------------- */ | | < | | | | | | | | | | | | | | | | | | | | | > | | | | | | | 7424 7425 7426 7427 7428 7429 7430 7431 7432 7433 7434 7435 7436 7437 7438 7439 7440 7441 7442 7443 7444 7445 7446 7447 7448 7449 7450 7451 7452 7453 7454 7455 7456 7457 7458 7459 7460 7461 7462 7463 7464 7465 7466 7467 7468 7469 | break; /* * End of dictionary-related instructions. * ----------------------------------------------------------------- */ case INST_CLOCK_READ: { /* Read the wall clock */ Tcl_WideInt wval; Tcl_Time now; switch (TclGetUInt1AtPtr(pc+1)) { case 0: /* clicks */ #ifdef TCL_WIDE_CLICKS wval = TclpGetWideClicks(); #else wval = (Tcl_WideInt)TclpGetClicks(); #endif break; case 1: /* microseconds */ Tcl_GetTime(&now); wval = (Tcl_WideInt)now.sec * 1000000 + now.usec; break; case 2: /* milliseconds */ Tcl_GetTime(&now); wval = (Tcl_WideInt)now.sec * 1000 + now.usec / 1000; break; case 3: /* seconds */ Tcl_GetTime(&now); wval = (Tcl_WideInt)now.sec; break; default: Tcl_Panic("clockRead instruction with unknown clock#"); break; } TclNewIntObj(objResultPtr, wval); TRACE_WITH_OBJ(("=> "), objResultPtr); NEXT_INST_F(2, 0, 1); } break; default: Tcl_Panic("TclNRExecuteByteCode: unrecognized opCode %u", *pc); } /* end of switch on opCode */ /* * Block for variables needed to process exception returns. |
︙ | ︙ | |||
8654 8655 8656 8657 8658 8659 8660 | } overflowBasic: Tcl_TakeBignumFromObj(NULL, valuePtr, &big1); Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); err = mp_init(&bigResult); if (err == MP_OKAY) { | | | | | | | 8654 8655 8656 8657 8658 8659 8660 8661 8662 8663 8664 8665 8666 8667 8668 8669 8670 8671 8672 8673 8674 8675 8676 8677 8678 | } overflowBasic: Tcl_TakeBignumFromObj(NULL, valuePtr, &big1); Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2); err = mp_init(&bigResult); if (err == MP_OKAY) { switch (opcode) { case INST_ADD: err = mp_add(&big1, &big2, &bigResult); break; case INST_SUB: err = mp_sub(&big1, &big2, &bigResult); break; case INST_MULT: err = mp_mul(&big1, &big2, &bigResult); break; case INST_DIV: if (mp_iszero(&big2)) { mp_clear(&big1); mp_clear(&big2); mp_clear(&bigResult); return DIVIDED_BY_ZERO; } err = mp_init(&bigRemainder); |
︙ | ︙ | |||
8958 8959 8960 8961 8962 8963 8964 | * None. * *---------------------------------------------------------------------- */ static void PrintByteCodeInfo( | | > > | > > > | > > > | > | > | > | 8958 8959 8960 8961 8962 8963 8964 8965 8966 8967 8968 8969 8970 8971 8972 8973 8974 8975 8976 8977 8978 8979 8980 8981 8982 8983 8984 8985 8986 8987 8988 8989 8990 8991 8992 8993 8994 8995 8996 8997 8998 8999 9000 9001 9002 9003 9004 9005 9006 9007 9008 9009 9010 9011 9012 9013 9014 9015 9016 9017 9018 | * None. * *---------------------------------------------------------------------- */ static void PrintByteCodeInfo( ByteCode *codePtr) /* The bytecode whose summary is printed to * stdout. */ { Proc *procPtr = codePtr->procPtr; Interp *iPtr = (Interp *) *codePtr->interpHandle; fprintf(stdout, "\nExecuting ByteCode 0x%p, refCt %" TCL_Z_MODIFIER "u, epoch %" TCL_Z_MODIFIER "u, interp 0x%p (epoch %" TCL_Z_MODIFIER "u)\n", codePtr, codePtr->refCount, codePtr->compileEpoch, iPtr, iPtr->compileEpoch); fprintf(stdout, " Source: "); TclPrintSource(stdout, codePtr->source, 60); fprintf(stdout, "\n Cmds %" TCL_Z_MODIFIER "u, src %" TCL_Z_MODIFIER "u, inst %" TCL_Z_MODIFIER "u, litObjs %" TCL_Z_MODIFIER "u, aux %" TCL_Z_MODIFIER "u, stkDepth %" TCL_Z_MODIFIER "u, code/src %.2f\n", codePtr->numCommands, codePtr->numSrcBytes, codePtr->numCodeBytes, codePtr->numLitObjects, codePtr->numAuxDataItems, codePtr->maxStackDepth, #ifdef TCL_COMPILE_STATS codePtr->numSrcBytes? ((float)codePtr->structureSize)/codePtr->numSrcBytes : #endif 0.0); #ifdef TCL_COMPILE_STATS fprintf(stdout, " Code %" TCL_Z_MODIFIER "u = header %" TCL_Z_MODIFIER "u+inst %" TCL_Z_MODIFIER "u+litObj %" TCL_Z_MODIFIER "u+exc %" TCL_Z_MODIFIER "u+aux %" TCL_Z_MODIFIER "u+cmdMap %" TCL_Z_MODIFIER "u\n", codePtr->structureSize, offsetof(ByteCode, localCachePtr), codePtr->numCodeBytes, codePtr->numLitObjects * sizeof(Tcl_Obj *), codePtr->numExceptRanges*sizeof(ExceptionRange), codePtr->numAuxDataItems * sizeof(AuxData), codePtr->numCmdLocBytes); #endif /* TCL_COMPILE_STATS */ if (procPtr != NULL) { fprintf(stdout, " Proc 0x%p, refCt %" TCL_Z_MODIFIER "u, args %" TCL_Z_MODIFIER "u, compiled locals %" TCL_Z_MODIFIER "u\n", procPtr, procPtr->refCount, procPtr->numArgs, procPtr->numCompiledLocals); } } #endif /* TCL_COMPILE_DEBUG */ /* |
︙ | ︙ | |||
9022 9023 9024 9025 9026 9027 9028 | * *---------------------------------------------------------------------- */ #ifdef TCL_COMPILE_DEBUG static void ValidatePcAndStackTop( | | | 9033 9034 9035 9036 9037 9038 9039 9040 9041 9042 9043 9044 9045 9046 9047 | * *---------------------------------------------------------------------- */ #ifdef TCL_COMPILE_DEBUG static void ValidatePcAndStackTop( ByteCode *codePtr, /* The bytecode whose summary is printed to * stdout. */ const unsigned char *pc, /* Points to first byte of a bytecode * instruction. The program counter. */ size_t stackTop, /* Current stack top. Must be between * stackLowerBound and stackUpperBound * (inclusive). */ int checkStack) /* 0 if the stack depth check should be |
︙ | ︙ | |||
9062 9063 9064 9065 9066 9067 9068 | stackTop, relativePc, stackUpperBound); if (cmd != NULL) { Tcl_Obj *message; TclNewLiteralStringObj(message, "\n executing "); Tcl_IncrRefCount(message); Tcl_AppendLimitedToObj(message, cmd, numChars, 100, NULL); | | | 9073 9074 9075 9076 9077 9078 9079 9080 9081 9082 9083 9084 9085 9086 9087 | stackTop, relativePc, stackUpperBound); if (cmd != NULL) { Tcl_Obj *message; TclNewLiteralStringObj(message, "\n executing "); Tcl_IncrRefCount(message); Tcl_AppendLimitedToObj(message, cmd, numChars, 100, NULL); fprintf(stderr, "%s\n", TclGetString(message)); Tcl_DecrRefCount(message); } else { fprintf(stderr, "\n"); } Tcl_Panic("TclNRExecuteByteCode execution failure: bad stack top"); } } |
︙ | ︙ | |||
9094 9095 9096 9097 9098 9099 9100 | *---------------------------------------------------------------------- */ static void IllegalExprOperandType( Tcl_Interp *interp, /* Interpreter to which error information * pertains. */ | | | 9105 9106 9107 9108 9109 9110 9111 9112 9113 9114 9115 9116 9117 9118 9119 | *---------------------------------------------------------------------- */ static void IllegalExprOperandType( Tcl_Interp *interp, /* Interpreter to which error information * pertains. */ const unsigned char *pc, /* Points to the instruction being executed * when the illegal type was found. */ Tcl_Obj *opndPtr) /* Points to the operand holding the value * with the illegal type. */ { void *ptr; int type; const unsigned char opcode = *pc; |
︙ | ︙ | |||
9158 9159 9160 9161 9162 9163 9164 | Tcl_Obj * TclGetSourceFromFrame( CmdFrame *cfPtr, Tcl_Size objc, Tcl_Obj *const objv[]) { if (cfPtr == NULL) { | | | | | | | | 9169 9170 9171 9172 9173 9174 9175 9176 9177 9178 9179 9180 9181 9182 9183 9184 9185 9186 9187 9188 9189 9190 9191 9192 9193 9194 9195 9196 9197 | Tcl_Obj * TclGetSourceFromFrame( CmdFrame *cfPtr, Tcl_Size objc, Tcl_Obj *const objv[]) { if (cfPtr == NULL) { return Tcl_NewListObj(objc, objv); } if (cfPtr->cmdObj == NULL) { if (cfPtr->cmd == NULL) { ByteCode *codePtr = (ByteCode *)cfPtr->data.tebc.codePtr; cfPtr->cmd = GetSrcInfoForPc((unsigned char *) cfPtr->data.tebc.pc, codePtr, &cfPtr->len, NULL, NULL); } if (cfPtr->cmd) { cfPtr->cmdObj = Tcl_NewStringObj(cfPtr->cmd, cfPtr->len); } else { cfPtr->cmdObj = Tcl_NewListObj(objc, objv); } Tcl_IncrRefCount(cfPtr->cmdObj); } return cfPtr->cmdObj; } void TclGetSrcInfoForPc( CmdFrame *cfPtr) |
︙ | ︙ | |||
9813 9814 9815 9816 9817 9818 9819 | statsPtr->currentByteCodeBytes / numCurrentByteCodes); Tcl_AppendPrintfToObj(objPtr, "Header %12.6g %8.1f%% %8.1f\n", currentHeaderBytes, Percent(currentHeaderBytes, statsPtr->currentByteCodeBytes), currentHeaderBytes / numCurrentByteCodes); Tcl_AppendPrintfToObj(objPtr, "Instructions %12.6g %8.1f%% %8.1f\n", statsPtr->currentInstBytes, | | | | | | | 9824 9825 9826 9827 9828 9829 9830 9831 9832 9833 9834 9835 9836 9837 9838 9839 9840 9841 9842 9843 9844 9845 9846 9847 9848 9849 9850 9851 9852 9853 9854 | statsPtr->currentByteCodeBytes / numCurrentByteCodes); Tcl_AppendPrintfToObj(objPtr, "Header %12.6g %8.1f%% %8.1f\n", currentHeaderBytes, Percent(currentHeaderBytes, statsPtr->currentByteCodeBytes), currentHeaderBytes / numCurrentByteCodes); Tcl_AppendPrintfToObj(objPtr, "Instructions %12.6g %8.1f%% %8.1f\n", statsPtr->currentInstBytes, Percent(statsPtr->currentInstBytes, statsPtr->currentByteCodeBytes), statsPtr->currentInstBytes / numCurrentByteCodes); Tcl_AppendPrintfToObj(objPtr, "Literal ptr array %12.6g %8.1f%% %8.1f\n", statsPtr->currentLitBytes, Percent(statsPtr->currentLitBytes, statsPtr->currentByteCodeBytes), statsPtr->currentLitBytes / numCurrentByteCodes); Tcl_AppendPrintfToObj(objPtr, "Exception table %12.6g %8.1f%% %8.1f\n", statsPtr->currentExceptBytes, Percent(statsPtr->currentExceptBytes, statsPtr->currentByteCodeBytes), statsPtr->currentExceptBytes / numCurrentByteCodes); Tcl_AppendPrintfToObj(objPtr, "Auxiliary data %12.6g %8.1f%% %8.1f\n", statsPtr->currentAuxBytes, Percent(statsPtr->currentAuxBytes, statsPtr->currentByteCodeBytes), statsPtr->currentAuxBytes / numCurrentByteCodes); Tcl_AppendPrintfToObj(objPtr, "Command map %12.6g %8.1f%% %8.1f\n", statsPtr->currentCmdMapBytes, Percent(statsPtr->currentCmdMapBytes, statsPtr->currentByteCodeBytes), statsPtr->currentCmdMapBytes / numCurrentByteCodes); /* * Detailed literal statistics. */ Tcl_AppendPrintfToObj(objPtr, "\nLiteral string sizes:\n"); |
︙ | ︙ |
Changes to generic/tclHash.c.
︙ | ︙ | |||
210 211 212 213 214 215 216 | static Tcl_HashEntry * FindHashEntry( Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */ const char *key) /* Key to use to find matching entry. */ { return CreateHashEntry(tablePtr, key, NULL); } | < | 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | static Tcl_HashEntry * FindHashEntry( Tcl_HashTable *tablePtr, /* Table in which to lookup entry. */ const char *key) /* Key to use to find matching entry. */ { return CreateHashEntry(tablePtr, key, NULL); } /* *---------------------------------------------------------------------- * * CreateHashEntry -- * * Given a hash table with string keys, and a string key, find the entry |
︙ | ︙ | |||
297 298 299 300 301 302 303 | for (hPtr = tablePtr->buckets[index]; hPtr != NULL; hPtr = hPtr->nextPtr) { if (hash != hPtr->hash) { continue; } /* if needle pointer equals content pointer or values equal */ if ((key == hPtr->key.string) | | < | 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | for (hPtr = tablePtr->buckets[index]; hPtr != NULL; hPtr = hPtr->nextPtr) { if (hash != hPtr->hash) { continue; } /* if needle pointer equals content pointer or values equal */ if ((key == hPtr->key.string) || compareKeysProc((void *) key, hPtr)) { if (newPtr) { *newPtr = 0; } return hPtr; } } } |
︙ | ︙ |
Changes to generic/tclIO.c.
︙ | ︙ | |||
93 94 95 96 97 98 99 100 101 102 103 104 105 106 | * copy. Note that the data buffer for the copy will be appended to this * structure. */ typedef struct CopyState { struct Channel *readPtr; /* Pointer to input channel. */ struct Channel *writePtr; /* Pointer to output channel. */ int readFlags; /* Original read channel flags. */ int writeFlags; /* Original write channel flags. */ Tcl_WideInt toRead; /* Number of bytes to copy, or -1. */ Tcl_WideInt total; /* Total bytes transferred (written). */ Tcl_Interp *interp; /* Interp that started the copy. */ Tcl_Obj *cmdPtr; /* Command to be invoked at completion. */ Tcl_Size bufSize; /* Size of appended buffer. */ | > | 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | * copy. Note that the data buffer for the copy will be appended to this * structure. */ typedef struct CopyState { struct Channel *readPtr; /* Pointer to input channel. */ struct Channel *writePtr; /* Pointer to output channel. */ int refCount; /* Reference counter. */ int readFlags; /* Original read channel flags. */ int writeFlags; /* Original write channel flags. */ Tcl_WideInt toRead; /* Number of bytes to copy, or -1. */ Tcl_WideInt total; /* Total bytes transferred (written). */ Tcl_Interp *interp; /* Interp that started the copy. */ Tcl_Obj *cmdPtr; /* Command to be invoked at completion. */ Tcl_Size bufSize; /* Size of appended buffer. */ |
︙ | ︙ | |||
218 219 220 221 222 223 224 225 226 227 228 229 230 231 | int charsLeft, int *factorPtr); static void RecycleBuffer(ChannelState *statePtr, ChannelBuffer *bufPtr, int mustDiscard); static int StackSetBlockMode(Channel *chanPtr, int mode); static int SetBlockMode(Tcl_Interp *interp, Channel *chanPtr, int mode); static void StopCopy(CopyState *csPtr); static void TranslateInputEOL(ChannelState *statePtr, char *dst, const char *src, int *dstLenPtr, int *srcLenPtr); static void UpdateInterest(Channel *chanPtr); static Tcl_Size Write(Channel *chanPtr, const char *src, Tcl_Size srcLen, Tcl_Encoding encoding); static Tcl_Obj * FixLevelCode(Tcl_Obj *msg); static void SpliceChannel(Tcl_Channel chan); | > | 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 | int charsLeft, int *factorPtr); static void RecycleBuffer(ChannelState *statePtr, ChannelBuffer *bufPtr, int mustDiscard); static int StackSetBlockMode(Channel *chanPtr, int mode); static int SetBlockMode(Tcl_Interp *interp, Channel *chanPtr, int mode); static void StopCopy(CopyState *csPtr); static void CopyDecrRefCount(CopyState *csPtr); static void TranslateInputEOL(ChannelState *statePtr, char *dst, const char *src, int *dstLenPtr, int *srcLenPtr); static void UpdateInterest(Channel *chanPtr); static Tcl_Size Write(Channel *chanPtr, const char *src, Tcl_Size srcLen, Tcl_Encoding encoding); static Tcl_Obj * FixLevelCode(Tcl_Obj *msg); static void SpliceChannel(Tcl_Channel chan); |
︙ | ︙ | |||
2083 2084 2085 2086 2087 2088 2089 | Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not flush channel \"%s\"", Tcl_GetChannelName((Tcl_Channel) chanPtr))); } return TCL_ERROR; } | | | 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 | Tcl_SetObjResult(interp, Tcl_ObjPrintf( "could not flush channel \"%s\"", Tcl_GetChannelName((Tcl_Channel) chanPtr))); } return TCL_ERROR; } statePtr->csPtrR = csPtrR; statePtr->csPtrW = csPtrW; } /* * Anything in the input queue and the push-back buffers of the * transformation going away is transformed data, but not yet read. As * unstacking means that the caller does not want to see transformed |
︙ | ︙ | |||
3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 | goto done; } done: TclChannelRelease((Tcl_Channel)chanPtr); return errorCode; } /* *---------------------------------------------------------------------- * * CloseChannel -- * * Utility procedure to close a channel and free associated resources. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 | goto done; } done: TclChannelRelease((Tcl_Channel)chanPtr); return errorCode; } static void FreeChannelState( void *blockPtr) /* Channel state to free. */ { ChannelState *statePtr = (ChannelState *)blockPtr; /* * Even after close some members can be filled again (in events etc). * Test in bug [79474c588] illustrates one leak (on remaining chanMsg). * Possible other fields need freeing on some constellations. */ DiscardInputQueued(statePtr, 1); if (statePtr->curOutPtr != NULL) { ReleaseChannelBuffer(statePtr->curOutPtr); } DiscardOutputQueued(statePtr); DeleteTimerHandler(statePtr); if (statePtr->chanMsg) { Tcl_DecrRefCount(statePtr->chanMsg); } if (statePtr->unreportedMsg) { Tcl_DecrRefCount(statePtr->unreportedMsg); } Tcl_Free(statePtr); } /* *---------------------------------------------------------------------- * * CloseChannel -- * * Utility procedure to close a channel and free associated resources. |
︙ | ︙ | |||
3177 3178 3179 3180 3181 3182 3183 | * There is only the TOP Channel, so we free the remaining pointers we * have and then ourselves. Since this is the last of the channels in the * stack, make sure to free the ChannelState structure associated with it. */ ChannelFree(chanPtr); | | | 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 | * There is only the TOP Channel, so we free the remaining pointers we * have and then ourselves. Since this is the last of the channels in the * stack, make sure to free the ChannelState structure associated with it. */ ChannelFree(chanPtr); Tcl_EventuallyFree(statePtr, FreeChannelState); return errorCode; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
3985 3986 3987 3988 3989 3990 3991 | } statePtr->chPtr = NULL; /* * Cancel any pending copy operation. */ | > | > > > | > > | 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 | } statePtr->chPtr = NULL; /* * Cancel any pending copy operation. */ if (statePtr->csPtrR) { StopCopy(statePtr->csPtrR); statePtr->csPtrR = NULL; } if (statePtr->csPtrW) { StopCopy(statePtr->csPtrW); statePtr->csPtrW = NULL; } /* * Must set the interest mask now to 0, otherwise infinite loops will * occur if Tcl_DoOneEvent is called before the channel is finally deleted * in FlushChannel. This can happen if the channel has a background flush * active. */ |
︙ | ︙ | |||
8707 8708 8709 8710 8711 8712 8713 | } } if (!statePtr->timer && (mask & TCL_WRITABLE) && GotFlag(statePtr, CHANNEL_NONBLOCKING) && bufPtr | | | < | 8743 8744 8745 8746 8747 8748 8749 8750 8751 8752 8753 8754 8755 8756 8757 8758 | } } if (!statePtr->timer && (mask & TCL_WRITABLE) && GotFlag(statePtr, CHANNEL_NONBLOCKING) && bufPtr && !IsBufferEmpty(bufPtr) && !IsBufferFull(bufPtr)) { TclChannelPreserve((Tcl_Channel)chanPtr); statePtr->timerChanPtr = chanPtr; statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME, ChannelTimerProc,chanPtr); } ChanWatch(chanPtr, mask); |
︙ | ︙ | |||
8794 8795 8796 8797 8798 8799 8800 | } Tcl_Release(statePtr); } } static void DeleteTimerHandler( | | < | < > | 8829 8830 8831 8832 8833 8834 8835 8836 8837 8838 8839 8840 8841 8842 8843 8844 8845 8846 8847 8848 8849 8850 8851 8852 8853 | } Tcl_Release(statePtr); } } static void DeleteTimerHandler( ChannelState *statePtr) { if (statePtr->timer != NULL) { Tcl_DeleteTimerHandler(statePtr->timer); CleanupTimerHandler(statePtr); } } static void CleanupTimerHandler( ChannelState *statePtr) { TclChannelRelease((Tcl_Channel)statePtr->timerChanPtr); statePtr->timer = NULL; statePtr->timerChanPtr = NULL; } /* *---------------------------------------------------------------------- |
︙ | ︙ | |||
9388 9389 9390 9391 9392 9393 9394 9395 9396 9397 9398 9399 9400 9401 9402 9403 9404 | * completed. */ csPtr = (CopyState *)Tcl_Alloc(offsetof(CopyState, buffer) + 1U + !moveBytes * inStatePtr->bufSize); csPtr->bufSize = !moveBytes * inStatePtr->bufSize; csPtr->readPtr = inPtr; csPtr->writePtr = outPtr; csPtr->readFlags = readFlags; csPtr->writeFlags = writeFlags; csPtr->toRead = toRead; csPtr->total = (Tcl_WideInt) 0; csPtr->interp = interp; if (cmdPtr) { Tcl_IncrRefCount(cmdPtr); } csPtr->cmdPtr = cmdPtr; | > > > > | | | 9422 9423 9424 9425 9426 9427 9428 9429 9430 9431 9432 9433 9434 9435 9436 9437 9438 9439 9440 9441 9442 9443 9444 9445 9446 9447 9448 9449 9450 9451 9452 9453 9454 9455 9456 9457 9458 9459 9460 9461 9462 9463 9464 | * completed. */ csPtr = (CopyState *)Tcl_Alloc(offsetof(CopyState, buffer) + 1U + !moveBytes * inStatePtr->bufSize); csPtr->bufSize = !moveBytes * inStatePtr->bufSize; csPtr->readPtr = inPtr; csPtr->writePtr = outPtr; csPtr->refCount = 2; /* two references below (inStatePtr, outStatePtr) */ csPtr->readFlags = readFlags; csPtr->writeFlags = writeFlags; csPtr->toRead = toRead; csPtr->total = (Tcl_WideInt) 0; csPtr->interp = interp; if (cmdPtr) { Tcl_IncrRefCount(cmdPtr); } csPtr->cmdPtr = cmdPtr; TclChannelPreserve(inChan); TclChannelPreserve(outChan); inStatePtr->csPtrR = csPtr; outStatePtr->csPtrW = csPtr; if (moveBytes) { return MoveBytes(csPtr); } /* * Special handling of -size 0 async transfers, so that the -command is * still called asynchronously. */ if ((nonBlocking == CHANNEL_NONBLOCKING) && (toRead == 0)) { Tcl_CreateTimerHandler(0, ZeroTransferTimerProc, csPtr); return TCL_OK; } /* * Start copying data between the channels. */ return CopyData(csPtr, 0); |
︙ | ︙ | |||
9687 9688 9689 9690 9691 9692 9693 9694 9695 9696 9697 9698 9699 9700 | Tcl_Size sizePart; Tcl_WideInt total; Tcl_WideInt size; const char *buffer; int moveBytes; int underflow; /* Input underflow */ inChan = (Tcl_Channel) csPtr->readPtr; outChan = (Tcl_Channel) csPtr->writePtr; inStatePtr = csPtr->readPtr->state; outStatePtr = csPtr->writePtr->state; interp = csPtr->interp; cmdPtr = csPtr->cmdPtr; | > > | 9725 9726 9727 9728 9729 9730 9731 9732 9733 9734 9735 9736 9737 9738 9739 9740 | Tcl_Size sizePart; Tcl_WideInt total; Tcl_WideInt size; const char *buffer; int moveBytes; int underflow; /* Input underflow */ csPtr->refCount++; /* avoid freeing during handling */ inChan = (Tcl_Channel) csPtr->readPtr; outChan = (Tcl_Channel) csPtr->writePtr; inStatePtr = csPtr->readPtr->state; outStatePtr = csPtr->writePtr->state; interp = csPtr->interp; cmdPtr = csPtr->cmdPtr; |
︙ | ︙ | |||
9831 9832 9833 9834 9835 9836 9837 | continue; } if (bufObj != NULL) { TclDecrRefCount(bufObj); bufObj = NULL; } | | | 9871 9872 9873 9874 9875 9876 9877 9878 9879 9880 9881 9882 9883 9884 9885 | continue; } if (bufObj != NULL) { TclDecrRefCount(bufObj); bufObj = NULL; } goto done; } } /* * Now write the buffer out. */ |
︙ | ︙ | |||
9917 9918 9919 9920 9921 9922 9923 | Tcl_CreateChannelHandler(outChan, TCL_WRITABLE, CopyEventProc, csPtr); } if (bufObj != NULL) { TclDecrRefCount(bufObj); bufObj = NULL; } | | | 9957 9958 9959 9960 9961 9962 9963 9964 9965 9966 9967 9968 9969 9970 9971 | Tcl_CreateChannelHandler(outChan, TCL_WRITABLE, CopyEventProc, csPtr); } if (bufObj != NULL) { TclDecrRefCount(bufObj); bufObj = NULL; } goto done; } /* * For background copies, we only do one buffer per invocation so we * don't starve the rest of the system. */ |
︙ | ︙ | |||
9939 9940 9941 9942 9943 9944 9945 | Tcl_CreateChannelHandler(outChan, TCL_WRITABLE, CopyEventProc, csPtr); } if (bufObj != NULL) { TclDecrRefCount(bufObj); bufObj = NULL; } | | | 9979 9980 9981 9982 9983 9984 9985 9986 9987 9988 9989 9990 9991 9992 9993 | Tcl_CreateChannelHandler(outChan, TCL_WRITABLE, CopyEventProc, csPtr); } if (bufObj != NULL) { TclDecrRefCount(bufObj); bufObj = NULL; } goto done; } } /* while */ if (bufObj != NULL) { TclDecrRefCount(bufObj); bufObj = NULL; } |
︙ | ︙ | |||
9991 9992 9993 9994 9995 9996 9997 9998 9999 10000 10001 10002 10003 10004 | result = TCL_ERROR; } else { Tcl_ResetResult(interp); Tcl_SetObjResult(interp, Tcl_NewWideIntObj(total)); } } } return result; } /* *---------------------------------------------------------------------- * * DoRead -- | > > > | 10031 10032 10033 10034 10035 10036 10037 10038 10039 10040 10041 10042 10043 10044 10045 10046 10047 | result = TCL_ERROR; } else { Tcl_ResetResult(interp); Tcl_SetObjResult(interp, Tcl_NewWideIntObj(total)); } } } done: CopyDecrRefCount(csPtr); return result; } /* *---------------------------------------------------------------------- * * DoRead -- |
︙ | ︙ | |||
10100 10101 10102 10103 10104 10105 10106 | * to fill the dst */ int code; moreData: code = GetInput(chanPtr); bufPtr = statePtr->inQueueHead; | < < | < | < | < < < | > > > > > > | 10143 10144 10145 10146 10147 10148 10149 10150 10151 10152 10153 10154 10155 10156 10157 10158 10159 10160 10161 10162 10163 10164 10165 10166 10167 10168 10169 10170 10171 10172 10173 10174 10175 10176 10177 10178 10179 | * to fill the dst */ int code; moreData: code = GetInput(chanPtr); bufPtr = statePtr->inQueueHead; if (GotFlag(statePtr, CHANNEL_EOF|CHANNEL_BLOCKED)) { /* * Further reads cannot do any more. */ break; } if (code || !bufPtr) { /* Read error (or channel dead/closed) */ goto readErr; } assert(IsBufferFull(bufPtr)); } if (!bufPtr) { readErr: UpdateInterest(chanPtr); TclChannelRelease((Tcl_Channel)chanPtr); return -1; } bytesRead = BytesLeft(bufPtr); bytesWritten = bytesToRead; TranslateInputEOL(statePtr, p, RemovePoint(bufPtr), &bytesWritten, &bytesRead); bufPtr->nextRemoved += bytesRead; |
︙ | ︙ | |||
10293 10294 10295 10296 10297 10298 10299 | ChannelState *inStatePtr, ChannelState *outStatePtr, long long toRead) { return inStatePtr->inEofChar == '\0' /* No eofChar to stop input */ && inStatePtr->inputTranslation == TCL_TRANSLATE_LF && outStatePtr->outputTranslation == TCL_TRANSLATE_LF | < < | < | < < < | | < | 10335 10336 10337 10338 10339 10340 10341 10342 10343 10344 10345 10346 10347 10348 10349 10350 10351 10352 10353 10354 10355 | ChannelState *inStatePtr, ChannelState *outStatePtr, long long toRead) { return inStatePtr->inEofChar == '\0' /* No eofChar to stop input */ && inStatePtr->inputTranslation == TCL_TRANSLATE_LF && outStatePtr->outputTranslation == TCL_TRANSLATE_LF && ((inStatePtr->encoding == GetBinaryEncoding() && outStatePtr->encoding == GetBinaryEncoding()) || (toRead == -1 && inStatePtr->encoding == outStatePtr->encoding && ENCODING_PROFILE_GET(inStatePtr->inputEncodingFlags) == TCL_ENCODING_PROFILE_TCL8 && ENCODING_PROFILE_GET(outStatePtr->inputEncodingFlags) == TCL_ENCODING_PROFILE_TCL8 )); } /* *---------------------------------------------------------------------- * * StopCopy -- * |
︙ | ︙ | |||
10372 10373 10374 10375 10376 10377 10378 10379 | Tcl_DeleteChannelHandler(inChan, CopyEventProc, csPtr); if (inChan != outChan) { Tcl_DeleteChannelHandler(outChan, CopyEventProc, csPtr); } Tcl_DeleteChannelHandler(inChan, MBEvent, csPtr); Tcl_DeleteChannelHandler(outChan, MBEvent, csPtr); TclDecrRefCount(csPtr->cmdPtr); } | > > > > | > > > > | > > > > > > > > > > > > > > > | 10407 10408 10409 10410 10411 10412 10413 10414 10415 10416 10417 10418 10419 10420 10421 10422 10423 10424 10425 10426 10427 10428 10429 10430 10431 10432 10433 10434 10435 10436 10437 10438 10439 10440 10441 10442 10443 10444 10445 10446 | Tcl_DeleteChannelHandler(inChan, CopyEventProc, csPtr); if (inChan != outChan) { Tcl_DeleteChannelHandler(outChan, CopyEventProc, csPtr); } Tcl_DeleteChannelHandler(inChan, MBEvent, csPtr); Tcl_DeleteChannelHandler(outChan, MBEvent, csPtr); TclDecrRefCount(csPtr->cmdPtr); csPtr->cmdPtr = NULL; } if (inStatePtr->csPtrR) { assert(inStatePtr->csPtrR == csPtr); inStatePtr->csPtrR = NULL; CopyDecrRefCount(csPtr); } if (outStatePtr->csPtrW) { assert(outStatePtr->csPtrW == csPtr); outStatePtr->csPtrW = NULL; CopyDecrRefCount(csPtr); } } static void CopyDecrRefCount( CopyState *csPtr) { if (csPtr->refCount-- > 1) { return; } TclChannelRelease((Tcl_Channel)csPtr->readPtr); TclChannelRelease((Tcl_Channel)csPtr->writePtr); Tcl_Free(csPtr); } /* *---------------------------------------------------------------------- * * StackSetBlockMode -- |
︙ | ︙ |
Changes to generic/tclIO.h.
︙ | ︙ | |||
183 184 185 186 187 188 189 | * handlers for. */ EventScriptRecord *scriptRecordPtr; /* Chain of all scripts registered for event * handlers ("fileevent") on this channel. */ Tcl_Size bufSize; /* What size buffers to allocate? */ Tcl_TimerToken timer; /* Handle to wakeup timer for this channel. */ Channel *timerChanPtr; /* Needed in order to decrement the refCount of | | | | 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | * handlers for. */ EventScriptRecord *scriptRecordPtr; /* Chain of all scripts registered for event * handlers ("fileevent") on this channel. */ Tcl_Size bufSize; /* What size buffers to allocate? */ Tcl_TimerToken timer; /* Handle to wakeup timer for this channel. */ Channel *timerChanPtr; /* Needed in order to decrement the refCount of * the right channel when the timer is * deleted. */ struct CopyState *csPtrR; /* State of background copy for which channel * is input, or NULL. */ struct CopyState *csPtrW; /* State of background copy for which channel * is output, or NULL. */ Channel *topChanPtr; /* Refers to topmost channel in a stack. Never * NULL. */ Channel *bottomChanPtr; /* Refers to bottommost channel in a stack. |
︙ | ︙ |
Changes to generic/tclIOCmd.c.
︙ | ︙ | |||
602 603 604 605 606 607 608 | newLoc = Tcl_Tell(chan); /* * TIP #219. * Capture error messages put by the driver into the bypass area and put * them into the regular interpreter result. */ | < | 602 603 604 605 606 607 608 609 610 611 612 613 614 615 | newLoc = Tcl_Tell(chan); /* * TIP #219. * Capture error messages put by the driver into the bypass area and put * them into the regular interpreter result. */ code = TclChanCaughtErrorBypass(interp, chan); TclChannelRelease(chan); if (code) { return TCL_ERROR; } |
︙ | ︙ |
Changes to generic/tclIORChan.c.
︙ | ︙ | |||
58 59 60 61 62 63 64 | static void TimerRunWrite(void *clientData); /* * The C layer channel type/driver definition used by the reflection. */ static const Tcl_ChannelType tclRChannelType = { | | | | | | | | | | | | | | | | | | < | | < | | < | < | | < | 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | static void TimerRunWrite(void *clientData); /* * The C layer channel type/driver definition used by the reflection. */ static const Tcl_ChannelType tclRChannelType = { "tclrchannel", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ NULL, /* Old close API */ ReflectInput, /* Handle read request */ ReflectOutput, /* Handle write request */ NULL, ReflectSetOption, /* Set options. */ ReflectGetOption, /* Get options. */ ReflectWatch, /* Initialize notifier */ NULL, /* Get OS handle from the channel. */ ReflectClose, /* Close channel. Clean instance data */ ReflectBlock, /* Set blocking/nonblocking. */ NULL, /* Flush channel. */ NULL, /* Handle events. */ ReflectSeekWide, /* Move access point (64 bit). */ #if TCL_THREADS ReflectThread, /* thread action, tracking owner */ #else NULL, /* thread action */ #endif ReflectTruncate /* Truncate. */ }; /* * Instance data for a reflected channel. =========================== */ typedef struct { Tcl_Channel chan; /* Back reference to generic channel * structure. */ Tcl_Interp *interp; /* Reference to the interpreter containing the * Tcl level part of the channel. NULL here * signals the channel is dead because the * interpreter/thread containing its Tcl * command is gone. */ #if TCL_THREADS Tcl_ThreadId thread; /* Thread the 'interp' belongs to. == Handler thread */ Tcl_ThreadId owner; /* Thread owning the structure. == Channel thread */ #endif Tcl_Obj *cmd; /* Callback command prefix */ Tcl_Obj *methods; /* Methods to append to command prefix */ Tcl_Obj *name; /* Name of the channel as created */ int mode; /* Mask of R/W mode */ int interest; /* Mask of events the channel is interested * in. */ int dead; /* Boolean signal that some operations * should no longer be attempted. */ Tcl_TimerToken readTimer; /* A token for the timer that is scheduled in * order to call Tcl_NotifyChannel when the * channel is readable */ Tcl_TimerToken writeTimer; /* A token for the timer that is scheduled in * order to call Tcl_NotifyChannel when the * channel is writable */ /* * Note regarding the usage of timers. * * Most channel implementations need a timer in the C level to ensure that * data in buffers is flushed out through the generation of fake file * events. |
︙ | ︙ | |||
262 263 264 265 266 267 268 | * ForwardParamBase. Where an operation does not need any special types, it * has no "subtype" and just uses ForwardParamBase, as listed above.) */ struct ForwardParamInput { ForwardParamBase base; /* "Supertype". MUST COME FIRST. */ char *buf; /* O: Where to store the read bytes */ | | | 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 | * ForwardParamBase. Where an operation does not need any special types, it * has no "subtype" and just uses ForwardParamBase, as listed above.) */ struct ForwardParamInput { ForwardParamBase base; /* "Supertype". MUST COME FIRST. */ char *buf; /* O: Where to store the read bytes */ Tcl_Size toRead; /* I: #bytes to read, * O: #bytes actually read */ }; struct ForwardParamOutput { ForwardParamBase base; /* "Supertype". MUST COME FIRST. */ const char *buf; /* I: Where the bytes to write come from */ Tcl_Size toWrite; /* I: #bytes to write, * O: #bytes actually written */ |
︙ | ︙ | |||
509 510 511 512 513 514 515 | Tcl_Obj *rcId; /* Handle of the new channel */ int mode; /* R/W mode of new channel. Has to match * abilities of handler commands */ Tcl_Obj *cmdObj; /* Command prefix, list of words */ Tcl_Obj *cmdNameObj; /* Command name */ Tcl_Channel chan; /* Token for the new channel */ Tcl_Obj *modeObj; /* mode in obj form for method call */ | | | 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 | Tcl_Obj *rcId; /* Handle of the new channel */ int mode; /* R/W mode of new channel. Has to match * abilities of handler commands */ Tcl_Obj *cmdObj; /* Command prefix, list of words */ Tcl_Obj *cmdNameObj; /* Command name */ Tcl_Channel chan; /* Token for the new channel */ Tcl_Obj *modeObj; /* mode in obj form for method call */ Tcl_Size listc; /* Result of 'initialize', and of */ Tcl_Obj **listv; /* its sublist in the 2nd element */ int methIndex; /* Encoded method name */ int result; /* Result code for 'initialize' */ Tcl_Obj *resObj; /* Result data for 'initialize' */ int methods; /* Bitmask for supported methods. */ Channel *chanPtr; /* 'chan' resolved to internal struct. */ Tcl_Obj *err; /* Error message */ |
︙ | ︙ | |||
2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 | resObj = Tcl_ObjPrintf("rc%lu", rcCounter); rcCounter++; Tcl_MutexUnlock(&rcCounterMutex); return resObj; } static void FreeReflectedChannel( void *blockPtr) { ReflectedChannel *rcPtr = (ReflectedChannel *) blockPtr; Channel *chanPtr = (Channel *) rcPtr->chan; TclChannelRelease((Tcl_Channel)chanPtr); | > > > > > > > > > > > > > > > > > > > > > > | < < < < < < < < | 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 | resObj = Tcl_ObjPrintf("rc%lu", rcCounter); rcCounter++; Tcl_MutexUnlock(&rcCounterMutex); return resObj; } static inline void CleanRefChannelInstance( ReflectedChannel *rcPtr) { if (rcPtr->name) { /* * Reset obj-type (channel is deleted or dead anyway) to avoid leakage * by cyclic references (see bug [79474c58800cdf94]). */ TclFreeInternalRep(rcPtr->name); Tcl_DecrRefCount(rcPtr->name); rcPtr->name = NULL; } if (rcPtr->methods) { Tcl_DecrRefCount(rcPtr->methods); rcPtr->methods = NULL; } if (rcPtr->cmd) { Tcl_DecrRefCount(rcPtr->cmd); rcPtr->cmd = NULL; } } static void FreeReflectedChannel( void *blockPtr) { ReflectedChannel *rcPtr = (ReflectedChannel *) blockPtr; Channel *chanPtr = (Channel *) rcPtr->chan; TclChannelRelease((Tcl_Channel)chanPtr); CleanRefChannelInstance(rcPtr); Tcl_Free(rcPtr); } /* *---------------------------------------------------------------------- * * InvokeTclMethod -- |
︙ | ︙ | |||
2598 2599 2600 2601 2602 2603 2604 | static void MarkDead( ReflectedChannel *rcPtr) { if (rcPtr->dead) { return; } | | < < < < < < < < < < < | 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 | static void MarkDead( ReflectedChannel *rcPtr) { if (rcPtr->dead) { return; } CleanRefChannelInstance(rcPtr); rcPtr->dead = 1; } static void DeleteReflectedChannelMap( void *clientData, /* The per-interpreter data structure. */ Tcl_Interp *interp) /* The interpreter being deleted. */ |
︙ | ︙ |
Changes to generic/tclIORTrans.c.
︙ | ︙ | |||
54 55 56 57 58 59 60 | /* * The C layer channel type/driver definition used by the reflection. */ static const Tcl_ChannelType tclRTransformType = { "tclrtransform", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel. */ | | | | | < | 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | /* * The C layer channel type/driver definition used by the reflection. */ static const Tcl_ChannelType tclRTransformType = { "tclrtransform", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel. */ NULL, ReflectInput, /* Handle read request. */ ReflectOutput, /* Handle write request. */ NULL, /* Move location of access point. */ ReflectSetOption, /* Set options. */ ReflectGetOption, /* Get options. */ ReflectWatch, /* Initialize notifier. */ ReflectHandle, /* Get OS handle from the channel. */ ReflectClose, /* Close channel, clean instance data. */ ReflectBlock, /* Set blocking/nonblocking. */ NULL, /* Flush channel. Not used by core. */ ReflectNotify, /* Handle events. */ ReflectSeekWide, /* Move access point (64 bit). */ NULL, /* thread action */ NULL /* truncate */ }; /* |
︙ | ︙ | |||
507 508 509 510 511 512 513 | int mode; /* R/W mode of parent, later the new channel. * Has to match the abilities of the handler * commands */ Tcl_Obj *cmdObj; /* Command prefix, list of words */ Tcl_Obj *cmdNameObj; /* Command name */ Tcl_Obj *rtId; /* Handle of the new transform (channel) */ Tcl_Obj *modeObj; /* mode in obj form for method call */ | | | 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 | int mode; /* R/W mode of parent, later the new channel. * Has to match the abilities of the handler * commands */ Tcl_Obj *cmdObj; /* Command prefix, list of words */ Tcl_Obj *cmdNameObj; /* Command name */ Tcl_Obj *rtId; /* Handle of the new transform (channel) */ Tcl_Obj *modeObj; /* mode in obj form for method call */ Tcl_Size listc; /* Result of 'initialize', and of */ Tcl_Obj **listv; /* its sublist in the 2nd element */ int methIndex; /* Encoded method name */ int result; /* Result code for 'initialize' */ Tcl_Obj *resObj; /* Result data for 'initialize' */ int methods; /* Bitmask for supported methods. */ ReflectedTransformMap *rtmPtr; /* Map of reflected transforms with handlers |
︙ | ︙ | |||
1101 1102 1103 1104 1105 1106 1107 | goto stop; } if (rtPtr->eofPending) { goto stop; } | < | 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 | goto stop; } if (rtPtr->eofPending) { goto stop; } /* * The buffer is exhausted, but the caller wants even more. We now * have to go to the underlying channel, get more bytes and then * transform them for delivery. We may not get what we want (full EOF * or temporarily out of data). * * Length (rtPtr->result) == 0, toRead > 0 here. Use 'buf'! as target |
︙ | ︙ | |||
1136 1137 1138 1139 1140 1141 1142 | } } /* else: 'maxRead < 0' == Accept the current value of toRead */ } if (toRead <= 0) { goto stop; } | < | 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 | } } /* else: 'maxRead < 0' == Accept the current value of toRead */ } if (toRead <= 0) { goto stop; } readBytes = Tcl_ReadRaw(rtPtr->parent, (char *) Tcl_SetByteArrayLength(bufObj, toRead), toRead); if (readBytes < 0) { if (Tcl_InputBlocked(rtPtr->parent) && (gotBytes > 0)) { /* |
︙ | ︙ | |||
1488 1489 1490 1491 1492 1493 1494 | * Arbitrary, per the parent channel. * *---------------------------------------------------------------------- */ static int ReflectSetOption( | | | 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 | * Arbitrary, per the parent channel. * *---------------------------------------------------------------------- */ static int ReflectSetOption( void *clientData, /* Channel to query */ Tcl_Interp *interp, /* Interpreter to leave error messages in */ const char *optionName, /* Name of requested option */ const char *newValue) /* The new value */ { ReflectedTransform *rtPtr = (ReflectedTransform *)clientData; /* |
︙ | ︙ | |||
1530 1531 1532 1533 1534 1535 1536 | * Arbitrary, per the parent channel. * *---------------------------------------------------------------------- */ static int ReflectGetOption( | | | 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 | * Arbitrary, per the parent channel. * *---------------------------------------------------------------------- */ static int ReflectGetOption( void *clientData, /* Channel to query */ Tcl_Interp *interp, /* Interpreter to leave error messages in */ const char *optionName, /* Name of requested option */ Tcl_DString *dsPtr) /* String to place the result into */ { ReflectedTransform *rtPtr = (ReflectedTransform *)clientData; /* |
︙ | ︙ | |||
1641 1642 1643 1644 1645 1646 1647 | return mask; } /* * Helpers. ========================================================= */ | < | 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 | return mask; } /* * Helpers. ========================================================= */ /* *---------------------------------------------------------------------- * * DecodeEventMask -- * * This function takes an internal bitmask of events and constructs the |
︙ | ︙ | |||
2071 2072 2073 2074 2075 2076 2077 | *---------------------------------------------------------------------- */ static ReflectedTransformMap * GetReflectedTransformMap( Tcl_Interp *interp) { | | > | 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 | *---------------------------------------------------------------------- */ static ReflectedTransformMap * GetReflectedTransformMap( Tcl_Interp *interp) { ReflectedTransformMap *rtmPtr = (ReflectedTransformMap *) Tcl_GetAssocData(interp, RTMKEY, NULL); if (rtmPtr == NULL) { rtmPtr = (ReflectedTransformMap *)Tcl_Alloc(sizeof(ReflectedTransformMap)); Tcl_InitHashTable(&rtmPtr->map, TCL_STRING_KEYS); Tcl_SetAssocData(interp, RTMKEY, (Tcl_InterpDeleteProc *) DeleteReflectedTransformMap, rtmPtr); } |
︙ | ︙ | |||
2104 2105 2106 2107 2108 2109 2110 | * registered in this interpreter. * *---------------------------------------------------------------------- */ static void DeleteReflectedTransformMap( | | | 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 | * registered in this interpreter. * *---------------------------------------------------------------------- */ static void DeleteReflectedTransformMap( void *clientData, /* The per-interpreter data structure. */ Tcl_Interp *interp) /* The interpreter being deleted. */ { ReflectedTransformMap *rtmPtr; /* The map */ Tcl_HashSearch hSearch; /* Search variable. */ Tcl_HashEntry *hPtr; /* Search variable. */ ReflectedTransform *rtPtr; #if TCL_THREADS |
︙ | ︙ | |||
2239 2240 2241 2242 2243 2244 2245 | static ReflectedTransformMap * GetThreadReflectedTransformMap(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!tsdPtr->rtmPtr) { | | > | 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 | static ReflectedTransformMap * GetThreadReflectedTransformMap(void) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (!tsdPtr->rtmPtr) { tsdPtr->rtmPtr = (ReflectedTransformMap *) Tcl_Alloc(sizeof(ReflectedTransformMap)); Tcl_InitHashTable(&tsdPtr->rtmPtr->map, TCL_STRING_KEYS); Tcl_CreateThreadExitHandler(DeleteThreadReflectedTransformMap, NULL); } return tsdPtr->rtmPtr; } |
︙ | ︙ | |||
2989 2990 2991 2992 2993 2994 2995 | *---------------------------------------------------------------------- */ static inline size_t ResultCopy( ResultBuffer *rPtr, /* The buffer to read from */ unsigned char *buf, /* The buffer to copy into */ | | | 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 | *---------------------------------------------------------------------- */ static inline size_t ResultCopy( ResultBuffer *rPtr, /* The buffer to read from */ unsigned char *buf, /* The buffer to copy into */ size_t toRead) /* Number of requested bytes */ { int copied; if (rPtr->used == 0) { /* * Nothing to copy in the case of an empty buffer. */ |
︙ | ︙ |
Changes to generic/tclIOSock.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | #if defined(_WIN32) /* * On Windows, we need to do proper Unicode->UTF-8 conversion. */ typedef struct { int initialized; | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #if defined(_WIN32) /* * On Windows, we need to do proper Unicode->UTF-8 conversion. */ typedef struct { int initialized; Tcl_DString errorMsg; /* UTF-8 encoded error-message */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; #undef gai_strerror static const char * gai_strerror( int code) |
︙ | ︙ | |||
71 72 73 74 75 76 77 | const char *native; if (Tcl_GetInt(NULL, string, portPtr) != TCL_OK) { /* * Don't bother translating 'proto' to native. */ | | > | 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | const char *native; if (Tcl_GetInt(NULL, string, portPtr) != TCL_OK) { /* * Don't bother translating 'proto' to native. */ if (Tcl_UtfToExternalDStringEx(interp, NULL, string, -1, 0, &ds, NULL) != TCL_OK) { Tcl_DStringFree(&ds); return TCL_ERROR; } native = Tcl_DStringValue(&ds); sp = getservbyname(native, proto); /* INTL: Native. */ Tcl_DStringFree(&ds); if (sp != NULL) { |
︙ | ︙ | |||
184 185 186 187 188 189 190 | struct addrinfo *v6head = NULL, *v6ptr = NULL; char *native = NULL, portbuf[TCL_INTEGER_SPACE], *portstring; const char *family = NULL; Tcl_DString ds; int result; if (host != NULL) { | | > | 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | struct addrinfo *v6head = NULL, *v6ptr = NULL; char *native = NULL, portbuf[TCL_INTEGER_SPACE], *portstring; const char *family = NULL; Tcl_DString ds; int result; if (host != NULL) { if (Tcl_UtfToExternalDStringEx(interp, NULL, host, -1, 0, &ds, NULL) != TCL_OK) { Tcl_DStringFree(&ds); return 0; } native = Tcl_DStringValue(&ds); } /* |
︙ | ︙ |
Changes to generic/tclIOUtil.c.
︙ | ︙ | |||
31 32 33 34 35 36 37 | /* * struct FilesystemRecord -- * * An item in a linked list of registered filesystems */ typedef struct FilesystemRecord { | | | < | < | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | /* * struct FilesystemRecord -- * * An item in a linked list of registered filesystems */ typedef struct FilesystemRecord { void *clientData; /* Client-specific data for the filesystem * (can be NULL) */ const Tcl_Filesystem *fsPtr;/* Pointer to filesystem dispatch table. */ struct FilesystemRecord *nextPtr; /* The next registered filesystem, or NULL to * indicate the end of the list. */ struct FilesystemRecord *prevPtr; /* The previous filesystem, or NULL to indicate * the ned of the list */ } FilesystemRecord; /* */ typedef struct { int initialized; size_t cwdPathEpoch; /* Compared with the global cwdPathEpoch to * determine whether cwdPathPtr is stale. */ size_t filesystemEpoch; Tcl_Obj *cwdPathPtr; /* A private copy of cwdPathPtr. Updated when * the value is accessed and cwdPathEpoch has * changed. */ void *cwdClientData; FilesystemRecord *filesystemList; size_t claims; } ThreadSpecificData; /* * Forward declarations. |
︙ | ︙ | |||
101 102 103 104 105 106 107 | * Functions that support the native filesystem functions listed above. They * are the same for win/unix, and not in tclInt.h because they are and should * be used only here. */ MODULE_SCOPE const char *const tclpFileAttrStrings[]; MODULE_SCOPE const TclFileAttrProcs tclpFileAttrProcs[]; | < | 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | * Functions that support the native filesystem functions listed above. They * are the same for win/unix, and not in tclInt.h because they are and should * be used only here. */ MODULE_SCOPE const char *const tclpFileAttrStrings[]; MODULE_SCOPE const TclFileAttrProcs tclpFileAttrProcs[]; /* * These these functions are not static either because routines in the native * (win/unix) directories call them or they are actually implemented in those * directories. They should be called from outside Tcl's native filesystem * routines. If we ever built the native filesystem support into a separate * code library, this could actually be enforced. |
︙ | ︙ | |||
238 239 240 241 242 243 244 | * Obsolete string-based APIs that should be removed in a future release, * perhaps in Tcl 9. */ /* Obsolete */ int Tcl_Stat( | | > | 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 | * Obsolete string-based APIs that should be removed in a future release, * perhaps in Tcl 9. */ /* Obsolete */ int Tcl_Stat( const char *path, /* Pathname of file to stat (in current system * encoding). */ struct stat *oldStyleBuf) /* Filled with results of stat call. */ { int ret; Tcl_StatBuf buf; Tcl_Obj *pathPtr = Tcl_NewStringObj(path,-1); Tcl_IncrRefCount(pathPtr); |
︙ | ︙ | |||
325 326 327 328 329 330 331 | } return ret; } /* Obsolete */ int Tcl_Access( | | | | 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 | } return ret; } /* Obsolete */ int Tcl_Access( const char *path, /* Pathname of file to access (in current * system encoding). */ int mode) /* Permission setting. */ { int ret; Tcl_Obj *pathPtr = Tcl_NewStringObj(path,-1); Tcl_IncrRefCount(pathPtr); ret = Tcl_FSAccess(pathPtr,mode); |
︙ | ︙ | |||
841 842 843 844 845 846 847 | * registered filesystems. * *---------------------------------------------------------------------- */ int Tcl_FSRegister( | | | 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 | * registered filesystems. * *---------------------------------------------------------------------- */ int Tcl_FSRegister( void *clientData, /* Client-specific data for this filesystem. */ const Tcl_Filesystem *fsPtr)/* The filesystem record for the new fs. */ { FilesystemRecord *newFilesystemPtr; if (fsPtr == NULL) { return TCL_ERROR; } |
︙ | ︙ | |||
1101 1102 1103 1104 1105 1106 1107 | static void FsAddMountsToGlobResult( Tcl_Obj *resultPtr, /* The current list of matching pathnames. Must * not be shared. */ Tcl_Obj *pathPtr, /* The directory that was searched. */ const char *pattern, /* Pattern to match mounts against. */ Tcl_GlobTypeData *types) /* Acceptable types. May be NULL. The | | < | 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 | static void FsAddMountsToGlobResult( Tcl_Obj *resultPtr, /* The current list of matching pathnames. Must * not be shared. */ Tcl_Obj *pathPtr, /* The directory that was searched. */ const char *pattern, /* Pattern to match mounts against. */ Tcl_GlobTypeData *types) /* Acceptable types. May be NULL. The * directory flag is particularly significant. */ { Tcl_Size mLength, gLength, i; int dir = (types == NULL || (types->type & TCL_GLOB_TYPE_DIR)); Tcl_Obj *mounts = FsListMounts(pathPtr, pattern); if (mounts == NULL) { return; |
︙ | ︙ | |||
1166 1167 1168 1169 1170 1171 1172 | /* * Deal with the root of the volume. */ len--; } len++; /* account for '/' in the mElt [Bug 1602539] */ | < | 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 | /* * Deal with the root of the volume. */ len--; } len++; /* account for '/' in the mElt [Bug 1602539] */ mElt = TclNewFSPathObj(pathPtr, mount + len, mlen - len); Tcl_ListObjAppendElement(NULL, resultPtr, mElt); } /* * Not comparing mounts to mounts, so no need to increment gLength */ |
︙ | ︙ | |||
1361 1362 1363 1364 1365 1366 1367 | * Call the the normalizePathProc routine of each registered filesystem. */ firstFsRecPtr = FsGetFirstFilesystem(); Claim(); if (!isVfsPath) { | < | 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 | * Call the the normalizePathProc routine of each registered filesystem. */ firstFsRecPtr = FsGetFirstFilesystem(); Claim(); if (!isVfsPath) { /* * Find and call the native filesystem handler first if there is one * because the root of Tcl's filesystem is always a native filesystem * (i.e., '/' on unix is native). */ for (fsRecPtr=firstFsRecPtr; fsRecPtr!=NULL; fsRecPtr=fsRecPtr->nextPtr) { |
︙ | ︙ | |||
1689 1690 1691 1692 1693 1694 1695 | int Tcl_FSEvalFileEx( Tcl_Interp *interp, /* Interpreter that evaluates the script. */ Tcl_Obj *pathPtr, /* Pathname of the file to process. * Tilde-substitution is performed on this * pathname. */ const char *encodingName) /* Either the name of an encoding or NULL to | | | 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 | int Tcl_FSEvalFileEx( Tcl_Interp *interp, /* Interpreter that evaluates the script. */ Tcl_Obj *pathPtr, /* Pathname of the file to process. * Tilde-substitution is performed on this * pathname. */ const char *encodingName) /* Either the name of an encoding or NULL to * use the utf-8 encoding. */ { Tcl_Size length; int result = TCL_ERROR; Tcl_StatBuf statBuf; Tcl_Obj *oldScriptFile; Interp *iPtr; const char *string; |
︙ | ︙ | |||
2082 2083 2084 2085 2086 2087 2088 | * *---------------------------------------------------------------------- */ int Tcl_FSStat( Tcl_Obj *pathPtr, /* Pathname of the file to call stat on (in | | | 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 | * *---------------------------------------------------------------------- */ int Tcl_FSStat( Tcl_Obj *pathPtr, /* Pathname of the file to call stat on (in * current system encoding). */ Tcl_StatBuf *buf) /* A buffer to hold the results of the call to * stat. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); if (fsPtr != NULL && fsPtr->statProc != NULL) { return fsPtr->statProc(pathPtr, buf); |
︙ | ︙ | |||
2117 2118 2119 2120 2121 2122 2123 | * *---------------------------------------------------------------------- */ int Tcl_FSLstat( Tcl_Obj *pathPtr, /* Pathname of the file to call stat on (in | | | 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 | * *---------------------------------------------------------------------- */ int Tcl_FSLstat( Tcl_Obj *pathPtr, /* Pathname of the file to call stat on (in * current system encoding). */ Tcl_StatBuf *buf) /* Filled with results of that call to stat. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); if (fsPtr != NULL) { if (fsPtr->lstatProc != NULL) { return fsPtr->lstatProc(pathPtr, buf); |
︙ | ︙ | |||
2154 2155 2156 2157 2158 2159 2160 | * See access documentation. * *---------------------------------------------------------------------- */ int Tcl_FSAccess( | | > | 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 | * See access documentation. * *---------------------------------------------------------------------- */ int Tcl_FSAccess( Tcl_Obj *pathPtr, /* Pathname of file to access (in current * system encoding). */ int mode) /* Permission setting. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); if (fsPtr != NULL && fsPtr->accessProc != NULL) { return fsPtr->accessProc(pathPtr, mode); } |
︙ | ︙ | |||
2191 2192 2193 2194 2195 2196 2197 | Tcl_Channel Tcl_FSOpenFileChannel( Tcl_Interp *interp, /* Interpreter for error reporting, or NULL */ Tcl_Obj *pathPtr, /* Pathname of file to open. */ const char *modeString, /* A list of POSIX open modes or a string such * as "rw". */ int permissions) /* What modes to use if opening the file | | < | 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 | Tcl_Channel Tcl_FSOpenFileChannel( Tcl_Interp *interp, /* Interpreter for error reporting, or NULL */ Tcl_Obj *pathPtr, /* Pathname of file to open. */ const char *modeString, /* A list of POSIX open modes or a string such * as "rw". */ int permissions) /* What modes to use if opening the file * involves creating it. */ { const Tcl_Filesystem *fsPtr; Tcl_Channel retVal = NULL; if (Tcl_FSGetNormalizedPath(interp, pathPtr) == NULL) { /* * Return the correct error message. */ return NULL; } |
︙ | ︙ | |||
3016 3017 3018 3019 3020 3021 3022 | * *---------------------------------------------------------------------- */ int Tcl_FSLoadFile( Tcl_Interp *interp, /* Used for error reporting. */ | | | | 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 | * *---------------------------------------------------------------------- */ int Tcl_FSLoadFile( Tcl_Interp *interp, /* Used for error reporting. */ Tcl_Obj *pathPtr, /* Pathname of the file containing the dynamic * shared object. */ const char *sym1, const char *sym2, /* Names of two functions to find in the * dynamic shared object. */ Tcl_LibraryInitProc **proc1Ptr, Tcl_LibraryInitProc **proc2Ptr, /* Places to store pointers to the functions * named by sym1 and sym2. */ Tcl_LoadHandle *handlePtr, /* A place to store the token for the loaded |
︙ | ︙ | |||
3105 3106 3107 3108 3109 3110 3111 | Tcl_Obj *shlibFile) { /* * Unlinking is not performed in the following cases: * * 1. The operating system is HPUX. * | | | | | < | 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 | Tcl_Obj *shlibFile) { /* * Unlinking is not performed in the following cases: * * 1. The operating system is HPUX. * * 2. If the environment variable TCL_TEMPLOAD_NO_UNLINK is present and * set to true (an integer > 0) * * 3. TCL_TEMPLOAD_NO_UNLINK is not true (an integer > 0) and AUFS * filesystem can be detected (using statfs, if available). */ #ifdef hpux (void)shlibFile; return 1; #else WCHAR *skipstr = getenv("TCL_TEMPLOAD_NO_UNLINK"); |
︙ | ︙ | |||
3651 3652 3653 3654 3655 3656 3657 | * *--------------------------------------------------------------------------- */ Tcl_Obj * Tcl_FSLink( Tcl_Obj *pathPtr, /* Pathaname of file. */ | < | < | 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 | * *--------------------------------------------------------------------------- */ Tcl_Obj * Tcl_FSLink( Tcl_Obj *pathPtr, /* Pathaname of file. */ Tcl_Obj *toPtr, /* NULL or the pathname of a file to link to. */ int linkAction) /* Action to perform. */ { const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr); if (fsPtr) { if (fsPtr->linkProc == NULL) { Tcl_SetErrno(ENOTSUP); |
︙ | ︙ | |||
3902 3903 3904 3905 3906 3907 3908 | Tcl_PathType TclGetPathType( Tcl_Obj *pathPtr, /* Pathname to determine type of. */ const Tcl_Filesystem **filesystemPtrPtr, /* If not NULL, a place in which to store a * pointer to the filesystem for this pathname * if it is absolute. */ | | > | 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 | Tcl_PathType TclGetPathType( Tcl_Obj *pathPtr, /* Pathname to determine type of. */ const Tcl_Filesystem **filesystemPtrPtr, /* If not NULL, a place in which to store a * pointer to the filesystem for this pathname * if it is absolute. */ Tcl_Size *driveNameLengthPtr, /* If not NULL, a place in which to store the * length of the volume name. */ Tcl_Obj **driveNameRef) /* If not NULL, for an absolute pathname, a * place to store a pointer to an object with a * refCount of 1, and whose value is the name * of the volume. */ { Tcl_Size pathLen; |
︙ | ︙ | |||
3956 3957 3958 3959 3960 3961 3962 | TclFSNonnativePathType( const char *path, /* Pathname to determine the type of. */ Tcl_Size pathLen, /* Length of the pathname. */ const Tcl_Filesystem **filesystemPtrPtr, /* If not NULL, a place to store a pointer to * the filesystem for this pathname when it is * an absolute pathname. */ | | > | < | 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 | TclFSNonnativePathType( const char *path, /* Pathname to determine the type of. */ Tcl_Size pathLen, /* Length of the pathname. */ const Tcl_Filesystem **filesystemPtrPtr, /* If not NULL, a place to store a pointer to * the filesystem for this pathname when it is * an absolute pathname. */ Tcl_Size *driveNameLengthPtr, /* If not NULL, a place to store the length of * the volume name if the pathname is absolute. */ Tcl_Obj **driveNameRef) /* If not NULL, a place to store a pointer to * an object having its its refCount already * incremented, and contining the name of the * volume if the pathname is absolute. */ { FilesystemRecord *fsRecPtr; Tcl_PathType type = TCL_PATH_RELATIVE; |
︙ | ︙ | |||
4074 4075 4076 4077 4078 4079 4080 | * *--------------------------------------------------------------------------- */ int Tcl_FSRenameFile( Tcl_Obj *srcPathPtr, /* The pathname of a file or directory to be | | | 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 | * *--------------------------------------------------------------------------- */ int Tcl_FSRenameFile( Tcl_Obj *srcPathPtr, /* The pathname of a file or directory to be * renamed. */ Tcl_Obj *destPathPtr) /* The new pathname for the file. */ { int retVal = -1; const Tcl_Filesystem *fsPtr, *fsPtr2; fsPtr = Tcl_FSGetFileSystemForPath(srcPathPtr); fsPtr2 = Tcl_FSGetFileSystemForPath(destPathPtr); |
︙ | ︙ |
Changes to generic/tclInt.h.
︙ | ︙ | |||
251 252 253 254 255 256 257 | typedef struct Namespace { char *name; /* The namespace's simple (unqualified) name. * This contains no ::'s. The name of the * global namespace is "" although "::" is an * synonym. */ char *fullName; /* The namespace's fully qualified name. This * starts with ::. */ | | | | 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 | typedef struct Namespace { char *name; /* The namespace's simple (unqualified) name. * This contains no ::'s. The name of the * global namespace is "" although "::" is an * synonym. */ char *fullName; /* The namespace's fully qualified name. This * starts with ::. */ void *clientData; /* An arbitrary value associated with this * namespace. */ Tcl_NamespaceDeleteProc *deleteProc; /* Procedure invoked when deleting the * namespace to, e.g., free clientData. */ struct Namespace *parentPtr;/* Points to the namespace that contains this * one. NULL if this is the global * namespace. */ #ifndef BREAK_NAMESPACE_COMPAT Tcl_HashTable childTable; /* Contains any child namespaces. Indexed by * strings; values have type (Namespace *). */ #else Tcl_HashTable *childTablePtr; /* Contains any child namespaces. Indexed by * strings; values have type (Namespace *). If * NULL, there are no children. */ #endif size_t nsId; /* Unique id for the namespace. */ Tcl_Interp *interp; /* The interpreter containing this * namespace. */ int flags; /* OR-ed combination of the namespace status * flags NS_DYING and NS_DEAD listed below. */ Tcl_Size activationCount; /* Number of "activations" or active call * frames for this namespace that are on the * Tcl call stack. The namespace won't be * freed until activationCount becomes zero. */ |
︙ | ︙ | |||
302 303 304 305 306 307 308 | * commands; however, no namespace qualifiers * are allowed. NULL if no export patterns are * registered. */ Tcl_Size numExportPatterns; /* Number of export patterns currently * registered using "namespace export". */ Tcl_Size maxExportPatterns; /* Number of export patterns for which space * is currently allocated. */ | | | | 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 | * commands; however, no namespace qualifiers * are allowed. NULL if no export patterns are * registered. */ Tcl_Size numExportPatterns; /* Number of export patterns currently * registered using "namespace export". */ Tcl_Size maxExportPatterns; /* Number of export patterns for which space * is currently allocated. */ Tcl_Size cmdRefEpoch; /* Incremented if a newly added command * shadows a command for which this namespace * has already cached a Command* pointer; this * causes all its cached Command* pointers to * be invalidated. */ Tcl_Size resolverEpoch; /* Incremented whenever (a) the name * resolution rules change for this namespace * or (b) a newly added command shadows a * command that is compiled to bytecodes. This * invalidates all byte codes compiled in the * namespace, causing the code to be * recompiled under the new rules.*/ Tcl_ResolveCmdProc *cmdResProc; |
︙ | ︙ | |||
414 415 416 417 418 419 420 | /* * Flags passed to TclGetNamespaceForQualName: * * TCL_GLOBAL_ONLY - (see tcl.h) Look only in the global ns. * TCL_NAMESPACE_ONLY - (see tcl.h) Look only in the context ns. * TCL_CREATE_NS_IF_UNKNOWN - Create unknown namespaces. * TCL_FIND_ONLY_NS - The name sought is a namespace name. | | | | 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 | /* * Flags passed to TclGetNamespaceForQualName: * * TCL_GLOBAL_ONLY - (see tcl.h) Look only in the global ns. * TCL_NAMESPACE_ONLY - (see tcl.h) Look only in the context ns. * TCL_CREATE_NS_IF_UNKNOWN - Create unknown namespaces. * TCL_FIND_ONLY_NS - The name sought is a namespace name. * TCL_FIND_IF_NOT_SIMPLE - Retrieve last namespace even if the rest of * name is not simple name (contains ::). */ #define TCL_CREATE_NS_IF_UNKNOWN 0x800 #define TCL_FIND_ONLY_NS 0x1000 #define TCL_FIND_IF_NOT_SIMPLE 0x2000 /* |
︙ | ︙ | |||
437 438 439 440 441 442 443 | typedef struct EnsembleConfig { Namespace *nsPtr; /* The namespace backing this ensemble up. */ Tcl_Command token; /* The token for the command that provides * ensemble support for the namespace, or NULL * if the command has been deleted (or never * existed; the global namespace never has an * ensemble command.) */ | | | 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 | typedef struct EnsembleConfig { Namespace *nsPtr; /* The namespace backing this ensemble up. */ Tcl_Command token; /* The token for the command that provides * ensemble support for the namespace, or NULL * if the command has been deleted (or never * existed; the global namespace never has an * ensemble command.) */ Tcl_Size epoch; /* The epoch at which this ensemble's table of * exported commands is valid. */ char **subcommandArrayPtr; /* Array of ensemble subcommand names. At all * consistent points, this will have the same * number of entries as there are entries in * the subcommandTable hash. */ Tcl_HashTable subcommandTable; /* Hash table of ensemble subcommand names, |
︙ | ︙ | |||
494 495 496 497 498 499 500 | * results passed directly back to the caller * (including the error code) unless the code * is TCL_CONTINUE in which case the * subcommand will be re-parsed by the ensemble * core, presumably because the ensemble * itself has been updated. */ Tcl_Obj *parameterList; /* List of ensemble parameter names. */ | | | 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 | * results passed directly back to the caller * (including the error code) unless the code * is TCL_CONTINUE in which case the * subcommand will be re-parsed by the ensemble * core, presumably because the ensemble * itself has been updated. */ Tcl_Obj *parameterList; /* List of ensemble parameter names. */ Tcl_Size numParameters; /* Cached number of parameters. This is either * 0 (if the parameterList field is NULL) or * the length of the list in the parameterList * field. */ } EnsembleConfig; /* * Various bits for the EnsembleConfig.flags field. |
︙ | ︙ | |||
524 525 526 527 528 529 530 | * specific C procedure whenever certain operations are performed on a * variable. */ typedef struct VarTrace { Tcl_VarTraceProc *traceProc;/* Procedure to call when operations given by * flags are performed on variable. */ | | | | 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 | * specific C procedure whenever certain operations are performed on a * variable. */ typedef struct VarTrace { Tcl_VarTraceProc *traceProc;/* Procedure to call when operations given by * flags are performed on variable. */ void *clientData; /* Argument to pass to proc. */ int flags; /* What events the trace procedure is * interested in: OR-ed combination of * TCL_TRACE_READS, TCL_TRACE_WRITES, * TCL_TRACE_UNSETS and TCL_TRACE_ARRAY. */ struct VarTrace *nextPtr; /* Next in list of traces associated with a * particular variable. */ } VarTrace; /* * The following structure defines a command trace, which is used to invoke a * specific C procedure whenever certain operations are performed on a * command. */ typedef struct CommandTrace { Tcl_CommandTraceProc *traceProc; /* Procedure to call when operations given by * flags are performed on command. */ void *clientData; /* Argument to pass to proc. */ int flags; /* What events the trace procedure is * interested in: OR-ed combination of * TCL_TRACE_RENAME, TCL_TRACE_DELETE. */ struct CommandTrace *nextPtr; /* Next in list of traces associated with a * particular command. */ Tcl_Size refCount; /* Used to ensure this structure is not |
︙ | ︙ | |||
824 825 826 827 828 829 830 | * MODULE_SCOPE int TclIsVarTemporary(Var *varPtr); * MODULE_SCOPE int TclIsVarArgument(Var *varPtr); * MODULE_SCOPE int TclIsVarResolved(Var *varPtr); */ #define TclVarFindHiddenArray(varPtr,arrayPtr) \ do { \ | | | | | | 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 | * MODULE_SCOPE int TclIsVarTemporary(Var *varPtr); * MODULE_SCOPE int TclIsVarArgument(Var *varPtr); * MODULE_SCOPE int TclIsVarResolved(Var *varPtr); */ #define TclVarFindHiddenArray(varPtr,arrayPtr) \ do { \ if ((arrayPtr == NULL) && TclIsVarInHash(varPtr) && \ (TclVarParentArray(varPtr) != NULL)) { \ arrayPtr = TclVarParentArray(varPtr); \ } \ } while(0) #define TclIsVarScalar(varPtr) \ !((varPtr)->flags & (VAR_ARRAY|VAR_LINK)) #define TclIsVarLink(varPtr) \ ((varPtr)->flags & VAR_LINK) |
︙ | ︙ | |||
893 894 895 896 897 898 899 | /* * Macros for direct variable access by TEBC. */ #define TclIsVarTricky(varPtr,trickyFlags) \ ( ((varPtr)->flags & (VAR_ARRAY|VAR_LINK|trickyFlags)) \ | | | | | | | 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 | /* * Macros for direct variable access by TEBC. */ #define TclIsVarTricky(varPtr,trickyFlags) \ ( ((varPtr)->flags & (VAR_ARRAY|VAR_LINK|trickyFlags)) \ || (TclIsVarInHash(varPtr) \ && (TclVarParentArray(varPtr) != NULL) \ && (TclVarParentArray(varPtr)->flags & (trickyFlags)))) #define TclIsVarDirectReadable(varPtr) \ ( (!TclIsVarTricky(varPtr,VAR_TRACED_READ)) \ && (varPtr)->value.objPtr) #define TclIsVarDirectWritable(varPtr) \ (!TclIsVarTricky(varPtr,VAR_TRACED_WRITE|VAR_DEAD_HASH|VAR_CONSTANT)) #define TclIsVarDirectUnsettable(varPtr) \ (!TclIsVarTricky(varPtr,VAR_TRACED_READ|VAR_TRACED_WRITE|VAR_TRACED_UNSET|VAR_DEAD_HASH|VAR_CONSTANT)) #define TclIsVarDirectModifyable(varPtr) \ ( (!TclIsVarTricky(varPtr,VAR_TRACED_READ|VAR_TRACED_WRITE|VAR_CONSTANT)) \ && (varPtr)->value.objPtr) #define TclIsVarDirectReadable2(varPtr, arrayPtr) \ (TclIsVarDirectReadable(varPtr) &&\ (!(arrayPtr) || !((arrayPtr)->flags & VAR_TRACED_READ))) #define TclIsVarDirectWritable2(varPtr, arrayPtr) \ (TclIsVarDirectWritable(varPtr) &&\ |
︙ | ︙ | |||
963 964 965 966 967 968 969 | */ typedef struct CompiledLocal { struct CompiledLocal *nextPtr; /* Next compiler-recognized local variable for * this procedure, or NULL if this is the last * local. */ | | | | | 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 | */ typedef struct CompiledLocal { struct CompiledLocal *nextPtr; /* Next compiler-recognized local variable for * this procedure, or NULL if this is the last * local. */ Tcl_Size nameLength; /* The number of bytes in local variable's name. * Among others used to speed up var lookups. */ Tcl_Size frameIndex; /* Index in the array of compiler-assigned * variables in the procedure call frame. */ Tcl_Obj *defValuePtr; /* Pointer to the default value of an * argument, if any. NULL if not an argument * or, if an argument, no default value. */ Tcl_ResolvedVarInfo *resolveInfo; /* Customized variable resolution info * supplied by the Tcl_ResolveCompiledVarProc * associated with a namespace. Each variable * is marked by a unique tag during * compilation, and that same tag is used to * find the variable at runtime. */ int flags; /* Flag bits for the local variable. Same as * the flags for the Var structure above, * although only VAR_ARGUMENT, VAR_TEMPORARY, * and VAR_RESOLVED make sense. */ char name[TCLFLEXARRAY]; /* Name of the local variable starts here. If * the name is NULL, this will just be '\0'. * The actual size of this field will be large * enough to hold the name. MUST BE THE LAST * FIELD IN THE STRUCTURE! */ } CompiledLocal; /* |
︙ | ︙ | |||
1039 1040 1041 1042 1043 1044 1045 | * clients to find out whenever a command is about to be executed. */ typedef struct Trace { Tcl_Size level; /* Only trace commands at nesting level less * than or equal to this. */ Tcl_CmdObjTraceProc2 *proc; /* Procedure to call to trace command. */ | | | 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 | * clients to find out whenever a command is about to be executed. */ typedef struct Trace { Tcl_Size level; /* Only trace commands at nesting level less * than or equal to this. */ Tcl_CmdObjTraceProc2 *proc; /* Procedure to call to trace command. */ void *clientData; /* Arbitrary value to pass to proc. */ struct Trace *nextPtr; /* Next in list of traces for this interp. */ int flags; /* Flags governing the trace - see * Tcl_CreateObjTrace for details. */ Tcl_CmdObjTraceDeleteProc *delProc; /* Procedure to call when trace is deleted. */ } Trace; |
︙ | ︙ | |||
1092 1093 1094 1095 1096 1097 1098 | ((objPtr)->typePtr)->proc : NULL) MODULE_SCOPE Tcl_Size TclLengthOne(Tcl_Obj *); /* * Abstract List * | | | < | > | 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 | ((objPtr)->typePtr)->proc : NULL) MODULE_SCOPE Tcl_Size TclLengthOne(Tcl_Obj *); /* * Abstract List * * This structure provides the functions used in List operations to emulate a * List for AbstractList types. */ static inline Tcl_Size TclObjTypeLength( Tcl_Obj *objPtr) { Tcl_ObjTypeLengthProc *proc = TclObjTypeHasProc(objPtr, lengthProc); return proc(objPtr); } static inline int TclObjTypeIndex( Tcl_Interp *interp, |
︙ | ︙ | |||
1167 1168 1169 1170 1171 1172 1173 | Tcl_Size numToInsert, Tcl_Obj *const insertObjs[]) { Tcl_ObjTypeReplaceProc *proc = TclObjTypeHasProc(objPtr, replaceProc); return proc(interp, objPtr, first, numToDelete, numToInsert, insertObjs); } static inline int | | > > | > < | | 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 | Tcl_Size numToInsert, Tcl_Obj *const insertObjs[]) { Tcl_ObjTypeReplaceProc *proc = TclObjTypeHasProc(objPtr, replaceProc); return proc(interp, objPtr, first, numToDelete, numToInsert, insertObjs); } static inline int TclObjTypeInOperator( Tcl_Interp *interp, Tcl_Obj *valueObj, Tcl_Obj *listObj, int *boolResult) { Tcl_ObjTypeInOperatorProc *proc = TclObjTypeHasProc(listObj, inOperProc); return proc(interp, valueObj, listObj, boolResult); } /* * The structure below defines an entry in the assocData hash table which is * associated with an interpreter. The entry contains a pointer to a function * to call when the interpreter is deleted, and a pointer to a user-defined * piece of data. */ typedef struct AssocData { Tcl_InterpDeleteProc *proc; /* Proc to call when deleting. */ void *clientData; /* Value to pass to proc. */ } AssocData; /* * The structure below defines a call frame. A call frame defines a naming * context for a procedure call: its local naming scope (for local variables) * and its global naming scope (a namespace, perhaps the global :: namespace). * A call frame can also define the naming context for a namespace eval or |
︙ | ︙ | |||
1228 1229 1230 1231 1232 1233 1234 | int isProcCallFrame; /* If 0, the frame was pushed to execute a * namespace command and var references are * treated as references to namespace vars; * varTablePtr and compiledLocals are ignored. * If FRAME_IS_PROC is set, the frame was * pushed to execute a Tcl procedure and may * have local vars. */ | | | < | | < | | 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 | int isProcCallFrame; /* If 0, the frame was pushed to execute a * namespace command and var references are * treated as references to namespace vars; * varTablePtr and compiledLocals are ignored. * If FRAME_IS_PROC is set, the frame was * pushed to execute a Tcl procedure and may * have local vars. */ Tcl_Size objc; /* This and objv below describe the arguments * for this procedure call. */ Tcl_Obj *const *objv; /* Array of argument objects. */ struct CallFrame *callerPtr;/* Value of interp->framePtr when this * procedure was invoked (i.e. next higher in * stack of all active procedures). */ struct CallFrame *callerVarPtr; /* Value of interp->varFramePtr when this * procedure was invoked (i.e. determines * variable scoping within caller). Same as * callerPtr unless an "uplevel" command or * something equivalent was active in the * caller). */ Tcl_Size level; /* Level of this procedure, for "uplevel" * purposes (i.e. corresponds to nesting of * callerVarPtr's, not callerPtr's). 1 for * outermost procedure, 0 for top-level. */ Proc *procPtr; /* Points to the structure defining the called * procedure. Used to get information such as * the number of compiled local variables * (local variables assigned entries ["slots"] * in the compiledLocals array below). */ TclVarHashTable *varTablePtr; /* Hash table containing local variables not * recognized by the compiler, or created at * execution time through, e.g., upvar. * Initially NULL and created if needed. */ Tcl_Size numCompiledLocals; /* Count of local variables recognized * by the compiler including arguments. */ Var *compiledLocals; /* Points to the array of local variables * recognized by the compiler. The compiler * emits code that refers to these variables * using an index into this array. */ void *clientData; /* Pointer to some context that is used by * object systems. The meaning of the contents * of this field is defined by the code that * sets it, and it should only ever be set by * the code that is pushing the frame. In that * case, the code that sets it should also * have some means of discovering what the * meaning of the value is, which we do not * specify. */ LocalCache *localCachePtr; Tcl_Obj *tailcallPtr; /* NULL if no tailcall is scheduled */ } CallFrame; #define FRAME_IS_PROC 0x1 #define FRAME_IS_LAMBDA 0x2 #define FRAME_IS_METHOD 0x4 /* The frame is a method body, and the frame's * clientData field contains a CallContext * reference. Part of TIP#257. */ |
︙ | ︙ | |||
1362 1363 1364 1365 1366 1367 1368 | struct { const void *codePtr;/* Byte code currently executed... */ const char *pc; /* ... and instruction pointer. */ } tebc; } data; Tcl_Obj *cmdObj; const char *cmd; /* The executed command, if possible... */ | | | | | | 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 | struct { const void *codePtr;/* Byte code currently executed... */ const char *pc; /* ... and instruction pointer. */ } tebc; } data; Tcl_Obj *cmdObj; const char *cmd; /* The executed command, if possible... */ Tcl_Size len; /* ... and its length. */ const struct CFWordBC *litarg; /* Link to set of literal arguments which have * ben pushed on the lineLABCPtr stack by * TclArgumentBCEnter(). These will be removed * by TclArgumentBCRelease. */ } CmdFrame; typedef struct CFWord { CmdFrame *framePtr; /* CmdFrame to access. */ Tcl_Size word; /* Index of the word in the command. */ Tcl_Size refCount; /* Number of times the word is on the * stack. */ } CFWord; typedef struct CFWordBC { CmdFrame *framePtr; /* CmdFrame to access. */ Tcl_Size pc; /* Instruction pointer of a command in * ExtCmdLoc.loc[.] */ Tcl_Size word; /* Index of word in * ExtCmdLoc.loc[cmd]->line[.] */ struct CFWordBC *prevPtr; /* Previous entry in stack for same Tcl_Obj. */ struct CFWordBC *nextPtr; /* Next entry for same command call. See * CmdFrame litarg field for the list start. */ Tcl_Obj *obj; /* Back reference to hash table key */ } CFWordBC; |
︙ | ︙ | |||
1410 1411 1412 1413 1414 1415 1416 | * released by the function TclFreeObj(), in the file "tclObj.c", and also by * the function TclThreadFinalizeObjects(), in the same file. */ #define CLL_END (-1) typedef struct ContLineLoc { | | | 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 | * released by the function TclFreeObj(), in the file "tclObj.c", and also by * the function TclThreadFinalizeObjects(), in the same file. */ #define CLL_END (-1) typedef struct ContLineLoc { Tcl_Size num; /* Number of entries in loc, not counting the * final -1 marker entry. */ Tcl_Size loc[TCLFLEXARRAY];/* Table of locations, as character offsets. * The table is allocated as part of the * structure, extending behind the nominal end * of the structure. An entry containing the * value -1 is put after the last location, as * end-marker/sentinel. */ |
︙ | ︙ | |||
1453 1454 1455 1456 1457 1458 1459 | * procedures (e.g. a lambda) so that their details can be reported correctly * by [info frame]. Contains a sub-structure for each extra field. */ typedef Tcl_Obj * (GetFrameInfoValueProc)(void *clientData); typedef struct { const char *name; /* Name of this field. */ | | | | | 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 | * procedures (e.g. a lambda) so that their details can be reported correctly * by [info frame]. Contains a sub-structure for each extra field. */ typedef Tcl_Obj * (GetFrameInfoValueProc)(void *clientData); typedef struct { const char *name; /* Name of this field. */ GetFrameInfoValueProc *proc;/* Function to generate a Tcl_Obj* from the * clientData, or just use the clientData * directly (after casting) if NULL. */ void *clientData; /* Context for above function, or Tcl_Obj* if * proc field is NULL. */ } ExtraFrameInfoField; typedef struct { Tcl_Size length; /* Length of array. */ ExtraFrameInfoField fields[2]; /* Really as long as necessary, but this is * long enough for nearly anything. */ } ExtraFrameInfo; /* *---------------------------------------------------------------- |
︙ | ︙ | |||
1583 1584 1585 1586 1587 1588 1589 | struct Command *cmdPtr; /* The command handle for the coroutine. */ struct ExecEnv *eePtr; /* The special execution environment (stacks, * etc.) for the coroutine. */ struct ExecEnv *callerEEPtr;/* The execution environment for the caller of * the coroutine, which might be the * interpreter global environment or another * coroutine. */ | | | | | | | > | | < | 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 | struct Command *cmdPtr; /* The command handle for the coroutine. */ struct ExecEnv *eePtr; /* The special execution environment (stacks, * etc.) for the coroutine. */ struct ExecEnv *callerEEPtr;/* The execution environment for the caller of * the coroutine, which might be the * interpreter global environment or another * coroutine. */ CorContext caller; /* Caller's saved execution context. */ CorContext running; /* This coroutine's saved execution context. */ Tcl_HashTable *lineLABCPtr; /* See Interp.lineLABCPtr */ void *stackLevel; Tcl_Size auxNumLevels; /* While the coroutine is running the * numLevels of the create/resume command is * stored here; for suspended coroutines it * holds the nesting numLevels at yield. */ Tcl_Size nargs; /* Number of args required for resuming this * coroutine; COROUTINE_ARGUMENTS_SINGLE_OPTIONAL * means "0 or 1" (default), * COROUTINE_ARGUMENTS_ARBITRARY means "any" */ Tcl_Obj *yieldPtr; /* The command to yield to. Stored here in * order to reset splice point in * TclNRCoroutineActivateCallback if the * coroutine is busy. */ } CoroutineData; typedef struct ExecEnv { ExecStack *execStackPtr; /* Points to the first item in the evaluation * stack on the heap. */ Tcl_Obj *constants[2]; /* Pointers to constant "0" and "1" objs. */ struct Tcl_Interp *interp; |
︙ | ︙ | |||
1655 1656 1657 1658 1659 1660 1661 | typedef struct LiteralTable { LiteralEntry **buckets; /* Pointer to bucket array. Each element * points to first entry in bucket's hash * chain, or NULL. */ LiteralEntry *staticBuckets[TCL_SMALL_HASH_TABLE]; /* Bucket array used for small tables to avoid * mallocs and frees. */ | | | | | | > | | 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 | typedef struct LiteralTable { LiteralEntry **buckets; /* Pointer to bucket array. Each element * points to first entry in bucket's hash * chain, or NULL. */ LiteralEntry *staticBuckets[TCL_SMALL_HASH_TABLE]; /* Bucket array used for small tables to avoid * mallocs and frees. */ TCL_HASH_TYPE numBuckets; /* Total number of buckets allocated at * **buckets. */ TCL_HASH_TYPE numEntries; /* Total number of entries present in * table. */ TCL_HASH_TYPE rebuildSize; /* Enlarge table when numEntries gets to be * this large. */ TCL_HASH_TYPE mask; /* Mask value used in hashing function. */ } LiteralTable; /* * The following structure defines for each Tcl interpreter various * statistics-related information about the bytecode compiler and * interpreter's operation in that interpreter. */ #ifdef TCL_COMPILE_STATS typedef struct ByteCodeStats { size_t numExecutions; /* Number of ByteCodes executed. */ size_t numCompilations; /* Number of ByteCodes created. */ size_t numByteCodesFreed; /* Number of ByteCodes destroyed. */ size_t instructionCount[256]; /* Number of times each instruction was * executed. */ double totalSrcBytes; /* Total source bytes ever compiled. */ double totalByteCodeBytes; /* Total bytes for all ByteCodes. */ double currentSrcBytes; /* Src bytes for all current ByteCodes. */ double currentByteCodeBytes;/* Code bytes in all current ByteCodes. */ size_t srcCount[32]; /* Source size distribution: # of srcs of * size [2**(n-1)..2**n), n in [0..32). */ size_t byteCodeCount[32]; /* ByteCode size distribution. */ size_t lifetimeCount[32]; /* ByteCode lifetime distribution (ms). */ double currentInstBytes; /* Instruction bytes-current ByteCodes. */ double currentLitBytes; /* Current literal bytes. */ double currentExceptBytes; /* Current exception table bytes. */ |
︙ | ︙ | |||
1713 1714 1715 1716 1717 1718 1719 | */ typedef struct { const char *name; /* The name of the subcommand. */ Tcl_ObjCmdProc2 *proc2; /* The implementation of the subcommand. */ CompileProc *compileProc; /* The compiler for the subcommand. */ Tcl_ObjCmdProc2 *nreProc2; /* NRE implementation of this command. */ | | | 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 | */ typedef struct { const char *name; /* The name of the subcommand. */ Tcl_ObjCmdProc2 *proc2; /* The implementation of the subcommand. */ CompileProc *compileProc; /* The compiler for the subcommand. */ Tcl_ObjCmdProc2 *nreProc2; /* NRE implementation of this command. */ void *clientData; /* Any clientData to give the command. */ int unsafe; /* Whether this command is to be hidden by * default in a safe interpreter. */ } EnsembleImplMap; /* *---------------------------------------------------------------- * Data structures related to commands. |
︙ | ︙ | |||
1792 1793 1794 1795 1796 1797 1798 | * that point to this command when it is * renamed, deleted, hidden, or exposed. */ CompileProc *compileProc; /* Procedure called to compile command. NULL * if no compile proc exists for command. */ Tcl_ObjCmdProc2 *objProc2; /* Object-based command procedure. */ void *objClientData2; /* Arbitrary value passed to object proc. */ Tcl_CmdProc *proc; /* String-based command procedure. */ | | | | 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 | * that point to this command when it is * renamed, deleted, hidden, or exposed. */ CompileProc *compileProc; /* Procedure called to compile command. NULL * if no compile proc exists for command. */ Tcl_ObjCmdProc2 *objProc2; /* Object-based command procedure. */ void *objClientData2; /* Arbitrary value passed to object proc. */ Tcl_CmdProc *proc; /* String-based command procedure. */ void *clientData; /* Arbitrary value passed to string proc. */ Tcl_CmdDeleteProc *deleteProc; /* Procedure invoked when deleting command to, * e.g., free all client data. */ void *deleteData; /* Arbitrary value passed to deleteProc. */ int flags; /* Miscellaneous bits of information about * command. See below for definitions. */ ImportRef *importRefPtr; /* List of each imported Command created in * another namespace when this command is * imported. These imported commands redirect * invocations back to this command. The list * is used to remove all those imported |
︙ | ︙ | |||
1835 1836 1837 1838 1839 1840 1841 | * TCL_TRACE_RENAME - A rename trace is in progress. Further * recursive renames will not be traced. * TCL_TRACE_DELETE - A delete trace is in progress. Further * recursive deletes will not be traced. * (these last two flags are defined in tcl.h) */ | | | | | | | | < | 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 | * TCL_TRACE_RENAME - A rename trace is in progress. Further * recursive renames will not be traced. * TCL_TRACE_DELETE - A delete trace is in progress. Further * recursive deletes will not be traced. * (these last two flags are defined in tcl.h) */ #define CMD_DYING 0x01 #define CMD_TRACE_ACTIVE 0x02 #define CMD_HAS_EXEC_TRACES 0x04 #define CMD_COMPILES_EXPANDED 0x08 #define CMD_REDEF_IN_PROGRESS 0x10 #define CMD_VIA_RESOLVER 0x20 #define CMD_DEAD 0x40 /* *---------------------------------------------------------------- * Data structures related to name resolution procedures. *---------------------------------------------------------------- */ |
︙ | ︙ | |||
1942 1943 1944 1945 1946 1947 1948 | /* Pointer to the exported Tcl stub table. In * ancient pre-8.1 versions of Tcl this was a * pointer to the objResultPtr or a pointer to a * buckets array in a hash table. Deployed stubs * enabled extensions check for a NULL pointer value * and for a TCL_STUBS_MAGIC value to verify they * are not [load]ing into one of those pre-stubs | | < | | 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 | /* Pointer to the exported Tcl stub table. In * ancient pre-8.1 versions of Tcl this was a * pointer to the objResultPtr or a pointer to a * buckets array in a hash table. Deployed stubs * enabled extensions check for a NULL pointer value * and for a TCL_STUBS_MAGIC value to verify they * are not [load]ing into one of those pre-stubs * interps. */ TclHandle handle; /* Handle used to keep track of when this * interp is deleted. */ Namespace *globalNsPtr; /* The interpreter's global namespace. */ Tcl_HashTable *hiddenCmdTablePtr; /* Hash table used by tclBasic.c to keep track * of hidden commands on a per-interp * basis. */ void *interpInfo; /* Information used by tclInterp.c to keep * track of parent/child interps on a * per-interp basis. */ void (*optimizer)(void *envPtr); /* * Information related to procedures and variables. See tclProc.c and * tclVar.c for usage. */ |
︙ | ︙ | |||
2013 2014 2015 2016 2017 2018 2019 | * calling Tcl_Eval. See below for valid * values. */ LiteralTable literalTable; /* Contains LiteralEntry's describing all Tcl * objects holding literals of scripts * compiled by the interpreter. Indexed by the * string representations of literals. Used to * avoid creating duplicate objects. */ | | | < | 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 | * calling Tcl_Eval. See below for valid * values. */ LiteralTable literalTable; /* Contains LiteralEntry's describing all Tcl * objects holding literals of scripts * compiled by the interpreter. Indexed by the * string representations of literals. Used to * avoid creating duplicate objects. */ Tcl_Size compileEpoch; /* Holds the current "compilation epoch" for * this interpreter. This is incremented to * invalidate existing ByteCodes when, e.g., a * command with a compile procedure is * redefined. */ Proc *compiledProcPtr; /* If a procedure is being compiled, a pointer * to its Proc structure; otherwise, this is * NULL. Set by ObjInterpProc in tclProc.c and * used by tclCompile.c to process local * variables appropriately. */ ResolverScheme *resolverPtr;/* Linked list of name resolution schemes * added to this interpreter. Schemes are * added and removed by calling * Tcl_AddInterpResolvers and * Tcl_RemoveInterpResolver respectively. */ Tcl_Obj *scriptFile; /* NULL means there is no nested source * command active; otherwise this points to * pathPtr of the file being sourced. */ |
︙ | ︙ | |||
2056 2057 2058 2059 2060 2061 2062 | ActiveCommandTrace *activeCmdTracePtr; /* First in list of active command traces for * interp, or NULL if no active traces. */ ActiveInterpTrace *activeInterpTracePtr; /* First in list of active traces for interp, * or NULL if no active traces. */ | | | | 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 | ActiveCommandTrace *activeCmdTracePtr; /* First in list of active command traces for * interp, or NULL if no active traces. */ ActiveInterpTrace *activeInterpTracePtr; /* First in list of active traces for interp, * or NULL if no active traces. */ Tcl_Size tracesForbiddingInline; /* Count of traces (in the list headed by * tracePtr) that forbid inline bytecode * compilation. */ /* * Fields used to manage extensible return options (TIP 90). */ |
︙ | ︙ | |||
2087 2088 2089 2090 2091 2092 2093 | * set. */ int granularityTicker; /* Counter used to determine how often to * check the limits. */ int exceeded; /* Which limits have been exceeded, described * as flag values the same as the 'active' * field. */ | | | 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 | * set. */ int granularityTicker; /* Counter used to determine how often to * check the limits. */ int exceeded; /* Which limits have been exceeded, described * as flag values the same as the 'active' * field. */ Tcl_Size cmdCount; /* Limit for how many commands to execute in * the interpreter. */ LimitHandler *cmdHandlers; /* Handlers to execute when the limit is * reached. */ int cmdGranularity; /* Mod factor used to determine how often to * evaluate the limit check. */ |
︙ | ︙ | |||
2123 2124 2125 2126 2127 2128 2129 | struct { Tcl_Obj *const *sourceObjs; /* What arguments were actually input into the * *root* ensemble command? (Nested ensembles * don't rewrite this.) NULL if we're not * processing an ensemble. */ | | | | 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 | struct { Tcl_Obj *const *sourceObjs; /* What arguments were actually input into the * *root* ensemble command? (Nested ensembles * don't rewrite this.) NULL if we're not * processing an ensemble. */ Tcl_Size numRemovedObjs;/* How many arguments have been stripped off * because of ensemble processing. */ Tcl_Size numInsertedObjs;/* How many of the current arguments were * inserted by an ensemble. */ } ensembleRewrite; /* * TIP #219: Global info for the I/O system. */ |
︙ | ︙ | |||
2164 2165 2166 2167 2168 2169 2170 | * values are "struct CmdFrame*". */ Tcl_HashTable *lineBCPtr; /* This table remembers for each ByteCode * object the location information for its * body. It is keyed by the address of the * Proc structure for a procedure. The values * are "struct ExtCmdLoc*". (See * tclCompile.h) */ | | | < | 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 | * values are "struct CmdFrame*". */ Tcl_HashTable *lineBCPtr; /* This table remembers for each ByteCode * object the location information for its * body. It is keyed by the address of the * Proc structure for a procedure. The values * are "struct ExtCmdLoc*". (See * tclCompile.h) */ Tcl_HashTable *lineLABCPtr; /* Tcl_Obj* (by exact pointer) -> CFWordBC* */ Tcl_HashTable *lineLAPtr; /* This table remembers for each argument of a * command on the execution stack the index of * the argument in the command, and the * location data of the command. It is keyed * by the address of the Tcl_Obj containing * the argument. The values are "struct * CFWord*" (See tclBasic.c). This allows * commands like uplevel, eval, etc. to find * location information for their arguments, * if they are a proper literal argument to an * invoking command. Alt view: An index to the * CmdFrame stack keyed by command argument * holders. */ ContLineLoc *scriptCLLocPtr;/* This table points to the location data for * invisible continuation lines in the script, * if any. This pointer is set by the function * TclEvalObjEx() in file "tclBasic.c", and * used by function ...() in the same file. * It does for the eval/direct path of script * execution what CompileEnv.clLoc does for * the bytecode compiler. */ /* * TIP #268. The currently active selection mode, i.e. the package require * preferences. */ int packagePrefer; /* Current package selection mode. */ |
︙ | ︙ | |||
2258 2259 2260 2261 2262 2263 2264 | * TIP #348 IMPLEMENTATION - Substituted error stack */ Tcl_Obj *errorStack; /* [info errorstack] value (as a Tcl_Obj). */ Tcl_Obj *upLiteral; /* "UP" literal for [info errorstack] */ Tcl_Obj *callLiteral; /* "CALL" literal for [info errorstack] */ Tcl_Obj *innerLiteral; /* "INNER" literal for [info errorstack] */ Tcl_Obj *innerContext; /* cached list for fast reallocation */ | | | 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 | * TIP #348 IMPLEMENTATION - Substituted error stack */ Tcl_Obj *errorStack; /* [info errorstack] value (as a Tcl_Obj). */ Tcl_Obj *upLiteral; /* "UP" literal for [info errorstack] */ Tcl_Obj *callLiteral; /* "CALL" literal for [info errorstack] */ Tcl_Obj *innerLiteral; /* "INNER" literal for [info errorstack] */ Tcl_Obj *innerContext; /* cached list for fast reallocation */ int resetErrorStack; /* controls cleaning up of ::errorStack */ #ifdef TCL_COMPILE_STATS /* * Statistical information about the bytecode compiler and interpreter's * operation. This should be the last field of Interp. */ |
︙ | ︙ | |||
2285 2286 2287 2288 2289 2290 2291 | /* * Macros for script cancellation support (TIP #285). */ #define TclCanceled(iPtr) \ (((iPtr)->flags & CANCELED) || ((iPtr)->flags & TCL_CANCEL_UNWIND)) | | | | | | 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 | /* * Macros for script cancellation support (TIP #285). */ #define TclCanceled(iPtr) \ (((iPtr)->flags & CANCELED) || ((iPtr)->flags & TCL_CANCEL_UNWIND)) #define TclSetCancelFlags(iPtr, cancelFlags) \ (iPtr)->flags |= CANCELED; \ if ((cancelFlags) & TCL_CANCEL_UNWIND) { \ (iPtr)->flags |= TCL_CANCEL_UNWIND; \ } #define TclUnsetCancelFlags(iPtr) \ (iPtr)->flags &= (~(CANCELED | TCL_CANCEL_UNWIND)) /* * Macros for splicing into and out of doubly linked lists. They assume |
︙ | ︙ | |||
2450 2451 2452 2453 2454 2455 2456 | (((x) + (TCL_ALIGN_BYTES - 1)) & ~(TCL_ALIGN_BYTES - 1)) /* * A common panic alert when memory allocation fails. */ #define TclOOM(ptr, size) \ | > | | 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 | (((x) + (TCL_ALIGN_BYTES - 1)) & ~(TCL_ALIGN_BYTES - 1)) /* * A common panic alert when memory allocation fails. */ #define TclOOM(ptr, size) \ ((size) && ((ptr) || (Tcl_Panic( \ "unable to alloc %" TCL_Z_MODIFIER "u bytes", (size_t)(size)), 1))) /* * The following enum values are used to specify the runtime platform setting * of the tclPlatform variable. */ typedef enum { |
︙ | ︙ | |||
2520 2521 2522 2523 2524 2525 2526 | * define the content of the list. The ListSpan specifies the range of slots * within the ListStore that hold elements for this list. The ListSpan is * optional in which case the list includes all the "in-use" slots of the * ListStore. * */ typedef struct ListStore { | | | | | | | > | | | | | | > | | | | | > | | > | | > | | | > | | | | | | | | > | | | > | < | > | | | | | | | | | | | | | | | > > | | | | | | | | | | | | | > | | | < | | | 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 | * define the content of the list. The ListSpan specifies the range of slots * within the ListStore that hold elements for this list. The ListSpan is * optional in which case the list includes all the "in-use" slots of the * ListStore. * */ typedef struct ListStore { Tcl_Size firstUsed; /* Index of first slot in use within slots[] */ Tcl_Size numUsed; /* Number of slots in use (starting firstUsed) */ Tcl_Size numAllocated; /* Total number of slots[] array slots. */ size_t refCount; /* Number of references to this instance. */ int flags; /* LISTSTORE_* flags */ Tcl_Obj *slots[TCLFLEXARRAY]; /* Variable size array. Grown as needed */ } ListStore; #define LISTSTORE_CANONICAL 0x1 /* All Tcl_Obj's referencing this * store have their string representation * derived from the list representation */ /* Max number of elements that can be contained in a list */ #define LIST_MAX \ ((Tcl_Size)(((size_t)TCL_SIZE_MAX - offsetof(ListStore, slots)) \ / sizeof(Tcl_Obj *))) /* Memory size needed for a ListStore to hold numSlots_ elements */ #define LIST_SIZE(numSlots_) \ ((Tcl_Size)(offsetof(ListStore, slots) \ + ((numSlots_) * sizeof(Tcl_Obj *)))) /* * ListSpan -- * See comments above for ListStore */ typedef struct ListSpan { Tcl_Size spanStart; /* Starting index of the span. */ Tcl_Size spanLength; /* Number of elements in the span. */ size_t refCount; /* Count of references to this span record. */ } ListSpan; #ifndef LIST_SPAN_THRESHOLD /* May be set on build line */ #define LIST_SPAN_THRESHOLD 101 #endif /* * ListRep -- * See comments above for ListStore */ typedef struct ListRep { ListStore *storePtr; /* element array shared amongst different * lists */ ListSpan *spanPtr; /* If not NULL, the span holds the range of * slots within *storePtr that contain this * list elements. */ } ListRep; /* * Macros used to get access list internal representations. * * Naming conventions: * ListRep* - expect a pointer to a valid ListRep * ListObj* - expect a pointer to a Tcl_Obj whose internal type is known to * be a list (tclListType). Will crash otherwise. * TclListObj* - expect a pointer to a Tcl_Obj whose internal type may or may not * be tclListType. These will convert as needed and return error if * conversion not possible. */ /* Returns the starting slot for this listRep in the contained ListStore */ #define ListRepStart(listRepPtr_) \ ((listRepPtr_)->spanPtr \ ? (listRepPtr_)->spanPtr->spanStart \ : (listRepPtr_)->storePtr->firstUsed) /* Returns the number of elements in this listRep */ #define ListRepLength(listRepPtr_) \ ((listRepPtr_)->spanPtr \ ? (listRepPtr_)->spanPtr->spanLength \ : (listRepPtr_)->storePtr->numUsed) /* Returns a pointer to the first slot containing this ListRep elements */ #define ListRepElementsBase(listRepPtr_) \ (&(listRepPtr_)->storePtr->slots[ListRepStart(listRepPtr_)]) /* Stores the number of elements and base address of the element array */ #define ListRepElements(listRepPtr_, objc_, objv_) \ (((objv_) = ListRepElementsBase(listRepPtr_)), \ ((objc_) = ListRepLength(listRepPtr_))) /* Returns 1/0 whether the ListRep's ListStore is shared. */ #define ListRepIsShared(listRepPtr_) ((listRepPtr_)->storePtr->refCount > 1) /* Returns a pointer to the ListStore component */ #define ListObjStorePtr(listObj_) \ ((ListStore *)((listObj_)->internalRep.twoPtrValue.ptr1)) /* Returns a pointer to the ListSpan component */ #define ListObjSpanPtr(listObj_) \ ((ListSpan *)((listObj_)->internalRep.twoPtrValue.ptr2)) /* Returns the ListRep internal representaton in a Tcl_Obj */ #define ListObjGetRep(listObj_, listRepPtr_) \ do { \ (listRepPtr_)->storePtr = ListObjStorePtr(listObj_); \ (listRepPtr_)->spanPtr = ListObjSpanPtr(listObj_); \ } while (0) /* Returns the length of the list */ #define ListObjLength(listObj_, len_) \ ((len_) = ListObjSpanPtr(listObj_) \ ? ListObjSpanPtr(listObj_)->spanLength \ : ListObjStorePtr(listObj_)->numUsed) /* Returns the starting slot index of this list's elements in the ListStore */ #define ListObjStart(listObj_) \ (ListObjSpanPtr(listObj_) \ ? ListObjSpanPtr(listObj_)->spanStart \ : ListObjStorePtr(listObj_)->firstUsed) /* Stores the element count and base address of this list's elements */ #define ListObjGetElements(listObj_, objc_, objv_) \ (((objv_) = &ListObjStorePtr(listObj_)->slots[ListObjStart(listObj_)]), \ (ListObjLength(listObj_, (objc_)))) /* * Returns 1/0 whether the internal representation (not the Tcl_Obj itself) * is shared. Note by intent this only checks for sharing of ListStore, * not spans. */ #define ListObjRepIsShared(listObj_) \ (ListObjStorePtr(listObj_)->refCount > 1) /* * Certain commands like concat are optimized if an existing string * representation of a list object is known to be in canonical format (i.e. * generated from the list representation). There are three conditions when * this will be the case: * (1) No string representation exists which means it will obviously have * to be generated from the list representation when needed * (2) The ListStore flags is marked canonical. This is done at the time * the string representation is generated from the list under certain * conditions (see comments in UpdateStringOfList). * (3) The list representation does not have a span component. This is * because list Tcl_Obj's with spans are always created from existing lists * and never from strings (see SetListFromAny) and thus their string * representation will always be canonical. */ #define ListObjIsCanonical(listObj_) \ (((listObj_)->bytes == NULL) \ || (ListObjStorePtr(listObj_)->flags & LISTSTORE_CANONICAL) \ || ListObjSpanPtr(listObj_) != NULL) /* * Converts the Tcl_Obj to a list if it isn't one and stores the element * count and base address of this list's elements in objcPtr_ and objvPtr_. * Return TCL_OK on success or TCL_ERROR if the Tcl_Obj cannot be * converted to a list. */ #define TclListObjGetElements(interp_, listObj_, objcPtr_, objvPtr_) \ ((TclHasInternalRep((listObj_), &tclListType)) \ ? ((ListObjGetElements((listObj_), *(objcPtr_), *(objvPtr_))), \ TCL_OK) \ : Tcl_ListObjGetElements( \ (interp_), (listObj_), (objcPtr_), (objvPtr_))) /* * Converts the Tcl_Obj to a list if it isn't one and stores the element * count in lenPtr_. Returns TCL_OK on success or TCL_ERROR if the * Tcl_Obj cannot be converted to a list. */ #define TclListObjLength(interp_, listObj_, lenPtr_) \ ((TclHasInternalRep((listObj_), &tclListType)) \ ? ((ListObjLength((listObj_), *(lenPtr_))), TCL_OK) \ : Tcl_ListObjLength((interp_), (listObj_), (lenPtr_))) #define TclListObjIsCanonical(listObj_) \ ((TclHasInternalRep((listObj_), &tclListType)) \ ? ListObjIsCanonical((listObj_)) \ : 0) /* * Modes for collecting (or not) in the implementations of TclNRForeachCmd, * TclNRLmapCmd and their compilations. */ #define TCL_EACH_KEEP_NONE 0 /* Discard iteration result like [foreach] */ #define TCL_EACH_COLLECT 1 /* Collect iteration result like [lmap] */ /* * Macros providing a faster path to booleans and integers: * Tcl_GetBooleanFromObj, Tcl_GetLongFromObj, Tcl_GetIntFromObj * and Tcl_GetIntForIndex. * * WARNING: these macros eval their args more than once. */ #define TclGetBooleanFromObj(interp, objPtr, intPtr) \ ((TclHasInternalRep((objPtr), &tclIntType) \ || TclHasInternalRep((objPtr), &tclBooleanType)) \ ? (*(intPtr) = ((objPtr)->internalRep.wideValue!=0), TCL_OK) \ : Tcl_GetBooleanFromObj((interp), (objPtr), (intPtr))) #ifdef TCL_WIDE_INT_IS_LONG #define TclGetLongFromObj(interp, objPtr, longPtr) \ ((TclHasInternalRep((objPtr), &tclIntType)) \ ? ((*(longPtr) = (objPtr)->internalRep.wideValue), TCL_OK) \ : Tcl_GetLongFromObj((interp), (objPtr), (longPtr))) #else #define TclGetLongFromObj(interp, objPtr, longPtr) \ ((TclHasInternalRep((objPtr), &tclIntType) \ && (objPtr)->internalRep.wideValue >= (Tcl_WideInt)(LONG_MIN) \ && (objPtr)->internalRep.wideValue <= (Tcl_WideInt)(LONG_MAX)) \ ? ((*(longPtr) = (long)(objPtr)->internalRep.wideValue), TCL_OK) \ : Tcl_GetLongFromObj((interp), (objPtr), (longPtr))) #endif #define TclGetIntFromObj(interp, objPtr, intPtr) \ ((TclHasInternalRep((objPtr), &tclIntType) \ && (objPtr)->internalRep.wideValue >= (Tcl_WideInt)(INT_MIN) \ && (objPtr)->internalRep.wideValue <= (Tcl_WideInt)(INT_MAX)) \ ? ((*(intPtr) = (int)(objPtr)->internalRep.wideValue), TCL_OK) \ : Tcl_GetIntFromObj((interp), (objPtr), (intPtr))) #define TclGetIntForIndexM(interp, objPtr, endValue, idxPtr) \ (((TclHasInternalRep((objPtr), &tclIntType)) \ && ((objPtr)->internalRep.wideValue >= 0) \ && ((objPtr)->internalRep.wideValue <= endValue)) \ ? ((*(idxPtr) = (objPtr)->internalRep.wideValue), TCL_OK) \ : Tcl_GetIntForIndex((interp), (objPtr), (endValue), (idxPtr))) /* * Macro used to save a function call for common uses of * Tcl_GetWideIntFromObj(). The ANSI C "prototype" is: * * MODULE_SCOPE int TclGetWideIntFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, * Tcl_WideInt *wideIntPtr); */ #define TclGetWideIntFromObj(interp, objPtr, wideIntPtr) \ ((TclHasInternalRep((objPtr), &tclIntType)) \ ? (*(wideIntPtr) = ((objPtr)->internalRep.wideValue), TCL_OK) \ : Tcl_GetWideIntFromObj((interp), (objPtr), (wideIntPtr))) /* * Flag values for TclTraceDictPath(). * * DICT_PATH_READ indicates that all entries on the path must exist but no * updates will be needed. * |
︙ | ︙ | |||
2786 2787 2788 2789 2790 2791 2792 | * more efficiency in 'path' manipulation and usage, and cleaner filesystem * code internally. */ #define TCL_FILESYSTEM_VERSION_2 ((Tcl_FSVersion) 0x2) typedef void *(TclFSGetCwdProc2)(void *clientData); typedef int (Tcl_FSLoadFileProc2) (Tcl_Interp *interp, Tcl_Obj *pathPtr, | | > | 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 | * more efficiency in 'path' manipulation and usage, and cleaner filesystem * code internally. */ #define TCL_FILESYSTEM_VERSION_2 ((Tcl_FSVersion) 0x2) typedef void *(TclFSGetCwdProc2)(void *clientData); typedef int (Tcl_FSLoadFileProc2) (Tcl_Interp *interp, Tcl_Obj *pathPtr, Tcl_LoadHandle *handlePtr, Tcl_FSUnloadFileProc **unloadProcPtr, int flags); /* * The following types are used for getting and storing platform-specific file * attributes in tclFCmd.c and the various platform-versions of that file. * This is done to have as much common code as possible in the file attributes * code. For more information about the callbacks, see TclFileAttrsCmd in * tclFCmd.c. |
︙ | ︙ | |||
2837 2838 2839 2840 2841 2842 2843 | /* *---------------------------------------------------------------- * Data structures for process-global values. *---------------------------------------------------------------- */ | | > | | | 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 | /* *---------------------------------------------------------------- * Data structures for process-global values. *---------------------------------------------------------------- */ typedef void (TclInitProcessGlobalValueProc)(char **valuePtr, TCL_HASH_TYPE *lengthPtr, Tcl_Encoding *encodingPtr); #ifdef _WIN32 # define TCLFSENCODING tclUtf8Encoding /* On Windows, all Unicode (except surrogates) are valid */ #else # define TCLFSENCODING NULL /* On Non-Windows, use the system encoding for validation checks */ #endif /* * A ProcessGlobalValue struct exists for each internal value in Tcl that is * to be shared among several threads. Each thread sees a (Tcl_Obj) copy of * the value, and the gobal value is kept as a counted string, with epoch and * mutex control. Each ProcessGlobalValue struct should be a static variable in * some file. */ typedef struct ProcessGlobalValue { Tcl_Size epoch; /* Epoch counter to detect changes in the * global value. */ TCL_HASH_TYPE numBytes; /* Length of the global string. */ char *value; /* The global string value. */ Tcl_Encoding encoding; /* system encoding when global string was * initialized. */ TclInitProcessGlobalValueProc *proc; /* A procedure to initialize the global string |
︙ | ︙ | |||
2877 2878 2879 2880 2881 2882 2883 | /* *---------------------------------------------------------------------- * Flags for TclParseNumber *---------------------------------------------------------------------- */ | | | | | | < | > | | | | > | | | | | < | | > > > > | | | | | | | | | | > > > | > > | | > > > > | > > | > > > > > | > > > > > < | | | | | | 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 | /* *---------------------------------------------------------------------- * Flags for TclParseNumber *---------------------------------------------------------------------- */ #define TCL_PARSE_DECIMAL_ONLY 1 /* Leading zero doesn't denote octal or * hex. */ #define TCL_PARSE_OCTAL_ONLY 2 /* Parse octal even without prefix. */ #define TCL_PARSE_HEXADECIMAL_ONLY 4 /* Parse hexadecimal even without prefix. */ #define TCL_PARSE_INTEGER_ONLY 8 /* Disable floating point parsing. */ #define TCL_PARSE_SCAN_PREFIXES 16 /* Use [scan] rules dealing with 0? * prefixes. */ #define TCL_PARSE_NO_WHITESPACE 32 /* Reject leading/trailing whitespace. */ #define TCL_PARSE_BINARY_ONLY 64 /* Parse binary even without prefix. */ #define TCL_PARSE_NO_UNDERSCORE 128 /* Reject underscore digit separator */ /* *---------------------------------------------------------------------- * Internal convenience macros for manipulating encoding flags. See * TCL_ENCODING_PROFILE_* in tcl.h *---------------------------------------------------------------------- */ #define ENCODING_PROFILE_MASK 0xFF000000 #define ENCODING_PROFILE_GET(flags_) \ ((flags_) & ENCODING_PROFILE_MASK) #define ENCODING_PROFILE_SET(flags_, profile_) \ do { \ (flags_) &= ~ENCODING_PROFILE_MASK; \ (flags_) |= ((profile_) & ENCODING_PROFILE_MASK); \ } while (0) /* *---------------------------------------------------------------------- * Common functions for calculating overallocation. Trivial but allows for * experimenting with growth factors without having to change code in * multiple places. See TclAttemptAllocElemsEx and similar for usage * examples. Best to use those functions. Direct use of TclUpsizeAlloc / * TclResizeAlloc is needed in special cases such as when total size of * memory block is limited to less than TCL_SIZE_MAX. * *---------------------------------------------------------------------- */ static inline Tcl_Size TclUpsizeAlloc( TCL_UNUSED(Tcl_Size), /* oldSize. For future experiments with * some growth algorithms that use this * information. */ Tcl_Size needed, Tcl_Size limit) { /* assert (oldCapacity < needed <= limit) */ if (needed < (limit - needed/2)) { return needed + needed / 2; } else { return limit; } } static inline Tcl_Size TclUpsizeRetry( Tcl_Size needed, Tcl_Size lastAttempt) { /* assert(needed < lastAttempt); */ if (needed < lastAttempt - 1) { /* (needed+lastAttempt)/2 but that formula may overflow Tcl_Size */ return needed + (lastAttempt - needed) / 2; } else { return needed; } } MODULE_SCOPE void * TclAllocElemsEx(Tcl_Size elemCount, Tcl_Size elemSize, Tcl_Size leadSize, Tcl_Size *capacityPtr); MODULE_SCOPE void * TclReallocElemsEx(void *oldPtr, Tcl_Size elemCount, Tcl_Size elemSize, Tcl_Size leadSize, Tcl_Size *capacityPtr); MODULE_SCOPE void * TclAttemptReallocElemsEx(void *oldPtr, Tcl_Size elemCount, Tcl_Size elemSize, Tcl_Size leadSize, Tcl_Size *capacityPtr); /* Alloc elemCount elements of size elemSize with leadSize header * returning actual capacity (in elements) in *capacityPtr. */ static inline void * TclAttemptAllocElemsEx( Tcl_Size elemCount, Tcl_Size elemSize, Tcl_Size leadSize, Tcl_Size *capacityPtr) { return TclAttemptReallocElemsEx( NULL, elemCount, elemSize, leadSize, capacityPtr); } /* Alloc numByte bytes, returning actual capacity in *capacityPtr. */ static inline void * TclAllocEx( Tcl_Size numBytes, Tcl_Size *capacityPtr) { return TclAllocElemsEx(numBytes, 1, 0, capacityPtr); } /* Alloc numByte bytes, returning actual capacity in *capacityPtr. */ static inline void * TclAttemptAllocEx( Tcl_Size numBytes, Tcl_Size *capacityPtr) { return TclAttemptAllocElemsEx(numBytes, 1, 0, capacityPtr); } /* Realloc numByte bytes, returning actual capacity in *capacityPtr. */ static inline void * TclReallocEx( void *oldPtr, Tcl_Size numBytes, Tcl_Size *capacityPtr) { return TclReallocElemsEx(oldPtr, numBytes, 1, 0, capacityPtr); } /* Realloc numByte bytes, returning actual capacity in *capacityPtr. */ static inline void * TclAttemptReallocEx( void *oldPtr, Tcl_Size numBytes, Tcl_Size *capacityPtr) { return TclAttemptReallocElemsEx(oldPtr, numBytes, 1, 0, capacityPtr); } /* *---------------------------------------------------------------- * Variables shared among Tcl modules but not used by the outside world. *---------------------------------------------------------------- */ MODULE_SCOPE char *tclNativeExecutableName; MODULE_SCOPE int tclFindExecutableSearchDone; MODULE_SCOPE char *tclMemDumpFileName; MODULE_SCOPE TclPlatformType tclPlatform; /* * Declarations related to internal encoding functions. */ MODULE_SCOPE Tcl_Encoding tclIdentityEncoding; MODULE_SCOPE Tcl_Encoding tclUtf8Encoding; MODULE_SCOPE int TclEncodingProfileNameToId(Tcl_Interp *interp, const char *profileName, int *profilePtr); MODULE_SCOPE const char *TclEncodingProfileIdToName(Tcl_Interp *interp, int profileId); MODULE_SCOPE void TclGetEncodingProfiles(Tcl_Interp *interp); /* * TIP #233 (Virtualized Time) * Data for the time hooks, if any. */ MODULE_SCOPE Tcl_GetTimeProc *tclGetTimeProcPtr; |
︙ | ︙ | |||
3102 3103 3104 3105 3106 3107 3108 | MODULE_SCOPE Tcl_ObjCmdProc2 TclNRCoroutineObjCmd; MODULE_SCOPE Tcl_ObjCmdProc2 TclNRYieldObjCmd; MODULE_SCOPE Tcl_ObjCmdProc2 TclNRYieldmObjCmd; MODULE_SCOPE Tcl_ObjCmdProc2 TclNRYieldToObjCmd; MODULE_SCOPE Tcl_ObjCmdProc2 TclNRInvoke; MODULE_SCOPE Tcl_NRPostProc TclNRReleaseValues; | | > | | | | | | | < < | | < < | | 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 | MODULE_SCOPE Tcl_ObjCmdProc2 TclNRCoroutineObjCmd; MODULE_SCOPE Tcl_ObjCmdProc2 TclNRYieldObjCmd; MODULE_SCOPE Tcl_ObjCmdProc2 TclNRYieldmObjCmd; MODULE_SCOPE Tcl_ObjCmdProc2 TclNRYieldToObjCmd; MODULE_SCOPE Tcl_ObjCmdProc2 TclNRInvoke; MODULE_SCOPE Tcl_NRPostProc TclNRReleaseValues; MODULE_SCOPE void TclSetTailcall(Tcl_Interp *interp, Tcl_Obj *tailcallPtr); MODULE_SCOPE void TclPushTailcallPoint(Tcl_Interp *interp); /* These two can be considered for the public api */ MODULE_SCOPE void TclMarkTailcall(Tcl_Interp *interp); MODULE_SCOPE void TclSkipTailcall(Tcl_Interp *interp); /* * This structure holds the data for the various iteration callbacks used to * NRE the 'for' and 'while' commands. We need a separate structure because we * have more than the 4 client data entries we can provide directly thorugh * the callback API. It is the 'word' information which puts us over the * limit. It is needed because the loop body is argument 4 of 'for' and * argument 2 of 'while'. Not providing the correct index confuses the #280 * code. We TclSmallAlloc/Free this. */ typedef struct ForIterData { Tcl_Obj *cond; /* Loop condition expression. */ Tcl_Obj *body; /* Loop body. */ Tcl_Obj *next; /* Loop step script, NULL for 'while'. */ const char *msg; /* Error message part. */ Tcl_Size word; /* Index of the body script in the command */ } ForIterData; /* TIP #357 - Structure doing the bookkeeping of handles for Tcl_LoadFile * and Tcl_FindSymbol. This structure corresponds to an opaque * typedef in tcl.h */ typedef void* TclFindSymbolProc(Tcl_Interp* interp, Tcl_LoadHandle loadHandle, const char* symbol); struct Tcl_LoadHandle_ { void *clientData; /* Client data is the load handle in the * native filesystem if a module was loaded * there, or an opaque pointer to a structure * for further bookkeeping on load-from-VFS * and load-from-memory */ TclFindSymbolProc* findSymbolProcPtr; /* Procedure that resolves symbols in a * loaded module */ Tcl_FSUnloadFileProc* unloadFileProcPtr; /* Procedure that unloads a loaded module */ }; /* Flags for conversion of doubles to digit strings */ #define TCL_DD_E_FORMAT 0x2 /* Use a fixed-length string of digits, * suitable for E format*/ #define TCL_DD_F_FORMAT 0x3 /* Use a fixed number of digits after the * decimal point, suitable for F format */ #define TCL_DD_SHORTEST 0x4 /* Use the shortest possible string */ #define TCL_DD_NO_QUICK 0x8 /* Debug flag: forbid quick FP conversion */ #define TCL_DD_CONVERSION_TYPE_MASK 0x3 /* Mask to isolate the conversion type */ /* *---------------------------------------------------------------- * Procedures shared among Tcl modules but not used by the outside world: |
︙ | ︙ | |||
3182 3183 3184 3185 3186 3187 3188 | const char *bytes, Tcl_Size numBytes); MODULE_SCOPE void TclArgumentEnter(Tcl_Interp *interp, Tcl_Obj *objv[], Tcl_Size objc, CmdFrame *cf); MODULE_SCOPE void TclArgumentRelease(Tcl_Interp *interp, Tcl_Obj *objv[], Tcl_Size objc); MODULE_SCOPE void TclArgumentBCEnter(Tcl_Interp *interp, Tcl_Obj *objv[], Tcl_Size objc, | | > | 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 | const char *bytes, Tcl_Size numBytes); MODULE_SCOPE void TclArgumentEnter(Tcl_Interp *interp, Tcl_Obj *objv[], Tcl_Size objc, CmdFrame *cf); MODULE_SCOPE void TclArgumentRelease(Tcl_Interp *interp, Tcl_Obj *objv[], Tcl_Size objc); MODULE_SCOPE void TclArgumentBCEnter(Tcl_Interp *interp, Tcl_Obj *objv[], Tcl_Size objc, void *codePtr, CmdFrame *cfPtr, Tcl_Size cmd, Tcl_Size pc); MODULE_SCOPE void TclArgumentBCRelease(Tcl_Interp *interp, CmdFrame *cfPtr); MODULE_SCOPE void TclArgumentGet(Tcl_Interp *interp, Tcl_Obj *obj, CmdFrame **cfPtrPtr, int *wordPtr); MODULE_SCOPE int TclAsyncNotifier(int sigNumber, Tcl_ThreadId threadId, void *clientData, int *flagPtr, int value); MODULE_SCOPE void TclAsyncMarkFromNotifier(void); |
︙ | ︙ | |||
3255 3256 3257 3258 3259 3260 3261 | MODULE_SCOPE void TclDeleteLateExitHandler(Tcl_ExitProc *proc, void *clientData); MODULE_SCOPE char * TclDStringAppendObj(Tcl_DString *dsPtr, Tcl_Obj *objPtr); MODULE_SCOPE char * TclDStringAppendDString(Tcl_DString *dsPtr, Tcl_DString *toAppendPtr); MODULE_SCOPE Tcl_Obj *const *TclFetchEnsembleRoot(Tcl_Interp *interp, | | > | 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 | MODULE_SCOPE void TclDeleteLateExitHandler(Tcl_ExitProc *proc, void *clientData); MODULE_SCOPE char * TclDStringAppendObj(Tcl_DString *dsPtr, Tcl_Obj *objPtr); MODULE_SCOPE char * TclDStringAppendDString(Tcl_DString *dsPtr, Tcl_DString *toAppendPtr); MODULE_SCOPE Tcl_Obj *const *TclFetchEnsembleRoot(Tcl_Interp *interp, Tcl_Obj *const *objv, Tcl_Size objc, Tcl_Size *objcPtr); MODULE_SCOPE Tcl_Obj *const *TclEnsembleGetRewriteValues(Tcl_Interp *interp); MODULE_SCOPE Tcl_Namespace *TclEnsureNamespace(Tcl_Interp *interp, Tcl_Namespace *namespacePtr); MODULE_SCOPE void TclFinalizeAllocSubsystem(void); MODULE_SCOPE void TclFinalizeAsync(void); MODULE_SCOPE void TclFinalizeDoubleConversion(void); MODULE_SCOPE void TclFinalizeEncodingSubsystem(void); |
︙ | ︙ | |||
3370 3371 3372 3373 3374 3375 3376 | MODULE_SCOPE Tcl_Command TclMakeEnsemble(Tcl_Interp *interp, const char *name, const EnsembleImplMap map[]); MODULE_SCOPE Tcl_Size TclMaxListLength(const char *bytes, Tcl_Size numBytes, const char **endPtr); MODULE_SCOPE int TclMergeReturnOptions(Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], Tcl_Obj **optionsPtrPtr, int *codePtr, int *levelPtr); | | | 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 | MODULE_SCOPE Tcl_Command TclMakeEnsemble(Tcl_Interp *interp, const char *name, const EnsembleImplMap map[]); MODULE_SCOPE Tcl_Size TclMaxListLength(const char *bytes, Tcl_Size numBytes, const char **endPtr); MODULE_SCOPE int TclMergeReturnOptions(Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[], Tcl_Obj **optionsPtrPtr, int *codePtr, int *levelPtr); MODULE_SCOPE Tcl_Obj * TclNoErrorStack(Tcl_Interp *interp, Tcl_Obj *options); MODULE_SCOPE int TclNokia770Doubles(void); MODULE_SCOPE void TclNsDecrRefCount(Namespace *nsPtr); MODULE_SCOPE int TclNamespaceDeleted(Namespace *nsPtr); MODULE_SCOPE void TclObjVarErrMsg(Tcl_Interp *interp, Tcl_Obj *part1Ptr, Tcl_Obj *part2Ptr, const char *operation, const char *reason, int index); #ifndef TCL_NO_DEPRECATED |
︙ | ︙ | |||
3401 3402 3403 3404 3405 3406 3407 | Tcl_Size numBytes, Tcl_Parse *parsePtr); MODULE_SCOPE Tcl_Size TclParseAllWhiteSpace(const char *src, Tcl_Size numBytes); MODULE_SCOPE int TclProcessReturn(Tcl_Interp *interp, int code, int level, Tcl_Obj *returnOpts); MODULE_SCOPE void TclUndoRefCount(Tcl_Obj *objPtr); MODULE_SCOPE int TclpObjLstat(Tcl_Obj *pathPtr, Tcl_StatBuf *buf); MODULE_SCOPE Tcl_Obj * TclpTempFileName(void); | | | > | | | | 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 | Tcl_Size numBytes, Tcl_Parse *parsePtr); MODULE_SCOPE Tcl_Size TclParseAllWhiteSpace(const char *src, Tcl_Size numBytes); MODULE_SCOPE int TclProcessReturn(Tcl_Interp *interp, int code, int level, Tcl_Obj *returnOpts); MODULE_SCOPE void TclUndoRefCount(Tcl_Obj *objPtr); MODULE_SCOPE int TclpObjLstat(Tcl_Obj *pathPtr, Tcl_StatBuf *buf); MODULE_SCOPE Tcl_Obj * TclpTempFileName(void); MODULE_SCOPE Tcl_Obj * TclpTempFileNameForLibrary(Tcl_Interp *interp, Tcl_Obj* pathPtr); MODULE_SCOPE int TclNewArithSeriesObj(Tcl_Interp *interp, Tcl_Obj **arithSeriesPtr, int useDoubles, Tcl_Obj *startObj, Tcl_Obj *endObj, Tcl_Obj *stepObj, Tcl_Obj *lenObj); MODULE_SCOPE Tcl_Obj * TclNewFSPathObj(Tcl_Obj *dirPtr, const char *addStrRep, Tcl_Size len); MODULE_SCOPE void TclpAlertNotifier(void *clientData); MODULE_SCOPE void * TclpNotifierData(void); MODULE_SCOPE void TclpServiceModeHook(int mode); MODULE_SCOPE void TclpSetTimer(const Tcl_Time *timePtr); MODULE_SCOPE int TclpWaitForEvent(const Tcl_Time *timePtr); MODULE_SCOPE void TclpCreateFileHandler(int fd, int mask, Tcl_FileProc *proc, void *clientData); MODULE_SCOPE int TclpDeleteFile(const void *path); MODULE_SCOPE void TclpDeleteFileHandler(int fd); |
︙ | ︙ | |||
3439 3440 3441 3442 3443 3444 3445 | MODULE_SCOPE int TclpThreadCreate(Tcl_ThreadId *idPtr, Tcl_ThreadCreateProc *proc, void *clientData, TCL_HASH_TYPE stackSize, int flags); MODULE_SCOPE Tcl_Size TclpFindVariable(const char *name, Tcl_Size *lengthPtr); MODULE_SCOPE void TclpInitLibraryPath(char **valuePtr, TCL_HASH_TYPE *lengthPtr, Tcl_Encoding *encodingPtr); MODULE_SCOPE void TclpInitLock(void); | | | 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 | MODULE_SCOPE int TclpThreadCreate(Tcl_ThreadId *idPtr, Tcl_ThreadCreateProc *proc, void *clientData, TCL_HASH_TYPE stackSize, int flags); MODULE_SCOPE Tcl_Size TclpFindVariable(const char *name, Tcl_Size *lengthPtr); MODULE_SCOPE void TclpInitLibraryPath(char **valuePtr, TCL_HASH_TYPE *lengthPtr, Tcl_Encoding *encodingPtr); MODULE_SCOPE void TclpInitLock(void); MODULE_SCOPE void * TclpInitNotifier(void); MODULE_SCOPE void TclpInitPlatform(void); MODULE_SCOPE void TclpInitUnlock(void); MODULE_SCOPE Tcl_Obj * TclpObjListVolumes(void); MODULE_SCOPE void TclpGlobalLock(void); MODULE_SCOPE void TclpGlobalUnlock(void); MODULE_SCOPE int TclpObjNormalizePath(Tcl_Interp *interp, Tcl_Obj *pathPtr, int nextCheckpoint); |
︙ | ︙ | |||
3521 3522 3523 3524 3525 3526 3527 | MODULE_SCOPE void TclSubstParse(Tcl_Interp *interp, const char *bytes, Tcl_Size numBytes, int flags, Tcl_Parse *parsePtr, Tcl_InterpState *statePtr); MODULE_SCOPE int TclSubstTokens(Tcl_Interp *interp, Tcl_Token *tokenPtr, Tcl_Size count, int *tokensLeftPtr, Tcl_Size line, Tcl_Size *clNextOuter, const char *outerScript); MODULE_SCOPE Tcl_Size TclTrim(const char *bytes, Tcl_Size numBytes, | | > | 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 | MODULE_SCOPE void TclSubstParse(Tcl_Interp *interp, const char *bytes, Tcl_Size numBytes, int flags, Tcl_Parse *parsePtr, Tcl_InterpState *statePtr); MODULE_SCOPE int TclSubstTokens(Tcl_Interp *interp, Tcl_Token *tokenPtr, Tcl_Size count, int *tokensLeftPtr, Tcl_Size line, Tcl_Size *clNextOuter, const char *outerScript); MODULE_SCOPE Tcl_Size TclTrim(const char *bytes, Tcl_Size numBytes, const char *trim, Tcl_Size numTrim, Tcl_Size *trimRight); MODULE_SCOPE Tcl_Size TclTrimLeft(const char *bytes, Tcl_Size numBytes, const char *trim, Tcl_Size numTrim); MODULE_SCOPE Tcl_Size TclTrimRight(const char *bytes, Tcl_Size numBytes, const char *trim, Tcl_Size numTrim); MODULE_SCOPE const char*TclGetCommandTypeName(Tcl_Command command); MODULE_SCOPE void TclRegisterCommandTypeName( Tcl_ObjCmdProc2 *implementationProc, |
︙ | ︙ | |||
3550 3551 3552 3553 3554 3555 3556 | Tcl_FSUnloadFileProc **unloadProcPtr, int flags); #endif MODULE_SCOPE void TclInitThreadStorage(void); MODULE_SCOPE void TclFinalizeThreadDataThread(void); MODULE_SCOPE void TclFinalizeThreadStorage(void); #ifdef TCL_WIDE_CLICKS | | | | | | 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 | Tcl_FSUnloadFileProc **unloadProcPtr, int flags); #endif MODULE_SCOPE void TclInitThreadStorage(void); MODULE_SCOPE void TclFinalizeThreadDataThread(void); MODULE_SCOPE void TclFinalizeThreadStorage(void); #ifdef TCL_WIDE_CLICKS MODULE_SCOPE long long TclpGetWideClicks(void); MODULE_SCOPE double TclpWideClicksToNanoseconds(long long clicks); MODULE_SCOPE double TclpWideClickInMicrosec(void); #else # ifdef _WIN32 # define TCL_WIDE_CLICKS 1 MODULE_SCOPE long long TclpGetWideClicks(void); MODULE_SCOPE double TclpWideClickInMicrosec(void); # define TclpWideClicksToNanoseconds(clicks) \ ((double)(clicks) * TclpWideClickInMicrosec() * 1000) # endif #endif MODULE_SCOPE long long TclpGetMicroseconds(void); MODULE_SCOPE int TclZlibInit(Tcl_Interp *interp); MODULE_SCOPE void * TclpThreadCreateKey(void); MODULE_SCOPE void TclpThreadDeleteKey(void *keyPtr); |
︙ | ︙ | |||
3583 3584 3585 3586 3587 3588 3589 | /* * Many parsing tasks need a common definition of whitespace. * Use this routine and macro to achieve that and place * optimization (fragile on changes) in one place. */ MODULE_SCOPE int TclIsSpaceProc(int byte); | | | | 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 | /* * Many parsing tasks need a common definition of whitespace. * Use this routine and macro to achieve that and place * optimization (fragile on changes) in one place. */ MODULE_SCOPE int TclIsSpaceProc(int byte); #define TclIsSpaceProcM(byte) \ (((byte) > 0x20) ? 0 : TclIsSpaceProc(byte)) /* *---------------------------------------------------------------- * Command procedures in the generic core: *---------------------------------------------------------------- */ |
︙ | ︙ | |||
3953 3954 3955 3956 3957 3958 3959 | MODULE_SCOPE int TclFullFinalizationRequested(void); /* * TIP #542 */ | | | | | | | | < | 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 | MODULE_SCOPE int TclFullFinalizationRequested(void); /* * TIP #542 */ MODULE_SCOPE size_t TclUniCharLen(const Tcl_UniChar *uniStr); MODULE_SCOPE int TclUniCharNcmp(const Tcl_UniChar *ucs, const Tcl_UniChar *uct, size_t numChars); MODULE_SCOPE int TclUniCharNcasecmp(const Tcl_UniChar *ucs, const Tcl_UniChar *uct, size_t numChars); MODULE_SCOPE int TclUniCharCaseMatch(const Tcl_UniChar *uniStr, const Tcl_UniChar *uniPattern, int nocase); /* * Just for the purposes of command-type registration. */ MODULE_SCOPE Tcl_ObjCmdProc2 TclEnsembleImplementationCmd; MODULE_SCOPE Tcl_ObjCmdProc2 TclAliasObjCmd; |
︙ | ︙ | |||
4019 4020 4021 4022 4023 4024 4025 | MODULE_SCOPE int TclIndexEncode(Tcl_Interp *interp, Tcl_Obj *objPtr, int before, int after, int *indexPtr); MODULE_SCOPE Tcl_Size TclIndexDecode(int encoded, Tcl_Size endValue); /* * Error message utility functions */ | | > | | | 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 | MODULE_SCOPE int TclIndexEncode(Tcl_Interp *interp, Tcl_Obj *objPtr, int before, int after, int *indexPtr); MODULE_SCOPE Tcl_Size TclIndexDecode(int encoded, Tcl_Size endValue); /* * Error message utility functions */ MODULE_SCOPE int TclCommandWordLimitError(Tcl_Interp *interp, Tcl_Size count); /* Constants used in index value encoding routines. */ #define TCL_INDEX_END ((Tcl_Size)-2) #define TCL_INDEX_START ((Tcl_Size)0) /* *---------------------------------------------------------------------- * * TclScaleTime -- * * TIP #233 (Virtualized Time): Wrapper around the time virutalisation |
︙ | ︙ | |||
4102 4103 4104 4105 4106 4107 4108 | # define TclIncrObjsFreed() \ tclObjsFreed++ #else # define TclIncrObjsAllocated() # define TclIncrObjsFreed() #endif /* TCL_COMPILE_STATS */ | | | | | | | | | | | | | | | | | | | | | | | 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 | # define TclIncrObjsFreed() \ tclObjsFreed++ #else # define TclIncrObjsAllocated() # define TclIncrObjsFreed() #endif /* TCL_COMPILE_STATS */ # define TclAllocObjStorage(objPtr) \ TclAllocObjStorageEx(NULL, (objPtr)) # define TclFreeObjStorage(objPtr) \ TclFreeObjStorageEx(NULL, (objPtr)) #ifndef TCL_MEM_DEBUG # define TclNewObj(objPtr) \ TclIncrObjsAllocated(); \ TclAllocObjStorage(objPtr); \ (objPtr)->refCount = 0; \ (objPtr)->bytes = &tclEmptyString; \ (objPtr)->length = 0; \ (objPtr)->typePtr = NULL; \ TCL_DTRACE_OBJ_CREATE(objPtr) /* * Invalidate the string rep first so we can use the bytes value for our * pointer chain, and signal an obj deletion (as opposed to shimmering) with * 'length == TCL_INDEX_NONE'. * Use empty 'if ; else' to handle use in unbraced outer if/else conditions. */ # define TclDecrRefCount(objPtr) \ if ((objPtr)->refCount-- > 1) ; else { \ if (!(objPtr)->typePtr || !(objPtr)->typePtr->freeIntRepProc) { \ TCL_DTRACE_OBJ_FREE(objPtr); \ if ((objPtr)->bytes \ && ((objPtr)->bytes != &tclEmptyString)) { \ Tcl_Free((objPtr)->bytes); \ } \ (objPtr)->length = TCL_INDEX_NONE; \ TclFreeObjStorage(objPtr); \ TclIncrObjsFreed(); \ } else { \ TclFreeObj(objPtr); \ } \ } #if TCL_THREADS && !defined(USE_THREAD_ALLOC) # define USE_THREAD_ALLOC 1 #endif #if defined(PURIFY) |
︙ | ︙ | |||
4245 4246 4247 4248 4249 4250 4251 | (objPtr) = tclFreeObjList; \ tclFreeObjList = (Tcl_Obj *) \ tclFreeObjList->internalRep.twoPtrValue.ptr1; \ Tcl_MutexUnlock(&tclObjMutex); \ } while (0) # define TclFreeObjStorageEx(interp, objPtr) \ | | | | | | 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 | (objPtr) = tclFreeObjList; \ tclFreeObjList = (Tcl_Obj *) \ tclFreeObjList->internalRep.twoPtrValue.ptr1; \ Tcl_MutexUnlock(&tclObjMutex); \ } while (0) # define TclFreeObjStorageEx(interp, objPtr) \ do { \ Tcl_MutexLock(&tclObjMutex); \ (objPtr)->internalRep.twoPtrValue.ptr1 = (void *) tclFreeObjList; \ tclFreeObjList = (objPtr); \ Tcl_MutexUnlock(&tclObjMutex); \ } while (0) #endif #else /* TCL_MEM_DEBUG */ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file, int line); |
︙ | ︙ | |||
4300 4301 4302 4303 4304 4305 4306 | * MODULE_SCOPE void TclInitStringRep(Tcl_Obj *objPtr, char *bytePtr, size_t len); * MODULE_SCOPE void TclAttemptInitStringRep(Tcl_Obj *objPtr, char *bytePtr, size_t len); * *---------------------------------------------------------------- */ #define TclInitEmptyStringRep(objPtr) \ | | < | | | | | | | | | | | | | | | | | | | | | | | | | | | | 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 | * MODULE_SCOPE void TclInitStringRep(Tcl_Obj *objPtr, char *bytePtr, size_t len); * MODULE_SCOPE void TclAttemptInitStringRep(Tcl_Obj *objPtr, char *bytePtr, size_t len); * *---------------------------------------------------------------- */ #define TclInitEmptyStringRep(objPtr) \ ((objPtr)->length = (((objPtr)->bytes = &tclEmptyString), 0)) #define TclInitStringRep(objPtr, bytePtr, len) \ if ((len) == 0) { \ TclInitEmptyStringRep(objPtr); \ } else { \ (objPtr)->bytes = (char *)Tcl_Alloc((len) + 1U); \ memcpy((objPtr)->bytes, (bytePtr) ? (bytePtr) : &tclEmptyString, (len)); \ (objPtr)->bytes[len] = '\0'; \ (objPtr)->length = (len); \ } #define TclAttemptInitStringRep(objPtr, bytePtr, len) \ ((((len) == 0) ? ( \ TclInitEmptyStringRep(objPtr) \ ) : ( \ (objPtr)->bytes = (char *)Tcl_AttemptAlloc((len) + 1U), \ (objPtr)->length = ((objPtr)->bytes) ? \ (memcpy((objPtr)->bytes, (bytePtr) ? (bytePtr) : &tclEmptyString, (len)), \ (objPtr)->bytes[len] = '\0', (len)) : (-1) \ )), (objPtr)->bytes) /* *---------------------------------------------------------------- * Macro used by the Tcl core to get the string representation's byte array * pointer from a Tcl_Obj. This is an inline version of Tcl_GetString(). The * macro's expression result is the string rep's byte pointer which might be * NULL. The bytes referenced by this pointer must not be modified by the * caller. The ANSI C "prototype" for this macro is: * * MODULE_SCOPE char * TclGetString(Tcl_Obj *objPtr); *---------------------------------------------------------------- */ #define TclGetString(objPtr) \ ((objPtr)->bytes? (objPtr)->bytes : Tcl_GetString(objPtr)) #define TclGetStringFromObj(objPtr, lenPtr) \ ((objPtr)->bytes \ ? (*(lenPtr) = (objPtr)->length, (objPtr)->bytes) \ : (Tcl_GetStringFromObj)((objPtr), (lenPtr))) /* *---------------------------------------------------------------- * Macro used by the Tcl core to clean out an object's internal * representation. Does not actually reset the rep's bytes. The ANSI C * "prototype" for this macro is: * * MODULE_SCOPE void TclFreeInternalRep(Tcl_Obj *objPtr); *---------------------------------------------------------------- */ #define TclFreeInternalRep(objPtr) \ if ((objPtr)->typePtr != NULL) { \ if ((objPtr)->typePtr->freeIntRepProc != NULL) { \ (objPtr)->typePtr->freeIntRepProc(objPtr); \ } \ (objPtr)->typePtr = NULL; \ } /* *---------------------------------------------------------------- * Macro used by the Tcl core to clean out an object's string representation. * The ANSI C "prototype" for this macro is: * * MODULE_SCOPE void TclInvalidateStringRep(Tcl_Obj *objPtr); *---------------------------------------------------------------- */ #define TclInvalidateStringRep(objPtr) \ do { \ Tcl_Obj *_isobjPtr = (Tcl_Obj *)(objPtr); \ if (_isobjPtr->bytes != NULL) { \ if (_isobjPtr->bytes != &tclEmptyString) { \ Tcl_Free((char *)_isobjPtr->bytes); \ } \ _isobjPtr->bytes = NULL; \ } \ } while (0) /* * These form part of the native filesystem support. They are needed here * because we have a few native filesystem functions (which are the same for * win/unix) in this file. */ |
︙ | ︙ | |||
4421 4422 4423 4424 4425 4426 4427 | * * MODULE_SCOPE void TclUnpackBignum(Tcl_Obj *objPtr, mp_int bignum); *---------------------------------------------------------------- */ #define TclUnpackBignum(objPtr, bignum) \ do { \ | | | | 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 | * * MODULE_SCOPE void TclUnpackBignum(Tcl_Obj *objPtr, mp_int bignum); *---------------------------------------------------------------- */ #define TclUnpackBignum(objPtr, bignum) \ do { \ Tcl_Obj *bignumObj = (objPtr); \ int bignumPayload = \ PTR2INT(bignumObj->internalRep.twoPtrValue.ptr2); \ if (bignumPayload == -1) { \ (bignum) = *((mp_int *) bignumObj->internalRep.twoPtrValue.ptr1); \ } else { \ (bignum).dp = (mp_digit *)bignumObj->internalRep.twoPtrValue.ptr1; \ (bignum).sign = bignumPayload >> 30; \ (bignum).alloc = (bignumPayload >> 15) & 0x7FFF; \ |
︙ | ︙ | |||
4475 4476 4477 4478 4479 4480 4481 | Tcl_Size allocated = 2 * _needed; \ Tcl_Token *oldPtr = (tokenPtr); \ Tcl_Token *newPtr; \ if (oldPtr == (staticPtr)) { \ oldPtr = NULL; \ } \ newPtr = (Tcl_Token *)Tcl_AttemptRealloc((char *) oldPtr, \ | | | | | 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 | Tcl_Size allocated = 2 * _needed; \ Tcl_Token *oldPtr = (tokenPtr); \ Tcl_Token *newPtr; \ if (oldPtr == (staticPtr)) { \ oldPtr = NULL; \ } \ newPtr = (Tcl_Token *)Tcl_AttemptRealloc((char *) oldPtr, \ allocated * sizeof(Tcl_Token)); \ if (newPtr == NULL) { \ allocated = _needed + (append) + TCL_MIN_TOKEN_GROWTH; \ newPtr = (Tcl_Token *)Tcl_Realloc((char *) oldPtr, \ allocated * sizeof(Tcl_Token)); \ } \ (available) = allocated; \ if (oldPtr == NULL) { \ memcpy(newPtr, staticPtr, \ (used) * sizeof(Tcl_Token)); \ } \ (tokenPtr) = newPtr; \ } \ } while (0) #define TclGrowParseTokenArray(parsePtr, append) \ TclGrowTokenArray((parsePtr)->tokenPtr, (parsePtr)->numTokens, \ |
︙ | ︙ | |||
4508 4509 4510 4511 4512 4513 4514 | * the result of Tcl_UtfToUniChar. The ANSI C "prototype" for this macro is: * * MODULE_SCOPE int TclUtfToUniChar(const char *string, Tcl_UniChar *ch); *---------------------------------------------------------------- */ #define TclUtfToUniChar(str, chPtr) \ | | | | | | | | | | | | | | | < | 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 | * the result of Tcl_UtfToUniChar. The ANSI C "prototype" for this macro is: * * MODULE_SCOPE int TclUtfToUniChar(const char *string, Tcl_UniChar *ch); *---------------------------------------------------------------- */ #define TclUtfToUniChar(str, chPtr) \ (((UCHAR(*(str))) < 0x80) ? \ ((*(chPtr) = UCHAR(*(str))), 1) \ : Tcl_UtfToUniChar(str, chPtr)) /* *---------------------------------------------------------------- * Macro counterpart of the Tcl_NumUtfChars() function. To be used in speed- * -sensitive points where it pays to avoid a function call in the common case * of counting along a string of all one-byte characters. The ANSI C * "prototype" for this macro is: * * MODULE_SCOPE void TclNumUtfCharsM(Tcl_Size numChars, const char *bytes, * Tcl_Size numBytes); * numBytes must be >= 0 *---------------------------------------------------------------- */ #define TclNumUtfCharsM(numChars, bytes, numBytes) \ do { \ Tcl_Size _count, _i = (numBytes); \ unsigned char *_str = (unsigned char *) (bytes); \ while (_i > 0 && (*_str < 0xC0)) { _i--; _str++; } \ _count = (numBytes) - _i; \ if (_i) { \ _count += Tcl_NumUtfChars((bytes) + _count, _i); \ } \ (numChars) = _count; \ } while (0); /* *---------------------------------------------------------------- * Macro that encapsulates the logic that determines when it is safe to * interpret a string as a byte array directly. In summary, the object must be * a byte array and must not have a string representation (as the operations * that it is used in are defined on strings, not byte arrays). Theoretically * it is possible to also be efficient in the case where the object's bytes * field is filled by generation from the byte array (c.f. list canonicality) * but we don't do that at the moment since this is purely about efficiency. * The ANSI C "prototype" for this macro is: * * MODULE_SCOPE int TclIsPureByteArray(Tcl_Obj *objPtr); *---------------------------------------------------------------- */ MODULE_SCOPE int TclIsPureByteArray(Tcl_Obj *objPtr); #define TclIsPureDict(objPtr) \ (((objPtr)->bytes == NULL) && TclHasInternalRep((objPtr), &tclDictType)) #define TclHasInternalRep(objPtr, type) \ ((objPtr)->typePtr == (type)) #define TclFetchInternalRep(objPtr, type) \ (TclHasInternalRep((objPtr), (type)) ? &(objPtr)->internalRep : NULL) /* *---------------------------------------------------------------- * Macro used by the Tcl core to increment a namespace's export epoch * counter. The ANSI C "prototype" for this macro is: * * MODULE_SCOPE void TclInvalidateNsCmdLookup(Namespace *nsPtr); |
︙ | ︙ | |||
4605 4606 4607 4608 4609 4610 4611 | MODULE_SCOPE Tcl_LibraryInitProc TclplatformtestInit; MODULE_SCOPE Tcl_LibraryInitProc TclObjTest_Init; MODULE_SCOPE Tcl_LibraryInitProc TclThread_Init; MODULE_SCOPE Tcl_LibraryInitProc Procbodytest_Init; MODULE_SCOPE Tcl_LibraryInitProc Procbodytest_SafeInit; MODULE_SCOPE Tcl_LibraryInitProc Tcl_ABSListTest_Init; | < | 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 | MODULE_SCOPE Tcl_LibraryInitProc TclplatformtestInit; MODULE_SCOPE Tcl_LibraryInitProc TclObjTest_Init; MODULE_SCOPE Tcl_LibraryInitProc TclThread_Init; MODULE_SCOPE Tcl_LibraryInitProc Procbodytest_Init; MODULE_SCOPE Tcl_LibraryInitProc Procbodytest_SafeInit; MODULE_SCOPE Tcl_LibraryInitProc Tcl_ABSListTest_Init; /* *---------------------------------------------------------------- * Macro used by the Tcl core to check whether a pattern has any characters * special to [string match]. The ANSI C "prototype" for this macro is: * * MODULE_SCOPE int TclMatchIsTrivial(const char *pattern); *---------------------------------------------------------------- |
︙ | ︙ | |||
4631 4632 4633 4634 4635 4636 4637 | * * MODULE_SCOPE void TclSetIntObj(Tcl_Obj *objPtr, Tcl_WideInt w); * MODULE_SCOPE void TclSetDoubleObj(Tcl_Obj *objPtr, double d); *---------------------------------------------------------------- */ #define TclSetIntObj(objPtr, i) \ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 | * * MODULE_SCOPE void TclSetIntObj(Tcl_Obj *objPtr, Tcl_WideInt w); * MODULE_SCOPE void TclSetDoubleObj(Tcl_Obj *objPtr, double d); *---------------------------------------------------------------- */ #define TclSetIntObj(objPtr, i) \ do { \ Tcl_ObjInternalRep ir; \ ir.wideValue = (Tcl_WideInt) i; \ TclInvalidateStringRep(objPtr); \ Tcl_StoreInternalRep(objPtr, &tclIntType, &ir); \ } while (0) #define TclSetDoubleObj(objPtr, d) \ do { \ Tcl_ObjInternalRep ir; \ ir.doubleValue = (double) d; \ TclInvalidateStringRep(objPtr); \ Tcl_StoreInternalRep(objPtr, &tclDoubleType, &ir); \ } while (0) /* *---------------------------------------------------------------- * Macros used by the Tcl core to create and initialise objects of standard * types, avoiding the corresponding function calls in time critical parts of * the core. The ANSI C "prototypes" for these macros are: * * MODULE_SCOPE void TclNewIntObj(Tcl_Obj *objPtr, Tcl_WideInt w); * MODULE_SCOPE void TclNewDoubleObj(Tcl_Obj *objPtr, double d); * MODULE_SCOPE void TclNewStringObj(Tcl_Obj *objPtr, const char *s, Tcl_Size len); * MODULE_SCOPE void TclNewLiteralStringObj(Tcl_Obj*objPtr, const char *sLiteral); * *---------------------------------------------------------------- */ #ifndef TCL_MEM_DEBUG #define TclNewIntObj(objPtr, w) \ do { \ TclIncrObjsAllocated(); \ TclAllocObjStorage(objPtr); \ (objPtr)->refCount = 0; \ (objPtr)->bytes = NULL; \ (objPtr)->internalRep.wideValue = (Tcl_WideInt)(w); \ (objPtr)->typePtr = &tclIntType; \ TCL_DTRACE_OBJ_CREATE(objPtr); \ } while (0) #define TclNewUIntObj(objPtr, uw) \ do { \ TclIncrObjsAllocated(); \ TclAllocObjStorage(objPtr); \ (objPtr)->refCount = 0; \ (objPtr)->bytes = NULL; \ Tcl_WideUInt uw_ = (uw); \ if (uw_ > WIDE_MAX) { \ mp_int bignumValue_; \ if (mp_init_u64(&bignumValue_, uw_) != MP_OKAY) { \ Tcl_Panic("%s: memory overflow", "TclNewUIntObj"); \ } \ TclSetBignumInternalRep((objPtr), &bignumValue_); \ } else { \ (objPtr)->internalRep.wideValue = (Tcl_WideInt)(uw_); \ (objPtr)->typePtr = &tclIntType; \ } \ TCL_DTRACE_OBJ_CREATE(objPtr); \ } while (0) #define TclNewIndexObj(objPtr, w) \ TclNewIntObj(objPtr, w) #define TclNewDoubleObj(objPtr, d) \ do { \ TclIncrObjsAllocated(); \ TclAllocObjStorage(objPtr); \ (objPtr)->refCount = 0; \ (objPtr)->bytes = NULL; \ (objPtr)->internalRep.doubleValue = (double)(d); \ (objPtr)->typePtr = &tclDoubleType; \ TCL_DTRACE_OBJ_CREATE(objPtr); \ } while (0) #define TclNewStringObj(objPtr, s, len) \ do { \ TclIncrObjsAllocated(); \ TclAllocObjStorage(objPtr); \ (objPtr)->refCount = 0; \ TclInitStringRep((objPtr), (s), (len)); \ (objPtr)->typePtr = NULL; \ TCL_DTRACE_OBJ_CREATE(objPtr); \ } while (0) #else /* TCL_MEM_DEBUG */ #define TclNewIntObj(objPtr, w) \ (objPtr) = Tcl_NewWideIntObj(w) #define TclNewUIntObj(objPtr, uw) \ do { \ Tcl_WideUInt uw_ = (uw); \ if (uw_ > WIDE_MAX) { \ mp_int bignumValue_; \ if (mp_init_u64(&bignumValue_, uw_) == MP_OKAY) { \ (objPtr) = Tcl_NewBignumObj(&bignumValue_); \ } else { \ (objPtr) = NULL; \ } \ } else { \ (objPtr) = Tcl_NewWideIntObj(uw_); \ } \ } while (0) #define TclNewIndexObj(objPtr, w) \ TclNewIntObj(objPtr, w) #define TclNewDoubleObj(objPtr, d) \ (objPtr) = Tcl_NewDoubleObj(d) |
︙ | ︙ | |||
4784 4785 4786 4787 4788 4789 4790 | /* *---------------------------------------------------------------- * Inline version of TclCleanupCommand; still need the function as it is in * the internal stubs, but the core can use the macro instead. */ | | < | | | | | | | | < | > | | 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 | /* *---------------------------------------------------------------- * Inline version of TclCleanupCommand; still need the function as it is in * the internal stubs, but the core can use the macro instead. */ #define TclCleanupCommandMacro(cmdPtr) \ do { \ if ((cmdPtr)->refCount-- <= 1) { \ Tcl_Free(cmdPtr); \ } \ } while (0) /* * inside this routine crement refCount first incase cmdPtr is replacing itself */ #define TclRoutineAssign(location, cmdPtr) \ do { \ (cmdPtr)->refCount++; \ if ((location) != NULL \ && (location--) <= 1) { \ Tcl_Free(((location))); \ } \ (location) = (cmdPtr); \ } while (0) #define TclRoutineHasName(cmdPtr) \ ((cmdPtr)->hPtr != NULL) /* *---------------------------------------------------------------- * Inline versions of Tcl_LimitReady() and Tcl_LimitExceeded to limit number * of calls out of the critical path. Note that this code isn't particularly * readable; the non-inline version (in tclInterp.c) is much easier to * understand. Note also that these macros takes different args (iPtr->limit) * to the non-inline version. */ #define TclLimitExceeded(limit) \ ((limit).exceeded != 0) #define TclLimitReady(limit) \ (((limit).active == 0) ? 0 : \ (++(limit).granularityTicker, \ ((((limit).active & TCL_LIMIT_COMMANDS) && \ (((limit).cmdGranularity == 1) || \ ((limit).granularityTicker % (limit).cmdGranularity == 0))) \ ? 1 : \ (((limit).active & TCL_LIMIT_TIME) && \ |
︙ | ︙ | |||
4938 4939 4940 4941 4942 4943 4944 | typedef struct NRE_callback { Tcl_NRPostProc *procPtr; void *data[4]; struct NRE_callback *nextPtr; } NRE_callback; | > | | 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 | typedef struct NRE_callback { Tcl_NRPostProc *procPtr; void *data[4]; struct NRE_callback *nextPtr; } NRE_callback; #define TOP_CB(iPtr) \ (((Interp *)(iPtr))->execEnvPtr->callbackPtr) /* * Inline version of Tcl_NRAddCallback. */ #define TclNRAddCallback(interp,postProcPtr,data0,data1,data2,data3) \ do { \ |
︙ | ︙ | |||
4977 4978 4979 4980 4981 4982 4983 | #define NRE_ASSERT(expr) #endif #include "tclIntDecls.h" #include "tclIntPlatDecls.h" #if !defined(USE_TCL_STUBS) && !defined(TCL_MEM_DEBUG) | | | | | 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 | #define NRE_ASSERT(expr) #endif #include "tclIntDecls.h" #include "tclIntPlatDecls.h" #if !defined(USE_TCL_STUBS) && !defined(TCL_MEM_DEBUG) #define Tcl_AttemptAlloc TclpAlloc #define Tcl_AttemptRealloc TclpRealloc #define Tcl_Free TclpFree #endif /* * Special hack for macOS, where the static linker (technically the 'ar' * command) hates empty object files, and accepts no flags to make it shut up. * * These symbols are otherwise completely useless. |
︙ | ︙ |
Changes to generic/tclInterp.c.
︙ | ︙ | |||
182 183 184 185 186 187 188 | * TIP#143 limit handler internal representation. */ struct LimitHandler { int flags; /* The state of this particular handler. */ Tcl_LimitHandlerProc *handlerProc; /* The handler callback. */ | | < < | 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 | * TIP#143 limit handler internal representation. */ struct LimitHandler { int flags; /* The state of this particular handler. */ Tcl_LimitHandlerProc *handlerProc; /* The handler callback. */ void *clientData; /* Opaque argument to the handler callback. */ Tcl_LimitHandlerDeleteProc *deleteProc; /* How to delete the clientData. */ LimitHandler *prevPtr; /* Previous item in linked list of * handlers. */ LimitHandler *nextPtr; /* Next item in linked list of handlers. */ }; /* * Values for the LimitHandler flags field. * LIMIT_HANDLER_ACTIVE - Whether the handler is currently being * processed; handlers are never to be reentered. * LIMIT_HANDLER_DELETED - Whether the handler has been deleted. This * should not normally be observed because when a handler is * deleted it is also spliced out of the list of handlers, but * even so we will be careful. */ #define LIMIT_HANDLER_ACTIVE 0x01 #define LIMIT_HANDLER_DELETED 0x02 /* * Prototypes for local static functions: */ static int AliasCreate(Tcl_Interp *interp, Tcl_Interp *childInterp, Tcl_Interp *parentInterp, |
︙ | ︙ | |||
273 274 275 276 277 278 279 | Tcl_Interp *interp); static void TimeLimitCallback(void *clientData); /* NRE enabling */ static Tcl_NRPostProc NRPostInvokeHidden; static Tcl_ObjCmdProc2 NRInterpCmd; static Tcl_ObjCmdProc2 NRChildCmd; | < | 271 272 273 274 275 276 277 278 279 280 281 282 283 284 | Tcl_Interp *interp); static void TimeLimitCallback(void *clientData); /* NRE enabling */ static Tcl_NRPostProc NRPostInvokeHidden; static Tcl_ObjCmdProc2 NRInterpCmd; static Tcl_ObjCmdProc2 NRChildCmd; /* *---------------------------------------------------------------------- * * Tcl_SetPreInitScript -- * * This routine is used to change the value of the internal variable, |
︙ | ︙ |
Changes to generic/tclListObj.c.
︙ | ︙ | |||
1612 1613 1614 1615 1616 1617 1618 | *---------------------------------------------------------------------- */ Tcl_Obj * TclListObjGetElement( Tcl_Obj *objPtr, /* List object for which an element array is * to be returned. */ | | < | 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 | *---------------------------------------------------------------------- */ Tcl_Obj * TclListObjGetElement( Tcl_Obj *objPtr, /* List object for which an element array is * to be returned. */ Tcl_Size index) { return ListObjStorePtr(objPtr)->slots[ListObjStart(objPtr) + index]; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
2013 2014 2015 2016 2017 2018 2019 | return TCL_OK; } if (TclObjTypeHasProc(listObj, lengthProc)) { *lenPtr = TclObjTypeLength(listObj); return TCL_OK; } | < | 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 | return TCL_OK; } if (TclObjTypeHasProc(listObj, lengthProc)) { *lenPtr = TclObjTypeLength(listObj); return TCL_OK; } if (TclListObjGetRep(interp, listObj, &listRep) != TCL_OK) { return TCL_ERROR; } *lenPtr = ListRepLength(&listRep); return TCL_OK; } |
︙ | ︙ | |||
3548 3549 3550 3551 3552 3553 3554 | /* Set the string length to what was actually written, the safe choice */ (void) Tcl_InitStringRep(listObj, NULL, dst - 1 - start); if (flagPtr != localFlags) { Tcl_Free(flagPtr); } } | < | 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 | /* Set the string length to what was actually written, the safe choice */ (void) Tcl_InitStringRep(listObj, NULL, dst - 1 - start); if (flagPtr != localFlags) { Tcl_Free(flagPtr); } } /* *------------------------------------------------------------------------ * * TclListTestObj -- * * Returns a list object with a specific internal rep and content. |
︙ | ︙ |
Changes to generic/tclLoad.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" | < | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * The following structure describes a library that has been loaded either * dynamically (with the "load" command) or statically (as indicated by a call * to Tcl_StaticLibrary). All such libraries are linked together into a * single list for the process. */ |
︙ | ︙ | |||
92 93 94 95 96 97 98 | static void LoadCleanupProc(void *clientData, Tcl_Interp *interp); static int IsStatic(LoadedLibrary *libraryPtr); static int UnloadLibrary(Tcl_Interp *interp, Tcl_Interp *target, LoadedLibrary *library, int keepLibrary, const char *fullFileName, int interpExiting); | < | 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | static void LoadCleanupProc(void *clientData, Tcl_Interp *interp); static int IsStatic(LoadedLibrary *libraryPtr); static int UnloadLibrary(Tcl_Interp *interp, Tcl_Interp *target, LoadedLibrary *library, int keepLibrary, const char *fullFileName, int interpExiting); static int IsStatic( LoadedLibrary *libraryPtr) { return (libraryPtr->fileName[0] == '\0'); } |
︙ | ︙ | |||
140 141 142 143 144 145 146 | const char *p, *fullFileName, *prefix; Tcl_LoadHandle loadHandle; Tcl_UniChar ch = 0; size_t len; int flags = 0; Tcl_Obj *const *savedobjv = objv; static const char *const options[] = { | | | 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | const char *p, *fullFileName, *prefix; Tcl_LoadHandle loadHandle; Tcl_UniChar ch = 0; size_t len; int flags = 0; Tcl_Obj *const *savedobjv = objv; static const char *const options[] = { "-global", "-lazy", "--", NULL }; enum loadOptionsEnum { LOAD_GLOBAL, LOAD_LAZY, LOAD_LAST } index; while (objc > 2) { if (TclGetString(objv[1])[0] != '-') { |
︙ | ︙ | |||
164 165 166 167 168 169 170 | } else if (LOAD_LAZY == index) { flags |= TCL_LOAD_LAZY; } else { break; } } if ((objc < 2) || (objc > 4)) { | | > | 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | } else if (LOAD_LAZY == index) { flags |= TCL_LOAD_LAZY; } else { break; } } if ((objc < 2) || (objc > 4)) { Tcl_WrongNumArgs(interp, 1, savedobjv, "?-global? ?-lazy? ?--? fileName ?prefix? ?interp?"); return TCL_ERROR; } if (Tcl_FSConvertToPathType(interp, objv[1]) != TCL_OK) { return TCL_ERROR; } fullFileName = TclGetString(objv[1]); |
︙ | ︙ | |||
750 751 752 753 754 755 756 | Tcl_DStringFree(&tmp); if (!complain && (code != TCL_OK)) { code = TCL_OK; Tcl_ResetResult(interp); } return code; } | < | | | | | | < | 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 | Tcl_DStringFree(&tmp); if (!complain && (code != TCL_OK)) { code = TCL_OK; Tcl_ResetResult(interp); } return code; } /* *---------------------------------------------------------------------- * * UnloadLibrary -- * * Unloads a library from an interpreter, and also from the process if it * is unloadable, i.e. if it provides an "unload" function. * * Results: * A standard Tcl result. * * Side effects: * See description. * *---------------------------------------------------------------------- */ static int UnloadLibrary( Tcl_Interp *interp, Tcl_Interp *target, LoadedLibrary *libraryPtr, int keepLibrary, const char *fullFileName, int interpExiting) { int code; InterpLibrary *ipFirstPtr, *ipPtr; LoadedLibrary *iterLibraryPtr; int trustedRefCount = -1, safeRefCount = -1; Tcl_LibraryUnloadProc *unloadProc = NULL; |
︙ | ︙ | |||
818 819 820 821 822 823 824 | code = TCL_ERROR; goto done; } } unloadProc = libraryPtr->unloadProc; } | < < | 815 816 817 818 819 820 821 822 823 824 825 826 827 828 | code = TCL_ERROR; goto done; } } unloadProc = libraryPtr->unloadProc; } /* * We are ready to unload the library. First, evaluate the unload * function. If this fails, we cannot proceed with unload. Also, we must * specify the proper flag to pass to the unload callback. * TCL_UNLOAD_DETACH_FROM_INTERPRETER is defined when the callback should * only remove itself from the interpreter; the library will be unloaded * in a future call of unload. In case the library will be unloaded just |
︙ | ︙ | |||
853 854 855 856 857 858 859 | if (safeRefCount <= 0 && trustedRefCount <= 0) { code = TCL_UNLOAD_DETACH_FROM_PROCESS; } } code = unloadProc(target, code); } | < < | 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 | if (safeRefCount <= 0 && trustedRefCount <= 0) { code = TCL_UNLOAD_DETACH_FROM_PROCESS; } } code = unloadProc(target, code); } if (code != TCL_OK) { Tcl_TransferResult(target, code, interp); goto done; } /* * Remove this library from the interpreter's library cache. */ ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL); ipPtr = ipFirstPtr; |
︙ | ︙ | |||
881 882 883 884 885 886 887 | ipPrevPtr->nextPtr = ipPtr->nextPtr; break; } } } Tcl_Free(ipPtr); Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc, ipFirstPtr); | < | 874 875 876 877 878 879 880 881 882 883 884 885 886 887 | ipPrevPtr->nextPtr = ipPtr->nextPtr; break; } } } Tcl_Free(ipPtr); Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc, ipFirstPtr); if (IsStatic(libraryPtr)) { goto done; } /* * The unload function was called succesfully. |
︙ | ︙ | |||
1104 1105 1106 1107 1108 1109 1110 | TclGetLoadedLibraries( Tcl_Interp *interp, /* Interpreter in which to return information * or error message. */ const char *targetName, /* Name of target interpreter or NULL. If * NULL, return info about all interps; * otherwise, just return info about this * interpreter. */ | | | < | 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 | TclGetLoadedLibraries( Tcl_Interp *interp, /* Interpreter in which to return information * or error message. */ const char *targetName, /* Name of target interpreter or NULL. If * NULL, return info about all interps; * otherwise, just return info about this * interpreter. */ const char *prefix) /* Prefix or NULL. If NULL, return info * for all prefixes. */ { Tcl_Interp *target; LoadedLibrary *libraryPtr; InterpLibrary *ipPtr; Tcl_Obj *resultObj, *pkgDesc[2]; if (targetName == NULL) { |
︙ | ︙ |
Changes to generic/tclNamesp.c.
︙ | ︙ | |||
1075 1076 1077 1078 1079 1080 1081 | Namespace *nsPtr) { return (nsPtr->flags & NS_DYING) ? 1 : 0; } void TclDeleteNamespaceChildren( | | < | 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 | Namespace *nsPtr) { return (nsPtr->flags & NS_DYING) ? 1 : 0; } void TclDeleteNamespaceChildren( Namespace *nsPtr) /* Namespace whose children to delete */ { Interp *iPtr = (Interp *) nsPtr->interp; Tcl_HashEntry *entryPtr; size_t i; int unchecked; Tcl_HashSearch search; /* |
︙ | ︙ | |||
3959 3960 3961 3962 3963 3964 3965 | Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", TclGetString(objv[1]), (char *)NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, resultPtr); return TCL_OK; } | < | 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 | Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", TclGetString(objv[1]), (char *)NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, resultPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * NamespaceParentCmd -- * * Invoked to implement the "namespace parent" command that returns the |
︙ | ︙ | |||
5153 5154 5155 5156 5157 5158 5159 | const char *command, /* First character in command that generated * the error. */ Tcl_Size length) /* Number of bytes in command (-1 means use * all bytes up to first null byte). */ { TclLogCommandInfo(interp, script, command, length, NULL, NULL); } | < | 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 | const char *command, /* First character in command that generated * the error. */ Tcl_Size length) /* Number of bytes in command (-1 means use * all bytes up to first null byte). */ { TclLogCommandInfo(interp, script, command, length, NULL, NULL); } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * tab-width: 8 * End: */ |
Changes to generic/tclOOCall.c.
︙ | ︙ | |||
151 152 153 154 155 156 157 | "TclOO method name", FreeMethodNameRep, DupMethodNameRep, NULL, NULL, TCL_OBJTYPE_V0 }; | < | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | "TclOO method name", FreeMethodNameRep, DupMethodNameRep, NULL, NULL, TCL_OBJTYPE_V0 }; /* * ---------------------------------------------------------------------- * * TclOODeleteContext -- * * Destroys a method call-chain context, which should not be in use. |
︙ | ︙ | |||
938 939 940 941 942 943 944 | } } if (contextCls) { foundPrivate |= AddPrivatesFromClassChainToCallContext(oPtr->selfCls, contextCls, methodNameObj, cbPtr, doneFilters, flags, filterDecl); } | | | 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 | } } if (contextCls) { foundPrivate |= AddPrivatesFromClassChainToCallContext(oPtr->selfCls, contextCls, methodNameObj, cbPtr, doneFilters, flags, filterDecl); } if (!blockedUnexported && oPtr->selfCls) { foundPrivate |= AddSimpleClassChainToCallContext(oPtr->selfCls, methodNameObj, cbPtr, doneFilters, flags, filterDecl); } return foundPrivate; } /* |
︙ | ︙ | |||
1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 | static inline void InitCallChain( CallChain *callPtr, Object *oPtr, int flags) { callPtr->flags = flags & (PUBLIC_METHOD | PRIVATE_METHOD | SPECIAL | FILTER_HANDLING); if (oPtr->flags & USE_CLASS_CACHE) { | > > > > > > > | > | | | > > > > > | 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 | static inline void InitCallChain( CallChain *callPtr, Object *oPtr, int flags) { /* * Note that it's possible to end up with a NULL oPtr->selfCls here if * there is a call into stereotypical object after it has finished running * its destructor phase. Such things can't be cached for a long time so the * epoch can be bogus. [Bug 7842f33a5c] */ callPtr->flags = flags & (PUBLIC_METHOD | PRIVATE_METHOD | SPECIAL | FILTER_HANDLING); if (oPtr->flags & USE_CLASS_CACHE) { oPtr = (oPtr->selfCls ? oPtr->selfCls->thisPtr : NULL); callPtr->flags |= USE_CLASS_CACHE; } if (oPtr) { callPtr->epoch = oPtr->fPtr->epoch; callPtr->objectCreationEpoch = oPtr->creationEpoch; callPtr->objectEpoch = oPtr->epoch; } else { callPtr->epoch = 0; callPtr->objectCreationEpoch = 0; callPtr->objectEpoch = 0; } callPtr->refCount = 1; callPtr->numChain = 0; callPtr->chain = callPtr->staticChain; } /* * ---------------------------------------------------------------------- |
︙ | ︙ | |||
1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 | IsStillValid( CallChain *callPtr, Object *oPtr, int flags, int mask) { if ((oPtr->flags & USE_CLASS_CACHE)) { oPtr = oPtr->selfCls->thisPtr; flags |= USE_CLASS_CACHE; } return ((callPtr->objectCreationEpoch == oPtr->creationEpoch) && (callPtr->epoch == oPtr->fPtr->epoch) && (callPtr->objectEpoch == oPtr->epoch) && ((callPtr->flags & mask) == (flags & mask))); | > > > > > > > | 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 | IsStillValid( CallChain *callPtr, Object *oPtr, int flags, int mask) { if ((oPtr->flags & USE_CLASS_CACHE)) { /* * If the object is in a weird state (due to stereotype tricks) then * just declare the cache invalid. [Bug 7842f33a5c] */ if (!oPtr->selfCls) { return 0; } oPtr = oPtr->selfCls->thisPtr; flags |= USE_CLASS_CACHE; } return ((callPtr->objectCreationEpoch == oPtr->creationEpoch) && (callPtr->epoch == oPtr->fPtr->epoch) && (callPtr->objectEpoch == oPtr->epoch) && ((callPtr->flags & mask) == (flags & mask))); |
︙ | ︙ | |||
1212 1213 1214 1215 1216 1217 1218 | if (IsStillValid(callPtr, oPtr, flags, reuseMask)) { callPtr->refCount++; goto returnContext; } Tcl_StoreInternalRep(cacheInThisObj, &methodNameType, NULL); } | > > > > > > > > | | | 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 | if (IsStillValid(callPtr, oPtr, flags, reuseMask)) { callPtr->refCount++; goto returnContext; } Tcl_StoreInternalRep(cacheInThisObj, &methodNameType, NULL); } /* * Note that it's possible to end up with a NULL oPtr->selfCls here if * there is a call into stereotypical object after it has finished * running its destructor phase. It's quite a tangle, but at that * point, we simply can't get stereotypes from the cache. * [Bug 7842f33a5c] */ if (oPtr->flags & USE_CLASS_CACHE && oPtr->selfCls) { if (oPtr->selfCls->classChainCache) { hPtr = Tcl_FindHashEntry(oPtr->selfCls->classChainCache, methodNameObj); } else { hPtr = NULL; } } else { if (oPtr->chainCache != NULL) { |
︙ | ︙ | |||
1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 | CallChain *callPtr; struct ChainBuilder cb; Tcl_Size count; Foundation *fPtr = clsPtr->thisPtr->fPtr; Tcl_HashEntry *hPtr; Tcl_HashTable doneFilters; Object obj; /* * Synthesize a temporary stereotypical object so that we can use existing * machinery to produce the stereotypical call chain. */ memset(&obj, 0, sizeof(Object)); | > > > > > > > > > > > | 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 | CallChain *callPtr; struct ChainBuilder cb; Tcl_Size count; Foundation *fPtr = clsPtr->thisPtr->fPtr; Tcl_HashEntry *hPtr; Tcl_HashTable doneFilters; Object obj; /* * Note that it's possible to end up with a NULL clsPtr here if there is * a call into stereotypical object after it has finished running its * destructor phase. It's quite a tangle, but at that point, we simply * can't get stereotypes. [Bug 7842f33a5c] */ if (clsPtr == NULL) { return NULL; } /* * Synthesize a temporary stereotypical object so that we can use existing * machinery to produce the stereotypical call chain. */ memset(&obj, 0, sizeof(Object)); |
︙ | ︙ | |||
1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 | /* * We hard-code the tail-recursive form. It's by far the most common case * *and* it is much more gentle on the stack. * * Note that mixins must be processed before the main class hierarchy. * [Bug 1998221] */ tailRecurse: FOREACH(superPtr, classPtr->mixins) { if (AddPrivatesFromClassChainToCallContext(superPtr, contextCls, methodName, cbPtr, doneFilters, flags|TRAVERSED_MIXIN, filterDecl)) { return 1; } } | > > > > > > > | 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 | /* * We hard-code the tail-recursive form. It's by far the most common case * *and* it is much more gentle on the stack. * * Note that mixins must be processed before the main class hierarchy. * [Bug 1998221] * * Note also that it's possible to end up with a null classPtr here if * there is a call into stereotypical object after it has finished running * its destructor phase. [Bug 7842f33a5c] */ tailRecurse: if (classPtr == NULL) { return 0; } FOREACH(superPtr, classPtr->mixins) { if (AddPrivatesFromClassChainToCallContext(superPtr, contextCls, methodName, cbPtr, doneFilters, flags|TRAVERSED_MIXIN, filterDecl)) { return 1; } } |
︙ | ︙ |
Changes to generic/tclOOInfo.c.
︙ | ︙ | |||
617 618 619 620 621 622 623 | Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(names[i], -1)); } if (numNames > 0) { Tcl_Free((void *)names); } } else if (oPtr->methodsPtr) { | > > > > > > | > > > > > > | | > | 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 | Tcl_ListObjAppendElement(NULL, resultObj, Tcl_NewStringObj(names[i], -1)); } if (numNames > 0) { Tcl_Free((void *)names); } } else if (oPtr->methodsPtr) { if (scope == -1) { /* * Handle legacy-mode matching. [Bug 36e5517a6850] */ int scopeFilter = flag | TRUE_PRIVATE_METHOD; FOREACH_HASH(namePtr, mPtr, oPtr->methodsPtr) { if (mPtr->typePtr && (mPtr->flags & scopeFilter) == flag) { Tcl_ListObjAppendElement(NULL, resultObj, namePtr); } } } else { FOREACH_HASH(namePtr, mPtr, oPtr->methodsPtr) { if (mPtr->typePtr && (mPtr->flags & SCOPE_FLAGS) == flag) { Tcl_ListObjAppendElement(NULL, resultObj, namePtr); } } } } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } |
︙ | ︙ | |||
1374 1375 1376 1377 1378 1379 1380 | } if (numNames > 0) { Tcl_Free((void *)names); } } else { FOREACH_HASH_DECLS; | > > > > > > | > > > > > > | | > | 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 | } if (numNames > 0) { Tcl_Free((void *)names); } } else { FOREACH_HASH_DECLS; if (scope == -1) { /* * Handle legacy-mode matching. [Bug 36e5517a6850] */ int scopeFilter = flag | TRUE_PRIVATE_METHOD; FOREACH_HASH(namePtr, mPtr, &clsPtr->classMethods) { if (mPtr->typePtr && (mPtr->flags & scopeFilter) == flag) { Tcl_ListObjAppendElement(NULL, resultObj, namePtr); } } } else { FOREACH_HASH(namePtr, mPtr, &clsPtr->classMethods) { if (mPtr->typePtr && (mPtr->flags & SCOPE_FLAGS) == flag) { Tcl_ListObjAppendElement(NULL, resultObj, namePtr); } } } } Tcl_SetObjResult(interp, resultObj); return TCL_OK; } |
︙ | ︙ |
Changes to generic/tclOOInt.h.
︙ | ︙ | |||
93 94 95 96 97 98 99 100 101 102 103 104 105 106 | * before the method executes. */ TclOO_PostCallProc *postCallProc; /* Callback to allow for additional cleanup * after the method executes. */ GetFrameInfoValueProc *gfivProc; /* Callback to allow for fine tuning of how * the method reports itself. */ } ProcedureMethod; #define TCLOO_PROCEDURE_METHOD_VERSION 0 /* * Flags for use in a ProcedureMethod. * | > > > > > > > > > > | 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | * before the method executes. */ TclOO_PostCallProc *postCallProc; /* Callback to allow for additional cleanup * after the method executes. */ GetFrameInfoValueProc *gfivProc; /* Callback to allow for fine tuning of how * the method reports itself. */ Command cmd; /* Space used to connect to [info frame] */ ExtraFrameInfo efi; /* Space used to store data for [info frame] */ Tcl_Interp *interp; /* Interpreter in which to compute the name of * the method. */ Tcl_Method method; /* Method to compute the name of. */ int callSiteFlags; /* Flags from the call chain. Only interested * in whether this is a constructor or * destructor, which we can't know until then * for messy reasons. Other flags are variable * but not used. */ } ProcedureMethod; #define TCLOO_PROCEDURE_METHOD_VERSION 0 /* * Flags for use in a ProcedureMethod. * |
︙ | ︙ |
Changes to generic/tclOOMethod.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 | #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "tclInt.h" #include "tclOOInt.h" #include "tclCompile.h" | < < < < < < < < < < < | < < < | < < | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "tclInt.h" #include "tclOOInt.h" #include "tclCompile.h" /* * Structure used to contain all the information needed about a call frame * used in a procedure-like method. */ typedef struct { CallFrame *framePtr; /* Reference to the call frame itself (it's * actually allocated on the Tcl stack). */ ProcErrorProc *errProc; /* The error handler for the body. */ Tcl_Obj *nameObj; /* The "name" of the command. Only used for a * few moments, so not reference. */ } PMFrameData; /* * Structure used to pass information about variable resolution to the * on-the-ground resolvers used when working with resolved compiled variables. */ |
︙ | ︙ | |||
79 80 81 82 83 84 85 86 87 88 89 90 91 92 | static void DeleteProcedureMethodRecord(ProcedureMethod *pmPtr); static void DeleteProcedureMethod(void *clientData); static int CloneProcedureMethod(Tcl_Interp *interp, void *clientData, void **newClientData); static ProcErrorProc MethodErrorHandler; static ProcErrorProc ConstructorErrorHandler; static ProcErrorProc DestructorErrorHandler; static Tcl_Obj * RenderDeclarerName(void *clientData); static int InvokeForwardMethod(void *clientData, Tcl_Interp *interp, Tcl_ObjectContext context, Tcl_Size objc, Tcl_Obj *const *objv); static void DeleteForwardMethod(void *clientData); static int CloneForwardMethod(Tcl_Interp *interp, void *clientData, void **newClientData); | > | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | static void DeleteProcedureMethodRecord(ProcedureMethod *pmPtr); static void DeleteProcedureMethod(void *clientData); static int CloneProcedureMethod(Tcl_Interp *interp, void *clientData, void **newClientData); static ProcErrorProc MethodErrorHandler; static ProcErrorProc ConstructorErrorHandler; static ProcErrorProc DestructorErrorHandler; static Tcl_Obj * RenderMethodName(void *clientData); static Tcl_Obj * RenderDeclarerName(void *clientData); static int InvokeForwardMethod(void *clientData, Tcl_Interp *interp, Tcl_ObjectContext context, Tcl_Size objc, Tcl_Obj *const *objv); static void DeleteForwardMethod(void *clientData); static int CloneForwardMethod(Tcl_Interp *interp, void *clientData, void **newClientData); |
︙ | ︙ | |||
110 111 112 113 114 115 116 117 118 119 120 121 122 123 | * Helper macros (derived from things private to tclVar.c) */ #define TclVarTable(contextNs) \ ((Tcl_HashTable *) (&((Namespace *) (contextNs))->varTable)) #define TclVarHashGetValue(hPtr) \ ((Tcl_Var) ((char *)hPtr - offsetof(VarInHash, entry))) /* * ---------------------------------------------------------------------- * * Tcl_NewInstanceMethod -- * * Attach a method to an object instance. | > > > > > > > > > > > > > > | 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | * Helper macros (derived from things private to tclVar.c) */ #define TclVarTable(contextNs) \ ((Tcl_HashTable *) (&((Namespace *) (contextNs))->varTable)) #define TclVarHashGetValue(hPtr) \ ((Tcl_Var) ((char *)hPtr - offsetof(VarInHash, entry))) static inline ProcedureMethod * AllocProcedureMethodRecord( int flags) { ProcedureMethod *pmPtr = (ProcedureMethod *) Tcl_Alloc(sizeof(ProcedureMethod)); memset(pmPtr, 0, sizeof(ProcedureMethod)); pmPtr->version = TCLOO_PROCEDURE_METHOD_VERSION; pmPtr->flags = flags & USE_DECLARER_NS; pmPtr->refCount = 1; pmPtr->cmd.clientData = &pmPtr->efi; return pmPtr; } /* * ---------------------------------------------------------------------- * * Tcl_NewInstanceMethod -- * * Attach a method to an object instance. |
︙ | ︙ | |||
430 431 432 433 434 435 436 | Tcl_Size argsLen; ProcedureMethod *pmPtr; Tcl_Method method; if (TclListObjLength(interp, argsObj, &argsLen) != TCL_OK) { return NULL; } | < < < < < | | 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 | Tcl_Size argsLen; ProcedureMethod *pmPtr; Tcl_Method method; if (TclListObjLength(interp, argsObj, &argsLen) != TCL_OK) { return NULL; } pmPtr = AllocProcedureMethodRecord(flags); method = TclOOMakeProcInstanceMethod(interp, oPtr, flags, nameObj, argsObj, bodyObj, &procMethodType, pmPtr, &pmPtr->procPtr); if (method == NULL) { Tcl_Free(pmPtr); } else if (pmPtrPtr != NULL) { *pmPtrPtr = pmPtr; } |
︙ | ︙ | |||
491 492 493 494 495 496 497 | procName = "<destructor>"; } else if (TclListObjLength(interp, argsObj, &argsLen) != TCL_OK) { return NULL; } else { procName = (nameObj==NULL ? "<constructor>" : TclGetString(nameObj)); } | < < < < < | | 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 | procName = "<destructor>"; } else if (TclListObjLength(interp, argsObj, &argsLen) != TCL_OK) { return NULL; } else { procName = (nameObj==NULL ? "<constructor>" : TclGetString(nameObj)); } pmPtr = AllocProcedureMethodRecord(flags); method = TclOOMakeProcMethod(interp, clsPtr, flags, nameObj, procName, argsObj, bodyObj, &procMethodType, pmPtr, &pmPtr->procPtr); if (argsLen == TCL_INDEX_NONE) { Tcl_DecrRefCount(argsObj); } if (method == NULL) { |
︙ | ︙ | |||
768 769 770 771 772 773 774 775 776 777 778 779 780 781 | */ if (TclOOObjectDestroyed(((CallContext *)context)->oPtr) || Tcl_InterpDeleted(interp)) { return TclNRObjectContextInvokeNext(interp, context, objc, objv, Tcl_ObjectContextSkippedArgs(context)); } /* * Allocate the special frame data. */ fdPtr = (PMFrameData *)TclStackAlloc(interp, sizeof(PMFrameData)); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 | */ if (TclOOObjectDestroyed(((CallContext *)context)->oPtr) || Tcl_InterpDeleted(interp)) { return TclNRObjectContextInvokeNext(interp, context, objc, objv, Tcl_ObjectContextSkippedArgs(context)); } /* * Finishes filling out the extra frame info so that [info frame] works if * that is not already set up. */ if (pmPtr->efi.length == 0) { Tcl_Method method = Tcl_ObjectContextMethod(context); pmPtr->efi.length = 2; pmPtr->efi.fields[0].name = "method"; pmPtr->efi.fields[0].proc = RenderMethodName; pmPtr->efi.fields[0].clientData = pmPtr; pmPtr->callSiteFlags = ((CallContext *) context)->callPtr->flags & (CONSTRUCTOR | DESTRUCTOR); pmPtr->interp = interp; pmPtr->method = method; if (pmPtr->gfivProc != NULL) { pmPtr->efi.fields[1].name = ""; pmPtr->efi.fields[1].proc = pmPtr->gfivProc; pmPtr->efi.fields[1].clientData = pmPtr; } else { if (Tcl_MethodDeclarerObject(method) != NULL) { pmPtr->efi.fields[1].name = "object"; } else { pmPtr->efi.fields[1].name = "class"; } pmPtr->efi.fields[1].proc = RenderDeclarerName; pmPtr->efi.fields[1].clientData = pmPtr; } } /* * Allocate the special frame data. */ fdPtr = (PMFrameData *)TclStackAlloc(interp, sizeof(PMFrameData)); |
︙ | ︙ | |||
798 799 800 801 802 803 804 | if (pmPtr->preCallProc != NULL) { int isFinished; result = pmPtr->preCallProc(pmPtr->clientData, interp, context, (Tcl_CallFrame *) fdPtr->framePtr, &isFinished); if (isFinished || result != TCL_OK) { | < < < < < < < | 818 819 820 821 822 823 824 825 826 827 828 829 830 831 | if (pmPtr->preCallProc != NULL) { int isFinished; result = pmPtr->preCallProc(pmPtr->clientData, interp, context, (Tcl_CallFrame *) fdPtr->framePtr, &isFinished); if (isFinished || result != TCL_OK) { Tcl_PopCallFrame(interp); TclStackFree(interp, fdPtr->framePtr); if (pmPtr->refCount-- <= 1) { DeleteProcedureMethodRecord(pmPtr); } TclStackFree(interp, fdPtr); return result; |
︙ | ︙ | |||
845 846 847 848 849 850 851 | if (pmPtr->postCallProc) { result = pmPtr->postCallProc(pmPtr->clientData, interp, context, Tcl_GetObjectNamespace(Tcl_ObjectContextObject(context)), result); } | < < < < < < < | 858 859 860 861 862 863 864 865 866 867 868 869 870 871 | if (pmPtr->postCallProc) { result = pmPtr->postCallProc(pmPtr->clientData, interp, context, Tcl_GetObjectNamespace(Tcl_ObjectContextObject(context)), result); } /* * Scrap the special frame data now that we're done with it. Note that we * are inlining DeleteProcedureMethod() here; this location is highly * sensitive when it comes to performance! */ if (pmPtr->refCount-- <= 1) { |
︙ | ︙ | |||
878 879 880 881 882 883 884 | Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const *objv, /* Array of arguments. */ PMFrameData *fdPtr) /* Place to store information about the call * frame. */ { Namespace *nsPtr = (Namespace *) contextPtr->oPtr->namespacePtr; int result; | < < < < < | < < < < < < < < | < | < < < < < < < > | > | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 | Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const *objv, /* Array of arguments. */ PMFrameData *fdPtr) /* Place to store information about the call * frame. */ { Namespace *nsPtr = (Namespace *) contextPtr->oPtr->namespacePtr; int result; CallFrame **framePtrPtr = &fdPtr->framePtr; ByteCode *codePtr; /* * Compute basic information on the basis of the type of method it is. */ if (contextPtr->callPtr->flags & CONSTRUCTOR) { fdPtr->nameObj = contextPtr->oPtr->fPtr->constructorName; fdPtr->errProc = ConstructorErrorHandler; } else if (contextPtr->callPtr->flags & DESTRUCTOR) { fdPtr->nameObj = contextPtr->oPtr->fPtr->destructorName; fdPtr->errProc = DestructorErrorHandler; } else { fdPtr->nameObj = Tcl_MethodName( Tcl_ObjectContextMethod((Tcl_ObjectContext) contextPtr)); fdPtr->errProc = MethodErrorHandler; } if (pmPtr->errProc != NULL) { fdPtr->errProc = pmPtr->errProc; } /* * Magic to enable things like [incr Tcl], which wants methods to run in * their class's namespace. */ if (pmPtr->flags & USE_DECLARER_NS) { Method *mPtr = contextPtr->callPtr->chain[contextPtr->index].mPtr; if (mPtr->declaringClassPtr != NULL) { nsPtr = (Namespace *) mPtr->declaringClassPtr->thisPtr->namespacePtr; } else { nsPtr = (Namespace *) mPtr->declaringObjectPtr->namespacePtr; } } /* * Compile the body. * * [Bug 2037727] Always call TclProcCompileProc so that we check not only * that we have bytecode, but also that it remains valid. Note that we set * the namespace of the code here directly; this is a hack, but the * alternative is *so* slow... */ pmPtr->procPtr->cmdPtr = &pmPtr->cmd; ByteCodeGetInternalRep(pmPtr->procPtr->bodyPtr, &tclByteCodeType, codePtr); if (codePtr) { codePtr->nsPtr = nsPtr; } result = TclProcCompileProc(interp, pmPtr->procPtr, pmPtr->procPtr->bodyPtr, nsPtr, "body of method", TclGetString(fdPtr->nameObj)); if (result != TCL_OK) { return result; } /* * Make the stack frame and fill it out with information about this call. * This operation doesn't ever actually fail. */ (void) TclPushStackFrame(interp, (Tcl_CallFrame **) framePtrPtr, (Tcl_Namespace *) nsPtr, FRAME_IS_PROC|FRAME_IS_METHOD); fdPtr->framePtr->clientData = contextPtr; fdPtr->framePtr->objc = objc; fdPtr->framePtr->objv = objv; fdPtr->framePtr->procPtr = pmPtr->procPtr; return TCL_OK; } /* * ---------------------------------------------------------------------- * * TclOOSetupVariableResolver, etc. -- * |
︙ | ︙ | |||
1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 | *rPtrPtr = &infoPtr->info; return TCL_OK; } /* * ---------------------------------------------------------------------- * * RenderDeclarerName -- * * Returns the name of the entity (object or class) which declared a * method. Used for producing information for [info frame] in such a way * that the expensive part of this (generating the object or class name * itself) isn't done until it is needed. * * ---------------------------------------------------------------------- */ static Tcl_Obj * RenderDeclarerName( void *clientData) { | > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 | *rPtrPtr = &infoPtr->info; return TCL_OK; } /* * ---------------------------------------------------------------------- * * RenderMethodName -- * * Returns the name of the declared method. Used for producing information * for [info frame]. * * ---------------------------------------------------------------------- */ static Tcl_Obj * RenderMethodName( void *clientData) { ProcedureMethod *pmPtr = (ProcedureMethod *) clientData; if (pmPtr->callSiteFlags & CONSTRUCTOR) { return TclOOGetFoundation(pmPtr->interp)->constructorName; } else if (pmPtr->callSiteFlags & DESTRUCTOR) { return TclOOGetFoundation(pmPtr->interp)->destructorName; } else { return Tcl_MethodName(pmPtr->method); } } /* * ---------------------------------------------------------------------- * * RenderDeclarerName -- * * Returns the name of the entity (object or class) which declared a * method. Used for producing information for [info frame] in such a way * that the expensive part of this (generating the object or class name * itself) isn't done until it is needed. * * ---------------------------------------------------------------------- */ static Tcl_Obj * RenderDeclarerName( void *clientData) { ProcedureMethod *pmPtr = (ProcedureMethod *) clientData; Tcl_Object object = Tcl_MethodDeclarerObject(pmPtr->method); if (object == NULL) { object = Tcl_GetClassAsObject(Tcl_MethodDeclarerClass(pmPtr->method)); } return TclOOObjectName(pmPtr->interp, (Object *) object); } /* * ---------------------------------------------------------------------- * * MethodErrorHandler, ConstructorErrorHandler, DestructorErrorHandler -- * |
︙ | ︙ | |||
1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 | * Create the actual copy of the method record, manufacturing a new proc * record. */ pm2Ptr = (ProcedureMethod *)Tcl_Alloc(sizeof(ProcedureMethod)); memcpy(pm2Ptr, pmPtr, sizeof(ProcedureMethod)); pm2Ptr->refCount = 1; Tcl_IncrRefCount(argsObj); Tcl_IncrRefCount(bodyObj); if (TclCreateProc(interp, NULL, "", argsObj, bodyObj, &pm2Ptr->procPtr) != TCL_OK) { Tcl_DecrRefCount(argsObj); Tcl_DecrRefCount(bodyObj); Tcl_Free(pm2Ptr); | > > | 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 | * Create the actual copy of the method record, manufacturing a new proc * record. */ pm2Ptr = (ProcedureMethod *)Tcl_Alloc(sizeof(ProcedureMethod)); memcpy(pm2Ptr, pmPtr, sizeof(ProcedureMethod)); pm2Ptr->refCount = 1; pm2Ptr->cmd.clientData = &pm2Ptr->efi; pm2Ptr->efi.length = 0; /* Trigger a reinit of this. */ Tcl_IncrRefCount(argsObj); Tcl_IncrRefCount(bodyObj); if (TclCreateProc(interp, NULL, "", argsObj, bodyObj, &pm2Ptr->procPtr) != TCL_OK) { Tcl_DecrRefCount(argsObj); Tcl_DecrRefCount(bodyObj); Tcl_Free(pm2Ptr); |
︙ | ︙ |
Changes to generic/tclObj.c.
︙ | ︙ | |||
345 346 347 348 349 350 351 | * On 32-bit systems, the ref counts do not cross 0x7fffffff. On 64-bit * implementations, ref counts will never reach this value (unless explicitly * incremented without actual references!) */ #define FREEDREFCOUNTFILLER \ (Tcl_Size)(sizeof(objPtr->refCount) == 4 ? 0xe8e8e8e8 : 0xe8e8e8e8e8e8e8e8) #endif | < | 345 346 347 348 349 350 351 352 353 354 355 356 357 358 | * On 32-bit systems, the ref counts do not cross 0x7fffffff. On 64-bit * implementations, ref counts will never reach this value (unless explicitly * incremented without actual references!) */ #define FREEDREFCOUNTFILLER \ (Tcl_Size)(sizeof(objPtr->refCount) == 4 ? 0xe8e8e8e8 : 0xe8e8e8e8e8e8e8e8) #endif /* *------------------------------------------------------------------------- * * TclInitObjectSubsystem -- * * This function is invoked to perform once-only initialization of the |
︙ | ︙ | |||
2564 2565 2566 2567 2568 2569 2570 | } return TCL_ERROR; } *intPtr = (int) l; return TCL_OK; #endif } | < | 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 | } return TCL_ERROR; } *intPtr = (int) l; return TCL_OK; #endif } /* *---------------------------------------------------------------------- * * SetIntFromAny -- * * Attempts to force the internal representation for a Tcl object to |
︙ | ︙ |
Changes to generic/tclPanic.c.
︙ | ︙ | |||
76 77 78 79 80 81 82 | const char *format, ...) { va_list argList; char *arg1, *arg2, *arg3; /* Additional arguments (variable in number) * to pass to fprintf. */ char *arg4, *arg5, *arg6, *arg7, *arg8; | < | 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | const char *format, ...) { va_list argList; char *arg1, *arg2, *arg3; /* Additional arguments (variable in number) * to pass to fprintf. */ char *arg4, *arg5, *arg6, *arg7, *arg8; va_start(argList, format); arg1 = va_arg(argList, char *); arg2 = va_arg(argList, char *); arg3 = va_arg(argList, char *); arg4 = va_arg(argList, char *); arg5 = va_arg(argList, char *); |
︙ | ︙ |
Changes to generic/tclParse.c.
︙ | ︙ | |||
1392 1393 1394 1395 1396 1397 1398 | ch = *src; while (numBytes && (braceCount>0 || ch != '}')) { switch (ch) { case '{': braceCount++; break; case '}': braceCount--; break; case '\\': /* if 2 or more left, consume 2, else consume | | | 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 | ch = *src; while (numBytes && (braceCount>0 || ch != '}')) { switch (ch) { case '{': braceCount++; break; case '}': braceCount--; break; case '\\': /* if 2 or more left, consume 2, else consume * just the \ and let it run into the end */ if (numBytes > 1) { src++; numBytes--; } } numBytes--; src++; ch= *src; |
︙ | ︙ |
Changes to generic/tclPathObj.c.
︙ | ︙ | |||
1515 1516 1517 1518 1519 1520 1521 | Tcl_FSNewNativePath( const Tcl_Filesystem *fromFilesystem, void *clientData) { Tcl_Obj *pathPtr = NULL; FsPath *fsPathPtr; | < | 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 | Tcl_FSNewNativePath( const Tcl_Filesystem *fromFilesystem, void *clientData) { Tcl_Obj *pathPtr = NULL; FsPath *fsPathPtr; if (fromFilesystem->internalToNormalizedProc != NULL) { pathPtr = (*fromFilesystem->internalToNormalizedProc)(clientData); } if (pathPtr == NULL) { return NULL; } |
︙ | ︙ | |||
2685 2686 2687 2688 2689 2690 2691 | /* Paths that cannot be resolved are skipped */ Tcl_ListObjAppendElement(NULL, resolvedPaths, resolvedPath); } } return resolvedPaths; } | < | 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 | /* Paths that cannot be resolved are skipped */ Tcl_ListObjAppendElement(NULL, resolvedPaths, resolvedPath); } } return resolvedPaths; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ |
Changes to generic/tclProc.c.
︙ | ︙ | |||
64 65 66 67 68 69 70 | * Tcl_GetStringFromObj should panic * instead. */ NULL, /* SetFromAny function; Tcl_ConvertToType * should panic instead. */ TCL_OBJTYPE_V0 }; | | | | | | | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | * Tcl_GetStringFromObj should panic * instead. */ NULL, /* SetFromAny function; Tcl_ConvertToType * should panic instead. */ TCL_OBJTYPE_V0 }; #define ProcSetInternalRep(objPtr, procPtr) \ do { \ Tcl_ObjInternalRep ir; \ (procPtr)->refCount++; \ ir.twoPtrValue.ptr1 = (procPtr); \ ir.twoPtrValue.ptr2 = NULL; \ Tcl_StoreInternalRep((objPtr), &tclProcBodyType, &ir); \ } while (0) #define ProcGetInternalRep(objPtr, procPtr) \ do { \ const Tcl_ObjInternalRep *irPtr; \ irPtr = TclFetchInternalRep((objPtr), &tclProcBodyType); \ (procPtr) = irPtr ? (Proc *)irPtr->twoPtrValue.ptr1 : NULL; \ } while (0) /* * The [upvar]/[uplevel] level reference type. Uses the wideValue field * to remember the integer value of a parsed #<integer> format. * * Uses the default behaviour throughout, and never disposes of the string |
︙ | ︙ | |||
111 112 113 114 115 116 117 | FreeLambdaInternalRep, /* freeIntRepProc */ DupLambdaInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ SetLambdaFromAny, /* setFromAnyProc */ TCL_OBJTYPE_V0 }; | | | | | | | | < | 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | FreeLambdaInternalRep, /* freeIntRepProc */ DupLambdaInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ SetLambdaFromAny, /* setFromAnyProc */ TCL_OBJTYPE_V0 }; #define LambdaSetInternalRep(objPtr, procPtr, nsObjPtr) \ do { \ Tcl_ObjInternalRep ir; \ ir.twoPtrValue.ptr1 = (procPtr); \ ir.twoPtrValue.ptr2 = (nsObjPtr); \ Tcl_IncrRefCount((nsObjPtr)); \ Tcl_StoreInternalRep((objPtr), &lambdaType, &ir); \ } while (0) #define LambdaGetInternalRep(objPtr, procPtr, nsObjPtr) \ do { \ const Tcl_ObjInternalRep *irPtr; \ irPtr = TclFetchInternalRep((objPtr), &lambdaType); \ (procPtr) = irPtr ? (Proc *)irPtr->twoPtrValue.ptr1 : NULL; \ (nsObjPtr) = irPtr ? (Tcl_Obj *)irPtr->twoPtrValue.ptr2 : NULL; \ } while (0) /* *---------------------------------------------------------------------- * * Tcl_ProcObjCmd -- * * This object-based function is invoked to process the "proc" Tcl |
︙ | ︙ | |||
151 152 153 154 155 156 157 | */ #undef TclObjInterpProc2 int Tcl_ProcObjCmd( TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ | | | 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | */ #undef TclObjInterpProc2 int Tcl_ProcObjCmd( TCL_UNUSED(void *), Tcl_Interp *interp, /* Current interpreter. */ Tcl_Size objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Interp *iPtr = (Interp *) interp; Proc *procPtr; const char *procName; const char *simpleName, *procArgs, *procBody; Namespace *nsPtr, *altNsPtr, *cxtNsPtr; |
︙ | ︙ | |||
1090 1091 1092 1093 1094 1095 1096 | for (i=1 ; i<=numArgs ; i++, defPtr++) { Tcl_Obj *argObj; Tcl_Obj *namePtr = localName(framePtr, i-1); if (defPtr->value.objPtr != NULL) { TclNewObj(argObj); | | > | 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 | for (i=1 ; i<=numArgs ; i++, defPtr++) { Tcl_Obj *argObj; Tcl_Obj *namePtr = localName(framePtr, i-1); if (defPtr->value.objPtr != NULL) { TclNewObj(argObj); Tcl_AppendStringsToObj(argObj, "?", TclGetString(namePtr), "?", (void *)NULL); } else if (defPtr->flags & VAR_IS_ARGS) { numArgs--; final = "?arg ...?"; break; } else { argObj = namePtr; Tcl_IncrRefCount(namePtr); |
︙ | ︙ | |||
1334 1335 1336 1337 1338 1339 1340 | * are being referenced at runtime. * *---------------------------------------------------------------------- */ static int InitArgsAndLocals( | | | 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 | * are being referenced at runtime. * *---------------------------------------------------------------------- */ static int InitArgsAndLocals( Tcl_Interp *interp, /* Interpreter in which procedure was * invoked. */ size_t skip1) /* Number of initial arguments to be skipped, * i.e., words in the "command name". */ { CallFrame *framePtr = ((Interp *)interp)->varFramePtr; Proc *procPtr = framePtr->procPtr; ByteCode *codePtr; |
︙ | ︙ | |||
1499 1500 1501 1502 1503 1504 1505 | * to be popped by the caller. * *---------------------------------------------------------------------- */ int TclPushProcCallFrame( | | | | 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 | * to be popped by the caller. * *---------------------------------------------------------------------- */ int TclPushProcCallFrame( void *clientData, /* Record describing procedure to be * interpreted. */ Tcl_Interp *interp, /* Interpreter in which procedure was * invoked. */ Tcl_Size objc, /* Count of number of arguments to this * procedure. */ Tcl_Obj *const objv[], /* Argument value objects. */ int isLambda) /* 1 if this is a call by ApplyObjCmd: it * needs special rules for error msg */ { |
︙ | ︙ | |||
1593 1594 1595 1596 1597 1598 1599 | * Depends on the commands in the procedure. * *---------------------------------------------------------------------- */ int TclObjInterpProc2( | | | | | | | 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 | * Depends on the commands in the procedure. * *---------------------------------------------------------------------- */ int TclObjInterpProc2( void *clientData, /* Record describing procedure to be * interpreted. */ Tcl_Interp *interp, /* Interpreter in which procedure was * invoked. */ Tcl_Size objc, /* Count of number of arguments to this * procedure. */ Tcl_Obj *const objv[]) /* Argument value objects. */ { /* * Not used much in the core; external interface for iTcl */ return Tcl_NRCallObjProc2(interp, TclNRInterpProc, clientData, objc, objv); } int TclNRInterpProc( void *clientData, /* Record describing procedure to be * interpreted. */ Tcl_Interp *interp, /* Interpreter in which procedure was * invoked. */ Tcl_Size objc, /* Count of number of arguments to this * procedure. */ Tcl_Obj *const objv[]) /* Argument value objects. */ { int result = TclPushProcCallFrame(clientData, interp, objc, objv, /*isLambda*/ 0); if (result != TCL_OK) { |
︙ | ︙ | |||
1687 1688 1689 1690 1691 1692 1693 | * Nearly anything; depends on the commands in the procedure body. * *---------------------------------------------------------------------- */ int TclNRInterpProcCore( | | | | 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 | * Nearly anything; depends on the commands in the procedure body. * *---------------------------------------------------------------------- */ int TclNRInterpProcCore( Tcl_Interp *interp, /* Interpreter in which procedure was * invoked. */ Tcl_Obj *procNameObj, /* Procedure name for error reporting. */ Tcl_Size skip, /* Number of initial arguments to be skipped, * i.e., words in the "command name". */ ProcErrorProc *errorProc) /* How to convert results from the script into * results of the overall procedure. */ { Interp *iPtr = (Interp *) interp; Proc *procPtr = iPtr->varFramePtr->procPtr; int result; |
︙ | ︙ | |||
2136 2137 2138 2139 2140 2141 2142 | * Memory gets freed. * *---------------------------------------------------------------------- */ void TclProcCleanupProc( | | | 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 | * Memory gets freed. * *---------------------------------------------------------------------- */ void TclProcCleanupProc( Proc *procPtr) /* Procedure to be deleted. */ { CompiledLocal *localPtr; Tcl_Obj *bodyPtr = procPtr->bodyPtr; Tcl_Obj *defPtr; Tcl_ResolvedVarInfo *resVarInfo; Tcl_HashEntry *hePtr = NULL; CmdFrame *cfPtr = NULL; |
︙ | ︙ | |||
2402 2403 2404 2405 2406 2407 2408 | * *---------------------------------------------------------------------- */ static void DupLambdaInternalRep( Tcl_Obj *srcPtr, /* Object with internal rep to copy. */ | | | | | 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 | * *---------------------------------------------------------------------- */ static void DupLambdaInternalRep( Tcl_Obj *srcPtr, /* Object with internal rep to copy. */ Tcl_Obj *copyPtr) /* Object with internal rep to set. */ { Proc *procPtr; Tcl_Obj *nsObjPtr; LambdaGetInternalRep(srcPtr, procPtr, nsObjPtr); assert(procPtr != NULL); procPtr->refCount++; LambdaSetInternalRep(copyPtr, procPtr, nsObjPtr); } static void FreeLambdaInternalRep( Tcl_Obj *objPtr) /* CmdName object with internal representation * to free. */ { Proc *procPtr; Tcl_Obj *nsObjPtr; LambdaGetInternalRep(objPtr, procPtr, nsObjPtr); assert(procPtr != NULL); if (procPtr->refCount-- <= 1) { TclProcCleanupProc(procPtr); } TclDecrRefCount(nsObjPtr); } static int SetLambdaFromAny( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ Tcl_Obj *objPtr) /* The object to convert. */ { Interp *iPtr = (Interp *) interp; const char *name; Tcl_Obj *argsPtr, *bodyPtr, *nsObjPtr, **objv; int isNew, result; Tcl_Size objc; CmdFrame *cfPtr = NULL; |
︙ | ︙ |
Changes to generic/tclProcess.c.
︙ | ︙ | |||
346 347 348 349 350 351 352 | TclNewIntObj(errorStrings[4], resolvedPid); *errorObjPtr = Tcl_NewListObj(5, errorStrings); } return TCL_PROCESS_UNKNOWN_STATUS; } } | < | 346 347 348 349 350 351 352 353 354 355 356 357 358 359 | TclNewIntObj(errorStrings[4], resolvedPid); *errorObjPtr = Tcl_NewListObj(5, errorStrings); } return TCL_PROCESS_UNKNOWN_STATUS; } } /* *---------------------------------------------------------------------- * * BuildProcessStatusObj -- * * Build a list object with process status. The first element is always * a standard Tcl return value, which can be either TCL_OK or TCL_ERROR. |
︙ | ︙ | |||
887 888 889 890 891 892 893 | Tcl_Pid pid, /* Process id. */ int options, /* Options passed to WaitProcessStatus. */ int *codePtr, /* If non-NULL, will receive either: * - 0 for normal exit. * - errno in case of error. * - non-zero exit code for abormal exit. * - signal number if killed or suspended. | | < | 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 | Tcl_Pid pid, /* Process id. */ int options, /* Options passed to WaitProcessStatus. */ int *codePtr, /* If non-NULL, will receive either: * - 0 for normal exit. * - errno in case of error. * - non-zero exit code for abormal exit. * - signal number if killed or suspended. * - Tcl_WaitPid status in all other cases. */ Tcl_Obj **msgObjPtr, /* If non-NULL, will receive error message. */ Tcl_Obj **errorObjPtr) /* If non-NULL, will receive error code. */ { Tcl_HashEntry *entry; ProcessInfo *info; TclProcessWaitStatus result; |
︙ | ︙ |
Changes to generic/tclRegexp.c.
︙ | ︙ | |||
107 108 109 110 111 112 113 | FreeRegexpInternalRep, /* freeIntRepProc */ DupRegexpInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ SetRegexpFromAny, /* setFromAnyProc */ TCL_OBJTYPE_V0 }; | | | | | | < | 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | FreeRegexpInternalRep, /* freeIntRepProc */ DupRegexpInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ SetRegexpFromAny, /* setFromAnyProc */ TCL_OBJTYPE_V0 }; #define RegexpSetInternalRep(objPtr, rePtr) \ do { \ Tcl_ObjInternalRep ir; \ (rePtr)->refCount++; \ ir.twoPtrValue.ptr1 = (rePtr); \ ir.twoPtrValue.ptr2 = NULL; \ Tcl_StoreInternalRep((objPtr), &tclRegexpType, &ir); \ } while (0) #define RegexpGetInternalRep(objPtr, rePtr) \ do { \ const Tcl_ObjInternalRep *irPtr; \ irPtr = TclFetchInternalRep((objPtr), &tclRegexpType); \ (rePtr) = irPtr ? (TclRegexp *)irPtr->twoPtrValue.ptr1 : NULL; \ } while (0) /* *---------------------------------------------------------------------- * * Tcl_RegExpCompile -- * * Compile a regular expression into a form suitable for fast matching. |
︙ | ︙ | |||
219 220 221 222 223 224 225 | /* * Convert the string to Unicode and perform the match. */ Tcl_DStringInit(&ds); ustr = Tcl_UtfToUniCharDString(text, TCL_INDEX_NONE, &ds); numChars = Tcl_DStringLength(&ds) / sizeof(Tcl_UniChar); | | | | 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 | /* * Convert the string to Unicode and perform the match. */ Tcl_DStringInit(&ds); ustr = Tcl_UtfToUniCharDString(text, TCL_INDEX_NONE, &ds); numChars = Tcl_DStringLength(&ds) / sizeof(Tcl_UniChar); result = RegExpExecUniChar(interp, re, ustr, numChars, TCL_INDEX_NONE /* nmatches */, flags); Tcl_DStringFree(&ds); return result; } /* *--------------------------------------------------------------------------- |
︙ | ︙ | |||
302 303 304 305 306 307 308 | static int RegExpExecUniChar( Tcl_Interp *interp, /* Interpreter to use for error reporting. */ Tcl_RegExp re, /* Compiled regular expression; returned by a * previous call to Tcl_GetRegExpFromObj */ const Tcl_UniChar *wString, /* String against which to match re. */ size_t numChars, /* Length of Tcl_UniChar string. */ | | | 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 | static int RegExpExecUniChar( Tcl_Interp *interp, /* Interpreter to use for error reporting. */ Tcl_RegExp re, /* Compiled regular expression; returned by a * previous call to Tcl_GetRegExpFromObj */ const Tcl_UniChar *wString, /* String against which to match re. */ size_t numChars, /* Length of Tcl_UniChar string. */ size_t nm, /* How many subexpression matches (counting * the whole match as subexpression 0) are of * interest. -1 means "don't know". */ int flags) /* Regular expression flags. */ { int status; TclRegexp *regexpPtr = (TclRegexp *) re; size_t last = regexpPtr->re.re_nsub + 1; |
︙ | ︙ | |||
363 364 365 366 367 368 369 | TclRegExpRangeUniChar( Tcl_RegExp re, /* Compiled regular expression that has been * passed to Tcl_RegExpExec. */ Tcl_Size index, /* 0 means give the range of the entire match, * > 0 means give the range of a matching * subrange, -1 means the range of the * rm_extend field. */ | | | | 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 | TclRegExpRangeUniChar( Tcl_RegExp re, /* Compiled regular expression that has been * passed to Tcl_RegExpExec. */ Tcl_Size index, /* 0 means give the range of the entire match, * > 0 means give the range of a matching * subrange, -1 means the range of the * rm_extend field. */ Tcl_Size *startPtr, /* Store address of first character in * (sub-)range here. */ Tcl_Size *endPtr) /* Store address of character just after last * in (sub-)range here. */ { TclRegexp *regexpPtr = (TclRegexp *) re; if ((regexpPtr->flags®_EXPECT) && (index == -1)) { *startPtr = regexpPtr->details.rm_extend.rm_so; *endPtr = regexpPtr->details.rm_extend.rm_eo; |
︙ | ︙ | |||
441 442 443 444 445 446 447 | Tcl_Interp *interp, /* Interpreter to use for error reporting. */ Tcl_RegExp re, /* Compiled regular expression; must have been * returned by previous call to * Tcl_GetRegExpFromObj. */ Tcl_Obj *textObj, /* Text against which to match re. */ Tcl_Size offset, /* Character index that marks where matching * should begin. */ | | | 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 | Tcl_Interp *interp, /* Interpreter to use for error reporting. */ Tcl_RegExp re, /* Compiled regular expression; must have been * returned by previous call to * Tcl_GetRegExpFromObj. */ Tcl_Obj *textObj, /* Text against which to match re. */ Tcl_Size offset, /* Character index that marks where matching * should begin. */ Tcl_Size nmatches, /* How many subexpression matches (counting * the whole match as subexpression 0) are of * interest. -1 means all of them. */ int flags) /* Regular expression execution flags. */ { TclRegexp *regexpPtr = (TclRegexp *) re; Tcl_UniChar *udata; Tcl_Size length; |
︙ | ︙ | |||
855 856 857 858 859 860 861 | *---------------------------------------------------------------------- */ static TclRegexp * CompileRegexp( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ const char *string, /* The regexp to compile (UTF-8). */ | | | 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 | *---------------------------------------------------------------------- */ static TclRegexp * CompileRegexp( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ const char *string, /* The regexp to compile (UTF-8). */ size_t length, /* The length of the string in bytes. */ int flags) /* Compilation flags. */ { TclRegexp *regexpPtr; const Tcl_UniChar *uniString; int numChars, status, i, exact; Tcl_DString stringBuf; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); |
︙ | ︙ |
Changes to generic/tclStrToD.c.
︙ | ︙ | |||
22 23 24 25 26 27 28 | #define copysign _copysign #endif #ifndef PRIx64 # define PRIx64 TCL_LL_MODIFIER "x" #endif | < | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #define copysign _copysign #endif #ifndef PRIx64 # define PRIx64 TCL_LL_MODIFIER "x" #endif /* * This code supports (at least hypothetically), IBM, Cray, VAX and IEEE-754 * floating point; of these, only IEEE-754 can represent NaN. IEEE-754 can be * uniquely determined by radix and by the widths of significand and exponent. */ #if (FLT_RADIX == 2) && (DBL_MANT_DIG == 53) && (DBL_MAX_EXP == 1024) |
︙ | ︙ | |||
4226 4227 4228 4229 4230 4231 4232 | * less - unless we're working in F format - because we know that * three groups of digits will always suffice for %#.17e, the * longest format that doesn't introduce empty precision. * * Extract the next group of digits. */ | < | 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 | * less - unless we're working in F format - because we know that * three groups of digits will always suffice for %#.17e, the * longest format that doesn't introduce empty precision. * * Extract the next group of digits. */ if ((err != MP_OKAY) || (mp_div(&b, &S, &dig, &b) != MP_OKAY) || (dig.used > 1)) { Tcl_Panic("wrong digit!"); } digit = dig.dp[0]; for (j = g-1; j >= 0; --j) { int t = itens[j]; |
︙ | ︙ | |||
4843 4844 4845 4846 4847 4848 4849 | const void *big) /* Integer to convert. */ { mp_int b; int bits, shift, i, lsb; double r; mp_err err; const mp_int *a = (const mp_int *)big; | < | 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 | const void *big) /* Integer to convert. */ { mp_int b; int bits, shift, i, lsb; double r; mp_err err; const mp_int *a = (const mp_int *)big; /* * We need a 'mantBits'-bit significand. Determine what shift will * give us that. */ bits = mp_count_bits(a); |
︙ | ︙ |
Changes to generic/tclStringObj.c.
︙ | ︙ | |||
455 456 457 458 459 460 461 | TclGetString(objPtr); numChars = TclNumUtfChars(objPtr->bytes, objPtr->length); } return numChars; } | < | 455 456 457 458 459 460 461 462 463 464 465 466 467 468 | TclGetString(objPtr); numChars = TclNumUtfChars(objPtr->bytes, objPtr->length); } return numChars; } /* *---------------------------------------------------------------------- * * TclCheckEmptyString -- * * Determine whether the string value of an object is or would be the * empty string, without generating a string representation. |
︙ | ︙ | |||
3515 3516 3517 3518 3519 3520 3521 | * * Side effects: * String representations may be generated. Internal representation may * be changed. * *--------------------------------------------------------------------------- */ | < | 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 | * * Side effects: * String representations may be generated. Internal representation may * be changed. * *--------------------------------------------------------------------------- */ static int UniCharNcasememcmp( const void *ucsPtr, /* Unicode string to compare to uct. */ const void *uctPtr, /* Unicode string ucs is compared to. */ size_t numChars) /* Number of Unichars to compare. */ { |
︙ | ︙ |
Changes to generic/tclStringRep.h.
︙ | ︙ | |||
14 15 16 17 18 19 20 | * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TCLSTRINGREP #define _TCLSTRINGREP | < | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TCLSTRINGREP #define _TCLSTRINGREP /* * The following structure is the internal rep for a String object. It keeps * track of how much memory has been used and how much has been allocated for * the various representations to enable growing and shrinking of * the String object with fewer mallocs. To optimize string * length and indexing operations, this structure also stores the number of * code points (independent of encoding form) once that value has been computed. |
︙ | ︙ |
Changes to generic/tclStubLibTbl.c.
︙ | ︙ | |||
29 30 31 32 33 34 35 | * Side effects: * Sets the stub table pointers. * *---------------------------------------------------------------------- */ MODULE_SCOPE const char * TclInitStubTable( | | | | | | | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | * Side effects: * Sets the stub table pointers. * *---------------------------------------------------------------------- */ MODULE_SCOPE const char * TclInitStubTable( const char *version) /* points to the version field of a * structure variable. */ { if (version) { if (tclStubsHandle == NULL) { /* This can only happen with -DBUILD_STATIC, so simulate * that the loading of Tcl succeeded, although we didn't * actually load it dynamically */ tclStubsHandle = (void *)1; } tclStubsPtr = ((const TclStubs **) version)[-1]; if (tclStubsPtr->hooks) { tclPlatStubsPtr = tclStubsPtr->hooks->tclPlatStubs; tclIntStubsPtr = tclStubsPtr->hooks->tclIntStubs; |
︙ | ︙ |
Changes to generic/tclTest.c.
︙ | ︙ | |||
286 287 288 289 290 291 292 293 294 295 296 297 298 299 | size_t length, int *cflagsPtr, int *eflagsPtr); static Tcl_CmdProc TestsetassocdataCmd; static Tcl_CmdProc TestsetCmd; static Tcl_CmdProc Testset2Cmd; static Tcl_CmdProc TestseterrorcodeCmd; static Tcl_ObjCmdProc2 TestsetobjerrorcodeCmd; static Tcl_CmdProc TestsetplatformCmd; static Tcl_CmdProc TeststaticlibraryCmd; static Tcl_CmdProc TesttranslatefilenameCmd; static Tcl_CmdProc TestupvarCmd; static Tcl_ObjCmdProc2 TestWrongNumArgsObjCmd; static Tcl_ObjCmdProc2 TestGetIndexFromObjStructObjCmd; static Tcl_CmdProc TestChannelCmd; static Tcl_CmdProc TestChannelEventCmd; | > | 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 | size_t length, int *cflagsPtr, int *eflagsPtr); static Tcl_CmdProc TestsetassocdataCmd; static Tcl_CmdProc TestsetCmd; static Tcl_CmdProc Testset2Cmd; static Tcl_CmdProc TestseterrorcodeCmd; static Tcl_ObjCmdProc2 TestsetobjerrorcodeCmd; static Tcl_CmdProc TestsetplatformCmd; static Tcl_ObjCmdProc TestSizeCmd; static Tcl_CmdProc TeststaticlibraryCmd; static Tcl_CmdProc TesttranslatefilenameCmd; static Tcl_CmdProc TestupvarCmd; static Tcl_ObjCmdProc2 TestWrongNumArgsObjCmd; static Tcl_ObjCmdProc2 TestGetIndexFromObjStructObjCmd; static Tcl_CmdProc TestChannelCmd; static Tcl_CmdProc TestChannelEventCmd; |
︙ | ︙ | |||
693 694 695 696 697 698 699 700 701 702 703 704 705 706 | TestFindFirstCmd, NULL, NULL); Tcl_CreateObjCommand2(interp, "testfindlast", TestFindLastCmd, NULL, NULL); Tcl_CreateObjCommand2(interp, "testgetintforindex", TestGetIntForIndexCmd, NULL, NULL); Tcl_CreateCommand(interp, "testsetplatform", TestsetplatformCmd, NULL, NULL); Tcl_CreateCommand(interp, "testsocket", TestSocketCmd, NULL, NULL); Tcl_CreateCommand(interp, "teststaticlibrary", TeststaticlibraryCmd, NULL, NULL); Tcl_CreateCommand(interp, "testtranslatefilename", TesttranslatefilenameCmd, NULL, NULL); Tcl_CreateCommand(interp, "testupvar", TestupvarCmd, NULL, NULL); | > | 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 | TestFindFirstCmd, NULL, NULL); Tcl_CreateObjCommand2(interp, "testfindlast", TestFindLastCmd, NULL, NULL); Tcl_CreateObjCommand2(interp, "testgetintforindex", TestGetIntForIndexCmd, NULL, NULL); Tcl_CreateCommand(interp, "testsetplatform", TestsetplatformCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testsize", TestSizeCmd, NULL, NULL); Tcl_CreateCommand(interp, "testsocket", TestSocketCmd, NULL, NULL); Tcl_CreateCommand(interp, "teststaticlibrary", TeststaticlibraryCmd, NULL, NULL); Tcl_CreateCommand(interp, "testtranslatefilename", TesttranslatefilenameCmd, NULL, NULL); Tcl_CreateCommand(interp, "testupvar", TestupvarCmd, NULL, NULL); |
︙ | ︙ | |||
4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 | } else { Tcl_AppendResult(interp, "unsupported platform: should be one of " "unix, or windows", (char *)NULL); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * TeststaticlibraryCmd -- * * This procedure implements the "teststaticlibrary" command. | > > > > > > > > > > > > > > > > > > > > > | 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 | } else { Tcl_AppendResult(interp, "unsupported platform: should be one of " "unix, or windows", (char *)NULL); return TCL_ERROR; } return TCL_OK; } static int TestSizeCmd( TCL_UNUSED(void *), /* Unused */ Tcl_Interp* interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const * objv) /* Parameter vector */ { if (objc != 2) { goto syntax; } if (strcmp(Tcl_GetString(objv[1]), "st_mtime") == 0) { Tcl_StatBuf *statPtr; Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sizeof(statPtr->st_mtime))); return TCL_OK; } syntax: Tcl_WrongNumArgs(interp, 1, objv, "st_mtime"); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TeststaticlibraryCmd -- * * This procedure implements the "teststaticlibrary" command. |
︙ | ︙ |
Changes to generic/tclThread.c.
︙ | ︙ | |||
140 141 142 143 144 145 146 | static void RememberSyncObject( void *objPtr, /* Pointer to sync object */ SyncObjRecord *recPtr) /* Record of sync objects */ { void **newList; int i, j; | < | 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | static void RememberSyncObject( void *objPtr, /* Pointer to sync object */ SyncObjRecord *recPtr) /* Record of sync objects */ { void **newList; int i, j; /* * Reuse any free slot in the list. */ for (i=0 ; i < recPtr->num ; ++i) { if (recPtr->list[i] == NULL) { |
︙ | ︙ |
Changes to generic/tclTomMathStubLib.c.
︙ | ︙ | |||
13 14 15 16 17 18 19 | #include "tclInt.h" #include "tclTomMath.h" MODULE_SCOPE const TclTomMathStubs *tclTomMathStubsPtr; const TclTomMathStubs *tclTomMathStubsPtr = NULL; | < | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #include "tclInt.h" #include "tclTomMath.h" MODULE_SCOPE const TclTomMathStubs *tclTomMathStubsPtr; const TclTomMathStubs *tclTomMathStubsPtr = NULL; /* *---------------------------------------------------------------------- * * TclTomMathInitStubs -- * * Initializes the Stubs table for Tcl's subset of libtommath |
︙ | ︙ |
Changes to generic/tclTrace.c.
︙ | ︙ | |||
1011 1012 1013 1014 1015 1016 1017 | if ((cmdPtr->compileProc != NULL) && !(cmdPtr->flags & CMD_HAS_EXEC_TRACES)){ Interp *iPtr = (Interp *) interp; iPtr->compileEpoch++; } cmdPtr->flags |= CMD_HAS_EXEC_TRACES; } | < | 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 | if ((cmdPtr->compileProc != NULL) && !(cmdPtr->flags & CMD_HAS_EXEC_TRACES)){ Interp *iPtr = (Interp *) interp; iPtr->compileEpoch++; } cmdPtr->flags |= CMD_HAS_EXEC_TRACES; } return TCL_OK; } /* *---------------------------------------------------------------------- * |
︙ | ︙ |
Changes to generic/tclUtf.c.
︙ | ︙ | |||
1713 1714 1715 1716 1717 1718 1719 | ct += TclUtfToUniChar(ct, &ch2); if (ch1 != ch2) { return ch1 - ch2; } } return UCHAR(*cs) - UCHAR(*ct); } | < | 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 | ct += TclUtfToUniChar(ct, &ch2); if (ch1 != ch2) { return ch1 - ch2; } } return UCHAR(*cs) - UCHAR(*ct); } /* *---------------------------------------------------------------------- * * TclUtfCasecmp -- * * Compare UTF chars of string cs to string ct case insensitively. |
︙ | ︙ | |||
1753 1754 1755 1756 1757 1758 1759 | if (ch1 != ch2) { return ch1 - ch2; } } } return UCHAR(*cs) - UCHAR(*ct); } | < | 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 | if (ch1 != ch2) { return ch1 - ch2; } } } return UCHAR(*cs) - UCHAR(*ct); } /* *---------------------------------------------------------------------- * * Tcl_UniCharToUpper -- * * Compute the uppercase equivalent of the given Unicode character. |
︙ | ︙ |
Changes to generic/tclUtil.c.
︙ | ︙ | |||
2594 2595 2596 2597 2598 2599 2600 | *---------------------------------------------------------------------- */ char * Tcl_DStringAppend( Tcl_DString *dsPtr, /* Structure describing dynamic string. */ const char *bytes, /* String to append. If length is | | > | | < | 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 | *---------------------------------------------------------------------- */ char * Tcl_DStringAppend( Tcl_DString *dsPtr, /* Structure describing dynamic string. */ const char *bytes, /* String to append. If length is * TCL_INDEX_NONE then this must be * null-terminated. */ Tcl_Size length) /* Number of bytes from "bytes" to append. If * TCL_INDEX_NONE, then append all of bytes, up * to null at end. */ { Tcl_Size newSize; if (length < 0) { length = strlen(bytes); } if (length > (TCL_SIZE_MAX - dsPtr->length - 1)) { Tcl_Panic("max size for a Tcl value (%" TCL_SIZE_MODIFIER "d bytes) exceeded", TCL_SIZE_MAX); return NULL; /* NOTREACHED */ } newSize = length + dsPtr->length + 1; if (newSize > dsPtr->spaceAvl) { if (dsPtr->string == dsPtr->staticSpace) { char *newString; newString = (char *) TclAllocEx(newSize, &dsPtr->spaceAvl); memcpy(newString, dsPtr->string, dsPtr->length); dsPtr->string = newString; |
︙ | ︙ |
Changes to generic/tclZipfs.c.
︙ | ︙ | |||
213 214 215 216 217 218 219 | */ typedef struct ZipEntry { char *name; /* The full pathname of the virtual file */ ZipFile *zipFilePtr; /* The ZIP file holding this virtual file */ size_t offset; /* Data offset into memory mapped ZIP file */ int numBytes; /* Uncompressed size of the virtual file. | | | | 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 | */ typedef struct ZipEntry { char *name; /* The full pathname of the virtual file */ ZipFile *zipFilePtr; /* The ZIP file holding this virtual file */ size_t offset; /* Data offset into memory mapped ZIP file */ int numBytes; /* Uncompressed size of the virtual file. * -1 for zip64 */ int numCompressedBytes; /* Compressed size of the virtual file. * -1 for zip64 */ int compressMethod; /* Compress method */ int isDirectory; /* 0 if file, 1 if directory, -1 if root */ int depth; /* Number of slashes in path. */ int crc32; /* CRC-32 as stored in ZIP */ int timestamp; /* Modification time */ int isEncrypted; /* True if data is encrypted */ int flags; |
︙ | ︙ | |||
806 807 808 809 810 811 812 | * Side effects: * On success, keys[] are updated. On failure, an error message is * left in interp if not NULL. * *------------------------------------------------------------------------ */ static int | | > | | | | > | 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 | * Side effects: * On success, keys[] are updated. On failure, an error message is * left in interp if not NULL. * *------------------------------------------------------------------------ */ static int DecodeCryptHeader( Tcl_Interp *interp, ZipEntry *z, unsigned long keys[3], /* Updated on success. Must have been * initialized by caller. */ unsigned char cryptHeader[ZIP_CRYPT_HDR_LEN]) /* From zip file content */ { int i; int ch; int len = z->zipFilePtr->passBuf[0] & 0xFF; char passBuf[260]; for (i = 0; i < len; i++) { |
︙ | ︙ | |||
1061 1062 1063 1064 1065 1066 1067 | * * Side effects: * Stores mapped path in dsPtr. * *------------------------------------------------------------------------ */ static char * | | > | | | | | 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 | * * Side effects: * Stores mapped path in dsPtr. * *------------------------------------------------------------------------ */ static char * MapPathToZipfs( Tcl_Interp *interp, const char *mountPath, /* Must be fully normalized */ const char *path, /* Archive content path to map */ Tcl_DString *dsPtr) /* Must be initialized and cleared * by caller */ { const char *joiner[2]; char *joinedPath; Tcl_Obj *unnormalizedObj; Tcl_Obj *normalizedObj; const char *normalizedPath; Tcl_Size normalizedLen; |
︙ | ︙ |
Changes to generic/tclZlib.c.
︙ | ︙ | |||
29 30 31 32 33 34 35 | #define TCL_ZLIB_VERSION "2.0.1" /* * Magic flags used with wbits fields to indicate that we're handling the gzip * format or automatic detection of format. Putting it here is slightly less * gross! */ | | | | | | > | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | #define TCL_ZLIB_VERSION "2.0.1" /* * Magic flags used with wbits fields to indicate that we're handling the gzip * format or automatic detection of format. Putting it here is slightly less * gross! */ enum WBitsFlags { WBITS_RAW = (-MAX_WBITS), /* RAW compressed data */ WBITS_ZLIB = (MAX_WBITS), /* Zlib-format compressed data */ WBITS_GZIP = (MAX_WBITS | 16), /* Gzip-format compressed data */ WBITS_AUTODETECT = (MAX_WBITS | 32) /* Auto-detect format from its header */ }; /* * Structure used for handling gzip headers that are generated from a * dictionary. It comprises the header structure itself plus some working * space that it is very convenient to have attached. */ |
︙ | ︙ | |||
60 61 62 63 64 65 66 | typedef struct { Tcl_Interp *interp; z_stream stream; /* The interface to the zlib library. */ int streamEnd; /* If we've got to end-of-stream. */ Tcl_Obj *inData, *outData; /* Input / output buffers (lists) */ Tcl_Obj *currentInput; /* Pointer to what is currently being * inflated. */ | | > | > | 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | typedef struct { Tcl_Interp *interp; z_stream stream; /* The interface to the zlib library. */ int streamEnd; /* If we've got to end-of-stream. */ Tcl_Obj *inData, *outData; /* Input / output buffers (lists) */ Tcl_Obj *currentInput; /* Pointer to what is currently being * inflated. */ Tcl_Size outPos; /* Index into output buffer to write to next. */ int mode; /* Either TCL_ZLIB_STREAM_DEFLATE or * TCL_ZLIB_STREAM_INFLATE. */ int format; /* Flags from the TCL_ZLIB_FORMAT_* */ int level; /* Default 5, 0-9 */ int flush; /* Stores the flush param for deferred the * decompression. */ int wbits; /* The encoded compression mode, so we can * restart the stream if necessary. */ Tcl_Command cmd; /* Token for the associated Tcl command. */ Tcl_Obj *compDictObj; /* Byte-array object containing compression * dictionary (not dictObj!) to use if * necessary. */ int flags; /* Miscellaneous flag bits. */ GzipHeader *gzHeaderPtr; /* If we've allocated a gzip header * structure. */ } ZlibStreamHandle; enum ZlibStreamHandleFlags { DICT_TO_SET = 0x1 /* If we need to set a compression dictionary * in the low-level engine at the next * opportunity. */ }; /* * Macros to make it clearer in some of the twiddlier accesses what is * happening. */ #define IsRawStream(zshPtr) ((zshPtr)->format == TCL_ZLIB_FORMAT_RAW) |
︙ | ︙ | |||
126 127 128 129 130 131 132 | Tcl_TimerToken timer; /* Timer used for keeping events fresh. */ Tcl_Obj *compDictObj; /* Byte-array object containing compression * dictionary (not dictObj!) to use if * necessary. */ } ZlibChannelData; /* | | > > | | | | | | | | | < < < < < | 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | Tcl_TimerToken timer; /* Timer used for keeping events fresh. */ Tcl_Obj *compDictObj; /* Byte-array object containing compression * dictionary (not dictObj!) to use if * necessary. */ } ZlibChannelData; /* * Value bits for the ZlibChannelData::flags field. */ enum ZlibChannelDataFlags { ASYNC = 0x01, /* Set if this is an asynchronous channel. */ IN_HEADER = 0x02, /* Set if the inHeader field has been * registered with the input compressor. */ OUT_HEADER = 0x04, /* Set if the outputHeader field has been * registered with the output decompressor. */ STREAM_DECOMPRESS = 0x08, /* Set to signal decompress pending data. */ STREAM_DONE = 0x10 /* Set to signal stream end up to transform * input. */ }; /* * Size of buffers allocated by default, and the range it can be set to. The * same sorts of values apply to streams, except with different limits (they * permit byte-level activity). Channels always use bytes unless told to use * larger buffers. */ |
︙ | ︙ | |||
183 184 185 186 187 188 189 | static inline int Deflate(z_streamp strm, void *bufferPtr, size_t bufferSize, int flush, size_t *writtenPtr); static void ExtractHeader(gz_header *headerPtr, Tcl_Obj *dictObj); static int GenerateHeader(Tcl_Interp *interp, Tcl_Obj *dictObj, GzipHeader *headerPtr, int *extraSizePtr); static int ZlibPushSubcmd(Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); | | > | | > | | 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 | static inline int Deflate(z_streamp strm, void *bufferPtr, size_t bufferSize, int flush, size_t *writtenPtr); static void ExtractHeader(gz_header *headerPtr, Tcl_Obj *dictObj); static int GenerateHeader(Tcl_Interp *interp, Tcl_Obj *dictObj, GzipHeader *headerPtr, int *extraSizePtr); static int ZlibPushSubcmd(Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static int ResultDecompress(ZlibChannelData *chanDataPtr, char *buf, int toRead, int flush, int *errorCodePtr); static Tcl_Channel ZlibStackChannelTransform(Tcl_Interp *interp, int mode, int format, int level, int limit, Tcl_Channel channel, Tcl_Obj *gzipHeaderDictPtr, Tcl_Obj *compDictObj); static void ZlibStreamCleanup(ZlibStreamHandle *zshPtr); static int ZlibStreamSubcmd(Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]); static inline void ZlibTransformEventTimerKill( ZlibChannelData *chanDataPtr); static void ZlibTransformTimerRun(void *clientData); /* * Type of zlib-based compressing and decompressing channels. */ static const Tcl_ChannelType zlibChannelType = { "zlib", TCL_CHANNEL_VERSION_5, NULL, ZlibTransformInput, ZlibTransformOutput, NULL, /* seekProc */ ZlibTransformSetOption, ZlibTransformGetOption, ZlibTransformWatch, ZlibTransformGetHandle, ZlibTransformClose, /* close2Proc */ ZlibTransformBlockMode, NULL, /* flushProc */ ZlibTransformEventHandler, NULL, /* wideSeekProc */ NULL, NULL }; |
︙ | ︙ | |||
258 259 260 261 262 263 264 | * Firstly, the case that is *different* because it's really coming * from the OS and is just being reported via zlib. It should be * really uncommon because Tcl handles all I/O rather than delegating * it to zlib, but proving it can't happen is hard. */ case Z_ERRNO: | | > | 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 | * Firstly, the case that is *different* because it's really coming * from the OS and is just being reported via zlib. It should be * really uncommon because Tcl handles all I/O rather than delegating * it to zlib, but proving it can't happen is hard. */ case Z_ERRNO: Tcl_SetObjResult(interp, Tcl_NewStringObj( Tcl_PosixError(interp), TCL_AUTO_LENGTH)); return; /* * Normal errors/conditions, some of which have additional detail and * some which don't. (This is not defined by array lookup because zlib * error codes are sometimes negative.) */ |
︙ | ︙ | |||
309 310 311 312 313 314 315 | default: codeStr = "UNKNOWN"; codeStr2 = codeStrBuf; snprintf(codeStrBuf, sizeof(codeStrBuf), "%d", code); break; } | | | 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 | default: codeStr = "UNKNOWN"; codeStr2 = codeStrBuf; snprintf(codeStrBuf, sizeof(codeStrBuf), "%d", code); break; } Tcl_SetObjResult(interp, Tcl_NewStringObj(zError(code), TCL_AUTO_LENGTH)); /* * Tricky point! We might pass NULL twice here (and will when the error * type is known). */ Tcl_SetErrorCode(interp, "TCL", "ZLIB", codeStr, codeStr2, (char *)NULL); |
︙ | ︙ | |||
346 347 348 349 350 351 352 | TclNewLiteralStringObj(objv[2], "BUF"); return Tcl_NewListObj(3, objv); case Z_VERSION_ERROR: TclNewLiteralStringObj(objv[2], "VERSION"); return Tcl_NewListObj(3, objv); case Z_ERRNO: TclNewLiteralStringObj(objv[2], "POSIX"); | | | | 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 | TclNewLiteralStringObj(objv[2], "BUF"); return Tcl_NewListObj(3, objv); case Z_VERSION_ERROR: TclNewLiteralStringObj(objv[2], "VERSION"); return Tcl_NewListObj(3, objv); case Z_ERRNO: TclNewLiteralStringObj(objv[2], "POSIX"); objv[3] = Tcl_NewStringObj(Tcl_ErrnoId(), TCL_AUTO_LENGTH); return Tcl_NewListObj(4, objv); case Z_NEED_DICT: TclNewLiteralStringObj(objv[2], "NEED_DICT"); TclNewIntObj(objv[3], (Tcl_WideInt) adler); return Tcl_NewListObj(4, objv); /* * These should _not_ happen! This function is for dealing with error * cases, not non-errors! */ |
︙ | ︙ | |||
401 402 403 404 405 406 407 | static inline int GetValue( Tcl_Interp *interp, Tcl_Obj *dictObj, const char *nameStr, Tcl_Obj **valuePtrPtr) { | | > > > > > > > > > > > > > | < < < < < < < < < | | | | | | > | | 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 | static inline int GetValue( Tcl_Interp *interp, Tcl_Obj *dictObj, const char *nameStr, Tcl_Obj **valuePtrPtr) { Tcl_Obj *name = Tcl_NewStringObj(nameStr, TCL_AUTO_LENGTH); int result = Tcl_DictObjGet(interp, dictObj, name, valuePtrPtr); TclDecrRefCount(name); return result; } /* * RFC 1952 says that header strings are in ISO 8859-1 (LATIN-1). */ static inline Tcl_Encoding Latin1(void) { Tcl_Encoding latin1enc = Tcl_GetEncoding(NULL, "iso8859-1"); if (latin1enc == NULL) { Tcl_Panic("no latin-1 encoding"); } return latin1enc; } static int GenerateHeader( Tcl_Interp *interp, /* Where to put error messages. */ Tcl_Obj *dictObj, /* The dictionary whose contents are to be * parsed. */ GzipHeader *headerPtr, /* Where to store the parsed-out values. */ int *extraSizePtr) /* Variable to add the length of header * strings (filename, comment) to. */ { Tcl_Obj *value; int len, result = TCL_ERROR; Tcl_Size length; Tcl_WideInt wideValue = 0; const char *valueStr; Tcl_Encoding latin1enc = Latin1(); static const char *const types[] = { "binary", "text" }; if (GetValue(interp, dictObj, "comment", &value) != TCL_OK) { goto error; } else if (value != NULL) { Tcl_EncodingState state; valueStr = TclGetStringFromObj(value, &length); result = Tcl_UtfToExternal(NULL, latin1enc, valueStr, length, TCL_ENCODING_START|TCL_ENCODING_END|TCL_ENCODING_PROFILE_STRICT, &state, headerPtr->nativeCommentBuf, MAX_COMMENT_LEN - 1, NULL, &len, NULL); if (result != TCL_OK) { if (interp) { if (result == TCL_CONVERT_UNKNOWN) { Tcl_AppendResult(interp, "Comment contains characters > 0xFF", (char *)NULL); } else { Tcl_AppendResult(interp, "Comment too large for zip", (char *)NULL); } } result = TCL_ERROR; /* TCL_CONVERT_* -> TCL_ERROR */ goto error; } headerPtr->nativeCommentBuf[len] = '\0'; headerPtr->header.comment = (Bytef *) headerPtr->nativeCommentBuf; if (extraSizePtr != NULL) { *extraSizePtr += len; } |
︙ | ︙ | |||
477 478 479 480 481 482 483 | if (GetValue(interp, dictObj, "filename", &value) != TCL_OK) { goto error; } else if (value != NULL) { Tcl_EncodingState state; valueStr = TclGetStringFromObj(value, &length); result = Tcl_UtfToExternal(NULL, latin1enc, valueStr, length, | | | | | | | | | | 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 | if (GetValue(interp, dictObj, "filename", &value) != TCL_OK) { goto error; } else if (value != NULL) { Tcl_EncodingState state; valueStr = TclGetStringFromObj(value, &length); result = Tcl_UtfToExternal(NULL, latin1enc, valueStr, length, TCL_ENCODING_START|TCL_ENCODING_END|TCL_ENCODING_PROFILE_STRICT, &state, headerPtr->nativeFilenameBuf, MAXPATHLEN - 1, NULL, &len, NULL); if (result != TCL_OK) { if (interp) { if (result == TCL_CONVERT_UNKNOWN) { Tcl_AppendResult(interp, "Filename contains characters > 0xFF", (char *)NULL); } else { Tcl_AppendResult(interp, "Filename too large for zip", (char *)NULL); } } result = TCL_ERROR; /* TCL_CONVERT_* -> TCL_ERROR */ goto error; } headerPtr->nativeFilenameBuf[len] = '\0'; headerPtr->header.name = (Bytef *) headerPtr->nativeFilenameBuf; if (extraSizePtr != NULL) { *extraSizePtr += len; } |
︙ | ︙ | |||
551 552 553 554 555 556 557 | * Side effects: * Updates the dictionary, which must be writable (i.e. refCount < 2). * *---------------------------------------------------------------------- */ #define SetValue(dictObj, key, value) \ | | > < < < < | < < | | < | | < < < < | < < | | < | | | | | 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 | * Side effects: * Updates the dictionary, which must be writable (i.e. refCount < 2). * *---------------------------------------------------------------------- */ #define SetValue(dictObj, key, value) \ Tcl_DictObjPut(NULL, (dictObj), Tcl_NewStringObj( \ (key), TCL_AUTO_LENGTH), (value)) static void ExtractHeader( gz_header *headerPtr, /* The gzip header to extract from. */ Tcl_Obj *dictObj) /* The dictionary to store in. */ { Tcl_Encoding latin1enc = NULL; Tcl_DString tmp; if (headerPtr->comment != Z_NULL) { if (latin1enc == NULL) { latin1enc = Latin1(); } (void) Tcl_ExternalToUtfDString(latin1enc, (char *) headerPtr->comment, TCL_AUTO_LENGTH, &tmp); SetValue(dictObj, "comment", Tcl_DStringToObj(&tmp)); } SetValue(dictObj, "crc", Tcl_NewBooleanObj(headerPtr->hcrc)); if (headerPtr->name != Z_NULL) { if (latin1enc == NULL) { latin1enc = Latin1(); } (void) Tcl_ExternalToUtfDString(latin1enc, (char *) headerPtr->name, TCL_AUTO_LENGTH, &tmp); SetValue(dictObj, "filename", Tcl_DStringToObj(&tmp)); } if (headerPtr->os != 255) { SetValue(dictObj, "os", Tcl_NewWideIntObj(headerPtr->os)); } if (headerPtr->time != 0 /* magic - no time */) { SetValue(dictObj, "time", Tcl_NewWideIntObj(headerPtr->time)); } if (headerPtr->text != Z_UNKNOWN) { SetValue(dictObj, "type", Tcl_NewStringObj( headerPtr->text ? "text" : "binary", TCL_AUTO_LENGTH)); } if (latin1enc != NULL) { Tcl_FreeEncoding(latin1enc); } } |
︙ | ︙ | |||
656 657 658 659 660 661 662 | Deflate( z_streamp strm, void *bufferPtr, size_t bufferSize, int flush, size_t *writtenPtr) { | < < | | 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 | Deflate( z_streamp strm, void *bufferPtr, size_t bufferSize, int flush, size_t *writtenPtr) { strm->next_out = (Bytef *) bufferPtr; strm->avail_out = bufferSize; int e = deflate(strm, flush); if (writtenPtr != NULL) { *writtenPtr = bufferSize - strm->avail_out; } return e; } static inline void |
︙ | ︙ | |||
733 734 735 736 737 738 739 | switch (format) { case TCL_ZLIB_FORMAT_RAW: wbits = WBITS_RAW; break; case TCL_ZLIB_FORMAT_GZIP: wbits = WBITS_GZIP; if (dictObj) { | | | 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 | switch (format) { case TCL_ZLIB_FORMAT_RAW: wbits = WBITS_RAW; break; case TCL_ZLIB_FORMAT_GZIP: wbits = WBITS_GZIP; if (dictObj) { gzHeaderPtr = (GzipHeader *) Tcl_Alloc(sizeof(GzipHeader)); memset(gzHeaderPtr, 0, sizeof(GzipHeader)); if (GenerateHeader(interp, dictObj, gzHeaderPtr, NULL) != TCL_OK) { Tcl_Free(gzHeaderPtr); return TCL_ERROR; } } |
︙ | ︙ | |||
767 768 769 770 771 772 773 | switch (format) { case TCL_ZLIB_FORMAT_RAW: wbits = WBITS_RAW; break; case TCL_ZLIB_FORMAT_GZIP: wbits = WBITS_GZIP; | | | 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 | switch (format) { case TCL_ZLIB_FORMAT_RAW: wbits = WBITS_RAW; break; case TCL_ZLIB_FORMAT_GZIP: wbits = WBITS_GZIP; gzHeaderPtr = (GzipHeader *) Tcl_Alloc(sizeof(GzipHeader)); memset(gzHeaderPtr, 0, sizeof(GzipHeader)); gzHeaderPtr->header.name = (Bytef *) gzHeaderPtr->nativeFilenameBuf; gzHeaderPtr->header.name_max = MAXPATHLEN - 1; gzHeaderPtr->header.comment = (Bytef *) gzHeaderPtr->nativeCommentBuf; gzHeaderPtr->header.name_max = MAX_COMMENT_LEN - 1; |
︙ | ︙ | |||
793 794 795 796 797 798 799 | } break; default: Tcl_Panic("bad mode, must be TCL_ZLIB_STREAM_DEFLATE or" " TCL_ZLIB_STREAM_INFLATE"); } | | | 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 | } break; default: Tcl_Panic("bad mode, must be TCL_ZLIB_STREAM_DEFLATE or" " TCL_ZLIB_STREAM_INFLATE"); } zshPtr = (ZlibStreamHandle *) Tcl_Alloc(sizeof(ZlibStreamHandle)); zshPtr->interp = interp; zshPtr->mode = mode; zshPtr->format = format; zshPtr->level = level; zshPtr->wbits = wbits; zshPtr->currentInput = NULL; zshPtr->streamEnd = 0; |
︙ | ︙ | |||
836 837 838 839 840 841 842 | } /* * I could do all this in C, but this is easier. */ if (interp != NULL) { | | > | | 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 | } /* * I could do all this in C, but this is easier. */ if (interp != NULL) { if (Tcl_EvalEx(interp, "::incr ::tcl::zlib::cmdcounter", TCL_AUTO_LENGTH, 0) != TCL_OK) { goto error; } Tcl_DStringInit(&cmdname); TclDStringAppendLiteral(&cmdname, "::tcl::zlib::streamcmd_"); TclDStringAppendObj(&cmdname, Tcl_GetObjResult(interp)); if (Tcl_FindCommand(interp, Tcl_DStringValue(&cmdname), NULL, 0) != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "BUG: Stream command name already exists", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "TCL", "BUG", "EXISTING_CMD", (char *)NULL); Tcl_DStringFree(&cmdname); goto error; } Tcl_ResetResult(interp); /* |
︙ | ︙ | |||
918 919 920 921 922 923 924 | * Invalidates the zlib stream handle as obtained from Tcl_ZlibStreamInit * *---------------------------------------------------------------------- */ static void ZlibStreamCmdDelete( | | | | 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 | * Invalidates the zlib stream handle as obtained from Tcl_ZlibStreamInit * *---------------------------------------------------------------------- */ static void ZlibStreamCmdDelete( void *clientData) { ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) clientData; zshPtr->cmd = NULL; ZlibStreamCleanup(zshPtr); } /* *---------------------------------------------------------------------- |
︙ | ︙ | |||
1237 1238 1239 1240 1241 1242 1243 | Tcl_Size size = 0; size_t outSize, toStore; unsigned char *bytes; if (zshPtr->streamEnd) { if (zshPtr->interp) { Tcl_SetObjResult(zshPtr->interp, Tcl_NewStringObj( | | | 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 | Tcl_Size size = 0; size_t outSize, toStore; unsigned char *bytes; if (zshPtr->streamEnd) { if (zshPtr->interp) { Tcl_SetObjResult(zshPtr->interp, Tcl_NewStringObj( "already past compressed stream end", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(zshPtr->interp, "TCL", "ZIP", "CLOSED", (char *)NULL); } return TCL_ERROR; } bytes = Tcl_GetBytesFromObj(zshPtr->interp, data, &size); if (bytes == NULL) { |
︙ | ︙ | |||
1280 1281 1282 1283 1284 1285 1286 | * size. */ outSize = deflateBound(&zshPtr->stream, size) + 100; if (outSize > BUFFER_SIZE_LIMIT) { outSize = BUFFER_SIZE_LIMIT; } | | | 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 | * size. */ outSize = deflateBound(&zshPtr->stream, size) + 100; if (outSize > BUFFER_SIZE_LIMIT) { outSize = BUFFER_SIZE_LIMIT; } dataTmp = (char *) Tcl_Alloc(outSize); while (1) { e = Deflate(&zshPtr->stream, dataTmp, outSize, flush, &toStore); /* * Test if we've filled the buffer up and have to ask deflate() to * give us some more. Note that the condition for needing to |
︙ | ︙ | |||
1314 1315 1316 1317 1318 1319 1320 | */ AppendByteArray(zshPtr->outData, dataTmp, outSize); if (outSize < BUFFER_SIZE_LIMIT) { outSize = BUFFER_SIZE_LIMIT; /* There may be *lots* of data left to output... */ | | | 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 | */ AppendByteArray(zshPtr->outData, dataTmp, outSize); if (outSize < BUFFER_SIZE_LIMIT) { outSize = BUFFER_SIZE_LIMIT; /* There may be *lots* of data left to output... */ dataTmp = (char *) Tcl_Realloc(dataTmp, outSize); } } /* * And append the final data block to the outData list. */ |
︙ | ︙ | |||
1356 1357 1358 1359 1360 1361 1362 | *---------------------------------------------------------------------- */ int Tcl_ZlibStreamGet( Tcl_ZlibStream zshandle, /* As obtained from Tcl_ZlibStreamInit */ Tcl_Obj *data, /* A place to append the data. */ | | | 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 | *---------------------------------------------------------------------- */ int Tcl_ZlibStreamGet( Tcl_ZlibStream zshandle, /* As obtained from Tcl_ZlibStreamInit */ Tcl_Obj *data, /* A place to append the data. */ Tcl_Size count) /* Number of bytes to grab as a maximum, you * may get less! */ { ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) zshandle; int e; Tcl_Size listLen, i, itemLen = 0, dataPos = 0; Tcl_Obj *itemObj; unsigned char *dataPtr, *itemPtr; |
︙ | ︙ | |||
1392 1393 1394 1395 1396 1397 1398 | count = MAX_BUFFER_SIZE; } /* * Prepare the place to store the data. */ | | | 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 | count = MAX_BUFFER_SIZE; } /* * Prepare the place to store the data. */ dataPtr = Tcl_SetByteArrayLength(data, existing + count); dataPtr += existing; zshPtr->stream.next_out = dataPtr; zshPtr->stream.avail_out = count; if (zshPtr->stream.avail_in == 0) { /* * zlib will probably need more data to decompress. |
︙ | ︙ | |||
1468 1469 1470 1471 1472 1473 1474 | * more to inflate. */ if (zshPtr->stream.avail_in > 0) { if (zshPtr->interp) { Tcl_SetObjResult(zshPtr->interp, Tcl_NewStringObj( "unexpected zlib internal state during" | | | 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 | * more to inflate. */ if (zshPtr->stream.avail_in > 0) { if (zshPtr->interp) { Tcl_SetObjResult(zshPtr->interp, Tcl_NewStringObj( "unexpected zlib internal state during" " decompression", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(zshPtr->interp, "TCL", "ZIP", "STATE", (char *)NULL); } Tcl_SetByteArrayLength(data, existing); return TCL_ERROR; } |
︙ | ︙ | |||
1513 1514 1515 1516 1517 1518 1519 | */ do { e = inflate(&zshPtr->stream, zshPtr->flush); if (e != Z_NEED_DICT || !HaveDictToSet(zshPtr)) { break; } | | | 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 | */ do { e = inflate(&zshPtr->stream, zshPtr->flush); if (e != Z_NEED_DICT || !HaveDictToSet(zshPtr)) { break; } e = SetInflateDictionary(&zshPtr->stream, zshPtr->compDictObj); DictWasSet(zshPtr); } while (e == Z_OK); } if (zshPtr->stream.avail_out > 0) { Tcl_SetByteArrayLength(data, existing + count - zshPtr->stream.avail_out); } |
︙ | ︙ | |||
1566 1567 1568 1569 1570 1571 1572 | /* * Get the next chunk off our list of chunks and grab the data out * of it. */ Tcl_ListObjIndex(NULL, zshPtr->outData, 0, &itemObj); itemPtr = Tcl_GetBytesFromObj(NULL, itemObj, &itemLen); | | | 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 | /* * Get the next chunk off our list of chunks and grab the data out * of it. */ Tcl_ListObjIndex(NULL, zshPtr->outData, 0, &itemObj); itemPtr = Tcl_GetBytesFromObj(NULL, itemObj, &itemLen); if ((itemLen - zshPtr->outPos) >= (count - dataPos)) { Tcl_Size len = count - dataPos; memcpy(dataPtr + dataPos, itemPtr + zshPtr->outPos, len); zshPtr->outPos += len; dataPos += len; if (zshPtr->outPos == itemLen) { zshPtr->outPos = 0; |
︙ | ︙ | |||
1813 1814 1815 1816 1817 1818 1819 | "TCL_ZLIB_FORMAT_GZIP, TCL_ZLIB_FORMAT_RAW or " "TCL_ZLIB_FORMAT_AUTO"); } if (gzipHeaderDictObj) { headerPtr = &header; memset(headerPtr, 0, sizeof(gz_header)); | | | | | | | | | 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 | "TCL_ZLIB_FORMAT_GZIP, TCL_ZLIB_FORMAT_RAW or " "TCL_ZLIB_FORMAT_AUTO"); } if (gzipHeaderDictObj) { headerPtr = &header; memset(headerPtr, 0, sizeof(gz_header)); nameBuf = (char *) Tcl_Alloc(MAXPATHLEN); header.name = (Bytef *) nameBuf; header.name_max = MAXPATHLEN - 1; commentBuf = (char *) Tcl_Alloc(MAX_COMMENT_LEN); header.comment = (Bytef *) commentBuf; header.comm_max = MAX_COMMENT_LEN - 1; } if (bufferSize < 1) { /* * Start with a buffer (up to) 3 times the size of the input data. */ if (inLen < 32 * 1024 * 1024) { bufferSize = 3 * inLen; } else if (inLen < 256 * 1024 * 1024) { bufferSize = 2 * inLen; } else { bufferSize = inLen; } } TclNewObj(obj); outData = Tcl_SetByteArrayLength(obj, bufferSize); memset(&stream, 0, sizeof(z_stream)); stream.avail_in = inLen+1; /* +1 because zlib can "over-request" * input (but ignore it!) */ stream.next_in = inData; stream.avail_out = bufferSize; stream.next_out = outData; /* * Initialize zlib for decompression. */ |
︙ | ︙ | |||
1883 1884 1885 1886 1887 1888 1889 | if ((stream.avail_in == 0) && (stream.avail_out > 0)) { e = Z_STREAM_ERROR; break; } newBufferSize = bufferSize + 5 * stream.avail_in; if (newBufferSize == bufferSize) { | | | 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 | if ((stream.avail_in == 0) && (stream.avail_out > 0)) { e = Z_STREAM_ERROR; break; } newBufferSize = bufferSize + 5 * stream.avail_in; if (newBufferSize == bufferSize) { newBufferSize = bufferSize + 1000; } newOutData = Tcl_SetByteArrayLength(obj, newBufferSize); /* * Set next out to the same offset in the new location. */ |
︙ | ︙ | |||
1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 | /* *---------------------------------------------------------------------- * * ZlibCmd -- * * Implementation of the [zlib] command. * *---------------------------------------------------------------------- */ static int ZlibCmd( TCL_UNUSED(void *), | > > | 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 | /* *---------------------------------------------------------------------- * * ZlibCmd -- * * Implementation of the [zlib] command. * * TODO: Convert this to an ensemble. * *---------------------------------------------------------------------- */ static int ZlibCmd( TCL_UNUSED(void *), |
︙ | ︙ | |||
2011 2012 2013 2014 2015 2016 2017 | } if (Tcl_GetIndexFromObj(interp, objv[1], commands, "command", 0, &command) != TCL_OK) { return TCL_ERROR; } switch (command) { | | | | | | | | | | | | | 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 | } if (Tcl_GetIndexFromObj(interp, objv[1], commands, "command", 0, &command) != TCL_OK) { return TCL_ERROR; } switch (command) { case CMD_ADLER: /* adler32 str ?startvalue? * -> checksum */ if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 2, objv, "data ?startValue?"); return TCL_ERROR; } data = Tcl_GetBytesFromObj(interp, objv[2], &dlen); if (data == NULL) { return TCL_ERROR; } if (objc>3 && Tcl_GetWideIntFromObj(interp, objv[3], &start) != TCL_OK) { return TCL_ERROR; } if (objc < 4) { start = Tcl_ZlibAdler32(0, NULL, 0); } Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) (uLong) Tcl_ZlibAdler32(start, data, dlen))); return TCL_OK; case CMD_CRC: /* crc32 str ?startvalue? * -> checksum */ if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 2, objv, "data ?startValue?"); return TCL_ERROR; } data = Tcl_GetBytesFromObj(interp, objv[2], &dlen); if (data == NULL) { return TCL_ERROR; } if (objc > 3 && Tcl_GetIntFromObj(interp, objv[3], (int *) &start) != TCL_OK) { return TCL_ERROR; } if (objc < 4) { start = Tcl_ZlibCRC32(0, NULL, 0); } Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) (uLong) Tcl_ZlibCRC32(start, data, dlen))); return TCL_OK; case CMD_DEFLATE: /* deflate data ?level? * -> rawCompressedData */ if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 2, objv, "data ?level?"); return TCL_ERROR; } if (objc > 3) { if (Tcl_GetIntFromObj(interp, objv[3], &level) != TCL_OK) { return TCL_ERROR; } if (level < 0 || level > 9) { goto badLevel; } } return Tcl_ZlibDeflate(interp, TCL_ZLIB_FORMAT_RAW, objv[2], level, NULL); case CMD_COMPRESS: /* compress data ?level? * -> zlibCompressedData */ if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 2, objv, "data ?level?"); return TCL_ERROR; } if (objc > 3) { if (Tcl_GetIntFromObj(interp, objv[3], &level) != TCL_OK) { return TCL_ERROR; } if (level < 0 || level > 9) { goto badLevel; } } return Tcl_ZlibDeflate(interp, TCL_ZLIB_FORMAT_ZLIB, objv[2], level, NULL); case CMD_GZIP: /* gzip data ?level? * -> gzippedCompressedData */ headerDictObj = NULL; /* * Legacy argument format support. */ if (objc == 4 |
︙ | ︙ | |||
2117 2118 2119 2120 2121 2122 2123 | if (Tcl_GetIndexFromObj(interp, objv[i], gzipopts, "option", 0, &option) != TCL_OK) { return TCL_ERROR; } switch (option) { case 0: | | | | | | < | | | | | | < | | | < > | > | 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 | if (Tcl_GetIndexFromObj(interp, objv[i], gzipopts, "option", 0, &option) != TCL_OK) { return TCL_ERROR; } switch (option) { case 0: headerDictObj = objv[i + 1]; break; case 1: if (Tcl_GetIntFromObj(interp, objv[i + 1], &level) != TCL_OK) { return TCL_ERROR; } if (level < 0 || level > 9) { extraInfoStr = "\n (in -level option)"; goto badLevel; } break; } } return Tcl_ZlibDeflate(interp, TCL_ZLIB_FORMAT_GZIP, objv[2], level, headerDictObj); case CMD_INFLATE: /* inflate rawcomprdata ?bufferSize? * -> decompressedData */ if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 2, objv, "data ?bufferSize?"); return TCL_ERROR; } if (objc > 3) { if (TclGetWideIntFromObj(interp, objv[3], &wideLen) != TCL_OK) { return TCL_ERROR; } if (wideLen < MIN_NONSTREAM_BUFFER_SIZE || wideLen > MAX_BUFFER_SIZE) { goto badBuffer; } buffersize = wideLen; } return Tcl_ZlibInflate(interp, TCL_ZLIB_FORMAT_RAW, objv[2], buffersize, NULL); case CMD_DECOMPRESS: /* decompress zlibcomprdata ?bufferSize? * -> decompressedData */ if (objc < 3 || objc > 4) { Tcl_WrongNumArgs(interp, 2, objv, "data ?bufferSize?"); return TCL_ERROR; } if (objc > 3) { if (TclGetWideIntFromObj(interp, objv[3], &wideLen) != TCL_OK) { return TCL_ERROR; } if (wideLen < MIN_NONSTREAM_BUFFER_SIZE || wideLen > MAX_BUFFER_SIZE) { goto badBuffer; } buffersize = wideLen; } return Tcl_ZlibInflate(interp, TCL_ZLIB_FORMAT_ZLIB, objv[2], buffersize, NULL); case CMD_GUNZIP: { /* gunzip gzippeddata ?-headerVar varName? * -> decompressedData */ Tcl_Obj *headerVarObj; if (objc < 3 || objc > 5 || ((objc & 1) == 0)) { Tcl_WrongNumArgs(interp, 2, objv, "data ?-headerVar varName?"); return TCL_ERROR; } headerDictObj = headerVarObj = NULL; for (i=3 ; i<objc ; i+=2) { static const char *const gunzipopts[] = { "-buffersize", "-headerVar", NULL }; if (Tcl_GetIndexFromObj(interp, objv[i], gunzipopts, "option", 0, &option) != TCL_OK) { return TCL_ERROR; } switch (option) { case 0: if (TclGetWideIntFromObj(interp, objv[i + 1], &wideLen) != TCL_OK) { return TCL_ERROR; } if (wideLen < MIN_NONSTREAM_BUFFER_SIZE || wideLen > MAX_BUFFER_SIZE) { goto badBuffer; } buffersize = wideLen; break; case 1: headerVarObj = objv[i + 1]; TclNewObj(headerDictObj); break; } } if (Tcl_ZlibInflate(interp, TCL_ZLIB_FORMAT_GZIP, objv[2], buffersize, headerDictObj) != TCL_OK) { if (headerDictObj) { TclDecrRefCount(headerDictObj); } return TCL_ERROR; } if (headerVarObj != NULL && Tcl_ObjSetVar2(interp, headerVarObj, NULL, headerDictObj, TCL_LEAVE_ERR_MSG) == NULL) { return TCL_ERROR; } return TCL_OK; } case CMD_STREAM: /* stream deflate/inflate/...gunzip options... * -> handleCmd */ return ZlibStreamSubcmd(interp, objc, objv); case CMD_PUSH: /* push mode channel options... * -> channel */ return ZlibPushSubcmd(interp, objc, objv); } return TCL_ERROR; badLevel: Tcl_SetObjResult(interp, Tcl_NewStringObj( "level must be 0 to 9", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMPRESSIONLEVEL", (char *)NULL); if (extraInfoStr) { Tcl_AddErrorInfo(interp, extraInfoStr); } return TCL_ERROR; badBuffer: Tcl_SetObjResult(interp, Tcl_ObjPrintf( |
︙ | ︙ | |||
2365 2366 2367 2368 2369 2370 2371 | */ for (i=3 ; i<objc ; i+=2) { if (Tcl_GetIndexFromObjStruct(interp, objv[i], desc, sizeof(OptDescriptor), "option", 0, &option) != TCL_OK) { return TCL_ERROR; } | | | > | 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 | */ for (i=3 ; i<objc ; i+=2) { if (Tcl_GetIndexFromObjStruct(interp, objv[i], desc, sizeof(OptDescriptor), "option", 0, &option) != TCL_OK) { return TCL_ERROR; } obj[desc[option].offset] = objv[i + 1]; } /* * If a compression level was given, parse it (integral: 0..9). Otherwise * use the default. */ if (levelObj == NULL) { level = Z_DEFAULT_COMPRESSION; } else if (Tcl_GetIntFromObj(interp, levelObj, &level) != TCL_OK) { return TCL_ERROR; } else if (level < 0 || level > 9) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "level must be 0 to 9", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMPRESSIONLEVEL", (char *)NULL); Tcl_AddErrorInfo(interp, "\n (in -level option)"); return TCL_ERROR; } if (compDictObj) { if (NULL == Tcl_GetBytesFromObj(interp, compDictObj, (Tcl_Size *)NULL)) { |
︙ | ︙ | |||
2487 2488 2489 2490 2491 2492 2493 | mode = TCL_ZLIB_STREAM_INFLATE; format = TCL_ZLIB_FORMAT_GZIP; break; default: Tcl_Panic("should be unreachable"); } | | | > | > | | | | | | | | | | > | 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 | mode = TCL_ZLIB_STREAM_INFLATE; format = TCL_ZLIB_FORMAT_GZIP; break; default: Tcl_Panic("should be unreachable"); } if (TclGetChannelFromObj(interp, objv[3], &chan, &chanMode, 0) != TCL_OK) { return TCL_ERROR; } /* * Sanity checks. */ if (mode == TCL_ZLIB_STREAM_DEFLATE && !(chanMode & TCL_WRITABLE)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "compression may only be applied to writable channels", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "TCL", "ZIP", "UNWRITABLE", (char *)NULL); return TCL_ERROR; } if (mode == TCL_ZLIB_STREAM_INFLATE && !(chanMode & TCL_READABLE)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "decompression may only be applied to readable channels", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "TCL", "ZIP", "UNREADABLE", (char *)NULL); return TCL_ERROR; } /* * Parse options. */ level = Z_DEFAULT_COMPRESSION; for (i=4 ; i<objc ; i++) { if (Tcl_GetIndexFromObj(interp, objv[i], pushOptions, "option", 0, &option) != TCL_OK) { return TCL_ERROR; } if (++i > objc - 1) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "value missing for %s option", pushOptions[option])); Tcl_SetErrorCode(interp, "TCL", "ZIP", "NOVAL", (char *)NULL); return TCL_ERROR; } switch (option) { case poHeader: /* -header headerDict */ headerObj = objv[i]; if (Tcl_DictObjSize(interp, headerObj, &dummy) != TCL_OK) { goto genericOptionError; } break; case poLevel: /* -level compLevel */ if (Tcl_GetIntFromObj(interp, objv[i], (int *) &level) != TCL_OK) { goto genericOptionError; } if (level < 0 || level > 9) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "level must be 0 to 9", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMPRESSIONLEVEL", (char *)NULL); goto genericOptionError; } break; case poLimit: /* -limit numBytes */ if (Tcl_GetIntFromObj(interp, objv[i], (int *) &limit) != TCL_OK) { goto genericOptionError; } if (limit < 1 || limit > MAX_BUFFER_SIZE) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "read ahead limit must be 1 to %d", MAX_BUFFER_SIZE)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "BUFFERSIZE", (char *)NULL); goto genericOptionError; } break; case poDictionary: /* -dictionary compDict */ if (format == TCL_ZLIB_FORMAT_GZIP) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "a compression dictionary may not be set in the " "gzip format", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "TCL", "ZIP", "BADOPT", (char *)NULL); goto genericOptionError; } compDictObj = objv[i]; break; } } if (compDictObj && (NULL == Tcl_GetBytesFromObj(interp, compDictObj, (Tcl_Size *)NULL))) { return TCL_ERROR; } if (ZlibStackChannelTransform(interp, mode, format, level, limit, chan, headerObj, compDictObj) == NULL) { return TCL_ERROR; } |
︙ | ︙ | |||
2598 2599 2600 2601 2602 2603 2604 | * Implementation of the commands returned by [zlib stream]. * *---------------------------------------------------------------------- */ static int ZlibStreamCmd( | | | | 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 | * Implementation of the commands returned by [zlib stream]. * *---------------------------------------------------------------------- */ static int ZlibStreamCmd( void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]) { Tcl_ZlibStream zstream = (Tcl_ZlibStream) clientData; int count, code; Tcl_Obj *obj; static const char *const cmds[] = { "add", "checksum", "close", "eof", "finalize", "flush", "fullflush", "get", "header", "put", "reset", NULL }; |
︙ | ︙ | |||
2724 2725 2726 2727 2728 2729 2730 | } return TCL_OK; } static int ZlibStreamAddCmd( | | | | | | | | | | | | | | 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 | } return TCL_OK; } static int ZlibStreamAddCmd( void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]) { Tcl_ZlibStream zstream = (Tcl_ZlibStream) clientData; int code, buffersize = -1, flush = -1; Tcl_Size i; Tcl_Obj *obj, *compDictObj = NULL; static const char *const add_options[] = { "-buffer", "-dictionary", "-finalize", "-flush", "-fullflush", NULL }; enum addOptions { ao_buffer, ao_dictionary, ao_finalize, ao_flush, ao_fullflush } index; for (i=2; i<objc-1; i++) { if (Tcl_GetIndexFromObj(interp, objv[i], add_options, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case ao_flush: /* -flush */ if (flush >= 0) { flush = -2; } else { flush = Z_SYNC_FLUSH; } break; case ao_fullflush: /* -fullflush */ if (flush >= 0) { flush = -2; } else { flush = Z_FULL_FLUSH; } break; case ao_finalize: /* -finalize */ if (flush >= 0) { flush = -2; } else { flush = Z_FINISH; } break; case ao_buffer: /* -buffer bufferSize */ if (i == objc - 2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"-buffer\" option must be followed by integer " "decompression buffersize", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "TCL", "ZIP", "NOVAL", (char *)NULL); return TCL_ERROR; } if (Tcl_GetIntFromObj(interp, objv[++i], &buffersize) != TCL_OK) { return TCL_ERROR; } if (buffersize < 1 || buffersize > MAX_BUFFER_SIZE) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "buffer size must be 1 to %d", MAX_BUFFER_SIZE)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "BUFFERSIZE", (char *)NULL); return TCL_ERROR; } break; case ao_dictionary: /* -dictionary compDict */ if (i == objc - 2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"-dictionary\" option must be followed by" " compression dictionary bytes", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "TCL", "ZIP", "NOVAL", (char *)NULL); return TCL_ERROR; } compDictObj = objv[++i]; break; } if (flush == -2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"-flush\", \"-fullflush\" and \"-finalize\" options" " are mutually exclusive", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "TCL", "ZIP", "EXCLUSIVE", (char *)NULL); return TCL_ERROR; } } if (flush == -1) { flush = 0; } |
︙ | ︙ | |||
2832 2833 2834 2835 2836 2837 2838 | Tcl_ZlibStreamSetCompressionDictionary(zstream, compDictObj); } /* * Send the data to the stream core, along with any flushing directive. */ | | | | | | | | | | | | 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 | Tcl_ZlibStreamSetCompressionDictionary(zstream, compDictObj); } /* * Send the data to the stream core, along with any flushing directive. */ if (Tcl_ZlibStreamPut(zstream, objv[objc - 1], flush) != TCL_OK) { return TCL_ERROR; } /* * Get such data out as we can (up to the requested length). */ TclNewObj(obj); code = Tcl_ZlibStreamGet(zstream, obj, buffersize); if (code == TCL_OK) { Tcl_SetObjResult(interp, obj); } else { TclDecrRefCount(obj); } return code; } static int ZlibStreamPutCmd( void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]) { Tcl_ZlibStream zstream = (Tcl_ZlibStream) clientData; int flush = -1; Tcl_Size i; Tcl_Obj *compDictObj = NULL; static const char *const put_options[] = { "-dictionary", "-finalize", "-flush", "-fullflush", NULL }; enum putOptions { po_dictionary, po_finalize, po_flush, po_fullflush } index; for (i=2; i<objc-1; i++) { if (Tcl_GetIndexFromObj(interp, objv[i], put_options, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch (index) { case po_flush: /* -flush */ if (flush >= 0) { flush = -2; } else { flush = Z_SYNC_FLUSH; } break; case po_fullflush: /* -fullflush */ if (flush >= 0) { flush = -2; } else { flush = Z_FULL_FLUSH; } break; case po_finalize: /* -finalize */ if (flush >= 0) { flush = -2; } else { flush = Z_FINISH; } break; case po_dictionary: /* -dictionary compDict */ if (i == objc - 2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"-dictionary\" option must be followed by" " compression dictionary bytes", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "TCL", "ZIP", "NOVAL", (char *)NULL); return TCL_ERROR; } compDictObj = objv[++i]; break; } if (flush == -2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"-flush\", \"-fullflush\" and \"-finalize\" options" " are mutually exclusive", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "TCL", "ZIP", "EXCLUSIVE", (char *)NULL); return TCL_ERROR; } } if (flush == -1) { flush = 0; } |
︙ | ︙ | |||
2939 2940 2941 2942 2943 2944 2945 | Tcl_ZlibStreamSetCompressionDictionary(zstream, compDictObj); } /* * Send the data to the stream core, along with any flushing directive. */ | | | | | > > > > > > > > > > > > | | | | | | | | | | > | | > > | | | | | | | | | | | | | | | | | | | | > | | | | > | | | > < | | | | < | | | | 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 | Tcl_ZlibStreamSetCompressionDictionary(zstream, compDictObj); } /* * Send the data to the stream core, along with any flushing directive. */ return Tcl_ZlibStreamPut(zstream, objv[objc - 1], flush); } static int ZlibStreamHeaderCmd( void *clientData, Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[]) { ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) clientData; Tcl_Obj *resultObj; if (objc != 2) { Tcl_WrongNumArgs(interp, 2, objv, NULL); return TCL_ERROR; } else if (zshPtr->mode != TCL_ZLIB_STREAM_INFLATE || zshPtr->format != TCL_ZLIB_FORMAT_GZIP) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "only gunzip streams can produce header information", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "TCL", "ZIP", "BADOP", (char *)NULL); return TCL_ERROR; } TclNewObj(resultObj); ExtractHeader(&zshPtr->gzHeaderPtr->header, resultObj); Tcl_SetObjResult(interp, resultObj); return TCL_OK; } /* *---------------------------------------------------------------------- * Set of functions to support channel stacking. *---------------------------------------------------------------------- */ static inline int HaveFlag( ZlibChannelData *chanDataPtr, int flag) { return (chanDataPtr->flags & flag) != 0; } /* * * ZlibTransformClose -- * * How to shut down a stacked compressing/decompressing transform. * *---------------------------------------------------------------------- */ static int ZlibTransformClose( void *instanceData, Tcl_Interp *interp, int flags) { ZlibChannelData *chanDataPtr = (ZlibChannelData *) instanceData; int e, result = TCL_OK; size_t written; if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) { return EINVAL; } /* * Delete the support timer. */ ZlibTransformEventTimerKill(chanDataPtr); /* * Flush any data waiting to be compressed. */ if (chanDataPtr->mode == TCL_ZLIB_STREAM_DEFLATE) { chanDataPtr->outStream.avail_in = 0; do { e = Deflate(&chanDataPtr->outStream, chanDataPtr->outBuffer, chanDataPtr->outAllocated, Z_FINISH, &written); /* * Can't be sure that deflate() won't declare the buffer to be * full (with Z_BUF_ERROR) so handle that case. */ if (e == Z_BUF_ERROR) { e = Z_OK; written = chanDataPtr->outAllocated; } if (e != Z_OK && e != Z_STREAM_END) { /* TODO: is this the right way to do errors on close? */ if (!TclInThreadExit()) { ConvertError(interp, e, chanDataPtr->outStream.adler); } result = TCL_ERROR; break; } if (written && Tcl_WriteRaw(chanDataPtr->parent, chanDataPtr->outBuffer, written) == TCL_IO_FAILURE) { /* TODO: is this the right way to do errors on close? * Note: when close is called from FinalizeIOSubsystem then * interp may be NULL */ if (!TclInThreadExit() && interp) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "error while finalizing file: %s", Tcl_PosixError(interp))); } result = TCL_ERROR; break; } } while (e != Z_STREAM_END); (void) deflateEnd(&chanDataPtr->outStream); } else { /* * If we have unused bytes from the read input (overshot by * Z_STREAM_END or on possible error), unget them back to the parent * channel, so that they appear as not being read yet. */ if (chanDataPtr->inStream.avail_in) { Tcl_Ungets(chanDataPtr->parent, (char *) chanDataPtr->inStream.next_in, chanDataPtr->inStream.avail_in, 0); } (void) inflateEnd(&chanDataPtr->inStream); } /* * Release all memory. */ if (chanDataPtr->compDictObj) { Tcl_DecrRefCount(chanDataPtr->compDictObj); chanDataPtr->compDictObj = NULL; } if (chanDataPtr->inBuffer) { Tcl_Free(chanDataPtr->inBuffer); chanDataPtr->inBuffer = NULL; } if (chanDataPtr->outBuffer) { Tcl_Free(chanDataPtr->outBuffer); chanDataPtr->outBuffer = NULL; } Tcl_Free(chanDataPtr); return result; } /* *---------------------------------------------------------------------- * * ZlibTransformInput -- * * Reader filter that does decompression. * *---------------------------------------------------------------------- */ static int ZlibTransformInput( void *instanceData, char *buf, int toRead, int *errorCodePtr) { ZlibChannelData *chanDataPtr = (ZlibChannelData *) instanceData; Tcl_DriverInputProc *inProc = Tcl_ChannelInputProc(Tcl_GetChannelType(chanDataPtr->parent)); int readBytes, gotBytes; if (chanDataPtr->mode == TCL_ZLIB_STREAM_DEFLATE) { return inProc(Tcl_GetChannelInstanceData(chanDataPtr->parent), buf, toRead, errorCodePtr); } gotBytes = 0; readBytes = chanDataPtr->inStream.avail_in; /* how many bytes in buffer now */ while (!HaveFlag(chanDataPtr, STREAM_DONE) && toRead > 0) { unsigned int n; int decBytes; /* if starting from scratch or continuation after full decompression */ if (!chanDataPtr->inStream.avail_in) { /* buffer to start, we can read to whole available buffer */ chanDataPtr->inStream.next_in = (Bytef *) chanDataPtr->inBuffer; } /* * If done - no read needed anymore, check we have to copy rest of * decompressed data, otherwise return with size (or 0 for Eof) */ if (HaveFlag(chanDataPtr, STREAM_DECOMPRESS)) { goto copyDecompressed; } /* * The buffer is exhausted, but the caller wants even more. We now * have to go to the underlying channel, get more bytes and then * transform them for delivery. We may not get what we want (full EOF * or temporarily out of data). */ /* Check free buffer size and adjust size of next chunk to read. */ n = chanDataPtr->inAllocated - ((char *) chanDataPtr->inStream.next_in - chanDataPtr->inBuffer); if (n <= 0) { /* Normally unreachable: not enough input buffer to uncompress. * Todo: firstly try to realloc inBuffer upto MAX_BUFFER_SIZE. */ *errorCodePtr = ENOBUFS; return -1; } if (n > chanDataPtr->readAheadLimit) { n = chanDataPtr->readAheadLimit; } readBytes = Tcl_ReadRaw(chanDataPtr->parent, (char *) chanDataPtr->inStream.next_in, n); /* * Three cases here: * 1. Got some data from the underlying channel (readBytes > 0) so * it should be fed through the decompression engine. * 2. Got an error (readBytes == -1) which we should report up except * for the case where we can convert it to a short read. * 3. Got an end-of-data from EOF or blocking (readBytes == 0). If * it is EOF, try flushing the data out of the decompressor. */ if (readBytes == -1) { /* See ReflectInput() in tclIORTrans.c */ if (Tcl_InputBlocked(chanDataPtr->parent) && (gotBytes > 0)) { break; } *errorCodePtr = Tcl_GetErrno(); return -1; } /* more bytes (or Eof if readBytes == 0) */ chanDataPtr->inStream.avail_in += readBytes; copyDecompressed: /* * Transform the read chunk, if not empty. Anything we get * back is a transformation result to be put into our buffers, and * the next iteration will put it into the result. * For the case readBytes is 0 which signaling Eof in parent, the * partial data waiting is converted and returned. */ decBytes = ResultDecompress(chanDataPtr, buf, toRead, (readBytes != 0) ? Z_NO_FLUSH : Z_SYNC_FLUSH, errorCodePtr); if (decBytes == -1) { return -1; } gotBytes += decBytes; buf += decBytes; toRead -= decBytes; if ((decBytes == 0) || HaveFlag(chanDataPtr, STREAM_DECOMPRESS)) { /* * The drain delivered nothing (or buffer too small to decompress). * Time to deliver what we've got. */ if (!gotBytes && !HaveFlag(chanDataPtr, STREAM_DONE)) { /* if no-data, but not ready - avoid signaling Eof, * continue in blocking mode, otherwise EAGAIN */ if (Tcl_InputBlocked(chanDataPtr->parent)) { continue; } *errorCodePtr = EAGAIN; return -1; } break; } |
︙ | ︙ | |||
3228 3229 3230 3231 3232 3233 3234 | static int ZlibTransformOutput( void *instanceData, const char *buf, int toWrite, int *errorCodePtr) { | | | | | | | | | | | > | | | > | | | | | | | | > | | 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 | static int ZlibTransformOutput( void *instanceData, const char *buf, int toWrite, int *errorCodePtr) { ZlibChannelData *chanDataPtr = (ZlibChannelData *) instanceData; Tcl_DriverOutputProc *outProc = Tcl_ChannelOutputProc(Tcl_GetChannelType(chanDataPtr->parent)); int e; size_t produced; Tcl_Obj *errObj; if (chanDataPtr->mode == TCL_ZLIB_STREAM_INFLATE) { return outProc(Tcl_GetChannelInstanceData(chanDataPtr->parent), buf, toWrite, errorCodePtr); } /* * No zero-length writes. Flushes must be explicit. */ if (toWrite == 0) { return 0; } chanDataPtr->outStream.next_in = (Bytef *) buf; chanDataPtr->outStream.avail_in = toWrite; while (chanDataPtr->outStream.avail_in > 0) { e = Deflate(&chanDataPtr->outStream, chanDataPtr->outBuffer, chanDataPtr->outAllocated, Z_NO_FLUSH, &produced); if (e != Z_OK || produced == 0) { break; } if (Tcl_WriteRaw(chanDataPtr->parent, chanDataPtr->outBuffer, produced) == TCL_IO_FAILURE) { *errorCodePtr = Tcl_GetErrno(); return -1; } } if (e == Z_OK) { return toWrite - chanDataPtr->outStream.avail_in; } errObj = Tcl_NewListObj(0, NULL); Tcl_ListObjAppendElement(NULL, errObj, Tcl_NewStringObj( "-errorcode", TCL_AUTO_LENGTH)); Tcl_ListObjAppendElement(NULL, errObj, ConvertErrorToList(e, chanDataPtr->outStream.adler)); Tcl_ListObjAppendElement(NULL, errObj, Tcl_NewStringObj(chanDataPtr->outStream.msg, TCL_AUTO_LENGTH)); Tcl_SetChannelError(chanDataPtr->parent, errObj); *errorCodePtr = EINVAL; return -1; } /* *---------------------------------------------------------------------- * * ZlibTransformFlush -- * * How to perform a flush of a compressing transform. * *---------------------------------------------------------------------- */ static int ZlibTransformFlush( Tcl_Interp *interp, ZlibChannelData *chanDataPtr, int flushType) { int e; size_t len; chanDataPtr->outStream.avail_in = 0; do { /* * Get the bytes to go out of the compression engine. */ e = Deflate(&chanDataPtr->outStream, chanDataPtr->outBuffer, chanDataPtr->outAllocated, flushType, &len); if (e != Z_OK && e != Z_BUF_ERROR) { ConvertError(interp, e, chanDataPtr->outStream.adler); return TCL_ERROR; } /* * Write the bytes we've received to the next layer. */ if (len > 0 && Tcl_WriteRaw(chanDataPtr->parent, chanDataPtr->outBuffer, len) == TCL_IO_FAILURE) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "problem flushing channel: %s", Tcl_PosixError(interp))); return TCL_ERROR; } /* |
︙ | ︙ | |||
3351 3352 3353 3354 3355 3356 3357 | static int ZlibTransformSetOption( /* not used */ void *instanceData, Tcl_Interp *interp, const char *optionName, const char *value) { | | | | | | | | | | | | | | | 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 | static int ZlibTransformSetOption( /* not used */ void *instanceData, Tcl_Interp *interp, const char *optionName, const char *value) { ZlibChannelData *chanDataPtr = (ZlibChannelData *) instanceData; Tcl_DriverSetOptionProc *setOptionProc = Tcl_ChannelSetOptionProc(Tcl_GetChannelType(chanDataPtr->parent)); static const char *compressChanOptions = "dictionary flush"; static const char *gzipChanOptions = "flush"; static const char *decompressChanOptions = "dictionary limit"; static const char *gunzipChanOptions = "flush limit"; int haveFlushOpt = (chanDataPtr->mode == TCL_ZLIB_STREAM_DEFLATE); if (optionName && (strcmp(optionName, "-dictionary") == 0) && (chanDataPtr->format != TCL_ZLIB_FORMAT_GZIP)) { Tcl_Obj *compDictObj; int code; TclNewStringObj(compDictObj, value, strlen(value)); Tcl_IncrRefCount(compDictObj); if (NULL == Tcl_GetBytesFromObj(interp, compDictObj, (Tcl_Size *)NULL)) { Tcl_DecrRefCount(compDictObj); return TCL_ERROR; } if (chanDataPtr->compDictObj) { TclDecrRefCount(chanDataPtr->compDictObj); } chanDataPtr->compDictObj = compDictObj; code = Z_OK; if (chanDataPtr->mode == TCL_ZLIB_STREAM_DEFLATE) { code = SetDeflateDictionary(&chanDataPtr->outStream, compDictObj); if (code != Z_OK) { ConvertError(interp, code, chanDataPtr->outStream.adler); return TCL_ERROR; } } else if (chanDataPtr->format == TCL_ZLIB_FORMAT_RAW) { code = SetInflateDictionary(&chanDataPtr->inStream, compDictObj); if (code != Z_OK) { ConvertError(interp, code, chanDataPtr->inStream.adler); return TCL_ERROR; } } return TCL_OK; } if (haveFlushOpt) { |
︙ | ︙ | |||
3412 3413 3414 3415 3416 3417 3418 | return TCL_ERROR; } /* * Try to actually do the flush now. */ | | | | > | | | | | | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 | return TCL_ERROR; } /* * Try to actually do the flush now. */ return ZlibTransformFlush(interp, chanDataPtr, flushType); } } else { if (optionName && strcmp(optionName, "-limit") == 0) { int newLimit; if (Tcl_GetInt(interp, value, &newLimit) != TCL_OK) { return TCL_ERROR; } else if (newLimit < 1 || newLimit > MAX_BUFFER_SIZE) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "-limit must be between 1 and 65536", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "READLIMIT", (char *)NULL); return TCL_ERROR; } } } if (setOptionProc == NULL) { if (chanDataPtr->format == TCL_ZLIB_FORMAT_GZIP) { return Tcl_BadChannelOption(interp, optionName, (chanDataPtr->mode == TCL_ZLIB_STREAM_DEFLATE) ? gzipChanOptions : gunzipChanOptions); } else { return Tcl_BadChannelOption(interp, optionName, (chanDataPtr->mode == TCL_ZLIB_STREAM_DEFLATE) ? compressChanOptions : decompressChanOptions); } } /* * Pass all unknown options down, to deeper transforms and/or the base * channel. */ return setOptionProc(Tcl_GetChannelInstanceData(chanDataPtr->parent), interp, optionName, value); } /* *---------------------------------------------------------------------- * * ZlibTransformGetOption -- * * Reading side of [fconfigure] on our channel. * *---------------------------------------------------------------------- */ static int ZlibTransformGetOption( void *instanceData, Tcl_Interp *interp, const char *optionName, Tcl_DString *dsPtr) { ZlibChannelData *chanDataPtr = (ZlibChannelData *) instanceData; Tcl_DriverGetOptionProc *getOptionProc = Tcl_ChannelGetOptionProc(Tcl_GetChannelType(chanDataPtr->parent)); static const char *compressChanOptions = "checksum dictionary"; static const char *gzipChanOptions = "checksum"; static const char *decompressChanOptions = "checksum dictionary limit"; static const char *gunzipChanOptions = "checksum header limit"; /* * The "crc" option reports the current CRC (calculated with the Adler32 * or CRC32 algorithm according to the format) given the data that has * been processed so far. */ if (optionName == NULL || strcmp(optionName, "-checksum") == 0) { uLong crc; char buf[12]; if (chanDataPtr->mode == TCL_ZLIB_STREAM_DEFLATE) { crc = chanDataPtr->outStream.adler; } else { crc = chanDataPtr->inStream.adler; } snprintf(buf, sizeof(buf), "%lu", crc); if (optionName == NULL) { Tcl_DStringAppendElement(dsPtr, "-checksum"); Tcl_DStringAppendElement(dsPtr, buf); } else { Tcl_DStringAppend(dsPtr, buf, TCL_AUTO_LENGTH); return TCL_OK; } } if ((chanDataPtr->format != TCL_ZLIB_FORMAT_GZIP) && (optionName == NULL || strcmp(optionName, "-dictionary") == 0)) { /* * Embedded NUL bytes are ok; they'll be C080-encoded. */ if (optionName == NULL) { Tcl_DStringAppendElement(dsPtr, "-dictionary"); if (chanDataPtr->compDictObj) { Tcl_DStringAppendElement(dsPtr, TclGetString(chanDataPtr->compDictObj)); } else { Tcl_DStringAppendElement(dsPtr, ""); } } else { if (chanDataPtr->compDictObj) { Tcl_Size length; const char *str = TclGetStringFromObj(chanDataPtr->compDictObj, &length); Tcl_DStringAppend(dsPtr, str, length); } return TCL_OK; } } /* * The "header" option, which is only valid on inflating gzip channels, * reports the header that has been read from the start of the stream. */ if (HaveFlag(chanDataPtr, IN_HEADER) && ((optionName == NULL) || (strcmp(optionName, "-header") == 0))) { Tcl_Obj *tmpObj; TclNewObj(tmpObj); ExtractHeader(&chanDataPtr->inHeader.header, tmpObj); if (optionName == NULL) { Tcl_DStringAppendElement(dsPtr, "-header"); Tcl_DStringAppendElement(dsPtr, TclGetString(tmpObj)); Tcl_DecrRefCount(tmpObj); } else { TclDStringAppendObj(dsPtr, tmpObj); Tcl_DecrRefCount(tmpObj); return TCL_OK; } } /* * Now we do the standard processing of the stream we wrapped. */ if (getOptionProc) { return getOptionProc(Tcl_GetChannelInstanceData(chanDataPtr->parent), interp, optionName, dsPtr); } if (optionName == NULL) { return TCL_OK; } if (chanDataPtr->format == TCL_ZLIB_FORMAT_GZIP) { return Tcl_BadChannelOption(interp, optionName, (chanDataPtr->mode == TCL_ZLIB_STREAM_DEFLATE) ? gzipChanOptions : gunzipChanOptions); } else { return Tcl_BadChannelOption(interp, optionName, (chanDataPtr->mode == TCL_ZLIB_STREAM_DEFLATE) ? compressChanOptions : decompressChanOptions); } } /* *---------------------------------------------------------------------- * * ZlibTransformWatch, ZlibTransformEventHandler -- * * If we have data pending, trigger a readable event after a short time * (in order to allow a real event to catch up). * *---------------------------------------------------------------------- */ static void ZlibTransformWatch( void *instanceData, int mask) { ZlibChannelData *chanDataPtr = (ZlibChannelData *) instanceData; Tcl_DriverWatchProc *watchProc; /* * This code is based on the code in tclIORTrans.c */ watchProc = Tcl_ChannelWatchProc(Tcl_GetChannelType(chanDataPtr->parent)); watchProc(Tcl_GetChannelInstanceData(chanDataPtr->parent), mask); if (!(mask & TCL_READABLE) || !HaveFlag(chanDataPtr, STREAM_DECOMPRESS)) { ZlibTransformEventTimerKill(chanDataPtr); } else if (chanDataPtr->timer == NULL) { chanDataPtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME, ZlibTransformTimerRun, chanDataPtr); } } static int ZlibTransformEventHandler( void *instanceData, int interestMask) { ZlibChannelData *chanDataPtr = (ZlibChannelData *) instanceData; ZlibTransformEventTimerKill(chanDataPtr); return interestMask; } static inline void ZlibTransformEventTimerKill( ZlibChannelData *chanDataPtr) { if (chanDataPtr->timer != NULL) { Tcl_DeleteTimerHandler(chanDataPtr->timer); chanDataPtr->timer = NULL; } } static void ZlibTransformTimerRun( void *clientData) { ZlibChannelData *chanDataPtr = (ZlibChannelData *) clientData; chanDataPtr->timer = NULL; Tcl_NotifyChannel(chanDataPtr->chan, TCL_READABLE); } /* *---------------------------------------------------------------------- * * ZlibTransformGetHandle -- * * Anything that needs the OS handle is told to get it from what we are * stacked on top of. * *---------------------------------------------------------------------- */ static int ZlibTransformGetHandle( void *instanceData, int direction, void **handlePtr) { ZlibChannelData *chanDataPtr = (ZlibChannelData *) instanceData; return Tcl_GetChannelHandle(chanDataPtr->parent, direction, handlePtr); } /* *---------------------------------------------------------------------- * * ZlibTransformBlockMode -- * * We need to keep track of the blocking mode; it changes our behavior. * *---------------------------------------------------------------------- */ static int ZlibTransformBlockMode( void *instanceData, int mode) { ZlibChannelData *chanDataPtr = (ZlibChannelData *) instanceData; if (mode == TCL_MODE_NONBLOCKING) { chanDataPtr->flags |= ASYNC; } else { chanDataPtr->flags &= ~ASYNC; } return TCL_OK; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
3722 3723 3724 3725 3726 3727 3728 | Tcl_Obj *gzipHeaderDictPtr, /* A description of header to use, or NULL to * use a default. Ignored if not compressing * to produce gzip-format data. */ Tcl_Obj *compDictObj) /* Byte-array object containing compression * dictionary (not dictObj!) to use if * necessary. */ { | > | | | | | | | | | | | | | | | | | | > | > | > | > | | > | | | | | | | > | > | > | | | | | > | | > | | | | > | | | | | | | | | | > | | | < | | | | > > > > | | | > | > | | | | 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 | Tcl_Obj *gzipHeaderDictPtr, /* A description of header to use, or NULL to * use a default. Ignored if not compressing * to produce gzip-format data. */ Tcl_Obj *compDictObj) /* Byte-array object containing compression * dictionary (not dictObj!) to use if * necessary. */ { ZlibChannelData *chanDataPtr = (ZlibChannelData *) Tcl_Alloc(sizeof(ZlibChannelData)); Tcl_Channel chan; int wbits = 0; if (mode != TCL_ZLIB_STREAM_DEFLATE && mode != TCL_ZLIB_STREAM_INFLATE) { Tcl_Panic("unknown mode: %d", mode); } memset(chanDataPtr, 0, sizeof(ZlibChannelData)); chanDataPtr->mode = mode; chanDataPtr->format = format; chanDataPtr->readAheadLimit = limit; if (format == TCL_ZLIB_FORMAT_GZIP || format == TCL_ZLIB_FORMAT_AUTO) { if (mode == TCL_ZLIB_STREAM_DEFLATE) { if (gzipHeaderDictPtr) { chanDataPtr->flags |= OUT_HEADER; if (GenerateHeader(interp, gzipHeaderDictPtr, &chanDataPtr->outHeader, NULL) != TCL_OK) { goto error; } } } else { chanDataPtr->flags |= IN_HEADER; chanDataPtr->inHeader.header.name = (Bytef *) &chanDataPtr->inHeader.nativeFilenameBuf; chanDataPtr->inHeader.header.name_max = MAXPATHLEN - 1; chanDataPtr->inHeader.header.comment = (Bytef *) &chanDataPtr->inHeader.nativeCommentBuf; chanDataPtr->inHeader.header.comm_max = MAX_COMMENT_LEN - 1; } } if (compDictObj != NULL) { chanDataPtr->compDictObj = Tcl_DuplicateObj(compDictObj); Tcl_IncrRefCount(chanDataPtr->compDictObj); Tcl_GetBytesFromObj(NULL, chanDataPtr->compDictObj, (Tcl_Size *)NULL); } switch (format) { case TCL_ZLIB_FORMAT_RAW: wbits = WBITS_RAW; break; case TCL_ZLIB_FORMAT_ZLIB: wbits = WBITS_ZLIB; break; case TCL_ZLIB_FORMAT_GZIP: wbits = WBITS_GZIP; break; case TCL_ZLIB_FORMAT_AUTO: wbits = WBITS_AUTODETECT; break; default: Tcl_Panic("bad format: %d", format); } /* * Initialize input inflater or the output deflater. */ if (mode == TCL_ZLIB_STREAM_INFLATE) { if (inflateInit2(&chanDataPtr->inStream, wbits) != Z_OK) { goto error; } chanDataPtr->inAllocated = DEFAULT_BUFFER_SIZE; if (chanDataPtr->inAllocated < chanDataPtr->readAheadLimit) { chanDataPtr->inAllocated = chanDataPtr->readAheadLimit; } chanDataPtr->inBuffer = (char *) Tcl_Alloc(chanDataPtr->inAllocated); if (HaveFlag(chanDataPtr, IN_HEADER)) { if (inflateGetHeader(&chanDataPtr->inStream, &chanDataPtr->inHeader.header) != Z_OK) { goto error; } } if (chanDataPtr->format == TCL_ZLIB_FORMAT_RAW && chanDataPtr->compDictObj) { if (SetInflateDictionary(&chanDataPtr->inStream, chanDataPtr->compDictObj) != Z_OK) { goto error; } } } else { if (deflateInit2(&chanDataPtr->outStream, level, Z_DEFLATED, wbits, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK) { goto error; } chanDataPtr->outAllocated = DEFAULT_BUFFER_SIZE; chanDataPtr->outBuffer = (char *) Tcl_Alloc(chanDataPtr->outAllocated); if (HaveFlag(chanDataPtr, OUT_HEADER)) { if (deflateSetHeader(&chanDataPtr->outStream, &chanDataPtr->outHeader.header) != Z_OK) { goto error; } } if (chanDataPtr->compDictObj) { if (SetDeflateDictionary(&chanDataPtr->outStream, chanDataPtr->compDictObj) != Z_OK) { goto error; } } } chan = Tcl_StackChannel(interp, &zlibChannelType, chanDataPtr, Tcl_GetChannelMode(channel), channel); if (chan == NULL) { goto error; } chanDataPtr->chan = chan; chanDataPtr->parent = Tcl_GetStackedChannel(chan); Tcl_SetObjResult(interp, Tcl_NewStringObj( Tcl_GetChannelName(chan), TCL_AUTO_LENGTH)); return chan; error: if (chanDataPtr->inBuffer) { Tcl_Free(chanDataPtr->inBuffer); inflateEnd(&chanDataPtr->inStream); } if (chanDataPtr->outBuffer) { Tcl_Free(chanDataPtr->outBuffer); deflateEnd(&chanDataPtr->outStream); } if (chanDataPtr->compDictObj) { Tcl_DecrRefCount(chanDataPtr->compDictObj); } Tcl_Free(chanDataPtr); return NULL; } /* *---------------------------------------------------------------------- * * ResultDecompress -- * * Extract uncompressed bytes from the compression engine and store them * in our buffer (buf) up to toRead bytes. * * Result: * Number of bytes decompressed or -1 if error (with *errorCodePtr updated * with reason). * * Side effects: * After execution it updates chanDataPtr->inStream (next_in, avail_in) to * reflect the data that has been decompressed. * *---------------------------------------------------------------------- */ static int ResultDecompress( ZlibChannelData *chanDataPtr, char *buf, int toRead, int flush, int *errorCodePtr) { int e, written, resBytes = 0; Tcl_Obj *errObj; chanDataPtr->flags &= ~STREAM_DECOMPRESS; chanDataPtr->inStream.next_out = (Bytef *) buf; chanDataPtr->inStream.avail_out = toRead; while (chanDataPtr->inStream.avail_out > 0) { e = inflate(&chanDataPtr->inStream, flush); /* * Apply a compression dictionary if one is needed and we have one. */ if (e == Z_NEED_DICT && chanDataPtr->compDictObj) { e = SetInflateDictionary(&chanDataPtr->inStream, chanDataPtr->compDictObj); if (e == Z_OK) { /* * A repetition of Z_NEED_DICT now is just an error. */ e = inflate(&chanDataPtr->inStream, flush); } } /* * avail_out is now the left over space in the output. Therefore * "toRead - avail_out" is the amount of bytes generated. */ written = toRead - chanDataPtr->inStream.avail_out; /* * The cases where we're definitely done. */ if (e == Z_STREAM_END) { chanDataPtr->flags |= STREAM_DONE; resBytes += written; break; } if (e == Z_OK) { if (written == 0) { break; } |
︙ | ︙ | |||
3931 3932 3933 3934 3935 3936 3937 | goto handleError; } /* * Check if the inflate stopped early. */ | | | > | | | > | | | | 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 | goto handleError; } /* * Check if the inflate stopped early. */ if (chanDataPtr->inStream.avail_in <= 0 && flush != Z_SYNC_FLUSH) { break; } } if (!HaveFlag(chanDataPtr, STREAM_DONE)) { /* if we have pending input data, but no available output buffer */ if (chanDataPtr->inStream.avail_in && !chanDataPtr->inStream.avail_out) { /* next time try to decompress it got readable (new output buffer) */ chanDataPtr->flags |= STREAM_DECOMPRESS; } } return resBytes; handleError: errObj = Tcl_NewListObj(0, NULL); Tcl_ListObjAppendElement(NULL, errObj, Tcl_NewStringObj( "-errorcode", TCL_AUTO_LENGTH)); Tcl_ListObjAppendElement(NULL, errObj, ConvertErrorToList(e, chanDataPtr->inStream.adler)); Tcl_ListObjAppendElement(NULL, errObj, Tcl_NewStringObj(chanDataPtr->inStream.msg, TCL_AUTO_LENGTH)); Tcl_SetChannelError(chanDataPtr->parent, errObj); *errorCodePtr = EINVAL; return -1; } /* *---------------------------------------------------------------------- * Finally, the TclZlibInit function. Used to install the zlib API. |
︙ | ︙ | |||
3976 3977 3978 3979 3980 3981 3982 | /* * This does two things. It creates a counter used in the creation of * stream commands, and it creates the namespace that will contain those * commands. */ | | > | 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 | /* * This does two things. It creates a counter used in the creation of * stream commands, and it creates the namespace that will contain those * commands. */ Tcl_EvalEx(interp, "namespace eval ::tcl::zlib {variable cmdcounter 0}", TCL_AUTO_LENGTH, 0); /* * Create the public scripted interface to this file's functionality. */ Tcl_CreateObjCommand2(interp, "zlib", ZlibCmd, 0, 0); |
︙ | ︙ | |||
4027 4028 4029 4030 4031 4032 4033 | int mode, int format, int level, Tcl_Obj *dictObj, Tcl_ZlibStream *zshandle) { if (interp) { | | > | 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 | int mode, int format, int level, Tcl_Obj *dictObj, Tcl_ZlibStream *zshandle) { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "unimplemented", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "TCL", "UNIMPLEMENTED", (char *)NULL); } return TCL_ERROR; } int Tcl_ZlibStreamClose( |
︙ | ︙ | |||
4095 4096 4097 4098 4099 4100 4101 | Tcl_Interp *interp, int format, Tcl_Obj *data, int level, Tcl_Obj *gzipHeaderDictObj) { if (interp) { | | > | > | 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 | Tcl_Interp *interp, int format, Tcl_Obj *data, int level, Tcl_Obj *gzipHeaderDictObj) { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "unimplemented", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "TCL", "UNIMPLEMENTED", (char *)NULL); } return TCL_ERROR; } int Tcl_ZlibInflate( Tcl_Interp *interp, int format, Tcl_Obj *data, size_t bufferSize, Tcl_Obj *gzipHeaderDictObj) { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "unimplemented", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "TCL", "UNIMPLEMENTED", (char *)NULL); } return TCL_ERROR; } unsigned int Tcl_ZlibCRC32( |
︙ | ︙ |
Changes to library/http/http.tcl.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # http.tcl -- # # Client-side HTTP for GET, POST, and HEAD commands. These routines can # be used in untrusted code that uses the Safesock security policy. # These procedures use a callback interface to avoid using vwait, which # is not defined in the safe base. # # See the file "license.terms" for information on usage and redistribution of # this file, and for a DISCLAIMER OF ALL WARRANTIES. package require Tcl 8.6- # Keep this in sync with pkgIndex.tcl and with the install directories in # Makefiles | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # http.tcl -- # # Client-side HTTP for GET, POST, and HEAD commands. These routines can # be used in untrusted code that uses the Safesock security policy. # These procedures use a callback interface to avoid using vwait, which # is not defined in the safe base. # # See the file "license.terms" for information on usage and redistribution of # this file, and for a DISCLAIMER OF ALL WARRANTIES. package require Tcl 8.6- # Keep this in sync with pkgIndex.tcl and with the install directories in # Makefiles package provide http 2.10b3 namespace eval http { # Allow resourcing to not clobber existing data variable http if {![info exists http]} { array set http { |
︙ | ︙ |
Changes to library/http/pkgIndex.tcl.
1 | if {![package vsatisfies [package provide Tcl] 8.6-]} {return} | | | 1 2 | if {![package vsatisfies [package provide Tcl] 8.6-]} {return} package ifneeded http 2.10b3 [list tclPkgSetup $dir http 2.10b3 {{http.tcl source {::http::config ::http::formatQuery ::http::geturl ::http::reset ::http::wait ::http::register ::http::unregister ::http::mapReply}}}] |
Changes to library/init.tcl.
︙ | ︙ | |||
105 106 107 108 109 110 111 | {::tcl::MacOSXPkgUnknown ::tclPkgUnknown}} } else { package unknown {::tcl::tm::UnknownHandler ::tclPkgUnknown} } # Set up the 'clock' ensemble | | < | < | | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | {::tcl::MacOSXPkgUnknown ::tclPkgUnknown}} } else { package unknown {::tcl::tm::UnknownHandler ::tclPkgUnknown} } # Set up the 'clock' ensemble apply {{} { set cmdmap [dict create] foreach cmd {add clicks format microseconds milliseconds scan seconds} { dict set cmdmap $cmd ::tcl::clock::$cmd } namespace inscope ::tcl::clock [list namespace ensemble create -command \ ::clock -map $cmdmap] ::tcl::unsupported::clock::configure -init-complete }} } # Conditionalize for presence of exec. if {[namespace which -command exec] eq ""} { # Some machines do not have exec. Also, on all |
︙ | ︙ |
Changes to library/manifest.txt.
1 2 3 4 5 6 | ### # Package manifest for all Tcl packages included in the /library file system ### apply {{dir} { set isafe [interp issafe] foreach {safe package version file} { | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | ### # Package manifest for all Tcl packages included in the /library file system ### apply {{dir} { set isafe [interp issafe] foreach {safe package version file} { 0 http 2.10b3 {http http.tcl} 1 msgcat 1.7.1 {msgcat msgcat.tcl} 1 opt 0.4.9 {opt optparse.tcl} 0 cookiejar 0.2.0 {cookiejar cookiejar.tcl} 0 tcl::idna 1.0.1 {cookiejar idna.tcl} 0 platform 1.0.19 {platform platform.tcl} 0 platform::shell 1.1.4 {platform shell.tcl} 1 tcltest 2.5.8 {tcltest tcltest.tcl} |
︙ | ︙ |
Changes to library/tclIndex.
︙ | ︙ | |||
91 92 93 94 95 96 97 | set auto_index(::safe::BadSubcommand) [list ::tcl::Pkg::source [file join $dir safe.tcl]] set auto_index(::safe::AliasEncodingSystem) [list ::tcl::Pkg::source [file join $dir safe.tcl]] set auto_index(::safe::AliasExeName) [list ::tcl::Pkg::source [file join $dir safe.tcl]] set auto_index(::safe::RejectExcessColons) [list ::tcl::Pkg::source [file join $dir safe.tcl]] set auto_index(::safe::VarName) [list ::tcl::Pkg::source [file join $dir safe.tcl]] set auto_index(::safe::Setup) [list ::tcl::Pkg::source [file join $dir safe.tcl]] set auto_index(::safe::setSyncMode) [list ::tcl::Pkg::source [file join $dir safe.tcl]] | | | 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | set auto_index(::safe::BadSubcommand) [list ::tcl::Pkg::source [file join $dir safe.tcl]] set auto_index(::safe::AliasEncodingSystem) [list ::tcl::Pkg::source [file join $dir safe.tcl]] set auto_index(::safe::AliasExeName) [list ::tcl::Pkg::source [file join $dir safe.tcl]] set auto_index(::safe::RejectExcessColons) [list ::tcl::Pkg::source [file join $dir safe.tcl]] set auto_index(::safe::VarName) [list ::tcl::Pkg::source [file join $dir safe.tcl]] set auto_index(::safe::Setup) [list ::tcl::Pkg::source [file join $dir safe.tcl]] set auto_index(::safe::setSyncMode) [list ::tcl::Pkg::source [file join $dir safe.tcl]] set auto_index(::tcl::tm::path) [list ::tcl::Pkg::source [file join $dir tm.tcl]] set auto_index(::tcl::tm::add) [list ::tcl::Pkg::source [file join $dir tm.tcl]] set auto_index(::tcl::tm::remove) [list ::tcl::Pkg::source [file join $dir tm.tcl]] set auto_index(::tcl::tm::list) [list ::tcl::Pkg::source [file join $dir tm.tcl]] set auto_index(::tcl::tm::UnknownHandler) [list ::tcl::Pkg::source [file join $dir tm.tcl]] set auto_index(::tcl::tm::Defaults) [list ::tcl::Pkg::source [file join $dir tm.tcl]] set auto_index(::tcl::tm::roots) [list ::tcl::Pkg::source [file join $dir tm.tcl]] set auto_index(::tcl::UpdateWordBreakREs) [list ::tcl::Pkg::source [file join $dir word.tcl]] |
︙ | ︙ |
Changes to library/tm.tcl.
︙ | ︙ | |||
93 94 95 96 97 98 99 | # respect to the existing paths, but also between themselves. Otherwise we # can still add bogus paths, by specifying them in a single call. This # makes the use of the new paths simpler as well, a trivial assignment of # the collected paths to the official state var. set newpaths $paths foreach p $args { | | | | 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | # respect to the existing paths, but also between themselves. Otherwise we # can still add bogus paths, by specifying them in a single call. This # makes the use of the new paths simpler as well, a trivial assignment of # the collected paths to the official state var. set newpaths $paths foreach p $args { if {($p eq "") || ($p in $newpaths)} { # Ignore any path which is empty or already on the list. continue } # Search for paths which are subdirectories of the new one. If there # are any then the new path violates the restriction about ancestors. set pos [lsearch -glob $newpaths ${p}/*] |
︙ | ︙ | |||
331 332 333 334 335 336 337 | } else { set sep ":" } for {set n $minor} {$n >= 0} {incr n -1} { foreach ev [::list \ TCL${major}.${n}_TM_PATH \ TCL${major}_${n}_TM_PATH \ | | | | | | | 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 | } else { set sep ":" } for {set n $minor} {$n >= 0} {incr n -1} { foreach ev [::list \ TCL${major}.${n}_TM_PATH \ TCL${major}_${n}_TM_PATH \ ] { if {![info exists env($ev)]} continue foreach p [split $env($ev) $sep] { # Paths relative to unresolvable home dirs are ignored if {![catch {file tildeexpand $p} expanded_path]} { path add $expanded_path } } } } return } # ::tcl::tm::roots -- |
︙ | ︙ |
Changes to macosx/README.
︙ | ︙ | |||
104 105 106 107 108 109 110 | ReleaseUniversal10.5SDK: build against the 10.5 SDK (with 10.5 deployment target). Note that the non-SDK configurations have their deployment target set to 10.6 (Tcl.xcodeproj). The Xcode projects refer to the toplevel tcl source directory via the TCL_SRCROOT user build setting, by default this is set to the project-relative path '../../tcl', if your tcl source directory is named differently, e.g. | | | | | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | ReleaseUniversal10.5SDK: build against the 10.5 SDK (with 10.5 deployment target). Note that the non-SDK configurations have their deployment target set to 10.6 (Tcl.xcodeproj). The Xcode projects refer to the toplevel tcl source directory via the TCL_SRCROOT user build setting, by default this is set to the project-relative path '../../tcl', if your tcl source directory is named differently, e.g. '../../tcl9.1', you need to manually change the TCL_SRCROOT setting by editing your ${USER}.pbxuser file (located inside the Tcl.xcodeproj bundle directory) with a text editor. - To build universal binaries outside of the Xcode IDE, set CFLAGS as follows: export CFLAGS="-arch x86_64 -arch arm64" This requires Mac OS X 10.6 and Xcode 10.2 and will work on any architecture. Note that configure requires CFLAGS to contain a least one architecture that can be run on the build machine (i.e. x86_64 on Core2/Xeon). Universal builds of Tcl TEA extensions are also possible with CFLAGS set as above, they will be [load]able by universal as well as thin binaries of Tcl. Detailed Instructions for building with macosx/GNUmakefile ---------------------------------------------------------- - Unpack the Tcl source release archive. - The following instructions assume the Tcl source tree is named "tcl${ver}", (where ${ver} is a shell variable containing the Tcl version number e.g. '9.1'). Setup this shell variable as follows: ver="9.1" - Setup environment variables as desired, e.g. for a universal build on 10.5: CFLAGS="-arch x86_64 -arch arm64 -mmacosx-version-min=10.5" export CFLAGS - Change to the directory containing the Tcl source tree and build: make -C tcl${ver}/macosx |
︙ | ︙ |
Changes to macosx/Tcl-Common.xcconfig.
︙ | ︙ | |||
28 29 30 31 32 33 34 | LIBDIR = $(PREFIX)/lib MANDIR = $(PREFIX)/man PREFIX = /usr/local TCL_CONFIGURE_ARGS = --enable-dtrace TCL_LIBRARY = $(LIBDIR)/tcl$(VERSION) TCL_PACKAGE_PATH = "$(LIBDIR)" TCL_DEFS = HAVE_TCL_CONFIG_H | | | 28 29 30 31 32 33 34 35 | LIBDIR = $(PREFIX)/lib MANDIR = $(PREFIX)/man PREFIX = /usr/local TCL_CONFIGURE_ARGS = --enable-dtrace TCL_LIBRARY = $(LIBDIR)/tcl$(VERSION) TCL_PACKAGE_PATH = "$(LIBDIR)" TCL_DEFS = HAVE_TCL_CONFIG_H VERSION = 9.1 |
Changes to macosx/tclMacOSXNotify.c.
︙ | ︙ | |||
842 843 844 845 846 847 848 | * Restore original signal mask. */ pthread_sigmask(SIG_SETMASK, ¬ifierSigMask, NULL); } UNLOCK_NOTIFIER_INIT; } | < | 842 843 844 845 846 847 848 849 850 851 852 853 854 855 | * Restore original signal mask. */ pthread_sigmask(SIG_SETMASK, ¬ifierSigMask, NULL); } UNLOCK_NOTIFIER_INIT; } /* *---------------------------------------------------------------------- * * TclpFinalizeNotifier -- * * This function is called to cleanup the notifier state before a thread |
︙ | ︙ |
Changes to tests/clock.test.
︙ | ︙ | |||
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 | return -code error "test case attempts to read unknown registry entry $path $key" } return [dict get $reg $path $key] } # Base test cases: test clock-0.1 "initial: auto-loading of ensemble and stubs on demand" -setup { set i [interp create]; # because clock can be used somewhere, test it in new interp: } -body { $i eval { lappend ret ens:[namespace ensemble exists ::clock] clock seconds; # init ensemble (but not yet stubs, loading of clock.tcl retarded) lappend ret ens:[namespace ensemble exists ::clock] lappend ret stubs:[expr {[namespace which -command ::tcl::clock::GetSystemTimeZone] ne ""}] clock format -now; # clock.tcl stubs expected lappend ret stubs:[expr {[namespace which -command ::tcl::clock::GetSystemTimeZone] ne ""}] } } -cleanup { interp delete $i | > > | | | 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 | return -code error "test case attempts to read unknown registry entry $path $key" } return [dict get $reg $path $key] } # Base test cases: # no lazy creation of clock-ensemble (interim, bug [9889f96f4da77e3b], [31fd84270644f67d]), # so ensemble created implicitely in init.tcl test clock-0.1 "initial: auto-loading of ensemble and stubs on demand" -setup { set i [interp create]; # because clock can be used somewhere, test it in new interp: } -body { $i eval { lappend ret ens:[namespace ensemble exists ::clock] clock seconds; # init ensemble (but not yet stubs, loading of clock.tcl retarded) lappend ret ens:[namespace ensemble exists ::clock] lappend ret stubs:[expr {[namespace which -command ::tcl::clock::GetSystemTimeZone] ne ""}] clock format -now; # clock.tcl stubs expected lappend ret stubs:[expr {[namespace which -command ::tcl::clock::GetSystemTimeZone] ne ""}] } } -cleanup { interp delete $i } -result {ens:1 ens:1 stubs:0 stubs:1} test clock-0.1a "initial: safe interpreter shares clock command with parent" -setup { set i [interp create] $i eval {set sci [interp create -safe]} } -body { $i eval { lappend ret ens:[namespace ensemble exists ::clock] $sci eval { clock seconds }; # init ensemble (but not yet stubs, loading of clock.tcl retarded) lappend ret ens:[namespace ensemble exists ::clock] lappend ret stubs:[expr {[namespace which -command ::tcl::clock::GetSystemTimeZone] ne ""}] $sci eval { clock format -now }; # clock.tcl stubs expected lappend ret stubs:[expr {[namespace which -command ::tcl::clock::GetSystemTimeZone] ne ""}] } } -cleanup { interp delete $i } -result {ens:1 ens:1 stubs:0 stubs:1} test clock-0.2 "initial: loading of format/locale does not overwrite interp state (errorInfo)" -setup { # be sure - we have no cached locale/msgcat, etc: if {[namespace which -command ::tcl::clock::ClearCaches] ne ""} { ::tcl::clock::ClearCaches } } -body { |
︙ | ︙ | |||
370 371 372 373 374 375 376 377 378 379 380 381 382 383 | set n [clock format [clock seconds] -g 1 -f "%s"] expr {[clock format -now -g 1 -f "%s"] in [list $n [incr n]]} } 1 test clock-1.9 "clock arguments: option doubly present" { list [catch {clock format 0 -gmt 1 -gmt 0} result] $result } {1 {bad option "-gmt": doubly present}} # BEGIN testcases2 # Test formatting of Gregorian year, month, day, all formats # Formats tested: %b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y %EY test clock-2.1 {conversion of 1872-01-01} { | > > > > | 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 | set n [clock format [clock seconds] -g 1 -f "%s"] expr {[clock format -now -g 1 -f "%s"] in [list $n [incr n]]} } 1 test clock-1.9 "clock arguments: option doubly present" { list [catch {clock format 0 -gmt 1 -gmt 0} result] $result } {1 {bad option "-gmt": doubly present}} test clock-1.10 {clock format: text with token (bug [a858d95f4bfddafb])} { clock format 0 -format text(%d) -gmt 1 } {text(01)} # BEGIN testcases2 # Test formatting of Gregorian year, month, day, all formats # Formats tested: %b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y %EY test clock-2.1 {conversion of 1872-01-01} { |
︙ | ︙ | |||
18919 18920 18921 18922 18923 18924 18925 18926 18927 18928 18929 18930 18931 18932 | } {Tue Dec 13 01:02:00 GMT 2011} test clock-6.22.19 {Greedy match (space wins as date-time separator)} { clock format [clock scan "111 213120" -format "%y%m%d %H%M%S" -gmt 1] -locale en -gmt 1 } {Mon Jan 01 21:31:20 GMT 2001} test clock-6.22.20 {Greedy match (second space wins as date-time separator)} { clock format [clock scan "111 2 13120" -format "%y%m%d %H%M%S" -gmt 1] -locale en -gmt 1 } {Sun Jan 02 13:12:00 GMT 2011} test clock-7.1 {Julian Day} { clock scan 0 -format %J -gmt true } -210866803200 test clock-7.2 {Julian Day} { | > > > > | 18925 18926 18927 18928 18929 18930 18931 18932 18933 18934 18935 18936 18937 18938 18939 18940 18941 18942 | } {Tue Dec 13 01:02:00 GMT 2011} test clock-6.22.19 {Greedy match (space wins as date-time separator)} { clock format [clock scan "111 213120" -format "%y%m%d %H%M%S" -gmt 1] -locale en -gmt 1 } {Mon Jan 01 21:31:20 GMT 2001} test clock-6.22.20 {Greedy match (second space wins as date-time separator)} { clock format [clock scan "111 2 13120" -format "%y%m%d %H%M%S" -gmt 1] -locale en -gmt 1 } {Sun Jan 02 13:12:00 GMT 2011} test clock-6.23 {clock scan: text with token (bug [a858d95f4bfddafb])} { clock scan {text(01)} -format text(%d) -gmt 1 -base 0 } 0 test clock-7.1 {Julian Day} { clock scan 0 -format %J -gmt true } -210866803200 test clock-7.2 {Julian Day} { |
︙ | ︙ |
Changes to tests/cmdAH.test.
︙ | ︙ | |||
18 19 20 21 22 23 24 25 26 27 28 29 30 31 | ::tcltest::loadTestedCommands catch [list package require -exact tcl::test [info patchlevel]] testConstraint testchmod [llength [info commands testchmod]] testConstraint testsetplatform [llength [info commands testsetplatform]] testConstraint testvolumetype [llength [info commands testvolumetype]] testConstraint testbytestring [llength [info commands testbytestring]] testConstraint linkDirectory [expr { ![testConstraint win] || ($::tcl_platform(osVersion) >= 5.0 && [lindex [file system [temporaryDirectory]] 1] eq "NTFS") }] testConstraint notWine [expr {![info exists ::env(CI_USING_WINE)]}] # File permissions broken on wsl without some "exotic" wsl configuration | > > > > | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | ::tcltest::loadTestedCommands catch [list package require -exact tcl::test [info patchlevel]] testConstraint testchmod [llength [info commands testchmod]] testConstraint testsetplatform [llength [info commands testsetplatform]] testConstraint testvolumetype [llength [info commands testvolumetype]] testConstraint testbytestring [llength [info commands testbytestring]] testConstraint time64bit [expr { $::tcl_platform(pointerSize) >= 8 || [llength [info command testsize]] && [testsize st_mtime] >= 8 }] testConstraint linkDirectory [expr { ![testConstraint win] || ($::tcl_platform(osVersion) >= 5.0 && [lindex [file system [temporaryDirectory]] 1] eq "NTFS") }] testConstraint notWine [expr {![info exists ::env(CI_USING_WINE)]}] # File permissions broken on wsl without some "exotic" wsl configuration |
︙ | ︙ | |||
1703 1704 1705 1706 1707 1708 1709 | test cmdAH-24.14.1 { Tcl_FileObjCmd: mtime (built-in Windows names with dir path and extension) } -constraints {win} -body { file mtime [file join [temporaryDirectory] CON.txt] } -match regexp -result {could not (?:get modification time|read)} -returnCodes error # 3155760000 is 64-bit Unix time, Wed Jan 01 00:00:00 GMT 2070: | | | | 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 | test cmdAH-24.14.1 { Tcl_FileObjCmd: mtime (built-in Windows names with dir path and extension) } -constraints {win} -body { file mtime [file join [temporaryDirectory] CON.txt] } -match regexp -result {could not (?:get modification time|read)} -returnCodes error # 3155760000 is 64-bit Unix time, Wed Jan 01 00:00:00 GMT 2070: test cmdAH-24.20.1 {Tcl_FileObjCmd: atime 64-bit time_t, bug [4718b41c56]} -constraints {time64bit} -setup { set filename [makeFile "" foo.text] } -body { # This test may fail if your system does not have a 64-bit time_t. # That is to be expected and is not a problem with Tcl. list [file atime $filename 3155760000] [file atime $filename] } -cleanup { removeFile $filename } -result {3155760000 3155760000} test cmdAH-24.20.2 {Tcl_FileObjCmd: mtime 64-bit time_t, bug [4718b41c56]} -constraints {time64bit} -setup { set filename [makeFile "" foo.text] } -body { # This test may fail if your system does not have a 64-bit time_t. # That is to be expected and is not a problem with Tcl. list [file mtime $filename 3155760000] [file mtime $filename] } -cleanup { file delete -force $filename |
︙ | ︙ |
Changes to tests/ioCmd.test.
︙ | ︙ | |||
492 493 494 495 496 497 498 | close $f set f [open $path(test1) r] fconfigure $f -translation binary set result [string length [read $f]] close $f set result } 5 | | | | 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 | close $f set f [open $path(test1) r] fconfigure $f -translation binary set result [string length [read $f]] close $f set result } 5 test iocmd-12.10.1 {POSIX open access modes: BINARY} -body { after 100 set f [open $path(test1) {WRONLY BINARY TRUNC}] puts $f Ɉ ;# throws an exception } -cleanup { close $f } -returnCodes 1 -match glob -result {error writing "*": invalid or incomplete multibyte or wide character} test iocmd-12.11 {POSIX open access modes: BINARY} { set f [open $path(test1) {WRONLY BINARY TRUNC}] puts $f H close $f set f [open $path(test1) r] fconfigure $f -translation binary set result [read -nonewline $f] close $f |
︙ | ︙ | |||
2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 | child eval { proc no-op args {} proc driver {sub args} {return {initialize finalize watch read}} chan event [chan create read driver] readable no-op } interp delete child } {} # ### ### ### ######### ######### ######### ## Same tests as above, but exercising the code forwarding and ## receiving driver operations to the originator thread. # -*- tcl -*- # ### ### ### ######### ######### ######### | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 | child eval { proc no-op args {} proc driver {sub args} {return {initialize finalize watch read}} chan event [chan create read driver] readable no-op } interp delete child } {} # 1st attempt without error in write, another with error in write: foreach ::writeErr {0 1} { test iocmd-32.3.$::writeErr {prevent copy-state against segfault by finalize, bug [79474c58800cdf94]} -setup { proc test_chan {args} { set rest [lassign $args mode chan] lappend ::ret $mode switch -exact $mode { read {puts $chan "Test" ; close $chan} write {if {$::writeErr} {return "boom"}; set data [lindex $rest 0]; string length $data} finalize {after 20 {set ::done done}} initialize {return "initialize watch finalize read write"} } } set clchlst {} set toev [after 5000 {set ::done tout}] } -body { set ::ret {} set ch [chan create "read write" test_chan] lappend clchlst $ch lassign [chan pipe] in1 out1 lappend clchlst $in1 $out1 lassign [chan pipe] in2 out2 lappend clchlst $in2 $out2 lassign [chan pipe] in3 out3 lappend clchlst $in3 $out3 # simulate exec: echo test >@ $out2 2>@ $out3 <@ $in1 &: fileevent $out2 writable [list apply {{cho che} { puts $cho test; close $cho; close $che }} $out2 $out3] # recopy to given chans in handler fileevent $in2 readable [list apply {{in out} { if {[catch { chan copy $in $out } msg]} { #puts err:$msg fileevent $in readable {} } }} $in2 $ch] fileevent $in3 readable [list apply {{in out} { if {[catch { chan copy $in $out } msg]} { #puts err:$msg fileevent $in readable {} } }} $in3 $ch] fileevent $out1 writable [list apply {{in out} { if {[catch { chan copy $in $out } msg]} { #puts err:$msg fileevent $out writable {} } }} $ch $out1] vwait ::done lappend ::ret $::done } -cleanup { foreach ch $clchlst { catch {close $ch} } after cancel $toev unset -nocomplain ::done ::ret ch in1 in2 in3 out1 out2 out3 toev clchlst } -result {initialize read write finalize done} }; unset ::writeErr # ### ### ### ######### ######### ######### ## Same tests as above, but exercising the code forwarding and ## receiving driver operations to the originator thread. # -*- tcl -*- # ### ### ### ######### ######### ######### |
︙ | ︙ |
Changes to tests/oo.test.
︙ | ︙ | |||
2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 | c create o } -body { lsort [info object methods o -all -private] } -cleanup { o destroy c destroy } -result $stdmethods test oo-18.1 {OO: define command support} { list [catch {oo::define oo::object {error foo}} msg] $msg $errorInfo } {1 foo {foo while executing "error foo" | > > > > > > > > > > > > > > > > > > > > > > > > | 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 | c create o } -body { lsort [info object methods o -all -private] } -cleanup { o destroy c destroy } -result $stdmethods test oo-17.15 {OO: class method list without -all (bug 36e5517a6850)} -setup { oo::class create c } -body { oo::define c { method foo {} {} method Bar {} {} private method gorp {} {} } list [lsort [info class methods c]] [lsort [info class methods c -private]] } -cleanup { c destroy } -result {foo {Bar foo}} test oo-17.16 {OO: instance method list without -all (bug 36e5517a6850)} -setup { oo::object create o } -body { oo::objdefine o { method foo {} {} method Bar {} {} private method gorp {} {} } list [lsort [info object methods o]] [lsort [info object methods o -private]] } -cleanup { o destroy } -result {foo {Bar foo}} test oo-18.1 {OO: define command support} { list [catch {oo::define oo::object {error foo}} msg] $msg $errorInfo } {1 foo {foo while executing "error foo" |
︙ | ︙ | |||
3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 | lsort {q w e r t y u i o p}; # Overwrite the Tcl stack info frame 0 } [c new] test } -match glob -cleanup { c destroy } -result {* cmd {info frame 0} method test class ::c level 0} # Prove that the issue in [Bug 1865054] isn't an issue any more test oo-23.1 {Self-like derivation; complex case!} -setup { oo::class create SELF { superclass oo::class unexport create new # Next is just a convenience | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 | lsort {q w e r t y u i o p}; # Overwrite the Tcl stack info frame 0 } [c new] test } -match glob -cleanup { c destroy } -result {* cmd {info frame 0} method test class ::c level 0} # Common code for oo-22.{3,4,5,6} oo::class create WorkerBase oo::class create WorkerSupport { superclass oo::class WorkerBase variable result stop method WithWorkers {nworkers args script} { set workers {} try { for {set n 1} {$n <= $nworkers} {incr n} { lappend workers [set worker [[self] new]] $worker schedule {*}$args } return [uplevel 1 $script] } finally { foreach worker $workers {$worker destroy} } } method run {nworkers} { set result {} set stopvar [my varname stop] set stop false my WithWorkers $nworkers [list my Work [my varname result]] { after idle [namespace code {set stop true}] vwait $stopvar } return $result } } oo::class create Worker { superclass WorkerBase method schedule {args} { set coro [namespace current]::coro if {![llength [info commands $coro]]} { coroutine $coro {*}$args } } method Work args {error unimplemented} method dump {} { info frame [expr {[info frame] - 1}] } } test oo-22.3 {OO and coroutines and info frame: Bug 87271f7cd6} -body { # Triggers a crash with incorrectly restored pmPtr->procPtr->cmdPtr WorkerSupport create A { superclass Worker method Work {var} { after 0 [info coroutine] yield lappend $var [my dump] } } A run 2 } -cleanup { catch {rename dump {}} catch {A destroy} } -match glob -result {{* method Work class ::A *} {* method Work class ::A *}} test oo-22.4 {OO and coroutines and info frame: Bug 87271f7cd6} -body { # Triggers a crash with incorrectly cloned pmPtr->procPtr->cmdPtr WorkerSupport create A { superclass Worker method Work {var} { after 0 [info coroutine] yield lappend $var [my dump] } } # Copies the methods, changing the declarer # Test it works with the source class still around oo::copy A B B run 2 } -cleanup { catch {rename dump {}} catch {A destroy} catch {B destroy} } -match glob -result {{* method Work class ::B *} {* method Work class ::B *}} test oo-22.5 {OO and coroutines and info frame: Bug 87271f7cd6} -body { # Triggers a crash with incorrectly cloned pmPtr->procPtr->cmdPtr WorkerSupport create A { superclass Worker method Work {var} { after 0 [info coroutine] yield lappend $var [my dump] } } # Copies the methods, changing the declarer # Test it works with the source class deleted oo::copy A B catch {A destroy} B run 2 } -cleanup { catch {rename dump {}} catch {B destroy} } -match glob -result {{* method Work class ::B *} {* method Work class ::B *}} test oo-22.6 {OO and coroutines and info frame: Bug 87271f7cd6} -body { # Triggers a crash with incorrectly cloned pmPtr->procPtr->cmdPtr WorkerSupport create A { superclass Worker method Work {var} { after 0 [info coroutine] yield lappend $var [my dump] } } # Copies the methods, changing the declarer # Test it works in the original source class with the copy around oo::copy A B B run 2 A run 2 } -cleanup { catch {rename dump {}} catch {A destroy} catch {B destroy} } -match glob -result {{* method Work class ::A *} {* method Work class ::A *}} WorkerBase destroy # Prove that the issue in [Bug 1865054] isn't an issue any more test oo-23.1 {Self-like derivation; complex case!} -setup { oo::class create SELF { superclass oo::class unexport create new # Next is just a convenience |
︙ | ︙ | |||
4398 4399 4400 4401 4402 4403 4404 | rename obj2 {} rename obj1 {} # doesn't crash return done } -cleanup { rename obj {} } -result done | > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 | rename obj2 {} rename obj1 {} # doesn't crash return done } -cleanup { rename obj {} } -result done test oo-35.7.1 {Bug 7842f33a5c: destructor cascading in stereotypes} -setup { oo::class create base oo::class create RpcClient { superclass base method write name { lappend ::result "RpcClient -> $name" } method create_bug {} { MkObjectRpc create cfg [self] 111 } } oo::class create MkObjectRpc { superclass base variable hdl constructor {rpcHdl mqHdl} { set hdl $mqHdl oo::objdefine [self] forward rpc $rpcHdl } destructor { my rpc write otto-$hdl } } set ::result {} } -body { set FH [RpcClient new] $FH create_bug $FH destroy join $result \n } -cleanup { base destroy } -result {} test oo-35.7.2 {Bug 7842f33a5c: destructor cascading in stereotypes} -setup { oo::class create base oo::class create RpcClient { superclass base method write name { lappend ::result "RpcClient -> $name" } method create_bug {} { MkObjectRpc create cfg [self] 111 } destructor { lappend ::result "Destroyed" } } oo::class create MkObjectRpc { superclass base variable hdl constructor {rpcHdl mqHdl} { set hdl $mqHdl oo::objdefine [self] forward rpc $rpcHdl } destructor { my rpc write otto-$hdl } } set ::result {} } -body { set FH [RpcClient new] $FH create_bug $FH destroy join $result \n } -cleanup { base destroy } -result {Destroyed} test oo-35.7.3 {Bug 7842f33a5c: destructor cascading in stereotypes} -setup { oo::class create base oo::class create RpcClient { superclass base variable interiorObjects method write name { lappend ::result "RpcClient -> $name" } method create_bug {} { set obj [MkObjectRpc create cfg [self] 111] lappend interiorObjects $obj return $obj } destructor { lappend ::result "Destroyed" # Explicit destroy of interior objects foreach obj $interiorObjects { $obj destroy } } } oo::class create MkObjectRpc { superclass base variable hdl constructor {rpcHdl mqHdl} { set hdl $mqHdl oo::objdefine [self] forward rpc $rpcHdl } destructor { my rpc write otto-$hdl } } set ::result {} } -body { set FH [RpcClient new] $FH create_bug $FH destroy join $result \n } -cleanup { base destroy } -result "Destroyed\nRpcClient -> otto-111" test oo-36.1 {TIP #470: introspection within oo::define} { oo::define oo::object self } ::oo::object test oo-36.2 {TIP #470: introspection within oo::define} -setup { oo::class create Cls } -body { oo::define Cls self |
︙ | ︙ |
Changes to unix/Makefile.in.
︙ | ︙ | |||
1071 1072 1073 1074 1075 1076 1077 | done; @echo "Installing package cookiejar 0.2 files to $(SCRIPT_INSTALL_DIR)/cookiejar0.2/" @for i in $(TOP_DIR)/library/cookiejar/*.tcl \ $(TOP_DIR)/library/cookiejar/*.gz; \ do \ $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)/cookiejar0.2"; \ done | | | | 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 | done; @echo "Installing package cookiejar 0.2 files to $(SCRIPT_INSTALL_DIR)/cookiejar0.2/" @for i in $(TOP_DIR)/library/cookiejar/*.tcl \ $(TOP_DIR)/library/cookiejar/*.gz; \ do \ $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)/cookiejar0.2"; \ done @echo "Installing package http 2.10b3 as a Tcl Module" @$(INSTALL_DATA) $(TOP_DIR)/library/http/http.tcl \ "$(MODULE_INSTALL_DIR)/9.0/http-2.10b3.tm" @echo "Installing package opt0.4 files to $(SCRIPT_INSTALL_DIR)/opt0.4/" @for i in $(TOP_DIR)/library/opt/*.tcl; do \ $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)/opt0.4"; \ done @echo "Installing package msgcat 1.7.1 as a Tcl Module" @$(INSTALL_DATA) $(TOP_DIR)/library/msgcat/msgcat.tcl \ "$(MODULE_INSTALL_DIR)/9.0/msgcat-1.7.1.tm" |
︙ | ︙ |
Changes to unix/configure.
︙ | ︙ | |||
5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 | ZLIB_OBJS=\${ZLIB_OBJS} ZLIB_SRCS=\${ZLIB_SRCS} ZLIB_INCLUDE=-I\${ZLIB_DIR} fi printf "%s\n" "#define HAVE_ZLIB 1" >>confdefs.h #------------------------------------------------------------------------ | > > > | 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 | ZLIB_OBJS=\${ZLIB_OBJS} ZLIB_SRCS=\${ZLIB_SRCS} ZLIB_INCLUDE=-I\${ZLIB_DIR} printf "%s\n" "#define TCL_WITH_INTERNAL_ZLIB 1" >>confdefs.h fi printf "%s\n" "#define HAVE_ZLIB 1" >>confdefs.h #------------------------------------------------------------------------ |
︙ | ︙ |
Changes to unix/configure.ac.
︙ | ︙ | |||
161 162 163 164 165 166 167 168 169 170 171 172 173 174 | AC_SEARCH_LIBS([deflateSetHeader],[z],[],[ zlib_ok=no ])]) AS_IF([test $zlib_ok = no], [ AC_SUBST(ZLIB_OBJS,[\${ZLIB_OBJS}]) AC_SUBST(ZLIB_SRCS,[\${ZLIB_SRCS}]) AC_SUBST(ZLIB_INCLUDE,[-I\${ZLIB_DIR}]) ]) AC_DEFINE(HAVE_ZLIB, 1, [Is there an installed zlib?]) #------------------------------------------------------------------------ # Add stuff for libtommath libtommath_ok=yes | > | 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | AC_SEARCH_LIBS([deflateSetHeader],[z],[],[ zlib_ok=no ])]) AS_IF([test $zlib_ok = no], [ AC_SUBST(ZLIB_OBJS,[\${ZLIB_OBJS}]) AC_SUBST(ZLIB_SRCS,[\${ZLIB_SRCS}]) AC_SUBST(ZLIB_INCLUDE,[-I\${ZLIB_DIR}]) AC_DEFINE(TCL_WITH_INTERNAL_ZLIB, 1, [Tcl with internal zlib]) ]) AC_DEFINE(HAVE_ZLIB, 1, [Is there an installed zlib?]) #------------------------------------------------------------------------ # Add stuff for libtommath libtommath_ok=yes |
︙ | ︙ |
Changes to unix/tcl.m4.
︙ | ︙ | |||
89 90 91 92 93 94 95 | if test x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d ${libdir} 2>/dev/null` \ `ls -d ${exec_prefix}/lib 2>/dev/null` \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /usr/local/lib 2>/dev/null` \ `ls -d /usr/contrib/lib 2>/dev/null` \ `ls -d /usr/pkg/lib 2>/dev/null` \ | | | | | 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | if test x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d ${libdir} 2>/dev/null` \ `ls -d ${exec_prefix}/lib 2>/dev/null` \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /usr/local/lib 2>/dev/null` \ `ls -d /usr/contrib/lib 2>/dev/null` \ `ls -d /usr/pkg/lib 2>/dev/null` \ `ls -d /usr/lib/tcl9.1 2>/dev/null` \ `ls -d /usr/lib 2>/dev/null` \ `ls -d /usr/lib64 2>/dev/null` \ `ls -d /usr/local/lib/tcl9.1 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl9.1 2>/dev/null` \ ; do if test -f "$i/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i; pwd)`" break fi done fi |
︙ | ︙ | |||
222 223 224 225 226 227 228 | if test x"${ac_cv_c_tkconfig}" = x ; then for i in `ls -d ${libdir} 2>/dev/null` \ `ls -d ${exec_prefix}/lib 2>/dev/null` \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /usr/local/lib 2>/dev/null` \ `ls -d /usr/contrib/lib 2>/dev/null` \ `ls -d /usr/pkg/lib 2>/dev/null` \ | | | | | 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 | if test x"${ac_cv_c_tkconfig}" = x ; then for i in `ls -d ${libdir} 2>/dev/null` \ `ls -d ${exec_prefix}/lib 2>/dev/null` \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /usr/local/lib 2>/dev/null` \ `ls -d /usr/contrib/lib 2>/dev/null` \ `ls -d /usr/pkg/lib 2>/dev/null` \ `ls -d /usr/lib/tk9.1 2>/dev/null` \ `ls -d /usr/lib 2>/dev/null` \ `ls -d /usr/lib64 2>/dev/null` \ `ls -d /usr/local/lib/tk9.1 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tk9.1 2>/dev/null` \ ; do if test -f "$i/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i; pwd)`" break fi done fi |
︙ | ︙ |
Changes to unix/tclConfig.h.in.
︙ | ︙ | |||
443 444 445 446 447 448 449 450 451 452 453 454 455 456 | /* Do 'long' and 'long long' have the same size (64-bit)? */ #undef TCL_WIDE_INT_IS_LONG /* Tcl with external libtommath */ #undef TCL_WITH_EXTERNAL_TOMMATH /* Is getcwd Posix-compliant? */ #undef USEGETWD /* Are we building with DTrace support? */ #undef USE_DTRACE /* Should we use FIONBIO? */ | > > > | 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 | /* Do 'long' and 'long long' have the same size (64-bit)? */ #undef TCL_WIDE_INT_IS_LONG /* Tcl with external libtommath */ #undef TCL_WITH_EXTERNAL_TOMMATH /* Tcl with internal zlib */ #undef TCL_WITH_INTERNAL_ZLIB /* Is getcwd Posix-compliant? */ #undef USEGETWD /* Are we building with DTrace support? */ #undef USE_DTRACE /* Should we use FIONBIO? */ |
︙ | ︙ |
Changes to unix/tclKqueueNotfy.c.
︙ | ︙ | |||
181 182 183 184 185 186 187 | * with regular files belonging to tsdPtr. */ if (TclOSfstat(filePtr->fd, &fdStat) == -1) { Tcl_Panic("fstat: %s", strerror(errno)); } else if ((fdStat.st_mode & S_IFMT) == S_IFREG || (fdStat.st_mode & S_IFMT) == S_IFDIR | | < | 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | * with regular files belonging to tsdPtr. */ if (TclOSfstat(filePtr->fd, &fdStat) == -1) { Tcl_Panic("fstat: %s", strerror(errno)); } else if ((fdStat.st_mode & S_IFMT) == S_IFREG || (fdStat.st_mode & S_IFMT) == S_IFDIR || (fdStat.st_mode & S_IFMT) == S_IFLNK) { switch (op) { case EV_ADD: if (isNew) { LIST_INSERT_HEAD(&tsdPtr->firstReadyFileHandlerPtr, filePtr, readyNode); } break; |
︙ | ︙ |
Changes to unix/tclLoadNext.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include <mach-o/rld.h> #include <streams/streams.h> | < | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include <mach-o/rld.h> #include <streams/streams.h> /* * Static procedures defined within this file. */ static void * FindSymbol(Tcl_Interp *interp, Tcl_LoadHandle loadHandle, const char *symbol); static void UnloadFile(Tcl_LoadHandle loadHandle); |
︙ | ︙ |
Changes to unix/tclLoadOSF.c.
︙ | ︙ | |||
32 33 34 35 36 37 38 | * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include <sys/types.h> #include <loader.h> | < | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include <sys/types.h> #include <loader.h> /* * Static procedures defined within this file. */ static void * FindSymbol(Tcl_Interp *interp, Tcl_LoadHandle loadHandle, const char *symbol); static void UnloadFile(Tcl_LoadHandle loadHandle); |
︙ | ︙ |
Changes to unix/tclUnixInit.c.
︙ | ︙ | |||
331 332 333 334 335 336 337 | * Need to check Darwin release at runtime in tclUnixFCmd.c and tclLoadDyld.c: * initialize release global at startup from uname(). */ #define GET_DARWIN_RELEASE 1 MODULE_SCOPE long tclMacOSXDarwinRelease; long tclMacOSXDarwinRelease = 0; #endif | < | 331 332 333 334 335 336 337 338 339 340 341 342 343 344 | * Need to check Darwin release at runtime in tclUnixFCmd.c and tclLoadDyld.c: * initialize release global at startup from uname(). */ #define GET_DARWIN_RELEASE 1 MODULE_SCOPE long tclMacOSXDarwinRelease; long tclMacOSXDarwinRelease = 0; #endif /* *--------------------------------------------------------------------------- * * TclpInitPlatform -- * * Initialize all the platform-dependent things like signals and |
︙ | ︙ |
Changes to win/Makefile.in.
︙ | ︙ | |||
154 155 156 157 158 159 160 | TEST_LIB_FILE = @LIBPREFIX@tcltest$(VER)${DLLSUFFIX}${LIBSUFFIX} TEST_LOAD_PRMS = lappend ::auto_path {$(ROOT_DIR_WIN_NATIVE)/tests};\ package ifneeded dde 1.4.5 [list load ${DDE_DLL_FILE}];\ package ifneeded registry 1.3.7 [list load ${REG_DLL_FILE}] TEST_LOAD_FACILITIES = package ifneeded tcl::test ${VERSION}@TCL_PATCH_LEVEL@ [list load ${TEST_DLL_FILE} Tcltest];\ $(TEST_LOAD_PRMS) ZLIB_DLL_FILE = zlib1.dll | | | 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | TEST_LIB_FILE = @LIBPREFIX@tcltest$(VER)${DLLSUFFIX}${LIBSUFFIX} TEST_LOAD_PRMS = lappend ::auto_path {$(ROOT_DIR_WIN_NATIVE)/tests};\ package ifneeded dde 1.4.5 [list load ${DDE_DLL_FILE}];\ package ifneeded registry 1.3.7 [list load ${REG_DLL_FILE}] TEST_LOAD_FACILITIES = package ifneeded tcl::test ${VERSION}@TCL_PATCH_LEVEL@ [list load ${TEST_DLL_FILE} Tcltest];\ $(TEST_LOAD_PRMS) ZLIB_DLL_FILE = zlib1.dll TOMMATH_DLL_FILE = libtommath.dll SHARED_LIBRARIES = $(TCL_DLL_FILE) @ZLIB_DLL_FILE@ @TOMMATH_DLL_FILE@ STATIC_LIBRARIES = $(TCL_LIB_FILE) TCLSH = tclsh$(VER)${EXESUFFIX} WINE = @WINE@ CAT32 = cat32$(EXEEXT) |
︙ | ︙ | |||
204 205 206 207 208 209 210 211 212 213 214 215 216 217 | RMDIR = rm -rf MKDIR = mkdir -p SHELL = @SHELL@ RM = rm -f COPY = cp LN = ln ### # Tip 430 - ZipFS Modifications ### TCL_ZIP_FILE = @TCL_ZIP_FILE@ TCL_VFS_PATH = libtcl.vfs/tcl_library | > | 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 | RMDIR = rm -rf MKDIR = mkdir -p SHELL = @SHELL@ RM = rm -f COPY = cp LN = ln GDB = gdb ### # Tip 430 - ZipFS Modifications ### TCL_ZIP_FILE = @TCL_ZIP_FILE@ TCL_VFS_PATH = libtcl.vfs/tcl_library |
︙ | ︙ | |||
907 908 909 910 911 912 913 | $(COPY) "$$i" "$(SCRIPT_INSTALL_DIR)"; \ done; @echo "Installing package cookiejar 0.2" @for j in $(ROOT_DIR)/library/cookiejar/*.tcl \ $(ROOT_DIR)/library/cookiejar/*.gz; do \ $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/cookiejar0.2"; \ done; | | | | 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 | $(COPY) "$$i" "$(SCRIPT_INSTALL_DIR)"; \ done; @echo "Installing package cookiejar 0.2" @for j in $(ROOT_DIR)/library/cookiejar/*.tcl \ $(ROOT_DIR)/library/cookiejar/*.gz; do \ $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/cookiejar0.2"; \ done; @echo "Installing package http 2.10b3 as a Tcl Module"; @$(COPY) $(ROOT_DIR)/library/http/http.tcl "$(MODULE_INSTALL_DIR)/9.0/http-2.10b3.tm"; @echo "Installing package opt 0.4.7"; @for j in $(ROOT_DIR)/library/opt/*.tcl; do \ $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/opt0.4"; \ done; @echo "Installing package msgcat 1.7.1 as a Tcl Module"; @$(COPY) $(ROOT_DIR)/library/msgcat/msgcat.tcl "$(MODULE_INSTALL_DIR)/9.0/msgcat-1.7.1.tm"; @echo "Installing package tcltest 2.5.8 as a Tcl Module"; |
︙ | ︙ | |||
1003 1004 1005 1006 1007 1008 1009 | shell: binaries @TCL_LIBRARY="$(LIBRARY_DIR)"; export TCL_LIBRARY; \ $(WINE) ./$(TCLSH) $(SCRIPT) # This target can be used to run tclsh inside either gdb or insight gdb: binaries @echo "set env TCL_LIBRARY=$(LIBRARY_DIR)" > gdb.run | | > > > > > > > > > | 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 | shell: binaries @TCL_LIBRARY="$(LIBRARY_DIR)"; export TCL_LIBRARY; \ $(WINE) ./$(TCLSH) $(SCRIPT) # This target can be used to run tclsh inside either gdb or insight gdb: binaries @echo "set env TCL_LIBRARY=$(LIBRARY_DIR)" > gdb.run $(GDB) ./$(TCLSH) --command=gdb.run rm gdb.run shquotequote = $(subst ',\",$(subst ",\",$(1))) gdb-test: tcltest @printf '%s ' 'set env TCL_LIBRARY=$(LIBRARY_DIR)' > gdb.run @printf '\n' >>gdb.run @printf '%s ' set args $(ROOT_DIR_NATIVE)/tests/all.tcl \ $(call shquotequote,$(TESTFLAGS)) -singleproc 1 >> gdb.run $(GDB) ${TEST_EXE_FILE} --command=gdb.run rm gdb.run depend: Makefile: $(SRC_DIR)/Makefile.in ./config.status |
︙ | ︙ |
Changes to win/configure.
︙ | ︙ | |||
5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 | ;; esac fi else case e in #( e) ZLIB_OBJS=\${ZLIB_OBJS} TOMMATH_OBJS=\${TOMMATH_OBJS} ;; esac fi | > > > | 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 | ;; esac fi else case e in #( e) printf "%s\n" "#define TCL_WITH_INTERNAL_ZLIB 1" >>confdefs.h ZLIB_OBJS=\${ZLIB_OBJS} TOMMATH_OBJS=\${TOMMATH_OBJS} ;; esac fi |
︙ | ︙ |
Changes to win/configure.ac.
︙ | ︙ | |||
151 152 153 154 155 156 157 158 159 160 161 162 163 164 | ]) ]) ], [ AC_SUBST(ZLIB_LIBS,[\${ZLIB_DIR_NATIVE}/win32/zdll.lib]) AC_SUBST(TOMMATH_LIBS,[\${TOMMATH_DIR_NATIVE}/win32/tommath.lib]) ]) ], [ AC_SUBST(ZLIB_OBJS,[\${ZLIB_OBJS}]) AC_SUBST(TOMMATH_OBJS,[\${TOMMATH_OBJS}]) ]) AC_DEFINE(HAVE_ZLIB, 1, [Is there an installed zlib?]) AC_SUBST(TCL_ZLIB_LIB_NAME, $zlib_lib_name) AC_SUBST(TCL_TOMMATH_LIB_NAME, $tommath_lib_name) AC_CHECK_TYPES([intptr_t, uintptr_t],,,[[ | > | 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | ]) ]) ], [ AC_SUBST(ZLIB_LIBS,[\${ZLIB_DIR_NATIVE}/win32/zdll.lib]) AC_SUBST(TOMMATH_LIBS,[\${TOMMATH_DIR_NATIVE}/win32/tommath.lib]) ]) ], [ AC_DEFINE(TCL_WITH_INTERNAL_ZLIB, 1, [Tcl with internal zlib]) AC_SUBST(ZLIB_OBJS,[\${ZLIB_OBJS}]) AC_SUBST(TOMMATH_OBJS,[\${TOMMATH_OBJS}]) ]) AC_DEFINE(HAVE_ZLIB, 1, [Is there an installed zlib?]) AC_SUBST(TCL_ZLIB_LIB_NAME, $zlib_lib_name) AC_SUBST(TCL_TOMMATH_LIB_NAME, $tommath_lib_name) AC_CHECK_TYPES([intptr_t, uintptr_t],,,[[ |
︙ | ︙ |
Changes to win/makefile.vc.
︙ | ︙ | |||
466 467 468 469 470 471 472 | LIBTCLVFSSUBDIR = libtcl.vfs LIBTCLVFS = $(OUT_DIR)\$(LIBTCLVFSSUBDIR) # Additional include and C macro definitions for the implicit rules # defined in rules.vc PRJ_INCLUDES = -I"$(TOMMATHDIR)" | | > > > > | 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 | LIBTCLVFSSUBDIR = libtcl.vfs LIBTCLVFS = $(OUT_DIR)\$(LIBTCLVFSSUBDIR) # Additional include and C macro definitions for the implicit rules # defined in rules.vc PRJ_INCLUDES = -I"$(TOMMATHDIR)" PRJ_DEFINES = /DMP_PREC=4 /Dinline=__inline /DHAVE_ZLIB=1 /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DMP_FIXED_CUTOFFS !if $(STATIC_BUILD) PRJ_DEFINES = $(PRJ_DEFINES) /DTCL_WITH_INTERNAL_ZLIB !endif # Additional Link libraries needed beyond those in rules.vc PRJ_LIBS = netapi32.lib user32.lib userenv.lib ws2_32.lib #--------------------------------------------------------------------- # TclTest flags #--------------------------------------------------------------------- |
︙ | ︙ |
Changes to win/tclWinChan.c.
︙ | ︙ | |||
104 105 106 107 108 109 110 | /* * This structure describes the channel type structure for file based IO. */ static const Tcl_ChannelType fileChannelType = { "file", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ | | | | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | /* * This structure describes the channel type structure for file based IO. */ static const Tcl_ChannelType fileChannelType = { "file", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ NULL, /* Close proc. */ FileInputProc, /* Input proc. */ FileOutputProc, /* Output proc. */ NULL, NULL, /* Set option proc. */ FileGetOptionProc, /* Get option proc. */ FileWatchProc, /* Set up the notifier to watch the channel. */ FileGetHandleProc, /* Get an OS handle from channel. */ FileCloseProc, /* close2proc. */ FileBlockProc, /* Set blocking or non-blocking mode.*/ NULL, /* flush proc. */ |
︙ | ︙ | |||
136 137 138 139 140 141 142 | /* * The number of 100-ns intervals between the Windows system epoch (1601-01-01 * on the proleptic Gregorian calendar) and the Posix epoch (1970-01-01). */ #define POSIX_EPOCH_AS_FILETIME \ ((long long) 116444736 * (long long) 1000000000) | < | 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | /* * The number of 100-ns intervals between the Windows system epoch (1601-01-01 * on the proleptic Gregorian calendar) and the Posix epoch (1970-01-01). */ #define POSIX_EPOCH_AS_FILETIME \ ((long long) 116444736 * (long long) 1000000000) /* *---------------------------------------------------------------------- * * TclWinGenerateChannelName -- * * This function generates names for channels. |
︙ | ︙ |
Changes to win/tclWinConsole.c.
︙ | ︙ | |||
276 277 278 279 280 281 282 | * stdout and stderr), and contention low. More finer-grained locking would * likely not only complicate implementation but be slower due to multiple * locks being held. Note console channels also differ from other Tcl * channel types in that the channel<->OS descriptor mapping is not one-to-one. */ SRWLOCK gConsoleLock; | < | 276 277 278 279 280 281 282 283 284 285 286 287 288 289 | * stdout and stderr), and contention low. More finer-grained locking would * likely not only complicate implementation but be slower due to multiple * locks being held. Note console channels also differ from other Tcl * channel types in that the channel<->OS descriptor mapping is not one-to-one. */ SRWLOCK gConsoleLock; /* Process-wide list of console handles. Access control through gConsoleLock */ static ConsoleHandleInfo *gConsoleHandleInfoList; /* * Process-wide list of channels that are listening for events. Again access * control through gConsoleLock. Common list for all threads is simplifies * locking and bookkeeping and is workable because in practice multiple |
︙ | ︙ | |||
337 338 339 340 341 342 343 | RingBufferInit( RingBuffer *ringPtr, Tcl_Size capacity) { if (capacity <= 0 || capacity > TCL_SIZE_MAX) { Tcl_Panic("Internal error: invalid ring buffer capacity requested."); } | | | 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 | RingBufferInit( RingBuffer *ringPtr, Tcl_Size capacity) { if (capacity <= 0 || capacity > TCL_SIZE_MAX) { Tcl_Panic("Internal error: invalid ring buffer capacity requested."); } ringPtr->bufPtr = (char *)Tcl_Alloc(capacity); ringPtr->capacity = capacity; ringPtr->start = 0; ringPtr->length = 0; } /* *------------------------------------------------------------------------ |
︙ | ︙ | |||
901 902 903 904 905 906 907 | if (needEvent) { ConsoleEvent *evPtr = (ConsoleEvent *)Tcl_Alloc(sizeof(ConsoleEvent)); /* See note above loop why this can be accessed without locks */ chanInfoPtr->flags |= CONSOLE_EVENT_QUEUED; chanInfoPtr->numRefs += 1; /* So it does not go away while event | | | 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 | if (needEvent) { ConsoleEvent *evPtr = (ConsoleEvent *)Tcl_Alloc(sizeof(ConsoleEvent)); /* See note above loop why this can be accessed without locks */ chanInfoPtr->flags |= CONSOLE_EVENT_QUEUED; chanInfoPtr->numRefs += 1; /* So it does not go away while event * is in queue */ evPtr->header.proc = ConsoleEventProc; evPtr->chanInfoPtr = chanInfoPtr; Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL); } } ReleaseSRWLockShared(&gConsoleLock); |
︙ | ︙ | |||
969 970 971 972 973 974 975 | * Closes the physical channel. * *---------------------------------------------------------------------- */ static int ConsoleCloseProc( | | | 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 | * Closes the physical channel. * *---------------------------------------------------------------------- */ static int ConsoleCloseProc( void *instanceData, /* Pointer to ConsoleChannelInfo structure. */ TCL_UNUSED(Tcl_Interp *), int flags) { ConsoleChannelInfo *chanInfoPtr = (ConsoleChannelInfo *)instanceData; ConsoleHandleInfo *handleInfoPtr; int errorCode = 0; ConsoleChannelInfo **nextPtrPtr; |
︙ | ︙ | |||
2002 2003 2004 2005 2006 2007 2008 | AllocateConsoleHandleInfo( HANDLE consoleHandle, int permissions) /* TCL_READABLE or TCL_WRITABLE */ { ConsoleHandleInfo *handleInfoPtr; DWORD consoleMode; | | | 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 | AllocateConsoleHandleInfo( HANDLE consoleHandle, int permissions) /* TCL_READABLE or TCL_WRITABLE */ { ConsoleHandleInfo *handleInfoPtr; DWORD consoleMode; handleInfoPtr = (ConsoleHandleInfo *)Tcl_Alloc(sizeof(*handleInfoPtr)); memset(handleInfoPtr, 0, sizeof(*handleInfoPtr)); handleInfoPtr->console = consoleHandle; InitializeSRWLock(&handleInfoPtr->lock); InitializeConditionVariable(&handleInfoPtr->consoleThreadCV); InitializeConditionVariable(&handleInfoPtr->interpThreadCV); RingBufferInit(&handleInfoPtr->buffer, CONSOLE_BUFFER_SIZE); handleInfoPtr->lastError = 0; |
︙ | ︙ |
Changes to win/tclWinFCmd.c.
︙ | ︙ | |||
48 49 50 51 52 53 54 | WIN_READONLY_ATTRIBUTE, WIN_SHORTNAME_ATTRIBUTE, WIN_SYSTEM_ATTRIBUTE }; static const int attributeArray[] = {FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_HIDDEN, 0, FILE_ATTRIBUTE_READONLY, 0, FILE_ATTRIBUTE_SYSTEM}; | < | 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | WIN_READONLY_ATTRIBUTE, WIN_SHORTNAME_ATTRIBUTE, WIN_SYSTEM_ATTRIBUTE }; static const int attributeArray[] = {FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_HIDDEN, 0, FILE_ATTRIBUTE_READONLY, 0, FILE_ATTRIBUTE_SYSTEM}; const char *const tclpFileAttrStrings[] = { "-archive", "-hidden", "-longname", "-readonly", "-shortname", "-system", NULL }; const TclFileAttrProcs tclpFileAttrProcs[] = { |
︙ | ︙ |
Changes to win/tclWinInt.h.
︙ | ︙ | |||
71 72 73 74 75 76 77 | typedef struct TclPipeThreadInfo { HANDLE evControl; /* Auto-reset event used by the main thread to * signal when the pipe thread should attempt * to do read/write operation. Additionally * used as signal to stop (state set to -1) */ volatile LONG state; /* Indicates current state of the thread */ | | < < | 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | typedef struct TclPipeThreadInfo { HANDLE evControl; /* Auto-reset event used by the main thread to * signal when the pipe thread should attempt * to do read/write operation. Additionally * used as signal to stop (state set to -1) */ volatile LONG state; /* Indicates current state of the thread */ void *clientData; /* Referenced data of the main thread */ HANDLE evWakeUp; /* Optional wake-up event worker set by shutdown */ } TclPipeThreadInfo; /* If pipe-workers will use some tcl subsystem, we can use Tcl_Alloc without * more overhead for finalize thread (should be executed anyway) * * #define _PTI_USE_CKALLOC 1 */ /* * State of the pipe-worker. * * State PTI_STATE_STOP possible from idle state only, worker owns TI structure. * Otherwise PTI_STATE_END used (main thread hold ownership of the TI). */ #define PTI_STATE_IDLE 0 /* idle or not yet initialzed */ #define PTI_STATE_WORK 1 /* in work */ #define PTI_STATE_STOP 2 /* thread should stop work (owns TI structure) */ #define PTI_STATE_END 4 /* thread should stop work (worker is busy) */ #define PTI_STATE_DOWN 8 /* worker is down */ MODULE_SCOPE TclPipeThreadInfo * TclPipeThreadCreateTI(TclPipeThreadInfo **pipeTIPtr, void *clientData, HANDLE wakeEvent); MODULE_SCOPE int TclPipeThreadWaitForSignal(TclPipeThreadInfo **pipeTIPtr); static inline void |
︙ | ︙ |
Changes to win/tclWinPipe.c.
︙ | ︙ | |||
1183 1184 1185 1186 1187 1188 1189 | CloseHandle(startInfo.hStdOutput); } if (startInfo.hStdError != INVALID_HANDLE_VALUE) { CloseHandle(startInfo.hStdError); } return result; } | < | 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 | CloseHandle(startInfo.hStdOutput); } if (startInfo.hStdError != INVALID_HANDLE_VALUE) { CloseHandle(startInfo.hStdError); } return result; } /* *---------------------------------------------------------------------- * * HasConsole -- * * Determines whether the current application is attached to a console. |
︙ | ︙ |
Changes to win/tclWinPort.h.
︙ | ︙ | |||
242 243 244 245 246 247 248 | #ifndef ETXTBSY # define ETXTBSY 139 /* Text file or pseudo-device busy */ #endif #ifndef EWOULDBLOCK # define EWOULDBLOCK 140 /* Operation would block */ #endif | < | 242 243 244 245 246 247 248 249 250 251 252 253 254 255 | #ifndef ETXTBSY # define ETXTBSY 139 /* Text file or pseudo-device busy */ #endif #ifndef EWOULDBLOCK # define EWOULDBLOCK 140 /* Operation would block */ #endif /* Visual Studio doesn't have these, so just choose some high numbers */ #ifndef ESOCKTNOSUPPORT # define ESOCKTNOSUPPORT 240 /* Socket type not supported */ #endif #ifndef ESHUTDOWN # define ESHUTDOWN 241 /* Can't send after socket shutdown */ #endif |
︙ | ︙ | |||
411 412 413 414 415 416 417 | # ifdef S_IFLNK # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) # else # define S_ISLNK(m) 0 # endif #endif /* !S_ISLNK */ | < | 410 411 412 413 414 415 416 417 418 419 420 421 422 423 | # ifdef S_IFLNK # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) # else # define S_ISLNK(m) 0 # endif #endif /* !S_ISLNK */ /* * Define MAXPATHLEN in terms of MAXPATH if available */ #ifndef MAXPATH # define MAXPATH MAX_PATH #endif /* MAXPATH */ |
︙ | ︙ | |||
519 520 521 522 523 524 525 | #define TclpSysFree(ptr) (HeapFree(GetProcessHeap(), \ 0, (HGLOBAL)ptr)) #define TclpSysRealloc(ptr, size) ((void*)HeapReAlloc(GetProcessHeap(), \ 0, (LPVOID)ptr, size)) /* This type is not defined in the Windows headers */ #define socklen_t int | < | 517 518 519 520 521 522 523 524 525 526 527 528 529 530 | #define TclpSysFree(ptr) (HeapFree(GetProcessHeap(), \ 0, (HGLOBAL)ptr)) #define TclpSysRealloc(ptr, size) ((void*)HeapReAlloc(GetProcessHeap(), \ 0, (LPVOID)ptr, size)) /* This type is not defined in the Windows headers */ #define socklen_t int /* * The following macros have trivial definitions, allowing generic code to * address platform-specific issues. */ #define TclpReleaseFile(file) Tcl_Free(file) |
︙ | ︙ |
Changes to win/tclWinSerial.c.
︙ | ︙ | |||
609 610 611 612 613 614 615 | SerialInfo *infoPtr, **nextPtrPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) { return EINVAL; } | < | 609 610 611 612 613 614 615 616 617 618 619 620 621 622 | SerialInfo *infoPtr, **nextPtrPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) { return EINVAL; } if (serialPtr->validMask & TCL_READABLE) { PurgeComm(serialPtr->handle, PURGE_RXABORT | PURGE_RXCLEAR); CloseHandle(serialPtr->osRead.hEvent); } serialPtr->validMask &= ~TCL_READABLE; if (serialPtr->writeThread) { |
︙ | ︙ | |||
1475 1476 1477 1478 1479 1480 1481 | * Use the pointer to keep the channel names unique, in case the handles * are shared between multiple channels (stdin/stdout). */ TclWinGenerateChannelName(channelName, "file", infoPtr); infoPtr->channel = Tcl_CreateChannel(&serialChannelType, channelName, infoPtr, permissions); | < | 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 | * Use the pointer to keep the channel names unique, in case the handles * are shared between multiple channels (stdin/stdout). */ TclWinGenerateChannelName(channelName, "file", infoPtr); infoPtr->channel = Tcl_CreateChannel(&serialChannelType, channelName, infoPtr, permissions); SetupComm(handle, infoPtr->sysBufRead, infoPtr->sysBufWrite); PurgeComm(handle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); /* * Default is blocking. |
︙ | ︙ |
Changes to win/tclWinSock.c.
︙ | ︙ | |||
58 59 60 61 62 63 64 | * Helper macros to make parts of this file clearer. The macros do exactly * what they say on the tin. :-) They also only ever refer to their arguments * once, and so can be used without regard to side effects. */ #define SET_BITS(var, bits) ((var) |= (bits)) #define CLEAR_BITS(var, bits) ((var) &= ~(bits)) | | | | | | | > | > > > > > | > | 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | * Helper macros to make parts of this file clearer. The macros do exactly * what they say on the tin. :-) They also only ever refer to their arguments * once, and so can be used without regard to side effects. */ #define SET_BITS(var, bits) ((var) |= (bits)) #define CLEAR_BITS(var, bits) ((var) &= ~(bits)) #define GOT_BITS(var, bits) (((var) & (bits)) != 0) /* "sock" + a pointer in hex + \0 */ #define SOCK_CHAN_LENGTH (16 + TCL_INTEGER_SPACE) /* * The following variable is used to tell whether this module has been * initialized. If 1, initialization of sockets was successful, if -1 then * socket initialization failed (WSAStartup failed). */ static int initialized = 0; static const WCHAR className[] = L"TclSocket"; TCL_DECLARE_MUTEX(socketMutex) /* * The following defines declare the messages used on socket windows. */ enum TclSocketMessages { SOCKET_MESSAGE = WM_USER+1, /* Sent by OS: something happened. */ SOCKET_SELECT = WM_USER+2, /* Adjust select mask. */ SOCKET_TERMINATE = WM_USER+3/* Stop worker thread. */ }; /* * Operations used with a SOCKET_SELECT message. */ enum SocketSelectOperations { SELECT = TRUE, /* Add socket to select. */ UNSELECT = FALSE /* Remove socket from select. */ }; /* * This is needed to comply with the strict aliasing rules of GCC, but it also * simplifies casting between the different sockaddr types. */ typedef union { |
︙ | ︙ | |||
146 147 148 149 150 151 152 | */ struct addrinfo *addrlist; /* Addresses to connect to. */ struct addrinfo *addr; /* Iterator over addrlist. */ struct addrinfo *myaddrlist;/* Local address. */ struct addrinfo *myaddr; /* Iterator over myaddrlist. */ int connectError; /* Cache status of async socket. */ | | > | | | < | < | < | | | | | | > | 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | */ struct addrinfo *addrlist; /* Addresses to connect to. */ struct addrinfo *addr; /* Iterator over addrlist. */ struct addrinfo *myaddrlist;/* Local address. */ struct addrinfo *myaddr; /* Iterator over myaddrlist. */ int connectError; /* Cache status of async socket. */ int cachedBlocking; /* Cache blocking mode of async socket. */ volatile int notifierConnectError; /* Async connect error set by notifier thread. * This error is still a windows error code. * Access must be protected by semaphore */ struct TcpState *nextPtr; /* The next socket on the per-thread socket * list. */ }; /* * These bits may be OR'ed together into the "flags" field of a TcpState * structure. */ enum TcpStateFlags { TCP_NONBLOCKING = (1<<0), /* Socket with non-blocking I/O. */ TCP_ASYNC_CONNECT = (1<<1), /* Async connect in progress. */ SOCKET_EOF = (1<<2), /* A zero read happened on the socket. */ SOCKET_PENDING = (1<<3), /* A message has been sent for this socket */ TCP_ASYNC_PENDING = (1<<4), /* TcpConnect was called to process an async * connect. This flag indicates that reentry is * still pending. */ TCP_ASYNC_FAILED = (1<<5), /* An async connect finally failed. */ TCP_ASYNC_TEST_MODE = (1<<8)/* Async testing activated. Do not * automatically continue connection * process */ }; /* * The following structure is what is added to the Tcl event queue when a * socket event occurs. */ typedef struct { |
︙ | ︙ | |||
197 198 199 200 201 202 203 | /* * This defines the minimum buffersize maintained by the kernel. */ #define TCP_BUFFER_SIZE 4096 | | > > > | < | 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | /* * This defines the minimum buffersize maintained by the kernel. */ #define TCP_BUFFER_SIZE 4096 /* * Per (main) thread data, holding list of things being waited upon and the * various handles to things doing the waiting/notification. */ typedef struct { HWND hwnd; /* Handle to window for socket messages. */ HANDLE socketThread; /* Thread handling the window */ Tcl_ThreadId threadId; /* Parent thread. */ HANDLE readyEvent; /* Event indicating that a socket event is * ready. Also used to indicate that the * socketThread has been initialized and has * started. */ HANDLE socketListLock; /* Win32 Event to lock the socketList */ TcpState *pendingTcpState; /* This socket is opened but not jet in the * list. This value is also checked by * the event structure. */ TcpState *socketList; /* Every open socket in this thread has an * entry on this list. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; |
︙ | ︙ | |||
233 234 235 236 237 238 239 | static void SocketExitHandler(void *clientData); static LRESULT CALLBACK SocketProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); static void TcpAccept(TcpFdList *fds, SOCKET newSocket, address addr); static int WaitForConnect(TcpState *statePtr, int *errorCodePtr); static int WaitForSocketEvent(TcpState *statePtr, int events, int *errorCodePtr); | | | 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 | static void SocketExitHandler(void *clientData); static LRESULT CALLBACK SocketProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); static void TcpAccept(TcpFdList *fds, SOCKET newSocket, address addr); static int WaitForConnect(TcpState *statePtr, int *errorCodePtr); static int WaitForSocketEvent(TcpState *statePtr, int events, int *errorCodePtr); static void AddSocketInfoFd(TcpState *statePtr, SOCKET socket); static int FindFDInList(TcpState *statePtr, SOCKET socket); static DWORD WINAPI SocketThread(LPVOID arg); static void TcpThreadActionProc(void *instanceData, int action); static int TcpCloseProc(void *, Tcl_Interp *); static Tcl_EventCheckProc SocketCheckProc; |
︙ | ︙ | |||
260 261 262 263 264 265 266 | * This structure describes the channel type structure for TCP socket * based IO: */ static const Tcl_ChannelType tcpChannelType = { "tcp", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ | | | | > > > > | > > > > > > > > | < | | | | | | | 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 | * This structure describes the channel type structure for TCP socket * based IO: */ static const Tcl_ChannelType tcpChannelType = { "tcp", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ NULL, /* Old close proc. Deprecated. */ TcpInputProc, /* Input proc. */ TcpOutputProc, /* Output proc. */ NULL, /* Seek proc. */ TcpSetOptionProc, /* Set option proc. */ TcpGetOptionProc, /* Get option proc. */ TcpWatchProc, /* Initialize notifier. */ TcpGetHandleProc, /* Get OS handles out of channel. */ TcpClose2Proc, /* New close2 proc. */ TcpBlockModeProc, /* Set blocking or non-blocking mode.*/ NULL, /* flush proc. */ NULL, /* handler proc. */ NULL, /* wide seek proc. */ TcpThreadActionProc, /* thread action proc. */ NULL /* truncate proc. */ }; /* * The following variable holds the network name of this host. */ static TclInitProcessGlobalValueProc InitializeHostName; static ProcessGlobalValue hostName = {0, 0, NULL, NULL, InitializeHostName, NULL, NULL}; /* *---------------------------------------------------------------------- * * SendSelectMessage -- * * Simple wrapper round the SendMessage syscall with a SOCKET_SELECT * message to add a bit of type safety. * *---------------------------------------------------------------------- */ static inline void SendSelectMessage( ThreadSpecificData *tsdPtr, /* Reference to this thread's worker. */ int operation, /* Whether to add or remove from the mask. */ TcpState *payload) /* What socket to add/remove. */ { SendMessageW(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) operation, (LPARAM) payload); } /* * Address print debug functions */ #if 0 static inline void printaddrinfo( struct addrinfo *ai, char *prefix) { char host[NI_MAXHOST], port[NI_MAXSERV]; getnameinfo(ai->ai_addr, ai->ai_addrlen, host, sizeof(host), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); } static void printaddrinfolist( struct addrinfo *addrlist, char *prefix) { struct addrinfo *ai; for (ai = addrlist; ai != NULL; ai = ai->ai_next) { |
︙ | ︙ | |||
344 345 346 347 348 349 350 | void InitializeHostName( char **valuePtr, size_t *lengthPtr, Tcl_Encoding *encodingPtr) { WCHAR wbuf[256]; | | | > < | 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 | void InitializeHostName( char **valuePtr, size_t *lengthPtr, Tcl_Encoding *encodingPtr) { WCHAR wbuf[256]; DWORD length = sizeof(wbuf) / sizeof(WCHAR); Tcl_DString ds; Tcl_DStringInit(&ds); if (GetComputerNameExW(ComputerNamePhysicalDnsFullyQualified, wbuf, &length) != 0) { /* * Convert string from native to UTF then change to lowercase. */ Tcl_UtfToLower(Tcl_WCharToUtfDString(wbuf, TCL_INDEX_NONE, &ds)); } else { TclInitSockets(); /* * The buffer size of 256 is recommended by the MSDN page that * documents gethostname() as being always adequate. */ |
︙ | ︙ | |||
410 411 412 413 414 415 416 | } /* *---------------------------------------------------------------------- * * TclInitSockets -- * | | | | > | | | | | 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 | } /* *---------------------------------------------------------------------- * * TclInitSockets -- * * Initialization of sockets for the thread. Also creates message * handling window class for the process if needed. * * Results: * Nothing. Panics on failure. * * Side effects: * If not already prepared, initializes the TSD structure and socket * message handling thread associated to the calling thread for the * subsystem of the driver. * *---------------------------------------------------------------------- */ void TclInitSockets(void) { /* Then Per thread initialization. */ DWORD id; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) TclThreadDataKeyGet(&dataKey); if (tsdPtr != NULL) { return; } InitSocketWindowClass(); /* * OK, this thread has never done anything with sockets before. Construct * a worker thread to handle asynchronous events related to sockets * assigned to _this_ thread. */ tsdPtr = TCL_TSD_INIT(&dataKey); tsdPtr->pendingTcpState = NULL; tsdPtr->socketList = NULL; tsdPtr->hwnd = NULL; tsdPtr->threadId = Tcl_GetCurrentThread(); tsdPtr->readyEvent = CreateEventW(NULL, FALSE, FALSE, NULL); if (tsdPtr->readyEvent == NULL) { goto initFailure; } tsdPtr->socketListLock = CreateEventW(NULL, FALSE, TRUE, NULL); if (tsdPtr->socketListLock == NULL) { goto initFailure; } |
︙ | ︙ | |||
503 504 505 506 507 508 509 | * *---------------------------------------------------------------------- */ void TclpFinalizeSockets(void) { | | > | 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 | * *---------------------------------------------------------------------- */ void TclpFinalizeSockets(void) { ThreadSpecificData *tsdPtr = (ThreadSpecificData *) TclThreadDataKeyGet(&dataKey); /* * Careful! This is a finalizer! */ if (tsdPtr == NULL) { return; |
︙ | ︙ | |||
558 559 560 561 562 563 564 | * Sets the device into blocking or nonblocking mode. * *---------------------------------------------------------------------- */ static int TcpBlockModeProc( | | | | 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 | * Sets the device into blocking or nonblocking mode. * *---------------------------------------------------------------------- */ static int TcpBlockModeProc( void *instanceData, /* Socket state. */ int mode) /* The mode to set. Can be one of * TCL_MODE_BLOCKING or * TCL_MODE_NONBLOCKING. */ { TcpState *statePtr = (TcpState *) instanceData; if (mode == TCL_MODE_NONBLOCKING) { SET_BITS(statePtr->flags, TCP_NONBLOCKING); } else { CLEAR_BITS(statePtr->flags, TCP_NONBLOCKING); } return 0; |
︙ | ︙ | |||
612 613 614 615 616 617 618 | WaitForConnect( TcpState *statePtr, /* State of the socket. */ int *errorCodePtr) /* Where to store errors? A passed * null-pointer activates background mode. */ { int result; int oldMode; | < | 633 634 635 636 637 638 639 640 641 642 643 644 645 646 | WaitForConnect( TcpState *statePtr, /* State of the socket. */ int *errorCodePtr) /* Where to store errors? A passed * null-pointer activates background mode. */ { int result; int oldMode; /* * Check if an async connect failed already and error reporting is * demanded, return the error ENOTCONN. */ if (errorCodePtr != NULL && GOT_BITS(statePtr->flags, TCP_ASYNC_FAILED)) { |
︙ | ︙ | |||
642 643 644 645 646 647 648 | * - Call by recv/send and blocking socket * (errorCodePtr != NULL && !GOT_BITS(flags, TCP_NONBLOCKING)) * - Call by the event queue (errorCodePtr == NULL) */ if (GOT_BITS(statePtr->flags, TCP_ASYNC_TEST_MODE) && errorCodePtr != NULL | | > | | 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 | * - Call by recv/send and blocking socket * (errorCodePtr != NULL && !GOT_BITS(flags, TCP_NONBLOCKING)) * - Call by the event queue (errorCodePtr == NULL) */ if (GOT_BITS(statePtr->flags, TCP_ASYNC_TEST_MODE) && errorCodePtr != NULL && GOT_BITS(statePtr->flags, TCP_NONBLOCKING)) { *errorCodePtr = EWOULDBLOCK; return -1; } /* * Be sure to disable event servicing so we are truly modal. */ oldMode = Tcl_SetServiceMode(TCL_SERVICE_NONE); /* * Loop in the blocking case until the connect signal is present */ while (1) { /* * Get the statePtr lock. */ ThreadSpecificData *tsdPtr = (ThreadSpecificData *) TclThreadDataKeyGet(&dataKey); WaitForSingleObject(tsdPtr->socketListLock, INFINITE); /* * Check for connect event. */ if (GOT_BITS(statePtr->readyEvents, FD_CONNECT)) { |
︙ | ︙ | |||
735 736 737 738 739 740 741 | if (errorCodePtr != NULL) { *errorCodePtr = ENOTCONN; } return -1; } | | | | | | 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 | if (errorCodePtr != NULL) { *errorCodePtr = ENOTCONN; } return -1; } /* * Free list lock. */ SetEvent(tsdPtr->socketListLock); /* * Background operation returns with no action as there was no connect * event */ if (errorCodePtr == NULL) { |
︙ | ︙ | |||
789 790 791 792 793 794 795 | * Reads input from the input device of the channel. * *---------------------------------------------------------------------- */ static int TcpInputProc( | | | > | 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 | * Reads input from the input device of the channel. * *---------------------------------------------------------------------- */ static int TcpInputProc( void *instanceData, /* Socket state. */ char *buf, /* Where to store data read. */ int bufSize, /* How much space is available in the * buffer? */ int *errorCodePtr) /* Where to store error code. */ { TcpState *statePtr = (TcpState *)instanceData; int bytesRead; DWORD error; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) TclThreadDataKeyGet(&dataKey); *errorCodePtr = 0; /* * First check to see if EOF was already detected, to prevent calling the * socket stack after the first time EOF is detected. */ |
︙ | ︙ | |||
880 881 882 883 884 885 886 | } /* * Check for error condition or underflow in non-blocking case. */ if (GOT_BITS(statePtr->flags, TCP_NONBLOCKING) | | | 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 | } /* * Check for error condition or underflow in non-blocking case. */ if (GOT_BITS(statePtr->flags, TCP_NONBLOCKING) || (error != WSAEWOULDBLOCK)) { Tcl_WinConvertError(error); *errorCodePtr = Tcl_GetErrno(); bytesRead = -1; break; } /* |
︙ | ︙ | |||
922 923 924 925 926 927 928 | * Produces output on the socket. * *---------------------------------------------------------------------- */ static int TcpOutputProc( | | | > | 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 | * Produces output on the socket. * *---------------------------------------------------------------------- */ static int TcpOutputProc( void *instanceData, /* Socket state. */ const char *buf, /* The data buffer. */ int toWrite, /* How many bytes to write? */ int *errorCodePtr) /* Where to store error code. */ { TcpState *statePtr = (TcpState *)instanceData; int written; DWORD error; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) TclThreadDataKeyGet(&dataKey); *errorCodePtr = 0; /* * Check if there is an async connect running. * For blocking sockets terminate connect, otherwise do one step. * For a non blocking socket return EWOULDBLOCK if connect not terminated |
︙ | ︙ | |||
1026 1027 1028 1029 1030 1031 1032 | * Closes the socket. * *---------------------------------------------------------------------- */ static int TcpCloseProc( | | | 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 | * Closes the socket. * *---------------------------------------------------------------------- */ static int TcpCloseProc( void *instanceData, /* The socket to close. */ TCL_UNUSED(Tcl_Interp *)) { TcpState *statePtr = (TcpState *)instanceData; /* TIP #218 */ int errorCode = 0; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); |
︙ | ︙ | |||
1052 1053 1054 1055 1056 1057 1058 | Tcl_WinConvertError((DWORD) WSAGetLastError()); errorCode = Tcl_GetErrno(); } Tcl_Free(thisfd); } if (statePtr->addrlist != NULL) { | | | | 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 | Tcl_WinConvertError((DWORD) WSAGetLastError()); errorCode = Tcl_GetErrno(); } Tcl_Free(thisfd); } if (statePtr->addrlist != NULL) { freeaddrinfo(statePtr->addrlist); } if (statePtr->myaddrlist != NULL) { freeaddrinfo(statePtr->myaddrlist); } /* * Clear an eventual tsd info list pointer. * * This may be called, if an async socket connect fails or is closed * between connect and thread action callback. |
︙ | ︙ | |||
1112 1113 1114 1115 1116 1117 1118 | * Shuts down one side of the socket. * *---------------------------------------------------------------------- */ static int TcpClose2Proc( | | | > | > | | 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 | * Shuts down one side of the socket. * *---------------------------------------------------------------------- */ static int TcpClose2Proc( void *instanceData, /* The socket to close. */ Tcl_Interp *interp, /* For error reporting. */ int flags) /* Flags that indicate which side to close. */ { TcpState *statePtr = (TcpState *)instanceData; int readError = 0; int writeError = 0; /* * Shutdown the OS socket handle. */ if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) == 0) { return TcpCloseProc(instanceData, interp); } /* * Single fd operation: Tcl_OpenTcpServer() does not set TCL_READABLE or * TCL_WRITABLE so this should never be called for a server socket. */ if ((flags & TCL_CLOSE_READ) && (shutdown(statePtr->sockets->fd, SD_RECEIVE) == SOCKET_ERROR)) { Tcl_WinConvertError((DWORD) WSAGetLastError()); readError = Tcl_GetErrno(); } if ((flags & TCL_CLOSE_WRITE) && (shutdown(statePtr->sockets->fd, SD_SEND) == SOCKET_ERROR)) { Tcl_WinConvertError((DWORD) WSAGetLastError()); writeError = Tcl_GetErrno(); } return (readError != 0) ? readError : writeError; } /* |
︙ | ︙ | |||
1162 1163 1164 1165 1166 1167 1168 | * Changes attributes of the socket at the system level. * *---------------------------------------------------------------------- */ static int TcpSetOptionProc( | | | 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 | * Changes attributes of the socket at the system level. * *---------------------------------------------------------------------- */ static int TcpSetOptionProc( void *instanceData, /* Socket state. */ Tcl_Interp *interp, /* For error reporting - can be NULL. */ const char *optionName, /* Name of the option to set. */ const char *value) /* New value for option. */ { TcpState *statePtr = (TcpState *)instanceData; SOCKET sock; size_t len = 0; |
︙ | ︙ | |||
1245 1246 1247 1248 1249 1250 1251 | * None. * *---------------------------------------------------------------------- */ static int TcpGetOptionProc( | | > > > < | | > | 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 | * None. * *---------------------------------------------------------------------- */ static int TcpGetOptionProc( void *instanceData, /* Socket state. */ Tcl_Interp *interp, /* For error reporting - can be NULL. */ const char *optionName, /* Name of the option to retrieve the value * for, or NULL to get all options and their * values. */ Tcl_DString *dsPtr) /* Where to store the computed value; * initialized by caller. */ { TcpState *statePtr = (TcpState *)instanceData; char host[NI_MAXHOST], port[NI_MAXSERV]; SOCKET sock; size_t len = 0; int reverseDNS = 0; #define SUPPRESS_RDNS_VAR "::tcl::unsupported::noReverseDNS" #define HAVE_OPTION(option) \ ((len > 1) && (optionName[1] == option[1]) && \ (strncmp(optionName, option, len) == 0)) /* * Go one step in async connect * * If any error is thrown save it as background error to report eventually * below. */ if (!GOT_BITS(statePtr->flags, TCP_ASYNC_TEST_MODE)) { WaitForConnect(statePtr, NULL); } sock = statePtr->sockets->fd; if (optionName != NULL) { len = strlen(optionName); } if (HAVE_OPTION("-error")) { /* * Do not return any errors if async connect is running. */ if (!GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)) { if (GOT_BITS(statePtr->flags, TCP_ASYNC_FAILED)) { /* * In case of a failed async connect, eventually report the * connect error only once. Do not report the system error, * as this comes again and again. */ if (statePtr->connectError != 0) { Tcl_DStringAppend(dsPtr, Tcl_ErrnoMsg(statePtr->connectError), TCL_INDEX_NONE); statePtr->connectError = 0; } } else { /* * Report an eventual last error of the socket system. */ |
︙ | ︙ | |||
1327 1328 1329 1330 1331 1332 1333 | /* * Return error message. */ if (err) { Tcl_WinConvertError(err); | | > < | | < | | 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 | /* * Return error message. */ if (err) { Tcl_WinConvertError(err); Tcl_DStringAppend(dsPtr, Tcl_ErrnoMsg(Tcl_GetErrno()), TCL_INDEX_NONE); } } } return TCL_OK; } if (HAVE_OPTION("-connecting")) { Tcl_DStringAppend(dsPtr, GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING) ? "1" : "0", TCL_INDEX_NONE); return TCL_OK; } if (interp != NULL && Tcl_GetVar(interp, SUPPRESS_RDNS_VAR, 0) != NULL) { reverseDNS = NI_NUMERICHOST; } if (HAVE_OPTION("-peername")) { address peername; socklen_t size = sizeof(peername); if (GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)) { /* * In async connect output an empty string */ |
︙ | ︙ | |||
1406 1407 1408 1409 1410 1411 1412 | Tcl_PosixError(interp))); } return TCL_ERROR; } } } | | < | 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 | Tcl_PosixError(interp))); } return TCL_ERROR; } } } if ((len == 0) || HAVE_OPTION("-sockname")) { TcpFdList *fds; address sockname; socklen_t size; int found = 0; if (len == 0) { Tcl_DStringAppendElement(dsPtr, "-sockname"); |
︙ | ︙ | |||
1479 1480 1481 1482 1483 1484 1485 | Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't get sockname: %s", Tcl_PosixError(interp))); } return TCL_ERROR; } } | | < | < | 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 | Tcl_SetObjResult(interp, Tcl_ObjPrintf( "can't get sockname: %s", Tcl_PosixError(interp))); } return TCL_ERROR; } } if ((len == 0) || HAVE_OPTION("-keepalive")) { int optlen; BOOL opt = FALSE; if (len == 0) { sock = statePtr->sockets->fd; Tcl_DStringAppendElement(dsPtr, "-keepalive"); } optlen = sizeof(BOOL); getsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&opt, &optlen); Tcl_DStringAppendElement(dsPtr, opt ? "1" : "0"); if (len > 0) { return TCL_OK; } } if ((len == 0) || HAVE_OPTION("-nodelay")) { int optlen; BOOL opt = FALSE; if (len == 0) { sock = statePtr->sockets->fd; Tcl_DStringAppendElement(dsPtr, "-nodelay"); } |
︙ | ︙ | |||
1541 1542 1543 1544 1545 1546 1547 | * already true. * *---------------------------------------------------------------------- */ static void TcpWatchProc( | | | 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 | * already true. * *---------------------------------------------------------------------- */ static void TcpWatchProc( void *instanceData, /* The socket state. */ int mask) /* Events of interest; an OR-ed combination of * TCL_READABLE, TCL_WRITABLE and * TCL_EXCEPTION. */ { TcpState *statePtr = (TcpState *)instanceData; /* |
︙ | ︙ | |||
1595 1596 1597 1598 1599 1600 1601 | * None. * *---------------------------------------------------------------------- */ static int TcpGetHandleProc( | | | | 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 | * None. * *---------------------------------------------------------------------- */ static int TcpGetHandleProc( void *instanceData, /* The socket state. */ TCL_UNUSED(int) /*direction*/, void **handlePtr) /* Where to store the handle. */ { TcpState *statePtr = (TcpState *)instanceData; *handlePtr = INT2PTR(statePtr->sockets->fd); return TCL_OK; } |
︙ | ︙ | |||
1619 1620 1621 1622 1623 1624 1625 | * This might be called in 3 circumstances: * - By a regular socket command * - By the event handler to continue an asynchronously connect * - By a blocking socket function (gets/puts) to terminate the * connect synchronously * * Results: | | | | | 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 | * This might be called in 3 circumstances: * - By a regular socket command * - By the event handler to continue an asynchronously connect * - By a blocking socket function (gets/puts) to terminate the * connect synchronously * * Results: * TCL_OK, if the socket was successfully connected or an asynchronous * connection is in progress. If an error occurs, TCL_ERROR is returned * and an error message is left in interp. * * Side effects: * Opens a socket. * * Remarks: * A single host name may resolve to more than one IP address, e.g. for * an IPv4/IPv6 dual stack host. For handling asynchronously connecting |
︙ | ︙ | |||
1648 1649 1650 1651 1652 1653 1654 | static int TcpConnect( Tcl_Interp *interp, /* For error reporting; can be NULL. */ TcpState *statePtr) { DWORD error; int async_connect = GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT); | | | | | | | > | | | | | | 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 | static int TcpConnect( Tcl_Interp *interp, /* For error reporting; can be NULL. */ TcpState *statePtr) { DWORD error; int async_connect = GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT); /* We are started with async connect and the * connect notification was not yet * received. */ int async_callback = GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING); /* We were called by the event procedure and * continue our loop. */ ThreadSpecificData *tsdPtr = (ThreadSpecificData *) TclThreadDataKeyGet(&dataKey); if (async_callback) { goto reenter; } for (statePtr->addr = statePtr->addrlist; statePtr->addr != NULL; statePtr->addr = statePtr->addr->ai_next) { for (statePtr->myaddr = statePtr->myaddrlist; statePtr->myaddr != NULL; statePtr->myaddr = statePtr->myaddr->ai_next) { /* * No need to try combinations of local and remote addresses * of different families. */ if (statePtr->myaddr->ai_family != statePtr->addr->ai_family) { continue; } /* * Close the socket if it is still open from the last unsuccessful * iteration. */ if (statePtr->sockets->fd != INVALID_SOCKET) { closesocket(statePtr->sockets->fd); } /* * Get statePtr lock. |
︙ | ︙ | |||
1990 1991 1992 1993 1994 1995 1996 | TclInitSockets(); /* * Do the name lookups for the local and remote addresses. */ if (!TclCreateSocketAddress(interp, &addrlist, host, port, 0, &errorMsg) | | | | | | | | | | | | 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 | TclInitSockets(); /* * Do the name lookups for the local and remote addresses. */ if (!TclCreateSocketAddress(interp, &addrlist, host, port, 0, &errorMsg) || !TclCreateSocketAddress(interp, &myaddrlist, myaddr, myport, 1, &errorMsg)) { if (addrlist != NULL) { freeaddrinfo(addrlist); } if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't open socket: %s", errorMsg)); } return NULL; } statePtr = NewSocketInfo(INVALID_SOCKET); statePtr->addrlist = addrlist; statePtr->myaddrlist = myaddrlist; if (async) { SET_BITS(statePtr->flags, TCP_ASYNC_CONNECT); |
︙ | ︙ | |||
2052 2053 2054 2055 2056 2057 2058 | *---------------------------------------------------------------------- */ Tcl_Channel Tcl_MakeTcpClientChannel( void *sock) /* The socket to wrap up into a channel. */ { | < < < < > | | > | 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 | *---------------------------------------------------------------------- */ Tcl_Channel Tcl_MakeTcpClientChannel( void *sock) /* The socket to wrap up into a channel. */ { TclInitSockets(); ThreadSpecificData *tsdPtr = (ThreadSpecificData *) TclThreadDataKeyGet(&dataKey); /* * Set kernel space buffering and non-blocking. */ TclSockMinimumBuffers(sock, TCP_BUFFER_SIZE); TcpState *statePtr = NewSocketInfo((SOCKET) sock); /* * Start watching for read/write events on the socket. */ statePtr->selectEvents = FD_READ | FD_CLOSE | FD_WRITE; SendSelectMessage(tsdPtr, SELECT, statePtr); char channelName[SOCK_CHAN_LENGTH]; TclWinGenerateChannelName(channelName, "sock", statePtr); statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName, statePtr, (TCL_READABLE | TCL_WRITABLE)); Tcl_SetChannelOption(NULL, statePtr->channel, "-translation", "auto crlf"); return statePtr->channel; } |
︙ | ︙ | |||
2105 2106 2107 2108 2109 2110 2111 | Tcl_Channel Tcl_OpenTcpServerEx( Tcl_Interp *interp, /* For error reporting - may be NULL. */ const char *service, /* Port number to open. */ const char *myHost, /* Name of local host. */ unsigned int flags, /* Flags. */ | | | | 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 | Tcl_Channel Tcl_OpenTcpServerEx( Tcl_Interp *interp, /* For error reporting - may be NULL. */ const char *service, /* Port number to open. */ const char *myHost, /* Name of local host. */ unsigned int flags, /* Flags. */ int backlog, /* Length of OS listen backlog queue, or -1 * for default. */ Tcl_TcpAcceptProc *acceptProc, /* Callback for accepting connections from new * clients. */ void *acceptProcData) /* Data for the callback. */ { SOCKET sock = INVALID_SOCKET; unsigned short chosenport = 0; |
︙ | ︙ | |||
2140 2141 2142 2143 2144 2145 2146 | if (!TclCreateSocketAddress(interp, &addrlist, myHost, port, 1, &errorMsg)) { goto error; } for (addrPtr = addrlist; addrPtr != NULL; addrPtr = addrPtr->ai_next) { sock = socket(addrPtr->ai_family, addrPtr->ai_socktype, | | | 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 | if (!TclCreateSocketAddress(interp, &addrlist, myHost, port, 1, &errorMsg)) { goto error; } for (addrPtr = addrlist; addrPtr != NULL; addrPtr = addrPtr->ai_next) { sock = socket(addrPtr->ai_family, addrPtr->ai_socktype, addrPtr->ai_protocol); if (sock == INVALID_SOCKET) { Tcl_WinConvertError((DWORD) WSAGetLastError()); continue; } /* * Win-NT has a misfeature that sockets are inherited in child |
︙ | ︙ | |||
2217 2218 2219 2220 2221 2222 2223 | /* * Set the maximum number of pending connect requests to the max * value allowed on each platform (Win32 and Win32s may be * different, and there may be differences between TCP/IP stacks). */ | | | | | 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 | /* * Set the maximum number of pending connect requests to the max * value allowed on each platform (Win32 and Win32s may be * different, and there may be differences between TCP/IP stacks). */ if (backlog < 0) { backlog = SOMAXCONN; } if (listen(sock, backlog) == SOCKET_ERROR) { Tcl_WinConvertError((DWORD) WSAGetLastError()); closesocket(sock); continue; } if (statePtr == NULL) { |
︙ | ︙ | |||
2243 2244 2245 2246 2247 2248 2249 | error: if (addrlist != NULL) { freeaddrinfo(addrlist); } if (statePtr != NULL) { | | > | 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 | error: if (addrlist != NULL) { freeaddrinfo(addrlist); } if (statePtr != NULL) { ThreadSpecificData *tsdPtr = (ThreadSpecificData *) TclThreadDataKeyGet(&dataKey); statePtr->acceptProc = acceptProc; statePtr->acceptProcData = acceptProcData; TclWinGenerateChannelName(channelName, "sock", statePtr); statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName, statePtr, 0); /* |
︙ | ︙ | |||
2272 2273 2274 2275 2276 2277 2278 | Tcl_CloseEx(NULL, statePtr->channel, 0); return NULL; } return statePtr->channel; } if (interp != NULL) { | | | 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 | Tcl_CloseEx(NULL, statePtr->channel, 0); return NULL; } return statePtr->channel; } if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't open socket: %s", (errorMsg ? errorMsg : Tcl_PosixError(interp)))); } if (sock != INVALID_SOCKET) { closesocket(sock); } |
︙ | ︙ | |||
2310 2311 2312 2313 2314 2315 2316 | address addr) /* Address of new socket. */ { TcpState *newInfoPtr; TcpState *statePtr = fds->statePtr; int len = sizeof(addr); char channelName[SOCK_CHAN_LENGTH]; char host[NI_MAXHOST], port[NI_MAXSERV]; | | > | 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 | address addr) /* Address of new socket. */ { TcpState *newInfoPtr; TcpState *statePtr = fds->statePtr; int len = sizeof(addr); char channelName[SOCK_CHAN_LENGTH]; char host[NI_MAXHOST], port[NI_MAXSERV]; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) TclThreadDataKeyGet(&dataKey); /* * Win-NT has a misfeature that sockets are inherited in child processes * by default. Turn off the inherit bit. */ SetHandleInformation((HANDLE) newSocket, HANDLE_FLAG_INHERIT, 0); |
︙ | ︙ | |||
2537 2538 2539 2540 2541 2542 2543 | */ WaitForSingleObject(tsdPtr->socketListLock, INFINITE); for (statePtr = tsdPtr->socketList; statePtr != NULL; statePtr = statePtr->nextPtr) { if (GOT_BITS(statePtr->readyEvents, statePtr->watchEvents | FD_CONNECT | FD_ACCEPT) | | | 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 | */ WaitForSingleObject(tsdPtr->socketListLock, INFINITE); for (statePtr = tsdPtr->socketList; statePtr != NULL; statePtr = statePtr->nextPtr) { if (GOT_BITS(statePtr->readyEvents, statePtr->watchEvents | FD_CONNECT | FD_ACCEPT) && !GOT_BITS(statePtr->flags, SOCKET_PENDING)) { SET_BITS(statePtr->flags, SOCKET_PENDING); evPtr = (SocketEvent *)Tcl_Alloc(sizeof(SocketEvent)); evPtr->header.proc = SocketEventProc; evPtr->socket = statePtr->sockets->fd; Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL); } } |
︙ | ︙ | |||
2605 2606 2607 2608 2609 2610 2611 | } /* * Discard events that have gone stale. */ if (!statePtr) { | | | 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 | } /* * Discard events that have gone stale. */ if (!statePtr) { SetEvent(tsdPtr->socketListLock); return 1; } /* * Clear flag that (this) event is pending */ |
︙ | ︙ | |||
2837 2838 2839 2840 2841 2842 2843 | * Populate new FD. */ fds->fd = socket; fds->statePtr = statePtr; fds->next = NULL; } | | < | > | 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 | * Populate new FD. */ fds->fd = socket; fds->statePtr = statePtr; fds->next = NULL; } /* *---------------------------------------------------------------------- * * NewSocketInfo -- * * This function allocates and initializes a new TcpState structure. * * Results: * Returns a newly allocated TcpState. * * Side effects: * None, except for allocation of memory. * *---------------------------------------------------------------------- */ static TcpState * NewSocketInfo( SOCKET socket) { TcpState *statePtr = (TcpState *)Tcl_Alloc(sizeof(TcpState)); memset(statePtr, 0, sizeof(TcpState)); /* * TIP #218. Removed the code inserting the new structure into the global |
︙ | ︙ | |||
2893 2894 2895 2896 2897 2898 2899 | * Processes socket events off the system queue. * *---------------------------------------------------------------------- */ static int WaitForSocketEvent( | | | < | > | 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 | * Processes socket events off the system queue. * *---------------------------------------------------------------------- */ static int WaitForSocketEvent( TcpState *statePtr, /* Information about this socket. */ int events, /* Events to look for. May be one of * FD_READ or FD_WRITE. */ int *errorCodePtr) /* Where to store errors? */ { int result = 1; int oldMode; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) TclThreadDataKeyGet(&dataKey); /* * Be sure to disable event servicing so we are truly modal. */ oldMode = Tcl_SetServiceMode(TCL_SERVICE_NONE); |
︙ | ︙ | |||
3028 3029 3030 3031 3032 3033 3034 | * This releases waiters on thread exit in TclpFinalizeSockets() */ SetEvent(tsdPtr->readyEvent); return msg.wParam; } | < | 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 | * This releases waiters on thread exit in TclpFinalizeSockets() */ SetEvent(tsdPtr->readyEvent); return msg.wParam; } /* *---------------------------------------------------------------------- * * SocketProc -- * * This function is called when WSAAsyncSelect has been used to register |
︙ | ︙ |
Changes to win/tclWinTest.c.
︙ | ︙ | |||
459 460 461 462 463 464 465 | goto done; } pTokenUser = (TOKEN_USER *)Tcl_Alloc(dw); if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dw, &dw)) { goto done; } aceEntry[nSids].sidLen = GetLengthSid(pTokenUser->User.Sid); | | | 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 | goto done; } pTokenUser = (TOKEN_USER *)Tcl_Alloc(dw); if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dw, &dw)) { goto done; } aceEntry[nSids].sidLen = GetLengthSid(pTokenUser->User.Sid); aceEntry[nSids].pSid = (PSID)Tcl_Alloc(aceEntry[nSids].sidLen); if (!CopySid(aceEntry[nSids].sidLen, aceEntry[nSids].pSid, pTokenUser->User.Sid)) { Tcl_Free(aceEntry[nSids].pSid); /* Since we have not ++'ed nSids */ goto done; } /* * Always include DACL modify rights so we don't get locked out |
︙ | ︙ | |||
501 502 503 504 505 506 507 | } pTokenGroup = (TOKEN_PRIMARY_GROUP *)Tcl_Alloc(dw); if (!GetTokenInformation(hToken, TokenPrimaryGroup, pTokenGroup, dw, &dw)) { Tcl_Free(pTokenGroup); goto done; } aceEntry[nSids].sidLen = GetLengthSid(pTokenGroup->PrimaryGroup); | | | 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 | } pTokenGroup = (TOKEN_PRIMARY_GROUP *)Tcl_Alloc(dw); if (!GetTokenInformation(hToken, TokenPrimaryGroup, pTokenGroup, dw, &dw)) { Tcl_Free(pTokenGroup); goto done; } aceEntry[nSids].sidLen = GetLengthSid(pTokenGroup->PrimaryGroup); aceEntry[nSids].pSid = (PSID)Tcl_Alloc(aceEntry[nSids].sidLen); if (!CopySid(aceEntry[nSids].sidLen, aceEntry[nSids].pSid, pTokenGroup->PrimaryGroup)) { Tcl_Free(pTokenGroup); Tcl_Free(aceEntry[nSids].pSid); /* Since we have not ++'ed nSids */ goto done; } Tcl_Free(pTokenGroup); |
︙ | ︙ | |||
531 532 533 534 535 536 537 | if (pmode & 0007) { /* World permissions */ PSID pWorldSid; if (!ConvertStringSidToSidA("S-1-1-0", &pWorldSid)) { goto done; } aceEntry[nSids].sidLen = GetLengthSid(pWorldSid); | | | 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 | if (pmode & 0007) { /* World permissions */ PSID pWorldSid; if (!ConvertStringSidToSidA("S-1-1-0", &pWorldSid)) { goto done; } aceEntry[nSids].sidLen = GetLengthSid(pWorldSid); aceEntry[nSids].pSid = (PSID)Tcl_Alloc(aceEntry[nSids].sidLen); if (!CopySid(aceEntry[nSids].sidLen, aceEntry[nSids].pSid, pWorldSid)) { LocalFree(pWorldSid); Tcl_Free(aceEntry[nSids].pSid); /* Since we have not ++'ed nSids */ goto done; } LocalFree(pWorldSid); |
︙ | ︙ |
Changes to win/tclWinThrd.c.
︙ | ︙ | |||
75 76 77 78 79 80 81 | /* * The per-thread event and queue pointers. */ #if TCL_THREADS typedef struct ThreadSpecificData { | | | | 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | /* * The per-thread event and queue pointers. */ #if TCL_THREADS typedef struct ThreadSpecificData { HANDLE condEvent; /* Per-thread condition event */ struct ThreadSpecificData *nextPtr; /* Queue pointers */ struct ThreadSpecificData *prevPtr; int flags; /* See flags below */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; #endif /* TCL_THREADS */ /* * State bits for the thread. |
︙ | ︙ | |||
116 117 118 119 120 121 122 | * Additions by AOL for specialized thread memory allocator. */ #ifdef USE_THREAD_ALLOC static DWORD tlsKey; typedef struct { | | | > | | < | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | * Additions by AOL for specialized thread memory allocator. */ #ifdef USE_THREAD_ALLOC static DWORD tlsKey; typedef struct { Tcl_Mutex tlock; CRITICAL_SECTION wlock; } allocMutex; #endif /* USE_THREAD_ALLOC */ /* * The per thread data passed from TclpThreadCreate * to TclWinThreadStart. */ typedef struct { LPTHREAD_START_ROUTINE lpStartAddress; /* Original startup routine */ LPVOID lpParameter; /* Original startup data */ unsigned int fpControl; /* Floating point control word from the * main thread */ } WinThread; /* *---------------------------------------------------------------------- * * TclWinThreadStart -- * * This procedure is the entry point for all new threads created |
︙ | ︙ | |||
563 564 565 566 567 568 569 | TclpGlobalLock(); /* * Double inside global lock check to avoid a race. */ if (*mutexPtr == NULL) { | | | | 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 | TclpGlobalLock(); /* * Double inside global lock check to avoid a race. */ if (*mutexPtr == NULL) { csPtr = (CRITICAL_SECTION *) Tcl_Alloc(sizeof(CRITICAL_SECTION)); InitializeCriticalSection(csPtr); *mutexPtr = (Tcl_Mutex) csPtr; TclRememberMutex(mutexPtr); } TclpGlobalUnlock(); } csPtr = *((CRITICAL_SECTION **)mutexPtr); EnterCriticalSection(csPtr); } |
︙ | ︙ | |||
655 656 657 658 659 660 661 | *---------------------------------------------------------------------- */ void Tcl_ConditionWait( Tcl_Condition *condPtr, /* Really (WinCondition **) */ Tcl_Mutex *mutexPtr, /* Really (CRITICAL_SECTION **) */ | | | 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 | *---------------------------------------------------------------------- */ void Tcl_ConditionWait( Tcl_Condition *condPtr, /* Really (WinCondition **) */ Tcl_Mutex *mutexPtr, /* Really (CRITICAL_SECTION **) */ const Tcl_Time *timePtr) /* Timeout on waiting period */ { WinCondition *winCondPtr; /* Per-condition queue head */ CRITICAL_SECTION *csPtr; /* Caller's Mutex, after casting */ DWORD wtime; /* Windows time value */ int timeout; /* True if we got a timeout */ int doExit = 0; /* True if we need to do exit setup */ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); |
︙ | ︙ | |||
922 923 924 925 926 927 928 | if (winCondPtr != NULL) { DeleteCriticalSection(&winCondPtr->condLock); Tcl_Free(winCondPtr); *condPtr = NULL; } } | < < < | 922 923 924 925 926 927 928 929 930 931 932 933 934 935 | if (winCondPtr != NULL) { DeleteCriticalSection(&winCondPtr->condLock); Tcl_Free(winCondPtr); *condPtr = NULL; } } /* * Additions by AOL for specialized thread memory allocator. */ #ifdef USE_THREAD_ALLOC Tcl_Mutex * TclpNewAllocMutex(void) |
︙ | ︙ | |||
1025 1026 1027 1028 1029 1030 1031 | success = TlsFree(tlsKey); if (!success) { Tcl_Panic("TlsFree failed from TclpFreeAllocCache"); } } } #endif /* USE_THREAD_ALLOC */ | < | 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 | success = TlsFree(tlsKey); if (!success) { Tcl_Panic("TlsFree failed from TclpFreeAllocCache"); } } } #endif /* USE_THREAD_ALLOC */ void * TclpThreadCreateKey(void) { DWORD *key; key = (DWORD *)TclpSysAlloc(sizeof *key); |
︙ | ︙ |
Changes to win/tclWinTime.c.
︙ | ︙ | |||
98 99 100 101 102 103 104 | */ static struct { int initialized; /* 1 if initialized, 0 otherwise */ int perfCounter; /* 1 if performance counter usable for wide * clicks */ double microsecsScale; /* Denominator scale between clock / microsecs */ } wideClick = {0, 0, 0.0}; | < | 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | */ static struct { int initialized; /* 1 if initialized, 0 otherwise */ int perfCounter; /* 1 if performance counter usable for wide * clicks */ double microsecsScale; /* Denominator scale between clock / microsecs */ } wideClick = {0, 0, 0.0}; /* * Declarations for functions defined later in this file. */ static void StopCalibration(void *clientData); static DWORD WINAPI CalibrationThread(LPVOID arg); |
︙ | ︙ |